• Здраво и добредојдовте на форумот на IT.mk.

    Доколку сеуште не сте дел од најголемата заедница на ИТ професионалци и ентузијасти во Македонија, можете бесплатно да се - процесот нема да ви одземе повеќе од 2-3 минути, а за полесна регистрација овозможивме и регистрирање со Facebook и Steam.

[C/C++] IP Address Parsing

  • Ја почнал/а темата
  • #1

LiquidWorm

Администратор
26 март 2007
2,667
183
www.zeroscience.mk
ipv4_parse.c
Код:
/*****************************
*			     *
*			     *
*  ipv4_parse.c              *
*			     *
*			     *
******************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ipv4_parse.h"


/*
 * ipv4_parse_sv()
 *
 *
 */

static
int ipv4_parse_sv (ipv4_parse_ctx *ctx, int idx, char *sv)

{
	int wc = 0;
	int x  = 0;

	// check if single value is wildcard (entire range from 0-255)
	
	wc = (strchr(sv, '*') == NULL ? 0 : 1);
	if(wc)
	{
		if(strlen(sv) != 0x1)
		{
			return(-1);
		}
		
		for(x=0; x<= 0xFF; ++x)
		{
			ctx->m_state[idx] [x] = 1;
		}
	}
	// single value (ex. "1", "2", "192", "10")
	
	else
	{
		ctx->m_state[idx] [(unsigned char) atoi(sv)] = 1;
	}
	
	return(0);

}

/*
 * ipv4_parse_r()
 *
 *
 */

static
int ipv4_parse_r (ipv4_parse_ctx *ctx, int idx, char *r)
{
	unsigned char hi = 0;
	unsigned char lo = 0;
	char *p1 = NULL;
	int x = 0;
	
	// parse low value & high value from range
	p1 - strchr(r, '-');
	*p1 = '\0';
	++p1;
	
	lo = (unsigned char) atoi(r);
	hi = (unsigned char) atoi(p1);
	
	// if low value is larger that high value,
	// return error (ex. "200-100").

	if(lo>=hi)
	{
		return(-1);
	}
	
	// enable range
	for(x=lo; x<=hi; ++x)
	{
		ctx->m_state[idx] [x] = 1;
	}
	
	return(0);
}

/*
 * ipv4_parse_tok()
 *
 *
 */

static
int ipv4_parse_tok (ipv4_parse_ctx *ctx, int idx, char *tok)
{
	int ret = 0;
	
	// does value have a dash indicating range in it?
	// (ex. "1-5"); if not, treat as single value (ex "1", "2", "*")
	// if so, treat as range (ex. "1-5")

	ret = (strchr(tok, '-') == NULL) ?
	ipv4_parse_sv(ctx, idx, tok) :
	 ipv4_parse_r (ctx, idx, tok);
	
	return(ret);
}

/*
 * ipv4_parse_octet()
 *
 *
 */

static
int ipv4_parse_octet (ipv4_parse_ctx *ctx, int idx, char *octet)
{
	char *tok = NULL;
	int ret = 0;

	// parse octet by comma character, if comma
	// character present
	
	tok = strtok(octet, ",");
	if(tok != NULL)
	{
		while(tok != NULL)
		{
			// treat each comma separated value as a
			// range or single value (like, "2-100", "7", etc)
			ret = ipv4_parse_tok(ctx, idx, tok);
			if(ret < 0)
			{
				return(-1);
			}

			tok = strtok(NULL, ",");
		}
	}
	// otherwise, no comma is present, treat as a range
	// or single value (like, "2-100", "7", etc)
	else
	{
		ret = ipv4_parse_tok(ctx, idx, octet);
		if(ret < 0)
		{
			return(-1);
		}
	}
	
	return(0);
}

