1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* $USAGI: ninfod.c,v 1.34 2003-01-15 06:41:23 mk Exp $ */
2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Copyright (C) 2002 USAGI/WIDE Project.
4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * All rights reserved.
5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Redistribution and use in source and binary forms, with or without
7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * modification, are permitted provided that the following conditions
8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * are met:
9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 1. Redistributions of source code must retain the above copyright
10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    notice, this list of conditions and the following disclaimer.
11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 2. Redistributions in binary form must reproduce the above copyright
12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    notice, this list of conditions and the following disclaimer in the
13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    documentation and/or other materials provided with the distribution.
14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 3. Neither the name of the project nor the names of its contributors
15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    may be used to endorse or promote products derived from this software
16313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    without specific prior written permission.
17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * SUCH DAMAGE.
29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Author:
32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 	YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_CONFIG_H
36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "config.h"
37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYS_TYPES_H
40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/types.h>
41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if STDC_HEADERS
43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <stdio.h>
44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <stdlib.h>
45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <stddef.h>
46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <stdarg.h>
47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_STDLIB_H
49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <stdlib.h>
50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_STRING_H
54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if !STDC_HEADERS && HAVE_MEMORY_H
55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <memory.h>
56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <string.h>
58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_STRINGS_H
60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <strings.h>
61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_INTTYPES_H
63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <inttypes.h>
64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_STDINT_H
66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <stdint.h>
67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_LIMITS_H
70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <limits.h>
71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_UNISTD_H
73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <unistd.h>
74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef TIME_WITH_SYS_TIME
77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/time.h>
78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <time.h>
79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# ifdef HAVE_SYS_TIME_H
81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <sys/time.h>
82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# else
83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <time.h>
84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYS_UIO_H
88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/uio.h>
89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/socket.h>
92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETINET_IN_H
94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netinet/in.h>
95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETINET_ICMP6_H
98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netinet/icmp6.h>
99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef HAVE_STRUCT_ICMP6_NODEINFO
101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include "icmp6_nodeinfo.h"
102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETDB_H
105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netdb.h>
106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <errno.h>
108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <signal.h>
110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYSLOG_H
112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <syslog.h>
113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_PWD_H
116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <pwd.h>
117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYS_CAPABILITY_H
120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/prctl.h>
121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/capability.h>
122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "ninfod.h"
125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef offsetof
127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define offsetof(aggregate,member)	((size_t)&((aggregate *)0)->member)
128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ID */
132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic char *RCSID __attribute__ ((unused)) = "$USAGI: ninfod.c,v 1.34 2003-01-15 06:41:23 mk Exp $";
133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Variables */
135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint sock;
136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint daemonized;
137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *appname;
139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int opt_d = 0;	/* debug */
140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int opt_h = 0;	/* help */
141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic char *opt_p = NINFOD_PIDFILE;	/* pidfile */
142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int got_signal = 0;	/* loop unless true */
143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint opt_v = 0;		/* verbose */
144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic uid_t opt_u;
145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int ipv6_pktinfo = IPV6_PKTINFO;
147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic const __inline__ char * log_level(int priority) {
151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	switch(priority) {
152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_EMERG:		return "EMERG";
153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_ALERT:		return "ALERT";
154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_CRIT:		return "CRIT";
155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_ERR:		return "ERR";
156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_WARNING:	return "WARNING";
157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_NOTICE:	return "NOTICE";
158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_INFO:		return "INFO";
159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case LOG_DEBUG:		return "DEBUG";
160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	default:		return "???";
161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid stderrlog(int pri, char *fmt, ...)
165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	va_list ap;
167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char ebuf[512];
168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *buf;
169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	size_t buflen;
170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	va_start(ap, fmt);
172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (buf = ebuf, buflen = sizeof(ebuf);
174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	     buflen < SIZE_MAX / 2;
175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	     free(buf != ebuf ? buf : NULL), buf = NULL, buflen *= 2) {
176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		size_t rem;
177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		size_t res;
178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		buf = malloc(buflen);
180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!buf)
181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;	/*XXX*/
182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		rem = buflen;
184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		res = snprintf(buf, rem, "[%s] ", log_level(pri));
186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (res >= rem)
187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		rem -= res;
189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		res = vsnprintf(buf + res, rem, fmt, ap);
191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (res >= rem)
193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (buf) {
198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fputs(buf, stderr);
199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		free(buf != ebuf ? buf : NULL);
200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	va_end(ap);
203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int __inline__ open_sock(void)
208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int set_recvpktinfo(int sock)
213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int on, ret;
215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	on = 1;
217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if defined(IPV6_RECVPKTINFO)
219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ret = setsockopt(sock,
220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 IPPROTO_IPV6, IPV6_RECVPKTINFO,
221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 &on, sizeof(on));
222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!ret)
223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if defined(IPV6_2292PKTINFO)
225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ret = setsockopt(sock,
226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 IPPROTO_IPV6, IPV6_2292PKTINFO,
227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 &on, sizeof(on));
228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!ret) {
229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ipv6_pktinfo = IPV6_2292PKTINFO;
230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO/IPV6_2292PKTINFO): %s\n",
234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      strerror(errno));
235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# else
236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO): %s\n",
237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      strerror(errno));
238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ret = setsockopt(sock,
241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 IPPROTO_IPV6, IPV6_PKTINFO,
242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 &on, sizeof(on));
243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!ret)
244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_ERR, "setsockopt(IPV6_PKTINFO): %s\n",
247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      strerror(errno));
248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return -1;
251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int __inline__ init_sock(int sock)
254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct icmp6_filter filter;
256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if NEED_IPV6CHECKSUM
257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	i = offsetof(struct icmp6_nodeinfo, ni_cksum);
260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (setsockopt(sock,
261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       IPPROTO_IPV6, IPV6_CHECKSUM,
262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       &i, sizeof(i)) < 0) {
263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "setsockopt(IPV6_CHECKSUM): %s\n",
264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      strerror(errno));
265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ICMP6_FILTER_SETBLOCKALL(&filter);
270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ICMP6_FILTER_SETPASS(ICMP6_NI_QUERY, &filter);
271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (setsockopt(sock,
272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       IPPROTO_ICMPV6, ICMP6_FILTER,
273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       &filter, sizeof(filter)) < 0) {
274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "setsockopt(ICMP6_FILTER): %s\n",
275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      strerror(errno));
276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (set_recvpktinfo(sock) < 0)
280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint ni_recv(struct packetcontext *p)
287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int sock = p->sock;
289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iovec iov[1];
290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct msghdr msgh;
291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char recvcbuf[CMSG_SPACE(sizeof(p->pktinfo))];
292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct cmsghdr *cmsg;
293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int cc;
294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s()\n", __func__);
296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(&iov, 0, sizeof(iov));
298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iov[0].iov_base = p->query;
299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iov[0].iov_len = sizeof(p->query);
300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(&msgh, 0, sizeof(msgh));
302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_name = (struct sockaddr *)&p->addr;
303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_namelen = sizeof(p->addr);
304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_iov = iov;
305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_iovlen = 1;
306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_control = recvcbuf;
307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_controllen = sizeof(recvcbuf);
308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if ((cc = recvmsg(sock, &msgh, 0)) < 0)
310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->querylen = cc;
313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->addrlen = msgh.msg_namelen;
314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg;
316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	     cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (cmsg->cmsg_level == IPPROTO_IPV6 &&
318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		    (cmsg->cmsg_type == IPV6_PKTINFO
319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if defined(IPV6_2292PKTINFO)
320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		     || cmsg->cmsg_type == IPV6_2292PKTINFO
321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		    )) {
323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memcpy(&p->pktinfo, CMSG_DATA(cmsg), sizeof(p->pktinfo));
324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint ni_send(struct packetcontext *p)
332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int sock = p->sock;
334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iovec iov[2];
335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char cbuf[CMSG_SPACE(sizeof(p->pktinfo))];
336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct msghdr msgh;
337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct cmsghdr *cmsg;
338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int cc;
339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s()\n", __func__);
341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(&iov, 0, sizeof(iov));
343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iov[0].iov_base = &p->reply;
344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iov[0].iov_len = sizeof(p->reply);
345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iov[1].iov_base = p->replydata;
346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iov[1].iov_len = p->replydatalen;
347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(&msgh, 0, sizeof(msgh));
349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_name = (struct sockaddr *)&p->addr;
350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_namelen = p->addrlen;
351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_iov = iov;
352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_iovlen = p->replydata ? 2 : 1;
353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_control = cbuf;
355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_controllen = sizeof(cbuf);
356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cmsg = CMSG_FIRSTHDR(&msgh);
358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cmsg->cmsg_level = IPPROTO_IPV6;
359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cmsg->cmsg_type = ipv6_pktinfo;
360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cmsg->cmsg_len = CMSG_LEN(sizeof(p->pktinfo));
361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(CMSG_DATA(cmsg), &p->pktinfo, sizeof(p->pktinfo));
362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	msgh.msg_controllen = cmsg->cmsg_len;
364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (p->delay) {
366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NANOSLEEP
367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct timespec ts, rts;
368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int err = 0;
369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		rts.tv_sec  = p->delay / 1000000;
371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		rts.tv_nsec = (long)(p->delay % 1000000) * 1000;
372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		do {
374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ts = rts;
375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			err = nanosleep(&ts, &rts);
376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		} while(err < 0);
377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		usleep(p->delay);	/*XXX: signal*/
379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cc = sendmsg(sock, &msgh, 0);
383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cc < 0)
384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_DEBUG, "sendmsg(): %s\n", strerror(errno));
385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ni_free(p->replydata);
387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ni_free(p);
388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return cc;
390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void sig_handler(int sig)
394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!got_signal)
396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_INFO, "singnal(%d) received, quitting.\n", sig);
397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	got_signal = 1;
398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void setup_sighandlers(void)
401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct sigaction act;
403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigset_t smask;
404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigemptyset(&smask);
405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaddset(&smask, SIGHUP);
406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaddset(&smask, SIGINT);
407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaddset(&smask, SIGQUIT);
408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaddset(&smask, SIGTERM);
409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(&act, 0, sizeof(act));
411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	act.sa_handler = sig_handler;
412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	act.sa_mask = smask;
413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaction(SIGHUP, &act, NULL);
415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaction(SIGINT, &act, NULL);
416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaction(SIGQUIT, &act, NULL);
417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaction(SIGTERM, &act, NULL);
418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void set_logfile(void)
421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setbuf(stderr, NULL);
423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	openlog(NINFOD, 0, LOG_USER);
425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void cleanup_pidfile(void)
429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int err;
431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (daemonized && opt_p) {
433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		err = unlink(opt_p);
434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "failed to unlink file '%s' : %s\n",
435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				opt_p, strerror(errno));
436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic FILE *fopen_excl(const char *file)
440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef __linux__
442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int fd;
443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	FILE *fp;
444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fd = open(file, O_CREAT | O_RDWR | O_EXCL,
446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (fd < 0)
448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return NULL;
449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return fdopen(file, "w+");
451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return fopen(file, "w+x");
453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void do_daemonize(void)
457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	FILE *fp = NULL;
459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	pid_t pid;
460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (opt_p) {
462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!access(opt_p, R_OK)) {
463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if ((fp = fopen(opt_p, "r"))) {
464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (fscanf(fp, "%d", &pid) != 1) {
465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					DEBUG(LOG_ERR, "pid file '%s' exists, but read failed.\n",
466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					      opt_p);
467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				} else {
468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					DEBUG(LOG_ERR, "pid file '%s' exists : %d\n",
469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					      opt_p, pid);
470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				fclose(fp);
472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				exit(1);
473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fp = fopen_excl(opt_p);
477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!fp) {
478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_ERR, "failed to open file '%s': %s\n",
479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      opt_p, strerror(errno));
480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(1);
481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (daemon(0, 0) < 0) {
485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "failed to daemon(): %s\n", strerror(errno));
486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		unlink(opt_p);
487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(1);
488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	daemonized = 1;
490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (fp) {
492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fprintf(fp, "%d\n", getpid());
493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fclose(fp);
494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef HAVE_LIBCAP
499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic const cap_value_t cap_net_raw = CAP_NET_RAW;
500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic const cap_value_t cap_setuid =  CAP_SETUID;
501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic cap_flag_value_t cap_ok;
502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic uid_t euid;
504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void limit_capabilities(void)
507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef HAVE_LIBCAP
509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_t cap_p, cap_cur_p;
510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_p = cap_init();
512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!cap_p) {
513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "cap_init: %s\n", strerror(errno));
514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_cur_p = cap_get_proc();
518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!cap_cur_p) {
519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "cap_get_proc: %s\n", strerror(errno));
520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti        }
522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* net_raw + setuid / net_raw */
524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok);
525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_ok != CAP_CLEAR) {
526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_net_raw, CAP_SET);
527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap_net_raw, CAP_SET);
528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_get_flag(cap_cur_p, CAP_SETUID, CAP_PERMITTED, &cap_ok);
531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_ok != CAP_CLEAR)
532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_setuid, CAP_SET);
533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_set_proc(cap_p) < 0) {
535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "cap_set_proc: %s\n", strerror(errno));
536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (errno != EPERM)
537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(-1);
538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "prctl: %s\n", strerror(errno));
542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_free(cap_cur_p);
546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_free(cap_p);
547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	euid = geteuid();
549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void drop_capabilities(void)
553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef HAVE_LIBCAP
555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_t cap_p;
556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_p = cap_init();
558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!cap_p) {
559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "cap_init: %s\n", strerror(errno));
560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* setuid / setuid */
564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_ok != CAP_CLEAR) {
565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_setuid, CAP_SET);
566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap_setuid, CAP_SET);
567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (cap_set_proc(cap_p) < 0) {
569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_ERR, "cap_set_proc: %s\n", strerror(errno));
570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(-1);
571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (seteuid(opt_u ? opt_u : getuid()) < 0) {
575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "setuid: %s\n", strerror(errno));
576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "prctl: %s\n", strerror(errno));
581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_clear(cap_p);
585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_set_proc(cap_p) < 0) {
586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "cap_set_proc: %s\n", strerror(errno));
587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_free(cap_p);
591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (setuid(getuid()) < 0) {
593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "setuid: %s\n", strerror(errno));
594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void parse_args(int argc, char **argv)
601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int c;
603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned long val;
604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *ep;
605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* parse options */
607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	while ((c = getopt(argc, argv, "dhvp:u:")) != -1) {
608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		switch(c) {
609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'd':	/* debug */
610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			opt_d = 1;
611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'v':	/* verbose */
613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			opt_v = 1;
614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'p':
616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			opt_p = optarg;
617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'u':
619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			val = strtoul(optarg, &ep, 10);
620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (!optarg || *ep) {
621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				struct passwd *pw = getpwnam(optarg);
622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (!pw) {
623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					DEBUG(LOG_ERR, "No such user: %s", optarg);
624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					exit(1);
625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				opt_u = pw->pw_uid;
627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			} else
628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				opt_u = val;
629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'h':	/* help */
631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		default:
632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			opt_h = 1;
633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	argc -= optind;
638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if 0
639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	argv += optind;
640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
642313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (argc)
643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		opt_h = 1;
644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void print_copying(void) {
647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fprintf(stderr,
648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		"Node Information Daemon\n"
649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		"Copyright (C)2002 USAGI/WIDE Project.  All Rights Reserved.\n"
650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		"\n"
651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	);
652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void print_usage(void) {
655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fprintf(stderr,
656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		"Usage: %s [-d] [-p pidfile] [-u user] [-h] [-v]\n\n",
657313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		appname
658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	);
659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* --------- */
662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint main (int argc, char **argv)
663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int sock_errno = 0;
665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int ret;
666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	appname = argv[0];
668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	set_logfile();
669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	limit_capabilities();
671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sock = open_sock();
673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (sock < 0)
674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sock_errno = errno;
675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	parse_args(argc, argv);
677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	drop_capabilities();
679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (opt_h || opt_v)
681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		print_copying();
682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (opt_h) {
683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		print_usage();
684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(1);
685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (sock_errno) {
688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_ERR, "socket: %s\n", strerror(sock_errno));
689313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(1);
690313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* initialize */
693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (init_sock(sock) < 0)
694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(1);
695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setup_sighandlers();
697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!opt_d)
698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		do_daemonize();
699313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
700313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	init_core(1);
701313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
702313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* main loop */
703313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	while (!got_signal) {
704313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct packetcontext *p;
705313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct icmp6_hdr *icmph;
706313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
707313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		char saddrbuf[NI_MAXHOST];
708313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int gni;
709313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
710313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
711313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		init_core(0);
712313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
713313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p = ni_malloc(sizeof(*p));
714313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!p) {
715313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING, "%s(): failed to allocate packet context; sleep 1 sec.\n",
716313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      __func__);
717313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			sleep(1);
718313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
719313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
720313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
721313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		while (!got_signal) {
722313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memset(p, 0, sizeof(*p));
723313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			p->sock = sock;
724313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
725313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ni_recv(p) < 0) {
726313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (got_signal)
727313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					break;
728313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (errno == EAGAIN || errno == EINTR)
729313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					continue;
730313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				/* XXX: syslog */
731313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				continue;
732313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
733313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
734313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
735313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
736313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
737313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		gni = getnameinfo((struct sockaddr *)&p->addr,
738313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				  p->addrlen,
739313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				  saddrbuf, sizeof(saddrbuf),
740313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				  NULL, 0,
741313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				  NI_NUMERICHOST);
742313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (gni)
743313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			sprintf(saddrbuf, "???");
744313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
745313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		init_core(0);
746313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
747313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (p->querylen < sizeof(struct icmp6_hdr)) {
748313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ni_free(p);
749313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING, "Too short icmp message from %s\n", saddrbuf);
750313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
751313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
752313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
753313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		icmph = (struct icmp6_hdr *)p->query;
754313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
755313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_DEBUG,
756313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      "type=%d, code=%d, cksum=0x%04x\n",
757313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      icmph->icmp6_type, icmph->icmp6_code,
758313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      ntohs(icmph->icmp6_cksum));
759313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
760313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (icmph->icmp6_type != ICMP6_NI_QUERY) {
761313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING,
762313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "Strange icmp type %d from %s\n",
763313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      icmph->icmp6_type, saddrbuf);
764313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ni_free(p);
765313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
766313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
767313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
768313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pr_nodeinfo(p);	/* this frees p */
769313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
770313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
771313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cleanup_pidfile();
772313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
773313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	exit(0);
774313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
775313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
776