Handle the case of an autoconf interface changing its rdomain.
To avoide code duplication have get_icmp6ev_by_rdomain() either return an existing icmp6ev in the correct rdomain or allocate one. OK? diff --git frontend.c frontend.c index 3bf418ba31e..624ff5562f3 100644 --- frontend.c +++ frontend.c @@ -502,7 +502,6 @@ void update_iface(uint32_t if_index, char* if_name) { struct iface *iface; - struct icmp6_ev *icmp6ev; struct imsg_ifinfo imsg_ifinfo; int flags, xflags, ifrdomain; @@ -516,32 +515,29 @@ update_iface(uint32_t if_index, char* if_name) if((ifrdomain = get_ifrdomain(if_name)) == -1) return; - if ((iface = get_iface_by_id(if_index)) == NULL) { + iface = get_iface_by_id(if_index); + + if (iface != NULL) { + if (iface->rdomain != ifrdomain) { + if (iface->icmp6ev != NULL) { + iface->icmp6ev->refcnt--; + if (iface->icmp6ev->refcnt == 0) { + event_del(&iface->icmp6ev->ev); + close(EVENT_FD(&iface->icmp6ev->ev)); + free(iface->icmp6ev); + } + iface->icmp6ev = NULL; + } + iface->rdomain = ifrdomain; + iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain); + } + } else { if ((iface = calloc(1, sizeof(*iface))) == NULL) fatal("calloc"); iface->if_index = if_index; iface->rdomain = ifrdomain; + iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain); - if ((icmp6ev = get_icmp6ev_by_rdomain(ifrdomain)) == NULL) { - if ((icmp6ev = calloc(1, sizeof(*icmp6ev))) == NULL) - fatal("calloc"); - icmp6ev->rcviov[0].iov_base = (caddr_t)icmp6ev->answer; - icmp6ev->rcviov[0].iov_len = sizeof(icmp6ev->answer); - icmp6ev->rcvmhdr.msg_name = (caddr_t)&icmp6ev->from; - icmp6ev->rcvmhdr.msg_namelen = sizeof(icmp6ev->from); - icmp6ev->rcvmhdr.msg_iov = icmp6ev->rcviov; - icmp6ev->rcvmhdr.msg_iovlen = 1; - icmp6ev->rcvmhdr.msg_controllen = - CMSG_SPACE(sizeof(struct in6_pktinfo)) + - CMSG_SPACE(sizeof(int)); - if ((icmp6ev->rcvmhdr.msg_control = malloc(icmp6ev-> - rcvmhdr.msg_controllen)) == NULL) - fatal("malloc"); - frontend_imsg_compose_main(IMSG_OPEN_ICMP6SOCK, 0, - &ifrdomain, sizeof(ifrdomain)); - } - iface->icmp6ev = icmp6ev; - iface->icmp6ev->refcnt++; LIST_INSERT_HEAD(&interfaces, iface, entries); } @@ -1121,13 +1117,35 @@ struct icmp6_ev* get_icmp6ev_by_rdomain(int rdomain) { struct iface *iface; + struct icmp6_ev *icmp6ev = NULL; LIST_FOREACH (iface, &interfaces, entries) { - if (iface->rdomain == rdomain) - return (iface->icmp6ev); + if (iface->rdomain == rdomain) { + icmp6ev = iface->icmp6ev; + break; + } } - return (NULL); + if (icmp6ev == NULL) { + if ((icmp6ev = calloc(1, sizeof(*icmp6ev))) == NULL) + fatal("calloc"); + icmp6ev->rcviov[0].iov_base = (caddr_t)icmp6ev->answer; + icmp6ev->rcviov[0].iov_len = sizeof(icmp6ev->answer); + icmp6ev->rcvmhdr.msg_name = (caddr_t)&icmp6ev->from; + icmp6ev->rcvmhdr.msg_namelen = sizeof(icmp6ev->from); + icmp6ev->rcvmhdr.msg_iov = icmp6ev->rcviov; + icmp6ev->rcvmhdr.msg_iovlen = 1; + icmp6ev->rcvmhdr.msg_controllen = + CMSG_SPACE(sizeof(struct in6_pktinfo)) + + CMSG_SPACE(sizeof(int)); + if ((icmp6ev->rcvmhdr.msg_control = malloc(icmp6ev-> + rcvmhdr.msg_controllen)) == NULL) + fatal("malloc"); + frontend_imsg_compose_main(IMSG_OPEN_ICMP6SOCK, 0, + &rdomain, sizeof(rdomain)); + } + icmp6ev->refcnt++; + return (icmp6ev); } void -- 2.29.2 -- I'm not entirely sure you are real.