]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
libnetlink: add size argument to rtnl_talk
authorStephen Hemminger <shemming@brocade.com>
Wed, 27 May 2015 19:26:14 +0000 (12:26 -0700)
committerStephen Hemminger <shemming@brocade.com>
Wed, 27 May 2015 20:00:21 +0000 (13:00 -0700)
There have been several instances where response from kernel
has overrun the stack buffer from the caller. Avoid future problems
by passing a size argument.

Also drop the unused peer and group arguments to rtnl_talk.

32 files changed:
bridge/fdb.c
bridge/link.c
bridge/mdb.c
bridge/vlan.c
genl/ctrl.c
include/libnetlink.h
ip/ipaddress.c
ip/ipaddrlabel.c
ip/ipfou.c
ip/ipl2tp.c
ip/iplink.c
ip/ipneigh.c
ip/ipnetns.c
ip/ipntable.c
ip/iproute.c
ip/iprule.c
ip/iptoken.c
ip/link_gre.c
ip/link_gre6.c
ip/link_ip6tnl.c
ip/link_iptnl.c
ip/link_vti.c
ip/link_vti6.c
ip/tcp_metrics.c
ip/xfrm_policy.c
ip/xfrm_state.c
lib/libgenl.c
lib/libnetlink.c
tc/m_action.c
tc/tc_class.c
tc/tc_filter.c
tc/tc_qdisc.c

index e34933b5f8b5410a429cca9b0a194e96f1e82f6f..278e55fd1b652a98fe488c514f292238feb39e26 100644 (file)
@@ -362,7 +362,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
                return -1;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -1;
 
        return 0;
index 1af1cf33017560b36e46dd4a6789fe19082a3346..a9b1262dfdc2d439fe6562d6fd562878f293dd72 100644 (file)
@@ -415,7 +415,7 @@ static int brlink_modify(int argc, char **argv)
                addattr_nest_end(&req.n, nest);
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -1;
 
        return 0;
index a6b2882708ba9f560143d051c634cdd654c48693..9a8ed540ce642ad8967d367bb1a46e50165cac99 100644 (file)
@@ -224,7 +224,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
 
        addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry));
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -1;
 
        return 0;
index 2ae739cf4925c0966edf23a934a7f053b63b8c3f..ac2f52311ea492165752a5431805b4439650fbe0 100644 (file)
@@ -131,7 +131,7 @@ static int vlan_modify(int cmd, int argc, char **argv)
 
        addattr_nest_end(&req.n, afspec);
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -1;
 
        return 0;
index 3546129087ece91332146e511bb6d16334775b9d..0bf4dc1ee0ba0f2dbf2ea9c7ca4e6772680306a2 100644 (file)
@@ -67,7 +67,7 @@ int genl_ctrl_resolve_family(const char *family)
 
        addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1);
 
-       if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) {
+       if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) {
                fprintf(stderr, "Error talking to the kernel\n");
                goto errout;
        }
@@ -334,7 +334,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
                        goto ctrl_done;
                }
 
-               if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) {
+               if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) {
                        fprintf(stderr, "Error talking to the kernel\n");
                        goto ctrl_done;
                }
index 898275b824d4976fe088d582ff7eeba8df7dc96c..bc1ab75e8656cb83b3b5ab5ee47e98e4009178a7 100644 (file)
@@ -54,8 +54,8 @@ extern int rtnl_dump_filter_l(struct rtnl_handle *rth,
                              const struct rtnl_dump_filter_arg *arg);
 extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
                            void *arg);
-extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
-                    unsigned groups, struct nlmsghdr *answer)
+extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
+                    struct nlmsghdr *answer, size_t len)
        __attribute__((warn_unused_result));
 extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int)
        __attribute__((warn_unused_result));
index 92afa4904917928fc0d4061dc5646527d3892af8..340e1c9aca9ff96c658134b0591a994a4dd906c5 100644 (file)
@@ -1136,7 +1136,7 @@ static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, voi
 
        ll_init_map(&rth);
 
-       ret = rtnl_talk(&rth, n, 0, 0, n);
+       ret = rtnl_talk(&rth, n, n, sizeof(*n));
        if ((ret < 0) && (errno == EEXIST))
                ret = 0;
 
@@ -1800,7 +1800,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
                return -1;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
index 19a93083a45df28eefbabc66e2f66ee5069203cc..a738ded0f5941451d585598459e720aebf2e9580 100644 (file)
@@ -182,7 +182,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv)
        if (req.ifal.ifal_family == AF_UNSPEC)
                req.ifal.ifal_family = AF_INET6;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
@@ -209,7 +209,7 @@ static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, vo
                if (rtnl_open(&rth2, 0) < 0)
                        return -1;
 
-               if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0)
+               if (rtnl_talk(&rth2, n, NULL, 0) < 0)
                        return -2;
 
                rtnl_close(&rth2);
index 2676045369d92529a824aedb25095ae1f935f79a..0b83c277c86086ab1d7dc6057fece3bd6b49ef23 100644 (file)
@@ -112,7 +112,7 @@ static int do_add(int argc, char **argv)
 
        fou_parse_opt(argc, argv, &req.n, true);
 
-       if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
@@ -124,7 +124,7 @@ static int do_del(int argc, char **argv)
 
        fou_parse_opt(argc, argv, &req.n, false);
 
-       if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
index 5cd863224fda09c724baaad2d75e8c379f390fe4..2f7c9bf1c737f2a53681fe67ba7d49e8333f429e 100644 (file)
@@ -119,7 +119,7 @@ static int create_tunnel(struct l2tp_parm *p)
                addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
        }
 
-       if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
@@ -132,7 +132,7 @@ static int delete_tunnel(struct l2tp_parm *p)
 
        addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
 
-       if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
@@ -166,7 +166,7 @@ static int create_session(struct l2tp_parm *p)
        if (p->ifname && p->ifname[0])
                addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
 
-       if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
@@ -179,7 +179,7 @@ static int delete_session(struct l2tp_parm *p)
 
        addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
        addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
-       if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
index bb437b96239a76bc6a30b7e652b84ebf5123040a..a4a498055d463518028e1e1435b86c828e9ca853 100644 (file)
@@ -674,7 +674,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 
                        req.i.ifi_index = 0;
                        addattr32(&req.n, sizeof(req), IFLA_GROUP, group);
-                       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+                       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                                exit(2);
                        return 0;
                }
@@ -773,7 +773,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
                return -1;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        return 0;
@@ -783,7 +783,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
 {
        int len;
        struct iplink_req req;
-       char answer[16384];
+       struct {
+               struct nlmsghdr n;
+               char buf[16384];
+       } answer;
 
        memset(&req, 0, sizeof(req));
 
@@ -803,10 +806,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
        }
        addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, (struct nlmsghdr *)answer) < 0)
+       if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
                return -2;
 
-       print_linkinfo(NULL, (struct nlmsghdr *)answer, stdout);
+       print_linkinfo(NULL, &answer.n, stdout);
 
        return 0;
 }
index eeec7bdd78c5f6e1c71a5ffb94c44b7f0aac7085..a9e23f450c16ecc0ac4a8ca80472cc6cd641aa50 100644 (file)
@@ -179,7 +179,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
                return -1;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        return 0;
index 438d59bc222e39b4e58331bec4680648bf251d44..be0c473783c1743234fc228a6f23e337fa5b09f0 100644 (file)
@@ -112,7 +112,7 @@ static int get_netnsid_from_name(const char *name)
                return fd;
 
        addattr32(&req.n, 1024, NETNSA_FD, fd);
