module/network: break out message parsing code

This also allows us to actually handle errors (by aborting run())
This commit is contained in:
Daniel Eklöf 2018-12-31 13:36:44 +01:00
parent 8352d89491
commit dcf8051f1a

View file

@ -33,6 +33,10 @@ struct private {
char *iface; char *iface;
struct particle *label; struct particle *label;
int nl_sock;
bool get_addresses;
int ifindex; int ifindex;
uint8_t mac[6]; uint8_t mac[6];
bool carrier; bool carrier;
@ -47,6 +51,8 @@ destroy(struct module *mod)
{ {
struct private *m = mod->private; struct private *m = mod->private;
assert(m->nl_sock == -1);
m->label->destroy(m->label); m->label->destroy(m->label);
tll_free(m->addrs); tll_free(m->addrs);
@ -304,8 +310,10 @@ handle_address(struct module *mod, uint16_t type,
const void *raw_addr = RTA_DATA(attr); const void *raw_addr = RTA_DATA(attr);
size_t addr_len = RTA_PAYLOAD(attr); size_t addr_len = RTA_PAYLOAD(attr);
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
char s[INET6_ADDRSTRLEN]; char s[INET6_ADDRSTRLEN];
inet_ntop(msg->ifa_family, raw_addr, s, sizeof(s)); inet_ntop(msg->ifa_family, raw_addr, s, sizeof(s));
#endif
LOG_DBG("%s: IFA_ADDRESS: %s", m->iface, s); LOG_DBG("%s: IFA_ADDRESS: %s", m->iface, s);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
@ -379,6 +387,61 @@ netlink_receive_messages(int sock, void **reply, size_t *len)
return true; return true;
} }
static bool
process_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
{
struct private *m = mod->private;
/* Process response */
for (; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
switch (hdr->nlmsg_type) {
case NLMSG_DONE:
if (m->ifindex == -1) {
LOG_ERR("%s: failed to find interface", m->iface);
return false;
}
/* Request initial list of IPv4/6 addresses */
if (m->get_addresses && m->ifindex != -1) {
m->get_addresses = false;
send_rt_request(m->nl_sock, RTM_GETADDR);
}
break;
case RTM_NEWLINK:
case RTM_DELLINK: {
const struct ifinfomsg *msg = NLMSG_DATA(hdr);
size_t msg_len = IFLA_PAYLOAD(hdr);
handle_link(mod, hdr->nlmsg_type, msg, msg_len);
break;
}
case RTM_NEWADDR:
case RTM_DELADDR: {
const struct ifaddrmsg *msg = NLMSG_DATA(hdr);
size_t msg_len = IFA_PAYLOAD(hdr);
handle_address(mod, hdr->nlmsg_type, msg, msg_len);
break;
}
case NLMSG_ERROR:{
const struct nlmsgerr *err = NLMSG_DATA(hdr);
LOG_ERRNO_P("netlink", err->error);
return false;
}
default:
LOG_WARN(
"unrecognized netlink message type: 0x%x", hdr->nlmsg_type);
break;
}
}
return true;
}
static int static int
run(struct module_run_context *ctx) run(struct module_run_context *ctx)
{ {
@ -387,24 +450,21 @@ run(struct module_run_context *ctx)
module_signal_ready(ctx); module_signal_ready(ctx);
int nl_sock = netlink_connect(); m->nl_sock = netlink_connect();
if (nl_sock == -1) if (m->nl_sock == -1)
return 1; return 1;
if (!send_rt_request(nl_sock, RTM_GETLINK)) { if (!send_rt_request(m->nl_sock, RTM_GETLINK)) {
close(nl_sock); close(m->nl_sock);
m->nl_sock = -1;
return 1; return 1;
} }
/* We must wait for NLMSG_DONE from the first request, before
* sending another one... */
bool get_addresses = true;
/* Main loop */ /* Main loop */
while (true) { while (true) {
struct pollfd fds[] = { struct pollfd fds[] = {
{.fd = ctx->abort_fd, .events = POLLIN}, {.fd = ctx->abort_fd, .events = POLLIN},
{.fd = nl_sock, .events = POLLIN} {.fd = m->nl_sock, .events = POLLIN}
}; };
poll(fds, 2, -1); poll(fds, 2, -1);
@ -422,58 +482,19 @@ run(struct module_run_context *ctx)
/* Read one (or more) messages */ /* Read one (or more) messages */
void *reply; void *reply;
size_t len; size_t len;
if (!netlink_receive_messages(nl_sock, &reply, &len)) if (!netlink_receive_messages(m->nl_sock, &reply, &len))
break; break;
/* Process response */ if (!process_reply(mod, (const struct nlmsghdr *)reply, len)) {
for (const struct nlmsghdr *hdr = (const struct nlmsghdr *)reply; free(reply);
NLMSG_OK(hdr, len); break;
hdr = NLMSG_NEXT(hdr, len))
{
switch (hdr->nlmsg_type) {
case NLMSG_DONE:
/* Request initial list of IPv4/6 addresses */
if (get_addresses && m->ifindex != -1) {
get_addresses = false;
send_rt_request(nl_sock, RTM_GETADDR);
}
break;
case RTM_NEWLINK:
case RTM_DELLINK: {
const struct ifinfomsg *msg = NLMSG_DATA(hdr);
size_t msg_len = IFLA_PAYLOAD(hdr);
handle_link(mod, hdr->nlmsg_type, msg, msg_len);
break;
}
case RTM_NEWADDR:
case RTM_DELADDR: {
const struct ifaddrmsg *msg = NLMSG_DATA(hdr);
size_t msg_len = IFA_PAYLOAD(hdr);
handle_address(mod, hdr->nlmsg_type, msg, msg_len);
break;
}
case NLMSG_ERROR:{
const struct nlmsgerr *err = NLMSG_DATA(hdr);
LOG_ERRNO_P("netlink", err->error);
break;
}
default:
LOG_WARN(
"unrecognized netlink message type: 0x%x", hdr->nlmsg_type);
break;
}
} }
free(reply); free(reply);
} }
close(nl_sock); close(m->nl_sock);
m->nl_sock = -1;
return 0; return 0;
} }
@ -484,6 +505,8 @@ module_network(const char *iface, struct particle *label)
priv->iface = strdup(iface); priv->iface = strdup(iface);
priv->label = label; priv->label = label;
priv->nl_sock = -1;
priv->get_addresses = true;
priv->ifindex = -1; priv->ifindex = -1;
priv->carrier = false; priv->carrier = false;
priv->state = IF_OPER_DOWN; priv->state = IF_OPER_DOWN;