Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eric Dumazet and committed by
Patrick McHardy
a8defca0 0c200d93

+152 -150
+73 -72
net/ipv4/netfilter/ipt_LOG.c
··· 24 24 #include <linux/netfilter/x_tables.h> 25 25 #include <linux/netfilter_ipv4/ipt_LOG.h> 26 26 #include <net/netfilter/nf_log.h> 27 + #include <net/netfilter/xt_log.h> 27 28 28 29 MODULE_LICENSE("GPL"); 29 30 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 30 31 MODULE_DESCRIPTION("Xtables: IPv4 packet logging to syslog"); 31 32 32 - /* Use lock to serialize, so printks don't overlap */ 33 - static DEFINE_SPINLOCK(log_lock); 34 - 35 33 /* One level of recursion won't kill us */ 36 - static void dump_packet(const struct nf_loginfo *info, 34 + static void dump_packet(struct sbuff *m, 35 + const struct nf_loginfo *info, 37 36 const struct sk_buff *skb, 38 37 unsigned int iphoff) 39 38 { ··· 47 48 48 49 ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph); 49 50 if (ih == NULL) { 50 - printk("TRUNCATED"); 51 + sb_add(m, "TRUNCATED"); 51 52 return; 52 53 } 53 54 54 55 /* Important fields: 55 56 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */ 56 57 /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */ 57 - printk("SRC=%pI4 DST=%pI4 ", 58 + sb_add(m, "SRC=%pI4 DST=%pI4 ", 58 59 &ih->saddr, &ih->daddr); 59 60 60 61 /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ 61 - printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", 62 + sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", 62 63 ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK, 63 64 ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id)); 64 65 65 66 /* Max length: 6 "CE DF MF " */ 66 67 if (ntohs(ih->frag_off) & IP_CE) 67 - printk("CE "); 68 + sb_add(m, "CE "); 68 69 if (ntohs(ih->frag_off) & IP_DF) 69 - printk("DF "); 70 + sb_add(m, "DF "); 70 71 if (ntohs(ih->frag_off) & IP_MF) 71 - printk("MF "); 72 + sb_add(m, "MF "); 72 73 73 74 /* Max length: 11 "FRAG:65535 " */ 74 75 if (ntohs(ih->frag_off) & IP_OFFSET) 75 - printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); 76 + sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); 76 77 77 78 if ((logflags & IPT_LOG_IPOPT) && 78 79 ih->ihl * 4 > sizeof(struct iphdr)) { ··· 84 85 op = skb_header_pointer(skb, iphoff+sizeof(_iph), 85 86 optsize, _opt); 86 87 if (op == NULL) { 87 - printk("TRUNCATED"); 88 + sb_add(m, "TRUNCATED"); 88 89 return; 89 90 } 90 91 91 92 /* Max length: 127 "OPT (" 15*4*2chars ") " */ 92 - printk("OPT ("); 93 + sb_add(m, "OPT ("); 93 94 for (i = 0; i < optsize; i++) 94 - printk("%02X", op[i]); 95 - printk(") "); 95 + sb_add(m, "%02X", op[i]); 96 + sb_add(m, ") "); 96 97 } 97 98 98 99 switch (ih->protocol) { ··· 101 102 const struct tcphdr *th; 102 103 103 104 /* Max length: 10 "PROTO=TCP " */ 104 - printk("PROTO=TCP "); 105 + sb_add(m, "PROTO=TCP "); 105 106 106 107 if (ntohs(ih->frag_off) & IP_OFFSET) 107 108 break; ··· 110 111 th = skb_header_pointer(skb, iphoff + ih->ihl * 4, 111 112 sizeof(_tcph), &_tcph); 112 113 if (th == NULL) { 113 - printk("INCOMPLETE [%u bytes] ", 114 + sb_add(m, "INCOMPLETE [%u bytes] ", 114 115 skb->len - iphoff - ih->ihl*4); 115 116 break; 116 117 } 117 118 118 119 /* Max length: 20 "SPT=65535 DPT=65535 " */ 119 - printk("SPT=%u DPT=%u ", 120 + sb_add(m, "SPT=%u DPT=%u ", 120 121 ntohs(th->source), ntohs(th->dest)); 121 122 /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ 122 123 if (logflags & IPT_LOG_TCPSEQ) 123 - printk("SEQ=%u ACK=%u ", 124 + sb_add(m, "SEQ=%u ACK=%u ", 124 125 ntohl(th->seq), ntohl(th->ack_seq)); 125 126 /* Max length: 13 "WINDOW=65535 " */ 126 - printk("WINDOW=%u ", ntohs(th->window)); 127 + sb_add(m, "WINDOW=%u ", ntohs(th->window)); 127 128 /* Max length: 9 "RES=0x3F " */ 128 - printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); 129 + sb_add(m, "RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); 129 130 /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ 130 131 if (th->cwr) 131 - printk("CWR "); 132 + sb_add(m, "CWR "); 132 133 if (th->ece) 133 - printk("ECE "); 134 + sb_add(m, "ECE "); 134 135 if (th->urg) 135 - printk("URG "); 136 + sb_add(m, "URG "); 136 137 if (th->ack) 137 - printk("ACK "); 138 + sb_add(m, "ACK "); 138 139 if (th->psh) 139 - printk("PSH "); 140 + sb_add(m, "PSH "); 140 141 if (th->rst) 141 - printk("RST "); 142 + sb_add(m, "RST "); 142 143 if (th->syn) 143 - printk("SYN "); 144 + sb_add(m, "SYN "); 144 145 if (th->fin) 145 - printk("FIN "); 146 + sb_add(m, "FIN "); 146 147 /* Max length: 11 "URGP=65535 " */ 147 - printk("URGP=%u ", ntohs(th->urg_ptr)); 148 + sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); 148 149 149 150 if ((logflags & IPT_LOG_TCPOPT) && 150 151 th->doff * 4 > sizeof(struct tcphdr)) { ··· 157 158 iphoff+ih->ihl*4+sizeof(_tcph), 158 159 optsize, _opt); 159 160 if (op == NULL) { 160 - printk("TRUNCATED"); 161 + sb_add(m, "TRUNCATED"); 161 162 return; 162 163 } 163 164 164 165 /* Max length: 127 "OPT (" 15*4*2chars ") " */ 165 - printk("OPT ("); 166 + sb_add(m, "OPT ("); 166 167 for (i = 0; i < optsize; i++) 167 - printk("%02X", op[i]); 168 - printk(") "); 168 + sb_add(m, "%02X", op[i]); 169 + sb_add(m, ") "); 169 170 } 170 171 break; 171 172 } ··· 176 177 177 178 if (ih->protocol == IPPROTO_UDP) 178 179 /* Max length: 10 "PROTO=UDP " */ 179 - printk("PROTO=UDP " ); 180 + sb_add(m, "PROTO=UDP " ); 180 181 else /* Max length: 14 "PROTO=UDPLITE " */ 181 - printk("PROTO=UDPLITE "); 182 + sb_add(m, "PROTO=UDPLITE "); 182 183 183 184 if (ntohs(ih->frag_off) & IP_OFFSET) 184 185 break; ··· 187 188 uh = skb_header_pointer(skb, iphoff+ih->ihl*4, 188 189 sizeof(_udph), &_udph); 189 190 if (uh == NULL) { 190 - printk("INCOMPLETE [%u bytes] ", 191 + sb_add(m, "INCOMPLETE [%u bytes] ", 191 192 skb->len - iphoff - ih->ihl*4); 192 193 break; 193 194 } 194 195 195 196 /* Max length: 20 "SPT=65535 DPT=65535 " */ 196 - printk("SPT=%u DPT=%u LEN=%u ", 197 + sb_add(m, "SPT=%u DPT=%u LEN=%u ", 197 198 ntohs(uh->source), ntohs(uh->dest), 198 199 ntohs(uh->len)); 199 200 break; ··· 220 221 [ICMP_ADDRESSREPLY] = 12 }; 221 222 222 223 /* Max length: 11 "PROTO=ICMP " */ 223 - printk("PROTO=ICMP "); 224 + sb_add(m, "PROTO=ICMP "); 224 225 225 226 if (ntohs(ih->frag_off) & IP_OFFSET) 226 227 break; ··· 229 230 ich = skb_header_pointer(skb, iphoff + ih->ihl * 4, 230 231 sizeof(_icmph), &_icmph); 231 232 if (ich == NULL) { 232 - printk("INCOMPLETE [%u bytes] ", 233 + sb_add(m, "INCOMPLETE [%u bytes] ", 233 234 skb->len - iphoff - ih->ihl*4); 234 235 break; 235 236 } 236 237 237 238 /* Max length: 18 "TYPE=255 CODE=255 " */ 238 - printk("TYPE=%u CODE=%u ", ich->type, ich->code); 239 + sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code); 239 240 240 241 /* Max length: 25 "INCOMPLETE [65535 bytes] " */ 241 242 if (ich->type <= NR_ICMP_TYPES && 242 243 required_len[ich->type] && 243 244 skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { 244 - printk("INCOMPLETE [%u bytes] ", 245 + sb_add(m, "INCOMPLETE [%u bytes] ", 245 246 skb->len - iphoff - ih->ihl*4); 246 247 break; 247 248 } ··· 250 251 case ICMP_ECHOREPLY: 251 252 case ICMP_ECHO: 252 253 /* Max length: 19 "ID=65535 SEQ=65535 " */ 253 - printk("ID=%u SEQ=%u ", 254 + sb_add(m, "ID=%u SEQ=%u ", 254 255 ntohs(ich->un.echo.id), 255 256 ntohs(ich->un.echo.sequence)); 256 257 break; 257 258 258 259 case ICMP_PARAMETERPROB: 259 260 /* Max length: 14 "PARAMETER=255 " */ 260 - printk("PARAMETER=%u ", 261 + sb_add(m, "PARAMETER=%u ", 261 262 ntohl(ich->un.gateway) >> 24); 262 263 break; 263 264 case ICMP_REDIRECT: 264 265 /* Max length: 24 "GATEWAY=255.255.255.255 " */ 265 - printk("GATEWAY=%pI4 ", &ich->un.gateway); 266 + sb_add(m, "GATEWAY=%pI4 ", &ich->un.gateway); 266 267 /* Fall through */ 267 268 case ICMP_DEST_UNREACH: 268 269 case ICMP_SOURCE_QUENCH: 269 270 case ICMP_TIME_EXCEEDED: 270 271 /* Max length: 3+maxlen */ 271 272 if (!iphoff) { /* Only recurse once. */ 272 - printk("["); 273 - dump_packet(info, skb, 273 + sb_add(m, "["); 274 + dump_packet(m, info, skb, 274 275 iphoff + ih->ihl*4+sizeof(_icmph)); 275 - printk("] "); 276 + sb_add(m, "] "); 276 277 } 277 278 278 279 /* Max length: 10 "MTU=65535 " */ 279 280 if (ich->type == ICMP_DEST_UNREACH && 280 281 ich->code == ICMP_FRAG_NEEDED) 281 - printk("MTU=%u ", ntohs(ich->un.frag.mtu)); 282 + sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu)); 282 283 } 283 284 break; 284 285 } ··· 291 292 break; 292 293 293 294 /* Max length: 9 "PROTO=AH " */ 294 - printk("PROTO=AH "); 295 + sb_add(m, "PROTO=AH "); 295 296 296 297 /* Max length: 25 "INCOMPLETE [65535 bytes] " */ 297 298 ah = skb_header_pointer(skb, iphoff+ih->ihl*4, 298 299 sizeof(_ahdr), &_ahdr); 299 300 if (ah == NULL) { 300 - printk("INCOMPLETE [%u bytes] ", 301 + sb_add(m, "INCOMPLETE [%u bytes] ", 301 302 skb->len - iphoff - ih->ihl*4); 302 303 break; 303 304 } 304 305 305 306 /* Length: 15 "SPI=0xF1234567 " */ 306 - printk("SPI=0x%x ", ntohl(ah->spi)); 307 + sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); 307 308 break; 308 309 } 309 310 case IPPROTO_ESP: { ··· 311 312 const struct ip_esp_hdr *eh; 312 313 313 314 /* Max length: 10 "PROTO=ESP " */ 314 - printk("PROTO=ESP "); 315 + sb_add(m, "PROTO=ESP "); 315 316 316 317 if (ntohs(ih->frag_off) & IP_OFFSET) 317 318 break; ··· 320 321 eh = skb_header_pointer(skb, iphoff+ih->ihl*4, 321 322 sizeof(_esph), &_esph); 322 323 if (eh == NULL) { 323 - printk("INCOMPLETE [%u bytes] ", 324 + sb_add(m, "INCOMPLETE [%u bytes] ", 324 325 skb->len - iphoff - ih->ihl*4); 325 326 break; 326 327 } 327 328 328 329 /* Length: 15 "SPI=0xF1234567 " */ 329 - printk("SPI=0x%x ", ntohl(eh->spi)); 330 + sb_add(m, "SPI=0x%x ", ntohl(eh->spi)); 330 331 break; 331 332 } 332 333 /* Max length: 10 "PROTO 255 " */ 333 334 default: 334 - printk("PROTO=%u ", ih->protocol); 335 + sb_add(m, "PROTO=%u ", ih->protocol); 335 336 } 336 337 337 338 /* Max length: 15 "UID=4294967295 " */ 338 339 if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) { 339 340 read_lock_bh(&skb->sk->sk_callback_lock); 340 341 if (skb->sk->sk_socket && skb->sk->sk_socket->file) 341 - printk("UID=%u GID=%u ", 342 + sb_add(m, "UID=%u GID=%u ", 342 343 skb->sk->sk_socket->file->f_cred->fsuid, 343 344 skb->sk->sk_socket->file->f_cred->fsgid); 344 345 read_unlock_bh(&skb->sk->sk_callback_lock); ··· 346 347 347 348 /* Max length: 16 "MARK=0xFFFFFFFF " */ 348 349 if (!iphoff && skb->mark) 349 - printk("MARK=0x%x ", skb->mark); 350 + sb_add(m, "MARK=0x%x ", skb->mark); 350 351 351 352 /* Proto Max log string length */ 352 353 /* IP: 40+46+6+11+127 = 230 */ ··· 363 364 /* maxlen = 230+ 91 + 230 + 252 = 803 */ 364 365 } 365 366 366 - static void dump_mac_header(const struct nf_loginfo *info, 367 + static void dump_mac_header(struct sbuff *m, 368 + const struct nf_loginfo *info, 367 369 const struct sk_buff *skb) 368 370 { 369 371 struct net_device *dev = skb->dev; ··· 378 378 379 379 switch (dev->type) { 380 380 case ARPHRD_ETHER: 381 - printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", 381 + sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", 382 382 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, 383 383 ntohs(eth_hdr(skb)->h_proto)); 384 384 return; ··· 387 387 } 388 388 389 389 fallback: 390 - printk("MAC="); 390 + sb_add(m, "MAC="); 391 391 if (dev->hard_header_len && 392 392 skb->mac_header != skb->network_header) { 393 393 const unsigned char *p = skb_mac_header(skb); 394 394 unsigned int i; 395 395 396 - printk("%02x", *p++); 396 + sb_add(m, "%02x", *p++); 397 397 for (i = 1; i < dev->hard_header_len; i++, p++) 398 - printk(":%02x", *p); 398 + sb_add(m, ":%02x", *p); 399 399 } 400 - printk(" "); 400 + sb_add(m, " "); 401 401 } 402 402 403 403 static struct nf_loginfo default_loginfo = { ··· 419 419 const struct nf_loginfo *loginfo, 420 420 const char *prefix) 421 421 { 422 + struct sbuff *m = sb_open(); 423 + 422 424 if (!loginfo) 423 425 loginfo = &default_loginfo; 424 426 425 - spin_lock_bh(&log_lock); 426 - printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, 427 + sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, 427 428 prefix, 428 429 in ? in->name : "", 429 430 out ? out->name : ""); ··· 435 434 436 435 physindev = skb->nf_bridge->physindev; 437 436 if (physindev && in != physindev) 438 - printk("PHYSIN=%s ", physindev->name); 437 + sb_add(m, "PHYSIN=%s ", physindev->name); 439 438 physoutdev = skb->nf_bridge->physoutdev; 440 439 if (physoutdev && out != physoutdev) 441 - printk("PHYSOUT=%s ", physoutdev->name); 440 + sb_add(m, "PHYSOUT=%s ", physoutdev->name); 442 441 } 443 442 #endif 444 443 445 444 /* MAC logging for input path only. */ 446 445 if (in && !out) 447 - dump_mac_header(loginfo, skb); 446 + dump_mac_header(m, loginfo, skb); 448 447 449 - dump_packet(loginfo, skb, 0); 450 - printk("\n"); 451 - spin_unlock_bh(&log_lock); 448 + dump_packet(m, loginfo, skb, 0); 449 + 450 + sb_close(m); 452 451 } 453 452 454 453 static unsigned int
+79 -78
net/ipv6/netfilter/ip6t_LOG.c
··· 23 23 #include <linux/netfilter/x_tables.h> 24 24 #include <linux/netfilter_ipv6/ip6_tables.h> 25 25 #include <net/netfilter/nf_log.h> 26 + #include <net/netfilter/xt_log.h> 26 27 27 28 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); 28 29 MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog"); ··· 33 32 #include <net/route.h> 34 33 #include <linux/netfilter_ipv6/ip6t_LOG.h> 35 34 36 - /* Use lock to serialize, so printks don't overlap */ 37 - static DEFINE_SPINLOCK(log_lock); 38 - 39 35 /* One level of recursion won't kill us */ 40 - static void dump_packet(const struct nf_loginfo *info, 36 + static void dump_packet(struct sbuff *m, 37 + const struct nf_loginfo *info, 41 38 const struct sk_buff *skb, unsigned int ip6hoff, 42 39 int recurse) 43 40 { ··· 54 55 55 56 ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); 56 57 if (ih == NULL) { 57 - printk("TRUNCATED"); 58 + sb_add(m, "TRUNCATED"); 58 59 return; 59 60 } 60 61 61 62 /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ 62 - printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); 63 + sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); 63 64 64 65 /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ 65 - printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", 66 + sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", 66 67 ntohs(ih->payload_len) + sizeof(struct ipv6hdr), 67 68 (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, 68 69 ih->hop_limit, ··· 77 78 78 79 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); 79 80 if (hp == NULL) { 80 - printk("TRUNCATED"); 81 + sb_add(m, "TRUNCATED"); 81 82 return; 82 83 } 83 84 84 85 /* Max length: 48 "OPT (...) " */ 85 86 if (logflags & IP6T_LOG_IPOPT) 86 - printk("OPT ( "); 87 + sb_add(m, "OPT ( "); 87 88 88 89 switch (currenthdr) { 89 90 case IPPROTO_FRAGMENT: { 90 91 struct frag_hdr _fhdr; 91 92 const struct frag_hdr *fh; 92 93 93 - printk("FRAG:"); 94 + sb_add(m, "FRAG:"); 94 95 fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), 95 96 &_fhdr); 96 97 if (fh == NULL) { 97 - printk("TRUNCATED "); 98 + sb_add(m, "TRUNCATED "); 98 99 return; 99 100 } 100 101 101 102 /* Max length: 6 "65535 " */ 102 - printk("%u ", ntohs(fh->frag_off) & 0xFFF8); 103 + sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); 103 104 104 105 /* Max length: 11 "INCOMPLETE " */ 105 106 if (fh->frag_off & htons(0x0001)) 106 - printk("INCOMPLETE "); 107 + sb_add(m, "INCOMPLETE "); 107 108 108 - printk("ID:%08x ", ntohl(fh->identification)); 109 + sb_add(m, "ID:%08x ", ntohl(fh->identification)); 109 110 110 111 if (ntohs(fh->frag_off) & 0xFFF8) 111 112 fragment = 1; ··· 119 120 case IPPROTO_HOPOPTS: 120 121 if (fragment) { 121 122 if (logflags & IP6T_LOG_IPOPT) 122 - printk(")"); 123 + sb_add(m, ")"); 123 124 return; 124 125 } 125 126 hdrlen = ipv6_optlen(hp); ··· 131 132 const struct ip_auth_hdr *ah; 132 133 133 134 /* Max length: 3 "AH " */ 134 - printk("AH "); 135 + sb_add(m, "AH "); 135 136 136 137 if (fragment) { 137 - printk(")"); 138 + sb_add(m, ")"); 138 139 return; 139 140 } 140 141 ··· 145 146 * Max length: 26 "INCOMPLETE [65535 146 147 * bytes] )" 147 148 */ 148 - printk("INCOMPLETE [%u bytes] )", 149 + sb_add(m, "INCOMPLETE [%u bytes] )", 149 150 skb->len - ptr); 150 151 return; 151 152 } 152 153 153 154 /* Length: 15 "SPI=0xF1234567 */ 154 - printk("SPI=0x%x ", ntohl(ah->spi)); 155 + sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); 155 156 156 157 } 157 158 ··· 163 164 const struct ip_esp_hdr *eh; 164 165 165 166 /* Max length: 4 "ESP " */ 166 - printk("ESP "); 167 + sb_add(m, "ESP "); 167 168 168 169 if (fragment) { 169 - printk(")"); 170 + sb_add(m, ")"); 170 171 return; 171 172 } 172 173 ··· 176 177 eh = skb_header_pointer(skb, ptr, sizeof(_esph), 177 178 &_esph); 178 179 if (eh == NULL) { 179 - printk("INCOMPLETE [%u bytes] )", 180 + sb_add(m, "INCOMPLETE [%u bytes] )", 180 181 skb->len - ptr); 181 182 return; 182 183 } 183 184 184 185 /* Length: 16 "SPI=0xF1234567 )" */ 185 - printk("SPI=0x%x )", ntohl(eh->spi) ); 186 + sb_add(m, "SPI=0x%x )", ntohl(eh->spi) ); 186 187 187 188 } 188 189 return; 189 190 default: 190 191 /* Max length: 20 "Unknown Ext Hdr 255" */ 191 - printk("Unknown Ext Hdr %u", currenthdr); 192 + sb_add(m, "Unknown Ext Hdr %u", currenthdr); 192 193 return; 193 194 } 194 195 if (logflags & IP6T_LOG_IPOPT) 195 - printk(") "); 196 + sb_add(m, ") "); 196 197 197 198 currenthdr = hp->nexthdr; 198 199 ptr += hdrlen; ··· 204 205 const struct tcphdr *th; 205 206 206 207 /* Max length: 10 "PROTO=TCP " */ 207 - printk("PROTO=TCP "); 208 + sb_add(m, "PROTO=TCP "); 208 209 209 210 if (fragment) 210 211 break; ··· 212 213 /* Max length: 25 "INCOMPLETE [65535 bytes] " */ 213 214 th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); 214 215 if (th == NULL) { 215 - printk("INCOMPLETE [%u bytes] ", skb->len - ptr); 216 + sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); 216 217 return; 217 218 } 218 219 219 220 /* Max length: 20 "SPT=65535 DPT=65535 " */ 220 - printk("SPT=%u DPT=%u ", 221 + sb_add(m, "SPT=%u DPT=%u ", 221 222 ntohs(th->source), ntohs(th->dest)); 222 223 /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ 223 224 if (logflags & IP6T_LOG_TCPSEQ) 224 - printk("SEQ=%u ACK=%u ", 225 + sb_add(m, "SEQ=%u ACK=%u ", 225 226 ntohl(th->seq), ntohl(th->ack_seq)); 226 227 /* Max length: 13 "WINDOW=65535 " */ 227 - printk("WINDOW=%u ", ntohs(th->window)); 228 + sb_add(m, "WINDOW=%u ", ntohs(th->window)); 228 229 /* Max length: 9 "RES=0x3C " */ 229 - printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); 230 + sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); 230 231 /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ 231 232 if (th->cwr) 232 - printk("CWR "); 233 + sb_add(m, "CWR "); 233 234 if (th->ece) 234 - printk("ECE "); 235 + sb_add(m, "ECE "); 235 236 if (th->urg) 236 - printk("URG "); 237 + sb_add(m, "URG "); 237 238 if (th->ack) 238 - printk("ACK "); 239 + sb_add(m, "ACK "); 239 240 if (th->psh) 240 - printk("PSH "); 241 + sb_add(m, "PSH "); 241 242 if (th->rst) 242 - printk("RST "); 243 + sb_add(m, "RST "); 243 244 if (th->syn) 244 - printk("SYN "); 245 + sb_add(m, "SYN "); 245 246 if (th->fin) 246 - printk("FIN "); 247 + sb_add(m, "FIN "); 247 248 /* Max length: 11 "URGP=65535 " */ 248 - printk("URGP=%u ", ntohs(th->urg_ptr)); 249 + sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); 249 250 250 251 if ((logflags & IP6T_LOG_TCPOPT) && 251 252 th->doff * 4 > sizeof(struct tcphdr)) { ··· 259 260 ptr + sizeof(struct tcphdr), 260 261 optsize, _opt); 261 262 if (op == NULL) { 262 - printk("OPT (TRUNCATED)"); 263 + sb_add(m, "OPT (TRUNCATED)"); 263 264 return; 264 265 } 265 266 266 267 /* Max length: 127 "OPT (" 15*4*2chars ") " */ 267 - printk("OPT ("); 268 + sb_add(m, "OPT ("); 268 269 for (i =0; i < optsize; i++) 269 - printk("%02X", op[i]); 270 - printk(") "); 270 + sb_add(m, "%02X", op[i]); 271 + sb_add(m, ") "); 271 272 } 272 273 break; 273 274 } ··· 278 279 279 280 if (currenthdr == IPPROTO_UDP) 280 281 /* Max length: 10 "PROTO=UDP " */ 281 - printk("PROTO=UDP " ); 282 + sb_add(m, "PROTO=UDP " ); 282 283 else /* Max length: 14 "PROTO=UDPLITE " */ 283 - printk("PROTO=UDPLITE "); 284 + sb_add(m, "PROTO=UDPLITE "); 284 285 285 286 if (fragment) 286 287 break; ··· 288 289 /* Max length: 25 "INCOMPLETE [65535 bytes] " */ 289 290 uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); 290 291 if (uh == NULL) { 291 - printk("INCOMPLETE [%u bytes] ", skb->len - ptr); 292 + sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); 292 293 return; 293 294 } 294 295 295 296 /* Max length: 20 "SPT=65535 DPT=65535 " */ 296 - printk("SPT=%u DPT=%u LEN=%u ", 297 + sb_add(m, "SPT=%u DPT=%u LEN=%u ", 297 298 ntohs(uh->source), ntohs(uh->dest), 298 299 ntohs(uh->len)); 299 300 break; ··· 303 304 const struct icmp6hdr *ic; 304 305 305 306 /* Max length: 13 "PROTO=ICMPv6 " */ 306 - printk("PROTO=ICMPv6 "); 307 + sb_add(m, "PROTO=ICMPv6 "); 307 308 308 309 if (fragment) 309 310 break; ··· 311 312 /* Max length: 25 "INCOMPLETE [65535 bytes] " */ 312 313 ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); 313 314 if (ic == NULL) { 314 - printk("INCOMPLETE [%u bytes] ", skb->len - ptr); 315 + sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); 315 316 return; 316 317 } 317 318 318 319 /* Max length: 18 "TYPE=255 CODE=255 " */ 319 - printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); 320 + sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); 320 321 321 322 switch (ic->icmp6_type) { 322 323 case ICMPV6_ECHO_REQUEST: 323 324 case ICMPV6_ECHO_REPLY: 324 325 /* Max length: 19 "ID=65535 SEQ=65535 " */ 325 - printk("ID=%u SEQ=%u ", 326 + sb_add(m, "ID=%u SEQ=%u ", 326 327 ntohs(ic->icmp6_identifier), 327 328 ntohs(ic->icmp6_sequence)); 328 329 break; ··· 333 334 334 335 case ICMPV6_PARAMPROB: 335 336 /* Max length: 17 "POINTER=ffffffff " */ 336 - printk("POINTER=%08x ", ntohl(ic->icmp6_pointer)); 337 + sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer)); 337 338 /* Fall through */ 338 339 case ICMPV6_DEST_UNREACH: 339 340 case ICMPV6_PKT_TOOBIG: 340 341 case ICMPV6_TIME_EXCEED: 341 342 /* Max length: 3+maxlen */ 342 343 if (recurse) { 343 - printk("["); 344 - dump_packet(info, skb, ptr + sizeof(_icmp6h), 345 - 0); 346 - printk("] "); 344 + sb_add(m, "["); 345 + dump_packet(m, info, skb, 346 + ptr + sizeof(_icmp6h), 0); 347 + sb_add(m, "] "); 347 348 } 348 349 349 350 /* Max length: 10 "MTU=65535 " */ 350 351 if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) 351 - printk("MTU=%u ", ntohl(ic->icmp6_mtu)); 352 + sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu)); 352 353 } 353 354 break; 354 355 } 355 356 /* Max length: 10 "PROTO=255 " */ 356 357 default: 357 - printk("PROTO=%u ", currenthdr); 358 + sb_add(m, "PROTO=%u ", currenthdr); 358 359 } 359 360 360 361 /* Max length: 15 "UID=4294967295 " */ 361 362 if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { 362 363 read_lock_bh(&skb->sk->sk_callback_lock); 363 364 if (skb->sk->sk_socket && skb->sk->sk_socket->file) 364 - printk("UID=%u GID=%u ", 365 + sb_add(m, "UID=%u GID=%u ", 365 366 skb->sk->sk_socket->file->f_cred->fsuid, 366 367 skb->sk->sk_socket->file->f_cred->fsgid); 367 368 read_unlock_bh(&skb->sk->sk_callback_lock); ··· 369 370 370 371 /* Max length: 16 "MARK=0xFFFFFFFF " */ 371 372 if (!recurse && skb->mark) 372 - printk("MARK=0x%x ", skb->mark); 373 + sb_add(m, "MARK=0x%x ", skb->mark); 373 374 } 374 375 375 - static void dump_mac_header(const struct nf_loginfo *info, 376 + static void dump_mac_header(struct sbuff *m, 377 + const struct nf_loginfo *info, 376 378 const struct sk_buff *skb) 377 379 { 378 380 struct net_device *dev = skb->dev; ··· 387 387 388 388 switch (dev->type) { 389 389 case ARPHRD_ETHER: 390 - printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", 390 + sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", 391 391 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, 392 392 ntohs(eth_hdr(skb)->h_proto)); 393 393 return; ··· 396 396 } 397 397 398 398 fallback: 399 - printk("MAC="); 399 + sb_add(m, "MAC="); 400 400 if (dev->hard_header_len && 401 401 skb->mac_header != skb->network_header) { 402 402 const unsigned char *p = skb_mac_header(skb); ··· 408 408 p = NULL; 409 409 410 410 if (p != NULL) { 411 - printk("%02x", *p++); 411 + sb_add(m, "%02x", *p++); 412 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 417 if (dev->type == ARPHRD_SIT) { 418 418 const struct iphdr *iph = 419 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 422 } else 423 - printk(" "); 423 + sb_add(m, " "); 424 424 } 425 425 426 426 static struct nf_loginfo default_loginfo = { ··· 442 442 const struct nf_loginfo *loginfo, 443 443 const char *prefix) 444 444 { 445 + struct sbuff *m = sb_open(); 446 + 445 447 if (!loginfo) 446 448 loginfo = &default_loginfo; 447 449 448 - spin_lock_bh(&log_lock); 449 - printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, 450 - prefix, 451 - in ? in->name : "", 452 - out ? out->name : ""); 450 + sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, 451 + prefix, 452 + in ? in->name : "", 453 + out ? out->name : ""); 453 454 454 455 /* MAC logging for input path only. */ 455 456 if (in && !out) 456 - dump_mac_header(loginfo, skb); 457 + dump_mac_header(m, loginfo, skb); 457 458 458 - dump_packet(loginfo, skb, skb_network_offset(skb), 1); 459 - printk("\n"); 460 - spin_unlock_bh(&log_lock); 459 + dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); 460 + 461 + sb_close(m); 461 462 } 462 463 463 464 static unsigned int