Generalize the inet_diag infrastructure
Subsystems (5)
cover Generalize the inet_diag infrastructure
This is an attempt to prepare the existing inet_diag infrastructure to work with arbitrary address family and protocol pair, not only AF_INET(6) and TCP/DCCP.
This set adds the sock_diag infrastructure, that handles the new SOCK_DIAG_BY_FAMILY message type by the NETLINK_INET_DIAG socket. The core API struct for this (called sock_diag_req) contains two fields - family and type - which specify which sockets to dump. Additional information is considered to be family handler specific.
The existing inet_diag code is patched to register himself inside the sock_diag and provide callbacks for dumping AF_INET/AF_INET6 IPPROTO_TCP/IPPROTO_DCCP sockets. The existing API facilities such as state filtering and bytecode is of course preserved and is treated by inet_diag specific data.
Binary compatibility with existing NETLINK_INET_DIAG is also kept.
No additional stuff in this set. The support for IPPROTO_UDP protocol and AF_UNIX family will come later if this set is approved.
Applies to net-next, patch for iproute2's ss tool (proving that the new code ... pretends to work) is at the end of the thread.
PATCH 1/11 inet_diag: Partly rename inet_ to sock_
The ultimate goal is to get the sock_diag module, that works in family+protocol terms. Currently this is suitable to do on the inet_diag basis, so rename parts of the code. It will be moved to sock_diag.c later.
--- include/linux/netlink.h | 2 +- net/dccp/diag.c | 2 +- net/ipv4/inet_diag.c | 33 +++++++++++++++++++-------------- net/ipv4/tcp_diag.c | 2 +- security/selinux/hooks.c | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-)
include/linux/netlink.h +1 -1
@@ -8,7 +8,7 @@#define NETLINK_UNUSED 1/* Unused number */ #define NETLINK_USERSOCK 2/* Reserved for user mode socket protocols */ #define NETLINK_FIREWALL 3/* Firewalling hook */ -#define NETLINK_INET_DIAG 4/* INET socket monitoring */ +#define NETLINK_SOCK_DIAG 4/* socket monitoring */ #define NETLINK_NFLOG 5/* netfilter/iptables ULOG */ #define NETLINK_XFRM 6/* ipsec */ #define NETLINK_SELINUX 7/* SELinux event notifications */
net/dccp/diag.c +1 -1
@@ -71,4 +71,4 @@ module_exit(dccp_diag_fini);MODULE_LICENSE ("GPL" );MODULE_AUTHOR ("Arnaldo Carvalho de Melo <[email protected]>" );MODULE_DESCRIPTION ("DCCP inet_diag handler" ); -MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_INET_DIAG ,DCCPDIAG_GETSOCK ); +MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_SOCK_DIAG ,DCCPDIAG_GETSOCK );
net/ipv4/inet_diag.c +19 -14
@@ -45,7 +45,7 @@ struct inet_diag_entry {u16 userlocks; }; -static struct sock *idiagnl; +static struct sock *sdiagnl;#define INET_DIAG_PUT (skb, attrtype, attrlen) \ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
@@ -56,7 +56,7 @@ static const struct inet_diag_handler *inet_diag_lock_handler(int type) {if (!inet_diag_table[type])request_module ("net-pf-%d-proto-%d-type-%d" ,PF_NETLINK , -NETLINK_INET_DIAG , type); +NETLINK_SOCK_DIAG , type);mutex_lock (&inet_diag_table_mutex);if (!inet_diag_table[type])
@@ -312,7 +312,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,kfree_skb (rep); goto out; } - err =netlink_unicast (idiagnl, rep,NETLINK_CB (in_skb).pid, + err =netlink_unicast (sdiagnl, rep,NETLINK_CB (in_skb).pid,MSG_DONTWAIT );if (err >0 ) err =0 ;
@@ -870,20 +870,25 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)return -EINVAL ; } -return netlink_dump_start (idiagnl, skb, nlh, +return netlink_dump_start (sdiagnl, skb, nlh, inet_diag_dump,NULL ,0 ); }return inet_diag_get_exact (skb, nlh); } -static DEFINE_MUTEX (inet_diag_mutex); +static int sock_diag_rcv_msg (struct sk_buff *skb,struct nlmsghdr *nlh) +{ +return inet_diag_rcv_msg (skb, nlh); +} + +static DEFINE_MUTEX (sock_diag_mutex); -static void inet_diag_rcv (struct sk_buff *skb) +static void sock_diag_rcv (struct sk_buff *skb) { -mutex_lock (&inet_diag_mutex); -netlink_rcv_skb (skb, &inet_diag_rcv_msg); -mutex_unlock (&inet_diag_mutex); +mutex_lock (&sock_diag_mutex); +netlink_rcv_skb (skb, &sock_diag_rcv_msg); +mutex_unlock (&sock_diag_mutex); }int inet_diag_register (const struct inet_diag_handler *h)
@@ -929,9 +934,9 @@ static int __init inet_diag_init(void)if (!inet_diag_table) goto out; - idiagnl =netlink_kernel_create (&init_net,NETLINK_INET_DIAG ,0 , - inet_diag_rcv,NULL ,THIS_MODULE ); -if (idiagnl ==NULL ) + sdiagnl =netlink_kernel_create (&init_net,NETLINK_SOCK_DIAG ,0 , + sock_diag_rcv,NULL ,THIS_MODULE ); +if (sdiagnl ==NULL ) goto out_free_table; err =0 ; out:
@@ -943,11 +948,11 @@ out_free_table: static void __exit inet_diag_exit(void) { -netlink_kernel_release (idiagnl); +netlink_kernel_release (sdiagnl);kfree (inet_diag_table); }module_init (inet_diag_init);module_exit (inet_diag_exit);MODULE_LICENSE ("GPL" ); -MODULE_ALIAS_NET_PF_PROTO (PF_NETLINK ,NETLINK_INET_DIAG ); +MODULE_ALIAS_NET_PF_PROTO (PF_NETLINK ,NETLINK_SOCK_DIAG );
net/ipv4/tcp_diag.c +1 -1
@@ -54,4 +54,4 @@ static void __exit tcp_diag_exit(void)module_init (tcp_diag_init);module_exit (tcp_diag_exit);MODULE_LICENSE ("GPL" ); -MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_INET_DIAG ,TCPDIAG_GETSOCK ); +MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_SOCK_DIAG ,TCPDIAG_GETSOCK );
security/selinux/hooks.c +1 -1
@@ -1090,7 +1090,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protocreturn SECCLASS_NETLINK_ROUTE_SOCKET ;case NETLINK_FIREWALL :return SECCLASS_NETLINK_FIREWALL_SOCKET ; -case NETLINK_INET_DIAG : +case NETLINK_SOCK_DIAG :return SECCLASS_NETLINK_TCPDIAG_SOCKET ;case NETLINK_NFLOG :return SECCLASS_NETLINK_NFLOG_SOCKET ;
Signature · 1 line
1.5.5.6
Re: [PATCH 1/11] inet_diag: Partly rename inet_ to sock_
include/linux/netlink.h line 14
Quoted 13 lines · On Tue, 06 Dec 2011 21:56:43 +0400 Pavel Emelyanov <[email protected]> wrote:
include/linux/netlink.h +1
-1@@ -8,7 +8,7 @@#define NETLINK_UNUSED 1/* Unused number */ #define NETLINK_USERSOCK 2/* Reserved for user mode socket protocols */ #define NETLINK_FIREWALL 3/* Firewalling hook */ -#define NETLINK_INET_DIAG 4/* INET socket monitoring */ +#define NETLINK_SOCK_DIAG 4/* socket monitoring */ #define NETLINK_NFLOG 5/* netfilter/iptables ULOG */ #define NETLINK_XFRM 6/* ipsec */ #define NETLINK_SELINUX 7/* SELinux event notifications */
This is a header file that is stripped and exported by other tools. You can add new entries but need to keep existing define's to avoid breaking source compatibility.
David Miller
maintainerRe: [PATCH 1/11] inet_diag: Partly rename inet_ to sock_
From: Stephen Hemminger <[email protected]>
Date: Tue, 6 Dec 2011 10:24:47 -0800
Quoted 12 lines
Quoted 9 lines · On Tue, 06 Dec 2011 21:56:43 +0400 Pavel Emelyanov <[email protected]> wrote:
include/linux/netlink.h +0
-1@@ -8,7 +8,7 @@#define NETLINK_UNUSED 1/* Unused number */ #define NETLINK_USERSOCK 2/* Reserved for user mode socket protocols */ #define NETLINK_FIREWALL 3/* Firewalling hook */ -#define NETLINK_INET_DIAG 4/* INET socket monitoring */
Quoted 8 lines
include/linux/netlink.h line 14
Quoted 4 lines
include/linux/netlink.h +1
-0+#define NETLINK_SOCK_DIAG 4/* socket monitoring */ #define NETLINK_NFLOG 5/* netfilter/iptables ULOG */ #define NETLINK_XFRM 6/* ipsec */ #define NETLINK_SELINUX 7/* SELinux event notifications */ This is a header file that is stripped and exported by other tools. You can add new entries but need to keep existing define's to avoid breaking source compatibility.
Indeed, NETLINK_INET_DIAG must be kept around forever because that's what userland source code references.
I'll fix this up when applying Pavel's patches, by simply adding a new alias that userland can start being coverted over to use.
PATCH 2/11 sock_diag: Introduce new message type
In reply to Pavel EmelyanovThis type will run the family+protocol based socket dumping. Also prepare the stub function for it.
--- include/linux/inet_diag.h | 1 + net/ipv4/inet_diag.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-)
include/linux/inet_diag.h +1 -0
@@ -6,6 +6,7 @@/* Just some random number */ #define TCPDIAG_GETSOCK 18#define DCCPDIAG_GETSOCK 19 +#define SOCK_DIAG_BY_FAMILY 20#define INET_DIAG_GETSOCK_MAX 24
net/ipv4/inet_diag.c +15 -2
@@ -850,7 +850,7 @@ unlock:return skb->len; } -static int inet_diag_rcv_msg (struct sk_buff *skb,struct nlmsghdr *nlh) +static int inet_diag_rcv_msg_compat (struct sk_buff *skb,struct nlmsghdr *nlh) {int hdrlen =sizeof (struct inet_diag_req );
@@ -877,9 +877,22 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)return inet_diag_get_exact (skb, nlh); } +static int __sock_diag_rcv_msg (struct sk_buff *skb,struct nlmsghdr *nlh) +{ +return -EOPNOTSUPP ; +} +static int sock_diag_rcv_msg (struct sk_buff *skb,struct nlmsghdr *nlh) { -return inet_diag_rcv_msg (skb, nlh); +switch (nlh->nlmsg_type) { +case TCPDIAG_GETSOCK : +case DCCPDIAG_GETSOCK : +return inet_diag_rcv_msg_compat (skb, nlh); +case SOCK_DIAG_BY_FAMILY : +return __sock_diag_rcv_msg (skb, nlh); +default : +return -EINVAL ; + } }static DEFINE_MUTEX (sock_diag_mutex);
Signature · 1 line
1.5.5.6
PATCH 3/11 inet_diag: Move byte-code finding up the call-stack
In reply to Pavel EmelyanovCurrent code calculates it at fixed offset. This offset will change, so move the BC calculation upper to make the further patching simpler.
--- net/ipv4/inet_diag.c | 36 +++++++++++++++++------------------- 1 files changed, 17 insertions(+), 19 deletions(-)
net/ipv4/inet_diag.c +17 -19
@@ -488,15 +488,13 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)static int inet_csk_diag_dump (struct sock *sk,struct sk_buff *skb, -struct netlink_callback *cb) +struct netlink_callback *cb, +const struct nlattr *bc) {struct inet_diag_req *r =NLMSG_DATA (cb->nlh); -if (nlmsg_attrlen (cb->nlh,sizeof (*r))) { +if (bc !=NULL ) {struct inet_diag_entry entry; -const struct nlattr *bc =nlmsg_find_attr (cb->nlh, -sizeof (*r), -INET_DIAG_REQ_BYTECODE );struct inet_sock *inet =inet_sk (sk); entry.family = sk->sk_family;
@@ -527,15 +525,13 @@ static int inet_csk_diag_dump(struct sock *sk,static int inet_twsk_diag_dump (struct inet_timewait_sock *tw,struct sk_buff *skb, -struct netlink_callback *cb) +struct netlink_callback *cb, +const struct nlattr *bc) {struct inet_diag_req *r =NLMSG_DATA (cb->nlh); -if (nlmsg_attrlen (cb->nlh,sizeof (*r))) { +if (bc !=NULL ) {struct inet_diag_entry entry; -const struct nlattr *bc =nlmsg_find_attr (cb->nlh, -sizeof (*r), -INET_DIAG_REQ_BYTECODE ); entry.family = tw->tw_family;#if defined(CONFIG_IPV6 ) || defined (CONFIG_IPV6_MODULE )
@@ -616,13 +612,13 @@ nlmsg_failure: }static int inet_diag_dump_reqs (struct sk_buff *skb,struct sock *sk, -struct netlink_callback *cb) +struct netlink_callback *cb, +const struct nlattr *bc) {struct inet_diag_entry entry;struct inet_diag_req *r =NLMSG_DATA (cb->nlh);struct inet_connection_sock *icsk =inet_csk (sk);struct listen_sock *lopt; -const struct nlattr *bc =NULL ;struct inet_sock *inet =inet_sk (sk);int j, s_j;int reqnum, s_reqnum;
@@ -642,9 +638,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,if (!lopt || !lopt->qlen) goto out; -if (nlmsg_attrlen (cb->nlh,sizeof (*r))) { - bc =nlmsg_find_attr (cb->nlh,sizeof (*r), -INET_DIAG_REQ_BYTECODE ); +if (bc !=NULL ) { entry.sport = inet->inet_num; entry.userlocks = sk->sk_userlocks; }
@@ -708,6 +702,10 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)struct inet_diag_req *r =NLMSG_DATA (cb->nlh);const struct inet_diag_handler *handler;struct inet_hashinfo *hashinfo; +const struct nlattr *bc =NULL ; + +if (nlmsg_attrlen (cb->nlh,sizeof (struct inet_diag_req ))) + bc =nlmsg_find_attr (cb->nlh,sizeof (*r),INET_DIAG_REQ_BYTECODE ); handler =inet_diag_lock_handler (cb->nlh->nlmsg_type);if (IS_ERR (handler))
@@ -747,7 +745,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) cb->args[3] > 0) goto syn_recv; -if (inet_csk_diag_dump (sk, skb, cb) <0 ) { +if (inet_csk_diag_dump (sk, skb, cb, bc) <0 ) {spin_unlock_bh (&ilb->lock); goto done; }
@@ -756,7 +754,7 @@ syn_recv:if (!(r->idiag_states &TCPF_SYN_RECV )) goto next_listen; -if (inet_diag_dump_reqs (skb, sk, cb) <0 ) { +if (inet_diag_dump_reqs (skb, sk, cb, bc) <0 ) {spin_unlock_bh (&ilb->lock); goto done; }
@@ -809,7 +807,7 @@ skip_listen_ht:if (r->id.idiag_dport != inet->inet_dport && r->id.idiag_dport) goto next_normal; -if (inet_csk_diag_dump (sk, skb, cb) <0 ) { +if (inet_csk_diag_dump (sk, skb, cb, bc) <0 ) {spin_unlock_bh (lock); goto done; }
@@ -831,7 +829,7 @@ next_normal:if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; -if (inet_twsk_diag_dump (tw, skb, cb) <0 ) { +if (inet_twsk_diag_dump (tw, skb, cb, bc) <0 ) {spin_unlock_bh (lock); goto done; }
Signature · 1 line
1.5.5.6
PATCH 5/11 sock_diag: Initial skeleton
In reply to Pavel EmelyanovWhen receiving the SOCK_DIAG_BY_FAMILY message we have to find the handler for provided family and pass the nl message to it.
This patch describes an infrastructure to work with such nandlers and implements stubs for AF_INET(6) ones.
--- include/linux/sock_diag.h | 23 ++++++++++ net/ipv4/inet_diag.c | 102 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 include/linux/sock_diag.h
include/linux/sock_diag.h new file +23 -0
@@ -0,0 +1,23 @@ +#ifndef __SOCK_DIAG_H__ +#define __SOCK_DIAG_H__ +struct sk_buff ; +struct nlmsghdr ; + +struct sock_diag_req { +__u8 sdiag_family; +__u8 sdiag_protocol; +}; + +struct sock_diag_handler { +__u8 family; +int (*dump)(struct sk_buff *skb,struct nlmsghdr *nlh); +}; + +int sock_diag_register (struct sock_diag_handler *h); +void sock_diag_unregister (struct sock_diag_handler *h); + +void sock_diag_register_inet_compat (int (*fn)(struct sk_buff *skb,struct nlmsghdr *nlh)); +void sock_diag_unregister_inet_compat (int (*fn)(struct sk_buff *skb,struct nlmsghdr *nlh)); + +extern struct sock *sock_diag_nlsk; +#endif
net/ipv4/inet_diag.c +100 -2
130 lines not on this page · raw message
Signature · 1 line
1.5.5.6
PATCH 6/11 inet_diag: Introduce new inet_diag_req header
In reply to Pavel EmelyanovThis one coinsides with the sock_diag_req in the beginning and contains only used fields from its previous analogue.
The existing code is patched to use the _compat version of it for now.
--- include/linux/inet_diag.h | 11 ++++++++++- net/ipv4/inet_diag.c | 14 +++++++------- 2 files changed, 17 insertions(+), 8 deletions(-)
include/linux/inet_diag.h +10 -1
@@ -23,7 +23,7 @@ struct inet_diag_sockid {/* Request structure */ -struct inet_diag_req { +struct inet_diag_req_compat {__u8 idiag_family;/* Family of addresses. */ __u8 idiag_src_len;__u8 idiag_dst_len;
@@ -35,6 +35,15 @@ struct inet_diag_req {__u32 idiag_dbs;/* Tables to dump (NI) */ }; +struct inet_diag_req { +__u8 sdiag_family; +__u8 sdiag_protocol; +__u8 idiag_ext; +__u8 pad; +__u32 idiag_states; +struct inet_diag_sockid id; +}; +enum {INET_DIAG_REQ_NONE ,INET_DIAG_REQ_BYTECODE ,
net/ipv4/inet_diag.c +7 -7
@@ -265,7 +265,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, {int err;struct sock *sk; -struct inet_diag_req *req =NLMSG_DATA (nlh); +struct inet_diag_req_compat *req =NLMSG_DATA (nlh);struct sk_buff *rep;struct inet_hashinfo *hashinfo;const struct inet_diag_handler *handler;
@@ -504,7 +504,7 @@ static int inet_csk_diag_dump(struct sock *sk,struct netlink_callback *cb, const struct nlattr *bc) { - struct inet_diag_req *r = NLMSG_DATA(cb->nlh); + struct inet_diag_req_compat *r = NLMSG_DATA(cb->nlh);if (bc !=NULL ) {struct inet_diag_entry entry;
@@ -541,7 +541,7 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,struct netlink_callback *cb, const struct nlattr *bc) { - struct inet_diag_req *r = NLMSG_DATA(cb->nlh); + struct inet_diag_req_compat *r = NLMSG_DATA(cb->nlh);if (bc !=NULL ) {struct inet_diag_entry entry;
@@ -629,7 +629,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, const struct nlattr *bc) {struct inet_diag_entry entry; -struct inet_diag_req *r =NLMSG_DATA (cb->nlh); +struct inet_diag_req_compat *r =NLMSG_DATA (cb->nlh);struct inet_connection_sock *icsk =inet_csk (sk);struct listen_sock *lopt;struct inet_sock *inet =inet_sk (sk);
@@ -712,12 +712,12 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) {int i, num;int s_i, s_num; -struct inet_diag_req *r =NLMSG_DATA (cb->nlh); +struct inet_diag_req_compat *r =NLMSG_DATA (cb->nlh);const struct inet_diag_handler *handler;struct inet_hashinfo *hashinfo;const struct nlattr *bc =NULL ; -if (nlmsg_attrlen (cb->nlh,sizeof (struct inet_diag_req ))) +if (nlmsg_attrlen (cb->nlh,sizeof (struct inet_diag_req_compat ))) bc =nlmsg_find_attr (cb->nlh,sizeof (*r),INET_DIAG_REQ_BYTECODE ); handler =inet_diag_lock_handler (inet_diag_type2proto (cb->nlh->nlmsg_type));
@@ -863,7 +863,7 @@ unlock:static int inet_diag_rcv_msg_compat (struct sk_buff *skb,struct nlmsghdr *nlh) { -int hdrlen =sizeof (struct inet_diag_req ); +int hdrlen =sizeof (struct inet_diag_req_compat );if (nlh->nlmsg_type >=INET_DIAG_GETSOCK_MAX ||nlmsg_len (nlh) < hdrlen)
Signature · 1 line
1.5.5.6
PATCH 7/11 inet_diag: Switch the _get_exact to work with new header
In reply to Pavel EmelyanovMake inet_diag_get_exact work with given header instead of calculating one from the nl message.
The SOCK_DIAG_BY_FAMILY just passes skb's one through, the compat code converts the old header to new one.
--- net/ipv4/inet_diag.c | 29 ++++++++++++++++++++++------- 1 files changed, 22 insertions(+), 7 deletions(-)
net/ipv4/inet_diag.c +22 -7
@@ -261,16 +261,16 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, }static int inet_diag_get_exact (struct sk_buff *in_skb, -const struct nlmsghdr *nlh) +const struct nlmsghdr *nlh, +struct inet_diag_req *req) {int err;struct sock *sk; -struct inet_diag_req_compat *req =NLMSG_DATA (nlh);struct sk_buff *rep;struct inet_hashinfo *hashinfo;const struct inet_diag_handler *handler; - handler =inet_diag_lock_handler (inet_diag_type2proto (nlh->nlmsg_type)); + handler =inet_diag_lock_handler (req->sdiag_protocol);if (IS_ERR (handler)) { err =PTR_ERR (handler); goto unlock;
@@ -279,13 +279,13 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, hashinfo = handler->idiag_hashinfo; err = -EINVAL ; -if (req->idiag_family ==AF_INET ) { +if (req->sdiag_family ==AF_INET ) { sk =inet_lookup (&init_net, hashinfo, req->id.idiag_dst[0 ], req->id.idiag_dport, req->id.idiag_src[0 ], req->id.idiag_sport, req->id.idiag_if); }#if defined(CONFIG_IPV6 ) || defined (CONFIG_IPV6_MODULE ) - else if (req->idiag_family == AF_INET6) { + else if (req->sdiag_family == AF_INET6) { sk = inet6_lookup(&init_net, hashinfo, (struct in6_addr *)req->id.idiag_dst, req->id.idiag_dport,
@@ -861,6 +861,21 @@ unlock:return skb->len; } +static int inet_diag_get_exact_compat (struct sk_buff *in_skb, +const struct nlmsghdr *nlh) +{ +struct inet_diag_req_compat *rc =NLMSG_DATA (nlh); +struct inet_diag_req req; + + req.sdiag_family = rc->idiag_family; + req.sdiag_protocol =inet_diag_type2proto (nlh->nlmsg_type); + req.idiag_ext = rc->idiag_ext; + req.idiag_states = rc->idiag_states; + req.id = rc->id; + +return inet_diag_get_exact (in_skb, nlh, &req); +} +static int inet_diag_rcv_msg_compat (struct sk_buff *skb,struct nlmsghdr *nlh) {int hdrlen =sizeof (struct inet_diag_req_compat );
@@ -885,7 +900,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) inet_diag_dump, NULL, 0); } -return inet_diag_get_exact (skb, nlh); +return inet_diag_get_exact_compat (skb, nlh); }static int inet_diag_handler_dump (struct sk_buff *skb,struct nlmsghdr *h)
@@ -899,7 +914,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)return -EAFNOSUPPORT ; } -return -EAFNOSUPPORT ; +return inet_diag_get_exact (skb, h, (struct inet_diag_req *)NLMSG_DATA (h)); }static struct sock_diag_handler inet_diag_handler = {
Signature · 1 line
1.5.5.6
PATCH 8/11 inet_diag: Switch the _dump to work with new header
In reply to Pavel EmelyanovMake inet_diag_dumo work with given header instead of calculating one from the nl message.
The SOCK_DIAG_BY_FAMILY just passes skb's one through, the compat code converts the old header to new one.
Also fix the bytecode calculation to find one at proper offset.
--- net/ipv4/inet_diag.c | 71 +++++++++++++++++++++++++++++++++++++------------ 1 files changed, 53 insertions(+), 18 deletions(-)
net/ipv4/inet_diag.c +53 -18
@@ -502,10 +502,9 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)static int inet_csk_diag_dump (struct sock *sk,struct sk_buff *skb,struct netlink_callback *cb, +struct inet_diag_req *r,const struct nlattr *bc) { -struct inet_diag_req_compat *r =NLMSG_DATA (cb->nlh); -if (bc !=NULL ) {struct inet_diag_entry entry;struct inet_sock *inet =inet_sk (sk);
@@ -539,10 +538,9 @@ static int inet_csk_diag_dump(struct sock *sk,static int inet_twsk_diag_dump (struct inet_timewait_sock *tw,struct sk_buff *skb,struct netlink_callback *cb, +struct inet_diag_req *r,const struct nlattr *bc) { -struct inet_diag_req_compat *r =NLMSG_DATA (cb->nlh); -if (bc !=NULL ) {struct inet_diag_entry entry;
@@ -626,10 +624,10 @@ nlmsg_failure:static int inet_diag_dump_reqs (struct sk_buff *skb,struct sock *sk,struct netlink_callback *cb, +struct inet_diag_req *r,const struct nlattr *bc) {struct inet_diag_entry entry; -struct inet_diag_req_compat *r =NLMSG_DATA (cb->nlh);struct inet_connection_sock *icsk =inet_csk (sk);struct listen_sock *lopt;struct inet_sock *inet =inet_sk (sk);
@@ -708,19 +706,15 @@ out:return err; } -static int inet_diag_dump (struct sk_buff *skb,struct netlink_callback *cb) +static int __inet_diag_dump (struct sk_buff *skb,struct netlink_callback *cb, +struct inet_diag_req *r,struct nlattr *bc) {int i, num;int s_i, s_num; -struct inet_diag_req_compat *r =NLMSG_DATA (cb->nlh);const struct inet_diag_handler *handler;struct inet_hashinfo *hashinfo; -const struct nlattr *bc =NULL ; - -if (nlmsg_attrlen (cb->nlh,sizeof (struct inet_diag_req_compat ))) - bc =nlmsg_find_attr (cb->nlh,sizeof (*r),INET_DIAG_REQ_BYTECODE ); - handler =inet_diag_lock_handler (inet_diag_type2proto (cb->nlh->nlmsg_type)); + handler =inet_diag_lock_handler (r->sdiag_protocol);if (IS_ERR (handler)) goto unlock;
@@ -758,7 +752,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) cb->args[3] > 0) goto syn_recv; -if (inet_csk_diag_dump (sk, skb, cb, bc) <0 ) { +if (inet_csk_diag_dump (sk, skb, cb, r, bc) <0 ) {spin_unlock_bh (&ilb->lock); goto done; }
@@ -767,7 +761,7 @@ syn_recv:if (!(r->idiag_states &TCPF_SYN_RECV )) goto next_listen; -if (inet_diag_dump_reqs (skb, sk, cb, bc) <0 ) { +if (inet_diag_dump_reqs (skb, sk, cb, r, bc) <0 ) {spin_unlock_bh (&ilb->lock); goto done; }
@@ -820,7 +814,7 @@ skip_listen_ht:if (r->id.idiag_dport != inet->inet_dport && r->id.idiag_dport) goto next_normal; -if (inet_csk_diag_dump (sk, skb, cb, bc) <0 ) { +if (inet_csk_diag_dump (sk, skb, cb, r, bc) <0 ) {spin_unlock_bh (lock); goto done; }
@@ -842,7 +836,7 @@ next_normal:if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; -if (inet_twsk_diag_dump (tw, skb, cb, bc) <0 ) { +if (inet_twsk_diag_dump (tw, skb, cb, r, bc) <0 ) {spin_unlock_bh (lock); goto done; }
@@ -861,6 +855,36 @@ unlock:return skb->len; } +static int inet_diag_dump (struct sk_buff *skb,struct netlink_callback *cb) +{ +struct nlattr *bc =NULL ; +int hdrlen =sizeof (struct inet_diag_req ); + +if (nlmsg_attrlen (cb->nlh, hdrlen)) + bc =nlmsg_find_attr (cb->nlh, hdrlen,INET_DIAG_REQ_BYTECODE ); + +return __inet_diag_dump (skb, cb, (struct inet_diag_req *)NLMSG_DATA (cb->nlh), bc); +} + +static int inet_diag_dump_compat (struct sk_buff *skb,struct netlink_callback *cb) +{ +struct inet_diag_req_compat *rc =NLMSG_DATA (cb->nlh); +struct inet_diag_req req; +struct nlattr *bc =NULL ; +int hdrlen =sizeof (struct inet_diag_req_compat ); + + req.sdiag_family = rc->idiag_family; + req.sdiag_protocol =inet_diag_type2proto (cb->nlh->nlmsg_type); + req.idiag_ext = rc->idiag_ext; + req.idiag_states = rc->idiag_states; + req.id = rc->id; + +if (nlmsg_attrlen (cb->nlh, hdrlen)) + bc =nlmsg_find_attr (cb->nlh, hdrlen,INET_DIAG_REQ_BYTECODE ); + +return __inet_diag_dump (skb, cb, &req, bc); +} +static int inet_diag_get_exact_compat (struct sk_buff *in_skb,const struct nlmsghdr *nlh) {
@@ -897,7 +921,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) }return netlink_dump_start (sdiagnl, skb, nlh, - inet_diag_dump,NULL ,0 ); + inet_diag_dump_compat,NULL ,0 ); }return inet_diag_get_exact_compat (skb, nlh);
@@ -911,7 +935,18 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)return -EINVAL ;if (h->nlmsg_flags &NLM_F_DUMP ) { -return -EAFNOSUPPORT ; +if (nlmsg_attrlen (h, hdrlen)) { +struct nlattr *attr; + attr =nlmsg_find_attr (h, hdrlen, +INET_DIAG_REQ_BYTECODE ); +if (attr ==NULL || +nla_len (attr) <sizeof (struct inet_diag_bc_op ) || +inet_diag_bc_audit (nla_data (attr),nla_len (attr))) +return -EINVAL ; + } + +return netlink_dump_start (sdiagnl, skb, h, + inet_diag_dump,NULL ,0 ); }return inet_diag_get_exact (skb, h, (struct inet_diag_req *)NLMSG_DATA (h));
Signature · 1 line
1.5.5.6
PATCH 9/11 inet_diag: Introduce socket family checks
In reply to Pavel EmelyanovThe new API will specify family to work with. Teach the existing socket walking code to bypass not interesting ones.
To preserve compatibility with existing behavior the _compat code sets interesting family to AF_UNSPEC to dump them all.
--- net/ipv4/inet_diag.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
net/ipv4/inet_diag.c +11 -1
@@ -743,6 +743,10 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,continue ; } +if (r->sdiag_family !=AF_UNSPEC && + sk->sk_family != r->sdiag_family) + goto next_listen; +if (r->id.idiag_sport != inet->inet_sport && r->id.idiag_sport) goto next_listen;
@@ -808,6 +812,9 @@ skip_listen_ht: goto next_normal;if (!(r->idiag_states & (1 << sk->sk_state))) goto next_normal; +if (r->sdiag_family !=AF_UNSPEC && + sk->sk_family != r->sdiag_family) + goto next_normal;if (r->id.idiag_sport != inet->inet_sport && r->id.idiag_sport) goto next_normal;
@@ -830,6 +837,9 @@ next_normal:if (num < s_num) goto next_dying; +if (r->sdiag_family !=AF_UNSPEC && + tw->tw_family != r->sdiag_family) + goto next_dying;if (r->id.idiag_sport != tw->tw_sport && r->id.idiag_sport) goto next_dying;
@@ -873,7 +883,7 @@ static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cstruct nlattr *bc =NULL ;int hdrlen =sizeof (struct inet_diag_req_compat ); - req.sdiag_family = rc->idiag_family; + req.sdiag_family =AF_UNSPEC ;/* compatibility */ req.sdiag_protocol =inet_diag_type2proto (cb->nlh->nlmsg_type); req.idiag_ext = rc->idiag_ext; req.idiag_states = rc->idiag_states;
Signature · 1 line
1.5.5.6
PATCH 10/11 inet_diag: Cleanup type2proto last user
In reply to Pavel EmelyanovNow all the code works with sock_diag_req-compatible structs, so it's possible to stop using the inet_diag_type2proto in inet_csk_diag_fill. Pass the inet_diag_req into it and use the sdiag_protocol field. At the same time remove the explicit ext argument, since it's also on the req.
However, this conversion is still required in _compat code, so just move this routine, not remove.
--- net/ipv4/inet_diag.c | 47 ++++++++++++++++++++++++----------------------- 1 files changed, 24 insertions(+), 23 deletions(-)
net/ipv4/inet_diag.c +24 -23
@@ -51,18 +51,6 @@ static struct sock *sdiagnl;#define INET_DIAG_PUT (skb, attrtype, attrlen) \ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) -static inline int inet_diag_type2proto (int type) -{ -switch (type) { -case TCPDIAG_GETSOCK : -return IPPROTO_TCP ; -case DCCPDIAG_GETSOCK : -return IPPROTO_DCCP ; -default : -return 0 ; - } -} -static DEFINE_MUTEX (inet_diag_table_mutex);static const struct inet_diag_handler *inet_diag_lock_handler (int proto)
@@ -85,8 +73,8 @@ static inline void inet_diag_unlock_handler( }static int inet_csk_diag_fill (struct sock *sk, -struct sk_buff *skb, -int ext,u32 pid,u32 seq,u16 nlmsg_flags, +struct sk_buff *skb,struct inet_diag_req *req, +u32 pid,u32 seq,u16 nlmsg_flags,const struct nlmsghdr *unlh) {const struct inet_sock *inet =inet_sk (sk);
@@ -97,8 +85,9 @@ static int inet_csk_diag_fill(struct sock *sk,struct inet_diag_meminfo *minfo =NULL ;unsigned char *b =skb_tail_pointer (skb);const struct inet_diag_handler *handler; +int ext = req->idiag_ext; - handler = inet_diag_table[inet_diag_type2proto (unlh->nlmsg_type)]; + handler = inet_diag_table[req->sdiag_protocol];BUG_ON (handler ==NULL ); nlh =NLMSG_PUT (skb, pid, seq, unlh->nlmsg_type,sizeof (*r));
@@ -198,8 +187,8 @@ nlmsg_failure: }static int inet_twsk_diag_fill (struct inet_timewait_sock *tw, -struct sk_buff *skb,int ext,u32 pid, -u32 seq,u16 nlmsg_flags, +struct sk_buff *skb,struct inet_diag_req *req, +u32 pid,u32 seq,u16 nlmsg_flags,const struct nlmsghdr *unlh) {long tmo;
@@ -250,14 +239,14 @@ nlmsg_failure: }static int sk_diag_fill (struct sock *sk,struct sk_buff *skb, -int ext,u32 pid,u32 seq,u16 nlmsg_flags, +struct inet_diag_req *r,u32 pid,u32 seq,u16 nlmsg_flags,const struct nlmsghdr *unlh) {if (sk->sk_state ==TCP_TIME_WAIT )return inet_twsk_diag_fill ((struct inet_timewait_sock *)sk, - skb, ext, pid, seq, nlmsg_flags, + skb, r, pid, seq, nlmsg_flags, unlh); -return inet_csk_diag_fill (sk, skb, ext, pid, seq, nlmsg_flags, unlh); +return inet_csk_diag_fill (sk, skb, r, pid, seq, nlmsg_flags, unlh); } static int inet_diag_get_exact(struct sk_buff *in_skb,
@@ -317,7 +306,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,if (!rep) goto out; - err =sk_diag_fill (sk, rep, req->idiag_ext, + err =sk_diag_fill (sk, rep, req,NETLINK_CB (in_skb).pid, nlh->nlmsg_seq,0 , nlh);if (err <0 ) {
@@ -530,7 +519,7 @@ static int inet_csk_diag_dump(struct sock *sk,return 0 ; } -return inet_csk_diag_fill (sk, skb, r->idiag_ext, +return inet_csk_diag_fill (sk, skb, r,NETLINK_CB (cb->skb).pid, cb->nlh->nlmsg_seq,NLM_F_MULTI , cb->nlh); }
@@ -565,7 +554,7 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,return 0 ; } -return inet_twsk_diag_fill (tw, skb, r->idiag_ext, +return inet_twsk_diag_fill (tw, skb, r,NETLINK_CB (cb->skb).pid, cb->nlh->nlmsg_seq,NLM_F_MULTI , cb->nlh); }
@@ -876,6 +865,18 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)return __inet_diag_dump (skb, cb, (struct inet_diag_req *)NLMSG_DATA (cb->nlh), bc); } +static inline int inet_diag_type2proto (int type) +{ +switch (type) { +case TCPDIAG_GETSOCK : +return IPPROTO_TCP ; +case DCCPDIAG_GETSOCK : +return IPPROTO_DCCP ; +default : +return 0 ; + } +} +static int inet_diag_dump_compat (struct sk_buff *skb,struct netlink_callback *cb) {struct inet_diag_req_compat *rc =NLMSG_DATA (cb->nlh);
Signature · 1 line
1.5.5.6
PATCH 11/11 sock_diag: Move the sock_ code to net/core/
In reply to Pavel EmelyanovThis patch moves the sock_ code from inet_diag.c to generic sock_diag.c file and provides necessary request_module-s calls and a pointer on inet_diag_compat dumping routine.
--- net/core/Makefile | 3 +- net/core/sock_diag.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++ net/ipv4/inet_diag.c | 105 ++--------------------------------- 3 files changed, 158 insertions(+), 100 deletions(-) create mode 100644 net/core/sock_diag.c
net/core/Makefile +2 -1
@@ -8,7 +8,8 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ - neighbour.o rtnetlink.o utils.o link_watch.o filter.o + neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ + sock_diag.o obj-$(CONFIG_XFRM) += flow.o obj-y += net-sysfs.o
net/core/sock_diag.c new file +150 -0
150 lines not on this page · raw message
net/ipv4/inet_diag.c +6 -99
162 lines not on this page · raw message
Signature · 1 line
1.5.5.6
PATCH 1/1 iproute: Use SOCK_DIAG_BY_FAMILY messages
In reply to Pavel EmelyanovApplies to cd72dcf13c8a4948ee5706794714287eeff62c90 commit of thegit://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git tree
---
include/linux/inet_diag.h +11 -1
@@ -6,6 +6,7 @@/* Just some random number */ #define TCPDIAG_GETSOCK 18#define DCCPDIAG_GETSOCK 19 +#define SOCK_DIAG_BY_FAMILY 20#define INET_DIAG_GETSOCK_MAX 24
@@ -22,7 +23,7 @@ struct inet_diag_sockid {/* Request structure */ -struct inet_diag_req { +struct inet_diag_req_compat {__u8 idiag_family;/* Family of addresses. */ __u8 idiag_src_len;__u8 idiag_dst_len;
@@ -34,6 +35,15 @@ struct inet_diag_req {__u32 idiag_dbs;/* Tables to dump (NI) */ }; +struct inet_diag_req { +__u8 sdiag_family; +__u8 sdiag_protocol; +__u8 idiag_ext; +__u8 pad; +__u32 idiag_states; +struct inet_diag_sockid id; +}; +enum {INET_DIAG_REQ_NONE ,INET_DIAG_REQ_BYTECODE ,
misc/ss.c +19 -10
@@ -1474,7 +1474,7 @@ static int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f)return 0 ; } -static int tcp_show_netlink (struct filter *f,FILE *dump_fp,int socktype) +static int __tcp_show_netlink (struct filter *f,FILE *dump_fp,int family,int socktype) {int fd;struct sockaddr_nl nladdr;
@@ -1496,12 +1496,13 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) nladdr.nl_family =AF_NETLINK ; req.nlh.nlmsg_len =sizeof (req); - req.nlh.nlmsg_type = socktype; + req.nlh.nlmsg_type =SOCK_DIAG_BY_FAMILY ; req.nlh.nlmsg_flags =NLM_F_ROOT |NLM_F_MATCH |NLM_F_REQUEST ; req.nlh.nlmsg_pid =0 ; req.nlh.nlmsg_seq =123456 ;memset (&req.r,0 ,sizeof (req.r)); - req.r.idiag_family =AF_INET ; + req.r.sdiag_family = family; + req.r.sdiag_protocol = socktype; req.r.idiag_states = f->states;if (show_mem) req.r.idiag_ext |= (1 <<(INET_DIAG_MEMINFO -1 ));
@@ -1589,10 +1590,6 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)return 0 ; }if (!dump_fp) { -if (!(f->families & (1 <<r->idiag_family))) { - h =NLMSG_NEXT (h, status); -continue ; - } err =tcp_show_sock (h,NULL );if (err <0 )return err;
@@ -1613,6 +1610,18 @@ skip_it:return 0 ; } +static int tcp_show_netlink (struct filter *f,FILE *dump_fp,int socktype) +{ +int err =0 ; + +if (f->families & (1 <<AF_INET )) + err |=__tcp_show_netlink (f, dump_fp,AF_INET , socktype); +if (f->families & (1 <<AF_INET6 )) + err |=__tcp_show_netlink (f, dump_fp,AF_INET6 , socktype); + +return err; +} +static int tcp_show_netlink_file (struct filter *f) {FILE *fp;
@@ -2789,7 +2798,7 @@ int main(int argc, char *argv[])exit (-1 ); } } -tcp_show_netlink (¤t_filter, dump_fp,TCPDIAG_GETSOCK ); +tcp_show_netlink (¤t_filter, dump_fp,IPPROTO_TCP );fflush (dump_fp);exit (0 ); }
@@ -2857,8 +2866,8 @@ int main(int argc, char *argv[])if (current_filter.dbs & (1 <<UDP_DB ))udp_show (¤t_filter);if (current_filter.dbs & (1 <<TCP_DB )) -tcp_show (¤t_filter,TCPDIAG_GETSOCK ); +tcp_show (¤t_filter,IPPROTO_TCP );if (current_filter.dbs & (1 <<DCCP_DB )) -tcp_show (¤t_filter,DCCPDIAG_GETSOCK ); +tcp_show (¤t_filter,IPPROTO_DCCP );return 0 ; }
Re: [PATCH] iproute: Use SOCK_DIAG_BY_FAMILY messages
Quoted 5 lines · On Tue, 06 Dec 2011 22:02:00 +0400 Pavel Emelyanov <[email protected]> wrote:
Applies to
cd72dcf13c8a4948ee5706794714287eeff62c90commit of thegit://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.gittreeSigned-off-by Pavel Emelyanov <[email protected]>
Rejected since this fails binary compatiablity with older kernels:
./misc/ss -a
State Recv-Q Send-Q Local Address:Port Peer Address:Port
TCPDIAG answers: Invalid argument
TCPDIAG answers: Invalid argument
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 4/11 inet_diag: Switch from _GETSOCK to IPPROTO_ numbers
Sorry, but the vger didn't let this message go to the list. Re-sending it with less spam-filter-prone subject.
When dumping the AF_INET/AF_INET6 sockets user will also specify the protocol, so prepare the protocol diag handlers to work with IPPROTO_ constants.
--- net/dccp/diag.c | 4 ++-- net/ipv4/inet_diag.c | 34 +++++++++++++++++++++++----------- net/ipv4/tcp_diag.c | 4 ++-- 3 files changed, 27 insertions(+), 15 deletions(-)
net/dccp/diag.c +2 -2
@@ -51,7 +51,7 @@ static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,static const struct inet_diag_handler dccp_diag_handler = { .idiag_hashinfo = &dccp_hashinfo, .idiag_get_info = dccp_diag_get_info, - .idiag_type =DCCPDIAG_GETSOCK , + .idiag_type =IPPROTO_DCCP , .idiag_info_size =sizeof (struct tcp_info ), };
@@ -71,4 +71,4 @@ module_exit(dccp_diag_fini);MODULE_LICENSE ("GPL" );MODULE_AUTHOR ("Arnaldo Carvalho de Melo <[email protected]>" );MODULE_DESCRIPTION ("DCCP inet_diag handler" ); -MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_SOCK_DIAG ,DCCPDIAG_GETSOCK ); +MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_SOCK_DIAG ,33 );
net/ipv4/inet_diag.c +23 -11
@@ -50,19 +50,31 @@ static struct sock *sdiagnl;#define INET_DIAG_PUT (skb, attrtype, attrlen) \ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) +static inline int inet_diag_type2proto (int type) +{ +switch (type) { +case TCPDIAG_GETSOCK : +return IPPROTO_TCP ; +case DCCPDIAG_GETSOCK : +return IPPROTO_DCCP ; +default : +return 0 ; + } +} +static DEFINE_MUTEX (inet_diag_table_mutex); -static const struct inet_diag_handler *inet_diag_lock_handler (int type) +static const struct inet_diag_handler *inet_diag_lock_handler (int proto) { -if (!inet_diag_table[type]) +if (!inet_diag_table[proto])request_module ("net-pf-%d-proto-%d-type-%d" ,PF_NETLINK , -NETLINK_SOCK_DIAG , type); +NETLINK_SOCK_DIAG , proto);mutex_lock (&inet_diag_table_mutex); -if (!inet_diag_table[type]) +if (!inet_diag_table[proto])return ERR_PTR (-ENOENT ); -return inet_diag_table[type]; +return inet_diag_table[proto]; } static inline void inet_diag_unlock_handler(
@@ -85,7 +97,7 @@ static int inet_csk_diag_fill(struct sock *sk,unsigned char *b =skb_tail_pointer (skb);const struct inet_diag_handler *handler; - handler = inet_diag_table[unlh->nlmsg_type]; + handler = inet_diag_table[inet_diag_type2proto (unlh->nlmsg_type)];BUG_ON (handler ==NULL ); nlh =NLMSG_PUT (skb, pid, seq, unlh->nlmsg_type,sizeof (*r));
@@ -257,7 +269,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,struct inet_hashinfo *hashinfo;const struct inet_diag_handler *handler; - handler =inet_diag_lock_handler (nlh->nlmsg_type); + handler =inet_diag_lock_handler (inet_diag_type2proto (nlh->nlmsg_type));if (IS_ERR (handler)) { err =PTR_ERR (handler); goto unlock;
@@ -707,7 +719,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)if (nlmsg_attrlen (cb->nlh,sizeof (struct inet_diag_req ))) bc =nlmsg_find_attr (cb->nlh,sizeof (*r),INET_DIAG_REQ_BYTECODE ); - handler =inet_diag_lock_handler (cb->nlh->nlmsg_type); + handler =inet_diag_lock_handler (inet_diag_type2proto (cb->nlh->nlmsg_type));if (IS_ERR (handler)) goto unlock;
@@ -907,7 +919,7 @@ int inet_diag_register(const struct inet_diag_handler *h)const __u16 type = h->idiag_type;int err = -EINVAL ; -if (type >=INET_DIAG_GETSOCK_MAX ) +if (type >=IPPROTO_MAX ) goto out;mutex_lock (&inet_diag_table_mutex);
@@ -926,7 +938,7 @@ void inet_diag_unregister(const struct inet_diag_handler *h) {const __u16 type = h->idiag_type; -if (type >=INET_DIAG_GETSOCK_MAX ) +if (type >=IPPROTO_MAX )return ;mutex_lock (&inet_diag_table_mutex);
@@ -937,7 +949,7 @@ EXPORT_SYMBOL_GPL(inet_diag_unregister);static int __init inet_diag_init (void ) { -const int inet_diag_table_size = (INET_DIAG_GETSOCK_MAX * +const int inet_diag_table_size = (IPPROTO_MAX *sizeof (struct inet_diag_handler *));int err = -ENOMEM ;
net/ipv4/tcp_diag.c +2 -2
@@ -37,7 +37,7 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,static const struct inet_diag_handler tcp_diag_handler = { .idiag_hashinfo = &tcp_hashinfo, .idiag_get_info = tcp_diag_get_info, - .idiag_type =TCPDIAG_GETSOCK , + .idiag_type =IPPROTO_TCP , .idiag_info_size =sizeof (struct tcp_info ), };
@@ -54,4 +54,4 @@ static void __exit tcp_diag_exit(void)module_init (tcp_diag_init);module_exit (tcp_diag_exit);MODULE_LICENSE ("GPL" ); -MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_SOCK_DIAG ,TCPDIAG_GETSOCK ); +MODULE_ALIAS_NET_PF_PROTO_TYPE (PF_NETLINK ,NETLINK_SOCK_DIAG ,6 );
Signature · 1 line
1.5.5.6
From: Pavel Emelyanov <[email protected]>
Date: Tue, 06 Dec 2011 21:56:10 +0400
Quoted 15 lines
This is an attempt to prepare the existing
inet_diaginfrastructure to work with arbitrary address family and protocol pair, not onlyAF_INET(6)and TCP/DCCP.This set adds the
sock_diaginfrastructure, that handles the newSOCK_DIAG_BY_FAMILYmessage type by theNETLINK_INET_DIAGsocket. The core API struct for this (calledsock_diag_req) contains two fields - family and type - which specify which sockets to dump. Additional information is considered to be family handler specific.The existing
inet_diagcode is patched to register himself inside thesock_diagand provide callbacks for dumping AF_INET/AF_INET6 IPPROTO_TCP/IPPROTO_DCCP sockets. The existing API facilities such as state filtering and bytecode is of course preserved and is treated byinet_diagspecific data.Binary compatibility with existing
NETLINK_INET_DIAGis also kept.
Quoted 7 lines
No additional stuff in this set. The support for
IPPROTO_UDPprotocol andAF_UNIXfamily will come later if this set is approved.Applies to net-next, patch for iproute2's ss tool (proving that the new code ... pretends to work) is at the end of the thread.
Signed-off-by Pavel Emelyanov <[email protected]>
Applied, with the retention of a NETLINK_INET_DIAG define in patch #1 for userspace compatability.