| --- a/src/ndp.c |
| +++ b/src/ndp.c |
| @@ -38,6 +38,7 @@ static void setup_route(struct in6_addr |
| static void setup_addr_for_relaying(struct in6_addr *addr, struct interface *iface, bool add); |
| static void handle_solicit(void *addr, void *data, size_t len, |
| struct interface *iface, void *dest); |
| +static void ping6(struct in6_addr *addr, const struct interface *iface); |
| |
| /* Filter ICMPv6 messages of type neighbor solicitation */ |
| static struct sock_filter bpf[] = { |
| @@ -235,6 +236,7 @@ int ndp_setup_interface(struct interface |
| static void ndp_netevent_cb(unsigned long event, struct netevent_handler_info *info) |
| { |
| struct interface *iface = info->iface; |
| + struct interface *c; |
| bool add = true; |
| |
| if (!iface || iface->ndp == MODE_DISABLED) |
| @@ -247,6 +249,16 @@ static void ndp_netevent_cb(unsigned lon |
| /* fall through */ |
| case NETEV_ADDR6_ADD: |
| setup_addr_for_relaying(&info->addr.in6, iface, add); |
| + if (iface->ndp == MODE_RELAY && iface->master) { |
| + avl_for_each_element(&interfaces, c, avl) { |
| + syslog(LOG_DEBUG, "setup_route add:%d. dev:%s(%d) %d", add, c->name, c->ifindex, c->ndp); |
| + if (c->ndp == MODE_RELAY && !c->master) |
| + netlink_setup_route(&info->addr.in6, 64, c->ifindex, NULL, 1024, add); |
| + } |
| + } |
| + /* Keep neighbor entries alive so we don't loose routes */ |
| + if (add) |
| + ping6(&info->addr.in6, iface); |
| break; |
| case NETEV_NEIGH6_DEL: |
| add = false; |
| @@ -271,6 +283,8 @@ static void ndp_netevent_cb(unsigned lon |
| |
| if (!add) |
| netlink_dump_neigh_table(false); |
| + else |
| + ping6(&info->addr.in6, iface); |
| break; |
| default: |
| break; |
| --- a/src/netlink.c |
| +++ b/src/netlink.c |
| @@ -179,7 +179,7 @@ static void refresh_iface_addr4(int ifin |
| free(addr); |
| } |
| |
| -static void refresh_iface_addr6(int ifindex) |
| +static void refresh_iface_addr6(int ifindex, bool add) |
| { |
| struct odhcpd_ipaddr *addr = NULL; |
| struct interface *iface; |
| @@ -283,6 +283,17 @@ static void refresh_iface_addr6(int ifin |
| break; |
| |
| memcpy(addr, iface->addr6, len * sizeof(*addr)); |
| + |
| + if (iface->ndp == MODE_RELAY && iface->master) { |
| + // Replay address changes on all slave interfaces |
| + struct interface *c; |
| + avl_for_each_element(&interfaces, c, avl) { |
| + syslog(LOG_DEBUG, "Replay address changes on all slave interfaces @ %s %d %d %d", c->name, c->ifindex, c->ndp, c->master); |
| + if (c->ndp == MODE_RELAY && !c->master) { |
| + netlink_setup_addr(addr, c->ifindex, true, add); |
| + } |
| + } |
| + } |
| } |
| |
| free(addr); |
| @@ -415,7 +426,7 @@ static int handle_rtm_addr(struct nlmsgh |
| &event_info); |
| } |
| |
| - refresh_iface_addr6(ifa->ifa_index); |
| + refresh_iface_addr6(ifa->ifa_index, add); |
| } else { |
| if (!nla[IFA_LOCAL]) |
| return NL_SKIP; |