33 #include <sys/socket.h>
34 #include <net/if_arp.h>
35 #include <netinet/in.h>
36 #include <linux/netlink.h>
37 #include <linux/rtnetlink.h>
38 #include <linux/if_packet.h>
49 struct sockaddr_nl l_addr;
52 int l_socket =
socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
58 memset(&l_addr, 0,
sizeof(l_addr));
59 l_addr.nl_family = AF_NETLINK;
60 if(bind(l_socket, (
struct sockaddr *)&l_addr,
sizeof(l_addr)) < 0)
66 l_len =
sizeof(l_addr);
67 if(getsockname(l_socket, (
struct sockaddr *)&l_addr, &l_len) < 0)
72 *p_pid = l_addr.nl_pid;
79 char l_buffer[NLMSG_ALIGN(
sizeof(
struct nlmsghdr)) + NLMSG_ALIGN(
sizeof(
struct rtgenmsg))];
81 struct nlmsghdr *l_hdr;
82 struct rtgenmsg *l_msg;
83 struct sockaddr_nl l_addr;
85 memset(l_buffer, 0,
sizeof(l_buffer));
87 l_hdr = (
struct nlmsghdr *)l_buffer;
88 l_msg = (
struct rtgenmsg *)NLMSG_DATA(l_hdr);
90 l_hdr->nlmsg_len = NLMSG_LENGTH(
sizeof(*l_msg));
91 l_hdr->nlmsg_type = p_request;
92 l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
94 l_hdr->nlmsg_seq = p_socket;
95 l_msg->rtgen_family = AF_UNSPEC;
97 memset(&l_addr, 0,
sizeof(l_addr));
98 l_addr.nl_family = AF_NETLINK;
99 return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (
struct sockaddr *)&l_addr,
sizeof(l_addr)));
104 struct sockaddr_nl l_addr;
114 l_msg.msg_name = (
void *)&l_addr;
115 l_msg.msg_namelen =
sizeof(l_addr);
116 l_msg.msg_iov = &l_iov;
117 l_msg.msg_iovlen = 1;
118 l_msg.msg_control = NULL;
119 l_msg.msg_controllen = 0;
121 l_result = recvmsg(p_socket, &l_msg, 0);
133 if(l_msg.msg_flags & MSG_TRUNC)
143 size_t l_size = 4096;
144 void *l_buffer = NULL;
152 if (l_buffer == NULL)
166 struct nlmsghdr *l_hdr;
167 for(l_hdr = (
struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (
unsigned int)l_read); l_hdr = (
struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
169 if((pid_t)l_hdr->nlmsg_pid != p_pid || (
int)l_hdr->nlmsg_seq != p_socket)
174 if(l_hdr->nlmsg_type == NLMSG_DONE)
180 if(l_hdr->nlmsg_type == NLMSG_ERROR)
268 return (
a >
b ?
a :
b);
276 return sizeof(
struct sockaddr_in);
280 return maxSize(
sizeof(
struct sockaddr_ll), offsetof(
struct sockaddr_ll, sll_addr) + p_dataSize);
282 return maxSize(
sizeof(
struct sockaddr), offsetof(
struct sockaddr, sa_data) + p_dataSize);
286 static void makeSockaddr(sa_family_t p_family,
struct sockaddr *p_dest,
void *p_data,
size_t p_size)
291 memcpy(&((
struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
297 memcpy(((
struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
298 ((
struct sockaddr_ll*)p_dest)->sll_halen = p_size;
301 memcpy(p_dest->sa_data, p_data, p_size);
304 p_dest->sa_family = p_family;
311 *p_resultList = p_entry;
315 struct ifaddrs *l_cur = *p_resultList;
333 struct ifinfomsg *l_info = (
struct ifinfomsg *)NLMSG_DATA(p_hdr);
335 size_t l_nameSize = 0;
336 size_t l_addrSize = 0;
337 size_t l_dataSize = 0;
339 size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr,
sizeof(
struct ifinfomsg));
340 struct rtattr *l_rta;
341 for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
343 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
344 switch(l_rta->rta_type)
348 l_addrSize += NLMSG_ALIGN(
calcAddrLen(AF_PACKET, l_rtaDataSize));
351 l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
354 l_dataSize += NLMSG_ALIGN(l_rtaSize);
361 l_entry =
uv__malloc(
sizeof(
struct ifaddrs) +
sizeof(
int) + l_nameSize + l_addrSize + l_dataSize);
369 l_index = ((
char *)l_entry) +
sizeof(
struct ifaddrs);
370 l_name = l_index +
sizeof(
int);
371 l_addr = l_name + l_nameSize;
372 l_data = l_addr + l_addrSize;
377 memcpy(l_index, &l_info->ifi_index,
sizeof(
int));
381 l_rtaSize = NLMSG_PAYLOAD(p_hdr,
sizeof(
struct ifinfomsg));
382 for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
384 void *l_rtaData = RTA_DATA(l_rta);
385 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
386 switch(l_rta->rta_type)
391 size_t l_addrLen =
calcAddrLen(AF_PACKET, l_rtaDataSize);
392 makeSockaddr(AF_PACKET, (
struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
393 ((
struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
394 ((
struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
395 if(l_rta->rta_type == IFLA_ADDRESS)
397 l_entry->
ifa_addr = (
struct sockaddr *)l_addr;
401 l_entry->ifa_broadaddr = (
struct sockaddr *)l_addr;
403 l_addr += NLMSG_ALIGN(l_addrLen);
407 strncpy(l_name, l_rtaData, l_rtaDataSize);
408 l_name[l_rtaDataSize] =
'\0';
412 memcpy(l_data, l_rtaData, l_rtaDataSize);
427 struct ifaddrs *l_cur = *p_links;
428 while(l_cur && l_num < p_numLinks)
430 char *l_indexPtr = ((
char *)l_cur) +
sizeof(
struct ifaddrs);
432 memcpy(&l_index, l_indexPtr,
sizeof(
int));
433 if(l_index == p_index)
446 struct ifaddrmsg *l_info = (
struct ifaddrmsg *)NLMSG_DATA(p_hdr);
449 size_t l_nameSize = 0;
450 size_t l_addrSize = 0;
452 int l_addedNetmask = 0;
454 size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr,
sizeof(
struct ifaddrmsg));
455 struct rtattr *l_rta;
461 for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
463 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
464 if(l_info->ifa_family == AF_PACKET)
469 switch(l_rta->rta_type)
473 l_addrSize += NLMSG_ALIGN(
calcAddrLen(l_info->ifa_family, l_rtaDataSize));
474 if((l_info->ifa_family == AF_INET || l_info->ifa_family ==
AF_INET6) && !l_addedNetmask)
477 l_addrSize += NLMSG_ALIGN(
calcAddrLen(l_info->ifa_family, l_rtaDataSize));
482 l_addrSize += NLMSG_ALIGN(
calcAddrLen(l_info->ifa_family, l_rtaDataSize));
485 l_nameSize += NLMSG_ALIGN(l_rtaDataSize + 1);
500 l_name = ((
char *)l_entry) +
sizeof(
struct ifaddrs);
501 l_addr = l_name + l_nameSize;
509 l_rtaSize = NLMSG_PAYLOAD(p_hdr,
sizeof(
struct ifaddrmsg));
510 for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
512 void *l_rtaData = RTA_DATA(l_rta);
513 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
514 switch(l_rta->rta_type)
520 size_t l_addrLen =
calcAddrLen(l_info->ifa_family, l_rtaDataSize);
521 makeSockaddr(l_info->ifa_family, (
struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
524 if(IN6_IS_ADDR_LINKLOCAL((
struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((
struct in6_addr *)l_rtaData))
526 ((
struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
533 if(l_rta->rta_type == IFA_ADDRESS)
541 l_entry->
ifa_addr = (
struct sockaddr *)l_addr;
544 else if(l_rta->rta_type == IFA_LOCAL)
550 l_entry->
ifa_addr = (
struct sockaddr *)l_addr;
554 l_entry->ifa_broadaddr = (
struct sockaddr *)l_addr;
556 l_addr += NLMSG_ALIGN(l_addrLen);
560 strncpy(l_name, l_rtaData, l_rtaDataSize);
561 l_name[l_rtaDataSize] =
'\0';
571 unsigned l_maxPrefix = (l_entry->
ifa_addr->sa_family == AF_INET ? 32 : 128);
572 unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
573 unsigned char l_mask[16] = {0};
575 for(
i=0;
i<(l_prefix/8); ++
i)
581 l_mask[
i] = 0xff << (8 - (l_prefix % 8));
596 for(; p_netlinkList; p_netlinkList = p_netlinkList->
m_next)
598 unsigned int l_nlsize = p_netlinkList->
m_size;
599 struct nlmsghdr *l_hdr;
600 for(l_hdr = p_netlinkList->
m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
602 if((pid_t)l_hdr->nlmsg_pid != p_pid || (
int)l_hdr->nlmsg_seq != p_socket)
607 if(l_hdr->nlmsg_type == NLMSG_DONE)
612 if(l_hdr->nlmsg_type == RTM_NEWLINK)
627 for(; p_netlinkList; p_netlinkList = p_netlinkList->
m_next)
629 unsigned int l_nlsize = p_netlinkList->
m_size;
630 struct nlmsghdr *l_hdr;
631 for(l_hdr = p_netlinkList->
m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
633 if((pid_t)l_hdr->nlmsg_pid != p_pid || (
int)l_hdr->nlmsg_seq != p_socket)
638 if(l_hdr->nlmsg_type == NLMSG_DONE)
643 if(l_hdr->nlmsg_type == RTM_NEWADDR)
692 l_numLinks =
interpretLinks(l_socket, l_pid, l_linkResults, ifap);
693 if(l_numLinks == -1 ||
interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1)