Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c23aaf2 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'inet_diag_cleanups'



Eric Dumazet says:

====================
inet_diag: cleanups and improvements

Before changing way request socks are dumped, let's clean up this code
a bit.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3855634d 34160ea3
Loading
Loading
Loading
Loading
+22 −21
Original line number Diff line number Diff line
@@ -13,12 +13,12 @@ struct netlink_callback;
struct inet_diag_handler {
	void		(*dump)(struct sk_buff *skb,
				struct netlink_callback *cb,
					struct inet_diag_req_v2 *r,
				const struct inet_diag_req_v2 *r,
				struct nlattr *bc);

	int		(*dump_one)(struct sk_buff *in_skb,
				    const struct nlmsghdr *nlh,
					struct inet_diag_req_v2 *req);
				    const struct inet_diag_req_v2 *req);

	void		(*idiag_get_info)(struct sock *sk,
					  struct inet_diag_msg *r,
@@ -28,16 +28,17 @@ struct inet_diag_handler {

struct inet_connection_sock;
int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
			      struct sk_buff *skb, struct inet_diag_req_v2 *req,
		      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
		      struct user_namespace *user_ns,
		      u32 pid, u32 seq, u16 nlmsg_flags,
		      const struct nlmsghdr *unlh);
void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
		struct netlink_callback *cb, struct inet_diag_req_v2 *r,
			 struct netlink_callback *cb,
			 const struct inet_diag_req_v2 *r,
			 struct nlattr *bc);
int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
			    struct sk_buff *in_skb, const struct nlmsghdr *nlh,
		struct inet_diag_req_v2 *req);
			    const struct inet_diag_req_v2 *req);

int inet_diag_bc_sk(const struct nlattr *_bc, struct sock *sk);

+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ void sock_diag_unregister(const 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));

int sock_diag_check_cookie(void *sk, __u32 *cookie);
int sock_diag_check_cookie(void *sk, const __u32 *cookie);
void sock_diag_save_cookie(void *sk, __u32 *cookie);

int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr);
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
static DEFINE_MUTEX(sock_diag_table_mutex);

int sock_diag_check_cookie(void *sk, __u32 *cookie)
int sock_diag_check_cookie(void *sk, const __u32 *cookie)
{
	if ((cookie[0] != INET_DIAG_NOCOOKIE ||
	     cookie[1] != INET_DIAG_NOCOOKIE) &&
+4 −3
Original line number Diff line number Diff line
@@ -49,13 +49,14 @@ static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
}

static void dccp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
		struct inet_diag_req_v2 *r, struct nlattr *bc)
			   const struct inet_diag_req_v2 *r, struct nlattr *bc)
{
	inet_diag_dump_icsk(&dccp_hashinfo, skb, cb, r, bc);
}

static int dccp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh,
		struct inet_diag_req_v2 *req)
static int dccp_diag_dump_one(struct sk_buff *in_skb,
			      const struct nlmsghdr *nlh,
			      const struct inet_diag_req_v2 *req)
{
	return inet_diag_dump_one_icsk(&dccp_hashinfo, in_skb, nlh, req);
}
+76 −78
Original line number Diff line number Diff line
@@ -38,8 +38,8 @@
static const struct inet_diag_handler **inet_diag_table;

struct inet_diag_entry {
	__be32 *saddr;
	__be32 *daddr;
	const __be32 *saddr;
	const __be32 *daddr;
	u16 sport;
	u16 dport;
	u16 family;
@@ -65,28 +65,27 @@ static const struct inet_diag_handler *inet_diag_lock_handler(int proto)
	return inet_diag_table[proto];
}

static inline void inet_diag_unlock_handler(
	const struct inet_diag_handler *handler)
static void inet_diag_unlock_handler(const struct inet_diag_handler *handler)
{
	mutex_unlock(&inet_diag_table_mutex);
}

int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
			      struct sk_buff *skb, struct inet_diag_req_v2 *req,
		      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
		      struct user_namespace *user_ns,
		      u32 portid, u32 seq, u16 nlmsg_flags,
		      const struct nlmsghdr *unlh)
{
	const struct inet_sock *inet = inet_sk(sk);
	const struct inet_diag_handler *handler;
	int ext = req->idiag_ext;
	struct inet_diag_msg *r;
	struct nlmsghdr  *nlh;
	struct nlattr *attr;
	void *info = NULL;
	const struct inet_diag_handler *handler;
	int ext = req->idiag_ext;

	handler = inet_diag_table[req->sdiag_protocol];
	BUG_ON(handler == NULL);
	BUG_ON(!handler);

	nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r),
			nlmsg_flags);
