--- 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 #include #include +#include #include #include #include @@ -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 #include +#include #include #include #include @@ -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;