Skip to content

Commit 432490f

Browse files
cyrillosdavem330
authored andcommitted
net: ip, diag -- Add diag interface for raw sockets
In criu we are actively using diag interface to collect sockets present in the system when dumping applications. And while for unix, tcp, udp[lite], packet, netlink it works as expected, the raw sockets do not have. Thus add it. v2: - add missing sock_put calls in raw_diag_dump_one (by eric.dumazet@) - implement @destroy for diag requests (by dsa@) v3: - add export of raw_abort for IPv6 (by dsa@) - pass net-admin flag into inet_sk_diag_fill due to changes in net-next branch (by dsa@) v4: - use @pad in struct inet_diag_req_v2 for raw socket protocol specification: raw module carries sockets which may have custom protocol passed from socket() syscall and sole @sdiag_protocol is not enough to match underlied ones - start reporting protocol specifed in socket() call when sockets are raw ones for the same reason: user space tools like ss may parse this attribute and use it for socket matching v5 (by eric.dumazet@): - use sock_hold in raw_sock_get instead of atomic_inc, we're holding (raw_v4_hashinfo|raw_v6_hashinfo)->lock when looking up so counter won't be zero here. v6: - use sdiag_raw_protocol() helper which will access @pad structure used for raw sockets protocol specification: we can't simply rename this member without breaking uapi v7: - sine sdiag_raw_protocol() helper is not suitable for uapi lets rather make an alias structure with proper names. __check_inet_diag_req_raw helper will catch if any of structure unintentionally changed. CC: David S. Miller <[email protected]> CC: Eric Dumazet <[email protected]> CC: David Ahern <[email protected]> CC: Alexey Kuznetsov <[email protected]> CC: James Morris <[email protected]> CC: Hideaki YOSHIFUJI <[email protected]> CC: Patrick McHardy <[email protected]> CC: Andrey Vagin <[email protected]> CC: Stephen Hemminger <[email protected]> Signed-off-by: Cyrill Gorcunov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f76a9db commit 432490f

File tree

9 files changed

+333
-4
lines changed

9 files changed

+333
-4
lines changed

include/net/raw.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323

2424
extern struct proto raw_prot;
2525

26+
extern struct raw_hashinfo raw_v4_hashinfo;
27+
struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
28+
unsigned short num, __be32 raddr,
29+
__be32 laddr, int dif);
30+
31+
int raw_abort(struct sock *sk, int err);
2632
void raw_icmp_error(struct sk_buff *, int, u32);
2733
int raw_local_deliver(struct sk_buff *, int);
2834

include/net/rawv6.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33

44
#include <net/protocol.h>
55

6+
extern struct raw_hashinfo raw_v6_hashinfo;
7+
struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
8+
unsigned short num, const struct in6_addr *loc_addr,
9+
const struct in6_addr *rmt_addr, int dif);
10+
11+
int raw_abort(struct sock *sk, int err);
12+
613
void raw6_icmp_error(struct sk_buff *, int nexthdr,
714
u8 type, u8 code, int inner_offset, __be32);
815
bool raw6_local_deliver(struct sk_buff *, int);

include/uapi/linux/inet_diag.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ struct inet_diag_req_v2 {
4343
struct inet_diag_sockid id;
4444
};
4545

46+
/*
47+
* SOCK_RAW sockets require the underlied protocol to be
48+
* additionally specified so we can use @pad member for
49+
* this, but we can't rename it because userspace programs
50+
* still may depend on this name. Instead lets use another
51+
* structure definition as an alias for struct
52+
* @inet_diag_req_v2.
53+
*/
54+
struct inet_diag_req_raw {
55+
__u8 sdiag_family;
56+
__u8 sdiag_protocol;
57+
__u8 idiag_ext;
58+
__u8 sdiag_raw_protocol;
59+
__u32 idiag_states;
60+
struct inet_diag_sockid id;
61+
};
62+
4663
enum {
4764
INET_DIAG_REQ_NONE,
4865
INET_DIAG_REQ_BYTECODE,

net/ipv4/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,14 @@ config INET_UDP_DIAG
430430
Support for UDP socket monitoring interface used by the ss tool.
431431
If unsure, say Y.
432432

433+
config INET_RAW_DIAG
434+
tristate "RAW: socket monitoring interface"
435+
depends on INET_DIAG && (IPV6 || IPV6=n)
436+
default n
437+
---help---
438+
Support for RAW socket monitoring interface used by the ss tool.
439+
If unsure, say Y.
440+
433441
config INET_DIAG_DESTROY
434442
bool "INET: allow privileged process to administratively close sockets"
435443
depends on INET_DIAG

net/ipv4/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
4040
obj-$(CONFIG_INET_DIAG) += inet_diag.o
4141
obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
4242
obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o
43+
obj-$(CONFIG_INET_RAW_DIAG) += raw_diag.o
4344
obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
4445
obj-$(CONFIG_TCP_CONG_BBR) += tcp_bbr.o
4546
obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o

net/ipv4/inet_diag.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,15 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
200200
if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO))
201201
goto errout;
202202

203+
/*
204+
* RAW sockets might have user-defined protocols assigned,
205+
* so report the one supplied on socket creation.
206+
*/
207+
if (sk->sk_type == SOCK_RAW) {
208+
if (nla_put_u8(skb, INET_DIAG_PROTOCOL, sk->sk_protocol))
209+
goto errout;
210+
}
211+
203212
if (!icsk) {
204213
handler->idiag_get_info(sk, r, NULL);
205214
goto out;

net/ipv4/raw.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ struct raw_frag_vec {
8989
int hlen;
9090
};
9191

92-
static struct raw_hashinfo raw_v4_hashinfo = {
92+
struct raw_hashinfo raw_v4_hashinfo = {
9393
.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
9494
};
95+
EXPORT_SYMBOL_GPL(raw_v4_hashinfo);
9596

9697
int raw_hash_sk(struct sock *sk)
9798
{
@@ -120,7 +121,7 @@ void raw_unhash_sk(struct sock *sk)
120121
}
121122
EXPORT_SYMBOL_GPL(raw_unhash_sk);
122123

123-
static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
124+
struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
124125
unsigned short num, __be32 raddr, __be32 laddr, int dif)
125126
{
126127
sk_for_each_from(sk) {
@@ -136,6 +137,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
136137
found:
137138
return sk;
138139
}
140+
EXPORT_SYMBOL_GPL(__raw_v4_lookup);
139141

140142
/*
141143
* 0 - deliver
@@ -912,6 +914,20 @@ static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg
912914
}
913915
#endif
914916

917+
int raw_abort(struct sock *sk, int err)
918+
{
919+
lock_sock(sk);
920+
921+
sk->sk_err = err;
922+
sk->sk_error_report(sk);
923+
udp_disconnect(sk, 0);
924+
925+
release_sock(sk);
926+
927+
return 0;
928+
}
929+
EXPORT_SYMBOL_GPL(raw_abort);
930+
915931
struct proto raw_prot = {
916932
.name = "RAW",
917933
.owner = THIS_MODULE,
@@ -937,6 +953,7 @@ struct proto raw_prot = {
937953
.compat_getsockopt = compat_raw_getsockopt,
938954
.compat_ioctl = compat_raw_ioctl,
939955
#endif
956+
.diag_destroy = raw_abort,
940957
};
941958

942959
#ifdef CONFIG_PROC_FS

0 commit comments

Comments
 (0)