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