diff options
author | Daniel Borkmann <dborkman@redhat.com> | 2013-08-21 13:48:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-22 19:19:50 -0400 |
commit | f925d0a62db3f1b6e463ef956d0855006538d002 (patch) | |
tree | ffc3a6c8cd61968f4eddab181ce8f216c7a96157 /net/ipv4 | |
parent | d8cdeda6ddbcb33debbb87590a7d42ff7f5b5cfd (diff) |
net: tcp_probe: add IPv6 support
The tcp_probe currently only supports analysis of IPv4 connections.
Therefore, it would be nice to have IPv6 supported as well. Since we
have the recently added %pISpc specifier that is IPv4/IPv6 generic,
build related sockaddress structures from the flow information and
pass this to our format string. Tested with SSH and HTTP sessions
on IPv4 and IPv6.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_probe.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index a2392f48ba35..301a3effe579 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c | |||
@@ -54,8 +54,11 @@ static const char procname[] = "tcpprobe"; | |||
54 | 54 | ||
55 | struct tcp_log { | 55 | struct tcp_log { |
56 | ktime_t tstamp; | 56 | ktime_t tstamp; |
57 | __be32 saddr, daddr; | 57 | union { |
58 | __be16 sport, dport; | 58 | struct sockaddr raw; |
59 | struct sockaddr_in v4; | ||
60 | struct sockaddr_in6 v6; | ||
61 | } src, dst; | ||
59 | u16 length; | 62 | u16 length; |
60 | u32 snd_nxt; | 63 | u32 snd_nxt; |
61 | u32 snd_una; | 64 | u32 snd_una; |
@@ -87,6 +90,30 @@ static inline int tcp_probe_avail(void) | |||
87 | return bufsize - tcp_probe_used() - 1; | 90 | return bufsize - tcp_probe_used() - 1; |
88 | } | 91 | } |
89 | 92 | ||
93 | #define tcp_probe_copy_fl_to_si4(inet, si4, mem) \ | ||
94 | do { \ | ||
95 | si4.sin_family = AF_INET; \ | ||
96 | si4.sin_port = inet->inet_##mem##port; \ | ||
97 | si4.sin_addr.s_addr = inet->inet_##mem##addr; \ | ||
98 | } while (0) \ | ||
99 | |||
100 | #if IS_ENABLED(CONFIG_IPV6) | ||
101 | #define tcp_probe_copy_fl_to_si6(inet, si6, mem) \ | ||
102 | do { \ | ||
103 | struct ipv6_pinfo *pi6 = inet->pinet6; \ | ||
104 | si6.sin6_family = AF_INET6; \ | ||
105 | si6.sin6_port = inet->inet_##mem##port; \ | ||
106 | si6.sin6_addr = pi6->mem##addr; \ | ||
107 | si6.sin6_flowinfo = 0; /* No need here. */ \ | ||
108 | si6.sin6_scope_id = 0; /* No need here. */ \ | ||
109 | } while (0) | ||
110 | #else | ||
111 | #define tcp_probe_copy_fl_to_si6(fl, si6, mem) \ | ||
112 | do { \ | ||
113 | memset(&si6, 0, sizeof(si6)); \ | ||
114 | } while (0) | ||
115 | #endif | ||
116 | |||
90 | /* | 117 | /* |
91 | * Hook inserted to be called before each receive packet. | 118 | * Hook inserted to be called before each receive packet. |
92 | * Note: arguments must match tcp_rcv_established()! | 119 | * Note: arguments must match tcp_rcv_established()! |
@@ -108,10 +135,19 @@ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
108 | struct tcp_log *p = tcp_probe.log + tcp_probe.head; | 135 | struct tcp_log *p = tcp_probe.log + tcp_probe.head; |
109 | 136 | ||
110 | p->tstamp = ktime_get(); | 137 | p->tstamp = ktime_get(); |
111 | p->saddr = inet->inet_saddr; | 138 | switch (sk->sk_family) { |
112 | p->sport = inet->inet_sport; | 139 | case AF_INET: |
113 | p->daddr = inet->inet_daddr; | 140 | tcp_probe_copy_fl_to_si4(inet, p->src.v4, s); |
114 | p->dport = inet->inet_dport; | 141 | tcp_probe_copy_fl_to_si4(inet, p->dst.v4, d); |
142 | break; | ||
143 | case AF_INET6: | ||
144 | tcp_probe_copy_fl_to_si6(inet, p->src.v6, s); | ||
145 | tcp_probe_copy_fl_to_si6(inet, p->dst.v6, d); | ||
146 | break; | ||
147 | default: | ||
148 | BUG(); | ||
149 | } | ||
150 | |||
115 | p->length = skb->len; | 151 | p->length = skb->len; |
116 | p->snd_nxt = tp->snd_nxt; | 152 | p->snd_nxt = tp->snd_nxt; |
117 | p->snd_una = tp->snd_una; | 153 | p->snd_una = tp->snd_una; |
@@ -159,12 +195,10 @@ static int tcpprobe_sprint(char *tbuf, int n) | |||
159 | = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start)); | 195 | = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start)); |
160 | 196 | ||
161 | return scnprintf(tbuf, n, | 197 | return scnprintf(tbuf, n, |
162 | "%lu.%09lu %pI4:%u %pI4:%u %d %#x %#x %u %u %u %u %u\n", | 198 | "%lu.%09lu %pISpc %pISpc %d %#x %#x %u %u %u %u %u\n", |
163 | (unsigned long) tv.tv_sec, | 199 | (unsigned long) tv.tv_sec, |
164 | (unsigned long) tv.tv_nsec, | 200 | (unsigned long) tv.tv_nsec, |
165 | &p->saddr, ntohs(p->sport), | 201 | &p->src, &p->dst, p->length, p->snd_nxt, p->snd_una, |
166 | &p->daddr, ntohs(p->dport), | ||
167 | p->length, p->snd_nxt, p->snd_una, | ||
168 | p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt, p->rcv_wnd); | 202 | p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt, p->rcv_wnd); |
169 | } | 203 | } |
170 | 204 | ||