xref: /aosp_15_r20/external/iputils/ninfod/ninfod.c (revision bd1f8aeb6080fa6544ec30aeca3eb4da100f359f)
1*bd1f8aebSAndroid Build Coastguard Worker /* $USAGI: ninfod.c,v 1.34 2003-01-15 06:41:23 mk 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 #if STDC_HEADERS
43*bd1f8aebSAndroid Build Coastguard Worker # include <stdio.h>
44*bd1f8aebSAndroid Build Coastguard Worker # include <stdlib.h>
45*bd1f8aebSAndroid Build Coastguard Worker # include <stddef.h>
46*bd1f8aebSAndroid Build Coastguard Worker # include <stdarg.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 
53*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_STRING_H
54*bd1f8aebSAndroid Build Coastguard Worker # if !STDC_HEADERS && HAVE_MEMORY_H
55*bd1f8aebSAndroid Build Coastguard Worker #  include <memory.h>
56*bd1f8aebSAndroid Build Coastguard Worker # endif
57*bd1f8aebSAndroid Build Coastguard Worker # include <string.h>
58*bd1f8aebSAndroid Build Coastguard Worker #endif
59*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_STRINGS_H
60*bd1f8aebSAndroid Build Coastguard Worker # include <strings.h>
61*bd1f8aebSAndroid Build Coastguard Worker #endif
62*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_INTTYPES_H
63*bd1f8aebSAndroid Build Coastguard Worker # include <inttypes.h>
64*bd1f8aebSAndroid Build Coastguard Worker #else
65*bd1f8aebSAndroid Build Coastguard Worker # if HAVE_STDINT_H
66*bd1f8aebSAndroid Build Coastguard Worker #  include <stdint.h>
67*bd1f8aebSAndroid Build Coastguard Worker # endif
68*bd1f8aebSAndroid Build Coastguard Worker #endif
69*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_LIMITS_H
70*bd1f8aebSAndroid Build Coastguard Worker # include <limits.h>
71*bd1f8aebSAndroid Build Coastguard Worker #endif
72*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
73*bd1f8aebSAndroid Build Coastguard Worker # include <unistd.h>
74*bd1f8aebSAndroid Build Coastguard Worker #endif
75*bd1f8aebSAndroid Build Coastguard Worker 
76*bd1f8aebSAndroid Build Coastguard Worker #ifdef TIME_WITH_SYS_TIME
77*bd1f8aebSAndroid Build Coastguard Worker # include <sys/time.h>
78*bd1f8aebSAndroid Build Coastguard Worker # include <time.h>
79*bd1f8aebSAndroid Build Coastguard Worker #else
80*bd1f8aebSAndroid Build Coastguard Worker # ifdef HAVE_SYS_TIME_H
81*bd1f8aebSAndroid Build Coastguard Worker #  include <sys/time.h>
82*bd1f8aebSAndroid Build Coastguard Worker # else
83*bd1f8aebSAndroid Build Coastguard Worker #  include <time.h>
84*bd1f8aebSAndroid Build Coastguard Worker # endif
85*bd1f8aebSAndroid Build Coastguard Worker #endif
86*bd1f8aebSAndroid Build Coastguard Worker 
87*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_SYS_UIO_H
88*bd1f8aebSAndroid Build Coastguard Worker #include <sys/uio.h>
89*bd1f8aebSAndroid Build Coastguard Worker #endif
90*bd1f8aebSAndroid Build Coastguard Worker 
91*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
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_ICMP6_H
98*bd1f8aebSAndroid Build Coastguard Worker # include <netinet/icmp6.h>
99*bd1f8aebSAndroid Build Coastguard Worker #endif
100*bd1f8aebSAndroid Build Coastguard Worker #ifndef HAVE_STRUCT_ICMP6_NODEINFO
101*bd1f8aebSAndroid Build Coastguard Worker # include "icmp6_nodeinfo.h"
102*bd1f8aebSAndroid Build Coastguard Worker #endif
103*bd1f8aebSAndroid Build Coastguard Worker 
104*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_NETDB_H
105*bd1f8aebSAndroid Build Coastguard Worker # include <netdb.h>
106*bd1f8aebSAndroid Build Coastguard Worker #endif
107*bd1f8aebSAndroid Build Coastguard Worker #include <errno.h>
108*bd1f8aebSAndroid Build Coastguard Worker 
109*bd1f8aebSAndroid Build Coastguard Worker #include <signal.h>
110*bd1f8aebSAndroid Build Coastguard Worker 
111*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_SYSLOG_H
112*bd1f8aebSAndroid Build Coastguard Worker # include <syslog.h>
113*bd1f8aebSAndroid Build Coastguard Worker #endif
114*bd1f8aebSAndroid Build Coastguard Worker 
115*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_PWD_H
116*bd1f8aebSAndroid Build Coastguard Worker # include <pwd.h>
117*bd1f8aebSAndroid Build Coastguard Worker #endif
118*bd1f8aebSAndroid Build Coastguard Worker 
119*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_SYS_CAPABILITY_H
120*bd1f8aebSAndroid Build Coastguard Worker # include <sys/prctl.h>
121*bd1f8aebSAndroid Build Coastguard Worker # include <sys/capability.h>
122*bd1f8aebSAndroid Build Coastguard Worker #endif
123*bd1f8aebSAndroid Build Coastguard Worker 
124*bd1f8aebSAndroid Build Coastguard Worker #include "ninfod.h"
125*bd1f8aebSAndroid Build Coastguard Worker 
126*bd1f8aebSAndroid Build Coastguard Worker #ifndef offsetof
127*bd1f8aebSAndroid Build Coastguard Worker # define offsetof(aggregate,member)	((size_t)&((aggregate *)0)->member)
128*bd1f8aebSAndroid Build Coastguard Worker #endif
129*bd1f8aebSAndroid Build Coastguard Worker 
130*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
131*bd1f8aebSAndroid Build Coastguard Worker /* ID */
132*bd1f8aebSAndroid Build Coastguard Worker static char *RCSID __attribute__ ((unused)) = "$USAGI: ninfod.c,v 1.34 2003-01-15 06:41:23 mk Exp $";
133*bd1f8aebSAndroid Build Coastguard Worker 
134*bd1f8aebSAndroid Build Coastguard Worker /* Variables */
135*bd1f8aebSAndroid Build Coastguard Worker int sock;
136*bd1f8aebSAndroid Build Coastguard Worker int daemonized;
137*bd1f8aebSAndroid Build Coastguard Worker 
138*bd1f8aebSAndroid Build Coastguard Worker char *appname;
139*bd1f8aebSAndroid Build Coastguard Worker static int opt_d = 0;	/* debug */
140*bd1f8aebSAndroid Build Coastguard Worker static int opt_h = 0;	/* help */
141*bd1f8aebSAndroid Build Coastguard Worker static char *opt_p = NINFOD_PIDFILE;	/* pidfile */
142*bd1f8aebSAndroid Build Coastguard Worker static int got_signal = 0;	/* loop unless true */
143*bd1f8aebSAndroid Build Coastguard Worker int opt_v = 0;		/* verbose */
144*bd1f8aebSAndroid Build Coastguard Worker static uid_t opt_u;
145*bd1f8aebSAndroid Build Coastguard Worker 
146*bd1f8aebSAndroid Build Coastguard Worker static int ipv6_pktinfo = IPV6_PKTINFO;
147*bd1f8aebSAndroid Build Coastguard Worker 
148*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
149*bd1f8aebSAndroid Build Coastguard Worker #if ENABLE_DEBUG
log_level(int priority)150*bd1f8aebSAndroid Build Coastguard Worker static const __inline__ char * log_level(int priority) {
151*bd1f8aebSAndroid Build Coastguard Worker 	switch(priority) {
152*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_EMERG:		return "EMERG";
153*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_ALERT:		return "ALERT";
154*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_CRIT:		return "CRIT";
155*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_ERR:		return "ERR";
156*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_WARNING:	return "WARNING";
157*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_NOTICE:	return "NOTICE";
158*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_INFO:		return "INFO";
159*bd1f8aebSAndroid Build Coastguard Worker 	case LOG_DEBUG:		return "DEBUG";
160*bd1f8aebSAndroid Build Coastguard Worker 	default:		return "???";
161*bd1f8aebSAndroid Build Coastguard Worker 	}
162*bd1f8aebSAndroid Build Coastguard Worker }
163*bd1f8aebSAndroid Build Coastguard Worker 
stderrlog(int pri,char * fmt,...)164*bd1f8aebSAndroid Build Coastguard Worker void stderrlog(int pri, char *fmt, ...)
165*bd1f8aebSAndroid Build Coastguard Worker {
166*bd1f8aebSAndroid Build Coastguard Worker 	va_list ap;
167*bd1f8aebSAndroid Build Coastguard Worker 	char ebuf[512];
168*bd1f8aebSAndroid Build Coastguard Worker 	char *buf;
169*bd1f8aebSAndroid Build Coastguard Worker 	size_t buflen;
170*bd1f8aebSAndroid Build Coastguard Worker 
171*bd1f8aebSAndroid Build Coastguard Worker 	va_start(ap, fmt);
172*bd1f8aebSAndroid Build Coastguard Worker 
173*bd1f8aebSAndroid Build Coastguard Worker 	for (buf = ebuf, buflen = sizeof(ebuf);
174*bd1f8aebSAndroid Build Coastguard Worker 	     buflen < SIZE_MAX / 2;
175*bd1f8aebSAndroid Build Coastguard Worker 	     free(buf != ebuf ? buf : NULL), buf = NULL, buflen *= 2) {
176*bd1f8aebSAndroid Build Coastguard Worker 		size_t rem;
177*bd1f8aebSAndroid Build Coastguard Worker 		size_t res;
178*bd1f8aebSAndroid Build Coastguard Worker 
179*bd1f8aebSAndroid Build Coastguard Worker 		buf = malloc(buflen);
180*bd1f8aebSAndroid Build Coastguard Worker 		if (!buf)
181*bd1f8aebSAndroid Build Coastguard Worker 			break;	/*XXX*/
182*bd1f8aebSAndroid Build Coastguard Worker 
183*bd1f8aebSAndroid Build Coastguard Worker 		rem = buflen;
184*bd1f8aebSAndroid Build Coastguard Worker 
185*bd1f8aebSAndroid Build Coastguard Worker 		res = snprintf(buf, rem, "[%s] ", log_level(pri));
186*bd1f8aebSAndroid Build Coastguard Worker 		if (res >= rem)
187*bd1f8aebSAndroid Build Coastguard Worker 			continue;
188*bd1f8aebSAndroid Build Coastguard Worker 		rem -= res;
189*bd1f8aebSAndroid Build Coastguard Worker 
190*bd1f8aebSAndroid Build Coastguard Worker 		res = vsnprintf(buf + res, rem, fmt, ap);
191*bd1f8aebSAndroid Build Coastguard Worker 
192*bd1f8aebSAndroid Build Coastguard Worker 		if (res >= rem)
193*bd1f8aebSAndroid Build Coastguard Worker 			continue;
194*bd1f8aebSAndroid Build Coastguard Worker 		break;
195*bd1f8aebSAndroid Build Coastguard Worker 	}
196*bd1f8aebSAndroid Build Coastguard Worker 
197*bd1f8aebSAndroid Build Coastguard Worker 	if (buf) {
198*bd1f8aebSAndroid Build Coastguard Worker 		fputs(buf, stderr);
199*bd1f8aebSAndroid Build Coastguard Worker 		free(buf != ebuf ? buf : NULL);
200*bd1f8aebSAndroid Build Coastguard Worker 	}
201*bd1f8aebSAndroid Build Coastguard Worker 
202*bd1f8aebSAndroid Build Coastguard Worker 	va_end(ap);
203*bd1f8aebSAndroid Build Coastguard Worker }
204*bd1f8aebSAndroid Build Coastguard Worker #endif
205*bd1f8aebSAndroid Build Coastguard Worker 
206*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
open_sock(void)207*bd1f8aebSAndroid Build Coastguard Worker static int __inline__ open_sock(void)
208*bd1f8aebSAndroid Build Coastguard Worker {
209*bd1f8aebSAndroid Build Coastguard Worker 	return socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
210*bd1f8aebSAndroid Build Coastguard Worker }
211*bd1f8aebSAndroid Build Coastguard Worker 
set_recvpktinfo(int sock)212*bd1f8aebSAndroid Build Coastguard Worker static int set_recvpktinfo(int sock)
213*bd1f8aebSAndroid Build Coastguard Worker {
214*bd1f8aebSAndroid Build Coastguard Worker 	int on, ret;
215*bd1f8aebSAndroid Build Coastguard Worker 
216*bd1f8aebSAndroid Build Coastguard Worker 	on = 1;
217*bd1f8aebSAndroid Build Coastguard Worker 
218*bd1f8aebSAndroid Build Coastguard Worker #if defined(IPV6_RECVPKTINFO)
219*bd1f8aebSAndroid Build Coastguard Worker 	ret = setsockopt(sock,
220*bd1f8aebSAndroid Build Coastguard Worker 			 IPPROTO_IPV6, IPV6_RECVPKTINFO,
221*bd1f8aebSAndroid Build Coastguard Worker 			 &on, sizeof(on));
222*bd1f8aebSAndroid Build Coastguard Worker 	if (!ret)
223*bd1f8aebSAndroid Build Coastguard Worker 		return 0;
224*bd1f8aebSAndroid Build Coastguard Worker # if defined(IPV6_2292PKTINFO)
225*bd1f8aebSAndroid Build Coastguard Worker 	ret = setsockopt(sock,
226*bd1f8aebSAndroid Build Coastguard Worker 			 IPPROTO_IPV6, IPV6_2292PKTINFO,
227*bd1f8aebSAndroid Build Coastguard Worker 			 &on, sizeof(on));
228*bd1f8aebSAndroid Build Coastguard Worker 	if (!ret) {
229*bd1f8aebSAndroid Build Coastguard Worker 		ipv6_pktinfo = IPV6_2292PKTINFO;
230*bd1f8aebSAndroid Build Coastguard Worker 		return 0;
231*bd1f8aebSAndroid Build Coastguard Worker 	}
232*bd1f8aebSAndroid Build Coastguard Worker 
233*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO/IPV6_2292PKTINFO): %s\n",
234*bd1f8aebSAndroid Build Coastguard Worker 	      strerror(errno));
235*bd1f8aebSAndroid Build Coastguard Worker # else
236*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO): %s\n",
237*bd1f8aebSAndroid Build Coastguard Worker 	      strerror(errno));
238*bd1f8aebSAndroid Build Coastguard Worker # endif
239*bd1f8aebSAndroid Build Coastguard Worker #else
240*bd1f8aebSAndroid Build Coastguard Worker 	ret = setsockopt(sock,
241*bd1f8aebSAndroid Build Coastguard Worker 			 IPPROTO_IPV6, IPV6_PKTINFO,
242*bd1f8aebSAndroid Build Coastguard Worker 			 &on, sizeof(on));
243*bd1f8aebSAndroid Build Coastguard Worker 	if (!ret)
244*bd1f8aebSAndroid Build Coastguard Worker 		return 0;
245*bd1f8aebSAndroid Build Coastguard Worker 
246*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_ERR, "setsockopt(IPV6_PKTINFO): %s\n",
247*bd1f8aebSAndroid Build Coastguard Worker 	      strerror(errno));
248*bd1f8aebSAndroid Build Coastguard Worker #endif
249*bd1f8aebSAndroid Build Coastguard Worker 
250*bd1f8aebSAndroid Build Coastguard Worker 	return -1;
251*bd1f8aebSAndroid Build Coastguard Worker }
252*bd1f8aebSAndroid Build Coastguard Worker 
init_sock(int sock)253*bd1f8aebSAndroid Build Coastguard Worker static int __inline__ init_sock(int sock)
254*bd1f8aebSAndroid Build Coastguard Worker {
255*bd1f8aebSAndroid Build Coastguard Worker 	struct icmp6_filter filter;
256*bd1f8aebSAndroid Build Coastguard Worker #if NEED_IPV6CHECKSUM
257*bd1f8aebSAndroid Build Coastguard Worker 	int i;
258*bd1f8aebSAndroid Build Coastguard Worker 
259*bd1f8aebSAndroid Build Coastguard Worker 	i = offsetof(struct icmp6_nodeinfo, ni_cksum);
260*bd1f8aebSAndroid Build Coastguard Worker 	if (setsockopt(sock,
261*bd1f8aebSAndroid Build Coastguard Worker 		       IPPROTO_IPV6, IPV6_CHECKSUM,
262*bd1f8aebSAndroid Build Coastguard Worker 		       &i, sizeof(i)) < 0) {
263*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "setsockopt(IPV6_CHECKSUM): %s\n",
264*bd1f8aebSAndroid Build Coastguard Worker 		      strerror(errno));
265*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
266*bd1f8aebSAndroid Build Coastguard Worker 	}
267*bd1f8aebSAndroid Build Coastguard Worker #endif
268*bd1f8aebSAndroid Build Coastguard Worker 
269*bd1f8aebSAndroid Build Coastguard Worker 	ICMP6_FILTER_SETBLOCKALL(&filter);
270*bd1f8aebSAndroid Build Coastguard Worker 	ICMP6_FILTER_SETPASS(ICMP6_NI_QUERY, &filter);
271*bd1f8aebSAndroid Build Coastguard Worker 	if (setsockopt(sock,
272*bd1f8aebSAndroid Build Coastguard Worker 		       IPPROTO_ICMPV6, ICMP6_FILTER,
273*bd1f8aebSAndroid Build Coastguard Worker 		       &filter, sizeof(filter)) < 0) {
274*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "setsockopt(ICMP6_FILTER): %s\n",
275*bd1f8aebSAndroid Build Coastguard Worker 		      strerror(errno));
276*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
277*bd1f8aebSAndroid Build Coastguard Worker 	}
278*bd1f8aebSAndroid Build Coastguard Worker 
279*bd1f8aebSAndroid Build Coastguard Worker 	if (set_recvpktinfo(sock) < 0)
280*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
281*bd1f8aebSAndroid Build Coastguard Worker 
282*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
283*bd1f8aebSAndroid Build Coastguard Worker }
284*bd1f8aebSAndroid Build Coastguard Worker 
285*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
ni_recv(struct packetcontext * p)286*bd1f8aebSAndroid Build Coastguard Worker int ni_recv(struct packetcontext *p)
287*bd1f8aebSAndroid Build Coastguard Worker {
288*bd1f8aebSAndroid Build Coastguard Worker 	int sock = p->sock;
289*bd1f8aebSAndroid Build Coastguard Worker 	struct iovec iov[1];
290*bd1f8aebSAndroid Build Coastguard Worker 	struct msghdr msgh;
291*bd1f8aebSAndroid Build Coastguard Worker 	char recvcbuf[CMSG_SPACE(sizeof(p->pktinfo))];
292*bd1f8aebSAndroid Build Coastguard Worker 	struct cmsghdr *cmsg;
293*bd1f8aebSAndroid Build Coastguard Worker 	int cc;
294*bd1f8aebSAndroid Build Coastguard Worker 
295*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
296*bd1f8aebSAndroid Build Coastguard Worker 
297*bd1f8aebSAndroid Build Coastguard Worker 	memset(&iov, 0, sizeof(iov));
298*bd1f8aebSAndroid Build Coastguard Worker 	iov[0].iov_base = p->query;
299*bd1f8aebSAndroid Build Coastguard Worker 	iov[0].iov_len = sizeof(p->query);
300*bd1f8aebSAndroid Build Coastguard Worker 
301*bd1f8aebSAndroid Build Coastguard Worker 	memset(&msgh, 0, sizeof(msgh));
302*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_name = (struct sockaddr *)&p->addr;
303*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_namelen = sizeof(p->addr);
304*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_iov = iov;
305*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_iovlen = 1;
306*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_control = recvcbuf;
307*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_controllen = sizeof(recvcbuf);
308*bd1f8aebSAndroid Build Coastguard Worker 
309*bd1f8aebSAndroid Build Coastguard Worker 	if ((cc = recvmsg(sock, &msgh, 0)) < 0)
310*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
311*bd1f8aebSAndroid Build Coastguard Worker 
312*bd1f8aebSAndroid Build Coastguard Worker 	p->querylen = cc;
313*bd1f8aebSAndroid Build Coastguard Worker 	p->addrlen = msgh.msg_namelen;
314*bd1f8aebSAndroid Build Coastguard Worker 
315*bd1f8aebSAndroid Build Coastguard Worker 	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg;
316*bd1f8aebSAndroid Build Coastguard Worker 	     cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
317*bd1f8aebSAndroid Build Coastguard Worker 		if (cmsg->cmsg_level == IPPROTO_IPV6 &&
318*bd1f8aebSAndroid Build Coastguard Worker 		    (cmsg->cmsg_type == IPV6_PKTINFO
319*bd1f8aebSAndroid Build Coastguard Worker #if defined(IPV6_2292PKTINFO)
320*bd1f8aebSAndroid Build Coastguard Worker 		     || cmsg->cmsg_type == IPV6_2292PKTINFO
321*bd1f8aebSAndroid Build Coastguard Worker #endif
322*bd1f8aebSAndroid Build Coastguard Worker 		    )) {
323*bd1f8aebSAndroid Build Coastguard Worker 			memcpy(&p->pktinfo, CMSG_DATA(cmsg), sizeof(p->pktinfo));
324*bd1f8aebSAndroid Build Coastguard Worker 			break;
325*bd1f8aebSAndroid Build Coastguard Worker 		}
326*bd1f8aebSAndroid Build Coastguard Worker 	}
327*bd1f8aebSAndroid Build Coastguard Worker 
328*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
329*bd1f8aebSAndroid Build Coastguard Worker }
330*bd1f8aebSAndroid Build Coastguard Worker 
ni_send(struct packetcontext * p)331*bd1f8aebSAndroid Build Coastguard Worker int ni_send(struct packetcontext *p)
332*bd1f8aebSAndroid Build Coastguard Worker {
333*bd1f8aebSAndroid Build Coastguard Worker 	int sock = p->sock;
334*bd1f8aebSAndroid Build Coastguard Worker 	struct iovec iov[2];
335*bd1f8aebSAndroid Build Coastguard Worker 	char cbuf[CMSG_SPACE(sizeof(p->pktinfo))];
336*bd1f8aebSAndroid Build Coastguard Worker 	struct msghdr msgh;
337*bd1f8aebSAndroid Build Coastguard Worker 	struct cmsghdr *cmsg;
338*bd1f8aebSAndroid Build Coastguard Worker 	int cc;
339*bd1f8aebSAndroid Build Coastguard Worker 
340*bd1f8aebSAndroid Build Coastguard Worker 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
341*bd1f8aebSAndroid Build Coastguard Worker 
342*bd1f8aebSAndroid Build Coastguard Worker 	memset(&iov, 0, sizeof(iov));
343*bd1f8aebSAndroid Build Coastguard Worker 	iov[0].iov_base = &p->reply;
344*bd1f8aebSAndroid Build Coastguard Worker 	iov[0].iov_len = sizeof(p->reply);
345*bd1f8aebSAndroid Build Coastguard Worker 	iov[1].iov_base = p->replydata;
346*bd1f8aebSAndroid Build Coastguard Worker 	iov[1].iov_len = p->replydatalen;
347*bd1f8aebSAndroid Build Coastguard Worker 
348*bd1f8aebSAndroid Build Coastguard Worker 	memset(&msgh, 0, sizeof(msgh));
349*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_name = (struct sockaddr *)&p->addr;
350*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_namelen = p->addrlen;
351*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_iov = iov;
352*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_iovlen = p->replydata ? 2 : 1;
353*bd1f8aebSAndroid Build Coastguard Worker 
354*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_control = cbuf;
355*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_controllen = sizeof(cbuf);
356*bd1f8aebSAndroid Build Coastguard Worker 
357*bd1f8aebSAndroid Build Coastguard Worker 	cmsg = CMSG_FIRSTHDR(&msgh);
358*bd1f8aebSAndroid Build Coastguard Worker 	cmsg->cmsg_level = IPPROTO_IPV6;
359*bd1f8aebSAndroid Build Coastguard Worker 	cmsg->cmsg_type = ipv6_pktinfo;
360*bd1f8aebSAndroid Build Coastguard Worker 	cmsg->cmsg_len = CMSG_LEN(sizeof(p->pktinfo));
361*bd1f8aebSAndroid Build Coastguard Worker 	memcpy(CMSG_DATA(cmsg), &p->pktinfo, sizeof(p->pktinfo));
362*bd1f8aebSAndroid Build Coastguard Worker 
363*bd1f8aebSAndroid Build Coastguard Worker 	msgh.msg_controllen = cmsg->cmsg_len;
364*bd1f8aebSAndroid Build Coastguard Worker 
365*bd1f8aebSAndroid Build Coastguard Worker 	if (p->delay) {
366*bd1f8aebSAndroid Build Coastguard Worker #if HAVE_NANOSLEEP
367*bd1f8aebSAndroid Build Coastguard Worker 		struct timespec ts, rts;
368*bd1f8aebSAndroid Build Coastguard Worker 		int err = 0;
369*bd1f8aebSAndroid Build Coastguard Worker 
370*bd1f8aebSAndroid Build Coastguard Worker 		rts.tv_sec  = p->delay / 1000000;
371*bd1f8aebSAndroid Build Coastguard Worker 		rts.tv_nsec = (long)(p->delay % 1000000) * 1000;
372*bd1f8aebSAndroid Build Coastguard Worker 
373*bd1f8aebSAndroid Build Coastguard Worker 		do {
374*bd1f8aebSAndroid Build Coastguard Worker 			ts = rts;
375*bd1f8aebSAndroid Build Coastguard Worker 			err = nanosleep(&ts, &rts);
376*bd1f8aebSAndroid Build Coastguard Worker 		} while(err < 0);
377*bd1f8aebSAndroid Build Coastguard Worker #else
378*bd1f8aebSAndroid Build Coastguard Worker 		usleep(p->delay);	/*XXX: signal*/
379*bd1f8aebSAndroid Build Coastguard Worker #endif
380*bd1f8aebSAndroid Build Coastguard Worker 	}
381*bd1f8aebSAndroid Build Coastguard Worker 
382*bd1f8aebSAndroid Build Coastguard Worker 	cc = sendmsg(sock, &msgh, 0);
383*bd1f8aebSAndroid Build Coastguard Worker 	if (cc < 0)
384*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_DEBUG, "sendmsg(): %s\n", strerror(errno));
385*bd1f8aebSAndroid Build Coastguard Worker 
386*bd1f8aebSAndroid Build Coastguard Worker 	ni_free(p->replydata);
387*bd1f8aebSAndroid Build Coastguard Worker 	ni_free(p);
388*bd1f8aebSAndroid Build Coastguard Worker 
389*bd1f8aebSAndroid Build Coastguard Worker 	return cc;
390*bd1f8aebSAndroid Build Coastguard Worker }
391*bd1f8aebSAndroid Build Coastguard Worker 
392*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
sig_handler(int sig)393*bd1f8aebSAndroid Build Coastguard Worker static void sig_handler(int sig)
394*bd1f8aebSAndroid Build Coastguard Worker {
395*bd1f8aebSAndroid Build Coastguard Worker 	if (!got_signal)
396*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_INFO, "singnal(%d) received, quitting.\n", sig);
397*bd1f8aebSAndroid Build Coastguard Worker 	got_signal = 1;
398*bd1f8aebSAndroid Build Coastguard Worker }
399*bd1f8aebSAndroid Build Coastguard Worker 
setup_sighandlers(void)400*bd1f8aebSAndroid Build Coastguard Worker static void setup_sighandlers(void)
401*bd1f8aebSAndroid Build Coastguard Worker {
402*bd1f8aebSAndroid Build Coastguard Worker 	struct sigaction act;
403*bd1f8aebSAndroid Build Coastguard Worker 	sigset_t smask;
404*bd1f8aebSAndroid Build Coastguard Worker 	sigemptyset(&smask);
405*bd1f8aebSAndroid Build Coastguard Worker 	sigaddset(&smask, SIGHUP);
406*bd1f8aebSAndroid Build Coastguard Worker 	sigaddset(&smask, SIGINT);
407*bd1f8aebSAndroid Build Coastguard Worker 	sigaddset(&smask, SIGQUIT);
408*bd1f8aebSAndroid Build Coastguard Worker 	sigaddset(&smask, SIGTERM);
409*bd1f8aebSAndroid Build Coastguard Worker 
410*bd1f8aebSAndroid Build Coastguard Worker 	memset(&act, 0, sizeof(act));
411*bd1f8aebSAndroid Build Coastguard Worker 	act.sa_handler = sig_handler;
412*bd1f8aebSAndroid Build Coastguard Worker 	act.sa_mask = smask;
413*bd1f8aebSAndroid Build Coastguard Worker 
414*bd1f8aebSAndroid Build Coastguard Worker 	sigaction(SIGHUP, &act, NULL);
415*bd1f8aebSAndroid Build Coastguard Worker 	sigaction(SIGINT, &act, NULL);
416*bd1f8aebSAndroid Build Coastguard Worker 	sigaction(SIGQUIT, &act, NULL);
417*bd1f8aebSAndroid Build Coastguard Worker 	sigaction(SIGTERM, &act, NULL);
418*bd1f8aebSAndroid Build Coastguard Worker }
419*bd1f8aebSAndroid Build Coastguard Worker 
set_logfile(void)420*bd1f8aebSAndroid Build Coastguard Worker static void set_logfile(void)
421*bd1f8aebSAndroid Build Coastguard Worker {
422*bd1f8aebSAndroid Build Coastguard Worker 	setbuf(stderr, NULL);
423*bd1f8aebSAndroid Build Coastguard Worker #if ENABLE_DEBUG
424*bd1f8aebSAndroid Build Coastguard Worker 	openlog(NINFOD, 0, LOG_USER);
425*bd1f8aebSAndroid Build Coastguard Worker #endif
426*bd1f8aebSAndroid Build Coastguard Worker }
427*bd1f8aebSAndroid Build Coastguard Worker 
cleanup_pidfile(void)428*bd1f8aebSAndroid Build Coastguard Worker static void cleanup_pidfile(void)
429*bd1f8aebSAndroid Build Coastguard Worker {
430*bd1f8aebSAndroid Build Coastguard Worker 	int err;
431*bd1f8aebSAndroid Build Coastguard Worker 
432*bd1f8aebSAndroid Build Coastguard Worker 	if (daemonized && opt_p) {
433*bd1f8aebSAndroid Build Coastguard Worker 		err = unlink(opt_p);
434*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "failed to unlink file '%s' : %s\n",
435*bd1f8aebSAndroid Build Coastguard Worker 				opt_p, strerror(errno));
436*bd1f8aebSAndroid Build Coastguard Worker 	}
437*bd1f8aebSAndroid Build Coastguard Worker }
438*bd1f8aebSAndroid Build Coastguard Worker 
fopen_excl(const char * file)439*bd1f8aebSAndroid Build Coastguard Worker static FILE *fopen_excl(const char *file)
440*bd1f8aebSAndroid Build Coastguard Worker {
441*bd1f8aebSAndroid Build Coastguard Worker #ifndef __linux__
442*bd1f8aebSAndroid Build Coastguard Worker 	int fd;
443*bd1f8aebSAndroid Build Coastguard Worker 	FILE *fp;
444*bd1f8aebSAndroid Build Coastguard Worker 
445*bd1f8aebSAndroid Build Coastguard Worker 	fd = open(file, O_CREAT | O_RDWR | O_EXCL,
446*bd1f8aebSAndroid Build Coastguard Worker 		  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
447*bd1f8aebSAndroid Build Coastguard Worker 	if (fd < 0)
448*bd1f8aebSAndroid Build Coastguard Worker 		return NULL;
449*bd1f8aebSAndroid Build Coastguard Worker 
450*bd1f8aebSAndroid Build Coastguard Worker 	return fdopen(file, "w+");
451*bd1f8aebSAndroid Build Coastguard Worker #else
452*bd1f8aebSAndroid Build Coastguard Worker 	return fopen(file, "w+x");
453*bd1f8aebSAndroid Build Coastguard Worker #endif
454*bd1f8aebSAndroid Build Coastguard Worker }
455*bd1f8aebSAndroid Build Coastguard Worker 
do_daemonize(void)456*bd1f8aebSAndroid Build Coastguard Worker static void do_daemonize(void)
457*bd1f8aebSAndroid Build Coastguard Worker {
458*bd1f8aebSAndroid Build Coastguard Worker 	FILE *fp = NULL;
459*bd1f8aebSAndroid Build Coastguard Worker 	pid_t pid;
460*bd1f8aebSAndroid Build Coastguard Worker 
461*bd1f8aebSAndroid Build Coastguard Worker 	if (opt_p) {
462*bd1f8aebSAndroid Build Coastguard Worker 		if (!access(opt_p, R_OK)) {
463*bd1f8aebSAndroid Build Coastguard Worker 			if ((fp = fopen(opt_p, "r"))) {
464*bd1f8aebSAndroid Build Coastguard Worker 				if (fscanf(fp, "%d", &pid) != 1) {
465*bd1f8aebSAndroid Build Coastguard Worker 					DEBUG(LOG_ERR, "pid file '%s' exists, but read failed.\n",
466*bd1f8aebSAndroid Build Coastguard Worker 					      opt_p);
467*bd1f8aebSAndroid Build Coastguard Worker 				} else {
468*bd1f8aebSAndroid Build Coastguard Worker 					DEBUG(LOG_ERR, "pid file '%s' exists : %d\n",
469*bd1f8aebSAndroid Build Coastguard Worker 					      opt_p, pid);
470*bd1f8aebSAndroid Build Coastguard Worker 				}
471*bd1f8aebSAndroid Build Coastguard Worker 				fclose(fp);
472*bd1f8aebSAndroid Build Coastguard Worker 				exit(1);
473*bd1f8aebSAndroid Build Coastguard Worker 			}
474*bd1f8aebSAndroid Build Coastguard Worker 		}
475*bd1f8aebSAndroid Build Coastguard Worker 
476*bd1f8aebSAndroid Build Coastguard Worker 		fp = fopen_excl(opt_p);
477*bd1f8aebSAndroid Build Coastguard Worker 		if (!fp) {
478*bd1f8aebSAndroid Build Coastguard Worker 			DEBUG(LOG_ERR, "failed to open file '%s': %s\n",
479*bd1f8aebSAndroid Build Coastguard Worker 			      opt_p, strerror(errno));
480*bd1f8aebSAndroid Build Coastguard Worker 			exit(1);
481*bd1f8aebSAndroid Build Coastguard Worker 		}
482*bd1f8aebSAndroid Build Coastguard Worker 	}
483*bd1f8aebSAndroid Build Coastguard Worker 
484*bd1f8aebSAndroid Build Coastguard Worker 	if (daemon(0, 0) < 0) {
485*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "failed to daemon(): %s\n", strerror(errno));
486*bd1f8aebSAndroid Build Coastguard Worker 		unlink(opt_p);
487*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
488*bd1f8aebSAndroid Build Coastguard Worker 	}
489*bd1f8aebSAndroid Build Coastguard Worker 	daemonized = 1;
490*bd1f8aebSAndroid Build Coastguard Worker 
491*bd1f8aebSAndroid Build Coastguard Worker 	if (fp) {
492*bd1f8aebSAndroid Build Coastguard Worker 		fprintf(fp, "%d\n", getpid());
493*bd1f8aebSAndroid Build Coastguard Worker 		fclose(fp);
494*bd1f8aebSAndroid Build Coastguard Worker 	}
495*bd1f8aebSAndroid Build Coastguard Worker }
496*bd1f8aebSAndroid Build Coastguard Worker 
497*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
498*bd1f8aebSAndroid Build Coastguard Worker #ifdef HAVE_LIBCAP
499*bd1f8aebSAndroid Build Coastguard Worker static const cap_value_t cap_net_raw = CAP_NET_RAW;
500*bd1f8aebSAndroid Build Coastguard Worker static const cap_value_t cap_setuid =  CAP_SETUID;
501*bd1f8aebSAndroid Build Coastguard Worker static cap_flag_value_t cap_ok;
502*bd1f8aebSAndroid Build Coastguard Worker #else
503*bd1f8aebSAndroid Build Coastguard Worker static uid_t euid;
504*bd1f8aebSAndroid Build Coastguard Worker #endif
505*bd1f8aebSAndroid Build Coastguard Worker 
limit_capabilities(void)506*bd1f8aebSAndroid Build Coastguard Worker static void limit_capabilities(void)
507*bd1f8aebSAndroid Build Coastguard Worker {
508*bd1f8aebSAndroid Build Coastguard Worker #ifdef HAVE_LIBCAP
509*bd1f8aebSAndroid Build Coastguard Worker 	cap_t cap_p, cap_cur_p;
510*bd1f8aebSAndroid Build Coastguard Worker 
511*bd1f8aebSAndroid Build Coastguard Worker 	cap_p = cap_init();
512*bd1f8aebSAndroid Build Coastguard Worker 	if (!cap_p) {
513*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "cap_init: %s\n", strerror(errno));
514*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
515*bd1f8aebSAndroid Build Coastguard Worker 	}
516*bd1f8aebSAndroid Build Coastguard Worker 
517*bd1f8aebSAndroid Build Coastguard Worker 	cap_cur_p = cap_get_proc();
518*bd1f8aebSAndroid Build Coastguard Worker 	if (!cap_cur_p) {
519*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "cap_get_proc: %s\n", strerror(errno));
520*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
521*bd1f8aebSAndroid Build Coastguard Worker         }
522*bd1f8aebSAndroid Build Coastguard Worker 
523*bd1f8aebSAndroid Build Coastguard Worker 	/* net_raw + setuid / net_raw */
524*bd1f8aebSAndroid Build Coastguard Worker 	cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok);
525*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_ok != CAP_CLEAR) {
526*bd1f8aebSAndroid Build Coastguard Worker 		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_net_raw, CAP_SET);
527*bd1f8aebSAndroid Build Coastguard Worker 		cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap_net_raw, CAP_SET);
528*bd1f8aebSAndroid Build Coastguard Worker 	}
529*bd1f8aebSAndroid Build Coastguard Worker 
530*bd1f8aebSAndroid Build Coastguard Worker 	cap_get_flag(cap_cur_p, CAP_SETUID, CAP_PERMITTED, &cap_ok);
531*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_ok != CAP_CLEAR)
532*bd1f8aebSAndroid Build Coastguard Worker 		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_setuid, CAP_SET);
533*bd1f8aebSAndroid Build Coastguard Worker 
534*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_set_proc(cap_p) < 0) {
535*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "cap_set_proc: %s\n", strerror(errno));
536*bd1f8aebSAndroid Build Coastguard Worker 		if (errno != EPERM)
537*bd1f8aebSAndroid Build Coastguard Worker 			exit(-1);
538*bd1f8aebSAndroid Build Coastguard Worker 	}
539*bd1f8aebSAndroid Build Coastguard Worker 
540*bd1f8aebSAndroid Build Coastguard Worker 	if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
541*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "prctl: %s\n", strerror(errno));
542*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
543*bd1f8aebSAndroid Build Coastguard Worker 	}
544*bd1f8aebSAndroid Build Coastguard Worker 
545*bd1f8aebSAndroid Build Coastguard Worker 	cap_free(cap_cur_p);
546*bd1f8aebSAndroid Build Coastguard Worker 	cap_free(cap_p);
547*bd1f8aebSAndroid Build Coastguard Worker #else
548*bd1f8aebSAndroid Build Coastguard Worker 	euid = geteuid();
549*bd1f8aebSAndroid Build Coastguard Worker #endif
550*bd1f8aebSAndroid Build Coastguard Worker }
551*bd1f8aebSAndroid Build Coastguard Worker 
drop_capabilities(void)552*bd1f8aebSAndroid Build Coastguard Worker static void drop_capabilities(void)
553*bd1f8aebSAndroid Build Coastguard Worker {
554*bd1f8aebSAndroid Build Coastguard Worker #ifdef HAVE_LIBCAP
555*bd1f8aebSAndroid Build Coastguard Worker 	cap_t cap_p;
556*bd1f8aebSAndroid Build Coastguard Worker 
557*bd1f8aebSAndroid Build Coastguard Worker 	cap_p = cap_init();
558*bd1f8aebSAndroid Build Coastguard Worker 	if (!cap_p) {
559*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "cap_init: %s\n", strerror(errno));
560*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
561*bd1f8aebSAndroid Build Coastguard Worker 	}
562*bd1f8aebSAndroid Build Coastguard Worker 
563*bd1f8aebSAndroid Build Coastguard Worker 	/* setuid / setuid */
564*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_ok != CAP_CLEAR) {
565*bd1f8aebSAndroid Build Coastguard Worker 		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_setuid, CAP_SET);
566*bd1f8aebSAndroid Build Coastguard Worker 		cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap_setuid, CAP_SET);
567*bd1f8aebSAndroid Build Coastguard Worker 
568*bd1f8aebSAndroid Build Coastguard Worker 		if (cap_set_proc(cap_p) < 0) {
569*bd1f8aebSAndroid Build Coastguard Worker 			DEBUG(LOG_ERR, "cap_set_proc: %s\n", strerror(errno));
570*bd1f8aebSAndroid Build Coastguard Worker 			exit(-1);
571*bd1f8aebSAndroid Build Coastguard Worker 		}
572*bd1f8aebSAndroid Build Coastguard Worker 	}
573*bd1f8aebSAndroid Build Coastguard Worker 
574*bd1f8aebSAndroid Build Coastguard Worker 	if (seteuid(opt_u ? opt_u : getuid()) < 0) {
575*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "setuid: %s\n", strerror(errno));
576*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
577*bd1f8aebSAndroid Build Coastguard Worker 	}
578*bd1f8aebSAndroid Build Coastguard Worker 
579*bd1f8aebSAndroid Build Coastguard Worker 	if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
580*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "prctl: %s\n", strerror(errno));
581*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
582*bd1f8aebSAndroid Build Coastguard Worker 	}
583*bd1f8aebSAndroid Build Coastguard Worker 
584*bd1f8aebSAndroid Build Coastguard Worker 	cap_clear(cap_p);
585*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_set_proc(cap_p) < 0) {
586*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "cap_set_proc: %s\n", strerror(errno));
587*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
588*bd1f8aebSAndroid Build Coastguard Worker 	}
589*bd1f8aebSAndroid Build Coastguard Worker 
590*bd1f8aebSAndroid Build Coastguard Worker 	cap_free(cap_p);
591*bd1f8aebSAndroid Build Coastguard Worker #else
592*bd1f8aebSAndroid Build Coastguard Worker 	if (setuid(getuid()) < 0) {
593*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "setuid: %s\n", strerror(errno));
594*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
595*bd1f8aebSAndroid Build Coastguard Worker 	}
596*bd1f8aebSAndroid Build Coastguard Worker #endif
597*bd1f8aebSAndroid Build Coastguard Worker }
598*bd1f8aebSAndroid Build Coastguard Worker 
599*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
parse_args(int argc,char ** argv)600*bd1f8aebSAndroid Build Coastguard Worker static void parse_args(int argc, char **argv)
601*bd1f8aebSAndroid Build Coastguard Worker {
602*bd1f8aebSAndroid Build Coastguard Worker 	int c;
603*bd1f8aebSAndroid Build Coastguard Worker 	unsigned long val;
604*bd1f8aebSAndroid Build Coastguard Worker 	char *ep;
605*bd1f8aebSAndroid Build Coastguard Worker 
606*bd1f8aebSAndroid Build Coastguard Worker 	/* parse options */
607*bd1f8aebSAndroid Build Coastguard Worker 	while ((c = getopt(argc, argv, "dhvp:u:")) != -1) {
608*bd1f8aebSAndroid Build Coastguard Worker 		switch(c) {
609*bd1f8aebSAndroid Build Coastguard Worker 		case 'd':	/* debug */
610*bd1f8aebSAndroid Build Coastguard Worker 			opt_d = 1;
611*bd1f8aebSAndroid Build Coastguard Worker 			break;
612*bd1f8aebSAndroid Build Coastguard Worker 		case 'v':	/* verbose */
613*bd1f8aebSAndroid Build Coastguard Worker 			opt_v = 1;
614*bd1f8aebSAndroid Build Coastguard Worker 			break;
615*bd1f8aebSAndroid Build Coastguard Worker 		case 'p':
616*bd1f8aebSAndroid Build Coastguard Worker 			opt_p = optarg;
617*bd1f8aebSAndroid Build Coastguard Worker 			break;
618*bd1f8aebSAndroid Build Coastguard Worker 		case 'u':
619*bd1f8aebSAndroid Build Coastguard Worker 			val = strtoul(optarg, &ep, 10);
620*bd1f8aebSAndroid Build Coastguard Worker 			if (!optarg || *ep) {
621*bd1f8aebSAndroid Build Coastguard Worker 				struct passwd *pw = getpwnam(optarg);
622*bd1f8aebSAndroid Build Coastguard Worker 				if (!pw) {
623*bd1f8aebSAndroid Build Coastguard Worker 					DEBUG(LOG_ERR, "No such user: %s", optarg);
624*bd1f8aebSAndroid Build Coastguard Worker 					exit(1);
625*bd1f8aebSAndroid Build Coastguard Worker 				}
626*bd1f8aebSAndroid Build Coastguard Worker 				opt_u = pw->pw_uid;
627*bd1f8aebSAndroid Build Coastguard Worker 			} else
628*bd1f8aebSAndroid Build Coastguard Worker 				opt_u = val;
629*bd1f8aebSAndroid Build Coastguard Worker 			break;
630*bd1f8aebSAndroid Build Coastguard Worker 		case 'h':	/* help */
631*bd1f8aebSAndroid Build Coastguard Worker 		default:
632*bd1f8aebSAndroid Build Coastguard Worker 			opt_h = 1;
633*bd1f8aebSAndroid Build Coastguard Worker 			break;
634*bd1f8aebSAndroid Build Coastguard Worker 		}
635*bd1f8aebSAndroid Build Coastguard Worker 	}
636*bd1f8aebSAndroid Build Coastguard Worker 
637*bd1f8aebSAndroid Build Coastguard Worker 	argc -= optind;
638*bd1f8aebSAndroid Build Coastguard Worker #if 0
639*bd1f8aebSAndroid Build Coastguard Worker 	argv += optind;
640*bd1f8aebSAndroid Build Coastguard Worker #endif
641*bd1f8aebSAndroid Build Coastguard Worker 
642*bd1f8aebSAndroid Build Coastguard Worker 	if (argc)
643*bd1f8aebSAndroid Build Coastguard Worker 		opt_h = 1;
644*bd1f8aebSAndroid Build Coastguard Worker }
645*bd1f8aebSAndroid Build Coastguard Worker 
print_copying(void)646*bd1f8aebSAndroid Build Coastguard Worker static void print_copying(void) {
647*bd1f8aebSAndroid Build Coastguard Worker 	fprintf(stderr,
648*bd1f8aebSAndroid Build Coastguard Worker 		"Node Information Daemon\n"
649*bd1f8aebSAndroid Build Coastguard Worker 		"Copyright (C)2002 USAGI/WIDE Project.  All Rights Reserved.\n"
650*bd1f8aebSAndroid Build Coastguard Worker 		"\n"
651*bd1f8aebSAndroid Build Coastguard Worker 	);
652*bd1f8aebSAndroid Build Coastguard Worker }
653*bd1f8aebSAndroid Build Coastguard Worker 
print_usage(void)654*bd1f8aebSAndroid Build Coastguard Worker static void print_usage(void) {
655*bd1f8aebSAndroid Build Coastguard Worker 	fprintf(stderr,
656*bd1f8aebSAndroid Build Coastguard Worker 		"Usage: %s [-d] [-p pidfile] [-u user] [-h] [-v]\n\n",
657*bd1f8aebSAndroid Build Coastguard Worker 		appname
658*bd1f8aebSAndroid Build Coastguard Worker 	);
659*bd1f8aebSAndroid Build Coastguard Worker }
660*bd1f8aebSAndroid Build Coastguard Worker 
661*bd1f8aebSAndroid Build Coastguard Worker /* --------- */
main(int argc,char ** argv)662*bd1f8aebSAndroid Build Coastguard Worker int main (int argc, char **argv)
663*bd1f8aebSAndroid Build Coastguard Worker {
664*bd1f8aebSAndroid Build Coastguard Worker 	int sock_errno = 0;
665*bd1f8aebSAndroid Build Coastguard Worker 	int ret;
666*bd1f8aebSAndroid Build Coastguard Worker 
667*bd1f8aebSAndroid Build Coastguard Worker 	appname = argv[0];
668*bd1f8aebSAndroid Build Coastguard Worker 	set_logfile();
669*bd1f8aebSAndroid Build Coastguard Worker 
670*bd1f8aebSAndroid Build Coastguard Worker 	limit_capabilities();
671*bd1f8aebSAndroid Build Coastguard Worker 
672*bd1f8aebSAndroid Build Coastguard Worker 	sock = open_sock();
673*bd1f8aebSAndroid Build Coastguard Worker 	if (sock < 0)
674*bd1f8aebSAndroid Build Coastguard Worker 		sock_errno = errno;
675*bd1f8aebSAndroid Build Coastguard Worker 
676*bd1f8aebSAndroid Build Coastguard Worker 	parse_args(argc, argv);
677*bd1f8aebSAndroid Build Coastguard Worker 
678*bd1f8aebSAndroid Build Coastguard Worker 	drop_capabilities();
679*bd1f8aebSAndroid Build Coastguard Worker 
680*bd1f8aebSAndroid Build Coastguard Worker 	if (opt_h || opt_v)
681*bd1f8aebSAndroid Build Coastguard Worker 		print_copying();
682*bd1f8aebSAndroid Build Coastguard Worker 	if (opt_h) {
683*bd1f8aebSAndroid Build Coastguard Worker 		print_usage();
684*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
685*bd1f8aebSAndroid Build Coastguard Worker 	}
686*bd1f8aebSAndroid Build Coastguard Worker 
687*bd1f8aebSAndroid Build Coastguard Worker 	if (sock_errno) {
688*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_ERR, "socket: %s\n", strerror(sock_errno));
689*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
690*bd1f8aebSAndroid Build Coastguard Worker 	}
691*bd1f8aebSAndroid Build Coastguard Worker 
692*bd1f8aebSAndroid Build Coastguard Worker 	/* initialize */
693*bd1f8aebSAndroid Build Coastguard Worker 	if (init_sock(sock) < 0)
694*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
695*bd1f8aebSAndroid Build Coastguard Worker 
696*bd1f8aebSAndroid Build Coastguard Worker 	setup_sighandlers();
697*bd1f8aebSAndroid Build Coastguard Worker 	if (!opt_d)
698*bd1f8aebSAndroid Build Coastguard Worker 		do_daemonize();
699*bd1f8aebSAndroid Build Coastguard Worker 
700*bd1f8aebSAndroid Build Coastguard Worker 	init_core(1);
701*bd1f8aebSAndroid Build Coastguard Worker 
702*bd1f8aebSAndroid Build Coastguard Worker 	/* main loop */
703*bd1f8aebSAndroid Build Coastguard Worker 	while (!got_signal) {
704*bd1f8aebSAndroid Build Coastguard Worker 		struct packetcontext *p;
705*bd1f8aebSAndroid Build Coastguard Worker 		struct icmp6_hdr *icmph;
706*bd1f8aebSAndroid Build Coastguard Worker #if ENABLE_DEBUG
707*bd1f8aebSAndroid Build Coastguard Worker 		char saddrbuf[NI_MAXHOST];
708*bd1f8aebSAndroid Build Coastguard Worker 		int gni;
709*bd1f8aebSAndroid Build Coastguard Worker #endif
710*bd1f8aebSAndroid Build Coastguard Worker 
711*bd1f8aebSAndroid Build Coastguard Worker 		init_core(0);
712*bd1f8aebSAndroid Build Coastguard Worker 
713*bd1f8aebSAndroid Build Coastguard Worker 		p = ni_malloc(sizeof(*p));
714*bd1f8aebSAndroid Build Coastguard Worker 		if (!p) {
715*bd1f8aebSAndroid Build Coastguard Worker 			DEBUG(LOG_WARNING, "%s(): failed to allocate packet context; sleep 1 sec.\n",
716*bd1f8aebSAndroid Build Coastguard Worker 			      __func__);
717*bd1f8aebSAndroid Build Coastguard Worker 			sleep(1);
718*bd1f8aebSAndroid Build Coastguard Worker 			continue;
719*bd1f8aebSAndroid Build Coastguard Worker 		}
720*bd1f8aebSAndroid Build Coastguard Worker 
721*bd1f8aebSAndroid Build Coastguard Worker 		while (!got_signal) {
722*bd1f8aebSAndroid Build Coastguard Worker 			memset(p, 0, sizeof(*p));
723*bd1f8aebSAndroid Build Coastguard Worker 			p->sock = sock;
724*bd1f8aebSAndroid Build Coastguard Worker 
725*bd1f8aebSAndroid Build Coastguard Worker 			if (ni_recv(p) < 0) {
726*bd1f8aebSAndroid Build Coastguard Worker 				if (got_signal)
727*bd1f8aebSAndroid Build Coastguard Worker 					break;
728*bd1f8aebSAndroid Build Coastguard Worker 				if (errno == EAGAIN || errno == EINTR)
729*bd1f8aebSAndroid Build Coastguard Worker 					continue;
730*bd1f8aebSAndroid Build Coastguard Worker 				/* XXX: syslog */
731*bd1f8aebSAndroid Build Coastguard Worker 				continue;
732*bd1f8aebSAndroid Build Coastguard Worker 			}
733*bd1f8aebSAndroid Build Coastguard Worker 			break;
734*bd1f8aebSAndroid Build Coastguard Worker 		}
735*bd1f8aebSAndroid Build Coastguard Worker 
736*bd1f8aebSAndroid Build Coastguard Worker #if ENABLE_DEBUG
737*bd1f8aebSAndroid Build Coastguard Worker 		gni = getnameinfo((struct sockaddr *)&p->addr,
738*bd1f8aebSAndroid Build Coastguard Worker 				  p->addrlen,
739*bd1f8aebSAndroid Build Coastguard Worker 				  saddrbuf, sizeof(saddrbuf),
740*bd1f8aebSAndroid Build Coastguard Worker 				  NULL, 0,
741*bd1f8aebSAndroid Build Coastguard Worker 				  NI_NUMERICHOST);
742*bd1f8aebSAndroid Build Coastguard Worker 		if (gni)
743*bd1f8aebSAndroid Build Coastguard Worker 			sprintf(saddrbuf, "???");
744*bd1f8aebSAndroid Build Coastguard Worker #endif
745*bd1f8aebSAndroid Build Coastguard Worker 		init_core(0);
746*bd1f8aebSAndroid Build Coastguard Worker 
747*bd1f8aebSAndroid Build Coastguard Worker 		if (p->querylen < sizeof(struct icmp6_hdr)) {
748*bd1f8aebSAndroid Build Coastguard Worker 			ni_free(p);
749*bd1f8aebSAndroid Build Coastguard Worker 			DEBUG(LOG_WARNING, "Too short icmp message from %s\n", saddrbuf);
750*bd1f8aebSAndroid Build Coastguard Worker 			continue;
751*bd1f8aebSAndroid Build Coastguard Worker 		}
752*bd1f8aebSAndroid Build Coastguard Worker 
753*bd1f8aebSAndroid Build Coastguard Worker 		icmph = (struct icmp6_hdr *)p->query;
754*bd1f8aebSAndroid Build Coastguard Worker 
755*bd1f8aebSAndroid Build Coastguard Worker 		DEBUG(LOG_DEBUG,
756*bd1f8aebSAndroid Build Coastguard Worker 		      "type=%d, code=%d, cksum=0x%04x\n",
757*bd1f8aebSAndroid Build Coastguard Worker 		      icmph->icmp6_type, icmph->icmp6_code,
758*bd1f8aebSAndroid Build Coastguard Worker 		      ntohs(icmph->icmp6_cksum));
759*bd1f8aebSAndroid Build Coastguard Worker 
760*bd1f8aebSAndroid Build Coastguard Worker 		if (icmph->icmp6_type != ICMP6_NI_QUERY) {
761*bd1f8aebSAndroid Build Coastguard Worker 			DEBUG(LOG_WARNING,
762*bd1f8aebSAndroid Build Coastguard Worker 			      "Strange icmp type %d from %s\n",
763*bd1f8aebSAndroid Build Coastguard Worker 			      icmph->icmp6_type, saddrbuf);
764*bd1f8aebSAndroid Build Coastguard Worker 			ni_free(p);
765*bd1f8aebSAndroid Build Coastguard Worker 			continue;
766*bd1f8aebSAndroid Build Coastguard Worker 		}
767*bd1f8aebSAndroid Build Coastguard Worker 
768*bd1f8aebSAndroid Build Coastguard Worker 		pr_nodeinfo(p);	/* this frees p */
769*bd1f8aebSAndroid Build Coastguard Worker 	}
770*bd1f8aebSAndroid Build Coastguard Worker 
771*bd1f8aebSAndroid Build Coastguard Worker 	cleanup_pidfile();
772*bd1f8aebSAndroid Build Coastguard Worker 
773*bd1f8aebSAndroid Build Coastguard Worker 	exit(0);
774*bd1f8aebSAndroid Build Coastguard Worker }
775*bd1f8aebSAndroid Build Coastguard Worker 
776