9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] parseip error
@ 2010-09-23 19:34 erik quanstrom
  2010-09-27 19:14 ` Sergey Zhilkin
  0 siblings, 1 reply; 2+ messages in thread
From: erik quanstrom @ 2010-09-23 19:34 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 589 bytes --]

parseip(355.355.355.355) -> 99.99.99.99

correction to parseip.c attached; test program
included.

- erik

-----
#include <u.h>
#include <libc.h>
#include <ip.h>

void
usage(void)
{
	fprint(2, "usage: parseip [ip ...]\n");
	exits("usage");
}

void
main(int argc, char **argv)
{
	uchar ip[IPaddrlen];
	int i;
	uvlong n;

	fmtinstall('I', eipfmt);
	ARGBEGIN{
	default:
		usage();
	}ARGEND
	for(i = 0; i < argc; i++){
		n = parseip(ip, argv[i]);
		if(n != -1)
			print("%s -> %I\n", argv[i], ip);
		else
			print("%s -> -1\n", argv[i]);
	}
	exits("");
}

[-- Attachment #2: parseip.c --]
[-- Type: text/plain, Size: 3899 bytes --]

#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <ip.h>

static char*
v4parseip0(uchar *to, char *from, int *err)
{
	int i;
	ulong l;
	char *p;

	p = from;
	for(i = 0; i < 4 && *p; i++){
		l = strtoul(p, &p, 0);
		if(l > 255)
			*err = 1;
		to[i] = l;
		if(*p == '.')
			p++;
	}
	switch(CLASS(to)){
	case 0:	/* class A - 1 uchar net */
	case 1:
		if(i == 3){
			to[3] = to[2];
			to[2] = to[1];
			to[1] = 0;
		} else if (i == 2){
			to[3] = to[1];
			to[1] = 0;
		}
		break;
	case 2:	/* class B - 2 uchar net */
		if(i == 3){
			to[3] = to[2];
			to[2] = 0;
		}
		break;
	}
	return p;
}

char*
v4parseip(uchar *to, char *from)
{
	int err;

	return v4parseip0(to, from, &err);
}

static int
ipcharok(int c)
{
	return c == '.' || c == ':' || isascii(c) && isxdigit(c);
}

static int
delimchar(int c)
{
	if(c == '\0')
		return 1;
	if(c == '.' || c == ':' || isascii(c) && isalnum(c))
		return 0;
	return 1;
}

/*
 * `from' may contain an address followed by other characters,
 * at least in /boot, so we permit whitespace (and more) after the address.
 * we do ensure that "delete" cannot be parsed as "de::".
 *
 * some callers don't check the return value for errors, so
 * set `to' to something distinctive in the case of a parse error.
 */
vlong
parseip(uchar *to, char *from)
{
	int i, err, elipsis = 0, v4 = 1;
	ulong x;
	char *p, *op;

	memset(to, 0, IPaddrlen);
	p = from;
	err = 0;
	for(i = 0; i < IPaddrlen && ipcharok(*p); i+=2){
		op = p;
		x = strtoul(p, &p, 16);
		if(*p == '.' || (*p == 0 && i == 0)){	/* ends with v4? */
			p = v4parseip0(to+i, op, &err);
			i += 4;
			break;
		}
		/* v6: at most 4 hex digits, followed by colon or delim */
		if(x != (ushort)x || *p != ':' && !delimchar(*p)) {
			memset(to, 0, IPaddrlen);
			return -1;			/* parse error */
		}
		to[i] = x>>8;
		to[i+1] = x;
		if(*p == ':'){
			v4 = 0;
			if(*++p == ':'){	/* :: is elided zero short(s) */
				if (elipsis) {
					memset(to, 0, IPaddrlen);
					return -1;	/* second :: */
				}
				elipsis = i+2;
				p++;
			}
		} else if (p == op)		/* strtoul made no progress? */
			break;
	}
	if (err || p == from || !delimchar(*p)) {
		memset(to, 0, IPaddrlen);
		return -1;				/* parse error */
	}
	if(i < IPaddrlen){
		memmove(&to[elipsis+IPaddrlen-i], &to[elipsis], i-elipsis);
		memset(&to[elipsis], 0, IPaddrlen-i);
	}
	if(v4){
		to[10] = to[11] = 0xff;
		return nhgetl(to + IPv4off);
	} else
		return 6;
}

/*
 *  hack to allow ip v4 masks to be entered in the old
 *  style
 */
vlong
parseipmask(uchar *to, char *from)
{
	int i, w;
	vlong x;
	uchar *p;

	if(*from == '/'){
		/* as a number of prefix bits */
		i = atoi(from+1);
		if(i < 0)
			i = 0;
		if(i > 128)
			i = 128;
		w = i;
		memset(to, 0, IPaddrlen);
		for(p = to; i >= 8; i -= 8)
			*p++ = 0xff;
		if(i > 0)
			*p = ~((1<<(8-i))-1);
		x = nhgetl(to+IPv4off);
		/*
		 * identify as ipv6 if the mask is inexpressible as a v4 mask
		 * (because it has too few mask bits).  Arguably, we could
		 * always return 6 here.
		 */
		if (w < 8*(IPaddrlen-IPv4addrlen))
			return 6;
	} else {
		/* as a straight v4 bit mask */
		x = parseip(to, from);
		if (x != -1)
			x = (ulong)nhgetl(to + IPv4off);
		if(memcmp(to, v4prefix, IPv4off) == 0)
			memset(to, 0xff, IPv4off);
	}
	return x;
}

/*
 *  parse a v4 ip address/mask in cidr format
 */
char*
v4parsecidr(uchar *addr, uchar *mask, char *from)
{
	int i;
	char *p;
	uchar *a;

	p = v4parseip(addr, from);

	if(*p == '/'){
		/* as a number of prefix bits */
		i = strtoul(p+1, &p, 0);
		if(i > 32)
			i = 32;
		memset(mask, 0, IPv4addrlen);
		for(a = mask; i >= 8; i -= 8)
			*a++ = 0xff;
		if(i > 0)
			*a = ~((1<<(8-i))-1);
	} else
		memmove(mask, defmask(addr), IPv4addrlen);
	return p;
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [9fans] parseip error
  2010-09-23 19:34 [9fans] parseip error erik quanstrom
@ 2010-09-27 19:14 ` Sergey Zhilkin
  0 siblings, 0 replies; 2+ messages in thread
