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