1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* $USAGI: ninfod_core.c,v 1.29 2003-07-16 09:49:01 yoshfuji 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#else
47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_STDLIB_H
48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <stdlib.h>
49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_THREADS && HAVE_PTHREAD_H
52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <pthread.h>
53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_STRING_H
55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if !STDC_HEADERS && HAVE_MEMORY_H
56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <memory.h>
57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <string.h>
59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_STRINGS_H
61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <strings.h>
62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_INTTYPES_H
64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <inttypes.h>
65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_STDINT_H
67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <stdint.h>
68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_UNISTD_H
71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <unistd.h>
72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if TIME_WITH_SYS_TIME
75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/time.h>
76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <time.h>
77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_SYS_TIME_H
79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <sys/time.h>
80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# else
81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <time.h>
82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYS_UIO_H
86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/uio.h>
87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETINET_IN_H
90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netinet/in.h>
91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETINET_ICMP6_H
94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netinet/icmp6.h>
95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef HAVE_STRUCT_ICMP6_NODEINFO
97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include "icmp6_nodeinfo.h"
98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETDB_H
101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netdb.h>
102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <errno.h>
104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYSLOG_H
106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <syslog.h>
107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "ninfod.h"
110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef offsetof
112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define offsetof(aggregate,member)	((size_t)&((aggregate *)0)->member)
113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ARRAY_SIZE(a)		(sizeof(a) / sizeof(a[0]))
116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ID */
119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic char *RCSID __attribute__ ((unused)) = "$USAGI: ninfod_core.c,v 1.29 2003-07-16 09:49:01 yoshfuji Exp $";
120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Variables */
122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint initialized = 0;
123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_THREADS && HAVE_LIBPTHREAD
125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittipthread_attr_t pattr;
126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic uint32_t suptypes[(MAX_SUPTYPES+31)>>5];
129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic size_t suptypes_len;
130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct subjinfo {
133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	uint8_t	code;
134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char	*name;
135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int	(*checksubj)(CHECKANDFILL_ARGS);
136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int	(*init)(INIT_ARGS);
137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct subjinfo subjinfo_table [] = {
140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[ICMP6_NI_SUBJ_IPV6] = {
141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.code = ICMP6_NI_SUBJ_IPV6,
142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "IPv6",
143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		//.init = init_nodeinfo_ipv6addr,
144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.checksubj = pr_nodeinfo_ipv6addr,
145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[ICMP6_NI_SUBJ_FQDN] = {
147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.code = ICMP6_NI_SUBJ_FQDN,
148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "FQDN",
149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		//.init = init_nodeinfo_nodename,
150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.checksubj = pr_nodeinfo_nodename,
151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[ICMP6_NI_SUBJ_IPV4] = {
153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.code = ICMP6_NI_SUBJ_IPV4,
154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "IPv4",
155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		//.init = init_nodeinfo_ipv4addr,
156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.checksubj = pr_nodeinfo_ipv4addr,
157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct subjinfo subjinfo_null = {
161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.name = "null",
162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.checksubj = pr_nodeinfo_noop,
163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic __inline__ struct subjinfo *subjinfo_lookup(int code)
166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (code >= ARRAY_SIZE(subjinfo_table))
168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return NULL;
169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (subjinfo_table[code].name == NULL)
170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return NULL;
171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return &subjinfo_table[code];
172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define QTYPEINFO_F_RATELIMIT	0x1
176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct qtypeinfo {
178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	uint16_t qtype;
179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char	*name;
180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int	(*getreply)(CHECKANDFILL_ARGS);
181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	void	(*init)(INIT_ARGS);
182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int	flags;
183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct qtypeinfo qtypeinfo_table[] = {
186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[NI_QTYPE_NOOP]		= {
187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.qtype = NI_QTYPE_NOOP,
188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "NOOP",
189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.getreply = pr_nodeinfo_noop,
190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_SUPTYPES
192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[NI_QTYPE_SUPTYPES]	= {
193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.qtype = NI_QTYPE_SUPTYPES,
194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "SupTypes",
195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.getreply = pr_nodeinfo_suptypes,
196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.init = init_nodeinfo_suptypes,
197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[NI_QTYPE_DNSNAME]	= {
200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.qtype = NI_QTYPE_DNSNAME,
201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "DnsName",
202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.getreply = pr_nodeinfo_nodename,
203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.init = init_nodeinfo_nodename,
204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[NI_QTYPE_NODEADDR]	= {
206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.qtype = NI_QTYPE_NODEADDR,
207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "NodeAddr",
208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.getreply = pr_nodeinfo_ipv6addr,
209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.init = init_nodeinfo_ipv6addr,
210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	[NI_QTYPE_IPV4ADDR]	= {
212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.qtype = NI_QTYPE_IPV4ADDR,
213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.name = "IPv4Addr",
214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.getreply = pr_nodeinfo_ipv4addr,
215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		.init = init_nodeinfo_ipv4addr,
216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	},
217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct qtypeinfo qtypeinfo_unknown = {
220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.name = "unknown",
221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.getreply = pr_nodeinfo_unknown,
222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.flags = QTYPEINFO_F_RATELIMIT,
223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct qtypeinfo qtypeinfo_refused = {
226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.name = "refused",
227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.getreply = pr_nodeinfo_refused,
228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	.flags = QTYPEINFO_F_RATELIMIT,
229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic __inline__ struct qtypeinfo *qtypeinfo_lookup(int qtype)
232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (qtype >= ARRAY_SIZE(qtypeinfo_table))
234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return &qtypeinfo_unknown;
235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (qtypeinfo_table[qtype].name == NULL)
236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return &qtypeinfo_unknown;
237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return &qtypeinfo_table[qtype];
238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* noop */
242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pr_nodeinfo_noop(CHECKANDFILL_ARGS)
243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s()\n", __func__);
245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (subjlen) {
247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_WARNING,
248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      "%s(): invalid subject length(%zu)\n",
249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      __func__, subjlen);
250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 1;
251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (reply) {
254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_type = ICMP6_NI_REPLY;
255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_code = ICMP6_NI_SUCCESS;
256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_cksum = 0;
257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_qtype = htons(NI_QTYPE_NOOP);
258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_flags = flags;
259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (subj_if)
262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		*subj_if = 0;
263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_SUPTYPES
268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* suptypes */
269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pr_nodeinfo_suptypes(CHECKANDFILL_ARGS)
270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s()\n", __func__);
272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (subjlen) {
274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_WARNING, "%s(): invalid subject length(%zu)\n",
275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      __func__, subjlen);
276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 1;
277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (reply) {
280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_type = ICMP6_NI_REPLY;
281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_code = ICMP6_NI_SUCCESS;
282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_cksum = 0;
283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_qtype = htons(NI_QTYPE_SUPTYPES);
284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_flags = flags&~NI_SUPTYPE_FLAG_COMPRESS;
285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->replydatalen = suptypes_len<<2;
287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->replydata = ni_malloc(p->replydatalen);
288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (p->replydata == NULL) {
289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			p->replydatalen = -1;
290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;	/*XXX*/
291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memcpy(p->replydata, suptypes, p->replydatalen);
294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid init_nodeinfo_suptypes(INIT_ARGS)
299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	size_t w, b;
301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!forced && initialized)
304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(suptypes, 0, sizeof(suptypes));
307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	suptypes_len = 0;
308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (i=0; i < ARRAY_SIZE(qtypeinfo_table); i++) {
310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		unsigned short qtype;
311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (qtypeinfo_table[i].name == NULL)
313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		qtype = qtypeinfo_table[i].qtype;
315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		w = qtype>>5;
316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		b = qtype&0x1f;
317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (w >= ARRAY_SIZE(suptypes)) {
318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* This is programming error. */
319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_ERR, "Warning: Too Large Supported Types\n");
320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(1);
321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		suptypes[w] |= htonl(1<<b);
323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (suptypes_len < w)
325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			suptypes_len = w;
326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	suptypes_len++;
328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* unknown qtype response */
333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pr_nodeinfo_unknown(CHECKANDFILL_ARGS)
334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!reply)
336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;	/*???*/
337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_type = ICMP6_NI_REPLY;
339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_code = ICMP6_NI_UNKNOWN;
340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_cksum = 0;
341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	//p->reply.ni_qtype = 0;
342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_flags = flags;
343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->replydata = NULL;
345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->replydatalen = 0;
346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* refused response */
351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pr_nodeinfo_refused(CHECKANDFILL_ARGS)
352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!reply)
354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;	/*???*/
355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_type = ICMP6_NI_REPLY;
357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_code = ICMP6_NI_REFUSED;
358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_cksum = 0;
359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	//p->reply.ni_qtype = 0;
360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_flags = flags;
361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->replydata = NULL;
363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->replydatalen = 0;
364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Policy */
370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int ni_policy(struct packetcontext *p)
371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	const struct in6_addr *saddr = &((const struct sockaddr_in6 *)&p->addr)->sin6_addr;
373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/*
375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * >0: reply
376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 *  0: refused
377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * <0: discard
378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Default policy is to refuse queries from
381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * non-local addresses; loopback, link-local or
382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * site-local are okay
383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!(IN6_IS_ADDR_LINKLOCAL(saddr) ||
385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      IN6_IS_ADDR_SITELOCAL(saddr) ||
386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      IN6_IS_ADDR_LOOPBACK(saddr)))
387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 1;
389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid init_core(int forced)
393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s()\n", __func__);
397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!initialized || forced) {
399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct timeval tv;
400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		unsigned int seed = 0;
401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pid_t pid;
402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (gettimeofday(&tv, NULL) < 0) {
404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING, "%s(): failed to gettimeofday()\n", __func__);
405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		} else {
406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			seed = (tv.tv_usec & 0xffffffff);
407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pid = getpid();
410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		seed ^= (((unsigned long)pid) & 0xffffffff);
411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		srand(seed);
413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_THREADS && HAVE_LIBPTHREAD
415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (initialized)
416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pthread_attr_destroy(&pattr);
417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pthread_attr_init(&pattr);
419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (i=0; i < ARRAY_SIZE(subjinfo_table); i++) {
424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (subjinfo_table[i].name == NULL)
425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (subjinfo_table[i].init)
427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			subjinfo_table[i].init(forced);
428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (i=0; i < ARRAY_SIZE(qtypeinfo_table); i++) {
431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (qtypeinfo_table[i].name == NULL)
432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (qtypeinfo_table[i].init)
434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			qtypeinfo_table[i].init(forced);
435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	initialized = 1;
438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return;
440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_THREADS && HAVE_LIBPTHREAD
443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void *ni_send_thread(void *data)
444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int ret;
446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s(): thread=%ld\n", __func__, pthread_self());
447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ret = ni_send(data);
448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s(): thread=%ld => %d\n", __func__, pthread_self(), ret);
449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return NULL;
450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int ni_send_fork(struct packetcontext *p)
453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	pid_t child = fork();
455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (child < 0)
456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (child == 0) {
458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pid_t grandchild = fork();
459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (grandchild < 0)
460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(1);
461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (grandchild == 0) {
462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			int ret;
463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_DEBUG, "%s(): worker=%d\n",
464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      __func__, getpid());
465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ret = ni_send(p);
466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_DEBUG, "%s(): worker=%d => %d\n",
467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      __func__, getpid(), ret);
468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(ret > 0 ? 1 : 0);
469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p->replydata);
471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p);
472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(0);
473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else {
474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		waitpid(child, NULL, 0);
475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p->replydata);
476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p);
477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int ni_ratelimit(void)
483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	static struct timeval last;
485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct timeval tv, sub;
486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (gettimeofday(&tv, NULL) < 0) {
488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_WARNING, "%s(): gettimeofday(): %s\n",
489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      __func__, strerror(errno));
490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!timerisset(&last)) {
494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		last = tv;
495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	timersub(&tv, &last, &sub);
499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (sub.tv_sec < 1)
501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 1;
502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	last = tv;
504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pr_nodeinfo(struct packetcontext *p)
508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct icmp6_nodeinfo *query = (struct icmp6_nodeinfo *)p->query;
510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *subject = (char *)(query + 1);
512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	size_t subjlen;
513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct subjinfo *subjinfo;
514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct qtypeinfo *qtypeinfo;
515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int replyonsubjcheck = 0;
516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned int subj_if;
517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char printbuf[128];
519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *cp;
521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_THREADS && HAVE_PTHREAD_H
523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	pthread_t thread;
524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int rc;
526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 0: Check destination address
528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 *		discard non-linklocal multicast
529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 *		discard non-nigroup multicast address(?)
530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (IN6_IS_ADDR_MULTICAST(&p->pktinfo.ipi6_addr)) {
532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!IN6_IS_ADDR_MC_LINKLOCAL(&p->pktinfo.ipi6_addr)) {
533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING,
534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "Destination is non-link-local multicast address.\n");
535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ni_free(p);
536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;
537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if 0
539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Do not discard NI Queries to multicast address
540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * other than its own NI Group Address(es) by default.
541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 */
542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!check_nigroup(&p->pktinfo.ipi6_addr)) {
543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING,
544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "Destination is link-local multicast address other than "
545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "NI Group address.\n");
546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ni_free(p);
547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;
548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 1: Check length */
553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (p->querylen < sizeof(struct icmp6_nodeinfo)) {
554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_WARNING, "Query too short\n");
555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p);
556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cp = printbuf;
561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (i = 0; i < sizeof(query->icmp6_ni_nonce); i++) {
562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cp += sprintf(cp, " %02x", query->icmp6_ni_nonce[i]);
563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s(): qtype=%d, flags=0x%04x, nonce[] = {%s }\n",
565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      __func__,
566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      ntohs(query->ni_qtype), ntohs(query->ni_flags), printbuf);
567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	subjlen = p->querylen - sizeof(struct icmp6_nodeinfo);
570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 2: Check Subject Code */
572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	switch(htons(query->ni_qtype)) {
573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case NI_QTYPE_NOOP:
574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case NI_QTYPE_SUPTYPES:
575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (query->ni_code != ICMP6_NI_SUBJ_FQDN) {
576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING,
577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "%s(): invalid/unknown code %u\n",
578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      __func__, query->ni_code);
579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			subjlen = 0;
580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		subjinfo = &subjinfo_null;
582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	default:
584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		subjinfo = subjinfo_lookup(query->ni_code);
585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!subjinfo) {
586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING,
587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "%s(): unknown code %u\n",
588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      __func__, query->ni_code);
589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ni_free(p);
590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;
591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 3: Lookup Qtype */
595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	qtypeinfo = qtypeinfo_lookup(ntohs(query->ni_qtype));
596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 4: Check Subject
598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 *         (And fill reply if it is available now)
599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (qtypeinfo->getreply == subjinfo->checksubj)
601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		replyonsubjcheck = 1;
602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (subjinfo->checksubj(p,
604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				subject, subjlen,
605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				query->ni_flags,
606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				replyonsubjcheck ? NULL : &subj_if,
607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				replyonsubjcheck)) {
608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (p->replydatalen < 0) {
609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING,
610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "failed to make reply: %s\n",
611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      strerror(errno));
612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p);
614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* XXX: Step 5: Check the policy */
618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	rc = ni_policy(p);
619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (rc <= 0) {
620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p->replydata);
621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->replydata = NULL;
622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->replydatalen = 0;
623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (rc < 0) {
624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING, "Ignored by policy.\n");
625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ni_free(p);
626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;
627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		DEBUG(LOG_WARNING, "Refused by policy.\n");
629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		replyonsubjcheck = 0;
630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		qtypeinfo = &qtypeinfo_refused;
631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 6: Fill the reply if not yet done */
634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!replyonsubjcheck) {
635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (qtypeinfo->getreply(p,
636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					NULL, 0,
637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					query->ni_flags,
638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					&subj_if,
639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					1)) {
640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (p->replydatalen) {
641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				DEBUG(LOG_WARNING,
642313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				      "failed to make reply: %s\n",
643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				      strerror(errno));
644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ni_free(p);
646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;
647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 7: Rate Limit */
651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (qtypeinfo->flags&QTYPEINFO_F_RATELIMIT &&
652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    ni_ratelimit()) {
653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p->replydata);
654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p);
655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
657313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 8: Fill Qtype / Nonce */
659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p->reply.ni_qtype = query->ni_qtype;
660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(p->reply.icmp6_ni_nonce, query->icmp6_ni_nonce, sizeof(p->reply.icmp6_ni_nonce));
661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 9: Source address selection */
663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (IN6_IS_ADDR_MULTICAST(&p->pktinfo.ipi6_addr)) {
664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* if query was sent to multicast address,
665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * use source address selection in kernel.
666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * XXX: anycast?
667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 */
668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memset(&p->pktinfo.ipi6_addr, 0, sizeof(p->pktinfo.ipi6_addr));
669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 	/* Random Delay between zero and MAX_ANYCAST_DELAY_TIME is
671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * required if query was sent to anycast or multicast address.
672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 */
673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->delay = (int) (MAX_ANYCAST_DELAY_TIME*rand()/(RAND_MAX+1.0));
674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else {
675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->delay = 0;
676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Step 10: Send the reply
679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * XXX: with possible random delay */
680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_THREADS && HAVE_LIBPTHREAD
681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* ni_send_thread() frees p */
682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pthread_create(&thread, &pattr, ni_send_thread, p)) {
683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p->replydata);
684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p);
685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* ni_send_fork() frees p */
689313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ni_send_fork(p)) {
690313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p->replydata);
691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ni_free(p);
692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
699