Add RDNSS and DNSSL support, RFC6106. Replace custom lists with TAILQ lists. Clean up plently of signed vs unsigned warnings and set WARNS=4. Adapted from FreeBSD.diff -r1.43 -r1.44 src/sys/netinet/icmp6.h
(roy)
--- src/sys/netinet/icmp6.h 2011/11/11 15:09:32 1.43
+++ src/sys/netinet/icmp6.h 2011/12/10 19:14:29 1.44
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: icmp6.h,v 1.43 2011/11/11 15:09:32 gdt Exp $ */ | 1 | /* $NetBSD: icmp6.h,v 1.44 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $ */ | 2 | /* $KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $ */ | |
3 | 3 | |||
4 | 4 | |||
5 | /* | 5 | /* | |
6 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 6 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
@@ -290,31 +290,30 @@ struct nd_opt_hdr { /* Neighbor discove | @@ -290,31 +290,30 @@ struct nd_opt_hdr { /* Neighbor discove | |||
290 | u_int8_t nd_opt_len; | 290 | u_int8_t nd_opt_len; | |
291 | /* followed by option specific data*/ | 291 | /* followed by option specific data*/ | |
292 | } __packed; | 292 | } __packed; | |
293 | 293 | |||
294 | #define ND_OPT_SOURCE_LINKADDR 1 | 294 | #define ND_OPT_SOURCE_LINKADDR 1 | |
295 | #define ND_OPT_TARGET_LINKADDR 2 | 295 | #define ND_OPT_TARGET_LINKADDR 2 | |
296 | #define ND_OPT_PREFIX_INFORMATION 3 | 296 | #define ND_OPT_PREFIX_INFORMATION 3 | |
297 | #define ND_OPT_REDIRECTED_HEADER 4 | 297 | #define ND_OPT_REDIRECTED_HEADER 4 | |
298 | #define ND_OPT_MTU 5 | 298 | #define ND_OPT_MTU 5 | |
299 | #define ND_OPT_ADVINTERVAL 7 | 299 | #define ND_OPT_ADVINTERVAL 7 | |
300 | #define ND_OPT_HOMEAGENT_INFO 8 | 300 | #define ND_OPT_HOMEAGENT_INFO 8 | |
301 | #define ND_OPT_SOURCE_ADDRLIST 9 | 301 | #define ND_OPT_SOURCE_ADDRLIST 9 | |
302 | #define ND_OPT_TARGET_ADDRLIST 10 | 302 | #define ND_OPT_TARGET_ADDRLIST 10 | |
303 | /* RFC5380 */ | 303 | #define ND_OPT_MAP 23 /* RFC 5380 */ | |
304 | #define ND_OPT_MAP 23 | 304 | #define ND_OPT_ROUTE_INFO 24 /* RFC 4191 */ | |
305 | /* RFC4191 */ | 305 | #define ND_OPT_RDNSS 25 /* RFC 6016 */ | |
306 | #define ND_OPT_ROUTE_INFO 24 | 306 | #define ND_OPT_DNSSL 31 /* RFC 6016 */ | |
307 | #define ND_OPT_RDNSS 25 | |||
308 | 307 | |||
309 | struct nd_opt_route_info { /* route info */ | 308 | struct nd_opt_route_info { /* route info */ | |
310 | u_int8_t nd_opt_rti_type; | 309 | u_int8_t nd_opt_rti_type; | |
311 | u_int8_t nd_opt_rti_len; | 310 | u_int8_t nd_opt_rti_len; | |
312 | u_int8_t nd_opt_rti_prefixlen; | 311 | u_int8_t nd_opt_rti_prefixlen; | |
313 | u_int8_t nd_opt_rti_flags; | 312 | u_int8_t nd_opt_rti_flags; | |
314 | u_int32_t nd_opt_rti_lifetime; | 313 | u_int32_t nd_opt_rti_lifetime; | |
315 | /* prefix follows */ | 314 | /* prefix follows */ | |
316 | }; | 315 | }; | |
317 | 316 | |||
318 | struct nd_opt_prefix_info { /* prefix information */ | 317 | struct nd_opt_prefix_info { /* prefix information */ | |
319 | u_int8_t nd_opt_pi_type; | 318 | u_int8_t nd_opt_pi_type; | |
320 | u_int8_t nd_opt_pi_len; | 319 | u_int8_t nd_opt_pi_len; | |
@@ -334,34 +333,42 @@ struct nd_opt_rd_hdr { /* redirected he | @@ -334,34 +333,42 @@ struct nd_opt_rd_hdr { /* redirected he | |||
334 | u_int8_t nd_opt_rh_len; | 333 | u_int8_t nd_opt_rh_len; | |
335 | u_int16_t nd_opt_rh_reserved1; | 334 | u_int16_t nd_opt_rh_reserved1; | |
336 | u_int32_t nd_opt_rh_reserved2; | 335 | u_int32_t nd_opt_rh_reserved2; | |
337 | /* followed by IP header and data */ | 336 | /* followed by IP header and data */ | |
338 | } __packed; | 337 | } __packed; | |
339 | 338 | |||
340 | struct nd_opt_mtu { /* MTU option */ | 339 | struct nd_opt_mtu { /* MTU option */ | |
341 | u_int8_t nd_opt_mtu_type; | 340 | u_int8_t nd_opt_mtu_type; | |
342 | u_int8_t nd_opt_mtu_len; | 341 | u_int8_t nd_opt_mtu_len; | |
343 | u_int16_t nd_opt_mtu_reserved; | 342 | u_int16_t nd_opt_mtu_reserved; | |
344 | u_int32_t nd_opt_mtu_mtu; | 343 | u_int32_t nd_opt_mtu_mtu; | |
345 | } __packed; | 344 | } __packed; | |
346 | 345 | |||
347 | struct nd_opt_rdnss { /* RDNSS option RFC 5006 */ | 346 | struct nd_opt_rdnss { /* RDNSS option RFC 6106 */ | |
348 | u_int8_t nd_opt_rdnss_type; | 347 | u_int8_t nd_opt_rdnss_type; | |
349 | u_int8_t nd_opt_rdnss_len; | 348 | u_int8_t nd_opt_rdnss_len; | |
350 | u_int16_t nd_opt_rdnss_reserved; | 349 | u_int16_t nd_opt_rdnss_reserved; | |
351 | u_int32_t nd_opt_rdnss_lifetime; | 350 | u_int32_t nd_opt_rdnss_lifetime; | |
352 | /* followed by list of IP prefixes */ | 351 | /* followed by list of IP prefixes */ | |
353 | } __packed; | 352 | } __packed; | |
354 | 353 | |||
354 | struct nd_opt_dnssl { /* DNSSL option RFC 6106 */ | |||
355 | u_int8_t nd_opt_dnssl_type; | |||
356 | u_int8_t nd_opt_dnssl_len; | |||
357 | u_int16_t nd_opt_dnssl_reserved; | |||
358 | u_int32_t nd_opt_dnssl_lifetime; | |||
359 | /* followed by list of IP prefixes */ | |||
360 | } __packed; | |||
361 | ||||
355 | /* | 362 | /* | |
356 | * icmp6 namelookup | 363 | * icmp6 namelookup | |
357 | */ | 364 | */ | |
358 | 365 | |||
359 | struct icmp6_namelookup { | 366 | struct icmp6_namelookup { | |
360 | struct icmp6_hdr icmp6_nl_hdr; | 367 | struct icmp6_hdr icmp6_nl_hdr; | |
361 | u_int8_t icmp6_nl_nonce[8]; | 368 | u_int8_t icmp6_nl_nonce[8]; | |
362 | int32_t icmp6_nl_ttl; | 369 | int32_t icmp6_nl_ttl; | |
363 | #if 0 | 370 | #if 0 | |
364 | u_int8_t icmp6_nl_len; | 371 | u_int8_t icmp6_nl_len; | |
365 | u_int8_t icmp6_nl_name[3]; | 372 | u_int8_t icmp6_nl_name[3]; | |
366 | #endif | 373 | #endif | |
367 | /* could be followed by options */ | 374 | /* could be followed by options */ |
--- src/usr.sbin/rtadvd/Makefile 2011/06/20 07:44:04 1.15
+++ src/usr.sbin/rtadvd/Makefile 2011/12/10 19:14:29 1.16
@@ -1,25 +1,25 @@ | @@ -1,25 +1,25 @@ | |||
1 | # $NetBSD: Makefile,v 1.15 2011/06/20 07:44:04 mrg Exp $ | 1 | # $NetBSD: Makefile,v 1.16 2011/12/10 19:14:29 roy Exp $ | |
2 | 2 | |||
3 | WARNS?= 2 # XXX -Wcast-qual -Wsign-compare | 3 | WARNS?= 4 | |
4 | 4 | |||
5 | .include <bsd.own.mk> | 5 | .include <bsd.own.mk> | |
6 | 6 | |||
7 | USE_FORT?= yes # network server | 7 | USE_FORT?= yes # network server | |
8 | 8 | |||
9 | PROG= rtadvd | 9 | PROG= rtadvd | |
10 | SRCS= rtadvd.c rrenum.c advcap.c if.c config.c timer.c dump.c | 10 | SRCS= rtadvd.c rrenum.c advcap.c if.c config.c timer.c dump.c | |
11 | 11 | |||
12 | CPPFLAGS+=-DINET6 -DROUTEINFO | 12 | CPPFLAGS+=-DINET6 | |
13 | MAN= rtadvd.8 rtadvd.conf.5 | 13 | MAN= rtadvd.8 rtadvd.conf.5 | |
14 | LDADD+= -lutil | 14 | LDADD+= -lutil | |
15 | DPADD+= ${LIBUTIL} | 15 | DPADD+= ${LIBUTIL} | |
16 | 16 | |||
17 | .if ${MKSHARE} != "no" | 17 | .if ${MKSHARE} != "no" | |
18 | FILESDIR= /usr/share/examples/rtadvd | 18 | FILESDIR= /usr/share/examples/rtadvd | |
19 | FILES= rtadvd.conf | 19 | FILES= rtadvd.conf | |
20 | .endif | 20 | .endif | |
21 | 21 | |||
22 | .include <bsd.prog.mk> | 22 | .include <bsd.prog.mk> | |
23 | 23 | |||
24 | .if defined(HAVE_GCC) | 24 | .if defined(HAVE_GCC) | |
25 | COPTS.dump.c=-fno-strict-aliasing | 25 | COPTS.dump.c=-fno-strict-aliasing |
--- src/usr.sbin/rtadvd/advcap.c 2006/03/18 22:07:15 1.12
+++ src/usr.sbin/rtadvd/advcap.c 2011/12/10 19:14:29 1.13
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: advcap.c,v 1.12 2006/03/18 22:07:15 dan Exp $ */ | 1 | /* $NetBSD: advcap.c,v 1.13 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: advcap.c,v 1.11 2003/05/19 09:46:50 keiichi Exp $ */ | 2 | /* $KAME: advcap.c,v 1.11 2003/05/19 09:46:50 keiichi Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1983 The Regents of the University of California. | 5 | * Copyright (c) 1983 The Regents of the University of California. | |
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 | |
@@ -77,54 +77,52 @@ char *RM; | @@ -77,54 +77,52 @@ char *RM; | |||
77 | * | 77 | * | |
78 | * Essentially all the work here is scanning and decoding escapes | 78 | * Essentially all the work here is scanning and decoding escapes | |
79 | * in string capabilities. We don't use stdio because the editor | 79 | * in string capabilities. We don't use stdio because the editor | |
80 | * doesn't, and because living w/o it is not hard. | 80 | * doesn't, and because living w/o it is not hard. | |
81 | */ | 81 | */ | |
82 | 82 | |||
83 | static char *tbuf; | 83 | static char *tbuf; | |
84 | static int hopcount; /* detect infinite loops in termcap, init 0 */ | 84 | static int hopcount; /* detect infinite loops in termcap, init 0 */ | |
85 | 85 | |||
86 | static char *remotefile; | 86 | static char *remotefile; | |
87 | 87 | |||
88 | extern char *conffile; | 88 | extern char *conffile; | |
89 | 89 | |||
90 | int tgetent __P((char *, char *)); | 90 | int tgetent(char *, char *); | |
91 | int getent __P((char *, char *, char *)); | 91 | int getent(char *, char *, char *); | |
92 | int tnchktc __P((void)); | 92 | int tnchktc(void); | |
93 | int tnamatch __P((char *)); | 93 | int tnamatch(char *); | |
94 | static char *tskip __P((char *)); | 94 | static char *tskip(char *); | |
95 | int64_t tgetnum __P((char *)); | 95 | int64_t tgetnum(char *); | |
96 | int tgetflag __P((char *)); | 96 | int tgetflag(char *); | |
97 | char *tgetstr __P((char *, char **)); | 97 | char *tgetstr(char *, char **); | |
98 | static char *tdecode __P((char *, char **)); | 98 | static char *tdecode(char *, char **); | |
99 | 99 | |||
100 | /* | 100 | /* | |
101 | * Get an entry for terminal name in buffer bp, | 101 | * Get an entry for terminal name in buffer bp, | |
102 | * from the termcap file. Parse is very rudimentary; | 102 | * from the termcap file. Parse is very rudimentary; | |
103 | * we just notice escaped newlines. | 103 | * we just notice escaped newlines. | |
104 | */ | 104 | */ | |
105 | int | 105 | int | |
106 | tgetent(bp, name) | 106 | tgetent(char *bp, char *name) | |
107 | char *bp, *name; | |||
108 | { | 107 | { | |
109 | char *cp; | 108 | char *cp; | |
110 | 109 | |||
111 | remotefile = cp = conffile ? conffile : _PATH_RTADVDCONF; | 110 | remotefile = cp = conffile ? conffile : __UNCONST(_PATH_RTADVDCONF); | |
112 | return (getent(bp, name, cp)); | 111 | return (getent(bp, name, cp)); | |
113 | } | 112 | } | |
114 | 113 | |||
115 | int | 114 | int | |
116 | getent(bp, name, cp) | 115 | getent(char *bp, char *name, char *cp) | |
117 | char *bp, *name, *cp; | |||
118 | { | 116 | { | |
119 | int c; | 117 | int c; | |
120 | int i = 0, cnt = 0; | 118 | int i = 0, cnt = 0; | |
121 | char ibuf[BUFSIZ]; | 119 | char ibuf[BUFSIZ]; | |
122 | int tf; | 120 | int tf; | |
123 | 121 | |||
124 | tbuf = bp; | 122 | tbuf = bp; | |
125 | tf = 0; | 123 | tf = 0; | |
126 | /* | 124 | /* | |
127 | * TERMCAP can have one of two things in it. It can be the | 125 | * TERMCAP can have one of two things in it. It can be the | |
128 | * name of a file to use instead of /etc/termcap. In this | 126 | * name of a file to use instead of /etc/termcap. In this | |
129 | * case it better start with a "/". Or it can be an entry to | 127 | * case it better start with a "/". Or it can be an entry to | |
130 | * use so we don't have to read the file. In this case it | 128 | * use so we don't have to read the file. In this case it | |
@@ -173,27 +171,27 @@ getent(bp, name, cp) | @@ -173,27 +171,27 @@ getent(bp, name, cp) | |||
173 | return (tnchktc()); | 171 | return (tnchktc()); | |
174 | } | 172 | } | |
175 | } | 173 | } | |
176 | } | 174 | } | |
177 | 175 | |||
178 | /* | 176 | /* | |
179 | * tnchktc: check the last entry, see if it's tc=xxx. If so, | 177 | * tnchktc: check the last entry, see if it's tc=xxx. If so, | |
180 | * recursively find xxx and append that entry (minus the names) | 178 | * recursively find xxx and append that entry (minus the names) | |
181 | * to take the place of the tc=xxx entry. This allows termcap | 179 | * to take the place of the tc=xxx entry. This allows termcap | |
182 | * entries to say "like an HP2621 but doesn't turn on the labels". | 180 | * entries to say "like an HP2621 but doesn't turn on the labels". | |
183 | * Note that this works because of the left to right scan. | 181 | * Note that this works because of the left to right scan. | |
184 | */ | 182 | */ | |
185 | int | 183 | int | |
186 | tnchktc() | 184 | tnchktc(void) | |
187 | { | 185 | { | |
188 | char *p, *q; | 186 | char *p, *q; | |
189 | char tcname[16]; /* name of similar terminal */ | 187 | char tcname[16]; /* name of similar terminal */ | |
190 | char tcbuf[BUFSIZ]; | 188 | char tcbuf[BUFSIZ]; | |
191 | char *holdtbuf = tbuf; | 189 | char *holdtbuf = tbuf; | |
192 | int l; | 190 | int l; | |
193 | 191 | |||
194 | p = tbuf + strlen(tbuf) - 2; /* before the last colon */ | 192 | p = tbuf + strlen(tbuf) - 2; /* before the last colon */ | |
195 | while (*--p != ':') | 193 | while (*--p != ':') | |
196 | if (p < tbuf) { | 194 | if (p < tbuf) { | |
197 | write(2, "Bad remcap entry\n", 18); | 195 | write(2, "Bad remcap entry\n", 18); | |
198 | return (0); | 196 | return (0); | |
199 | } | 197 | } | |
@@ -222,55 +220,53 @@ tnchktc() | @@ -222,55 +220,53 @@ tnchktc() | |||
222 | } | 220 | } | |
223 | strcpy(p, q); | 221 | strcpy(p, q); | |
224 | tbuf = holdtbuf; | 222 | tbuf = holdtbuf; | |
225 | return (1); | 223 | return (1); | |
226 | } | 224 | } | |
227 | 225 | |||
228 | /* | 226 | /* | |
229 | * Tnamatch deals with name matching. The first field of the termcap | 227 | * Tnamatch deals with name matching. The first field of the termcap | |
230 | * entry is a sequence of names separated by |'s, so we compare | 228 | * entry is a sequence of names separated by |'s, so we compare | |
231 | * against each such name. The normal : terminator after the last | 229 | * against each such name. The normal : terminator after the last | |
232 | * name (before the first field) stops us. | 230 | * name (before the first field) stops us. | |
233 | */ | 231 | */ | |
234 | int | 232 | int | |
235 | tnamatch(np) | 233 | tnamatch(char *np) | |
236 | char *np; | |||
237 | { | 234 | { | |
238 | char *Np, *Bp; | 235 | char *Np, *Bp; | |
239 | 236 | |||
240 | Bp = tbuf; | 237 | Bp = tbuf; | |
241 | if (*Bp == '#') | 238 | if (*Bp == '#') | |
242 | return (0); | 239 | return (0); | |
243 | for (;;) { | 240 | for (;;) { | |
244 | for (Np = np; *Np && *Bp == *Np; Bp++, Np++) | 241 | for (Np = np; *Np && *Bp == *Np; Bp++, Np++) | |
245 | continue; | 242 | continue; | |
246 | if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) | 243 | if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) | |
247 | return (1); | 244 | return (1); | |
248 | while (*Bp && *Bp != ':' && *Bp != '|') | 245 | while (*Bp && *Bp != ':' && *Bp != '|') | |
249 | Bp++; | 246 | Bp++; | |
250 | if (*Bp == 0 || *Bp == ':') | 247 | if (*Bp == 0 || *Bp == ':') | |
251 | return (0); | 248 | return (0); | |
252 | Bp++; | 249 | Bp++; | |
253 | } | 250 | } | |
254 | } | 251 | } | |
255 | 252 | |||
256 | /* | 253 | /* | |
257 | * Skip to the next field. Notice that this is very dumb, not | 254 | * Skip to the next field. Notice that this is very dumb, not | |
258 | * knowing about \: escapes or any such. If necessary, :'s can be put | 255 | * knowing about \: escapes or any such. If necessary, :'s can be put | |
259 | * into the termcap file in octal. | 256 | * into the termcap file in octal. | |
260 | */ | 257 | */ | |
261 | static char * | 258 | static char * | |
262 | tskip(bp) | 259 | tskip(char *bp) | |
263 | char *bp; | |||
264 | { | 260 | { | |
265 | int dquote; | 261 | int dquote; | |
266 | 262 | |||
267 | dquote = 0; | 263 | dquote = 0; | |
268 | while (*bp) { | 264 | while (*bp) { | |
269 | switch (*bp) { | 265 | switch (*bp) { | |
270 | case ':': | 266 | case ':': | |
271 | if (!dquote) | 267 | if (!dquote) | |
272 | goto breakbreak; | 268 | goto breakbreak; | |
273 | else | 269 | else | |
274 | bp++; | 270 | bp++; | |
275 | break; | 271 | break; | |
276 | case '\\': | 272 | case '\\': | |
@@ -294,28 +290,27 @@ breakbreak: | @@ -294,28 +290,27 @@ breakbreak: | |||
294 | bp++; | 290 | bp++; | |
295 | return (bp); | 291 | return (bp); | |
296 | } | 292 | } | |
297 | 293 | |||
298 | /* | 294 | /* | |
299 | * Return the (numeric) option id. | 295 | * Return the (numeric) option id. | |
300 | * Numeric options look like | 296 | * Numeric options look like | |
301 | * li#80 | 297 | * li#80 | |
302 | * i.e. the option string is separated from the numeric value by | 298 | * i.e. the option string is separated from the numeric value by | |
303 | * a # character. If the option is not found we return -1. | 299 | * a # character. If the option is not found we return -1. | |
304 | * Note that we handle octal numbers beginning with 0. | 300 | * Note that we handle octal numbers beginning with 0. | |
305 | */ | 301 | */ | |
306 | int64_t | 302 | int64_t | |
307 | tgetnum(id) | 303 | tgetnum(char *id) | |
308 | char *id; | |||
309 | { | 304 | { | |
310 | int64_t i; | 305 | int64_t i; | |
311 | int base; | 306 | int base; | |
312 | char *bp = tbuf; | 307 | char *bp = tbuf; | |
313 | 308 | |||
314 | for (;;) { | 309 | for (;;) { | |
315 | bp = tskip(bp); | 310 | bp = tskip(bp); | |
316 | if (*bp == 0) | 311 | if (*bp == 0) | |
317 | return (-1); | 312 | return (-1); | |
318 | if (strncmp(bp, id, strlen(id)) != 0) | 313 | if (strncmp(bp, id, strlen(id)) != 0) | |
319 | continue; | 314 | continue; | |
320 | bp += strlen(id); | 315 | bp += strlen(id); | |
321 | if (*bp == '@') | 316 | if (*bp == '@') | |
@@ -330,106 +325,102 @@ tgetnum(id) | @@ -330,106 +325,102 @@ tgetnum(id) | |||
330 | while (isdigit((unsigned char)*bp)) | 325 | while (isdigit((unsigned char)*bp)) | |
331 | i *= base, i += *bp++ - '0'; | 326 | i *= base, i += *bp++ - '0'; | |
332 | return (i); | 327 | return (i); | |
333 | } | 328 | } | |
334 | } | 329 | } | |
335 | 330 | |||
336 | /* | 331 | /* | |
337 | * Handle a flag option. | 332 | * Handle a flag option. | |
338 | * Flag options are given "naked", i.e. followed by a : or the end | 333 | * Flag options are given "naked", i.e. followed by a : or the end | |
339 | * of the buffer. Return 1 if we find the option, or 0 if it is | 334 | * of the buffer. Return 1 if we find the option, or 0 if it is | |
340 | * not given. | 335 | * not given. | |
341 | */ | 336 | */ | |
342 | int | 337 | int | |
343 | tgetflag(id) | 338 | tgetflag(char *id) | |
344 | char *id; | |||
345 | { | 339 | { | |
346 | char *bp = tbuf; | 340 | char *bp = tbuf; | |
347 | 341 | |||
348 | for (;;) { | 342 | for (;;) { | |
349 | bp = tskip(bp); | 343 | bp = tskip(bp); | |
350 | if (!*bp) | 344 | if (!*bp) | |
351 | return (0); | 345 | return (0); | |
352 | if (strncmp(bp, id, strlen(id)) == 0) { | 346 | if (strncmp(bp, id, strlen(id)) == 0) { | |
353 | bp += strlen(id); | 347 | bp += strlen(id); | |
354 | if (!*bp || *bp == ':') | 348 | if (!*bp || *bp == ':') | |
355 | return (1); | 349 | return (1); | |
356 | else if (*bp == '@') | 350 | else if (*bp == '@') | |
357 | return (0); | 351 | return (0); | |
358 | } | 352 | } | |
359 | } | 353 | } | |
360 | } | 354 | } | |
361 | 355 | |||
362 | /* | 356 | /* | |
363 | * Get a string valued option. | 357 | * Get a string valued option. | |
364 | * These are given as | 358 | * These are given as | |
365 | * cl=^Z | 359 | * cl=^Z | |
366 | * Much decoding is done on the strings, and the strings are | 360 | * Much decoding is done on the strings, and the strings are | |
367 | * placed in area, which is a ref parameter which is updated. | 361 | * placed in area, which is a ref parameter which is updated. | |
368 | * No checking on area overflow. | 362 | * No checking on area overflow. | |
369 | */ | 363 | */ | |
370 | char * | 364 | char * | |
371 | tgetstr(id, area) | 365 | tgetstr(char *id, char **area) | |
372 | char *id, **area; | |||
373 | { | 366 | { | |
374 | char *bp = tbuf; | 367 | char *bp = tbuf; | |
375 | 368 | |||
376 | for (;;) { | 369 | for (;;) { | |
377 | bp = tskip(bp); | 370 | bp = tskip(bp); | |
378 | if (!*bp) | 371 | if (!*bp) | |
379 | return (0); | 372 | return (0); | |
380 | if (strncmp(bp, id, strlen(id)) != 0) | 373 | if (strncmp(bp, id, strlen(id)) != 0) | |
381 | continue; | 374 | continue; | |
382 | bp += strlen(id); | 375 | bp += strlen(id); | |
383 | if (*bp == '@') | 376 | if (*bp == '@') | |
384 | return (0); | 377 | return (0); | |
385 | if (*bp != '=') | 378 | if (*bp != '=') | |
386 | continue; | 379 | continue; | |
387 | bp++; | 380 | bp++; | |
388 | return (tdecode(bp, area)); | 381 | return (tdecode(bp, area)); | |
389 | } | 382 | } | |
390 | } | 383 | } | |
391 | 384 | |||
392 | /* | 385 | /* | |
393 | * Tdecode does the grung work to decode the | 386 | * Tdecode does the grung work to decode the | |
394 | * string capability escapes. | 387 | * string capability escapes. | |
395 | */ | 388 | */ | |
396 | static char * | 389 | static char * | |
397 | tdecode(str, area) | 390 | tdecode(char *str, char **area) | |
398 | char *str; | |||
399 | char **area; | |||
400 | { | 391 | { | |
401 | char *cp; | 392 | char *cp; | |
402 | int c; | 393 | int c; | |
403 | char *dp; | 394 | const char *dps = "E\033^^\\\\::n\nr\rt\tb\bf\f\"\"", *dp; | |
404 | int i; | 395 | int i; | |
405 | char term; | 396 | char term; | |
406 | 397 | |||
407 | term = ':'; | 398 | term = ':'; | |
408 | cp = *area; | 399 | cp = *area; | |
409 | again: | 400 | again: | |
410 | if (*str == '"') { | 401 | if (*str == '"') { | |
411 | term = '"'; | 402 | term = '"'; | |
412 | str++; | 403 | str++; | |
413 | } | 404 | } | |
414 | while ((c = *str++) && c != term) { | 405 | while ((c = *str++) && c != term) { | |
415 | switch (c) { | 406 | switch (c) { | |
416 | 407 | |||
417 | case '^': | 408 | case '^': | |
418 | c = *str++ & 037; | 409 | c = *str++ & 037; | |
419 | break; | 410 | break; | |
420 | 411 | |||
421 | case '\\': | 412 | case '\\': | |
422 | dp = "E\033^^\\\\::n\nr\rt\tb\bf\f\"\""; | 413 | dp = dps; | |
423 | c = *str++; | 414 | c = *str++; | |
424 | nextc: | 415 | nextc: | |
425 | if (*dp++ == c) { | 416 | if (*dp++ == c) { | |
426 | c = *dp++; | 417 | c = *dp++; | |
427 | break; | 418 | break; | |
428 | } | 419 | } | |
429 | dp++; | 420 | dp++; | |
430 | if (*dp) | 421 | if (*dp) | |
431 | goto nextc; | 422 | goto nextc; | |
432 | if (isdigit((unsigned char)c)) { | 423 | if (isdigit((unsigned char)c)) { | |
433 | c -= '0', i = 2; | 424 | c -= '0', i = 2; | |
434 | do | 425 | do | |
435 | c <<= 3, c |= *str++ - '0'; | 426 | c <<= 3, c |= *str++ - '0'; |
--- src/usr.sbin/rtadvd/advcap.h 2006/03/05 23:47:08 1.6
+++ src/usr.sbin/rtadvd/advcap.h 2011/12/10 19:14:29 1.7
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: advcap.h,v 1.6 2006/03/05 23:47:08 rpaulo Exp $ */ | 1 | /* $NetBSD: advcap.h,v 1.7 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: advcap.h,v 1.5 2003/06/09 05:40:54 t-momose Exp $ */ | 2 | /* $KAME: advcap.h,v 1.5 2003/06/09 05:40:54 t-momose Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1994,1995 by Andrey A. Chernov, Moscow, Russia. | 5 | * Copyright (C) 1994,1995 by Andrey A. Chernov, Moscow, Russia. | |
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 | |
@@ -26,21 +26,21 @@ | @@ -26,21 +26,21 @@ | |||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | 27 | * SUCH DAMAGE. | |
28 | */ | 28 | */ | |
29 | 29 | |||
30 | /* Based on Id: termcap.h,v 1.8 1996/09/10 12:42:10 peter Exp */ | 30 | /* Based on Id: termcap.h,v 1.8 1996/09/10 12:42:10 peter Exp */ | |
31 | 31 | |||
32 | #ifndef _ADVCAP_H_ | 32 | #ifndef _ADVCAP_H_ | |
33 | #define _ADVCAP_H_ | 33 | #define _ADVCAP_H_ | |
34 | 34 | |||
35 | #include <sys/cdefs.h> | 35 | #include <sys/cdefs.h> | |
36 | 36 | |||
37 | __BEGIN_DECLS | 37 | __BEGIN_DECLS | |
38 | 38 | |||
39 | extern int agetent __P((char *, const char *)); | 39 | extern int agetent(char *, const char *); | |
40 | extern int agetflag __P((const char *)); | 40 | extern int agetflag(const char *); | |
41 | extern int64_t agetnum __P((const char *)); | 41 | extern int64_t agetnum(const char *); | |
42 | extern char *agetstr __P((const char *, char **)); | 42 | extern char *agetstr(const char *, char **); | |
43 | 43 | |||
44 | __END_DECLS | 44 | __END_DECLS | |
45 | 45 | |||
46 | #endif /* _ADVCAP_H_ */ | 46 | #endif /* _ADVCAP_H_ */ |
--- src/usr.sbin/rtadvd/config.h 2006/03/05 23:47:08 1.6
+++ src/usr.sbin/rtadvd/config.h 2011/12/10 19:14:29 1.7
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: config.h,v 1.6 2006/03/05 23:47:08 rpaulo Exp $ */ | 1 | /* $NetBSD: config.h,v 1.7 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: config.h,v 1.9 2003/08/06 04:19:40 ono Exp $ */ | 2 | /* $KAME: config.h,v 1.9 2003/08/06 04:19:40 ono Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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 | |
@@ -20,28 +20,29 @@ | @@ -20,28 +20,29 @@ | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | 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 | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | extern void getconfig __P((char *)); | 33 | extern void getconfig(char *); | |
34 | extern void delete_prefix __P((struct prefix *)); | 34 | extern void delete_prefix(struct prefix *); | |
35 | extern void invalidate_prefix __P((struct prefix *)); | 35 | extern void invalidate_prefix(struct prefix *); | |
36 | extern void update_prefix __P((struct prefix *)); | 36 | extern void update_prefix(struct prefix *); | |
37 | extern void make_prefix __P((struct rainfo *, int, struct in6_addr *, int)); | 37 | extern void make_prefix(struct rainfo *, int, struct in6_addr *, int); | |
38 | extern void make_packet __P((struct rainfo *)); | 38 | extern void make_packet(struct rainfo *); | |
39 | extern void get_prefix __P((struct rainfo *)); | 39 | extern void get_prefix(struct rainfo *); | |
40 | ||||
41 | 40 | |||
42 | /* | 41 | /* | |
43 | * it is highly unlikely to have 100 prefix information options, | 42 | * it is highly unlikely to have 100 information options, | |
44 | * so it should be okay to limit it | 43 | * so it should be okay to limit it | |
45 | */ | 44 | */ | |
46 | #define MAXPREFIX 100 | 45 | #define MAXPREFIX 100 | |
47 | #define MAXROUTE 100 | 46 | #define MAXROUTE 100 | |
47 | #define MAXRDNSS 100 | |||
48 | #define MAXDNSSL 100 |
--- src/usr.sbin/rtadvd/timer.h 2006/03/05 23:47:08 1.6
+++ src/usr.sbin/rtadvd/timer.h 2011/12/10 19:14:29 1.7
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: timer.h,v 1.6 2006/03/05 23:47:08 rpaulo Exp $ */ | 1 | /* $NetBSD: timer.h,v 1.7 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: timer.h,v 1.5 2002/05/31 13:30:38 jinmei Exp $ */ | 2 | /* $KAME: timer.h,v 1.5 2002/05/31 13:30:38 jinmei 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 | |
@@ -30,36 +30,36 @@ | @@ -30,36 +30,36 @@ | |||
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* a < b */ | 33 | /* a < b */ | |
34 | #define TIMEVAL_LT(a, b) (((a).tv_sec < (b).tv_sec) ||\ | 34 | #define TIMEVAL_LT(a, b) (((a).tv_sec < (b).tv_sec) ||\ | |
35 | (((a).tv_sec == (b).tv_sec) && \ | 35 | (((a).tv_sec == (b).tv_sec) && \ | |
36 | ((a).tv_usec < (b).tv_usec))) | 36 | ((a).tv_usec < (b).tv_usec))) | |
37 | 37 | |||
38 | /* a <= b */ | 38 | /* a <= b */ | |
39 | #define TIMEVAL_LEQ(a, b) (((a).tv_sec < (b).tv_sec) ||\ | 39 | #define TIMEVAL_LEQ(a, b) (((a).tv_sec < (b).tv_sec) ||\ | |
40 | (((a).tv_sec == (b).tv_sec) &&\ | 40 | (((a).tv_sec == (b).tv_sec) &&\ | |
41 | ((a).tv_usec <= (b).tv_usec))) | 41 | ((a).tv_usec <= (b).tv_usec))) | |
42 | 42 | |||
43 | extern TAILQ_HEAD(rtadvd_timer_head_t, rtadvd_timer) ra_timer; | |||
43 | struct rtadvd_timer { | 44 | struct rtadvd_timer { | |
44 | struct rtadvd_timer *next; | 45 | TAILQ_ENTRY(rtadvd_timer) next; | |
45 | struct rtadvd_timer *prev; | |||
46 | struct rainfo *rai; | 46 | struct rainfo *rai; | |
47 | struct timeval tm; | 47 | struct timeval tm; | |
48 | 48 | |||
49 | struct rtadvd_timer *(*expire) __P((void *)); /* expiration function */ | 49 | struct rtadvd_timer *(*expire) (void *); /* expiration function */ | |
50 | void *expire_data; | 50 | void *expire_data; | |
51 | void (*update) __P((void *, struct timeval *)); /* update function */ | 51 | void (*update) __P((void *, struct timeval *)); /* update function */ | |
52 | void *update_data; | 52 | void *update_data; | |
53 | }; | 53 | }; | |
54 | 54 | |||
55 | void rtadvd_timer_init __P((void)); | 55 | void rtadvd_timer_init(void); | |
56 | struct rtadvd_timer *rtadvd_add_timer __P((struct rtadvd_timer *(*) __P((void *)), | 56 | struct rtadvd_timer *rtadvd_add_timer(struct rtadvd_timer *(*) (void *), | |
57 | void (*) __P((void *, struct timeval *)), void *, void *)); | 57 | void (*) (void *, struct timeval *), void *, void *); | |
58 | void rtadvd_set_timer __P((struct timeval *, struct rtadvd_timer *)); | 58 | void rtadvd_set_timer(struct timeval *, struct rtadvd_timer *); | |
59 | void rtadvd_remove_timer __P((struct rtadvd_timer **)); | 59 | void rtadvd_remove_timer(struct rtadvd_timer **); | |
60 | struct timeval * rtadvd_check_timer __P((void)); | 60 | struct timeval * rtadvd_check_timer(void); | |
61 | struct timeval * rtadvd_timer_rest __P((struct rtadvd_timer *)); | 61 | struct timeval * rtadvd_timer_rest(struct rtadvd_timer *); | |
62 | void TIMEVAL_ADD __P((struct timeval *, struct timeval *, | 62 | void TIMEVAL_ADD(struct timeval *, struct timeval *, | |
63 | struct timeval *)); | 63 | struct timeval *); | |
64 | void TIMEVAL_SUB __P((struct timeval *, struct timeval *, | 64 | void TIMEVAL_SUB(struct timeval *, struct timeval *, | |
65 | struct timeval *)); | 65 | struct timeval *); |
--- src/usr.sbin/rtadvd/config.c 2006/05/11 08:35:47 1.25
+++ src/usr.sbin/rtadvd/config.c 2011/12/10 19:14:29 1.26
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: config.c,v 1.25 2006/05/11 08:35:47 mrg Exp $ */ | 1 | /* $NetBSD: config.c,v 1.26 2011/12/10 19:14:29 roy 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 | |
@@ -56,82 +56,104 @@ | @@ -56,82 +56,104 @@ | |||
56 | #include <stdlib.h> | 56 | #include <stdlib.h> | |
57 | #include <search.h> | 57 | #include <search.h> | |
58 | #include <unistd.h> | 58 | #include <unistd.h> | |
59 | #include <ifaddrs.h> | 59 | #include <ifaddrs.h> | |
60 | 60 | |||
61 | #include "rtadvd.h" | 61 | #include "rtadvd.h" | |
62 | #include "advcap.h" | 62 | #include "advcap.h" | |
63 | #include "timer.h" | 63 | #include "timer.h" | |
64 | #include "if.h" | 64 | #include "if.h" | |
65 | #include "config.h" | 65 | #include "config.h" | |
66 | 66 | |||
67 | static time_t prefix_timo = (60 * 120); /* 2 hours. | 67 | static time_t prefix_timo = (60 * 120); /* 2 hours. | |
68 | * XXX: should be configurable. */ | 68 | * XXX: should be configurable. */ | |
69 | extern struct rainfo *ralist; | 69 | static struct rtadvd_timer *prefix_timeout(void *); | |
70 | static void makeentry(char *, size_t, int, const char *); | |||
71 | static int getinet6sysctl(int); | |||
70 | 72 | |||
71 | static struct rtadvd_timer *prefix_timeout __P((void *)); | 73 | static size_t | |
72 | static void makeentry __P((char *, size_t, int, char *)); | 74 | encode_domain(char *dst, const char *src) | |
73 | static int getinet6sysctl __P((int)); | 75 | { | |
76 | ssize_t len; | |||
77 | char *odst, *p; | |||
78 | ||||
79 | odst = dst; | |||
80 | while (src && (len = strlen(src)) != 0) { | |||
81 | p = strchr(src, '.'); | |||
82 | *dst++ = len = MIN(63, p == NULL ? len : p - src); | |||
83 | memcpy(dst, src, len); | |||
84 | dst += len; | |||
85 | if (p == NULL) | |||
86 | break; | |||
87 | src = p + 1; | |||
88 | } | |||
89 | *dst++ = '\0'; | |||
90 | ||||
91 | return dst - odst; | |||
92 | } | |||
74 | 93 | |||
75 | void | 94 | void | |
76 | getconfig(intface) | 95 | getconfig(intface) | |
77 | char *intface; | 96 | char *intface; | |
78 | { | 97 | { | |
79 | int stat, i; | 98 | int stat, c, i; | |
80 | char tbuf[BUFSIZ]; | 99 | char tbuf[BUFSIZ]; | |
81 | struct rainfo *tmp; | 100 | struct rainfo *tmp; | |
82 | long val; | 101 | int32_t val; | |
83 | int64_t val64; | 102 | int64_t val64; | |
84 | char buf[BUFSIZ]; | 103 | char buf[BUFSIZ]; | |
85 | char *bp = buf; | 104 | char *bp = buf; | |
86 | char *addr, *flagstr; | 105 | char *addr, *flagstr, *ap; | |
87 | static int forwarding = -1; | 106 | static int forwarding = -1; | |
107 | char entbuf[256], abuf[256]; | |||
88 | 108 | |||
89 | #define MUSTHAVE(var, cap) \ | 109 | #define MUSTHAVE(var, cap) \ | |
90 | do { \ | 110 | do { \ | |
91 | int64_t t; \ | 111 | int64_t t; \ | |
92 | if ((t = agetnum(cap)) < 0) { \ | 112 | if ((t = agetnum(cap)) < 0) { \ | |
93 | fprintf(stderr, "rtadvd: need %s for interface %s\n", \ | 113 | fprintf(stderr, "rtadvd: need %s for interface %s\n", \ | |
94 | cap, intface); \ | 114 | cap, intface); \ | |
95 | exit(1); \ | 115 | exit(1); \ | |
96 | } \ | 116 | } \ | |
97 | var = t; \ | 117 | var = t; \ | |
98 | } while (0) | 118 | } while (0) | |
99 | #define MAYHAVE(var, cap, def) \ | 119 | #define MAYHAVE(var, cap, def) \ | |
100 | do { \ | 120 | do { \ | |
101 | if ((var = agetnum(cap)) < 0) \ | 121 | if ((var = agetnum(cap)) < 0) \ | |
102 | var = def; \ | 122 | var = def; \ | |
103 | } while (0) | 123 | } while (0) | |
124 | #define ELM_MALLOC(p,error_action) \ | |||
125 | do { \ | |||
126 | p = malloc(sizeof(*p)); \ | |||
127 | if (p == NULL) { \ | |||
128 | syslog(LOG_ERR, "<%s> malloc failed: %s", \ | |||
129 | __func__, strerror(errno)); \ | |||
130 | error_action; \ | |||
131 | } \ | |||
132 | memset(p, 0, sizeof(*p)); \ | |||
133 | } while(0) | |||
134 | ||||
104 | 135 | |||
105 | if ((stat = agetent(tbuf, intface)) <= 0) { | 136 | if ((stat = agetent(tbuf, intface)) <= 0) { | |
106 | memset(tbuf, 0, sizeof(tbuf)); | 137 | memset(tbuf, 0, sizeof(tbuf)); | |
107 | syslog(LOG_INFO, | 138 | syslog(LOG_INFO, | |
108 | "<%s> %s isn't defined in the configuration file" | 139 | "<%s> %s isn't defined in the configuration file" | |
109 | " or the configuration file doesn't exist." | 140 | " or the configuration file doesn't exist." | |
110 | " Treat it as default", | 141 | " Treat it as default", | |
111 | __func__, intface); | 142 | __func__, intface); | |
112 | } | 143 | } | |
113 | 144 | |||
114 | tmp = (struct rainfo *)malloc(sizeof(*ralist)); | 145 | ELM_MALLOC(tmp, exit(1)); | |
115 | if (tmp == NULL) { | |||
116 | syslog(LOG_INFO, "<%s> %s: can't allocate enough memory", | |||
117 | __func__, intface); | |||
118 | exit(1); | |||
119 | } | |||
120 | memset(tmp, 0, sizeof(*tmp)); | 146 | memset(tmp, 0, sizeof(*tmp)); | |
121 | tmp->prefix.next = tmp->prefix.prev = &tmp->prefix; | |||
122 | #ifdef ROUTEINFO | |||
123 | tmp->route.next = tmp->route.prev = &tmp->route; | |||
124 | #endif | |||
125 | 147 | |||
126 | /* check if we are allowed to forward packets (if not determined) */ | 148 | /* check if we are allowed to forward packets (if not determined) */ | |
127 | if (forwarding < 0) { | 149 | if (forwarding < 0) { | |
128 | if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0) | 150 | if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0) | |
129 | exit(1); | 151 | exit(1); | |
130 | } | 152 | } | |
131 | 153 | |||
132 | /* get interface information */ | 154 | /* get interface information */ | |
133 | if (agetflag("nolladdr")) | 155 | if (agetflag("nolladdr")) | |
134 | tmp->advlinkopt = 0; | 156 | tmp->advlinkopt = 0; | |
135 | else | 157 | else | |
136 | tmp->advlinkopt = 1; | 158 | tmp->advlinkopt = 1; | |
137 | if (tmp->advlinkopt) { | 159 | if (tmp->advlinkopt) { | |
@@ -148,42 +170,42 @@ getconfig(intface) | @@ -148,42 +170,42 @@ getconfig(intface) | |||
148 | if ((tmp->phymtu = if_getmtu(intface)) == 0) { | 170 | if ((tmp->phymtu = if_getmtu(intface)) == 0) { | |
149 | tmp->phymtu = IPV6_MMTU; | 171 | tmp->phymtu = IPV6_MMTU; | |
150 | syslog(LOG_WARNING, | 172 | syslog(LOG_WARNING, | |
151 | "<%s> can't get interface mtu of %s. Treat as %d", | 173 | "<%s> can't get interface mtu of %s. Treat as %d", | |
152 | __func__, intface, IPV6_MMTU); | 174 | __func__, intface, IPV6_MMTU); | |
153 | } | 175 | } | |
154 | 176 | |||
155 | /* | 177 | /* | |
156 | * set router configuration variables. | 178 | * set router configuration variables. | |
157 | */ | 179 | */ | |
158 | MAYHAVE(val, "maxinterval", DEF_MAXRTRADVINTERVAL); | 180 | MAYHAVE(val, "maxinterval", DEF_MAXRTRADVINTERVAL); | |
159 | if (val < MIN_MAXINTERVAL || val > MAX_MAXINTERVAL) { | 181 | if (val < MIN_MAXINTERVAL || val > MAX_MAXINTERVAL) { | |
160 | syslog(LOG_ERR, | 182 | syslog(LOG_ERR, | |
161 | "<%s> maxinterval (%ld) on %s is invalid " | 183 | "<%s> maxinterval (%d) on %s is invalid " | |
162 | "(must be between %u and %u)", __func__, val, | 184 | "(must be between %u and %u)", __func__, val, | |
163 | intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL); | 185 | intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL); | |
164 | exit(1); | 186 | exit(1); | |
165 | } | 187 | } | |
166 | tmp->maxinterval = (u_int)val; | 188 | tmp->maxinterval = val; | |
167 | MAYHAVE(val, "mininterval", tmp->maxinterval/3); | 189 | MAYHAVE(val, "mininterval", tmp->maxinterval/3); | |
168 | if (val < MIN_MININTERVAL || val > (tmp->maxinterval * 3) / 4) { | 190 | if (val < MIN_MININTERVAL || val > (tmp->maxinterval * 3) / 4) { | |
169 | syslog(LOG_ERR, | 191 | syslog(LOG_ERR, | |
170 | "<%s> mininterval (%ld) on %s is invalid " | 192 | "<%s> mininterval (%d) on %s is invalid " | |
171 | "(must be between %u and %d)", | 193 | "(must be between %u and %d)", | |
172 | __func__, val, intface, MIN_MININTERVAL, | 194 | __func__, val, intface, MIN_MININTERVAL, | |
173 | (tmp->maxinterval * 3) / 4); | 195 | (tmp->maxinterval * 3) / 4); | |
174 | exit(1); | 196 | exit(1); | |
175 | } | 197 | } | |
176 | tmp->mininterval = (u_int)val; | 198 | tmp->mininterval = val; | |
177 | 199 | |||
178 | MAYHAVE(val, "chlim", DEF_ADVCURHOPLIMIT); | 200 | MAYHAVE(val, "chlim", DEF_ADVCURHOPLIMIT); | |
179 | tmp->hoplimit = val & 0xff; | 201 | tmp->hoplimit = val & 0xff; | |
180 | 202 | |||
181 | if ((flagstr = (char *)agetstr("raflags", &bp))) { | 203 | if ((flagstr = (char *)agetstr("raflags", &bp))) { | |
182 | val = 0; | 204 | val = 0; | |
183 | if (strchr(flagstr, 'm')) | 205 | if (strchr(flagstr, 'm')) | |
184 | val |= ND_RA_FLAG_MANAGED; | 206 | val |= ND_RA_FLAG_MANAGED; | |
185 | if (strchr(flagstr, 'o')) | 207 | if (strchr(flagstr, 'o')) | |
186 | val |= ND_RA_FLAG_OTHER; | 208 | val |= ND_RA_FLAG_OTHER; | |
187 | if (strchr(flagstr, 'h')) | 209 | if (strchr(flagstr, 'h')) | |
188 | val |= ND_RA_FLAG_RTPREF_HIGH; | 210 | val |= ND_RA_FLAG_RTPREF_HIGH; | |
189 | if (strchr(flagstr, 'l')) { | 211 | if (strchr(flagstr, 'l')) { | |
@@ -203,133 +225,132 @@ getconfig(intface) | @@ -203,133 +225,132 @@ getconfig(intface) | |||
203 | #define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ | 225 | #define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ | |
204 | #define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */ | 226 | #define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */ | |
205 | #endif | 227 | #endif | |
206 | tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK; | 228 | tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK; | |
207 | if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV) { | 229 | if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV) { | |
208 | syslog(LOG_ERR, "<%s> invalid router preference (%02x) on %s", | 230 | syslog(LOG_ERR, "<%s> invalid router preference (%02x) on %s", | |
209 | __func__, tmp->rtpref, intface); | 231 | __func__, tmp->rtpref, intface); | |
210 | exit(1); | 232 | exit(1); | |
211 | } | 233 | } | |
212 | 234 | |||
213 | MAYHAVE(val, "rltime", tmp->maxinterval * 3); | 235 | MAYHAVE(val, "rltime", tmp->maxinterval * 3); | |
214 | if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) { | 236 | if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) { | |
215 | syslog(LOG_ERR, | 237 | syslog(LOG_ERR, | |
216 | "<%s> router lifetime (%ld) on %s is invalid " | 238 | "<%s> router lifetime (%d) on %s is invalid " | |
217 | "(must be 0 or between %d and %d)", | 239 | "(must be 0 or between %d and %d)", | |
218 | __func__, val, intface, | 240 | __func__, val, intface, | |
219 | tmp->maxinterval, MAXROUTERLIFETIME); | 241 | tmp->maxinterval, MAXROUTERLIFETIME); | |
220 | exit(1); | 242 | exit(1); | |
221 | } | 243 | } | |
222 | /* | 244 | /* | |
223 | * Basically, hosts MUST NOT send Router Advertisement messages at any | 245 | * Basically, hosts MUST NOT send Router Advertisement messages at any | |
224 | * time (RFC 2461, Section 6.2.3). However, it would sometimes be | 246 | * time (RFC 2461, Section 6.2.3). However, it would sometimes be | |
225 | * useful to allow hosts to advertise some parameters such as prefix | 247 | * useful to allow hosts to advertise some parameters such as prefix | |
226 | * information and link MTU. Thus, we allow hosts to invoke rtadvd | 248 | * information and link MTU. Thus, we allow hosts to invoke rtadvd | |
227 | * only when router lifetime (on every advertising interface) is | 249 | * only when router lifetime (on every advertising interface) is | |
228 | * explicitly set zero. (see also the above section) | 250 | * explicitly set zero. (see also the above section) | |
229 | */ | 251 | */ | |
230 | if (val && forwarding == 0) { | 252 | if (val && forwarding == 0) { | |
231 | syslog(LOG_ERR, | 253 | syslog(LOG_ERR, | |
232 | "<%s> non zero router lifetime is specified for %s, " | 254 | "<%s> non zero router lifetime is specified for %s, " | |
233 | "which must not be allowed for hosts. you must " | 255 | "which must not be allowed for hosts. you must " | |
234 | "change router lifetime or enable IPv6 forwarding.", | 256 | "change router lifetime or enable IPv6 forwarding.", | |
235 | __func__, intface); | 257 | __func__, intface); | |
236 | exit(1); | 258 | exit(1); | |
237 | } | 259 | } | |
238 | tmp->lifetime = val & 0xffff; | 260 | tmp->lifetime = val & 0xffff; | |
239 | 261 | |||
240 | MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME); | 262 | MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME); | |
241 | if (val < 0 || val > MAXREACHABLETIME) { | 263 | if (val < 0 || val > MAXREACHABLETIME) { | |
242 | syslog(LOG_ERR, | 264 | syslog(LOG_ERR, | |
243 | "<%s> reachable time (%ld) on %s is invalid " | 265 | "<%s> reachable time (%d) on %s is invalid " | |
244 | "(must be no greater than %d)", | 266 | "(must be no greater than %d)", | |
245 | __func__, val, intface, MAXREACHABLETIME); | 267 | __func__, val, intface, MAXREACHABLETIME); | |
246 | exit(1); | 268 | exit(1); | |
247 | } | 269 | } | |
248 | tmp->reachabletime = (u_int32_t)val; | 270 | tmp->reachabletime = (uint32_t)val; | |
249 | 271 | |||
250 | MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER); | 272 | MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER); | |
251 | if (val64 < 0 || val64 > 0xffffffff) { | 273 | if (val64 < 0 || val64 > 0xffffffff) { | |
252 | syslog(LOG_ERR, "<%s> retrans time (%lld) on %s out of range", | 274 | syslog(LOG_ERR, "<%s> retrans time (%lld) on %s out of range", | |
253 | __func__, (long long)val64, intface); | 275 | __func__, (long long)val64, intface); | |
254 | exit(1); | 276 | exit(1); | |
255 | } | 277 | } | |
256 | tmp->retranstimer = (u_int32_t)val64; | 278 | tmp->retranstimer = (uint32_t)val64; | |
257 | 279 | |||
258 | if (agetnum("hapref") != -1 || agetnum("hatime") != -1) { | 280 | if (agetnum("hapref") != -1 || agetnum("hatime") != -1) { | |
259 | syslog(LOG_ERR, | 281 | syslog(LOG_ERR, | |
260 | "<%s> mobile-ip6 configuration not supported", | 282 | "<%s> mobile-ip6 configuration not supported", | |
261 | __func__); | 283 | __func__); | |
262 | exit(1); | 284 | exit(1); | |
263 | } | 285 | } | |
264 | /* prefix information */ | 286 | /* prefix information */ | |
265 | 287 | |||
266 | /* | 288 | /* | |
267 | * This is an implementation specific parameter to consider | 289 | * This is an implementation specific parameter to consider | |
268 | * link propagation delays and poorly synchronized clocks when | 290 | * link propagation delays and poorly synchronized clocks when | |
269 | * checking consistency of advertised lifetimes. | 291 | * checking consistency of advertised lifetimes. | |
270 | */ | 292 | */ | |
271 | MAYHAVE(val, "clockskew", 0); | 293 | MAYHAVE(val, "clockskew", 0); | |
272 | tmp->clockskew = val; | 294 | tmp->clockskew = val; | |
273 | 295 | |||
274 | tmp->pfxs = 0; | 296 | tmp->pfxs++; | |
297 | TAILQ_INIT(&tmp->prefix); | |||
275 | for (i = -1; i < MAXPREFIX; i++) { | 298 | for (i = -1; i < MAXPREFIX; i++) { | |
276 | struct prefix *pfx; | 299 | struct prefix *pfx; | |
277 | char entbuf[256]; | |||
278 | 300 | |||
279 | makeentry(entbuf, sizeof(entbuf), i, "addr"); | 301 | makeentry(entbuf, sizeof(entbuf), i, "addr"); | |
280 | addr = (char *)agetstr(entbuf, &bp); | 302 | addr = (char *)agetstr(entbuf, &bp); | |
281 | if (addr == NULL) | 303 | if (addr == NULL) | |
282 | continue; | 304 | continue; | |
283 | 305 | |||
284 | /* allocate memory to store prefix information */ | 306 | /* allocate memory to store prefix information */ | |
285 | if ((pfx = malloc(sizeof(struct prefix))) == NULL) { | 307 | if ((pfx = malloc(sizeof(struct prefix))) == NULL) { | |
286 | syslog(LOG_ERR, | 308 | syslog(LOG_ERR, | |
287 | "<%s> can't allocate enough memory", | 309 | "<%s> can't allocate enough memory", | |
288 | __func__); | 310 | __func__); | |
289 | exit(1); | 311 | exit(1); | |
290 | } | 312 | } | |
291 | memset(pfx, 0, sizeof(*pfx)); | 313 | memset(pfx, 0, sizeof(*pfx)); | |
292 | 314 | |||
293 | /* link into chain */ | 315 | TAILQ_INSERT_TAIL(&tmp->prefix, pfx, next); | |
294 | insque(pfx, &tmp->prefix); | |||
295 | pfx->rainfo = tmp; | |||
296 | tmp->pfxs++; | 316 | tmp->pfxs++; | |
317 | pfx->rainfo = tmp; | |||
297 | 318 | |||
298 | pfx->origin = PREFIX_FROM_CONFIG; | 319 | pfx->origin = PREFIX_FROM_CONFIG; | |
299 | 320 | |||
300 | if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) { | 321 | if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) { | |
301 | syslog(LOG_ERR, | 322 | syslog(LOG_ERR, | |
302 | "<%s> inet_pton failed for %s", | 323 | "<%s> inet_pton failed for %s", | |
303 | __func__, addr); | 324 | __func__, addr); | |
304 | exit(1); | 325 | exit(1); | |
305 | } | 326 | } | |
306 | if (IN6_IS_ADDR_MULTICAST(&pfx->prefix)) { | 327 | if (IN6_IS_ADDR_MULTICAST(&pfx->prefix)) { | |
307 | syslog(LOG_ERR, | 328 | syslog(LOG_ERR, | |
308 | "<%s> multicast prefix (%s) must " | 329 | "<%s> multicast prefix (%s) must " | |
309 | "not be advertised on %s", | 330 | "not be advertised on %s", | |
310 | __func__, addr, intface); | 331 | __func__, addr, intface); | |
311 | exit(1); | 332 | exit(1); | |
312 | } | 333 | } | |
313 | if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix)) | 334 | if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix)) | |
314 | syslog(LOG_NOTICE, | 335 | syslog(LOG_NOTICE, | |
315 | "<%s> link-local prefix (%s) will be" | 336 | "<%s> link-local prefix (%s) will be" | |
316 | " advertised on %s", | 337 | " advertised on %s", | |
317 | __func__, addr, intface); | 338 | __func__, addr, intface); | |
318 | 339 | |||
319 | makeentry(entbuf, sizeof(entbuf), i, "prefixlen"); | 340 | makeentry(entbuf, sizeof(entbuf), i, "prefixlen"); | |
320 | MAYHAVE(val, entbuf, 64); | 341 | MAYHAVE(val, entbuf, 64); | |
321 | if (val < 0 || val > 128) { | 342 | if (val < 0 || val > 128) { | |
322 | syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s " | 343 | syslog(LOG_ERR, "<%s> prefixlen (%d) for %s " | |
323 | "on %s out of range", | 344 | "on %s out of range", | |
324 | __func__, val, addr, intface); | 345 | __func__, val, addr, intface); | |
325 | exit(1); | 346 | exit(1); | |
326 | } | 347 | } | |
327 | pfx->prefixlen = (int)val; | 348 | pfx->prefixlen = (int)val; | |
328 | 349 | |||
329 | makeentry(entbuf, sizeof(entbuf), i, "pinfoflags"); | 350 | makeentry(entbuf, sizeof(entbuf), i, "pinfoflags"); | |
330 | if ((flagstr = (char *)agetstr(entbuf, &bp))) { | 351 | if ((flagstr = (char *)agetstr(entbuf, &bp))) { | |
331 | val = 0; | 352 | val = 0; | |
332 | if (strchr(flagstr, 'l')) | 353 | if (strchr(flagstr, 'l')) | |
333 | val |= ND_OPT_PI_FLAG_ONLINK; | 354 | val |= ND_OPT_PI_FLAG_ONLINK; | |
334 | if (strchr(flagstr, 'a')) | 355 | if (strchr(flagstr, 'a')) | |
335 | val |= ND_OPT_PI_FLAG_AUTO; | 356 | val |= ND_OPT_PI_FLAG_AUTO; | |
@@ -339,144 +360,136 @@ getconfig(intface) | @@ -339,144 +360,136 @@ getconfig(intface) | |||
339 | } | 360 | } | |
340 | pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK; | 361 | pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK; | |
341 | pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO; | 362 | pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO; | |
342 | 363 | |||
343 | makeentry(entbuf, sizeof(entbuf), i, "vltime"); | 364 | makeentry(entbuf, sizeof(entbuf), i, "vltime"); | |
344 | MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME); | 365 | MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME); | |
345 | if (val64 < 0 || val64 > 0xffffffff) { | 366 | if (val64 < 0 || val64 > 0xffffffff) { | |
346 | syslog(LOG_ERR, "<%s> vltime (%lld) for " | 367 | syslog(LOG_ERR, "<%s> vltime (%lld) for " | |
347 | "%s/%d on %s is out of range", | 368 | "%s/%d on %s is out of range", | |
348 | __func__, (long long)val64, | 369 | __func__, (long long)val64, | |
349 | addr, pfx->prefixlen, intface); | 370 | addr, pfx->prefixlen, intface); | |
350 | exit(1); | 371 | exit(1); | |
351 | } | 372 | } | |
352 | pfx->validlifetime = (u_int32_t)val64; | 373 | pfx->validlifetime = (uint32_t)val64; | |
353 | 374 | |||
354 | makeentry(entbuf, sizeof(entbuf), i, "vltimedecr"); | 375 | makeentry(entbuf, sizeof(entbuf), i, "vltimedecr"); | |
355 | if (agetflag(entbuf)) { | 376 | if (agetflag(entbuf)) { | |
356 | struct timeval now; | 377 | struct timeval now; | |
357 | gettimeofday(&now, 0); | 378 | gettimeofday(&now, 0); | |
358 | pfx->vltimeexpire = | 379 | pfx->vltimeexpire = | |
359 | now.tv_sec + pfx->validlifetime; | 380 | now.tv_sec + pfx->validlifetime; | |
360 | } | 381 | } | |
361 | 382 | |||
362 | makeentry(entbuf, sizeof(entbuf), i, "pltime"); | 383 | makeentry(entbuf, sizeof(entbuf), i, "pltime"); | |
363 | MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME); | 384 | MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME); | |
364 | if (val64 < 0 || val64 > 0xffffffff) { | 385 | if (val64 < 0 || val64 > 0xffffffff) { | |
365 | syslog(LOG_ERR, | 386 | syslog(LOG_ERR, | |
366 | "<%s> pltime (%lld) for %s/%d on %s " | 387 | "<%s> pltime (%lld) for %s/%d on %s " | |
367 | "is out of range", | 388 | "is out of range", | |
368 | __func__, (long long)val64, | 389 | __func__, (long long)val64, | |
369 | addr, pfx->prefixlen, intface); | 390 | addr, pfx->prefixlen, intface); | |
370 | exit(1); | 391 | exit(1); | |
371 | } | 392 | } | |
372 | pfx->preflifetime = (u_int32_t)val64; | 393 | pfx->preflifetime = (uint32_t)val64; | |
373 | 394 | |||
374 | makeentry(entbuf, sizeof(entbuf), i, "pltimedecr"); | 395 | makeentry(entbuf, sizeof(entbuf), i, "pltimedecr"); | |
375 | if (agetflag(entbuf)) { | 396 | if (agetflag(entbuf)) { | |
376 | struct timeval now; | 397 | struct timeval now; | |
377 | gettimeofday(&now, 0); | 398 | gettimeofday(&now, 0); | |
378 | pfx->pltimeexpire = | 399 | pfx->pltimeexpire = | |
379 | now.tv_sec + pfx->preflifetime; | 400 | now.tv_sec + pfx->preflifetime; | |
380 | } | 401 | } | |
381 | } | 402 | } | |
382 | if (tmp->pfxs == 0) | 403 | if (TAILQ_FIRST(&tmp->prefix) == NULL) | |
383 | get_prefix(tmp); | 404 | get_prefix(tmp); | |
384 | 405 | |||
385 | MAYHAVE(val, "mtu", 0); | 406 | MAYHAVE(val64, "mtu", 0); | |
386 | if (val < 0 || val > 0xffffffff) { | 407 | if (val64 < 0 || val64 > 0xffffffff) { | |
387 | syslog(LOG_ERR, | 408 | syslog(LOG_ERR, | |
388 | "<%s> mtu (%ld) on %s out of range", | 409 | "<%s> mtu (%" PRIi64 ") on %s out of range", | |
389 | __func__, val, intface); | 410 | __func__, val64, intface); | |
390 | exit(1); | 411 | exit(1); | |
391 | } | 412 | } | |
392 | tmp->linkmtu = (u_int32_t)val; | 413 | tmp->linkmtu = (uint32_t)val64; | |
393 | if (tmp->linkmtu == 0) { | 414 | if (tmp->linkmtu == 0) { | |
394 | char *mtustr; | 415 | char *mtustr; | |
395 | 416 | |||
396 | if ((mtustr = (char *)agetstr("mtu", &bp)) && | 417 | if ((mtustr = (char *)agetstr("mtu", &bp)) && | |
397 | strcmp(mtustr, "auto") == 0) | 418 | strcmp(mtustr, "auto") == 0) | |
398 | tmp->linkmtu = tmp->phymtu; | 419 | tmp->linkmtu = tmp->phymtu; | |
399 | } | 420 | } | |
400 | else if (tmp->linkmtu < IPV6_MMTU || tmp->linkmtu > tmp->phymtu) { | 421 | else if (tmp->linkmtu < IPV6_MMTU || tmp->linkmtu > tmp->phymtu) { | |
401 | syslog(LOG_ERR, | 422 | syslog(LOG_ERR, | |
402 | "<%s> advertised link mtu (%lu) on %s is invalid (must " | 423 | "<%s> advertised link mtu (%d) on %s is invalid (must " | |
403 | "be between least MTU (%d) and physical link MTU (%d)", | 424 | "be between least MTU (%d) and physical link MTU (%d)", | |
404 | __func__, (unsigned long)tmp->linkmtu, intface, | 425 | __func__, tmp->linkmtu, intface, | |
405 | IPV6_MMTU, tmp->phymtu); | 426 | IPV6_MMTU, tmp->phymtu); | |
406 | exit(1); | 427 | exit(1); | |
407 | } | 428 | } | |
408 | 429 | |||
409 | #ifdef SIOCSIFINFO_IN6 | 430 | #ifdef SIOCSIFINFO_IN6 | |
410 | { | 431 | { | |
411 | struct in6_ndireq ndi; | 432 | struct in6_ndireq ndi; | |
412 | int s; | 433 | int s; | |
413 | 434 | |||
414 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | 435 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | |
415 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | 436 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | |
416 | strerror(errno)); | 437 | strerror(errno)); | |
417 | exit(1); | 438 | exit(1); | |
418 | } | 439 | } | |
419 | memset(&ndi, 0, sizeof(ndi)); | 440 | memset(&ndi, 0, sizeof(ndi)); | |
420 | strncpy(ndi.ifname, intface, IFNAMSIZ); | 441 | strncpy(ndi.ifname, intface, IFNAMSIZ); | |
421 | if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&ndi) < 0) { | 442 | if (ioctl(s, SIOCGIFINFO_IN6, &ndi) < 0) { | |
422 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s", | 443 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s", | |
423 | __func__, intface, strerror(errno)); | 444 | __func__, intface, strerror(errno)); | |
424 | } | 445 | } | |
425 | 446 | |||
426 | /* reflect the RA info to the host variables in kernel */ | 447 | /* reflect the RA info to the host variables in kernel */ | |
427 | ndi.ndi.chlim = tmp->hoplimit; | 448 | ndi.ndi.chlim = tmp->hoplimit; | |
428 | ndi.ndi.retrans = tmp->retranstimer; | 449 | ndi.ndi.retrans = tmp->retranstimer; | |
429 | ndi.ndi.basereachable = tmp->reachabletime; | 450 | ndi.ndi.basereachable = tmp->reachabletime; | |
430 | if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&ndi) < 0) { | 451 | if (ioctl(s, SIOCSIFINFO_IN6, &ndi) < 0) { | |
431 | syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s", | 452 | syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s", | |
432 | __func__, intface, strerror(errno)); | 453 | __func__, intface, strerror(errno)); | |
433 | } | 454 | } | |
434 | close(s); | 455 | close(s); | |
435 | } | 456 | } | |
436 | #endif | 457 | #endif | |
437 | 458 | |||
438 | /* route information */ | 459 | /* route information */ | |
439 | #ifdef ROUTEINFO | 460 | TAILQ_INIT(&tmp->route); | |
440 | tmp->routes = 0; | |||
441 | for (i = -1; i < MAXROUTE; i++) { | 461 | for (i = -1; i < MAXROUTE; i++) { | |
442 | struct rtinfo *rti; | 462 | struct rtinfo *rti; | |
443 | char entbuf[256], oentbuf[256]; | 463 | char oentbuf[256]; | |
444 | 464 | |||
445 | makeentry(entbuf, sizeof(entbuf), i, "rtprefix"); | 465 | makeentry(entbuf, sizeof(entbuf), i, "rtprefix"); | |
446 | addr = (char *)agetstr(entbuf, &bp); | 466 | addr = (char *)agetstr(entbuf, &bp); | |
447 | if (addr == NULL) { | 467 | if (addr == NULL) { | |
448 | makeentry(oentbuf, sizeof(oentbuf), i, "rtrprefix"); | 468 | makeentry(oentbuf, sizeof(oentbuf), i, "rtrprefix"); | |
449 | addr = (char *)agetstr(oentbuf, &bp); | 469 | addr = (char *)agetstr(oentbuf, &bp); | |
450 | if (addr) { | 470 | if (addr) { | |
451 | fprintf(stderr, "%s was obsoleted. Use %s.\n", | 471 | fprintf(stderr, "%s was obsoleted. Use %s.\n", | |
452 | oentbuf, entbuf); | 472 | oentbuf, entbuf); | |
453 | } | 473 | } | |
454 | } | 474 | } | |
455 | if (addr == NULL) | 475 | if (addr == NULL) | |
456 | continue; | 476 | continue; | |
457 | 477 | |||
458 | /* allocate memory to store prefix information */ | 478 | ELM_MALLOC(rti, exit(1)); | |
459 | if ((rti = malloc(sizeof(struct rtinfo))) == NULL) { | |||
460 | syslog(LOG_ERR, | |||
461 | "<%s> can't allocate enough memory", | |||
462 | __func__); | |||
463 | exit(1); | |||
464 | } | |||
465 | memset(rti, 0, sizeof(*rti)); | 479 | memset(rti, 0, sizeof(*rti)); | |
466 | 480 | |||
467 | /* link into chain */ | 481 | /* link into chain */ | |
468 | insque(rti, &tmp->route); | 482 | TAILQ_INSERT_TAIL(&tmp->route, rti, next); | |
469 | tmp->routes++; | |||
470 | 483 | |||
471 | if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) { | 484 | if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) { | |
472 | syslog(LOG_ERR, "<%s> inet_pton failed for %s", | 485 | syslog(LOG_ERR, "<%s> inet_pton failed for %s", | |
473 | __func__, addr); | 486 | __func__, addr); | |
474 | exit(1); | 487 | exit(1); | |
475 | } | 488 | } | |
476 | #if 0 | 489 | #if 0 | |
477 | /* | 490 | /* | |
478 | * XXX: currently there's no restriction in route information | 491 | * XXX: currently there's no restriction in route information | |
479 | * prefix according to | 492 | * prefix according to | |
480 | * draft-ietf-ipngwg-router-selection-00.txt. | 493 | * draft-ietf-ipngwg-router-selection-00.txt. | |
481 | * However, I think the similar restriction be necessary. | 494 | * However, I think the similar restriction be necessary. | |
482 | */ | 495 | */ | |
@@ -500,27 +513,27 @@ getconfig(intface) | @@ -500,27 +513,27 @@ getconfig(intface) | |||
500 | makeentry(entbuf, sizeof(entbuf), i, "rtplen"); | 513 | makeentry(entbuf, sizeof(entbuf), i, "rtplen"); | |
501 | /* XXX: 256 is a magic number for compatibility check. */ | 514 | /* XXX: 256 is a magic number for compatibility check. */ | |
502 | MAYHAVE(val, entbuf, 256); | 515 | MAYHAVE(val, entbuf, 256); | |
503 | if (val == 256) { | 516 | if (val == 256) { | |
504 | makeentry(oentbuf, sizeof(oentbuf), i, "rtrplen"); | 517 | makeentry(oentbuf, sizeof(oentbuf), i, "rtrplen"); | |
505 | MAYHAVE(val, oentbuf, 256); | 518 | MAYHAVE(val, oentbuf, 256); | |
506 | if (val != 256) { | 519 | if (val != 256) { | |
507 | fprintf(stderr, "%s was obsoleted. Use %s.\n", | 520 | fprintf(stderr, "%s was obsoleted. Use %s.\n", | |
508 | oentbuf, entbuf); | 521 | oentbuf, entbuf); | |
509 | } else | 522 | } else | |
510 | val = 64; | 523 | val = 64; | |
511 | } | 524 | } | |
512 | if (val < 0 || val > 128) { | 525 | if (val < 0 || val > 128) { | |
513 | syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s on %s " | 526 | syslog(LOG_ERR, "<%s> prefixlen (%d) for %s on %s " | |
514 | "out of range", | 527 | "out of range", | |
515 | __func__, val, addr, intface); | 528 | __func__, val, addr, intface); | |
516 | exit(1); | 529 | exit(1); | |
517 | } | 530 | } | |
518 | rti->prefixlen = (int)val; | 531 | rti->prefixlen = (int)val; | |
519 | 532 | |||
520 | makeentry(entbuf, sizeof(entbuf), i, "rtflags"); | 533 | makeentry(entbuf, sizeof(entbuf), i, "rtflags"); | |
521 | if ((flagstr = (char *)agetstr(entbuf, &bp))) { | 534 | if ((flagstr = (char *)agetstr(entbuf, &bp))) { | |
522 | val = 0; | 535 | val = 0; | |
523 | if (strchr(flagstr, 'h')) | 536 | if (strchr(flagstr, 'h')) | |
524 | val |= ND_RA_FLAG_RTPREF_HIGH; | 537 | val |= ND_RA_FLAG_RTPREF_HIGH; | |
525 | if (strchr(flagstr, 'l')) { | 538 | if (strchr(flagstr, 'l')) { | |
526 | if ((val & ND_RA_FLAG_RTPREF_HIGH)) { | 539 | if ((val & ND_RA_FLAG_RTPREF_HIGH)) { | |
@@ -569,73 +582,149 @@ getconfig(intface) | @@ -569,73 +582,149 @@ getconfig(intface) | |||
569 | } else { | 582 | } else { | |
570 | fprintf(stderr, "%s should be specified " | 583 | fprintf(stderr, "%s should be specified " | |
571 | "for interface %s.\n", | 584 | "for interface %s.\n", | |
572 | entbuf, intface); | 585 | entbuf, intface); | |
573 | val64 = tmp->lifetime; | 586 | val64 = tmp->lifetime; | |
574 | } | 587 | } | |
575 | } | 588 | } | |
576 | if (val64 < 0 || val64 > 0xffffffff) { | 589 | if (val64 < 0 || val64 > 0xffffffff) { | |
577 | syslog(LOG_ERR, "<%s> route lifetime (%lld) for " | 590 | syslog(LOG_ERR, "<%s> route lifetime (%lld) for " | |
578 | "%s/%d on %s out of range", __func__, | 591 | "%s/%d on %s out of range", __func__, | |
579 | (long long)val64, addr, rti->prefixlen, intface); | 592 | (long long)val64, addr, rti->prefixlen, intface); | |
580 | exit(1); | 593 | exit(1); | |
581 | } | 594 | } | |
582 | rti->ltime = (u_int32_t)val64; | 595 | rti->ltime = (uint32_t)val64; | |
596 | } | |||
597 | ||||
598 | /* RDNSS */ | |||
599 | TAILQ_INIT(&tmp->rdnss); | |||
600 | for (i = -1; i < MAXRDNSS; i++) { | |||
601 | struct rdnss *rdnss; | |||
602 | struct rdnss_addr *rdnsa; | |||
603 | ||||
604 | makeentry(entbuf, sizeof(entbuf), i, "rdnss"); | |||
605 | addr = (char *)agetstr(entbuf, &bp); | |||
606 | if (addr == NULL) | |||
607 | continue; | |||
608 | ||||
609 | ELM_MALLOC(rdnss, exit(1)); | |||
610 | TAILQ_INIT(&rdnss->list); | |||
611 | ||||
612 | for (ap = addr; ap - addr < (ssize_t)strlen(addr); ap += c+1) { | |||
613 | c = strcspn(ap, ","); | |||
614 | strncpy(abuf, ap, c); | |||
615 | abuf[c] = '\0'; | |||
616 | ELM_MALLOC(rdnsa, exit(1)); | |||
617 | if (inet_pton(AF_INET6, abuf, &rdnsa->addr) != 1) { | |||
618 | syslog(LOG_ERR, "<%s> inet_pton failed for %s", | |||
619 | __func__, addr); | |||
620 | exit(1); | |||
621 | } | |||
622 | TAILQ_INSERT_TAIL(&rdnss->list, rdnsa, next); | |||
623 | } | |||
624 | ||||
625 | makeentry(entbuf, sizeof(entbuf), i, "rdnssltime"); | |||
626 | MAYHAVE(val64, entbuf, tmp->maxinterval * 3 / 2); | |||
627 | if (val64 < tmp->maxinterval || | |||
628 | val64 > tmp->maxinterval * 2) | |||
629 | { | |||
630 | syslog(LOG_ERR, "<%s> %s (%lld) on %s is invalid", | |||
631 | __func__, entbuf, (long long)val64, intface); | |||
632 | exit(1); | |||
633 | } | |||
634 | rdnss->lifetime = (uint32_t)val64; | |||
635 | ||||
636 | TAILQ_INSERT_TAIL(&tmp->rdnss, rdnss, next); | |||
637 | } | |||
638 | ||||
639 | /* DNSSL */ | |||
640 | TAILQ_INIT(&tmp->dnssl); | |||
641 | for (i = -1; i < MAXDNSSL; i++) { | |||
642 | struct dnssl *dnssl; | |||
643 | struct dnssl_domain *dnsd; | |||
644 | ||||
645 | makeentry(entbuf, sizeof(entbuf), i, "dnssl"); | |||
646 | addr = (char *)agetstr(entbuf, &bp); | |||
647 | if (addr == NULL) | |||
648 | continue; | |||
649 | ||||
650 | ELM_MALLOC(dnssl, exit(1)); | |||
651 | TAILQ_INIT(&dnssl->list); | |||
652 | ||||
653 | for (ap = addr; ap - addr < (ssize_t)strlen(addr); ap += c+1) { | |||
654 | c = strcspn(ap, ","); | |||
655 | strncpy(abuf, ap, c); | |||
656 | abuf[c] = '\0'; | |||
657 | ELM_MALLOC(dnsd, exit(1)); | |||
658 | dnsd->len = encode_domain(dnsd->domain, abuf); | |||
659 | TAILQ_INSERT_TAIL(&dnssl->list, dnsd, next); | |||
660 | } | |||
661 | ||||
662 | makeentry(entbuf, sizeof(entbuf), i, "dnsslltime"); | |||
663 | MAYHAVE(val64, entbuf, tmp->maxinterval * 3 / 2); | |||
664 | if (val64 < tmp->maxinterval || | |||
665 | val64 > tmp->maxinterval * 2) | |||
666 | { | |||
667 | syslog(LOG_ERR, "<%s> %s (%lld) on %s is invalid", | |||
668 | __func__, entbuf, (long long)val64, intface); | |||
669 | exit(1); | |||
670 | } | |||
671 | dnssl->lifetime = (uint32_t)val64; | |||
672 | ||||
673 | TAILQ_INSERT_TAIL(&tmp->dnssl, dnssl, next); | |||
583 | } | 674 | } | |
584 | #endif | |||
585 | 675 | |||
586 | /* okey */ | 676 | /* okey */ | |
587 | tmp->next = ralist; | 677 | TAILQ_INSERT_TAIL(&ralist, tmp, next); | |
588 | ralist = tmp; | |||
589 | 678 | |||
590 | /* construct the sending packet */ | 679 | /* construct the sending packet */ | |
591 | make_packet(tmp); | 680 | make_packet(tmp); | |
592 | 681 | |||
593 | /* set timer */ | 682 | /* set timer */ | |
594 | tmp->timer = rtadvd_add_timer(ra_timeout, ra_timer_update, | 683 | tmp->timer = rtadvd_add_timer(ra_timeout, ra_timer_update, | |
595 | tmp, tmp); | 684 | tmp, tmp); | |
596 | ra_timer_update((void *)tmp, &tmp->timer->tm); | 685 | ra_timer_update((void *)tmp, &tmp->timer->tm); | |
597 | rtadvd_set_timer(&tmp->timer->tm, tmp->timer); | 686 | rtadvd_set_timer(&tmp->timer->tm, tmp->timer); | |
598 | } | 687 | } | |
599 | 688 | |||
600 | void | 689 | void | |
601 | get_prefix(struct rainfo *rai) | 690 | get_prefix(struct rainfo *rai) | |
602 | { | 691 | { | |
603 | struct ifaddrs *ifap, *ifa; | 692 | struct ifaddrs *ifap, *ifa; | |
604 | struct prefix *pp; | 693 | struct prefix *pp; | |
605 | struct in6_addr *a; | 694 | struct in6_addr *a; | |
606 | u_char *p, *ep, *m, *lim; | 695 | unsigned char *p, *ep, *m, *lim; | |
607 | char ntopbuf[INET6_ADDRSTRLEN]; | 696 | char ntopbuf[INET6_ADDRSTRLEN]; | |
608 | 697 | |||
609 | if (getifaddrs(&ifap) < 0) { | 698 | if (getifaddrs(&ifap) < 0) { | |
610 | syslog(LOG_ERR, | 699 | syslog(LOG_ERR, | |
611 | "<%s> can't get interface addresses", | 700 | "<%s> can't get interface addresses", | |
612 | __func__); | 701 | __func__); | |
613 | exit(1); | 702 | exit(1); | |
614 | } | 703 | } | |
615 | 704 | |||
616 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | 705 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | |
617 | int plen; | 706 | int plen; | |
618 | 707 | |||
619 | if (strcmp(ifa->ifa_name, rai->ifname) != 0) | 708 | if (strcmp(ifa->ifa_name, rai->ifname) != 0) | |
620 | continue; | 709 | continue; | |
621 | if (ifa->ifa_addr->sa_family != AF_INET6) | 710 | if (ifa->ifa_addr->sa_family != AF_INET6) | |
622 | continue; | 711 | continue; | |
623 | a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; | 712 | a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; | |
624 | if (IN6_IS_ADDR_LINKLOCAL(a)) | 713 | if (IN6_IS_ADDR_LINKLOCAL(a)) | |
625 | continue; | 714 | continue; | |
626 | /* get prefix length */ | 715 | /* get prefix length */ | |
627 | m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; | 716 | m = (unsigned char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; | |
628 | lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len; | 717 | lim = (unsigned char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len; | |
629 | plen = prefixlen(m, lim); | 718 | plen = prefixlen(m, lim); | |
630 | if (plen <= 0 || plen > 128) { | 719 | if (plen <= 0 || plen > 128) { | |
631 | syslog(LOG_ERR, "<%s> failed to get prefixlen " | 720 | syslog(LOG_ERR, "<%s> failed to get prefixlen " | |
632 | "or prefix is invalid", | 721 | "or prefix is invalid", | |
633 | __func__); | 722 | __func__); | |
634 | exit(1); | 723 | exit(1); | |
635 | } | 724 | } | |
636 | if (plen == 128) /* XXX */ | 725 | if (plen == 128) /* XXX */ | |
637 | continue; | 726 | continue; | |
638 | if (find_prefix(rai, a, plen)) { | 727 | if (find_prefix(rai, a, plen)) { | |
639 | /* ignore a duplicated prefix. */ | 728 | /* ignore a duplicated prefix. */ | |
640 | continue; | 729 | continue; | |
641 | } | 730 | } | |
@@ -644,66 +733,59 @@ get_prefix(struct rainfo *rai) | @@ -644,66 +733,59 @@ get_prefix(struct rainfo *rai) | |||
644 | if ((pp = malloc(sizeof(*pp))) == NULL) { | 733 | if ((pp = malloc(sizeof(*pp))) == NULL) { | |
645 | syslog(LOG_ERR, | 734 | syslog(LOG_ERR, | |
646 | "<%s> can't get allocate buffer for prefix", | 735 | "<%s> can't get allocate buffer for prefix", | |
647 | __func__); | 736 | __func__); | |
648 | exit(1); | 737 | exit(1); | |
649 | } | 738 | } | |
650 | memset(pp, 0, sizeof(*pp)); | 739 | memset(pp, 0, sizeof(*pp)); | |
651 | 740 | |||
652 | /* set prefix, sweep bits outside of prefixlen */ | 741 | /* set prefix, sweep bits outside of prefixlen */ | |
653 | pp->prefixlen = plen; | 742 | pp->prefixlen = plen; | |
654 | memcpy(&pp->prefix, a, sizeof(*a)); | 743 | memcpy(&pp->prefix, a, sizeof(*a)); | |
655 | if (1) | 744 | if (1) | |
656 | { | 745 | { | |
657 | p = (u_char *)&pp->prefix; | 746 | p = (unsigned char *)&pp->prefix; | |
658 | ep = (u_char *)(&pp->prefix + 1); | 747 | ep = (unsigned char *)(&pp->prefix + 1); | |
659 | while (m < lim && p < ep) | 748 | while (m < lim && p < ep) | |
660 | *p++ &= *m++; | 749 | *p++ &= *m++; | |
661 | while (p < ep) | 750 | while (p < ep) | |
662 | *p++ = 0x00; | 751 | *p++ = 0x00; | |
663 | } | 752 | } | |
664 | if (!inet_ntop(AF_INET6, &pp->prefix, ntopbuf, | 753 | if (!inet_ntop(AF_INET6, &pp->prefix, ntopbuf, | |
665 | sizeof(ntopbuf))) { | 754 | sizeof(ntopbuf))) { | |
666 | syslog(LOG_ERR, "<%s> inet_ntop failed", __func__); | 755 | syslog(LOG_ERR, "<%s> inet_ntop failed", __func__); | |
667 | exit(1); | 756 | exit(1); | |
668 | } | 757 | } | |
669 | syslog(LOG_DEBUG, | 758 | syslog(LOG_DEBUG, | |
670 | "<%s> add %s/%d to prefix list on %s", | 759 | "<%s> add %s/%d to prefix list on %s", | |
671 | __func__, ntopbuf, pp->prefixlen, rai->ifname); | 760 | __func__, ntopbuf, pp->prefixlen, rai->ifname); | |
672 | 761 | |||
673 | /* set other fields with protocol defaults */ | 762 | /* set other fields with protocol defaults */ | |
674 | pp->validlifetime = DEF_ADVVALIDLIFETIME; | 763 | pp->validlifetime = DEF_ADVVALIDLIFETIME; | |
675 | pp->preflifetime = DEF_ADVPREFERREDLIFETIME; | 764 | pp->preflifetime = DEF_ADVPREFERREDLIFETIME; | |
676 | pp->onlinkflg = 1; | 765 | pp->onlinkflg = 1; | |
677 | pp->autoconfflg = 1; | 766 | pp->autoconfflg = 1; | |
678 | pp->origin = PREFIX_FROM_KERNEL; | 767 | pp->origin = PREFIX_FROM_KERNEL; | |
679 | pp->rainfo = rai; | 768 | pp->rainfo = rai; | |
680 | 769 | |||
681 | /* link into chain */ | 770 | /* link into chain */ | |
682 | insque(pp, &rai->prefix); | 771 | TAILQ_INSERT_TAIL(&rai->prefix, pp, next); | |
683 | ||||
684 | /* counter increment */ | |||
685 | rai->pfxs++; | |||
686 | } | 772 | } | |
687 | 773 | |||
688 | freeifaddrs(ifap); | 774 | freeifaddrs(ifap); | |
689 | } | 775 | } | |
690 | 776 | |||
691 | static void | 777 | static void | |
692 | makeentry(buf, len, id, string) | 778 | makeentry(char *buf, size_t len, int id, const char *string) | |
693 | char *buf; | |||
694 | size_t len; | |||
695 | int id; | |||
696 | char *string; | |||
697 | { | 779 | { | |
698 | 780 | |||
699 | if (id < 0) | 781 | if (id < 0) | |
700 | strlcpy(buf, string, len); | 782 | strlcpy(buf, string, len); | |
701 | else | 783 | else | |
702 | snprintf(buf, len, "%s%d", string, id); | 784 | snprintf(buf, len, "%s%d", string, id); | |
703 | } | 785 | } | |
704 | 786 | |||
705 | /* | 787 | /* | |
706 | * Add a prefix to the list of specified interface and reconstruct | 788 | * Add a prefix to the list of specified interface and reconstruct | |
707 | * the outgoing packet. | 789 | * the outgoing packet. | |
708 | * The prefix must not be in the list. | 790 | * The prefix must not be in the list. | |
709 | * XXX: other parameters of the prefix(e.g. lifetime) should be | 791 | * XXX: other parameters of the prefix(e.g. lifetime) should be | |
@@ -719,63 +801,63 @@ add_prefix(struct rainfo *rai, struct in | @@ -719,63 +801,63 @@ add_prefix(struct rainfo *rai, struct in | |||
719 | syslog(LOG_ERR, "<%s> memory allocation failed", | 801 | syslog(LOG_ERR, "<%s> memory allocation failed", | |
720 | __func__); | 802 | __func__); | |
721 | return; /* XXX: error or exit? */ | 803 | return; /* XXX: error or exit? */ | |
722 | } | 804 | } | |
723 | memset(prefix, 0, sizeof(*prefix)); | 805 | memset(prefix, 0, sizeof(*prefix)); | |
724 | prefix->prefix = ipr->ipr_prefix.sin6_addr; | 806 | prefix->prefix = ipr->ipr_prefix.sin6_addr; | |
725 | prefix->prefixlen = ipr->ipr_plen; | 807 | prefix->prefixlen = ipr->ipr_plen; | |
726 | prefix->validlifetime = ipr->ipr_vltime; | 808 | prefix->validlifetime = ipr->ipr_vltime; | |
727 | prefix->preflifetime = ipr->ipr_pltime; | 809 | prefix->preflifetime = ipr->ipr_pltime; | |
728 | prefix->onlinkflg = ipr->ipr_raf_onlink; | 810 | prefix->onlinkflg = ipr->ipr_raf_onlink; | |
729 | prefix->autoconfflg = ipr->ipr_raf_auto; | 811 | prefix->autoconfflg = ipr->ipr_raf_auto; | |
730 | prefix->origin = PREFIX_FROM_DYNAMIC; | 812 | prefix->origin = PREFIX_FROM_DYNAMIC; | |
731 | 813 | |||
732 | insque(prefix, &rai->prefix); | |||
733 | prefix->rainfo = rai; | 814 | prefix->rainfo = rai; | |
815 | TAILQ_INSERT_TAIL(&rai->prefix, prefix, next); | |||
816 | rai->pfxs++; | |||
734 | 817 | |||
735 | syslog(LOG_DEBUG, "<%s> new prefix %s/%d was added on %s", | 818 | syslog(LOG_DEBUG, "<%s> new prefix %s/%d was added on %s", | |
736 | __func__, inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr, | 819 | __func__, inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr, | |
737 | ntopbuf, INET6_ADDRSTRLEN), | 820 | ntopbuf, INET6_ADDRSTRLEN), | |
738 | ipr->ipr_plen, rai->ifname); | 821 | ipr->ipr_plen, rai->ifname); | |
739 | 822 | |||
740 | /* free the previous packet */ | 823 | /* free the previous packet */ | |
741 | free(rai->ra_data); | 824 | free(rai->ra_data); | |
742 | rai->ra_data = NULL; | 825 | rai->ra_data = NULL; | |
743 | 826 | |||
744 | /* reconstruct the packet */ | 827 | /* reconstruct the packet */ | |
745 | rai->pfxs++; | |||
746 | make_packet(rai); | 828 | make_packet(rai); | |
747 | } | 829 | } | |
748 | 830 | |||
749 | /* | 831 | /* | |
750 | * Delete a prefix to the list of specified interface and reconstruct | 832 | * Delete a prefix to the list of specified interface and reconstruct | |
751 | * the outgoing packet. | 833 | * the outgoing packet. | |
752 | * The prefix must be in the list. | 834 | * The prefix must be in the list. | |
753 | */ | 835 | */ | |
754 | void | 836 | void | |
755 | delete_prefix(struct prefix *prefix) | 837 | delete_prefix(struct prefix *prefix) | |
756 | { | 838 | { | |
757 | char ntopbuf[INET6_ADDRSTRLEN]; | 839 | char ntopbuf[INET6_ADDRSTRLEN]; | |
758 | struct rainfo *rai = prefix->rainfo; | 840 | struct rainfo *rai = prefix->rainfo; | |
759 | 841 | |||
760 | remque(prefix); | 842 | TAILQ_REMOVE(&rai->prefix, prefix, next); | |
843 | rai->pfxs--; | |||
761 | syslog(LOG_DEBUG, "<%s> prefix %s/%d was deleted on %s", | 844 | syslog(LOG_DEBUG, "<%s> prefix %s/%d was deleted on %s", | |
762 | __func__, inet_ntop(AF_INET6, &prefix->prefix, | 845 | __func__, inet_ntop(AF_INET6, &prefix->prefix, | |
763 | ntopbuf, INET6_ADDRSTRLEN), | 846 | ntopbuf, INET6_ADDRSTRLEN), | |
764 | prefix->prefixlen, rai->ifname); | 847 | prefix->prefixlen, rai->ifname); | |
765 | if (prefix->timer) | 848 | if (prefix->timer) | |
766 | rtadvd_remove_timer(&prefix->timer); | 849 | rtadvd_remove_timer(&prefix->timer); | |
767 | free(prefix); | 850 | free(prefix); | |
768 | rai->pfxs--; | |||
769 | } | 851 | } | |
770 | 852 | |||
771 | void | 853 | void | |
772 | invalidate_prefix(struct prefix *prefix) | 854 | invalidate_prefix(struct prefix *prefix) | |
773 | { | 855 | { | |
774 | char ntopbuf[INET6_ADDRSTRLEN]; | 856 | char ntopbuf[INET6_ADDRSTRLEN]; | |
775 | struct timeval timo; | 857 | struct timeval timo; | |
776 | struct rainfo *rai = prefix->rainfo; | 858 | struct rainfo *rai = prefix->rainfo; | |
777 | 859 | |||
778 | if (prefix->timer) { /* sanity check */ | 860 | if (prefix->timer) { /* sanity check */ | |
779 | syslog(LOG_ERR, | 861 | syslog(LOG_ERR, | |
780 | "<%s> assumption failure: timer already exists", | 862 | "<%s> assumption failure: timer already exists", | |
781 | __func__); | 863 | __func__); | |
@@ -837,27 +919,27 @@ update_prefix(struct prefix * prefix) | @@ -837,27 +919,27 @@ update_prefix(struct prefix * prefix) | |||
837 | */ | 919 | */ | |
838 | static int | 920 | static int | |
839 | init_prefix(struct in6_prefixreq *ipr) | 921 | init_prefix(struct in6_prefixreq *ipr) | |
840 | { | 922 | { | |
841 | #if 0 | 923 | #if 0 | |
842 | int s; | 924 | int s; | |
843 | 925 | |||
844 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | 926 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | |
845 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | 927 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | |
846 | strerror(errno)); | 928 | strerror(errno)); | |
847 | exit(1); | 929 | exit(1); | |
848 | } | 930 | } | |
849 | 931 | |||
850 | if (ioctl(s, SIOCGIFPREFIX_IN6, (caddr_t)ipr) < 0) { | 932 | if (ioctl(s, SIOCGIFPREFIX_IN6, ipr) < 0) { | |
851 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFPREFIX %s", __func__, | 933 | syslog(LOG_INFO, "<%s> ioctl:SIOCGIFPREFIX %s", __func__, | |
852 | strerror(errno)); | 934 | strerror(errno)); | |
853 | 935 | |||
854 | ipr->ipr_vltime = DEF_ADVVALIDLIFETIME; | 936 | ipr->ipr_vltime = DEF_ADVVALIDLIFETIME; | |
855 | ipr->ipr_pltime = DEF_ADVPREFERREDLIFETIME; | 937 | ipr->ipr_pltime = DEF_ADVPREFERREDLIFETIME; | |
856 | ipr->ipr_raf_onlink = 1; | 938 | ipr->ipr_raf_onlink = 1; | |
857 | ipr->ipr_raf_auto = 1; | 939 | ipr->ipr_raf_auto = 1; | |
858 | /* omit other field initialization */ | 940 | /* omit other field initialization */ | |
859 | } | 941 | } | |
860 | else if (ipr->ipr_origin < PR_ORIG_RR) { | 942 | else if (ipr->ipr_origin < PR_ORIG_RR) { | |
861 | char ntopbuf[INET6_ADDRSTRLEN]; | 943 | char ntopbuf[INET6_ADDRSTRLEN]; | |
862 | 944 | |||
863 | syslog(LOG_WARNING, "<%s> Added prefix(%s)'s origin %d is" | 945 | syslog(LOG_WARNING, "<%s> Added prefix(%s)'s origin %d is" | |
@@ -896,82 +978,99 @@ make_prefix(struct rainfo *rai, int ifin | @@ -896,82 +978,99 @@ make_prefix(struct rainfo *rai, int ifin | |||
896 | ipr.ipr_prefix.sin6_family = AF_INET6; | 978 | ipr.ipr_prefix.sin6_family = AF_INET6; | |
897 | ipr.ipr_prefix.sin6_addr = *addr; | 979 | ipr.ipr_prefix.sin6_addr = *addr; | |
898 | ipr.ipr_plen = plen; | 980 | ipr.ipr_plen = plen; | |
899 | 981 | |||
900 | if (init_prefix(&ipr)) | 982 | if (init_prefix(&ipr)) | |
901 | return; /* init failed by some error */ | 983 | return; /* init failed by some error */ | |
902 | add_prefix(rai, &ipr); | 984 | add_prefix(rai, &ipr); | |
903 | } | 985 | } | |
904 | 986 | |||
905 | void | 987 | void | |
906 | make_packet(struct rainfo *rainfo) | 988 | make_packet(struct rainfo *rainfo) | |
907 | { | 989 | { | |
908 | size_t packlen, lladdroptlen = 0; | 990 | size_t packlen, lladdroptlen = 0; | |
909 | u_char *buf; | 991 | char *buf; | |
910 | struct nd_router_advert *ra; | 992 | struct nd_router_advert *ra; | |
911 | struct nd_opt_prefix_info *ndopt_pi; | 993 | struct nd_opt_prefix_info *ndopt_pi; | |
912 | struct nd_opt_mtu *ndopt_mtu; | 994 | struct nd_opt_mtu *ndopt_mtu; | |
913 | struct prefix *pfx; | 995 | struct prefix *pfx; | |
914 | #ifdef ROUTEINFO | |||
915 | struct nd_opt_route_info *ndopt_rti; | 996 | struct nd_opt_route_info *ndopt_rti; | |
916 | struct rtinfo *rti; | 997 | struct rtinfo *rti; | |
917 | #endif | 998 | struct nd_opt_rdnss *ndopt_rdnss; | |
999 | struct rdnss *rdns; | |||
1000 | struct rdnss_addr *rdnsa; | |||
1001 | struct nd_opt_dnssl *ndopt_dnssl; | |||
1002 | struct dnssl *dnsl; | |||
1003 | struct dnssl_domain *dnsd; | |||
1004 | size_t len, plen; | |||
918 | 1005 | |||
919 | /* calculate total length */ | 1006 | /* calculate total length */ | |
920 | packlen = sizeof(struct nd_router_advert); | 1007 | packlen = sizeof(struct nd_router_advert); | |
921 | if (rainfo->advlinkopt) { | 1008 | if (rainfo->advlinkopt) { | |
922 | if ((lladdroptlen = lladdropt_length(rainfo->sdl)) == 0) { | 1009 | if ((lladdroptlen = lladdropt_length(rainfo->sdl)) == 0) { | |
923 | syslog(LOG_INFO, | 1010 | syslog(LOG_INFO, | |
924 | "<%s> link-layer address option has" | 1011 | "<%s> link-layer address option has" | |
925 | " null length on %s. Treat as not included.", | 1012 | " null length on %s. Treat as not included.", | |
926 | __func__, rainfo->ifname); | 1013 | __func__, rainfo->ifname); | |
927 | rainfo->advlinkopt = 0; | 1014 | rainfo->advlinkopt = 0; | |
928 | } | 1015 | } | |
929 | packlen += lladdroptlen; | 1016 | packlen += lladdroptlen; | |
930 | } | 1017 | } | |
931 | if (rainfo->pfxs) | 1018 | if (TAILQ_FIRST(&rainfo->prefix) != NULL) | |
932 | packlen += sizeof(struct nd_opt_prefix_info) * rainfo->pfxs; | 1019 | packlen += sizeof(struct nd_opt_prefix_info) * rainfo->pfxs; | |
933 | if (rainfo->linkmtu) | 1020 | if (rainfo->linkmtu) | |
934 | packlen += sizeof(struct nd_opt_mtu); | 1021 | packlen += sizeof(struct nd_opt_mtu); | |
935 | #ifdef ROUTEINFO | 1022 | TAILQ_FOREACH(rti, &rainfo->route, next) | |
936 | for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) | |||
937 | packlen += sizeof(struct nd_opt_route_info) + | 1023 | packlen += sizeof(struct nd_opt_route_info) + | |
938 | ((rti->prefixlen + 0x3f) >> 6) * 8; | 1024 | ((rti->prefixlen + 0x3f) >> 6) * 8; | |
939 | #endif | 1025 | ||
1026 | TAILQ_FOREACH(rdns, &rainfo->rdnss, next) { | |||
1027 | packlen += sizeof(struct nd_opt_rdnss); | |||
1028 | TAILQ_FOREACH(rdnsa, &rdns->list, next) | |||
1029 | packlen += sizeof(rdnsa->addr); | |||
1030 | } | |||
1031 | TAILQ_FOREACH(dnsl, &rainfo->dnssl, next) { | |||
1032 | packlen += sizeof(struct nd_opt_dnssl); | |||
1033 | len = 0; | |||
1034 | TAILQ_FOREACH(dnsd, &dnsl->list, next) | |||
1035 | len += dnsd->len; | |||
1036 | len += len % 8 ? 8 - len % 8 : 0; | |||
1037 | packlen += len; | |||
1038 | } | |||
940 | 1039 | |||
941 | /* allocate memory for the packet */ | 1040 | /* allocate memory for the packet */ | |
942 | if ((buf = malloc(packlen)) == NULL) { | 1041 | if ((buf = malloc(packlen)) == NULL) { | |
943 | syslog(LOG_ERR, | 1042 | syslog(LOG_ERR, | |
944 | "<%s> can't get enough memory for an RA packet", | 1043 | "<%s> can't get enough memory for an RA packet", | |
945 | __func__); | 1044 | __func__); | |
946 | exit(1); | 1045 | exit(1); | |
947 | } | 1046 | } | |
948 | if (rainfo->ra_data) { | 1047 | if (rainfo->ra_data) { | |
949 | /* free the previous packet */ | 1048 | /* free the previous packet */ | |
950 | free(rainfo->ra_data); | 1049 | free(rainfo->ra_data); | |
951 | rainfo->ra_data = NULL; | 1050 | rainfo->ra_data = NULL; | |
952 | } | 1051 | } | |
953 | rainfo->ra_data = buf; | 1052 | rainfo->ra_data = buf; | |
954 | /* XXX: what if packlen > 576? */ | 1053 | /* XXX: what if packlen > 576? */ | |
955 | rainfo->ra_datalen = packlen; | 1054 | rainfo->ra_datalen = packlen; | |
956 | 1055 | |||
957 | /* | 1056 | /* | |
958 | * construct the packet | 1057 | * construct the packet | |
959 | */ | 1058 | */ | |
960 | ra = (struct nd_router_advert *)buf; | 1059 | ra = (struct nd_router_advert *)buf; | |
961 | ra->nd_ra_type = ND_ROUTER_ADVERT; | 1060 | ra->nd_ra_type = ND_ROUTER_ADVERT; | |
962 | ra->nd_ra_code = 0; | 1061 | ra->nd_ra_code = 0; | |
963 | ra->nd_ra_cksum = 0; | 1062 | ra->nd_ra_cksum = 0; | |
964 | ra->nd_ra_curhoplimit = (u_int8_t)(0xff & rainfo->hoplimit); | 1063 | ra->nd_ra_curhoplimit = (uint8_t)(0xff & rainfo->hoplimit); | |
965 | ra->nd_ra_flags_reserved = 0; /* just in case */ | 1064 | ra->nd_ra_flags_reserved = 0; /* just in case */ | |
966 | /* | 1065 | /* | |
967 | * XXX: the router preference field, which is a 2-bit field, should be | 1066 | * XXX: the router preference field, which is a 2-bit field, should be | |
968 | * initialized before other fields. | 1067 | * initialized before other fields. | |
969 | */ | 1068 | */ | |
970 | ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref; | 1069 | ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref; | |
971 | ra->nd_ra_flags_reserved |= | 1070 | ra->nd_ra_flags_reserved |= | |
972 | rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0; | 1071 | rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0; | |
973 | ra->nd_ra_flags_reserved |= | 1072 | ra->nd_ra_flags_reserved |= | |
974 | rainfo->otherflg ? ND_RA_FLAG_OTHER : 0; | 1073 | rainfo->otherflg ? ND_RA_FLAG_OTHER : 0; | |
975 | ra->nd_ra_router_lifetime = htons(rainfo->lifetime); | 1074 | ra->nd_ra_router_lifetime = htons(rainfo->lifetime); | |
976 | ra->nd_ra_reachable = htonl(rainfo->reachabletime); | 1075 | ra->nd_ra_reachable = htonl(rainfo->reachabletime); | |
977 | ra->nd_ra_retransmit = htonl(rainfo->retranstimer); | 1076 | ra->nd_ra_retransmit = htonl(rainfo->retranstimer); | |
@@ -981,31 +1080,28 @@ make_packet(struct rainfo *rainfo) | @@ -981,31 +1080,28 @@ make_packet(struct rainfo *rainfo) | |||
981 | lladdropt_fill(rainfo->sdl, (struct nd_opt_hdr *)buf); | 1080 | lladdropt_fill(rainfo->sdl, (struct nd_opt_hdr *)buf); | |
982 | buf += lladdroptlen; | 1081 | buf += lladdroptlen; | |
983 | } | 1082 | } | |
984 | 1083 | |||
985 | if (rainfo->linkmtu) { | 1084 | if (rainfo->linkmtu) { | |
986 | ndopt_mtu = (struct nd_opt_mtu *)buf; | 1085 | ndopt_mtu = (struct nd_opt_mtu *)buf; | |
987 | ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU; | 1086 | ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU; | |
988 | ndopt_mtu->nd_opt_mtu_len = 1; | 1087 | ndopt_mtu->nd_opt_mtu_len = 1; | |
989 | ndopt_mtu->nd_opt_mtu_reserved = 0; | 1088 | ndopt_mtu->nd_opt_mtu_reserved = 0; | |
990 | ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu); | 1089 | ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu); | |
991 | buf += sizeof(struct nd_opt_mtu); | 1090 | buf += sizeof(struct nd_opt_mtu); | |
992 | } | 1091 | } | |
993 | 1092 | |||
994 | 1093 | TAILQ_FOREACH(pfx, &rainfo->prefix, next) { | ||
995 | 1094 | uint32_t vltime, pltime; | ||
996 | for (pfx = rainfo->prefix.next; | |||
997 | pfx != &rainfo->prefix; pfx = pfx->next) { | |||
998 | u_int32_t vltime, pltime; | |||
999 | struct timeval now; | 1095 | struct timeval now; | |
1000 | 1096 | |||
1001 | ndopt_pi = (struct nd_opt_prefix_info *)buf; | 1097 | ndopt_pi = (struct nd_opt_prefix_info *)buf; | |
1002 | ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; | 1098 | ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; | |
1003 | ndopt_pi->nd_opt_pi_len = 4; | 1099 | ndopt_pi->nd_opt_pi_len = 4; | |
1004 | ndopt_pi->nd_opt_pi_prefix_len = pfx->prefixlen; | 1100 | ndopt_pi->nd_opt_pi_prefix_len = pfx->prefixlen; | |
1005 | ndopt_pi->nd_opt_pi_flags_reserved = 0; | 1101 | ndopt_pi->nd_opt_pi_flags_reserved = 0; | |
1006 | if (pfx->onlinkflg) | 1102 | if (pfx->onlinkflg) | |
1007 | ndopt_pi->nd_opt_pi_flags_reserved |= | 1103 | ndopt_pi->nd_opt_pi_flags_reserved |= | |
1008 | ND_OPT_PI_FLAG_ONLINK; | 1104 | ND_OPT_PI_FLAG_ONLINK; | |
1009 | if (pfx->autoconfflg) | 1105 | if (pfx->autoconfflg) | |
1010 | ndopt_pi->nd_opt_pi_flags_reserved |= | 1106 | ndopt_pi->nd_opt_pi_flags_reserved |= | |
1011 | ND_OPT_PI_FLAG_AUTO; | 1107 | ND_OPT_PI_FLAG_AUTO; | |
@@ -1034,42 +1130,73 @@ make_packet(struct rainfo *rainfo) | @@ -1034,42 +1130,73 @@ make_packet(struct rainfo *rainfo) | |||
1034 | * this can happen if vltime is decrement but pltime | 1130 | * this can happen if vltime is decrement but pltime | |
1035 | * is not. | 1131 | * is not. | |
1036 | */ | 1132 | */ | |
1037 | pltime = vltime; | 1133 | pltime = vltime; | |
1038 | } | 1134 | } | |
1039 | ndopt_pi->nd_opt_pi_valid_time = htonl(vltime); | 1135 | ndopt_pi->nd_opt_pi_valid_time = htonl(vltime); | |
1040 | ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime); | 1136 | ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime); | |
1041 | ndopt_pi->nd_opt_pi_reserved2 = 0; | 1137 | ndopt_pi->nd_opt_pi_reserved2 = 0; | |
1042 | ndopt_pi->nd_opt_pi_prefix = pfx->prefix; | 1138 | ndopt_pi->nd_opt_pi_prefix = pfx->prefix; | |
1043 | 1139 | |||
1044 | buf += sizeof(struct nd_opt_prefix_info); | 1140 | buf += sizeof(struct nd_opt_prefix_info); | |
1045 | } | 1141 | } | |
1046 | 1142 | |||
1047 | #ifdef ROUTEINFO | 1143 | TAILQ_FOREACH(rti, &rainfo->route, next) { | |
1048 | for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) { | 1144 | uint8_t psize = (rti->prefixlen + 0x3f) >> 6; | |
1049 | u_int8_t psize = (rti->prefixlen + 0x3f) >> 6; | |||
1050 | 1145 | |||
1051 | ndopt_rti = (struct nd_opt_route_info *)buf; | 1146 | ndopt_rti = (struct nd_opt_route_info *)buf; | |
1052 | ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO; | 1147 | ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO; | |
1053 | ndopt_rti->nd_opt_rti_len = 1 + psize; | 1148 | ndopt_rti->nd_opt_rti_len = 1 + psize; | |
1054 | ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen; | 1149 | ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen; | |
1055 | ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref; | 1150 | ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref; | |
1056 | ndopt_rti->nd_opt_rti_lifetime = htonl(rti->ltime); | 1151 | ndopt_rti->nd_opt_rti_lifetime = htonl(rti->ltime); | |
1057 | memcpy(ndopt_rti + 1, &rti->prefix, psize * 8); | 1152 | memcpy(ndopt_rti + 1, &rti->prefix, psize * 8); | |
1058 | buf += sizeof(struct nd_opt_route_info) + psize * 8; | 1153 | buf += sizeof(struct nd_opt_route_info) + psize * 8; | |
1059 | } | 1154 | } | |
1060 | #endif | |||
1061 | 1155 | |||
1062 | return; | 1156 | TAILQ_FOREACH(rdns, &rainfo->rdnss, next) { | |
1157 | ndopt_rdnss = (struct nd_opt_rdnss *)buf; | |||
1158 | ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS; | |||
1159 | ndopt_rdnss->nd_opt_rdnss_len = 1; | |||
1160 | ndopt_rdnss->nd_opt_rdnss_reserved = 0; | |||
1161 | ndopt_rdnss->nd_opt_rdnss_lifetime = htonl(rdns->lifetime); | |||
1162 | buf += sizeof(*ndopt_rdnss); | |||
1163 | ||||
1164 | TAILQ_FOREACH(rdnsa, &rdns->list, next) { | |||
1165 | memcpy(buf, &rdnsa->addr, sizeof(rdnsa->addr)); | |||
1166 | ndopt_rdnss->nd_opt_rdnss_len += 2; | |||
1167 | buf += sizeof(rdnsa->addr); | |||
1168 | } | |||
1169 | } | |||
1170 | ||||
1171 | TAILQ_FOREACH(dnsl, &rainfo->dnssl, next) { | |||
1172 | ndopt_dnssl = (struct nd_opt_dnssl *)buf; | |||
1173 | ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL; | |||
1174 | ndopt_dnssl->nd_opt_dnssl_len = 0; | |||
1175 | ndopt_dnssl->nd_opt_dnssl_reserved = 0; | |||
1176 | ndopt_dnssl->nd_opt_dnssl_lifetime = htonl(dnsl->lifetime); | |||
1177 | buf += sizeof(*ndopt_dnssl); | |||
1178 | ||||
1179 | TAILQ_FOREACH(dnsd, &dnsl->list, next) { | |||
1180 | memcpy(buf, dnsd->domain, dnsd->len); | |||
1181 | buf += dnsd->len; | |||
1182 | } | |||
1183 | /* Ensure our length is padded correctly */ | |||
1184 | len = buf - (char *)ndopt_dnssl; | |||
1185 | plen = len % 8 ? 8 - len % 8 : 0; | |||
1186 | memset(buf, 0, plen); | |||
1187 | buf += plen; | |||
1188 | ndopt_dnssl->nd_opt_dnssl_len = (len + plen) / 8; | |||
1189 | } | |||
1063 | } | 1190 | } | |
1064 | 1191 | |||
1065 | static int | 1192 | static int | |
1066 | getinet6sysctl(int code) | 1193 | getinet6sysctl(int code) | |
1067 | { | 1194 | { | |
1068 | int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; | 1195 | int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; | |
1069 | int value; | 1196 | int value; | |
1070 | size_t size; | 1197 | size_t size; | |
1071 | 1198 | |||
1072 | mib[3] = code; | 1199 | mib[3] = code; | |
1073 | size = sizeof(value); | 1200 | size = sizeof(value); | |
1074 | if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) | 1201 | if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) | |
1075 | < 0) { | 1202 | < 0) { |
--- src/usr.sbin/rtadvd/dump.c 2008/12/29 04:01:21 1.8
+++ src/usr.sbin/rtadvd/dump.c 2011/12/10 19:14:29 1.9
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: dump.c,v 1.8 2008/12/29 04:01:21 christos Exp $ */ | 1 | /* $NetBSD: dump.c,v 1.9 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: dump.c,v 1.34 2004/06/14 05:35:59 itojun Exp $ */ | 2 | /* $KAME: dump.c,v 1.34 2004/06/14 05:35:59 itojun Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 2000 WIDE Project. | 5 | * Copyright (C) 2000 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 | |
@@ -49,68 +49,67 @@ | @@ -49,68 +49,67 @@ | |||
49 | #include <stdarg.h> | 49 | #include <stdarg.h> | |
50 | #include <syslog.h> | 50 | #include <syslog.h> | |
51 | #include <string.h> | 51 | #include <string.h> | |
52 | #include <errno.h> | 52 | #include <errno.h> | |
53 | #include <netdb.h> | 53 | #include <netdb.h> | |
54 | 54 | |||
55 | #include "rtadvd.h" | 55 | #include "rtadvd.h" | |
56 | #include "timer.h" | 56 | #include "timer.h" | |
57 | #include "if.h" | 57 | #include "if.h" | |
58 | #include "dump.h" | 58 | #include "dump.h" | |
59 | 59 | |||
60 | static FILE *fp; | 60 | static FILE *fp; | |
61 | 61 | |||
62 | extern struct rainfo *ralist; | 62 | static char *ether_str(struct sockaddr_dl *); | |
63 | static void if_dump(void); | |||
63 | 64 | |||
64 | static char *ether_str __P((struct sockaddr_dl *)); | 65 | static const char *rtpref_str[] = { | |
65 | static void if_dump __P((void)); | |||
66 | ||||
67 | static char *rtpref_str[] = { | |||
68 | "medium", /* 00 */ | 66 | "medium", /* 00 */ | |
69 | "high", /* 01 */ | 67 | "high", /* 01 */ | |
70 | "rsv", /* 10 */ | 68 | "rsv", /* 10 */ | |
71 | "low" /* 11 */ | 69 | "low" /* 11 */ | |
72 | }; | 70 | }; | |
73 | 71 | |||
74 | static char * | 72 | static char * | |
75 | ether_str(sdl) | 73 | ether_str(struct sockaddr_dl *sdl) | |
76 | struct sockaddr_dl *sdl; | |||
77 | { | 74 | { | |
78 | static char hbuf[NI_MAXHOST]; | 75 | static char hbuf[NI_MAXHOST]; | |
79 | 76 | |||
80 | if (sdl->sdl_alen) { | 77 | if (sdl->sdl_alen) { | |
81 | if (getnameinfo((struct sockaddr *)sdl, sdl->sdl_len, | 78 | if (getnameinfo((struct sockaddr *)sdl, sdl->sdl_len, | |
82 | hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | 79 | hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | |
83 | snprintf(hbuf, sizeof(hbuf), "<invalid>"); | 80 | snprintf(hbuf, sizeof(hbuf), "<invalid>"); | |
84 | } else | 81 | } else | |
85 | snprintf(hbuf, sizeof(hbuf), "NONE"); | 82 | snprintf(hbuf, sizeof(hbuf), "NONE"); | |
86 | 83 | |||
87 | return(hbuf); | 84 | return(hbuf); | |
88 | } | 85 | } | |
89 | 86 | |||
90 | static void | 87 | static void | |
91 | if_dump() | 88 | if_dump(void) | |
92 | { | 89 | { | |
93 | struct rainfo *rai; | 90 | struct rainfo *rai; | |
94 | struct prefix *pfx; | 91 | struct prefix *pfx; | |
95 | #ifdef ROUTEINFO | |||
96 | struct rtinfo *rti; | 92 | struct rtinfo *rti; | |
97 | #endif | 93 | struct rdnss *rdns; | |
94 | struct rdnss_addr *rdnsa; | |||
95 | struct dnssl *dnsl; | |||
96 | struct dnssl_domain *dnsd; | |||
97 | char *p, len; | |||
98 | char prefixbuf[INET6_ADDRSTRLEN]; | 98 | char prefixbuf[INET6_ADDRSTRLEN]; | |
99 | int first; | |||
100 | struct timeval now; | 99 | struct timeval now; | |
101 | 100 | |||
102 | gettimeofday(&now, NULL); /* XXX: unused in most cases */ | 101 | gettimeofday(&now, NULL); /* XXX: unused in most cases */ | |
103 | for (rai = ralist; rai; rai = rai->next) { | 102 | TAILQ_FOREACH(rai, &ralist, next) { | |
104 | fprintf(fp, "%s:\n", rai->ifname); | 103 | fprintf(fp, "%s:\n", rai->ifname); | |
105 | 104 | |||
106 | fprintf(fp, " Status: %s\n", | 105 | fprintf(fp, " Status: %s\n", | |
107 | (iflist[rai->ifindex]->ifm_flags & IFF_UP) ? "UP" : | 106 | (iflist[rai->ifindex]->ifm_flags & IFF_UP) ? "UP" : | |
108 | "DOWN"); | 107 | "DOWN"); | |
109 | 108 | |||
110 | /* control information */ | 109 | /* control information */ | |
111 | if (rai->lastsent.tv_sec) { | 110 | if (rai->lastsent.tv_sec) { | |
112 | /* note that ctime() appends CR by itself */ | 111 | /* note that ctime() appends CR by itself */ | |
113 | fprintf(fp, " Last RA sent: %s", | 112 | fprintf(fp, " Last RA sent: %s", | |
114 | ctime((time_t *)&rai->lastsent.tv_sec)); | 113 | ctime((time_t *)&rai->lastsent.tv_sec)); | |
115 | } | 114 | } | |
116 | if (rai->timer) { | 115 | if (rai->timer) { | |
@@ -141,34 +140,31 @@ if_dump() | @@ -141,34 +140,31 @@ if_dump() | |||
141 | fprintf(fp, " DefaultLifetime: %d, MaxAdvInterval: %d, " | 140 | fprintf(fp, " DefaultLifetime: %d, MaxAdvInterval: %d, " | |
142 | "MinAdvInterval: %d\n", rai->lifetime, rai->maxinterval, | 141 | "MinAdvInterval: %d\n", rai->lifetime, rai->maxinterval, | |
143 | rai->mininterval); | 142 | rai->mininterval); | |
144 | fprintf(fp, " Flags: %s%s%s, ", | 143 | fprintf(fp, " Flags: %s%s%s, ", | |
145 | rai->managedflg ? "M" : "", rai->otherflg ? "O" : "", | 144 | rai->managedflg ? "M" : "", rai->otherflg ? "O" : "", | |
146 | ""); | 145 | ""); | |
147 | fprintf(fp, "Preference: %s, ", | 146 | fprintf(fp, "Preference: %s, ", | |
148 | rtpref_str[(rai->rtpref >> 3) & 0xff]); | 147 | rtpref_str[(rai->rtpref >> 3) & 0xff]); | |
149 | fprintf(fp, "MTU: %d\n", rai->linkmtu); | 148 | fprintf(fp, "MTU: %d\n", rai->linkmtu); | |
150 | fprintf(fp, " ReachableTime: %d, RetransTimer: %d, " | 149 | fprintf(fp, " ReachableTime: %d, RetransTimer: %d, " | |
151 | "CurHopLimit: %d\n", rai->reachabletime, | 150 | "CurHopLimit: %d\n", rai->reachabletime, | |
152 | rai->retranstimer, rai->hoplimit); | 151 | rai->retranstimer, rai->hoplimit); | |
153 | if (rai->clockskew) | 152 | if (rai->clockskew) | |
154 | fprintf(fp, " Clock skew: %ldsec\n", | 153 | fprintf(fp, " Clock skew: %dsec\n", | |
155 | rai->clockskew); | 154 | rai->clockskew); | |
156 | for (first = 1, pfx = rai->prefix.next; pfx != &rai->prefix; | 155 | TAILQ_FOREACH(pfx, &rai->prefix, next) { | |
157 | pfx = pfx->next) { | 156 | if (pfx == TAILQ_FIRST(&rai->prefix)) | |
158 | if (first) { | |||
159 | fprintf(fp, " Prefixes:\n"); | 157 | fprintf(fp, " Prefixes:\n"); | |
160 | first = 0; | |||
161 | } | |||
162 | fprintf(fp, " %s/%d(", | 158 | fprintf(fp, " %s/%d(", | |
163 | inet_ntop(AF_INET6, &pfx->prefix, prefixbuf, | 159 | inet_ntop(AF_INET6, &pfx->prefix, prefixbuf, | |
164 | sizeof(prefixbuf)), pfx->prefixlen); | 160 | sizeof(prefixbuf)), pfx->prefixlen); | |
165 | switch (pfx->origin) { | 161 | switch (pfx->origin) { | |
166 | case PREFIX_FROM_KERNEL: | 162 | case PREFIX_FROM_KERNEL: | |
167 | fprintf(fp, "KERNEL, "); | 163 | fprintf(fp, "KERNEL, "); | |
168 | break; | 164 | break; | |
169 | case PREFIX_FROM_CONFIG: | 165 | case PREFIX_FROM_CONFIG: | |
170 | fprintf(fp, "CONFIG, "); | 166 | fprintf(fp, "CONFIG, "); | |
171 | break; | 167 | break; | |
172 | case PREFIX_FROM_DYNAMIC: | 168 | case PREFIX_FROM_DYNAMIC: | |
173 | fprintf(fp, "DYNAMIC, "); | 169 | fprintf(fp, "DYNAMIC, "); | |
174 | break; | 170 | break; | |
@@ -200,52 +196,82 @@ if_dump() | @@ -200,52 +196,82 @@ if_dump() | |||
200 | pfx->autoconfflg ? "A" : "", | 196 | pfx->autoconfflg ? "A" : "", | |
201 | ""); | 197 | ""); | |
202 | if (pfx->timer) { | 198 | if (pfx->timer) { | |
203 | struct timeval *rest; | 199 | struct timeval *rest; | |
204 | 200 | |||
205 | rest = rtadvd_timer_rest(pfx->timer); | 201 | rest = rtadvd_timer_rest(pfx->timer); | |
206 | if (rest) { /* XXX: what if not? */ | 202 | if (rest) { /* XXX: what if not? */ | |
207 | fprintf(fp, ", expire in: %ld", | 203 | fprintf(fp, ", expire in: %ld", | |
208 | (long)rest->tv_sec); | 204 | (long)rest->tv_sec); | |
209 | } | 205 | } | |
210 | } | 206 | } | |
211 | fprintf(fp, ")\n"); | 207 | fprintf(fp, ")\n"); | |
212 | } | 208 | } | |
213 | #ifdef ROUTEINFO | 209 | ||
214 | for (first = 1, rti = rai->route.next; rti != &rai->route; | 210 | TAILQ_FOREACH(rti, &rai->route, next) { | |
215 | rti = rti->next) { | 211 | if (rti == TAILQ_FIRST(&rai->route)) | |
216 | if (first) { | |||
217 | fprintf(fp, " Route Information:\n"); | 212 | fprintf(fp, " Route Information:\n"); | |
218 | first = 0; | |||
219 | } | |||
220 | fprintf(fp, " %s/%d (", | 213 | fprintf(fp, " %s/%d (", | |
221 | inet_ntop(AF_INET6, &rti->prefix, | 214 | inet_ntop(AF_INET6, &rti->prefix, | |
222 | prefixbuf, sizeof(prefixbuf)), | 215 | prefixbuf, sizeof(prefixbuf)), | |
223 | rti->prefixlen); | 216 | rti->prefixlen); | |
224 | fprintf(fp, "preference: %s, ", | 217 | fprintf(fp, "preference: %s, ", | |
225 | rtpref_str[0xff & (rti->rtpref >> 3)]); | 218 | rtpref_str[0xff & (rti->rtpref >> 3)]); | |
226 | if (rti->ltime == ND6_INFINITE_LIFETIME) | 219 | if (rti->ltime == ND6_INFINITE_LIFETIME) | |
227 | fprintf(fp, "lifetime: infinity"); | 220 | fprintf(fp, "lifetime: infinity"); | |
228 | else | 221 | else | |
229 | fprintf(fp, "lifetime: %ld", (long)rti->ltime); | 222 | fprintf(fp, "lifetime: %ld", (long)rti->ltime); | |
230 | fprintf(fp, ")\n"); | 223 | fprintf(fp, ")\n"); | |
231 | } | 224 | } | |
232 | #endif | 225 | ||
226 | TAILQ_FOREACH(rdns, &rai->rdnss, next) { | |||
227 | fprintf(fp, " Recursive DNS Servers:\n"); | |||
228 | if (rdns->lifetime == ND6_INFINITE_LIFETIME) | |||
229 | fprintf(fp, " lifetime: infinity\n"); | |||
230 | else | |||
231 | fprintf(fp, " lifetime: %ld\n", | |||
232 | (long)rdns->lifetime); | |||
233 | TAILQ_FOREACH(rdnsa, &rdns->list, next) | |||
234 | fprintf(fp, " %s\n", | |||
235 | inet_ntop(AF_INET6, &rdnsa->addr, | |||
236 | prefixbuf, sizeof(prefixbuf))); | |||
237 | } | |||
238 | ||||
239 | TAILQ_FOREACH(dnsl, &rai->dnssl, next) { | |||
240 | fprintf(fp, " DNS Search List:\n"); | |||
241 | if (dnsl->lifetime == ND6_INFINITE_LIFETIME) | |||
242 | fprintf(fp, " lifetime: infinity\n"); | |||
243 | else | |||
244 | fprintf(fp, " lifetime: %ld\n", | |||
245 | (long)dnsl->lifetime); | |||
246 | TAILQ_FOREACH(dnsd, &dnsl->list, next) { | |||
247 | fprintf(fp, " "); | |||
248 | for (p = dnsd->domain, len = *p++; | |||
249 | len != 0; | |||
250 | len = *p++) | |||
251 | { | |||
252 | if (p != dnsd->domain) | |||
253 | fputc('.', fp); | |||
254 | while(len-- != 0) | |||
255 | fputc(*p++, fp); | |||
256 | } | |||
257 | fputc('\n', fp); | |||
258 | } | |||
259 | } | |||
233 | } | 260 | } | |
234 | } | 261 | } | |
235 | 262 | |||
236 | void | 263 | void | |
237 | rtadvd_dump_file(dumpfile) | 264 | rtadvd_dump_file(const char *dumpfile) | |
238 | char *dumpfile; | |||
239 | { | 265 | { | |
240 | syslog(LOG_DEBUG, "<%s> dump current status to %s", __func__, | 266 | syslog(LOG_DEBUG, "<%s> dump current status to %s", __func__, | |
241 | dumpfile); | 267 | dumpfile); | |
242 | 268 | |||
243 | if ((fp = fopen(dumpfile, "w")) == NULL) { | 269 | if ((fp = fopen(dumpfile, "w")) == NULL) { | |
244 | syslog(LOG_WARNING, "<%s> open a dump file(%s)", | 270 | syslog(LOG_WARNING, "<%s> open a dump file(%s)", | |
245 | __func__, dumpfile); | 271 | __func__, dumpfile); | |
246 | return; | 272 | return; | |
247 | } | 273 | } | |
248 | 274 | |||
249 | if_dump(); | 275 | if_dump(); | |
250 | 276 | |||
251 | fclose(fp); | 277 | fclose(fp); |
--- src/usr.sbin/rtadvd/dump.h 2000/05/23 11:37:58 1.1
+++ src/usr.sbin/rtadvd/dump.h 2011/12/10 19:14:29 1.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: dump.h,v 1.1 2000/05/23 11:37:58 itojun Exp $ */ | 1 | /* $NetBSD: dump.h,v 1.2 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: dump.h,v 1.1 2000/05/23 11:31:26 itojun Exp $ */ | 2 | /* $KAME: dump.h,v 1.1 2000/05/23 11:31:26 itojun 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 | |
@@ -20,14 +20,14 @@ | @@ -20,14 +20,14 @@ | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | 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 | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | extern void rtadvd_dump_file __P((char *)); | 33 | extern void rtadvd_dump_file(const char *); |
--- src/usr.sbin/rtadvd/if.c 2006/03/05 23:47:08 1.18
+++ src/usr.sbin/rtadvd/if.c 2011/12/10 19:14:29 1.19
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if.c,v 1.18 2006/03/05 23:47:08 rpaulo Exp $ */ | 1 | /* $NetBSD: if.c,v 1.19 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: if.c,v 1.36 2004/11/30 22:32:01 suz Exp $ */ | 2 | /* $KAME: if.c,v 1.36 2004/11/30 22:32:01 suz Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, and 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 | |
@@ -44,38 +44,38 @@ | @@ -44,38 +44,38 @@ | |||
44 | #include <netinet/icmp6.h> | 44 | #include <netinet/icmp6.h> | |
45 | #include <unistd.h> | 45 | #include <unistd.h> | |
46 | #include <errno.h> | 46 | #include <errno.h> | |
47 | #include <stdlib.h> | 47 | #include <stdlib.h> | |
48 | #include <string.h> | 48 | #include <string.h> | |
49 | #include <syslog.h> | 49 | #include <syslog.h> | |
50 | #include "rtadvd.h" | 50 | #include "rtadvd.h" | |
51 | #include "if.h" | 51 | #include "if.h" | |
52 | 52 | |||
53 | #define ROUNDUP(a, size) \ | 53 | #define ROUNDUP(a, size) \ | |
54 | (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) | 54 | (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) | |
55 | 55 | |||
56 | #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ | 56 | #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ | |
57 | ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ | 57 | ((char *)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ | |
58 | sizeof(u_long)) :\ | 58 | sizeof(u_long)) :\ | |
59 | sizeof(u_long))) | 59 | sizeof(u_long))) | |
60 | 60 | |||
61 | struct if_msghdr **iflist; | 61 | struct if_msghdr **iflist; | |
62 | int iflist_init_ok; | 62 | int iflist_init_ok; | |
63 | size_t ifblock_size; | 63 | size_t ifblock_size; | |
64 | char *ifblock; | 64 | char *ifblock; | |
65 | 65 | |||
66 | static void get_iflist __P((char **buf, size_t *size)); | 66 | static void get_iflist(char **buf, size_t *size); | |
67 | static void parse_iflist __P((struct if_msghdr ***ifmlist_p, char *buf, | 67 | static void parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, | |
68 | size_t bufsize)); | 68 | size_t bufsize); | |
69 | 69 | |||
70 | static void | 70 | static void | |
71 | get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) | 71 | get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) | |
72 | { | 72 | { | |
73 | int i; | 73 | int i; | |
74 | 74 | |||
75 | for (i = 0; i < RTAX_MAX; i++) { | 75 | for (i = 0; i < RTAX_MAX; i++) { | |
76 | if (addrs & (1 << i)) { | 76 | if (addrs & (1 << i)) { | |
77 | rti_info[i] = sa; | 77 | rti_info[i] = sa; | |
78 | NEXT_SA(sa); | 78 | NEXT_SA(sa); | |
79 | } | 79 | } | |
80 | else | 80 | else | |
81 | rti_info[i] = NULL; | 81 | rti_info[i] = NULL; | |
@@ -130,54 +130,54 @@ if_getmtu(char *name) | @@ -130,54 +130,54 @@ if_getmtu(char *name) | |||
130 | freeifaddrs(ifap); | 130 | freeifaddrs(ifap); | |
131 | 131 | |||
132 | #ifdef SIOCGIFMTU /* XXX: this ifdef may not be necessary */ | 132 | #ifdef SIOCGIFMTU /* XXX: this ifdef may not be necessary */ | |
133 | if (mtu == 0) { | 133 | if (mtu == 0) { | |
134 | struct ifreq ifr; | 134 | struct ifreq ifr; | |
135 | int s; | 135 | int s; | |
136 | 136 | |||
137 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) | 137 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) | |
138 | return(0); | 138 | return(0); | |
139 | 139 | |||
140 | ifr.ifr_addr.sa_family = AF_INET6; | 140 | ifr.ifr_addr.sa_family = AF_INET6; | |
141 | strncpy(ifr.ifr_name, name, | 141 | strncpy(ifr.ifr_name, name, | |
142 | sizeof(ifr.ifr_name)); | 142 | sizeof(ifr.ifr_name)); | |
143 | if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) { | 143 | if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { | |
144 | close(s); | 144 | close(s); | |
145 | return(0); | 145 | return(0); | |
146 | } | 146 | } | |
147 | close(s); | 147 | close(s); | |
148 | 148 | |||
149 | mtu = ifr.ifr_mtu; | 149 | mtu = ifr.ifr_mtu; | |
150 | } | 150 | } | |
151 | #endif | 151 | #endif | |
152 | 152 | |||
153 | return(mtu); | 153 | return(mtu); | |
154 | } | 154 | } | |
155 | 155 | |||
156 | /* give interface index and its old flags, then new flags returned */ | 156 | /* give interface index and its old flags, then new flags returned */ | |
157 | int | 157 | int | |
158 | if_getflags(int ifindex, int oifflags) | 158 | if_getflags(int ifindex, int oifflags) | |
159 | { | 159 | { | |
160 | struct ifreq ifr; | 160 | struct ifreq ifr; | |
161 | int s; | 161 | int s; | |
162 | 162 | |||
163 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | 163 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | |
164 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | 164 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | |
165 | strerror(errno)); | 165 | strerror(errno)); | |
166 | return (oifflags & ~IFF_UP); | 166 | return (oifflags & ~IFF_UP); | |
167 | } | 167 | } | |
168 | 168 | |||
169 | if_indextoname(ifindex, ifr.ifr_name); | 169 | if_indextoname(ifindex, ifr.ifr_name); | |
170 | if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { | 170 | if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { | |
171 | syslog(LOG_ERR, "<%s> ioctl:SIOCGIFFLAGS: failed for %s", | 171 | syslog(LOG_ERR, "<%s> ioctl:SIOCGIFFLAGS: failed for %s", | |
172 | __func__, ifr.ifr_name); | 172 | __func__, ifr.ifr_name); | |
173 | close(s); | 173 | close(s); | |
174 | return (oifflags & ~IFF_UP); | 174 | return (oifflags & ~IFF_UP); | |
175 | } | 175 | } | |
176 | close(s); | 176 | close(s); | |
177 | return (ifr.ifr_flags); | 177 | return (ifr.ifr_flags); | |
178 | } | 178 | } | |
179 | 179 | |||
180 | #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) | 180 | #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) | |
181 | int | 181 | int | |
182 | lladdropt_length(struct sockaddr_dl *sdl) | 182 | lladdropt_length(struct sockaddr_dl *sdl) | |
183 | { | 183 | { | |
@@ -345,39 +345,39 @@ get_ifam_ifindex(char *buf) | @@ -345,39 +345,39 @@ get_ifam_ifindex(char *buf) | |||
345 | int | 345 | int | |
346 | get_ifm_flags(char *buf) | 346 | get_ifm_flags(char *buf) | |
347 | { | 347 | { | |
348 | struct if_msghdr *ifm = (struct if_msghdr *)buf; | 348 | struct if_msghdr *ifm = (struct if_msghdr *)buf; | |
349 | 349 | |||
350 | return (ifm->ifm_flags); | 350 | return (ifm->ifm_flags); | |
351 | } | 351 | } | |
352 | 352 | |||
353 | int | 353 | int | |
354 | get_prefixlen(char *buf) | 354 | get_prefixlen(char *buf) | |
355 | { | 355 | { | |
356 | struct rt_msghdr *rtm = (struct rt_msghdr *)buf; | 356 | struct rt_msghdr *rtm = (struct rt_msghdr *)buf; | |
357 | struct sockaddr *sa, *rti_info[RTAX_MAX]; | 357 | struct sockaddr *sa, *rti_info[RTAX_MAX]; | |
358 | u_char *p, *lim; | 358 | unsigned char *p, *lim; | |
359 | 359 | |||
360 | sa = (struct sockaddr *)(rtm + 1); | 360 | sa = (struct sockaddr *)(rtm + 1); | |
361 | get_rtaddrs(rtm->rtm_addrs, sa, rti_info); | 361 | get_rtaddrs(rtm->rtm_addrs, sa, rti_info); | |
362 | sa = rti_info[RTAX_NETMASK]; | 362 | sa = rti_info[RTAX_NETMASK]; | |
363 | 363 | |||
364 | p = (u_char *)(&SIN6(sa)->sin6_addr); | 364 | p = (unsigned char *)(&SIN6(sa)->sin6_addr); | |
365 | lim = (u_char *)sa + sa->sa_len; | 365 | lim = (unsigned char *)sa + sa->sa_len; | |
366 | return prefixlen(p, lim); | 366 | return prefixlen(p, lim); | |
367 | } | 367 | } | |
368 | 368 | |||
369 | int | 369 | int | |
370 | prefixlen(u_char *p, u_char *lim) | 370 | prefixlen(const unsigned char *p, const unsigned char *lim) | |
371 | { | 371 | { | |
372 | int masklen; | 372 | int masklen; | |
373 | 373 | |||
374 | for (masklen = 0; p < lim; p++) { | 374 | for (masklen = 0; p < lim; p++) { | |
375 | switch (*p) { | 375 | switch (*p) { | |
376 | case 0xff: | 376 | case 0xff: | |
377 | masklen += 8; | 377 | masklen += 8; | |
378 | break; | 378 | break; | |
379 | case 0xfe: | 379 | case 0xfe: | |
380 | masklen += 7; | 380 | masklen += 7; | |
381 | break; | 381 | break; | |
382 | case 0xfc: | 382 | case 0xfc: | |
383 | masklen += 6; | 383 | masklen += 6; |
--- src/usr.sbin/rtadvd/if.h 2006/03/05 23:47:08 1.7
+++ src/usr.sbin/rtadvd/if.h 2011/12/10 19:14:29 1.8
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if.h,v 1.7 2006/03/05 23:47:08 rpaulo Exp $ */ | 1 | /* $NetBSD: if.h,v 1.8 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: if.h,v 1.12 2003/09/21 07:17:03 itojun Exp $ */ | 2 | /* $KAME: if.h,v 1.12 2003/09/21 07:17:03 itojun Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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 | |
@@ -27,31 +27,31 @@ | @@ -27,31 +27,31 @@ | |||
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 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 | 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 | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #define RTADV_TYPE2BITMASK(type) (0x1 << type) | 33 | #define RTADV_TYPE2BITMASK(type) (0x1 << type) | |
34 | 34 | |||
35 | extern struct if_msghdr **iflist; | 35 | extern struct if_msghdr **iflist; | |
36 | extern size_t ifblock_size; | 36 | extern size_t ifblock_size; | |
37 | extern char *ifblock; | 37 | extern char *ifblock; | |
38 | 38 | |||
39 | struct nd_opt_hdr; | 39 | struct nd_opt_hdr; | |
40 | struct sockaddr_dl *if_nametosdl __P((char *)); | 40 | struct sockaddr_dl *if_nametosdl(char *); | |
41 | int if_getmtu __P((char *)); | 41 | int if_getmtu(char *); | |
42 | int if_getflags __P((int, int)); | 42 | int if_getflags(int, int); | |
43 | int lladdropt_length __P((struct sockaddr_dl *)); | 43 | int lladdropt_length(struct sockaddr_dl *); | |
44 | void lladdropt_fill __P((struct sockaddr_dl *, struct nd_opt_hdr *)); | 44 | void lladdropt_fill(struct sockaddr_dl *, struct nd_opt_hdr *); | |
45 | char *get_next_msg __P((char *, char *, int, size_t *, int)); | 45 | char *get_next_msg(char *, char *, int, size_t *, int); | |
46 | struct in6_addr *get_addr __P((char *)); | 46 | struct in6_addr *get_addr(char *); | |
47 | int get_rtm_ifindex __P((char *)); | 47 | int get_rtm_ifindex(char *); | |
48 | int get_ifm_ifindex __P((char *)); | 48 | int get_ifm_ifindex(char *); | |
49 | int get_ifam_ifindex __P((char *)); | 49 | int get_ifam_ifindex(char *); | |
50 | int get_ifm_flags __P((char *)); | 50 | int get_ifm_flags(char *); | |
51 | int get_prefixlen __P((char *)); | 51 | int get_prefixlen(char *); | |
52 | int prefixlen __P((u_char *, u_char *)); | 52 | int prefixlen(const unsigned char *, const unsigned char *); | |
53 | int rtmsg_type __P((char *)); | 53 | int rtmsg_type(char *); | |
54 | int ifmsg_type __P((char *)); | 54 | int ifmsg_type(char *); | |
55 | int rtmsg_len __P((char *)); | 55 | int rtmsg_len(char *); | |
56 | int ifmsg_len __P((char *)); | 56 | int ifmsg_len(char *); | |
57 | void init_iflist __P((void)); | 57 | void init_iflist(void); |
--- src/usr.sbin/rtadvd/Attic/rrenum.c 2006/05/11 08:35:47 1.13
+++ src/usr.sbin/rtadvd/Attic/rrenum.c 2011/12/10 19:14:29 1.14
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rrenum.c,v 1.13 2006/05/11 08:35:47 mrg Exp $ */ | 1 | /* $NetBSD: rrenum.c,v 1.14 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: rrenum.c,v 1.14 2004/06/14 05:36:00 itojun Exp $ */ | 2 | /* $KAME: rrenum.c,v 1.14 2004/06/14 05:36:00 itojun Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, and 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 | |
@@ -150,27 +150,27 @@ do_use_prefix(int len, struct rr_pco_mat | @@ -150,27 +150,27 @@ do_use_prefix(int len, struct rr_pco_mat | |||
150 | if (rpm->rpm_code == RPM_PCO_ADD) | 150 | if (rpm->rpm_code == RPM_PCO_ADD) | |
151 | return; | 151 | return; | |
152 | 152 | |||
153 | irr->irr_u_uselen = 0; | 153 | irr->irr_u_uselen = 0; | |
154 | irr->irr_u_keeplen = 0; | 154 | irr->irr_u_keeplen = 0; | |
155 | irr->irr_raf_mask_onlink = 0; | 155 | irr->irr_raf_mask_onlink = 0; | |
156 | irr->irr_raf_mask_auto = 0; | 156 | irr->irr_raf_mask_auto = 0; | |
157 | irr->irr_vltime = 0; | 157 | irr->irr_vltime = 0; | |
158 | irr->irr_pltime = 0; | 158 | irr->irr_pltime = 0; | |
159 | memset(&irr->irr_flags, 0, sizeof(irr->irr_flags)); | 159 | memset(&irr->irr_flags, 0, sizeof(irr->irr_flags)); | |
160 | irr->irr_useprefix.sin6_len = 0; /* let it mean, no addition */ | 160 | irr->irr_useprefix.sin6_len = 0; /* let it mean, no addition */ | |
161 | irr->irr_useprefix.sin6_family = 0; | 161 | irr->irr_useprefix.sin6_family = 0; | |
162 | irr->irr_useprefix.sin6_addr = in6addr_any; | 162 | irr->irr_useprefix.sin6_addr = in6addr_any; | |
163 | if (ioctl(s, rrcmd2pco[rpm->rpm_code], (caddr_t)irr) < 0 && | 163 | if (ioctl(s, rrcmd2pco[rpm->rpm_code], irr) < 0 && | |
164 | errno != EADDRNOTAVAIL) | 164 | errno != EADDRNOTAVAIL) | |
165 | syslog(LOG_ERR, "<%s> ioctl: %s", __func__, | 165 | syslog(LOG_ERR, "<%s> ioctl: %s", __func__, | |
166 | strerror(errno)); | 166 | strerror(errno)); | |
167 | return; | 167 | return; | |
168 | } | 168 | } | |
169 | 169 | |||
170 | for (rpu = (struct rr_pco_use *)(rpm + 1), | 170 | for (rpu = (struct rr_pco_use *)(rpm + 1), | |
171 | rpulim = (struct rr_pco_use *)((char *)rpm + len); | 171 | rpulim = (struct rr_pco_use *)((char *)rpm + len); | |
172 | rpu < rpulim; | 172 | rpu < rpulim; | |
173 | rpu += 1) { | 173 | rpu += 1) { | |
174 | /* init in6_rrenumreq fields */ | 174 | /* init in6_rrenumreq fields */ | |
175 | irr->irr_u_uselen = rpu->rpu_uselen; | 175 | irr->irr_u_uselen = rpu->rpu_uselen; | |
176 | irr->irr_u_keeplen = rpu->rpu_keeplen; | 176 | irr->irr_u_keeplen = rpu->rpu_keeplen; | |
@@ -182,41 +182,40 @@ do_use_prefix(int len, struct rr_pco_mat | @@ -182,41 +182,40 @@ do_use_prefix(int len, struct rr_pco_mat | |||
182 | irr->irr_pltime = ntohl(rpu->rpu_pltime); | 182 | irr->irr_pltime = ntohl(rpu->rpu_pltime); | |
183 | irr->irr_raf_onlink = | 183 | irr->irr_raf_onlink = | |
184 | (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK) == 0 ? 0 : 1; | 184 | (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK) == 0 ? 0 : 1; | |
185 | irr->irr_raf_auto = | 185 | irr->irr_raf_auto = | |
186 | (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? 0 : 1; | 186 | (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? 0 : 1; | |
187 | irr->irr_rrf_decrvalid = | 187 | irr->irr_rrf_decrvalid = | |
188 | (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME) == 0 ? 0 : 1; | 188 | (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME) == 0 ? 0 : 1; | |
189 | irr->irr_rrf_decrprefd = | 189 | irr->irr_rrf_decrprefd = | |
190 | (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME) == 0 ? 0 : 1; | 190 | (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME) == 0 ? 0 : 1; | |
191 | irr->irr_useprefix.sin6_len = sizeof(irr->irr_useprefix); | 191 | irr->irr_useprefix.sin6_len = sizeof(irr->irr_useprefix); | |
192 | irr->irr_useprefix.sin6_family = AF_INET6; | 192 | irr->irr_useprefix.sin6_family = AF_INET6; | |
193 | irr->irr_useprefix.sin6_addr = rpu->rpu_prefix; | 193 | irr->irr_useprefix.sin6_addr = rpu->rpu_prefix; | |
194 | 194 | |||
195 | if (ioctl(s, rrcmd2pco[rpm->rpm_code], (caddr_t)irr) < 0 && | 195 | if (ioctl(s, rrcmd2pco[rpm->rpm_code], irr) < 0 && | |
196 | errno != EADDRNOTAVAIL) | 196 | errno != EADDRNOTAVAIL) | |
197 | syslog(LOG_ERR, "<%s> ioctl: %s", __func__, | 197 | syslog(LOG_ERR, "<%s> ioctl: %s", __func__, | |
198 | strerror(errno)); | 198 | strerror(errno)); | |
199 | 199 | |||
200 | /* very adhoc: should be rewritten */ | 200 | /* very adhoc: should be rewritten */ | |
201 | if (rpm->rpm_code == RPM_PCO_CHANGE && | 201 | if (rpm->rpm_code == RPM_PCO_CHANGE && | |
202 | IN6_ARE_ADDR_EQUAL(&rpm->rpm_prefix, &rpu->rpu_prefix) && | 202 | IN6_ARE_ADDR_EQUAL(&rpm->rpm_prefix, &rpu->rpu_prefix) && | |
203 | rpm->rpm_matchlen == rpu->rpu_uselen && | 203 | rpm->rpm_matchlen == rpu->rpu_uselen && | |
204 | rpu->rpu_uselen == rpu->rpu_keeplen) { | 204 | rpu->rpu_uselen == rpu->rpu_keeplen) { | |
205 | if ((rai = if_indextorainfo(ifindex)) == NULL) | 205 | if ((rai = if_indextorainfo(ifindex)) == NULL) | |
206 | continue; /* non-advertising IF */ | 206 | continue; /* non-advertising IF */ | |
207 | 207 | |||
208 | for (pp = rai->prefix.next; pp != &rai->prefix; | 208 | TAILQ_FOREACH(pp, &rai->prefix, next) { | |
209 | pp = pp->next) { | |||
210 | struct timeval now; | 209 | struct timeval now; | |
211 | 210 | |||
212 | if (prefix_match(&pp->prefix, pp->prefixlen, | 211 | if (prefix_match(&pp->prefix, pp->prefixlen, | |
213 | &rpm->rpm_prefix, | 212 | &rpm->rpm_prefix, | |
214 | rpm->rpm_matchlen)) { | 213 | rpm->rpm_matchlen)) { | |
215 | /* change parameters */ | 214 | /* change parameters */ | |
216 | pp->validlifetime = ntohl(rpu->rpu_vltime); | 215 | pp->validlifetime = ntohl(rpu->rpu_vltime); | |
217 | pp->preflifetime = ntohl(rpu->rpu_pltime); | 216 | pp->preflifetime = ntohl(rpu->rpu_pltime); | |
218 | if (irr->irr_rrf_decrvalid) { | 217 | if (irr->irr_rrf_decrvalid) { | |
219 | gettimeofday(&now, 0); | 218 | gettimeofday(&now, 0); | |
220 | pp->vltimeexpire = | 219 | pp->vltimeexpire = | |
221 | now.tv_sec + pp->validlifetime; | 220 | now.tv_sec + pp->validlifetime; | |
222 | } else | 221 | } else | |
@@ -278,98 +277,98 @@ do_pco(struct icmp6_router_renum *rr, in | @@ -278,98 +277,98 @@ do_pco(struct icmp6_router_renum *rr, in | |||
278 | syslog(LOG_ERR, "<%s> if_indextoname: %s", __func__, | 277 | syslog(LOG_ERR, "<%s> if_indextoname: %s", __func__, | |
279 | strerror(errno)); | 278 | strerror(errno)); | |
280 | return 1; | 279 | return 1; | |
281 | } | 280 | } | |
282 | return 0; | 281 | return 0; | |
283 | } | 282 | } | |
284 | 283 | |||
285 | /* | 284 | /* | |
286 | * call do_pco() for each Prefix Control Operations(PCOs) in a received | 285 | * call do_pco() for each Prefix Control Operations(PCOs) in a received | |
287 | * Router Renumbering Command packet. | 286 | * Router Renumbering Command packet. | |
288 | * return 0 on success, 1 on failure | 287 | * return 0 on success, 1 on failure | |
289 | */ | 288 | */ | |
290 | static int | 289 | static int | |
291 | do_rr(int len, struct icmp6_router_renum *rr) | 290 | do_rr(size_t len, struct icmp6_router_renum *rr) | |
292 | { | 291 | { | |
293 | struct rr_pco_match *rpm; | 292 | struct rr_pco_match *rpm; | |
294 | char *cp, *lim; | 293 | char *cp, *lim; | |
295 | 294 | |||
296 | lim = (char *)rr + len; | 295 | lim = (char *)rr + len; | |
297 | cp = (char *)(rr + 1); | 296 | cp = (char *)(rr + 1); | |
298 | len -= sizeof(struct icmp6_router_renum); | 297 | len -= sizeof(struct icmp6_router_renum); | |
299 | 298 | |||
300 | /* get iflist block from kernel again, to get up-to-date information */ | 299 | /* get iflist block from kernel again, to get up-to-date information */ | |
301 | init_iflist(); | 300 | init_iflist(); | |
302 | 301 | |||
303 | while (cp < lim) { | 302 | while (cp < lim) { | |
304 | int rpmlen; | 303 | size_t rpmlen; | |
305 | 304 | |||
306 | rpm = (struct rr_pco_match *)cp; | 305 | rpm = (struct rr_pco_match *)cp; | |
307 | if (len < sizeof(struct rr_pco_match)) { | 306 | if (len < sizeof(struct rr_pco_match)) { | |
308 | tooshort: | 307 | tooshort: | |
309 | syslog(LOG_ERR, "<%s> pkt too short. left len = %d. " | 308 | syslog(LOG_ERR, "<%s> pkt too short. left len = %zd. " | |
310 | "gabage at end of pkt?", __func__, len); | 309 | "gabage at end of pkt?", __func__, len); | |
311 | return 1; | 310 | return 1; | |
312 | } | 311 | } | |
313 | rpmlen = rpm->rpm_len << 3; | 312 | rpmlen = rpm->rpm_len << 3; | |
314 | if (len < rpmlen) | 313 | if (len < rpmlen) | |
315 | goto tooshort; | 314 | goto tooshort; | |
316 | 315 | |||
317 | if (do_pco(rr, rpmlen, rpm)) { | 316 | if (do_pco(rr, rpmlen, rpm)) { | |
318 | syslog(LOG_WARNING, "<%s> invalid PCO", __func__); | 317 | syslog(LOG_WARNING, "<%s> invalid PCO", __func__); | |
319 | goto next; | 318 | goto next; | |
320 | } | 319 | } | |
321 | 320 | |||
322 | next: | 321 | next: | |
323 | cp += rpmlen; | 322 | cp += rpmlen; | |
324 | len -= rpmlen; | 323 | len -= rpmlen; | |
325 | } | 324 | } | |
326 | 325 | |||
327 | return 0; | 326 | return 0; | |
328 | } | 327 | } | |
329 | 328 | |||
330 | /* | 329 | /* | |
331 | * check validity of a router renumbering command packet | 330 | * check validity of a router renumbering command packet | |
332 | * return 0 on success, 1 on failure | 331 | * return 0 on success, 1 on failure | |
333 | */ | 332 | */ | |
334 | static int | 333 | static int | |
335 | rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from, | 334 | rr_command_check(size_t len, struct icmp6_router_renum *rr, | |
336 | struct in6_addr *dst) | 335 | struct in6_addr *from, struct in6_addr *dst) | |
337 | { | 336 | { | |
338 | char ntopbuf[INET6_ADDRSTRLEN]; | 337 | char ntopbuf[INET6_ADDRSTRLEN]; | |
339 | 338 | |||
340 | /* omit rr minimal length check. hope kernel have done it. */ | 339 | /* omit rr minimal length check. hope kernel have done it. */ | |
341 | /* rr_command length check */ | 340 | /* rr_command length check */ | |
342 | if (len < (sizeof(struct icmp6_router_renum) + | 341 | if (len < (sizeof(struct icmp6_router_renum) + | |
343 | sizeof(struct rr_pco_match))) { | 342 | sizeof(struct rr_pco_match))) { | |
344 | syslog(LOG_ERR, "<%s> rr_command len %d is too short", | 343 | syslog(LOG_ERR, "<%s> rr_command len %zd is too short", | |
345 | __func__, len); | 344 | __func__, len); | |
346 | return 1; | 345 | return 1; | |
347 | } | 346 | } | |
348 | 347 | |||
349 | /* destination check. only for multicast. omit unicast check. */ | 348 | /* destination check. only for multicast. omit unicast check. */ | |
350 | if (IN6_IS_ADDR_MULTICAST(dst) && !IN6_IS_ADDR_MC_LINKLOCAL(dst) && | 349 | if (IN6_IS_ADDR_MULTICAST(dst) && !IN6_IS_ADDR_MC_LINKLOCAL(dst) && | |
351 | !IN6_IS_ADDR_MC_SITELOCAL(dst)) { | 350 | !IN6_IS_ADDR_MC_SITELOCAL(dst)) { | |
352 | syslog(LOG_ERR, "<%s> dst mcast addr %s is illegal", | 351 | syslog(LOG_ERR, "<%s> dst mcast addr %s is illegal", | |
353 | __func__, | 352 | __func__, | |
354 | inet_ntop(AF_INET6, dst, ntopbuf, INET6_ADDRSTRLEN)); | 353 | inet_ntop(AF_INET6, dst, ntopbuf, INET6_ADDRSTRLEN)); | |
355 | return 1; | 354 | return 1; | |
356 | } | 355 | } | |
357 | 356 | |||
358 | /* seqnum and segnum check */ | 357 | /* seqnum and segnum check */ | |
359 | if (rro.rro_seqnum > rr->rr_seqnum) { | 358 | if (rro.rro_seqnum > rr->rr_seqnum) { | |
360 | syslog(LOG_WARNING, | 359 | syslog(LOG_WARNING, | |
361 | "<%s> rcvd old seqnum %d from %s", | 360 | "<%s> rcvd old seqnum %d from %s", | |
362 | __func__, (u_int32_t)ntohl(rr->rr_seqnum), | 361 | __func__, (uint32_t)ntohl(rr->rr_seqnum), | |
363 | inet_ntop(AF_INET6, from, ntopbuf, INET6_ADDRSTRLEN)); | 362 | inet_ntop(AF_INET6, from, ntopbuf, INET6_ADDRSTRLEN)); | |
364 | return 1; | 363 | return 1; | |
365 | } | 364 | } | |
366 | if (rro.rro_seqnum == rr->rr_seqnum && | 365 | if (rro.rro_seqnum == rr->rr_seqnum && | |
367 | (rr->rr_flags & ICMP6_RR_FLAGS_TEST) == 0 && | 366 | (rr->rr_flags & ICMP6_RR_FLAGS_TEST) == 0 && | |
368 | RR_ISSET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum)) { | 367 | RR_ISSET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum)) { | |
369 | if ((rr->rr_flags & ICMP6_RR_FLAGS_REQRESULT) != 0) | 368 | if ((rr->rr_flags & ICMP6_RR_FLAGS_REQRESULT) != 0) | |
370 | syslog(LOG_WARNING, | 369 | syslog(LOG_WARNING, | |
371 | "<%s> rcvd duped segnum %d from %s", | 370 | "<%s> rcvd duped segnum %d from %s", | |
372 | __func__, rr->rr_segnum, | 371 | __func__, rr->rr_segnum, | |
373 | inet_ntop(AF_INET6, from, ntopbuf, | 372 | inet_ntop(AF_INET6, from, ntopbuf, | |
374 | INET6_ADDRSTRLEN)); | 373 | INET6_ADDRSTRLEN)); | |
375 | return 0; | 374 | return 0; | |
@@ -405,61 +404,63 @@ rr_command_input(int len, struct icmp6_r | @@ -405,61 +404,63 @@ rr_command_input(int len, struct icmp6_r | |||
405 | } | 404 | } | |
406 | 405 | |||
407 | /* update segnum */ | 406 | /* update segnum */ | |
408 | RR_SET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum); | 407 | RR_SET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum); | |
409 | 408 | |||
410 | return; | 409 | return; | |
411 | 410 | |||
412 | failed: | 411 | failed: | |
413 | syslog(LOG_ERR, "<%s> received RR was invalid", __func__); | 412 | syslog(LOG_ERR, "<%s> received RR was invalid", __func__); | |
414 | return; | 413 | return; | |
415 | } | 414 | } | |
416 | 415 | |||
417 | void | 416 | void | |
418 | rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi, | 417 | rr_input(size_t len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi, | |
419 | struct sockaddr_in6 *from, struct in6_addr *dst) | 418 | struct sockaddr_in6 *from, struct in6_addr *dst) | |
420 | { | 419 | { | |
421 | char ntopbuf[2][INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; | 420 | char ntopbuf[2][INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; | |
422 | 421 | |||
423 | syslog(LOG_DEBUG, | 422 | syslog(LOG_DEBUG, | |
424 | "<%s> RR received from %s to %s on %s", | 423 | "<%s> RR received from %s to %s on %s", | |
425 | __func__, | 424 | __func__, | |
426 | inet_ntop(AF_INET6, &from->sin6_addr, | 425 | inet_ntop(AF_INET6, &from->sin6_addr, | |
427 | ntopbuf[0], INET6_ADDRSTRLEN), | 426 | ntopbuf[0], INET6_ADDRSTRLEN), | |
428 | inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN), | 427 | inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN), | |
429 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 428 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
430 | 429 | |||
431 | /* packet validation based on Section 4.1 of RFC2894 */ | 430 | /* packet validation based on Section 4.1 of RFC2894 */ | |
432 | if (len < sizeof(struct icmp6_router_renum)) { | 431 | if (len < sizeof(struct icmp6_router_renum)) { | |
433 | syslog(LOG_NOTICE, | 432 | syslog(LOG_NOTICE, | |
434 | "<%s>: RR short message (size %d) from %s to %s on %s", | 433 | "<%s>: RR short message (size %zd) from %s to %s on %s", | |
435 | __func__, len, | 434 | __func__, len, | |
436 | inet_ntop(AF_INET6, &from->sin6_addr, | 435 | inet_ntop(AF_INET6, &from->sin6_addr, | |
437 | ntopbuf[0], INET6_ADDRSTRLEN), | 436 | ntopbuf[0], INET6_ADDRSTRLEN), | |
438 | inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN), | 437 | inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN), | |
439 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 438 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
440 | return; | 439 | return; | |
441 | } | 440 | } | |
442 | 441 | |||
443 | /* | 442 | /* | |
444 | * If the IPv6 destination address is neither an All Routers multicast | 443 | * If the IPv6 destination address is neither an All Routers multicast | |
445 | * address [AARCH] nor one of the receiving router's unicast addresses, | 444 | * address [AARCH] nor one of the receiving router's unicast addresses, | |
446 | * the message MUST be discarded and SHOULD be logged to network | 445 | * the message MUST be discarded and SHOULD be logged to network | |
447 | * management. | 446 | * management. | |
448 | * We rely on the kernel input routine for unicast addresses, and thus | 447 | * We rely on the kernel input routine for unicast addresses, and thus | |
449 | * check multicast destinations only. | 448 | * check multicast destinations only. | |
450 | */ | 449 | */ | |
451 | if (IN6_IS_ADDR_MULTICAST(&pi->ipi6_addr) && | 450 | if (IN6_IS_ADDR_MULTICAST(&pi->ipi6_addr) && | |
452 | !IN6_ARE_ADDR_EQUAL(&in6a_site_allrouters, &pi->ipi6_addr)) { | 451 | !IN6_ARE_ADDR_EQUAL(&sin6_sitelocal_allrouters.sin6_addr, | |
452 | &pi->ipi6_addr)) | |||
453 | { | |||
453 | syslog(LOG_NOTICE, | 454 | syslog(LOG_NOTICE, | |
454 | "<%s>: RR message with invalid destination (%s) " | 455 | "<%s>: RR message with invalid destination (%s) " | |
455 | "from %s on %s", | 456 | "from %s on %s", | |
456 | __func__, | 457 | __func__, | |
457 | inet_ntop(AF_INET6, &dst, ntopbuf[0], INET6_ADDRSTRLEN), | 458 | inet_ntop(AF_INET6, &dst, ntopbuf[0], INET6_ADDRSTRLEN), | |
458 | inet_ntop(AF_INET6, &from->sin6_addr, | 459 | inet_ntop(AF_INET6, &from->sin6_addr, | |
459 | ntopbuf[1], INET6_ADDRSTRLEN), | 460 | ntopbuf[1], INET6_ADDRSTRLEN), | |
460 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 461 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
461 | return; | 462 | return; | |
462 | } | 463 | } | |
463 | 464 | |||
464 | rr_rcvifindex = pi->ipi6_ifindex; | 465 | rr_rcvifindex = pi->ipi6_ifindex; | |
465 | 466 |
--- src/usr.sbin/rtadvd/Attic/rrenum.h 2001/01/21 15:39:33 1.4
+++ src/usr.sbin/rtadvd/Attic/rrenum.h 2011/12/10 19:14:29 1.5
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rrenum.h,v 1.4 2001/01/21 15:39:33 itojun Exp $ */ | 1 | /* $NetBSD: rrenum.h,v 1.5 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: rrenum.h,v 1.3 2001/01/21 15:37:14 itojun Exp $ */ | 2 | /* $KAME: rrenum.h,v 1.3 2001/01/21 15:37:14 itojun 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 | |
@@ -20,15 +20,15 @@ | @@ -20,15 +20,15 @@ | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | 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 | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | void rr_input __P((int, struct icmp6_router_renum *, struct in6_pktinfo *, | 33 | void rr_input(size_t, struct icmp6_router_renum *, struct in6_pktinfo *, | |
34 | struct sockaddr_in6 *, struct in6_addr *)); | 34 | struct sockaddr_in6 *, struct in6_addr *); |
--- src/usr.sbin/rtadvd/rtadvd.c 2009/04/19 08:40:48 1.35
+++ src/usr.sbin/rtadvd/rtadvd.c 2011/12/10 19:14:29 1.36
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rtadvd.c,v 1.35 2009/04/19 08:40:48 lukem Exp $ */ | 1 | /* $NetBSD: rtadvd.c,v 1.36 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: rtadvd.c,v 1.92 2005/10/17 14:40:02 suz Exp $ */ | 2 | /* $KAME: rtadvd.c,v 1.92 2005/10/17 14:40:02 suz Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, and 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 | |
@@ -56,106 +56,125 @@ | @@ -56,106 +56,125 @@ | |||
56 | #include <syslog.h> | 56 | #include <syslog.h> | |
57 | #include <util.h> | 57 | #include <util.h> | |
58 | #include <poll.h> | 58 | #include <poll.h> | |
59 | 59 | |||
60 | #include "rtadvd.h" | 60 | #include "rtadvd.h" | |
61 | #include "rrenum.h" | 61 | #include "rrenum.h" | |
62 | #include "advcap.h" | 62 | #include "advcap.h" | |
63 | #include "timer.h" | 63 | #include "timer.h" | |
64 | #include "if.h" | 64 | #include "if.h" | |
65 | #include "config.h" | 65 | #include "config.h" | |
66 | #include "dump.h" | 66 | #include "dump.h" | |
67 | 67 | |||
68 | struct msghdr rcvmhdr; | 68 | struct msghdr rcvmhdr; | |
69 | static u_char *rcvcmsgbuf; | 69 | static unsigned char *rcvcmsgbuf; | |
70 | static size_t rcvcmsgbuflen; | 70 | static size_t rcvcmsgbuflen; | |
71 | static u_char *sndcmsgbuf = NULL; | 71 | static unsigned char *sndcmsgbuf = NULL; | |
72 | static size_t sndcmsgbuflen; | 72 | static size_t sndcmsgbuflen; | |
73 | volatile sig_atomic_t do_dump; | 73 | volatile sig_atomic_t do_dump; | |
74 | volatile sig_atomic_t do_die; | 74 | volatile sig_atomic_t do_die; | |
75 | struct msghdr sndmhdr; | 75 | struct msghdr sndmhdr; | |
76 | struct iovec rcviov[2]; | 76 | struct iovec rcviov[2]; | |
77 | struct iovec sndiov[2]; | 77 | struct iovec sndiov[2]; | |
78 | struct sockaddr_in6 rcvfrom; | 78 | struct sockaddr_in6 rcvfrom; | |
79 | struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6}; | 79 | static const char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX configurable */ | |
80 | struct in6_addr in6a_site_allrouters; | |||
81 | static char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX: should be configurable */ | |||
82 | static char *mcastif; | 80 | static char *mcastif; | |
83 | int sock; | 81 | int sock; | |
84 | int rtsock = -1; | 82 | int rtsock = -1; | |
85 | int accept_rr = 0; | 83 | int accept_rr = 0; | |
86 | int dflag = 0, sflag = 0; | 84 | int dflag = 0, sflag = 0; | |
87 | 85 | |||
88 | char *conffile = NULL; | 86 | char *conffile = NULL; | |
89 | 87 | |||
90 | struct rainfo *ralist = NULL; | 88 | struct ralist_head_t ralist = TAILQ_HEAD_INITIALIZER(ralist); | |
89 | ||||
91 | struct nd_optlist { | 90 | struct nd_optlist { | |
92 | struct nd_optlist *next; | 91 | TAILQ_ENTRY(nd_optlist) next; | |
93 | struct nd_opt_hdr *opt; | 92 | struct nd_opt_hdr *opt; | |
94 | }; | 93 | }; | |
95 | union nd_opts { | 94 | union nd_opts { | |
96 | struct nd_opt_hdr *nd_opt_array[9]; | 95 | struct nd_opt_hdr *nd_opt_array[9]; | |
97 | struct { | 96 | struct { | |
98 | struct nd_opt_hdr *zero; | 97 | struct nd_opt_hdr *zero; | |
99 | struct nd_opt_hdr *src_lladdr; | 98 | struct nd_opt_hdr *src_lladdr; | |
100 | struct nd_opt_hdr *tgt_lladdr; | 99 | struct nd_opt_hdr *tgt_lladdr; | |
101 | struct nd_opt_prefix_info *pi; | 100 | struct nd_opt_prefix_info *pi; | |
102 | struct nd_opt_rd_hdr *rh; | 101 | struct nd_opt_rd_hdr *rh; | |
103 | struct nd_opt_mtu *mtu; | 102 | struct nd_opt_mtu *mtu; | |
104 | struct nd_optlist *list; | 103 | TAILQ_HEAD(, nd_optlist) list; | |
105 | } nd_opt_each; | 104 | } nd_opt_each; | |
106 | }; | 105 | }; | |
107 | #define nd_opts_src_lladdr nd_opt_each.src_lladdr | 106 | #define nd_opts_src_lladdr nd_opt_each.src_lladdr | |
108 | #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr | 107 | #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr | |
109 | #define nd_opts_pi nd_opt_each.pi | 108 | #define nd_opts_pi nd_opt_each.pi | |
110 | #define nd_opts_rh nd_opt_each.rh | 109 | #define nd_opts_rh nd_opt_each.rh | |
111 | #define nd_opts_mtu nd_opt_each.mtu | 110 | #define nd_opts_mtu nd_opt_each.mtu | |
112 | #define nd_opts_list nd_opt_each.list | 111 | #define nd_opts_list nd_opt_each.list | |
113 | 112 | |||
114 | #define NDOPT_FLAG_SRCLINKADDR 0x1 | 113 | #define NDOPT_FLAG_SRCLINKADDR (1 << 0) | |
115 | #define NDOPT_FLAG_TGTLINKADDR 0x2 | 114 | #define NDOPT_FLAG_TGTLINKADDR (1 << 1) | |
116 | #define NDOPT_FLAG_PREFIXINFO 0x4 | 115 | #define NDOPT_FLAG_PREFIXINFO (1 << 2) | |
117 | #define NDOPT_FLAG_RDHDR 0x8 | 116 | #define NDOPT_FLAG_RDHDR (1 << 3) | |
118 | #define NDOPT_FLAG_MTU 0x10 | 117 | #define NDOPT_FLAG_MTU (1 << 4) | |
119 | 118 | #define NDOPT_FLAG_RDNSS (1 << 5) | ||
120 | u_int32_t ndopt_flags[] = { | 119 | #define NDOPT_FLAG_DNSSL (1 << 6) | |
121 | 0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR, | 120 | ||
122 | NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU, | 121 | uint32_t ndopt_flags[] = { | |
122 | [ND_OPT_SOURCE_LINKADDR] = NDOPT_FLAG_SRCLINKADDR, | |||
123 | [ND_OPT_TARGET_LINKADDR] = NDOPT_FLAG_TGTLINKADDR, | |||
124 | [ND_OPT_PREFIX_INFORMATION] = NDOPT_FLAG_PREFIXINFO, | |||
125 | [ND_OPT_REDIRECTED_HEADER] = NDOPT_FLAG_RDHDR, | |||
126 | [ND_OPT_MTU] = NDOPT_FLAG_MTU, | |||
127 | [ND_OPT_RDNSS] = NDOPT_FLAG_RDNSS, | |||
128 | [ND_OPT_DNSSL] = NDOPT_FLAG_DNSSL, | |||
129 | }; | |||
130 | ||||
131 | struct sockaddr_in6 sin6_linklocal_allnodes = { | |||
132 | .sin6_len = sizeof(sin6_linklocal_allnodes), | |||
133 | .sin6_family = AF_INET6, | |||
134 | .sin6_addr = IN6ADDR_LINKLOCAL_ALLNODES_INIT, | |||
135 | }; | |||
136 | struct sockaddr_in6 sin6_linklocal_allrouters = { | |||
137 | .sin6_len = sizeof(sin6_linklocal_allrouters), | |||
138 | .sin6_family = AF_INET6, | |||
139 | .sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT, | |||
140 | }; | |||
141 | struct sockaddr_in6 sin6_sitelocal_allrouters = { | |||
142 | .sin6_len = sizeof(sin6_sitelocal_allrouters), | |||
143 | .sin6_family = AF_INET6, | |||
144 | .sin6_addr = IN6ADDR_SITELOCAL_ALLROUTERS_INIT, | |||
123 | }; | 145 | }; | |
124 | 146 | |||
125 | int main __P((int, char *[])); | 147 | int main(int, char *[]); | |
126 | static void set_die __P((int)); | 148 | static void set_die(int); | |
127 | static void die __P((void)); | 149 | static void die(void); | |
128 | static void sock_open __P((void)); | 150 | static void sock_open(void); | |
129 | static void rtsock_open __P((void)); | 151 | static void rtsock_open(void); | |
130 | static void rtadvd_input __P((void)); | 152 | static void rtadvd_input(void); | |
131 | static void rs_input __P((int, struct nd_router_solicit *, | 153 | static void rs_input(int, struct nd_router_solicit *, | |
132 | struct in6_pktinfo *, struct sockaddr_in6 *)); | 154 | struct in6_pktinfo *, struct sockaddr_in6 *); | |
133 | static void ra_input __P((int, struct nd_router_advert *, | 155 | static void ra_input(int, struct nd_router_advert *, | |
134 | struct in6_pktinfo *, struct sockaddr_in6 *)); | 156 | struct in6_pktinfo *, struct sockaddr_in6 *); | |
135 | static int prefix_check __P((struct nd_opt_prefix_info *, struct rainfo *, | 157 | static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *, | |
136 | struct sockaddr_in6 *)); | 158 | struct sockaddr_in6 *); | |
137 | static int nd6_options __P((struct nd_opt_hdr *, int, | 159 | static int nd6_options(struct nd_opt_hdr *, int, union nd_opts *, uint32_t); | |
138 | union nd_opts *, u_int32_t)); | 160 | static void free_ndopts(union nd_opts *); | |
139 | static void free_ndopts __P((union nd_opts *)); | 161 | static void ra_output(struct rainfo *); | |
140 | static void ra_output __P((struct rainfo *)); | 162 | static void rtmsg_input(void); | |
141 | static void rtmsg_input __P((void)); | 163 | static void rtadvd_set_dump_file(int); | |
142 | static void rtadvd_set_dump_file __P((int)); | 164 | static void set_short_delay(struct rainfo *); | |
143 | static void set_short_delay __P((struct rainfo *)); | |||
144 | 165 | |||
145 | int | 166 | int | |
146 | main(argc, argv) | 167 | main(int argc, char *argv[]) | |
147 | int argc; | |||
148 | char *argv[]; | |||
149 | { | 168 | { | |
150 | struct pollfd set[2]; | 169 | struct pollfd set[2]; | |
151 | struct timeval *timeout; | 170 | struct timeval *timeout; | |
152 | int i, ch; | 171 | int i, ch; | |
153 | int fflag = 0, logopt; | 172 | int fflag = 0, logopt; | |
154 | 173 | |||
155 | /* get command line options and arguments */ | 174 | /* get command line options and arguments */ | |
156 | #define OPTIONS "c:dDfM:Rs" | 175 | #define OPTIONS "c:dDfM:Rs" | |
157 | while ((ch = getopt(argc, argv, OPTIONS)) != -1) { | 176 | while ((ch = getopt(argc, argv, OPTIONS)) != -1) { | |
158 | #undef OPTIONS | 177 | #undef OPTIONS | |
159 | switch (ch) { | 178 | switch (ch) { | |
160 | case 'c': | 179 | case 'c': | |
161 | conffile = optarg; | 180 | conffile = optarg; | |
@@ -202,31 +221,26 @@ main(argc, argv) | @@ -202,31 +221,26 @@ main(argc, argv) | |||
202 | (void)setlogmask(LOG_UPTO(LOG_ERR)); | 221 | (void)setlogmask(LOG_UPTO(LOG_ERR)); | |
203 | if (dflag == 1) | 222 | if (dflag == 1) | |
204 | (void)setlogmask(LOG_UPTO(LOG_INFO)); | 223 | (void)setlogmask(LOG_UPTO(LOG_INFO)); | |
205 | 224 | |||
206 | /* timer initialization */ | 225 | /* timer initialization */ | |
207 | rtadvd_timer_init(); | 226 | rtadvd_timer_init(); | |
208 | 227 | |||
209 | /* get iflist block from kernel */ | 228 | /* get iflist block from kernel */ | |
210 | init_iflist(); | 229 | init_iflist(); | |
211 | 230 | |||
212 | while (argc--) | 231 | while (argc--) | |
213 | getconfig(*argv++); | 232 | getconfig(*argv++); | |
214 | 233 | |||
215 | if (inet_pton(AF_INET6, ALLNODES, &sin6_allnodes.sin6_addr) != 1) { | |||
216 | fprintf(stderr, "fatal: inet_pton failed\n"); | |||
217 | exit(1); | |||
218 | } | |||
219 | ||||
220 | if (!fflag) | 234 | if (!fflag) | |
221 | daemon(1, 0); | 235 | daemon(1, 0); | |
222 | 236 | |||
223 | sock_open(); | 237 | sock_open(); | |
224 | 238 | |||
225 | /* record the current PID */ | 239 | /* record the current PID */ | |
226 | if (pidfile(NULL) < 0) { | 240 | if (pidfile(NULL) < 0) { | |
227 | syslog(LOG_ERR, | 241 | syslog(LOG_ERR, | |
228 | "<%s> failed to open the pid log file, run anyway.", | 242 | "<%s> failed to open the pid log file, run anyway.", | |
229 | __func__); | 243 | __func__); | |
230 | } | 244 | } | |
231 | 245 | |||
232 | set[0].fd = sock; | 246 | set[0].fd = sock; | |
@@ -276,66 +290,64 @@ main(argc, argv) | @@ -276,66 +290,64 @@ main(argc, argv) | |||
276 | continue; | 290 | continue; | |
277 | } | 291 | } | |
278 | if (i == 0) /* timeout */ | 292 | if (i == 0) /* timeout */ | |
279 | continue; | 293 | continue; | |
280 | if (rtsock != -1 && set[1].revents & POLLIN) | 294 | if (rtsock != -1 && set[1].revents & POLLIN) | |
281 | rtmsg_input(); | 295 | rtmsg_input(); | |
282 | if (set[0].revents & POLLIN) | 296 | if (set[0].revents & POLLIN) | |
283 | rtadvd_input(); | 297 | rtadvd_input(); | |
284 | } | 298 | } | |
285 | exit(0); /* NOTREACHED */ | 299 | exit(0); /* NOTREACHED */ | |
286 | } | 300 | } | |
287 | 301 | |||
288 | static void | 302 | static void | |
289 | rtadvd_set_dump_file(sig) | 303 | rtadvd_set_dump_file(int sig) | |
290 | int sig; | |||
291 | { | 304 | { | |
292 | do_dump = 1; | 305 | do_dump = 1; | |
293 | } | 306 | } | |
294 | 307 | |||
295 | static void | 308 | static void | |
296 | set_die(sig) | 309 | set_die(int sig) | |
297 | int sig; | |||
298 | { | 310 | { | |
299 | do_die = 1; | 311 | do_die = 1; | |
300 | } | 312 | } | |
301 | 313 | |||
302 | static void | 314 | static void | |
303 | die() | 315 | die(void) | |
304 | { | 316 | { | |
305 | struct rainfo *ra; | 317 | struct rainfo *ra; | |
306 | int i; | 318 | int i; | |
307 | const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS; | 319 | const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS; | |
308 | 320 | |||
309 | if (dflag > 1) { | 321 | if (dflag > 1) { | |
310 | syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n", | 322 | syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n", | |
311 | __func__); | 323 | __func__); | |
312 | } | 324 | } | |
313 | 325 | |||
314 | for (ra = ralist; ra; ra = ra->next) { | 326 | TAILQ_FOREACH(ra, &ralist, next) { | |
315 | ra->lifetime = 0; | 327 | ra->lifetime = 0; | |
316 | make_packet(ra); | 328 | make_packet(ra); | |
317 | } | 329 | } | |
318 | for (i = 0; i < retrans; i++) { | 330 | for (i = 0; i < retrans; i++) { | |
319 | for (ra = ralist; ra; ra = ra->next) | 331 | TAILQ_FOREACH(ra, &ralist, next) | |
320 | ra_output(ra); | 332 | ra_output(ra); | |
321 | sleep(MIN_DELAY_BETWEEN_RAS); | 333 | sleep(MIN_DELAY_BETWEEN_RAS); | |
322 | } | 334 | } | |
323 | exit(0); | 335 | exit(0); | |
324 | /*NOTREACHED*/ | 336 | /*NOTREACHED*/ | |
325 | } | 337 | } | |
326 | 338 | |||
327 | static void | 339 | static void | |
328 | rtmsg_input() | 340 | rtmsg_input(void) | |
329 | { | 341 | { | |
330 | int n, type, ifindex = 0, plen; | 342 | int n, type, ifindex = 0, plen; | |
331 | size_t len; | 343 | size_t len; | |
332 | union rt_msghdr_buf { | 344 | union rt_msghdr_buf { | |
333 | struct rt_msghdr rt_msghdr; | 345 | struct rt_msghdr rt_msghdr; | |
334 | char data[2048]; | 346 | char data[2048]; | |
335 | } buffer; | 347 | } buffer; | |
336 | char *msg, *next, *lim; | 348 | char *msg, *next, *lim; | |
337 | char ifname[IF_NAMESIZE]; | 349 | char ifname[IF_NAMESIZE]; | |
338 | struct prefix *prefix; | 350 | struct prefix *prefix; | |
339 | struct rainfo *rai; | 351 | struct rainfo *rai; | |
340 | struct in6_addr *addr; | 352 | struct in6_addr *addr; | |
341 | char addrbuf[INET6_ADDRSTRLEN]; | 353 | char addrbuf[INET6_ADDRSTRLEN]; | |
@@ -535,29 +547,29 @@ rtmsg_input() | @@ -535,29 +547,29 @@ rtmsg_input() | |||
535 | /* | 547 | /* | |
536 | * An advertised prefix has been added or invalidated. | 548 | * An advertised prefix has been added or invalidated. | |
537 | * Will notice the change in a short delay. | 549 | * Will notice the change in a short delay. | |
538 | */ | 550 | */ | |
539 | rai->initcounter = 0; | 551 | rai->initcounter = 0; | |
540 | set_short_delay(rai); | 552 | set_short_delay(rai); | |
541 | } | 553 | } | |
542 | } | 554 | } | |
543 | 555 | |||
544 | return; | 556 | return; | |
545 | } | 557 | } | |
546 | 558 | |||
547 | void | 559 | void | |
548 | rtadvd_input() | 560 | rtadvd_input(void) | |
549 | { | 561 | { | |
550 | int i; | 562 | ssize_t i; | |
551 | int *hlimp = NULL; | 563 | int *hlimp = NULL; | |
552 | #ifdef OLDRAWSOCKET | 564 | #ifdef OLDRAWSOCKET | |
553 | struct ip6_hdr *ip; | 565 | struct ip6_hdr *ip; | |
554 | #endif | 566 | #endif | |
555 | struct icmp6_hdr *icp; | 567 | struct icmp6_hdr *icp; | |
556 | int ifindex = 0; | 568 | int ifindex = 0; | |
557 | struct cmsghdr *cm; | 569 | struct cmsghdr *cm; | |
558 | struct in6_pktinfo *pi = NULL; | 570 | struct in6_pktinfo *pi = NULL; | |
559 | char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; | 571 | char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; | |
560 | struct in6_addr dst = in6addr_any; | 572 | struct in6_addr dst = in6addr_any; | |
561 | 573 | |||
562 | /* | 574 | /* | |
563 | * Get message. We reset msg_controllen since the field could | 575 | * Get message. We reset msg_controllen since the field could | |
@@ -600,39 +612,39 @@ rtadvd_input() | @@ -600,39 +612,39 @@ rtadvd_input() | |||
600 | /* | 612 | /* | |
601 | * If we happen to receive data on an interface which is now down, | 613 | * If we happen to receive data on an interface which is now down, | |
602 | * just discard the data. | 614 | * just discard the data. | |
603 | */ | 615 | */ | |
604 | if ((iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) { | 616 | if ((iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) { | |
605 | syslog(LOG_INFO, | 617 | syslog(LOG_INFO, | |
606 | "<%s> received data on a disabled interface (%s)", | 618 | "<%s> received data on a disabled interface (%s)", | |
607 | __func__, | 619 | __func__, | |
608 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 620 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
609 | return; | 621 | return; | |
610 | } | 622 | } | |
611 | 623 | |||
612 | #ifdef OLDRAWSOCKET | 624 | #ifdef OLDRAWSOCKET | |
613 | if (i < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) { | 625 | if ((size_t)i < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) { | |
614 | syslog(LOG_ERR, | 626 | syslog(LOG_ERR, | |
615 | "<%s> packet size(%d) is too short", | 627 | "<%s> packet size(%d) is too short", | |
616 | __func__, i); | 628 | __func__, i); | |
617 | return; | 629 | return; | |
618 | } | 630 | } | |
619 | 631 | |||
620 | ip = (struct ip6_hdr *)rcvmhdr.msg_iov[0].iov_base; | 632 | ip = (struct ip6_hdr *)rcvmhdr.msg_iov[0].iov_base; | |
621 | icp = (struct icmp6_hdr *)(ip + 1); /* XXX: ext. hdr? */ | 633 | icp = (struct icmp6_hdr *)(ip + 1); /* XXX: ext. hdr? */ | |
622 | #else | 634 | #else | |
623 | if (i < sizeof(struct icmp6_hdr)) { | 635 | if ((size_t)i < sizeof(struct icmp6_hdr)) { | |
624 | syslog(LOG_ERR, | 636 | syslog(LOG_ERR, | |
625 | "<%s> packet size(%d) is too short", | 637 | "<%s> packet size(%zd) is too short", | |
626 | __func__, i); | 638 | __func__, i); | |
627 | return; | 639 | return; | |
628 | } | 640 | } | |
629 | 641 | |||
630 | icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base; | 642 | icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base; | |
631 | #endif | 643 | #endif | |
632 | 644 | |||
633 | switch (icp->icmp6_type) { | 645 | switch (icp->icmp6_type) { | |
634 | case ND_ROUTER_SOLICIT: | 646 | case ND_ROUTER_SOLICIT: | |
635 | /* | 647 | /* | |
636 | * Message verification - RFC-2461 6.1.1 | 648 | * Message verification - RFC-2461 6.1.1 | |
637 | * XXX: these checks must be done in the kernel as well, | 649 | * XXX: these checks must be done in the kernel as well, | |
638 | * but we can't completely rely on them. | 650 | * but we can't completely rely on them. | |
@@ -647,30 +659,30 @@ rtadvd_input() | @@ -647,30 +659,30 @@ rtadvd_input() | |||
647 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 659 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
648 | return; | 660 | return; | |
649 | } | 661 | } | |
650 | if (icp->icmp6_code) { | 662 | if (icp->icmp6_code) { | |
651 | syslog(LOG_NOTICE, | 663 | syslog(LOG_NOTICE, | |
652 | "<%s> RS with invalid ICMP6 code(%d) " | 664 | "<%s> RS with invalid ICMP6 code(%d) " | |
653 | "received from %s on %s", | 665 | "received from %s on %s", | |
654 | __func__, icp->icmp6_code, | 666 | __func__, icp->icmp6_code, | |
655 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | 667 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | |
656 | INET6_ADDRSTRLEN), | 668 | INET6_ADDRSTRLEN), | |
657 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 669 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
658 | return; | 670 | return; | |
659 | } | 671 | } | |
660 | if (i < sizeof(struct nd_router_solicit)) { | 672 | if ((size_t)i < sizeof(struct nd_router_solicit)) { | |
661 | syslog(LOG_NOTICE, | 673 | syslog(LOG_NOTICE, | |
662 | "<%s> RS from %s on %s does not have enough " | 674 | "<%s> RS from %s on %s does not have enough " | |
663 | "length (len = %d)", | 675 | "length (len = %zd)", | |
664 | __func__, | 676 | __func__, | |
665 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | 677 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | |
666 | INET6_ADDRSTRLEN), | 678 | INET6_ADDRSTRLEN), | |
667 | if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); | 679 | if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); | |
668 | return; | 680 | return; | |
669 | } | 681 | } | |
670 | rs_input(i, (struct nd_router_solicit *)icp, pi, &rcvfrom); | 682 | rs_input(i, (struct nd_router_solicit *)icp, pi, &rcvfrom); | |
671 | break; | 683 | break; | |
672 | case ND_ROUTER_ADVERT: | 684 | case ND_ROUTER_ADVERT: | |
673 | /* | 685 | /* | |
674 | * Message verification - RFC-2461 6.1.2 | 686 | * Message verification - RFC-2461 6.1.2 | |
675 | * XXX: there's a same dilemma as above... | 687 | * XXX: there's a same dilemma as above... | |
676 | */ | 688 | */ | |
@@ -684,30 +696,30 @@ rtadvd_input() | @@ -684,30 +696,30 @@ rtadvd_input() | |||
684 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 696 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
685 | return; | 697 | return; | |
686 | } | 698 | } | |
687 | if (icp->icmp6_code) { | 699 | if (icp->icmp6_code) { | |
688 | syslog(LOG_NOTICE, | 700 | syslog(LOG_NOTICE, | |
689 | "<%s> RA with invalid ICMP6 code(%d) " | 701 | "<%s> RA with invalid ICMP6 code(%d) " | |
690 | "received from %s on %s", | 702 | "received from %s on %s", | |
691 | __func__, icp->icmp6_code, | 703 | __func__, icp->icmp6_code, | |
692 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | 704 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | |
693 | INET6_ADDRSTRLEN), | 705 | INET6_ADDRSTRLEN), | |
694 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 706 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
695 | return; | 707 | return; | |
696 | } | 708 | } | |
697 | if (i < sizeof(struct nd_router_advert)) { | 709 | if ((size_t)i < sizeof(struct nd_router_advert)) { | |
698 | syslog(LOG_NOTICE, | 710 | syslog(LOG_NOTICE, | |
699 | "<%s> RA from %s on %s does not have enough " | 711 | "<%s> RA from %s on %s does not have enough " | |
700 | "length (len = %d)", | 712 | "length (len = %zd)", | |
701 | __func__, | 713 | __func__, | |
702 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | 714 | inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf, | |
703 | INET6_ADDRSTRLEN), | 715 | INET6_ADDRSTRLEN), | |
704 | if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); | 716 | if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); | |
705 | return; | 717 | return; | |
706 | } | 718 | } | |
707 | ra_input(i, (struct nd_router_advert *)icp, pi, &rcvfrom); | 719 | ra_input(i, (struct nd_router_advert *)icp, pi, &rcvfrom); | |
708 | break; | 720 | break; | |
709 | case ICMP6_ROUTER_RENUMBERING: | 721 | case ICMP6_ROUTER_RENUMBERING: | |
710 | if (accept_rr == 0) { | 722 | if (accept_rr == 0) { | |
711 | syslog(LOG_ERR, "<%s> received a router renumbering " | 723 | syslog(LOG_ERR, "<%s> received a router renumbering " | |
712 | "message, but not allowed to be accepted", | 724 | "message, but not allowed to be accepted", | |
713 | __func__); | 725 | __func__); | |
@@ -739,26 +751,27 @@ rs_input(int len, struct nd_router_solic | @@ -739,26 +751,27 @@ rs_input(int len, struct nd_router_solic | |||
739 | union nd_opts ndopts; | 751 | union nd_opts ndopts; | |
740 | struct rainfo *ra; | 752 | struct rainfo *ra; | |
741 | struct soliciter *sol; | 753 | struct soliciter *sol; | |
742 | 754 | |||
743 | syslog(LOG_DEBUG, | 755 | syslog(LOG_DEBUG, | |
744 | "<%s> RS received from %s on %s", | 756 | "<%s> RS received from %s on %s", | |
745 | __func__, | 757 | __func__, | |
746 | inet_ntop(AF_INET6, &from->sin6_addr, | 758 | inet_ntop(AF_INET6, &from->sin6_addr, | |
747 | ntopbuf, INET6_ADDRSTRLEN), | 759 | ntopbuf, INET6_ADDRSTRLEN), | |
748 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 760 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
749 | 761 | |||
750 | /* ND option check */ | 762 | /* ND option check */ | |
751 | memset(&ndopts, 0, sizeof(ndopts)); | 763 | memset(&ndopts, 0, sizeof(ndopts)); | |
764 | TAILQ_INIT(&ndopts.nd_opts_list); | |||
752 | if (nd6_options((struct nd_opt_hdr *)(rs + 1), | 765 | if (nd6_options((struct nd_opt_hdr *)(rs + 1), | |
753 | len - sizeof(struct nd_router_solicit), | 766 | len - sizeof(struct nd_router_solicit), | |
754 | &ndopts, NDOPT_FLAG_SRCLINKADDR)) { | 767 | &ndopts, NDOPT_FLAG_SRCLINKADDR)) { | |
755 | syslog(LOG_INFO, | 768 | syslog(LOG_INFO, | |
756 | "<%s> ND option check failed for an RS from %s on %s", | 769 | "<%s> ND option check failed for an RS from %s on %s", | |
757 | __func__, | 770 | __func__, | |
758 | inet_ntop(AF_INET6, &from->sin6_addr, | 771 | inet_ntop(AF_INET6, &from->sin6_addr, | |
759 | ntopbuf, INET6_ADDRSTRLEN), | 772 | ntopbuf, INET6_ADDRSTRLEN), | |
760 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 773 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
761 | return; | 774 | return; | |
762 | } | 775 | } | |
763 | 776 | |||
764 | /* | 777 | /* | |
@@ -766,74 +779,70 @@ rs_input(int len, struct nd_router_solic | @@ -766,74 +779,70 @@ rs_input(int len, struct nd_router_solic | |||
766 | * must be no source link-layer address option in the message. | 779 | * must be no source link-layer address option in the message. | |
767 | * (RFC-2461 6.1.1) | 780 | * (RFC-2461 6.1.1) | |
768 | */ | 781 | */ | |
769 | if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) && | 782 | if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) && | |
770 | ndopts.nd_opts_src_lladdr) { | 783 | ndopts.nd_opts_src_lladdr) { | |
771 | syslog(LOG_INFO, | 784 | syslog(LOG_INFO, | |
772 | "<%s> RS from unspecified src on %s has a link-layer" | 785 | "<%s> RS from unspecified src on %s has a link-layer" | |
773 | " address option", | 786 | " address option", | |
774 | __func__, | 787 | __func__, | |
775 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 788 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
776 | goto done; | 789 | goto done; | |
777 | } | 790 | } | |
778 | 791 | |||
779 | ra = ralist; | 792 | TAILQ_FOREACH(ra, &ralist, next) { | |
780 | while (ra != NULL) { | |||
781 | if (pi->ipi6_ifindex == ra->ifindex) | 793 | if (pi->ipi6_ifindex == ra->ifindex) | |
782 | break; | 794 | break; | |
783 | ra = ra->next; | |||
784 | } | 795 | } | |
785 | if (ra == NULL) { | 796 | if (ra == NULL) { | |
786 | syslog(LOG_INFO, | 797 | syslog(LOG_INFO, | |
787 | "<%s> RS received on non advertising interface(%s)", | 798 | "<%s> RS received on non advertising interface(%s)", | |
788 | __func__, | 799 | __func__, | |
789 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 800 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
790 | goto done; | 801 | goto done; | |
791 | } | 802 | } | |
792 | 803 | |||
793 | ra->rsinput++; /* increment statistics */ | 804 | ra->rsinput++; /* increment statistics */ | |
794 | 805 | |||
795 | /* | 806 | /* | |
796 | * Decide whether to send RA according to the rate-limit | 807 | * Decide whether to send RA according to the rate-limit | |
797 | * consideration. | 808 | * consideration. | |
798 | */ | 809 | */ | |
799 | 810 | |||
800 | /* record sockaddr waiting for RA, if possible */ | 811 | /* record sockaddr waiting for RA, if possible */ | |
801 | sol = (struct soliciter *)malloc(sizeof(*sol)); | 812 | sol = malloc(sizeof(*sol)); | |
802 | if (sol) { | 813 | if (sol) { | |
803 | sol->addr = *from; | 814 | sol->addr = *from; | |
804 | /* XXX RFC2553 need clarification on flowinfo */ | 815 | /* XXX RFC2553 need clarification on flowinfo */ | |
805 | sol->addr.sin6_flowinfo = 0; | 816 | sol->addr.sin6_flowinfo = 0; | |
806 | sol->next = ra->soliciter; | 817 | TAILQ_INSERT_HEAD(&ra->soliciter, sol, next); | |
807 | ra->soliciter = sol; | |||
808 | } | 818 | } | |
809 | 819 | |||
810 | /* | 820 | /* | |
811 | * If there is already a waiting RS packet, don't | 821 | * If there is already a waiting RS packet, don't | |
812 | * update the timer. | 822 | * update the timer. | |
813 | */ | 823 | */ | |
814 | if (ra->waiting++) | 824 | if (ra->waiting++) | |
815 | goto done; | 825 | goto done; | |
816 | 826 | |||
817 | set_short_delay(ra); | 827 | set_short_delay(ra); | |
818 | 828 | |||
819 | done: | 829 | done: | |
820 | free_ndopts(&ndopts); | 830 | free_ndopts(&ndopts); | |
821 | return; | 831 | return; | |
822 | } | 832 | } | |
823 | 833 | |||
824 | static void | 834 | static void | |
825 | set_short_delay(rai) | 835 | set_short_delay(struct rainfo *rai) | |
826 | struct rainfo *rai; | |||
827 | { | 836 | { | |
828 | long delay; /* must not be greater than 1000000 */ | 837 | long delay; /* must not be greater than 1000000 */ | |
829 | struct timeval interval, now, min_delay, tm_tmp, *rest; | 838 | struct timeval interval, now, min_delay, tm_tmp, *rest; | |
830 | 839 | |||
831 | /* | 840 | /* | |
832 | * Compute a random delay. If the computed value | 841 | * Compute a random delay. If the computed value | |
833 | * corresponds to a time later than the time the next | 842 | * corresponds to a time later than the time the next | |
834 | * multicast RA is scheduled to be sent, ignore the random | 843 | * multicast RA is scheduled to be sent, ignore the random | |
835 | * delay and send the advertisement at the | 844 | * delay and send the advertisement at the | |
836 | * already-scheduled time. RFC2461 6.2.6 | 845 | * already-scheduled time. RFC2461 6.2.6 | |
837 | */ | 846 | */ | |
838 | delay = arc4random() % MAX_RA_DELAY_TIME; | 847 | delay = arc4random() % MAX_RA_DELAY_TIME; | |
839 | interval.tv_sec = 0; | 848 | interval.tv_sec = 0; | |
@@ -860,49 +869,53 @@ set_short_delay(rai) | @@ -860,49 +869,53 @@ set_short_delay(rai) | |||
860 | TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); | 869 | TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); | |
861 | TIMEVAL_ADD(&min_delay, &interval, &interval); | 870 | TIMEVAL_ADD(&min_delay, &interval, &interval); | |
862 | } | 871 | } | |
863 | rtadvd_set_timer(&interval, rai->timer); | 872 | rtadvd_set_timer(&interval, rai->timer); | |
864 | } | 873 | } | |
865 | 874 | |||
866 | static void | 875 | static void | |
867 | ra_input(int len, struct nd_router_advert *ra, | 876 | ra_input(int len, struct nd_router_advert *ra, | |
868 | struct in6_pktinfo *pi, struct sockaddr_in6 *from) | 877 | struct in6_pktinfo *pi, struct sockaddr_in6 *from) | |
869 | { | 878 | { | |
870 | struct rainfo *rai; | 879 | struct rainfo *rai; | |
871 | char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; | 880 | char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; | |
872 | union nd_opts ndopts; | 881 | union nd_opts ndopts; | |
873 | char *on_off[] = {"OFF", "ON"}; | 882 | const char *on_off[] = {"OFF", "ON"}; | |
874 | u_int32_t reachabletime, retranstimer, mtu; | 883 | uint32_t reachabletime, retranstimer, mtu; | |
884 | struct nd_optlist *optp; | |||
875 | int inconsistent = 0; | 885 | int inconsistent = 0; | |
876 | 886 | |||
877 | syslog(LOG_DEBUG, | 887 | syslog(LOG_DEBUG, | |
878 | "<%s> RA received from %s on %s", | 888 | "<%s> RA received from %s on %s", | |
879 | __func__, | 889 | __func__, | |
880 | inet_ntop(AF_INET6, &from->sin6_addr, | 890 | inet_ntop(AF_INET6, &from->sin6_addr, | |
881 | ntopbuf, INET6_ADDRSTRLEN), | 891 | ntopbuf, INET6_ADDRSTRLEN), | |
882 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 892 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
883 | 893 | |||
884 | /* ND option check */ | 894 | /* ND option check */ | |
885 | memset(&ndopts, 0, sizeof(ndopts)); | 895 | memset(&ndopts, 0, sizeof(ndopts)); | |
896 | TAILQ_INIT(&ndopts.nd_opts_list); | |||
886 | if (nd6_options((struct nd_opt_hdr *)(ra + 1), | 897 | if (nd6_options((struct nd_opt_hdr *)(ra + 1), | |
887 | len - sizeof(struct nd_router_advert), | 898 | len - sizeof(struct nd_router_advert), | |
888 | &ndopts, NDOPT_FLAG_SRCLINKADDR | | 899 | &ndopts, NDOPT_FLAG_SRCLINKADDR | | |
889 | NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) { | 900 | NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU | | |
901 | NDOPT_FLAG_RDNSS | NDOPT_FLAG_DNSSL)) | |||
902 | { | |||
890 | syslog(LOG_INFO, | 903 | syslog(LOG_INFO, | |
891 | "<%s> ND option check failed for an RA from %s on %s", | 904 | "<%s> ND option check failed for an RA from %s on %s", | |
892 | __func__, | 905 | __func__, | |
893 | inet_ntop(AF_INET6, &from->sin6_addr, | 906 | inet_ntop(AF_INET6, &from->sin6_addr, | |
894 | ntopbuf, INET6_ADDRSTRLEN), | 907 | ntopbuf, INET6_ADDRSTRLEN), | |
895 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | 908 | if_indextoname(pi->ipi6_ifindex, ifnamebuf)); | |
896 | return; | 909 | return; | |
897 | } | 910 | } | |
898 | 911 | |||
899 | /* | 912 | /* | |
900 | * RA consistency check according to RFC-2461 6.2.7 | 913 | * RA consistency check according to RFC-2461 6.2.7 | |
901 | */ | 914 | */ | |
902 | if ((rai = if_indextorainfo(pi->ipi6_ifindex)) == 0) { | 915 | if ((rai = if_indextorainfo(pi->ipi6_ifindex)) == 0) { | |
903 | syslog(LOG_INFO, | 916 | syslog(LOG_INFO, | |
904 | "<%s> received RA from %s on non-advertising" | 917 | "<%s> received RA from %s on non-advertising" | |
905 | " interface(%s)", | 918 | " interface(%s)", | |
906 | __func__, | 919 | __func__, | |
907 | inet_ntop(AF_INET6, &from->sin6_addr, | 920 | inet_ntop(AF_INET6, &from->sin6_addr, | |
908 | ntopbuf, INET6_ADDRSTRLEN), | 921 | ntopbuf, INET6_ADDRSTRLEN), | |
@@ -989,55 +1002,48 @@ ra_input(int len, struct nd_router_adver | @@ -989,55 +1002,48 @@ ra_input(int len, struct nd_router_adver | |||
989 | if (mtu && rai->linkmtu && mtu != rai->linkmtu) { | 1002 | if (mtu && rai->linkmtu && mtu != rai->linkmtu) { | |
990 | syslog(LOG_INFO, | 1003 | syslog(LOG_INFO, | |
991 | "<%s> MTU option value inconsistent on %s:" | 1004 | "<%s> MTU option value inconsistent on %s:" | |
992 | " %d from %s, %d from us", | 1005 | " %d from %s, %d from us", | |
993 | __func__, | 1006 | __func__, | |
994 | rai->ifname, mtu, | 1007 | rai->ifname, mtu, | |
995 | inet_ntop(AF_INET6, &from->sin6_addr, | 1008 | inet_ntop(AF_INET6, &from->sin6_addr, | |
996 | ntopbuf, INET6_ADDRSTRLEN), | 1009 | ntopbuf, INET6_ADDRSTRLEN), | |
997 | rai->linkmtu); | 1010 | rai->linkmtu); | |
998 | inconsistent++; | 1011 | inconsistent++; | |
999 | } | 1012 | } | |
1000 | } | 1013 | } | |
1001 | /* Preferred and Valid Lifetimes for prefixes */ | 1014 | /* Preferred and Valid Lifetimes for prefixes */ | |
1002 | { | 1015 | if (ndopts.nd_opts_pi) | |
1003 | struct nd_optlist *optp = ndopts.nd_opts_list; | 1016 | if (prefix_check(ndopts.nd_opts_pi, rai, from)) | |
1004 | 1017 | inconsistent++; | ||
1005 | if (ndopts.nd_opts_pi) { | 1018 | TAILQ_FOREACH(optp, &ndopts.nd_opts_list, next) | |
1006 | if (prefix_check(ndopts.nd_opts_pi, rai, from)) | 1019 | if (prefix_check((struct nd_opt_prefix_info *)optp->opt, | |
1007 | inconsistent++; | 1020 | rai, from)) | |
1008 | } | 1021 | inconsistent++; | |
1009 | while (optp) { | |||
1010 | if (prefix_check((struct nd_opt_prefix_info *)optp->opt, | |||
1011 | rai, from)) | |||
1012 | inconsistent++; | |||
1013 | optp = optp->next; | |||
1014 | } | |||
1015 | } | |||
1016 | 1022 | |||
1017 | if (inconsistent) | 1023 | if (inconsistent) | |
1018 | rai->rainconsistent++; | 1024 | rai->rainconsistent++; | |
1019 | 1025 | |||
1020 | done: | 1026 | done: | |
1021 | free_ndopts(&ndopts); | 1027 | free_ndopts(&ndopts); | |
1022 | return; | 1028 | return; | |
1023 | } | 1029 | } | |
1024 | 1030 | |||
1025 | /* return a non-zero value if the received prefix is inconsitent with ours */ | 1031 | /* return a non-zero value if the received prefix is inconsitent with ours */ | |
1026 | static int | 1032 | static int | |
1027 | prefix_check(struct nd_opt_prefix_info *pinfo, | 1033 | prefix_check(struct nd_opt_prefix_info *pinfo, | |
1028 | struct rainfo *rai, struct sockaddr_in6 *from) | 1034 | struct rainfo *rai, struct sockaddr_in6 *from) | |
1029 | { | 1035 | { | |
1030 | u_int32_t preferred_time, valid_time; | 1036 | uint32_t preferred_time, valid_time; | |
1031 | struct prefix *pp; | 1037 | struct prefix *pp; | |
1032 | int inconsistent = 0; | 1038 | int inconsistent = 0; | |
1033 | char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN]; | 1039 | char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN]; | |
1034 | struct timeval now; | 1040 | struct timeval now; | |
1035 | 1041 | |||
1036 | #if 0 /* impossible */ | 1042 | #if 0 /* impossible */ | |
1037 | if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION) | 1043 | if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION) | |
1038 | return(0); | 1044 | return(0); | |
1039 | #endif | 1045 | #endif | |
1040 | 1046 | |||
1041 | /* | 1047 | /* | |
1042 | * log if the adveritsed prefix has link-local scope(sanity check?) | 1048 | * log if the adveritsed prefix has link-local scope(sanity check?) | |
1043 | */ | 1049 | */ | |
@@ -1146,96 +1152,98 @@ prefix_check(struct nd_opt_prefix_info * | @@ -1146,96 +1152,98 @@ prefix_check(struct nd_opt_prefix_info * | |||
1146 | ntopbuf, INET6_ADDRSTRLEN), | 1152 | ntopbuf, INET6_ADDRSTRLEN), | |
1147 | pp->validlifetime); | 1153 | pp->validlifetime); | |
1148 | inconsistent++; | 1154 | inconsistent++; | |
1149 | } | 1155 | } | |
1150 | 1156 | |||
1151 | return(inconsistent); | 1157 | return(inconsistent); | |
1152 | } | 1158 | } | |
1153 | 1159 | |||
1154 | struct prefix * | 1160 | struct prefix * | |
1155 | find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen) | 1161 | find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen) | |
1156 | { | 1162 | { | |
1157 | struct prefix *pp; | 1163 | struct prefix *pp; | |
1158 | int bytelen, bitlen; | 1164 | int bytelen, bitlen; | |
1159 | u_char bitmask; | 1165 | unsigned char bitmask; | |
1160 | 1166 | |||
1161 | for (pp = rai->prefix.next; pp != &rai->prefix; pp = pp->next) { | 1167 | TAILQ_FOREACH(pp, &rai->prefix, next) { | |
1162 | if (plen != pp->prefixlen) | 1168 | if (plen != pp->prefixlen) | |
1163 | continue; | 1169 | continue; | |
1164 | bytelen = plen / 8; | 1170 | bytelen = plen / 8; | |
1165 | bitlen = plen % 8; | 1171 | bitlen = plen % 8; | |
1166 | bitmask = 0xff << (8 - bitlen); | 1172 | bitmask = 0xff << (8 - bitlen); | |
1167 | if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen)) | 1173 | if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen)) | |
1168 | continue; | 1174 | continue; | |
1169 | if (bitlen == 0 || | 1175 | if (bitlen == 0 || | |
1170 | ((prefix->s6_addr[bytelen] & bitmask) == | 1176 | ((prefix->s6_addr[bytelen] & bitmask) == | |
1171 | (pp->prefix.s6_addr[bytelen] & bitmask))) { | 1177 | (pp->prefix.s6_addr[bytelen] & bitmask))) { | |
1172 | return(pp); | 1178 | return(pp); | |
1173 | } | 1179 | } | |
1174 | } | 1180 | } | |
1175 | 1181 | |||
1176 | return(NULL); | 1182 | return(NULL); | |
1177 | } | 1183 | } | |
1178 | 1184 | |||
1179 | /* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */ | 1185 | /* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */ | |
1180 | int | 1186 | int | |
1181 | prefix_match(struct in6_addr *p0, int plen0, | 1187 | prefix_match(struct in6_addr *p0, int plen0, | |
1182 | struct in6_addr *p1, int plen1) | 1188 | struct in6_addr *p1, int plen1) | |
1183 | { | 1189 | { | |
1184 | int bytelen, bitlen; | 1190 | int bytelen, bitlen; | |
1185 | u_char bitmask; | 1191 | unsigned char bitmask; | |
1186 | 1192 | |||
1187 | if (plen0 < plen1) | 1193 | if (plen0 < plen1) | |
1188 | return(0); | 1194 | return(0); | |
1189 | bytelen = plen1 / 8; | 1195 | bytelen = plen1 / 8; | |
1190 | bitlen = plen1 % 8; | 1196 | bitlen = plen1 % 8; | |
1191 | bitmask = 0xff << (8 - bitlen); | 1197 | bitmask = 0xff << (8 - bitlen); | |
1192 | if (memcmp((void *)p0, (void *)p1, bytelen)) | 1198 | if (memcmp((void *)p0, (void *)p1, bytelen)) | |
1193 | return(0); | 1199 | return(0); | |
1194 | if (bitlen == 0 || | 1200 | if (bitlen == 0 || | |
1195 | ((p0->s6_addr[bytelen] & bitmask) == | 1201 | ((p0->s6_addr[bytelen] & bitmask) == | |
1196 | (p1->s6_addr[bytelen] & bitmask))) { | 1202 | (p1->s6_addr[bytelen] & bitmask))) { | |
1197 | return(1); | 1203 | return(1); | |
1198 | } | 1204 | } | |
1199 | 1205 | |||
1200 | return(0); | 1206 | return(0); | |
1201 | } | 1207 | } | |
1202 | 1208 | |||
1203 | static int | 1209 | static int | |
1204 | nd6_options(struct nd_opt_hdr *hdr, int limit, | 1210 | nd6_options(struct nd_opt_hdr *hdr, int limit, | |
1205 | union nd_opts *ndopts, u_int32_t optflags) | 1211 | union nd_opts *ndopts, uint32_t optflags) | |
1206 | { | 1212 | { | |
1207 | int optlen = 0; | 1213 | int optlen = 0; | |
1208 | 1214 | |||
1209 | for (; limit > 0; limit -= optlen) { | 1215 | for (; limit > 0; limit -= optlen) { | |
1210 | if (limit < sizeof(struct nd_opt_hdr)) { | 1216 | if ((size_t)limit < sizeof(struct nd_opt_hdr)) { | |
1211 | syslog(LOG_INFO, "<%s> short option header", __func__); | 1217 | syslog(LOG_INFO, "<%s> short option header", __func__); | |
1212 | goto bad; | 1218 | goto bad; | |
1213 | } | 1219 | } | |
1214 | 1220 | |||
1215 | hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen); | 1221 | hdr = (struct nd_opt_hdr *)((char *)hdr + optlen); | |
1216 | if (hdr->nd_opt_len == 0) { | 1222 | if (hdr->nd_opt_len == 0) { | |
1217 | syslog(LOG_INFO, | 1223 | syslog(LOG_INFO, | |
1218 | "<%s> bad ND option length(0) (type = %d)", | 1224 | "<%s> bad ND option length(0) (type = %d)", | |
1219 | __func__, hdr->nd_opt_type); | 1225 | __func__, hdr->nd_opt_type); | |
1220 | goto bad; | 1226 | goto bad; | |
1221 | } | 1227 | } | |
1222 | optlen = hdr->nd_opt_len << 3; | 1228 | optlen = hdr->nd_opt_len << 3; | |
1223 | if (optlen > limit) { | 1229 | if (optlen > limit) { | |
1224 | syslog(LOG_INFO, "<%s> short option", __func__); | 1230 | syslog(LOG_INFO, "<%s> short option", __func__); | |
1225 | goto bad; | 1231 | goto bad; | |
1226 | } | 1232 | } | |
1227 | 1233 | |||
1228 | if (hdr->nd_opt_type > ND_OPT_MTU) | 1234 | if (hdr->nd_opt_type > ND_OPT_MTU && | |
1235 | hdr->nd_opt_type != ND_OPT_RDNSS && | |||
1236 | hdr->nd_opt_type != ND_OPT_DNSSL) | |||
1229 | { | 1237 | { | |
1230 | syslog(LOG_INFO, "<%s> unknown ND option(type %d)", | 1238 | syslog(LOG_INFO, "<%s> unknown ND option(type %d)", | |
1231 | __func__, hdr->nd_opt_type); | 1239 | __func__, hdr->nd_opt_type); | |
1232 | continue; | 1240 | continue; | |
1233 | } | 1241 | } | |
1234 | 1242 | |||
1235 | if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) { | 1243 | if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) { | |
1236 | syslog(LOG_INFO, "<%s> unexpected ND option(type %d)", | 1244 | syslog(LOG_INFO, "<%s> unexpected ND option(type %d)", | |
1237 | __func__, hdr->nd_opt_type); | 1245 | __func__, hdr->nd_opt_type); | |
1238 | continue; | 1246 | continue; | |
1239 | } | 1247 | } | |
1240 | 1248 | |||
1241 | /* | 1249 | /* | |
@@ -1268,78 +1276,76 @@ nd6_options(struct nd_opt_hdr *hdr, int | @@ -1268,78 +1276,76 @@ nd6_options(struct nd_opt_hdr *hdr, int | |||
1268 | { | 1276 | { | |
1269 | struct nd_optlist *pfxlist; | 1277 | struct nd_optlist *pfxlist; | |
1270 | 1278 | |||
1271 | if (ndopts->nd_opts_pi == 0) { | 1279 | if (ndopts->nd_opts_pi == 0) { | |
1272 | ndopts->nd_opts_pi = | 1280 | ndopts->nd_opts_pi = | |
1273 | (struct nd_opt_prefix_info *)hdr; | 1281 | (struct nd_opt_prefix_info *)hdr; | |
1274 | continue; | 1282 | continue; | |
1275 | } | 1283 | } | |
1276 | if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) { | 1284 | if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) { | |
1277 | syslog(LOG_ERR, "<%s> can't allocate memory", | 1285 | syslog(LOG_ERR, "<%s> can't allocate memory", | |
1278 | __func__); | 1286 | __func__); | |
1279 | goto bad; | 1287 | goto bad; | |
1280 | } | 1288 | } | |
1281 | pfxlist->next = ndopts->nd_opts_list; | |||
1282 | pfxlist->opt = hdr; | 1289 | pfxlist->opt = hdr; | |
1283 | ndopts->nd_opts_list = pfxlist; | 1290 | TAILQ_INSERT_TAIL(&ndopts->nd_opts_list, pfxlist, next); | |
1284 | 1291 | |||
1285 | break; | 1292 | break; | |
1286 | } | 1293 | } | |
1287 | default: /* impossible */ | 1294 | default: /* impossible */ | |
1288 | break; | 1295 | break; | |
1289 | } | 1296 | } | |
1290 | } | 1297 | } | |
1291 | 1298 | |||
1292 | return(0); | 1299 | return(0); | |
1293 | 1300 | |||
1294 | bad: | 1301 | bad: | |
1295 | free_ndopts(ndopts); | 1302 | free_ndopts(ndopts); | |
1296 | 1303 | |||
1297 | return(-1); | 1304 | return(-1); | |
1298 | } | 1305 | } | |
1299 | 1306 | |||
1300 | static void | 1307 | static void | |
1301 | free_ndopts(union nd_opts *ndopts) | 1308 | free_ndopts(union nd_opts *ndopts) | |
1302 | { | 1309 | { | |
1303 | struct nd_optlist *opt = ndopts->nd_opts_list, *next; | 1310 | struct nd_optlist *opt; | |
1304 | 1311 | |||
1305 | while (opt) { | 1312 | while ((opt = TAILQ_FIRST(&ndopts->nd_opts_list)) != NULL) { | |
1306 | next = opt->next; | 1313 | TAILQ_REMOVE(&ndopts->nd_opts_list, opt, next); | |
1307 | free(opt); | 1314 | free(opt); | |
1308 | opt = next; | |||
1309 | } | 1315 | } | |
1310 | } | 1316 | } | |
1311 | 1317 | |||
1312 | void | 1318 | void | |
1313 | sock_open() | 1319 | sock_open(void) | |
1314 | { | 1320 | { | |
1315 | struct icmp6_filter filt; | 1321 | struct icmp6_filter filt; | |
1316 | struct ipv6_mreq mreq; | 1322 | struct ipv6_mreq mreq; | |
1317 | struct rainfo *ra = ralist; | 1323 | struct rainfo *ra; | |
1318 | int on; | 1324 | int on; | |
1319 | /* XXX: should be max MTU attached to the node */ | 1325 | /* XXX: should be max MTU attached to the node */ | |
1320 | static u_char answer[1500]; | 1326 | static unsigned char answer[1500]; | |
1321 | 1327 | |||
1322 | rcvcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + | 1328 | rcvcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + | |
1323 | CMSG_SPACE(sizeof(int)); | 1329 | CMSG_SPACE(sizeof(int)); | |
1324 | rcvcmsgbuf = (u_char *)malloc(rcvcmsgbuflen); | 1330 | rcvcmsgbuf = malloc(rcvcmsgbuflen); | |
1325 | if (rcvcmsgbuf == NULL) { | 1331 | if (rcvcmsgbuf == NULL) { | |
1326 | syslog(LOG_ERR, "<%s> not enough core", __func__); | 1332 | syslog(LOG_ERR, "<%s> not enough core", __func__); | |
1327 | exit(1); | 1333 | exit(1); | |
1328 | } | 1334 | } | |
1329 | 1335 | |||
1330 | sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + | 1336 | sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + | |
1331 | CMSG_SPACE(sizeof(int)); | 1337 | CMSG_SPACE(sizeof(int)); | |
1332 | sndcmsgbuf = (u_char *)malloc(sndcmsgbuflen); | 1338 | sndcmsgbuf = malloc(sndcmsgbuflen); | |
1333 | if (sndcmsgbuf == NULL) { | 1339 | if (sndcmsgbuf == NULL) { | |
1334 | syslog(LOG_ERR, "<%s> not enough core", __func__); | 1340 | syslog(LOG_ERR, "<%s> not enough core", __func__); | |
1335 | exit(1); | 1341 | exit(1); | |
1336 | } | 1342 | } | |
1337 | 1343 | |||
1338 | if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { | 1344 | if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { | |
1339 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | 1345 | syslog(LOG_ERR, "<%s> socket: %s", __func__, | |
1340 | strerror(errno)); | 1346 | strerror(errno)); | |
1341 | exit(1); | 1347 | exit(1); | |
1342 | } | 1348 | } | |
1343 | 1349 | |||
1344 | /* specify to tell receiving interface */ | 1350 | /* specify to tell receiving interface */ | |
1345 | on = 1; | 1351 | on = 1; | |
@@ -1383,139 +1389,138 @@ sock_open() | @@ -1383,139 +1389,138 @@ sock_open() | |||
1383 | if (accept_rr) | 1389 | if (accept_rr) | |
1384 | ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt); | 1390 | ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt); | |
1385 | if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, | 1391 | if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, | |
1386 | sizeof(filt)) < 0) { | 1392 | sizeof(filt)) < 0) { | |
1387 | syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s", | 1393 | syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s", | |
1388 | __func__, strerror(errno)); | 1394 | __func__, strerror(errno)); | |
1389 | exit(1); | 1395 | exit(1); | |
1390 | } | 1396 | } | |
1391 | 1397 | |||
1392 | /* | 1398 | /* | |
1393 | * join all routers multicast address on each advertising interface. | 1399 | * join all routers multicast address on each advertising interface. | |
1394 | */ | 1400 | */ | |
1395 | if (inet_pton(AF_INET6, ALLROUTERS_LINK, | 1401 | if (inet_pton(AF_INET6, ALLROUTERS_LINK, | |
1396 | &mreq.ipv6mr_multiaddr.s6_addr) | 1402 | mreq.ipv6mr_multiaddr.s6_addr) != 1) | |
1397 | != 1) { | 1403 | { | |
1398 | syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", | 1404 | syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", | |
1399 | __func__); | 1405 | __func__); | |
1400 | exit(1); | 1406 | exit(1); | |
1401 | } | 1407 | } | |
1402 | while (ra) { | 1408 | TAILQ_FOREACH(ra, &ralist, next) { | |
1403 | mreq.ipv6mr_interface = ra->ifindex; | 1409 | mreq.ipv6mr_interface = ra->ifindex; | |
1404 | if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, | 1410 | if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, | |
1405 | sizeof(mreq)) < 0) { | 1411 | sizeof(mreq)) < 0) { | |
1406 | syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s", | 1412 | syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s", | |
1407 | __func__, ra->ifname, strerror(errno)); | 1413 | __func__, ra->ifname, strerror(errno)); | |
1408 | exit(1); | 1414 | exit(1); | |
1409 | } | 1415 | } | |
1410 | ra = ra->next; | |||
1411 | } | 1416 | } | |
1412 | 1417 | |||
1413 | /* | 1418 | /* | |
1414 | * When attending router renumbering, join all-routers site-local | 1419 | * When attending router renumbering, join all-routers site-local | |
1415 | * multicast group. | 1420 | * multicast group. | |
1416 | */ | 1421 | */ | |
1417 | if (accept_rr) { | 1422 | if (accept_rr) { | |
1418 | if (inet_pton(AF_INET6, ALLROUTERS_SITE, | 1423 | if (inet_pton(AF_INET6, ALLROUTERS_SITE, | |
1419 | &in6a_site_allrouters) != 1) { | 1424 | mreq.ipv6mr_multiaddr.s6_addr) != 1) | |
1425 | { | |||
1420 | syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", | 1426 | syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", | |
1421 | __func__); | 1427 | __func__); | |
1422 | exit(1); | 1428 | exit(1); | |
1423 | } | 1429 | } | |
1424 | mreq.ipv6mr_multiaddr = in6a_site_allrouters; | 1430 | ra = TAILQ_FIRST(&ralist); | |
1425 | if (mcastif) { | 1431 | if (mcastif) { | |
1426 | if ((mreq.ipv6mr_interface = if_nametoindex(mcastif)) | 1432 | if ((mreq.ipv6mr_interface = if_nametoindex(mcastif)) | |
1427 | == 0) { | 1433 | == 0) { | |
1428 | syslog(LOG_ERR, | 1434 | syslog(LOG_ERR, | |
1429 | "<%s> invalid interface: %s", | 1435 | "<%s> invalid interface: %s", | |
1430 | __func__, mcastif); | 1436 | __func__, mcastif); | |
1431 | exit(1); | 1437 | exit(1); | |
1432 | } | 1438 | } | |
1433 | } else | 1439 | } else | |
1434 | mreq.ipv6mr_interface = ralist->ifindex; | 1440 | mreq.ipv6mr_interface = ra->ifindex; | |
1435 | if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, | 1441 | if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, | |
1436 | &mreq, sizeof(mreq)) < 0) { | 1442 | &mreq, sizeof(mreq)) < 0) { | |
1437 | syslog(LOG_ERR, | 1443 | syslog(LOG_ERR, | |
1438 | "<%s> IPV6_JOIN_GROUP(site) on %s: %s", | 1444 | "<%s> IPV6_JOIN_GROUP(site) on %s: %s", | |
1439 | __func__, | 1445 | __func__, | |
1440 | mcastif ? mcastif : ralist->ifname, | 1446 | mcastif ? mcastif : ra->ifname, | |
1441 | strerror(errno)); | 1447 | strerror(errno)); | |
1442 | exit(1); | 1448 | exit(1); | |
1443 | } | 1449 | } | |
1444 | } | 1450 | } | |
1445 | 1451 | |||
1446 | /* initialize msghdr for receiving packets */ | 1452 | /* initialize msghdr for receiving packets */ | |
1447 | rcviov[0].iov_base = (caddr_t)answer; | 1453 | rcviov[0].iov_base = answer; | |
1448 | rcviov[0].iov_len = sizeof(answer); | 1454 | rcviov[0].iov_len = sizeof(answer); | |
1449 | rcvmhdr.msg_name = (caddr_t)&rcvfrom; | 1455 | rcvmhdr.msg_name = &rcvfrom; | |
1450 | rcvmhdr.msg_namelen = sizeof(rcvfrom); | 1456 | rcvmhdr.msg_namelen = sizeof(rcvfrom); | |
1451 | rcvmhdr.msg_iov = rcviov; | 1457 | rcvmhdr.msg_iov = rcviov; | |
1452 | rcvmhdr.msg_iovlen = 1; | 1458 | rcvmhdr.msg_iovlen = 1; | |
1453 | rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; | 1459 | rcvmhdr.msg_control = rcvcmsgbuf; | |
1454 | rcvmhdr.msg_controllen = rcvcmsgbuflen; | 1460 | rcvmhdr.msg_controllen = rcvcmsgbuflen; | |
1455 | 1461 | |||
1456 | /* initialize msghdr for sending packets */ | 1462 | /* initialize msghdr for sending packets */ | |
1457 | sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); | 1463 | sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); | |
1458 | sndmhdr.msg_iov = sndiov; | 1464 | sndmhdr.msg_iov = sndiov; | |
1459 | sndmhdr.msg_iovlen = 1; | 1465 | sndmhdr.msg_iovlen = 1; | |
1460 | sndmhdr.msg_control = (caddr_t)sndcmsgbuf; | 1466 | sndmhdr.msg_control = (void *)sndcmsgbuf; | |
1461 | sndmhdr.msg_controllen = sndcmsgbuflen; | 1467 | sndmhdr.msg_controllen = sndcmsgbuflen; | |
1462 | 1468 | |||
1463 | return; | 1469 | return; | |
1464 | } | 1470 | } | |
1465 | 1471 | |||
1466 | /* open a routing socket to watch the routing table */ | 1472 | /* open a routing socket to watch the routing table */ | |
1467 | static void | 1473 | static void | |
1468 | rtsock_open() | 1474 | rtsock_open(void) | |
1469 | { | 1475 | { | |
1470 | if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { | 1476 | if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { | |
1471 | syslog(LOG_ERR, | 1477 | syslog(LOG_ERR, | |
1472 | "<%s> socket: %s", __func__, strerror(errno)); | 1478 | "<%s> socket: %s", __func__, strerror(errno)); | |
1473 | exit(1); | 1479 | exit(1); | |
1474 | } | 1480 | } | |
1475 | } | 1481 | } | |
1476 | 1482 | |||
1477 | struct rainfo * | 1483 | struct rainfo * | |
1478 | if_indextorainfo(int idx) | 1484 | if_indextorainfo(unsigned int idx) | |
1479 | { | 1485 | { | |
1480 | struct rainfo *rai = ralist; | 1486 | struct rainfo *rai; | |
1481 | 1487 | |||
1482 | for (rai = ralist; rai; rai = rai->next) { | 1488 | TAILQ_FOREACH(rai, &ralist, next) { | |
1483 | if (rai->ifindex == idx) | 1489 | if (rai->ifindex == idx) | |
1484 | return(rai); | 1490 | return(rai); | |
1485 | } | 1491 | } | |
1486 | 1492 | |||
1487 | return(NULL); /* search failed */ | 1493 | return(NULL); /* search failed */ | |
1488 | } | 1494 | } | |
1489 | 1495 | |||
1490 | static void | 1496 | static void | |
1491 | ra_output(rainfo) | 1497 | ra_output(struct rainfo *rainfo) | |
1492 | struct rainfo *rainfo; | |||
1493 | { | 1498 | { | |
1494 | int i; | 1499 | int i; | |
1495 | struct cmsghdr *cm; | 1500 | struct cmsghdr *cm; | |
1496 | struct in6_pktinfo *pi; | 1501 | struct in6_pktinfo *pi; | |
1497 | struct soliciter *sol, *nextsol; | 1502 | struct soliciter *sol; | |
1498 | 1503 | |||
1499 | if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) { | 1504 | if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) { | |
1500 | syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA", | 1505 | syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA", | |
1501 | __func__, rainfo->ifname); | 1506 | __func__, rainfo->ifname); | |
1502 | return; | 1507 | return; | |
1503 | } | 1508 | } | |
1504 | 1509 | |||
1505 | make_packet(rainfo); /* XXX: inefficient */ | 1510 | make_packet(rainfo); /* XXX: inefficient */ | |
1506 | 1511 | |||
1507 | sndmhdr.msg_name = (caddr_t)&sin6_allnodes; | 1512 | sndmhdr.msg_name = (void *)&sin6_linklocal_allnodes; | |
1508 | sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data; | 1513 | sndmhdr.msg_iov[0].iov_base = (void *)rainfo->ra_data; | |
1509 | sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen; | 1514 | sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen; | |
1510 | 1515 | |||
1511 | cm = CMSG_FIRSTHDR(&sndmhdr); | 1516 | cm = CMSG_FIRSTHDR(&sndmhdr); | |
1512 | /* specify the outgoing interface */ | 1517 | /* specify the outgoing interface */ | |
1513 | cm->cmsg_level = IPPROTO_IPV6; | 1518 | cm->cmsg_level = IPPROTO_IPV6; | |
1514 | cm->cmsg_type = IPV6_PKTINFO; | 1519 | cm->cmsg_type = IPV6_PKTINFO; | |
1515 | cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | 1520 | cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | |
1516 | pi = (struct in6_pktinfo *)CMSG_DATA(cm); | 1521 | pi = (struct in6_pktinfo *)CMSG_DATA(cm); | |
1517 | memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/ | 1522 | memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/ | |
1518 | pi->ipi6_ifindex = rainfo->ifindex; | 1523 | pi->ipi6_ifindex = rainfo->ifindex; | |
1519 | 1524 | |||
1520 | /* specify the hop limit of the packet */ | 1525 | /* specify the hop limit of the packet */ | |
1521 | { | 1526 | { | |
@@ -1524,59 +1529,55 @@ struct rainfo *rainfo; | @@ -1524,59 +1529,55 @@ struct rainfo *rainfo; | |||
1524 | cm = CMSG_NXTHDR(&sndmhdr, cm); | 1529 | cm = CMSG_NXTHDR(&sndmhdr, cm); | |
1525 | cm->cmsg_level = IPPROTO_IPV6; | 1530 | cm->cmsg_level = IPPROTO_IPV6; | |
1526 | cm->cmsg_type = IPV6_HOPLIMIT; | 1531 | cm->cmsg_type = IPV6_HOPLIMIT; | |
1527 | cm->cmsg_len = CMSG_LEN(sizeof(int)); | 1532 | cm->cmsg_len = CMSG_LEN(sizeof(int)); | |
1528 | memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); | 1533 | memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); | |
1529 | } | 1534 | } | |
1530 | 1535 | |||
1531 | syslog(LOG_DEBUG, | 1536 | syslog(LOG_DEBUG, | |
1532 | "<%s> send RA on %s, # of waitings = %d", | 1537 | "<%s> send RA on %s, # of waitings = %d", | |
1533 | __func__, rainfo->ifname, rainfo->waiting); | 1538 | __func__, rainfo->ifname, rainfo->waiting); | |
1534 | 1539 | |||
1535 | i = sendmsg(sock, &sndmhdr, 0); | 1540 | i = sendmsg(sock, &sndmhdr, 0); | |
1536 | 1541 | |||
1537 | if (i < 0 || i != rainfo->ra_datalen) { | 1542 | if (i < 0 || (size_t)i != rainfo->ra_datalen) { | |
1538 | if (i < 0) { | 1543 | if (i < 0) { | |
1539 | syslog(LOG_ERR, "<%s> sendmsg on %s: %s", | 1544 | syslog(LOG_ERR, "<%s> sendmsg on %s: %s", | |
1540 | __func__, rainfo->ifname, | 1545 | __func__, rainfo->ifname, | |
1541 | strerror(errno)); | 1546 | strerror(errno)); | |
1542 | } | 1547 | } | |
1543 | } | 1548 | } | |
1544 | 1549 | |||
1545 | /* | 1550 | /* | |
1546 | * unicast advertisements | 1551 | * unicast advertisements | |
1547 | * XXX commented out. reason: though spec does not forbit it, unicast | 1552 | * XXX commented out. reason: though spec does not forbit it, unicast | |
1548 | * advert does not really help | 1553 | * advert does not really help | |
1549 | */ | 1554 | */ | |
1550 | for (sol = rainfo->soliciter; sol; sol = nextsol) { | 1555 | while ((sol = TAILQ_FIRST(&rainfo->soliciter)) != NULL) { | |
1551 | nextsol = sol->next; | |||
1552 | ||||
1553 | #if 0 | 1556 | #if 0 | |
1554 | sndmhdr.msg_name = (caddr_t)&sol->addr; | 1557 | sndmhdr.msg_name = (void *)&sol->addr; | |
1555 | i = sendmsg(sock, &sndmhdr, 0); | 1558 | i = sendmsg(sock, &sndmhdr, 0); | |
1556 | if (i < 0 || i != rainfo->ra_datalen) { | 1559 | if (i < 0 || i != rainfo->ra_datalen) { | |
1557 | if (i < 0) { | 1560 | if (i < 0) { | |
1558 | syslog(LOG_ERR, | 1561 | syslog(LOG_ERR, | |
1559 | "<%s> unicast sendmsg on %s: %s", | 1562 | "<%s> unicast sendmsg on %s: %s", | |
1560 | __func__, rainfo->ifname, | 1563 | __func__, rainfo->ifname, | |
1561 | strerror(errno)); | 1564 | strerror(errno)); | |
1562 | } | 1565 | } | |
1563 | } | 1566 | } | |
1564 | #endif | 1567 | #endif | |
1565 | 1568 | TAILQ_REMOVE(&rainfo->soliciter, sol, next); | ||
1566 | sol->next = NULL; | |||
1567 | free(sol); | 1569 | free(sol); | |
1568 | } | 1570 | } | |
1569 | rainfo->soliciter = NULL; | |||
1570 | 1571 | |||
1571 | /* update counter */ | 1572 | /* update counter */ | |
1572 | if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS) | 1573 | if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS) | |
1573 | rainfo->initcounter++; | 1574 | rainfo->initcounter++; | |
1574 | rainfo->raoutput++; | 1575 | rainfo->raoutput++; | |
1575 | 1576 | |||
1576 | /* update timestamp */ | 1577 | /* update timestamp */ | |
1577 | gettimeofday(&rainfo->lastsent, NULL); | 1578 | gettimeofday(&rainfo->lastsent, NULL); | |
1578 | 1579 | |||
1579 | /* reset waiting conter */ | 1580 | /* reset waiting conter */ | |
1580 | rainfo->waiting = 0; | 1581 | rainfo->waiting = 0; | |
1581 | } | 1582 | } | |
1582 | 1583 |
--- src/usr.sbin/rtadvd/rtadvd.conf.5 2009/11/01 15:19:19 1.14
+++ src/usr.sbin/rtadvd/rtadvd.conf.5 2011/12/10 19:14:29 1.15
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | .\" $NetBSD: rtadvd.conf.5,v 1.14 2009/11/01 15:19:19 jakllsch Exp $ | 1 | .\" $NetBSD: rtadvd.conf.5,v 1.15 2011/12/10 19:14:29 roy Exp $ | |
2 | .\" $KAME: rtadvd.conf.5,v 1.50 2005/01/14 05:30:59 jinmei Exp $ | 2 | .\" $KAME: rtadvd.conf.5,v 1.50 2005/01/14 05:30:59 jinmei Exp $ | |
3 | .\" | 3 | .\" | |
4 | .\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 4 | .\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
5 | .\" All rights reserved. | 5 | .\" All rights reserved. | |
6 | .\" | 6 | .\" | |
7 | .\" Redistribution and use in source and binary forms, with or without | 7 | .\" Redistribution and use in source and binary forms, with or without | |
8 | .\" modification, are permitted provided that the following conditions | 8 | .\" modification, are permitted provided that the following conditions | |
9 | .\" are met: | 9 | .\" are met: | |
10 | .\" 1. Redistributions of source code must retain the above copyright | 10 | .\" 1. Redistributions of source code must retain the above copyright | |
11 | .\" notice, this list of conditions and the following disclaimer. | 11 | .\" notice, this list of conditions and the following disclaimer. | |
12 | .\" 2. Redistributions in binary form must reproduce the above copyright | 12 | .\" 2. Redistributions in binary form must reproduce the above copyright | |
13 | .\" notice, this list of conditions and the following disclaimer in the | 13 | .\" notice, this list of conditions and the following disclaimer in the | |
14 | .\" documentation and/or other materials provided with the distribution. | 14 | .\" documentation and/or other materials provided with the distribution. | |
@@ -18,27 +18,27 @@ | @@ -18,27 +18,27 @@ | |||
18 | .\" | 18 | .\" | |
19 | .\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | 19 | .\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
20 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 20 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 21 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 22 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
23 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 23 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 24 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
25 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 25 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 26 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
27 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 27 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
28 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 28 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
29 | .\" SUCH DAMAGE. | 29 | .\" SUCH DAMAGE. | |
30 | .\" | 30 | .\" | |
31 | .Dd November 1, 2009 | 31 | .Dd December 7, 2012 | |
32 | .Dt RTADVD.CONF 5 | 32 | .Dt RTADVD.CONF 5 | |
33 | .Os | 33 | .Os | |
34 | .Sh NAME | 34 | .Sh NAME | |
35 | .Nm rtadvd.conf | 35 | .Nm rtadvd.conf | |
36 | .Nd config file for router advertisement daemon | 36 | .Nd config file for router advertisement daemon | |
37 | .Sh DESCRIPTION | 37 | .Sh DESCRIPTION | |
38 | This file describes how the router advertisement packets must be constructed | 38 | This file describes how the router advertisement packets must be constructed | |
39 | for each of the interfaces. | 39 | for each of the interfaces. | |
40 | .Pp | 40 | .Pp | |
41 | As described in | 41 | As described in | |
42 | .Xr rtadvd 8 , | 42 | .Xr rtadvd 8 , | |
43 | you do not have to set this configuration file up at all, | 43 | you do not have to set this configuration file up at all, | |
44 | unless you need some special configurations. | 44 | unless you need some special configurations. | |
@@ -323,26 +323,86 @@ old version of the program. | @@ -323,26 +323,86 @@ old version of the program. | |||
323 | In the above list, each keyword beginning with | 323 | In the above list, each keyword beginning with | |
324 | .Dq Li rt | 324 | .Dq Li rt | |
325 | could be replaced with the one beginning with | 325 | could be replaced with the one beginning with | |
326 | .Dq Li rtr | 326 | .Dq Li rtr | |
327 | for backward compatibility reason. | 327 | for backward compatibility reason. | |
328 | For example, | 328 | For example, | |
329 | .Cm rtrplen | 329 | .Cm rtrplen | |
330 | is accepted instead of | 330 | is accepted instead of | |
331 | .Cm rtplen . | 331 | .Cm rtplen . | |
332 | However, keywords that start with | 332 | However, keywords that start with | |
333 | .Dq Li rtr | 333 | .Dq Li rtr | |
334 | have basically been obsoleted, and should not be used any more. | 334 | have basically been obsoleted, and should not be used any more. | |
335 | .Pp | 335 | .Pp | |
336 | The following items are for ICMPv6 Recursive DNS Server Option and | |||
337 | DNS Search List Option | |||
338 | .Pq RFC 6106 , | |||
339 | which will be attached to router advertisement header. | |||
340 | These items are optional. | |||
341 | .Bl -tag -width indent | |||
342 | .It Cm \&rdnss | |||
343 | (str) The IPv6 address of one or more recursive DNS servers. | |||
344 | The argument must be inside double quotes. | |||
345 | Multiple DNS servers can be specified in a comma-separated string. | |||
346 | If different lifetimes are needed for different servers, | |||
347 | separate entries can be given by using | |||
348 | .Cm rdnss , | |||
349 | .Cm rdnss0 , | |||
350 | .Cm rdnss1 , | |||
351 | .Cm rdnss2 ... | |||
352 | options with corresponding | |||
353 | .Cm rdnssltime , | |||
354 | .Cm rdnssltime0 , | |||
355 | .Cm rdnssltime1 , | |||
356 | .Cm rdnssltime2 ... | |||
357 | entries. | |||
358 | Note that the maximum number of servers depends on the receiver side. | |||
359 | See also | |||
360 | .Xr resolver 5 | |||
361 | manual page for resolver implementation in | |||
362 | .Fx . | |||
363 | .It Cm \&rdnssltime | |||
364 | The lifetime of the | |||
365 | .Cm rdnss | |||
366 | DNS server entries. | |||
367 | The default value is 3/2 of the interval time. | |||
368 | .It Cm \&dnssl | |||
369 | (str) One or more domain names in a comma-separated string. | |||
370 | These domain names will be used when making DNS queries on a | |||
371 | non-fully-qualified domain name. | |||
372 | If different lifetimes are needed for different domains, separate entries | |||
373 | can be given by using | |||
374 | .Cm dnssl , | |||
375 | .Cm dnssl0 , | |||
376 | .Cm dnssl1 , | |||
377 | .Cm dnssl2 ... | |||
378 | options with corresponding | |||
379 | .Cm dnsslltime , | |||
380 | .Cm dnsslltime0 , | |||
381 | .Cm dnsslltime1 , | |||
382 | .Cm dnsslltime2 ... | |||
383 | entries. | |||
384 | Note that the maximum number of names depends on the receiver side. | |||
385 | See also | |||
386 | .Xr resolver 5 | |||
387 | manual page for resolver implementation in | |||
388 | .Fx . | |||
389 | .It Cm \&dnsslltime | |||
390 | The lifetime of the | |||
391 | .Cm dnssl | |||
392 | DNS search list entries. | |||
393 | The default value is 3/2 of the interval time. | |||
394 | .El | |||
395 | .Pp | |||
336 | You can also refer one line from another by using | 396 | You can also refer one line from another by using | |
337 | .Cm tc | 397 | .Cm tc | |
338 | capability. | 398 | capability. | |
339 | See | 399 | See | |
340 | .Xr termcap 5 | 400 | .Xr termcap 5 | |
341 | for details on the capability. | 401 | for details on the capability. | |
342 | .Sh EXAMPLES | 402 | .Sh EXAMPLES | |
343 | As presented above, all of the advertised parameters have default values | 403 | As presented above, all of the advertised parameters have default values | |
344 | defined in specifications, and hence you usually do not have to set them | 404 | defined in specifications, and hence you usually do not have to set them | |
345 | by hand, unless you need special non-default values. | 405 | by hand, unless you need special non-default values. | |
346 | It can cause interoperability problem if you use an ill-configured | 406 | It can cause interoperability problem if you use an ill-configured | |
347 | parameter. | 407 | parameter. | |
348 | .Pp | 408 | .Pp | |
@@ -359,47 +419,64 @@ ne0:\\ | @@ -359,47 +419,64 @@ ne0:\\ | |||
359 | .Pp | 419 | .Pp | |
360 | The following example manually configures prefixes advertised from the | 420 | The following example manually configures prefixes advertised from the | |
361 | .Li ef0 | 421 | .Li ef0 | |
362 | interface. | 422 | interface. | |
363 | The configuration must be used with the | 423 | The configuration must be used with the | |
364 | .Fl s | 424 | .Fl s | |
365 | option to | 425 | option to | |
366 | .Xr rtadvd 8 . | 426 | .Xr rtadvd 8 . | |
367 | .Bd -literal | 427 | .Bd -literal | |
368 | ef0:\\ | 428 | ef0:\\ | |
369 | :addr="2001:db8:ffff:1000::":prefixlen#64: | 429 | :addr="2001:db8:ffff:1000::":prefixlen#64: | |
370 | .Ed | 430 | .Ed | |
371 | .Pp | 431 | .Pp | |
432 | The following example configures the | |||
433 | .Li wlan0 | |||
434 | interface and adds two DNS servers and a DNS domain search options | |||
435 | using the default option lifetime values. | |||
436 | .Bd -literal -offset | |||
437 | wlan0:\\ | |||
438 | :addr="2001:db8:ffff:1000::":prefixlen#64:\\ | |||
439 | :rdnss="2001:db8:ffff::10,2001:db8:ffff::2:43":\\ | |||
440 | :dnssl="example.com": | |||
441 | .Ed | |||
442 | .Pp | |||
372 | The following example presents the default values in an explicit manner. | 443 | The following example presents the default values in an explicit manner. | |
373 | The configuration is provided just for reference purposes; | 444 | The configuration is provided just for reference purposes; | |
374 | YOU DO NOT NEED TO HAVE IT AT ALL. | 445 | YOU DO NOT NEED TO HAVE IT AT ALL. | |
375 | .Bd -literal | 446 | .Bd -literal | |
376 | default:\\ | 447 | default:\\ | |
377 | :chlim#64:raflags#0:rltime#1800:rtime#0:retrans#0:\\ | 448 | :chlim#64:raflags#0:rltime#1800:rtime#0:retrans#0:\\ | |
378 | :pinfoflags="la":vltime#2592000:pltime#604800:mtu#0: | 449 | :pinfoflags="la":vltime#2592000:pltime#604800:mtu#0: | |
379 | ef0:\\ | 450 | ef0:\\ | |
380 | :addr="2001:db8:ffff:1000::":prefixlen#64:tc=default: | 451 | :addr="2001:db8:ffff:1000::":prefixlen#64:tc=default: | |
381 | .Ed | 452 | .Ed | |
382 | .Sh SEE ALSO | 453 | .Sh SEE ALSO | |
383 | .Xr termcap 5 , | 454 | .Xr termcap 5 , | |
384 | .Xr rtadvd 8 , | 455 | .Xr rtadvd 8 , | |
385 | .Xr rtsol 8 | 456 | .Xr rtsol 8 | |
386 | .Pp | 457 | .Pp | |
387 | Thomas Narten, Erik Nordmark and W. A. Simpson, | 458 | Thomas Narten, Erik Nordmark and W. A. Simpson, | |
388 | .Do | 459 | .Do | |
389 | Neighbor Discovery for IP version 6 (IPv6) | 460 | Neighbor Discovery for IP version 6 (IPv6) | |
390 | .Dc , | 461 | .Dc , | |
391 | RFC 2461 | 462 | RFC 2461 | |
392 | .Pp | 463 | .Pp | |
393 | Richard Draves, | 464 | Richard Draves, | |
394 | .Do | 465 | .Do | |
395 | Default Router Preferences and More-Specific Routes | 466 | Default Router Preferences and More-Specific Routes | |
396 | .Dc , | 467 | .Dc , | |
397 | RFC 4191 | 468 | RFC 4191 | |
469 | .Pp | |||
470 | J. Jeong, S. Park, L. Beloeil, S. Madanapalli | |||
471 | .Do | |||
472 | IPv6 Router Advertisement Options for DNS Configuration | |||
473 | .Dc , | |||
474 | RFC 6106 | |||
398 | .Sh HISTORY | 475 | .Sh HISTORY | |
399 | The | 476 | The | |
400 | .Xr rtadvd 8 | 477 | .Xr rtadvd 8 | |
401 | and the configuration file | 478 | and the configuration file | |
402 | .Nm | 479 | .Nm | |
403 | first appeared in WIDE Hydrangea IPv6 protocol stack kit. | 480 | first appeared in WIDE Hydrangea IPv6 protocol stack kit. | |
404 | .\" .Sh BUGS | 481 | .\" .Sh BUGS | |
405 | .\" (to be written) | 482 | .\" (to be written) |
--- src/usr.sbin/rtadvd/rtadvd.h 2006/03/05 23:47:08 1.10
+++ src/usr.sbin/rtadvd/rtadvd.h 2011/12/10 19:14:29 1.11
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rtadvd.h,v 1.10 2006/03/05 23:47:08 rpaulo Exp $ */ | 1 | /* $NetBSD: rtadvd.h,v 1.11 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: rtadvd.h,v 1.30 2005/10/17 14:40:02 suz Exp $ */ | 2 | /* $KAME: rtadvd.h,v 1.30 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 | |
@@ -23,28 +23,34 @@ | @@ -23,28 +23,34 @@ | |||
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #define ALLNODES "ff02::1" | 33 | #define ALLNODES "ff02::1" | |
34 | #define ALLROUTERS_LINK "ff02::2" | 34 | #define ALLROUTERS_LINK "ff02::2" | |
35 | #define ALLROUTERS_SITE "ff05::2" | 35 | #define ALLROUTERS_SITE "ff05::2" | |
36 | #define ANY "::" | 36 | ||
37 | #define RTSOLLEN 8 | 37 | #define IN6ADDR_SITELOCAL_ALLROUTERS_INIT \ | |
38 | {{{ 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | |||
39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}} | |||
40 | ||||
41 | //extern struct sockaddr_in6 sin6_linklocal_allnodes; | |||
42 | //extern struct sockaddr_in6 sin6_linklocal_allrouters; | |||
43 | extern struct sockaddr_in6 sin6_sitelocal_allrouters; | |||
38 | 44 | |||
39 | /* protocol constants and default values */ | 45 | /* protocol constants and default values */ | |
40 | #define DEF_MAXRTRADVINTERVAL 600 | 46 | #define DEF_MAXRTRADVINTERVAL 600 | |
41 | #define DEF_ADVLINKMTU 0 | 47 | #define DEF_ADVLINKMTU 0 | |
42 | #define DEF_ADVREACHABLETIME 0 | 48 | #define DEF_ADVREACHABLETIME 0 | |
43 | #define DEF_ADVRETRANSTIMER 0 | 49 | #define DEF_ADVRETRANSTIMER 0 | |
44 | #define DEF_ADVCURHOPLIMIT 64 | 50 | #define DEF_ADVCURHOPLIMIT 64 | |
45 | #define DEF_ADVVALIDLIFETIME 2592000 | 51 | #define DEF_ADVVALIDLIFETIME 2592000 | |
46 | #define DEF_ADVPREFERREDLIFETIME 604800 | 52 | #define DEF_ADVPREFERREDLIFETIME 604800 | |
47 | 53 | |||
48 | #define MAXROUTERLIFETIME 9000 | 54 | #define MAXROUTERLIFETIME 9000 | |
49 | #define MIN_MAXINTERVAL 4 | 55 | #define MIN_MAXINTERVAL 4 | |
50 | #define MAX_MAXINTERVAL 1800 | 56 | #define MAX_MAXINTERVAL 1800 | |
@@ -52,110 +58,132 @@ | @@ -52,110 +58,132 @@ | |||
52 | #define MAXREACHABLETIME 3600000 | 58 | #define MAXREACHABLETIME 3600000 | |
53 | 59 | |||
54 | #define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 | 60 | #define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 | |
55 | #define MAX_INITIAL_RTR_ADVERTISEMENTS 3 | 61 | #define MAX_INITIAL_RTR_ADVERTISEMENTS 3 | |
56 | #define MAX_FINAL_RTR_ADVERTISEMENTS 3 | 62 | #define MAX_FINAL_RTR_ADVERTISEMENTS 3 | |
57 | #define MIN_DELAY_BETWEEN_RAS 3 | 63 | #define MIN_DELAY_BETWEEN_RAS 3 | |
58 | #define MAX_RA_DELAY_TIME 500000 /* usec */ | 64 | #define MAX_RA_DELAY_TIME 500000 /* usec */ | |
59 | 65 | |||
60 | #define PREFIX_FROM_KERNEL 1 | 66 | #define PREFIX_FROM_KERNEL 1 | |
61 | #define PREFIX_FROM_CONFIG 2 | 67 | #define PREFIX_FROM_CONFIG 2 | |
62 | #define PREFIX_FROM_DYNAMIC 3 | 68 | #define PREFIX_FROM_DYNAMIC 3 | |
63 | 69 | |||
64 | struct prefix { | 70 | struct prefix { | |
65 | struct prefix *next; /* forward link */ | 71 | TAILQ_ENTRY(prefix) next; | |
66 | struct prefix *prev; /* previous link */ | |||
67 | 72 | |||
68 | struct rainfo *rainfo; /* back pointer to the interface */ | 73 | struct rainfo *rainfo; /* back pointer to the interface */ | |
69 | 74 | |||
70 | struct rtadvd_timer *timer; /* expiration timer. used when a prefix | 75 | struct rtadvd_timer *timer; /* expiration timer. used when a prefix | |
71 | * derived from the kernel is deleted. | 76 | * derived from the kernel is deleted. | |
72 | */ | 77 | */ | |
73 | 78 | |||
74 | u_int32_t validlifetime; /* AdvValidLifetime */ | 79 | uint32_t validlifetime; /* AdvValidLifetime */ | |
75 | long vltimeexpire; /* expiration of vltime; decrement case only */ | 80 | long vltimeexpire; /* expiration of vltime; decrement case only */ | |
76 | u_int32_t preflifetime; /* AdvPreferredLifetime */ | 81 | uint32_t preflifetime; /* AdvPreferredLifetime */ | |
77 | long pltimeexpire; /* expiration of pltime; decrement case only */ | 82 | long pltimeexpire; /* expiration of pltime; decrement case only */ | |
78 | u_int onlinkflg; /* bool: AdvOnLinkFlag */ | 83 | uint16_t onlinkflg; /* bool: AdvOnLinkFlag */ | |
79 | u_int autoconfflg; /* bool: AdvAutonomousFlag */ | 84 | uint16_t autoconfflg; /* bool: AdvAutonomousFlag */ | |
80 | int prefixlen; | 85 | int prefixlen; | |
81 | int origin; /* from kernel or config */ | 86 | int origin; /* from kernel or config */ | |
82 | struct in6_addr prefix; | 87 | struct in6_addr prefix; | |
83 | }; | 88 | }; | |
84 | 89 | |||
85 | #ifdef ROUTEINFO | |||
86 | struct rtinfo { | 90 | struct rtinfo { | |
87 | struct rtinfo *prev; /* previous link */ | 91 | TAILQ_ENTRY(rtinfo) next; | |
88 | struct rtinfo *next; /* forward link */ | |||
89 | 92 | |||
90 | u_int32_t ltime; /* route lifetime */ | 93 | uint32_t ltime; /* route lifetime */ | |
91 | u_int rtpref; /* route preference */ | 94 | uint16_t rtpref; /* route preference */ | |
92 | int prefixlen; | 95 | int prefixlen; | |
93 | struct in6_addr prefix; | 96 | struct in6_addr prefix; | |
94 | }; | 97 | }; | |
95 | #endif | 98 | ||
99 | struct rdnss_addr { | |||
100 | TAILQ_ENTRY(rdnss_addr) next; | |||
101 | ||||
102 | struct in6_addr addr; | |||
103 | }; | |||
104 | ||||
105 | struct rdnss { | |||
106 | TAILQ_ENTRY(rdnss) next; | |||
107 | ||||
108 | TAILQ_HEAD(, rdnss_addr) list; | |||
109 | uint32_t lifetime; | |||
110 | }; | |||
111 | ||||
112 | struct dnssl_domain { | |||
113 | TAILQ_ENTRY(dnssl_domain) next; | |||
114 | ||||
115 | int len; | |||
116 | char domain[256]; | |||
117 | }; | |||
118 | ||||
119 | struct dnssl { | |||
120 | TAILQ_ENTRY(dnssl) next; | |||
121 | ||||
122 | TAILQ_HEAD(, dnssl_domain) list; | |||
123 | uint32_t lifetime; | |||
124 | }; | |||
96 | 125 | |||
97 | struct soliciter { | 126 | struct soliciter { | |
98 | struct soliciter *next; | 127 | TAILQ_ENTRY(soliciter) next; | |
128 | ||||
99 | struct sockaddr_in6 addr; | 129 | struct sockaddr_in6 addr; | |
100 | }; | 130 | }; | |
101 | 131 | |||
102 | struct rainfo { | 132 | struct rainfo { | |
103 | /* pointer for list */ | 133 | TAILQ_ENTRY(rainfo) next; | |
104 | struct rainfo *next; | |||
105 | 134 | |||
106 | /* timer related parameters */ | 135 | /* timer related parameters */ | |
107 | struct rtadvd_timer *timer; | 136 | struct rtadvd_timer *timer; | |
108 | int initcounter; /* counter for the first few advertisements */ | 137 | int initcounter; /* counter for the first few advertisements */ | |
109 | struct timeval lastsent; /* timestamp when the latest RA was sent */ | 138 | struct timeval lastsent; /* timestamp when the latest RA was sent */ | |
110 | int waiting; /* number of RS waiting for RA */ | 139 | int waiting; /* number of RS waiting for RA */ | |
111 | 140 | |||
112 | /* interface information */ | 141 | /* interface information */ | |
113 | int ifindex; | 142 | uint16_t ifindex; | |
114 | int advlinkopt; /* bool: whether include link-layer addr opt */ | 143 | int advlinkopt; /* bool: whether include link-layer addr opt */ | |
115 | struct sockaddr_dl *sdl; | 144 | struct sockaddr_dl *sdl; | |
116 | char ifname[16]; | 145 | char ifname[16]; | |
117 | int phymtu; /* mtu of the physical interface */ | 146 | uint32_t phymtu; /* mtu of the physical interface */ | |
118 | 147 | |||
119 | /* Router configuration variables */ | 148 | /* Router configuration variables */ | |
120 | u_short lifetime; /* AdvDefaultLifetime */ | 149 | uint16_t lifetime; /* AdvDefaultLifetime */ | |
121 | u_int maxinterval; /* MaxRtrAdvInterval */ | 150 | uint16_t maxinterval; /* MaxRtrAdvInterval */ | |
122 | u_int mininterval; /* MinRtrAdvInterval */ | 151 | uint16_t mininterval; /* MinRtrAdvInterval */ | |
123 | int managedflg; /* AdvManagedFlag */ | 152 | int managedflg; /* AdvManagedFlag */ | |
124 | int otherflg; /* AdvOtherConfigFlag */ | 153 | int otherflg; /* AdvOtherConfigFlag */ | |
125 | 154 | |||
126 | int rtpref; /* router preference */ | 155 | int rtpref; /* router preference */ | |
127 | u_int32_t linkmtu; /* AdvLinkMTU */ | 156 | uint32_t linkmtu; /* AdvLinkMTU */ | |
128 | u_int32_t reachabletime; /* AdvReachableTime */ | 157 | uint32_t reachabletime; /* AdvReachableTime */ | |
129 | u_int32_t retranstimer; /* AdvRetransTimer */ | 158 | uint32_t retranstimer; /* AdvRetransTimer */ | |
130 | u_int hoplimit; /* AdvCurHopLimit */ | 159 | uint16_t hoplimit; /* AdvCurHopLimit */ | |
131 | struct prefix prefix; /* AdvPrefixList(link head) */ | 160 | TAILQ_HEAD(, prefix) prefix; /* AdvPrefixList(link head) */ | |
132 | int pfxs; /* number of prefixes */ | 161 | int pfxs; | |
133 | long clockskew; /* used for consisitency check of lifetimes */ | 162 | uint16_t clockskew;/* used for consisitency check of lifetimes */ | |
134 | 163 | |||
135 | #ifdef ROUTEINFO | 164 | TAILQ_HEAD(, rtinfo) route; | |
136 | struct rtinfo route; /* route information option (link head) */ | 165 | TAILQ_HEAD(, rdnss) rdnss; /* RDNSS list */ | |
137 | int routes; /* number of route information options */ | 166 | TAILQ_HEAD(, dnssl) dnssl; /* DNS Search List */ | |
138 | #endif | |||
139 | 167 | |||
140 | /* actual RA packet data and its length */ | 168 | /* actual RA packet data and its length */ | |
141 | size_t ra_datalen; | 169 | size_t ra_datalen; | |
142 | u_char *ra_data; | 170 | char *ra_data; | |
143 | 171 | |||
144 | /* statistics */ | 172 | /* statistics */ | |
145 | u_quad_t raoutput; /* number of RAs sent */ | 173 | uint64_t raoutput; /* number of RAs sent */ | |
146 | u_quad_t rainput; /* number of RAs received */ | 174 | uint64_t rainput; /* number of RAs received */ | |
147 | u_quad_t rainconsistent; /* number of RAs inconsistent with ours */ | 175 | uint64_t rainconsistent; /* number of RAs inconsistent with ours */ | |
148 | u_quad_t rsinput; /* number of RSs received */ | 176 | uint64_t rsinput; /* number of RSs received */ | |
149 | 177 | |||
150 | /* info about soliciter */ | 178 | /* info about soliciter */ | |
151 | struct soliciter *soliciter; /* recent solication source */ | 179 | TAILQ_HEAD(, soliciter) soliciter; /* recent solication source */ | |
152 | }; | 180 | }; | |
153 | 181 | |||
154 | struct rtadvd_timer *ra_timeout __P((void *)); | 182 | extern TAILQ_HEAD(ralist_head_t, rainfo) ralist; | |
155 | void ra_timer_update __P((void *, struct timeval *)); | |||
156 | 183 | |||
157 | int prefix_match __P((struct in6_addr *, int, struct in6_addr *, int)); | 184 | struct rtadvd_timer *ra_timeout(void *); | |
158 | struct rainfo *if_indextorainfo __P((int)); | 185 | void ra_timer_update(void *, struct timeval *); | |
159 | struct prefix *find_prefix __P((struct rainfo *, struct in6_addr *, int)); | |||
160 | 186 | |||
161 | extern struct in6_addr in6a_site_allrouters; | 187 | int prefix_match(struct in6_addr *, int, struct in6_addr *, int); | |
188 | struct rainfo *if_indextorainfo(unsigned int); | |||
189 | struct prefix *find_prefix(struct rainfo *, struct in6_addr *, int); |
--- src/usr.sbin/rtadvd/timer.c 2006/03/05 23:47:08 1.9
+++ src/usr.sbin/rtadvd/timer.c 2011/12/10 19:14:29 1.10
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: timer.c,v 1.9 2006/03/05 23:47:08 rpaulo Exp $ */ | 1 | /* $NetBSD: timer.c,v 1.10 2011/12/10 19:14:29 roy Exp $ */ | |
2 | /* $KAME: timer.c,v 1.11 2005/04/14 06:22:35 suz Exp $ */ | 2 | /* $KAME: timer.c,v 1.11 2005/04/14 06:22:35 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 | |
@@ -20,148 +20,147 @@ | @@ -20,148 +20,147 @@ | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | 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 | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/queue.h> | |||
33 | #include <sys/time.h> | 34 | #include <sys/time.h> | |
34 | 35 | |||
35 | #include <unistd.h> | 36 | #include <unistd.h> | |
36 | #include <syslog.h> | 37 | #include <syslog.h> | |
37 | #include <stdlib.h> | 38 | #include <stdlib.h> | |
38 | #include <string.h> | 39 | #include <string.h> | |
39 | #include <search.h> | 40 | #include <search.h> | |
40 | #include "timer.h" | 41 | #include "timer.h" | |
41 | 42 | |||
42 | static struct rtadvd_timer timer_head; | 43 | struct rtadvd_timer_head_t ra_timer = TAILQ_HEAD_INITIALIZER(ra_timer); | |
43 | 44 | |||
44 | #define MILLION 1000000 | 45 | #define MILLION 1000000 | |
45 | #define TIMEVAL_EQUAL(t1,t2) ((t1)->tv_sec == (t2)->tv_sec &&\ | 46 | #define TIMEVAL_EQUAL(t1,t2) ((t1)->tv_sec == (t2)->tv_sec &&\ | |
46 | (t1)->tv_usec == (t2)->tv_usec) | 47 | (t1)->tv_usec == (t2)->tv_usec) | |
47 | 48 | |||
48 | static struct timeval tm_max = {0x7fffffff, 0x7fffffff}; | 49 | static struct timeval tm_limit = {0x7fffffff, 0x7fffffff}; | |
50 | static struct timeval tm_max; | |||
49 | 51 | |||
50 | void | 52 | void | |
51 | rtadvd_timer_init() | 53 | rtadvd_timer_init(void) | |
52 | { | 54 | { | |
53 | memset(&timer_head, 0, sizeof(timer_head)); | |||
54 | 55 | |||
55 | timer_head.next = timer_head.prev = &timer_head; | 56 | TAILQ_INIT(&ra_timer); | |
56 | timer_head.tm = tm_max; | 57 | tm_max = tm_limit; | |
57 | } | 58 | } | |
58 | 59 | |||
59 | struct rtadvd_timer * | 60 | struct rtadvd_timer * | |
60 | rtadvd_add_timer(struct rtadvd_timer *(*timeout) __P((void *)), | 61 | rtadvd_add_timer(struct rtadvd_timer *(*timeout) (void *), | |
61 | void (*update) __P((void *, struct timeval *)), | 62 | void (*update) (void *, struct timeval *), | |
62 | void *timeodata, void *updatedata) | 63 | void *timeodata, void *updatedata) | |
63 | { | 64 | { | |
64 | struct rtadvd_timer *newtimer; | 65 | struct rtadvd_timer *newtimer; | |
65 | 66 | |||
66 | if ((newtimer = malloc(sizeof(*newtimer))) == NULL) { | 67 | if ((newtimer = malloc(sizeof(*newtimer))) == NULL) { | |
67 | syslog(LOG_ERR, | 68 | syslog(LOG_ERR, | |
68 | "<%s> can't allocate memory", __func__); | 69 | "<%s> can't allocate memory", __func__); | |
69 | exit(1); | 70 | exit(1); | |
70 | } | 71 | } | |
71 | 72 | |||
72 | memset(newtimer, 0, sizeof(*newtimer)); | 73 | memset(newtimer, 0, sizeof(*newtimer)); | |
73 | 74 | |||
74 | if (timeout == NULL) { | 75 | if (timeout == NULL) { | |
75 | syslog(LOG_ERR, | 76 | syslog(LOG_ERR, | |
76 | "<%s> timeout function unspecified", __func__); | 77 | "<%s> timeout function unspecified", __func__); | |
77 | exit(1); | 78 | exit(1); | |
78 | } | 79 | } | |
79 | newtimer->expire = timeout; | 80 | newtimer->expire = timeout; | |
80 | newtimer->update = update; | 81 | newtimer->update = update; | |
81 | newtimer->expire_data = timeodata; | 82 | newtimer->expire_data = timeodata; | |
82 | newtimer->update_data = updatedata; | 83 | newtimer->update_data = updatedata; | |
83 | newtimer->tm = tm_max; | 84 | newtimer->tm = tm_max; | |
84 | 85 | |||
85 | /* link into chain */ | 86 | /* link into chain */ | |
86 | insque(newtimer, &timer_head); | 87 | TAILQ_INSERT_TAIL(&ra_timer, newtimer, next); | |
87 | 88 | |||
88 | return(newtimer); | 89 | return(newtimer); | |
89 | } | 90 | } | |
90 | 91 | |||
91 | void | 92 | void | |
92 | rtadvd_remove_timer(struct rtadvd_timer **timer) | 93 | rtadvd_remove_timer(struct rtadvd_timer **timer) | |
93 | { | 94 | { | |
94 | remque(*timer); | 95 | ||
96 | TAILQ_REMOVE(&ra_timer, *timer, next); | |||
95 | free(*timer); | 97 | free(*timer); | |
96 | *timer = NULL; | 98 | *timer = NULL; | |
97 | } | 99 | } | |
98 | 100 | |||
99 | void | 101 | void | |
100 | rtadvd_set_timer(struct timeval *tm, struct rtadvd_timer *timer) | 102 | rtadvd_set_timer(struct timeval *tm, struct rtadvd_timer *timer) | |
101 | { | 103 | { | |
102 | struct timeval now; | 104 | struct timeval now; | |
103 | 105 | |||
104 | /* reset the timer */ | 106 | /* reset the timer */ | |
105 | gettimeofday(&now, NULL); | 107 | gettimeofday(&now, NULL); | |
106 | 108 | |||
107 | TIMEVAL_ADD(&now, tm, &timer->tm); | 109 | TIMEVAL_ADD(&now, tm, &timer->tm); | |
108 | 110 | |||
109 | /* update the next expiration time */ | 111 | /* update the next expiration time */ | |
110 | if (TIMEVAL_LT(timer->tm, timer_head.tm)) | 112 | if (TIMEVAL_LT(timer->tm, tm_max)) | |
111 | timer_head.tm = timer->tm; | 113 | tm_max = timer->tm; | |
112 | 114 | |||
113 | return; | 115 | return; | |
114 | } | 116 | } | |
115 | 117 | |||
116 | /* | 118 | /* | |
117 | * Check expiration for each timer. If a timer expires, | 119 | * Check expiration for each timer. If a timer expires, | |
118 | * call the expire function for the timer and update the timer. | 120 | * call the expire function for the timer and update the timer. | |
119 | * Return the next interval for select() call. | 121 | * Return the next interval for select() call. | |
120 | */ | 122 | */ | |
121 | struct timeval * | 123 | struct timeval * | |
122 | rtadvd_check_timer() | 124 | rtadvd_check_timer(void) | |
123 | { | 125 | { | |
124 | static struct timeval returnval; | 126 | static struct timeval returnval; | |
125 | struct timeval now; | 127 | struct timeval now; | |
126 | struct rtadvd_timer *tm = timer_head.next, *tm_next; | 128 | struct rtadvd_timer *tm; | |
127 | 129 | |||
128 | gettimeofday(&now, NULL); | 130 | gettimeofday(&now, NULL); | |
131 | tm_max = tm_limit; | |||
129 | 132 | |||
130 | timer_head.tm = tm_max; | 133 | TAILQ_FOREACH(tm, &ra_timer, next) { | |
131 | ||||
132 | for (tm = timer_head.next; tm != &timer_head; tm = tm_next) { | |||
133 | tm_next = tm->next; | |||
134 | ||||
135 | if (TIMEVAL_LEQ(tm->tm, now)) { | 134 | if (TIMEVAL_LEQ(tm->tm, now)) { | |
136 | if ((*tm->expire)(tm->expire_data) == NULL) | 135 | if ((*tm->expire)(tm->expire_data) == NULL) | |
137 | continue; /* the timer was removed */ | 136 | continue; /* the timer was removed */ | |
138 | if (tm->update) | 137 | if (tm->update) | |
139 | (*tm->update)(tm->update_data, &tm->tm); | 138 | (*tm->update)(tm->update_data, &tm->tm); | |
140 | TIMEVAL_ADD(&tm->tm, &now, &tm->tm); | 139 | TIMEVAL_ADD(&tm->tm, &now, &tm->tm); | |
141 | } | 140 | } | |
142 | 141 | |||
143 | if (TIMEVAL_LT(tm->tm, timer_head.tm)) | 142 | if (TIMEVAL_LT(tm->tm, tm_max)) | |
144 | timer_head.tm = tm->tm; | 143 | tm_max = tm->tm; | |
145 | } | 144 | } | |
146 | 145 | |||
147 | if (TIMEVAL_EQUAL(&tm_max, &timer_head.tm)) { | 146 | if (TIMEVAL_EQUAL(&tm_max, &tm_limit)) { | |
148 | /* no need to timeout */ | 147 | /* no need to timeout */ | |
149 | return(NULL); | 148 | return(NULL); | |
150 | } else if (TIMEVAL_LT(timer_head.tm, now)) { | 149 | } else if (TIMEVAL_LT(tm_max, now)) { | |
151 | /* this may occur when the interval is too small */ | 150 | /* this may occur when the interval is too small */ | |
152 | returnval.tv_sec = returnval.tv_usec = 0; | 151 | returnval.tv_sec = returnval.tv_usec = 0; | |
153 | } else | 152 | } else | |
154 | TIMEVAL_SUB(&timer_head.tm, &now, &returnval); | 153 | TIMEVAL_SUB(&tm_max, &now, &returnval); | |
155 | return(&returnval); | 154 | return(&returnval); | |
156 | } | 155 | } | |
157 | 156 | |||
158 | struct timeval * | 157 | struct timeval * | |
159 | rtadvd_timer_rest(struct rtadvd_timer *timer) | 158 | rtadvd_timer_rest(struct rtadvd_timer *timer) | |
160 | { | 159 | { | |
161 | static struct timeval returnval, now; | 160 | static struct timeval returnval, now; | |
162 | 161 | |||
163 | gettimeofday(&now, NULL); | 162 | gettimeofday(&now, NULL); | |
164 | if (TIMEVAL_LEQ(timer->tm, now)) { | 163 | if (TIMEVAL_LEQ(timer->tm, now)) { | |
165 | syslog(LOG_DEBUG, | 164 | syslog(LOG_DEBUG, | |
166 | "<%s> a timer must be expired, but not yet", | 165 | "<%s> a timer must be expired, but not yet", | |
167 | __func__); | 166 | __func__); |