svn commit: r222521 - user/hrs/ipv6/usr.sbin/rtsold

Hiroki Sato hrs at FreeBSD.org
Tue May 31 12:03:35 UTC 2011


Author: hrs
Date: Tue May 31 12:03:34 2011
New Revision: 222521
URL: http://svn.freebsd.org/changeset/base/222521

Log:
  - Implement RA option expiration based on the lifetime field.
  - Add option length check described in RFC 6106 Section 5.3.1.

Modified:
  user/hrs/ipv6/usr.sbin/rtsold/rtsol.c
  user/hrs/ipv6/usr.sbin/rtsold/rtsold.c
  user/hrs/ipv6/usr.sbin/rtsold/rtsold.h

Modified: user/hrs/ipv6/usr.sbin/rtsold/rtsol.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtsold/rtsol.c	Tue May 31 09:22:52 2011	(r222520)
+++ user/hrs/ipv6/usr.sbin/rtsold/rtsol.c	Tue May 31 12:03:34 2011	(r222521)
@@ -83,7 +83,6 @@ static const struct sockaddr_in6 sin6_al
 static void call_script(const int, const char *const *, void *);
 static size_t dname_labeldec(char *, const char *);
 static int safefile(const char *);
-static int ra_opt_handler(struct ifinfo *);
 
 #define _ARGS_OTHER	otherconf_script, ifi->ifname
 #define _ARGS_RESADD	resolvconf_script, "-a", ifi->ifname
@@ -244,10 +243,7 @@ rtsol_input(int s)
 	struct nd_opt_rdnss *rdnss;
 	struct nd_opt_dnssl *dnssl;
 	size_t len;
-	char nsbuf[11 + INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1 + 1];
-	/* 11 = sizeof("nameserver "), 1+1 = \n\0 termination */
-	char slbuf[7 + NI_MAXHOST + 1 + 1];
-	/* 7 = sizeof("search "), 1+1 = \n\0 termination */
+	char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1 + 1];
 	char dname[NI_MAXHOST + 1];
 	struct timeval now;
 	struct timeval lifetime;
@@ -400,6 +396,16 @@ rtsol_input(int s)
 		case ND_OPT_RDNSS:
 			rdnss = (struct nd_opt_rdnss *)raoptp;
 