-       if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) {
+       if (rtnl_talk(&rtnsh, &req.n, &answer.n, sizeof(answer)) < 0) {
                close(fd);
                return -2;
        }
@@ -697,7 +697,7 @@ static int set_netnsid_from_name(const char *name, int nsid)
 
        addattr32(&req.n, 1024, NETNSA_FD, fd);
        addattr32(&req.n, 1024, NETNSA_NSID, nsid);
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                err = -2;
 
        close(fd);
index ea7ca2d28dd337a5fe453793e547c437b8e993ac..5e84b95165915e3b36bfa021d70575718646b0b6 100644 (file)
@@ -313,7 +313,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv)
                          RTA_PAYLOAD(parms_rta));
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        return 0;
index 670a4c64d235263bc60b50f003cc7ce8b67b07cc..64bc4c33ae00a1a43ebbb9863d6cdc2dd8aa7d2e 100644 (file)
@@ -1163,7 +1163,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
        if (req.r.rtm_family == AF_UNSPEC)
                req.r.rtm_family = AF_INET;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
@@ -1626,7 +1626,7 @@ static int iproute_get(int argc, char **argv)
        if (req.r.rtm_family == AF_UNSPEC)
                req.r.rtm_family = AF_INET;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0)
+       if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
                exit(2);
 
        if (connected && !from_ok) {
@@ -1669,7 +1669,7 @@ static int iproute_get(int argc, char **argv)
                req.n.nlmsg_flags = NLM_F_REQUEST;
                req.n.nlmsg_type = RTM_GETROUTE;
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0)
+               if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
                        exit(2);
        }
 
@@ -1690,7 +1690,7 @@ static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n,
 
        ll_init_map(&rth);
 
-       ret = rtnl_talk(&rth, n, 0, 0, n);
+       ret = rtnl_talk(&rth, n, n, sizeof(*n));
        if ((ret < 0) && (errno == EEXIST))
                ret = 0;
 
index 986a5bcbab15c9e2a240cf3ed350484bcbc220d1..714278a2be58af0b2c6a80373110e69f9824f486 100644 (file)
@@ -380,7 +380,7 @@ static int iprule_modify(int cmd, int argc, char **argv)
        if (!table_ok && cmd == RTM_NEWRULE)
                req.r.rtm_table = RT_TABLE_MAIN;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
@@ -407,7 +407,7 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a
                if (rtnl_open(&rth2, 0) < 0)
                        return -1;
 
-               if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0)
+               if (rtnl_talk(&rth2, n, NULL, 0) < 0)
                        return -2;
 
                rtnl_close(&rth2);
index 655f1601e89d1b25d7c04b9f31fb2f1a78ec682a..a38194c9c08ef9882e2b4895fbb0b14004da598d 100644 (file)
@@ -182,7 +182,7 @@ static int iptoken_set(int argc, char **argv)
                return -1;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return -2;
 
        return 0;
index 193726109ee6b0c74cf9a112c1b1940a43fcb123..58f416ca9720bc7bbc0ae661329f7473189f9f3c 100644 (file)
@@ -84,7 +84,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
                req.i.ifi_family = preferred_family;
                req.i.ifi_index = ifi->ifi_index;
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+               if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
 get_failed:
                        fprintf(stderr,
                                "Failed to get existing tunnel info.\n");
index f18919cc8c4baccbcdd14b05bd8542dd09518894..e00ea0917bf575cd4bdd27454cf6482b6641ca7e 100644 (file)
@@ -91,7 +91,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
                req.i.ifi_family = preferred_family;
                req.i.ifi_index = ifi->ifi_index;
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+               if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
 get_failed:
                        fprintf(stderr,
                                "Failed to get existing tunnel info.\n");
index cf59a9338f5738add81536eb13a37027c33f787e..f771c75de42d08a27390a223f2f818978476a813 100644 (file)
@@ -89,7 +89,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
                req.i.ifi_family = preferred_family;
                req.i.ifi_index = ifi->ifi_index;
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+               if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
 get_failed:
                        fprintf(stderr,
                                "Failed to get existing tunnel info.\n");
