| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: config.c,v 1.26 2011/12/10 19:14:29 roy Exp $ */ | | 1 | /* $NetBSD: config.c,v 1.27 2011/12/11 20:44:44 christos Exp $ */ |
2 | /* $KAME: config.c,v 1.93 2005/10/17 14:40:02 suz Exp $ */ | | 2 | /* $KAME: config.c,v 1.93 2005/10/17 14:40:02 suz Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (C) 1998 WIDE Project. | | 5 | * Copyright (C) 1998 WIDE Project. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
| @@ -82,28 +82,27 @@ encode_domain(char *dst, const char *src | | | @@ -82,28 +82,27 @@ encode_domain(char *dst, const char *src |
82 | *dst++ = len = MIN(63, p == NULL ? len : p - src); | | 82 | *dst++ = len = MIN(63, p == NULL ? len : p - src); |
83 | memcpy(dst, src, len); | | 83 | memcpy(dst, src, len); |
84 | dst += len; | | 84 | dst += len; |
85 | if (p == NULL) | | 85 | if (p == NULL) |
86 | break; | | 86 | break; |
87 | src = p + 1; | | 87 | src = p + 1; |
88 | } | | 88 | } |
89 | *dst++ = '\0'; | | 89 | *dst++ = '\0'; |
90 | | | 90 | |
91 | return dst - odst; | | 91 | return dst - odst; |
92 | } | | 92 | } |
93 | | | 93 | |
94 | void | | 94 | void |
95 | getconfig(intface) | | 95 | getconfig(const char *intface) |
96 | char *intface; | | | |
97 | { | | 96 | { |
98 | int stat, c, i; | | 97 | int stat, c, i; |
99 | char tbuf[BUFSIZ]; | | 98 | char tbuf[BUFSIZ]; |
100 | struct rainfo *tmp; | | 99 | struct rainfo *tmp; |
101 | int32_t val; | | 100 | int32_t val; |
102 | int64_t val64; | | 101 | int64_t val64; |
103 | char buf[BUFSIZ]; | | 102 | char buf[BUFSIZ]; |
104 | char *bp = buf; | | 103 | char *bp = buf; |
105 | char *addr, *flagstr, *ap; | | 104 | char *addr, *flagstr, *ap; |
106 | static int forwarding = -1; | | 105 | static int forwarding = -1; |
107 | char entbuf[256], abuf[256]; | | 106 | char entbuf[256], abuf[256]; |
108 | | | 107 | |
109 | #define MUSTHAVE(var, cap) \ | | 108 | #define MUSTHAVE(var, cap) \ |
| @@ -113,47 +112,45 @@ getconfig(intface) | | | @@ -113,47 +112,45 @@ getconfig(intface) |
113 | fprintf(stderr, "rtadvd: need %s for interface %s\n", \ | | 112 | fprintf(stderr, "rtadvd: need %s for interface %s\n", \ |
114 | cap, intface); \ | | 113 | cap, intface); \ |
115 | exit(1); \ | | 114 | exit(1); \ |
116 | } \ | | 115 | } \ |
117 | var = t; \ | | 116 | var = t; \ |
118 | } while (0) | | 117 | } while (0) |
119 | #define MAYHAVE(var, cap, def) \ | | 118 | #define MAYHAVE(var, cap, def) \ |
120 | do { \ | | 119 | do { \ |
121 | if ((var = agetnum(cap)) < 0) \ | | 120 | if ((var = agetnum(cap)) < 0) \ |
122 | var = def; \ | | 121 | var = def; \ |
123 | } while (0) | | 122 | } while (0) |
124 | #define ELM_MALLOC(p,error_action) \ | | 123 | #define ELM_MALLOC(p,error_action) \ |
125 | do { \ | | 124 | do { \ |
126 | p = malloc(sizeof(*p)); \ | | 125 | p = calloc(1, sizeof(*p)); \ |
127 | if (p == NULL) { \ | | 126 | if (p == NULL) { \ |
128 | syslog(LOG_ERR, "<%s> malloc failed: %s", \ | | 127 | syslog(LOG_ERR, "<%s> calloc failed: %m", \ |
129 | __func__, strerror(errno)); \ | | 128 | __func__); \ |
130 | error_action; \ | | 129 | error_action; \ |
131 | } \ | | 130 | } \ |
132 | memset(p, 0, sizeof(*p)); \ | | 131 | } while(/*CONSTCOND*/0) |
133 | } while(0) | | | |
134 | | | 132 | |
135 | | | 133 | |
136 | if ((stat = agetent(tbuf, intface)) <= 0) { | | 134 | if ((stat = agetent(tbuf, intface)) <= 0) { |
137 | memset(tbuf, 0, sizeof(tbuf)); | | 135 | memset(tbuf, 0, sizeof(tbuf)); |
138 | syslog(LOG_INFO, | | 136 | syslog(LOG_INFO, |
139 | "<%s> %s isn't defined in the configuration file" | | 137 | "<%s> %s isn't defined in the configuration file" |
140 | " or the configuration file doesn't exist." | | 138 | " or the configuration file doesn't exist." |
141 | " Treat it as default", | | 139 | " Treat it as default", |
142 | __func__, intface); | | 140 | __func__, intface); |
143 | } | | 141 | } |
144 | | | 142 | |
145 | ELM_MALLOC(tmp, exit(1)); | | 143 | ELM_MALLOC(tmp, exit(1)); |
146 | memset(tmp, 0, sizeof(*tmp)); | | | |
147 | | | 144 | |
148 | /* check if we are allowed to forward packets (if not determined) */ | | 145 | /* check if we are allowed to forward packets (if not determined) */ |
149 | if (forwarding < 0) { | | 146 | if (forwarding < 0) { |
150 | if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0) | | 147 | if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0) |
151 | exit(1); | | 148 | exit(1); |
152 | } | | 149 | } |
153 | | | 150 | |
154 | /* get interface information */ | | 151 | /* get interface information */ |
155 | if (agetflag("nolladdr")) | | 152 | if (agetflag("nolladdr")) |
156 | tmp->advlinkopt = 0; | | 153 | tmp->advlinkopt = 0; |
157 | else | | 154 | else |
158 | tmp->advlinkopt = 1; | | 155 | tmp->advlinkopt = 1; |
159 | if (tmp->advlinkopt) { | | 156 | if (tmp->advlinkopt) { |
| @@ -294,33 +291,32 @@ getconfig(intface) | | | @@ -294,33 +291,32 @@ getconfig(intface) |
294 | tmp->clockskew = val; | | 291 | tmp->clockskew = val; |
295 | | | 292 | |
296 | tmp->pfxs++; | | 293 | tmp->pfxs++; |
297 | TAILQ_INIT(&tmp->prefix); | | 294 | TAILQ_INIT(&tmp->prefix); |
298 | for (i = -1; i < MAXPREFIX; i++) { | | 295 | for (i = -1; i < MAXPREFIX; i++) { |
299 | struct prefix *pfx; | | 296 | struct prefix *pfx; |
300 | | | 297 | |
301 | makeentry(entbuf, sizeof(entbuf), i, "addr"); | | 298 | makeentry(entbuf, sizeof(entbuf), i, "addr"); |
302 | addr = (char *)agetstr(entbuf, &bp); | | 299 | addr = (char *)agetstr(entbuf, &bp); |
303 | if (addr == NULL) | | 300 | if (addr == NULL) |
304 | continue; | | 301 | continue; |
305 | | | 302 | |
306 | /* allocate memory to store prefix information */ | | 303 | /* allocate memory to store prefix information */ |
307 | if ((pfx = malloc(sizeof(struct prefix))) == NULL) { | | 304 | if ((pfx = calloc(1, sizeof(*pfx))) == NULL) { |
308 | syslog(LOG_ERR, | | 305 | syslog(LOG_ERR, |
309 | "<%s> can't allocate enough memory", | | 306 | "<%s> can't allocate memory: %m", |
310 | __func__); | | 307 | __func__); |
311 | exit(1); | | 308 | exit(1); |
312 | } | | 309 | } |
313 | memset(pfx, 0, sizeof(*pfx)); | | | |
314 | | | 310 | |
315 | TAILQ_INSERT_TAIL(&tmp->prefix, pfx, next); | | 311 | TAILQ_INSERT_TAIL(&tmp->prefix, pfx, next); |
316 | tmp->pfxs++; | | 312 | tmp->pfxs++; |
317 | pfx->rainfo = tmp; | | 313 | pfx->rainfo = tmp; |
318 | | | 314 | |
319 | pfx->origin = PREFIX_FROM_CONFIG; | | 315 | pfx->origin = PREFIX_FROM_CONFIG; |
320 | | | 316 | |
321 | if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) { | | 317 | if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) { |
322 | syslog(LOG_ERR, | | 318 | syslog(LOG_ERR, |
323 | "<%s> inet_pton failed for %s", | | 319 | "<%s> inet_pton failed for %s", |
324 | __func__, addr); | | 320 | __func__, addr); |
325 | exit(1); | | 321 | exit(1); |
326 | } | | 322 | } |
| @@ -423,44 +419,43 @@ getconfig(intface) | | | @@ -423,44 +419,43 @@ getconfig(intface) |
423 | "<%s> advertised link mtu (%d) on %s is invalid (must " | | 419 | "<%s> advertised link mtu (%d) on %s is invalid (must " |
424 | "be between least MTU (%d) and physical link MTU (%d)", | | 420 | "be between least MTU (%d) and physical link MTU (%d)", |
425 | __func__, tmp->linkmtu, intface, | | 421 | __func__, tmp->linkmtu, intface, |
426 | IPV6_MMTU, tmp->phymtu); | | 422 | IPV6_MMTU, tmp->phymtu); |
427 | exit(1); | | 423 | exit(1); |
428 | } | | 424 | } |
429 | | | 425 | |
430 | #ifdef SIOCSIFINFO_IN6 | | 426 | #ifdef SIOCSIFINFO_IN6 |
431 | { | | 427 | { |
432 | struct in6_ndireq ndi; | | 428 | struct in6_ndireq ndi; |
433 | int s; | | 429 | int s; |
434 | | | 430 | |
435 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | | 431 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { |
436 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | | 432 | syslog(LOG_ERR, "<%s> socket: %m", __func__); |
437 | strerror(errno)); | | | |
438 | exit(1); | | 433 | exit(1); |
439 | } | | 434 | } |
440 | memset(&ndi, 0, sizeof(ndi)); | | 435 | memset(&ndi, 0, sizeof(ndi)); |
441 | strncpy(ndi.ifname, intface, IFNAMSIZ); | | 436 | strncpy(ndi.ifname, intface, IFNAMSIZ); |
442 | if (ioctl(s, SIOCGIFINFO_IN6, &ndi) < 0) { | | 437 | if (ioctl(s, SIOCGIFINFO_IN6, &ndi) < 0) { |
443 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s", | | 438 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %m", |
444 | __func__, intface, strerror(errno)); | | 439 | __func__, intface); |
445 | } | | 440 | } |
446 | | | 441 | |
447 | /* reflect the RA info to the host variables in kernel */ | | 442 | /* reflect the RA info to the host variables in kernel */ |
448 | ndi.ndi.chlim = tmp->hoplimit; | | 443 | ndi.ndi.chlim = tmp->hoplimit; |
449 | ndi.ndi.retrans = tmp->retranstimer; | | 444 | ndi.ndi.retrans = tmp->retranstimer; |
450 | ndi.ndi.basereachable = tmp->reachabletime; | | 445 | ndi.ndi.basereachable = tmp->reachabletime; |
451 | if (ioctl(s, SIOCSIFINFO_IN6, &ndi) < 0) { | | 446 | if (ioctl(s, SIOCSIFINFO_IN6, &ndi) < 0) { |
452 | syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s", | | 447 | syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %m", |
453 | __func__, intface, strerror(errno)); | | 448 | __func__, intface); |
454 | } | | 449 | } |
455 | close(s); | | 450 | close(s); |
456 | } | | 451 | } |
457 | #endif | | 452 | #endif |
458 | | | 453 | |
459 | /* route information */ | | 454 | /* route information */ |
460 | TAILQ_INIT(&tmp->route); | | 455 | TAILQ_INIT(&tmp->route); |
461 | for (i = -1; i < MAXROUTE; i++) { | | 456 | for (i = -1; i < MAXROUTE; i++) { |
462 | struct rtinfo *rti; | | 457 | struct rtinfo *rti; |
463 | char oentbuf[256]; | | 458 | char oentbuf[256]; |
464 | | | 459 | |
465 | makeentry(entbuf, sizeof(entbuf), i, "rtprefix"); | | 460 | makeentry(entbuf, sizeof(entbuf), i, "rtprefix"); |
466 | addr = (char *)agetstr(entbuf, &bp); | | 461 | addr = (char *)agetstr(entbuf, &bp); |
| @@ -720,33 +715,32 @@ get_prefix(struct rainfo *rai) | | | @@ -720,33 +715,32 @@ get_prefix(struct rainfo *rai) |
720 | syslog(LOG_ERR, "<%s> failed to get prefixlen " | | 715 | syslog(LOG_ERR, "<%s> failed to get prefixlen " |
721 | "or prefix is invalid", | | 716 | "or prefix is invalid", |
722 | __func__); | | 717 | __func__); |
723 | exit(1); | | 718 | exit(1); |
724 | } | | 719 | } |
725 | if (plen == 128) /* XXX */ | | 720 | if (plen == 128) /* XXX */ |
726 | continue; | | 721 | continue; |
727 | if (find_prefix(rai, a, plen)) { | | 722 | if (find_prefix(rai, a, plen)) { |
728 | /* ignore a duplicated prefix. */ | | 723 | /* ignore a duplicated prefix. */ |
729 | continue; | | 724 | continue; |
730 | } | | 725 | } |
731 | | | 726 | |
732 | /* allocate memory to store prefix info. */ | | 727 | /* allocate memory to store prefix info. */ |
733 | if ((pp = malloc(sizeof(*pp))) == NULL) { | | 728 | if ((pp = calloc(1, sizeof(*pp))) == NULL) { |
734 | syslog(LOG_ERR, | | 729 | syslog(LOG_ERR, |
735 | "<%s> can't get allocate buffer for prefix", | | 730 | "<%s> can't get allocate buffer for prefix", |
736 | __func__); | | 731 | __func__); |
737 | exit(1); | | 732 | exit(1); |
738 | } | | 733 | } |
739 | memset(pp, 0, sizeof(*pp)); | | | |
740 | | | 734 | |
741 | /* set prefix, sweep bits outside of prefixlen */ | | 735 | /* set prefix, sweep bits outside of prefixlen */ |
742 | pp->prefixlen = plen; | | 736 | pp->prefixlen = plen; |
743 | memcpy(&pp->prefix, a, sizeof(*a)); | | 737 | memcpy(&pp->prefix, a, sizeof(*a)); |
744 | if (1) | | 738 | if (1) |
745 | { | | 739 | { |
746 | p = (unsigned char *)&pp->prefix; | | 740 | p = (unsigned char *)&pp->prefix; |
747 | ep = (unsigned char *)(&pp->prefix + 1); | | 741 | ep = (unsigned char *)(&pp->prefix + 1); |
748 | while (m < lim && p < ep) | | 742 | while (m < lim && p < ep) |
749 | *p++ &= *m++; | | 743 | *p++ &= *m++; |
750 | while (p < ep) | | 744 | while (p < ep) |
751 | *p++ = 0x00; | | 745 | *p++ = 0x00; |
752 | } | | 746 | } |
| @@ -787,32 +781,31 @@ makeentry(char *buf, size_t len, int id, | | | @@ -787,32 +781,31 @@ makeentry(char *buf, size_t len, int id, |
787 | /* | | 781 | /* |
788 | * Add a prefix to the list of specified interface and reconstruct | | 782 | * Add a prefix to the list of specified interface and reconstruct |
789 | * the outgoing packet. | | 783 | * the outgoing packet. |
790 | * The prefix must not be in the list. | | 784 | * The prefix must not be in the list. |
791 | * XXX: other parameters of the prefix(e.g. lifetime) should be | | 785 | * XXX: other parameters of the prefix(e.g. lifetime) should be |
792 | * able to be specified. | | 786 | * able to be specified. |
793 | */ | | 787 | */ |
794 | static void | | 788 | static void |
795 | add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr) | | 789 | add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr) |
796 | { | | 790 | { |
797 | struct prefix *prefix; | | 791 | struct prefix *prefix; |
798 | char ntopbuf[INET6_ADDRSTRLEN]; | | 792 | char ntopbuf[INET6_ADDRSTRLEN]; |
799 | | | 793 | |
800 | if ((prefix = malloc(sizeof(*prefix))) == NULL) { | | 794 | if ((prefix = calloc(1, sizeof(*prefix))) == NULL) { |
801 | syslog(LOG_ERR, "<%s> memory allocation failed", | | 795 | syslog(LOG_ERR, "<%s> memory allocation failed", |
802 | __func__); | | 796 | __func__); |
803 | return; /* XXX: error or exit? */ | | 797 | return; /* XXX: error or exit? */ |
804 | } | | 798 | } |
805 | memset(prefix, 0, sizeof(*prefix)); | | | |
806 | prefix->prefix = ipr->ipr_prefix.sin6_addr; | | 799 | prefix->prefix = ipr->ipr_prefix.sin6_addr; |
807 | prefix->prefixlen = ipr->ipr_plen; | | 800 | prefix->prefixlen = ipr->ipr_plen; |
808 | prefix->validlifetime = ipr->ipr_vltime; | | 801 | prefix->validlifetime = ipr->ipr_vltime; |
809 | prefix->preflifetime = ipr->ipr_pltime; | | 802 | prefix->preflifetime = ipr->ipr_pltime; |
810 | prefix->onlinkflg = ipr->ipr_raf_onlink; | | 803 | prefix->onlinkflg = ipr->ipr_raf_onlink; |
811 | prefix->autoconfflg = ipr->ipr_raf_auto; | | 804 | prefix->autoconfflg = ipr->ipr_raf_auto; |
812 | prefix->origin = PREFIX_FROM_DYNAMIC; | | 805 | prefix->origin = PREFIX_FROM_DYNAMIC; |
813 | | | 806 | |
814 | prefix->rainfo = rai; | | 807 | prefix->rainfo = rai; |
815 | TAILQ_INSERT_TAIL(&rai->prefix, prefix, next); | | 808 | TAILQ_INSERT_TAIL(&rai->prefix, prefix, next); |
816 | rai->pfxs++; | | 809 | rai->pfxs++; |
817 | | | 810 | |
818 | syslog(LOG_DEBUG, "<%s> new prefix %s/%d was added on %s", | | 811 | syslog(LOG_DEBUG, "<%s> new prefix %s/%d was added on %s", |
| @@ -914,34 +907,32 @@ update_prefix(struct prefix * prefix) | | | @@ -914,34 +907,32 @@ update_prefix(struct prefix * prefix) |
914 | | | 907 | |
915 | /* | | 908 | /* |
916 | * Try to get an in6_prefixreq contents for a prefix which matches | | 909 | * Try to get an in6_prefixreq contents for a prefix which matches |
917 | * ipr->ipr_prefix and ipr->ipr_plen and belongs to | | 910 | * ipr->ipr_prefix and ipr->ipr_plen and belongs to |
918 | * the interface whose name is ipr->ipr_name[]. | | 911 | * the interface whose name is ipr->ipr_name[]. |
919 | */ | | 912 | */ |
920 | static int | | 913 | static int |
921 | init_prefix(struct in6_prefixreq *ipr) | | 914 | init_prefix(struct in6_prefixreq *ipr) |
922 | { | | 915 | { |
923 | #if 0 | | 916 | #if 0 |
924 | int s; | | 917 | int s; |
925 | | | 918 | |
926 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | | 919 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { |
927 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | | 920 | syslog(LOG_ERR, "<%s> socket: %m", __func__); |
928 | strerror(errno)); | | | |
929 | exit(1); | | 921 | exit(1); |
930 | } | | 922 | } |
931 | | | 923 | |
932 | if (ioctl(s, SIOCGIFPREFIX_IN6, ipr) < 0) { | | 924 | if (ioctl(s, SIOCGIFPREFIX_IN6, ipr) < 0) { |
933 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFPREFIX %s", __func__, | | 925 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFPREFIX: %m", __func__); |
934 | strerror(errno)); | | | |
935 | | | 926 | |
936 | ipr->ipr_vltime = DEF_ADVVALIDLIFETIME; | | 927 | ipr->ipr_vltime = DEF_ADVVALIDLIFETIME; |
937 | ipr->ipr_pltime = DEF_ADVPREFERREDLIFETIME; | | 928 | ipr->ipr_pltime = DEF_ADVPREFERREDLIFETIME; |
938 | ipr->ipr_raf_onlink = 1; | | 929 | ipr->ipr_raf_onlink = 1; |
939 | ipr->ipr_raf_auto = 1; | | 930 | ipr->ipr_raf_auto = 1; |
940 | /* omit other field initialization */ | | 931 | /* omit other field initialization */ |
941 | } | | 932 | } |
942 | else if (ipr->ipr_origin < PR_ORIG_RR) { | | 933 | else if (ipr->ipr_origin < PR_ORIG_RR) { |
943 | char ntopbuf[INET6_ADDRSTRLEN]; | | 934 | char ntopbuf[INET6_ADDRSTRLEN]; |
944 | | | 935 | |
945 | syslog(LOG_WARNING, "<%s> Added prefix(%s)'s origin %d is" | | 936 | syslog(LOG_WARNING, "<%s> Added prefix(%s)'s origin %d is" |
946 | "lower than PR_ORIG_RR(router renumbering)." | | 937 | "lower than PR_ORIG_RR(router renumbering)." |
947 | "This should not happen if I am router", __func__, | | 938 | "This should not happen if I am router", __func__, |
| @@ -960,28 +951,28 @@ init_prefix(struct in6_prefixreq *ipr) | | | @@ -960,28 +951,28 @@ init_prefix(struct in6_prefixreq *ipr) |
960 | ipr->ipr_raf_auto = 1; | | 951 | ipr->ipr_raf_auto = 1; |
961 | return 0; | | 952 | return 0; |
962 | #endif | | 953 | #endif |
963 | } | | 954 | } |
964 | | | 955 | |
965 | void | | 956 | void |
966 | make_prefix(struct rainfo *rai, int ifindex, struct in6_addr *addr, int plen) | | 957 | make_prefix(struct rainfo *rai, int ifindex, struct in6_addr *addr, int plen) |
967 | { | | 958 | { |
968 | struct in6_prefixreq ipr; | | 959 | struct in6_prefixreq ipr; |
969 | | | 960 | |
970 | memset(&ipr, 0, sizeof(ipr)); | | 961 | memset(&ipr, 0, sizeof(ipr)); |
971 | if (if_indextoname(ifindex, ipr.ipr_name) == NULL) { | | 962 | if (if_indextoname(ifindex, ipr.ipr_name) == NULL) { |
972 | syslog(LOG_ERR, "<%s> Prefix added interface No.%d doesn't" | | 963 | syslog(LOG_ERR, "<%s> Prefix added interface No.%d doesn't" |
973 | "exist. This should not happen! %s", __func__, | | 964 | "exist. This should not happen: %m", __func__, |
974 | ifindex, strerror(errno)); | | 965 | ifindex); |
975 | exit(1); | | 966 | exit(1); |
976 | } | | 967 | } |
977 | ipr.ipr_prefix.sin6_len = sizeof(ipr.ipr_prefix); | | 968 | ipr.ipr_prefix.sin6_len = sizeof(ipr.ipr_prefix); |
978 | ipr.ipr_prefix.sin6_family = AF_INET6; | | 969 | ipr.ipr_prefix.sin6_family = AF_INET6; |
979 | ipr.ipr_prefix.sin6_addr = *addr; | | 970 | ipr.ipr_prefix.sin6_addr = *addr; |
980 | ipr.ipr_plen = plen; | | 971 | ipr.ipr_plen = plen; |
981 | | | 972 | |
982 | if (init_prefix(&ipr)) | | 973 | if (init_prefix(&ipr)) |
983 | return; /* init failed by some error */ | | 974 | return; /* init failed by some error */ |
984 | add_prefix(rai, &ipr); | | 975 | add_prefix(rai, &ipr); |
985 | } | | 976 | } |
986 | | | 977 | |
987 | void | | 978 | void |
| @@ -1028,82 +1019,89 @@ make_packet(struct rainfo *rainfo) | | | @@ -1028,82 +1019,89 @@ make_packet(struct rainfo *rainfo) |
1028 | TAILQ_FOREACH(rdnsa, &rdns->list, next) | | 1019 | TAILQ_FOREACH(rdnsa, &rdns->list, next) |
1029 | packlen += sizeof(rdnsa->addr); | | 1020 | packlen += sizeof(rdnsa->addr); |
1030 | } | | 1021 | } |
1031 | TAILQ_FOREACH(dnsl, &rainfo->dnssl, next) { | | 1022 | TAILQ_FOREACH(dnsl, &rainfo->dnssl, next) { |
1032 | packlen += sizeof(struct nd_opt_dnssl); | | 1023 | packlen += sizeof(struct nd_opt_dnssl); |
1033 | len = 0; | | 1024 | len = 0; |
1034 | TAILQ_FOREACH(dnsd, &dnsl->list, next) | | 1025 | TAILQ_FOREACH(dnsd, &dnsl->list, next) |
1035 | len += dnsd->len; | | 1026 | len += dnsd->len; |
1036 | len += len % 8 ? 8 - len % 8 : 0; | | 1027 | len += len % 8 ? 8 - len % 8 : 0; |
1037 | packlen += len; | | 1028 | packlen += len; |
1038 | } | | 1029 | } |
1039 | | | 1030 | |
1040 | /* allocate memory for the packet */ | | 1031 | /* allocate memory for the packet */ |
1041 | if ((buf = malloc(packlen)) == NULL) { | | 1032 | if ((buf = realloc(rainfo->ra_data, packlen)) == NULL) { |
1042 | syslog(LOG_ERR, | | 1033 | syslog(LOG_ERR, |
1043 | "<%s> can't get enough memory for an RA packet", | | 1034 | "<%s> can't get enough memory for an RA packet %m", |
1044 | __func__); | | 1035 | __func__); |
1045 | exit(1); | | 1036 | exit(1); |
1046 | } | | 1037 | } |
1047 | if (rainfo->ra_data) { | | | |
1048 | /* free the previous packet */ | | | |
1049 | free(rainfo->ra_data); | | | |
1050 | rainfo->ra_data = NULL; | | | |
1051 | } | | | |
1052 | rainfo->ra_data = buf; | | 1038 | rainfo->ra_data = buf; |
1053 | /* XXX: what if packlen > 576? */ | | 1039 | /* XXX: what if packlen > 576? */ |
1054 | rainfo->ra_datalen = packlen; | | 1040 | rainfo->ra_datalen = packlen; |
1055 | | | 1041 | #define CHECKLEN(size) \ |
| | | 1042 | do { \ |
| | | 1043 | if (buf + size > rainfo->ra_data + packlen) { \ |
| | | 1044 | syslog(LOG_ERR, \ |
| | | 1045 | "<%s, %d> RA packet does not fit in %zu",\ |
| | | 1046 | __func__, __LINE__, packlen); \ |
| | | 1047 | exit(1); \ |
| | | 1048 | } \ |
| | | 1049 | } while (/*CONSTCOND*/0) |
1056 | /* | | 1050 | /* |
1057 | * construct the packet | | 1051 | * construct the packet |
1058 | */ | | 1052 | */ |
| | | 1053 | CHECKLEN(sizeof(*ra)); |
1059 | ra = (struct nd_router_advert *)buf; | | 1054 | ra = (struct nd_router_advert *)buf; |
1060 | ra->nd_ra_type = ND_ROUTER_ADVERT; | | 1055 | ra->nd_ra_type = ND_ROUTER_ADVERT; |
1061 | ra->nd_ra_code = 0; | | 1056 | ra->nd_ra_code = 0; |
1062 | ra->nd_ra_cksum = 0; | | 1057 | ra->nd_ra_cksum = 0; |
1063 | ra->nd_ra_curhoplimit = (uint8_t)(0xff & rainfo->hoplimit); | | 1058 | ra->nd_ra_curhoplimit = (uint8_t)(0xff & rainfo->hoplimit); |
1064 | ra->nd_ra_flags_reserved = 0; /* just in case */ | | 1059 | ra->nd_ra_flags_reserved = 0; /* just in case */ |
1065 | /* | | 1060 | /* |
1066 | * XXX: the router preference field, which is a 2-bit field, should be | | 1061 | * XXX: the router preference field, which is a 2-bit field, should be |
1067 | * initialized before other fields. | | 1062 | * initialized before other fields. |
1068 | */ | | 1063 | */ |
1069 | ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref; | | 1064 | ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref; |
1070 | ra->nd_ra_flags_reserved |= | | 1065 | ra->nd_ra_flags_reserved |= |
1071 | rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0; | | 1066 | rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0; |
1072 | ra->nd_ra_flags_reserved |= | | 1067 | ra->nd_ra_flags_reserved |= |
1073 | rainfo->otherflg ? ND_RA_FLAG_OTHER : 0; | | 1068 | rainfo->otherflg ? ND_RA_FLAG_OTHER : 0; |
1074 | ra->nd_ra_router_lifetime = htons(rainfo->lifetime); | | 1069 | ra->nd_ra_router_lifetime = htons(rainfo->lifetime); |
1075 | ra->nd_ra_reachable = htonl(rainfo->reachabletime); | | 1070 | ra->nd_ra_reachable = htonl(rainfo->reachabletime); |
1076 | ra->nd_ra_retransmit = htonl(rainfo->retranstimer); | | 1071 | ra->nd_ra_retransmit = htonl(rainfo->retranstimer); |
1077 | buf += sizeof(*ra); | | 1072 | buf += sizeof(*ra); |
1078 | | | 1073 | |
1079 | if (rainfo->advlinkopt) { | | 1074 | if (rainfo->advlinkopt) { |
| | | 1075 | CHECKLEN(sizeof(struct nd_opt_hdr)); |
1080 | lladdropt_fill(rainfo->sdl, (struct nd_opt_hdr *)buf); | | 1076 | lladdropt_fill(rainfo->sdl, (struct nd_opt_hdr *)buf); |
1081 | buf += lladdroptlen; | | 1077 | buf += lladdroptlen; |
1082 | } | | 1078 | } |
1083 | | | 1079 | |
1084 | if (rainfo->linkmtu) { | | 1080 | if (rainfo->linkmtu) { |
| | | 1081 | CHECKLEN(sizeof(*ndopt_mtu)); |
1085 | ndopt_mtu = (struct nd_opt_mtu *)buf; | | 1082 | ndopt_mtu = (struct nd_opt_mtu *)buf; |
1086 | ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU; | | 1083 | ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU; |
1087 | ndopt_mtu->nd_opt_mtu_len = 1; | | 1084 | ndopt_mtu->nd_opt_mtu_len = 1; |
1088 | ndopt_mtu->nd_opt_mtu_reserved = 0; | | 1085 | ndopt_mtu->nd_opt_mtu_reserved = 0; |
1089 | ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu); | | 1086 | ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu); |
1090 | buf += sizeof(struct nd_opt_mtu); | | 1087 | buf += sizeof(struct nd_opt_mtu); |
1091 | } | | 1088 | } |
1092 | | | 1089 | |
1093 | TAILQ_FOREACH(pfx, &rainfo->prefix, next) { | | 1090 | TAILQ_FOREACH(pfx, &rainfo->prefix, next) { |
1094 | uint32_t vltime, pltime; | | 1091 | uint32_t vltime, pltime; |
1095 | struct timeval now; | | 1092 | struct timeval now; |
1096 | | | 1093 | |
| | | 1094 | CHECKLEN(sizeof(*ndopt_pi)); |
1097 | ndopt_pi = (struct nd_opt_prefix_info *)buf; | | 1095 | ndopt_pi = (struct nd_opt_prefix_info *)buf; |
1098 | ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; | | 1096 | ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; |
1099 | ndopt_pi->nd_opt_pi_len = 4; | | 1097 | ndopt_pi->nd_opt_pi_len = 4; |
1100 | ndopt_pi->nd_opt_pi_prefix_len = pfx->prefixlen; | | 1098 | ndopt_pi->nd_opt_pi_prefix_len = pfx->prefixlen; |
1101 | ndopt_pi->nd_opt_pi_flags_reserved = 0; | | 1099 | ndopt_pi->nd_opt_pi_flags_reserved = 0; |
1102 | if (pfx->onlinkflg) | | 1100 | if (pfx->onlinkflg) |
1103 | ndopt_pi->nd_opt_pi_flags_reserved |= | | 1101 | ndopt_pi->nd_opt_pi_flags_reserved |= |
1104 | ND_OPT_PI_FLAG_ONLINK; | | 1102 | ND_OPT_PI_FLAG_ONLINK; |
1105 | if (pfx->autoconfflg) | | 1103 | if (pfx->autoconfflg) |
1106 | ndopt_pi->nd_opt_pi_flags_reserved |= | | 1104 | ndopt_pi->nd_opt_pi_flags_reserved |= |
1107 | ND_OPT_PI_FLAG_AUTO; | | 1105 | ND_OPT_PI_FLAG_AUTO; |
1108 | if (pfx->timer) | | 1106 | if (pfx->timer) |
1109 | vltime = 0; | | 1107 | vltime = 0; |
| @@ -1133,78 +1131,84 @@ make_packet(struct rainfo *rainfo) | | | @@ -1133,78 +1131,84 @@ make_packet(struct rainfo *rainfo) |
1133 | pltime = vltime; | | 1131 | pltime = vltime; |
1134 | } | | 1132 | } |
1135 | ndopt_pi->nd_opt_pi_valid_time = htonl(vltime); | | 1133 | ndopt_pi->nd_opt_pi_valid_time = htonl(vltime); |
1136 | ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime); | | 1134 | ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime); |
1137 | ndopt_pi->nd_opt_pi_reserved2 = 0; | | 1135 | ndopt_pi->nd_opt_pi_reserved2 = 0; |
1138 | ndopt_pi->nd_opt_pi_prefix = pfx->prefix; | | 1136 | ndopt_pi->nd_opt_pi_prefix = pfx->prefix; |
1139 | | | 1137 | |
1140 | buf += sizeof(struct nd_opt_prefix_info); | | 1138 | buf += sizeof(struct nd_opt_prefix_info); |
1141 | } | | 1139 | } |
1142 | | | 1140 | |
1143 | TAILQ_FOREACH(rti, &rainfo->route, next) { | | 1141 | TAILQ_FOREACH(rti, &rainfo->route, next) { |
1144 | uint8_t psize = (rti->prefixlen + 0x3f) >> 6; | | 1142 | uint8_t psize = (rti->prefixlen + 0x3f) >> 6; |
1145 | | | 1143 | |
| | | 1144 | CHECKLEN(sizeof(*ndopt_rti)); |
1146 | ndopt_rti = (struct nd_opt_route_info *)buf; | | 1145 | ndopt_rti = (struct nd_opt_route_info *)buf; |
1147 | ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO; | | 1146 | ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO; |
1148 | ndopt_rti->nd_opt_rti_len = 1 + psize; | | 1147 | ndopt_rti->nd_opt_rti_len = 1 + psize; |
1149 | ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen; | | 1148 | ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen; |
1150 | ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref; | | 1149 | ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref; |
1151 | ndopt_rti->nd_opt_rti_lifetime = htonl(rti->ltime); | | 1150 | ndopt_rti->nd_opt_rti_lifetime = htonl(rti->ltime); |
1152 | memcpy(ndopt_rti + 1, &rti->prefix, psize * 8); | | 1151 | memcpy(ndopt_rti + 1, &rti->prefix, psize * 8); |
1153 | buf += sizeof(struct nd_opt_route_info) + psize * 8; | | 1152 | buf += sizeof(struct nd_opt_route_info) + psize * 8; |
1154 | } | | 1153 | } |
1155 | | | 1154 | |
1156 | TAILQ_FOREACH(rdns, &rainfo->rdnss, next) { | | 1155 | TAILQ_FOREACH(rdns, &rainfo->rdnss, next) { |
| | | 1156 | CHECKLEN(sizeof(*ndopt_rdnss)); |
1157 | ndopt_rdnss = (struct nd_opt_rdnss *)buf; | | 1157 | ndopt_rdnss = (struct nd_opt_rdnss *)buf; |
1158 | ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS; | | 1158 | ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS; |
1159 | ndopt_rdnss->nd_opt_rdnss_len = 1; | | 1159 | ndopt_rdnss->nd_opt_rdnss_len = 1; |
1160 | ndopt_rdnss->nd_opt_rdnss_reserved = 0; | | 1160 | ndopt_rdnss->nd_opt_rdnss_reserved = 0; |
1161 | ndopt_rdnss->nd_opt_rdnss_lifetime = htonl(rdns->lifetime); | | 1161 | ndopt_rdnss->nd_opt_rdnss_lifetime = htonl(rdns->lifetime); |
1162 | buf += sizeof(*ndopt_rdnss); | | 1162 | buf += sizeof(*ndopt_rdnss); |
1163 | | | 1163 | |
1164 | TAILQ_FOREACH(rdnsa, &rdns->list, next) { | | 1164 | TAILQ_FOREACH(rdnsa, &rdns->list, next) { |
| | | 1165 | CHECKLEN(sizeof(rdnsa->addr)); |
1165 | memcpy(buf, &rdnsa->addr, sizeof(rdnsa->addr)); | | 1166 | memcpy(buf, &rdnsa->addr, sizeof(rdnsa->addr)); |
1166 | ndopt_rdnss->nd_opt_rdnss_len += 2; | | 1167 | ndopt_rdnss->nd_opt_rdnss_len += 2; |
1167 | buf += sizeof(rdnsa->addr); | | 1168 | buf += sizeof(rdnsa->addr); |
1168 | } | | 1169 | } |
1169 | } | | 1170 | } |
1170 | | | 1171 | |
1171 | TAILQ_FOREACH(dnsl, &rainfo->dnssl, next) { | | 1172 | TAILQ_FOREACH(dnsl, &rainfo->dnssl, next) { |
| | | 1173 | CHECKLEN(sizeof(*ndopt_dnssl)); |
1172 | ndopt_dnssl = (struct nd_opt_dnssl *)buf; | | 1174 | ndopt_dnssl = (struct nd_opt_dnssl *)buf; |
1173 | ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL; | | 1175 | ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL; |
1174 | ndopt_dnssl->nd_opt_dnssl_len = 0; | | 1176 | ndopt_dnssl->nd_opt_dnssl_len = 0; |
1175 | ndopt_dnssl->nd_opt_dnssl_reserved = 0; | | 1177 | ndopt_dnssl->nd_opt_dnssl_reserved = 0; |
1176 | ndopt_dnssl->nd_opt_dnssl_lifetime = htonl(dnsl->lifetime); | | 1178 | ndopt_dnssl->nd_opt_dnssl_lifetime = htonl(dnsl->lifetime); |
1177 | buf += sizeof(*ndopt_dnssl); | | 1179 | buf += sizeof(*ndopt_dnssl); |
1178 | | | 1180 | |
1179 | TAILQ_FOREACH(dnsd, &dnsl->list, next) { | | 1181 | TAILQ_FOREACH(dnsd, &dnsl->list, next) { |
| | | 1182 | CHECKLEN(dnsd->len); |
1180 | memcpy(buf, dnsd->domain, dnsd->len); | | 1183 | memcpy(buf, dnsd->domain, dnsd->len); |
1181 | buf += dnsd->len; | | 1184 | buf += dnsd->len; |
1182 | } | | 1185 | } |
1183 | /* Ensure our length is padded correctly */ | | 1186 | /* Ensure our length is padded correctly */ |
1184 | len = buf - (char *)ndopt_dnssl; | | 1187 | len = buf - (char *)ndopt_dnssl; |
1185 | plen = len % 8 ? 8 - len % 8 : 0; | | 1188 | plen = len % 8 ? 8 - len % 8 : 0; |
| | | 1189 | CHECKLEN(plen); |
1186 | memset(buf, 0, plen); | | 1190 | memset(buf, 0, plen); |
1187 | buf += plen; | | 1191 | buf += plen; |
1188 | ndopt_dnssl->nd_opt_dnssl_len = (len + plen) / 8; | | 1192 | ndopt_dnssl->nd_opt_dnssl_len = (len + plen) / 8; |
1189 | } | | 1193 | } |
| | | 1194 | memset(buf, 0, packlen - (buf - rainfo->ra_data)); |
1190 | } | | 1195 | } |
1191 | | | 1196 | |
1192 | static int | | 1197 | static int |
1193 | getinet6sysctl(int code) | | 1198 | getinet6sysctl(int code) |
1194 | { | | 1199 | { |
1195 | int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; | | 1200 | int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; |
1196 | int value; | | 1201 | int value; |
1197 | size_t size; | | 1202 | size_t size; |
1198 | | | 1203 | |
1199 | mib[3] = code; | | 1204 | mib[3] = code; |
1200 | size = sizeof(value); | | 1205 | size = sizeof(value); |
1201 | if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) | | 1206 | if (sysctl(mib, __arraycount(mib), &value, &size, NULL, 0) |
1202 | < 0) { | | 1207 | < 0) { |
1203 | syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s", | | 1208 | syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %m", |
1204 | __func__, code, | | 1209 | __func__, code); |
1205 | strerror(errno)); | | 1210 | return -1; |
1206 | return(-1); | | | |
1207 | } | | 1211 | } |
1208 | else | | 1212 | else |
1209 | return(value); | | 1213 | return value; |
1210 | } | | 1214 | } |