1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* $USAGI: ni_ifaddrs.c,v 1.8 2007-10-11 06:25:21 yoshfuji Exp $ */ 2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Copyright (C) 2002 USAGI/WIDE Project. 4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * All rights reserved. 5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Redistribution and use in source and binary forms, with or without 7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * modification, are permitted provided that the following conditions 8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * are met: 9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 1. Redistributions of source code must retain the above copyright 10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * notice, this list of conditions and the following disclaimer. 11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 2. Redistributions in binary form must reproduce the above copyright 12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * notice, this list of conditions and the following disclaimer in the 13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * documentation and/or other materials provided with the distribution. 14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 3. Neither the name of the project nor the names of its contributors 15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * may be used to endorse or promote products derived from this software 16313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * without specific prior written permission. 17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * SUCH DAMAGE. 29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* reformatted by indent -kr -i8 -l 1000 */ 32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* USAGI: ifaddrs.c,v 1.18 2002/03/06 01:50:46 yoshfuji Exp */ 33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/************************************************************************** 35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ifaddrs.c 36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Copyright (C)2000 Hideaki YOSHIFUJI, All Rights Reserved. 37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Redistribution and use in source and binary forms, with or without 39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * modification, are permitted provided that the following conditions 40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * are met: 41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 1. Redistributions of source code must retain the above copyright 42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * notice, this list of conditions and the following disclaimer. 43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 2. Redistributions in binary form must reproduce the above copyright 44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * notice, this list of conditions and the following disclaimer in the 45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * documentation and/or other materials provided with the distribution. 46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 3. Neither the name of the author nor the names of its contributors 47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * may be used to endorse or promote products derived from this software 48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * without specific prior written permission. 49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * SUCH DAMAGE. 61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "config.h" 64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <string.h> 66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <time.h> 67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <malloc.h> 68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <errno.h> 69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <unistd.h> 70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/socket.h> 72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <asm/types.h> 73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/netlink.h> 74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/rtnetlink.h> 75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/types.h> 76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/socket.h> 77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netpacket/packet.h> 78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <net/ethernet.h> /* the L2 protocols */ 79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/uio.h> 80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <net/if.h> 81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <net/if_arp.h> 82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "ni_ifaddrs.h" 83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netinet/in.h> 84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef _USAGI_LIBINET6 86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "libc-compat.h" 87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti//#define IFA_LOCAL IFA_LOCAL 90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic const char *RCSID __attribute__ ((unused)) = "$USAGI: ni_ifaddrs.c,v 1.8 2007-10-11 06:25:21 yoshfuji Exp $ based on USAGI: ifaddrs.c,v 1.18 2002/03/06 01:50:46 yoshfuji Exp"; 92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ====================================================================== */ 94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct nlmsg_list { 95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsg_list *nlm_next; 96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsghdr *nlh; 97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int size; 98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti time_t seq; 99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef IFA_LOCAL 102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct rtmaddr_ifamap { 103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *address; 104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *local; 105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *broadcast; 106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int address_len; 107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int local_len; 108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int broadcast_len; 109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ====================================================================== */ 113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int nl_sendreq(int sd, int request, int flags, int *seq) 114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char reqbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))]; 116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_nl nladdr; 117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsghdr *req_hdr; 118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct rtgenmsg *req_msg; 119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti time_t t = time(NULL); 120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (seq) 122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *seq = t; 123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&reqbuf, 0, sizeof(reqbuf)); 124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_hdr = (struct nlmsghdr *) reqbuf; 125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_msg = (struct rtgenmsg *) NLMSG_DATA(req_hdr); 126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*req_msg)); 127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_hdr->nlmsg_type = request; 128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_hdr->nlmsg_flags = flags | NLM_F_REQUEST; 129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_hdr->nlmsg_pid = 0; 130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_hdr->nlmsg_seq = t; 131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_msg->rtgen_family = AF_UNSPEC; 132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&nladdr, 0, sizeof(nladdr)); 133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nladdr.nl_family = AF_NETLINK; 134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (sendto(sd, (void *) req_hdr, req_hdr->nlmsg_len, 0, (struct sockaddr *) &nladdr, sizeof(nladdr))); 135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int nl_recvmsg(int sd, int request, int seq, void *buf, size_t buflen, int *flags) 138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct msghdr msg; 140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct iovec iov = { buf, buflen }; 141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_nl nladdr; 142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int read_len; 143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (;;) { 145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_name = (void *) &nladdr; 146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_namelen = sizeof(nladdr); 147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_iov = &iov; 148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_iovlen = 1; 149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_control = NULL; 150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_controllen = 0; 151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_flags = 0; 152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti read_len = recvmsg(sd, &msg, 0); 153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((read_len < 0 && errno == EINTR) 154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti || (msg.msg_flags & MSG_TRUNC)) 155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (flags) 157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *flags = msg.msg_flags; 158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return read_len; 161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int nl_getmsg(int sd, int request, int seq, struct nlmsghdr **nlhp, int *done) 164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsghdr *nh; 166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti size_t bufsize = 65536, lastbufsize = 0; 167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *buff = NULL; 168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int result = 0, read_size; 169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int msg_flags; 170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pid_t pid = getpid(); 171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (;;) { 172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *newbuff = realloc(buff, bufsize); 173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (newbuff == NULL || bufsize < lastbufsize) { 174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(newbuff); 175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti result = -1; 176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti buff = newbuff; 179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti result = read_size = nl_recvmsg(sd, request, seq, buff, bufsize, &msg_flags); 180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (read_size < 0 || (msg_flags & MSG_TRUNC)) { 181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti lastbufsize = bufsize; 182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti bufsize *= 2; 183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (read_size == 0) 186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nh = (struct nlmsghdr *) buff; 188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (nh = (struct nlmsghdr *) buff; NLMSG_OK(nh, read_size); nh = (struct nlmsghdr *) NLMSG_NEXT(nh, read_size)) { 189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nh->nlmsg_pid != pid || nh->nlmsg_seq != seq) 190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nh->nlmsg_type == NLMSG_DONE) { 192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (*done)++; 193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; /* ok */ 194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nh->nlmsg_type == NLMSG_ERROR) { 196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA(nh); 197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti result = -1; 198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) 199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = EIO; 200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = -nlerr->error; 202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (result < 0) 208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (buff) { 209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int saved_errno = errno; 210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(buff); 211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti buff = NULL; 212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = saved_errno; 213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *nlhp = (struct nlmsghdr *) buff; 215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return result; 216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int nl_getlist(int sd, int seq, int request, struct nlmsg_list **nlm_list, struct nlmsg_list **nlm_end) 219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsghdr *nlh = NULL; 221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int status; 222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int done = 0; 223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti status = nl_sendreq(sd, request, NLM_F_ROOT | NLM_F_MATCH, &seq); 225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (status < 0) 226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return status; 227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (seq == 0) 228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti seq = (int) time(NULL); 229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (!done) { 230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti status = nl_getmsg(sd, request, seq, &nlh, &done); 231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (status < 0) 232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return status; 233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nlh) { 234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsg_list *nlm_next = (struct nlmsg_list *) malloc(sizeof(struct nlmsg_list)); 235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nlm_next == NULL) { 236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int saved_errno = errno; 237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(nlh); 238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = saved_errno; 239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti status = -1; 240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_next->nlm_next = NULL; 242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_next->nlh = (struct nlmsghdr *) nlh; 243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_next->size = status; 244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_next->seq = seq; 245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (*nlm_list == NULL) { 246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *nlm_list = nlm_next; 247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *nlm_end = nlm_next; 248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (*nlm_end)->nlm_next = nlm_next; 250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *nlm_end = nlm_next; 251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return status >= 0 ? seq : status; 256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------------------------------------------- */ 259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void free_nlmsglist(struct nlmsg_list *nlm0) 260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsg_list *nlm, *nlm_next; 262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int saved_errno; 263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!nlm0) 264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti saved_errno = errno; 266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm = nlm0; 267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while(nlm) { 268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if(nlm->nlh) 269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(nlm->nlh); 270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_next = nlm->nlm_next; 271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(nlm); 272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm = nlm_next; 273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = saved_errno; 275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void free_data(void *data) 278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int saved_errno = errno; 280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (data != NULL) 281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(data); 282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = saved_errno; 283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------------------------------------------- */ 286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void nl_close(int sd) 287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int saved_errno = errno; 289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sd >= 0) 290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti close(sd); 291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = saved_errno; 292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------------------------------------------- */ 295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int nl_open(void) 296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_nl nladdr; 298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int sd; 299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sd < 0) 302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&nladdr, 0, sizeof(nladdr)); 304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nladdr.nl_family = AF_NETLINK; 305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (bind(sd, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { 306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nl_close(sd); 307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return sd; 310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ====================================================================== */ 313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint ni_ifaddrs(struct ni_ifaddrs **ifap, sa_family_t family) 314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int sd; 316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm; 317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* - - - - - - - - - - - - - - - */ 318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int icnt; 319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti size_t dlen, xlen; 320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti uint32_t max_ifindex = 0; 321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pid_t pid = getpid(); 323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int seq = 0; 324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int result; 325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int build; /* 0 or 1 */ 326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------- */ 328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* initialize */ 329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icnt = dlen = xlen = 0; 330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlmsg_list = nlmsg_end = NULL; 331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifap) 333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *ifap = NULL; 334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------- */ 336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* open socket and bind */ 337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sd = nl_open(); 338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sd < 0) 339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------- */ 342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* gather info */ 343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((seq = nl_getlist(sd, seq + 1, RTM_GETADDR, &nlmsg_list, &nlmsg_end)) < 0) { 344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free_nlmsglist(nlmsg_list); 345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nl_close(sd); 346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------- */ 350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Estimate size of result buffer and fill it */ 351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (build = 0; build <= 1; build++) { 352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ni_ifaddrs *ifl = NULL, *ifa = NULL; 353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct nlmsghdr *nlh, *nlh0; 354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *data = NULL, *xdata = NULL; 355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti uint16_t *ifflist = NULL; 356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef IFA_LOCAL 357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct rtmaddr_ifamap ifamap; 358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (build) { 361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifa = data = calloc(1, NLMSG_ALIGN(sizeof(struct ni_ifaddrs[icnt])) 362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti + dlen + xlen); 363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifap != NULL) 364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *ifap = ifa; 365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else { 366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free_data(data); 367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti result = 0; 368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (data == NULL) { 371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free_data(data); 372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti result = -1; 373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifl = NULL; 376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti data += NLMSG_ALIGN(sizeof(struct ni_ifaddrs)) * icnt; 377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti xdata = data + dlen; 378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifflist = xdata + xlen; 379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (nlm = nlmsg_list; nlm; nlm = nlm->nlm_next) { 382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int nlmlen = nlm->size; 383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(nlh0 = nlm->nlh)) 384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (nlh = nlh0; NLMSG_OK(nlh, nlmlen); nlh = NLMSG_NEXT(nlh, nlmlen)) { 386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifaddrmsg *ifam = NULL; 387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct rtattr *rta; 388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti size_t nlm_struct_size = 0; 390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sa_family_t nlm_family = 0; 391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti uint32_t nlm_scope = 0, nlm_index = 0; 392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned int nlm_flags; 393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti size_t rtasize; 394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef IFA_LOCAL 396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&ifamap, 0, sizeof(ifamap)); 397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* check if the message is what we want */ 400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nlh->nlmsg_pid != pid || nlh->nlmsg_seq != nlm->seq) 401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nlh->nlmsg_type == NLMSG_DONE) { 403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; /* ok */ 404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti switch (nlh->nlmsg_type) { 406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case RTM_NEWADDR: 407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifam = (struct ifaddrmsg *) NLMSG_DATA(nlh); 408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_struct_size = sizeof(*ifam); 409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_family = ifam->ifa_family; 410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_scope = ifam->ifa_scope; 411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_index = ifam->ifa_index; 412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nlm_flags = ifam->ifa_flags; 413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (family && nlm_family != family) 414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (build) { 416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifa->ifa_ifindex = nlm_index; 417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifa->ifa_flags = nlm_flags; 418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti default: 421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!build) { 425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (max_ifindex < nlm_index) 426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti max_ifindex = nlm_index; 427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifl != NULL) 429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifl->ifa_next = ifa; 430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rtasize = NLMSG_PAYLOAD(nlh, nlmlen) - NLMSG_ALIGN(nlm_struct_size); 433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (rta = (struct rtattr *) (((char *) NLMSG_DATA(nlh)) + 434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti NLMSG_ALIGN(nlm_struct_size)); 435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti RTA_OK(rta, rtasize); 436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rta = RTA_NEXT(rta, rtasize)) { 437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *rtadata = RTA_DATA(rta); 438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti size_t rtapayload = RTA_PAYLOAD(rta); 439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti switch (nlh->nlmsg_type) { 441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case RTM_NEWADDR: 442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nlm_family == AF_PACKET) 443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti switch (rta->rta_type) { 445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef IFA_LOCAL 446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case IFA_ADDRESS: 447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.address = rtadata; 448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.address_len = rtapayload; 449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case IFA_LOCAL: 451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.local = rtadata; 452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.local_len = rtapayload; 453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case IFA_BROADCAST: 455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.broadcast = rtadata; 456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.broadcast_len = rtapayload; 457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case IFA_LABEL: 459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case IFA_UNSPEC: 461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case IFA_LOCAL: 464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!build) 465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dlen += NLMSG_ALIGN(rtapayload); 466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else { 467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(data, rtadata, rtapayload); 468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifa->ifa_addr = data; 469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti data += NLMSG_ALIGN(rtapayload); 470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case IFA_CACHEINFO: 474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!build) 475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti xlen += NLMSG_ALIGN(rtapayload); 476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else { 477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(xdata, rtadata, rtapayload); 478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifa->ifa_cacheinfo = xdata; 479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti xdata += NLMSG_ALIGN(rtapayload); 480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef IFA_LOCAL 486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nlh->nlmsg_type == RTM_NEWADDR && nlm_family != AF_PACKET) { 487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ifamap.local) { 488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.local = ifamap.address; 489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.local_len = ifamap.address_len; 490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ifamap.address) { 492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.address = ifamap.local; 493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.address_len = ifamap.local_len; 494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifamap.address_len != ifamap.local_len || 496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (ifamap.address != NULL && 497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcmp(ifamap.address, ifamap.local, ifamap.address_len))) { 498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* p2p; address is peer and local is ours */ 499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.broadcast = ifamap.address; 500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.broadcast_len = ifamap.address_len; 501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.address = ifamap.local; 502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifamap.address_len = ifamap.local_len; 503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifamap.address) { 505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!build) 506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dlen += NLMSG_ALIGN(ifamap.address_len); 507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else { 508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifa->ifa_addr = (struct sockaddr *) data; 509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(ifa->ifa_addr, ifamap.address, ifamap.address_len); 510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti data += NLMSG_ALIGN(ifamap.address_len); 511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!build) { 516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icnt++; 517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifl = ifa++; 519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!build) { 523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (icnt == 0 && (dlen + xlen == 0)) { 524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifap != NULL) 525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *ifap = NULL; 526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; /* cannot found any addresses */ 527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------- */ 532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Finalize */ 533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free_nlmsglist(nlmsg_list); 534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nl_close(sd); 535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------------------------------------------------------------------- */ 539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid ni_freeifaddrs(struct ni_ifaddrs *ifa) 540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(ifa); 542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 544