libowfat/socket/scan_ip6.c

89 lines
1.8 KiB
C
Raw Normal View History

2001-02-05 22:09:26 +00:00
#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
*/
2014-03-14 19:42:54 +00:00
size_t scan_ip6(const char *s,char ip[16])
2001-02-05 22:09:26 +00:00
{
2014-03-14 19:42:54 +00:00
size_t i;
size_t len=0;
2001-02-05 22:09:26 +00:00
unsigned long u;
char suffix[16];
unsigned int prefixlen=0;
unsigned int suffixlen=0;
2001-02-05 22:09:26 +00:00
2001-06-18 21:28:21 +00:00
if ((i=scan_ip4(s,ip+12))) {
for (len=0; len<12; ++len) ip[len]=V4mappedprefix[len];
return i;
}
for (i=0; i<16; i++) ip[i]=0;
2001-02-05 22:09:26 +00:00
for (;;) {
if (*s == ':') {
++len;
++s;
if (*s == ':') { /* Found "::", skip to part 2 */
++len;
++s;
2001-02-05 22:09:26 +00:00
break;
}
}
i = scan_xlong(s,&u);
if (!i) return 0;
if (prefixlen==12 && s[i]=='.') {
/* the last 4 bytes may be written as IPv4 address */
2001-06-18 21:28:21 +00:00
i=scan_ip4(s,ip+12);
2001-02-05 22:09:26 +00:00
if (i)
return i+len;
else
return 0;
}
2014-03-14 19:42:54 +00:00
ip[prefixlen++] = (char)(u >> 8);
ip[prefixlen++] = (char)u;
2001-02-05 22:09:26 +00:00
s += i; len += i;
if (prefixlen==16)
return len;
}
/* part 2, after "::" */
for (;;) {
if (*s == ':') {
if (suffixlen==0)
break;
s++;
len++;
} else if (suffixlen)
2001-02-05 22:09:26 +00:00
break;
i = scan_xlong(s,&u);
if (!i) {
if (suffixlen)
--len;
2001-02-05 22:09:26 +00:00
break;
}
if (suffixlen+prefixlen<=12 && s[i]=='.') {
2014-03-14 19:42:54 +00:00
size_t j=scan_ip4(s,suffix+suffixlen);
2001-02-05 22:09:26 +00:00
if (j) {
suffixlen+=4;
len+=j;
break;
} else
prefixlen=12-suffixlen; /* make end-of-loop test true */
}
2014-03-14 19:42:54 +00:00
suffix[suffixlen++] = (char)(u >> 8);
suffix[suffixlen++] = (char)u;
2001-02-05 22:09:26 +00:00
s += i; len += i;
if (prefixlen+suffixlen==16)
break;
}
for (i=0; i<suffixlen; i++)
ip[16-suffixlen+i] = suffix[i];
return len;
}