diff options
author | Hans Dedecker <dedeckeh@gmail.com> | 2017-02-01 10:44:51 +0100 |
---|---|---|
committer | Hans Dedecker <dedeckeh@gmail.com> | 2017-02-09 15:00:50 +0100 |
commit | 8a615ad3c4f2318667630e2505888df09901320d (patch) | |
tree | 9e80bd99135b1919a263adc5ce79d645f9bbd3af /src/odhcpd.c | |
parent | 0129f7926b9a0f993058dca9775e64021527eb32 (diff) |
npd: rework IPv6 relay logic (FS#396)
Rework the IPv6 relay logic to make it more robust by making
use of libnltiny to process netlink messages.
At the same time reimplement the IPv6 relay finite state machine
to make the relay logic less error prone
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
Diffstat (limited to 'src/odhcpd.c')
-rw-r--r-- | src/odhcpd.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/src/odhcpd.c b/src/odhcpd.c index f259239..97d33e1 100644 --- a/src/odhcpd.c +++ b/src/odhcpd.c @@ -31,6 +31,7 @@ #include <netpacket/packet.h> #include <linux/netlink.h> #include <linux/if_addr.h> +#include <linux/neighbour.h> #include <linux/rtnetlink.h> #include <sys/socket.h> @@ -94,7 +95,7 @@ int main(int argc, char **argv) ioctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (!(rtnl_socket = odhcpd_create_nl_socket(NETLINK_ROUTE, 0))) { + if (!(rtnl_socket = odhcpd_create_nl_socket(NETLINK_ROUTE))) { syslog(LOG_ERR, "Unable to open nl socket: %s", strerror(errno)); return 2; } @@ -122,7 +123,7 @@ int main(int argc, char **argv) return 0; } -struct nl_sock *odhcpd_create_nl_socket(int protocol, int groups) +struct nl_sock *odhcpd_create_nl_socket(int protocol) { struct nl_sock *nl_sock; @@ -130,9 +131,6 @@ struct nl_sock *odhcpd_create_nl_socket(int protocol, int groups) if (!nl_sock) goto err; - if (groups) - nl_join_groups(nl_sock, groups); - if (nl_connect(nl_sock, protocol) < 0) goto err; @@ -356,9 +354,9 @@ int odhcpd_get_linklocal_interface_address(int ifindex, struct in6_addr *lladdr) return status; } -int odhcpd_setup_route(const struct in6_addr *addr, int prefixlen, +int odhcpd_setup_route(const struct in6_addr *addr, const int prefixlen, const struct interface *iface, const struct in6_addr *gw, - uint32_t metric, bool add) + const uint32_t metric, const bool add) { struct nl_msg *msg; struct rtmsg rtm = { @@ -395,6 +393,37 @@ int odhcpd_setup_route(const struct in6_addr *addr, int prefixlen, return nl_wait_for_ack(rtnl_socket); } +int odhcpd_setup_proxy_neigh(const struct in6_addr *addr, + const struct interface *iface, const bool add) +{ + struct nl_msg *msg; + struct ndmsg ndm = { + .ndm_family = AF_INET6, + .ndm_flags = NTF_PROXY, + .ndm_ifindex = iface->ifindex, + }; + int ret = 0, flags = NLM_F_REQUEST; + + if (add) + flags |= NLM_F_REPLACE | NLM_F_CREATE; + + msg = nlmsg_alloc_simple(add ? RTM_NEWNEIGH : RTM_DELNEIGH, flags); + if (!msg) + return -1; + + nlmsg_append(msg, &ndm, sizeof(ndm), 0); + + nla_put(msg, NDA_DST, sizeof(*addr), addr); + + ret = nl_send_auto_complete(rtnl_socket, msg); + nlmsg_free(msg); + + if (ret < 0) + return ret; + + return nl_wait_for_ack(rtnl_socket); +} + struct interface* odhcpd_get_interface_by_index(int ifindex) { struct interface *iface; @@ -450,6 +479,11 @@ static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int even e->handle_error(ret); } + if (e->recv_msgs) { + e->recv_msgs(e); + return; + } + while (true) { struct iovec iov = {data_buf, sizeof(data_buf)}; struct msghdr msg = { |