config.c revision 301809
1/*	$FreeBSD: stable/10/usr.sbin/rtadvd/config.c 301809 2016-06-10 18:21:05Z ngie $	*/
2/*	$KAME: config.c,v 1.84 2003/08/05 12:34:23 itojun Exp $	*/
3
4/*
5 * Copyright (C) 1998 WIDE Project.
6 * Copyright (C) 2011 Hiroki Sato <hrs@FreeBSD.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/param.h>
35#include <sys/ioctl.h>
36#include <sys/socket.h>
37
38#include <net/if.h>
39#include <net/if_var.h>
40#include <net/route.h>
41#include <net/if_dl.h>
42
43#include <netinet/in.h>
44#include <netinet/in_var.h>
45#include <netinet/ip6.h>
46#include <netinet6/ip6_var.h>
47#include <netinet/icmp6.h>
48#include <netinet6/nd6.h>
49
50#include <arpa/inet.h>
51
52#include <stdio.h>
53#include <syslog.h>
54#include <errno.h>
55#include <inttypes.h>
56#include <netdb.h>
57#include <string.h>
58#include <search.h>
59#include <stdlib.h>
60#include <time.h>
61#include <unistd.h>
62#include <ifaddrs.h>
63
64#include "rtadvd.h"
65#include "advcap.h"
66#include "timer.h"
67#include "if.h"
68#include "config.h"
69
70/* label of tcapcode + number + domain name + zero octet */
71static char entbuf[10 + 3 + NI_MAXHOST + 1];
72static char oentbuf[10 + 3 + NI_MAXHOST + 1];
73static char abuf[DNAME_LABELENC_MAXLEN];
74
75static time_t prefix_timo = (60 * 120);	/* 2 hours.
76					 * XXX: should be configurable. */
77
78static struct rtadvd_timer *prefix_timeout(void *);
79static void makeentry(char *, size_t, int, const char *);
80static size_t dname_labelenc(char *, const char *);
81
82/* Encode domain name label encoding in RFC 1035 Section 3.1 */
83static size_t
84dname_labelenc(char *dst, const char *src)
85{
86	char *dst_origin;
87	char *p;
88	size_t len;
89
90	dst_origin = dst;
91	len = strlen(src);
92
93	/* Length fields per 63 octets + '\0' (<= DNAME_LABELENC_MAXLEN) */
94	memset(dst, 0, len + len / 64 + 1 + 1);
95
96	syslog(LOG_DEBUG, "<%s> labelenc = %s", __func__, src);
97	while (src && (len = strlen(src)) != 0) {
98		/* Put a length field with 63 octet limitation first. */
99		p = strchr(src, '.');
100		if (p == NULL)
101			*dst++ = len = MIN(63, len);
102		else
103			*dst++ = len = MIN(63, p - src);
104		/* Copy 63 octets at most. */
105		memcpy(dst, src, len);
106		dst += len;
107		if (p == NULL) /* the last label */
108			break;
109		src = p + 1;
110	}
111	/* Always need a 0-length label at the tail. */
112	*dst++ = '\0';
113
114	syslog(LOG_DEBUG, "<%s> labellen = %td", __func__, dst - dst_origin);
115	return (dst - dst_origin);
116}
117
118#define	MUSTHAVE(var, cap)						\
119    do {								\
120	int64_t t;							\
121	if ((t = agetnum(cap)) < 0) {					\
122		fprintf(stderr, "rtadvd: need %s for interface %s\n",	\
123			cap, intface);					\
124		exit(1);						\
125	}								\
126	var = t;							\
127     } while (0)
128
129#define	MAYHAVE(var, cap, def)						\
130     do {								\
131	if ((var = agetnum(cap)) < 0)					\
132		var = def;						\
133     } while (0)
134
135int
136loadconfig_index(int idx)
137{
138	char ifname[IFNAMSIZ];
139
140	syslog(LOG_DEBUG, "<%s> enter", __func__);
141
142	if (if_indextoname(idx, ifname) != NULL)
143		return (loadconfig_ifname(ifname));
144	else
145		return (1);
146}
147
148int
149loadconfig_ifname(char *ifname)
150{
151	struct ifinfo *ifi;
152
153	syslog(LOG_DEBUG, "<%s> enter", __func__);
154
155	update_ifinfo(&ifilist, UPDATE_IFINFO_ALL);
156	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
157		/* NULL means all IFs will be processed. */
158		if (ifname != NULL &&
159		    strcmp(ifi->ifi_ifname, ifname) != 0)
160			continue;
161
162		if (!ifi->ifi_persist) {
163			syslog(LOG_INFO,
164			    "<%s> %s is not a target interface.  "
165			    "Ignored at this moment.", __func__,
166			    ifi->ifi_ifname);
167			continue;
168
169		}
170		if (ifi->ifi_ifindex == 0) {
171			syslog(LOG_ERR,
172			    "<%s> %s not found.  "
173			    "Ignored at this moment.", __func__,
174			    ifi->ifi_ifname);
175			continue;
176		}
177		if (getconfig(ifi) == NULL) {
178			syslog(LOG_ERR,
179			    "<%s> invalid configuration for %s.  "
180			    "Ignored at this moment.", __func__,
181			    ifi->ifi_ifname);
182			continue;
183		}
184	}
185	return (0);
186}
187
188int
189rm_ifinfo_index(int idx)
190{
191	struct ifinfo *ifi;
192
193	ifi = if_indextoifinfo(idx);
194	if (ifi == NULL) {
195		syslog(LOG_ERR, "<%s>: ifinfo not found (idx=%d)",
196		    __func__, idx);
197		return (-1);
198	}
199
200	return (rm_ifinfo(ifi));
201}
202
203int
204rm_ifinfo(struct ifinfo *ifi)
205{
206	int error;
207
208	syslog(LOG_DEBUG, "<%s> enter (%s).", __func__, ifi->ifi_ifname);
209	switch (ifi->ifi_state) {
210	case IFI_STATE_UNCONFIGURED:
211		return (0);
212		break;
213	default:
214		ifi->ifi_state = IFI_STATE_UNCONFIGURED;
215		syslog(LOG_DEBUG,
216		    "<%s> ifname=%s marked as UNCONFIGURED.",
217		    __func__, ifi->ifi_ifname);
218
219		/* XXX: No MC leaving here because index is disappeared */
220
221		/* Inactivate timer */
222		rtadvd_remove_timer(ifi->ifi_ra_timer);
223		ifi->ifi_ra_timer = NULL;
224		break;
225	}
226
227	/* clean up ifi */
228	if (!ifi->ifi_persist) {
229		TAILQ_REMOVE(&ifilist, ifi, ifi_next);
230		syslog(LOG_DEBUG, "<%s>: ifinfo (idx=%d) removed.",
231		    __func__, ifi->ifi_ifindex);
232	} else {
233		/* recreate an empty entry */
234		update_persist_ifinfo(&ifilist, ifi->ifi_ifname);
235		syslog(LOG_DEBUG, "<%s>: ifname=%s is persistent.",
236		    __func__, ifi->ifi_ifname);
237	}
238
239	/* clean up rai if any */
240	switch (ifi->ifi_state) {
241	case IFI_STATE_CONFIGURED:
242		if (ifi->ifi_rainfo != NULL) {
243			error = rm_rainfo(ifi->ifi_rainfo);
244			if (error)
245				return (error);
246			ifi->ifi_rainfo = NULL;
247		}
248		break;
249	case IFI_STATE_TRANSITIVE:
250		if (ifi->ifi_rainfo == ifi->ifi_rainfo_trans) {
251			if (ifi->ifi_rainfo != NULL) {
252				error = rm_rainfo(ifi->ifi_rainfo);
253				if (error)
254					return (error);
255				ifi->ifi_rainfo = NULL;
256				ifi->ifi_rainfo_trans = NULL;
257			}
258		} else {
259			if (ifi->ifi_rainfo != NULL) {
260				error = rm_rainfo(ifi->ifi_rainfo);
261				if (error)
262					return (error);
263				ifi->ifi_rainfo = NULL;
264			}
265			if (ifi->ifi_rainfo_trans != NULL) {
266				error = rm_rainfo(ifi->ifi_rainfo_trans);
267				if (error)
268					return (error);
269				ifi->ifi_rainfo_trans = NULL;
270			}
271		}
272	}
273
274	syslog(LOG_DEBUG, "<%s> leave (%s).", __func__, ifi->ifi_ifname);
275	if (!ifi->ifi_persist)
276		free(ifi);
277	return (0);
278}
279
280int
281rm_rainfo(struct rainfo *rai)
282{
283	struct prefix *pfx;
284	struct soliciter *sol;
285	struct rdnss *rdn;
286	struct rdnss_addr *rdna;
287	struct dnssl *dns;
288	struct rtinfo *rti;
289
290	syslog(LOG_DEBUG, "<%s>: enter",  __func__);
291
292	TAILQ_REMOVE(&railist, rai, rai_next);
293	if (rai->rai_ifinfo != NULL)
294		syslog(LOG_DEBUG, "<%s>: rainfo (idx=%d) removed.",
295		    __func__, rai->rai_ifinfo->ifi_ifindex);
296
297	if (rai->rai_ra_data != NULL)
298		free(rai->rai_ra_data);
299
300	while ((pfx = TAILQ_FIRST(&rai->rai_prefix)) != NULL)
301		delete_prefix(pfx);
302	while ((sol = TAILQ_FIRST(&rai->rai_soliciter)) != NULL) {
303		TAILQ_REMOVE(&rai->rai_soliciter, sol, sol_next);
304		free(sol);
305	}
306	while ((rdn = TAILQ_FIRST(&rai->rai_rdnss)) != NULL) {
307		TAILQ_REMOVE(&rai->rai_rdnss, rdn, rd_next);
308		while ((rdna = TAILQ_FIRST(&rdn->rd_list)) != NULL) {
309			TAILQ_REMOVE(&rdn->rd_list, rdna, ra_next);
310			free(rdna);
311		}
312		free(rdn);
313	}
314	while ((dns = TAILQ_FIRST(&rai->rai_dnssl)) != NULL) {
315		TAILQ_REMOVE(&rai->rai_dnssl, dns, dn_next);
316		free(dns);
317	}
318	while ((rti = TAILQ_FIRST(&rai->rai_route)) != NULL) {
319		TAILQ_REMOVE(&rai->rai_route, rti, rti_next);
320		free(rti);
321	}
322	free(rai);
323	syslog(LOG_DEBUG, "<%s>: leave",  __func__);
324
325	return (0);
326}
327
328struct ifinfo *
329getconfig(struct ifinfo *ifi)
330{
331	int stat, i;
332	int error;
333	char tbuf[BUFSIZ];
334	struct rainfo *rai;
335	struct rainfo *rai_old;
336	int32_t val;
337	int64_t val64;
338	char buf[BUFSIZ];
339	char *bp = buf;
340	char *addr, *flagstr;
341
342	if (ifi == NULL)	/* if does not exist */
343		return (NULL);
344
345	if (ifi->ifi_state == IFI_STATE_TRANSITIVE &&
346	    ifi->ifi_rainfo == NULL) {
347		syslog(LOG_INFO, "<%s> %s is shutting down.  Skipped.",
348		    __func__, ifi->ifi_ifname);
349		return (NULL);
350	}
351
352	if ((stat = agetent(tbuf, ifi->ifi_ifname)) <= 0) {
353		memset(tbuf, 0, sizeof(tbuf));
354		syslog(LOG_INFO,
355		    "<%s> %s isn't defined in the configuration file"
356		    " or the configuration file doesn't exist."
357		    " Treat it as default",
358		     __func__, ifi->ifi_ifname);
359	}
360
361	ELM_MALLOC(rai, exit(1));
362	TAILQ_INIT(&rai->rai_prefix);
363	TAILQ_INIT(&rai->rai_route);
364	TAILQ_INIT(&rai->rai_rdnss);
365	TAILQ_INIT(&rai->rai_dnssl);
366	TAILQ_INIT(&rai->rai_soliciter);
367	rai->rai_ifinfo = ifi;
368
369	/* gather on-link prefixes from the network interfaces. */
370	if (agetflag("noifprefix"))
371		rai->rai_advifprefix = 0;
372	else
373		rai->rai_advifprefix = 1;
374
375	/* get interface information */
376	if (agetflag("nolladdr"))
377		rai->rai_advlinkopt = 0;
378	else
379		rai->rai_advlinkopt = 1;
380	if (rai->rai_advlinkopt) {
381		if (ifi->ifi_sdl.sdl_type == 0) {
382			syslog(LOG_ERR,
383			    "<%s> can't get information of %s",
384			    __func__, ifi->ifi_ifname);
385			goto getconfig_free_rai;
386		}
387	}
388
389	/*
390	 * set router configuration variables.
391	 */
392	MAYHAVE(val, "maxinterval", DEF_MAXRTRADVINTERVAL);
393	if (val < MIN_MAXINTERVAL || val > MAX_MAXINTERVAL) {
394		syslog(LOG_ERR,
395		    "<%s> maxinterval (%" PRIu32 ") on %s is invalid "
396		    "(must be between %u and %u)", __func__, val,
397		    ifi->ifi_ifname, MIN_MAXINTERVAL, MAX_MAXINTERVAL);
398		goto getconfig_free_rai;
399	}
400	rai->rai_maxinterval = (uint16_t)val;
401
402	MAYHAVE(val, "mininterval", rai->rai_maxinterval/3);
403	if ((uint16_t)val < MIN_MININTERVAL ||
404	    (uint16_t)val > (rai->rai_maxinterval * 3) / 4) {
405		syslog(LOG_ERR,
406		    "<%s> mininterval (%" PRIu32 ") on %s is invalid "
407		    "(must be between %d and %d)",
408		    __func__, val, ifi->ifi_ifname, MIN_MININTERVAL,
409		    (rai->rai_maxinterval * 3) / 4);
410		goto getconfig_free_rai;
411	}
412	rai->rai_mininterval = (uint16_t)val;
413
414	MAYHAVE(val, "chlim", DEF_ADVCURHOPLIMIT);
415	rai->rai_hoplimit = val & 0xff;
416
417	if ((flagstr = (char *)agetstr("raflags", &bp))) {
418		val = 0;
419		if (strchr(flagstr, 'm'))
420			val |= ND_RA_FLAG_MANAGED;
421		if (strchr(flagstr, 'o'))
422			val |= ND_RA_FLAG_OTHER;
423		if (strchr(flagstr, 'h'))
424			val |= ND_RA_FLAG_RTPREF_HIGH;
425		if (strchr(flagstr, 'l')) {
426			if ((val & ND_RA_FLAG_RTPREF_HIGH)) {
427				syslog(LOG_ERR, "<%s> the \'h\' and \'l\'"
428				    " router flags are exclusive", __func__);
429				goto getconfig_free_rai;
430			}
431			val |= ND_RA_FLAG_RTPREF_LOW;
432		}
433	} else
434		MAYHAVE(val, "raflags", 0);
435
436	rai->rai_managedflg = val & ND_RA_FLAG_MANAGED;
437	rai->rai_otherflg = val & ND_RA_FLAG_OTHER;
438#ifndef ND_RA_FLAG_RTPREF_MASK
439#define ND_RA_FLAG_RTPREF_MASK	0x18 /* 00011000 */
440#define ND_RA_FLAG_RTPREF_RSV	0x10 /* 00010000 */
441#endif
442	rai->rai_rtpref = val & ND_RA_FLAG_RTPREF_MASK;
443	if (rai->rai_rtpref == ND_RA_FLAG_RTPREF_RSV) {
444		syslog(LOG_ERR, "<%s> invalid router preference (%02x) on %s",
445		    __func__, rai->rai_rtpref, ifi->ifi_ifname);
446		goto getconfig_free_rai;
447	}
448
449	MAYHAVE(val, "rltime", rai->rai_maxinterval * 3);
450	if ((uint16_t)val && ((uint16_t)val < rai->rai_maxinterval ||
451	    (uint16_t)val > MAXROUTERLIFETIME)) {
452		syslog(LOG_ERR,
453		    "<%s> router lifetime (%" PRIu32 ") on %s is invalid "
454		    "(must be 0 or between %d and %d)",
455		    __func__, val, ifi->ifi_ifname, rai->rai_maxinterval,
456		    MAXROUTERLIFETIME);
457		goto getconfig_free_rai;
458	}
459	rai->rai_lifetime = val & 0xffff;
460
461	MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
462	if (val < 0 || val > MAXREACHABLETIME) {
463		syslog(LOG_ERR,
464		    "<%s> reachable time (%" PRIu32 ") on %s is invalid "
465		    "(must be no greater than %d)",
466		    __func__, val, ifi->ifi_ifname, MAXREACHABLETIME);
467		goto getconfig_free_rai;
468	}
469	rai->rai_reachabletime = (uint32_t)val;
470
471	MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER);
472	if (val64 < 0 || val64 > 0xffffffff) {
473		syslog(LOG_ERR, "<%s> retrans time (%" PRIu64 ") on %s out of range",
474		    __func__, val64, ifi->ifi_ifname);
475		goto getconfig_free_rai;
476	}
477	rai->rai_retranstimer = (uint32_t)val64;
478
479	if (agetnum("hapref") != -1 || agetnum("hatime") != -1) {
480		syslog(LOG_ERR,
481		    "<%s> mobile-ip6 configuration not supported",
482		    __func__);
483		goto getconfig_free_rai;
484	}
485	/* prefix information */
486
487	/*
488	 * This is an implementation specific parameter to consider
489	 * link propagation delays and poorly synchronized clocks when
490	 * checking consistency of advertised lifetimes.
491	 */
492	MAYHAVE(val, "clockskew", 0);
493	rai->rai_clockskew = val;
494
495	rai->rai_pfxs = 0;
496	for (i = -1; i < MAXPREFIX; i++) {
497		struct prefix *pfx;
498
499		makeentry(entbuf, sizeof(entbuf), i, "addr");
500		addr = (char *)agetstr(entbuf, &bp);
501		if (addr == NULL)
502			continue;
503
504		/* allocate memory to store prefix information */
505		ELM_MALLOC(pfx, exit(1));
506		pfx->pfx_rainfo = rai;
507		pfx->pfx_origin = PREFIX_FROM_CONFIG;
508
509		if (inet_pton(AF_INET6, addr, &pfx->pfx_prefix) != 1) {
510			syslog(LOG_ERR,
511			    "<%s> inet_pton failed for %s",
512			    __func__, addr);
513			goto getconfig_free_pfx;
514		}
515		if (IN6_IS_ADDR_MULTICAST(&pfx->pfx_prefix)) {
516			syslog(LOG_ERR,
517			    "<%s> multicast prefix (%s) must "
518			    "not be advertised on %s",
519			    __func__, addr, ifi->ifi_ifname);
520			goto getconfig_free_pfx;
521		}
522		if (IN6_IS_ADDR_LINKLOCAL(&pfx->pfx_prefix))
523			syslog(LOG_NOTICE,
524			    "<%s> link-local prefix (%s) will be"
525			    " advertised on %s",
526			    __func__, addr, ifi->ifi_ifname);
527
528		makeentry(entbuf, sizeof(entbuf), i, "prefixlen");
529		MAYHAVE(val, entbuf, 64);
530		if (val < 0 || val > 128) {
531			syslog(LOG_ERR, "<%s> prefixlen (%" PRIu32 ") for %s "
532			    "on %s out of range",
533			    __func__, val, addr, ifi->ifi_ifname);
534			goto getconfig_free_pfx;
535		}
536		pfx->pfx_prefixlen = (int)val;
537
538		makeentry(entbuf, sizeof(entbuf), i, "pinfoflags");
539		if ((flagstr = (char *)agetstr(entbuf, &bp))) {
540			val = 0;
541			if (strchr(flagstr, 'l'))
542				val |= ND_OPT_PI_FLAG_ONLINK;
543			if (strchr(flagstr, 'a'))
544				val |= ND_OPT_PI_FLAG_AUTO;
545		} else {
546			MAYHAVE(val, entbuf,
547			    (ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO));
548		}
549		pfx->pfx_onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
550		pfx->pfx_autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
551
552		makeentry(entbuf, sizeof(entbuf), i, "vltime");
553		MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
554		if (val64 < 0 || val64 > 0xffffffff) {
555			syslog(LOG_ERR, "<%s> vltime (%" PRIu64 ") for "
556			    "%s/%d on %s is out of range",
557			    __func__, val64,
558			    addr, pfx->pfx_prefixlen, ifi->ifi_ifname);
559			goto getconfig_free_pfx;
560		}
561		pfx->pfx_validlifetime = (uint32_t)val64;
562
563		makeentry(entbuf, sizeof(entbuf), i, "vltimedecr");
564		if (agetflag(entbuf)) {
565			struct timespec now;
566
567			clock_gettime(CLOCK_MONOTONIC_FAST, &now);
568			pfx->pfx_vltimeexpire =
569				now.tv_sec + pfx->pfx_validlifetime;
570		}
571
572		makeentry(entbuf, sizeof(entbuf), i, "pltime");
573		MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
574		if (val64 < 0 || val64 > 0xffffffff) {
575			syslog(LOG_ERR,
576			    "<%s> pltime (%" PRIu64 ") for %s/%d on %s "
577			    "is out of range",
578			    __func__, val64,
579			    addr, pfx->pfx_prefixlen, ifi->ifi_ifname);
580			goto getconfig_free_pfx;
581		}
582		pfx->pfx_preflifetime = (uint32_t)val64;
583
584		makeentry(entbuf, sizeof(entbuf), i, "pltimedecr");
585		if (agetflag(entbuf)) {
586			struct timespec now;
587
588			clock_gettime(CLOCK_MONOTONIC_FAST, &now);
589			pfx->pfx_pltimeexpire =
590			    now.tv_sec + pfx->pfx_preflifetime;
591		}
592		/* link into chain */
593		TAILQ_INSERT_TAIL(&rai->rai_prefix, pfx, pfx_next);
594		rai->rai_pfxs++;
595		continue;
596getconfig_free_pfx:
597		free(pfx);
598	}
599	if (rai->rai_advifprefix && rai->rai_pfxs == 0)
600		get_prefix(rai);
601
602	MAYHAVE(val64, "mtu", 0);
603	if (val < 0 || val64 > 0xffffffff) {
604		syslog(LOG_ERR,
605		    "<%s> mtu (%" PRIu64 ") on %s out of range",
606		    __func__, val64, ifi->ifi_ifname);
607		goto getconfig_free_rai;
608	}
609	rai->rai_linkmtu = (uint32_t)val64;
610	if (rai->rai_linkmtu == 0) {
611		char *mtustr;
612
613		if ((mtustr = (char *)agetstr("mtu", &bp)) &&
614		    strcmp(mtustr, "auto") == 0)
615			rai->rai_linkmtu = ifi->ifi_phymtu;
616	}
617	else if (rai->rai_linkmtu < IPV6_MMTU ||
618	    rai->rai_linkmtu > ifi->ifi_phymtu) {
619		syslog(LOG_ERR,
620		    "<%s> advertised link mtu (%" PRIu32 ") on %s is invalid (must "
621		    "be between least MTU (%d) and physical link MTU (%d)",
622		    __func__, rai->rai_linkmtu, ifi->ifi_ifname,
623		    IPV6_MMTU, ifi->ifi_phymtu);
624		goto getconfig_free_rai;
625	}
626
627#ifdef SIOCSIFINFO_IN6
628	{
629		struct in6_ndireq ndi;
630		int s;
631
632		if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
633			syslog(LOG_ERR, "<%s> socket: %s", __func__,
634			    strerror(errno));
635			exit(1);
636		}
637		memset(&ndi, 0, sizeof(ndi));
638		strlcpy(ndi.ifname, ifi->ifi_ifname, sizeof(ndi.ifname));
639		if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&ndi) < 0)
640			syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s",
641			    __func__, ifi->ifi_ifname, strerror(errno));
642
643		/* reflect the RA info to the host variables in kernel */
644		ndi.ndi.chlim = rai->rai_hoplimit;
645		ndi.ndi.retrans = rai->rai_retranstimer;
646		ndi.ndi.basereachable = rai->rai_reachabletime;
647		if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&ndi) < 0)
648			syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s",
649			    __func__, ifi->ifi_ifname, strerror(errno));
650
651		close(s);
652	}
653#endif
654
655	/* route information */
656	rai->rai_routes = 0;
657	for (i = -1; i < MAXROUTE; i++) {
658		struct rtinfo *rti;
659
660		makeentry(entbuf, sizeof(entbuf), i, "rtprefix");
661		addr = (char *)agetstr(entbuf, &bp);
662		if (addr == NULL) {
663			makeentry(oentbuf, sizeof(oentbuf), i, "rtrprefix");
664			addr = (char *)agetstr(oentbuf, &bp);
665			if (addr)
666				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
667				    oentbuf, entbuf);
668		}
669		if (addr == NULL)
670			continue;
671
672		/* allocate memory to store prefix information */
673		ELM_MALLOC(rti, exit(1));
674
675		if (inet_pton(AF_INET6, addr, &rti->rti_prefix) != 1) {
676			syslog(LOG_ERR, "<%s> inet_pton failed for %s",
677			    __func__, addr);
678			goto getconfig_free_rti;
679		}
680#if 0
681		/*
682		 * XXX: currently there's no restriction in route information
683		 * prefix according to
684		 * draft-ietf-ipngwg-router-selection-00.txt.
685		 * However, I think the similar restriction be necessary.
686		 */
687		MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
688		if (IN6_IS_ADDR_MULTICAST(&rti->prefix)) {
689			syslog(LOG_ERR,
690			    "<%s> multicast route (%s) must "
691			    "not be advertised on %s",
692			    __func__, addr, ifi->ifi_ifname);
693			goto getconfig_free_rti;
694		}
695		if (IN6_IS_ADDR_LINKLOCAL(&rti->prefix)) {
696			syslog(LOG_NOTICE,
697			    "<%s> link-local route (%s) will "
698			    "be advertised on %s",
699			    __func__, addr, ifi->ifi_ifname);
700			goto getconfig_free_rti;
701		}
702#endif
703
704		makeentry(entbuf, sizeof(entbuf), i, "rtplen");
705		/* XXX: 256 is a magic number for compatibility check. */
706		MAYHAVE(val, entbuf, 256);
707		if (val == 256) {
708			makeentry(oentbuf, sizeof(oentbuf), i, "rtrplen");
709			MAYHAVE(val, oentbuf, 256);
710			if (val != 256)
711				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
712				    oentbuf, entbuf);
713			else
714				val = 64;
715		}
716		if (val < 0 || val > 128) {
717			syslog(LOG_ERR, "<%s> prefixlen (%" PRIu32 ") for %s on %s "
718			    "out of range",
719			    __func__, val, addr, ifi->ifi_ifname);
720			goto getconfig_free_rti;
721		}
722		rti->rti_prefixlen = (int)val;
723
724		makeentry(entbuf, sizeof(entbuf), i, "rtflags");
725		if ((flagstr = (char *)agetstr(entbuf, &bp))) {
726			val = 0;
727			if (strchr(flagstr, 'h'))
728				val |= ND_RA_FLAG_RTPREF_HIGH;
729			if (strchr(flagstr, 'l')) {
730				if ((val & ND_RA_FLAG_RTPREF_HIGH)) {
731					syslog(LOG_ERR,
732					    "<%s> the \'h\' and \'l\' route"
733					    " preferences are exclusive",
734					    __func__);
735					goto getconfig_free_rti;
736				}
737				val |= ND_RA_FLAG_RTPREF_LOW;
738			}
739		} else
740			MAYHAVE(val, entbuf, 256); /* XXX */
741		if (val == 256) {
742			makeentry(oentbuf, sizeof(oentbuf), i, "rtrflags");
743			MAYHAVE(val, oentbuf, 256);
744			if (val != 256) {
745				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
746				    oentbuf, entbuf);
747			} else
748				val = 0;
749		}
750		rti->rti_rtpref = val & ND_RA_FLAG_RTPREF_MASK;
751		if (rti->rti_rtpref == ND_RA_FLAG_RTPREF_RSV) {
752			syslog(LOG_ERR, "<%s> invalid route preference (%02x) "
753			    "for %s/%d on %s",
754			    __func__, rti->rti_rtpref, addr,
755			    rti->rti_prefixlen, ifi->ifi_ifname);
756			goto getconfig_free_rti;
757		}
758
759		/*
760		 * Since the spec does not a default value, we should make
761		 * this entry mandatory.  However, FreeBSD 4.4 has shipped
762		 * with this field being optional, we use the router lifetime
763		 * as an ad-hoc default value with a warning message.
764		 */
765		makeentry(entbuf, sizeof(entbuf), i, "rtltime");
766		MAYHAVE(val64, entbuf, -1);
767		if (val64 == -1) {
768			makeentry(oentbuf, sizeof(oentbuf), i, "rtrltime");
769			MAYHAVE(val64, oentbuf, -1);
770			if (val64 != -1)
771				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
772				    oentbuf, entbuf);
773			else {
774				fprintf(stderr, "%s should be specified "
775				    "for interface %s.\n", entbuf,
776				    ifi->ifi_ifname);
777				val64 = rai->rai_lifetime;
778			}
779		}
780		if (val64 < 0 || val64 > 0xffffffff) {
781			syslog(LOG_ERR, "<%s> route lifetime (%" PRIu64 ") for "
782			    "%s/%d on %s out of range", __func__,
783			    val64, addr, rti->rti_prefixlen,
784			    ifi->ifi_ifname);
785			goto getconfig_free_rti;
786		}
787		rti->rti_ltime = (uint32_t)val64;
788
789		/* link into chain */
790		TAILQ_INSERT_TAIL(&rai->rai_route, rti, rti_next);
791		rai->rai_routes++;
792		continue;
793getconfig_free_rti:
794		free(rti);
795	}
796
797	/* DNS server and DNS search list information */
798	for (i = -1; i < MAXRDNSSENT ; i++) {
799		struct rdnss *rdn;
800		struct rdnss_addr *rdna;
801		char *ap;
802		int c;
803
804		makeentry(entbuf, sizeof(entbuf), i, "rdnss");
805		addr = (char *)agetstr(entbuf, &bp);
806		if (addr == NULL)
807			break;
808		ELM_MALLOC(rdn, exit(1));
809
810		TAILQ_INIT(&rdn->rd_list);
811
812		for (ap = addr; ap - addr < (ssize_t)strlen(addr); ap += c+1) {
813			c = strcspn(ap, ",");
814			strncpy(abuf, ap, c);
815			abuf[c] = '\0';
816			ELM_MALLOC(rdna, goto getconfig_free_rdn);
817			if (inet_pton(AF_INET6, abuf, &rdna->ra_dns) != 1) {
818				syslog(LOG_ERR, "<%s> inet_pton failed for %s",
819				    __func__, abuf);
820				free(rdna);
821				goto getconfig_free_rdn;
822			}
823			TAILQ_INSERT_TAIL(&rdn->rd_list, rdna, ra_next);
824		}
825
826		makeentry(entbuf, sizeof(entbuf), i, "rdnssltime");
827		MAYHAVE(val, entbuf, (rai->rai_maxinterval * 3 / 2));
828		if ((uint16_t)val < rai->rai_maxinterval ||
829		    (uint16_t)val > rai->rai_maxinterval * 2) {
830			syslog(LOG_ERR, "%s (%" PRIu16 ") on %s is invalid "
831			    "(must be between %d and %d)",
832			    entbuf, val, ifi->ifi_ifname, rai->rai_maxinterval,
833			    rai->rai_maxinterval * 2);
834			goto getconfig_free_rdn;
835		}
836		rdn->rd_ltime = val;
837
838		/* link into chain */
839		TAILQ_INSERT_TAIL(&rai->rai_rdnss, rdn, rd_next);
840		continue;
841getconfig_free_rdn:
842		while ((rdna = TAILQ_FIRST(&rdn->rd_list)) != NULL) {
843			TAILQ_REMOVE(&rdn->rd_list, rdna, ra_next);
844			free(rdna);
845		}
846		free(rdn);
847	}
848
849	for (i = -1; i < MAXDNSSLENT ; i++) {
850		struct dnssl *dns;
851		struct dnssl_addr *dnsa;
852		char *ap;
853		int c;
854
855		makeentry(entbuf, sizeof(entbuf), i, "dnssl");
856		addr = (char *)agetstr(entbuf, &bp);
857		if (addr == NULL)
858			break;
859
860		ELM_MALLOC(dns, exit(1));
861
862		TAILQ_INIT(&dns->dn_list);
863
864		for (ap = addr; ap - addr < (ssize_t)strlen(addr); ap += c+1) {
865			c = strcspn(ap, ",");
866			strncpy(abuf, ap, c);
867			abuf[c] = '\0';
868			ELM_MALLOC(dnsa, goto getconfig_free_dns);
869			dnsa->da_len = dname_labelenc(dnsa->da_dom, abuf);
870			syslog(LOG_DEBUG, "<%s>: dnsa->da_len = %d", __func__,
871			    dnsa->da_len);
872			TAILQ_INSERT_TAIL(&dns->dn_list, dnsa, da_next);
873		}
874
875		makeentry(entbuf, sizeof(entbuf), i, "dnsslltime");
876		MAYHAVE(val, entbuf, (rai->rai_maxinterval * 3 / 2));
877		if ((uint16_t)val < rai->rai_maxinterval ||
878		    (uint16_t)val > rai->rai_maxinterval * 2) {
879			syslog(LOG_ERR, "%s (%" PRIu16 ") on %s is invalid "
880			    "(must be between %d and %d)",
881			    entbuf, val, ifi->ifi_ifname, rai->rai_maxinterval,
882			    rai->rai_maxinterval * 2);
883			goto getconfig_free_dns;
884		}
885		dns->dn_ltime = val;
886
887		/* link into chain */
888		TAILQ_INSERT_TAIL(&rai->rai_dnssl, dns, dn_next);
889		continue;
890getconfig_free_dns:
891		while ((dnsa = TAILQ_FIRST(&dns->dn_list)) != NULL) {
892			TAILQ_REMOVE(&dns->dn_list, dnsa, da_next);
893			free(dnsa);
894		}
895		free(dns);
896	}
897	/* construct the sending packet */
898	make_packet(rai);
899
900	/*
901	 * If an entry with the same ifindex exists, remove it first.
902	 * Before the removal, RDNSS and DNSSL options with
903	 * zero-lifetime will be sent.
904	 */
905	switch (ifi->ifi_state) {
906	case IFI_STATE_UNCONFIGURED:
907		/* UNCONFIGURED -> TRANSITIVE */
908
909		error = sock_mc_join(&sock, ifi->ifi_ifindex);
910		if (error)
911			exit(1);
912
913		ifi->ifi_state = IFI_STATE_TRANSITIVE;
914		ifi->ifi_burstcount = MAX_INITIAL_RTR_ADVERTISEMENTS;
915		ifi->ifi_burstinterval = MAX_INITIAL_RTR_ADVERT_INTERVAL;
916
917		/* The same two rai mean initial burst */
918		ifi->ifi_rainfo = rai;
919		ifi->ifi_rainfo_trans = rai;
920		TAILQ_INSERT_TAIL(&railist, rai, rai_next);
921
922		if (ifi->ifi_ra_timer == NULL)
923			ifi->ifi_ra_timer = rtadvd_add_timer(ra_timeout,
924			    ra_timer_update, ifi, ifi);
925		ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm);
926		rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm,
927		    ifi->ifi_ra_timer);
928
929		syslog(LOG_DEBUG,
930		    "<%s> ifname=%s marked as TRANSITIVE (initial burst).",
931		    __func__, ifi->ifi_ifname);
932		break;
933	case IFI_STATE_CONFIGURED:
934		/* CONFIGURED -> TRANSITIVE */
935		rai_old = ifi->ifi_rainfo;
936		if (rai_old == NULL) {
937			syslog(LOG_ERR,
938			    "<%s> ifi_rainfo is NULL"
939			    " in IFI_STATE_CONFIGURED.", __func__);
940			ifi = NULL;
941			break;
942		} else {
943			struct rdnss *rdn;
944			struct dnssl *dns;
945
946			rai_old->rai_lifetime = 0;
947			TAILQ_FOREACH(rdn, &rai_old->rai_rdnss, rd_next)
948			    rdn->rd_ltime = 0;
949			TAILQ_FOREACH(dns, &rai_old->rai_dnssl, dn_next)
950			    dns->dn_ltime = 0;
951
952			ifi->ifi_rainfo_trans = rai_old;
953			ifi->ifi_state = IFI_STATE_TRANSITIVE;
954			ifi->ifi_burstcount = MAX_FINAL_RTR_ADVERTISEMENTS;
955			ifi->ifi_burstinterval = MIN_DELAY_BETWEEN_RAS;
956
957			ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm);
958			rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm,
959			    ifi->ifi_ra_timer);
960
961			syslog(LOG_DEBUG,
962			    "<%s> ifname=%s marked as TRANSITIVE"
963			    " (transitional burst)",
964			    __func__, ifi->ifi_ifname);
965		}
966		ifi->ifi_rainfo = rai;
967		TAILQ_INSERT_TAIL(&railist, rai, rai_next);
968		break;
969	case IFI_STATE_TRANSITIVE:
970		if (ifi->ifi_rainfo != NULL) {
971			if (ifi->ifi_rainfo == ifi->ifi_rainfo_trans) {
972				/* Reinitialize initial burst */
973				rm_rainfo(ifi->ifi_rainfo);
974				ifi->ifi_rainfo = rai;
975				ifi->ifi_rainfo_trans = rai;
976				ifi->ifi_burstcount =
977				    MAX_INITIAL_RTR_ADVERTISEMENTS;
978				ifi->ifi_burstinterval =
979				    MAX_INITIAL_RTR_ADVERT_INTERVAL;
980			} else {
981				/* Replace ifi_rainfo with the new one */
982				rm_rainfo(ifi->ifi_rainfo);
983				ifi->ifi_rainfo = rai;
984			}
985			TAILQ_INSERT_TAIL(&railist, rai, rai_next);
986
987			ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm);
988			rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm,
989			    ifi->ifi_ra_timer);
990		} else {
991			/* XXX: NOTREACHED.  Being shut down. */
992			syslog(LOG_ERR,
993			    "<%s> %s is shutting down.  Skipped.",
994			    __func__, ifi->ifi_ifname);
995			rm_rainfo(rai);
996
997			return (NULL);
998		}
999		break;
1000	}
1001
1002	return (ifi);
1003
1004getconfig_free_rai:
1005	free(rai);
1006	return (NULL);
1007}
1008
1009void
1010get_prefix(struct rainfo *rai)
1011{
1012	struct ifaddrs *ifap, *ifa;
1013	struct prefix *pfx;
1014	struct in6_addr *a;
1015	struct ifinfo *ifi;
1016	char *p, *ep, *m, *lim;
1017	char ntopbuf[INET6_ADDRSTRLEN];
1018
1019	if (getifaddrs(&ifap) < 0) {
1020		syslog(LOG_ERR,
1021		    "<%s> can't get interface addresses",
1022		    __func__);
1023		exit(1);
1024	}
1025	ifi = rai->rai_ifinfo;
1026
1027	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1028		int plen;
1029
1030		if (strcmp(ifa->ifa_name, ifi->ifi_ifname) != 0)
1031			continue;
1032		if (ifa->ifa_addr->sa_family != AF_INET6)
1033			continue;
1034		a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
1035		if (IN6_IS_ADDR_LINKLOCAL(a))
1036			continue;
1037
1038		/* get prefix length */
1039		m = (char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
1040		lim = (char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len;
1041		plen = prefixlen(m, lim);
1042		if (plen <= 0 || plen > 128) {
1043			syslog(LOG_ERR, "<%s> failed to get prefixlen "
1044			    "or prefix is invalid",
1045			    __func__);
1046			exit(1);
1047		}
1048		if (plen == 128)	/* XXX */
1049			continue;
1050		if (find_prefix(rai, a, plen)) {
1051			/* ignore a duplicated prefix. */
1052			continue;
1053		}
1054
1055		/* allocate memory to store prefix info. */
1056		ELM_MALLOC(pfx, exit(1));
1057
1058		/* set prefix, sweep bits outside of prefixlen */
1059		pfx->pfx_prefixlen = plen;
1060		memcpy(&pfx->pfx_prefix, a, sizeof(*a));
1061		p = (char *)&pfx->pfx_prefix;
1062		ep = (char *)(&pfx->pfx_prefix + 1);
1063		while (m < lim && p < ep)
1064			*p++ &= *m++;
1065		while (p < ep)
1066			*p++ = 0x00;
1067	        if (!inet_ntop(AF_INET6, &pfx->pfx_prefix, ntopbuf,
1068	            sizeof(ntopbuf))) {
1069			syslog(LOG_ERR, "<%s> inet_ntop failed", __func__);
1070			exit(1);
1071		}
1072		syslog(LOG_DEBUG,
1073		    "<%s> add %s/%d to prefix list on %s",
1074		    __func__, ntopbuf, pfx->pfx_prefixlen, ifi->ifi_ifname);
1075
1076		/* set other fields with protocol defaults */
1077		pfx->pfx_validlifetime = DEF_ADVVALIDLIFETIME;
1078		pfx->pfx_preflifetime = DEF_ADVPREFERREDLIFETIME;
1079		pfx->pfx_onlinkflg = 1;
1080		pfx->pfx_autoconfflg = 1;
1081		pfx->pfx_origin = PREFIX_FROM_KERNEL;
1082		pfx->pfx_rainfo = rai;
1083
1084		/* link into chain */
1085		TAILQ_INSERT_TAIL(&rai->rai_prefix, pfx, pfx_next);
1086
1087		/* counter increment */
1088		rai->rai_pfxs++;
1089	}
1090
1091	freeifaddrs(ifap);
1092}
1093
1094static void
1095makeentry(char *buf, size_t len, int id, const char *string)
1096{
1097
1098	if (id < 0)
1099		strlcpy(buf, string, len);
1100	else
1101		snprintf(buf, len, "%s%d", string, id);
1102}
1103
1104/*
1105 * Add a prefix to the list of specified interface and reconstruct
1106 * the outgoing packet.
1107 * The prefix must not be in the list.
1108 * XXX: other parameters of the prefix (e.g. lifetime) should be
1109 * able to be specified.
1110 */
1111static void
1112add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
1113{
1114	struct prefix *pfx;
1115	struct ifinfo *ifi;
1116	char ntopbuf[INET6_ADDRSTRLEN];
1117
1118	ifi = rai->rai_ifinfo;
1119	ELM_MALLOC(pfx, return);
1120	pfx->pfx_prefix = ipr->ipr_prefix.sin6_addr;
1121	pfx->pfx_prefixlen = ipr->ipr_plen;
1122	pfx->pfx_validlifetime = ipr->ipr_vltime;
1123	pfx->pfx_preflifetime = ipr->ipr_pltime;
1124	pfx->pfx_onlinkflg = ipr->ipr_raf_onlink;
1125	pfx->pfx_autoconfflg = ipr->ipr_raf_auto;
1126	pfx->pfx_origin = PREFIX_FROM_DYNAMIC;
1127	pfx->pfx_rainfo = rai;
1128
1129	TAILQ_INSERT_TAIL(&rai->rai_prefix, pfx, pfx_next);
1130
1131	syslog(LOG_DEBUG, "<%s> new prefix %s/%d was added on %s",
1132	    __func__,
1133	    inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr, ntopbuf,
1134		sizeof(ntopbuf)), ipr->ipr_plen, ifi->ifi_ifname);
1135
1136	rai->rai_pfxs++;
1137}
1138
1139/*
1140 * Delete a prefix to the list of specified interface and reconstruct
1141 * the outgoing packet.
1142 * The prefix must be in the list.
1143 */
1144void
1145delete_prefix(struct prefix *pfx)
1146{
1147	struct rainfo *rai;
1148	struct ifinfo *ifi;
1149	char ntopbuf[INET6_ADDRSTRLEN];
1150
1151	rai = pfx->pfx_rainfo;
1152	ifi = rai->rai_ifinfo;
1153	TAILQ_REMOVE(&rai->rai_prefix, pfx, pfx_next);
1154	syslog(LOG_DEBUG, "<%s> prefix %s/%d was deleted on %s",
1155	    __func__,
1156	    inet_ntop(AF_INET6, &pfx->pfx_prefix, ntopbuf,
1157		sizeof(ntopbuf)), pfx->pfx_prefixlen, ifi->ifi_ifname);
1158	if (pfx->pfx_timer)
1159		rtadvd_remove_timer(pfx->pfx_timer);
1160	free(pfx);
1161
1162	rai->rai_pfxs--;
1163}
1164
1165void
1166invalidate_prefix(struct prefix *pfx)
1167{
1168	struct timespec timo;
1169	struct rainfo *rai;
1170	struct ifinfo *ifi;
1171	char ntopbuf[INET6_ADDRSTRLEN];
1172
1173	rai = pfx->pfx_rainfo;
1174	ifi = rai->rai_ifinfo;
1175	if (pfx->pfx_timer) {	/* sanity check */
1176		syslog(LOG_ERR,
1177		    "<%s> assumption failure: timer already exists",
1178		    __func__);
1179		exit(1);
1180	}
1181
1182	syslog(LOG_DEBUG, "<%s> prefix %s/%d was invalidated on %s, "
1183	    "will expire in %ld seconds", __func__,
1184	    inet_ntop(AF_INET6, &pfx->pfx_prefix, ntopbuf, sizeof(ntopbuf)),
1185	    pfx->pfx_prefixlen, ifi->ifi_ifname, (long)prefix_timo);
1186
1187	/* set the expiration timer */
1188	pfx->pfx_timer = rtadvd_add_timer(prefix_timeout, NULL, pfx, NULL);
1189	if (pfx->pfx_timer == NULL) {
1190		syslog(LOG_ERR, "<%s> failed to add a timer for a prefix. "
1191		    "remove the prefix", __func__);
1192		delete_prefix(pfx);
1193	}
1194	timo.tv_sec = prefix_timo;
1195	timo.tv_nsec = 0;
1196	rtadvd_set_timer(&timo, pfx->pfx_timer);
1197}
1198
1199static struct rtadvd_timer *
1200prefix_timeout(void *arg)
1201{
1202
1203	delete_prefix((struct prefix *)arg);
1204
1205	return (NULL);
1206}
1207
1208void
1209update_prefix(struct prefix *pfx)
1210{
1211	struct rainfo *rai;
1212	struct ifinfo *ifi;
1213	char ntopbuf[INET6_ADDRSTRLEN];
1214
1215	rai = pfx->pfx_rainfo;
1216	ifi = rai->rai_ifinfo;
1217	if (pfx->pfx_timer == NULL) { /* sanity check */
1218		syslog(LOG_ERR,
1219		    "<%s> assumption failure: timer does not exist",
1220		    __func__);
1221		exit(1);
1222	}
1223
1224	syslog(LOG_DEBUG, "<%s> prefix %s/%d was re-enabled on %s",
1225	    __func__, inet_ntop(AF_INET6, &pfx->pfx_prefix, ntopbuf,
1226		sizeof(ntopbuf)), pfx->pfx_prefixlen, ifi->ifi_ifname);
1227
1228	/* stop the expiration timer */
1229	rtadvd_remove_timer(pfx->pfx_timer);
1230	pfx->pfx_timer = NULL;
1231}
1232
1233/*
1234 * Try to get an in6_prefixreq contents for a prefix which matches
1235 * ipr->ipr_prefix and ipr->ipr_plen and belongs to
1236 * the interface whose name is ipr->ipr_name[].
1237 */
1238static int
1239init_prefix(struct in6_prefixreq *ipr)
1240{
1241#if 0
1242	int s;
1243
1244	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1245		syslog(LOG_ERR, "<%s> socket: %s", __func__,
1246		    strerror(errno));
1247		exit(1);
1248	}
1249
1250	if (ioctl(s, SIOCGIFPREFIX_IN6, (caddr_t)ipr) < 0) {
1251		syslog(LOG_INFO, "<%s> ioctl:SIOCGIFPREFIX %s", __func__,
1252		    strerror(errno));
1253
1254		ipr->ipr_vltime = DEF_ADVVALIDLIFETIME;
1255		ipr->ipr_pltime = DEF_ADVPREFERREDLIFETIME;
1256		ipr->ipr_raf_onlink = 1;
1257		ipr->ipr_raf_auto = 1;
1258		/* omit other field initialization */
1259	}
1260	else if (ipr->ipr_origin < PR_ORIG_RR) {
1261		char ntopbuf[INET6_ADDRSTRLEN];
1262
1263		syslog(LOG_WARNING, "<%s> Added prefix(%s)'s origin %d is"
1264		    "lower than PR_ORIG_RR(router renumbering)."
1265		    "This should not happen if I am router", __func__,
1266		    inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr, ntopbuf,
1267			sizeof(ntopbuf)), ipr->ipr_origin);
1268		close(s);
1269		return (1);
1270	}
1271
1272	close(s);
1273	return (0);
1274#else
1275	ipr->ipr_vltime = DEF_ADVVALIDLIFETIME;
1276	ipr->ipr_pltime = DEF_ADVPREFERREDLIFETIME;
1277	ipr->ipr_raf_onlink = 1;
1278	ipr->ipr_raf_auto = 1;
1279	return (0);
1280#endif
1281}
1282
1283void
1284make_prefix(struct rainfo *rai, int ifindex, struct in6_addr *addr, int plen)
1285{
1286	struct in6_prefixreq ipr;
1287
1288	memset(&ipr, 0, sizeof(ipr));
1289	if (if_indextoname(ifindex, ipr.ipr_name) == NULL) {
1290		syslog(LOG_ERR, "<%s> Prefix added interface No.%d doesn't "
1291		    "exist. This should not happen! %s", __func__,
1292		    ifindex, strerror(errno));
1293		exit(1);
1294	}
1295	ipr.ipr_prefix.sin6_len = sizeof(ipr.ipr_prefix);
1296	ipr.ipr_prefix.sin6_family = AF_INET6;
1297	ipr.ipr_prefix.sin6_addr = *addr;
1298	ipr.ipr_plen = plen;
1299
1300	if (init_prefix(&ipr))
1301		return; /* init failed by some error */
1302	add_prefix(rai, &ipr);
1303}
1304
1305void
1306make_packet(struct rainfo *rai)
1307{
1308	size_t packlen, lladdroptlen = 0;
1309	char *buf;
1310	struct nd_router_advert *ra;
1311	struct nd_opt_prefix_info *ndopt_pi;
1312	struct nd_opt_mtu *ndopt_mtu;
1313	struct nd_opt_route_info *ndopt_rti;
1314	struct rtinfo *rti;
1315	struct nd_opt_rdnss *ndopt_rdnss;
1316	struct rdnss *rdn;
1317	struct nd_opt_dnssl *ndopt_dnssl;
1318	struct dnssl *dns;
1319	size_t len;
1320	struct prefix *pfx;
1321	struct ifinfo *ifi;
1322
1323	ifi = rai->rai_ifinfo;
1324	/* calculate total length */
1325	packlen = sizeof(struct nd_router_advert);
1326	if (rai->rai_advlinkopt) {
1327		if ((lladdroptlen = lladdropt_length(&ifi->ifi_sdl)) == 0) {
1328			syslog(LOG_INFO,
1329			    "<%s> link-layer address option has"
1330			    " null length on %s.  Treat as not included.",
1331			    __func__, ifi->ifi_ifname);
1332			rai->rai_advlinkopt = 0;
1333		}
1334		packlen += lladdroptlen;
1335	}
1336	if (rai->rai_pfxs)
1337		packlen += sizeof(struct nd_opt_prefix_info) * rai->rai_pfxs;
1338	if (rai->rai_linkmtu)
1339		packlen += sizeof(struct nd_opt_mtu);
1340
1341	TAILQ_FOREACH(rti, &rai->rai_route, rti_next)
1342		packlen += sizeof(struct nd_opt_route_info) +
1343			   ((rti->rti_prefixlen + 0x3f) >> 6) * 8;
1344
1345	TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
1346		struct rdnss_addr *rdna;
1347
1348		packlen += sizeof(struct nd_opt_rdnss);
1349		TAILQ_FOREACH(rdna, &rdn->rd_list, ra_next)
1350			packlen += sizeof(rdna->ra_dns);
1351	}
1352	TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
1353		struct dnssl_addr *dnsa;
1354
1355		packlen += sizeof(struct nd_opt_dnssl);
1356		len = 0;
1357		TAILQ_FOREACH(dnsa, &dns->dn_list, da_next)
1358			len += dnsa->da_len;
1359
1360		/* A zero octet and 8 octet boundary */
1361		len++;
1362		len += (len % 8) ? 8 - len % 8 : 0;
1363
1364		packlen += len;
1365	}
1366	/* allocate memory for the packet */
1367	if ((buf = malloc(packlen)) == NULL) {
1368		syslog(LOG_ERR,
1369		    "<%s> can't get enough memory for an RA packet",
1370		    __func__);
1371		exit(1);
1372	}
1373	memset(buf, 0, packlen);
1374	if (rai->rai_ra_data)	/* Free old data if any. */
1375		free(rai->rai_ra_data);
1376	rai->rai_ra_data = buf;
1377	/* XXX: what if packlen > 576? */
1378	rai->rai_ra_datalen = packlen;
1379
1380	/*
1381	 * construct the packet
1382	 */
1383	ra = (struct nd_router_advert *)buf;
1384	ra->nd_ra_type = ND_ROUTER_ADVERT;
1385	ra->nd_ra_code = 0;
1386	ra->nd_ra_cksum = 0;
1387	ra->nd_ra_curhoplimit = (uint8_t)(0xff & rai->rai_hoplimit);
1388	ra->nd_ra_flags_reserved = 0; /* just in case */
1389	/*
1390	 * XXX: the router preference field, which is a 2-bit field, should be
1391	 * initialized before other fields.
1392	 */
1393	ra->nd_ra_flags_reserved = 0xff & rai->rai_rtpref;
1394	ra->nd_ra_flags_reserved |=
1395		rai->rai_managedflg ? ND_RA_FLAG_MANAGED : 0;
1396	ra->nd_ra_flags_reserved |=
1397		rai->rai_otherflg ? ND_RA_FLAG_OTHER : 0;
1398	ra->nd_ra_router_lifetime = htons(rai->rai_lifetime);
1399	ra->nd_ra_reachable = htonl(rai->rai_reachabletime);
1400	ra->nd_ra_retransmit = htonl(rai->rai_retranstimer);
1401	buf += sizeof(*ra);
1402
1403	if (rai->rai_advlinkopt) {
1404		lladdropt_fill(&ifi->ifi_sdl, (struct nd_opt_hdr *)buf);
1405		buf += lladdroptlen;
1406	}
1407
1408	if (rai->rai_linkmtu) {
1409		ndopt_mtu = (struct nd_opt_mtu *)buf;
1410		ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
1411		ndopt_mtu->nd_opt_mtu_len = 1;
1412		ndopt_mtu->nd_opt_mtu_reserved = 0;
1413		ndopt_mtu->nd_opt_mtu_mtu = htonl(rai->rai_linkmtu);
1414		buf += sizeof(struct nd_opt_mtu);
1415	}
1416
1417	TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
1418		uint32_t vltime, pltime;
1419		struct timespec now;
1420
1421		ndopt_pi = (struct nd_opt_prefix_info *)buf;
1422		ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
1423		ndopt_pi->nd_opt_pi_len = 4;
1424		ndopt_pi->nd_opt_pi_prefix_len = pfx->pfx_prefixlen;
1425		ndopt_pi->nd_opt_pi_flags_reserved = 0;
1426		if (pfx->pfx_onlinkflg)
1427			ndopt_pi->nd_opt_pi_flags_reserved |=
1428				ND_OPT_PI_FLAG_ONLINK;
1429		if (pfx->pfx_autoconfflg)
1430			ndopt_pi->nd_opt_pi_flags_reserved |=
1431				ND_OPT_PI_FLAG_AUTO;
1432		if (pfx->pfx_timer)
1433			vltime = 0;
1434		else {
1435			if (pfx->pfx_vltimeexpire || pfx->pfx_pltimeexpire)
1436				clock_gettime(CLOCK_MONOTONIC_FAST, &now);
1437			if (pfx->pfx_vltimeexpire == 0)
1438				vltime = pfx->pfx_validlifetime;
1439			else
1440				vltime = ((time_t)pfx->pfx_vltimeexpire > now.tv_sec) ?
1441				    pfx->pfx_vltimeexpire - now.tv_sec : 0;
1442		}
1443		if (pfx->pfx_timer)
1444			pltime = 0;
1445		else {
1446			if (pfx->pfx_pltimeexpire == 0)
1447				pltime = pfx->pfx_preflifetime;
1448			else
1449				pltime = ((time_t)pfx->pfx_pltimeexpire > now.tv_sec) ?
1450				    pfx->pfx_pltimeexpire - now.tv_sec : 0;
1451		}
1452		if (vltime < pltime) {
1453			/*
1454			 * this can happen if vltime is decrement but pltime
1455			 * is not.
1456			 */
1457			pltime = vltime;
1458		}
1459		ndopt_pi->nd_opt_pi_valid_time = htonl(vltime);
1460		ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime);
1461		ndopt_pi->nd_opt_pi_reserved2 = 0;
1462		ndopt_pi->nd_opt_pi_prefix = pfx->pfx_prefix;
1463
1464		buf += sizeof(struct nd_opt_prefix_info);
1465	}
1466
1467	TAILQ_FOREACH(rti, &rai->rai_route, rti_next) {
1468		uint8_t psize = (rti->rti_prefixlen + 0x3f) >> 6;
1469
1470		ndopt_rti = (struct nd_opt_route_info *)buf;
1471		ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO;
1472		ndopt_rti->nd_opt_rti_len = 1 + psize;
1473		ndopt_rti->nd_opt_rti_prefixlen = rti->rti_prefixlen;
1474		ndopt_rti->nd_opt_rti_flags = 0xff & rti->rti_rtpref;
1475		ndopt_rti->nd_opt_rti_lifetime = htonl(rti->rti_ltime);
1476		memcpy(ndopt_rti + 1, &rti->rti_prefix, psize * 8);
1477		buf += sizeof(struct nd_opt_route_info) + psize * 8;
1478	}
1479
1480	TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
1481		struct rdnss_addr *rdna;
1482
1483		ndopt_rdnss = (struct nd_opt_rdnss *)buf;
1484		ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
1485		ndopt_rdnss->nd_opt_rdnss_len = 0;
1486		ndopt_rdnss->nd_opt_rdnss_reserved = 0;
1487		ndopt_rdnss->nd_opt_rdnss_lifetime = htonl(rdn->rd_ltime);
1488		buf += sizeof(struct nd_opt_rdnss);
1489
1490		TAILQ_FOREACH(rdna, &rdn->rd_list, ra_next) {
1491			memcpy(buf, &rdna->ra_dns, sizeof(rdna->ra_dns));
1492			buf += sizeof(rdna->ra_dns);
1493		}
1494		/* Length field should be in 8 octets */
1495		ndopt_rdnss->nd_opt_rdnss_len = (buf - (char *)ndopt_rdnss) / 8;
1496
1497		syslog(LOG_DEBUG, "<%s>: nd_opt_dnss_len = %d", __func__,
1498		    ndopt_rdnss->nd_opt_rdnss_len);
1499	}
1500
1501	TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
1502		struct dnssl_addr *dnsa;
1503
1504		ndopt_dnssl = (struct nd_opt_dnssl *)buf;
1505		ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL;
1506		ndopt_dnssl->nd_opt_dnssl_len = 0;
1507		ndopt_dnssl->nd_opt_dnssl_reserved = 0;
1508		ndopt_dnssl->nd_opt_dnssl_lifetime = htonl(dns->dn_ltime);
1509		buf += sizeof(*ndopt_dnssl);
1510
1511		TAILQ_FOREACH(dnsa, &dns->dn_list, da_next) {
1512			memcpy(buf, dnsa->da_dom, dnsa->da_len);
1513			buf += dnsa->da_len;
1514		}
1515
1516		/* A zero octet after encoded DNS server list. */
1517		*buf++ = '\0';
1518
1519		/* Padding to next 8 octets boundary */
1520		len = buf - (char *)ndopt_dnssl;
1521		len += (len % 8) ? 8 - len % 8 : 0;
1522
1523		/* Length field must be in 8 octets */
1524		ndopt_dnssl->nd_opt_dnssl_len = len / 8;
1525
1526		syslog(LOG_DEBUG, "<%s>: nd_opt_dnssl_len = %d", __func__,
1527		    ndopt_dnssl->nd_opt_dnssl_len);
1528	}
1529	return;
1530}
1531