/*
 * ipv4_parse_ctx_init()
 *
 * the ip range is treated as four arrays of 256
 * unsigned char value. each array represents one
 * of the four octets in an ip address. Positions
 * in the array are marked as either one or zero.
 * Positions are marked as one if those values were
 * supplied in the range. For example:
 *
 * char *range = "10.1.1.1";
 *
 * would result in the 10th byte of the 1st array
 * being set to the value of one, whie the 1st
 * byte of the 2nd, 3rd and 4th arrays being set to
 * one.
 *
 * Once the range has been completely parsed and
 * all values stored in the arrays (the state), a
 * series of for loops can be used to iterate
 * through the range.
 *
 * IP address range parser for nmap-style command
 * line syntax.
 *
 * Example:
 *
 * "192.168.1,2,3,4-12,70.*"
 *
 *
 *
 */

int ipv4_parse_ctx_init (ipv4_parse_ctx *ctx, char *range)
{
	char *oc[4];
	int x = 0;
	
	if(ctx == NULL || range == NULL)
	{
		return(-1);
	}
	
	memset(ctx, 0x00, sizeof(ipv4_parse_ctx));

	// parse ip address range into 4 octets
	
	if((oc[0] = strtok(range, ".")) == NULL ||
	   (oc[1] = strtok(NULL,  ".")) == NULL ||
	   (oc[2] = strtok(NULL,  ".")) == NULL ||
	   (oc[3] = strtok(NULL,  ".")) == NULL)
	{
		return(-1);
	}
	
	// parse each octet
	
	if(ipv4_parse_octet(ctx, 0, oc[0]) < 0 ||
	   ipv4_parse_octet(ctx, 1, oc[1]) < 0 ||
	   ipv4_parse_octet(ctx, 2, oc[2]) < 0 ||
	   ipv4_parse_octet(ctx, 3, oc[3]) < 0)
	{
		return(-1);
	}

	return(0);
}

/*
 * ipv4_parse_next_addr()
 *
 * this function is used to iterate through the
 * previously parsed IP address range.
 *
 *
 *
 */
int ipv4_parse_next (ipv4_parse_ctx *ctx, unsigned int *addr)
{
	if(ctx == NULL || addr == NULL)
	{
		return(-1);
	}
	
	for( ; ctx->m_index[0] <= 0xFF; ++ctx->m_index[0])
	{
		if(ctx->m_state[0] [ctx->m_index[0]] != 0)
		{
			for( ; ctx->m_index[1] <= 0xFF; ++ctx->m_index[1])
			{
				if(ctx->m_state[1] [ctx->m_index[1]] != 0)
				{
					for( ; ctx->m_index[2] <= 0xFF; ++ctx->m_index[2])
					{
						if(ctx->m_state[2] [ctx->m_index[2]] != 0)
						{
							for( ; ctx->m_index[3] <= 0xFF; ++ctx->m_index[3])
							{
								if(ctx->m_state[3] [ctx->m_index[3]] != 0)
								{
									*addr = ((ctx->m_index[0] << 0) & 0x000000FF) ^ ((ctx->m_index[1] << 8) & 0x0000FF00) ^ ((ctx->m_index[2] << 16) & 0x00FF0000) ^ ((ctx->m_index[3] << 24) & 0xFF000000);
									++ctx->m_index[3];

									return(0);
								}
							}
							ctx->m_index[3] = 0;
						}
					}
					ctx->m_index[2] = 0;
				}
			}
			ctx->m_index[1] = 0;
		}
	}
	
	return(-1);
}
//it.com.mk
main.c
Код:
/*
 * main.c
 *
 */

#include <stdio.h>
#include "ipv4_parse.h"

int main(int argc, char *argv[])
{
	ipv4_parse_ctx ctx;  // context to hold state of ip range
	unsigned int addr = 0;
	int ret = 0;

	if(argc != 2)
	{
		printf("usage: %s ip_range\r\n", argv[0]);
		return(1);
	}

	// perform initial parsing of ip range
	
	ret = ipv4_parse_ctx_init(&ctx, argv[1]);
	if(ret < 0)
	{
		printf("*** ipv4_parse_ctx_init() failed.\r\n");
		return(1);
	}
	
	// print out each ip in range
	
	while(1)
	{
		// get next ip in range
		ret = ipv4_parse_next (&ctx, &addr);
		if(ret < 0)
		{
			printf("*** end of range.\r\n");
			break;
		}
	
		// print is out
		printf("ADDR: %d.%d.%d.%d\r\n", (addr >> 0) & 0xFF, (addr >> 8) & 0xFF, (addr >> 16) & 0xFF, (addr >> 24) & 0xFF);
	}
	
	return(0);
}
//it.com.mk
ipv4_parse.h
Код:
/*
 * ipv4_parse.h
 *
 */

