Hi, in some circumstances ospfd behaves not the way a user would expect and it's not easy understand how to recover. With below diff ospfd recovers automatically from the following three cases.
1) netstart When someone runs the netstart script on a running system it most likely assigns the already configured addresses. This leads first to a removal of the address and then it is added again. ospfd now lost it's multicast group but is not able to re-join. To recover ospfd these steps are needed (without the diff): - remove interface from ospfd.conf - ospfctl reload - add interface to ospfd.conf - ospfctl reload 2) netmask change When the netmask changes but the IP address stays the same a reload is needed. Otherwise the adjacency will not come up again on the interface with the changed config. I think this is not obvious for a user since the config file needs no change. 3) dest address change When the dest address on a point-to-point interface is changed but the local address stays the same recovery procedure is needed as for 1). But ospfd.conf does not change. While working on this I thought that it would be nice to use the ifindex for joining and leaving multicast groups via setsockopts instead of the IP. But I can not judge if it would be useful in other cases. In addition it would be nice if the kernel would do nothing if the new address and mask is the sam as the existing one. This is my 2nd attempt. See this thread for the previous one with discussion: https://marc.info/?t=149842729800001&r=1&w=2 OK? Remi Index: kroute.c =================================================================== RCS file: /cvs/src/usr.sbin/ospfd/kroute.c,v retrieving revision 1.109 diff -u -p -r1.109 kroute.c --- kroute.c 11 Feb 2018 02:27:33 -0000 1.109 +++ kroute.c 12 Jun 2018 20:41:43 -0000 @@ -1074,6 +1074,7 @@ if_newaddr(u_short ifindex, struct socka { struct kif_node *kif; struct kif_addr *ka; + struct ifaddr ifn; if (ifa == NULL || ifa->sin_family != AF_INET) return; @@ -1094,6 +1095,12 @@ if_newaddr(u_short ifindex, struct socka ka->dstbrd.s_addr = INADDR_NONE; TAILQ_INSERT_TAIL(&kif->addrs, ka, entry); + + ifn.addr = ka->addr; + ifn.mask = ka->mask; + ifn.dst = ka->dstbrd; + ifn.ifindex = ifindex; + main_imsg_compose_ospfe(IMSG_IFADDRADD, 0, &ifn, sizeof(ifn)); } void @@ -1102,7 +1109,7 @@ if_deladdr(u_short ifindex, struct socka { struct kif_node *kif; struct kif_addr *ka, *nka; - struct ifaddrdel ifc; + struct ifaddr ifc; if (ifa == NULL || ifa->sin_family != AF_INET) return; Index: ospfd.h =================================================================== RCS file: /cvs/src/usr.sbin/ospfd/ospfd.h,v retrieving revision 1.100 diff -u -p -r1.100 ospfd.h --- ospfd.h 11 Feb 2018 02:27:33 -0000 1.100 +++ ospfd.h 12 Jun 2018 20:41:43 -0000 @@ -132,6 +132,7 @@ enum imsg_type { IMSG_RECONF_REDIST, IMSG_RECONF_END, IMSG_DEMOTE, + IMSG_IFADDRADD, IMSG_IFADDRDEL }; @@ -363,8 +364,10 @@ struct iface { u_int8_t passive; }; -struct ifaddrdel { +struct ifaddr { struct in_addr addr; + struct in_addr mask; + struct in_addr dst; unsigned int ifindex; }; Index: ospfe.c =================================================================== RCS file: /cvs/src/usr.sbin/ospfd/ospfe.c,v retrieving revision 1.100 diff -u -p -r1.100 ospfe.c --- ospfe.c 5 Feb 2018 12:11:28 -0000 1.100 +++ ospfe.c 18 Jun 2018 05:56:16 -0000 @@ -275,7 +275,7 @@ ospfe_dispatch_main(int fd, short event, { static struct area *narea; static struct iface *niface; - struct ifaddrdel *ifc; + struct ifaddr *ifc; struct imsg imsg; struct imsgev *iev = bula; struct imsgbuf *ibuf = &iev->ibuf; @@ -361,9 +361,38 @@ ospfe_dispatch_main(int fd, short event, } } break; + case IMSG_IFADDRADD: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct ifaddr)) + fatalx("IFADDRADD imsg with wrong len"); + ifc = imsg.data; + + LIST_FOREACH(area, &oeconf->area_list, entry) { + LIST_FOREACH(iface, &area->iface_list, entry) { + if (ifc->ifindex == iface->ifindex && + ifc->addr.s_addr == + iface->addr.s_addr) { + iface->mask = ifc->mask; + iface->dst = ifc->dst; + /* + * Previous down event might + * have failed if the address + * was not present at that + * time. + */ + if_fsm(iface, IF_EVT_DOWN); + if_fsm(iface, IF_EVT_UP); + log_warnx("interface %s:%s " + "returned", iface->name, + inet_ntoa(iface->addr)); + break; + } + } + } + break; case IMSG_IFADDRDEL: if (imsg.hdr.len != IMSG_HEADER_SIZE + - sizeof(struct ifaddrdel)) + sizeof(struct ifaddr)) fatalx("IFADDRDEL imsg with wrong len"); ifc = imsg.data;