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;
58 memset(&l_addr, 0,
sizeof(l_addr));
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;
97 memset(&l_addr, 0,
sizeof(l_addr));
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;
108 l_iov.iov_base = p_buffer;
109 l_iov.iov_len = p_len;
121 l_result = recvmsg(p_socket, &l_msg, 0);
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);
280 return maxSize(
sizeof(
struct sockaddr_ll),
offsetof(
struct sockaddr_ll, sll_addr) + p_dataSize);
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)
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)
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)
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);
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);
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)
544 else if(l_rta->rta_type == IFA_LOCAL)
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)
static NetlinkList * getResultList(int p_socket, int p_request, pid_t p_pid)
static int netlink_send(int p_socket, int p_request)
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
static NetlinkList * newListItem(struct nlmsghdr *p_data, unsigned int p_size)
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
static struct nlmsghdr * getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done)
static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
static int netlink_socket(pid_t *p_pid)
static struct ifaddrs * findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
int getifaddrs(struct ifaddrs **ifap)
static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
struct NetlinkList NetlinkList
static void freeResultList(NetlinkList *p_list)
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
void freeifaddrs(struct ifaddrs *ifa)
static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
static size_t maxSize(size_t a, size_t b)
static static fork const void static count close
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd socket
#define offsetof(type, member)
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen sendto
unsigned short int sa_family_t
struct NetlinkList * m_next
struct sockaddr * ifa_addr
struct ifaddrs * ifa_next
struct sockaddr * ifa_dstaddr
struct sockaddr * ifa_netmask
struct in6_addr sin6_addr
void * uv__malloc(size_t size)