11 #include <net/if_arp.h>
12 #include <netinet/in.h>
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
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>
34 struct sockaddr_storage *address) {
41 PRINT_DEBUG(
"parse_address()");
43 if(!raw_address || strlen(raw_address) < 1) {
44 PRINT_ERROR(
"No valid IP address specified");
49 memset(address, 0,
sizeof(
struct sockaddr_storage));
50 colon_pos =
strpos(raw_address,
":");
53 PRINT_ERROR(
"No valid port specified (%s)\n", raw_address);
61 strncpy(ip, strchr(raw_address,
'[') + 1,
62 strchr(raw_address,
'[') - strchr(raw_address,
']'));
64 is_ipv6 = inet_pton(AF_INET6, ip, address);
65 PRINT_DEBUG(
"is_ipv6 == %s", is_ipv6 ?
"TRUE" :
"FALSE");
67 address->ss_family = AF_INET6;
68 port = atoi(strrchr(raw_address,
':') + 1);
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);
77 address->ss_family = AF_INET;
78 port = atoi(raw_address + colon_pos + 1);
82 PRINT_ERROR(
"No valid port specified (%d)\n", port);
87 ((
struct sockaddr_in6 *)address)->sin6_port = htons(port);
90 ((
struct sockaddr_in *)address)->sin_port = htons(port);
107 BOOL parse_url(
const char *url,
char *ip,
int ip_size,
int *port,
char *rest,
111 if(!url || strlen(url) < 8) {
112 PRINT_ERROR(
"The argument 'url' is not set or is empty");
116 PRINT_DEBUG(
"passed url: %s", url);
118 if(*(url + 4) ==
's') {
120 PRINT_DEBUG(
"HTTPS is not supported, skipping");
124 const char *ip_begin = strchr(url,
':') + 3;
125 PRINT_DEBUG(
"ip_begin: %s", ip_begin);
127 PRINT_DEBUG(
"is_ipv6: %s", (is_ipv6 ?
"TRUE" :
"FALSE"));
129 char *rest_begin = NULL;
131 if(!(rest_begin = strchr(ip_begin,
']')) || !(rest_begin = strchr(rest_begin,
'/'))) {
133 PRINT_ERROR(
"Error: (IPv6) rest_begin is NULL\n");
136 PRINT_DEBUG(
"rest_begin: %s", rest_begin);
139 if(!(rest_begin = strchr(ip_begin,
'/'))) {
140 PRINT_ERROR(
"Error: rest_begin is NULL\n");
145 if(rest_begin != NULL) {
146 strcpy(rest, rest_begin);
149 char *working_str = (
char *)malloc(
sizeof(
char) * 256);
151 memset(working_str,
'\0', 256);
153 PRINT_DEBUG(
"size to copy: %d", (
int)(rest_begin - ip_begin));
154 strncpy(working_str, ip_begin, (
size_t)(rest_begin - ip_begin));
155 PRINT_DEBUG(
"working_str: %s", working_str);
156 char *port_begin = strrchr(working_str,
':');
157 PRINT_DEBUG(
"port_begin: %s", port_begin);
158 if(port_begin != NULL) {
161 sscanf(working_str,
"%s %d", ip_with_brackets, port);
162 PRINT_DEBUG(
"port: %d", *port);
163 if(strlen(ip_with_brackets) < 1) {
164 PRINT_ERROR(
"Malformed header_location detected in: '%s'", url);
166 free(ip_with_brackets);
169 if(*ip_with_brackets ==
'[') {
170 PRINT_DEBUG(
"ip_with_brackets: %s", ip_with_brackets);
176 strcpy(ip, ip_with_brackets);
177 PRINT_DEBUG(
"ip: %s", ip);
180 if(rest_begin == NULL) {
181 PRINT_ERROR(
"Malformed header_location detected in: '%s'", url);
183 free(ip_with_brackets);
188 free(ip_with_brackets);
193 const char *address) {
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;
202 PRINT_DEBUG(
"find_interface(%s, \"%s\", \"%s\")",
203 saddr == NULL ? NULL :
"saddr",
209 PRINT_ERROR(
"No interface string-buffer available");
214 PRINT_ERROR(
"No IP address string-buffer available");
219 PRINT_ERROR(
"No address structure-buffer available");
224 is_ipv6 = inet_pton(AF_INET6,
226 (
void *)&saddr6->sin6_addr) > 0;
230 if (((strlen(interface) == 0) && (strlen(address) == 0)) ||
231 (strcmp(
"0.0.0.0", address) == 0) || (strcmp(
"::", address) == 0)) {
233 saddr->ss_family = AF_INET6;
234 saddr6->sin6_addr = in6addr_any;
235 PRINT_DEBUG(
"find_interface(): Matched all addresses (::)\n");
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)");
246 if (getifaddrs(&interfaces) < 0) {
247 PRINT_ERROR(
"Could not find any interfaces\n");
254 for (ifa = interfaces; ifa && ifa->ifa_next; ifa = ifa->ifa_next) {
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;
261 memset(compare_address,
'\0',
sizeof(
char) * IPv6_STR_MAX_SIZE);
264 if (is_ipv6 && ss_family == AF_INET6) {
265 PRINT_DEBUG(
"Extracting an IPv6 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));
274 else if (!is_ipv6 && ss_family == AF_INET) {
275 PRINT_DEBUG(
"Extracting an IPv4 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));
296 BOOL addr_is_bindall = ((strcmp(
"0.0.0.0", address) == 0) ||
297 (strcmp(
"::", address) == 0) || (strlen(address) == 0)) ?
TRUE :
FALSE;
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) &&
304 addr_present && (strcmp(address, compare_address) == 0)) ||
309 ifindex = if_nametoindex(ifa->ifa_name);
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);
316 if (!is_ipv6 && ss_family == AF_INET) {
317 saddr4->sin_addr = ifaddr4->sin_addr;
318 PRINT_DEBUG(
"Setting IPv4 saddr");
320 else if (is_ipv6 && ss_family == AF_INET6){
321 saddr6->sin6_addr = ifaddr6->sin6_addr;
322 PRINT_DEBUG(
"Setting IPv6 saddr");
326 saddr->ss_family = ss_family;
330 PRINT_DEBUG(
"Match failed, trying next interface (if any)");
337 freeifaddrs(interfaces);
341 if(compare_address != NULL) {
342 free(compare_address);
348 #if defined BSD || defined __APPLE__
352 const struct sockaddr_storage *ss_ip,
const char *ip,
char *mac_buffer) {
353 char *mac_string = mac_buffer ? mac_buffer :
357 PRINT_DEBUG(
"Using BSD style MAC discovery (sysctl)");
358 int sysctl_flags[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS,
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;
368 struct sockaddr_storage *local_ss_ip = NULL;
372 local_ss_ip = (
struct sockaddr_storage *)ss_ip;
374 local_ss_ip = malloc(
sizeof *local_ss_ip);
375 memset(local_ss_ip, 0,
sizeof *local_ss_ip);
377 PRINT_ERROR(
"get_mac_address_from_socket(): Failed to get MAC from given"
382 PRINT_ERROR(
"Neither IP nor SOCKADDR given, MAC not fetched");
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 "
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");
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 "
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) {
413 rtm = (
struct rt_msghdr *)arp_buffer_next;
416 sin_arp = (
struct sockaddr_inarp *)(rtm + 1);
417 sdl = (
struct sockaddr_dl *)(sin_arp + 1);
420 if (((
struct sockaddr_in *)local_ss_ip)->sin_addr.s_addr !=
421 sin_arp->sin_addr.s_addr) {
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],
436 if(local_ss_ip && !ss_ip)
439 PRINT_DEBUG(
"Determined MAC string: %s", mac_string);
447 if (local_ss_ip && !ss_ip)
456 const struct sockaddr_storage *ss_ip,
const char *ip,
char *mac_buffer) {
457 char *mac_string = mac_buffer ? mac_buffer :
459 memset(mac_string,
'\0', MAC_STR_MAX_SIZE);
462 PRINT_DEBUG(
"Using Linux style MAC discovery (ioctl SIOCGARP)");
464 unsigned char *mac = NULL;
466 memset(&arp,
'\0',
sizeof(
struct arpreq));
467 sa_family_t ss_fam = AF_INET;
471 PRINT_ERROR(
"Neither IP string nor sockaddr given, MAC not fetched");
478 if ((ss_ip && ss_ip->ss_family == AF_INET6)
481 PRINT_DEBUG(
"Looking for IPv6-MAC association");
483 else if ((ss_ip && ss_ip->ss_family == AF_INET)
485 PRINT_DEBUG(
"Looking for IPv4-MAC association");
488 PRINT_ERROR(
"ss_ip or ip variable error");
492 ((
struct sockaddr_storage *)&arp.arp_pa)->ss_family = ss_fam;
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;
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;
508 (
struct sockaddr_storage *)&arp.arp_pa)) {
509 PRINT_ERROR(
"Failed to get MAC from given IP (%s): %s", ip,
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");
529 for(ifa = interfaces; ifa && ifa->ifa_next; ifa = ifa->ifa_next) {
532 if(strcmp(ifa->ifa_name,
"lo") == 0) {
533 PRINT_DEBUG(
"Skipping interface 'lo'");
538 PRINT_DEBUG(
"Trying interface '%s'", ifa->ifa_name);
539 strncpy(arp.arp_dev, ifa->ifa_name, 15);
541 ((
struct sockaddr_storage *)&arp.arp_ha)->ss_family = ARPHRD_ETHER;
544 if(ioctl(sock,
SIOCGARP, &arp) < 0) {
550 PRINT_DEBUG(
"get_mac_address_from_socket(): ioctl(): (%d) %s", errno,
555 PRINT_ERROR(
"get_mac_address_from_socket(): ioctl(): (%d) %s", errno,
561 mac = (
unsigned char *)&arp.arp_ha.sa_data[0];
565 freeifaddrs(interfaces);
568 PRINT_DEBUG(
"mac is NULL");
574 sprintf(mac_string,
"%x:%x:%x:%x:%x:%x", *mac, *(mac + 1), *(mac + 2),
575 *(mac + 3), *(mac + 4), *(mac + 5));
578 PRINT_DEBUG(
"Determined MAC string: %s", mac_string);
584 char *str_first = NULL;
587 if (address != NULL) {
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) {
601 if (strcmp(address,
"0.0.0.0") == 0)
604 str_first = malloc(4);
605 memset(str_first,
'\0', 4);
606 strncpy(str_first, address, 3);
607 int_first = atoi(str_first);
609 if (int_first > 223 && int_first < 240) {
616 printf(
"Supplied address ('%s') is not valid\n", address);
625 char *ip = ip_buffer ? ip_buffer : NULL;
628 PRINT_DEBUG(
"Socket address is empty");
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;
638 PRINT_WARN(
"Not an IP socket address");
643 ip = malloc(ip_size);
645 if (inet_ntop(saddr->ss_family, sock_addr, ip, ip_size) == NULL) {
646 PRINT_ERROR(
"Erroneous sock address");
660 struct sockaddr_in6 saddr6;
662 return inet_pton(AF_INET6, ip, (
void *)&saddr6) > 0;
666 BOOL is_ipv6 = inet_pton(AF_INET6, ip, (
void *)&saddr6->sin6_addr) > 0;
669 saddr6->sin6_family = AF_INET6;
675 struct in_addr saddr;
677 return inet_pton(AF_INET, ip, (
void *)&saddr) > 0;
681 BOOL is_ipv4 = inet_pton(AF_INET, ip, (
void *)&saddr->sin_addr) > 0;
684 saddr->sin_family = AF_INET;
690 struct sockaddr_storage *saddr) {
693 in_port_t *sock_port;
696 PRINT_DEBUG(
"IP address is empty");
700 if (port < 1 || port > 65535) {
701 PRINT_DEBUG(
"Invalid port number");
706 PRINT_DEBUG(
"Socket address is empty");
711 sock_addr = (
void *)&((
struct sockaddr_in6 *)saddr)->sin6_addr;
712 sock_port = (in_port_t *)&((
struct sockaddr_in6 *)saddr)->sin6_port;
714 sock_addr = (
void *)&((
struct sockaddr_in *)saddr)->sin_addr;
715 sock_port = (in_port_t *)&((
struct sockaddr_in *)saddr)->sin_port;
717 PRINT_ERROR(
"Erroneous IP address");
721 res = inet_pton(saddr->ss_family, ip, sock_addr);
723 *sock_port = htons(port);
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);
737 PRINT_ERROR(
"Erroneous socket address");
#define IPv6_STR_MAX_SIZE
BOOL is_address_ipv4(const char *ip)
#define IPv4_STR_MAX_SIZE
char * get_ip_from_sock_address(const struct sockaddr_storage *saddr, char *ip_buffer)
BOOL is_address_ipv4_ex(const char *ip, struct sockaddr_in *saddr)
BOOL is_address_ipv6_ex(const char *ip, struct sockaddr_in6 *saddr6)
int parse_address(const char *raw_address, struct sockaddr_storage *address)
char * get_mac_address_from_socket(const SOCKET sock, const struct sockaddr_storage *ss_ip, const char *ip, char *mac_buffer)
int get_port_from_sock_address(const struct sockaddr_storage *saddr)
int strpos(const char *haystack, const char *needle)
BOOL parse_url(const char *url, char *ip, int ip_size, int *port, char *rest, int rest_size)
int find_interface(struct sockaddr_storage *saddr, const char *interface, const char *address)
BOOL is_address_multicast(const char *address)
BOOL set_ip_and_port_in_sock_address(const char *ip, int port, struct sockaddr_storage *saddr)
BOOL is_address_ipv6(const char *ip)