Date: Sun, 5 Jun 2011 11:20:19 +0000 (UTC) From: Hiroki Sato <hrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r222710 - user/hrs/ipv6/usr.sbin/rtadvd Message-ID: <201106051120.p55BKJ62053566@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hrs Date: Sun Jun 5 11:20:19 2011 New Revision: 222710 URL: http://svn.freebsd.org/changeset/base/222710 Log: Specify requirements for RA sending/receiving based on lifetime, IFF_ND6_ACCEPT_RTADV, and net.inet6.ip6.forwarding. ra_output: (lifetime == 0) = output (lifetime != 0 && (ACCEPT_RTADV || !ip6.forwarding) = no output ra_input: ACCEPT_RTADV = input !ACCEPT_RTADV = no input Note that the current implementation sends RAs with zero-lifetime even if ip6.forwarding == 0. This behavior is derived from KAME and different from RFC 4861. Modified: user/hrs/ipv6/usr.sbin/rtadvd/config.c user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c Modified: user/hrs/ipv6/usr.sbin/rtadvd/config.c ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvd/config.c Sun Jun 5 10:07:12 2011 (r222709) +++ user/hrs/ipv6/usr.sbin/rtadvd/config.c Sun Jun 5 11:20:19 2011 (r222710) @@ -34,7 +34,6 @@ #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/time.h> -#include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> @@ -76,7 +75,6 @@ static time_t prefix_timo = (60 * 120); static struct rtadvd_timer *prefix_timeout(void *); static void makeentry(char *, size_t, int, const char *); -static int getinet6sysctl(int); static size_t dname_labelenc(char *, const char *); /* Encode domain name label encoding in RFC 1035 Section 3.1 */ @@ -215,7 +213,6 @@ getconfig(int idx) char *bp = buf; char *addr, *flagstr; char intface[IFNAMSIZ]; - static int forwarding = -1; if (if_indextoname(idx, intface) == NULL) { syslog(LOG_ERR, "<%s> invalid index number (%d)", @@ -247,11 +244,6 @@ getconfig(int idx) TAILQ_INIT(&rai->rai_dnssl); TAILQ_INIT(&rai->rai_soliciter); - /* check if we are allowed to forward packets (if not determined) */ - if (forwarding < 0) - if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0) - exit(1); - /* gather on-link prefixes from the network interfaces. */ if (agetflag("noifprefix")) rai->rai_advifprefix = 0; @@ -355,22 +347,6 @@ getconfig(int idx) MAXROUTERLIFETIME); return (-1); } - /* - * Basically, hosts MUST NOT send Router Advertisement messages at any - * time (RFC 4861, Section 6.2.3). However, it would sometimes be - * useful to allow hosts to advertise some parameters such as prefix - * information and link MTU. Thus, we allow hosts to invoke rtadvd - * only when router lifetime (on every advertising interface) is - * explicitly set zero. (see also the above section) - */ - if (val && forwarding == 0) { - syslog(LOG_ERR, - "<%s> non zero router lifetime is specified for %s, " - "which must not be allowed for hosts. you must " - "change router lifetime or enable IPv6 forwarding.", - __func__, intface); - return (-1); - } rai->rai_lifetime = val & 0xffff; MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME); @@ -1312,23 +1288,3 @@ make_packet(struct rainfo *rai) } return; } - -static int -getinet6sysctl(int code) -{ - int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; - int value; - size_t size; - - mib[3] = code; - size = sizeof(value); - if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) - < 0) { - syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s", - __func__, code, - strerror(errno)); - return (-1); - } - else - return (value); -} Modified: user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c Sun Jun 5 10:07:12 2011 (r222709) +++ user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c Sun Jun 5 11:20:19 2011 (r222710) @@ -31,10 +31,12 @@ */ #include <sys/param.h> +#include <sys/ioctl.h> #include <sys/socket.h> #include <sys/uio.h> #include <sys/time.h> #include <sys/queue.h> +#include <sys/sysctl.h> #include <net/if.h> #include <net/if_media.h> @@ -47,6 +49,10 @@ #include <arpa/inet.h> +#include <net/if_var.h> +#include <netinet/in_var.h> +#include <netinet6/nd6.h> + #include <time.h> #include <unistd.h> #include <stdio.h> @@ -174,6 +180,8 @@ static void rtmsg_input(void); static void rtadvd_set_dump_file(int); static void set_short_delay(struct rainfo *); static int ifl_lookup(char *, char **, int); +static int check_accept_rtadv(int); +static int getinet6sysctl(int); int main(int argc, char *argv[]) @@ -1030,6 +1038,61 @@ set_short_delay(struct rainfo *rai) rtadvd_set_timer(&interval, rai->rai_timer); } +static int +check_accept_rtadv(int idx) +{ + struct in6_ndireq nd; + u_char ifname[IFNAMSIZ]; + int s6; + int error; + + if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, + "<%s> open socket failed for idx=%d.", + __func__, idx); + return (0); + } + if ((if_indextoname(idx, ifname)) == NULL) { + syslog(LOG_ERR, + "<%s> ifindex->ifname failed (idx=%d).", + __func__, idx); + close(s6); + return (0); + } + memset(&nd, 0, sizeof(nd)); + strncpy(nd.ifname, ifname, sizeof(nd.ifname)); + error = ioctl(s6, SIOCGIFINFO_IN6, &nd); + if (error) { + syslog(LOG_ERR, + "<%s> ioctl(SIOCGIFINFO_IN6) failed for idx=%d.", + __func__, idx); + nd.ndi.flags = 0; + } + close(s6); + + return (nd.ndi.flags & ND6_IFF_ACCEPT_RTADV); +} + +static int +getinet6sysctl(int code) +{ + int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; + int value; + size_t size; + + mib[3] = code; + size = sizeof(value); + if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) + < 0) { + syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s", + __func__, code, + strerror(errno)); + return (-1); + } + else + return (value); +} + static void ra_input(int len, struct nd_router_advert *nra, struct in6_pktinfo *pi, struct sockaddr_in6 *from) @@ -1047,6 +1110,16 @@ ra_input(int len, struct nd_router_adver inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf, sizeof(ntopbuf)), if_indextoname(pi->ipi6_ifindex, ifnamebuf)); + if (!check_accept_rtadv(pi->ipi6_ifindex)) { + syslog(LOG_INFO, + "<%s> An RA from %s on %s ignored (no ACCEPT_RTADV flag).", + __func__, + inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf, + sizeof(ntopbuf)), if_indextoname(pi->ipi6_ifindex, + ifnamebuf)); + return; + } + /* ND option check */ memset(&ndopts, 0, sizeof(ndopts)); error = nd6_options((struct nd_opt_hdr *)(nra + 1), @@ -1639,6 +1712,41 @@ ra_output(struct rainfo *rai) return; } + /* + * Check lifetime, ACCEPT_RTADV flag, and ip6.forwarding. + * + * (lifetime == 0) = output + * (lifetime != 0 && (ACCEPT_RTADV || !ip6.forwarding) = no output + * + * Basically, hosts MUST NOT send Router Advertisement + * messages at any time (RFC 4861, Section 6.2.3). However, it + * would sometimes be useful to allow hosts to advertise some + * parameters such as prefix information and link MTU. Thus, + * we allow hosts to invoke rtadvd only when router lifetime + * (on every advertising interface) is explicitly set + * zero. (see also the above section) + */ + syslog(LOG_DEBUG, + "<%s> check lifetime=%d, ACCEPT_RTADV=%d, ip6.forwarding=%d on %s", + __func__, rai->rai_lifetime, check_accept_rtadv(rai->rai_ifindex), + getinet6sysctl(IPV6CTL_FORWARDING), rai->rai_ifname); + if (rai->rai_lifetime != 0) { + if (check_accept_rtadv(rai->rai_ifindex)) { + syslog(LOG_INFO, + "<%s> non-zero lifetime RA " + "on RA receiving interface %s." + " Ignored.", __func__, rai->rai_ifname); + return; + } + if (getinet6sysctl(IPV6CTL_FORWARDING) == 0) { + syslog(LOG_INFO, + "<%s> non-zero lifetime RA " + "but net.inet6.ip6.forwarding=0. " + "Ignored.", __func__); + return; + } + } + make_packet(rai); /* XXX: inefficient */ sndmhdr.msg_name = (caddr_t)&sin6_linklocal_allnodes;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106051120.p55BKJ62053566>