@ -0,0 +1,26 @@ | |||
.TH scan_ip4 3 | |||
.SH NAME | |||
scan_ip4 \- parse an IPv4 number in dotted-decimal notation | |||
.SH SYNTAX | |||
.B #include <ip4.h> | |||
int \fBscan_ip4\fP(const char *\fIsrc\fR,char \fIip\fR[4]); | |||
.SH DESCRIPTION | |||
scan_ip4 parses an IPv4 number in dotted-decimal ASCII representation | |||
from \fIsrc\fR and writes the result into \fIip\fR. It returns the | |||
number of bytes read from \fIsrc\fR or 0 if the parsing failed. | |||
Unlike many other IP parsing routines, scan_ip4 does not recognize octal | |||
(like \fB0177.0.0.1\fR) or hexadecimal numbers (like \fB0x7f000001\fR). | |||
.SH EXAMPLE | |||
#include <str.h> | |||
.br | |||
#include <ip4.h> | |||
char buf[]="160.45.40.10"; | |||
char ip[4]; | |||
if (scan_ip4(buf,ip) != str_len(buf)) | |||
parse_error(); | |||
.SH "SEE ALSO" | |||
fmt_ip4(3), scan_ip6(3) |
@ -0,0 +1,19 @@ | |||
#include "scan.h" | |||
#include "ip4.h" | |||
unsigned int scan_ip4(const char *s,char ip[4]) | |||
{ | |||
unsigned int len; | |||
unsigned long u; | |||
int i; | |||
len = 0; | |||
for (i=0; i<4; ++i) { | |||
register unsigned int j; | |||
len+=(j=scan_ulong(s,&u))+1; | |||
if (!j) return 0; | |||
ip[i]=u; s+=j; | |||
if (*s!='.') return 0; ++s; | |||
} | |||
return len-1; | |||
} |
@ -0,0 +1,35 @@ | |||
.TH scan_ip6 3 | |||
.SH NAME | |||
scan_ip6 \- parse an IPv6 number in ASCII representation | |||
.SH SYNTAX | |||
.B #include <ip6.h> | |||
int \fBscan_ip6\fP(const char *\fIsrc\fR,char \fIip\fR[16]); | |||
.SH DESCRIPTION | |||
scan_ip6 parses an IPv6 number in RFC1884 ASCII representation | |||
from \fIsrc\fR and writes the result into \fIip\fR. It returns the | |||
number of bytes read from \fIsrc\fR or 0 if the parsing failed. | |||
scan_ip6 accepts upper and lower case hex letters, it understands "::" | |||
compression and partial IPv4 addresses as in "::FFFF:129.144.52.38". | |||
To allow transparent usage of IPv4 in IPv6 applications, scan_ip6 also | |||
understands IPv4 addresses in dotted-decimal notation and will return | |||
an IPv4-mapped IPv6 address (i.e. "127.0.0.1" will be parsed as | |||
"::FFFF:127.0.0.1". | |||
Unlike many other IP parsing routines, scan_ip6 does not recognize octal | |||
(like \fB0177.0.0.1\fR) or hexadecimal numbers (like \fB0x7f000001\fR) | |||
in the IPv4 part. | |||
.SH EXAMPLE | |||
#include <str.h> | |||
.br | |||
#include <ip6.h> | |||
char buf[]="::1"; | |||
char ip[16]; | |||
if (scan_ip6(buf,ip) != str_len(buf)) | |||
parse_error(); | |||
.SH "SEE ALSO" | |||
fmt_ip6(3), scan_ip4(3) |
@ -0,0 +1,109 @@ | |||
#include "scan.h" | |||
#include "ip4.h" | |||
#include "ip6.h" | |||
/* | |||
* IPv6 addresses are really ugly to parse. | |||
* Syntax: (h = hex digit) | |||
* 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh | |||
* 2. any number of 0000 may be abbreviated as "::", but only once | |||
* 3. The last two words may be written as IPv4 address | |||
*/ | |||
unsigned int scan_ip6(const char *s,char ip[16]) | |||
{ | |||
unsigned int i; | |||
unsigned int len=0; | |||
unsigned long u; | |||
char suffix[16]; | |||
int prefixlen=0; | |||
int suffixlen=0; | |||
for (i=0; i<16; i++) ip[i]=0; | |||
for (;;) { | |||
if (*s == ':') { | |||
len++; | |||
if (s[1] == ':') { /* Found "::", skip to part 2 */ | |||
s+=2; | |||
len++; | |||
break; | |||
} | |||
s++; | |||
} | |||
i = scan_xlong(s,&u); | |||
if (!i) return 0; | |||
if (prefixlen==12 && s[i]=='.') { | |||
/* the last 4 bytes may be written as IPv4 address */ | |||
i=ip4_scan(s,ip+12); | |||
if (i) | |||
return i+len; | |||
else | |||
return 0; | |||
} | |||
ip[prefixlen++] = (u >> 8); | |||
ip[prefixlen++] = (u & 255); | |||
s += i; len += i; | |||
if (prefixlen==16) | |||
return len; | |||
} | |||
/* part 2, after "::" */ | |||
for (;;) { | |||
if (*s == ':') { | |||
if (suffixlen==0) | |||
break; | |||
s++; | |||
len++; | |||
} else if (suffixlen!=0) | |||
break; | |||
i = scan_xlong(s,&u); | |||
if (!i) { | |||
len--; | |||
break; | |||
} | |||
if (suffixlen+prefixlen<=12 && s[i]=='.') { | |||
int j=ip4_scan(s,suffix+suffixlen); | |||
if (j) { | |||
suffixlen+=4; | |||
len+=j; | |||
break; | |||
} else | |||
prefixlen=12-suffixlen; /* make end-of-loop test true */ | |||
} | |||
suffix[suffixlen++] = (u >> 8); | |||
suffix[suffixlen++] = (u & 255); | |||
s += i; len += i; | |||
if (prefixlen+suffixlen==16) | |||
break; | |||
} | |||
for (i=0; i<suffixlen; i++) | |||
ip[16-suffixlen+i] = suffix[i]; | |||
return len; | |||
} | |||
static long int fromhex(unsigned char c) { | |||
if (c>='0' && c<='9') | |||
return c-'0'; | |||
else if (c>='A' && c<='F') | |||
return c-'A'+10; | |||
else if (c>='a' && c<='f') | |||
return c-'a'+10; | |||
return -1; | |||
} | |||
unsigned int scan_ip6_flat(const char *s,char ip[16]) | |||
{ | |||
int i; | |||
for (i=0; i<16; i++) { | |||
int tmp; | |||
tmp=fromhex(*s++); | |||
if (tmp<0) return 0; | |||
ip[i]=tmp << 4; | |||
tmp=fromhex(*s++); | |||
if (tmp<0) return 0; | |||
ip[i]+=tmp; | |||
} | |||
return 32; | |||
} |