X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fodhcpd.c;h=5774a4f5d399006bb2a2b60df219fde88c6cfdc9;hp=56f4498dfc8364f1b4e6593db1ed8313997c8c42;hb=0ce78e8831ef9b34f1d0a6b240e106747eae8370;hpb=69c2f4c4d46437299c9a61a51393771436b89015 diff --git a/src/odhcpd.c b/src/odhcpd.c index 56f4498..5774a4f 100644 --- a/src/odhcpd.c +++ b/src/odhcpd.c @@ -188,61 +188,6 @@ ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest, } -int odhcpd_iterate_interface_neighbors(const struct interface *iface, - void(*cb_neigh)(const struct in6_addr *addr, - const struct interface *iface, void *data), void *data) -{ - struct { - struct nlmsghdr nhm; - struct ndmsg ndm; - } req = {{sizeof(req), RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP, - ++rtnl_seq, 0}, {AF_INET6, 0, 0, iface->ifindex, 0, 0, 0}}; - - if (send(rtnl_socket, &req, sizeof(req), 0) < (ssize_t)sizeof(req)) - return -1; - - uint8_t buf[8192]; - ssize_t len = 0; - - for (struct nlmsghdr *nhm = NULL; ; nhm = NLMSG_NEXT(nhm, len)) { - while (len < 0 || !NLMSG_OK(nhm, (size_t)len)) { - len = recv(rtnl_socket, buf, sizeof(buf), 0); - nhm = (struct nlmsghdr*)buf; - if (len < 0 || !NLMSG_OK(nhm, (size_t)len)) { - if (errno == EINTR) - continue; - else - return -1; - } - } - - if (nhm->nlmsg_type != RTM_NEWNEIGH) - break; - - struct ndmsg *ndm = NLMSG_DATA(nhm); - if (ndm->ndm_ifindex != iface->ifindex || - (ndm->ndm_state & NUD_FAILED)) - continue; - - struct rtattr *rta = (struct rtattr*)&ndm[1]; - size_t alen = NLMSG_PAYLOAD(nhm, sizeof(*ndm)); - - while (RTA_OK(rta, alen)) { - if (rta->rta_type == NDA_DST && - RTA_PAYLOAD(rta) == sizeof(struct in6_addr)) { - cb_neigh(RTA_DATA(rta), iface, data); - break; - } else { - rta = RTA_NEXT(rta, alen); - } - } - - } - - return 0; -} - - // Detect an IPV6-address currently assigned to the given interface ssize_t odhcpd_get_interface_addresses(int ifindex, struct odhcpd_ipaddr *addrs, size_t cnt) @@ -329,6 +274,56 @@ int odhcpd_get_preferred_interface_address(int ifindex, struct in6_addr *addr) return ret; } +void odhcpd_setup_route(const struct in6_addr *addr, int prefixlen, + const struct interface *iface, const struct in6_addr *gw, + int metric, bool add) +{ + struct req { + struct nlmsghdr nh; + struct rtmsg rtm; + struct rtattr rta_dst; + struct in6_addr dst_addr; + struct rtattr rta_oif; + uint32_t ifindex; + struct rtattr rta_table; + uint32_t table; + struct rtattr rta_prio; + uint32_t prio; + struct rtattr rta_gw; + struct in6_addr gw; + } req = { + {sizeof(req), 0, NLM_F_REQUEST, ++rtnl_seq, 0}, + {AF_INET6, prefixlen, 0, 0, 0, 0, 0, 0, 0}, + {sizeof(struct rtattr) + sizeof(struct in6_addr), RTA_DST}, + *addr, + {sizeof(struct rtattr) + sizeof(uint32_t), RTA_OIF}, + iface->ifindex, + {sizeof(struct rtattr) + sizeof(uint32_t), RTA_TABLE}, + RT_TABLE_MAIN, + {sizeof(struct rtattr) + sizeof(uint32_t), RTA_PRIORITY}, + metric, + {sizeof(struct rtattr) + sizeof(struct in6_addr), RTA_GATEWAY}, + IN6ADDR_ANY_INIT, + }; + + if (gw) + req.gw = *gw; + + if (add) { + req.nh.nlmsg_type = RTM_NEWROUTE; + req.nh.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); + req.rtm.rtm_protocol = RTPROT_STATIC; + req.rtm.rtm_scope = (gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK; + req.rtm.rtm_type = RTN_UNICAST; + } else { + req.nh.nlmsg_type = RTM_DELROUTE; + req.rtm.rtm_scope = RT_SCOPE_NOWHERE; + } + + req.nh.nlmsg_len = (gw) ? sizeof(req) : offsetof(struct req, rta_gw); + send(rtnl_socket, &req, req.nh.nlmsg_len, MSG_DONTWAIT); +} + struct interface* odhcpd_get_interface_by_index(int ifindex) { struct interface *iface;