Give some love to ospf6d. The goal is to have ospf6d looks like ospfd, this could be useful to have changes made in one daemon from one go inside the other.
I will do it step by step until I get to the point where "ospf6ctl reload" works. First step is to refactor kernel route message handling, no functionnal change. Denis Index: kroute.c =================================================================== RCS file: /cvs/src/usr.sbin/ospf6d/kroute.c,v retrieving revision 1.60 diff -u -p -r1.60 kroute.c --- kroute.c 2 Jan 2019 21:32:55 -0000 1.60 +++ kroute.c 9 Dec 2019 17:35:33 -0000 @@ -80,7 +80,7 @@ struct kroute_node *kroute_match(struct int protect_lo(void); void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); -void if_change(u_short, int, struct if_data *); +void if_change(u_short, int, struct if_data *, struct sockaddr_dl *); void if_newaddr(u_short, struct sockaddr_in6 *, struct sockaddr_in6 *, struct sockaddr_in6 *); void if_deladdr(u_short, struct sockaddr_in6 *, @@ -90,6 +90,7 @@ void if_announce(void *); int send_rtmsg(int, int, struct kroute *); int dispatch_rtmsg(void); int fetchtable(void); +int rtmsg_process(char *, size_t); RB_HEAD(kroute_tree, kroute_node) krt; RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare) @@ -801,7 +802,8 @@ get_rtaddrs(int addrs, struct sockaddr * } void -if_change(u_short ifindex, int flags, struct if_data *ifd) +if_change(u_short ifindex, int flags, struct if_data *ifd, + struct sockaddr_dl *sdl) { struct kroute_node *kr, *tkr; struct iface *iface; @@ -809,7 +811,7 @@ if_change(u_short ifindex, int flags, st wasvalid = kif_validate(ifindex); - if ((iface = kif_update(ifindex, flags, ifd, NULL)) == NULL) { + if ((iface = kif_update(ifindex, flags, ifd, sdl)) == NULL) { log_warn("if_change: kif_update(%u)", ifindex); return; } @@ -1135,12 +1137,8 @@ fetchtable(void) { size_t len; int mib[7]; - char *buf, *next, *lim; - struct rt_msghdr *rtm; - struct sockaddr *sa, *rti_info[RTAX_MAX]; - struct sockaddr_in6 *sa_in6; - struct sockaddr_rtlabel *label; - struct kroute_node *kr; + char *buf; + int rv; mib[0] = CTL_NET; mib[1] = PF_ROUTE; @@ -1164,102 +1162,10 @@ fetchtable(void) return (-1); } - lim = buf + len; - for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); - get_rtaddrs(rtm->rtm_addrs, sa, rti_info); - - if ((sa = rti_info[RTAX_DST]) == NULL) - continue; - - /* Skip ARP/ND cache and broadcast routes. */ - if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST)) - continue; - - if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { - log_warn("fetchtable"); - free(buf); - return (-1); - } - - kr->r.flags = F_KERNEL; - kr->r.priority = rtm->rtm_priority; - - switch (sa->sa_family) { - case AF_INET6: - kr->r.prefix = - ((struct sockaddr_in6 *)sa)->sin6_addr; - sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK]; - if (rtm->rtm_flags & RTF_STATIC) - kr->r.flags |= F_STATIC; - if (rtm->rtm_flags & RTF_BLACKHOLE) - kr->r.flags |= F_BLACKHOLE; - if (rtm->rtm_flags & RTF_REJECT) - kr->r.flags |= F_REJECT; - if (rtm->rtm_flags & RTF_DYNAMIC) - kr->r.flags |= F_DYNAMIC; - if (sa_in6 != NULL) { - if (sa_in6->sin6_len == 0) - break; - kr->r.prefixlen = - mask2prefixlen(sa_in6); - } else if (rtm->rtm_flags & RTF_HOST) - kr->r.prefixlen = 128; - else - fatalx("classful IPv6 route?!!"); - break; - default: - free(kr); - continue; - } - - kr->r.ifindex = rtm->rtm_index; - if ((sa = rti_info[RTAX_GATEWAY]) != NULL) - switch (sa->sa_family) { - case AF_INET6: - if (rtm->rtm_flags & RTF_CONNECTED) { - kr->r.flags |= F_CONNECTED; - break; - } - - sa_in6 = (struct sockaddr_in6 *)sa; - /* - * XXX The kernel provides the scope via the - * XXX kame hack instead of the scope_id field. - */ - recoverscope(sa_in6); - kr->r.nexthop = sa_in6->sin6_addr; - kr->r.scope = sa_in6->sin6_scope_id; - break; - case AF_LINK: - /* - * Traditional BSD connected routes have - * a gateway of type AF_LINK. - */ - kr->r.flags |= F_CONNECTED; - break; - } - - if (rtm->rtm_priority == kr_state.fib_prio) { - send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); - free(kr); - } else { - if ((label = (struct sockaddr_rtlabel *) - rti_info[RTAX_LABEL]) != NULL) { - kr->r.rtlabel = - rtlabel_name2id(label->sr_label); - kr->r.ext_tag = - rtlabel_id2tag(kr->r.rtlabel); - } - kroute_insert(kr); - } - - } + rv = rtmsg_process(buf, len); free(buf); - return (0); + + return (rv); } int @@ -1267,12 +1173,8 @@ fetchifs(u_short ifindex) { size_t len; int mib[6]; - char *buf, *next, *lim; - struct rt_msghdr *rtm; - struct if_msghdr ifm; - struct ifa_msghdr *ifam; - struct iface *iface; - struct sockaddr *sa, *rti_info[RTAX_MAX]; + char *buf; + int rv; mib[0] = CTL_NET; mib[1] = PF_ROUTE; @@ -1295,38 +1197,10 @@ fetchifs(u_short ifindex) return (-1); } - lim = buf + len; - for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - switch (rtm->rtm_type) { - case RTM_IFINFO: - bcopy(rtm, &ifm, sizeof ifm); - sa = (struct sockaddr *)(next + sizeof(ifm)); - get_rtaddrs(ifm.ifm_addrs, sa, rti_info); - - if ((iface = kif_update(ifm.ifm_index, - ifm.ifm_flags, &ifm.ifm_data, - (struct sockaddr_dl *)rti_info[RTAX_IFP])) == NULL) - break; - case RTM_NEWADDR: - ifam = (struct ifa_msghdr *)rtm; - if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | - RTA_BRD)) == 0) - break; - sa = (struct sockaddr *)(ifam + 1); - get_rtaddrs(ifam->ifam_addrs, sa, rti_info); - - if_newaddr(ifam->ifam_index, - (struct sockaddr_in6 *)rti_info[RTAX_IFA], - (struct sockaddr_in6 *)rti_info[RTAX_NETMASK], - (struct sockaddr_in6 *)rti_info[RTAX_BRD]); - break; - } - } + rv = rtmsg_process(buf, len); free(buf); - return (0); + + return (rv); } int @@ -1334,7 +1208,25 @@ dispatch_rtmsg(void) { char buf[RT_BUF_SIZE]; ssize_t n; - char *next, *lim; + + if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { + if (errno == EAGAIN || errno == EINTR) + return (0); + log_warn("dispatch_rtmsg: read error"); + return (-1); + } + + if (n == 0) { + log_warnx("routing socket closed"); + return (-1); + } + + return (rtmsg_process(buf, n)); +} + +int +rtmsg_process(char *buf, size_t len) +{ struct rt_msghdr *rtm; struct if_msghdr ifm; struct ifa_msghdr *ifam; @@ -1348,25 +1240,15 @@ dispatch_rtmsg(void) unsigned int scope; u_short ifindex = 0; int rv; + size_t offset; + char *next; - if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { - if (errno == EAGAIN || errno == EINTR) - return (0); - log_warn("dispatch_rtmsg: read error"); - return (-1); - } - - if (n == 0) { - log_warnx("routing socket closed"); - return (-1); - } - - lim = buf + n; - for (next = buf; next < lim; next += rtm->rtm_msglen) { + for (offset = 0; offset < len; offset += rtm->rtm_msglen) { + next = buf + offset; rtm = (struct rt_msghdr *)next; - if (lim < next + sizeof(u_short) || - lim < next + rtm->rtm_msglen) - fatalx("dispatch_rtmsg: partial rtm in buffer"); + if (len < offset + sizeof(u_short) || + len < offset + rtm->rtm_msglen) + fatalx("rtmsg_process: partial rtm in buffer"); if (rtm->rtm_version != RTM_VERSION) continue; @@ -1378,18 +1260,25 @@ dispatch_rtmsg(void) mpath = 0; prio = 0; - if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE || - rtm->rtm_type == RTM_DELETE) { - sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); - get_rtaddrs(rtm->rtm_addrs, sa, rti_info); + sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); + get_rtaddrs(rtm->rtm_addrs, sa, rti_info); + + switch (rtm->rtm_type) { + case RTM_ADD: + case RTM_GET: + case RTM_CHANGE: + case RTM_DELETE: + if (rtm->rtm_errno) /* failed attempts... */ + continue; if (rtm->rtm_tableid != kr_state.rdomain) continue; - if (rtm->rtm_pid == kr_state.pid) /* caused by us */ + if (rtm->rtm_type == RTM_GET && + rtm->rtm_pid == kr_state.pid) /* caused by us */ continue; - if (rtm->rtm_errno) /* failed attempts... */ + if ((sa = rti_info[RTAX_DST]) == NULL) continue; /* Skip ARP/ND cache and broadcast routes. */ @@ -1399,6 +1288,8 @@ dispatch_rtmsg(void) if (rtm->rtm_flags & RTF_MPATH) mpath = 1; prio = rtm->rtm_priority; + flags = (prio == kr_state.fib_prio) ? + F_OSPFD_INSERTED : F_KERNEL; switch (sa->sa_family) { case AF_INET6: @@ -1431,6 +1322,9 @@ dispatch_rtmsg(void) if ((sa = rti_info[RTAX_GATEWAY]) != NULL) { switch (sa->sa_family) { case AF_INET6: + if (rtm->rtm_flags & RTF_CONNECTED) + flags |= F_CONNECTED; + sa_in6 = (struct sockaddr_in6 *)sa; /* * XXX The kernel provides the scope @@ -1450,10 +1344,11 @@ dispatch_rtmsg(void) switch (rtm->rtm_type) { case RTM_ADD: + case RTM_GET: case RTM_CHANGE: if (IN6_IS_ADDR_UNSPECIFIED(&nexthop) && !(flags & F_CONNECTED)) { - log_warnx("dispatch_rtmsg no nexthop for %s/%u", + log_warnx("rtmsg_process no nexthop for %s/%u", log_in6addr(&prefix), prefixlen); continue; } @@ -1467,7 +1362,7 @@ dispatch_rtmsg(void) kr = okr; if (mpath && (kr = kroute_matchgw(okr, &nexthop, scope)) == NULL) { - log_warnx("dispatch_rtmsg mpath route" + log_warnx("rtmsg_process: mpath route" " not found"); /* add routes we missed out earlier */ goto add; @@ -1502,7 +1397,7 @@ dispatch_rtmsg(void) add: if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { - log_warn("dispatch_rtmsg"); + log_warn("rtmsg_process calloc"); return (-1); } kr->r.prefix = prefix; @@ -1540,31 +1435,29 @@ add: if ((kr = kroute_find(&prefix, prefixlen, prio)) == NULL) continue; + if (!(kr->r.flags & F_KERNEL)) + continue; /* get the correct route */ okr = kr; if (mpath && (kr = kroute_matchgw(kr, &nexthop, scope)) == NULL) { - log_warnx("dispatch_rtmsg mpath route" + log_warnx("rtmsg_process mpath route" " not found"); return (-1); } - if (!(kr->r.flags & F_KERNEL)) - continue; if (kroute_remove(kr) == -1) return (-1); break; case RTM_IFINFO: memcpy(&ifm, next, sizeof(ifm)); - if_change(ifm.ifm_index, ifm.ifm_flags, - &ifm.ifm_data); + if_change(ifm.ifm_index, ifm.ifm_flags, &ifm.ifm_data, + (struct sockaddr_dl *)rti_info[RTAX_IFP]); break; case RTM_NEWADDR: ifam = (struct ifa_msghdr *)rtm; if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | RTA_BRD)) == 0) break; - sa = (struct sockaddr *)(ifam + 1); - get_rtaddrs(ifam->ifam_addrs, sa, rti_info); if_newaddr(ifam->ifam_index, (struct sockaddr_in6 *)rti_info[RTAX_IFA], @@ -1576,8 +1469,6 @@ add: if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | RTA_BRD)) == 0) break; - sa = (struct sockaddr *)(ifam + 1); - get_rtaddrs(ifam->ifam_addrs, sa, rti_info); if_deladdr(ifam->ifam_index, (struct sockaddr_in6 *)rti_info[RTAX_IFA], @@ -1592,5 +1483,5 @@ add: break; } } - return (0); + return (offset); }