Deleted Added
full compact
rtadvd.c (71333) rtadvd.c (78064)
1/* $FreeBSD: head/usr.sbin/rtadvd/rtadvd.c 71333 2001-01-21 15:25:46Z itojun $ */
2/* $KAME: rtadvd.c,v 1.30 2000/06/22 20:16:12 itojun Exp $ */
1/* $FreeBSD: head/usr.sbin/rtadvd/rtadvd.c 78064 2001-06-11 12:39:29Z ume $ */
2/* $KAME: rtadvd.c,v 1.50 2001/02/04 06:15:15 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:

--- 18 unchanged lines hidden (view full) ---

29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/socket.h>
35#include <sys/uio.h>
36#include <sys/time.h>
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:

--- 18 unchanged lines hidden (view full) ---

29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/socket.h>
35#include <sys/uio.h>
36#include <sys/time.h>
37#include <sys/queue.h>
37
38#include <net/if.h>
39#include <net/route.h>
40#include <net/if_dl.h>
41#include <netinet/in.h>
42#include <netinet/ip6.h>
43#include <netinet6/ip6_var.h>
44#include <netinet/icmp6.h>

--- 18 unchanged lines hidden (view full) ---

63#include "dump.h"
64
65struct msghdr rcvmhdr;
66static u_char *rcvcmsgbuf;
67static size_t rcvcmsgbuflen;
68static u_char *sndcmsgbuf = NULL;
69static size_t sndcmsgbuflen;
70static int do_dump;
38
39#include <net/if.h>
40#include <net/route.h>
41#include <net/if_dl.h>
42#include <netinet/in.h>
43#include <netinet/ip6.h>
44#include <netinet6/ip6_var.h>
45#include <netinet/icmp6.h>

--- 18 unchanged lines hidden (view full) ---

64#include "dump.h"
65
66struct msghdr rcvmhdr;
67static u_char *rcvcmsgbuf;
68static size_t rcvcmsgbuflen;
69static u_char *sndcmsgbuf = NULL;
70static size_t sndcmsgbuflen;
71static int do_dump;
72static int do_die;
71struct msghdr sndmhdr;
72struct iovec rcviov[2];
73struct iovec sndiov[2];
74struct sockaddr_in6 from;
75struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
73struct msghdr sndmhdr;
74struct iovec rcviov[2];
75struct iovec sndiov[2];
76struct sockaddr_in6 from;
77struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
78struct in6_addr in6a_site_allrouters;
76static char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX: should be configurable */
77static char *pidfilename = "/var/run/rtadvd.pid"; /* should be configurable */
79static char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX: should be configurable */
80static char *pidfilename = "/var/run/rtadvd.pid"; /* should be configurable */
78int sock, rtsock;
81static char *mcastif;
82int sock;
83int rtsock = -1;
79#ifdef MIP6
80int mobileip6 = 0;
81#endif
82int accept_rr = 0;
83int dflag = 0, sflag = 0;
84
85u_char *conffile = NULL;
86

--- 28 unchanged lines hidden (view full) ---

115#define NDOPT_FLAG_MTU 0x10
116
117u_int32_t ndopt_flags[] = {
118 0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR,
119 NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU
120};
121
122int main __P((int, char *[]));
84#ifdef MIP6
85int mobileip6 = 0;
86#endif
87int accept_rr = 0;
88int dflag = 0, sflag = 0;
89
90u_char *conffile = NULL;
91

--- 28 unchanged lines hidden (view full) ---

120#define NDOPT_FLAG_MTU 0x10
121
122u_int32_t ndopt_flags[] = {
123 0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR,
124 NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU
125};
126
127int main __P((int, char *[]));
123static void die __P((int));
128static void set_die __P((int));
129static void die __P((void));
124static void sock_open __P((void));
125static void rtsock_open __P((void));
126static void rtadvd_input __P((void));
127static void rs_input __P((int, struct nd_router_solicit *,
128 struct in6_pktinfo *, struct sockaddr_in6 *));
129static void ra_input __P((int, struct nd_router_advert *,
130 struct in6_pktinfo *, struct sockaddr_in6 *));
131static int prefix_check __P((struct nd_opt_prefix_info *, struct rainfo *,
132 struct sockaddr_in6 *));
133static int nd6_options __P((struct nd_opt_hdr *, int,
134 union nd_opts *, u_int32_t));
135static void free_ndopts __P((union nd_opts *));
130static void sock_open __P((void));
131static void rtsock_open __P((void));
132static void rtadvd_input __P((void));
133static void rs_input __P((int, struct nd_router_solicit *,
134 struct in6_pktinfo *, struct sockaddr_in6 *));
135static void ra_input __P((int, struct nd_router_advert *,
136 struct in6_pktinfo *, struct sockaddr_in6 *));
137static int prefix_check __P((struct nd_opt_prefix_info *, struct rainfo *,
138 struct sockaddr_in6 *));
139static int nd6_options __P((struct nd_opt_hdr *, int,
140 union nd_opts *, u_int32_t));
141static void free_ndopts __P((union nd_opts *));
136static struct rainfo *if_indextorainfo __P((int));
137static void ra_output __P((struct rainfo *));
138static void rtmsg_input __P((void));
139static void rtadvd_set_dump_file __P((void));
140
141struct prefix *find_prefix __P((struct rainfo *, struct in6_addr *, int));
142
143int
144main(argc, argv)

--- 7 unchanged lines hidden (view full) ---

152 int fflag = 0;
153 FILE *pidfp;
154 pid_t pid;
155
156 openlog("rtadvd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
157
158 /* get command line options and arguments */
159#ifdef MIP6
142static void ra_output __P((struct rainfo *));
143static void rtmsg_input __P((void));
144static void rtadvd_set_dump_file __P((void));
145
146struct prefix *find_prefix __P((struct rainfo *, struct in6_addr *, int));
147
148int
149main(argc, argv)

--- 7 unchanged lines hidden (view full) ---

157 int fflag = 0;
158 FILE *pidfp;
159 pid_t pid;
160
161 openlog("rtadvd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
162
163 /* get command line options and arguments */
164#ifdef MIP6
160#define OPTIONS "c:dDfmRs"
165#define OPTIONS "c:dDfM:mRs"
161#else
166#else
162#define OPTIONS "c:dDfRs"
167#define OPTIONS "c:dDfM:Rs"
163#endif
164 while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
165#undef OPTIONS
166 switch(ch) {
167 case 'c':
168 conffile = optarg;
169 break;
170 case 'd':
171 dflag = 1;
172 break;
173 case 'D':
174 dflag = 2;
175 break;
176 case 'f':
177 fflag = 1;
178 break;
168#endif
169 while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
170#undef OPTIONS
171 switch(ch) {
172 case 'c':
173 conffile = optarg;
174 break;
175 case 'd':
176 dflag = 1;
177 break;
178 case 'D':
179 dflag = 2;
180 break;
181 case 'f':
182 fflag = 1;
183 break;
184 case 'M':
185 mcastif = optarg;
186 break;
179#ifdef MIP6
180 case 'm':
181 mobileip6 = 1;
182 break;
183#endif
184 case 'R':
187#ifdef MIP6
188 case 'm':
189 mobileip6 = 1;
190 break;
191#endif
192 case 'R':
185 accept_rr = 1;
193 fprintf(stderr, "rtadvd: "
194 "the -R option is currently ignored.\n");
195 /* accept_rr = 1; */
196 /* run anyway... */
186 break;
187 case 's':
188 sflag = 1;
189 break;
190 }
191 }
192 argc -= optind;
193 argv += optind;
194 if (argc == 0) {
195 fprintf(stderr,
196#ifdef MIP6
197 break;
198 case 's':
199 sflag = 1;
200 break;
201 }
202 }
203 argc -= optind;
204 argv += optind;
205 if (argc == 0) {
206 fprintf(stderr,
207#ifdef MIP6
197 "usage: rtadvd [-dDfmRs] [-c conffile] "
208 "usage: rtadvd [-dDfMmRs] [-c conffile] "
198#else
209#else
199 "usage: rtadvd [-dDfRs] [-c conffile] "
210 "usage: rtadvd [-dDfMRs] [-c conffile] "
200#endif
201 "interfaces...\n");
202 exit(1);
203 }
204
205 /* set log level */
206 if (dflag == 0)
207 (void)setlogmask(LOG_UPTO(LOG_ERR));

--- 30 unchanged lines hidden (view full) ---

238 else {
239 fprintf(pidfp, "%d\n", pid);
240 fclose(pidfp);
241 }
242
243 FD_ZERO(&fdset);
244 FD_SET(sock, &fdset);
245 maxfd = sock;
211#endif
212 "interfaces...\n");
213 exit(1);
214 }
215
216 /* set log level */
217 if (dflag == 0)
218 (void)setlogmask(LOG_UPTO(LOG_ERR));

--- 30 unchanged lines hidden (view full) ---

249 else {
250 fprintf(pidfp, "%d\n", pid);
251 fclose(pidfp);
252 }
253
254 FD_ZERO(&fdset);
255 FD_SET(sock, &fdset);
256 maxfd = sock;
246 rtsock_open();
247 FD_SET(rtsock, &fdset);
248 if (rtsock > sock)
257 if (sflag == 0) {
258 rtsock_open();
259 FD_SET(rtsock, &fdset);
260 if (rtsock > sock)
249 maxfd = rtsock;
261 maxfd = rtsock;
262 } else
263 rtsock = -1;
250
264
251 signal(SIGTERM, (void *)die);
265 signal(SIGTERM, (void *)set_die);
252 signal(SIGUSR1, (void *)rtadvd_set_dump_file);
253
254 while (1) {
255 struct fd_set select_fd = fdset; /* reinitialize */
256
257 if (do_dump) { /* SIGUSR1 */
258 do_dump = 0;
259 rtadvd_dump_file(dumpfilename);
260 }
261
266 signal(SIGUSR1, (void *)rtadvd_set_dump_file);
267
268 while (1) {
269 struct fd_set select_fd = fdset; /* reinitialize */
270
271 if (do_dump) { /* SIGUSR1 */
272 do_dump = 0;
273 rtadvd_dump_file(dumpfilename);
274 }
275
276 if (do_die) {
277 die();
278 /*NOTREACHED*/
279 }
280
262 /* timer expiration check and reset the timer */
263 timeout = rtadvd_check_timer();
264
265 if (timeout != NULL) {
266 syslog(LOG_DEBUG,
267 "<%s> set timer to %ld:%ld. waiting for "
268 "inputs or timeout",
269 __FUNCTION__,

--- 10 unchanged lines hidden (view full) ---

280 /* EINTR would occur upon SIGUSR1 for status dump */
281 if (errno != EINTR)
282 syslog(LOG_ERR, "<%s> select: %s",
283 __FUNCTION__, strerror(errno));
284 continue;
285 }
286 if (i == 0) /* timeout */
287 continue;
281 /* timer expiration check and reset the timer */
282 timeout = rtadvd_check_timer();
283
284 if (timeout != NULL) {
285 syslog(LOG_DEBUG,
286 "<%s> set timer to %ld:%ld. waiting for "
287 "inputs or timeout",
288 __FUNCTION__,

--- 10 unchanged lines hidden (view full) ---

299 /* EINTR would occur upon SIGUSR1 for status dump */
300 if (errno != EINTR)
301 syslog(LOG_ERR, "<%s> select: %s",
302 __FUNCTION__, strerror(errno));
303 continue;
304 }
305 if (i == 0) /* timeout */
306 continue;
288 if (sflag == 0 && FD_ISSET(rtsock, &select_fd))
307 if (rtsock != -1 && FD_ISSET(rtsock, &select_fd))
289 rtmsg_input();
290 if (FD_ISSET(sock, &select_fd))
291 rtadvd_input();
292 }
293 exit(0); /* NOTREACHED */
294}
295
296static void
297rtadvd_set_dump_file()
298{
299 do_dump = 1;
300}
301
302static void
308 rtmsg_input();
309 if (FD_ISSET(sock, &select_fd))
310 rtadvd_input();
311 }
312 exit(0); /* NOTREACHED */
313}
314
315static void
316rtadvd_set_dump_file()
317{
318 do_dump = 1;
319}
320
321static void
303die(sig)
322set_die(sig)
304 int sig;
305{
323 int sig;
324{
325 do_die = 1;
326}
327
328static void
329die()
330{
306 struct rainfo *ra;
307 int i;
308 const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
309
310 if (dflag > 1) {
311 syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n",
312 __FUNCTION__);
313 }

--- 12 unchanged lines hidden (view full) ---

326}
327
328static void
329rtmsg_input()
330{
331 int n, type, ifindex = 0, plen;
332 size_t len;
333 char msg[2048], *next, *lim;
331 struct rainfo *ra;
332 int i;
333 const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
334
335 if (dflag > 1) {
336 syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n",
337 __FUNCTION__);
338 }

--- 12 unchanged lines hidden (view full) ---

351}
352
353static void
354rtmsg_input()
355{
356 int n, type, ifindex = 0, plen;
357 size_t len;
358 char msg[2048], *next, *lim;
334 u_char ifname[16];
359 u_char ifname[IF_NAMESIZE];
335 struct prefix *prefix;
336 struct rainfo *rai;
337 struct in6_addr *addr;
338 char addrbuf[INET6_ADDRSTRLEN];
339
360 struct prefix *prefix;
361 struct rainfo *rai;
362 struct in6_addr *addr;
363 char addrbuf[INET6_ADDRSTRLEN];
364
340 n = read(rtsock, msg, 2048);
365 n = read(rtsock, msg, sizeof(msg));
341 if (dflag > 1) {
342 syslog(LOG_DEBUG,
343 "<%s> received a routing message "
344 "(type = %d, len = %d)",
345 __FUNCTION__,
346 rtmsg_type(msg), n);
347 }
348 if (n > rtmsg_len(msg)) {

--- 522 unchanged lines hidden (view full) ---

871 inet_ntop(AF_INET6, &from->sin6_addr,
872 ntopbuf, INET6_ADDRSTRLEN),
873 if_indextoname(pi->ipi6_ifindex, ifnamebuf));
874
875 /* ND option check */
876 memset(&ndopts, 0, sizeof(ndopts));
877 if (nd6_options((struct nd_opt_hdr *)(ra + 1),
878 len - sizeof(struct nd_router_advert),
366 if (dflag > 1) {
367 syslog(LOG_DEBUG,
368 "<%s> received a routing message "
369 "(type = %d, len = %d)",
370 __FUNCTION__,
371 rtmsg_type(msg), n);
372 }
373 if (n > rtmsg_len(msg)) {

--- 522 unchanged lines hidden (view full) ---

896 inet_ntop(AF_INET6, &from->sin6_addr,
897 ntopbuf, INET6_ADDRSTRLEN),
898 if_indextoname(pi->ipi6_ifindex, ifnamebuf));
899
900 /* ND option check */
901 memset(&ndopts, 0, sizeof(ndopts));
902 if (nd6_options((struct nd_opt_hdr *)(ra + 1),
903 len - sizeof(struct nd_router_advert),
879 &ndopts,
880 NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
904 &ndopts, NDOPT_FLAG_SRCLINKADDR |
905 NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
881 syslog(LOG_ERR,
882 "<%s> ND option check failed for an RA from %s on %s",
883 __FUNCTION__,
884 inet_ntop(AF_INET6, &from->sin6_addr,
885 ntopbuf, INET6_ADDRSTRLEN),
886 if_indextoname(pi->ipi6_ifindex, ifnamebuf));
887 return;
888 }

--- 11 unchanged lines hidden (view full) ---

900 if_indextoname(pi->ipi6_ifindex, ifnamebuf));
901 goto done;
902 }
903 rai->rainput++; /* increment statistics */
904
905 /* Cur Hop Limit value */
906 if (ra->nd_ra_curhoplimit && rai->hoplimit &&
907 ra->nd_ra_curhoplimit != rai->hoplimit) {
906 syslog(LOG_ERR,
907 "<%s> ND option check failed for an RA from %s on %s",
908 __FUNCTION__,
909 inet_ntop(AF_INET6, &from->sin6_addr,
910 ntopbuf, INET6_ADDRSTRLEN),
911 if_indextoname(pi->ipi6_ifindex, ifnamebuf));
912 return;
913 }

--- 11 unchanged lines hidden (view full) ---

925 if_indextoname(pi->ipi6_ifindex, ifnamebuf));
926 goto done;
927 }
928 rai->rainput++; /* increment statistics */
929
930 /* Cur Hop Limit value */
931 if (ra->nd_ra_curhoplimit && rai->hoplimit &&
932 ra->nd_ra_curhoplimit != rai->hoplimit) {
908 syslog(LOG_WARNING,
933 syslog(LOG_INFO,
909 "<%s> CurHopLimit inconsistent on %s:"
910 " %d from %s, %d from us",
911 __FUNCTION__,
912 rai->ifname,
913 ra->nd_ra_curhoplimit,
914 inet_ntop(AF_INET6, &from->sin6_addr,
915 ntopbuf, INET6_ADDRSTRLEN),
916 rai->hoplimit);
917 inconsistent++;
918 }
919 /* M flag */
920 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
921 rai->managedflg) {
934 "<%s> CurHopLimit inconsistent on %s:"
935 " %d from %s, %d from us",
936 __FUNCTION__,
937 rai->ifname,
938 ra->nd_ra_curhoplimit,
939 inet_ntop(AF_INET6, &from->sin6_addr,
940 ntopbuf, INET6_ADDRSTRLEN),
941 rai->hoplimit);
942 inconsistent++;
943 }
944 /* M flag */
945 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
946 rai->managedflg) {
922 syslog(LOG_WARNING,
947 syslog(LOG_INFO,
923 "<%s> M flag inconsistent on %s:"
924 " %s from %s, %s from us",
925 __FUNCTION__,
926 rai->ifname,
927 on_off[!rai->managedflg],
928 inet_ntop(AF_INET6, &from->sin6_addr,
929 ntopbuf, INET6_ADDRSTRLEN),
930 on_off[rai->managedflg]);
931 inconsistent++;
932 }
933 /* O flag */
934 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
935 rai->otherflg) {
948 "<%s> M flag inconsistent on %s:"
949 " %s from %s, %s from us",
950 __FUNCTION__,
951 rai->ifname,
952 on_off[!rai->managedflg],
953 inet_ntop(AF_INET6, &from->sin6_addr,
954 ntopbuf, INET6_ADDRSTRLEN),
955 on_off[rai->managedflg]);
956 inconsistent++;
957 }
958 /* O flag */
959 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
960 rai->otherflg) {
936 syslog(LOG_WARNING,
961 syslog(LOG_INFO,
937 "<%s> O flag inconsistent on %s:"
938 " %s from %s, %s from us",
939 __FUNCTION__,
940 rai->ifname,
941 on_off[!rai->otherflg],
942 inet_ntop(AF_INET6, &from->sin6_addr,
943 ntopbuf, INET6_ADDRSTRLEN),
944 on_off[rai->otherflg]);
945 inconsistent++;
946 }
947 /* Reachable Time */
948 reachabletime = ntohl(ra->nd_ra_reachable);
949 if (reachabletime && rai->reachabletime &&
950 reachabletime != rai->reachabletime) {
962 "<%s> O flag inconsistent on %s:"
963 " %s from %s, %s from us",
964 __FUNCTION__,
965 rai->ifname,
966 on_off[!rai->otherflg],
967 inet_ntop(AF_INET6, &from->sin6_addr,
968 ntopbuf, INET6_ADDRSTRLEN),
969 on_off[rai->otherflg]);
970 inconsistent++;
971 }
972 /* Reachable Time */
973 reachabletime = ntohl(ra->nd_ra_reachable);
974 if (reachabletime && rai->reachabletime &&
975 reachabletime != rai->reachabletime) {
951 syslog(LOG_WARNING,
976 syslog(LOG_INFO,
952 "<%s> ReachableTime inconsistent on %s:"
953 " %d from %s, %d from us",
954 __FUNCTION__,
955 rai->ifname,
956 reachabletime,
957 inet_ntop(AF_INET6, &from->sin6_addr,
958 ntopbuf, INET6_ADDRSTRLEN),
959 rai->reachabletime);
960 inconsistent++;
961 }
962 /* Retrans Timer */
963 retranstimer = ntohl(ra->nd_ra_retransmit);
964 if (retranstimer && rai->retranstimer &&
965 retranstimer != rai->retranstimer) {
977 "<%s> ReachableTime inconsistent on %s:"
978 " %d from %s, %d from us",
979 __FUNCTION__,
980 rai->ifname,
981 reachabletime,
982 inet_ntop(AF_INET6, &from->sin6_addr,
983 ntopbuf, INET6_ADDRSTRLEN),
984 rai->reachabletime);
985 inconsistent++;
986 }
987 /* Retrans Timer */
988 retranstimer = ntohl(ra->nd_ra_retransmit);
989 if (retranstimer && rai->retranstimer &&
990 retranstimer != rai->retranstimer) {
966 syslog(LOG_WARNING,
991 syslog(LOG_INFO,
967 "<%s> RetranceTimer inconsistent on %s:"
968 " %d from %s, %d from us",
969 __FUNCTION__,
970 rai->ifname,
971 retranstimer,
972 inet_ntop(AF_INET6, &from->sin6_addr,
973 ntopbuf, INET6_ADDRSTRLEN),
974 rai->retranstimer);
975 inconsistent++;
976 }
977 /* Values in the MTU options */
978 if (ndopts.nd_opts_mtu) {
979 mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
980 if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
992 "<%s> RetranceTimer inconsistent on %s:"
993 " %d from %s, %d from us",
994 __FUNCTION__,
995 rai->ifname,
996 retranstimer,
997 inet_ntop(AF_INET6, &from->sin6_addr,
998 ntopbuf, INET6_ADDRSTRLEN),
999 rai->retranstimer);
1000 inconsistent++;
1001 }
1002 /* Values in the MTU options */
1003 if (ndopts.nd_opts_mtu) {
1004 mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
1005 if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
981 syslog(LOG_WARNING,
1006 syslog(LOG_INFO,
982 "<%s> MTU option value inconsistent on %s:"
983 " %d from %s, %d from us",
984 __FUNCTION__,
985 rai->ifname, mtu,
986 inet_ntop(AF_INET6, &from->sin6_addr,
987 ntopbuf, INET6_ADDRSTRLEN),
988 rai->linkmtu);
989 inconsistent++;
990 }
991 }
992 /* Preferred and Valid Lifetimes for prefixes */
993 {
994 struct nd_optlist *optp = ndopts.nd_opts_list;
1007 "<%s> MTU option value inconsistent on %s:"
1008 " %d from %s, %d from us",
1009 __FUNCTION__,
1010 rai->ifname, mtu,
1011 inet_ntop(AF_INET6, &from->sin6_addr,
1012 ntopbuf, INET6_ADDRSTRLEN),
1013 rai->linkmtu);
1014 inconsistent++;
1015 }
1016 }
1017 /* Preferred and Valid Lifetimes for prefixes */
1018 {
1019 struct nd_optlist *optp = ndopts.nd_opts_list;
995
1020
996 if (ndopts.nd_opts_pi) {
997 if (prefix_check(ndopts.nd_opts_pi, rai, from))
998 inconsistent++;
999 }
1000 while (optp) {
1001 if (prefix_check((struct nd_opt_prefix_info *)optp->opt,
1002 rai, from))
1003 inconsistent++;
1004 optp = optp->next;
1005 }
1006 }
1007
1021 if (ndopts.nd_opts_pi) {
1022 if (prefix_check(ndopts.nd_opts_pi, rai, from))
1023 inconsistent++;
1024 }
1025 while (optp) {
1026 if (prefix_check((struct nd_opt_prefix_info *)optp->opt,
1027 rai, from))
1028 inconsistent++;
1029 optp = optp->next;
1030 }
1031 }
1032
1008 if (inconsistent) {
1009 printf("RA input %d inconsistents\n", inconsistent);
1033 if (inconsistent)
1010 rai->rainconsistent++;
1034 rai->rainconsistent++;
1011 }
1012
1013 done:
1014 free_ndopts(&ndopts);
1015 return;
1016}
1017
1018/* return a non-zero value if the received prefix is inconsitent with ours */
1019static int
1020prefix_check(struct nd_opt_prefix_info *pinfo,
1021 struct rainfo *rai, struct sockaddr_in6 *from)
1022{
1023 u_int32_t preferred_time, valid_time;
1024 struct prefix *pp;
1025 int inconsistent = 0;
1026 u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
1035
1036 done:
1037 free_ndopts(&ndopts);
1038 return;
1039}
1040
1041/* return a non-zero value if the received prefix is inconsitent with ours */
1042static int
1043prefix_check(struct nd_opt_prefix_info *pinfo,
1044 struct rainfo *rai, struct sockaddr_in6 *from)
1045{
1046 u_int32_t preferred_time, valid_time;
1047 struct prefix *pp;
1048 int inconsistent = 0;
1049 u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
1050 struct timeval now;
1027
1028#if 0 /* impossible */
1029 if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION)
1030 return(0);
1031#endif
1032
1033 /*
1034 * log if the adveritsed prefix has link-local scope(sanity check?)

--- 21 unchanged lines hidden (view full) ---

1056 pinfo->nd_opt_pi_prefix_len,
1057 inet_ntop(AF_INET6, &from->sin6_addr,
1058 ntopbuf, INET6_ADDRSTRLEN),
1059 rai->ifname);
1060 return(0);
1061 }
1062
1063 preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
1051
1052#if 0 /* impossible */
1053 if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION)
1054 return(0);
1055#endif
1056
1057 /*
1058 * log if the adveritsed prefix has link-local scope(sanity check?)

--- 21 unchanged lines hidden (view full) ---

1080 pinfo->nd_opt_pi_prefix_len,
1081 inet_ntop(AF_INET6, &from->sin6_addr,
1082 ntopbuf, INET6_ADDRSTRLEN),
1083 rai->ifname);
1084 return(0);
1085 }
1086
1087 preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
1064 if (preferred_time != pp->preflifetime) {
1065 syslog(LOG_WARNING,
1088 if (pp->pltimeexpire) {
1089 /*
1090 * The lifetime is decremented in real time, so we should
1091 * compare the expiration time.
1092 * (RFC 2461 Section 6.2.7.)
1093 * XXX: can we really expect that all routers on the link
1094 * have synchronized clocks?
1095 */
1096 gettimeofday(&now, NULL);
1097 preferred_time += now.tv_sec;
1098
1099 if (rai->clockskew &&
1100 abs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
1101 syslog(LOG_INFO,
1102 "<%s> prefeerred lifetime for %s/%d"
1103 " (decr. in real time) inconsistent on %s:"
1104 " %d from %s, %ld from us",
1105 __FUNCTION__,
1106 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1107 prefixbuf, INET6_ADDRSTRLEN),
1108 pinfo->nd_opt_pi_prefix_len,
1109 rai->ifname, preferred_time,
1110 inet_ntop(AF_INET6, &from->sin6_addr,
1111 ntopbuf, INET6_ADDRSTRLEN),
1112 pp->pltimeexpire);
1113 inconsistent++;
1114 }
1115 }
1116 else if (preferred_time != pp->preflifetime) {
1117 syslog(LOG_INFO,
1066 "<%s> prefeerred lifetime for %s/%d"
1067 " inconsistent on %s:"
1068 " %d from %s, %d from us",
1069 __FUNCTION__,
1070 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1071 prefixbuf, INET6_ADDRSTRLEN),
1072 pinfo->nd_opt_pi_prefix_len,
1073 rai->ifname, preferred_time,
1074 inet_ntop(AF_INET6, &from->sin6_addr,
1075 ntopbuf, INET6_ADDRSTRLEN),
1076 pp->preflifetime);
1118 "<%s> prefeerred lifetime for %s/%d"
1119 " inconsistent on %s:"
1120 " %d from %s, %d from us",
1121 __FUNCTION__,
1122 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1123 prefixbuf, INET6_ADDRSTRLEN),
1124 pinfo->nd_opt_pi_prefix_len,
1125 rai->ifname, preferred_time,
1126 inet_ntop(AF_INET6, &from->sin6_addr,
1127 ntopbuf, INET6_ADDRSTRLEN),
1128 pp->preflifetime);
1077 inconsistent++;
1078 }
1079
1080 valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
1129 }
1130
1131 valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
1081 if (valid_time != pp->validlifetime) {
1082 syslog(LOG_WARNING,
1132 if (pp->vltimeexpire) {
1133 gettimeofday(&now, NULL);
1134 valid_time += now.tv_sec;
1135
1136 if (rai->clockskew &&
1137 abs(valid_time - pp->vltimeexpire) > rai->clockskew) {
1138 syslog(LOG_INFO,
1139 "<%s> valid lifetime for %s/%d"
1140 " (decr. in real time) inconsistent on %s:"
1141 " %d from %s, %ld from us",
1142 __FUNCTION__,
1143 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1144 prefixbuf, INET6_ADDRSTRLEN),
1145 pinfo->nd_opt_pi_prefix_len,
1146 rai->ifname, preferred_time,
1147 inet_ntop(AF_INET6, &from->sin6_addr,
1148 ntopbuf, INET6_ADDRSTRLEN),
1149 pp->vltimeexpire);
1150 inconsistent++;
1151 }
1152 }
1153 else if (valid_time != pp->validlifetime) {
1154 syslog(LOG_INFO,
1083 "<%s> valid lifetime for %s/%d"
1084 " inconsistent on %s:"
1085 " %d from %s, %d from us",
1086 __FUNCTION__,
1087 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1088 prefixbuf, INET6_ADDRSTRLEN),
1089 pinfo->nd_opt_pi_prefix_len,
1090 rai->ifname, valid_time,

--- 22 unchanged lines hidden (view full) ---

1113 if (prefix->s6_addr[bytelen] >> (8 - bitlen) ==
1114 pp->prefix.s6_addr[bytelen] >> (8 - bitlen))
1115 return(pp);
1116 }
1117
1118 return(NULL);
1119}
1120
1155 "<%s> valid lifetime for %s/%d"
1156 " inconsistent on %s:"
1157 " %d from %s, %d from us",
1158 __FUNCTION__,
1159 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1160 prefixbuf, INET6_ADDRSTRLEN),
1161 pinfo->nd_opt_pi_prefix_len,
1162 rai->ifname, valid_time,

--- 22 unchanged lines hidden (view full) ---

1185 if (prefix->s6_addr[bytelen] >> (8 - bitlen) ==
1186 pp->prefix.s6_addr[bytelen] >> (8 - bitlen))
1187 return(pp);
1188 }
1189
1190 return(NULL);
1191}
1192
1193/* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */
1194int
1195prefix_match(struct in6_addr *p0, int plen0,
1196 struct in6_addr *p1, int plen1)
1197{
1198 int bytelen, bitlen;
1199
1200 if (plen0 < plen1)
1201 return(0);
1202 bytelen = plen1 / 8;
1203 bitlen = plen1 % 8;
1204 if (memcmp((void *)p0, (void *)p1, bytelen))
1205 return(0);
1206 if (p0->s6_addr[bytelen] >> (8 - bitlen) ==
1207 p1->s6_addr[bytelen] >> (8 - bitlen))
1208 return(1);
1209
1210 return(0);
1211}
1212
1121static int
1122nd6_options(struct nd_opt_hdr *hdr, int limit,
1123 union nd_opts *ndopts, u_int32_t optflags)
1124{
1125 int optlen = 0;
1126
1127 for (; limit > 0; limit -= optlen) {
1128 hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen);

--- 142 unchanged lines hidden (view full) ---

1271 }
1272#else /* old adv. API */
1273 if (setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
1274 sizeof(on)) < 0) {
1275 syslog(LOG_ERR, "<%s> IPV6_HOPLIMIT: %s",
1276 __FUNCTION__, strerror(errno));
1277 exit(1);
1278 }
1213static int
1214nd6_options(struct nd_opt_hdr *hdr, int limit,
1215 union nd_opts *ndopts, u_int32_t optflags)
1216{
1217 int optlen = 0;
1218
1219 for (; limit > 0; limit -= optlen) {
1220 hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen);

--- 142 unchanged lines hidden (view full) ---

1363 }
1364#else /* old adv. API */
1365 if (setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
1366 sizeof(on)) < 0) {
1367 syslog(LOG_ERR, "<%s> IPV6_HOPLIMIT: %s",
1368 __FUNCTION__, strerror(errno));
1369 exit(1);
1370 }
1279#endif
1371#endif
1280
1281 ICMP6_FILTER_SETBLOCKALL(&filt);
1282 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
1283 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
1284 if (accept_rr)
1285 ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt);
1286 if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
1287 sizeof(filt)) < 0) {
1288 syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s",
1289 __FUNCTION__, strerror(errno));
1290 exit(1);
1291 }
1292
1293 /*
1294 * join all routers multicast address on each advertising interface.
1295 */
1372
1373 ICMP6_FILTER_SETBLOCKALL(&filt);
1374 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
1375 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
1376 if (accept_rr)
1377 ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt);
1378 if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
1379 sizeof(filt)) < 0) {
1380 syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s",
1381 __FUNCTION__, strerror(errno));
1382 exit(1);
1383 }
1384
1385 /*
1386 * join all routers multicast address on each advertising interface.
1387 */
1296 if (inet_pton(AF_INET6, ALLROUTERS, &mreq.ipv6mr_multiaddr.s6_addr)
1388 if (inet_pton(AF_INET6, ALLROUTERS_LINK,
1389 &mreq.ipv6mr_multiaddr.s6_addr)
1297 != 1) {
1298 syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
1299 __FUNCTION__);
1300 exit(1);
1301 }
1302 while(ra) {
1303 mreq.ipv6mr_interface = ra->ifindex;
1390 != 1) {
1391 syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
1392 __FUNCTION__);
1393 exit(1);
1394 }
1395 while(ra) {
1396 mreq.ipv6mr_interface = ra->ifindex;
1304 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1305 &mreq,
1397 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
1306 sizeof(mreq)) < 0) {
1398 sizeof(mreq)) < 0) {
1307 syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP on %s: %s",
1399 syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s",
1308 __FUNCTION__, ra->ifname, strerror(errno));
1309 exit(1);
1310 }
1311 ra = ra->next;
1312 }
1400 __FUNCTION__, ra->ifname, strerror(errno));
1401 exit(1);
1402 }
1403 ra = ra->next;
1404 }
1405
1406 /*
1407 * When attending router renumbering, join all-routers site-local
1408 * multicast group.
1409 */
1410 if (accept_rr) {
1411 if (inet_pton(AF_INET6, ALLROUTERS_SITE,
1412 &in6a_site_allrouters) != 1) {
1413 syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
1414 __FUNCTION__);
1415 exit(1);
1416 }
1417 mreq.ipv6mr_multiaddr = in6a_site_allrouters;
1418 if (mcastif) {
1419 if ((mreq.ipv6mr_interface = if_nametoindex(mcastif))
1420 == 0) {
1421 syslog(LOG_ERR,
1422 "<%s> invalid interface: %s",
1423 __FUNCTION__, mcastif);
1424 exit(1);
1425 }
1426 } else
1427 mreq.ipv6mr_interface = ralist->ifindex;
1428 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1429 &mreq, sizeof(mreq)) < 0) {
1430 syslog(LOG_ERR,
1431 "<%s> IPV6_JOIN_GROUP(site) on %s: %s",
1432 __FUNCTION__,
1433 mcastif ? mcastif : ralist->ifname,
1434 strerror(errno));
1435 exit(1);
1436 }
1437 }
1313
1314 /* initialize msghdr for receiving packets */
1315 rcviov[0].iov_base = (caddr_t)answer;
1316 rcviov[0].iov_len = sizeof(answer);
1317 rcvmhdr.msg_name = (caddr_t)&from;
1318 rcvmhdr.msg_namelen = sizeof(from);
1319 rcvmhdr.msg_iov = rcviov;
1320 rcvmhdr.msg_iovlen = 1;

