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