diff options
Diffstat (limited to 'zebra/kernel_netlink.c')
| -rw-r--r-- | zebra/kernel_netlink.c | 144 |
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, |
