diff --git a/src/drivers/netlink.c b/src/drivers/netlink.c index 0e960f48c..de89f0543 100644 --- a/src/drivers/netlink.c +++ b/src/drivers/netlink.c @@ -32,6 +32,15 @@ static void netlink_receive_link(struct netlink_data *netlink, NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg))); } +static void netlink_receive_neigh(struct netlink_data *netlink, + void (*cb)(void *ctx, struct nlmsghdr *h), + struct nlmsghdr *h) +{ + if (cb == NULL) + return; + cb(netlink->cfg->ctx, h); +} + static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx) { @@ -61,10 +70,21 @@ static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx) netlink_receive_link(netlink, netlink->cfg->newlink_cb, h); break; + case RTM_DELLINK: netlink_receive_link(netlink, netlink->cfg->dellink_cb, h); break; + + case RTM_NEWNEIGH: + netlink_receive_neigh(netlink, netlink->cfg->newneigh_cb, + h); + break; + + case RTM_DELNEIGH: + netlink_receive_neigh(netlink, netlink->cfg->delneigh_cb, + h); + break; } h = NLMSG_NEXT(h, left); @@ -107,7 +127,9 @@ struct netlink_data * netlink_init(struct netlink_config *cfg) os_memset(&local, 0, sizeof(local)); local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; + local.nl_groups = 0; + local.nl_groups |= nl_mgrp(RTMGRP_LINK); + local.nl_groups |= nl_mgrp(RTMGRP_NEIGH); if (bind(netlink->sock, (struct sockaddr *) &local, sizeof(local)) < 0) { wpa_printf(MSG_ERROR, "netlink: Failed to bind netlink " diff --git a/src/drivers/netlink.h b/src/drivers/netlink.h index 3a7340e51..f0442248d 100644 --- a/src/drivers/netlink.h +++ b/src/drivers/netlink.h @@ -18,8 +18,19 @@ struct netlink_config { size_t len); void (*dellink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf, size_t len); + void (*newneigh_cb)(void *ctx, struct nlmsghdr *h); + void (*delneigh_cb)(void *ctx, struct nlmsghdr *h); }; +static inline u32 nl_mgrp(u32 group) +{ + if (group > 31 ) { + fprintf(stderr, "Use setsockopt for this group %d\n", group); + return(0); + } + return group ? (1 << (group - 1)) : 0; +} + struct netlink_data * netlink_init(struct netlink_config *cfg); void netlink_deinit(struct netlink_data *netlink); int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex, diff --git a/src/drivers/priv_netlink.h b/src/drivers/priv_netlink.h index d3f091c39..e6b24f2f4 100644 --- a/src/drivers/priv_netlink.h +++ b/src/drivers/priv_netlink.h @@ -40,11 +40,16 @@ #define NETLINK_ROUTE 0 #define RTMGRP_LINK 1 +#define RTMGRP_NOTIFY 2 +#define RTMGRP_NEIGH 3 + #define RTM_BASE 0x10 #define RTM_NEWLINK (RTM_BASE + 0) #define RTM_DELLINK (RTM_BASE + 1) #define RTM_SETLINK (RTM_BASE + 3) +#define RTM_NEWNEIGH 28 +#define RTM_DELNEIGH 29 #define NLMSG_ALIGNTO 4 #define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1)) #define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))