ifaddrs.c revision da4cacd1fa7a02a59b1b2adf8dcac58da7dfd81e
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber/*
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberCopyright (c) 2013, Kenneth MacKay
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberAll rights reserved.
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberRedistribution and use in source and binary forms, with or without modification,
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberare permitted provided that the following conditions are met:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber * Redistributions of source code must retain the above copyright notice, this
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber list of conditions and the following disclaimer.
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber * Redistributions in binary form must reproduce the above copyright notice,
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber this list of conditions and the following disclaimer in the documentation
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber and/or other materials provided with the distribution.
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane GraberSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber*/
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include "ifaddrs.h"
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <string.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <stdlib.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <errno.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <unistd.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <sys/socket.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <net/if_arp.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <netinet/in.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <linux/netlink.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber#include <linux/rtnetlink.h>
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Grabertypedef struct NetlinkList
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct NetlinkList *m_next;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct nlmsghdr *m_data;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned int m_size;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber} NetlinkList;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic int netlink_socket(void)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_socket < 0)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct sockaddr_nl l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memset(&l_addr, 0, sizeof(l_addr));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addr.nl_family = AF_NETLINK;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber close(l_socket);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return l_socket;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic int netlink_send(int p_socket, int p_request)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memset(l_buffer, 0, sizeof(l_buffer));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_hdr->nlmsg_type = p_request;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_hdr->nlmsg_pid = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_hdr->nlmsg_seq = p_socket;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg->rtgen_family = AF_UNSPEC;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct sockaddr_nl l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memset(&l_addr, 0, sizeof(l_addr));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addr.nl_family = AF_NETLINK;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct msghdr l_msg;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct iovec l_iov = { p_buffer, p_len };
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct sockaddr_nl l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(;;)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg.msg_name = (void *)&l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg.msg_namelen = sizeof(l_addr);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg.msg_iov = &l_iov;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg.msg_iovlen = 1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg.msg_control = NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg.msg_controllen = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_msg.msg_flags = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber int l_result = recvmsg(p_socket, &l_msg, 0);
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_result < 0)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(errno == EINTR)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber continue;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -2;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_msg.msg_flags & MSG_TRUNC)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber { // buffer was too small
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return l_result;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_size = 4096;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber void *l_buffer = NULL;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(;;)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber free(l_buffer);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_buffer = malloc(l_size);
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber int l_read = netlink_recv(p_socket, l_buffer, l_size);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber *p_size = l_read;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_read == -2)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber free(l_buffer);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_read >= 0)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber pid_t l_pid = getpid();
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct nlmsghdr *l_hdr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber 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))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber continue;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_hdr->nlmsg_type == NLMSG_DONE)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber *p_done = 1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_hdr->nlmsg_type == NLMSG_ERROR)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber free(l_buffer);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return l_buffer;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_size *= 2;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber NetlinkList *l_item = malloc(sizeof(NetlinkList));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_item->m_next = NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_item->m_data = p_data;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_item->m_size = p_size;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return l_item;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic void freeResultList(NetlinkList *p_list)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber NetlinkList *l_cur;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber while(p_list)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_cur = p_list;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber p_list = p_list->m_next;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber free(l_cur->m_data);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber free(l_cur);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic NetlinkList *getResultList(int p_socket, int p_request)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(netlink_send(p_socket, p_request) < 0)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber NetlinkList *l_list = NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber NetlinkList *l_end = NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber int l_size;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber int l_done = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber while(!l_done)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(!l_hdr)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber { // error
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber freeResultList(l_list);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return NULL;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber NetlinkList *l_item = newListItem(l_hdr, l_size);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(!l_list)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_list = l_item;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber else
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_end->m_next = l_item;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_end = l_item;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return l_list;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic size_t maxSize(size_t a, size_t b)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return (a > b ? a : b);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber switch(p_family)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case AF_INET:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return sizeof(struct sockaddr_in);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case AF_INET6:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return sizeof(struct sockaddr_in6);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case AF_PACKET:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber default:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber switch(p_family)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case AF_INET:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case AF_INET6:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case AF_PACKET:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber ((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber default:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memcpy(p_dest->sa_data, p_data, p_size);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber p_dest->sa_family = p_family;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(!*p_resultList)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber *p_resultList = p_entry;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber else
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct ifaddrs *l_cur = *p_resultList;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber while(l_cur->ifa_next)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_cur = l_cur->ifa_next;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_cur->ifa_next = p_entry;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_nameSize = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_addrSize = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_dataSize = 0;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct rtattr *l_rta;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber switch(l_rta->rta_type)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_ADDRESS:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_BROADCAST:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_IFNAME:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_STATS:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_dataSize += NLMSG_ALIGN(l_rtaSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber default:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memset(l_entry, 0, sizeof(struct ifaddrs));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_name = "";
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber char *l_addr = l_name + l_nameSize;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber char *l_data = l_addr + l_addrSize;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_flags = l_info->ifi_flags;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber void *l_rtaData = RTA_DATA(l_rta);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber switch(l_rta->rta_type)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_ADDRESS:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_BROADCAST:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_rta->rta_type == IFLA_ADDRESS)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_addr = (struct sockaddr *)l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber else
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addr += NLMSG_ALIGN(l_addrLen);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_IFNAME:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber strncpy(l_name, l_rtaData, l_rtaDataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_name[l_rtaDataSize] = '\0';
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_name = l_name;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFLA_STATS:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memcpy(l_data, l_rtaData, l_rtaDataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_data = l_data;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber default:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber addToEnd(p_resultList, l_entry);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber p_links[l_info->ifi_index - 1] = l_entry;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_nameSize = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_addrSize = 0;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber int l_addedNetmask = 0;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct rtattr *l_rta;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_info->ifa_family == AF_PACKET)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber continue;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber switch(l_rta->rta_type)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_ADDRESS:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_LOCAL:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber { // make room for netmask
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addedNetmask = 1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_BROADCAST:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_LABEL:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber default:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memset(l_entry, 0, sizeof(struct ifaddrs));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber char *l_addr = l_name + l_nameSize;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber void *l_rtaData = RTA_DATA(l_rta);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber switch(l_rta->rta_type)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_ADDRESS:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_BROADCAST:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_LOCAL:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_info->ifa_family == AF_INET6)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_rta->rta_type == IFA_ADDRESS)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_entry->ifa_addr)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber else
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_addr = (struct sockaddr *)l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber else if(l_rta->rta_type == IFA_LOCAL)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_entry->ifa_addr)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_dstaddr = l_entry->ifa_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_addr = (struct sockaddr *)l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber else
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_addr += NLMSG_ALIGN(l_addrLen);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber case IFA_LABEL:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber strncpy(l_name, l_rtaData, l_rtaDataSize);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_name[l_rtaDataSize] = '\0';
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_name = l_name;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber default:
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber char l_mask[16] = {0};
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned i;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(i=0; i<(l_prefix/8); ++i)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_mask[i] = 0xff;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
da4cacd1fa7a02a59b1b2adf8dcac58da7dfd81etw if (l_prefix % 8) {
da4cacd1fa7a02a59b1b2adf8dcac58da7dfd81etw l_mask[i] = 0xff << (8 - (l_prefix % 8));
da4cacd1fa7a02a59b1b2adf8dcac58da7dfd81etw }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_entry->ifa_netmask = (struct sockaddr *)l_addr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber addToEnd(p_resultList, l_entry);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber pid_t l_pid = getpid();
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned int l_nlsize = p_netlinkList->m_size;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct nlmsghdr *l_hdr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber continue;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_hdr->nlmsg_type == NLMSG_DONE)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_hdr->nlmsg_type == RTM_NEWLINK)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber interpretLink(l_hdr, p_links, p_resultList);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber else if(l_hdr->nlmsg_type == RTM_NEWADDR)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber interpretAddr(l_hdr, p_links, p_resultList);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberstatic unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned l_links = 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber pid_t l_pid = getpid();
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned int l_nlsize = p_netlinkList->m_size;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct nlmsghdr *l_hdr;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber continue;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_hdr->nlmsg_type == NLMSG_DONE)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber break;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_hdr->nlmsg_type == RTM_NEWLINK)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber ++l_links;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return l_links;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graberint getifaddrs(struct ifaddrs **ifap)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(!ifap)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber *ifap = NULL;
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber int l_socket = netlink_socket();
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(l_socket < 0)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(!l_linkResults)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber close(l_socket);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber if(!l_addrResults)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber close(l_socket);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber freeResultList(l_linkResults);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return -1;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct ifaddrs *l_links[l_numLinks];
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
55c76589fd19e5f04697dcfd0084039cd77ef304Stéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber interpret(l_socket, l_linkResults, l_links, ifap);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber interpret(l_socket, l_addrResults, l_links, ifap);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber freeResultList(l_linkResults);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber freeResultList(l_addrResults);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber close(l_socket);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber return 0;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Grabervoid freeifaddrs(struct ifaddrs *ifa)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber{
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber struct ifaddrs *l_cur;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber while(ifa)
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber {
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber l_cur = ifa;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber ifa = ifa->ifa_next;
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber free(l_cur);
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber }
4ba0d9af63fbf7e9acfa068a1fe36b3d287b9c6bStéphane Graber}