summaryrefslogtreecommitdiff
path: root/zebra/kernel_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/kernel_netlink.c')
-rw-r--r--zebra/kernel_netlink.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 4bd0ac27f6..31d8294a0f 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -290,9 +290,20 @@ static int netlink_recvbuf(struct nlsock *nl, uint32_t newsize)
return 0;
}
+static const char *group2str(uint32_t group)
+{
+ switch (group) {
+ case RTNLGRP_TUNNEL:
+ return "RTNLGRP_TUNNEL";
+ default:
+ return "UNKNOWN";
+ }
+}
+
/* Make socket for Linux netlink interface. */
static int netlink_socket(struct nlsock *nl, unsigned long groups,
- unsigned long ext_groups, ns_id_t ns_id)
+ uint32_t ext_groups[], uint8_t ext_group_size,
+ ns_id_t ns_id)
{
int ret;
struct sockaddr_nl snl;
@@ -311,18 +322,30 @@ static int netlink_socket(struct nlsock *nl, unsigned long groups,
snl.nl_family = AF_NETLINK;
snl.nl_groups = groups;
+ if (ext_group_size) {
+ uint8_t i;
+
+ for (i = 0; i < ext_group_size; i++) {
#if defined SOL_NETLINK
- if (ext_groups) {
- ret = setsockopt(sock, SOL_NETLINK,
- NETLINK_ADD_MEMBERSHIP, &ext_groups,
- sizeof(ext_groups));
- if (ret < 0) {
+ ret = setsockopt(sock, SOL_NETLINK,
+ NETLINK_ADD_MEMBERSHIP,
+ &ext_groups[i],
+ sizeof(ext_groups[i]));
+ if (ret < 0) {
+ zlog_notice(
+ "can't setsockopt NETLINK_ADD_MEMBERSHIP for group %s(%u), this linux kernel does not support it: %s(%d)",
+ group2str(ext_groups[i]),
+ ext_groups[i],
+ safe_strerror(errno), errno);
+ }
+#else
zlog_notice(
- "can't setsockopt NETLINK_ADD_MEMBERSHIP: %s(%d)",
- safe_strerror(errno), errno);
+ "Unable to use NETLINK_ADD_MEMBERSHIP via SOL_NETLINK for %s(%u) since the linux kernel does not support the socket option",
+ group2str(ext_groups[i]),
+ ext_groups[i]);
+#endif
}
}
-#endif
/* Bind the socket to the netlink structure for anything. */
ret = bind(sock, (struct sockaddr *)&snl, sizeof(snl));
@@ -1734,7 +1757,8 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink.name, sizeof(zns->netlink.name),
"netlink-listen (NS %u)", zns->ns_id);
zns->netlink.sock = -1;
- if (netlink_socket(&zns->netlink, groups, ext_groups, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink, groups, &ext_groups, 1, zns->ns_id) <
+ 0) {
zlog_err("Failure to create %s socket",
zns->netlink.name);
exit(-1);
@@ -1745,7 +1769,7 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
"netlink-cmd (NS %u)", zns->ns_id);
zns->netlink_cmd.sock = -1;
- if (netlink_socket(&zns->netlink_cmd, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_cmd, 0, 0, 0, zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_cmd.name);
exit(-1);
@@ -1758,7 +1782,7 @@ void kernel_init(struct zebra_ns *zns)
sizeof(zns->netlink_dplane_out.name), "netlink-dp (NS %u)",
zns->ns_id);
zns->netlink_dplane_out.sock = -1;
- if (netlink_socket(&zns->netlink_dplane_out, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_dplane_out, 0, 0, 0, zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_out.name);
exit(-1);
@@ -1771,7 +1795,7 @@ void kernel_init(struct zebra_ns *zns)
sizeof(zns->netlink_dplane_in.name), "netlink-dp-in (NS %u)",
zns->ns_id);
zns->netlink_dplane_in.sock = -1;
- if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, 0,
+ if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, 0, 0,
zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_in.name);