From: Sergey Zhilkin @ 2010-09-27 19:14 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

Strange IP :)

On Thu, Sep 23, 2010 at 11:34 PM, erik quanstrom <quanstro@quanstro.net> wrote:
> parseip(355.355.355.355) -> 99.99.99.99
>
> correction to parseip.c attached; test program
> included.
>
> - erik
>
> -----
> #include <u.h>
> #include <libc.h>
> #include <ip.h>
>
> void
> usage(void)
> {
>        fprint(2, "usage: parseip [ip ...]\n");
>        exits("usage");
> }
>
> void
> main(int argc, char **argv)
> {
>        uchar ip[IPaddrlen];
>        int i;
>        uvlong n;
>
>        fmtinstall('I', eipfmt);
>        ARGBEGIN{
>        default:
>                usage();
>        }ARGEND
>        for(i = 0; i < argc; i++){
>                n = parseip(ip, argv[i]);
>                if(n != -1)
>                        print("%s -> %I\n", argv[i], ip);
>                else
>                        print("%s -> -1\n", argv[i]);
>        }
>        exits("");
> }



-- 
С наилучшими пожеланиями
Жилкин Сергей
With best regards
Zhilkin Sergey

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-09-27 19:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-23 19:34 [9fans] parseip error erik quanstrom
2010-09-27 19:14 ` Sergey Zhilkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).