* [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).