The Assimilation Project  based on Assimilation version 1.1.2.1454725746
netaddr.c
Go to the documentation of this file.
1 
27 #include <stdlib.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include <projectcommon.h>
31 #include <netaddr.h>
32 #include <address_family_numbers.h>
33 #ifdef _MSC_VER
34 # include <ws2tcpip.h>
35 #endif
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39 #ifdef HAVE_SYS_SOCKET_H
40 # include <sys/socket.h>
41 #endif
42 #ifdef HAVE_NETDB_H
43 # include <netdb.h>
44 #endif
45 
46 FSTATIC struct sockaddr_in6 _netaddr_ipv6sockaddr(const NetAddr* self);
47 FSTATIC struct sockaddr_in _netaddr_ipv4sockaddr(const NetAddr* self);
49 FSTATIC guint16 _netaddr_port(const NetAddr* self);
50 FSTATIC void _netaddr_setport(NetAddr* self, guint16);
51 FSTATIC guint16 _netaddr_addrtype(const NetAddr* self);
52 FSTATIC gboolean _netaddr_ismcast(const NetAddr* self);
53 FSTATIC gboolean _netaddr_islocal(const NetAddr* self);
54 FSTATIC gboolean _netaddr_isanyaddr(const NetAddr* self);
55 FSTATIC gconstpointer _netaddr_addrinnetorder(gsize *addrlen);
56 FSTATIC gboolean _netaddr_equal(const NetAddr*, const NetAddr*);
57 FSTATIC guint _netaddr_hash(const NetAddr*);
58 FSTATIC gchar * _netaddr_toStringflex(const NetAddr*, gboolean canonformat);
59 FSTATIC gchar * _netaddr_toString(gconstpointer);
60 FSTATIC gchar * _netaddr_canonStr(const NetAddr*);
62 FSTATIC gchar * _netaddr_toString_ipv6_ipv4(const NetAddr* self, gboolean ipv4format);
63 FSTATIC NetAddr* _netaddr_string_ipv4_new(const char* addrstr);
64 FSTATIC NetAddr* _netaddr_string_ipv6_new(const char* addrstr);
65 FSTATIC NetAddr* _netaddr_string_macaddr_new(const char* addrstr);
66 
68 
76 
77 static const guchar ipv6loop [16] = CONST_IPV6_LOOPBACK;
78 static const guchar ipv4loopversion2 [16] = {CONST_IPV6_IPV4SPACE, 127, 0, 0, 1};
79 static const guchar ipv4loop [4] = CONST_IPV4_LOOPBACK;
80 
82 FSTATIC gchar *
83 _netaddr_toString_ipv6_ipv4(const NetAddr* self, gboolean ipv4format)
84 {
85  const char * prefix;
86  const char * suffix;
87  if (self->_addrport) {
88  prefix = (ipv4format ? "" : "[::ffff:");
89  suffix = (ipv4format ? ":" : "]:" );
90  }else{
91  prefix = (ipv4format ? "" : "::ffff:");
92  suffix = ""; // Not used
93  }
94 
95  if (self->_addrport) {
96  return g_strdup_printf("%s%d.%d.%d.%d%s%d",
97  prefix,
98  ((const guchar*)self->_addrbody)[12],
99  ((const guchar*)self->_addrbody)[13],
100  ((const guchar*)self->_addrbody)[14],
101  ((const guchar*)self->_addrbody)[15],
102  suffix,
103  self->_addrport);
104  }
105  return g_strdup_printf("%s%d.%d.%d.%d",
106  prefix,
107  ((const guchar*)self->_addrbody)[12],
108  ((const guchar*)self->_addrbody)[13],
109  ((const guchar*)self->_addrbody)[14],
110  ((const guchar*)self->_addrbody)[15]);
111 }
114 FSTATIC gchar *
115 _netaddr_toString(gconstpointer baseobj)
116 {
117  const NetAddr* self = CASTTOCONSTCLASS(NetAddr, baseobj);
118  return _netaddr_toStringflex(self, FALSE);
119 }
120 
121 FSTATIC gchar *
123 {
124  return _netaddr_toStringflex(self, TRUE);
125 }
126 
128 NetAddr*
130 {
131 
132  switch (self->_addrtype) {
133  case ADDR_FAMILY_IPV6:
134  // Return a copy of this IPv6 address
135  return netaddr_ipv6_new(self->_addrbody, self->_addrport);
136 
137  case ADDR_FAMILY_IPV4: {
138  const int ipv4prefixlen = 12;
139  guchar ipv6addr[16] = {CONST_IPV6_IPV4SPACE, 0, 0, 0, 0};
140  // We have an IPv4 address we want to convert to an IPv6 address
141  if (memcmp(self->_addrbody, ipv4loop, sizeof(ipv4loop)) == 0) {
142  // Convert loopback addresses from v4 to v6
143  memcpy(ipv6addr, ipv6loop, sizeof(ipv6loop));
144  }else{
145  memcpy(ipv6addr+ipv4prefixlen, self->_addrbody, 4);
146  }
147  return netaddr_ipv6_new(ipv6addr, self->_addrport);
148  }
149 
150  default: // OOPS!
151  break;
152  }
154  g_return_val_if_reached(NULL);
155 }
156 
157 
159 FSTATIC gchar *
160 _netaddr_toStringflex(const NetAddr* self, gboolean canon_format)
161 {
162  gchar * ret = NULL;
163  GString* gsret = NULL;
164  int nbyte;
165  if (self->_addrtype == ADDR_FAMILY_IPV4) {
166  if (self->_addrport) {
167  return g_strdup_printf("%d.%d.%d.%d:%d",
168  ((const guchar*)self->_addrbody)[0],
169  ((const guchar*)self->_addrbody)[1],
170  ((const guchar*)self->_addrbody)[2],
171  ((const guchar*)self->_addrbody)[3],
172  self->_addrport);
173  }
174  return g_strdup_printf("%d.%d.%d.%d",
175  ((const guchar*)self->_addrbody)[0],
176  ((const guchar*)self->_addrbody)[1],
177  ((const guchar*)self->_addrbody)[2],
178  ((const guchar*)self->_addrbody)[3]);
179  }
180  gsret = g_string_new("");
181  if (self->_addrtype == ADDR_FAMILY_IPV6) {
182  gboolean doublecolonyet = FALSE;
183  gboolean justhaddoublecolon = FALSE;
184  int zerocount = 0;
185  guchar ipv4prefix[] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
186  if (self->_addrlen != 16) {
187  g_string_free(gsret, TRUE); gsret = NULL;
188  return g_strdup("{invalid ipv6}");
189  }
190  if (self->_addrport) {
191  g_string_append(gsret, "[");
192  }
193  if (memcmp(self->_addrbody, ipv4prefix, sizeof(ipv4prefix)) == 0) {
194  g_string_free(gsret, TRUE); gsret = NULL;
195  return _netaddr_toString_ipv6_ipv4(self, canon_format);
196  }
197  for (nbyte = 0; nbyte < self->_addrlen; nbyte += 2) {
198  guint16 byte0 = ((const guchar*)self->_addrbody)[nbyte];
199  guint16 byte1 = ((const guchar*)self->_addrbody)[nbyte+1];
200  guint16 word = (byte0 << 8 | byte1);
201  if (!doublecolonyet && word == 0x00) {
202  ++zerocount;
203  continue;
204  }
205  if (zerocount == 1) {
206  g_string_append_printf(gsret, (nbyte == 2 ? "0" : ":0"));
207  zerocount=0;
208  }else if (zerocount > 1) {
209  g_string_append_printf(gsret, "::");
210  zerocount=0;
211  doublecolonyet = TRUE;
212  justhaddoublecolon = TRUE;
213  }
214  g_string_append_printf(gsret
215  , ((nbyte == 0 || justhaddoublecolon) ? "%x" : ":%x"), word);
216  justhaddoublecolon = FALSE;
217  }
218  if (zerocount == 1) {
219  g_string_append_printf(gsret, ":00");
220  }else if (zerocount > 1) {
221  g_string_append_printf(gsret, "::");
222  }
223  if (self->_addrport) {
224  g_string_append_printf(gsret, "]:%d", self->_addrport);
225  }
226 
227  }else{
228  for (nbyte = 0; nbyte < self->_addrlen; ++nbyte) {
229  g_string_append_printf(gsret, (nbyte == 0 ? "%02x" : "-%02x"),
230  ((const guchar*)self->_addrbody)[nbyte]);
231  }
232  }
233  ret = gsret->str;
234  g_string_free(gsret, FALSE);
235  return ret;
236 }
237 
239 FSTATIC gboolean
240 _netaddr_equal(const NetAddr*self, const NetAddr*other)
241 {
243  const guchar ipv6v4 [12] = {CONST_IPV6_IPV4SPACE};// Where IPv4 addrs are found inside IPv6 space
244  gint memcmprc;
245 
246 
247  DEBUGMSG5("%s.%d: Comparing (type %d, length %d) vs (type %d, length %d)"
248  , __FUNCTION__, __LINE__, self->_addrtype, self->_addrlen, other->_addrtype, other->_addrlen)
249  DEBUGMSG5("%s.%d: checking ports for equality (if v4/v6 addresses)", __FUNCTION__, __LINE__)
250  if ((self->_addrtype == ADDR_FAMILY_IPV6 || self->_addrtype == ADDR_FAMILY_IPV4)
251  && (other->_addrtype == ADDR_FAMILY_IPV6 || other->_addrtype == ADDR_FAMILY_IPV4)
252  && self->_addrport != other->_addrport) {
253  DEBUGMSG5("%s.%d: selfport:%d, otherport:%d", __FUNCTION__, __LINE__, self->_addrport, other->_addrport);
254  return FALSE;
255  }
256 
257  if (self->_addrtype == ADDR_FAMILY_IPV6) {
258  DEBUGMSG5("%s.%d: self is IPv6", __FUNCTION__, __LINE__)
259  if (other->_addrtype == ADDR_FAMILY_IPV4) {
260  const guchar *selfabody = self->_addrbody;
261  // Check for equivalent IPv4 and IPv6 addresses
262  DEBUGMSG5("%s.%d: checking equivalent v6/v4 addresses", __FUNCTION__, __LINE__)
263  if (memcmp(selfabody, ipv6v4, sizeof(ipv6v4)) == 0
264  && memcmp(selfabody+12, other->_addrbody, 4) == 0) {
265  DEBUGMSG5("%s.%d: v6/v4 addresses are equivalent", __FUNCTION__, __LINE__)
266  return TRUE;
267  }
268  DEBUGMSG5("%s.%d: checking v6/v4 loopbacks", __FUNCTION__, __LINE__)
269  // Check for the equivalent loopback addresses between IPv4 and IPv6
271  if (memcmp(self->_addrbody, ipv6loop, sizeof(ipv6loop)) == 0
272  && memcmp(other->_addrbody, ipv4loop, sizeof(ipv4loop)) == 0) {
273  DEBUGMSG5("%s.%d: v6/v4 addresses are both loopbacks", __FUNCTION__, __LINE__)
274  return TRUE;
275  }
276  DEBUGMSG5("%s.%d: v6/v4 addresses are not equivalent", __FUNCTION__, __LINE__)
277  return FALSE;
278  }else if (other->_addrtype == ADDR_FAMILY_IPV6) {
279  // Well... Are we cross comparing the two types of ipv6 loopback addresses?
280  // These are: ::1 and ::ff:127.0.0.1 Kinda weird - but seems valid...
281  DEBUGMSG5("%s.%d: other is IPv6 too", __FUNCTION__, __LINE__)
282  if (memcmp(self->_addrbody, ipv6loop, sizeof(ipv6loop)) == 0) {
283  DEBUGMSG5("%s.%d: comparing loopbacks", __FUNCTION__, __LINE__);
284  if (memcmp(other->_addrbody, ipv4loopversion2, sizeof(ipv4loopversion2)) == 0) {
285  return TRUE;
286  }
287  }else if (memcmp(self->_addrbody, ipv4loopversion2, sizeof(ipv4loopversion2)) == 0) {
288  DEBUGMSG5("%s.%d: comparing loopbacks the other way", __FUNCTION__, __LINE__);
289  if (memcmp(other->_addrbody, ipv6loop, sizeof(ipv6loop)) == 0) {
290  return TRUE;
291  }
292  }
293  }
294  }
295 
296  DEBUGMSG5("%s.%d: checking to see if we need to reverse operands...", __FUNCTION__, __LINE__)
297 
298  if (self->_addrtype == ADDR_FAMILY_IPV4 && other->_addrtype == ADDR_FAMILY_IPV6) {
299  gboolean retval;
300  // Switch the operands and try again...
301  DEBUGMSG5("%s.%d: switching operands", __FUNCTION__, __LINE__)
302  retval = _netaddr_equal(other, self);
303  DEBUGMSG5("%s.%d: returning %s after switching operands", __FUNCTION__, __LINE__
304  , (retval ? "True" : "False"));
305  return retval;
306  }
307  DEBUGMSG5("%s.%d: checking type and length...", __FUNCTION__, __LINE__)
308  // Other than ipv4 vs ipv6 (handled above) we require addresses to be of the same type
309  if (self->_addrtype != other->_addrtype || self->_addrlen != other->_addrlen) {
310  DEBUGMSG5("%s.%d: self->addrtype:%d, other->addrtype:%d", __FUNCTION__, __LINE__, self->_addrtype, other->_addrtype);
311  DEBUGMSG5("%s.%d: self->addrlen: %d, other->addrlen: %d", __FUNCTION__, __LINE__, self->_addrlen, other->_addrlen);
312  return FALSE;
313  }
314  memcmprc = memcmp(self->_addrbody, other->_addrbody, self->_addrlen);
315  DEBUGMSG5("%s.%d: memcmp(self, other, %d) returned %d", __FUNCTION__, __LINE__
316  , self->_addrlen, memcmprc);
317  return memcmprc == 0;
318 }
319 
320 #ifndef CHAR_BIT
321 # define CHAR_BIT 8
322 #endif
323 FSTATIC guint
327 _netaddr_hash(const NetAddr* self)
328 {
329  // For an explanation of the random hash seed see https://lwn.net/Articles/474912/
330  const guint shift = 7;
331  static guint hashseed = 0;
332  int j;
333  NetAddr* v6addr = NULL;
334  const NetAddr* addrtouse = self;
335  guint result;
336  const guchar v6loopback[16] = CONST_IPV6_LOOPBACK;
337  while (0 == hashseed) {
338  hashseed = (guint)g_random_int();
339  }
340 
341 
342  DEBUGMSG5("%s.%d: %d/%d:%d NetAddr", __FUNCTION__, __LINE__
343  , self->_addrtype, self->_addrlen, self->_addrport);
344  // Convert v4 addresses into v6 so that we match the compare operation's behavior
345  if (self->_addrtype == ADDR_FAMILY_IPV4) {
346  DEBUGMSG5("%s.%d: Hashing IPv6", __FUNCTION__, __LINE__);
347 
348  // This is kind of high overhead... Could be optimized if need be
349  if (memcmp(self->_addrbody, ipv4loop, sizeof(ipv4loop))== 0) {
350  DEBUGMSG5("%s.%d: Returning an IPv6 loopback value", __FUNCTION__, __LINE__);
351  v6addr = netaddr_ipv6_new(v6loopback, self->_addrport);
352  }else{
353  DEBUGMSG5("%s.%d: Returning an IPv6 replacement value", __FUNCTION__, __LINE__);
354  v6addr = _netaddr_toIPv6(self);
355  }
356  addrtouse = v6addr;
357  }else if (self->_addrtype == ADDR_FAMILY_IPV6) {
358  DEBUGMSG5("%s.%d: Hashing IPv6", __FUNCTION__, __LINE__);
359  if (memcmp(self->_addrbody, ipv4loopversion2, sizeof(ipv4loopversion2)) == 0) {
360  DEBUGMSG5("%s.%d: Returning an IPv6 loopback value", __FUNCTION__, __LINE__);
361  v6addr = netaddr_ipv6_new(v6loopback, self->_addrport);
362  addrtouse = v6addr;
363  }
364  }
365 
366  g_return_val_if_fail(addrtouse != NULL, 0);
367  result = (guint)(addrtouse->_addrtype) ^ hashseed;
368  if (addrtouse->_addrtype == ADDR_FAMILY_IPV6 || addrtouse->_addrtype == ADDR_FAMILY_IPV4) {
369  result ^= addrtouse->_addrport;
370  }
371  for (j=0; j < addrtouse->_addrlen; ++j) {
372  // Circular shift with addrbody xored in...
373  // Addresses are typically either 4 bytes or 16 bytes (6 and 8 bytes are also possible)
374  // So 4 bytes means the first byte gets shifted by 28 bits, and 16 means it
375  // all wraps around a lot ;-)
376  result = ((result << shift) | (result >> (sizeof(result)*CHAR_BIT - shift)))
377  ^ ((guint)((guint8*)addrtouse->_addrbody)[j]);
378  }
379  if (v6addr) {
380  UNREF(v6addr);
381  addrtouse = NULL;
382  }
383  return result;
384 }
385 
387 WINEXPORT gboolean
388 netaddr_g_hash_equal(gconstpointer lhs, gconstpointer rhs)
389 {
390  const NetAddr* a_lhs = CASTTOCONSTCLASS(NetAddr, lhs);
391  const NetAddr* a_rhs = CASTTOCONSTCLASS(NetAddr, rhs);
392  return a_lhs->equal(a_lhs, a_rhs);
393 }
394 
396 WINEXPORT guint
397 netaddr_g_hash_hash(gconstpointer addrptr)
398 {
399  const NetAddr* self = CASTTOCONSTCLASS(NetAddr, addrptr);
400  return self->hash(self);
401 }
402 
404 FSTATIC void
406 {
407  NetAddr* self = CASTTOCLASS(NetAddr, base);
408  if (self->_addrbody) {
409  FREE(self->_addrbody);
410  self->_addrbody = NULL;
411  }
412  FREECLASSOBJ(self);
413  self = NULL;
414 }
415 
416 
418 FSTATIC guint16
419 _netaddr_port(const NetAddr* self)
420 {
421  return self->_addrport;
422 }
423 
424 
426 FSTATIC void
427 _netaddr_setport(NetAddr* self, guint16 port)
428 {
429  self->_addrport = port;
430 }
431 
432 
434 FSTATIC guint16
436 {
437  return self->_addrtype;
438 }
439 
441 FSTATIC gboolean
443 {
444  if (self->_addrbody == NULL) {
445  return FALSE;
446  }
448  switch (self->_addrtype) {
449  case ADDR_FAMILY_IPV4: {
450  guint8 byte0 = ((guint8*)self->_addrbody)[0];
451  return (byte0 >= 224 && byte0 <= 239);
452  }
453  break;;
454  }
455  return FALSE;
456 }
458 FSTATIC gboolean
460 {
461  switch (self->_addrtype) {
462  case ADDR_FAMILY_IPV4: {
463  guint8 byte0 = ((guint8*)self->_addrbody)[0];
464  return byte0 == 127;;
465  }
466  case ADDR_FAMILY_IPV6: {
467  const guint8 ipv6local[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
468  const guint8 ipv4localprefix[13] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff, 127};
469  if (memcmp(self->_addrbody, ipv6local, sizeof(ipv6local)) == 0) {
470  return TRUE;
471  }
472  if (memcmp(self->_addrbody, ipv4localprefix, sizeof(ipv4localprefix)) == 0) {
473  return TRUE;
474  }
475  break;
476  }
477 
478  default:
479  break;
480  }
481  return FALSE;
482 }
483 
484 FSTATIC gboolean
486 {
487  const guint8 anyaddr[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
488  const guint8 v6v4anyaddr[16] = {CONST_IPV6_IPV4SPACE, 0, 0, 0, 0};
489  if (self->_addrtype != ADDR_FAMILY_IPV4 && self->_addrtype != ADDR_FAMILY_IPV6) {
490  return FALSE;
491  }
492  if (memcmp(self->_addrbody, anyaddr, self->_addrlen) == 0) {
493  return TRUE;
494  }
495  return memcmp(self->_addrbody, v6v4anyaddr, self->_addrlen) == 0;
496 }
497 
498 
500 NetAddr*
501 netaddr_new(gsize objsize,
502  guint16 port,
503  guint16 addrtype,
504  gconstpointer addrbody,
505  guint16 addrlen)
506 {
507  AssimObj* baseobj;
508  NetAddr* self;
509 
510 
512  if (objsize < sizeof(NetAddr)) {
513  objsize = sizeof(NetAddr);
514  }
515  g_return_val_if_fail(addrbody != NULL, NULL);
516  g_return_val_if_fail(addrlen >= 4, NULL);
517 
518 
519 
520  baseobj = assimobj_new(objsize);
521  proj_class_register_subclassed(baseobj, "NetAddr");
522  self = CASTTOCLASS(NetAddr, baseobj);
523  g_return_val_if_fail(self != NULL, NULL);
524 
525  baseobj->_finalize = _netaddr_finalize;
526  baseobj->toString = _netaddr_toString;
527  self->canonStr = _netaddr_canonStr;
528  self->toIPv6 = _netaddr_toIPv6;
529  self->_addrport = port;
530  self->_addrtype = addrtype;
531  self->_addrlen = addrlen;
532  self->ipv6sockaddr = _netaddr_ipv6sockaddr;
533  self->ipv4sockaddr = _netaddr_ipv4sockaddr;
534  self->_addrbody = g_memdup(addrbody, addrlen);
535  self->port = _netaddr_port;
536  self->setport = _netaddr_setport;
537  self->addrtype = _netaddr_addrtype;
538  self->ismcast = _netaddr_ismcast;
539  self->islocal = _netaddr_islocal;
540  self->isanyaddr = _netaddr_isanyaddr;
541  self->equal = _netaddr_equal;
542  self->hash = _netaddr_hash;
543 
544  return self;
545 
546 }
547 
548 /*
549  *
550  * Let's get rid of this warning/error:
551  *
552  * error: stack protector not protecting function: all local arrays are less than 8 bytes long
553  *
554  * We used to have an extra array here just for this purpose, but in recent versions the optimizer
555  * realized we weren't using it, and eliminated it. So now we'll add it to the 'addresses' array.
556  * Hopefully some future optimizer won't realize they're just for the stack protector too...
557  *
558  * But the chances of that are small, because we pass it to netaddr_ipv4_new(), which in theory
559  * might use those extra bytes for *something*... Of course, it "knows" the array is 4 bytes
560  * long, because it's supposed to be a binary ipv4 address...
561  *
562  * In turn, it passes the array to netaddr_new(), along with a length of 4 (constant)
563  * All these functions are in the same file, so in theory a really good optimizer could figure
564  * this out and then screw us, but it would have to work a lot harder to do it ;-)
565  */
566 #define EXTRA_STACK_PROTECTOR_BYTES 8 // Make the stack protector really happy...
567 
570 _netaddr_string_ipv4_new(const char* addrstr)
571 {
572  // Must have four numbers [0-255] in decimal - optionally followed by : port number...
573  int dotpositions[3];
574  int colonpos = -1;
575  guint8 addresses[4 + EXTRA_STACK_PROTECTOR_BYTES];
576  guint whichdot = 0;
577  int byte;
578  NetAddr* ret;
579  int port = 0;
580 
581  guint j;
582  int debug = FALSE;
583  int lastpos = 0;
584 
585  //debug = g_ascii_isdigit(addrstr[0]);
586 
587  if (debug) {
588  g_debug("CHECKING [%s]", addrstr);
589  }
590 
591  // Scruffy IPv4 string format verification
592  for (j=0; addrstr[j]; ++j) {
593  if (debug) {
594  g_debug("Looking at '%c'", addrstr[j]);
595  }
596  switch(addrstr[j]) {
597  case '0': case '1': case '2': case '3': case '4':
598  case '5': case '6': case '7': case '8': case '9':
599  continue;
600 
601  case '.':
602  if (whichdot >= DIMOF(dotpositions)
603  || colonpos >= 0) {
604  return NULL;
605  }
606  dotpositions[whichdot] = j;
607  whichdot += 1;
608  continue;
609 
610  case '\0':
611  break;
612  case ':':
613  if (colonpos >= 0) {
614  return NULL;
615  }
616  colonpos = j;
617  break;
618 
619  default:
620  if (debug) {
621  g_debug("Illegal character [%c]", addrstr[j]);
622  }
623 
624  return NULL;
625  }
626  if (j > 21) {
627  return NULL;
628  }
629  }
630  lastpos = j;
631  if (debug) {
632  g_debug("whichdot = %d", whichdot);
633  }
634  if (whichdot != 3) {
635  return NULL;
636  }
637  byte = atoi(addrstr);
638  if (debug) {
639  g_debug("byte %d = %d", 0, byte);
640  }
641  if (byte < 0 || byte > 255) {
642  return NULL;
643  }
644  addresses[0] = byte;
645 
646 
647  for (j=0; j < DIMOF(dotpositions); ++j) {
648  byte = atoi(addrstr+dotpositions[j]+1);
649  if (debug) {
650  g_debug("byte %d = %d", j, byte);
651  }
652  if (byte < 0 || byte > 255) {
653  return NULL;
654  }
655  addresses[j+1] = (guint8)byte;
656  }
657  if (colonpos >= 0) {
658  if (colonpos > (lastpos - 2)) {
659  return NULL;
660  }
661  port = atoi(addrstr+colonpos+1);
662  if (port > 65535) {
663  g_debug("found bad (%s) IPV4 port", addrstr+colonpos+1);
664  return NULL;
665  }
666  if (debug) {
667  g_debug("found good IPV4 port [%d]", port);
668  }
669  }
670  if (debug) {
671  g_debug("Returning good IPV4 address!");
672  }
673  ret = netaddr_ipv4_new(addresses, port);
674  if (debug) {
675  g_debug("Returning good IPV4 address [%p]!", ret);
676  }
677  return ret;
678 }
679 
684 _netaddr_string_ipv6_new(const char* addrstr)
685 {
686 /*
687  * ipv6
688  * OR
689  * [ipv6]:decimal-port
690  *
691  * The 'IPv6' part is described by RFC 4291
692  *
693  *
694  * It consists of a sequence of 0-8 collections of 1-4 hexadecimal digits separated by
695  * colon characters.
696  * If there are fewer than 8 collections of digits, then there must be exactly one :: string
697  * in the address string. This :: tag represents a variable-length sequence of zeros in the address.
698  *
699  * There is also another variant on the format of the IPv6 portion:
700  *
701  * It can be "::ffff:" followed by an IPv4 address in typical IPv4 dotted decimal notation.
702  * @todo make _netaddr_string_ipv6_new() support the special format used for
703  * IPv6-encapsulated IPv4 addresses.
704  *
705  */
706  int len = strlen(addrstr);
707  const char * firstaddrdigit = addrstr;
708  const char * lastaddrdigit = addrstr+len-1;
709  const char * curaddrdigit;
710  unsigned j;
711  long port = 0;
712  guint16 addrchunks[8];
713  guint8 addrbytes[16];
714  guint8* addrptr;
715  guint chunkindex = 0;
716  int coloncolonindex = -1;
717  guint coloncolonlength = 0;
718  char* firstbadhexchar = NULL;
719  NetAddr* retval;
720  const char v4prefix[] = "ffff:";
721  const guint v4prefixlen = sizeof(v4prefix)-1;
722  gboolean v4encapsulated = FALSE;
723  guint conversionbase = 16;
724  char delimchar = ':';
725  guint maxchunkindex = DIMOF(addrchunks);
726  long maxchunkvalue = 65535;
727 
728  DEBUGMSG5("%s.%d(\"%s\")", __FUNCTION__, __LINE__, addrstr);
729  memset(addrchunks, 0, sizeof(addrchunks));
730 
731  if (*addrstr == '[') {
732  // Then we have a port number - look for ']' and ':'
733  char * rbracketpos = strchr(addrstr+1, ']');
734  char * firstbadchar = rbracketpos;
735 
736  if (rbracketpos == NULL || rbracketpos[1] != ':') {
737  return NULL;
738  }
739  firstaddrdigit += 1;
740  lastaddrdigit = rbracketpos - 1;
741  port = strtol(rbracketpos+2, &firstbadchar, 10);
742  if (*firstbadchar != '\0' || port <= 0 || port >= 65536) {
743  DEBUGMSG5("%s.%d: Not IPv6 format due to bad port number syntax"
744  , __FUNCTION__, __LINE__);
745  return NULL;
746  }
747  }
748  // Now, we know where the collection of address characters starts and ends
749  if (firstaddrdigit[0] == ':' && firstaddrdigit[1] == ':') {
750  coloncolonindex = 0;
751  firstaddrdigit += 2;
752  // Let's see if it might be an ipv4 address encapsulated as ipv6...
753  DEBUGMSG5("%s.%d: LOOKING to see if we have an encapsulated IPv4 address. [%s] [%s]"
754  , __FUNCTION__, __LINE__, firstaddrdigit, v4prefix);
755  if (strncmp(firstaddrdigit, v4prefix, v4prefixlen) == 0) {
756  DEBUGMSG5("%s.%d: May have an encapsulated IPv4 address. [%s]"
757  , __FUNCTION__, __LINE__, firstaddrdigit);
758  if (strchr(firstaddrdigit + v4prefixlen, '.') != NULL) {
759  // We have '.'s but no more ':'s...
760  DEBUGMSG5("%s.%d: Appear to have an encapsulated IPv4 address."
761  , __FUNCTION__, __LINE__);
762  v4encapsulated = TRUE;
763  conversionbase = 10; // IPv4 addresses are decimal
764  delimchar = '.'; // IPv4 addresses use . delimiters
765  maxchunkindex = 4; // IPv4 addresses have exactly 4 parts
766  maxchunkvalue = 255; // IPv4 address elements are single bytes
767  firstaddrdigit += v4prefixlen;
768  }
769  }
770  }
771  curaddrdigit = firstaddrdigit;
772  // Loop over the characters, breaking them into a series of hexadecimal (or decimal) chunks
773  for (chunkindex=0; chunkindex < maxchunkindex && curaddrdigit <= lastaddrdigit; ++chunkindex) {
774  long chunk = strtol(curaddrdigit, &firstbadhexchar, conversionbase);
775  DEBUGMSG5("%s.%d: chunk %d begins [%s] converts to 0x%lx", __FUNCTION__, __LINE__
776  , chunkindex, curaddrdigit, (unsigned long)chunk);
777  if (chunk < 0 || chunk > maxchunkvalue) {
778  DEBUGMSG5("%s.%d: Not IPv6 format due to invalid chunk value [%ld]"
779  , __FUNCTION__, __LINE__, chunk);
780  return NULL;
781  }
782  // Remember the value of this chunk...
783  addrchunks[chunkindex] = (guint16)chunk;
784 
785  // Was the ending delimiter what we expected?
786  if (firstbadhexchar <= lastaddrdigit && *firstbadhexchar != delimchar) {
787  DEBUGMSG5("%s.%d: Not IPv6 format due to invalid character [%c]"
788  , __FUNCTION__, __LINE__, *firstbadhexchar);
789  return NULL;
790  }
791  curaddrdigit = firstbadhexchar;
792  if (v4encapsulated && *firstbadhexchar == delimchar) {
793  curaddrdigit += 1;
794  // Is there a :: in this position in the address?
795  }else if (!v4encapsulated && firstbadhexchar[0] == ':') {
796  if (firstbadhexchar[1] == ':') {
797  if (coloncolonindex >= 0) {
798  // :: can only appear once in the address
799  DEBUGMSG5("%s.%d: Not IPv6 format due to multiple ::'s"
800  , __FUNCTION__, __LINE__);
801  return NULL;
802  }
803  coloncolonindex = chunkindex + 1;
804  curaddrdigit += 2;
805  }else{
806  curaddrdigit += 1;
807  }
808  }else if (*firstbadhexchar != ']' && *firstbadhexchar != '\0') {
809  DEBUGMSG5("%s.%d: Not IPv6 format due to illegal char [%c]"
810  , __FUNCTION__, __LINE__, *firstbadhexchar);
811  return NULL;
812  }
813 
814  if (firstbadhexchar >= lastaddrdigit + 1) {
815  break;
816  }
817  }
818  if (firstbadhexchar != NULL && firstbadhexchar != lastaddrdigit + 1) {
819  DEBUGMSG5("%s.%d: Not IPv6 format due to excess length.", __FUNCTION__, __LINE__);
820  DEBUGMSG5("%s.%d: firstbadhexchar = %p, lastaddrdigit = %p, diff=%ld"
821  , __FUNCTION__, __LINE__, firstbadhexchar, lastaddrdigit
822  , (long)(lastaddrdigit-firstbadhexchar));
823  return NULL;
824  }
825  if (coloncolonindex >= 0 && chunkindex == DIMOF(addrchunks)-1) {
826  DEBUGMSG5("%s.%d: Not IPv6 format due to full length with :: present"
827  , __FUNCTION__, __LINE__);
828  return NULL;
829  }
830  if (coloncolonindex < 0 && chunkindex != DIMOF(addrchunks)-1) {
831  DEBUGMSG5("%s.%d: Not IPv6 format due to too few digits."
832  , __FUNCTION__, __LINE__);
833  return NULL;
834  }
835  // OK --- now we have something that looks a lot like a legit IPv6 address.
836  // let's see if we can make a NetAddr out of it...
837  if (coloncolonindex >= 0) {
838  coloncolonlength = (DIMOF(addrchunks)-1) - chunkindex;
839  DEBUGMSG5("%s.%d: coloncolonlength is %d, index is %d", __FUNCTION__, __LINE__
840  , coloncolonlength, coloncolonindex);
841  }
842  DEBUGMSG5("%s.%d: chunkindex is %d", __FUNCTION__, __LINE__, chunkindex);
843 
844  addrptr = addrbytes;
845 
846 
847  if (v4encapsulated) {
848  // Take care of the encapsulated IPv4 special case...
849  const guint8 v4prefix[] = {CONST_IPV6_IPV4SPACE};
850  const guint offset = sizeof(v4prefix);
851  if (chunkindex != 3) {
852  DEBUGMSG5("%s.%d: Not IPv4 encapsulated as IPv6 format due to too few digits."
853  , __FUNCTION__, __LINE__);
854  return NULL;
855  }
856  memcpy(addrbytes, v4prefix, sizeof(v4prefix));
857  addrbytes[offset+0] = (guint8)addrchunks[0];
858  addrbytes[offset+1] = (guint8)addrchunks[1];
859  addrbytes[offset+2] = (guint8)addrchunks[2];
860  addrbytes[offset+3] = (guint8)addrchunks[3];
861  }else{
862  // Otherwise we have a more normal IPv6 address
863  memset(addrbytes, 0, DIMOF(addrbytes));
864  // Make our set of chunks into an IPv6 address in binary
865  for (j=0; j <= chunkindex; ++j) {
866  // Is this where the :: goes?
867  if (((gint)j) == coloncolonindex) {
868  // Insert the right number of zeros
869  memset(addrptr, 0, coloncolonlength*2);
870  addrptr += 2*coloncolonlength;
871  }
872  // Copy the next bit of data
873  addrptr[0] = (((addrchunks[j]) >> 8) & 0xff);
874  addrptr[1] = addrchunks[j] & 0xff;
875  addrptr += 2;
876  }
877  // Did the :: appear at the end of the address - weird but legal...
878  if (coloncolonindex == (gint)chunkindex + 1) {
879  DEBUGMSG5("%s.%d: Appending %d zeros to the end of the address"
880  , __FUNCTION__, __LINE__, coloncolonlength*2);
881  memset(addrptr, 0, coloncolonlength*2);
882  addrptr += 2*coloncolonlength;
883  }
884  DEBUGMSG5("%s.%d: addrptr == addrbytes+%ld", __FUNCTION__, __LINE__
885  , (long)(addrptr-addrbytes));
886  g_return_val_if_fail(addrptr == addrbytes+DIMOF(addrbytes), NULL);
887  }
888  retval = netaddr_ipv6_new(addrbytes, port);
889  DUMP5(addrstr, &retval->baseclass, " Converted the former into the latter...(ignore the extra ':')");
890  return retval;
891 }
892 
895 NetAddr*
896 _netaddr_string_macaddr_new(const char *addrstr)
897 {
898  guint8 hexvals[8];
899  unsigned hexindex = 0;
900 
901  const char * cp;
902  char * nextcp;
903 
904  for (cp = addrstr; *cp; hexindex++, cp=nextcp) {
905  long hexvalue;
906  if (hexindex >= DIMOF(hexvals)) {
907  return NULL;
908  }
909  hexvalue = strtol(cp, &nextcp, 16);
910  if (hexvalue < 0 || hexvalue > 255 || nextcp == cp) {
911  return NULL;
912  }
913  hexvals[hexindex] = hexvalue;
914  if (*nextcp == '-' || *nextcp == ':') {
915  nextcp++;
916  // Disallow a final : or -
917  if (*nextcp == '\0') {
918  return NULL;
919  }
920  }
921  }
922  if (hexindex == 6) {
923  return netaddr_mac48_new(hexvals);
924  }
925  if (hexindex == 8) {
926  return netaddr_mac64_new(hexvals);
927  }
928  return NULL;
929 }
930 
932 NetAddr*
933 netaddr_string_new(const char* addrstr)
934 {
935  NetAddr* retval = NULL;
936  char addr0 = addrstr[0];
937 
938  if (addr0 == '[' || addr0 == ':') {
939  return _netaddr_string_ipv6_new(addrstr);
940  }
941 
942  if (isdigit(addr0)) {
943  retval = _netaddr_string_ipv4_new(addrstr);
944  if (!retval) {
945  retval = _netaddr_string_ipv6_new(addrstr);
946  if (!retval) {
947  retval = _netaddr_string_macaddr_new(addrstr);
948  }
949  }
950  }else if (isxdigit(addr0)) {
951  retval = _netaddr_string_ipv6_new(addrstr);
952  if (!retval) {
953  retval = _netaddr_string_macaddr_new(addrstr);
954  }
955  }
956  return retval;
957 }
958 
960 NetAddr*
961 netaddr_dns_new(const char * sysname_or_addr) //< System name/address
962 {
963 #ifdef HAVE_GETADDRINFO
964  NetAddr* ret = NULL;
965  const char* digits = ":[0123456789ABCDEFabcdef";
966  const char * colonpos;
967  char* sysname;
968  int rc;
969  const char* service = NULL;
970  struct addrinfo hints;
971  struct addrinfo*sysinfo;
972 
973  // See if it _could_ be a numeric address...
974  if (strchr(digits, sysname_or_addr[0]) != NULL) {
975  ret = netaddr_string_new(sysname_or_addr);
976  if (NULL != ret) {
977  return ret;
978  }
979  // Who knows, maybe they gave a symbolic port and a constant IP address...
980  // In any case, give it another shot...
981  }
982 
983  // See if they specified a port...
984  colonpos = strchr(sysname_or_addr, ':');
985 
986  if (NULL == colonpos) {
987  service = "0";
988  sysname = g_strdup(sysname_or_addr);
989  }else{
990  service = colonpos + 1;
991  if (strlen(service) < 1 || atol(service) < 0 || atol(service) > 65535) {
992  return NULL;
993  }
994  sysname = g_strndup(sysname_or_addr, colonpos-sysname_or_addr);
995  }
996  memset(&hints, 0, sizeof(hints));
997  hints.ai_family = AF_UNSPEC;
998  hints.ai_socktype = SOCK_DGRAM;
999  rc = getaddrinfo(sysname, service, &hints, &sysinfo);
1000  if (0 != rc) {
1001  DEBUGMSG("%s.%d: Could not resolve %s - reason: %s"
1002  , __FUNCTION__, __LINE__, sysname, gai_strerror(rc));
1003  }else{
1004  ret = netaddr_sockaddr_new((struct sockaddr_in6*)sysinfo[0].ai_addr
1005  , sysinfo[0].ai_addrlen);
1006  freeaddrinfo(sysinfo);
1007  }
1008  g_free(sysname); sysname = NULL;
1009 #else
1010 # error "Must have a replacement for getaddrinfo(3)"
1011 #endif
1012  return ret;
1013 }
1014 
1015 
1017 NetAddr*
1018 netaddr_macaddr_new(gconstpointer macbuf,
1019  guint16 maclen)
1020 {
1021 
1022  g_return_val_if_fail(maclen == 6 || maclen == 8, NULL);
1023  return netaddr_new(0, 0, ADDR_FAMILY_802, macbuf, maclen);
1024 }
1025 
1027 NetAddr*
1028 netaddr_mac48_new(gconstpointer macbuf)
1029 {
1030  return netaddr_macaddr_new(macbuf, 6);
1031 }
1032 
1034 NetAddr*
1035 netaddr_mac64_new(gconstpointer macbuf)
1036 {
1037  return netaddr_macaddr_new(macbuf, 8);
1038 }
1039 
1041 NetAddr*
1042 netaddr_ipv4_new(gconstpointer ipbuf,
1043  guint16 port)
1044 {
1045  return netaddr_new(0, port, ADDR_FAMILY_IPV4, ipbuf, 4);
1046 }
1047 
1049 NetAddr*
1050 netaddr_ipv6_new(gconstpointer ipbuf,
1051  guint16 port)
1052 {
1053  return netaddr_new(0, port, ADDR_FAMILY_IPV6, ipbuf, 16);
1054 }
1055 
1056 
1057 
1058 
1060 NetAddr*
1061 netaddr_sockaddr_new(const struct sockaddr_in6 *sa_in6,
1062  socklen_t length)
1063 {
1064  const struct sockaddr_in* sa_in = (const struct sockaddr_in*)sa_in6;
1065 
1066  (void)length;
1067  switch(sa_in->sin_family) {
1068  case AF_INET:
1069  return netaddr_new(0, ntohs(sa_in->sin_port),
1070  ADDR_FAMILY_IPV4, &sa_in->sin_addr, 4);
1071  break;
1072 
1073  case AF_INET6:
1075  return netaddr_new(0, ntohs(sa_in6->sin6_port),
1076  ADDR_FAMILY_IPV6, &sa_in6->sin6_addr, 16);
1077  break;
1078  }
1079  g_return_val_if_reached(NULL);
1080 }
1081 
1082 FSTATIC struct sockaddr_in6
1083 _netaddr_ipv6sockaddr(const NetAddr* self) //<[in] NetAddr object to convert to IPv6 sockaddr
1084 {
1085  struct sockaddr_in6 saddr;
1086 
1087  memset(&saddr, 0x00, sizeof(saddr));
1088 
1089  switch (self->_addrtype) {
1090  case ADDR_FAMILY_IPV4:
1091  g_return_val_if_fail(4 == self->_addrlen, saddr);
1092  saddr.sin6_family = AF_INET6;
1093  saddr.sin6_port = htons(self->_addrport);
1096  // (this works because saddr is initialized to zero)
1097  saddr.sin6_addr.s6_addr[10] = 0xff;
1098  saddr.sin6_addr.s6_addr[11] = 0xff;
1099  memcpy(saddr.sin6_addr.s6_addr+12, self->_addrbody, self->_addrlen);
1100  DEBUGMSG3("%s:%s: sin6_family 0x%x, sin6_port %d"
1101  , __FILE__, __FUNCTION__
1102  , saddr.sin6_family, ntohs(saddr.sin6_port));
1103  DEBUGMSG3("%s:%s:s6_addr(v4): %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
1104  , __FILE__, __FUNCTION__
1105  , saddr.sin6_addr.s6_addr[0],saddr.sin6_addr.s6_addr[1]
1106  , saddr.sin6_addr.s6_addr[2],saddr.sin6_addr.s6_addr[3]
1107  , saddr.sin6_addr.s6_addr[4],saddr.sin6_addr.s6_addr[5]
1108  , saddr.sin6_addr.s6_addr[6],saddr.sin6_addr.s6_addr[7]
1109  , saddr.sin6_addr.s6_addr[8],saddr.sin6_addr.s6_addr[8]
1110  , saddr.sin6_addr.s6_addr[10],saddr.sin6_addr.s6_addr[11]
1111  , saddr.sin6_addr.s6_addr[12],saddr.sin6_addr.s6_addr[13]
1112  , saddr.sin6_addr.s6_addr[14],saddr.sin6_addr.s6_addr[15]);
1113 
1114  break;
1115 
1116  case ADDR_FAMILY_IPV6:
1117  g_return_val_if_fail(16 == self->_addrlen, saddr);
1118  saddr.sin6_family = AF_INET6;
1119  saddr.sin6_port = htons(self->_addrport);
1120  memcpy(&saddr.sin6_addr, self->_addrbody, self->_addrlen);
1121  break;
1122 
1123  default:
1124  g_return_val_if_reached(saddr);
1125  }
1126  return saddr;
1127 }
1128 
1129 FSTATIC struct sockaddr_in
1130 _netaddr_ipv4sockaddr(const NetAddr* self) //<[in] NetAddr object to convert to IPv4 sockaddr
1131 {
1132  struct sockaddr_in saddr;
1133 
1134  memset(&saddr, 0x00, sizeof(saddr));
1135 
1136  switch (self->_addrtype) {
1137  case ADDR_FAMILY_IPV4:
1138  g_return_val_if_fail(4 == self->_addrlen, saddr);
1139  saddr.sin_family = AF_INET;
1140  saddr.sin_port = htons(self->_addrport);
1141  memcpy(&saddr.sin_addr, self->_addrbody, 4);
1142  break;
1143 
1144  default:
1145  g_return_val_if_reached(saddr);
1146  }
1147  return saddr;
1148 }
IETF/IANA Address family assignments.
FSTATIC gboolean _netaddr_equal(const NetAddr *, const NetAddr *)
Return TRUE if these two addresses are "equal" (equivalent)
Definition: netaddr.c:240
#define CHAR_BIT
Definition: netaddr.c:321
FSTATIC struct sockaddr_in6 _netaddr_ipv6sockaddr(const NetAddr *self)
Definition: netaddr.c:1083
FSTATIC gchar * _netaddr_toString_ipv6_ipv4(const NetAddr *self, gboolean ipv4format)
Convert this IPv6-encapsulated IPv4 NetAddr to a string.
Definition: netaddr.c:83
FSTATIC guint16 _netaddr_addrtype(const NetAddr *self)
Return the address type of this NetAddr.
Definition: netaddr.c:435
FSTATIC void _netaddr_setport(NetAddr *self, guint16)
Set the port of this NetAddr.
Definition: netaddr.c:427
FSTATIC gboolean _netaddr_islocal(const NetAddr *self)
Return TRUE if this is a multicast address.
Definition: netaddr.c:459
FSTATIC gchar * _netaddr_toString(gconstpointer)
Convert this IPv6-encapsulated IPv4 NetAddr to an IPv4 representation Convert this NetAddr to a strin...
Definition: netaddr.c:115
FSTATIC gchar * _netaddr_canonStr(const NetAddr *)
Definition: netaddr.c:122
NetAddr * netaddr_macaddr_new(gconstpointer macbuf, guint16 maclen)
Create new NetAddr from a MAC address.
Definition: netaddr.c:1018
#define DEBUGMSG(...)
Definition: proj_classes.h:87
NetAddr * netaddr_dns_new(const char *sysname_or_addr)
Create a NetAddr from a DNS name or an ipv4 or ipv6 constant string.
Definition: netaddr.c:961
NetAddr * netaddr_mac64_new(gconstpointer macbuf)
Create new NetAddr from a MAC64 address.
Definition: netaddr.c:1035
#define DEBUGMSG5(...)
Definition: proj_classes.h:93
FSTATIC void _netaddr_finalize(AssimObj *self)
Finalize (free) this object.
Definition: netaddr.c:405
AssimObj baseclass
Definition: netaddr.h:44
guint16 _addrport
private: Address port (if applicable)
Definition: netaddr.h:61
FSTATIC gboolean _netaddr_isanyaddr(const NetAddr *self)
Definition: netaddr.c:485
FSTATIC NetAddr * _netaddr_string_macaddr_new(const char *addrstr)
Create a NetAddr from a 48-bit or 64-bit-format MAC address string.
Definition: netaddr.c:896
NetAddr * netaddr_ipv4_new(gconstpointer ipbuf, guint16 port)
Create new NetAddr from a IPv4 address.
Definition: netaddr.c:1042
#define WINEXPORT
Definition: projectcommon.h:45
#define FSTATIC
Definition: projectcommon.h:31
#define DEBUGMSG3(...)
Definition: proj_classes.h:91
NetAddr * netaddr_sockaddr_new(const struct sockaddr_in6 *sa_in6, socklen_t length)
Create new NetAddr from a struct sockaddr
Definition: netaddr.c:1061
FSTATIC gchar * _netaddr_toStringflex(const NetAddr *, gboolean canonformat)
Convert this NetAddr to a string.
Definition: netaddr.c:160
#define FREECLASSOBJ(obj)
Free a C-class object.
Definition: proj_classes.h:76
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
NetAddr * netaddr_mac48_new(gconstpointer macbuf)
Create new NetAddr from a MAC48 address.
Definition: netaddr.c:1028
FSTATIC gboolean _netaddr_ismcast(const NetAddr *self)
Return TRUE if this is a multicast address.
Definition: netaddr.c:442
#define __FUNCTION__
FSTATIC gconstpointer _netaddr_addrinnetorder(gsize *addrlen)
gpointer proj_class_register_subclassed(gpointer object, const char *static_subclassname)
Log the creation of a subclassed object from a superclassed object.
Definition: proj_classes.c:192
#define CONST_IPV6_LOOPBACK
Definition: netaddr.h:76
NetAddr * netaddr_ipv6_new(gconstpointer ipbuf, guint16 port)
Create new NetAddr from a IPv6 address.
Definition: netaddr.c:1050
#define FREE(m)
Our interface to free.
Definition: projectcommon.h:29
WINEXPORT gboolean netaddr_g_hash_equal(gconstpointer lhs, gconstpointer rhs)
g_hash_table equal comparator for a NetAddr
Definition: netaddr.c:388
gchar *(* toString)(gconstpointer)
Produce malloc-ed string representation.
Definition: assimobj.h:58
#define ADDR_FAMILY_IPV6
IPv6.
#define CASTTOCONSTCLASS(Cclass, obj)
Safely cast 'obj' to const C-class 'class' - verifying that it was registered as being of type class ...
Definition: proj_classes.h:71
Project common header file.
#define DIMOF(a)
Definition: lldp_min.c:30
NetAddr * anyaddr
Definition: pcap+mainloop.c:86
#define CONST_IPV6_IPV4SPACE
Definition: netaddr.h:78
struct _NetAddr NetAddr
Definition: netaddr.h:36
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
#define DUMP5(prefix, obj, suffix)
Definition: proj_classes.h:99
FSTATIC NetAddr * _netaddr_toIPv6(const NetAddr *)
Convert this IPv6-encapsulated IPv4 NetAddr to an IPv4 representation.
Definition: netaddr.c:129
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
FSTATIC guint _netaddr_hash(const NetAddr *)
NetAddr hash function which worries about denial of service via hash collisions.
Definition: netaddr.c:327
gboolean(* equal)(const NetAddr *, const NetAddr *)
Compare NetAddrs.
Definition: netaddr.h:53
Defines interfaces for the NetAddr (network address) object.
FSTATIC NetAddr * _netaddr_string_ipv6_new(const char *addrstr)
Convert a string into an IPv6 address - possibly including a port as per RFC 4291.
Definition: netaddr.c:684
NetAddr * netaddr_new(gsize objsize, guint16 port, guint16 addrtype, gconstpointer addrbody, guint16 addrlen)
Generic NetAddr constructor.
Definition: netaddr.c:501
guint16 _addrlen
private: Length of _addrbody
Definition: netaddr.h:60
FSTATIC guint16 _netaddr_port(const NetAddr *self)
Return the port of this NetAddr.
Definition: netaddr.c:419
WINEXPORT guint netaddr_g_hash_hash(gconstpointer addrptr)
g_hash_table hash function for a NetAddr
Definition: netaddr.c:397
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
#define ADDR_FAMILY_802
Level 2 physical (MAC) addresses.
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
guint16 _addrtype
private: Address type
Definition: netaddr.h:59
FSTATIC NetAddr * _netaddr_string_ipv4_new(const char *addrstr)
Convert a string to an IPv4 NetAddr.
Definition: netaddr.c:570
NetAddr * netaddr_string_new(const char *addrstr)
Create a NetAddr from an ipv4, ipv6 or MAC address string.
Definition: netaddr.c:933
#define ADDR_FAMILY_IPV4
IPv4.
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
FSTATIC struct sockaddr_in _netaddr_ipv4sockaddr(const NetAddr *self)
Definition: netaddr.c:1130
#define CONST_IPV4_LOOPBACK
Definition: netaddr.h:77
#define EXTRA_STACK_PROTECTOR_BYTES
Definition: netaddr.c:566
gpointer _addrbody
private: Address body
Definition: netaddr.h:58