return 0;
}
+/* Request for specific interface or address information from the kernel */
+static int
+netlink_request_intf_addr (struct zebra_ns *zns,
+ int family, int type,
+ u_int32_t filter_mask)
+{
+ struct
+ {
+ struct nlmsghdr n;
+ struct ifinfomsg ifm;
+ char buf[256];
+ } req;
+
+ /* Form the request, specifying filter (rtattr) if needed. */
+ memset (&req, 0, sizeof (req));
+ req.n.nlmsg_type = type;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.ifm.ifi_family = family;
+
+ /* Include filter, if specified. */
+ if (filter_mask)
+ addattr32 (&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask);
+
+ return netlink_request (&zns->netlink_cmd, &req.n);
+}
+
/* Interface lookup by netlink socket. */
int
interface_lookup_netlink (struct zebra_ns *zns)
int ret;
/* Get interface information. */
- ret = netlink_request (AF_PACKET, RTM_GETLINK, &zns->netlink_cmd);
+ ret = netlink_request_intf_addr (zns, AF_PACKET, RTM_GETLINK, 0);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 1);
return ret;
/* Get IPv4 address of the interfaces. */
- ret = netlink_request (AF_INET, RTM_GETADDR, &zns->netlink_cmd);
+ ret = netlink_request_intf_addr (zns, AF_INET, RTM_GETADDR, 0);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1);
return ret;
/* Get IPv6 address of the interfaces. */
- ret = netlink_request (AF_INET6, RTM_GETADDR, &zns->netlink_cmd);
+ ret = netlink_request_intf_addr (zns, AF_INET6, RTM_GETADDR, 0);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1);
return netlink_parse_info (filter, nl, zns, 0, startup);
}
-/* Get type specified information from netlink. */
+/* Issue request message to kernel via netlink socket. GET messages
+ * are issued through this interface.
+ */
int
-netlink_request (int family, int type, struct nlsock *nl)
+netlink_request (struct nlsock *nl, struct nlmsghdr *n)
{
int ret;
struct sockaddr_nl snl;
int save_errno;
- struct
- {
- struct nlmsghdr nlh;
- struct rtgenmsg g;
- } req;
-
/* Check netlink socket. */
if (nl->sock < 0)
{
return -1;
}
+ /* Fill common fields for all requests. */
+ n->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ n->nlmsg_pid = nl->snl.nl_pid;
+ n->nlmsg_seq = ++nl->seq;
+
memset (&snl, 0, sizeof snl);
snl.nl_family = AF_NETLINK;
- memset (&req, 0, sizeof req);
- req.nlh.nlmsg_len = sizeof req;
- req.nlh.nlmsg_type = type;
- req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
- req.nlh.nlmsg_pid = nl->snl.nl_pid;
- req.nlh.nlmsg_seq = ++nl->seq;
- req.g.rtgen_family = family;
-
- /* linux appears to check capabilities on every message
- * have to raise caps for every message sent
- */
+ /* Raise capabilities and send message, then lower capabilities. */
if (zserv_privs.change (ZPRIVS_RAISE))
{
zlog_err("Can't raise privileges");
return -1;
}
- ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
+ ret = sendto (nl->sock, (void *)n, n->nlmsg_len, 0,
(struct sockaddr *) &snl, sizeof snl);
save_errno = errno;
ns_id_t, int startup),
struct nlmsghdr *n, struct nlsock *nl,
struct zebra_ns *zns, int startup);
-extern int netlink_request (int family, int type, struct nlsock *nl);
+extern int netlink_request (struct nlsock *nl, struct nlmsghdr *n);
#endif /* HAVE_NETLINK */
return 0;
}
+/* Request for specific route information from the kernel */
+static int
+netlink_request_route (struct zebra_ns *zns, int family, int type)
+{
+ struct
+ {
+ struct nlmsghdr n;
+ struct rtmsg rtm;
+ } req;
+
+ /* Form the request, specifying filter (rtattr) if needed. */
+ memset (&req, 0, sizeof (req));
+ req.n.nlmsg_type = type;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.rtm.rtm_family = family;
+
+ return netlink_request (&zns->netlink_cmd, &req.n);
+}
+
/* Routing table read function using netlink interface. Only called
bootstrap time. */
int
int ret;
/* Get IPv4 routing table. */
- ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd);
+ ret = netlink_request_route (zns, AF_INET, RTM_GETROUTE);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);
return ret;
/* Get IPv6 routing table. */
- ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd);
+ ret = netlink_request_route (zns, AF_INET6, RTM_GETROUTE);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);