--- 16 unchanged lines hidden (view full) ---

1337{
1338 if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
1339 syslog(LOG_ERR,
1340 "<%s> socket: %s", __FUNCTION__, strerror(errno));
1341 exit(1);
1342 }
1343}
1344
1438
1439 /* initialize msghdr for receiving packets */
1440 rcviov[0].iov_base = (caddr_t)answer;
1441 rcviov[0].iov_len = sizeof(answer);
1442 rcvmhdr.msg_name = (caddr_t)&from;
1443 rcvmhdr.msg_namelen = sizeof(from);
1444 rcvmhdr.msg_iov = rcviov;
1445 rcvmhdr.msg_iovlen = 1;

--- 16 unchanged lines hidden (view full) ---

1462{
1463 if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
1464 syslog(LOG_ERR,
1465 "<%s> socket: %s", __FUNCTION__, strerror(errno));
1466 exit(1);
1467 }
1468}
1469
1345static struct rainfo *
1470struct rainfo *
1346if_indextorainfo(int index)
1347{
1348 struct rainfo *rai = ralist;
1349
1350 for (rai = ralist; rai; rai = rai->next) {
1351 if (rai->ifindex == index)
1352 return(rai);
1353 }

--- 11 unchanged lines hidden (view full) ---

1365 struct soliciter *sol, *nextsol;
1366
1367 if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
1368 syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA",
1369 __FUNCTION__, rainfo->ifname);
1370 return;
1371 }
1372
1471if_indextorainfo(int index)
1472{
1473 struct rainfo *rai = ralist;
1474
1475 for (rai = ralist; rai; rai = rai->next) {
1476 if (rai->ifindex == index)
1477 return(rai);
1478 }

--- 11 unchanged lines hidden (view full) ---

1490 struct soliciter *sol, *nextsol;
1491
1492 if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
1493 syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA",
1494 __FUNCTION__, rainfo->ifname);
1495 return;
1496 }
1497
1498 make_packet(rainfo); /* XXX: inefficient */
1499
1373 sndmhdr.msg_name = (caddr_t)&sin6_allnodes;
1374 sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data;
1375 sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
1376
1377 cm = CMSG_FIRSTHDR(&sndmhdr);
1378 /* specify the outgoing interface */
1379 cm->cmsg_level = IPPROTO_IPV6;
1380 cm->cmsg_type = IPV6_PKTINFO;

