|
@@ -426,7 +426,7 @@ out:
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk);
|
|
|
|
|
|
-static int inet_diag_get_exact(struct sk_buff *in_skb,
|
|
|
+static int inet_diag_cmd_exact(int cmd, struct sk_buff *in_skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
const struct inet_diag_req_v2 *req)
|
|
|
{
|
|
@@ -436,8 +436,12 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,
|
|
|
handler = inet_diag_lock_handler(req->sdiag_protocol);
|
|
|
if (IS_ERR(handler))
|
|
|
err = PTR_ERR(handler);
|
|
|
- else
|
|
|
+ else if (cmd == SOCK_DIAG_BY_FAMILY)
|
|
|
err = handler->dump_one(in_skb, nlh, req);
|
|
|
+ else if (cmd == SOCK_DESTROY && handler->destroy)
|
|
|
+ err = handler->destroy(in_skb, req);
|
|
|
+ else
|
|
|
+ err = -EOPNOTSUPP;
|
|
|
inet_diag_unlock_handler(handler);
|
|
|
|
|
|
return err;
|
|
@@ -950,7 +954,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
|
|
|
req.idiag_states = rc->idiag_states;
|
|
|
req.id = rc->id;
|
|
|
|
|
|
- return inet_diag_get_exact(in_skb, nlh, &req);
|
|
|
+ return inet_diag_cmd_exact(SOCK_DIAG_BY_FAMILY, in_skb, nlh, &req);
|
|
|
}
|
|
|
|
|
|
static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
@@ -984,7 +988,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
|
return inet_diag_get_exact_compat(skb, nlh);
|
|
|
}
|
|
|
|
|
|
-static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
|
+static int inet_diag_handler_cmd(struct sk_buff *skb, struct nlmsghdr *h)
|
|
|
{
|
|
|
int hdrlen = sizeof(struct inet_diag_req_v2);
|
|
|
struct net *net = sock_net(skb->sk);
|
|
@@ -992,7 +996,8 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
|
if (nlmsg_len(h) < hdrlen)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (h->nlmsg_flags & NLM_F_DUMP) {
|
|
|
+ if (h->nlmsg_type == SOCK_DIAG_BY_FAMILY &&
|
|
|
+ h->nlmsg_flags & NLM_F_DUMP) {
|
|
|
if (nlmsg_attrlen(h, hdrlen)) {
|
|
|
struct nlattr *attr;
|
|
|
|
|
@@ -1011,7 +1016,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return inet_diag_get_exact(skb, h, nlmsg_data(h));
|
|
|
+ return inet_diag_cmd_exact(h->nlmsg_type, skb, h, nlmsg_data(h));
|
|
|
}
|
|
|
|
|
|
static
|
|
@@ -1062,14 +1067,16 @@ int inet_diag_handler_get_info(struct sk_buff *skb, struct sock *sk)
|
|
|
|
|
|
static const struct sock_diag_handler inet_diag_handler = {
|
|
|
.family = AF_INET,
|
|
|
- .dump = inet_diag_handler_dump,
|
|
|
+ .dump = inet_diag_handler_cmd,
|
|
|
.get_info = inet_diag_handler_get_info,
|
|
|
+ .destroy = inet_diag_handler_cmd,
|
|
|
};
|
|
|
|
|
|
static const struct sock_diag_handler inet6_diag_handler = {
|
|
|
.family = AF_INET6,
|
|
|
- .dump = inet_diag_handler_dump,
|
|
|
+ .dump = inet_diag_handler_cmd,
|
|
|
.get_info = inet_diag_handler_get_info,
|
|
|
+ .destroy = inet_diag_handler_cmd,
|
|
|
};
|
|
|
|
|
|
int inet_diag_register(const struct inet_diag_handler *h)
|