diff --git a/ip6.h b/ip6.h index 4e7680e..c71615c 100644 --- a/ip6.h +++ b/ip6.h @@ -2,9 +2,15 @@ #define IP6_H #include "byte.h" +#include "uint32.h" -unsigned int scan_ip6(const char *src,char *ip); -unsigned int fmt_ip6(char *dest,const char *ip); +unsigned int scan_ip6(const char* src,char* ip); +unsigned int fmt_ip6(char* dest,const char* ip); +unsigned int fmt_ip6c(char* dest,const char* ip); + +unsigned int scan_ip6if(const char* src,char* ip,uint32* scope_id); +unsigned int fmt_ip6if(char* dest,const char* ip,uint32 scope_id); +unsigned int fmt_ip6ifc(char* dest,const char* ip,uint32 scope_id); unsigned int scan_ip6_flat(const char *src,char *); unsigned int fmt_ip6_flat(char *dest,const char *); diff --git a/socket/fmt_ip6.3 b/socket/fmt_ip6.3 index d38a768..7a1e840 100644 --- a/socket/fmt_ip6.3 +++ b/socket/fmt_ip6.3 @@ -29,4 +29,4 @@ contain every possible fmt_ip6 output plus \\0. char ip[16]; buf[fmt_ip6(buf,ip)]=0; .SH "SEE ALSO" -scan_ip6(3), fmt_ip4(3) +fmt_ip6c(3), fmt_ip6if(3), scan_ip6(3), fmt_ip4(3) diff --git a/socket/fmt_ip6c.3 b/socket/fmt_ip6c.3 new file mode 100644 index 0000000..607a57d --- /dev/null +++ b/socket/fmt_ip6c.3 @@ -0,0 +1,32 @@ +.TH fmt_ip6c 3 +.SH NAME +fmt_ip6c \- write a formatted ASCII representation of an IPv6 number +.SH SYNTAX +.B #include + +unsigned int \fBfmt_ip6c\fP(char *\fIdest\fR,const char \fIip\fR[16]); +.SH DESCRIPTION +fmt_ip6c formats an IPv6 number in ASCII representation from \fIip\fR and +writes the result into \fIdest\fR. It returns the number of bytes +written. + +fmt_ip6c will apply "::" compression to the output. + +If \fIip\fR is an IPv4-mapped IPv6 address, fmt_ip6c will output it as +IPv4 address. + +If \fIdest\fR equals FMT_LEN (i.e. is zero), fmt_ip6c returns the number +of bytes it would have written. + +fmt_ip6c does not append \\0. + +For convenience, ip6.h defines the integer IP6_FMT to be big enough to +contain every possible fmt_ip6c output plus \\0. +.SH EXAMPLE +#include + + char buf[IP6_FMT]; + char ip[16]; + buf[fmt_ip6c(buf,ip)]=0; +.SH "SEE ALSO" +fmt_ip6(3), fmt_ip6ifc(3), scan_ip6(3), fmt_ip4(3) diff --git a/socket/fmt_ip6c.c b/socket/fmt_ip6c.c new file mode 100644 index 0000000..64ac8de --- /dev/null +++ b/socket/fmt_ip6c.c @@ -0,0 +1,13 @@ +#include "fmt.h" +#include "byte.h" +#include "ip4.h" +#include "ip6.h" + +unsigned int fmt_ip6c(char *s,const char ip[16]) +{ + if (ip6_isv4mapped(ip)) + return fmt_ip4(s,ip+12); + else + return fmt_ip6(s,ip); +} + diff --git a/socket/fmt_ip6if.3 b/socket/fmt_ip6if.3 new file mode 100644 index 0000000..b8fa4f7 --- /dev/null +++ b/socket/fmt_ip6if.3 @@ -0,0 +1,35 @@ +.TH fmt_ip6if 3 +.SH NAME +fmt_ip6if \- write a formatted ASCII representation of an IPv6 number +.SH SYNTAX +.B #include + +unsigned int \fBfmt_ip6if\fP(char *\fIdest\fR,const char \fIip\fR[16],uint32 \fIscope_id\fR); +.SH DESCRIPTION +fmt_ip6if formats an IPv6 number in ASCII representation from \fIip\fR and +writes the result into \fIdest\fR. It returns the number of bytes +written. + +fmt_ip6if will apply "::" compression to the output. + +If \fIip\fR is an IPv4-mapped IPv6 address, fmt_ip6if will output the last +4 bytes as IPv4 number in dotted-decimal notation. + +If \fIdest\fR equals FMT_LEN (i.e. is zero), fmt_ip6if returns the number +of bytes it would have written. + +fmt_ip6 does not append \\0. + +ip6.h defines the integer IP6_FMT to be big enough to contain every +possible fmt_ip6 output plus \\0. However, for fmt_ip6if you need to +add 1 for the '%' and IF_NAMESIZE from for the interface +name. +.SH EXAMPLE +#include + + char buf[IP6_FMT]; + char ip[16]; + scope_id sid; + buf[fmt_ip6if(buf,ip,sid)]=0; +.SH "SEE ALSO" +scan_ip6(3), fmt_ip4(3) diff --git a/socket/fmt_ip6if.c b/socket/fmt_ip6if.c new file mode 100644 index 0000000..aba677e --- /dev/null +++ b/socket/fmt_ip6if.c @@ -0,0 +1,15 @@ +#include "ip6.h" +#include "str.h" +#include "fmt.h" +#include "socket.h" + +unsigned int fmt_ip6if(char* dest,const char* ip,uint32 scope_id) { + int i=fmt_ip6(dest,ip); + if (scope_id) { + if (dest) { + dest[i]='%'; ++i; dest+=i; + } + i+=fmt_str(dest,socket_getifname(scope_id)); + } + return i; +} diff --git a/socket/fmt_ip6ifc.3 b/socket/fmt_ip6ifc.3 new file mode 100644 index 0000000..34eb12b --- /dev/null +++ b/socket/fmt_ip6ifc.3 @@ -0,0 +1,35 @@ +.TH fmt_ip6ifc 3 +.SH NAME +fmt_ip6ifc \- write a formatted ASCII representation of an IPv6 number +.SH SYNTAX +.B #include + +unsigned int \fBfmt_ip6ifc\fP(char *\fIdest\fR,const char \fIip\fR[16],uint32 \fIscope_id\fR); +.SH DESCRIPTION +fmt_ip6ifc formats an IPv6 number in ASCII representation from \fIip\fR and +writes the result into \fIdest\fR. It returns the number of bytes +written. + +fmt_ip6ifc will apply "::" compression to the output. + +If \fIip\fR is an IPv4-mapped IPv6 address, fmt_ip6ifc will output it as +IPv4 address. + +If \fIdest\fR equals FMT_LEN (i.e. is zero), fmt_ip6ifc returns the number +of bytes it would have written. + +fmt_ip6 does not append \\0. + +ip6.h defines the integer IP6_FMT to be big enough to contain every +possible fmt_ip6 output plus \\0. However, for fmt_ip6ifc you need to +add 1 for the '%' and IF_NAMESIZE from for the interface +name. +.SH EXAMPLE +#include + + char buf[IP6_FMT]; + char ip[16]; + scope_id sid; + buf[fmt_ip6ifc(buf,ip,sid)]=0; +.SH "SEE ALSO" +scan_ip6(3), fmt_ip4(3) diff --git a/socket/fmt_ip6ifc.c b/socket/fmt_ip6ifc.c new file mode 100644 index 0000000..51f872d --- /dev/null +++ b/socket/fmt_ip6ifc.c @@ -0,0 +1,13 @@ +#include "fmt.h" +#include "byte.h" +#include "ip4.h" +#include "ip6.h" + +unsigned int fmt_ip6ifc(char *s,const char ip[16],uint32 scope_id) +{ + if (ip6_isv4mapped(ip)) + return fmt_ip4(s,ip+12); + else + return fmt_ip6if(s,ip,scope_id); +} + diff --git a/socket/scan_ip6if.3 b/socket/scan_ip6if.3 new file mode 100644 index 0000000..1d60787 --- /dev/null +++ b/socket/scan_ip6if.3 @@ -0,0 +1,41 @@ +.TH scan_ip6if 3 +.SH NAME +scan_ip6 \- parse an IPv6 number and interface in ASCII representation +.SH SYNTAX +.B #include + +int \fBscan_ip6if\fP(const char *\fIsrc\fR,char \fIip\fR[16],uint32* scope_id); +.SH DESCRIPTION +scan_ip6if parses an IPv6 number in RFC1884 ASCII representation +from \fIsrc\fR and writes the result into \fIip\fR. If the IPv6 number +is followed by the percent sign, scan_ip6if takes the word following +that, tries to parse it as network interface and writes the result to +\fIscope_id\fR. + +It returns the number of bytes read from \fIsrc\fR or 0 if the parsing +failed. + +scan_ip6if 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_ip6if 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_ip6if does not recognize octal +(like \fB0177.0.0.1\fR) or hexadecimal numbers (like \fB0x7f000001\fR) +in the IPv4 part. +.SH EXAMPLE +#include +.br +#include + + char buf[]="::1%lo"; + char ip[16]; + uint32 scope_id; + if (scan_ip6if(buf,ip,&scope_id) != str_len(buf)) + parse_error(); + +.SH "SEE ALSO" +fmt_ip6(3), scan_ip4(3), fmt_ip6if(3) diff --git a/socket/scan_ip6if.c b/socket/scan_ip6if.c new file mode 100644 index 0000000..ec1a794 --- /dev/null +++ b/socket/scan_ip6if.c @@ -0,0 +1,29 @@ +#include "ip6.h" +#include "byte.h" +#include +#include "socket.h" +#if defined(__linux__) +#include +#endif + +unsigned int scan_ip6if(const char* src,char* ip,uint32* scope_id) { + int i=scan_ip6(src,ip); + *scope_id=0; + if (src[i]=='%') { + int j; + char* tmp; + for (j=i+1; isalnum(src[j]); ++j) ; + if (!src[j]) + tmp=(char*)src+i+1; + else { + tmp=alloca(j-i); + byte_copy(tmp,j-(i+1),src+i+1); + tmp[j-(i+1)]=0; + } + if (*tmp) { + *scope_id=socket_getifidx(tmp); + return j; + } + } + return i; +} diff --git a/socket/socket_getifname.c b/socket/socket_getifname.c index 21b4514..1902fd5 100644 --- a/socket/socket_getifname.c +++ b/socket/socket_getifname.c @@ -7,7 +7,7 @@ #include "haven2i.h" #ifdef HAVE_N2I -static char ifname[IFNAMSIZ]; +static char ifname[IF_NAMESIZE]; const char* socket_getifname(uint32 _interface) { char *tmp=if_indextoname(_interface,ifname); diff --git a/t.c b/t.c index 8e3db16..68aece6 100644 --- a/t.c +++ b/t.c @@ -18,16 +18,31 @@ #include #include #include +#include #define rdtscl(low) \ __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx") int main(int argc,char* argv[]) { + char buf[IP6_FMT+100]; + int i; + char ip[16]; + uint32 scope_id; + char* s="fec0::1:220:e0ff:fe69:ad92%eth0/64"; + char blubip[16]="\0\0\0\0\0\0\0\0\0\0\xff\xff\x7f\0\0\001"; + i=scan_ip6if(s,ip,&scope_id); + assert(s[i]=='/'); + buffer_put(buffer_1,buf,fmt_ip6if(buf,ip,scope_id)); + buffer_putnlflush(buffer_1); + buffer_put(buffer_1,buf,fmt_ip6ifc(buf,blubip,scope_id)); + buffer_putnlflush(buffer_1); +#if 0 char buf[100]; int i; printf("%d\n",i=fmt_pad(buf,"fnord",5,7,10)); buf[i]=0; puts(buf); +#endif #if 0 char ip[16]; char buf[32];