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 --- |