X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fodhcpd.c;h=5774a4f5d399006bb2a2b60df219fde88c6cfdc9;hp=3fb3009e56e5a14b12731b88ac324ab5b85f554d;hb=42cdb6d45ac8dd677f40fe66c72c6028e853fc89;hpb=fd3e3bbc461fcbbaefff9339da2e9b6c85a5b4a1 diff --git a/src/odhcpd.c b/src/odhcpd.c index 3fb3009..5774a4f 100644 --- a/src/odhcpd.c +++ b/src/odhcpd.c @@ -174,12 +174,6 @@ ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest, || IN6_IS_ADDR_MC_LINKLOCAL(&dest->sin6_addr)) dest->sin6_scope_id = iface->ifindex; - // IPV6_PKTINFO doesn't really work for IPv6-raw sockets (bug?) - if (dest->sin6_port == 0) { - msg.msg_control = NULL; - msg.msg_controllen = 0; - } - char ipbuf[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &dest->sin6_addr, ipbuf, sizeof(ipbuf)); @@ -194,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) { - // TODO - cb_neigh(NULL, 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) @@ -335,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;