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.c144
1 files changed, 24 insertions, 120 deletions
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index d0c1bc812d..ad0d4bf56b 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -20,12 +20,6 @@
#include <zebra.h>
-#if defined(HANDLE_NETLINK_FUZZING)
-#include <stdio.h>
-#include <string.h>
-#include "libfrr.h"
-#endif /* HANDLE_NETLINK_FUZZING */
-
#ifdef HAVE_NETLINK
#include "linklist.h"
@@ -96,14 +90,7 @@
*/
#define NL_DEFAULT_BATCH_SEND_THRESHOLD (15 * NL_PKT_BUF_SIZE)
-/*
- * For every request sent to the kernel that has failed we get an error message,
- * which contains a standard netlink message header and the payload consisting
- * of an error code and the original netlink mesage. So the receiving buffer
- * must be at least as big as the transmitting buffer increased by some space
- * for headers.
- */
-#define NL_BATCH_RX_BUFSIZE (NL_DEFAULT_BATCH_BUFSIZE + NL_PKT_BUF_SIZE)
+#define NL_BATCH_RX_BUFSIZE NL_RCV_PKT_BUF_SIZE
static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"},
{RTM_DELROUTE, "RTM_DELROUTE"},
@@ -404,86 +391,6 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
return 0;
}
-#if defined(HANDLE_NETLINK_FUZZING)
-/* Using globals here to avoid adding function parameters */
-
-/* Keep distinct filenames for netlink fuzzy collection */
-static unsigned int netlink_file_counter = 1;
-
-/* File name to read fuzzed netlink from */
-static char netlink_fuzz_file[MAXPATHLEN] = "";
-
-/* Flag for whether to read from file or not */
-bool netlink_read;
-
-/**
- * netlink_read_init() - Starts the message parser
- * @fname: Filename to read.
- */
-void netlink_read_init(const char *fname)
-{
- struct zebra_dplane_info dp_info;
-
- snprintf(netlink_fuzz_file, MAXPATHLEN, "%s", fname);
- /* Creating this fake socket for testing purposes */
- struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
-
- /* Capture key info from zns struct */
- zebra_dplane_info_from_zns(&dp_info, zns, false);
-
- netlink_parse_info(netlink_information_fetch, &zns->netlink,
- &dp_info, 1, 0);
-}
-
-/**
- * netlink_write_incoming() - Writes all data received from netlink to a file
- * @buf: Data from netlink.
- * @size: Size of data.
- * @counter: Counter for keeping filenames distinct.
- */
-static void netlink_write_incoming(const char *buf, const unsigned int size,
- unsigned int counter)
-{
- char fname[MAXPATHLEN];
- FILE *f;
-
- snprintf(fname, MAXPATHLEN, "%s/%s_%u", frr_vtydir, "netlink", counter);
- frr_with_privs(&zserv_privs) {
- f = fopen(fname, "w");
- }
- if (f) {
- fwrite(buf, 1, size, f);
- fclose(f);
- }
-}
-
-/**
- * netlink_read_file() - Reads netlink data from file
- * @buf: Netlink buffer being overwritten.
- * @fname: File name to read from.
- *
- * Return: Size of file.
- */
-static long netlink_read_file(char *buf, const char *fname)
-{
- FILE *f;
- long file_bytes = -1;
-
- frr_with_privs(&zserv_privs) {
- f = fopen(fname, "r");
- }
- if (f) {
- fseek(f, 0, SEEK_END);
- file_bytes = ftell(f);
- rewind(f);
- fread(buf, NL_RCV_PKT_BUF_SIZE, 1, f);
- fclose(f);
- }
- return file_bytes;
-}
-
-#endif /* HANDLE_NETLINK_FUZZING */
-
static int kernel_read(struct thread *thread)
{
struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG(thread);
@@ -834,18 +741,7 @@ static int netlink_recv_msg(const struct nlsock *nl, struct msghdr msg,
msg.msg_iovlen = 1;
do {
-#if defined(HANDLE_NETLINK_FUZZING)
- /* Check if reading and filename is set */
- if (netlink_read && '\0' != netlink_fuzz_file[0]) {
- zlog_debug("Reading netlink fuzz file");
- status = netlink_read_file(buf, netlink_fuzz_file);
- ((struct sockaddr_nl *)msg.msg_name)->nl_pid = 0;
- } else {
- status = recvmsg(nl->sock, &msg, 0);
- }
-#else
status = recvmsg(nl->sock, &msg, 0);
-#endif /* HANDLE_NETLINK_FUZZING */
} while (status == -1 && errno == EINTR);
if (status == -1) {
@@ -877,13 +773,6 @@ static int netlink_recv_msg(const struct nlsock *nl, struct msghdr msg,
zlog_hexdump(buf, status);
}
-#if defined(HANDLE_NETLINK_FUZZING)
- if (!netlink_read) {
- zlog_debug("Writing incoming netlink message");
- netlink_write_incoming(buf, status, netlink_file_counter++);
- }
-#endif /* HANDLE_NETLINK_FUZZING */
-
return status;
}
@@ -1173,14 +1062,17 @@ static int nl_batch_read_resp(struct nl_batch *bth)
msg.msg_name = (void *)&snl;
msg.msg_namelen = sizeof(snl);
- status = netlink_recv_msg(nl, msg, nl_batch_rx_buf,
- sizeof(nl_batch_rx_buf));
- if (status == -1 || status == 0)
- return status;
+ /*
+ * The responses are not batched, so we need to read and process one
+ * message at a time.
+ */
+ while (true) {
+ status = netlink_recv_msg(nl, msg, nl_batch_rx_buf,
+ sizeof(nl_batch_rx_buf));
+ if (status == -1 || status == 0)
+ return status;
- for (h = (struct nlmsghdr *)nl_batch_rx_buf;
- (status >= 0 && NLMSG_OK(h, (unsigned int)status));
- h = NLMSG_NEXT(h, status)) {
+ h = (struct nlmsghdr *)nl_batch_rx_buf;
ignore_msg = false;
seq = h->nlmsg_seq;
/*
@@ -1561,6 +1453,15 @@ void kernel_init(struct zebra_ns *zns)
if (ret < 0)
zlog_notice("Registration for extended dp ACK failed : %d %s",
errno, safe_strerror(errno));
+
+ /*
+ * Trim off the payload of the original netlink message in the
+ * acknowledgment. This option is available since Linux 4.2, so if
+ * setsockopt fails, ignore the error.
+ */
+ one = 1;
+ ret = setsockopt(zns->netlink_dplane.sock, SOL_NETLINK, NETLINK_CAP_ACK,
+ &one, sizeof(one));
#endif
/* Register kernel socket. */
@@ -1577,8 +1478,11 @@ void kernel_init(struct zebra_ns *zns)
zns->netlink_dplane.name, safe_strerror(errno), errno);
/* Set receive buffer size if it's set from command line */
- if (nl_rcvbufsize)
+ if (nl_rcvbufsize) {
netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
+ netlink_recvbuf(&zns->netlink_cmd, nl_rcvbufsize);
+ netlink_recvbuf(&zns->netlink_dplane, nl_rcvbufsize);
+ }
netlink_install_filter(zns->netlink.sock,
zns->netlink_cmd.snl.nl_pid,