index cab174f9973bfddd61f2d5a30c7b9dd8edbadd83..9d6bc986053d62c472247cd16326ce09616c5639 100644 (file)
@@ -91,7 +91,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
                req.i.ifi_family = preferred_family;
                req.i.ifi_index = ifi->ifi_index;
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+               if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
 get_failed:
                        fprintf(stderr,
                                "Failed to get existing tunnel info.\n");
index 59ac4c483075e922f3b3c6a9c2d4eb79c5951006..f3fea338fa4e80dd908bfe0f42b8c504ef3f2a3c 100644 (file)
@@ -71,7 +71,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
                req.i.ifi_family = preferred_family;
                req.i.ifi_index = ifi->ifi_index;
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+               if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
 get_failed:
                        fprintf(stderr,
                                "Failed to get existing tunnel info.\n");
index 282896df917a09b8420539684ea9473522eb5e9c..c146f791abaaab38fdc25b22477121bf3dabfc49 100644 (file)
@@ -67,7 +67,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
                req.i.ifi_family = preferred_family;
                req.i.ifi_index = ifi->ifi_index;
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+               if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
 get_failed:
                        fprintf(stderr,
                                "Failed to get existing tunnel info.\n");
index bbbb4cc0cfff36ab5b1bbafd2f3259ef23ed4fe7..bdc503ef831ccee7344c402745093898379e5b58 100644 (file)
@@ -467,10 +467,10 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv)
        }
 
        if (ack) {
-               if (rtnl_talk(&grth, &req.n, 0, 0, NULL) < 0)
+               if (rtnl_talk(&grth, &req.n, NULL, 0) < 0)
                        return -2;
        } else if (atype >= 0) {
-               if (rtnl_talk(&grth, &req.n, 0, 0, &req.n) < 0)
+               if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0)
                        return -2;
                if (process_msg(NULL, &req.n, stdout) < 0) {
                        fprintf(stderr, "Dump terminated\n");
index 9429923ce5dbbe198d9b04485de2a034e413232d..8f4d1a0751248314e9b216704e99733dcbc88363 100644 (file)
@@ -393,7 +393,7 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv)
        if (req.xpinfo.sel.family == AF_UNSPEC)
                req.xpinfo.sel.family = AF_INET;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        rtnl_close(&rth);
@@ -555,7 +555,7 @@ int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
 }
 
 static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
-                                    void *res_nlbuf)
+                                    void *res_nlbuf, size_t res_size)
 {
        struct rtnl_handle rth;
        struct {
@@ -670,7 +670,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
                          (void *)&ctx, ctx.sctx.len);
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf) < 0)
+       if (rtnl_talk(&rth, &req.n, res_nlbuf, res_size) < 0)
                exit(2);
 
        rtnl_close(&rth);
@@ -680,7 +680,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
 
 static int xfrm_policy_delete(int argc, char **argv)
 {
-       return xfrm_policy_get_or_delete(argc, argv, 1, NULL);
+       return xfrm_policy_get_or_delete(argc, argv, 1, NULL, 0);
 }
 
 static int xfrm_policy_get(int argc, char **argv)
@@ -690,7 +690,7 @@ static int xfrm_policy_get(int argc, char **argv)
 
        memset(buf, 0, sizeof(buf));
 
-       xfrm_policy_get_or_delete(argc, argv, 0, n);
+       xfrm_policy_get_or_delete(argc, argv, 0, n, sizeof(buf));
 
        if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) {
                fprintf(stderr, "An error :-)\n");
@@ -1064,7 +1064,7 @@ static int xfrm_spd_setinfo(int argc, char **argv)
        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
                exit(1);
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        rtnl_close(&rth);
@@ -1091,7 +1091,7 @@ static int xfrm_spd_getinfo(int argc, char **argv)
        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
                exit(1);
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0)
+       if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
                exit(2);
 
        print_spdinfo(&req.n, (void*)stdout);
