Index: sys/net/if.c =================================================================== --- sys/net/if.c +++ sys/net/if.c @@ -2512,7 +2512,8 @@ return (error); error = if_setlladdr(ifp, ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len); - EVENTHANDLER_INVOKE(iflladdr_event, ifp); + if (error == 0) + EVENTHANDLER_INVOKE(iflladdr_event, ifp); break; case SIOCAIFGROUP: @@ -3373,16 +3374,6 @@ ifr.ifr_flagshigh = ifp->if_flags >> 16; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); } -#ifdef INET - /* - * Also send gratuitous ARPs to notify other nodes about - * the address change. - */ - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (ifa->ifa_addr->sa_family == AF_INET) - arp_ifinit(ifp, ifa); - } -#endif } return (0); } Index: sys/net/if_vlan.c =================================================================== --- sys/net/if_vlan.c +++ sys/net/if_vlan.c @@ -523,7 +523,7 @@ #ifndef VLAN_ARRAY struct ifvlan *next; #endif - int i; + int error, i; /* * Check if it's a trunk interface first of all @@ -544,8 +544,11 @@ LIST_FOREACH_SAFE(ifv, &ifp->if_vlantrunk->hash[i], ifv_list, next) { #endif /* VLAN_ARRAY */ VLAN_UNLOCK(); - if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp), + error = if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp), ifp->if_addrlen); + if (error == 0) + EVENTHANDLER_INVOKE(iflladdr_event, + ifv->ifv_ifp); VLAN_LOCK(); } VLAN_UNLOCK(); Index: sys/netgraph/ng_eiface.c =================================================================== --- sys/netgraph/ng_eiface.c +++ sys/netgraph/ng_eiface.c @@ -489,7 +489,8 @@ } error = if_setlladdr(priv->ifp, (u_char *)msg->data, ETHER_ADDR_LEN); - EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); + if (error == 0) + EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); break; } Index: sys/netgraph/ng_ether.c =================================================================== --- sys/netgraph/ng_ether.c +++ sys/netgraph/ng_ether.c @@ -534,7 +534,8 @@ } error = if_setlladdr(priv->ifp, (u_char *)msg->data, ETHER_ADDR_LEN); - EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); + if (error == 0) + EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); break; } case NGM_ETHER_GET_PROMISC: Index: sys/netinet/if_ether.c =================================================================== --- sys/netinet/if_ether.c +++ sys/netinet/if_ether.c @@ -144,7 +144,9 @@ static void arp_update_lle(struct arphdr *ah, struct ifnet *ifp, struct llentry *la); static void arp_mark_lle_reachable(struct llentry *la); +static void arp_iflladdr(void *arg __unused, struct ifnet *ifp); +static eventhandler_tag iflladdr_tag; static const struct netisr_handler arp_nh = { .nh_name = "arp", @@ -1163,10 +1165,33 @@ ifa->ifa_rtrequest = NULL; } +/* + * A handler for interface link layer address change event. + */ +static __noinline void +arp_iflladdr(void *arg __unused, struct ifnet *ifp) +{ + struct ifaddr *ifa; + + if ((ifp->if_flags & IFF_UP) == 0) + return; + + /* + * Also send gratuitous ARPs to notify other nodes about + * the address change. + */ + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family == AF_INET) + arp_ifinit(ifp, ifa); + } +} + static void arp_init(void) { netisr_register(&arp_nh); + iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, + arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY); } SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0);