network: move manager_rtnl_process_neighbor() to networkd-neighbor.c
This commit is contained in:
@@ -538,186 +538,6 @@ static int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *mess
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(message);
|
|
||||||
assert(lladdr);
|
|
||||||
assert(size);
|
|
||||||
assert(str);
|
|
||||||
|
|
||||||
*str = NULL;
|
|
||||||
|
|
||||||
r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6);
|
|
||||||
if (r >= 0) {
|
|
||||||
*size = sizeof(lladdr->ip.in6);
|
|
||||||
if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0)
|
|
||||||
log_warning_errno(r, "Could not print lower address: %m");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac);
|
|
||||||
if (r >= 0) {
|
|
||||||
*size = sizeof(lladdr->mac);
|
|
||||||
*str = new(char, ETHER_ADDR_TO_STRING_MAX);
|
|
||||||
if (!*str) {
|
|
||||||
log_oom();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
ether_addr_to_string(&lladdr->mac, *str);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in);
|
|
||||||
if (r >= 0) {
|
|
||||||
*size = sizeof(lladdr->ip.in);
|
|
||||||
if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0)
|
|
||||||
log_warning_errno(r, "Could not print lower address: %m");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
|
||||||
Link *link = NULL;
|
|
||||||
Neighbor *neighbor = NULL;
|
|
||||||
int ifindex, family, r;
|
|
||||||
uint16_t type, state;
|
|
||||||
union in_addr_union in_addr = IN_ADDR_NULL;
|
|
||||||
_cleanup_free_ char *addr_str = NULL;
|
|
||||||
union lladdr_union lladdr;
|
|
||||||
size_t lladdr_size = 0;
|
|
||||||
_cleanup_free_ char *lladdr_str = NULL;
|
|
||||||
|
|
||||||
assert(rtnl);
|
|
||||||
assert(message);
|
|
||||||
assert(m);
|
|
||||||
|
|
||||||
if (sd_netlink_message_is_error(message)) {
|
|
||||||
r = sd_netlink_message_get_errno(message);
|
|
||||||
if (r < 0)
|
|
||||||
log_message_warning_errno(message, r, "rtnl: failed to receive neighbor message, ignoring");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_get_type(message, &type);
|
|
||||||
if (r < 0) {
|
|
||||||
log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
} else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) {
|
|
||||||
log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_rtnl_message_neigh_get_state(message, &state);
|
|
||||||
if (r < 0) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
} else if (!FLAGS_SET(state, NUD_PERMANENT)) {
|
|
||||||
log_debug("rtnl: received non-static neighbor, ignoring.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex);
|
|
||||||
if (r < 0) {
|
|
||||||
log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
} else if (ifindex <= 0) {
|
|
||||||
log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = link_get(m, ifindex, &link);
|
|
||||||
if (r < 0 || !link) {
|
|
||||||
/* when enumerating we might be out of sync, but we will get the neighbor again, so just
|
|
||||||
* ignore it */
|
|
||||||
if (!m->enumerating)
|
|
||||||
log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_rtnl_message_neigh_get_family(message, &family);
|
|
||||||
if (r < 0) {
|
|
||||||
log_link_warning(link, "rtnl: received neighbor message without family, ignoring.");
|
|
||||||
return 0;
|
|
||||||
} else if (!IN_SET(family, AF_INET, AF_INET6)) {
|
|
||||||
log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", family);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (family) {
|
|
||||||
case AF_INET:
|
|
||||||
r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in);
|
|
||||||
if (r < 0) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AF_INET6:
|
|
||||||
r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6);
|
|
||||||
if (r < 0) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert_not_reached("Received unsupported address family");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_addr_to_string(family, &in_addr, &addr_str) < 0)
|
|
||||||
log_link_warning_errno(link, r, "Could not print address: %m");
|
|
||||||
|
|
||||||
r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str);
|
|
||||||
if (r < 0) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case RTM_NEWNEIGH:
|
|
||||||
if (neighbor)
|
|
||||||
log_link_debug(link, "Received remembered neighbor: %s->%s",
|
|
||||||
strnull(addr_str), strnull(lladdr_str));
|
|
||||||
else {
|
|
||||||
/* A neighbor appeared that we did not request */
|
|
||||||
r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
|
|
||||||
if (r < 0) {
|
|
||||||
log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m",
|
|
||||||
strnull(addr_str), strnull(lladdr_str));
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
log_link_debug(link, "Remembering foreign neighbor: %s->%s",
|
|
||||||
strnull(addr_str), strnull(lladdr_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_DELNEIGH:
|
|
||||||
if (neighbor) {
|
|
||||||
log_link_debug(link, "Forgetting neighbor: %s->%s",
|
|
||||||
strnull(addr_str), strnull(lladdr_str));
|
|
||||||
(void) neighbor_free(neighbor);
|
|
||||||
} else
|
|
||||||
log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
|
|
||||||
strnull(addr_str), strnull(lladdr_str));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert_not_reached("Received invalid RTNL message type");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
_cleanup_free_ char *buf = NULL;
|
_cleanup_free_ char *buf = NULL;
|
||||||
Link *link = NULL;
|
Link *link = NULL;
|
||||||
|
|||||||
@@ -383,6 +383,186 @@ int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(message);
|
||||||
|
assert(lladdr);
|
||||||
|
assert(size);
|
||||||
|
assert(str);
|
||||||
|
|
||||||
|
*str = NULL;
|
||||||
|
|
||||||
|
r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6);
|
||||||
|
if (r >= 0) {
|
||||||
|
*size = sizeof(lladdr->ip.in6);
|
||||||
|
if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0)
|
||||||
|
log_warning_errno(r, "Could not print lower address: %m");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac);
|
||||||
|
if (r >= 0) {
|
||||||
|
*size = sizeof(lladdr->mac);
|
||||||
|
*str = new(char, ETHER_ADDR_TO_STRING_MAX);
|
||||||
|
if (!*str) {
|
||||||
|
log_oom();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
ether_addr_to_string(&lladdr->mac, *str);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in);
|
||||||
|
if (r >= 0) {
|
||||||
|
*size = sizeof(lladdr->ip.in);
|
||||||
|
if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0)
|
||||||
|
log_warning_errno(r, "Could not print lower address: %m");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
|
Link *link = NULL;
|
||||||
|
Neighbor *neighbor = NULL;
|
||||||
|
int ifindex, family, r;
|
||||||
|
uint16_t type, state;
|
||||||
|
union in_addr_union in_addr = IN_ADDR_NULL;
|
||||||
|
_cleanup_free_ char *addr_str = NULL;
|
||||||
|
union lladdr_union lladdr;
|
||||||
|
size_t lladdr_size = 0;
|
||||||
|
_cleanup_free_ char *lladdr_str = NULL;
|
||||||
|
|
||||||
|
assert(rtnl);
|
||||||
|
assert(message);
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
if (sd_netlink_message_is_error(message)) {
|
||||||
|
r = sd_netlink_message_get_errno(message);
|
||||||
|
if (r < 0)
|
||||||
|
log_message_warning_errno(message, r, "rtnl: failed to receive neighbor message, ignoring");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_netlink_message_get_type(message, &type);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
} else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) {
|
||||||
|
log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_rtnl_message_neigh_get_state(message, &state);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
} else if (!FLAGS_SET(state, NUD_PERMANENT)) {
|
||||||
|
log_debug("rtnl: received non-static neighbor, ignoring.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
} else if (ifindex <= 0) {
|
||||||
|
log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = link_get(m, ifindex, &link);
|
||||||
|
if (r < 0 || !link) {
|
||||||
|
/* when enumerating we might be out of sync, but we will get the neighbor again, so just
|
||||||
|
* ignore it */
|
||||||
|
if (!m->enumerating)
|
||||||
|
log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_rtnl_message_neigh_get_family(message, &family);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning(link, "rtnl: received neighbor message without family, ignoring.");
|
||||||
|
return 0;
|
||||||
|
} else if (!IN_SET(family, AF_INET, AF_INET6)) {
|
||||||
|
log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", family);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (family) {
|
||||||
|
case AF_INET:
|
||||||
|
r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AF_INET6:
|
||||||
|
r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert_not_reached("Received unsupported address family");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_addr_to_string(family, &in_addr, &addr_str) < 0)
|
||||||
|
log_link_warning_errno(link, r, "Could not print address: %m");
|
||||||
|
|
||||||
|
r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RTM_NEWNEIGH:
|
||||||
|
if (neighbor)
|
||||||
|
log_link_debug(link, "Received remembered neighbor: %s->%s",
|
||||||
|
strnull(addr_str), strnull(lladdr_str));
|
||||||
|
else {
|
||||||
|
/* A neighbor appeared that we did not request */
|
||||||
|
r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m",
|
||||||
|
strnull(addr_str), strnull(lladdr_str));
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
log_link_debug(link, "Remembering foreign neighbor: %s->%s",
|
||||||
|
strnull(addr_str), strnull(lladdr_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_DELNEIGH:
|
||||||
|
if (neighbor) {
|
||||||
|
log_link_debug(link, "Forgetting neighbor: %s->%s",
|
||||||
|
strnull(addr_str), strnull(lladdr_str));
|
||||||
|
(void) neighbor_free(neighbor);
|
||||||
|
} else
|
||||||
|
log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
|
||||||
|
strnull(addr_str), strnull(lladdr_str));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert_not_reached("Received invalid RTNL message type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int neighbor_section_verify(Neighbor *neighbor) {
|
int neighbor_section_verify(Neighbor *neighbor) {
|
||||||
if (section_is_invalid(neighbor->section))
|
if (section_is_invalid(neighbor->section))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ int neighbor_section_verify(Neighbor *neighbor);
|
|||||||
|
|
||||||
int link_set_neighbors(Link *link);
|
int link_set_neighbors(Link *link);
|
||||||
|
|
||||||
|
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
|
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
|
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr);
|
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr);
|
||||||
|
|||||||
Reference in New Issue
Block a user