blob: e77dc8dded8db3e5b44622f296e91153b82e6b2f [file] [log] [blame]
--- 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;