X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fodhcpd.c;h=837004b0be95eed67bef9769522d4e6ce4455869;hp=6f38d5c1c06117aa182ea9862234ba76cff6e24e;hb=f0e354befd6f787c1ed8ebc1ea514e9195f54433;hpb=18df6cca092743a07be8e0f05d0a9ef941957b66 diff --git a/src/odhcpd.c b/src/odhcpd.c index 6f38d5c..837004b 100644 --- a/src/odhcpd.c +++ b/src/odhcpd.c @@ -234,7 +234,7 @@ static int cb_valid_handler(struct nl_msg *msg, void *arg) struct odhcpd_ipaddr *addrs = *(ctxt->addrs); struct nlmsghdr *hdr = nlmsg_hdr(msg); struct ifaddrmsg *ifa; - struct nlattr *nla[__IFA_MAX]; + struct nlattr *nla[__IFA_MAX], *nla_addr = NULL; if (hdr->nlmsg_type != RTM_NEWADDR) return NL_SKIP; @@ -246,7 +246,22 @@ static int cb_valid_handler(struct nl_msg *msg, void *arg) return NL_SKIP; nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL); - if (!nla[IFA_ADDRESS]) + + switch (ifa->ifa_family) { + case AF_INET6: + if (nla[IFA_ADDRESS]) + nla_addr = nla[IFA_ADDRESS]; + break; + + case AF_INET: + if (nla[IFA_LOCAL]) + nla_addr = nla[IFA_LOCAL]; + break; + + default: + break; + } + if (!nla_addr) return NL_SKIP; addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1)); @@ -256,9 +271,13 @@ static int cb_valid_handler(struct nl_msg *msg, void *arg) memset(&addrs[ctxt->ret], 0, sizeof(addrs[ctxt->ret])); addrs[ctxt->ret].prefix = ifa->ifa_prefixlen; - nla_memcpy(&addrs[ctxt->ret].addr, nla[IFA_ADDRESS], + nla_memcpy(&addrs[ctxt->ret].addr, nla_addr, sizeof(addrs[ctxt->ret].addr)); + if (nla[IFA_BROADCAST]) + nla_memcpy(&addrs[ctxt->ret].broadcast, nla[IFA_BROADCAST], + sizeof(addrs[ctxt->ret].broadcast)); + if (nla[IFA_CACHEINFO]) { struct ifa_cacheinfo *ifc = nla_data(nla[IFA_CACHEINFO]); @@ -295,8 +314,15 @@ static int cb_error_handler(_unused struct sockaddr_nl *nla, struct nlmsgerr *er return NL_STOP; } -// compare prefixes -static int prefixcmp(const void *va, const void *vb) +static int prefix_cmp(const void *va, const void *vb) +{ + const struct odhcpd_ipaddr *a = va, *b = vb; + return (ntohl(a->addr.in.s_addr) < ntohl(b->addr.in.s_addr)) ? 1 : + (ntohl(a->addr.in.s_addr) > ntohl(b->addr.in.s_addr)) ? -1 : 0; +} + +// compare IPv6 prefixes +static int prefix6_cmp(const void *va, const void *vb) { const struct odhcpd_ipaddr *a = va, *b = vb; uint32_t a_pref = IN6_IS_ADDR_ULA(&a->addr.in6) ? 1 : a->preferred; @@ -353,7 +379,7 @@ ssize_t odhcpd_get_interface_addresses(int ifindex, bool v6, struct odhcpd_ipadd time_t now = odhcpd_time(); struct odhcpd_ipaddr *addr = *addrs; - qsort(addr, ctxt.ret, sizeof(*addr), prefixcmp); + qsort(addr, ctxt.ret, sizeof(*addr), v6 ? prefix6_cmp : prefix_cmp); for (ssize_t i = 0; i < ctxt.ret; ++i) { if (addr[i].preferred < UINT32_MAX - now) @@ -540,7 +566,7 @@ static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int even { struct odhcpd_event *e = container_of(u, struct odhcpd_event, uloop); - uint8_t data_buf[RELAYD_BUFFER_SIZE], cmsg_buf[128]; + uint8_t data_buf[8192], cmsg_buf[128]; union { struct sockaddr_in6 in6; struct sockaddr_in in;