LIBSSDP
 All Classes Files Functions Variables Typedefs Macros
net_utils.c
Go to the documentation of this file.
1 
7 #include <arpa/inet.h>
8 #include <errno.h>
9 #include <ifaddrs.h>
10 #include <net/if.h>
11 #include <net/if_arp.h>
12 #include <netinet/in.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
17 
18 #if defined BSD || defined __APPLE__
19 #include <netinet/if_ether.h>
20 #include <sys/sysctl.h>
21 #include <net/if_dl.h>
22 #include <net/if_types.h>
23 #include <net/route.h>
24 #include <sys/file.h>
25 #endif
26 
27 #include "common_definitions.h"
28 #include "log.h"
29 #include "net_definitions.h"
30 #include "net_utils.h"
31 #include "string_utils.h"
32 
33 int parse_address(const char *raw_address,
34  struct sockaddr_storage *address) {
35  int ret = 0;
36  char *ip = NULL;
37  int colon_pos = 0;
38  int port = 0;
39  BOOL is_ipv6;
40 
41  PRINT_DEBUG("parse_address()");
42 
43  if(!raw_address || strlen(raw_address) < 1) {
44  PRINT_ERROR("No valid IP address specified");
45  goto err;
46  }
47 
48  /* Allocate the input address */
49  memset(address, 0, sizeof(struct sockaddr_storage));
50  colon_pos = strpos(raw_address, ":");
51 
52  if(colon_pos < 1) {
53  PRINT_ERROR("No valid port specified (%s)\n", raw_address);
54  goto err;
55  }
56 
57  ip = (char *)malloc(sizeof(char) * IPv6_STR_MAX_SIZE);
58  memset(ip, '\0', sizeof(char) * IPv6_STR_MAX_SIZE);
59 
60  /* Get rid of [] if IPv6 */
61  strncpy(ip, strchr(raw_address, '[') + 1,
62  strchr(raw_address, '[') - strchr(raw_address, ']'));
63 
64  is_ipv6 = inet_pton(AF_INET6, ip, address);
65  PRINT_DEBUG("is_ipv6 == %s", is_ipv6 ? "TRUE" : "FALSE");
66  if(is_ipv6) {
67  address->ss_family = AF_INET6;
68  port = atoi(strrchr(raw_address, ':') + 1);
69  }
70  else {
71  memset(ip, '\0', sizeof(char) * IPv6_STR_MAX_SIZE);
72  strncpy(ip, raw_address, colon_pos);
73  if(!inet_pton(AF_INET, ip, &(((struct sockaddr_in *)address)->sin_addr))) {
74  PRINT_ERROR("No valid IP address specified (%s)\n", ip);
75  goto err;
76  }
77  address->ss_family = AF_INET;
78  port = atoi(raw_address + colon_pos + 1);
79  }
80 
81  if(port < 80 || port > PORT_MAX_NUMBER) {
82  PRINT_ERROR("No valid port specified (%d)\n", port);
83  goto err;
84  }
85 
86  if(is_ipv6) {
87  ((struct sockaddr_in6 *)address)->sin6_port = htons(port);
88  }
89  else {
90  ((struct sockaddr_in *)address)->sin_port = htons(port);
91  }
92 
93  goto success;
94 
95 err:
96  ret = 1;
97 
98 success:
99  if (ip)
100  free(ip);
101 
102  return ret;
103 }
104 
105 // TODO: remove ip_size ?
106 // TODO: make work with dnames also.
107 BOOL parse_url(const char *url, char *ip, int ip_size, int *port, char *rest,
108  int rest_size) {
109 
110  /* Check if HTTPS */
111  if(!url || strlen(url) < 8) {
112  PRINT_ERROR("The argument 'url' is not set or is empty");
113  return FALSE;
114  }
115 
116  PRINT_DEBUG("passed url: %s", url);
117 
118  if(*(url + 4) == 's') {
119  /* HTTPS is not supported at the moment, skip */
120  PRINT_DEBUG("HTTPS is not supported, skipping");
121  return FALSE;
122  }
123 
124  const char *ip_begin = strchr(url, ':') + 3; // http[s?]://^<ip>:<port>/<rest>
125  PRINT_DEBUG("ip_begin: %s", ip_begin);
126  BOOL is_ipv6 = *ip_begin == '[' ? TRUE : FALSE;
127  PRINT_DEBUG("is_ipv6: %s", (is_ipv6 ? "TRUE" : "FALSE"));
128 
129  char *rest_begin = NULL;
130  if(is_ipv6) {
131  if(!(rest_begin = strchr(ip_begin, ']')) || !(rest_begin = strchr(rest_begin, '/'))) {
132  // [<ipv6>]^:<port>/<rest> && :<port>^/<rest>
133  PRINT_ERROR("Error: (IPv6) rest_begin is NULL\n");
134  return FALSE;
135  }
136  PRINT_DEBUG("rest_begin: %s", rest_begin);
137  }
138  else {
139  if(!(rest_begin = strchr(ip_begin, '/'))) { // <ip>:<port>^/<rest>
140  PRINT_ERROR("Error: rest_begin is NULL\n");
141  return FALSE;
142  }
143  }
144 
145  if(rest_begin != NULL) {
146  strcpy(rest, rest_begin);
147  }
148 
149  char *working_str = (char *)malloc(sizeof(char) * 256); // temporary string buffer
150  char *ip_with_brackets = (char *)malloc(sizeof(char) * IPv6_STR_MAX_SIZE + 2); // temporary IP buffer
151  memset(working_str, '\0', 256);
152  memset(ip_with_brackets, '\0', IPv6_STR_MAX_SIZE + 2);
153  PRINT_DEBUG("size to copy: %d", (int)(rest_begin - ip_begin));
154  strncpy(working_str, ip_begin, (size_t)(rest_begin - ip_begin)); // "<ip>:<port>"
155  PRINT_DEBUG("working_str: %s", working_str);
156  char *port_begin = strrchr(working_str, ':'); // "<ip>^:<port>^"
157  PRINT_DEBUG("port_begin: %s", port_begin);
158  if(port_begin != NULL) {
159  *port_begin = ' '; // "<ip>^ <port>^"
160  // maybe memset instead of value assignment ?
161  sscanf(working_str, "%s %d", ip_with_brackets, port); // "<%s> <%d>"
162  PRINT_DEBUG("port: %d", *port);
163  if(strlen(ip_with_brackets) < 1) {
164  PRINT_ERROR("Malformed header_location detected in: '%s'", url);
165  free(working_str);
166  free(ip_with_brackets);
167  return FALSE;
168  }
169  if(*ip_with_brackets == '[') {
170  PRINT_DEBUG("ip_with_brackets: %s", ip_with_brackets);
171  //strncpy(ip, ip_with_brackets + 1, strlen(ip_with_brackets) - 1); // uncomment in case we dont need brackets
172  }
173  else {
174  //strcpy(ip, ip_with_brackets); // uncomment in case we dont need brackets
175  }
176  strcpy(ip, ip_with_brackets);
177  PRINT_DEBUG("ip: %s", ip);
178  }
179 
180  if(rest_begin == NULL) {
181  PRINT_ERROR("Malformed header_location detected in: '%s'", url);
182  free(working_str);
183  free(ip_with_brackets);
184  return FALSE;
185  }
186 
187  free(working_str);
188  free(ip_with_brackets);
189  return TRUE;
190 }
191 
192 int find_interface(struct sockaddr_storage *saddr, const char *interface,
193  const char *address) {
194  // TODO: for porting to Windows see http://msdn.microsoft.com/en-us/library/aa365915.aspx
195  struct ifaddrs *interfaces, *ifa;
196  struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)saddr;
197  struct sockaddr_in *saddr4 = (struct sockaddr_in *)saddr;
198  char *compare_address = NULL;
199  int ifindex = -1;
200  BOOL is_ipv6 = FALSE;
201 
202  PRINT_DEBUG("find_interface(%s, \"%s\", \"%s\")",
203  saddr == NULL ? NULL : "saddr",
204  interface,
205  address);
206 
207  /* Make sure we have the buffers allocated */
208  if (!interface) {
209  PRINT_ERROR("No interface string-buffer available");
210  return -1;
211  }
212 
213  if (!address) {
214  PRINT_ERROR("No IP address string-buffer available");
215  return -1;
216  }
217 
218  if (!saddr) {
219  PRINT_ERROR("No address structure-buffer available");
220  return -1;
221  }
222 
223  /* Check if address is IPv6*/
224  is_ipv6 = inet_pton(AF_INET6,
225  address,
226  (void *)&saddr6->sin6_addr) > 0;
227 
228  /* If address not set or is bind-on-all
229  then set a bindall address in the struct */
230  if (((strlen(interface) == 0) && (strlen(address) == 0)) ||
231  (strcmp("0.0.0.0", address) == 0) || (strcmp("::", address) == 0)) {
232  if (is_ipv6) {
233  saddr->ss_family = AF_INET6;
234  saddr6->sin6_addr = in6addr_any;
235  PRINT_DEBUG("find_interface(): Matched all addresses (::)\n");
236  }
237  else {
238  saddr->ss_family = AF_INET;
239  saddr4->sin_addr.s_addr = htonl(INADDR_ANY);
240  PRINT_DEBUG("find_interface(): Matched all addresses (0.0.0.0)");
241  }
242  return 0;
243  }
244 
245  /* Try to query for all devices on the system */
246  if (getifaddrs(&interfaces) < 0) {
247  PRINT_ERROR("Could not find any interfaces\n");
248  return -1;
249  }
250 
251  compare_address = malloc(sizeof(char) * IPv6_STR_MAX_SIZE);
252 
253  /* Loop through the interfaces*/
254  for (ifa = interfaces; ifa && ifa->ifa_next; ifa = ifa->ifa_next) {
255 
256  /* Helpers */
257  struct sockaddr_in6 *ifaddr6 = (struct sockaddr_in6 *)ifa->ifa_addr;
258  struct sockaddr_in *ifaddr4 = (struct sockaddr_in *)ifa->ifa_addr;
259  int ss_family = ifa->ifa_addr->sa_family;
260 
261  memset(compare_address, '\0', sizeof(char) * IPv6_STR_MAX_SIZE);
262 
263  /* Extract the IP address in printable format */
264  if (is_ipv6 && ss_family == AF_INET6) {
265  PRINT_DEBUG("Extracting an IPv6 address");
266  get_ip_from_sock_address((struct sockaddr_storage *)ifaddr6,
267  compare_address);
268  if (compare_address[0] == '\0') {
269  PRINT_ERROR("Could not extract printable IPv6 for the interface %s: "
270  "(%d) %s", ifa->ifa_name, errno, strerror(errno));
271  return -1;
272  }
273  }
274  else if (!is_ipv6 && ss_family == AF_INET) {
275  PRINT_DEBUG("Extracting an IPv4 address");
276  get_ip_from_sock_address((struct sockaddr_storage *)ifaddr4,
277  compare_address);
278  if (compare_address[0] == '\0') {
279  PRINT_ERROR("Could not extract printable IPv4 for the interface %s: "
280  "(%d) %s", ifa->ifa_name, errno, strerror(errno));
281  return -1;
282  }
283  }
284  else {
285  continue;
286  }
287 
288  /* Check if this is the desired interface and/or address
289  5 possible scenarios:
290  interface and address given
291  only interface given (address is automatically bindall)
292  only address given
293  none given (address is automatically bindall) */
294  BOOL if_present = strlen(interface) > 0 ? TRUE : FALSE;
295  BOOL addr_present = strlen(address) > 0 ? TRUE : FALSE;
296  BOOL addr_is_bindall = ((strcmp("0.0.0.0", address) == 0) ||
297  (strcmp("::", address) == 0) || (strlen(address) == 0)) ? TRUE : FALSE;
298 
299  if ((if_present && (strcmp(interface, ifa->ifa_name) == 0) &&
300  addr_present && (strcmp(address, compare_address) == 0)) ||
301  (if_present && (strcmp(interface, ifa->ifa_name) == 0) &&
302  addr_is_bindall) ||
303  (!if_present &&
304  addr_present && (strcmp(address, compare_address) == 0)) ||
305  (!if_present &&
306  addr_is_bindall)) {
307 
308  /* Set the interface index to be returned*/
309  ifindex = if_nametoindex(ifa->ifa_name);
310 
311  PRINT_DEBUG("Matched interface (with index %d) name '%s' with %s "
312  "address %s", ifindex, ifa->ifa_name,
313  (ss_family == AF_INET ? "IPv4" : "IPv6"), compare_address);
314 
315  /* Set the appropriate address in the sockaddr struct */
316  if (!is_ipv6 && ss_family == AF_INET) {
317  saddr4->sin_addr = ifaddr4->sin_addr;
318  PRINT_DEBUG("Setting IPv4 saddr");
319  }
320  else if (is_ipv6 && ss_family == AF_INET6){
321  saddr6->sin6_addr = ifaddr6->sin6_addr;
322  PRINT_DEBUG("Setting IPv6 saddr");
323  }
324 
325  /* Set family to IP version*/
326  saddr->ss_family = ss_family;
327 
328  break;
329  } else {
330  PRINT_DEBUG("Match failed, trying next interface (if any)");
331  }
332 
333  }
334 
335  /* Free getifaddrs allocations */
336  if(interfaces) {
337  freeifaddrs(interfaces);
338  }
339 
340  /* free our compare buffer */
341  if(compare_address != NULL) {
342  free(compare_address);
343  }
344 
345  return ifindex;
346 }
347 
348 #if defined BSD || defined __APPLE__
349 // TODO: fix for IPv6
350 /* MacOS X variant of the function */
351 char *get_mac_address_from_socket(const SOCKET sock,
352  const struct sockaddr_storage *ss_ip, const char *ip, char *mac_buffer) {
353  char *mac_string = mac_buffer ? mac_buffer :
354  malloc(sizeof(char) * MAC_STR_MAX_SIZE);
355  memset(mac_string, '\0', MAC_STR_MAX_SIZE);
356 
357  PRINT_DEBUG("Using BSD style MAC discovery (sysctl)");
358  int sysctl_flags[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS,
359  RTF_LLINFO };
360  char *arp_buffer = NULL;
361  char *arp_buffer_end = NULL;
362  char *arp_buffer_next = NULL;
363  struct rt_msghdr *rtm = NULL;
364  struct sockaddr_inarp *sin_arp = NULL;
365  struct sockaddr_dl *sdl = NULL;
366  size_t arp_buffer_size;
367  BOOL found_arp = FALSE;
368  struct sockaddr_storage *local_ss_ip = NULL; /* Used if ss_ip is NULL */
369 
370  /* Choose IP source */
371  if (ss_ip) {
372  local_ss_ip = (struct sockaddr_storage *)ss_ip;
373  } else if (ip) {
374  local_ss_ip = malloc(sizeof *local_ss_ip);
375  memset(local_ss_ip, 0, sizeof *local_ss_ip);
376  if (!set_ip_and_port_in_sock_address(ip, 0, local_ss_ip)) {
377  PRINT_ERROR("get_mac_address_from_socket(): Failed to get MAC from given"
378  " IP (%s)", ip);
379  goto err;
380  }
381  } else {
382  PRINT_ERROR("Neither IP nor SOCKADDR given, MAC not fetched");
383  goto err;
384  }
385 
386  /* See how much we need to allocate */
387  if (sysctl(sysctl_flags, 6, NULL, &arp_buffer_size, NULL, 0) < 0) {
388  PRINT_ERROR("get_mac_address_from_socket(): sysctl(): Could not determine "
389  "needed size");
390  goto err;
391  }
392 
393  /* Allocate needed memmory */
394  if ((arp_buffer = malloc(arp_buffer_size)) == NULL) {
395  PRINT_ERROR("get_mac_address_from_socket(): Failed to allocate memory for "
396  "the arp table buffer");
397  goto err;
398  }
399 
400  /* Fetch the arp table */
401  if(sysctl(sysctl_flags, 6, arp_buffer, &arp_buffer_size, NULL, 0) < 0) {
402  PRINT_ERROR("get_mac_address_from_socket(): sysctl(): Could not retrieve "
403  "arp table");
404  goto err;
405  }
406 
407  /* Loop through the arp table/list */
408  arp_buffer_end = arp_buffer + arp_buffer_size;
409  for(arp_buffer_next = arp_buffer; arp_buffer_next < arp_buffer_end;
410  arp_buffer_next += rtm->rtm_msglen) {
411 
412  /* See it through another perspective */
413  rtm = (struct rt_msghdr *)arp_buffer_next;
414 
415  /* Skip to the address portion */
416  sin_arp = (struct sockaddr_inarp *)(rtm + 1);
417  sdl = (struct sockaddr_dl *)(sin_arp + 1);
418 
419  /* Check if this address is the one we are looking for */
420  if (((struct sockaddr_in *)local_ss_ip)->sin_addr.s_addr !=
421  sin_arp->sin_addr.s_addr) {
422  continue;
423  }
424  found_arp = TRUE;
425 
426  /* Then proudly save the MAC to a string */
427  if (sdl->sdl_alen) {
428  unsigned char *cp = (unsigned char *)LLADDR(sdl);
429  sprintf(mac_string, "%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3],
430  cp[4], cp[5]);
431  }
432 
433  }
434 
435  free(arp_buffer);
436  if(local_ss_ip && !ss_ip)
437  free(local_ss_ip);
438 
439  PRINT_DEBUG("Determined MAC string: %s", mac_string);
440  return mac_string;
441 
442 err:
443  if (arp_buffer)
444  free(arp_buffer);
445  if (!mac_buffer)
446  free(mac_string);
447  if (local_ss_ip && !ss_ip)
448  free(local_ss_ip);
449 
450  return NULL;
451 }
452 
453 #else
454 /* Linux variant of the function */
456  const struct sockaddr_storage *ss_ip, const char *ip, char *mac_buffer) {
457  char *mac_string = mac_buffer ? mac_buffer :
458  malloc(sizeof(char) * MAC_STR_MAX_SIZE);
459  memset(mac_string, '\0', MAC_STR_MAX_SIZE);
460 
461  /* Linux (and rest) solution */
462  PRINT_DEBUG("Using Linux style MAC discovery (ioctl SIOCGARP)");
463  struct arpreq arp;
464  unsigned char *mac = NULL;
465 
466  memset(&arp, '\0', sizeof(struct arpreq));
467  sa_family_t ss_fam = AF_INET;
468 
469  /* Sanity check */
470  if(!ss_ip && !ip){
471  PRINT_ERROR("Neither IP string nor sockaddr given, MAC not fetched");
472  if (!mac_buffer)
473  free(mac_string);
474  return NULL;
475  }
476 
477  /* Check if IPv6 */
478  if ((ss_ip && ss_ip->ss_family == AF_INET6)
479  || (ip && is_address_ipv6(ip))) {
480  ss_fam = AF_INET6;
481  PRINT_DEBUG("Looking for IPv6-MAC association");
482  }
483  else if ((ss_ip && ss_ip->ss_family == AF_INET)
484  || (ip && is_address_ipv4(ip))) {
485  PRINT_DEBUG("Looking for IPv4-MAC association");
486  }
487  else {
488  PRINT_ERROR("ss_ip or ip variable error");
489  }
490 
491  /* Assign address family for arpreq */
492  ((struct sockaddr_storage *)&arp.arp_pa)->ss_family = ss_fam;
493 
494  /* Fill the fields */
495  if (ss_ip) {
496  if(ss_fam == AF_INET) {
497  struct in_addr *sin_a = &((struct sockaddr_in *)&arp.arp_pa)->sin_addr;
498  *sin_a = ((struct sockaddr_in *)ss_ip)->sin_addr;
499  }
500  else {
501  struct in6_addr *sin6_a =
502  &((struct sockaddr_in6 *)&arp.arp_pa)->sin6_addr;
503  *sin6_a = ((struct sockaddr_in6 *)ss_ip)->sin6_addr;
504  }
505  }
506  else if (ip) {
508  (struct sockaddr_storage *)&arp.arp_pa)) {
509  PRINT_ERROR("Failed to get MAC from given IP (%s): %s", ip,
510  strerror(errno));
511  if (!mac_buffer)
512  free(mac_string);
513  return NULL;
514  }
515  }
516 
517  /* Go through all interfaces' arp-tables and search for the MAC */
518  /* Possible explanation: Linux arp-tables are if-name specific */
519  struct ifaddrs *interfaces = NULL, *ifa = NULL;
520  if (getifaddrs(&interfaces) < 0) {
521  PRINT_ERROR("get_mac_address_from_socket(): getifaddrs():Could not "
522  "retrieve interfaces");
523  if (!mac_buffer)
524  free(mac_string);
525  return NULL;
526  }
527 
528  /* Start looping through the interfaces*/
529  for(ifa = interfaces; ifa && ifa->ifa_next; ifa = ifa->ifa_next) {
530 
531  /* Skip the loopback interface */
532  if(strcmp(ifa->ifa_name, "lo") == 0) {
533  PRINT_DEBUG("Skipping interface 'lo'");
534  continue;
535  }
536 
537  /* Copy current interface name into the arpreq structure */
538  PRINT_DEBUG("Trying interface '%s'", ifa->ifa_name);
539  strncpy(arp.arp_dev, ifa->ifa_name, 15);
540 
541  ((struct sockaddr_storage *)&arp.arp_ha)->ss_family = ARPHRD_ETHER;
542 
543  /* Ask for the arp-table */
544  if(ioctl(sock, SIOCGARP, &arp) < 0) {
545 
546  /* Handle failure */
547  if(errno == 6) {
548  /* if error is "Unknown device or address" then continue/try
549  next interface */
550  PRINT_DEBUG("get_mac_address_from_socket(): ioctl(): (%d) %s", errno,
551  strerror(errno));
552  continue;
553  }
554  else {
555  PRINT_ERROR("get_mac_address_from_socket(): ioctl(): (%d) %s", errno,
556  strerror(errno));
557  continue;
558  }
559  }
560 
561  mac = (unsigned char *)&arp.arp_ha.sa_data[0];
562 
563  }
564 
565  freeifaddrs(interfaces);
566 
567  if(!mac) {
568  PRINT_DEBUG("mac is NULL");
569  if (!mac_buffer)
570  free(mac_string);
571  return NULL;
572  }
573 
574  sprintf(mac_string, "%x:%x:%x:%x:%x:%x", *mac, *(mac + 1), *(mac + 2),
575  *(mac + 3), *(mac + 4), *(mac + 5));
576  mac = NULL;
577 
578  PRINT_DEBUG("Determined MAC string: %s", mac_string);
579  return mac_string;
580 }
581 #endif
582 
583 BOOL is_address_multicast(const char *address) {
584  char *str_first = NULL;
585  int int_first = 0;
586  BOOL is_ipv6;
587  if (address != NULL) {
588  is_ipv6 = is_address_ipv6(address);
589 
590  if (is_ipv6) {
591  struct in6_addr ip6_ll;
592  struct in6_addr ip6_addr;
593  inet_pton(AF_INET6, "ff02::c", &ip6_ll);
594  inet_pton(AF_INET6, address, &ip6_addr);
595  if (ip6_ll.s6_addr == ip6_addr.s6_addr) {
596  return TRUE;
597  }
598  return FALSE;
599  }
600  else {
601  if (strcmp(address, "0.0.0.0") == 0)
602  return TRUE;
603 
604  str_first = malloc(4);
605  memset(str_first, '\0', 4);
606  strncpy(str_first, address, 3);
607  int_first = atoi(str_first);
608  free(str_first);
609  if (int_first > 223 && int_first < 240) {
610  return TRUE;
611  }
612  return FALSE;
613  }
614  }
615 
616  printf("Supplied address ('%s') is not valid\n", address);
617 
618  return FALSE;
619 }
620 
621 char *get_ip_from_sock_address(const struct sockaddr_storage *saddr,
622  char *ip_buffer) {
623  void *sock_addr;
624  size_t ip_size = IPv4_STR_MAX_SIZE;
625  char *ip = ip_buffer ? ip_buffer : NULL;
626 
627  if (!saddr) {
628  PRINT_DEBUG("Socket address is empty");
629  goto err;
630  }
631 
632  if (saddr->ss_family == AF_INET) {
633  sock_addr = (void *)&((struct sockaddr_in *)saddr)->sin_addr;
634  } else if (saddr->ss_family == AF_INET6) {
635  sock_addr = (void *)&((struct sockaddr_in6 *)saddr)->sin6_addr;
636  ip_size = IPv6_STR_MAX_SIZE;
637  } else {
638  PRINT_WARN("Not an IP socket address");
639  goto err;
640  }
641 
642  if (!ip)
643  ip = malloc(ip_size);
644 
645  if (inet_ntop(saddr->ss_family, sock_addr, ip, ip_size) == NULL) {
646  PRINT_ERROR("Erroneous sock address");
647  if (!ip_buffer)
648  free(ip);
649  else
650  ip_buffer[0] = '\0';
651 
652  ip = NULL;
653  }
654 
655 err:
656  return ip;
657 }
658 
659 inline BOOL is_address_ipv6(const char *ip) {
660  struct sockaddr_in6 saddr6;
661 
662  return inet_pton(AF_INET6, ip, (void *)&saddr6) > 0;
663 }
664 
665 BOOL is_address_ipv6_ex(const char *ip, struct sockaddr_in6 *saddr6) {
666  BOOL is_ipv6 = inet_pton(AF_INET6, ip, (void *)&saddr6->sin6_addr) > 0;
667 
668  if (is_ipv6)
669  saddr6->sin6_family = AF_INET6;
670 
671  return is_ipv6;
672 }
673 
674 inline BOOL is_address_ipv4(const char *ip) {
675  struct in_addr saddr;
676 
677  return inet_pton(AF_INET, ip, (void *)&saddr) > 0;
678 }
679 
680 BOOL is_address_ipv4_ex(const char *ip, struct sockaddr_in *saddr) {
681  BOOL is_ipv4 = inet_pton(AF_INET, ip, (void *)&saddr->sin_addr) > 0;
682 
683  if (is_ipv4)
684  saddr->sin_family = AF_INET;
685 
686  return is_ipv4;
687 }
688 
689 BOOL set_ip_and_port_in_sock_address(const char *ip, int port,
690  struct sockaddr_storage *saddr) {
691  int res = 0;
692  void *sock_addr;
693  in_port_t *sock_port;
694 
695  if (!ip) {
696  PRINT_DEBUG("IP address is empty");
697  goto err;
698  }
699 
700  if (port < 1 || port > 65535) {
701  PRINT_DEBUG("Invalid port number");
702  goto err;
703  }
704 
705  if (!saddr) {
706  PRINT_DEBUG("Socket address is empty");
707  goto err;
708  }
709 
710  if (is_address_ipv6_ex(ip, (struct sockaddr_in6 *)saddr)) {
711  sock_addr = (void *)&((struct sockaddr_in6 *)saddr)->sin6_addr;
712  sock_port = (in_port_t *)&((struct sockaddr_in6 *)saddr)->sin6_port;
713  } else if (is_address_ipv4_ex(ip, (struct sockaddr_in *)saddr)) {
714  sock_addr = (void *)&((struct sockaddr_in *)saddr)->sin_addr;
715  sock_port = (in_port_t *)&((struct sockaddr_in *)saddr)->sin_port;
716  } else {
717  PRINT_ERROR("Erroneous IP address");
718  goto err;
719  }
720 
721  res = inet_pton(saddr->ss_family, ip, sock_addr);
722  if (res > 0)
723  *sock_port = htons(port);
724 
725 err:
726  return res > 0;
727 }
728 
729 int get_port_from_sock_address(const struct sockaddr_storage *saddr) {
730  int port = 0;
731 
732  if (saddr->ss_family == AF_INET) {
733  port = ntohs(((struct sockaddr_in *)saddr)->sin_port);
734  } else if (saddr->ss_family == AF_INET6) {
735  port = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port);
736  } else {
737  PRINT_ERROR("Erroneous socket address");
738  }
739 
740  return port;
741 }
#define IPv6_STR_MAX_SIZE
BOOL is_address_ipv4(const char *ip)
Definition: net_utils.c:674
#define IPv4_STR_MAX_SIZE
char * get_ip_from_sock_address(const struct sockaddr_storage *saddr, char *ip_buffer)
Definition: net_utils.c:621
int SOCKET
BOOL is_address_ipv4_ex(const char *ip, struct sockaddr_in *saddr)
Definition: net_utils.c:680
BOOL is_address_ipv6_ex(const char *ip, struct sockaddr_in6 *saddr6)
Definition: net_utils.c:665
#define TRUE
int parse_address(const char *raw_address, struct sockaddr_storage *address)
Definition: net_utils.c:33
#define FALSE
char * get_mac_address_from_socket(const SOCKET sock, const struct sockaddr_storage *ss_ip, const char *ip, char *mac_buffer)
Definition: net_utils.c:455
int get_port_from_sock_address(const struct sockaddr_storage *saddr)
Definition: net_utils.c:729
#define SIOCGARP
int strpos(const char *haystack, const char *needle)
Definition: string_utils.c:11
BOOL parse_url(const char *url, char *ip, int ip_size, int *port, char *rest, int rest_size)
Definition: net_utils.c:107
#define PORT_MAX_NUMBER
int BOOL
int find_interface(struct sockaddr_storage *saddr, const char *interface, const char *address)
Definition: net_utils.c:192
BOOL is_address_multicast(const char *address)
Definition: net_utils.c:583
#define MAC_STR_MAX_SIZE
BOOL set_ip_and_port_in_sock_address(const char *ip, int port, struct sockaddr_storage *saddr)
Definition: net_utils.c:689
BOOL is_address_ipv6(const char *ip)
Definition: net_utils.c:659