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