Commit 8dc2f49f authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[TCP]: Modular ipv6 support in tcpdiag

This patch allows tcpdiag to support ipv6 work as a module when itself
is also a module.

I was planning for a more extensible method but now I think the effort
would be better directed at a new generic socket netlink interface than
the TCP-specific tcpdiag.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cbb8b182
...@@ -351,6 +351,7 @@ config INET_TUNNEL ...@@ -351,6 +351,7 @@ config INET_TUNNEL
config IP_TCPDIAG config IP_TCPDIAG
tristate "IP: TCP socket monitoring interface" tristate "IP: TCP socket monitoring interface"
depends on INET
default y default y
---help--- ---help---
Support for TCP socket monitoring interface used by native Linux Support for TCP socket monitoring interface used by native Linux
...@@ -358,5 +359,8 @@ config IP_TCPDIAG ...@@ -358,5 +359,8 @@ config IP_TCPDIAG
If unsure, say Y. If unsure, say Y.
config IP_TCPDIAG_IPV6
def_bool (IP_TCPDIAG=y && IPV6=y) || (IP_TCPDIAG=m && IPV6)
source "net/ipv4/ipvs/Kconfig" source "net/ipv4/ipvs/Kconfig"
...@@ -103,14 +103,12 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk, ...@@ -103,14 +103,12 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
r->tcpdiag_wqueue = 0; r->tcpdiag_wqueue = 0;
r->tcpdiag_uid = 0; r->tcpdiag_uid = 0;
r->tcpdiag_inode = 0; r->tcpdiag_inode = 0;
#ifdef CONFIG_IPV6
if (r->tcpdiag_family == AF_INET6) { if (r->tcpdiag_family == AF_INET6) {
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src, ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
&tw->tw_v6_rcv_saddr); &tw->tw_v6_rcv_saddr);
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst, ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
&tw->tw_v6_daddr); &tw->tw_v6_daddr);
} }
#endif
nlh->nlmsg_len = skb->tail - b; nlh->nlmsg_len = skb->tail - b;
return skb->len; return skb->len;
} }
...@@ -120,7 +118,6 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk, ...@@ -120,7 +118,6 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
r->id.tcpdiag_src[0] = inet->rcv_saddr; r->id.tcpdiag_src[0] = inet->rcv_saddr;
r->id.tcpdiag_dst[0] = inet->daddr; r->id.tcpdiag_dst[0] = inet->daddr;
#ifdef CONFIG_IPV6
if (r->tcpdiag_family == AF_INET6) { if (r->tcpdiag_family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
...@@ -129,7 +126,6 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk, ...@@ -129,7 +126,6 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst, ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
&np->daddr); &np->daddr);
} }
#endif
#define EXPIRES_IN_MS(tmo) ((tmo-jiffies)*1000+HZ-1)/HZ #define EXPIRES_IN_MS(tmo) ((tmo-jiffies)*1000+HZ-1)/HZ
...@@ -188,11 +184,19 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk, ...@@ -188,11 +184,19 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
return -1; return -1;
} }
extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif); extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport,
#ifdef CONFIG_IPV6 int dif);
#ifdef CONFIG_IP_TCPDIAG_IPV6
extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
struct in6_addr *daddr, u16 dport, struct in6_addr *daddr, u16 dport,
int dif); int dif);
#else
static inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
struct in6_addr *daddr, u16 dport,
int dif)
{
return NULL;
}
#endif #endif
static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
...@@ -207,13 +211,11 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) ...@@ -207,13 +211,11 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
req->id.tcpdiag_src[0], req->id.tcpdiag_sport, req->id.tcpdiag_src[0], req->id.tcpdiag_sport,
req->id.tcpdiag_if); req->id.tcpdiag_if);
} }
#ifdef CONFIG_IPV6
else if (req->tcpdiag_family == AF_INET6) { else if (req->tcpdiag_family == AF_INET6) {
sk = tcp_v6_lookup((struct in6_addr*)req->id.tcpdiag_dst, req->id.tcpdiag_dport, sk = tcp_v6_lookup((struct in6_addr*)req->id.tcpdiag_dst, req->id.tcpdiag_dport,
(struct in6_addr*)req->id.tcpdiag_src, req->id.tcpdiag_sport, (struct in6_addr*)req->id.tcpdiag_src, req->id.tcpdiag_sport,
req->id.tcpdiag_if); req->id.tcpdiag_if);
} }
#endif
else { else {
return -EINVAL; return -EINVAL;
} }
...@@ -422,14 +424,12 @@ static int tcpdiag_dump_sock(struct sk_buff *skb, struct sock *sk, ...@@ -422,14 +424,12 @@ static int tcpdiag_dump_sock(struct sk_buff *skb, struct sock *sk,
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
entry.family = sk->sk_family; entry.family = sk->sk_family;
#ifdef CONFIG_IPV6
if (entry.family == AF_INET6) { if (entry.family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
entry.saddr = np->rcv_saddr.s6_addr32; entry.saddr = np->rcv_saddr.s6_addr32;
entry.daddr = np->daddr.s6_addr32; entry.daddr = np->daddr.s6_addr32;
} else } else
#endif
{ {
entry.saddr = &inet->rcv_saddr; entry.saddr = &inet->rcv_saddr;
entry.daddr = &inet->daddr; entry.daddr = &inet->daddr;
...@@ -482,14 +482,12 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk, ...@@ -482,14 +482,12 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
r->tcpdiag_wqueue = 0; r->tcpdiag_wqueue = 0;
r->tcpdiag_uid = sock_i_uid(sk); r->tcpdiag_uid = sock_i_uid(sk);
r->tcpdiag_inode = 0; r->tcpdiag_inode = 0;
#ifdef CONFIG_IPV6
if (r->tcpdiag_family == AF_INET6) { if (r->tcpdiag_family == AF_INET6) {
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src, ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
&req->af.v6_req.loc_addr); &req->af.v6_req.loc_addr);
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst, ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
&req->af.v6_req.rmt_addr); &req->af.v6_req.rmt_addr);
} }
#endif
nlh->nlmsg_len = skb->tail - b; nlh->nlmsg_len = skb->tail - b;
return skb->len; return skb->len;
...@@ -545,16 +543,12 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk, ...@@ -545,16 +543,12 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
if (bc) { if (bc) {
entry.saddr = entry.saddr =
#ifdef CONFIG_IPV6
(entry.family == AF_INET6) ? (entry.family == AF_INET6) ?
req->af.v6_req.loc_addr.s6_addr32 : req->af.v6_req.loc_addr.s6_addr32 :
#endif
&req->af.v4_req.loc_addr; &req->af.v4_req.loc_addr;
entry.daddr = entry.daddr =
#ifdef CONFIG_IPV6
(entry.family == AF_INET6) ? (entry.family == AF_INET6) ?
req->af.v6_req.rmt_addr.s6_addr32 : req->af.v6_req.rmt_addr.s6_addr32 :
#endif
&req->af.v4_req.rmt_addr; &req->af.v4_req.rmt_addr;
entry.dport = ntohs(req->rmt_port); entry.dport = ntohs(req->rmt_port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment