bin/152928: [patch] rtadvd don't send RA on i/f that's down

J.R. Oldroyd fbsd at opal.com
Wed Dec 8 17:00:25 UTC 2010


>Number:         152928
>Category:       bin
>Synopsis:       [patch] rtadvd don't send RA on i/f that's down
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Dec 08 17:00:23 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     J.R. Oldroyd
>Release:        FreeBSD 8.1-RELEASE amd64
>Organization:
>Environment:
System: FreeBSD xx.opal.com 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Mon Jul 19 02:36:49 UTC 2010 root at mason.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
>Description:
rtadvd looks to see if an interface is UP and doesn't send RAs if it's not.
However, if the interface is marked up but the media is down at the moment,
it does still send an RA.  This causes endless syslog messages of the form:

rtadvd[1619]: <ra_output> sendmsg on vge0: No buffer space available

The attached patch adds a check to see if the media is up and only sends
the RA if it is. 
>How-To-Repeat:
Run rtadvd on an interface of your choice.
Unplug the media cable from the interface.
Observe repeated syslog error messages.
>Fix:
--- usr.sbin/rtadvd/if.h.orig	2010-07-29 09:59:22.000000000 -0400
+++ usr.sbin/rtadvd/if.h	2010-12-08 11:07:48.000000000 -0500
@@ -40,6 +40,7 @@
 struct sockaddr_dl *if_nametosdl(char *);
 int if_getmtu(char *);
 int if_getflags(int, int);
+int if_getifmstatus(char *);
 int lladdropt_length(struct sockaddr_dl *);
 void lladdropt_fill(struct sockaddr_dl *, struct nd_opt_hdr *);
 int rtbuf_len(void);
--- usr.sbin/rtadvd/if.c.orig	2010-07-29 09:59:22.000000000 -0400
+++ usr.sbin/rtadvd/if.c	2010-12-08 11:13:13.000000000 -0500
@@ -35,6 +35,7 @@
 #include <sys/sysctl.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
+#include <net/if_media.h>
 #include <net/if_types.h>
 #include <net/ethernet.h>
 #include <ifaddrs.h>
@@ -203,6 +204,31 @@
 	return (ifr.ifr_flags);
 }
 
+/* get interface media status */
+int
+if_getifmstatus(char *name)
+{
+	struct ifmediareq ifmr;
+	int s;
+
+	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+		syslog(LOG_ERR, "<%s> socket: %s", __func__,
+		       strerror(errno));
+		return (~IFM_AVALID);
+	}
+
+	(void) memset(&ifmr, 0, sizeof(ifmr));
+	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
+	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+		syslog(LOG_ERR, "<%s> ioctl:SIOCGIFMEDIA: failed for %s",
+		       __func__, ifmr.ifm_name);
+		close(s);
+		return (~IFM_AVALID);
+	}
+	close(s);
+	return (ifmr.ifm_status);
+}
+
 #define ROUNDUP8(a) (1 + (((a) - 1) | 7))
 int
 lladdropt_length(struct sockaddr_dl *sdl)
@@ -503,7 +529,7 @@
 
 /*
  * alloc buffer and parse if_msghdrs block passed as arg,
- * and init the buffer as list of pointers ot each of the if_msghdr.
+ * and init the buffer as list of pointers to each of the if_msghdr.
  */
 static void
 parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
--- usr.sbin/rtadvd/rtadvd.c.orig	2010-07-29 09:59:22.000000000 -0400
+++ usr.sbin/rtadvd/rtadvd.c	2010-12-08 11:22:35.000000000 -0500
@@ -37,6 +37,7 @@
 #include <sys/queue.h>
 
 #include <net/if.h>
+#include <net/if_media.h>
 #include <net/route.h>
 #include <net/if_dl.h>
 #include <netinet/in.h>
@@ -1556,6 +1557,7 @@
 	struct cmsghdr *cm;
 	struct in6_pktinfo *pi;
 	struct soliciter *sol, *nextsol;
+	struct ifmediareq ifmr;
 
 	if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
 		syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA",
@@ -1563,6 +1565,14 @@
 		return;
 	}
 
+	if ((if_getifmstatus(rainfo->ifname) & (IFM_AVALID | IFM_ACTIVE))
+	    != (IFM_AVALID | IFM_ACTIVE)) {
+		syslog(LOG_DEBUG,
+		    "<%s> %s media is not active, skip sending RA",
+		    __func__, rainfo->ifname);
+		return;
+	}
+
 	make_packet(rainfo);	/* XXX: inefficient */
 
 	sndmhdr.msg_name = (caddr_t)&sin6_allnodes;
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list