import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / net / ipv6 / netfilter / ip6t_LOG.c
1 /*
2  * This is a module which is used for logging packets.
3  */
4 #include <linux/module.h>
5 #include <linux/skbuff.h>
6 #include <linux/ip.h>
7 #include <linux/spinlock.h>
8 #include <linux/icmpv6.h>
9 #include <net/udp.h>
10 #include <net/tcp.h>
11 #include <net/ipv6.h>
12 #include <linux/netfilter_ipv6/ip6_tables.h>
13
14 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
15 MODULE_DESCRIPTION("IP6 tables LOG target module");
16 MODULE_LICENSE("GPL");
17
18 struct in_device;
19 #include <net/route.h>
20 #include <linux/netfilter_ipv6/ip6t_LOG.h>
21
22 #if 0
23 #define DEBUGP printk
24 #else
25 #define DEBUGP(format, args...)
26 #endif
27
28 #define NIP6(addr) \
29         ntohs((addr).s6_addr16[0]), \
30         ntohs((addr).s6_addr16[1]), \
31         ntohs((addr).s6_addr16[2]), \
32         ntohs((addr).s6_addr16[3]), \
33         ntohs((addr).s6_addr16[4]), \
34         ntohs((addr).s6_addr16[5]), \
35         ntohs((addr).s6_addr16[6]), \
36         ntohs((addr).s6_addr16[7])
37
38 /* FIXME evil kludge */
39
40 struct ahhdr {
41         __u8  nexthdr;
42         __u8  hdrlen;
43         __u16 reserved;
44         __u32 spi;
45         __u32 seq_no;
46 };
47
48 struct esphdr {
49         __u32 spi;
50         __u32 seq_no;
51 };
52
53 /* Use lock to serialize, so printks don't overlap */
54 static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
55
56 /* One level of recursion won't kill us */
57 static void dump_packet(const struct ip6t_log_info *info,
58                         const struct sk_buff *skb, unsigned int ip6hoff,
59                         int recurse)
60 {
61         u_int8_t currenthdr;
62         int fragment;
63         struct ipv6hdr *ipv6h;
64         unsigned int ptr;
65         unsigned int hdrlen = 0;
66
67         if (skb->len - ip6hoff < sizeof(*ipv6h)) {
68                 printk("TRUNCATED");
69                 return;
70         }
71         ipv6h = (struct ipv6hdr *)(skb->data + ip6hoff);
72
73         /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */
74         printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->saddr));
75         printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
76
77         /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
78         printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
79                ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr),
80                (ntohl(*(u_int32_t *)ipv6h) & 0x0ff00000) >> 20,
81                ipv6h->hop_limit,
82                (ntohl(*(u_int32_t *)ipv6h) & 0x000fffff));
83
84         fragment = 0;
85         ptr = ip6hoff + sizeof(struct ipv6hdr);
86         currenthdr = ipv6h->nexthdr;
87         while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
88                 struct ipv6_opt_hdr *hdr;
89
90                 if (skb->len - ptr < sizeof(*hdr)) {
91                         printk("TRUNCATED");
92                         return;
93                 }
94                 hdr = (struct ipv6_opt_hdr *)(skb->data + ptr);
95
96                 /* Max length: 48 "OPT (...) " */
97                 if (info->logflags & IP6T_LOG_IPOPT)
98                         printk("OPT ( ");
99
100                 switch (currenthdr) {
101                 case IPPROTO_FRAGMENT: {
102                         struct frag_hdr *fhdr;
103
104                         printk("FRAG:");
105                         if (skb->len - ptr < sizeof(*fhdr)) {
106                                 printk("TRUNCATED ");
107                                 return;
108                         }
109                         fhdr = (struct frag_hdr *)(skb->data + ptr);
110
111                         /* Max length: 6 "65535 " */
112                         printk("%u ", ntohs(fhdr->frag_off) & 0xFFF8);
113
114                         /* Max length: 11 "INCOMPLETE " */
115                         if (fhdr->frag_off & htons(0x0001))
116                                 printk("INCOMPLETE ");
117
118                         printk("ID:%08x ", ntohl(fhdr->identification));
119
120                         if (ntohs(fhdr->frag_off) & 0xFFF8)
121                                 fragment = 1;
122
123                         hdrlen = 8;
124
125                         break;
126                 }
127                 case IPPROTO_DSTOPTS:
128                 case IPPROTO_ROUTING:
129                 case IPPROTO_HOPOPTS:
130                         if (fragment) {
131                                 if (info->logflags & IP6T_LOG_IPOPT)
132                                         printk(")");
133                                 return;
134                         }
135                         hdrlen = ipv6_optlen(hdr);
136                         break;
137                 /* Max Length */
138                 case IPPROTO_AH:
139                         if (info->logflags & IP6T_LOG_IPOPT) {
140                                 struct ahhdr *ah;
141
142                                 /* Max length: 3 "AH " */
143                                 printk("AH ");
144
145                                 if (fragment) {
146                                         printk(")");
147                                         return;
148                                 }
149
150                                 if (skb->len - ptr < sizeof(*ah)) {
151                                         /*
152                                          * Max length: 26 "INCOMPLETE [65535    
153                                          *  bytes] )"
154                                          */
155                                         printk("INCOMPLETE [%u bytes] )",
156                                                skb->len - ptr);
157                                         return;
158                                 }
159                                 ah = (struct ahhdr *)(skb->data + ptr);
160
161                                 /* Length: 15 "SPI=0xF1234567 */
162                                 printk("SPI=0x%x ", ntohl(ah->spi));
163
164                         }
165
166                         hdrlen = (hdr->hdrlen+2)<<2;
167                         break;
168                 case IPPROTO_ESP:
169                         if (info->logflags & IP6T_LOG_IPOPT) {
170                                 struct esphdr *esph;
171
172                                 /* Max length: 4 "ESP " */
173                                 printk("ESP ");
174
175                                 if (fragment) {
176                                         printk(")");
177                                         return;
178                                 }
179
180                                 /*
181                                  * Max length: 26 "INCOMPLETE [65535 bytes] )"
182                                  */
183                                 if (skb->len - ptr < sizeof(*esph)) {
184                                         printk("INCOMPLETE [%u bytes] )",
185                                                skb->len - ptr);
186                                         return;
187                                 }
188                                 esph = (struct esphdr *)(skb->data + ptr);
189
190                                 /* Length: 16 "SPI=0xF1234567 )" */
191                                 printk("SPI=0x%x )", ntohl(esph->spi) );
192
193                         }
194                         return;
195                 default:
196                         /* Max length: 20 "Unknown Ext Hdr 255" */
197                         printk("Unknown Ext Hdr %u", currenthdr);
198                         return;
199                 }
200                 if (info->logflags & IP6T_LOG_IPOPT)
201                         printk(") ");
202
203                 currenthdr = hdr->nexthdr;
204                 ptr += hdrlen;
205         }
206
207         switch (currenthdr) {
208         case IPPROTO_TCP: {
209                 struct tcphdr *tcph;
210
211                 /* Max length: 10 "PROTO=TCP " */
212                 printk("PROTO=TCP ");
213
214                 if (fragment)
215                         break;
216
217                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
218                 if (skb->len - ptr < sizeof(*tcph)) {
219                         printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
220                         return;
221                 }
222                 tcph = (struct tcphdr *)(skb->data + ptr);
223
224                 /* Max length: 20 "SPT=65535 DPT=65535 " */
225                 printk("SPT=%u DPT=%u ",
226                        ntohs(tcph->source), ntohs(tcph->dest));
227                 /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
228                 if (info->logflags & IP6T_LOG_TCPSEQ)
229                         printk("SEQ=%u ACK=%u ",
230                                ntohl(tcph->seq), ntohl(tcph->ack_seq));
231                 /* Max length: 13 "WINDOW=65535 " */
232                 printk("WINDOW=%u ", ntohs(tcph->window));
233                 /* Max length: 9 "RES=0x3C " */
234                 printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
235                 /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
236                 if (tcph->cwr)
237                         printk("CWR ");
238                 if (tcph->ece)
239                         printk("ECE ");
240                 if (tcph->urg)
241                         printk("URG ");
242                 if (tcph->ack)
243                         printk("ACK ");
244                 if (tcph->psh)
245                         printk("PSH ");
246                 if (tcph->rst)
247                         printk("RST ");
248                 if (tcph->syn)
249                         printk("SYN ");
250                 if (tcph->fin)
251                         printk("FIN ");
252                 /* Max length: 11 "URGP=65535 " */
253                 printk("URGP=%u ", ntohs(tcph->urg_ptr));
254
255                 if ((info->logflags & IP6T_LOG_TCPOPT)
256                     && tcph->doff * 4 > sizeof(struct tcphdr)) {
257                         u_int8_t *op;
258                         unsigned int i;
259                         unsigned int optsize = tcph->doff * 4
260                                                - sizeof(struct tcphdr);
261
262                         if (skb->len - ptr - sizeof(struct tcphdr) < optsize) {
263                                 printk("OPT (TRUNCATED)");
264                                 return;
265                         }
266                         op = (u_int8_t *)(skb->data + ptr
267                                           + sizeof(struct tcphdr));
268
269                         /* Max length: 127 "OPT (" 15*4*2chars ") " */
270                         printk("OPT (");
271                         for (i =0; i < optsize; i++)
272                                 printk("%02X", op[i]);
273                         printk(") ");
274                 }
275                 break;
276         }
277         case IPPROTO_UDP: {
278                 struct udphdr *udph;
279
280                 /* Max length: 10 "PROTO=UDP " */
281                 printk("PROTO=UDP ");
282
283                 if (fragment)
284                         break;
285
286                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
287                 if (skb->len - ptr < sizeof(*udph)) {
288                         printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
289                         return;
290                 }
291                 udph = (struct udphdr *)(skb->data + ptr);
292
293                 /* Max length: 20 "SPT=65535 DPT=65535 " */
294                 printk("SPT=%u DPT=%u LEN=%u ",
295                        ntohs(udph->source), ntohs(udph->dest),
296                        ntohs(udph->len));
297                 break;
298         }
299         case IPPROTO_ICMPV6: {
300                 struct icmp6hdr *icmp6h;
301
302                 /* Max length: 13 "PROTO=ICMPv6 " */
303                 printk("PROTO=ICMPv6 ");
304
305                 if (fragment)
306                         break;
307
308                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
309                 if (skb->len - ptr < sizeof(*icmp6h)) {
310                         printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
311                         return;
312                 }
313                 icmp6h = (struct icmp6hdr *)(skb->data + ptr);
314
315                 /* Max length: 18 "TYPE=255 CODE=255 " */
316                 printk("TYPE=%u CODE=%u ", icmp6h->icmp6_type, icmp6h->icmp6_code);
317
318                 switch (icmp6h->icmp6_type) {
319                 case ICMPV6_ECHO_REQUEST:
320                 case ICMPV6_ECHO_REPLY:
321                         /* Max length: 19 "ID=65535 SEQ=65535 " */
322                         printk("ID=%u SEQ=%u ",
323                                 ntohs(icmp6h->icmp6_identifier),
324                                 ntohs(icmp6h->icmp6_sequence));
325                         break;
326                 case ICMPV6_MGM_QUERY:
327                 case ICMPV6_MGM_REPORT:
328                 case ICMPV6_MGM_REDUCTION:
329                         break;
330
331                 case ICMPV6_PARAMPROB:
332                         /* Max length: 17 "POINTER=ffffffff " */
333                         printk("POINTER=%08x ", ntohl(icmp6h->icmp6_pointer));
334                         /* Fall through */
335                 case ICMPV6_DEST_UNREACH:
336                 case ICMPV6_PKT_TOOBIG:
337                 case ICMPV6_TIME_EXCEED:
338                         /* Max length: 3+maxlen */
339                         if (recurse) {
340                                 printk("[");
341                                 dump_packet(info, skb, ptr + sizeof(*icmp6h),
342                                             0);
343                                 printk("] ");
344                         }
345
346                         /* Max length: 10 "MTU=65535 " */
347                         if (icmp6h->icmp6_type == ICMPV6_PKT_TOOBIG)
348                                 printk("MTU=%u ", ntohl(icmp6h->icmp6_mtu));
349                 }
350                 break;
351         }
352         /* Max length: 10 "PROTO=255 " */
353         default:
354                 printk("PROTO=%u ", currenthdr);
355         }
356 }
357
358 static unsigned int
359 ip6t_log_target(struct sk_buff **pskb,
360                 unsigned int hooknum,
361                 const struct net_device *in,
362                 const struct net_device *out,
363                 const void *targinfo,
364                 void *userinfo)
365 {
366         const struct ip6t_log_info *loginfo = targinfo;
367         char level_string[4] = "< >";
368
369         level_string[1] = '0' + (loginfo->level % 8);
370         spin_lock_bh(&log_lock);
371         printk(level_string);
372         printk("%sIN=%s OUT=%s ",
373                 loginfo->prefix,
374                 in ? in->name : "",
375                 out ? out->name : "");
376         if (in && !out) {
377                 unsigned int len;
378                 /* MAC logging for input chain only. */
379                 printk("MAC=");
380                 if ((*pskb)->dev && (len = (*pskb)->dev->hard_header_len) &&
381                     (*pskb)->mac.raw != (*pskb)->nh.raw) {
382                         unsigned char *p = (*pskb)->mac.raw;
383                         int i;
384
385                         if ((*pskb)->dev->type == ARPHRD_SIT &&
386                             (p -= ETH_HLEN) < (*pskb)->head)
387                                 p = NULL;
388
389                         if (p != NULL) {
390                                 for (i = 0; i < len; i++)
391                                         printk("%02x%s", p[i],
392                                                i == len - 1 ? "" : ":");
393                         }
394                         printk(" ");
395
396                         if ((*pskb)->dev->type == ARPHRD_SIT) {
397                                 struct iphdr *iph;
398                                 
399                                 iph = (struct iphdr *)(*pskb)->mac.raw;
400                                 printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ",
401                                        NIPQUAD(iph->saddr),
402                                        NIPQUAD(iph->daddr));
403                         }
404                 } else
405                         printk(" ");
406         }
407
408         dump_packet(loginfo, (*pskb), (u8*)(*pskb)->nh.ipv6h - (*pskb)->data,
409                     1);
410         printk("\n");
411         spin_unlock_bh(&log_lock);
412
413         return IP6T_CONTINUE;
414 }
415
416 static int ip6t_log_checkentry(const char *tablename,
417                                const struct ip6t_entry *e,
418                                void *targinfo,
419                                unsigned int targinfosize,
420                                unsigned int hook_mask)
421 {
422         const struct ip6t_log_info *loginfo = targinfo;
423
424         if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_log_info))) {
425                 DEBUGP("LOG: targinfosize %u != %u\n",
426                        targinfosize, IP6T_ALIGN(sizeof(struct ip6t_log_info)));
427                 return 0;
428         }
429
430         if (loginfo->level >= 8) {
431                 DEBUGP("LOG: level %u >= 8\n", loginfo->level);
432                 return 0;
433         }
434
435         if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
436                 DEBUGP("LOG: prefix term %i\n",
437                        loginfo->prefix[sizeof(loginfo->prefix)-1]);
438                 return 0;
439         }
440
441         return 1;
442 }
443
444 static struct ip6t_target ip6t_log_reg
445 = { { NULL, NULL }, "LOG", ip6t_log_target, ip6t_log_checkentry, NULL, 
446     THIS_MODULE };
447
448 static int __init init(void)
449 {
450         if (ip6t_register_target(&ip6t_log_reg))
451                 return -EINVAL;
452
453         return 0;
454 }
455
456 static void __exit fini(void)
457 {
458         ip6t_unregister_target(&ip6t_log_reg);
459 }
460
461 module_init(init);
462 module_exit(fini);