#ifndef __IPV4_PARSE_H__
#define __IPV4_PARSE_H__

#ifdef __cplusplus
extern "C" {
#endif

typedef struct ipv4_parse_ctx
{
	unsigned char m_state[4] [256];
	unsigned short m_index[4];

} ipv4_parse_ctx;

/*
 * ipv4_parse_ctx_init()
 *
 *
 */

int ipv4_parse_ctx_init (ipv4_parse_ctx *ctx, char *range);

/*
 * ipv4_parse_next_addr()
 *
 *
 */

int ipv4_parse_next (ipv4_parse_ctx *ctx, unsigned int *addr);

#ifdef __cplusplus
}
#endif

#endif /* __ IPV4_PARSE_H__ */
//it.com.mk
:potenje:
 
  • Ја почнал/а темата
  • #3

LiquidWorm

Администратор
26 март 2007
2,667
183
www.zeroscience.mk
IPv4_Parse претставува пример на ефикасен код за расчленување (parsing) на IP адреси. Препорака за компајлирање: MS Visual Studio. Трите фајлови ја сочинуваат функционалноста потребна за расчленување на IP адреса. Инаку идејата е превземена од добро познатата CLI (Command Line Interface) алатка: Network Mapper (Nmap) која го постави стандардот за расчленување на IP адреси преку command-line во 1990-тите години.

Инаку овие кодови повеќе служат во индустријата за апликативно инженерство, колку од нешто да се започне за да се направи едноставна алатка за расчленување на адреси, едноставно не ги печати адресите во STDOUT... но може лесно да се направи овие адреси да се пренесат во низа, нормално со додатно програмирање... ;)

ipv4_parse.c кодот го претставува срцето на програмата. Содржи неколку функции кои меѓусебно се комбинираат за да се повика расчленувањето од main.c кодот. Додека main.c кодот може да се смета како драјвер за расчленувачката машина (parsing engine).

ipv4_parse.h е C/C++ хедер (header) фајл за дефинирање на прототипи за функциите во ipv4_parse.c.

И тоа е тоа..чисто за почеток на некој голем проект што вклучува IP address parsing ова би било некој почеток...

Не сум јас авторот на кодот, туку наидов од некоја книга/скрипта..но еве се надевам дека колку толку објаснив со свои зборови, можеби има нешто повеќе во ова..па некој поискусен може да се придружи во објаснување и сл. :bravo:

:bye1:
 
  • Ја почнал/а темата
  • #4

LiquidWorm

Администратор
26 март 2007
2,667
183
www.zeroscience.mk
значи како nmap.. да ставам да скенира некој достиг (range) (192.168.1.0/24)
би требало да испечати:

192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
...
 

vasildb

Intern
17 април 2007
209
6
Изгледа нешто треба да се внесе во командната линија. Ако внесам таму 192.168.1.0/24 ми го печати ова
ADDR: 192.168.1.0
*** end of range.
Press any key to continue . . .
Исто се случува и ако внесам која било IP адреса, вклучувајќи ја и мојата.
Ај ако можеш кажи што треба да направам.
 
  • Ја почнал/а темата
  • #6

LiquidWorm

Администратор
26 март 2007
2,667
183
www.zeroscience.mk
а проба место /24 на крај да ставиш /16 или /8 ?

моментално немам инсталирано MS Visual Studio... ќе видам што како кога ќе имам можност... ;)
 

staki

Intern
26 јуни 2007
147
3
дали некој ја пробал оваа програма со Dev C++?
Јас сега пробав и ми правесе проблеми.
 

vasildb

Intern
17 април 2007
209
6
Не е Dev C++ за вакви програми. Сними си VS. Иначе на крај во Dev C++ треба да додадеш

system("Pause");
return 0;
 

Нови мислења

Последни Теми

Статистика

Теми
43,595
Мислења
824,255
Членови
28,088
Најнов член
JonTurk
На врв Дно