+			/* Optlen sanity check (Section 5.3.1 in RFC 6106) */
+			if (rdnss->nd_opt_rdnss_len < 3) {
+				warnmsg(LOG_INFO, __func__,
+		    			"too short RDNSS option"
+					"in RA from %s was ignored.",
+					inet_ntop(AF_INET6, &from.sin6_addr,
+						  ntopbuf, INET6_ADDRSTRLEN));
+				break;
+			}
+
 			addr = (struct in6_addr *)(raoptp + sizeof(*rdnss));
 			while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) {
 				if (inet_ntop(AF_INET6, addr, ntopbuf,
@@ -447,16 +453,25 @@ rtsol_input(int s)
 		case ND_OPT_DNSSL:
 			dnssl = (struct nd_opt_dnssl *)raoptp;
 
+			/* Optlen sanity check (Section 5.3.1 in RFC 6106) */
+			if (dnssl->nd_opt_dnssl_len < 2) {
+				warnmsg(LOG_INFO, __func__,
+		    			"too short DNSSL option"
+					"in RA from %s was ignored.",
+					inet_ntop(AF_INET6, &from.sin6_addr,
+						  ntopbuf, INET6_ADDRSTRLEN));
+				break;
+			}
+
 			p = raoptp + sizeof(*dnssl);
 			while (0 < (len = dname_labeldec(dname, p))) {
-				sprintf(slbuf, "%s ", dname);
-				warnmsg(LOG_DEBUG, __func__, "slbuf = %s",
-				    slbuf);
+				warnmsg(LOG_DEBUG, __func__, "dname = %s",
+				    dname);
 
 				ELM_MALLOC(rao, break);
 				rao->rao_type = ndo->nd_opt_type;
-				rao->rao_len = strlen(nsbuf);
-				rao->rao_msg = strdup(slbuf);
+				rao->rao_len = strlen(dname);
+				rao->rao_msg = strdup(dname);
 				if (rao->rao_msg == NULL) {
 					warnmsg(LOG_ERR, __func__,
 					    "strdup failed: %s",
@@ -498,8 +513,9 @@ rtsol_input(int s)
 static char resstr_ns_prefix[] = "nameserver ";
 static char resstr_sh_prefix[] = "search ";
 static char resstr_nl[] = "\n";
+static char resstr_sp[] = " ";
 
-static int
+int
 ra_opt_handler(struct ifinfo *ifi)
 {
 	struct ra_opt *rao;
@@ -548,6 +564,10 @@ ra_opt_handler(struct ifinfo *ifi)
 			ELM_MALLOC(smp, continue);
 			smp->sm_msg = rao->rao_msg;
 			TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
+
+			ELM_MALLOC(smp, continue);
+			smp->sm_msg = resstr_sp;
+			TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
 			break;
 		default:
 			break;

Modified: user/hrs/ipv6/usr.sbin/rtsold/rtsold.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtsold/rtsold.c	Tue May 31 09:22:52 2011	(r222520)
+++ user/hrs/ipv6/usr.sbin/rtsold/rtsold.c	Tue May 31 12:03:34 2011	(r222521)
@@ -570,6 +570,19 @@ rtsol_check_timer(void)
 				    "state = %d", ifi->ifname,
 				    ifi->state);
 
+			/* Remove all RA options. */
+			if (!TAILQ_EMPTY(&ifi->ifi_ra_opt)) {
+				struct ra_opt *rao;
+				struct ra_opt *rao_tmp;
+
+				rao = TAILQ_FIRST(&ifi->ifi_ra_opt);
+				while (rao != NULL) {
+					rao_tmp = TAILQ_NEXT(rao, rao_next);
+					free(rao_tmp->rao_msg);
+					free(rao_tmp);
+					rao = rao_tmp;
+				}
+			}
 			switch (ifi->state) {
 			case IFS_DOWN:
 			case IFS_TENTATIVE:
@@ -635,8 +648,29 @@ rtsol_check_timer(void)
 				break;
 			}
 			rtsol_timer_update(ifi);
+		} else {
+			/* Expiration check for RA options. */
+			struct ra_opt *rao;
+			struct ra_opt *rao_tmp;
+			int expire = 0;
+
+			TAILQ_FOREACH_SAFE(rao, &ifi->ifi_ra_opt, rao_next, rao_tmp) {
+				warnmsg(LOG_DEBUG, __func__,
+					"RA expiration timer: "
+					"type=%d, msg=%s, timer=%ld:%08ld",
+					rao->rao_type, (char *)rao->rao_msg,
+					(long)rao->rao_expire.tv_sec,
+					(long)rao->rao_expire.tv_usec);
+				if (timercmp(&now, &rao->rao_expire, >=)) {
+					warnmsg(LOG_DEBUG, __func__,
+						"RA expiration timer: expired.");
+					TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
+					expire = 1;
+				}
+			}
+			if (expire)
+				ra_opt_handler(ifi);
 		}
-
 		if (timercmp(&ifi->expire, &rtsol_timer, <))
 			rtsol_timer = ifi->expire;
 	}

Modified: user/hrs/ipv6/usr.sbin/rtsold/rtsold.h
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtsold/rtsold.h	Tue May 31 09:22:52 2011	(r222520)
+++ user/hrs/ipv6/usr.sbin/rtsold/rtsold.h	Tue May 31 12:03:34 2011	(r222521)
@@ -118,6 +118,7 @@ void rtsol_timer_update(struct ifinfo *)
 extern void warnmsg(int, const char *, const char *, ...)
      __attribute__((__format__(__printf__, 3, 4)));
 extern char **autoifprobe(void);
+extern int ra_opt_handler(struct ifinfo *);
 
 /* if.c */
 extern int ifinit(void);


More information about the svn-src-user mailing list