33 # include <ws2tcpip.h>
75 if (self->_addrport) {
76 prefix = (ipv4format ?
"" :
"[::ffff:");
77 suffix = (ipv4format ?
":" :
"]:" );
79 prefix = (ipv4format ?
"" :
"::ffff:");
83 if (self->_addrport) {
84 return g_strdup_printf(
"%s%d.%d.%d.%d%s%d",
86 ((
const guchar*)self->_addrbody)[12],
87 ((
const guchar*)self->_addrbody)[13],
88 ((
const guchar*)self->_addrbody)[14],
89 ((
const guchar*)self->_addrbody)[15],
93 return g_strdup_printf(
"%s%d.%d.%d.%d",
95 ((
const guchar*)self->_addrbody)[12],
96 ((
const guchar*)self->_addrbody)[13],
97 ((
const guchar*)self->_addrbody)[14],
98 ((
const guchar*)self->_addrbody)[15]);
120 switch (self->_addrtype) {
126 const int ipv4prefixlen = 12;
129 if (memcmp(self->_addrbody, ipv4loop,
sizeof(ipv4loop)) == 0) {
131 memcpy(ipv6addr, ipv6loop,
sizeof(ipv6loop));
133 memcpy(ipv6addr+ipv4prefixlen, self->_addrbody, 4);
142 g_return_val_if_reached(NULL);
151 GString* gsret = NULL;
154 if (self->_addrport) {
155 return g_strdup_printf(
"%d.%d.%d.%d:%d",
156 ((
const guchar*)self->_addrbody)[0],
157 ((
const guchar*)self->_addrbody)[1],
158 ((
const guchar*)self->_addrbody)[2],
159 ((
const guchar*)self->_addrbody)[3],
162 return g_strdup_printf(
"%d.%d.%d.%d",
163 ((
const guchar*)self->_addrbody)[0],
164 ((
const guchar*)self->_addrbody)[1],
165 ((
const guchar*)self->_addrbody)[2],
166 ((
const guchar*)self->_addrbody)[3]);
168 gsret = g_string_new(
"");
170 gboolean doublecolonyet = FALSE;
171 gboolean justhaddoublecolon = FALSE;
173 guchar ipv4prefix[] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
174 if (self->_addrlen != 16) {
175 g_string_free(gsret, TRUE); gsret = NULL;
176 return g_strdup(
"{invalid ipv6}");
178 if (self->_addrport) {
179 g_string_append(gsret,
"[");
181 if (memcmp(self->_addrbody, ipv4prefix,
sizeof(ipv4prefix)) == 0) {
182 g_string_free(gsret, TRUE); gsret = NULL;
185 for (nbyte = 0; nbyte <
self->_addrlen; nbyte += 2) {
186 guint16 byte0 = ((
const guchar*)self->_addrbody)[nbyte];
187 guint16
byte1 = ((
const guchar*)self->_addrbody)[nbyte+1];
188 guint16 word = (byte0 << 8 |
byte1);
189 if (!doublecolonyet && word == 0x00) {
193 if (zerocount == 1) {
194 g_string_append_printf(gsret, (nbyte == 2 ?
"0" :
":0"));
196 }
else if (zerocount > 1) {
197 g_string_append_printf(gsret,
"::");
199 doublecolonyet = TRUE;
200 justhaddoublecolon = TRUE;
202 g_string_append_printf(gsret
203 , ((nbyte == 0 || justhaddoublecolon) ?
"%x" :
":%x"), word);
204 justhaddoublecolon = FALSE;
206 if (zerocount == 1) {
207 g_string_append_printf(gsret,
":00");
208 }
else if (zerocount > 1) {
209 g_string_append_printf(gsret,
"::");
211 if (self->_addrport) {
212 g_string_append_printf(gsret,
"]:%d", self->_addrport);
216 for (nbyte = 0; nbyte <
self->_addrlen; ++nbyte) {
217 g_string_append_printf(gsret, (nbyte == 0 ?
"%02x" :
":%02x"),
218 ((
const guchar*)self->_addrbody)[nbyte]);
222 g_string_free(gsret, FALSE);
235 DEBUGMSG5(
"%s.%d: Comparing (type %d, length %d) vs (type %d, length %d)"
240 && self->_addrport != other->
_addrport) {
248 const guchar *selfabody =
self->_addrbody;
251 if (memcmp(selfabody, ipv6v4,
sizeof(ipv6v4)) == 0
252 && memcmp(selfabody+12, other->
_addrbody, 4) == 0) {
259 if (memcmp(self->_addrbody, ipv6loop,
sizeof(ipv6loop)) == 0
260 && memcmp(other->
_addrbody, ipv4loop,
sizeof(ipv4loop)) == 0) {
270 if (memcmp(self->_addrbody, ipv6loop,
sizeof(ipv6loop)) == 0) {
272 if (memcmp(other->
_addrbody, ipv4loopversion2,
sizeof(ipv4loopversion2)) == 0) {
275 }
else if (memcmp(self->_addrbody, ipv4loopversion2,
sizeof(ipv4loopversion2)) == 0) {
277 if (memcmp(other->
_addrbody, ipv6loop,
sizeof(ipv6loop)) == 0) {
292 , (retval ?
"True" :
"False"));
302 memcmprc = memcmp(self->_addrbody, other->
_addrbody, self->_addrlen);
304 , self->_addrlen, memcmprc);
305 return memcmprc == 0;
318 const guint shift = 7;
319 static guint hashseed = 0;
322 const NetAddr* addrtouse =
self;
325 while (0 == hashseed) {
326 hashseed = (guint)g_random_int();
331 , self->_addrtype, self->_addrlen, self->_addrport);
337 if (memcmp(self->_addrbody, ipv4loop,
sizeof(ipv4loop))== 0) {
347 if (memcmp(self->_addrbody, ipv4loopversion2,
sizeof(ipv4loopversion2)) == 0) {
354 g_return_val_if_fail(addrtouse != NULL, 0);
355 result = (guint)(addrtouse->
_addrtype) ^ hashseed;
359 for (j=0; j < addrtouse->
_addrlen; ++j) {
364 result = ((result << shift) | (result >> (
sizeof(result)*
CHAR_BIT - shift)))
365 ^ ((guint)((guint8*)addrtouse->
_addrbody)[j]);
380 return a_lhs->
equal(a_lhs, a_rhs);
388 return self->hash(
self);
396 if (self->_addrbody) {
397 FREE(self->_addrbody);
398 self->_addrbody = NULL;
409 return self->_addrport;
417 self->_addrport = port;
425 return self->_addrtype;
432 if (self->_addrbody == NULL) {
436 switch (self->_addrtype) {
438 guint8 byte0 = ((guint8*)self->_addrbody)[0];
439 return (byte0 >= 224 && byte0 <= 239);
449 switch (self->_addrtype) {
451 guint8 byte0 = ((guint8*)self->_addrbody)[0];
452 return byte0 == 127;;
455 const guint8 ipv6local[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
456 const guint8 ipv4localprefix[13] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff, 127};
457 if (memcmp(self->_addrbody, ipv6local,
sizeof(ipv6local)) == 0) {
460 if (memcmp(self->_addrbody, ipv4localprefix,
sizeof(ipv4localprefix)) == 0) {
477 gconstpointer addrbody,
485 if (objsize <
sizeof(
NetAddr)) {
488 g_return_val_if_fail(addrbody != NULL, NULL);
489 g_return_val_if_fail(addrlen >= 4, NULL);
496 g_return_val_if_fail(
self != NULL, NULL);
503 self->_addrtype = addrtype;
504 self->_addrlen = addrlen;
507 self->_addrbody = g_memdup(addrbody, addrlen);
528 guint8 stack_protector_dummy[8];
538 (void)stack_protector_dummy;
542 g_debug(
"CHECKING [%s]", addrstr);
546 for (j=0; addrstr[j]; ++j) {
548 g_debug(
"Looking at '%c'", addrstr[j]);
551 case '0':
case '1':
case '2':
case '3':
case '4':
552 case '5':
case '6':
case '7':
case '8':
case '9':
556 if (whichdot >=
DIMOF(dotpositions)
560 dotpositions[whichdot] = j;
575 g_debug(
"Illegal character [%c]", addrstr[j]);
586 g_debug(
"whichdot = %d", whichdot);
591 byte = atoi(addrstr);
593 g_debug(
"byte %d = %d", 0, byte);
595 if (byte < 0 || byte > 255) {
601 for (j=0; j <
DIMOF(dotpositions); ++j) {
602 byte = atoi(addrstr+dotpositions[j]+1);
604 g_debug(
"byte %d = %d", j, byte);
606 if (byte < 0 || byte > 255) {
609 addresses[j+1] = (guint8)byte;
612 if (colonpos > (lastpos - 2)) {
615 port = atoi(addrstr+colonpos+1);
617 g_debug(
"found bad (%s) IPV4 port", addrstr+colonpos+1);
621 g_debug(
"found good IPV4 port [%d]", port);
625 g_debug(
"Returning good IPV4 address!");
629 g_debug(
"Returning good IPV4 address [%p]!", ret);
660 int len = strlen(addrstr);
661 const char * firstaddrdigit = addrstr;
662 const char * lastaddrdigit = addrstr+len-1;
663 const char * curaddrdigit;
666 guint16 addrchunks[8];
667 guint8 addrbytes[16];
669 guint chunkindex = 0;
670 int coloncolonindex = -1;
671 guint coloncolonlength = 0;
672 char* firstbadhexchar = NULL;
674 const char v4prefix[] =
"ffff:";
675 const guint v4prefixlen =
sizeof(v4prefix)-1;
676 gboolean v4encapsulated = FALSE;
677 guint conversionbase = 16;
678 char delimchar =
':';
679 guint maxchunkindex =
DIMOF(addrchunks);
680 long maxchunkvalue = 65535;
683 memset(addrchunks, 0,
sizeof(addrchunks));
685 if (*addrstr ==
'[') {
687 char * rbracketpos = strchr(addrstr+1,
']');
688 char * firstbadchar = rbracketpos;
690 if (rbracketpos == NULL || rbracketpos[1] !=
':') {
694 lastaddrdigit = rbracketpos - 1;
695 port = strtol(rbracketpos+2, &firstbadchar, 10);
696 if (*firstbadchar !=
'\0' || port <= 0 || port >= 65536) {
697 DEBUGMSG5(
"%s.%d: Not IPv6 format due to bad port number syntax"
703 if (firstaddrdigit[0] ==
':' && firstaddrdigit[1] ==
':') {
707 DEBUGMSG5(
"%s.%d: LOOKING to see if we have an encapsulated IPv4 address. [%s] [%s]"
709 if (strncmp(firstaddrdigit, v4prefix, v4prefixlen) == 0) {
710 DEBUGMSG5(
"%s.%d: May have an encapsulated IPv4 address. [%s]"
712 if (strchr(firstaddrdigit + v4prefixlen,
'.') != NULL) {
714 DEBUGMSG5(
"%s.%d: Appear to have an encapsulated IPv4 address."
716 v4encapsulated = TRUE;
721 firstaddrdigit += v4prefixlen;
725 curaddrdigit = firstaddrdigit;
727 for (chunkindex=0; chunkindex < maxchunkindex && curaddrdigit <= lastaddrdigit; ++chunkindex) {
728 long chunk = strtol(curaddrdigit, &firstbadhexchar, conversionbase);
730 , chunkindex, curaddrdigit, (
unsigned long)chunk);
731 if (chunk < 0 || chunk > maxchunkvalue) {
732 DEBUGMSG5(
"%s.%d: Not IPv6 format due to invalid chunk value [%ld]"
737 addrchunks[chunkindex] = (guint16)chunk;
740 if (firstbadhexchar <= lastaddrdigit && *firstbadhexchar != delimchar) {
741 DEBUGMSG5(
"%s.%d: Not IPv6 format due to invalid character [%c]"
745 curaddrdigit = firstbadhexchar;
746 if (v4encapsulated && *firstbadhexchar == delimchar) {
749 }
else if (!v4encapsulated && firstbadhexchar[0] ==
':') {
750 if (firstbadhexchar[1] ==
':') {
751 if (coloncolonindex >= 0) {
753 DEBUGMSG5(
"%s.%d: Not IPv6 format due to multiple ::'s"
757 coloncolonindex = chunkindex + 1;
762 }
else if (*firstbadhexchar !=
']' && *firstbadhexchar !=
'\0') {
763 DEBUGMSG5(
"%s.%d: Not IPv6 format due to illegal char [%c]"
768 if (firstbadhexchar >= lastaddrdigit + 1) {
772 if (firstbadhexchar != NULL && firstbadhexchar != lastaddrdigit + 1) {
774 DEBUGMSG5(
"%s.%d: firstbadhexchar = %p, lastaddrdigit = %p, diff=%ld"
775 ,
__FUNCTION__, __LINE__, firstbadhexchar, lastaddrdigit
776 , (
long)(lastaddrdigit-firstbadhexchar));
779 if (coloncolonindex >= 0 && chunkindex ==
DIMOF(addrchunks)-1) {
780 DEBUGMSG5(
"%s.%d: Not IPv6 format due to full length with :: present"
784 if (coloncolonindex < 0 && chunkindex !=
DIMOF(addrchunks)-1) {
785 DEBUGMSG5(
"%s.%d: Not IPv6 format due to too few digits."
791 if (coloncolonindex >= 0) {
792 coloncolonlength = (
DIMOF(addrchunks)-1) - chunkindex;
794 , coloncolonlength, coloncolonindex);
801 if (v4encapsulated) {
804 const guint offset =
sizeof(v4prefix);
805 if (chunkindex != 3) {
806 DEBUGMSG5(
"%s.%d: Not IPv4 encapsulated as IPv6 format due to too few digits."
810 memcpy(addrbytes, v4prefix,
sizeof(v4prefix));
811 addrbytes[offset+0] = (guint8)addrchunks[0];
812 addrbytes[offset+1] = (guint8)addrchunks[1];
813 addrbytes[offset+2] = (guint8)addrchunks[2];
814 addrbytes[offset+3] = (guint8)addrchunks[3];
817 memset(addrbytes, 0,
DIMOF(addrbytes));
819 for (j=0; j <= chunkindex; ++j) {
821 if (((gint)j) == coloncolonindex) {
823 memset(addrptr, 0, coloncolonlength*2);
824 addrptr += 2*coloncolonlength;
827 addrptr[0] = (((addrchunks[j]) >> 8) & 0xff);
828 addrptr[1] = addrchunks[j] & 0xff;
832 if (coloncolonindex == (gint)chunkindex + 1) {
833 DEBUGMSG5(
"%s.%d: Appending %d zeros to the end of the address"
835 memset(addrptr, 0, coloncolonlength*2);
836 addrptr += 2*coloncolonlength;
839 , (
long)(addrptr-addrbytes));
840 g_return_val_if_fail(addrptr == addrbytes+
DIMOF(addrbytes), NULL);
843 DUMP5(addrstr, &retval->
baseclass,
" Converted the former into the latter...(ignore the extra ':')");
851 if (addrstr[0] ==
'[' || addrstr[0] ==
':') {
869 g_return_val_if_fail(maclen == 6 || maclen == 8, NULL);
911 const struct sockaddr_in* sa_in = (
const struct sockaddr_in*)sa_in6;
914 switch(sa_in->sin_family) {
926 g_return_val_if_reached(NULL);
932 struct sockaddr_in6 saddr;
934 memset(&saddr, 0x00,
sizeof(saddr));
936 switch (self->_addrtype) {
938 g_return_val_if_fail(4 == self->_addrlen, saddr);
939 saddr.sin6_family = AF_INET6;
940 saddr.sin6_port = htons(self->_addrport);
944 saddr.sin6_addr.s6_addr[10] = 0xff;
945 saddr.sin6_addr.s6_addr[11] = 0xff;
946 memcpy(saddr.sin6_addr.s6_addr+12, self->_addrbody, self->_addrlen);
947 DEBUGMSG3(
"%s:%s: sin6_family 0x%x, sin6_port %d"
949 , saddr.sin6_family, ntohs(saddr.sin6_port));
950 DEBUGMSG3(
"%s:%s:s6_addr(v4): %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
952 , saddr.sin6_addr.s6_addr[0],saddr.sin6_addr.s6_addr[1]
953 , saddr.sin6_addr.s6_addr[2],saddr.sin6_addr.s6_addr[3]
954 , saddr.sin6_addr.s6_addr[4],saddr.sin6_addr.s6_addr[5]
955 , saddr.sin6_addr.s6_addr[6],saddr.sin6_addr.s6_addr[7]
956 , saddr.sin6_addr.s6_addr[8],saddr.sin6_addr.s6_addr[8]
957 , saddr.sin6_addr.s6_addr[10],saddr.sin6_addr.s6_addr[11]
958 , saddr.sin6_addr.s6_addr[12],saddr.sin6_addr.s6_addr[13]
959 , saddr.sin6_addr.s6_addr[14],saddr.sin6_addr.s6_addr[15]);
964 g_return_val_if_fail(16 == self->_addrlen, saddr);
965 saddr.sin6_family = AF_INET6;
966 saddr.sin6_port = htons(self->_addrport);
967 memcpy(&saddr.sin6_addr, self->_addrbody, self->_addrlen);
971 g_return_val_if_reached(saddr);
979 struct sockaddr_in saddr;
981 memset(&saddr, 0x00,
sizeof(saddr));
983 switch (self->_addrtype) {
985 g_return_val_if_fail(4 == self->_addrlen, saddr);
986 saddr.sin_family = AF_INET;
987 saddr.sin_port = htons(self->_addrport);
988 memcpy(&saddr.sin_addr, self->_addrbody, 4);
992 g_return_val_if_reached(saddr);