xref: /aosp_15_r20/external/iputils/ninfod/ninfod_addrs.c (revision bd1f8aeb6080fa6544ec30aeca3eb4da100f359f)
1*bd1f8aebSAndroid Build Coastguard Worker /* $USAGI: ninfod_addrs.c,v 1.18 2003-07-16 09:49:01 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  * Author:
32*bd1f8aebSAndroid Build Coastguard Worker  * 	YOSHIFUJI Hideaki <[email protected]>
33*bd1f8aebSAndroid Build Coastguard Worker  */
34*bd1f8aebSAndroid Build Coastguard Worker 
35*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_CONFIG_H
36*bd1f8aebSAndroid Build Coastguard Worker #include "config.h"
37*bd1f8aebSAndroid Build Coastguard Worker #endif
38*bd1f8aebSAndroid Build Coastguard Worker 
39*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_SYS_TYPES_H
40*bd1f8aebSAndroid Build Coastguard Worker # include <sys/types.h>
41*bd1f8aebSAndroid Build Coastguard Worker #endif
42*bd1f8aebSAndroid Build Coastguard Worker 
43*bd1f8aebSAndroid Build Coastguard Worker #if STDC_HEADERS
44*bd1f8aebSAndroid Build Coastguard Worker # include <stdio.h>
45*bd1f8aebSAndroid Build Coastguard Worker # include <stdlib.h>
46*bd1f8aebSAndroid Build Coastguard Worker # include <stddef.h>
47*bd1f8aebSAndroid Build Coastguard Worker #else
48*bd1f8aebSAndroid Build Coastguard Worker # if HAVE_STDLIB_H
49*bd1f8aebSAndroid Build Coastguard Worker #  include <stdlib.h>
50*bd1f8aebSAndroid Build Coastguard Worker # endif
51*bd1f8aebSAndroid Build Coastguard Worker #endif
52*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_STRING_H
53*bd1f8aebSAndroid Build Coastguard Worker # if !STDC_HEADERS && HAVE_MEMORY_H
54*bd1f8aebSAndroid Build Coastguard Worker #  include <memory.h>
55*bd1f8aebSAndroid Build Coastguard Worker # endif
56*bd1f8aebSAndroid Build Coastguard Worker # include <string.h>
57*bd1f8aebSAndroid Build Coastguard Worker #endif
58*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_STRINGS_H
59*bd1f8aebSAndroid Build Coastguard Worker # include <strings.h>
60*bd1f8aebSAndroid Build Coastguard Worker #endif
61*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_INTTYPES_H
62*bd1f8aebSAndroid Build Coastguard Worker # include <inttypes.h>
63*bd1f8aebSAndroid Build Coastguard Worker #else
64*bd1f8aebSAndroid Build Coastguard Worker # if HAVE_STDINT_H
65*bd1f8aebSAndroid Build Coastguard Worker #  include <stdint.h>
66*bd1f8aebSAndroid Build Coastguard Worker # endif
67*bd1f8aebSAndroid Build Coastguard Worker #endif
68*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
69*bd1f8aebSAndroid Build Coastguard Worker # include <unistd.h>
70*bd1f8aebSAndroid Build Coastguard Worker #endif
71*bd1f8aebSAndroid Build Coastguard Worker 
72*bd1f8aebSAndroid Build Coastguard Worker #if TIME_WITH_SYS_TIME
73*bd1f8aebSAndroid Build Coastguard Worker # include <sys/time.h>
74*bd1f8aebSAndroid Build Coastguard Worker # include <time.h>
75*bd1f8aebSAndroid Build Coastguard Worker #else
76*bd1f8aebSAndroid Build Coastguard Worker # if HAVE_SYS_TIME_H
77*bd1f8aebSAndroid Build Coastguard Worker #  include <sys/time.h>
78*bd1f8aebSAndroid Build Coastguard Worker # else
79*bd1f8aebSAndroid Build Coastguard Worker #  include <time.h>
80*bd1f8aebSAndroid Build Coastguard Worker # endif
81*bd1f8aebSAndroid Build Coastguard Worker #endif
82*bd1f8aebSAndroid Build Coastguard Worker 
83*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_SYS_UIO_H
84*bd1f8aebSAndroid Build Coastguard Worker #include <sys/uio.h>
85*bd1f8aebSAndroid Build Coastguard Worker #endif
86*bd1f8aebSAndroid Build Coastguard Worker 
87*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
88*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_LINUX_RTNETLINK_H
89*bd1f8aebSAndroid Build Coastguard Worker #include <asm/types.h>
90*bd1f8aebSAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
91*bd1f8aebSAndroid Build Coastguard Worker #endif
92*bd1f8aebSAndroid Build Coastguard Worker 
93*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_NETINET_IN_H
94*bd1f8aebSAndroid Build Coastguard Worker # include <netinet/in.h>
95*bd1f8aebSAndroid Build Coastguard Worker #endif
96*bd1f8aebSAndroid Build Coastguard Worker 
97*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_NETINET_IP6_H
98*bd1f8aebSAndroid Build Coastguard Worker # include <netinet/ip6.h>
99*bd1f8aebSAndroid Build Coastguard Worker #endif
100*bd1f8aebSAndroid Build Coastguard Worker 
101*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_NETINET_ICMP6_H
102*bd1f8aebSAndroid Build Coastguard Worker # include <netinet/icmp6.h>
103*bd1f8aebSAndroid Build Coastguard Worker #endif
104*bd1f8aebSAndroid Build Coastguard Worker #ifndef HAVE_STRUCT_ICMP6_NODEINFO
105*bd1f8aebSAndroid Build Coastguard Worker # include "icmp6_nodeinfo.h"
106*bd1f8aebSAndroid Build Coastguard Worker #endif
107*bd1f8aebSAndroid Build Coastguard Worker 
108*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_NETDB_H
109*bd1f8aebSAndroid Build Coastguard Worker # include <netdb.h>
110*bd1f8aebSAndroid Build Coastguard Worker #endif
111*bd1f8aebSAndroid Build Coastguard Worker #include <errno.h>
112*bd1f8aebSAndroid Build Coastguard Worker 
113*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_SYSLOG_H
114*bd1f8aebSAndroid Build Coastguard Worker # include <syslog.h>
115*bd1f8aebSAndroid Build Coastguard Worker #endif
116*bd1f8aebSAndroid Build Coastguard Worker 
117*bd1f8aebSAndroid Build Coastguard Worker #include "ninfod.h"
118*bd1f8aebSAndroid Build Coastguard Worker #include "ni_ifaddrs.h"
119*bd1f8aebSAndroid Build Coastguard Worker 
120*bd1f8aebSAndroid Build Coastguard Worker #ifndef offsetof
121*bd1f8aebSAndroid Build Coastguard Worker # define offsetof(aggregate,member)	((size_t)&((aggregate *)0)->member)
122*bd1f8aebSAndroid Build Coastguard Worker #endif
123*bd1f8aebSAndroid Build Coastguard Worker 
124*bd1f8aebSAndroid Build Coastguard Worker /* ---------- */
125*bd1f8aebSAndroid Build Coastguard Worker /* ID */
126*bd1f8aebSAndroid Build Coastguard Worker static char *RCSID __attribute__ ((unused)) = "$USAGI: ninfod_addrs.c,v 1.18 2003-07-16 09:49:01 yoshfuji Exp $";
127*bd1f8aebSAndroid Build Coastguard Worker 
128*bd1f8aebSAndroid Build Coastguard Worker /* ---------- */
129*bd1f8aebSAndroid Build Coastguard Worker /* ipv6 address */
init_nodeinfo_ipv6addr(INIT_ARGS)130*bd1f8aebSAndroid Build Coastguard Worker void init_nodeinfo_ipv6addr(INIT_ARGS)
131*bd1f8aebSAndroid Build Coastguard Worker {
132*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
133*bd1f8aebSAndroid Build Coastguard Worker 	return;
134*bd1f8aebSAndroid Build Coastguard Worker }
135*bd1f8aebSAndroid Build Coastguard Worker 
filter_ipv6addr(const struct in6_addr * ifaddr,unsigned int flags)136*bd1f8aebSAndroid Build Coastguard Worker int filter_ipv6addr(const struct in6_addr *ifaddr, unsigned int flags)
137*bd1f8aebSAndroid Build Coastguard Worker {
138*bd1f8aebSAndroid Build Coastguard Worker 	if (IN6_IS_ADDR_UNSPECIFIED(ifaddr) ||
139*bd1f8aebSAndroid Build Coastguard Worker 	    IN6_IS_ADDR_LOOPBACK(ifaddr)) {
140*bd1f8aebSAndroid Build Coastguard Worker 		return 1;
141*bd1f8aebSAndroid Build Coastguard Worker 	} else if (IN6_IS_ADDR_V4COMPAT(ifaddr) ||
142*bd1f8aebSAndroid Build Coastguard Worker 		   IN6_IS_ADDR_V4MAPPED(ifaddr)) {
143*bd1f8aebSAndroid Build Coastguard Worker 		return !(flags & NI_NODEADDR_FLAG_COMPAT);
144*bd1f8aebSAndroid Build Coastguard Worker 	} else if (IN6_IS_ADDR_LINKLOCAL(ifaddr)) {
145*bd1f8aebSAndroid Build Coastguard Worker 		return !(flags & NI_NODEADDR_FLAG_LINKLOCAL);
146*bd1f8aebSAndroid Build Coastguard Worker 	} else if (IN6_IS_ADDR_SITELOCAL(ifaddr)) {
147*bd1f8aebSAndroid Build Coastguard Worker 		return !(flags & NI_NODEADDR_FLAG_SITELOCAL);
148*bd1f8aebSAndroid Build Coastguard Worker 	}
149*bd1f8aebSAndroid Build Coastguard Worker 	return !(flags & NI_NODEADDR_FLAG_GLOBAL);
150*bd1f8aebSAndroid Build Coastguard Worker }
151*bd1f8aebSAndroid Build Coastguard Worker 
pr_nodeinfo_ipv6addr(CHECKANDFILL_ARGS)152*bd1f8aebSAndroid Build Coastguard Worker int pr_nodeinfo_ipv6addr(CHECKANDFILL_ARGS)
153*bd1f8aebSAndroid Build Coastguard Worker {
154*bd1f8aebSAndroid Build Coastguard Worker 	struct ni_ifaddrs *ifa0;
155*bd1f8aebSAndroid Build Coastguard Worker 	unsigned int ifindex = 0;
156*bd1f8aebSAndroid Build Coastguard Worker 
157*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
158*bd1f8aebSAndroid Build Coastguard Worker 
159*bd1f8aebSAndroid Build Coastguard Worker 	if (subject && subjlen != sizeof(struct in6_addr)) {
160*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_INFO,
161*bd1f8aebSAndroid Build Coastguard Worker 		      "%s(): invalid subject length %zu for IPv6 Address Subject\n",
162*bd1f8aebSAndroid Build Coastguard Worker 		      __func__, subjlen);
163*bd1f8aebSAndroid Build Coastguard Worker 		return 1;
164*bd1f8aebSAndroid Build Coastguard Worker 	}
165*bd1f8aebSAndroid Build Coastguard Worker 	if (ni_ifaddrs(&ifa0, AF_INET6))
166*bd1f8aebSAndroid Build Coastguard Worker 		return -1;	/* failed to get addresses */
167*bd1f8aebSAndroid Build Coastguard Worker 
168*bd1f8aebSAndroid Build Coastguard Worker 	/* pass 0: consider subject and determine subjected interface */
169*bd1f8aebSAndroid Build Coastguard Worker 	if (subject) {
170*bd1f8aebSAndroid Build Coastguard Worker 		struct ni_ifaddrs *ifa;
171*bd1f8aebSAndroid Build Coastguard Worker 
172*bd1f8aebSAndroid Build Coastguard Worker 		for (ifa = ifa0; ifa; ifa = ifa->ifa_next) {
173*bd1f8aebSAndroid Build Coastguard Worker 			if (!ifa->ifa_addr)
174*bd1f8aebSAndroid Build Coastguard Worker 				continue;
175*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & (IFA_F_TENTATIVE|IFA_F_SECONDARY))
176*bd1f8aebSAndroid Build Coastguard Worker 				continue;
177*bd1f8aebSAndroid Build Coastguard Worker 			if (!ifindex &&
178*bd1f8aebSAndroid Build Coastguard Worker 			    IN6_ARE_ADDR_EQUAL(&p->pktinfo.ipi6_addr,
179*bd1f8aebSAndroid Build Coastguard Worker 					       (struct in6_addr *)subject)) {
180*bd1f8aebSAndroid Build Coastguard Worker 				/*
181*bd1f8aebSAndroid Build Coastguard Worker 				 * if subject is equal to destination
182*bd1f8aebSAndroid Build Coastguard Worker 				 * address, receiving interface is
183*bd1f8aebSAndroid Build Coastguard Worker 				 * the candidate subject interface.
184*bd1f8aebSAndroid Build Coastguard Worker 				 */
185*bd1f8aebSAndroid Build Coastguard Worker 				ifindex = p->pktinfo.ipi6_ifindex;
186*bd1f8aebSAndroid Build Coastguard Worker 			}
187*bd1f8aebSAndroid Build Coastguard Worker 			if (!IN6_IS_ADDR_LOOPBACK((struct in6_addr *)subject) &&
188*bd1f8aebSAndroid Build Coastguard Worker 			    IN6_ARE_ADDR_EQUAL((struct in6_addr *)ifa->ifa_addr,
189*bd1f8aebSAndroid Build Coastguard Worker 					       (struct in6_addr *)subject)) {
190*bd1f8aebSAndroid Build Coastguard Worker 				/*
191*bd1f8aebSAndroid Build Coastguard Worker 				 * address is assigned on some interface.
192*bd1f8aebSAndroid Build Coastguard Worker 				 * if multiple interfaces have the same interface,
193*bd1f8aebSAndroid Build Coastguard Worker 				 *  1) prefer receiving interface
194*bd1f8aebSAndroid Build Coastguard Worker 				 *  2) use first found one
195*bd1f8aebSAndroid Build Coastguard Worker 				 */
196*bd1f8aebSAndroid Build Coastguard Worker 				if (!ifindex ||
197*bd1f8aebSAndroid Build Coastguard Worker 				    (p->pktinfo.ipi6_ifindex == ifindex))
198*bd1f8aebSAndroid Build Coastguard Worker 					ifindex = ifa->ifa_ifindex;
199*bd1f8aebSAndroid Build Coastguard Worker 			}
200*bd1f8aebSAndroid Build Coastguard Worker 		}
201*bd1f8aebSAndroid Build Coastguard Worker 		if (!ifindex) {
202*bd1f8aebSAndroid Build Coastguard Worker 			ni_freeifaddrs(ifa0);
203*bd1f8aebSAndroid Build Coastguard Worker 			return 1;	/* subject not found */
204*bd1f8aebSAndroid Build Coastguard Worker 		}
205*bd1f8aebSAndroid Build Coastguard Worker 		if (subj_if)
206*bd1f8aebSAndroid Build Coastguard Worker 			*subj_if = ifindex;
207*bd1f8aebSAndroid Build Coastguard Worker 	} else {
208*bd1f8aebSAndroid Build Coastguard Worker 		ifindex = subj_if ? *subj_if : 0;
209*bd1f8aebSAndroid Build Coastguard Worker 		if (ifindex == 0)
210*bd1f8aebSAndroid Build Coastguard Worker 			ifindex = p->pktinfo.ipi6_ifindex;
211*bd1f8aebSAndroid Build Coastguard Worker 		if (ifindex == 0) {
212*bd1f8aebSAndroid Build Coastguard Worker 			ni_freeifaddrs(ifa0);
213*bd1f8aebSAndroid Build Coastguard Worker 			return 1;	/* XXX */
214*bd1f8aebSAndroid Build Coastguard Worker 		}
215*bd1f8aebSAndroid Build Coastguard Worker 	}
216*bd1f8aebSAndroid Build Coastguard Worker 
217*bd1f8aebSAndroid Build Coastguard Worker 	if (reply) {
218*bd1f8aebSAndroid Build Coastguard Worker 		struct ni_ifaddrs *ifa;
219*bd1f8aebSAndroid Build Coastguard Worker 		unsigned int addrs0 = 0, paddrs0 = 0;
220*bd1f8aebSAndroid Build Coastguard Worker 		unsigned int addrs, paddrs = 0, daddrs = 0;
221*bd1f8aebSAndroid Build Coastguard Worker 
222*bd1f8aebSAndroid Build Coastguard Worker 		flags &= ~NI_NODEADDR_FLAG_TRUNCATE;
223*bd1f8aebSAndroid Build Coastguard Worker 
224*bd1f8aebSAndroid Build Coastguard Worker 		/* pass 1: count addresses and preferred addresses to be returned */
225*bd1f8aebSAndroid Build Coastguard Worker 		for (ifa = ifa0; ifa; ifa = ifa->ifa_next) {
226*bd1f8aebSAndroid Build Coastguard Worker 			if (!ifa->ifa_addr)
227*bd1f8aebSAndroid Build Coastguard Worker 				continue;
228*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & (IFA_F_TENTATIVE|IFA_F_SECONDARY))
229*bd1f8aebSAndroid Build Coastguard Worker 				continue;
230*bd1f8aebSAndroid Build Coastguard Worker 			if (!(flags & NI_NODEADDR_FLAG_ALL) &&
231*bd1f8aebSAndroid Build Coastguard Worker 			    ifa->ifa_ifindex != ifindex)
232*bd1f8aebSAndroid Build Coastguard Worker 				continue;
233*bd1f8aebSAndroid Build Coastguard Worker 			if (filter_ipv6addr((struct in6_addr *)ifa->ifa_addr, flags))
234*bd1f8aebSAndroid Build Coastguard Worker 				continue;
235*bd1f8aebSAndroid Build Coastguard Worker 
236*bd1f8aebSAndroid Build Coastguard Worker 			if (addrs0 + 1 >= ((MAX_REPLY_SIZE - sizeof(struct icmp6_nodeinfo)) / (sizeof(uint32_t) + sizeof(struct in6_addr)))) {
237*bd1f8aebSAndroid Build Coastguard Worker 				flags |= ~NI_NODEADDR_FLAG_TRUNCATE;
238*bd1f8aebSAndroid Build Coastguard Worker 				break;
239*bd1f8aebSAndroid Build Coastguard Worker 			}
240*bd1f8aebSAndroid Build Coastguard Worker 
241*bd1f8aebSAndroid Build Coastguard Worker 			addrs0++;
242*bd1f8aebSAndroid Build Coastguard Worker 			if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
243*bd1f8aebSAndroid Build Coastguard Worker 				paddrs0++;
244*bd1f8aebSAndroid Build Coastguard Worker 		}
245*bd1f8aebSAndroid Build Coastguard Worker 
246*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_type = ICMP6_NI_REPLY;
247*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_code = ICMP6_NI_SUCCESS;
248*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_cksum = 0;
249*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_qtype = htons(NI_QTYPE_NODEADDR);
250*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_flags = flags&(NI_NODEADDR_FLAG_COMPAT|
251*bd1f8aebSAndroid Build Coastguard Worker 					   NI_NODEADDR_FLAG_LINKLOCAL|
252*bd1f8aebSAndroid Build Coastguard Worker 					   NI_NODEADDR_FLAG_SITELOCAL|
253*bd1f8aebSAndroid Build Coastguard Worker 					   NI_NODEADDR_FLAG_GLOBAL);
254*bd1f8aebSAndroid Build Coastguard Worker 
255*bd1f8aebSAndroid Build Coastguard Worker 		/* pass 2: store addresses */
256*bd1f8aebSAndroid Build Coastguard Worker 		p->replydatalen = (sizeof(uint32_t)+sizeof(struct in6_addr)) * addrs0;
257*bd1f8aebSAndroid Build Coastguard Worker 		p->replydata = p->replydatalen ? ni_malloc(p->replydatalen) : NULL;
258*bd1f8aebSAndroid Build Coastguard Worker 
259*bd1f8aebSAndroid Build Coastguard Worker 		if (p->replydatalen && !p->replydata) {
260*bd1f8aebSAndroid Build Coastguard Worker 			p->reply.ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
261*bd1f8aebSAndroid Build Coastguard Worker 			addrs0 = paddrs0 = 0;
262*bd1f8aebSAndroid Build Coastguard Worker 		}
263*bd1f8aebSAndroid Build Coastguard Worker 
264*bd1f8aebSAndroid Build Coastguard Worker 		for (ifa = ifa0, addrs = 0;
265*bd1f8aebSAndroid Build Coastguard Worker 		     ifa && addrs < addrs0;
266*bd1f8aebSAndroid Build Coastguard Worker 		     ifa = ifa->ifa_next) {
267*bd1f8aebSAndroid Build Coastguard Worker 			char *cp;
268*bd1f8aebSAndroid Build Coastguard Worker 			uint32_t ttl;
269*bd1f8aebSAndroid Build Coastguard Worker 
270*bd1f8aebSAndroid Build Coastguard Worker 			if (!ifa->ifa_addr)
271*bd1f8aebSAndroid Build Coastguard Worker 				continue;
272*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & (IFA_F_TENTATIVE|IFA_F_SECONDARY))
273*bd1f8aebSAndroid Build Coastguard Worker 				continue;
274*bd1f8aebSAndroid Build Coastguard Worker 			if (!(flags & NI_NODEADDR_FLAG_ALL) &&
275*bd1f8aebSAndroid Build Coastguard Worker 			    ((subj_if && *subj_if) ? (ifa->ifa_ifindex != *subj_if) :
276*bd1f8aebSAndroid Build Coastguard Worker 						     (ifa->ifa_ifindex != p->pktinfo.ipi6_ifindex)))
277*bd1f8aebSAndroid Build Coastguard Worker 				continue;
278*bd1f8aebSAndroid Build Coastguard Worker 			if (filter_ipv6addr((struct in6_addr *)ifa->ifa_addr, flags))
279*bd1f8aebSAndroid Build Coastguard Worker 				continue;
280*bd1f8aebSAndroid Build Coastguard Worker 
281*bd1f8aebSAndroid Build Coastguard Worker #if ENABLE_TTL
282*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_cacheinfo) {
283*bd1f8aebSAndroid Build Coastguard Worker 				ttl = ifa->ifa_cacheinfo->ifa_valid > 0x7fffffff ?
284*bd1f8aebSAndroid Build Coastguard Worker 				      htonl(0x7fffffff) : htonl(ifa->ifa_cacheinfo->ifa_valid);
285*bd1f8aebSAndroid Build Coastguard Worker 			} else {
286*bd1f8aebSAndroid Build Coastguard Worker 				ttl = (ifa->ifa_flags & IFA_F_PERMANENT) ? htonl(0x7fffffff) : 0;
287*bd1f8aebSAndroid Build Coastguard Worker 			}
288*bd1f8aebSAndroid Build Coastguard Worker #else
289*bd1f8aebSAndroid Build Coastguard Worker 			ttl = 0;
290*bd1f8aebSAndroid Build Coastguard Worker #endif
291*bd1f8aebSAndroid Build Coastguard Worker 
292*bd1f8aebSAndroid Build Coastguard Worker 			cp = p->replydata +
293*bd1f8aebSAndroid Build Coastguard Worker 			     (sizeof(uint32_t)+sizeof(struct in6_addr)) * (ifa->ifa_flags & IFA_F_DEPRECATED ? paddrs0+daddrs : paddrs);
294*bd1f8aebSAndroid Build Coastguard Worker 			memcpy(cp, &ttl, sizeof(ttl));
295*bd1f8aebSAndroid Build Coastguard Worker 			memcpy(cp + sizeof(ttl), ifa->ifa_addr, sizeof(struct in6_addr));
296*bd1f8aebSAndroid Build Coastguard Worker 
297*bd1f8aebSAndroid Build Coastguard Worker 			addrs++;
298*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & IFA_F_DEPRECATED)
299*bd1f8aebSAndroid Build Coastguard Worker 				daddrs++;
300*bd1f8aebSAndroid Build Coastguard Worker 			else
301*bd1f8aebSAndroid Build Coastguard Worker 				paddrs++;
302*bd1f8aebSAndroid Build Coastguard Worker 		}
303*bd1f8aebSAndroid Build Coastguard Worker 	}
304*bd1f8aebSAndroid Build Coastguard Worker 
305*bd1f8aebSAndroid Build Coastguard Worker 	ni_freeifaddrs(ifa0);
306*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
307*bd1f8aebSAndroid Build Coastguard Worker }
308*bd1f8aebSAndroid Build Coastguard Worker 
309*bd1f8aebSAndroid Build Coastguard Worker /* ipv4 address */
init_nodeinfo_ipv4addr(INIT_ARGS)310*bd1f8aebSAndroid Build Coastguard Worker void init_nodeinfo_ipv4addr(INIT_ARGS)
311*bd1f8aebSAndroid Build Coastguard Worker {
312*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
313*bd1f8aebSAndroid Build Coastguard Worker 	return;
314*bd1f8aebSAndroid Build Coastguard Worker }
315*bd1f8aebSAndroid Build Coastguard Worker 
filter_ipv4addr(const struct in_addr * ifaddr,unsigned int flags)316*bd1f8aebSAndroid Build Coastguard Worker int filter_ipv4addr(const struct in_addr *ifaddr, unsigned int flags)
317*bd1f8aebSAndroid Build Coastguard Worker {
318*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
319*bd1f8aebSAndroid Build Coastguard Worker }
320*bd1f8aebSAndroid Build Coastguard Worker 
pr_nodeinfo_ipv4addr(CHECKANDFILL_ARGS)321*bd1f8aebSAndroid Build Coastguard Worker int pr_nodeinfo_ipv4addr(CHECKANDFILL_ARGS)
322*bd1f8aebSAndroid Build Coastguard Worker {
323*bd1f8aebSAndroid Build Coastguard Worker 	struct ni_ifaddrs *ifa0;
324*bd1f8aebSAndroid Build Coastguard Worker 	unsigned int ifindex = 0;
325*bd1f8aebSAndroid Build Coastguard Worker 
326*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
327*bd1f8aebSAndroid Build Coastguard Worker 
328*bd1f8aebSAndroid Build Coastguard Worker 	if (subject && subjlen != sizeof(struct in_addr)) {
329*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_INFO,
330*bd1f8aebSAndroid Build Coastguard Worker 		      "%s(): invalid subject length %zu for IPv4 Address Subject\n",
331*bd1f8aebSAndroid Build Coastguard Worker 		      __func__, subjlen);
332*bd1f8aebSAndroid Build Coastguard Worker 		return 1;
333*bd1f8aebSAndroid Build Coastguard Worker 	}
334*bd1f8aebSAndroid Build Coastguard Worker 	if (ni_ifaddrs(&ifa0, AF_INET))
335*bd1f8aebSAndroid Build Coastguard Worker 		return -1;	/* failed to get addresses */
336*bd1f8aebSAndroid Build Coastguard Worker 
337*bd1f8aebSAndroid Build Coastguard Worker 	/* pass 0: consider subject and determine subjected interface */
338*bd1f8aebSAndroid Build Coastguard Worker 	if (subject) {
339*bd1f8aebSAndroid Build Coastguard Worker 		struct ni_ifaddrs *ifa;
340*bd1f8aebSAndroid Build Coastguard Worker 
341*bd1f8aebSAndroid Build Coastguard Worker 		for (ifa = ifa0; ifa; ifa = ifa->ifa_next) {
342*bd1f8aebSAndroid Build Coastguard Worker 			if (!ifa->ifa_addr)
343*bd1f8aebSAndroid Build Coastguard Worker 				continue;
344*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & (IFA_F_TENTATIVE|IFA_F_SECONDARY))
345*bd1f8aebSAndroid Build Coastguard Worker 				continue;
346*bd1f8aebSAndroid Build Coastguard Worker 			if ((((struct in_addr *)subject)->s_addr != htonl(INADDR_LOOPBACK)) &&
347*bd1f8aebSAndroid Build Coastguard Worker 			    memcmp((struct in_addr *)ifa->ifa_addr,
348*bd1f8aebSAndroid Build Coastguard Worker 				   (struct in_addr *)subject,
349*bd1f8aebSAndroid Build Coastguard Worker 				   sizeof(struct in_addr)) == 0) {
350*bd1f8aebSAndroid Build Coastguard Worker 				/*
351*bd1f8aebSAndroid Build Coastguard Worker 				 * address is assigned on some interface.
352*bd1f8aebSAndroid Build Coastguard Worker 				 * if multiple interfaces have the same interface,
353*bd1f8aebSAndroid Build Coastguard Worker 				 *  1) prefer receiving interface
354*bd1f8aebSAndroid Build Coastguard Worker 				 *  2) use first found one
355*bd1f8aebSAndroid Build Coastguard Worker 				 */
356*bd1f8aebSAndroid Build Coastguard Worker 				if (!ifindex ||
357*bd1f8aebSAndroid Build Coastguard Worker 				    (p->pktinfo.ipi6_ifindex == ifindex))
358*bd1f8aebSAndroid Build Coastguard Worker 					ifindex = ifa->ifa_ifindex;
359*bd1f8aebSAndroid Build Coastguard Worker 			}
360*bd1f8aebSAndroid Build Coastguard Worker 		}
361*bd1f8aebSAndroid Build Coastguard Worker 		if (!ifindex) {
362*bd1f8aebSAndroid Build Coastguard Worker 			ni_freeifaddrs(ifa0);
363*bd1f8aebSAndroid Build Coastguard Worker 			return 1;	/* subject not found */
364*bd1f8aebSAndroid Build Coastguard Worker 		}
365*bd1f8aebSAndroid Build Coastguard Worker 		if (subj_if)
366*bd1f8aebSAndroid Build Coastguard Worker 			*subj_if = ifindex;
367*bd1f8aebSAndroid Build Coastguard Worker 	} else {
368*bd1f8aebSAndroid Build Coastguard Worker 		ifindex = subj_if ? *subj_if : 0;
369*bd1f8aebSAndroid Build Coastguard Worker 		if (ifindex == 0)
370*bd1f8aebSAndroid Build Coastguard Worker 			ifindex = p->pktinfo.ipi6_ifindex;
371*bd1f8aebSAndroid Build Coastguard Worker 		if (ifindex == 0) {
372*bd1f8aebSAndroid Build Coastguard Worker 			ni_freeifaddrs(ifa0);
373*bd1f8aebSAndroid Build Coastguard Worker 			return 1;	/* XXX */
374*bd1f8aebSAndroid Build Coastguard Worker 		}
375*bd1f8aebSAndroid Build Coastguard Worker 	}
376*bd1f8aebSAndroid Build Coastguard Worker 
377*bd1f8aebSAndroid Build Coastguard Worker 	if (reply) {
378*bd1f8aebSAndroid Build Coastguard Worker 		struct ni_ifaddrs *ifa;
379*bd1f8aebSAndroid Build Coastguard Worker 		unsigned int addrs0 = 0, paddrs0 = 0;
380*bd1f8aebSAndroid Build Coastguard Worker 		unsigned int addrs, paddrs = 0, daddrs = 0;
381*bd1f8aebSAndroid Build Coastguard Worker 
382*bd1f8aebSAndroid Build Coastguard Worker 		flags &= ~NI_IPV4ADDR_FLAG_TRUNCATE;
383*bd1f8aebSAndroid Build Coastguard Worker 
384*bd1f8aebSAndroid Build Coastguard Worker 		/* pass 1: count addresses and preferred addresses to be returned */
385*bd1f8aebSAndroid Build Coastguard Worker 		for (ifa = ifa0; ifa; ifa = ifa->ifa_next) {
386*bd1f8aebSAndroid Build Coastguard Worker 			if (!ifa->ifa_addr)
387*bd1f8aebSAndroid Build Coastguard Worker 				continue;
388*bd1f8aebSAndroid Build Coastguard Worker #if 1	/* not used in kernel */
389*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & (IFA_F_TENTATIVE))
390*bd1f8aebSAndroid Build Coastguard Worker 				continue;
391*bd1f8aebSAndroid Build Coastguard Worker #endif
392*bd1f8aebSAndroid Build Coastguard Worker 			if (!(flags & NI_NODEADDR_FLAG_ALL) &&
393*bd1f8aebSAndroid Build Coastguard Worker 			    ((subj_if && *subj_if) ? (ifa->ifa_ifindex != *subj_if) :
394*bd1f8aebSAndroid Build Coastguard Worker 						     (ifa->ifa_ifindex != p->pktinfo.ipi6_ifindex)))
395*bd1f8aebSAndroid Build Coastguard Worker 				continue;
396*bd1f8aebSAndroid Build Coastguard Worker 			if (filter_ipv4addr((struct in_addr *)ifa->ifa_addr, flags))
397*bd1f8aebSAndroid Build Coastguard Worker 				continue;
398*bd1f8aebSAndroid Build Coastguard Worker 
399*bd1f8aebSAndroid Build Coastguard Worker 			if (addrs0 + 1 >= ((MAX_REPLY_SIZE - sizeof(struct icmp6_nodeinfo)) / (sizeof(uint32_t) + sizeof(struct in_addr)))) {
400*bd1f8aebSAndroid Build Coastguard Worker 				flags |= NI_IPV4ADDR_FLAG_TRUNCATE;
401*bd1f8aebSAndroid Build Coastguard Worker 				break;
402*bd1f8aebSAndroid Build Coastguard Worker 			}
403*bd1f8aebSAndroid Build Coastguard Worker 
404*bd1f8aebSAndroid Build Coastguard Worker 			addrs0++;
405*bd1f8aebSAndroid Build Coastguard Worker 			if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
406*bd1f8aebSAndroid Build Coastguard Worker 				paddrs0++;
407*bd1f8aebSAndroid Build Coastguard Worker 		}
408*bd1f8aebSAndroid Build Coastguard Worker 
409*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_type = ICMP6_NI_REPLY;
410*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_code = ICMP6_NI_SUCCESS;
411*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_cksum = 0;
412*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_qtype = htons(NI_QTYPE_IPV4ADDR);
413*bd1f8aebSAndroid Build Coastguard Worker 		p->reply.ni_flags = flags & NI_IPV4ADDR_FLAG_ALL;
414*bd1f8aebSAndroid Build Coastguard Worker 
415*bd1f8aebSAndroid Build Coastguard Worker 		/* pass 2: store addresses */
416*bd1f8aebSAndroid Build Coastguard Worker 		p->replydatalen = (sizeof(uint32_t)+sizeof(struct in_addr)) * addrs0;
417*bd1f8aebSAndroid Build Coastguard Worker 		p->replydata = addrs0 ? ni_malloc(p->replydatalen) : NULL;
418*bd1f8aebSAndroid Build Coastguard Worker 
419*bd1f8aebSAndroid Build Coastguard Worker 		if (p->replydatalen && !p->replydata) {
420*bd1f8aebSAndroid Build Coastguard Worker 			p->reply.ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
421*bd1f8aebSAndroid Build Coastguard Worker 			addrs0 = paddrs0 = 0;
422*bd1f8aebSAndroid Build Coastguard Worker 		}
423*bd1f8aebSAndroid Build Coastguard Worker 
424*bd1f8aebSAndroid Build Coastguard Worker 		for (ifa = ifa0, addrs = 0;
425*bd1f8aebSAndroid Build Coastguard Worker 		     ifa && addrs < addrs0;
426*bd1f8aebSAndroid Build Coastguard Worker 		     ifa = ifa->ifa_next) {
427*bd1f8aebSAndroid Build Coastguard Worker 			char *cp;
428*bd1f8aebSAndroid Build Coastguard Worker 			uint32_t ttl;
429*bd1f8aebSAndroid Build Coastguard Worker 
430*bd1f8aebSAndroid Build Coastguard Worker 			if (!ifa->ifa_addr)
431*bd1f8aebSAndroid Build Coastguard Worker 				continue;
432*bd1f8aebSAndroid Build Coastguard Worker #if 1	/* not used in kernel */
433*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & (IFA_F_TENTATIVE))
434*bd1f8aebSAndroid Build Coastguard Worker 				continue;
435*bd1f8aebSAndroid Build Coastguard Worker #endif
436*bd1f8aebSAndroid Build Coastguard Worker 			if (!(flags & NI_NODEADDR_FLAG_ALL) &&
437*bd1f8aebSAndroid Build Coastguard Worker 			    (ifa->ifa_ifindex != ifindex))
438*bd1f8aebSAndroid Build Coastguard Worker 				continue;
439*bd1f8aebSAndroid Build Coastguard Worker 			if (filter_ipv4addr((struct in_addr *)ifa->ifa_addr, flags))
440*bd1f8aebSAndroid Build Coastguard Worker 				continue;
441*bd1f8aebSAndroid Build Coastguard Worker 
442*bd1f8aebSAndroid Build Coastguard Worker #if ENABLE_TTL
443*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_cacheinfo) {
444*bd1f8aebSAndroid Build Coastguard Worker 				ttl = ifa->ifa_cacheinfo->ifa_valid > 0x7fffffff ?
445*bd1f8aebSAndroid Build Coastguard Worker 				      htonl(0x7fffffff) : htonl(ifa->ifa_cacheinfo->ifa_valid);
446*bd1f8aebSAndroid Build Coastguard Worker 			} else {
447*bd1f8aebSAndroid Build Coastguard Worker 				ttl = 0;	/*XXX*/
448*bd1f8aebSAndroid Build Coastguard Worker 			}
449*bd1f8aebSAndroid Build Coastguard Worker #else
450*bd1f8aebSAndroid Build Coastguard Worker 			ttl = 0;
451*bd1f8aebSAndroid Build Coastguard Worker #endif
452*bd1f8aebSAndroid Build Coastguard Worker 
453*bd1f8aebSAndroid Build Coastguard Worker 			cp = (p->replydata +
454*bd1f8aebSAndroid Build Coastguard Worker 			      (sizeof(uint32_t)+sizeof(struct in_addr)) * (ifa->ifa_flags & IFA_F_DEPRECATED ? paddrs0+daddrs : paddrs));
455*bd1f8aebSAndroid Build Coastguard Worker 			memcpy(cp, &ttl, sizeof(ttl));
456*bd1f8aebSAndroid Build Coastguard Worker 			memcpy(cp + sizeof(ttl), ifa->ifa_addr, sizeof(struct in_addr));
457*bd1f8aebSAndroid Build Coastguard Worker 
458*bd1f8aebSAndroid Build Coastguard Worker 			addrs++;
459*bd1f8aebSAndroid Build Coastguard Worker 			if (ifa->ifa_flags & IFA_F_DEPRECATED)
460*bd1f8aebSAndroid Build Coastguard Worker 				daddrs++;
461*bd1f8aebSAndroid Build Coastguard Worker 			else
462*bd1f8aebSAndroid Build Coastguard Worker 				paddrs++;
463*bd1f8aebSAndroid Build Coastguard Worker 		}
464*bd1f8aebSAndroid Build Coastguard Worker 	}
465*bd1f8aebSAndroid Build Coastguard Worker 
466*bd1f8aebSAndroid Build Coastguard Worker 	ni_freeifaddrs(ifa0);
467*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
468*bd1f8aebSAndroid Build Coastguard Worker }
469*bd1f8aebSAndroid Build Coastguard Worker 
470