@@ -125,7 +124,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,

#if IS_ENABLED(CONFIG_IPV6)
	if (r->idiag_family == AF_INET6) {

		*(struct in6_addr *)r->id.idiag_src = sk->sk_v6_rcv_saddr;
		*(struct in6_addr *)r->id.idiag_dst = sk->sk_v6_daddr;

@@ -155,7 +153,7 @@ 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;

	if (icsk == NULL) {
	if (!icsk) {
		handler->idiag_get_info(sk, r, NULL);
		goto out;
	}
@@ -213,23 +211,25 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
EXPORT_SYMBOL_GPL(inet_sk_diag_fill);

static int inet_csk_diag_fill(struct sock *sk,
			      struct sk_buff *skb, struct inet_diag_req_v2 *req,
			      struct sk_buff *skb,
			      const struct inet_diag_req_v2 *req,
			      struct user_namespace *user_ns,
			      u32 portid, u32 seq, u16 nlmsg_flags,
			      const struct nlmsghdr *unlh)
{
	return inet_sk_diag_fill(sk, inet_csk(sk),
			skb, req, user_ns, portid, seq, nlmsg_flags, unlh);
	return inet_sk_diag_fill(sk, inet_csk(sk), skb, req,
				 user_ns, portid, seq, nlmsg_flags, unlh);
}

static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
			       struct sk_buff *skb, struct inet_diag_req_v2 *req,
			       struct sk_buff *skb,
			       const struct inet_diag_req_v2 *req,
			       u32 portid, u32 seq, u16 nlmsg_flags,
			       const struct nlmsghdr *unlh)
{
	s32 tmo;
	struct inet_diag_msg *r;
	struct nlmsghdr *nlh;
	s32 tmo;

	nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r),
			nlmsg_flags);
@@ -277,7 +277,7 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
}

static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
			struct inet_diag_req_v2 *r,
			const struct inet_diag_req_v2 *r,
			struct user_namespace *user_ns,
			u32 portid, u32 seq, u16 nlmsg_flags,
			const struct nlmsghdr *unlh)
@@ -290,36 +290,35 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
				  nlmsg_flags, unlh);
}

int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb,
		const struct nlmsghdr *nlh, struct inet_diag_req_v2 *req)