@@ -1143,7 +1143,7 @@ static int xfrm_policy_flush(int argc, char **argv)
        if (show_stats > 1)
                fprintf(stderr, "Flush policy\n");
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        rtnl_close(&rth);
index 04af50b348e672213c5a9560afe8425ac997b3cc..d2831d007ced4a1d8e45051c99c7dbfb2ae99f3e 100644 (file)
@@ -688,7 +688,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
        if (req.xsinfo.family == AF_UNSPEC)
                req.xsinfo.family = AF_INET;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        rtnl_close(&rth);
@@ -825,7 +825,7 @@ static int xfrm_state_allocspi(int argc, char **argv)
                req.xspi.info.family = AF_INET;
 
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0)
+       if (rtnl_talk(&rth, &req.n, res_n, sizeof(res_buf)) < 0)
                exit(2);
 
        if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
@@ -1015,7 +1015,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
                req.xsid.family = AF_INET;
 
        if (delete) {
-               if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+               if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                        exit(2);
        } else {
                char buf[NLMSG_BUF_SIZE];
@@ -1023,7 +1023,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
 
                memset(buf, 0, sizeof(buf));
 
-               if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0)
+               if (rtnl_talk(&rth, &req.n, res_n, sizeof(req)) < 0)
                        exit(2);
 
                if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
@@ -1297,7 +1297,7 @@ static int xfrm_sad_getinfo(int argc, char **argv)
        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
                exit(1);
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0)
+       if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
                exit(2);
 
        print_sadinfo(&req.n, (void*)stdout);
@@ -1351,7 +1351,7 @@ static int xfrm_state_flush(int argc, char **argv)
                fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n",
                        strxf_xfrmproto(req.xsf.proto));
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        rtnl_close(&rth);
index ef3e5db60c8cbcec82b808f6e91b384ee66771ed..acb1478389476105ab8bddb83a6ff887d01fdff1 100644 (file)
@@ -53,7 +53,7 @@ int genl_resolve_family(struct rtnl_handle *grth, const char *family)
        addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
                  family, strlen(family) + 1);
 
-       if (rtnl_talk(grth, &req.n, 0, 0, &req.n) < 0) {
+       if (rtnl_talk(grth, &req.n, &req.n, sizeof(req)) < 0) {
                fprintf(stderr, "Error talking to the kernel\n");
                return -2;
        }
index 77e07ef7cf602dd2b18e78e3702da9358088a868..901236e62a9fd9aff47484e5fed5a49b4cfe0a08 100644 (file)
 
 #include "libnetlink.h"
 
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
 int rcvbuf = 1024 * 1024;
 
 void rtnl_close(struct rtnl_handle *rth)
@@ -300,8 +304,8 @@ int rtnl_dump_filter(struct rtnl_handle *rth,
        return rtnl_dump_filter_l(rth, a);
 }
 
-int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
-             unsigned groups, struct nlmsghdr *answer)
+int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
+             struct nlmsghdr *answer, size_t len)
 {
        int status;
        unsigned seq;
@@ -317,12 +321,10 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
                .msg_iov = &iov,
                .msg_iovlen = 1,
        };
-       char   buf[16384];
+       char   buf[32768];
 
        memset(&nladdr, 0, sizeof(nladdr));
        nladdr.nl_family = AF_NETLINK;
-       nladdr.nl_pid = peer;
-       nladdr.nl_groups = groups;
 
        n->nlmsg_seq = seq = ++rtnl->seq;
 
@@ -330,7 +332,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
                n->nlmsg_flags |= NLM_F_ACK;
 
        status = sendmsg(rtnl->fd, &msg, 0);
-
        if (status < 0) {
                perror("Cannot talk to rtnetlink");
                return -1;
@@ -339,7 +340,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
        memset(buf,0,sizeof(buf));
 
        iov.iov_base = buf;
-
        while (1) {
                iov.iov_len = sizeof(buf);
                status = recvmsg(rtnl->fd, &msg, 0);
@@ -372,7 +372,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
                                exit(1);
                        }
 
-                       if (nladdr.nl_pid != peer ||
+                       if (nladdr.nl_pid != 0 ||
                            h->nlmsg_pid != rtnl->local.nl_pid ||
                            h->nlmsg_seq != seq) {
                                /* Don't forget to skip that message. */
@@ -385,20 +385,22 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
                                struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
                                if (l < sizeof(struct nlmsgerr)) {
                                        fprintf(stderr, "ERROR truncated\n");
-                               } else {
-                                       if (!err->error) {
-                                               if (answer)
-                                                       memcpy(answer, h, h->nlmsg_len);
-                                               return 0;
-                                       }
-
-                                       fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error));
-                                       errno = -err->error;
+                               } else if (!err->error) {
+                                       if (answer)
+                                               memcpy(answer, h,
+                                                      MIN(len, h->nlmsg_len));
+                                       return 0;
                                }
+
+                               fprintf(stderr, "RTNETLINK answers: %s\n",
+                                       strerror(-err->error));
+                               errno = -err->error;
                                return -1;
                        }
+
                        if (answer) {
-                               memcpy(answer, h, h->nlmsg_len);
+                               memcpy(answer, h,
+                                      MIN(len, h->nlmsg_len));
                                return 0;
                        }
 
@@ -407,10 +409,12 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
                        status -= NLMSG_ALIGN(len);
                        h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
                }
+
                if (msg.msg_flags & MSG_TRUNC) {
                        fprintf(stderr, "Message truncated\n");
                        continue;
                }
+
                if (status) {
                        fprintf(stderr, "!!!Remnant of size %d\n", status);
                        exit(1);
index 7a83f0d57b7529e5438fab860865784b597e8f1a..d363d273068f23eb5a428d8d56fed15ebb4306cc 100644 (file)
@@ -472,7 +472,7 @@ static int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p)
        if (cmd == RTM_GETACTION)
                ans = &req.n;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, ans) < 0) {
+       if (rtnl_talk(&rth, &req.n, ans, MAX_MSG) < 0) {
                fprintf(stderr, "We have an error talking to the kernel\n");
                return 1;
        }
@@ -517,7 +517,7 @@ static int tc_action_modify(int cmd, unsigned flags, int *argc_p, char ***argv_p
        }
        tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) {
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
                fprintf(stderr, "We have an error talking to the kernel\n");
                ret = -1;
        }
@@ -587,7 +587,7 @@ static int tc_act_list_or_flush(int argc, char **argv, int event)
                req.n.nlmsg_type = RTM_DELACTION;
                req.n.nlmsg_flags |= NLM_F_ROOT;
                req.n.nlmsg_flags |= NLM_F_REQUEST;
-               if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) {
+               if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
                        fprintf(stderr, "We have an error flushing\n");
                        return 1;
                }
index 877048aa93af80e6d68cd239e3f99dc1edb18489..3acd030f92593bbd36a6a7987f022dd5168ceb7f 100644 (file)
@@ -153,7 +153,7 @@ static int tc_class_modify(int cmd, unsigned flags, int argc, char **argv)
                }
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return 2;
 
        return 0;
index c1038a4bc8271b524b685538559ca3bf46967ed9..9e416008eaa9b708142faf3e644db440ce699bde 100644 (file)
@@ -167,7 +167,7 @@ static int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv)
                }
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) {
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
                fprintf(stderr, "We have an error talking to the kernel\n");
                return 2;
        }
index c71937d0da212be648adf23d739083f7a6a55dfd..c31ae8d296cedeec5435271e8f23fa7352940a2b 100644 (file)
@@ -187,7 +187,7 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
                req.t.tcm_ifindex = idx;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                return 2;
 
        return 0;