diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-10-04 14:56:05 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-10-04 14:56:05 -0400 |
commit | a8defca048fd11eb2d1a17ab61a60a856292dd4e (patch) | |
tree | b486460fd1f2310cd4572bd36c126a3fa8b3a5c5 /net/ipv6 | |
parent | 0c200d935346fe0ebde9b6dffbb683dddd166fb9 (diff) |
netfilter: ipt_LOG: add bufferisation to call printk() once
ipt_LOG & ip6t_LOG use lot of calls to printk() and use a lock in a hope
several cpus wont mix their output in syslog.
printk() being very expensive [1], its better to call it once, on a
prebuilt and complete line. Also, with mixed IPv4 and IPv6 trafic,
separate IPv4/IPv6 locks dont avoid garbage.
I used an allocation of a 1024 bytes structure, sort of seq_printf() but
with a fixed size limit.
Use a static buffer if dynamic allocation failed.
Emit a once time alert if buffer size happens to be too short.
[1]: printk() has various features like printk_delay()...
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6t_LOG.c | 157 |
1 files changed, 79 insertions, 78 deletions
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 0a07ae7b933f..09c88891a753 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/netfilter/x_tables.h> | 23 | #include <linux/netfilter/x_tables.h> |
24 | #include <linux/netfilter_ipv6/ip6_tables.h> | 24 | #include <linux/netfilter_ipv6/ip6_tables.h> |
25 | #include <net/netfilter/nf_log.h> | 25 | #include <net/netfilter/nf_log.h> |
26 | #include <net/netfilter/xt_log.h> | ||
26 | 27 | ||
27 | MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); | 28 | MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); |
28 | MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog"); | 29 | MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog"); |
@@ -32,11 +33,9 @@ struct in_device; | |||
32 | #include <net/route.h> | 33 | #include <net/route.h> |
33 | #include <linux/netfilter_ipv6/ip6t_LOG.h> | 34 | #include <linux/netfilter_ipv6/ip6t_LOG.h> |
34 | 35 | ||
35 | /* Use lock to serialize, so printks don't overlap */ | ||
36 | static DEFINE_SPINLOCK(log_lock); | ||
37 | |||
38 | /* One level of recursion won't kill us */ | 36 | /* One level of recursion won't kill us */ |
39 | static void dump_packet(const struct nf_loginfo *info, | 37 | static void dump_packet(struct sbuff *m, |
38 | const struct nf_loginfo *info, | ||
40 | const struct sk_buff *skb, unsigned int ip6hoff, | 39 | const struct sk_buff *skb, unsigned int ip6hoff, |
41 | int recurse) | 40 | int recurse) |
42 | { | 41 | { |
@@ -55,15 +54,15 @@ static void dump_packet(const struct nf_loginfo *info, | |||
55 | 54 | ||
56 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); | 55 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); |
57 | if (ih == NULL) { | 56 | if (ih == NULL) { |
58 | printk("TRUNCATED"); | 57 | sb_add(m, "TRUNCATED"); |
59 | return; | 58 | return; |
60 | } | 59 | } |
61 | 60 | ||
62 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ | 61 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ |
63 | printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); | 62 | sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); |
64 | 63 | ||
65 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | 64 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ |
66 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | 65 | sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", |
67 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), | 66 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), |
68 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, | 67 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, |
69 | ih->hop_limit, | 68 | ih->hop_limit, |
@@ -78,35 +77,35 @@ static void dump_packet(const struct nf_loginfo *info, | |||
78 | 77 | ||
79 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | 78 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); |
80 | if (hp == NULL) { | 79 | if (hp == NULL) { |
81 | printk("TRUNCATED"); | 80 | sb_add(m, "TRUNCATED"); |
82 | return; | 81 | return; |
83 | } | 82 | } |
84 | 83 | ||
85 | /* Max length: 48 "OPT (...) " */ | 84 | /* Max length: 48 "OPT (...) " */ |
86 | if (logflags & IP6T_LOG_IPOPT) | 85 | if (logflags & IP6T_LOG_IPOPT) |
87 | printk("OPT ( "); | 86 | sb_add(m, "OPT ( "); |
88 | 87 | ||
89 | switch (currenthdr) { | 88 | switch (currenthdr) { |
90 | case IPPROTO_FRAGMENT: { | 89 | case IPPROTO_FRAGMENT: { |
91 | struct frag_hdr _fhdr; | 90 | struct frag_hdr _fhdr; |
92 | const struct frag_hdr *fh; | 91 | const struct frag_hdr *fh; |
93 | 92 | ||
94 | printk("FRAG:"); | 93 | sb_add(m, "FRAG:"); |
95 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), | 94 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), |
96 | &_fhdr); | 95 | &_fhdr); |
97 | if (fh == NULL) { | 96 | if (fh == NULL) { |
98 | printk("TRUNCATED "); | 97 | sb_add(m, "TRUNCATED "); |
99 | return; | 98 | return; |
100 | } | 99 | } |
101 | 100 | ||
102 | /* Max length: 6 "65535 " */ | 101 | /* Max length: 6 "65535 " */ |
103 | printk("%u ", ntohs(fh->frag_off) & 0xFFF8); | 102 | sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); |
104 | 103 | ||
105 | /* Max length: 11 "INCOMPLETE " */ | 104 | /* Max length: 11 "INCOMPLETE " */ |
106 | if (fh->frag_off & htons(0x0001)) | 105 | if (fh->frag_off & htons(0x0001)) |
107 | printk("INCOMPLETE "); | 106 | sb_add(m, "INCOMPLETE "); |
108 | 107 | ||
109 | printk("ID:%08x ", ntohl(fh->identification)); | 108 | sb_add(m, "ID:%08x ", ntohl(fh->identification)); |
110 | 109 | ||
111 | if (ntohs(fh->frag_off) & 0xFFF8) | 110 | if (ntohs(fh->frag_off) & 0xFFF8) |
112 | fragment = 1; | 111 | fragment = 1; |
@@ -120,7 +119,7 @@ static void dump_packet(const struct nf_loginfo *info, | |||
120 | case IPPROTO_HOPOPTS: | 119 | case IPPROTO_HOPOPTS: |
121 | if (fragment) { | 120 | if (fragment) { |
122 | if (logflags & IP6T_LOG_IPOPT) | 121 | if (logflags & IP6T_LOG_IPOPT) |
123 | printk(")"); | 122 | sb_add(m, ")"); |
124 | return; | 123 | return; |
125 | } | 124 | } |
126 | hdrlen = ipv6_optlen(hp); | 125 | hdrlen = ipv6_optlen(hp); |
@@ -132,10 +131,10 @@ static void dump_packet(const struct nf_loginfo *info, | |||
132 | const struct ip_auth_hdr *ah; | 131 | const struct ip_auth_hdr *ah; |
133 | 132 | ||
134 | /* Max length: 3 "AH " */ | 133 | /* Max length: 3 "AH " */ |
135 | printk("AH "); | 134 | sb_add(m, "AH "); |
136 | 135 | ||
137 | if (fragment) { | 136 | if (fragment) { |
138 | printk(")"); | 137 | sb_add(m, ")"); |
139 | return; | 138 | return; |
140 | } | 139 | } |
141 | 140 | ||
@@ -146,13 +145,13 @@ static void dump_packet(const struct nf_loginfo *info, | |||
146 | * Max length: 26 "INCOMPLETE [65535 | 145 | * Max length: 26 "INCOMPLETE [65535 |
147 | * bytes] )" | 146 | * bytes] )" |
148 | */ | 147 | */ |
149 | printk("INCOMPLETE [%u bytes] )", | 148 | sb_add(m, "INCOMPLETE [%u bytes] )", |
150 | skb->len - ptr); | 149 | skb->len - ptr); |
151 | return; | 150 | return; |
152 | } | 151 | } |
153 | 152 | ||
154 | /* Length: 15 "SPI=0xF1234567 */ | 153 | /* Length: 15 "SPI=0xF1234567 */ |
155 | printk("SPI=0x%x ", ntohl(ah->spi)); | 154 | sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); |
156 | 155 | ||
157 | } | 156 | } |
158 | 157 | ||
@@ -164,10 +163,10 @@ static void dump_packet(const struct nf_loginfo *info, | |||
164 | const struct ip_esp_hdr *eh; | 163 | const struct ip_esp_hdr *eh; |
165 | 164 | ||
166 | /* Max length: 4 "ESP " */ | 165 | /* Max length: 4 "ESP " */ |
167 | printk("ESP "); | 166 | sb_add(m, "ESP "); |
168 | 167 | ||
169 | if (fragment) { | 168 | if (fragment) { |
170 | printk(")"); | 169 | sb_add(m, ")"); |
171 | return; | 170 | return; |
172 | } | 171 | } |
173 | 172 | ||
@@ -177,23 +176,23 @@ static void dump_packet(const struct nf_loginfo *info, | |||
177 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), | 176 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), |
178 | &_esph); | 177 | &_esph); |
179 | if (eh == NULL) { | 178 | if (eh == NULL) { |
180 | printk("INCOMPLETE [%u bytes] )", | 179 | sb_add(m, "INCOMPLETE [%u bytes] )", |
181 | skb->len - ptr); | 180 | skb->len - ptr); |
182 | return; | 181 | return; |
183 | } | 182 | } |
184 | 183 | ||
185 | /* Length: 16 "SPI=0xF1234567 )" */ | 184 | /* Length: 16 "SPI=0xF1234567 )" */ |
186 | printk("SPI=0x%x )", ntohl(eh->spi) ); | 185 | sb_add(m, "SPI=0x%x )", ntohl(eh->spi) ); |
187 | 186 | ||
188 | } | 187 | } |
189 | return; | 188 | return; |
190 | default: | 189 | default: |
191 | /* Max length: 20 "Unknown Ext Hdr 255" */ | 190 | /* Max length: 20 "Unknown Ext Hdr 255" */ |
192 | printk("Unknown Ext Hdr %u", currenthdr); | 191 | sb_add(m, "Unknown Ext Hdr %u", currenthdr); |
193 | return; | 192 | return; |
194 | } | 193 | } |
195 | if (logflags & IP6T_LOG_IPOPT) | 194 | if (logflags & IP6T_LOG_IPOPT) |
196 | printk(") "); | 195 | sb_add(m, ") "); |
197 | 196 | ||
198 | currenthdr = hp->nexthdr; | 197 | currenthdr = hp->nexthdr; |
199 | ptr += hdrlen; | 198 | ptr += hdrlen; |
@@ -205,7 +204,7 @@ static void dump_packet(const struct nf_loginfo *info, | |||
205 | const struct tcphdr *th; | 204 | const struct tcphdr *th; |
206 | 205 | ||
207 | /* Max length: 10 "PROTO=TCP " */ | 206 | /* Max length: 10 "PROTO=TCP " */ |
208 | printk("PROTO=TCP "); | 207 | sb_add(m, "PROTO=TCP "); |
209 | 208 | ||
210 | if (fragment) | 209 | if (fragment) |
211 | break; | 210 | break; |
@@ -213,40 +212,40 @@ static void dump_packet(const struct nf_loginfo *info, | |||
213 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | 212 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ |
214 | th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); | 213 | th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); |
215 | if (th == NULL) { | 214 | if (th == NULL) { |
216 | printk("INCOMPLETE [%u bytes] ", skb->len - ptr); | 215 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); |
217 | return; | 216 | return; |
218 | } | 217 | } |
219 | 218 | ||
220 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | 219 | /* Max length: 20 "SPT=65535 DPT=65535 " */ |
221 | printk("SPT=%u DPT=%u ", | 220 | sb_add(m, "SPT=%u DPT=%u ", |
222 | ntohs(th->source), ntohs(th->dest)); | 221 | ntohs(th->source), ntohs(th->dest)); |
223 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ | 222 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ |
224 | if (logflags & IP6T_LOG_TCPSEQ) | 223 | if (logflags & IP6T_LOG_TCPSEQ) |
225 | printk("SEQ=%u ACK=%u ", | 224 | sb_add(m, "SEQ=%u ACK=%u ", |
226 | ntohl(th->seq), ntohl(th->ack_seq)); | 225 | ntohl(th->seq), ntohl(th->ack_seq)); |
227 | /* Max length: 13 "WINDOW=65535 " */ | 226 | /* Max length: 13 "WINDOW=65535 " */ |
228 | printk("WINDOW=%u ", ntohs(th->window)); | 227 | sb_add(m, "WINDOW=%u ", ntohs(th->window)); |
229 | /* Max length: 9 "RES=0x3C " */ | 228 | /* Max length: 9 "RES=0x3C " */ |
230 | printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); | 229 | sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); |
231 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ | 230 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ |
232 | if (th->cwr) | 231 | if (th->cwr) |
233 | printk("CWR "); | 232 | sb_add(m, "CWR "); |
234 | if (th->ece) | 233 | if (th->ece) |
235 | printk("ECE "); | 234 | sb_add(m, "ECE "); |
236 | if (th->urg) | 235 | if (th->urg) |
237 | printk("URG "); | 236 | sb_add(m, "URG "); |
238 | if (th->ack) | 237 | if (th->ack) |
239 | printk("ACK "); | 238 | sb_add(m, "ACK "); |
240 | if (th->psh) | 239 | if (th->psh) |
241 | printk("PSH "); | 240 | sb_add(m, "PSH "); |
242 | if (th->rst) | 241 | if (th->rst) |
243 | printk("RST "); | 242 | sb_add(m, "RST "); |
244 | if (th->syn) | 243 | if (th->syn) |
245 | printk("SYN "); | 244 | sb_add(m, "SYN "); |
246 | if (th->fin) | 245 | if (th->fin) |
247 | printk("FIN "); | 246 | sb_add(m, "FIN "); |
248 | /* Max length: 11 "URGP=65535 " */ | 247 | /* Max length: 11 "URGP=65535 " */ |
249 | printk("URGP=%u ", ntohs(th->urg_ptr)); | 248 | sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); |
250 | 249 | ||
251 | if ((logflags & IP6T_LOG_TCPOPT) && | 250 | if ((logflags & IP6T_LOG_TCPOPT) && |
252 | th->doff * 4 > sizeof(struct tcphdr)) { | 251 | th->doff * 4 > sizeof(struct tcphdr)) { |
@@ -260,15 +259,15 @@ static void dump_packet(const struct nf_loginfo *info, | |||
260 | ptr + sizeof(struct tcphdr), | 259 | ptr + sizeof(struct tcphdr), |
261 | optsize, _opt); | 260 | optsize, _opt); |
262 | if (op == NULL) { | 261 | if (op == NULL) { |
263 | printk("OPT (TRUNCATED)"); | 262 | sb_add(m, "OPT (TRUNCATED)"); |
264 | return; | 263 | return; |
265 | } | 264 | } |
266 | 265 | ||
267 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | 266 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ |
268 | printk("OPT ("); | 267 | sb_add(m, "OPT ("); |
269 | for (i =0; i < optsize; i++) | 268 | for (i =0; i < optsize; i++) |
270 | printk("%02X", op[i]); | 269 | sb_add(m, "%02X", op[i]); |
271 | printk(") "); | 270 | sb_add(m, ") "); |
272 | } | 271 | } |
273 | break; | 272 | break; |
274 | } | 273 | } |
@@ -279,9 +278,9 @@ static void dump_packet(const struct nf_loginfo *info, | |||
279 | 278 | ||
280 | if (currenthdr == IPPROTO_UDP) | 279 | if (currenthdr == IPPROTO_UDP) |
281 | /* Max length: 10 "PROTO=UDP " */ | 280 | /* Max length: 10 "PROTO=UDP " */ |
282 | printk("PROTO=UDP " ); | 281 | sb_add(m, "PROTO=UDP " ); |
283 | else /* Max length: 14 "PROTO=UDPLITE " */ | 282 | else /* Max length: 14 "PROTO=UDPLITE " */ |
284 | printk("PROTO=UDPLITE "); | 283 | sb_add(m, "PROTO=UDPLITE "); |
285 | 284 | ||
286 | if (fragment) | 285 | if (fragment) |
287 | break; | 286 | break; |
@@ -289,12 +288,12 @@ static void dump_packet(const struct nf_loginfo *info, | |||
289 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | 288 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ |
290 | uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); | 289 | uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); |
291 | if (uh == NULL) { | 290 | if (uh == NULL) { |
292 | printk("INCOMPLETE [%u bytes] ", skb->len - ptr); | 291 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); |
293 | return; | 292 | return; |
294 | } | 293 | } |
295 | 294 | ||
296 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | 295 | /* Max length: 20 "SPT=65535 DPT=65535 " */ |
297 | printk("SPT=%u DPT=%u LEN=%u ", | 296 | sb_add(m, "SPT=%u DPT=%u LEN=%u ", |
298 | ntohs(uh->source), ntohs(uh->dest), | 297 | ntohs(uh->source), ntohs(uh->dest), |
299 | ntohs(uh->len)); | 298 | ntohs(uh->len)); |
300 | break; | 299 | break; |
@@ -304,7 +303,7 @@ static void dump_packet(const struct nf_loginfo *info, | |||
304 | const struct icmp6hdr *ic; | 303 | const struct icmp6hdr *ic; |
305 | 304 | ||
306 | /* Max length: 13 "PROTO=ICMPv6 " */ | 305 | /* Max length: 13 "PROTO=ICMPv6 " */ |
307 | printk("PROTO=ICMPv6 "); | 306 | sb_add(m, "PROTO=ICMPv6 "); |
308 | 307 | ||
309 | if (fragment) | 308 | if (fragment) |
310 | break; | 309 | break; |
@@ -312,18 +311,18 @@ static void dump_packet(const struct nf_loginfo *info, | |||
312 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | 311 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ |
313 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); | 312 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); |
314 | if (ic == NULL) { | 313 | if (ic == NULL) { |
315 | printk("INCOMPLETE [%u bytes] ", skb->len - ptr); | 314 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); |
316 | return; | 315 | return; |
317 | } | 316 | } |
318 | 317 | ||
319 | /* Max length: 18 "TYPE=255 CODE=255 " */ | 318 | /* Max length: 18 "TYPE=255 CODE=255 " */ |
320 | printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); | 319 | sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); |
321 | 320 | ||
322 | switch (ic->icmp6_type) { | 321 | switch (ic->icmp6_type) { |
323 | case ICMPV6_ECHO_REQUEST: | 322 | case ICMPV6_ECHO_REQUEST: |
324 | case ICMPV6_ECHO_REPLY: | 323 | case ICMPV6_ECHO_REPLY: |
325 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | 324 | /* Max length: 19 "ID=65535 SEQ=65535 " */ |
326 | printk("ID=%u SEQ=%u ", | 325 | sb_add(m, "ID=%u SEQ=%u ", |
327 | ntohs(ic->icmp6_identifier), | 326 | ntohs(ic->icmp6_identifier), |
328 | ntohs(ic->icmp6_sequence)); | 327 | ntohs(ic->icmp6_sequence)); |
329 | break; | 328 | break; |
@@ -334,35 +333,35 @@ static void dump_packet(const struct nf_loginfo *info, | |||
334 | 333 | ||
335 | case ICMPV6_PARAMPROB: | 334 | case ICMPV6_PARAMPROB: |
336 | /* Max length: 17 "POINTER=ffffffff " */ | 335 | /* Max length: 17 "POINTER=ffffffff " */ |
337 | printk("POINTER=%08x ", ntohl(ic->icmp6_pointer)); | 336 | sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer)); |
338 | /* Fall through */ | 337 | /* Fall through */ |
339 | case ICMPV6_DEST_UNREACH: | 338 | case ICMPV6_DEST_UNREACH: |
340 | case ICMPV6_PKT_TOOBIG: | 339 | case ICMPV6_PKT_TOOBIG: |
341 | case ICMPV6_TIME_EXCEED: | 340 | case ICMPV6_TIME_EXCEED: |
342 | /* Max length: 3+maxlen */ | 341 | /* Max length: 3+maxlen */ |
343 | if (recurse) { | 342 | if (recurse) { |
344 | printk("["); | 343 | sb_add(m, "["); |
345 | dump_packet(info, skb, ptr + sizeof(_icmp6h), | 344 | dump_packet(m, info, skb, |
346 | 0); | 345 | ptr + sizeof(_icmp6h), 0); |
347 | printk("] "); | 346 | sb_add(m, "] "); |
348 | } | 347 | } |
349 | 348 | ||
350 | /* Max length: 10 "MTU=65535 " */ | 349 | /* Max length: 10 "MTU=65535 " */ |
351 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) | 350 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) |
352 | printk("MTU=%u ", ntohl(ic->icmp6_mtu)); | 351 | sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu)); |
353 | } | 352 | } |
354 | break; | 353 | break; |
355 | } | 354 | } |
356 | /* Max length: 10 "PROTO=255 " */ | 355 | /* Max length: 10 "PROTO=255 " */ |
357 | default: | 356 | default: |
358 | printk("PROTO=%u ", currenthdr); | 357 | sb_add(m, "PROTO=%u ", currenthdr); |
359 | } | 358 | } |
360 | 359 | ||
361 | /* Max length: 15 "UID=4294967295 " */ | 360 | /* Max length: 15 "UID=4294967295 " */ |
362 | if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { | 361 | if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { |
363 | read_lock_bh(&skb->sk->sk_callback_lock); | 362 | read_lock_bh(&skb->sk->sk_callback_lock); |
364 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | 363 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) |
365 | printk("UID=%u GID=%u ", | 364 | sb_add(m, "UID=%u GID=%u ", |
366 | skb->sk->sk_socket->file->f_cred->fsuid, | 365 | skb->sk->sk_socket->file->f_cred->fsuid, |
367 | skb->sk->sk_socket->file->f_cred->fsgid); | 366 | skb->sk->sk_socket->file->f_cred->fsgid); |
368 | read_unlock_bh(&skb->sk->sk_callback_lock); | 367 | read_unlock_bh(&skb->sk->sk_callback_lock); |
@@ -370,10 +369,11 @@ static void dump_packet(const struct nf_loginfo *info, | |||
370 | 369 | ||
371 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | 370 | /* Max length: 16 "MARK=0xFFFFFFFF " */ |
372 | if (!recurse && skb->mark) | 371 | if (!recurse && skb->mark) |
373 | printk("MARK=0x%x ", skb->mark); | 372 | sb_add(m, "MARK=0x%x ", skb->mark); |
374 | } | 373 | } |
375 | 374 | ||
376 | static void dump_mac_header(const struct nf_loginfo *info, | 375 | static void dump_mac_header(struct sbuff *m, |
376 | const struct nf_loginfo *info, | ||
377 | const struct sk_buff *skb) | 377 | const struct sk_buff *skb) |
378 | { | 378 | { |
379 | struct net_device *dev = skb->dev; | 379 | struct net_device *dev = skb->dev; |
@@ -387,7 +387,7 @@ static void dump_mac_header(const struct nf_loginfo *info, | |||
387 | 387 | ||
388 | switch (dev->type) { | 388 | switch (dev->type) { |
389 | case ARPHRD_ETHER: | 389 | case ARPHRD_ETHER: |
390 | printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | 390 | sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", |
391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | 391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, |
392 | ntohs(eth_hdr(skb)->h_proto)); | 392 | ntohs(eth_hdr(skb)->h_proto)); |
393 | return; | 393 | return; |
@@ -396,7 +396,7 @@ static void dump_mac_header(const struct nf_loginfo *info, | |||
396 | } | 396 | } |
397 | 397 | ||
398 | fallback: | 398 | fallback: |
399 | printk("MAC="); | 399 | sb_add(m, "MAC="); |
400 | if (dev->hard_header_len && | 400 | if (dev->hard_header_len && |
401 | skb->mac_header != skb->network_header) { | 401 | skb->mac_header != skb->network_header) { |
402 | const unsigned char *p = skb_mac_header(skb); | 402 | const unsigned char *p = skb_mac_header(skb); |
@@ -408,19 +408,19 @@ fallback: | |||
408 | p = NULL; | 408 | p = NULL; |
409 | 409 | ||
410 | if (p != NULL) { | 410 | if (p != NULL) { |
411 | printk("%02x", *p++); | 411 | sb_add(m, "%02x", *p++); |
412 | for (i = 1; i < len; i++) | 412 | for (i = 1; i < len; i++) |
413 | printk(":%02x", p[i]); | 413 | sb_add(m, ":%02x", p[i]); |
414 | } | 414 | } |
415 | printk(" "); | 415 | sb_add(m, " "); |
416 | 416 | ||
417 | if (dev->type == ARPHRD_SIT) { | 417 | if (dev->type == ARPHRD_SIT) { |
418 | const struct iphdr *iph = | 418 | const struct iphdr *iph = |
419 | (struct iphdr *)skb_mac_header(skb); | 419 | (struct iphdr *)skb_mac_header(skb); |
420 | printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); | 420 | sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); |
421 | } | 421 | } |
422 | } else | 422 | } else |
423 | printk(" "); | 423 | sb_add(m, " "); |
424 | } | 424 | } |
425 | 425 | ||
426 | static struct nf_loginfo default_loginfo = { | 426 | static struct nf_loginfo default_loginfo = { |
@@ -442,22 +442,23 @@ ip6t_log_packet(u_int8_t pf, | |||
442 | const struct nf_loginfo *loginfo, | 442 | const struct nf_loginfo *loginfo, |
443 | const char *prefix) | 443 | const char *prefix) |
444 | { | 444 | { |
445 | struct sbuff *m = sb_open(); | ||
446 | |||
445 | if (!loginfo) | 447 | if (!loginfo) |
446 | loginfo = &default_loginfo; | 448 | loginfo = &default_loginfo; |
447 | 449 | ||
448 | spin_lock_bh(&log_lock); | 450 | sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, |
449 | printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, | 451 | prefix, |
450 | prefix, | 452 | in ? in->name : "", |
451 | in ? in->name : "", | 453 | out ? out->name : ""); |
452 | out ? out->name : ""); | ||
453 | 454 | ||
454 | /* MAC logging for input path only. */ | 455 | /* MAC logging for input path only. */ |
455 | if (in && !out) | 456 | if (in && !out) |
456 | dump_mac_header(loginfo, skb); | 457 | dump_mac_header(m, loginfo, skb); |
458 | |||
459 | dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); | ||
457 | 460 | ||
458 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); | 461 | sb_close(m); |
459 | printk("\n"); | ||
460 | spin_unlock_bh(&log_lock); | ||
461 | } | 462 | } |
462 | 463 | ||
463 | static unsigned int | 464 | static unsigned int |