]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/kernel_netlink.c
zebra: Check for netlink message next fault
[mirror_frr.git] / zebra / kernel_netlink.c
index 6d164cfdabf700e8a91c801f87f3b1e7c8c5604c..cd881dcc244d5cb9fa85eb4819468945a1b1c5a2 100644 (file)
@@ -390,8 +390,8 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
        }
 }
 
-int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data,
-             unsigned int alen)
+int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
+             const void *data, unsigned int alen)
 {
        int len;
        struct rtattr *rta;
@@ -415,8 +415,8 @@ int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data,
        return 0;
 }
 
-int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, void *data,
-                 unsigned int alen)
+int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
+                 const void *data, unsigned int alen)
 {
        unsigned int len;
        struct rtattr *subrta;
@@ -545,7 +545,6 @@ static void netlink_parse_extended_ack(struct nlmsghdr *h)
 
                if (off > h->nlmsg_len) {
                        zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS\n");
-                       off = 0;
                } else if (!(h->nlmsg_flags & NLM_F_CAPPED)) {
                        /*
                         * Header of failed message
@@ -639,7 +638,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
 
                read_in++;
                for (h = (struct nlmsghdr *)buf;
-                    NLMSG_OK(h, (unsigned int)status);
+                    (status >= 0 && NLMSG_OK(h, (unsigned int)status));
                     h = NLMSG_NEXT(h, status)) {
                        /* Finish of reading. */
                        if (h->nlmsg_type == NLMSG_DONE)
@@ -772,6 +771,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
                        error = (*filter)(h, zns->ns_id, startup);
                        if (error < 0) {
                                zlog_err("%s filter function error", nl->name);
+                               zlog_backtrace(LOG_ERR);
                                ret = error;
                        }
                }
@@ -829,9 +829,6 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
        n->nlmsg_seq = ++nl->seq;
        n->nlmsg_pid = nl->snl.nl_pid;
 
-       /* Request an acknowledgement by setting NLM_F_ACK */
-       n->nlmsg_flags |= NLM_F_ACK;
-
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_debug(
                        "netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x",
@@ -942,12 +939,20 @@ 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;
-       netlink_socket(&zns->netlink, groups, zns->ns_id);
+       if (netlink_socket(&zns->netlink, groups, zns->ns_id) < 0) {
+               zlog_err("Failure to create %s socket",
+                        zns->netlink.name);
+               exit(-1);
+       }
 
        snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
                 "netlink-cmd (NS %u)", zns->ns_id);
        zns->netlink_cmd.sock = -1;
-       netlink_socket(&zns->netlink_cmd, 0, zns->ns_id);
+       if (netlink_socket(&zns->netlink_cmd, 0, zns->ns_id) < 0) {
+               zlog_err("Failure to create %s socket",
+                        zns->netlink_cmd.name);
+               exit(-1);
+       }
 
        /*
         * SOL_NETLINK is not available on all platforms yet
@@ -969,23 +974,24 @@ void kernel_init(struct zebra_ns *zns)
 #endif
 
        /* Register kernel socket. */
-       if (zns->netlink.sock > 0) {
-               /* Only want non-blocking on the netlink event socket */
-               if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
-                       zlog_err("Can't set %s socket flags: %s",
-                                zns->netlink.name, safe_strerror(errno));
-
-               /* Set receive buffer size if it's set from command line */
-               if (nl_rcvbufsize)
-                       netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
-
-               netlink_install_filter(zns->netlink.sock,
-                                      zns->netlink_cmd.snl.nl_pid);
-               zns->t_netlink = NULL;
-
-               thread_add_read(zebrad.master, kernel_read, zns,
-                               zns->netlink.sock, &zns->t_netlink);
-       }
+       if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
+               zlog_err("Can't set %s socket error: %s(%d)",
+                        zns->netlink.name, safe_strerror(errno), errno);
+
+       if (fcntl(zns->netlink_cmd.sock, F_SETFL, O_NONBLOCK) < 0)
+               zlog_err("Can't set %s socket error: %s(%d)",
+                        zns->netlink_cmd.name, safe_strerror(errno), errno);
+
+       /* Set receive buffer size if it's set from command line */
+       if (nl_rcvbufsize)
+               netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
+
+       netlink_install_filter(zns->netlink.sock,
+                              zns->netlink_cmd.snl.nl_pid);
+       zns->t_netlink = NULL;
+
+       thread_add_read(zebrad.master, kernel_read, zns,
+                       zns->netlink.sock, &zns->t_netlink);
 
        rt_netlink_init();
 }