Commit 33166f29 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Andrei Vagin

net: sockets -- Don't spam log with known errors

For example if diag module is not built then we should
not spam with error message but we will print an error
if only a particular socket is really used.

v2:
 - continue passing @ns into error handler because it should
   be balanced with receieve handler by number of arguments;
   while we don't use it yet in our handlers better to reserve
   it immediately for future use;

 - strictly speaking probing raw diag module has not much sense
   by now -- the kernel doesn't support its autoloading in some
   versions; still for code consistency we should do the same
   things for all modules.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@gmail.com>
parent 88a52c2b
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
struct ns_id; struct ns_id;
extern int do_rtnl_req(int nl, void *req, int size, extern int do_rtnl_req(int nl, void *req, int size,
int (*receive_callback)(struct nlmsghdr *h, struct ns_id *ns, void *), int (*receive_callback)(struct nlmsghdr *h, struct ns_id *ns, void *),
int (*error_callback)(int err, void *), struct ns_id *ns, void *); int (*error_callback)(int err, struct ns_id *ns, void *), struct ns_id *ns, void *);
extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, extern int addattr_l(struct nlmsghdr *n, int maxlen, int type,
const void *data, int alen); const void *data, int alen);
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
static int nlmsg_receive(char *buf, int len, static int nlmsg_receive(char *buf, int len,
int (*cb)(struct nlmsghdr *, struct ns_id *ns, void *), int (*cb)(struct nlmsghdr *, struct ns_id *ns, void *),
int (*err_cb)(int, void *), struct ns_id *ns, void *arg) int (*err_cb)(int, struct ns_id *, void *), struct ns_id *ns, void *arg)
{ {
struct nlmsghdr *hdr; struct nlmsghdr *hdr;
...@@ -22,7 +22,7 @@ static int nlmsg_receive(char *buf, int len, ...@@ -22,7 +22,7 @@ static int nlmsg_receive(char *buf, int len,
if (hdr->nlmsg_type == NLMSG_DONE) { if (hdr->nlmsg_type == NLMSG_DONE) {
int *len = (int *)NLMSG_DATA(hdr); int *len = (int *)NLMSG_DATA(hdr);
if (*len < 0) if (*len < 0)
return err_cb(*len, arg); return err_cb(*len, ns, arg);
return 0; return 0;
} }
if (hdr->nlmsg_type == NLMSG_ERROR) { if (hdr->nlmsg_type == NLMSG_ERROR) {
...@@ -36,7 +36,7 @@ static int nlmsg_receive(char *buf, int len, ...@@ -36,7 +36,7 @@ static int nlmsg_receive(char *buf, int len,
if (err->error == 0) if (err->error == 0)
return 0; return 0;
return err_cb(err->error, arg); return err_cb(err->error, ns, arg);
} }
if (cb(hdr, ns, arg)) if (cb(hdr, ns, arg))
return -1; return -1;
...@@ -45,7 +45,7 @@ static int nlmsg_receive(char *buf, int len, ...@@ -45,7 +45,7 @@ static int nlmsg_receive(char *buf, int len,
return 1; return 1;
} }
static int rtnl_return_err(int err, void *arg) static int rtnl_return_err(int err, struct ns_id *ns, void *arg)
{ {
errno = -err; errno = -err;
pr_perror("ERROR %d reported by netlink", err); pr_perror("ERROR %d reported by netlink", err);
...@@ -54,7 +54,7 @@ static int rtnl_return_err(int err, void *arg) ...@@ -54,7 +54,7 @@ static int rtnl_return_err(int err, void *arg)
int do_rtnl_req(int nl, void *req, int size, int do_rtnl_req(int nl, void *req, int size,
int (*receive_callback)(struct nlmsghdr *h, struct ns_id *ns, void *), int (*receive_callback)(struct nlmsghdr *h, struct ns_id *ns, void *),
int (*error_callback)(int err, void *), struct ns_id *ns, void *arg) int (*error_callback)(int err, struct ns_id *ns, void *arg), struct ns_id *ns, void *arg)
{ {
struct msghdr msg; struct msghdr msg;
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
......
...@@ -212,7 +212,7 @@ static int probe_recv_one(struct nlmsghdr *h, struct ns_id *ns, void *arg) ...@@ -212,7 +212,7 @@ static int probe_recv_one(struct nlmsghdr *h, struct ns_id *ns, void *arg)
return -1; return -1;
} }
static int probe_err(int err, void *arg) static int probe_err(int err, struct ns_id *ns, void *arg)
{ {
int expected_err = *(int *)arg; int expected_err = *(int *)arg;
...@@ -716,18 +716,57 @@ static int inet_receive_one(struct nlmsghdr *h, struct ns_id *ns, void *arg) ...@@ -716,18 +716,57 @@ static int inet_receive_one(struct nlmsghdr *h, struct ns_id *ns, void *arg)
static int do_collect_req(int nl, struct sock_diag_req *req, int size, static int do_collect_req(int nl, struct sock_diag_req *req, int size,
int (*receive_callback)(struct nlmsghdr *h, struct ns_id *ns, void *), int (*receive_callback)(struct nlmsghdr *h, struct ns_id *ns, void *),
int (*error_callback)(int err, struct ns_id *ns, void *),
struct ns_id *ns, void *arg) struct ns_id *ns, void *arg)
{ {
int tmp; int tmp = do_rtnl_req(nl, req, size, receive_callback, error_callback, ns, arg);
tmp = do_rtnl_req(nl, req, size, receive_callback, NULL, ns, arg);
if (tmp == 0) if (tmp == 0)
set_collect_bit(req->r.n.sdiag_family, req->r.n.sdiag_protocol); set_collect_bit(req->r.n.sdiag_family, req->r.n.sdiag_protocol);
return tmp; return tmp;
} }
static int collect_err(int err, struct ns_id *ns, void *arg)
{
struct sock_diag_greq *gr = arg;
char family[32], proto[32];
char msg[256];
/*
* If module is not compiled or unloaded,
* we should simply pass error up to a caller
* which then warn a user.
*/
if (err == -ENOENT)
return -ENOENT;
/*
* Diag modules such as unix, packet, netlink
* may return EINVAL on older kernels.
*/
if (err == -EINVAL) {
if (gr->family == AF_UNIX ||
gr->family == AF_PACKET ||
gr->family == AF_NETLINK)
return -EINVAL;
}
/*
* Rest is more serious, just print enough information.
* In case if everything is OK -- point as well.
*/
snprintf(msg, sizeof(msg),
"Sockects collect procedure family %s proto %s\n",
socket_family_name(gr->family, family, sizeof(family)),
socket_proto_name(gr->protocol, proto, sizeof(proto)));
if (!err)
pr_info("%s: OK\n", msg);
else
pr_err("%s: %s\n", msg, strerror(-err));
return err;
}
int collect_sockets(struct ns_id *ns) int collect_sockets(struct ns_id *ns)
{ {
int err = 0, tmp; int err = 0, tmp;
...@@ -746,7 +785,7 @@ int collect_sockets(struct ns_id *ns) ...@@ -746,7 +785,7 @@ int collect_sockets(struct ns_id *ns)
req.r.u.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_VFS | req.r.u.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_VFS |
UDIAG_SHOW_PEER | UDIAG_SHOW_ICONS | UDIAG_SHOW_PEER | UDIAG_SHOW_ICONS |
UDIAG_SHOW_RQLEN; UDIAG_SHOW_RQLEN;
tmp = do_collect_req(nl, &req, sizeof(req), unix_receive_one, ns, NULL); tmp = do_collect_req(nl, &req, sizeof(req), unix_receive_one, collect_err, ns, &req.r.u);
if (tmp) if (tmp)
err = tmp; err = tmp;
...@@ -759,7 +798,7 @@ int collect_sockets(struct ns_id *ns) ...@@ -759,7 +798,7 @@ int collect_sockets(struct ns_id *ns)
(1 << TCP_FIN_WAIT1) | (1 << TCP_FIN_WAIT2) | (1 << TCP_FIN_WAIT1) | (1 << TCP_FIN_WAIT2) |
(1 << TCP_CLOSE_WAIT) | (1 << TCP_LAST_ACK) | (1 << TCP_CLOSE_WAIT) | (1 << TCP_LAST_ACK) |
(1 << TCP_CLOSING) | (1 << TCP_SYN_SENT); (1 << TCP_CLOSING) | (1 << TCP_SYN_SENT);
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) if (tmp)
err = tmp; err = tmp;
...@@ -768,7 +807,7 @@ int collect_sockets(struct ns_id *ns) ...@@ -768,7 +807,7 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_UDP; req.r.i.sdiag_protocol = IPPROTO_UDP;
req.r.i.idiag_ext = 0; req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */ req.r.i.idiag_states = -1; /* All */
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) if (tmp)
err = tmp; err = tmp;
...@@ -777,7 +816,7 @@ int collect_sockets(struct ns_id *ns) ...@@ -777,7 +816,7 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_UDPLITE; req.r.i.sdiag_protocol = IPPROTO_UDPLITE;
req.r.i.idiag_ext = 0; req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */ req.r.i.idiag_states = -1; /* All */
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) if (tmp)
err = tmp; err = tmp;
...@@ -786,12 +825,9 @@ int collect_sockets(struct ns_id *ns) ...@@ -786,12 +825,9 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_RAW; req.r.i.sdiag_protocol = IPPROTO_RAW;
req.r.i.idiag_ext = 0; req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */ req.r.i.idiag_states = -1; /* All */
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) { if (tmp)
pr_warn("The current kernel doesn't support ipv4 raw_diag module\n"); err = tmp;
if (tmp != -ENOENT)
err = tmp;
}
/* Collect IPv6 TCP sockets */ /* Collect IPv6 TCP sockets */
req.r.i.sdiag_family = AF_INET6; req.r.i.sdiag_family = AF_INET6;
...@@ -802,7 +838,7 @@ int collect_sockets(struct ns_id *ns) ...@@ -802,7 +838,7 @@ int collect_sockets(struct ns_id *ns)
(1 << TCP_FIN_WAIT1) | (1 << TCP_FIN_WAIT2) | (1 << TCP_FIN_WAIT1) | (1 << TCP_FIN_WAIT2) |
(1 << TCP_CLOSE_WAIT) | (1 << TCP_LAST_ACK) | (1 << TCP_CLOSE_WAIT) | (1 << TCP_LAST_ACK) |
(1 << TCP_CLOSING) | (1 << TCP_SYN_SENT); (1 << TCP_CLOSING) | (1 << TCP_SYN_SENT);
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) if (tmp)
err = tmp; err = tmp;
...@@ -811,7 +847,7 @@ int collect_sockets(struct ns_id *ns) ...@@ -811,7 +847,7 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_UDP; req.r.i.sdiag_protocol = IPPROTO_UDP;
req.r.i.idiag_ext = 0; req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */ req.r.i.idiag_states = -1; /* All */
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) if (tmp)
err = tmp; err = tmp;
...@@ -820,7 +856,7 @@ int collect_sockets(struct ns_id *ns) ...@@ -820,7 +856,7 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_UDPLITE; req.r.i.sdiag_protocol = IPPROTO_UDPLITE;
req.r.i.idiag_ext = 0; req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */ req.r.i.idiag_states = -1; /* All */
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) if (tmp)
err = tmp; err = tmp;
...@@ -829,33 +865,24 @@ int collect_sockets(struct ns_id *ns) ...@@ -829,33 +865,24 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_RAW; req.r.i.sdiag_protocol = IPPROTO_RAW;
req.r.i.idiag_ext = 0; req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */ req.r.i.idiag_states = -1; /* All */
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, collect_err, ns, &req.r.i);
if (tmp) { if (tmp)
pr_warn("The current kernel doesn't support ipv6 raw_diag module\n"); err = tmp;
if (tmp != -ENOENT)
err = tmp;
}
req.r.p.sdiag_family = AF_PACKET; req.r.p.sdiag_family = AF_PACKET;
req.r.p.sdiag_protocol = 0; req.r.p.sdiag_protocol = 0;
req.r.p.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST | req.r.p.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST |
PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG; PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG;
tmp = do_collect_req(nl, &req, sizeof(req), packet_receive_one, ns, NULL); tmp = do_collect_req(nl, &req, sizeof(req), packet_receive_one, collect_err, ns, &req.r.p);
if (tmp) { if (tmp)
pr_warn("The current kernel doesn't support packet_diag\n"); err = tmp;
if (ns->ns_pid == 0 || tmp != -ENOENT) /* Fedora 19 */
err = tmp;
}
req.r.n.sdiag_family = AF_NETLINK; req.r.n.sdiag_family = AF_NETLINK;
req.r.n.sdiag_protocol = NDIAG_PROTO_ALL; req.r.n.sdiag_protocol = NDIAG_PROTO_ALL;
req.r.n.ndiag_show = NDIAG_SHOW_GROUPS; req.r.n.ndiag_show = NDIAG_SHOW_GROUPS;
tmp = do_collect_req(nl, &req, sizeof(req), netlink_receive_one, ns, NULL); tmp = do_collect_req(nl, &req, sizeof(req), netlink_receive_one, collect_err, ns, &req.r.n);
if (tmp) { if (tmp)
pr_warn("The current kernel doesn't support netlink_diag\n"); err = tmp;
if (ns->ns_pid == 0 || tmp != -ENOENT) /* Fedora 19 */
err = tmp;
}
/* don't need anymore */ /* don't need anymore */
close(nl); close(nl);
......
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