Commit c079e121 authored by Stephen Hemminger's avatar Stephen Hemminger

libnetlink: add size argument to rtnl_talk

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.
parent bde5baa5
...@@ -362,7 +362,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) ...@@ -362,7 +362,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
return -1; return -1;
} }
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
return -1; return -1;
return 0; return 0;
......
...@@ -415,7 +415,7 @@ static int brlink_modify(int argc, char **argv) ...@@ -415,7 +415,7 @@ static int brlink_modify(int argc, char **argv)
addattr_nest_end(&req.n, nest); 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 -1;
return 0; return 0;
......
...@@ -224,7 +224,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) ...@@ -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)); 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 -1;
return 0; return 0;
......
...@@ -131,7 +131,7 @@ static int vlan_modify(int cmd, int argc, char **argv) ...@@ -131,7 +131,7 @@ static int vlan_modify(int cmd, int argc, char **argv)
addattr_nest_end(&req.n, afspec); 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 -1;
return 0; return 0;
......
...@@ -67,7 +67,7 @@ int genl_ctrl_resolve_family(const char *family) ...@@ -67,7 +67,7 @@ int genl_ctrl_resolve_family(const char *family)
addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); 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"); fprintf(stderr, "Error talking to the kernel\n");
goto errout; goto errout;
} }
...@@ -334,7 +334,7 @@ static int ctrl_list(int cmd, int argc, char **argv) ...@@ -334,7 +334,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
goto ctrl_done; 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"); fprintf(stderr, "Error talking to the kernel\n");
goto ctrl_done; goto ctrl_done;
} }
......
...@@ -54,8 +54,8 @@ extern int rtnl_dump_filter_l(struct rtnl_handle *rth, ...@@ -54,8 +54,8 @@ extern int rtnl_dump_filter_l(struct rtnl_handle *rth,
const struct rtnl_dump_filter_arg *arg); const struct rtnl_dump_filter_arg *arg);
extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
void *arg); void *arg);
extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
unsigned groups, struct nlmsghdr *answer) struct nlmsghdr *answer, size_t len)
__attribute__((warn_unused_result)); __attribute__((warn_unused_result));
extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int) extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int)
__attribute__((warn_unused_result)); __attribute__((warn_unused_result));
......
...@@ -1136,7 +1136,7 @@ static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, voi ...@@ -1136,7 +1136,7 @@ static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, voi
ll_init_map(&rth); 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)) if ((ret < 0) && (errno == EEXIST))
ret = 0; ret = 0;
...@@ -1800,7 +1800,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) ...@@ -1800,7 +1800,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
return -1; return -1;
} }
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
return -2; return -2;
return 0; return 0;
......
...@@ -182,7 +182,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv) ...@@ -182,7 +182,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv)
if (req.ifal.ifal_family == AF_UNSPEC) if (req.ifal.ifal_family == AF_UNSPEC)
req.ifal.ifal_family = AF_INET6; 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 -2;
return 0; return 0;
...@@ -209,7 +209,7 @@ static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, vo ...@@ -209,7 +209,7 @@ static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, vo
if (rtnl_open(&rth2, 0) < 0) if (rtnl_open(&rth2, 0) < 0)
return -1; return -1;
if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) if (rtnl_talk(&rth2, n, NULL, 0) < 0)
return -2; return -2;
rtnl_close(&rth2); rtnl_close(&rth2);
......
...@@ -112,7 +112,7 @@ static int do_add(int argc, char **argv) ...@@ -112,7 +112,7 @@ static int do_add(int argc, char **argv)
fou_parse_opt(argc, argv, &req.n, true); 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 -2;
return 0; return 0;
...@@ -124,7 +124,7 @@ static int do_del(int argc, char **argv) ...@@ -124,7 +124,7 @@ static int do_del(int argc, char **argv)
fou_parse_opt(argc, argv, &req.n, false); 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 -2;
return 0; return 0;
......
...@@ -119,7 +119,7 @@ static int create_tunnel(struct l2tp_parm *p) ...@@ -119,7 +119,7 @@ static int create_tunnel(struct l2tp_parm *p)
addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port); 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 -2;
return 0; return 0;
...@@ -132,7 +132,7 @@ static int delete_tunnel(struct l2tp_parm *p) ...@@ -132,7 +132,7 @@ static int delete_tunnel(struct l2tp_parm *p)
addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id); 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 -2;
return 0; return 0;
...@@ -166,7 +166,7 @@ static int create_session(struct l2tp_parm *p) ...@@ -166,7 +166,7 @@ static int create_session(struct l2tp_parm *p)
if (p->ifname && p->ifname[0]) if (p->ifname && p->ifname[0])
addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname); 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 -2;
return 0; return 0;
...@@ -179,7 +179,7 @@ static int delete_session(struct l2tp_parm *p) ...@@ -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_CONN_ID, p->tunnel_id);
addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_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 -2;
return 0; return 0;
......
...@@ -674,7 +674,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) ...@@ -674,7 +674,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
req.i.ifi_index = 0; req.i.ifi_index = 0;
addattr32(&req.n, sizeof(req), IFLA_GROUP, group); 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); exit(2);
return 0; return 0;
} }
...@@ -773,7 +773,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) ...@@ -773,7 +773,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
return -1; return -1;
} }
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
exit(2); exit(2);
return 0; return 0;
...@@ -783,7 +783,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask) ...@@ -783,7 +783,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
{ {
int len; int len;
struct iplink_req req; struct iplink_req req;
char answer[16384]; struct {
struct nlmsghdr n;
char buf[16384];
} answer;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
...@@ -803,10 +806,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask) ...@@ -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); 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; return -2;
print_linkinfo(NULL, (struct nlmsghdr *)answer, stdout); print_linkinfo(NULL, &answer.n, stdout);
return 0; return 0;
} }
......
...@@ -179,7 +179,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) ...@@ -179,7 +179,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
return -1; return -1;
} }
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
exit(2); exit(2);
return 0; return 0;
......
...@@ -112,7 +112,7 @@ static int get_netnsid_from_name(const char *name) ...@@ -112,7 +112,7 @@ static int get_netnsid_from_name(const char *name)
return fd; return fd;
addattr32(&req.n, 1024, NETNSA_FD, 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); close(fd);
return -2; return -2;
} }
...@@ -697,7 +697,7 @@ static int set_netnsid_from_name(const char *name, int nsid) ...@@ -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_FD, fd);
addattr32(&req.n, 1024, NETNSA_NSID, nsid); 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; err = -2;
close(fd); close(fd);
......
...@@ -313,7 +313,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv) ...@@ -313,7 +313,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv)
RTA_PAYLOAD(parms_rta)); 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); exit(2);
return 0; return 0;
......
...@@ -1163,7 +1163,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -1163,7 +1163,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
if (req.r.rtm_family == AF_UNSPEC) if (req.r.rtm_family == AF_UNSPEC)
req.r.rtm_family = AF_INET; 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 -2;
return 0; return 0;
...@@ -1626,7 +1626,7 @@ static int iproute_get(int argc, char **argv) ...@@ -1626,7 +1626,7 @@ static int iproute_get(int argc, char **argv)
if (req.r.rtm_family == AF_UNSPEC) if (req.r.rtm_family == AF_UNSPEC)
req.r.rtm_family = AF_INET; 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); exit(2);
if (connected && !from_ok) { if (connected && !from_ok) {
...@@ -1669,7 +1669,7 @@ static int iproute_get(int argc, char **argv) ...@@ -1669,7 +1669,7 @@ static int iproute_get(int argc, char **argv)
req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = RTM_GETROUTE; 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); exit(2);
} }
...@@ -1690,7 +1690,7 @@ static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, ...@@ -1690,7 +1690,7 @@ static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n,
ll_init_map(&rth); 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)) if ((ret < 0) && (errno == EEXIST))
ret = 0; ret = 0;
......
...@@ -380,7 +380,7 @@ static int iprule_modify(int cmd, int argc, char **argv) ...@@ -380,7 +380,7 @@ static int iprule_modify(int cmd, int argc, char **argv)
if (!table_ok && cmd == RTM_NEWRULE) if (!table_ok && cmd == RTM_NEWRULE)
req.r.rtm_table = RT_TABLE_MAIN; 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 -2;
return 0; return 0;
...@@ -407,7 +407,7 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a ...@@ -407,7 +407,7 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a
if (rtnl_open(&rth2, 0) < 0) if (rtnl_open(&rth2, 0) < 0)
return -1; return -1;
if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) if (rtnl_talk(&rth2, n, NULL, 0) < 0)
return -2; return -2;
rtnl_close(&rth2); rtnl_close(&rth2);
......
...@@ -182,7 +182,7 @@ static int iptoken_set(int argc, char **argv) ...@@ -182,7 +182,7 @@ static int iptoken_set(int argc, char **argv)
return -1; return -1;
} }
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
return -2; return -2;
return 0; return 0;
......
...@@ -84,7 +84,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, ...@@ -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_family = preferred_family;
req.i.ifi_index = ifi->ifi_index; 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: get_failed:
fprintf(stderr, fprintf(stderr,
"Failed to get existing tunnel info.\n"); "Failed to get existing tunnel info.\n");
......
...@@ -91,7 +91,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, ...@@ -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_family = preferred_family;
req.i.ifi_index = ifi->ifi_index; 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: get_failed:
fprintf(stderr, fprintf(stderr,
"Failed to get existing tunnel info.\n"); "Failed to get existing tunnel info.\n");
......
...@@ -89,7 +89,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, ...@@ -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_family = preferred_family;
req.i.ifi_index = ifi->ifi_index; 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: get_failed:
fprintf(stderr, fprintf(stderr,
"Failed to get existing tunnel info.\n"); "Failed to get existing tunnel info.\n");
......
...@@ -91,7 +91,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, ...@@ -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_family = preferred_family;
req.i.ifi_index = ifi->ifi_index; 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: get_failed:
fprintf(stderr, fprintf(stderr,
"Failed to get existing tunnel info.\n"); "Failed to get existing tunnel info.\n");
......
...@@ -71,7 +71,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv, ...@@ -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_family = preferred_family;
req.i.ifi_index = ifi->ifi_index; 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: get_failed:
fprintf(stderr, fprintf(stderr,
"Failed to get existing tunnel info.\n"); "Failed to get existing tunnel info.\n");
......
...@@ -67,7 +67,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, ...@@ -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_family = preferred_family;
req.i.ifi_index = ifi->ifi_index; 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: get_failed:
fprintf(stderr, fprintf(stderr,
"Failed to get existing tunnel info.\n"); "Failed to get existing tunnel info.\n");
......
...@@ -467,10 +467,10 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv) ...@@ -467,10 +467,10 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv)
} }
if (ack) { if (ack) {
if (rtnl_talk(&grth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&grth, &req.n, NULL, 0) < 0)
return -2; return -2;
} else if (atype >= 0) { } 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; return -2;
if (process_msg(NULL, &req.n, stdout) < 0) { if (process_msg(NULL, &req.n, stdout) < 0) {
fprintf(stderr, "Dump terminated\n"); fprintf(stderr, "Dump terminated\n");
......
...@@ -393,7 +393,7 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -393,7 +393,7 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv)
if (req.xpinfo.sel.family == AF_UNSPEC) if (req.xpinfo.sel.family == AF_UNSPEC)
req.xpinfo.sel.family = AF_INET; 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); exit(2);
rtnl_close(&rth); rtnl_close(&rth);
...@@ -555,7 +555,7 @@ int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n, ...@@ -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, 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 rtnl_handle rth;
struct { struct {
...@@ -670,7 +670,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, ...@@ -670,7 +670,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
(void *)&ctx, ctx.sctx.len); (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); exit(2);
rtnl_close(&rth); rtnl_close(&rth);
...@@ -680,7 +680,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, ...@@ -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) 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) static int xfrm_policy_get(int argc, char **argv)
...@@ -690,7 +690,7 @@ 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)); 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) { if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) {
fprintf(stderr, "An error :-)\n"); fprintf(stderr, "An error :-)\n");
...@@ -1064,7 +1064,7 @@ static int xfrm_spd_setinfo(int argc, char **argv) ...@@ -1064,7 +1064,7 @@ static int xfrm_spd_setinfo(int argc, char **argv)
if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
exit(1); exit(1);
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
exit(2); exit(2);
rtnl_close(&rth); rtnl_close(&rth);
...@@ -1091,7 +1091,7 @@ static int xfrm_spd_getinfo(int argc, char **argv) ...@@ -1091,7 +1091,7 @@ static int xfrm_spd_getinfo(int argc, char **argv)
if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
exit(1); 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); exit(2);
print_spdinfo(&req.n, (void*)stdout); print_spdinfo(&req.n, (void*)stdout);
...@@ -1143,7 +1143,7 @@ static int xfrm_policy_flush(int argc, char **argv) ...@@ -1143,7 +1143,7 @@ static int xfrm_policy_flush(int argc, char **argv)
if (show_stats > 1) if (show_stats > 1)
fprintf(stderr, "Flush policy\n"); 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); exit(2);
rtnl_close(&rth); rtnl_close(&rth);
......
...@@ -688,7 +688,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -688,7 +688,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
if (req.xsinfo.family == AF_UNSPEC) if (req.xsinfo.family == AF_UNSPEC)
req.xsinfo.family = AF_INET; 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); exit(2);
rtnl_close(&rth); rtnl_close(&rth);
...@@ -825,7 +825,7 @@ static int xfrm_state_allocspi(int argc, char **argv) ...@@ -825,7 +825,7 @@ static int xfrm_state_allocspi(int argc, char **argv)
req.xspi.info.family = AF_INET; 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); exit(2);
if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { 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) ...@@ -1015,7 +1015,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
req.xsid.family = AF_INET; req.xsid.family = AF_INET;
if (delete) { if (delete) {
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
exit(2); exit(2);
} else { } else {
char buf[NLMSG_BUF_SIZE]; char buf[NLMSG_BUF_SIZE];
...@@ -1023,7 +1023,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete) ...@@ -1023,7 +1023,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
memset(buf, 0, sizeof(buf)); 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); exit(2);
if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
...@@ -1297,7 +1297,7 @@ static int xfrm_sad_getinfo(int argc, char **argv) ...@@ -1297,7 +1297,7 @@ static int xfrm_sad_getinfo(int argc, char **argv)
if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
exit(1); 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); exit(2);
print_sadinfo(&req.n, (void*)stdout); print_sadinfo(&req.n, (void*)stdout);
...@@ -1351,7 +1351,7 @@ static int xfrm_state_flush(int argc, char **argv) ...@@ -1351,7 +1351,7 @@ static int xfrm_state_flush(int argc, char **argv)
fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n", fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n",
strxf_xfrmproto(req.xsf.proto)); 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); exit(2);
rtnl_close(&rth); rtnl_close(&rth);
......
...@@ -53,7 +53,7 @@ int genl_resolve_family(struct rtnl_handle *grth, const char *family) ...@@ -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, addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
family, strlen(family) + 1); 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"); fprintf(stderr, "Error talking to the kernel\n");
return -2; return -2;
} }
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
#include "libnetlink.h" #include "libnetlink.h"
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
int rcvbuf = 1024 * 1024; int rcvbuf = 1024 * 1024;
void rtnl_close(struct rtnl_handle *rth) void rtnl_close(struct rtnl_handle *rth)
...@@ -300,8 +304,8 @@ int rtnl_dump_filter(struct rtnl_handle *rth, ...@@ -300,8 +304,8 @@ int rtnl_dump_filter(struct rtnl_handle *rth,
return rtnl_dump_filter_l(rth, a); return rtnl_dump_filter_l(rth, a);
} }
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
unsigned groups, struct nlmsghdr *answer) struct nlmsghdr *answer, size_t len)
{ {
int status; int status;
unsigned seq; unsigned seq;
...@@ -317,12 +321,10 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, ...@@ -317,12 +321,10 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
.msg_iov = &iov, .msg_iov = &iov,
.msg_iovlen = 1, .msg_iovlen = 1,
}; };
char buf[16384]; char buf[32768];
memset(&nladdr, 0, sizeof(nladdr)); memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK; nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = peer;
nladdr.nl_groups = groups;
n->nlmsg_seq = seq = ++rtnl->seq; n->nlmsg_seq = seq = ++rtnl->seq;
...@@ -330,7 +332,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, ...@@ -330,7 +332,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
n->nlmsg_flags |= NLM_F_ACK; n->nlmsg_flags |= NLM_F_ACK;
status = sendmsg(rtnl->fd, &msg, 0); status = sendmsg(rtnl->fd, &msg, 0);
if (status < 0) { if (status < 0) {
perror("Cannot talk to rtnetlink"); perror("Cannot talk to rtnetlink");
return -1; return -1;
...@@ -339,7 +340,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, ...@@ -339,7 +340,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
memset(buf,0,sizeof(buf)); memset(buf,0,sizeof(buf));
iov.iov_base = buf; iov.iov_base = buf;
while (1) { while (1) {
iov.iov_len = sizeof(buf); iov.iov_len = sizeof(buf);
status = recvmsg(rtnl->fd, &msg, 0); status = recvmsg(rtnl->fd, &msg, 0);
...@@ -372,7 +372,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, ...@@ -372,7 +372,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
exit(1); exit(1);
} }
if (nladdr.nl_pid != peer || if (nladdr.nl_pid != 0 ||
h->nlmsg_pid != rtnl->local.nl_pid || h->nlmsg_pid != rtnl->local.nl_pid ||
h->nlmsg_seq != seq) { h->nlmsg_seq != seq) {
/* Don't forget to skip that message. */ /* Don't forget to skip that message. */
...@@ -385,20 +385,22 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, ...@@ -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); struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
if (l < sizeof(struct nlmsgerr)) { if (l < sizeof(struct nlmsgerr)) {
fprintf(stderr, "ERROR truncated\n"); fprintf(stderr, "ERROR truncated\n");
} else { } else if (!err->error) {
if (!err->error) { if (answer)
if (answer) memcpy(answer, h,
memcpy(answer, h, h->nlmsg_len); MIN(len, h->nlmsg_len));
return 0; return 0;
}
fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error));
errno = -err->error;
} }
fprintf(stderr, "RTNETLINK answers: %s\n",
strerror(-err->error));
errno = -err->error;
return -1; return -1;
} }
if (answer) { if (answer) {
memcpy(answer, h, h->nlmsg_len); memcpy(answer, h,
MIN(len, h->nlmsg_len));
return 0; return 0;
} }
...@@ -407,10 +409,12 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, ...@@ -407,10 +409,12 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
status -= NLMSG_ALIGN(len); status -= NLMSG_ALIGN(len);
h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
} }
if (msg.msg_flags & MSG_TRUNC) { if (msg.msg_flags & MSG_TRUNC) {
fprintf(stderr, "Message truncated\n"); fprintf(stderr, "Message truncated\n");
continue; continue;
} }
if (status) { if (status) {
fprintf(stderr, "!!!Remnant of size %d\n", status); fprintf(stderr, "!!!Remnant of size %d\n", status);
exit(1); exit(1);
......
...@@ -472,7 +472,7 @@ static int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p) ...@@ -472,7 +472,7 @@ static int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p)
if (cmd == RTM_GETACTION) if (cmd == RTM_GETACTION)
ans = &req.n; 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"); fprintf(stderr, "We have an error talking to the kernel\n");
return 1; return 1;
} }
...@@ -517,7 +517,7 @@ static int tc_action_modify(int cmd, unsigned flags, int *argc_p, char ***argv_p ...@@ -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; 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"); fprintf(stderr, "We have an error talking to the kernel\n");
ret = -1; ret = -1;
} }
...@@ -587,7 +587,7 @@ static int tc_act_list_or_flush(int argc, char **argv, int event) ...@@ -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_type = RTM_DELACTION;
req.n.nlmsg_flags |= NLM_F_ROOT; req.n.nlmsg_flags |= NLM_F_ROOT;
req.n.nlmsg_flags |= NLM_F_REQUEST; 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"); fprintf(stderr, "We have an error flushing\n");
return 1; return 1;
} }
......
...@@ -153,7 +153,7 @@ static int tc_class_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -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 2;
return 0; return 0;
......
...@@ -167,7 +167,7 @@ static int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -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"); fprintf(stderr, "We have an error talking to the kernel\n");
return 2; return 2;
} }
......
...@@ -187,7 +187,7 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -187,7 +187,7 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
req.t.tcm_ifindex = idx; 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 2;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment