X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fndp.c;h=b4767ea618eebc81f156f0ac77145e22851488d3;hp=e201ac99f44826ff889d7c5bfe575d093376322d;hb=94afe3bf59b7ad6f3f7a4d0de609412b88387586;hpb=eea7d037b93020dd5d5d2e5a698e88650a0f0912 diff --git a/src/ndp.c b/src/ndp.c index e201ac9..b4767ea 100644 --- a/src/ndp.c +++ b/src/ndp.c @@ -33,9 +33,8 @@ #include #include -#include "router.h" #include "dhcpv6.h" -#include "ndp.h" +#include "odhcpd.h" struct event_socket { struct odhcpd_event ev; @@ -49,7 +48,6 @@ static void handle_rtnl_event(struct odhcpd_event *ev); static int cb_rtnl_valid(struct nl_msg *msg, void *arg); static void catch_rtnl_err(struct odhcpd_event *e, int error); -static int addr6_dump_rqs = 0; static int ping_socket = -1; static struct event_socket rtnl_event = { .ev = { @@ -151,11 +149,11 @@ static void dump_neigh_table(const bool proxy) nlmsg_free(msg); } -static void dump_addr6_table(void) +static void dump_addr_table(bool v6) { struct nl_msg *msg; struct ifaddrmsg ifa = { - .ifa_family = AF_INET6, + .ifa_family = v6 ? AF_INET6 : AF_INET, }; msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); @@ -169,20 +167,6 @@ static void dump_addr6_table(void) nlmsg_free(msg); } -void ndp_handle_addr6_dump(void) -{ - if (!addr6_dump_rqs) - return; - - dump_addr6_table(); - addr6_dump_rqs = 0; -} - -inline void ndp_rqs_addr6_dump(void) -{ - addr6_dump_rqs++; -} - int setup_ndp_interface(struct interface *iface, bool enable) { int ret = 0, procfd; @@ -254,8 +238,6 @@ int setup_ndp_interface(struct interface *iface, bool enable) dump_neigh_table(false); else dump_neigh = false; - - ndp_rqs_addr6_dump(); } if (dump_neigh) @@ -341,40 +323,18 @@ static void setup_route(struct in6_addr *addr, struct interface *iface, bool add odhcpd_setup_route(addr, 128, iface, NULL, 1024, add); } -// compare prefixes -static int prefixcmp(const void *va, const void *vb) -{ - const struct odhcpd_ipaddr *a = va, *b = vb; - uint32_t a_pref = IN6_IS_ADDR_ULA(&a->addr) ? 1 : a->preferred; - uint32_t b_pref = IN6_IS_ADDR_ULA(&b->addr) ? 1 : b->preferred; - return (a_pref < b_pref) ? 1 : (a_pref > b_pref) ? -1 : 0; -} - // Check address update -static void check_addr_updates(struct interface *iface) +static void check_addr6_updates(struct interface *iface) { - struct odhcpd_ipaddr addr[RELAYD_MAX_ADDRS] = {{IN6ADDR_ANY_INIT, 0, 0, 0, 0}}; - time_t now = odhcpd_time(); - ssize_t len = odhcpd_get_interface_addresses(iface->ifindex, addr, ARRAY_SIZE(addr)); + struct odhcpd_ipaddr *addr = NULL; + ssize_t len = odhcpd_get_interface_addresses(iface->ifindex, true, &addr); if (len < 0) return; - qsort(addr, len, sizeof(*addr), prefixcmp); - - for (int i = 0; i < len; ++i) { - addr[i].addr.s6_addr32[3] = 0; - - if (addr[i].preferred < UINT32_MAX - now) - addr[i].preferred += now; - - if (addr[i].valid < UINT32_MAX - now) - addr[i].valid += now; - } - bool change = len != (ssize_t)iface->ia_addr_len; for (ssize_t i = 0; !change && i < len; ++i) - if (!IN6_ARE_ADDR_EQUAL(&addr[i].addr, &iface->ia_addr[i].addr) || + if (!IN6_ARE_ADDR_EQUAL(&addr[i].addr.in6, &iface->ia_addr[i].addr.in6) || (addr[i].preferred > 0) != (iface->ia_addr[i].preferred > 0) || addr[i].valid < iface->ia_addr[i].valid || addr[i].preferred < iface->ia_addr[i].preferred) @@ -383,11 +343,12 @@ static void check_addr_updates(struct interface *iface) if (change) dhcpv6_ia_preupdate(iface); - memcpy(iface->ia_addr, addr, len * sizeof(*addr)); + free(iface->ia_addr); + iface->ia_addr = addr; iface->ia_addr_len = len; if (change) - dhcpv6_ia_postupdate(iface, now); + dhcpv6_ia_postupdate(iface); if (change) { syslog(LOG_INFO, "Raising SIGUSR1 due to address change on %s", iface->ifname); @@ -395,7 +356,7 @@ static void check_addr_updates(struct interface *iface) } } -void setup_addr_for_relaying(struct in6_addr *addr, struct interface *iface, bool add) +static void setup_addr_for_relaying(struct in6_addr *addr, struct interface *iface, bool add) { struct interface *c; char ipbuf[INET6_ADDRSTRLEN]; @@ -406,32 +367,17 @@ void setup_addr_for_relaying(struct in6_addr *addr, struct interface *iface, boo if (iface == c || (c->ndp != RELAYD_RELAY && !add)) continue; - add = (c->ndp == RELAYD_RELAY ? add : false); + bool neigh_add = (c->ndp == RELAYD_RELAY ? add : false); - if (odhcpd_setup_proxy_neigh(addr, c, add)) + if (odhcpd_setup_proxy_neigh(addr, c, neigh_add)) syslog(LOG_DEBUG, "Failed to %s proxy neighbour entry %s%%%s", - add ? "add" : "delete", ipbuf, iface->ifname); + neigh_add ? "add" : "delete", ipbuf, c->ifname); else syslog(LOG_DEBUG, "%s proxy neighbour entry %s%%%s", - add ? "Added" : "Deleted", ipbuf, iface->ifname); + neigh_add ? "Added" : "Deleted", ipbuf, c->ifname); } } -void setup_ping6(struct in6_addr *addr, struct interface *iface) -{ - struct interface *c; - - list_for_each_entry(c, &interfaces, head) { - if (iface == c || c->ndp != RELAYD_RELAY || - c->external == true) - continue; - - ping6(addr, c); - } -} - -static struct in6_addr last_solicited; - static void handle_rtnl_event(struct odhcpd_event *e) { struct event_socket *ev_sock = container_of(e, struct event_socket, ev); @@ -468,6 +414,7 @@ static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg) case RTM_NEWADDR: add = true; + /* fall through */ case RTM_DELADDR: { struct ifaddrmsg *ifa = nlmsg_data(hdr); struct nlattr *nla[__IFA_MAX]; @@ -490,10 +437,10 @@ static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg) return NL_SKIP; inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf)); - syslog(LOG_DEBUG, "Netlink %s %s%%%s", true ? "newaddr" : "deladdr", + syslog(LOG_DEBUG, "Netlink %s %s%%%s", add ? "newaddr" : "deladdr", ipbuf, iface->ifname); - check_addr_updates(iface); + check_addr6_updates(iface); if (iface->ndp != RELAYD_RELAY) break; @@ -508,6 +455,7 @@ static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg) case RTM_NEWNEIGH: add = true; + /* fall through */ case RTM_DELNEIGH: { struct ndmsg *ndm = nlmsg_data(hdr); struct nlattr *nla[__NDA_MAX]; @@ -530,7 +478,7 @@ static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg) return NL_SKIP; inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf)); - syslog(LOG_DEBUG, "Netlink %s %s%%%s", true ? "newneigh" : "delneigh", + syslog(LOG_DEBUG, "Netlink %s %s%%%s", add ? "newneigh" : "delneigh", ipbuf, iface->ifname); if (ndm->ndm_flags & NTF_PROXY) { @@ -546,14 +494,8 @@ static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg) if (add && !(ndm->ndm_state & (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE | - NUD_PERMANENT | NUD_NOARP))) { - if (!IN6_ARE_ADDR_EQUAL(&last_solicited, addr)) { - last_solicited = *addr; - setup_ping6(addr, iface); - } - + NUD_PERMANENT | NUD_NOARP))) return NL_OK; - } setup_addr_for_relaying(addr, iface, add); setup_route(addr, iface, add); @@ -583,7 +525,7 @@ static void catch_rtnl_err(struct odhcpd_event *e, int error) if (nl_socket_set_buffer_size(ev_sock->sock, ev_sock->sock_bufsize, 0)) goto err; - dump_addr6_table(); + dump_addr_table(true); return; err: