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