int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
			    struct sk_buff *in_skb,
			    const struct nlmsghdr *nlh,
			    const struct inet_diag_req_v2 *req)
{
	int err;
	struct sock *sk;
	struct sk_buff *rep;
	struct net *net = sock_net(in_skb->sk);
	struct sk_buff *rep;
	struct sock *sk;
	int err;

	err = -EINVAL;
	if (req->sdiag_family == AF_INET) {
	if (req->sdiag_family == AF_INET)
		sk = inet_lookup(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 IS_ENABLED(CONFIG_IPV6)
	else if (req->sdiag_family == AF_INET6) {
	else if (req->sdiag_family == AF_INET6)
		sk = inet6_lookup(net, hashinfo,
				  (struct in6_addr *)req->id.idiag_dst,
				  req->id.idiag_dport,
				  (struct in6_addr *)req->id.idiag_src,
				  req->id.idiag_sport,
				  req->id.idiag_if);
	}
#endif
	else {
	else
		goto out_nosk;
	}

	err = -ENOENT;
	if (sk == NULL)
	if (!sk)
		goto out_nosk;

	err = sock_diag_check_cookie(sk, req->id.idiag_cookie);
@@ -359,7 +358,7 @@ EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk);

static int inet_diag_get_exact(struct sk_buff *in_skb,
			       const struct nlmsghdr *nlh,
			       struct inet_diag_req_v2 *req)
			       const struct inet_diag_req_v2 *req)
{
	const struct inet_diag_handler *handler;
	int err;
@@ -400,7 +399,6 @@ static int bitstring_match(const __be32 *a1, const __be32 *a2, int bits)
	return 1;
}


static int inet_diag_bc_run(const struct nlattr *_bc,
			    const struct inet_diag_entry *entry)
{
@@ -434,10 +432,10 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
			break;
		case INET_DIAG_BC_S_COND:
		case INET_DIAG_BC_D_COND: {
			struct inet_diag_hostcond *cond;
			__be32 *addr;
			const struct inet_diag_hostcond *cond;
			const __be32 *addr;

			cond = (struct inet_diag_hostcond *)(op + 1);
			cond = (const struct inet_diag_hostcond *)(op + 1);
			if (cond->port != -1 &&
			    cond->port != (op->code == INET_DIAG_BC_S_COND ?
					     entry->sport : entry->dport)) {
@@ -488,16 +486,15 @@ static int inet_diag_bc_run(const struct nlattr *_bc,

int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
{
	struct inet_diag_entry entry;
	struct inet_sock *inet = inet_sk(sk);
	struct inet_diag_entry entry;

	if (bc == NULL)
	if (!bc)
		return 1;

	entry.family = sk->sk_family;
#if IS_ENABLED(CONFIG_IPV6)
	if (entry.family == AF_INET6) {

		entry.saddr = sk->sk_v6_rcv_saddr.s6_addr32;
		entry.daddr = sk->sk_v6_daddr.s6_addr32;
	} else
@@ -535,8 +532,8 @@ static int valid_cc(const void *bc, int len, int cc)
static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
			   int *min_len)
{
	int addr_len;
	struct inet_diag_hostcond *cond;
	int addr_len;

	/* Check hostcond space. */
	*min_len += sizeof(struct inet_diag_hostcond);
@@ -570,7 +567,7 @@ static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
}

/* Validate a port comparison operator. */
static inline bool valid_port_comparison(const struct inet_diag_bc_op *op,
static bool valid_port_comparison(const struct inet_diag_bc_op *op,
				  int len, int *min_len)
{
	/* Port comparisons put the port in a follow-on inet_diag_bc_op. */
@@ -586,10 +583,9 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
	int  len = bytecode_len;

	while (len > 0) {
		const struct inet_diag_bc_op *op = bc;
		int min_len = sizeof(struct inet_diag_bc_op);
		const struct inet_diag_bc_op *op = bc;

//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
		switch (op->code) {
		case INET_DIAG_BC_S_COND:
		case INET_DIAG_BC_D_COND:
@@ -630,7 +626,7 @@ 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_v2 *r,
			      const struct inet_diag_req_v2 *r,
			      const struct nlattr *bc)
{
	if (!inet_diag_bc_sk(bc, sk))
@@ -671,7 +667,7 @@ static void twsk_build_assert(void)
static int inet_twsk_diag_dump(struct sock *sk,
			       struct sk_buff *skb,
			       struct netlink_callback *cb,
			       struct inet_diag_req_v2 *r,
			       const struct inet_diag_req_v2 *r,
			       const struct nlattr *bc)
{
	twsk_build_assert();
@@ -687,11 +683,11 @@ static int inet_twsk_diag_dump(struct sock *sk,
/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses
 * from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6.
 */
static inline void inet_diag_req_addrs(const struct sock *sk,
static void inet_diag_req_addrs(const struct sock *sk,
				const struct request_sock *req,
				struct inet_diag_entry *entry)
{
	struct inet_request_sock *ireq = inet_rsk(req);
	const struct inet_request_sock *ireq = inet_rsk(req);

#if IS_ENABLED(CONFIG_IPV6)
	if (sk->sk_family == AF_INET6) {
@@ -761,6 +757,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
#if IS_ENABLED(CONFIG_IPV6)
	if (r->idiag_family == AF_INET6) {
		struct inet_diag_entry entry;

		inet_diag_req_addrs(sk, req, &entry);
		memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr));
		memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr));
@@ -773,15 +770,14 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,

static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
			       struct netlink_callback *cb,
			       struct inet_diag_req_v2 *r,
			       const struct inet_diag_req_v2 *r,
			       const struct nlattr *bc)
{
	struct inet_diag_entry entry;
	struct inet_connection_sock *icsk = inet_csk(sk);
	struct listen_sock *lopt;
	struct inet_sock *inet = inet_sk(sk);
	int j, s_j;
	int reqnum, s_reqnum;
	struct inet_diag_entry entry;
	int j, s_j, reqnum, s_reqnum;
	struct listen_sock *lopt;
	int err = 0;

	s_j = cb->args[3];
@@ -798,7 +794,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
	if (!lopt || !lopt->qlen)
		goto out;

	if (bc != NULL) {
	if (bc) {
		entry.sport = inet->inet_num;
		entry.userlocks = sk->sk_userlocks;
	}
@@ -845,11 +841,11 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
}

void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
		struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc)
			 struct netlink_callback *cb,
			 const struct inet_diag_req_v2 *r, struct nlattr *bc)
{
	int i, num;
	int s_i, s_num;
	struct net *net = sock_net(skb->sk);
	int i, num, s_i, s_num;

	s_i = cb->args[1];
	s_num = num = cb->args[2];
@@ -859,9 +855,9 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
			goto skip_listen_ht;

		for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
			struct sock *sk;
			struct hlist_nulls_node *node;
			struct inet_listen_hashbucket *ilb;
			struct hlist_nulls_node *node;
			struct sock *sk;

			num = 0;
			ilb = &hashinfo->listening_hash[i];
@@ -926,8 +922,8 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
	for (i = s_i; i <= hashinfo->ehash_mask; i++) {
		struct inet_ehash_bucket *head = &hashinfo->ehash[i];
		spinlock_t *lock = inet_ehash_lockp(hashinfo, i);
		struct sock *sk;
		struct hlist_nulls_node *node;
		struct sock *sk;

		num = 0;

@@ -939,8 +935,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,

		spin_lock_bh(lock);
		sk_nulls_for_each(sk, node, &head->chain) {
			int res;
			int state;
			int state, res;

			if (!net_eq(sock_net(sk), net))
				continue;
@@ -983,7 +978,8 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
EXPORT_SYMBOL_GPL(inet_diag_dump_icsk);

static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
		struct inet_diag_req_v2 *r, struct nlattr *bc)
			    const struct inet_diag_req_v2 *r,
			    struct nlattr *bc)
{
	const struct inet_diag_handler *handler;
	int err = 0;
@@ -1000,8 +996,8 @@ 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 nlattr *bc = NULL;
	int hdrlen = sizeof(struct inet_diag_req_v2);
	struct nlattr *bc = NULL;

	if (nlmsg_attrlen(cb->nlh, hdrlen))
		bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE);
@@ -1009,7 +1005,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
	return __inet_diag_dump(skb, cb, nlmsg_data(cb->nlh), bc);
}

static inline int inet_diag_type2proto(int type)
static int inet_diag_type2proto(int type)
{
	switch (type) {
	case TCPDIAG_GETSOCK:
@@ -1021,12 +1017,13 @@ static inline int inet_diag_type2proto(int type)
	}
}

static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cb)
static int inet_diag_dump_compat(struct sk_buff *skb,
				 struct netlink_callback *cb)
{
	struct inet_diag_req *rc = nlmsg_data(cb->nlh);
	int hdrlen = sizeof(struct inet_diag_req);
	struct inet_diag_req_v2 req;
	struct nlattr *bc = NULL;
	int hdrlen = sizeof(struct inet_diag_req);

	req.sdiag_family = AF_UNSPEC; /* compatibility */
	req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type);
@@ -1070,7 +1067,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)

			attr = nlmsg_find_attr(nlh, hdrlen,
					       INET_DIAG_REQ_BYTECODE);
			if (attr == NULL ||
			if (!attr ||
			    nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
			    inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
				return -EINVAL;
@@ -1097,9 +1094,10 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
	if (h->nlmsg_flags & NLM_F_DUMP) {
		if (nlmsg_attrlen(h, hdrlen)) {
			struct nlattr *attr;

			attr = nlmsg_find_attr(h, hdrlen,
					       INET_DIAG_REQ_BYTECODE);
			if (attr == NULL ||
			if (!attr ||
			    nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
			    inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
				return -EINVAL;
@@ -1135,7 +1133,7 @@ int inet_diag_register(const struct inet_diag_handler *h)

	mutex_lock(&inet_diag_table_mutex);
	err = -EEXIST;
	if (inet_diag_table[type] == NULL) {
	if (!inet_diag_table[type]) {
		inet_diag_table[type] = h;
		err = 0;
	}
Loading