• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $USAGI: ninfod_core.c,v 1.29 2003-07-16 09:49:01 yoshfuji Exp $ */
2 /*
3  * Copyright (C) 2002 USAGI/WIDE Project.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the project nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 /*
31  * Author:
32  * 	YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
33  */
34 
35 #if HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 
39 #if HAVE_SYS_TYPES_H
40 # include <sys/types.h>
41 #endif
42 #if STDC_HEADERS
43 # include <stdio.h>
44 # include <stdlib.h>
45 # include <stddef.h>
46 #else
47 # if HAVE_STDLIB_H
48 #  include <stdlib.h>
49 # endif
50 #endif
51 #if ENABLE_THREADS && HAVE_PTHREAD_H
52 # include <pthread.h>
53 #endif
54 #if HAVE_STRING_H
55 # if !STDC_HEADERS && HAVE_MEMORY_H
56 #  include <memory.h>
57 # endif
58 # include <string.h>
59 #endif
60 #if HAVE_STRINGS_H
61 # include <strings.h>
62 #endif
63 #if HAVE_INTTYPES_H
64 # include <inttypes.h>
65 #else
66 # if HAVE_STDINT_H
67 #  include <stdint.h>
68 # endif
69 #endif
70 #if HAVE_UNISTD_H
71 # include <unistd.h>
72 #endif
73 
74 #if TIME_WITH_SYS_TIME
75 # include <sys/time.h>
76 # include <time.h>
77 #else
78 # if HAVE_SYS_TIME_H
79 #  include <sys/time.h>
80 # else
81 #  include <time.h>
82 # endif
83 #endif
84 
85 #if HAVE_SYS_UIO_H
86 #include <sys/uio.h>
87 #endif
88 
89 #if HAVE_NETINET_IN_H
90 # include <netinet/in.h>
91 #endif
92 
93 #if HAVE_NETINET_ICMP6_H
94 # include <netinet/icmp6.h>
95 #endif
96 #ifndef HAVE_STRUCT_ICMP6_NODEINFO
97 # include "icmp6_nodeinfo.h"
98 #endif
99 
100 #if HAVE_NETDB_H
101 # include <netdb.h>
102 #endif
103 #include <errno.h>
104 
105 #if HAVE_SYSLOG_H
106 # include <syslog.h>
107 #endif
108 
109 #include "ninfod.h"
110 
111 #ifndef offsetof
112 # define offsetof(aggregate,member)	((size_t)&((aggregate *)0)->member)
113 #endif
114 
115 #define ARRAY_SIZE(a)		(sizeof(a) / sizeof(a[0]))
116 
117 /* ---------- */
118 /* ID */
119 static char *RCSID __attribute__ ((unused)) = "$USAGI: ninfod_core.c,v 1.29 2003-07-16 09:49:01 yoshfuji Exp $";
120 
121 /* Variables */
122 int initialized = 0;
123 
124 #if ENABLE_THREADS && HAVE_LIBPTHREAD
125 pthread_attr_t pattr;
126 #endif
127 
128 static uint32_t suptypes[(MAX_SUPTYPES+31)>>5];
129 static size_t suptypes_len;
130 
131 /* ---------- */
132 struct subjinfo {
133 	uint8_t	code;
134 	char	*name;
135 	int	(*checksubj)(CHECKANDFILL_ARGS);
136 	int	(*init)(INIT_ARGS);
137 };
138 
139 static struct subjinfo subjinfo_table [] = {
140 	[ICMP6_NI_SUBJ_IPV6] = {
141 		.code = ICMP6_NI_SUBJ_IPV6,
142 		.name = "IPv6",
143 		//.init = init_nodeinfo_ipv6addr,
144 		.checksubj = pr_nodeinfo_ipv6addr,
145 	},
146 	[ICMP6_NI_SUBJ_FQDN] = {
147 		.code = ICMP6_NI_SUBJ_FQDN,
148 		.name = "FQDN",
149 		//.init = init_nodeinfo_nodename,
150 		.checksubj = pr_nodeinfo_nodename,
151 	},
152 	[ICMP6_NI_SUBJ_IPV4] = {
153 		.code = ICMP6_NI_SUBJ_IPV4,
154 		.name = "IPv4",
155 		//.init = init_nodeinfo_ipv4addr,
156 		.checksubj = pr_nodeinfo_ipv4addr,
157 	},
158 };
159 
160 static struct subjinfo subjinfo_null = {
161 	.name = "null",
162 	.checksubj = pr_nodeinfo_noop,
163 };
164 
subjinfo_lookup(int code)165 static __inline__ struct subjinfo *subjinfo_lookup(int code)
166 {
167 	if (code >= ARRAY_SIZE(subjinfo_table))
168 		return NULL;
169 	if (subjinfo_table[code].name == NULL)
170 		return NULL;
171 	return &subjinfo_table[code];
172 }
173 
174 /* ---------- */
175 #define QTYPEINFO_F_RATELIMIT	0x1
176 
177 struct qtypeinfo {
178 	uint16_t qtype;
179 	char	*name;
180 	int	(*getreply)(CHECKANDFILL_ARGS);
181 	void	(*init)(INIT_ARGS);
182 	int	flags;
183 };
184 
185 static struct qtypeinfo qtypeinfo_table[] = {
186 	[NI_QTYPE_NOOP]		= {
187 		.qtype = NI_QTYPE_NOOP,
188 		.name = "NOOP",
189 		.getreply = pr_nodeinfo_noop,
190 	},
191 #if ENABLE_SUPTYPES
192 	[NI_QTYPE_SUPTYPES]	= {
193 		.qtype = NI_QTYPE_SUPTYPES,
194 		.name = "SupTypes",
195 		.getreply = pr_nodeinfo_suptypes,
196 		.init = init_nodeinfo_suptypes,
197 	},
198 #endif
199 	[NI_QTYPE_DNSNAME]	= {
200 		.qtype = NI_QTYPE_DNSNAME,
201 		.name = "DnsName",
202 		.getreply = pr_nodeinfo_nodename,
203 		.init = init_nodeinfo_nodename,
204 	},
205 	[NI_QTYPE_NODEADDR]	= {
206 		.qtype = NI_QTYPE_NODEADDR,
207 		.name = "NodeAddr",
208 		.getreply = pr_nodeinfo_ipv6addr,
209 		.init = init_nodeinfo_ipv6addr,
210 	},
211 	[NI_QTYPE_IPV4ADDR]	= {
212 		.qtype = NI_QTYPE_IPV4ADDR,
213 		.name = "IPv4Addr",
214 		.getreply = pr_nodeinfo_ipv4addr,
215 		.init = init_nodeinfo_ipv4addr,
216 	},
217 };
218 
219 static struct qtypeinfo qtypeinfo_unknown = {
220 	.name = "unknown",
221 	.getreply = pr_nodeinfo_unknown,
222 	.flags = QTYPEINFO_F_RATELIMIT,
223 };
224 
225 static struct qtypeinfo qtypeinfo_refused = {
226 	.name = "refused",
227 	.getreply = pr_nodeinfo_refused,
228 	.flags = QTYPEINFO_F_RATELIMIT,
229 };
230 
qtypeinfo_lookup(int qtype)231 static __inline__ struct qtypeinfo *qtypeinfo_lookup(int qtype)
232 {
233 	if (qtype >= ARRAY_SIZE(qtypeinfo_table))
234 		return &qtypeinfo_unknown;
235 	if (qtypeinfo_table[qtype].name == NULL)
236 		return &qtypeinfo_unknown;
237 	return &qtypeinfo_table[qtype];
238 }
239 
240 /* ---------- */
241 /* noop */
pr_nodeinfo_noop(CHECKANDFILL_ARGS)242 int pr_nodeinfo_noop(CHECKANDFILL_ARGS)
243 {
244 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
245 
246 	if (subjlen) {
247 		DEBUG(LOG_WARNING,
248 		      "%s(): invalid subject length(%zu)\n",
249 		      __func__, subjlen);
250 		return 1;
251 	}
252 
253 	if (reply) {
254 		p->reply.ni_type = ICMP6_NI_REPLY;
255 		p->reply.ni_code = ICMP6_NI_SUCCESS;
256 		p->reply.ni_cksum = 0;
257 		p->reply.ni_qtype = htons(NI_QTYPE_NOOP);
258 		p->reply.ni_flags = flags;
259 	}
260 
261 	if (subj_if)
262 		*subj_if = 0;
263 
264 	return 0;
265 }
266 
267 #if ENABLE_SUPTYPES
268 /* suptypes */
pr_nodeinfo_suptypes(CHECKANDFILL_ARGS)269 int pr_nodeinfo_suptypes(CHECKANDFILL_ARGS)
270 {
271 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
272 
273 	if (subjlen) {
274 		DEBUG(LOG_WARNING, "%s(): invalid subject length(%zu)\n",
275 		      __func__, subjlen);
276 		return 1;
277 	}
278 
279 	if (reply) {
280 		p->reply.ni_type = ICMP6_NI_REPLY;
281 		p->reply.ni_code = ICMP6_NI_SUCCESS;
282 		p->reply.ni_cksum = 0;
283 		p->reply.ni_qtype = htons(NI_QTYPE_SUPTYPES);
284 		p->reply.ni_flags = flags&~NI_SUPTYPE_FLAG_COMPRESS;
285 
286 		p->replydatalen = suptypes_len<<2;
287 		p->replydata = ni_malloc(p->replydatalen);
288 		if (p->replydata == NULL) {
289 			p->replydatalen = -1;
290 			return -1;	/*XXX*/
291 		}
292 
293 		memcpy(p->replydata, suptypes, p->replydatalen);
294 	}
295 	return 0;
296 }
297 
init_nodeinfo_suptypes(INIT_ARGS)298 void init_nodeinfo_suptypes(INIT_ARGS)
299 {
300 	size_t w, b;
301 	int i;
302 
303 	if (!forced && initialized)
304 		return;
305 
306 	memset(suptypes, 0, sizeof(suptypes));
307 	suptypes_len = 0;
308 
309 	for (i=0; i < ARRAY_SIZE(qtypeinfo_table); i++) {
310 		unsigned short qtype;
311 
312 		if (qtypeinfo_table[i].name == NULL)
313 			continue;
314 		qtype = qtypeinfo_table[i].qtype;
315 		w = qtype>>5;
316 		b = qtype&0x1f;
317 		if (w >= ARRAY_SIZE(suptypes)) {
318 			/* This is programming error. */
319 			DEBUG(LOG_ERR, "Warning: Too Large Supported Types\n");
320 			exit(1);
321 		}
322 		suptypes[w] |= htonl(1<<b);
323 
324 		if (suptypes_len < w)
325 			suptypes_len = w;
326 	}
327 	suptypes_len++;
328 }
329 #endif
330 
331 /* ---------- */
332 /* unknown qtype response */
pr_nodeinfo_unknown(CHECKANDFILL_ARGS)333 int pr_nodeinfo_unknown(CHECKANDFILL_ARGS)
334 {
335 	if (!reply)
336 		return -1;	/*???*/
337 
338 	p->reply.ni_type = ICMP6_NI_REPLY;
339 	p->reply.ni_code = ICMP6_NI_UNKNOWN;
340 	p->reply.ni_cksum = 0;
341 	//p->reply.ni_qtype = 0;
342 	p->reply.ni_flags = flags;
343 
344 	p->replydata = NULL;
345 	p->replydatalen = 0;
346 
347 	return 0;
348 }
349 
350 /* refused response */
pr_nodeinfo_refused(CHECKANDFILL_ARGS)351 int pr_nodeinfo_refused(CHECKANDFILL_ARGS)
352 {
353 	if (!reply)
354 		return -1;	/*???*/
355 
356 	p->reply.ni_type = ICMP6_NI_REPLY;
357 	p->reply.ni_code = ICMP6_NI_REFUSED;
358 	p->reply.ni_cksum = 0;
359 	//p->reply.ni_qtype = 0;
360 	p->reply.ni_flags = flags;
361 
362 	p->replydata = NULL;
363 	p->replydatalen = 0;
364 
365 	return 0;
366 }
367 
368 /* ---------- */
369 /* Policy */
ni_policy(struct packetcontext * p)370 static int ni_policy(struct packetcontext *p)
371 {
372 	const struct in6_addr *saddr = &((const struct sockaddr_in6 *)&p->addr)->sin6_addr;
373 
374 	/*
375 	 * >0: reply
376 	 *  0: refused
377 	 * <0: discard
378 	 */
379 
380 	/* Default policy is to refuse queries from
381 	 * non-local addresses; loopback, link-local or
382 	 * site-local are okay
383 	 */
384 	if (!(IN6_IS_ADDR_LINKLOCAL(saddr) ||
385 	      IN6_IS_ADDR_SITELOCAL(saddr) ||
386 	      IN6_IS_ADDR_LOOPBACK(saddr)))
387 		return 0;
388 	return 1;
389 }
390 
391 /* ---------- */
init_core(int forced)392 void init_core(int forced)
393 {
394 	int i;
395 
396 	DEBUG(LOG_DEBUG, "%s()\n", __func__);
397 
398 	if (!initialized || forced) {
399 		struct timeval tv;
400 		unsigned int seed = 0;
401 		pid_t pid;
402 
403 		if (gettimeofday(&tv, NULL) < 0) {
404 			DEBUG(LOG_WARNING, "%s(): failed to gettimeofday()\n", __func__);
405 		} else {
406 			seed = (tv.tv_usec & 0xffffffff);
407 		}
408 
409 		pid = getpid();
410 		seed ^= (((unsigned long)pid) & 0xffffffff);
411 
412 		srand(seed);
413 
414 #if ENABLE_THREADS && HAVE_LIBPTHREAD
415 		if (initialized)
416 			pthread_attr_destroy(&pattr);
417 
418 		pthread_attr_init(&pattr);
419 		pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
420 #endif
421 	}
422 
423 	for (i=0; i < ARRAY_SIZE(subjinfo_table); i++) {
424 		if (subjinfo_table[i].name == NULL)
425 			continue;
426 		if (subjinfo_table[i].init)
427 			subjinfo_table[i].init(forced);
428 	}
429 
430 	for (i=0; i < ARRAY_SIZE(qtypeinfo_table); i++) {
431 		if (qtypeinfo_table[i].name == NULL)
432 			continue;
433 		if (qtypeinfo_table[i].init)
434 			qtypeinfo_table[i].init(forced);
435 	}
436 
437 	initialized = 1;
438 
439 	return;
440 }
441 
442 #if ENABLE_THREADS && HAVE_LIBPTHREAD
ni_send_thread(void * data)443 static void *ni_send_thread(void *data)
444 {
445 	int ret;
446 	DEBUG(LOG_DEBUG, "%s(): thread=%ld\n", __func__, pthread_self());
447 	ret = ni_send(data);
448 	DEBUG(LOG_DEBUG, "%s(): thread=%ld => %d\n", __func__, pthread_self(), ret);
449 	return NULL;
450 }
451 #else
ni_send_fork(struct packetcontext * p)452 static int ni_send_fork(struct packetcontext *p)
453 {
454 	pid_t child = fork();
455 	if (child < 0)
456 		return -1;
457 	if (child == 0) {
458 		pid_t grandchild = fork();
459 		if (grandchild < 0)
460 			exit(1);
461 		if (grandchild == 0) {
462 			int ret;
463 			DEBUG(LOG_DEBUG, "%s(): worker=%d\n",
464 			      __func__, getpid());
465 			ret = ni_send(p);
466 			DEBUG(LOG_DEBUG, "%s(): worker=%d => %d\n",
467 			      __func__, getpid(), ret);
468 			exit(ret > 0 ? 1 : 0);
469 		}
470 		ni_free(p->replydata);
471 		ni_free(p);
472 		exit(0);
473 	} else {
474 		waitpid(child, NULL, 0);
475 		ni_free(p->replydata);
476 		ni_free(p);
477 	}
478 	return 0;
479 }
480 #endif
481 
ni_ratelimit(void)482 static int ni_ratelimit(void)
483 {
484 	static struct timeval last;
485 	struct timeval tv, sub;
486 
487 	if (gettimeofday(&tv, NULL) < 0) {
488 		DEBUG(LOG_WARNING, "%s(): gettimeofday(): %s\n",
489 		      __func__, strerror(errno));
490 		return -1;
491 	}
492 
493 	if (!timerisset(&last)) {
494 		last = tv;
495 		return 0;
496 	}
497 
498 	timersub(&tv, &last, &sub);
499 
500 	if (sub.tv_sec < 1)
501 		return 1;
502 
503 	last = tv;
504 	return 0;
505 }
506 
pr_nodeinfo(struct packetcontext * p)507 int pr_nodeinfo(struct packetcontext *p)
508 {
509 	struct icmp6_nodeinfo *query = (struct icmp6_nodeinfo *)p->query;
510 
511 	char *subject = (char *)(query + 1);
512 	size_t subjlen;
513 	struct subjinfo *subjinfo;
514 	struct qtypeinfo *qtypeinfo;
515 	int replyonsubjcheck = 0;
516 	unsigned int subj_if;
517 #if ENABLE_DEBUG
518 	char printbuf[128];
519 	int i;
520 	char *cp;
521 #endif
522 #if ENABLE_THREADS && HAVE_PTHREAD_H
523 	pthread_t thread;
524 #endif
525 	int rc;
526 
527 	/* Step 0: Check destination address
528 	 *		discard non-linklocal multicast
529 	 *		discard non-nigroup multicast address(?)
530 	 */
531 	if (IN6_IS_ADDR_MULTICAST(&p->pktinfo.ipi6_addr)) {
532 		if (!IN6_IS_ADDR_MC_LINKLOCAL(&p->pktinfo.ipi6_addr)) {
533 			DEBUG(LOG_WARNING,
534 			      "Destination is non-link-local multicast address.\n");
535 			ni_free(p);
536 			return -1;
537 		}
538 #if 0
539 		/* Do not discard NI Queries to multicast address
540 		 * other than its own NI Group Address(es) by default.
541 		 */
542 		if (!check_nigroup(&p->pktinfo.ipi6_addr)) {
543 			DEBUG(LOG_WARNING,
544 			      "Destination is link-local multicast address other than "
545 			      "NI Group address.\n");
546 			ni_free(p);
547 			return -1;
548 		}
549 #endif
550 	}
551 
552 	/* Step 1: Check length */
553 	if (p->querylen < sizeof(struct icmp6_nodeinfo)) {
554 		DEBUG(LOG_WARNING, "Query too short\n");
555 		ni_free(p);
556 		return -1;
557 	}
558 
559 #if ENABLE_DEBUG
560 	cp = printbuf;
561 	for (i = 0; i < sizeof(query->icmp6_ni_nonce); i++) {
562 		cp += sprintf(cp, " %02x", query->icmp6_ni_nonce[i]);
563 	}
564 	DEBUG(LOG_DEBUG, "%s(): qtype=%d, flags=0x%04x, nonce[] = {%s }\n",
565 	      __func__,
566 	      ntohs(query->ni_qtype), ntohs(query->ni_flags), printbuf);
567 #endif
568 
569 	subjlen = p->querylen - sizeof(struct icmp6_nodeinfo);
570 
571 	/* Step 2: Check Subject Code */
572 	switch(htons(query->ni_qtype)) {
573 	case NI_QTYPE_NOOP:
574 	case NI_QTYPE_SUPTYPES:
575 		if (query->ni_code != ICMP6_NI_SUBJ_FQDN) {
576 			DEBUG(LOG_WARNING,
577 			      "%s(): invalid/unknown code %u\n",
578 			      __func__, query->ni_code);
579 			subjlen = 0;
580 		}
581 		subjinfo = &subjinfo_null;
582 		break;
583 	default:
584 		subjinfo = subjinfo_lookup(query->ni_code);
585 		if (!subjinfo) {
586 			DEBUG(LOG_WARNING,
587 			      "%s(): unknown code %u\n",
588 			      __func__, query->ni_code);
589 			ni_free(p);
590 			return -1;
591 		}
592 	}
593 
594 	/* Step 3: Lookup Qtype */
595 	qtypeinfo = qtypeinfo_lookup(ntohs(query->ni_qtype));
596 
597 	/* Step 4: Check Subject
598 	 *         (And fill reply if it is available now)
599 	 */
600 	if (qtypeinfo->getreply == subjinfo->checksubj)
601 		replyonsubjcheck = 1;
602 
603 	if (subjinfo->checksubj(p,
604 				subject, subjlen,
605 				query->ni_flags,
606 				replyonsubjcheck ? NULL : &subj_if,
607 				replyonsubjcheck)) {
608 		if (p->replydatalen < 0) {
609 			DEBUG(LOG_WARNING,
610 			      "failed to make reply: %s\n",
611 			      strerror(errno));
612 		}
613 		ni_free(p);
614 		return -1;
615 	}
616 
617 	/* XXX: Step 5: Check the policy */
618 	rc = ni_policy(p);
619 	if (rc <= 0) {
620 		ni_free(p->replydata);
621 		p->replydata = NULL;
622 		p->replydatalen = 0;
623 		if (rc < 0) {
624 			DEBUG(LOG_WARNING, "Ignored by policy.\n");
625 			ni_free(p);
626 			return -1;
627 		}
628 		DEBUG(LOG_WARNING, "Refused by policy.\n");
629 		replyonsubjcheck = 0;
630 		qtypeinfo = &qtypeinfo_refused;
631 	}
632 
633 	/* Step 6: Fill the reply if not yet done */
634 	if (!replyonsubjcheck) {
635 		if (qtypeinfo->getreply(p,
636 					NULL, 0,
637 					query->ni_flags,
638 					&subj_if,
639 					1)) {
640 			if (p->replydatalen) {
641 				DEBUG(LOG_WARNING,
642 				      "failed to make reply: %s\n",
643 				      strerror(errno));
644 			}
645 			ni_free(p);
646 			return -1;
647 		}
648 	}
649 
650 	/* Step 7: Rate Limit */
651 	if (qtypeinfo->flags&QTYPEINFO_F_RATELIMIT &&
652 	    ni_ratelimit()) {
653 		ni_free(p->replydata);
654 		ni_free(p);
655 		return -1;
656 	}
657 
658 	/* Step 8: Fill Qtype / Nonce */
659 	p->reply.ni_qtype = query->ni_qtype;
660 	memcpy(p->reply.icmp6_ni_nonce, query->icmp6_ni_nonce, sizeof(p->reply.icmp6_ni_nonce));
661 
662 	/* Step 9: Source address selection */
663 	if (IN6_IS_ADDR_MULTICAST(&p->pktinfo.ipi6_addr)) {
664 		/* if query was sent to multicast address,
665 		 * use source address selection in kernel.
666 		 * XXX: anycast?
667 		 */
668 		memset(&p->pktinfo.ipi6_addr, 0, sizeof(p->pktinfo.ipi6_addr));
669 
670 	 	/* Random Delay between zero and MAX_ANYCAST_DELAY_TIME is
671 		 * required if query was sent to anycast or multicast address.
672 		 */
673 		p->delay = (int) (MAX_ANYCAST_DELAY_TIME*rand()/(RAND_MAX+1.0));
674 	} else {
675 		p->delay = 0;
676 	}
677 
678 	/* Step 10: Send the reply
679 	 * XXX: with possible random delay */
680 #if ENABLE_THREADS && HAVE_LIBPTHREAD
681 	/* ni_send_thread() frees p */
682 	if (pthread_create(&thread, &pattr, ni_send_thread, p)) {
683 		ni_free(p->replydata);
684 		ni_free(p);
685 		return -1;
686 	}
687 #else
688 	/* ni_send_fork() frees p */
689 	if (ni_send_fork(p)) {
690 		ni_free(p->replydata);
691 		ni_free(p);
692 		return -1;
693 	}
694 #endif
695 
696 	return 0;
697 }
698 
699