aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-10-04 14:56:05 -0400
committerPatrick McHardy <kaber@trash.net>2010-10-04 14:56:05 -0400
commita8defca048fd11eb2d1a17ab61a60a856292dd4e (patch)
treeb486460fd1f2310cd4572bd36c126a3fa8b3a5c5 /net/ipv6
parent0c200d935346fe0ebde9b6dffbb683dddd166fb9 (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.c157
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
27MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); 28MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
28MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog"); 29MODULE_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 */
36static DEFINE_SPINLOCK(log_lock);
37
38/* One level of recursion won't kill us */ 36/* One level of recursion won't kill us */
39static void dump_packet(const struct nf_loginfo *info, 37static 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
376static void dump_mac_header(const struct nf_loginfo *info, 375static 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
398fallback: 398fallback:
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
426static struct nf_loginfo default_loginfo = { 426static 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
463static unsigned int 464static unsigned int