Skip to content

Commit

Permalink
net: ip, diag -- Add diag interface for raw sockets
Browse files Browse the repository at this point in the history
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 <davem@davemloft.net>
CC: Eric Dumazet <eric.dumazet@gmail.com>
CC: David Ahern <dsa@cumulusnetworks.com>
CC: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
CC: James Morris <jmorris@namei.org>
CC: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
CC: Patrick McHardy <kaber@trash.net>
CC: Andrey Vagin <avagin@openvz.org>
CC: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
cyrillos authored and davem330 committed Oct 23, 2016
1 parent f76a9db commit 432490f
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 4 deletions.
6 changes: 6 additions & 0 deletions include/net/raw.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@

extern struct proto raw_prot;

extern struct raw_hashinfo raw_v4_hashinfo;
struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
unsigned short num, __be32 raddr,
__be32 laddr, int dif);

int raw_abort(struct sock *sk, int err);
void raw_icmp_error(struct sk_buff *, int, u32);
int raw_local_deliver(struct sk_buff *, int);

Expand Down
7 changes: 7 additions & 0 deletions include/net/rawv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

#include <net/protocol.h>

extern struct raw_hashinfo raw_v6_hashinfo;
struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
unsigned short num, const struct in6_addr *loc_addr,
const struct in6_addr *rmt_addr, int dif);

int raw_abort(struct sock *sk, int err);

void raw6_icmp_error(struct sk_buff *, int nexthdr,
u8 type, u8 code, int inner_offset, __be32);
bool raw6_local_deliver(struct sk_buff *, int);
Expand Down
17 changes: 17 additions & 0 deletions include/uapi/linux/inet_diag.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ struct inet_diag_req_v2 {
struct inet_diag_sockid id;
};

/*
* SOCK_RAW sockets require the underlied protocol to be
* additionally specified so we can use @pad member for
* this, but we can't rename it because userspace programs
* still may depend on this name. Instead lets use another
* structure definition as an alias for struct
* @inet_diag_req_v2.
*/
struct inet_diag_req_raw {
__u8 sdiag_family;
__u8 sdiag_protocol;
__u8 idiag_ext;
__u8 sdiag_raw_protocol;
__u32 idiag_states;
struct inet_diag_sockid id;
};

enum {
INET_DIAG_REQ_NONE,
INET_DIAG_REQ_BYTECODE,
Expand Down
8 changes: 8 additions & 0 deletions net/ipv4/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,14 @@ config INET_UDP_DIAG
Support for UDP socket monitoring interface used by the ss tool.
If unsure, say Y.

config INET_RAW_DIAG
tristate "RAW: socket monitoring interface"
depends on INET_DIAG && (IPV6 || IPV6=n)
default n
---help---
Support for RAW socket monitoring interface used by the ss tool.
If unsure, say Y.

config INET_DIAG_DESTROY
bool "INET: allow privileged process to administratively close sockets"
depends on INET_DIAG
Expand Down
1 change: 1 addition & 0 deletions net/ipv4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
obj-$(CONFIG_INET_DIAG) += inet_diag.o
obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o
obj-$(CONFIG_INET_RAW_DIAG) += raw_diag.o
obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
obj-$(CONFIG_TCP_CONG_BBR) += tcp_bbr.o
obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
Expand Down
9 changes: 9 additions & 0 deletions net/ipv4/inet_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,15 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO))
goto errout;

/*
* RAW sockets might have user-defined protocols assigned,
* so report the one supplied on socket creation.
*/
if (sk->sk_type == SOCK_RAW) {
if (nla_put_u8(skb, INET_DIAG_PROTOCOL, sk->sk_protocol))
goto errout;
}

if (!icsk) {
handler->idiag_get_info(sk, r, NULL);
goto out;
Expand Down
21 changes: 19 additions & 2 deletions net/ipv4/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,10 @@ struct raw_frag_vec {
int hlen;
};

static struct raw_hashinfo raw_v4_hashinfo = {
struct raw_hashinfo raw_v4_hashinfo = {
.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
};
EXPORT_SYMBOL_GPL(raw_v4_hashinfo);

int raw_hash_sk(struct sock *sk)
{
Expand Down Expand Up @@ -120,7 +121,7 @@ void raw_unhash_sk(struct sock *sk)
}
EXPORT_SYMBOL_GPL(raw_unhash_sk);

static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
unsigned short num, __be32 raddr, __be32 laddr, int dif)
{
sk_for_each_from(sk) {
Expand All @@ -136,6 +137,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
found:
return sk;
}
EXPORT_SYMBOL_GPL(__raw_v4_lookup);

/*
* 0 - deliver
Expand Down Expand Up @@ -912,6 +914,20 @@ static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg
}
#endif

int raw_abort(struct sock *sk, int err)
{
lock_sock(sk);

sk->sk_err = err;
sk->sk_error_report(sk);
udp_disconnect(sk, 0);

release_sock(sk);

return 0;
}
EXPORT_SYMBOL_GPL(raw_abort);

struct proto raw_prot = {
.name = "RAW",
.owner = THIS_MODULE,
Expand All @@ -937,6 +953,7 @@ struct proto raw_prot = {
.compat_getsockopt = compat_raw_getsockopt,
.compat_ioctl = compat_raw_ioctl,
#endif
.diag_destroy = raw_abort,
};

#ifdef CONFIG_PROC_FS
Expand Down
Loading

0 comments on commit 432490f

Please sign in to comment.