xref: /aosp_15_r20/external/iputils/ninfod/ni_ifaddrs.c (revision bd1f8aeb6080fa6544ec30aeca3eb4da100f359f)
1*bd1f8aebSAndroid Build Coastguard Worker /* $USAGI: ni_ifaddrs.c,v 1.8 2007-10-11 06:25:21 yoshfuji Exp $ */
2*bd1f8aebSAndroid Build Coastguard Worker /*
3*bd1f8aebSAndroid Build Coastguard Worker  * Copyright (C) 2002 USAGI/WIDE Project.
4*bd1f8aebSAndroid Build Coastguard Worker  * All rights reserved.
5*bd1f8aebSAndroid Build Coastguard Worker  *
6*bd1f8aebSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
7*bd1f8aebSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
8*bd1f8aebSAndroid Build Coastguard Worker  * are met:
9*bd1f8aebSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
10*bd1f8aebSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
11*bd1f8aebSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
12*bd1f8aebSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
13*bd1f8aebSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
14*bd1f8aebSAndroid Build Coastguard Worker  * 3. Neither the name of the project nor the names of its contributors
15*bd1f8aebSAndroid Build Coastguard Worker  *    may be used to endorse or promote products derived from this software
16*bd1f8aebSAndroid Build Coastguard Worker  *    without specific prior written permission.
17*bd1f8aebSAndroid Build Coastguard Worker  *
18*bd1f8aebSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19*bd1f8aebSAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*bd1f8aebSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*bd1f8aebSAndroid Build Coastguard Worker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22*bd1f8aebSAndroid Build Coastguard Worker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*bd1f8aebSAndroid Build Coastguard Worker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*bd1f8aebSAndroid Build Coastguard Worker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*bd1f8aebSAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*bd1f8aebSAndroid Build Coastguard Worker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*bd1f8aebSAndroid Build Coastguard Worker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*bd1f8aebSAndroid Build Coastguard Worker  * SUCH DAMAGE.
29*bd1f8aebSAndroid Build Coastguard Worker  */
30*bd1f8aebSAndroid Build Coastguard Worker 
31*bd1f8aebSAndroid Build Coastguard Worker /* reformatted by indent -kr -i8 -l 1000 */
32*bd1f8aebSAndroid Build Coastguard Worker /* USAGI: ifaddrs.c,v 1.18 2002/03/06 01:50:46 yoshfuji Exp */
33*bd1f8aebSAndroid Build Coastguard Worker 
34*bd1f8aebSAndroid Build Coastguard Worker /**************************************************************************
35*bd1f8aebSAndroid Build Coastguard Worker  * ifaddrs.c
36*bd1f8aebSAndroid Build Coastguard Worker  * Copyright (C)2000 Hideaki YOSHIFUJI, All Rights Reserved.
37*bd1f8aebSAndroid Build Coastguard Worker  *
38*bd1f8aebSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
39*bd1f8aebSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
40*bd1f8aebSAndroid Build Coastguard Worker  * are met:
41*bd1f8aebSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
42*bd1f8aebSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
43*bd1f8aebSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
44*bd1f8aebSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
45*bd1f8aebSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
46*bd1f8aebSAndroid Build Coastguard Worker  * 3. Neither the name of the author nor the names of its contributors
47*bd1f8aebSAndroid Build Coastguard Worker  *    may be used to endorse or promote products derived from this software
48*bd1f8aebSAndroid Build Coastguard Worker  *    without specific prior written permission.
49*bd1f8aebSAndroid Build Coastguard Worker  *
50*bd1f8aebSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
51*bd1f8aebSAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52*bd1f8aebSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53*bd1f8aebSAndroid Build Coastguard Worker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
54*bd1f8aebSAndroid Build Coastguard Worker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55*bd1f8aebSAndroid Build Coastguard Worker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56*bd1f8aebSAndroid Build Coastguard Worker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57*bd1f8aebSAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58*bd1f8aebSAndroid Build Coastguard Worker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59*bd1f8aebSAndroid Build Coastguard Worker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60*bd1f8aebSAndroid Build Coastguard Worker  * SUCH DAMAGE.
61*bd1f8aebSAndroid Build Coastguard Worker  */
62*bd1f8aebSAndroid Build Coastguard Worker 
63*bd1f8aebSAndroid Build Coastguard Worker #include "config.h"
64*bd1f8aebSAndroid Build Coastguard Worker 
65*bd1f8aebSAndroid Build Coastguard Worker #include <string.h>
66*bd1f8aebSAndroid Build Coastguard Worker #include <time.h>
67*bd1f8aebSAndroid Build Coastguard Worker #include <malloc.h>
68*bd1f8aebSAndroid Build Coastguard Worker #include <errno.h>
69*bd1f8aebSAndroid Build Coastguard Worker #include <unistd.h>
70*bd1f8aebSAndroid Build Coastguard Worker 
71*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
72*bd1f8aebSAndroid Build Coastguard Worker #include <asm/types.h>
73*bd1f8aebSAndroid Build Coastguard Worker #include <linux/netlink.h>
74*bd1f8aebSAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
75*bd1f8aebSAndroid Build Coastguard Worker #include <sys/types.h>
76*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
77*bd1f8aebSAndroid Build Coastguard Worker #include <netpacket/packet.h>
78*bd1f8aebSAndroid Build Coastguard Worker #include <net/ethernet.h>	/* the L2 protocols */
79*bd1f8aebSAndroid Build Coastguard Worker #include <sys/uio.h>
80*bd1f8aebSAndroid Build Coastguard Worker #include <net/if.h>
81*bd1f8aebSAndroid Build Coastguard Worker #include <net/if_arp.h>
82*bd1f8aebSAndroid Build Coastguard Worker #include "ni_ifaddrs.h"
83*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/in.h>
84*bd1f8aebSAndroid Build Coastguard Worker 
85*bd1f8aebSAndroid Build Coastguard Worker #ifdef _USAGI_LIBINET6
86*bd1f8aebSAndroid Build Coastguard Worker #include "libc-compat.h"
87*bd1f8aebSAndroid Build Coastguard Worker #endif
88*bd1f8aebSAndroid Build Coastguard Worker 
89*bd1f8aebSAndroid Build Coastguard Worker //#define IFA_LOCAL	IFA_LOCAL
90*bd1f8aebSAndroid Build Coastguard Worker 
91*bd1f8aebSAndroid Build Coastguard Worker static 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";
92*bd1f8aebSAndroid Build Coastguard Worker 
93*bd1f8aebSAndroid Build Coastguard Worker /* ====================================================================== */
94*bd1f8aebSAndroid Build Coastguard Worker struct nlmsg_list {
95*bd1f8aebSAndroid Build Coastguard Worker 	struct nlmsg_list *nlm_next;
96*bd1f8aebSAndroid Build Coastguard Worker 	struct nlmsghdr *nlh;
97*bd1f8aebSAndroid Build Coastguard Worker 	int size;
98*bd1f8aebSAndroid Build Coastguard Worker 	time_t seq;
99*bd1f8aebSAndroid Build Coastguard Worker };
100*bd1f8aebSAndroid Build Coastguard Worker 
101*bd1f8aebSAndroid Build Coastguard Worker #ifndef IFA_LOCAL
102*bd1f8aebSAndroid Build Coastguard Worker struct rtmaddr_ifamap {
103*bd1f8aebSAndroid Build Coastguard Worker 	void *address;
104*bd1f8aebSAndroid Build Coastguard Worker 	void *local;
105*bd1f8aebSAndroid Build Coastguard Worker 	void *broadcast;
106*bd1f8aebSAndroid Build Coastguard Worker 	int address_len;
107*bd1f8aebSAndroid Build Coastguard Worker 	int local_len;
108*bd1f8aebSAndroid Build Coastguard Worker 	int broadcast_len;
109*bd1f8aebSAndroid Build Coastguard Worker };
110*bd1f8aebSAndroid Build Coastguard Worker #endif
111*bd1f8aebSAndroid Build Coastguard Worker 
112*bd1f8aebSAndroid Build Coastguard Worker /* ====================================================================== */
nl_sendreq(int sd,int request,int flags,int * seq)113*bd1f8aebSAndroid Build Coastguard Worker static int nl_sendreq(int sd, int request, int flags, int *seq)
114*bd1f8aebSAndroid Build Coastguard Worker {
115*bd1f8aebSAndroid Build Coastguard Worker 	char reqbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
116*bd1f8aebSAndroid Build Coastguard Worker 	struct sockaddr_nl nladdr;
117*bd1f8aebSAndroid Build Coastguard Worker 	struct nlmsghdr *req_hdr;
118*bd1f8aebSAndroid Build Coastguard Worker 	struct rtgenmsg *req_msg;
119*bd1f8aebSAndroid Build Coastguard Worker 	time_t t = time(NULL);
120*bd1f8aebSAndroid Build Coastguard Worker 
121*bd1f8aebSAndroid Build Coastguard Worker 	if (seq)
122*bd1f8aebSAndroid Build Coastguard Worker 		*seq = t;
123*bd1f8aebSAndroid Build Coastguard Worker 	memset(&reqbuf, 0, sizeof(reqbuf));
124*bd1f8aebSAndroid Build Coastguard Worker 	req_hdr = (struct nlmsghdr *) reqbuf;
125*bd1f8aebSAndroid Build Coastguard Worker 	req_msg = (struct rtgenmsg *) NLMSG_DATA(req_hdr);
126*bd1f8aebSAndroid Build Coastguard Worker 	req_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*req_msg));
127*bd1f8aebSAndroid Build Coastguard Worker 	req_hdr->nlmsg_type = request;
128*bd1f8aebSAndroid Build Coastguard Worker 	req_hdr->nlmsg_flags = flags | NLM_F_REQUEST;
129*bd1f8aebSAndroid Build Coastguard Worker 	req_hdr->nlmsg_pid = 0;
130*bd1f8aebSAndroid Build Coastguard Worker 	req_hdr->nlmsg_seq = t;
131*bd1f8aebSAndroid Build Coastguard Worker 	req_msg->rtgen_family = AF_UNSPEC;
132*bd1f8aebSAndroid Build Coastguard Worker 	memset(&nladdr, 0, sizeof(nladdr));
133*bd1f8aebSAndroid Build Coastguard Worker 	nladdr.nl_family = AF_NETLINK;
134*bd1f8aebSAndroid Build Coastguard Worker 	return (sendto(sd, (void *) req_hdr, req_hdr->nlmsg_len, 0, (struct sockaddr *) &nladdr, sizeof(nladdr)));
135*bd1f8aebSAndroid Build Coastguard Worker }
136*bd1f8aebSAndroid Build Coastguard Worker 
nl_recvmsg(int sd,int request,int seq,void * buf,size_t buflen,int * flags)137*bd1f8aebSAndroid Build Coastguard Worker static int nl_recvmsg(int sd, int request, int seq, void *buf, size_t buflen, int *flags)
138*bd1f8aebSAndroid Build Coastguard Worker {
139*bd1f8aebSAndroid Build Coastguard Worker 	struct msghdr msg;
140*bd1f8aebSAndroid Build Coastguard Worker 	struct iovec iov = { buf, buflen };
141*bd1f8aebSAndroid Build Coastguard Worker 	struct sockaddr_nl nladdr;
142*bd1f8aebSAndroid Build Coastguard Worker 	int read_len;
143*bd1f8aebSAndroid Build Coastguard Worker 
144*bd1f8aebSAndroid Build Coastguard Worker 	for (;;) {
145*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_name = (void *) &nladdr;
146*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_namelen = sizeof(nladdr);
147*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_iov = &iov;
148*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_iovlen = 1;
149*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_control = NULL;
150*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_controllen = 0;
151*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_flags = 0;
152*bd1f8aebSAndroid Build Coastguard Worker 		read_len = recvmsg(sd, &msg, 0);
153*bd1f8aebSAndroid Build Coastguard Worker 		if ((read_len < 0 && errno == EINTR)
154*bd1f8aebSAndroid Build Coastguard Worker 		    || (msg.msg_flags & MSG_TRUNC))
155*bd1f8aebSAndroid Build Coastguard Worker 			continue;
156*bd1f8aebSAndroid Build Coastguard Worker 		if (flags)
157*bd1f8aebSAndroid Build Coastguard Worker 			*flags = msg.msg_flags;
158*bd1f8aebSAndroid Build Coastguard Worker 		break;
159*bd1f8aebSAndroid Build Coastguard Worker 	}
160*bd1f8aebSAndroid Build Coastguard Worker 	return read_len;
161*bd1f8aebSAndroid Build Coastguard Worker }
162*bd1f8aebSAndroid Build Coastguard Worker 
nl_getmsg(int sd,int request,int seq,struct nlmsghdr ** nlhp,int * done)163*bd1f8aebSAndroid Build Coastguard Worker static int nl_getmsg(int sd, int request, int seq, struct nlmsghdr **nlhp, int *done)
164*bd1f8aebSAndroid Build Coastguard Worker {
165*bd1f8aebSAndroid Build Coastguard Worker 	struct nlmsghdr *nh;
166*bd1f8aebSAndroid Build Coastguard Worker 	size_t bufsize = 65536, lastbufsize = 0;
167*bd1f8aebSAndroid Build Coastguard Worker 	void *buff = NULL;
168*bd1f8aebSAndroid Build Coastguard Worker 	int result = 0, read_size;
169*bd1f8aebSAndroid Build Coastguard Worker 	int msg_flags;
170*bd1f8aebSAndroid Build Coastguard Worker 	pid_t pid = getpid();
171*bd1f8aebSAndroid Build Coastguard Worker 	for (;;) {
172*bd1f8aebSAndroid Build Coastguard Worker 		void *newbuff = realloc(buff, bufsize);
173*bd1f8aebSAndroid Build Coastguard Worker 		if (newbuff == NULL || bufsize < lastbufsize) {
174*bd1f8aebSAndroid Build Coastguard Worker 			free(newbuff);
175*bd1f8aebSAndroid Build Coastguard Worker 			result = -1;
176*bd1f8aebSAndroid Build Coastguard Worker 			break;
177*bd1f8aebSAndroid Build Coastguard Worker 		}
178*bd1f8aebSAndroid Build Coastguard Worker 		buff = newbuff;
179*bd1f8aebSAndroid Build Coastguard Worker 		result = read_size = nl_recvmsg(sd, request, seq, buff, bufsize, &msg_flags);
180*bd1f8aebSAndroid Build Coastguard Worker 		if (read_size < 0 || (msg_flags & MSG_TRUNC)) {
181*bd1f8aebSAndroid Build Coastguard Worker 			lastbufsize = bufsize;
182*bd1f8aebSAndroid Build Coastguard Worker 			bufsize *= 2;
183*bd1f8aebSAndroid Build Coastguard Worker 			continue;
184*bd1f8aebSAndroid Build Coastguard Worker 		}
185*bd1f8aebSAndroid Build Coastguard Worker 		if (read_size == 0)
186*bd1f8aebSAndroid Build Coastguard Worker 			break;
187*bd1f8aebSAndroid Build Coastguard Worker 		nh = (struct nlmsghdr *) buff;
188*bd1f8aebSAndroid Build Coastguard Worker 		for (nh = (struct nlmsghdr *) buff; NLMSG_OK(nh, read_size); nh = (struct nlmsghdr *) NLMSG_NEXT(nh, read_size)) {
189*bd1f8aebSAndroid Build Coastguard Worker 			if (nh->nlmsg_pid != pid || nh->nlmsg_seq != seq)
190*bd1f8aebSAndroid Build Coastguard Worker 				continue;
191*bd1f8aebSAndroid Build Coastguard Worker 			if (nh->nlmsg_type == NLMSG_DONE) {
192*bd1f8aebSAndroid Build Coastguard Worker 				(*done)++;
193*bd1f8aebSAndroid Build Coastguard Worker 				break;	/* ok */
194*bd1f8aebSAndroid Build Coastguard Worker 			}
195*bd1f8aebSAndroid Build Coastguard Worker 			if (nh->nlmsg_type == NLMSG_ERROR) {
196*bd1f8aebSAndroid Build Coastguard Worker 				struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA(nh);
197*bd1f8aebSAndroid Build Coastguard Worker 				result = -1;
198*bd1f8aebSAndroid Build Coastguard Worker 				if (nh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
199*bd1f8aebSAndroid Build Coastguard Worker 					errno = EIO;
200*bd1f8aebSAndroid Build Coastguard Worker 				else
201*bd1f8aebSAndroid Build Coastguard Worker 					errno = -nlerr->error;
202*bd1f8aebSAndroid Build Coastguard Worker 				break;
203*bd1f8aebSAndroid Build Coastguard Worker 			}
204*bd1f8aebSAndroid Build Coastguard Worker 		}
205*bd1f8aebSAndroid Build Coastguard Worker 		break;
206*bd1f8aebSAndroid Build Coastguard Worker 	}
207*bd1f8aebSAndroid Build Coastguard Worker 	if (result < 0)
208*bd1f8aebSAndroid Build Coastguard Worker 		if (buff) {
209*bd1f8aebSAndroid Build Coastguard Worker 			int saved_errno = errno;
210*bd1f8aebSAndroid Build Coastguard Worker 			free(buff);
211*bd1f8aebSAndroid Build Coastguard Worker 			buff = NULL;
212*bd1f8aebSAndroid Build Coastguard Worker 			errno = saved_errno;
213*bd1f8aebSAndroid Build Coastguard Worker 		}
214*bd1f8aebSAndroid Build Coastguard Worker 	*nlhp = (struct nlmsghdr *) buff;
215*bd1f8aebSAndroid Build Coastguard Worker 	return result;
216*bd1f8aebSAndroid Build Coastguard Worker }
217*bd1f8aebSAndroid Build Coastguard Worker 
nl_getlist(int sd,int seq,int request,struct nlmsg_list ** nlm_list,struct nlmsg_list ** nlm_end)218*bd1f8aebSAndroid Build Coastguard Worker static int nl_getlist(int sd, int seq, int request, struct nlmsg_list **nlm_list, struct nlmsg_list **nlm_end)
219*bd1f8aebSAndroid Build Coastguard Worker {
220*bd1f8aebSAndroid Build Coastguard Worker 	struct nlmsghdr *nlh = NULL;
221*bd1f8aebSAndroid Build Coastguard Worker 	int status;
222*bd1f8aebSAndroid Build Coastguard Worker 	int done = 0;
223*bd1f8aebSAndroid Build Coastguard Worker 
224*bd1f8aebSAndroid Build Coastguard Worker 	status = nl_sendreq(sd, request, NLM_F_ROOT | NLM_F_MATCH, &seq);
225*bd1f8aebSAndroid Build Coastguard Worker 	if (status < 0)
226*bd1f8aebSAndroid Build Coastguard Worker 		return status;
227*bd1f8aebSAndroid Build Coastguard Worker 	if (seq == 0)
228*bd1f8aebSAndroid Build Coastguard Worker 		seq = (int) time(NULL);
229*bd1f8aebSAndroid Build Coastguard Worker 	while (!done) {
230*bd1f8aebSAndroid Build Coastguard Worker 		status = nl_getmsg(sd, request, seq, &nlh, &done);
231*bd1f8aebSAndroid Build Coastguard Worker 		if (status < 0)
232*bd1f8aebSAndroid Build Coastguard Worker 			return status;
233*bd1f8aebSAndroid Build Coastguard Worker 		if (nlh) {
234*bd1f8aebSAndroid Build Coastguard Worker 			struct nlmsg_list *nlm_next = (struct nlmsg_list *) malloc(sizeof(struct nlmsg_list));
235*bd1f8aebSAndroid Build Coastguard Worker 			if (nlm_next == NULL) {
236*bd1f8aebSAndroid Build Coastguard Worker 				int saved_errno = errno;
237*bd1f8aebSAndroid Build Coastguard Worker 				free(nlh);
238*bd1f8aebSAndroid Build Coastguard Worker 				errno = saved_errno;
239*bd1f8aebSAndroid Build Coastguard Worker 				status = -1;
240*bd1f8aebSAndroid Build Coastguard Worker 			} else {
241*bd1f8aebSAndroid Build Coastguard Worker 				nlm_next->nlm_next = NULL;
242*bd1f8aebSAndroid Build Coastguard Worker 				nlm_next->nlh = (struct nlmsghdr *) nlh;
243*bd1f8aebSAndroid Build Coastguard Worker 				nlm_next->size = status;
244*bd1f8aebSAndroid Build Coastguard Worker 				nlm_next->seq = seq;
245*bd1f8aebSAndroid Build Coastguard Worker 				if (*nlm_list == NULL) {
246*bd1f8aebSAndroid Build Coastguard Worker 					*nlm_list = nlm_next;
247*bd1f8aebSAndroid Build Coastguard Worker 					*nlm_end = nlm_next;
248*bd1f8aebSAndroid Build Coastguard Worker 				} else {
249*bd1f8aebSAndroid Build Coastguard Worker 					(*nlm_end)->nlm_next = nlm_next;
250*bd1f8aebSAndroid Build Coastguard Worker 					*nlm_end = nlm_next;
251*bd1f8aebSAndroid Build Coastguard Worker 				}
252*bd1f8aebSAndroid Build Coastguard Worker 			}
253*bd1f8aebSAndroid Build Coastguard Worker 		}
254*bd1f8aebSAndroid Build Coastguard Worker 	}
255*bd1f8aebSAndroid Build Coastguard Worker 	return status >= 0 ? seq : status;
256*bd1f8aebSAndroid Build Coastguard Worker }
257*bd1f8aebSAndroid Build Coastguard Worker 
258*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------------------------------------------- */
free_nlmsglist(struct nlmsg_list * nlm0)259*bd1f8aebSAndroid Build Coastguard Worker static void free_nlmsglist(struct nlmsg_list *nlm0)
260*bd1f8aebSAndroid Build Coastguard Worker {
261*bd1f8aebSAndroid Build Coastguard Worker 	struct nlmsg_list *nlm, *nlm_next;
262*bd1f8aebSAndroid Build Coastguard Worker 	int saved_errno;
263*bd1f8aebSAndroid Build Coastguard Worker 	if (!nlm0)
264*bd1f8aebSAndroid Build Coastguard Worker 		return;
265*bd1f8aebSAndroid Build Coastguard Worker 	saved_errno = errno;
266*bd1f8aebSAndroid Build Coastguard Worker 	nlm = nlm0;
267*bd1f8aebSAndroid Build Coastguard Worker 	while(nlm) {
268*bd1f8aebSAndroid Build Coastguard Worker 		if(nlm->nlh)
269*bd1f8aebSAndroid Build Coastguard Worker 			free(nlm->nlh);
270*bd1f8aebSAndroid Build Coastguard Worker 		nlm_next = nlm->nlm_next;
271*bd1f8aebSAndroid Build Coastguard Worker 		free(nlm);
272*bd1f8aebSAndroid Build Coastguard Worker 		nlm = nlm_next;
273*bd1f8aebSAndroid Build Coastguard Worker 	}
274*bd1f8aebSAndroid Build Coastguard Worker 	errno = saved_errno;
275*bd1f8aebSAndroid Build Coastguard Worker }
276*bd1f8aebSAndroid Build Coastguard Worker 
free_data(void * data)277*bd1f8aebSAndroid Build Coastguard Worker static void free_data(void *data)
278*bd1f8aebSAndroid Build Coastguard Worker {
279*bd1f8aebSAndroid Build Coastguard Worker 	int saved_errno = errno;
280*bd1f8aebSAndroid Build Coastguard Worker 	if (data != NULL)
281*bd1f8aebSAndroid Build Coastguard Worker 		free(data);
282*bd1f8aebSAndroid Build Coastguard Worker 	errno = saved_errno;
283*bd1f8aebSAndroid Build Coastguard Worker }
284*bd1f8aebSAndroid Build Coastguard Worker 
285*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------------------------------------------- */
nl_close(int sd)286*bd1f8aebSAndroid Build Coastguard Worker static void nl_close(int sd)
287*bd1f8aebSAndroid Build Coastguard Worker {
288*bd1f8aebSAndroid Build Coastguard Worker 	int saved_errno = errno;
289*bd1f8aebSAndroid Build Coastguard Worker 	if (sd >= 0)
290*bd1f8aebSAndroid Build Coastguard Worker 		close(sd);
291*bd1f8aebSAndroid Build Coastguard Worker 	errno = saved_errno;
292*bd1f8aebSAndroid Build Coastguard Worker }
293*bd1f8aebSAndroid Build Coastguard Worker 
294*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------------------------------------------- */
nl_open(void)295*bd1f8aebSAndroid Build Coastguard Worker static int nl_open(void)
296*bd1f8aebSAndroid Build Coastguard Worker {
297*bd1f8aebSAndroid Build Coastguard Worker 	struct sockaddr_nl nladdr;
298*bd1f8aebSAndroid Build Coastguard Worker 	int sd;
299*bd1f8aebSAndroid Build Coastguard Worker 
300*bd1f8aebSAndroid Build Coastguard Worker 	sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
301*bd1f8aebSAndroid Build Coastguard Worker 	if (sd < 0)
302*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
303*bd1f8aebSAndroid Build Coastguard Worker 	memset(&nladdr, 0, sizeof(nladdr));
304*bd1f8aebSAndroid Build Coastguard Worker 	nladdr.nl_family = AF_NETLINK;
305*bd1f8aebSAndroid Build Coastguard Worker 	if (bind(sd, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
306*bd1f8aebSAndroid Build Coastguard Worker 		nl_close(sd);
307*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
308*bd1f8aebSAndroid Build Coastguard Worker 	}
309*bd1f8aebSAndroid Build Coastguard Worker 	return sd;
310*bd1f8aebSAndroid Build Coastguard Worker }
311*bd1f8aebSAndroid Build Coastguard Worker 
312*bd1f8aebSAndroid Build Coastguard Worker /* ====================================================================== */
ni_ifaddrs(struct ni_ifaddrs ** ifap,sa_family_t family)313*bd1f8aebSAndroid Build Coastguard Worker int ni_ifaddrs(struct ni_ifaddrs **ifap, sa_family_t family)
314*bd1f8aebSAndroid Build Coastguard Worker {
315*bd1f8aebSAndroid Build Coastguard Worker 	int sd;
316*bd1f8aebSAndroid Build Coastguard Worker 	struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm;
317*bd1f8aebSAndroid Build Coastguard Worker 	/* - - - - - - - - - - - - - - - */
318*bd1f8aebSAndroid Build Coastguard Worker 	int icnt;
319*bd1f8aebSAndroid Build Coastguard Worker 	size_t dlen, xlen;
320*bd1f8aebSAndroid Build Coastguard Worker 	uint32_t max_ifindex = 0;
321*bd1f8aebSAndroid Build Coastguard Worker 
322*bd1f8aebSAndroid Build Coastguard Worker 	pid_t pid = getpid();
323*bd1f8aebSAndroid Build Coastguard Worker 	int seq = 0;
324*bd1f8aebSAndroid Build Coastguard Worker 	int result;
325*bd1f8aebSAndroid Build Coastguard Worker 	int build;		/* 0 or 1 */
326*bd1f8aebSAndroid Build Coastguard Worker 
327*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------- */
328*bd1f8aebSAndroid Build Coastguard Worker 	/* initialize */
329*bd1f8aebSAndroid Build Coastguard Worker 	icnt = dlen = xlen = 0;
330*bd1f8aebSAndroid Build Coastguard Worker 	nlmsg_list = nlmsg_end = NULL;
331*bd1f8aebSAndroid Build Coastguard Worker 
332*bd1f8aebSAndroid Build Coastguard Worker 	if (ifap)
333*bd1f8aebSAndroid Build Coastguard Worker 		*ifap = NULL;
334*bd1f8aebSAndroid Build Coastguard Worker 
335*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------- */
336*bd1f8aebSAndroid Build Coastguard Worker 	/* open socket and bind */
337*bd1f8aebSAndroid Build Coastguard Worker 	sd = nl_open();
338*bd1f8aebSAndroid Build Coastguard Worker 	if (sd < 0)
339*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
340*bd1f8aebSAndroid Build Coastguard Worker 
341*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------- */
342*bd1f8aebSAndroid Build Coastguard Worker 	/* gather info */
343*bd1f8aebSAndroid Build Coastguard Worker 	if ((seq = nl_getlist(sd, seq + 1, RTM_GETADDR, &nlmsg_list, &nlmsg_end)) < 0) {
344*bd1f8aebSAndroid Build Coastguard Worker 		free_nlmsglist(nlmsg_list);
345*bd1f8aebSAndroid Build Coastguard Worker 		nl_close(sd);
346*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
347*bd1f8aebSAndroid Build Coastguard Worker 	}
348*bd1f8aebSAndroid Build Coastguard Worker 
349*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------- */
350*bd1f8aebSAndroid Build Coastguard Worker 	/* Estimate size of result buffer and fill it */
351*bd1f8aebSAndroid Build Coastguard Worker 	for (build = 0; build <= 1; build++) {
352*bd1f8aebSAndroid Build Coastguard Worker 		struct ni_ifaddrs *ifl = NULL, *ifa = NULL;
353*bd1f8aebSAndroid Build Coastguard Worker 		struct nlmsghdr *nlh, *nlh0;
354*bd1f8aebSAndroid Build Coastguard Worker 		void *data = NULL, *xdata = NULL;
355*bd1f8aebSAndroid Build Coastguard Worker 		uint16_t *ifflist = NULL;
356*bd1f8aebSAndroid Build Coastguard Worker #ifndef IFA_LOCAL
357*bd1f8aebSAndroid Build Coastguard Worker 		struct rtmaddr_ifamap ifamap;
358*bd1f8aebSAndroid Build Coastguard Worker #endif
359*bd1f8aebSAndroid Build Coastguard Worker 
360*bd1f8aebSAndroid Build Coastguard Worker 		if (build) {
361*bd1f8aebSAndroid Build Coastguard Worker 			ifa = data = calloc(1, NLMSG_ALIGN(sizeof(struct ni_ifaddrs[icnt]))
362*bd1f8aebSAndroid Build Coastguard Worker 					    + dlen + xlen);
363*bd1f8aebSAndroid Build Coastguard Worker 			if (ifap != NULL)
364*bd1f8aebSAndroid Build Coastguard Worker 				*ifap = ifa;
365*bd1f8aebSAndroid Build Coastguard Worker 			else {
366*bd1f8aebSAndroid Build Coastguard Worker 				free_data(data);
367*bd1f8aebSAndroid Build Coastguard Worker 				result = 0;
368*bd1f8aebSAndroid Build Coastguard Worker 				break;
369*bd1f8aebSAndroid Build Coastguard Worker 			}
370*bd1f8aebSAndroid Build Coastguard Worker 			if (data == NULL) {
371*bd1f8aebSAndroid Build Coastguard Worker 				free_data(data);
372*bd1f8aebSAndroid Build Coastguard Worker 				result = -1;
373*bd1f8aebSAndroid Build Coastguard Worker 				break;
374*bd1f8aebSAndroid Build Coastguard Worker 			}
375*bd1f8aebSAndroid Build Coastguard Worker 			ifl = NULL;
376*bd1f8aebSAndroid Build Coastguard Worker 			data += NLMSG_ALIGN(sizeof(struct ni_ifaddrs)) * icnt;
377*bd1f8aebSAndroid Build Coastguard Worker 			xdata = data + dlen;
378*bd1f8aebSAndroid Build Coastguard Worker 			ifflist = xdata + xlen;
379*bd1f8aebSAndroid Build Coastguard Worker 		}
380*bd1f8aebSAndroid Build Coastguard Worker 
381*bd1f8aebSAndroid Build Coastguard Worker 		for (nlm = nlmsg_list; nlm; nlm = nlm->nlm_next) {
382*bd1f8aebSAndroid Build Coastguard Worker 			int nlmlen = nlm->size;
383*bd1f8aebSAndroid Build Coastguard Worker 			if (!(nlh0 = nlm->nlh))
384*bd1f8aebSAndroid Build Coastguard Worker 				continue;
385*bd1f8aebSAndroid Build Coastguard Worker 			for (nlh = nlh0; NLMSG_OK(nlh, nlmlen); nlh = NLMSG_NEXT(nlh, nlmlen)) {
386*bd1f8aebSAndroid Build Coastguard Worker 				struct ifaddrmsg *ifam = NULL;
387*bd1f8aebSAndroid Build Coastguard Worker 				struct rtattr *rta;
388*bd1f8aebSAndroid Build Coastguard Worker 
389*bd1f8aebSAndroid Build Coastguard Worker 				size_t nlm_struct_size = 0;
390*bd1f8aebSAndroid Build Coastguard Worker 				sa_family_t nlm_family = 0;
391*bd1f8aebSAndroid Build Coastguard Worker 				uint32_t nlm_scope = 0, nlm_index = 0;
392*bd1f8aebSAndroid Build Coastguard Worker 				unsigned int nlm_flags;
393*bd1f8aebSAndroid Build Coastguard Worker 				size_t rtasize;
394*bd1f8aebSAndroid Build Coastguard Worker 
395*bd1f8aebSAndroid Build Coastguard Worker #ifndef IFA_LOCAL
396*bd1f8aebSAndroid Build Coastguard Worker 				memset(&ifamap, 0, sizeof(ifamap));
397*bd1f8aebSAndroid Build Coastguard Worker #endif
398*bd1f8aebSAndroid Build Coastguard Worker 
399*bd1f8aebSAndroid Build Coastguard Worker 				/* check if the message is what we want */
400*bd1f8aebSAndroid Build Coastguard Worker 				if (nlh->nlmsg_pid != pid || nlh->nlmsg_seq != nlm->seq)
401*bd1f8aebSAndroid Build Coastguard Worker 					continue;
402*bd1f8aebSAndroid Build Coastguard Worker 				if (nlh->nlmsg_type == NLMSG_DONE) {
403*bd1f8aebSAndroid Build Coastguard Worker 					break;	/* ok */
404*bd1f8aebSAndroid Build Coastguard Worker 				}
405*bd1f8aebSAndroid Build Coastguard Worker 				switch (nlh->nlmsg_type) {
406*bd1f8aebSAndroid Build Coastguard Worker 				case RTM_NEWADDR:
407*bd1f8aebSAndroid Build Coastguard Worker 					ifam = (struct ifaddrmsg *) NLMSG_DATA(nlh);
408*bd1f8aebSAndroid Build Coastguard Worker 					nlm_struct_size = sizeof(*ifam);
409*bd1f8aebSAndroid Build Coastguard Worker 					nlm_family = ifam->ifa_family;
410*bd1f8aebSAndroid Build Coastguard Worker 					nlm_scope = ifam->ifa_scope;
411*bd1f8aebSAndroid Build Coastguard Worker 					nlm_index = ifam->ifa_index;
412*bd1f8aebSAndroid Build Coastguard Worker 					nlm_flags = ifam->ifa_flags;
413*bd1f8aebSAndroid Build Coastguard Worker 					if (family && nlm_family != family)
414*bd1f8aebSAndroid Build Coastguard Worker 						continue;
415*bd1f8aebSAndroid Build Coastguard Worker 					if (build) {
416*bd1f8aebSAndroid Build Coastguard Worker 						ifa->ifa_ifindex = nlm_index;
417*bd1f8aebSAndroid Build Coastguard Worker 						ifa->ifa_flags = nlm_flags;
418*bd1f8aebSAndroid Build Coastguard Worker 					}
419*bd1f8aebSAndroid Build Coastguard Worker 					break;
420*bd1f8aebSAndroid Build Coastguard Worker 				default:
421*bd1f8aebSAndroid Build Coastguard Worker 					continue;
422*bd1f8aebSAndroid Build Coastguard Worker 				}
423*bd1f8aebSAndroid Build Coastguard Worker 
424*bd1f8aebSAndroid Build Coastguard Worker 				if (!build) {
425*bd1f8aebSAndroid Build Coastguard Worker 					if (max_ifindex < nlm_index)
426*bd1f8aebSAndroid Build Coastguard Worker 						max_ifindex = nlm_index;
427*bd1f8aebSAndroid Build Coastguard Worker 				} else {
428*bd1f8aebSAndroid Build Coastguard Worker 					if (ifl != NULL)
429*bd1f8aebSAndroid Build Coastguard Worker 						ifl->ifa_next = ifa;
430*bd1f8aebSAndroid Build Coastguard Worker 				}
431*bd1f8aebSAndroid Build Coastguard Worker 
432*bd1f8aebSAndroid Build Coastguard Worker 				rtasize = NLMSG_PAYLOAD(nlh, nlmlen) - NLMSG_ALIGN(nlm_struct_size);
433*bd1f8aebSAndroid Build Coastguard Worker 				for (rta = (struct rtattr *) (((char *) NLMSG_DATA(nlh)) +
434*bd1f8aebSAndroid Build Coastguard Worker 									NLMSG_ALIGN(nlm_struct_size));
435*bd1f8aebSAndroid Build Coastguard Worker 				     RTA_OK(rta, rtasize);
436*bd1f8aebSAndroid Build Coastguard Worker 				     rta = RTA_NEXT(rta, rtasize)) {
437*bd1f8aebSAndroid Build Coastguard Worker 					void *rtadata = RTA_DATA(rta);
438*bd1f8aebSAndroid Build Coastguard Worker 					size_t rtapayload = RTA_PAYLOAD(rta);
439*bd1f8aebSAndroid Build Coastguard Worker 
440*bd1f8aebSAndroid Build Coastguard Worker 					switch (nlh->nlmsg_type) {
441*bd1f8aebSAndroid Build Coastguard Worker 					case RTM_NEWADDR:
442*bd1f8aebSAndroid Build Coastguard Worker 						if (nlm_family == AF_PACKET)
443*bd1f8aebSAndroid Build Coastguard Worker 							break;
444*bd1f8aebSAndroid Build Coastguard Worker 						switch (rta->rta_type) {
445*bd1f8aebSAndroid Build Coastguard Worker #ifndef IFA_LOCAL
446*bd1f8aebSAndroid Build Coastguard Worker 						case IFA_ADDRESS:
447*bd1f8aebSAndroid Build Coastguard Worker 							ifamap.address = rtadata;
448*bd1f8aebSAndroid Build Coastguard Worker 							ifamap.address_len = rtapayload;
449*bd1f8aebSAndroid Build Coastguard Worker 							break;
450*bd1f8aebSAndroid Build Coastguard Worker 						case IFA_LOCAL:
451*bd1f8aebSAndroid Build Coastguard Worker 							ifamap.local = rtadata;
452*bd1f8aebSAndroid Build Coastguard Worker 							ifamap.local_len = rtapayload;
453*bd1f8aebSAndroid Build Coastguard Worker 							break;
454*bd1f8aebSAndroid Build Coastguard Worker 						case IFA_BROADCAST:
455*bd1f8aebSAndroid Build Coastguard Worker 							ifamap.broadcast = rtadata;
456*bd1f8aebSAndroid Build Coastguard Worker 							ifamap.broadcast_len = rtapayload;
457*bd1f8aebSAndroid Build Coastguard Worker 							break;
458*bd1f8aebSAndroid Build Coastguard Worker 						case IFA_LABEL:
459*bd1f8aebSAndroid Build Coastguard Worker 							break;
460*bd1f8aebSAndroid Build Coastguard Worker 						case IFA_UNSPEC:
461*bd1f8aebSAndroid Build Coastguard Worker 							break;
462*bd1f8aebSAndroid Build Coastguard Worker #else
463*bd1f8aebSAndroid Build Coastguard Worker 						case IFA_LOCAL:
464*bd1f8aebSAndroid Build Coastguard Worker 							if (!build)
465*bd1f8aebSAndroid Build Coastguard Worker 								dlen += NLMSG_ALIGN(rtapayload);
466*bd1f8aebSAndroid Build Coastguard Worker 							else {
467*bd1f8aebSAndroid Build Coastguard Worker 								memcpy(data, rtadata, rtapayload);
468*bd1f8aebSAndroid Build Coastguard Worker 								ifa->ifa_addr = data;
469*bd1f8aebSAndroid Build Coastguard Worker 								data += NLMSG_ALIGN(rtapayload);
470*bd1f8aebSAndroid Build Coastguard Worker 							}
471*bd1f8aebSAndroid Build Coastguard Worker 							break;
472*bd1f8aebSAndroid Build Coastguard Worker #endif
473*bd1f8aebSAndroid Build Coastguard Worker 						case IFA_CACHEINFO:
474*bd1f8aebSAndroid Build Coastguard Worker 							if (!build)
475*bd1f8aebSAndroid Build Coastguard Worker 								xlen += NLMSG_ALIGN(rtapayload);
476*bd1f8aebSAndroid Build Coastguard Worker 							else {
477*bd1f8aebSAndroid Build Coastguard Worker 								memcpy(xdata, rtadata, rtapayload);
478*bd1f8aebSAndroid Build Coastguard Worker 								ifa->ifa_cacheinfo = xdata;
479*bd1f8aebSAndroid Build Coastguard Worker 								xdata += NLMSG_ALIGN(rtapayload);
480*bd1f8aebSAndroid Build Coastguard Worker 							}
481*bd1f8aebSAndroid Build Coastguard Worker 							break;
482*bd1f8aebSAndroid Build Coastguard Worker 						}
483*bd1f8aebSAndroid Build Coastguard Worker 					}
484*bd1f8aebSAndroid Build Coastguard Worker 				}
485*bd1f8aebSAndroid Build Coastguard Worker #ifndef IFA_LOCAL
486*bd1f8aebSAndroid Build Coastguard Worker 				if (nlh->nlmsg_type == RTM_NEWADDR && nlm_family != AF_PACKET) {
487*bd1f8aebSAndroid Build Coastguard Worker 					if (!ifamap.local) {
488*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.local = ifamap.address;
489*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.local_len = ifamap.address_len;
490*bd1f8aebSAndroid Build Coastguard Worker 					}
491*bd1f8aebSAndroid Build Coastguard Worker 					if (!ifamap.address) {
492*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.address = ifamap.local;
493*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.address_len = ifamap.local_len;
494*bd1f8aebSAndroid Build Coastguard Worker 					}
495*bd1f8aebSAndroid Build Coastguard Worker 					if (ifamap.address_len != ifamap.local_len ||
496*bd1f8aebSAndroid Build Coastguard Worker 					    (ifamap.address != NULL &&
497*bd1f8aebSAndroid Build Coastguard Worker 					     memcmp(ifamap.address, ifamap.local, ifamap.address_len))) {
498*bd1f8aebSAndroid Build Coastguard Worker 						/* p2p; address is peer and local is ours */
499*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.broadcast = ifamap.address;
500*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.broadcast_len = ifamap.address_len;
501*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.address = ifamap.local;
502*bd1f8aebSAndroid Build Coastguard Worker 						ifamap.address_len = ifamap.local_len;
503*bd1f8aebSAndroid Build Coastguard Worker 					}
504*bd1f8aebSAndroid Build Coastguard Worker 					if (ifamap.address) {
505*bd1f8aebSAndroid Build Coastguard Worker 						if (!build)
506*bd1f8aebSAndroid Build Coastguard Worker 							dlen += NLMSG_ALIGN(ifamap.address_len);
507*bd1f8aebSAndroid Build Coastguard Worker 						else {
508*bd1f8aebSAndroid Build Coastguard Worker 							ifa->ifa_addr = (struct sockaddr *) data;
509*bd1f8aebSAndroid Build Coastguard Worker 							memcpy(ifa->ifa_addr, ifamap.address, ifamap.address_len);
510*bd1f8aebSAndroid Build Coastguard Worker 							data += NLMSG_ALIGN(ifamap.address_len);
511*bd1f8aebSAndroid Build Coastguard Worker 						}
512*bd1f8aebSAndroid Build Coastguard Worker 					}
513*bd1f8aebSAndroid Build Coastguard Worker 				}
514*bd1f8aebSAndroid Build Coastguard Worker #endif
515*bd1f8aebSAndroid Build Coastguard Worker 				if (!build) {
516*bd1f8aebSAndroid Build Coastguard Worker 					icnt++;
517*bd1f8aebSAndroid Build Coastguard Worker 				} else {
518*bd1f8aebSAndroid Build Coastguard Worker 					ifl = ifa++;
519*bd1f8aebSAndroid Build Coastguard Worker 				}
520*bd1f8aebSAndroid Build Coastguard Worker 			}
521*bd1f8aebSAndroid Build Coastguard Worker 		}
522*bd1f8aebSAndroid Build Coastguard Worker 		if (!build) {
523*bd1f8aebSAndroid Build Coastguard Worker 			if (icnt == 0 && (dlen + xlen == 0)) {
524*bd1f8aebSAndroid Build Coastguard Worker 				if (ifap != NULL)
525*bd1f8aebSAndroid Build Coastguard Worker 					*ifap = NULL;
526*bd1f8aebSAndroid Build Coastguard Worker 				break;	/* cannot found any addresses */
527*bd1f8aebSAndroid Build Coastguard Worker 			}
528*bd1f8aebSAndroid Build Coastguard Worker 		}
529*bd1f8aebSAndroid Build Coastguard Worker 	}
530*bd1f8aebSAndroid Build Coastguard Worker 
531*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------- */
532*bd1f8aebSAndroid Build Coastguard Worker 	/* Finalize */
533*bd1f8aebSAndroid Build Coastguard Worker 	free_nlmsglist(nlmsg_list);
534*bd1f8aebSAndroid Build Coastguard Worker 	nl_close(sd);
535*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
536*bd1f8aebSAndroid Build Coastguard Worker }
537*bd1f8aebSAndroid Build Coastguard Worker 
538*bd1f8aebSAndroid Build Coastguard Worker /* ---------------------------------------------------------------------- */
ni_freeifaddrs(struct ni_ifaddrs * ifa)539*bd1f8aebSAndroid Build Coastguard Worker void ni_freeifaddrs(struct ni_ifaddrs *ifa)
540*bd1f8aebSAndroid Build Coastguard Worker {
541*bd1f8aebSAndroid Build Coastguard Worker 	free(ifa);
542*bd1f8aebSAndroid Build Coastguard Worker }
543*bd1f8aebSAndroid Build Coastguard Worker 
544