--- 88 unchanged lines hidden (view full) ---

1469{
1470 struct rainfo *rai = (struct rainfo *)data;
1471 long interval;
1472
1473 /*
1474 * Whenever a multicast advertisement is sent from an interface,
1475 * the timer is reset to a uniformly-distributed random value
1476 * between the interface's configured MinRtrAdvInterval and
1500 sndmhdr.msg_name = (caddr_t)&sin6_allnodes;
1501 sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data;
1502 sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
1503
1504 cm = CMSG_FIRSTHDR(&sndmhdr);
1505 /* specify the outgoing interface */
1506 cm->cmsg_level = IPPROTO_IPV6;
1507 cm->cmsg_type = IPV6_PKTINFO;

--- 88 unchanged lines hidden (view full) ---

1596{
1597 struct rainfo *rai = (struct rainfo *)data;
1598 long interval;
1599
1600 /*
1601 * Whenever a multicast advertisement is sent from an interface,
1602 * the timer is reset to a uniformly-distributed random value
1603 * between the interface's configured MinRtrAdvInterval and
1477 * MaxRtrAdvInterval(discovery-v2-02 6.2.4).
1604 * MaxRtrAdvInterval (RFC2461 6.2.4).
1478 */
1479 interval = rai->mininterval;
1480 interval += random() % (rai->maxinterval - rai->mininterval);
1481
1482 /*
1483 * For the first few advertisements (up to
1484 * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval
1485 * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer

--- 17 unchanged lines hidden ---
1605 */
1606 interval = rai->mininterval;
1607 interval += random() % (rai->maxinterval - rai->mininterval);
1608
1609 /*
1610 * For the first few advertisements (up to
1611 * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval
1612 * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer

--- 17 unchanged lines hidden ---