ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / net / ipv4 / netfilter / ipfwadm_core.c
1 /* Minor modifications to fit on compatibility framework:
2    Rusty.Russell@rustcorp.com.au
3 */
4
5 #include <linux/config.h>
6 #define CONFIG_IP_FIREWALL
7 #define CONFIG_IP_FIREWALL_VERBOSE
8 #define CONFIG_IP_MASQUERADE
9 #define CONFIG_IP_ACCT
10 #define CONFIG_IP_TRANSPARENT_PROXY
11 #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
12 #define CONFIG_IP_FIREWALL_NETLINK
13 #endif
14
15 /*
16  *      IP firewalling code. This is taken from 4.4BSD. Please note the
17  *      copyright message below. As per the GPL it must be maintained
18  *      and the licenses thus do not conflict. While this port is subject
19  *      to the GPL I also place my modifications under the original
20  *      license in recognition of the original copyright.
21  *                              -- Alan Cox.
22  *
23  *      $Id: ipfwadm_core.c,v 1.11 2002/01/24 15:50:31 davem Exp $
24  *
25  *      Ported from BSD to Linux,
26  *              Alan Cox 22/Nov/1994.
27  *      Zeroing /proc and other additions
28  *              Jos Vos 4/Feb/1995.
29  *      Merged and included the FreeBSD-Current changes at Ugen's request
30  *      (but hey it's a lot cleaner now). Ugen would prefer in some ways
31  *      we waited for his final product but since Linux 1.2.0 is about to
32  *      appear it's not practical - Read: It works, it's not clean but please
33  *      don't consider it to be his standard of finished work.
34  *              Alan Cox 12/Feb/1995
35  *      Porting bidirectional entries from BSD, fixing accounting issues,
36  *      adding struct ip_fwpkt for checking packets with interface address
37  *              Jos Vos 5/Mar/1995.
38  *      Established connections (ACK check), ACK check on bidirectional rules,
39  *      ICMP type check.
40  *              Wilfred Mollenvanger 7/7/1995.
41  *      TCP attack protection.
42  *              Alan Cox 25/8/95, based on information from bugtraq.
43  *      ICMP type printk, IP_FW_F_APPEND
44  *              Bernd Eckenfels 1996-01-31
45  *      Split blocking chain into input and output chains, add new "insert" and
46  *      "append" commands to replace semi-intelligent "add" command, let "delete".
47  *      only delete the first matching entry, use 0xFFFF (0xFF) as ports (ICMP
48  *      types) when counting packets being 2nd and further fragments.
49  *              Jos Vos <jos@xos.nl> 8/2/1996.
50  *      Add support for matching on device names.
51  *              Jos Vos <jos@xos.nl> 15/2/1996.
52  *      Transparent proxying support.
53  *              Willy Konynenberg <willy@xos.nl> 10/5/96.
54  *      Make separate accounting on incoming and outgoing packets possible.
55  *              Jos Vos <jos@xos.nl> 18/5/1996.
56  *      Added trap out of bad frames.
57  *              Alan Cox <alan@cymru.net> 17/11/1996
58  *
59  *
60  * Masquerading functionality
61  *
62  * Copyright (c) 1994 Pauline Middelink
63  *
64  * The pieces which added masquerading functionality are totally
65  * my responsibility and have nothing to with the original authors
66  * copyright or doing.
67  *
68  * Parts distributed under GPL.
69  *
70  * Fixes:
71  *      Pauline Middelink       :       Added masquerading.
72  *      Alan Cox                :       Fixed an error in the merge.
73  *      Thomas Quinot           :       Fixed port spoofing.
74  *      Alan Cox                :       Cleaned up retransmits in spoofing.
75  *      Alan Cox                :       Cleaned up length setting.
76  *      Wouter Gadeyne          :       Fixed masquerading support of ftp PORT commands
77  *
78  *      Juan Jose Ciarlante     :       Masquerading code moved to ip_masq.c
79  *      Andi Kleen :            Print frag_offsets and the ip flags properly.
80  *
81  *      All the real work was done by .....
82  *
83  */
84
85
86 /*
87  * Copyright (c) 1993 Daniel Boulet
88  * Copyright (c) 1994 Ugen J.S.Antsilevich
89  *
90  * Redistribution and use in source forms, with and without modification,
91  * are permitted provided that this entire comment appears intact.
92  *
93  * Redistribution in binary form may occur without any restrictions.
94  * Obviously, it would be nice if you gave credit where credit is due
95  * but requiring it would be too onerous.
96  *
97  * This software is provided ``AS IS'' without any warranties of any kind.
98  */
99
100 #include <asm/uaccess.h>
101 #include <asm/system.h>
102 #include <linux/types.h>
103 #include <linux/kernel.h>
104 #include <linux/sched.h>
105 #include <linux/string.h>
106 #include <linux/errno.h>
107 #include <linux/module.h>
108
109 #include <linux/socket.h>
110 #include <linux/sockios.h>
111 #include <linux/in.h>
112 #include <linux/inet.h>
113 #include <linux/netdevice.h>
114 #include <linux/icmp.h>
115 #include <linux/udp.h>
116 #include <net/ip.h>
117 #include <net/protocol.h>
118 #include <net/route.h>
119 #include <net/tcp.h>
120 #include <net/udp.h>
121 #include <net/sock.h>
122 #include <net/icmp.h>
123 #include <linux/netlink.h>
124 #include <linux/init.h>
125 #include <linux/spinlock.h>
126 #include <linux/netfilter_ipv4/ipfwadm_core.h>
127 #include <linux/netfilter_ipv4/compat_firewall.h>
128 #include <linux/netfilter_ipv4/lockhelp.h>
129 #include <linux/netfilter_ipv4/ip_nat_core.h>
130
131 #include <net/checksum.h>
132 #include <linux/proc_fs.h>
133 #include <linux/stat.h>
134
135 MODULE_LICENSE("Dual BSD/GPL");
136 MODULE_DESCRIPTION("ipfwadm backwards compatibility layer");
137
138 /*
139  *      Implement IP packet firewall
140  */
141
142 #ifdef DEBUG_IP_FIREWALL
143 #define dprintf1(a)             printk(a)
144 #define dprintf2(a1,a2)         printk(a1,a2)
145 #define dprintf3(a1,a2,a3)      printk(a1,a2,a3)
146 #define dprintf4(a1,a2,a3,a4)   printk(a1,a2,a3,a4)
147 #else
148 #define dprintf1(a)
149 #define dprintf2(a1,a2)
150 #define dprintf3(a1,a2,a3)
151 #define dprintf4(a1,a2,a3,a4)
152 #endif
153
154 #define print_ip(a)      printk("%u.%u.%u.%u", NIPQUAD(a));
155
156 #ifdef DEBUG_IP_FIREWALL
157 #define dprint_ip(a)    print_ip(a)
158 #else
159 #define dprint_ip(a)
160 #endif
161
162 static DECLARE_RWLOCK(ip_fw_lock);
163
164 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
165
166 struct ip_fw *ip_fw_fwd_chain;
167 struct ip_fw *ip_fw_in_chain;
168 struct ip_fw *ip_fw_out_chain;
169 struct ip_fw *ip_acct_chain;
170 struct ip_fw *ip_masq_chain;
171
172 static struct ip_fw **chains[] =
173         {&ip_fw_fwd_chain, &ip_fw_in_chain, &ip_fw_out_chain, &ip_acct_chain,
174          &ip_masq_chain
175         };
176 #endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
177
178 #ifdef CONFIG_IP_FIREWALL
179 int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
180 int ip_fw_in_policy=IP_FW_F_ACCEPT;
181 int ip_fw_out_policy=IP_FW_F_ACCEPT;
182
183 static int *policies[] =
184         {&ip_fw_fwd_policy, &ip_fw_in_policy, &ip_fw_out_policy};
185
186 #endif
187
188 #ifdef CONFIG_IP_FIREWALL_NETLINK
189 struct sock *ipfwsk;
190 #endif
191
192 /*
193  *      Returns 1 if the port is matched by the vector, 0 otherwise
194  */
195
196 extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
197 {
198         if (!nports)
199                 return 1;
200         if ( range_flag )
201         {
202                 if ( portptr[0] <= port && port <= portptr[1] )
203                 {
204                         return( 1 );
205                 }
206                 nports -= 2;
207                 portptr += 2;
208         }
209         while ( nports-- > 0 )
210         {
211                 if ( *portptr++ == port )
212                 {
213                         return( 1 );
214                 }
215         }
216         return(0);
217 }
218
219 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
220
221 #ifdef CONFIG_IP_FIREWALL_VERBOSE
222
223 /*
224  *      VERY ugly piece of code which actually makes kernel printf for
225  *      matching packets.
226  */
227
228 static char *chain_name(struct ip_fw *chain, int mode)
229 {
230         switch (mode) {
231         case IP_FW_MODE_ACCT_IN: return "acct in";
232         case IP_FW_MODE_ACCT_OUT: return "acct out";
233         default:
234                 if (chain == ip_fw_fwd_chain)
235                         return "fw-fwd";
236                 else if (chain == ip_fw_in_chain)
237                         return "fw-in";
238                 else
239                         return "fw-out";
240         }
241 }
242
243 static char *rule_name(struct ip_fw *f, int mode, char *buf)
244 {
245         if (mode == IP_FW_MODE_ACCT_IN || mode == IP_FW_MODE_ACCT_OUT)
246                 return "";
247
248         if(f->fw_flg&IP_FW_F_ACCEPT) {
249                 if(f->fw_flg&IP_FW_F_REDIR) {
250                         sprintf(buf, "acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
251                         return buf;
252                 } else if(f->fw_flg&IP_FW_F_MASQ)
253                         return "acc/masq ";
254                 else
255                         return "acc ";
256         } else if(f->fw_flg&IP_FW_F_ICMPRPL) {
257                 return "rej ";
258         } else {
259                 return "deny ";
260         }
261 }
262
263 static void print_packet(struct sk_buff **pskb,
264                          u16 src_port, u16 dst_port, u16 icmp_type,
265                          char *chain, char *rule, char *devname)
266 {
267         __u32 *opt = (__u32 *) ((*pskb)->nh.iph + 1);
268         int opti;
269         __u16 foff = ntohs((*pskb)->nh.iph->frag_off);
270         int protocol = (*pskb)->nh.iph->protocol;
271
272         printk(KERN_INFO "IP %s %s%s", chain, rule, devname);
273
274         switch (protocol) {
275         case IPPROTO_TCP:
276                 printk(" TCP ");
277                 break;
278         case IPPROTO_UDP:
279                 printk(" UDP ");
280                 break;
281         case IPPROTO_ICMP:
282                 printk(" ICMP/%d ", icmp_type);
283                 break;
284         default:
285                 printk(" PROTO=%d ", protocol);
286                 break;
287         };
288
289         print_ip((*pskb)->nh.iph->saddr);
290         if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
291                 printk(":%hu", src_port);
292         printk(" ");
293         print_ip((*pskb)->nh.iph->daddr);
294         if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
295                 printk(":%hu", dst_port);
296         printk(" L=%hu S=0x%2.2hX I=%hu FO=0x%4.4hX T=%hu",
297                ntohs((*pskb)->nh.iph->tot_len),
298                (*pskb)->nh.iph->tos,
299                ntohs((*pskb)->nh.iph->id),
300                foff & IP_OFFSET,
301                (*pskb)->nh.iph->ttl);
302         if (foff & IP_DF)
303                 printk(" DF=1");
304         if (foff & IP_MF)
305                 printk(" MF=1");
306         for (opti = 0; opti < ((*pskb)->nh.iph->ihl - sizeof(struct iphdr) / 4); opti++)
307                 printk(" O=0x%8.8X", *opt++);
308         printk("\n");
309 }
310 #endif
311
312 /*
313  *      Returns one of the generic firewall policies, like FW_ACCEPT.
314  *      Also does accounting so you can feed it the accounting chain.
315  *
316  *      The modes is either IP_FW_MODE_FW (normal firewall mode),
317  *      IP_FW_MODE_ACCT_IN or IP_FW_MODE_ACCT_OUT (accounting mode,
318  *      steps through the entire chain and handles fragments
319  *      differently), or IP_FW_MODE_CHK (handles user-level check,
320  *      counters are not updated).
321  */
322
323
324 int ip_fw_chk(struct sk_buff **pskb,
325               struct net_device *rif, __u16 *redirport,
326               struct ip_fw *chain, int policy, int mode)
327 {
328         struct ip_fw *f;
329         __u32                   src, dst;
330         __u16                   src_port=0xFFFF, dst_port=0xFFFF, icmp_type=0xFF;
331         unsigned short          f_prt=0, prt;
332         char                    notcpsyn=0, notcpack=0, match;
333         unsigned short          offset;
334         int                     answer;
335         unsigned char           tosand, tosxor;
336         int                     protocol;
337
338         /*
339          *      If the chain is empty follow policy. The BSD one
340          *      accepts anything giving you a time window while
341          *      flushing and rebuilding the tables.
342          */
343
344         /*
345          *      This way we handle fragmented packets.
346          *      we ignore all fragments but the first one
347          *      so the whole packet can't be reassembled.
348          *      This way we relay on the full info which
349          *      stored only in first packet.
350          *
351          *      Note that this theoretically allows partial packet
352          *      spoofing. Not very dangerous but paranoid people may
353          *      wish to play with this. It also allows the so called
354          *      "fragment bomb" denial of service attack on some types
355          *      of system.
356          */
357
358         offset = ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET;
359         protocol = (*pskb)->nh.iph->protocol;
360
361         /*
362          *      Don't allow a fragment of TCP 8 bytes in. Nobody
363          *      normal causes this. Its a cracker trying to break
364          *      in by doing a flag overwrite to pass the direction
365          *      checks.
366          */
367
368         if (offset == 1 && protocol == IPPROTO_TCP)
369                 return FW_BLOCK;
370
371         if (offset!=0 && !(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)) &&
372                 (protocol == IPPROTO_TCP ||
373                  protocol == IPPROTO_UDP ||
374                  protocol == IPPROTO_ICMP))
375                 return FW_ACCEPT;
376
377         /*
378          *       Header fragment for TCP is too small to check the bits.
379          */
380
381         if (protocol == IPPROTO_TCP &&
382             ((*pskb)->nh.iph->ihl<<2)+16 > ntohs((*pskb)->nh.iph->tot_len))
383                 return FW_BLOCK;
384
385         /*
386          *      Too short.
387          *
388          *      But only too short for a packet with ports...
389          */
390
391         else if ((ntohs((*pskb)->nh.iph->tot_len) <
392                   8 + ((*pskb)->nh.iph->ihl << 2)) &&
393                  (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP))
394                 return FW_BLOCK;
395
396         src = (*pskb)->nh.iph->saddr;
397         dst = (*pskb)->nh.iph->daddr;
398
399         /*
400          *      If we got interface from which packet came
401          *      we can use the address directly. This is unlike
402          *      4.4BSD derived systems that have an address chain
403          *      per device. We have a device per address with dummy
404          *      devices instead.
405          */
406
407         dprintf1("Packet ");
408         switch (protocol) {
409                 case IPPROTO_TCP:
410                         dprintf1("TCP ");
411                         /* ports stay 0xFFFF if it is not the first fragment */
412                         if (!offset) {
413                                 struct tcphdr tcph;
414
415                                 if (skb_copy_bits(*pskb,
416                                                   (*pskb)->nh.iph->ihl * 4,
417                                                   &tcph, sizeof(tcph)))
418                                         return FW_BLOCK;
419
420                                 src_port = ntohs(tcph.source);
421                                 dst_port = ntohs(tcph.dest);
422
423                                 if(!tcph.ack && !tcph.rst)
424                                         /* We do NOT have ACK, value TRUE */
425                                         notcpack = 1;
426                                 if(!tcph.syn || !notcpack)
427                                         /* We do NOT have SYN, value TRUE */
428                                         notcpsyn = 1;
429                         }
430                         prt = IP_FW_F_TCP;
431                         break;
432                 case IPPROTO_UDP:
433                         dprintf1("UDP ");
434                         /* ports stay 0xFFFF if it is not the first fragment */
435                         if (!offset) {
436                                 struct udphdr udph;
437
438                                 if (skb_copy_bits(*pskb,
439                                                   (*pskb)->nh.iph->ihl * 4,
440                                                   &udph, sizeof(udph)))
441                                         return FW_BLOCK;
442
443                                 src_port = ntohs(udph.source);
444                                 dst_port = ntohs(udph.dest);
445                         }
446                         prt = IP_FW_F_UDP;
447                         break;
448                 case IPPROTO_ICMP:
449                         /* icmp_type stays 255 if it is not the first fragment */
450                         if (!offset) {
451                                 struct icmphdr icmph;
452
453                                 if (skb_copy_bits(*pskb,
454                                                   (*pskb)->nh.iph->ihl * 4,
455                                                   &icmph, sizeof(icmph)))
456                                         return FW_BLOCK;
457
458                                 icmp_type = (__u16) icmph.type;
459                         }
460                         dprintf2("ICMP:%d ", icmp_type);
461                         prt = IP_FW_F_ICMP;
462                         break;
463                 default:
464                         dprintf2("p=%d ", protocol);
465                         prt = IP_FW_F_ALL;
466                         break;
467         }
468 #ifdef DEBUG_IP_FIREWALL
469         dprint_ip(src);
470
471         if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
472                 /* This will print 65535 when it is not the first fragment! */
473                 dprintf2(":%d ", src_port);
474         dprint_ip(dst);
475         if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
476                 /* This will print 65535 when it is not the first fragment! */
477                 dprintf2(":%d ", dst_port);
478         dprintf1("\n");
479 #endif
480
481         if (mode == IP_FW_MODE_CHK)
482                 READ_LOCK(&ip_fw_lock);
483         else
484                 WRITE_LOCK(&ip_fw_lock);
485         
486         for (f = chain; f; f = f->fw_next) {
487                 /*
488                  *      This is a bit simpler as we don't have to walk
489                  *      an interface chain as you do in BSD - same logic
490                  *      however.
491                  */
492
493                 /*
494                  *      Match can become 0x01 (a "normal" match was found),
495                  *      0x02 (a reverse match was found), and 0x03 (the
496                  *      IP addresses match in both directions).
497                  *      Now we know in which direction(s) we should look
498                  *      for a match for the TCP/UDP ports.  Both directions
499                  *      might match (e.g., when both addresses are on the
500                  *      same network for which an address/mask is given), but
501                  *      the ports might only match in one direction.
502                  *      This was obviously wrong in the original BSD code.
503                  */
504                 match = 0x00;
505
506                 if ((src & f->fw_smsk.s_addr) == f->fw_src.s_addr &&
507                     (dst & f->fw_dmsk.s_addr) == f->fw_dst.s_addr)
508                         /* normal direction */
509                         match |= 0x01;
510
511                 if ((f->fw_flg & IP_FW_F_BIDIR) &&
512                     (dst & f->fw_smsk.s_addr) == f->fw_src.s_addr &&
513                     (src & f->fw_dmsk.s_addr) == f->fw_dst.s_addr)
514                         /* reverse direction */
515                         match |= 0x02;
516
517                 if (!match)
518                         continue;
519
520                 /*
521                  *      Look for a VIA device match
522                  */
523                 if (f->fw_viadev) {
524                         if (rif != f->fw_viadev)
525                                 continue;       /* Mismatch */
526                 }
527
528                 /* This looks stupid, because we scan almost static
529                    list, searching for static key. However, this way seems
530                    to be only reasonable way of handling fw_via rules
531                    (btw bsd makes the same thing).
532
533                    It will not affect performance if you will follow
534                    the following simple rules:
535
536                    - if interface is aliased, ALWAYS specify fw_viadev,
537                      so that previous check will guarantee, that we will
538                      not waste time when packet arrive on another interface.
539
540                    - avoid using fw_via.s_addr if fw_via.s_addr is owned
541                      by an aliased interface.
542
543                                                                        --ANK
544                  */
545                 if (f->fw_via.s_addr && rif) {
546                         struct in_ifaddr *ifa;
547
548                         if (rif->ip_ptr == NULL)
549                                 continue;       /* Mismatch */
550
551                         for (ifa = ((struct in_device*)(rif->ip_ptr))->ifa_list;
552                              ifa; ifa = ifa->ifa_next) {
553                                 if (ifa->ifa_local == f->fw_via.s_addr)
554                                         goto ifa_ok;
555                         }
556                         continue;       /* Mismatch */
557
558                 ifa_ok:;
559                 }
560
561                 /*
562                  *      Ok the chain addresses match.
563                  */
564
565 #ifdef CONFIG_IP_ACCT
566                 /*
567                  *      See if we're in accounting mode and only want to
568                  *      count incoming or outgoing packets.
569                  */
570
571                 if (mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT) &&
572                    ((mode == IP_FW_MODE_ACCT_IN && f->fw_flg&IP_FW_F_ACCTOUT) ||
573                     (mode == IP_FW_MODE_ACCT_OUT && f->fw_flg&IP_FW_F_ACCTIN)))
574                         continue;
575
576 #endif
577                 /*
578                  * For all non-TCP packets and/or non-first fragments,
579                  * notcpsyn and notcpack will always be FALSE,
580                  * so the IP_FW_F_TCPSYN and IP_FW_F_TCPACK flags
581                  * are actually ignored for these packets.
582                  */
583
584                 if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
585                         continue;
586
587                 if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
588                         continue;
589
590                 f_prt=f->fw_flg&IP_FW_F_KIND;
591                 if (f_prt != IP_FW_F_ALL) {
592                         /*
593                          *      Specific firewall - packet's protocol
594                          *      must match firewall's.
595                          */
596
597                         if (prt != f_prt)
598                                 continue;
599
600                         if((prt==IP_FW_F_ICMP &&
601                                 ! port_match(&f->fw_pts[0], f->fw_nsp,
602                                         icmp_type,f->fw_flg&IP_FW_F_SRNG)) ||
603                             !(prt==IP_FW_F_ICMP || ((match & 0x01) &&
604                                 port_match(&f->fw_pts[0], f->fw_nsp, src_port,
605                                         f->fw_flg&IP_FW_F_SRNG) &&
606                                 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
607                                         f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
608                                 port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
609                                         f->fw_flg&IP_FW_F_SRNG) &&
610                                 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
611                                         f->fw_flg&IP_FW_F_DRNG))))
612                         {
613                                 continue;
614                         }
615                 }
616
617 #ifdef CONFIG_IP_FIREWALL_VERBOSE
618                 if (f->fw_flg & IP_FW_F_PRN)
619                 {
620                         char buf[16];
621
622                         print_packet(pskb, src_port, dst_port, icmp_type,
623                                      chain_name(chain, mode),
624                                      rule_name(f, mode, buf),
625                                      rif ? rif->name : "-");
626                 }
627 #endif
628                 if (mode != IP_FW_MODE_CHK) {
629                         f->fw_bcnt += ntohs((*pskb)->nh.iph->tot_len);
630                         f->fw_pcnt++;
631                 }
632                 if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)))
633                         break;
634         } /* Loop */
635
636         if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) {
637
638                 /*
639                  * We rely on policy defined in the rejecting entry or, if no match
640                  * was found, we rely on the general policy variable for this type
641                  * of firewall.
642                  */
643
644                 if (f != NULL) {
645                         policy = f->fw_flg;
646                         tosand = f->fw_tosand;
647                         tosxor = f->fw_tosxor;
648                 } else {
649                         tosand = 0xFF;
650                         tosxor = 0x00;
651                 }
652
653                 if (policy & IP_FW_F_ACCEPT) {
654                         /* Adjust priority and recompute checksum */
655                         __u8 tos = (*pskb)->nh.iph->tos;
656
657                         if (((tos & tosand) ^ tosxor) != tos) {
658                                 if (!skb_ip_make_writable(pskb,
659                                           offsetof(struct iphdr, tos)+1))
660                                         goto drop_it;
661
662                                 (*pskb)->nh.iph->tos = (tos & tosand) ^ tosxor;
663                                 ip_send_check((*pskb)->nh.iph);
664                         }
665
666 #ifdef CONFIG_IP_TRANSPARENT_PROXY
667                         if (policy & IP_FW_F_REDIR) {
668                                 if (redirport)
669                                         if ((*redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp])) == 0) {
670                                                 /* Wildcard redirection.
671                                                  * Note that redirport will become
672                                                  * 0xFFFF for non-TCP/UDP packets.
673                                                  */
674                                                 *redirport = htons(dst_port);
675                                         }
676                                 answer = FW_REDIRECT;
677                         } else
678 #endif
679 #ifdef CONFIG_IP_MASQUERADE
680                         if (policy & IP_FW_F_MASQ)
681                                 answer = FW_MASQUERADE;
682                         else
683 #endif
684                                 answer = FW_ACCEPT;
685
686                 } else if (policy & IP_FW_F_ICMPRPL)
687                         answer = FW_REJECT;
688                 else {
689                 drop_it:
690                         answer = FW_BLOCK;
691                 }
692
693 #ifdef CONFIG_IP_FIREWALL_NETLINK
694                 if ((policy & IP_FW_F_PRN) && (answer == FW_REJECT || answer == FW_BLOCK))
695                 {
696                         struct sk_buff *skb = alloc_skb(128,
697                                         (mode == IP_FW_MODE_CHK) ?
698                                         GFP_KERNEL : GFP_ATOMIC);
699                         if (skb) {
700                                 int len = min_t(unsigned int,
701                                         128,
702                                         ntohs((*pskb)->nh.iph->tot_len));
703
704                                 skb_put(skb, len);
705                                 skb_copy_bits(*pskb,
706                                         ((char *)(*pskb)->nh.iph -
707                                          (char *)(*pskb)->data),
708                                         skb->data, len);
709                                 if (netlink_post(NETLINK_FIREWALL, skb))
710                                         kfree_skb(skb);
711                         }
712                 }
713 #endif
714         } else
715                 /* we're doing accounting, always ok */
716                 answer = 0;
717         
718         if (mode == IP_FW_MODE_CHK)
719                 READ_UNLOCK(&ip_fw_lock);
720         else
721                 WRITE_UNLOCK(&ip_fw_lock);
722
723         return answer;
724 }
725
726
727 static void zero_fw_chain(struct ip_fw *chainptr)
728 {
729         struct ip_fw *ctmp=chainptr;
730         
731         WRITE_LOCK(&ip_fw_lock);
732         while(ctmp)
733         {
734                 ctmp->fw_pcnt=0L;
735                 ctmp->fw_bcnt=0L;
736                 ctmp=ctmp->fw_next;
737         }
738         WRITE_UNLOCK(&ip_fw_lock);
739 }
740
741 static void free_fw_chain(struct ip_fw *volatile* chainptr)
742 {
743         WRITE_LOCK(&ip_fw_lock);
744         while ( *chainptr != NULL )
745         {
746                 struct ip_fw *ftmp;
747                 ftmp = *chainptr;
748                 *chainptr = ftmp->fw_next;
749                 if (ftmp->fw_viadev
750                     && ftmp->fw_viadev != (struct net_device *)-1)
751                         dev_put(ftmp->fw_viadev);
752                 kfree(ftmp);
753                 /* We will block in cleanup's unregister sockopt if unloaded,
754                    so this is safe. */
755                 module_put(THIS_MODULE);
756         }
757         WRITE_UNLOCK(&ip_fw_lock);
758 }
759
760 /* Volatiles to keep some of the compiler versions amused */
761
762 static int insert_in_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
763 {
764         struct ip_fw *ftmp;
765
766         /* Are we unloading now?  We will block on nf_unregister_sockopt */
767         if (!try_module_get(THIS_MODULE))
768                 return ENOPROTOOPT;
769
770         ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL );
771         if ( ftmp == NULL )
772         {
773 #ifdef DEBUG_IP_FIREWALL
774                 printk("ip_fw_ctl:  malloc said no\n");
775 #endif
776                 return( ENOMEM );
777         }
778
779         memcpy(ftmp, frwl, len);
780         /*
781          *      Allow the more recent "minimise cost" flag to be
782          *      set. [Rob van Nieuwkerk]
783          */
784         ftmp->fw_tosand |= 0x01;
785         ftmp->fw_tosxor &= 0xFE;
786         ftmp->fw_pcnt=0L;
787         ftmp->fw_bcnt=0L;
788
789         WRITE_LOCK(&ip_fw_lock);
790
791         if ((ftmp->fw_vianame)[0]) {
792                 if (!(ftmp->fw_viadev = dev_get_by_name(ftmp->fw_vianame)))
793                         ftmp->fw_viadev = (struct net_device *) -1;
794         } else
795                 ftmp->fw_viadev = NULL;
796
797         ftmp->fw_next = *chainptr;
798         *chainptr=ftmp;
799         WRITE_UNLOCK(&ip_fw_lock);
800         return(0);
801 }
802
803 static int append_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
804 {
805         struct ip_fw *ftmp;
806         struct ip_fw *chtmp=NULL;
807         struct ip_fw *volatile chtmp_prev=NULL;
808
809         /* Are we unloading now?  We will block on nf_unregister_sockopt */
810         if (!try_module_get(THIS_MODULE))
811                 return ENOPROTOOPT;
812
813         ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL );
814         if ( ftmp == NULL )
815         {
816 #ifdef DEBUG_IP_FIREWALL
817                 printk("ip_fw_ctl:  malloc said no\n");
818 #endif
819                 return( ENOMEM );
820         }
821
822         memcpy(ftmp, frwl, len);
823         /*
824          *      Allow the more recent "minimise cost" flag to be
825          *      set. [Rob van Nieuwkerk]
826          */
827         ftmp->fw_tosand |= 0x01;
828         ftmp->fw_tosxor &= 0xFE;
829         ftmp->fw_pcnt=0L;
830         ftmp->fw_bcnt=0L;
831
832         ftmp->fw_next = NULL;
833
834         WRITE_LOCK(&ip_fw_lock);
835
836         if ((ftmp->fw_vianame)[0]) {
837                 if (!(ftmp->fw_viadev = dev_get_by_name(ftmp->fw_vianame)))
838                         ftmp->fw_viadev = (struct net_device *) -1;
839         } else
840                 ftmp->fw_viadev = NULL;
841
842         chtmp_prev=NULL;
843         for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
844                 chtmp_prev=chtmp;
845
846         if (chtmp_prev)
847                 chtmp_prev->fw_next=ftmp;
848         else
849                 *chainptr=ftmp;
850         WRITE_UNLOCK(&ip_fw_lock);
851         return(0);
852 }
853
854 static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
855 {
856         struct ip_fw    *ftmp,*ltmp;
857         unsigned short  tport1,tport2,tmpnum;
858         char            matches,was_found;
859
860         WRITE_LOCK(&ip_fw_lock);
861
862         ftmp=*chainptr;
863
864         if ( ftmp == NULL )
865         {
866 #ifdef DEBUG_IP_FIREWALL
867                 printk("ip_fw_ctl:  chain is empty\n");
868 #endif
869                 WRITE_UNLOCK(&ip_fw_lock);
870                 return( EINVAL );
871         }
872
873         ltmp=NULL;
874         was_found=0;
875
876         while( !was_found && ftmp != NULL )
877         {
878                 matches=1;
879                 if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
880                      ||  ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
881                      ||  ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
882                      ||  ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
883                      ||  ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
884                      ||  ftmp->fw_flg!=frwl->fw_flg)
885                         matches=0;
886
887                 tport1=ftmp->fw_nsp+ftmp->fw_ndp;
888                 tport2=frwl->fw_nsp+frwl->fw_ndp;
889                 if (tport1!=tport2)
890                         matches=0;
891                 else if (tport1!=0)
892                 {
893                         for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
894                         if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
895                                 matches=0;
896                 }
897                 if (strncmp(ftmp->fw_vianame, frwl->fw_vianame, IFNAMSIZ))
898                         matches=0;
899                 if(matches)
900                 {
901                         was_found=1;
902                         if (ftmp->fw_viadev
903                             && ftmp->fw_viadev != (struct net_device *)-1)
904                                 dev_put(ftmp->fw_viadev);
905                         if (ltmp)
906                         {
907                                 ltmp->fw_next=ftmp->fw_next;
908                                 kfree(ftmp);
909                                 ftmp=ltmp->fw_next;
910                         }
911                         else
912                         {
913                                 *chainptr=ftmp->fw_next;
914                                 kfree(ftmp);
915                                 ftmp=*chainptr;
916                         }
917                 }
918                 else
919                 {
920                         ltmp = ftmp;
921                         ftmp = ftmp->fw_next;
922                  }
923         }
924         WRITE_UNLOCK(&ip_fw_lock);
925         if (was_found) {
926                 /* We will block in cleanup's unregister sockopt if unloaded,
927                    so this is safe. */
928                 module_put(THIS_MODULE);
929                 return 0;
930         } else
931                 return(EINVAL);
932 }
933
934 #endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
935
936 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
937 {
938
939         if ( len != sizeof(struct ip_fw) )
940         {
941 #ifdef DEBUG_IP_FIREWALL
942                 printk("ip_fw_ctl: len=%d, want %d\n",len, sizeof(struct ip_fw));
943 #endif
944                 return(NULL);
945         }
946
947         if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
948         {
949 #ifdef DEBUG_IP_FIREWALL
950                 printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
951                         frwl->fw_flg);
952 #endif
953                 return(NULL);
954         }
955
956 #ifndef CONFIG_IP_TRANSPARENT_PROXY
957         if (frwl->fw_flg & IP_FW_F_REDIR) {
958 #ifdef DEBUG_IP_FIREWALL
959                 printk("ip_fw_ctl: unsupported flag IP_FW_F_REDIR\n");
960 #endif
961                 return(NULL);
962         }
963 #endif
964
965 #ifndef CONFIG_IP_MASQUERADE
966         if (frwl->fw_flg & IP_FW_F_MASQ) {
967 #ifdef DEBUG_IP_FIREWALL
968                 printk("ip_fw_ctl: unsupported flag IP_FW_F_MASQ\n");
969 #endif
970                 return(NULL);
971         }
972 #endif
973
974         if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
975         {
976 #ifdef DEBUG_IP_FIREWALL
977                 printk("ip_fw_ctl: src range set but fw_nsp=%d\n",
978                         frwl->fw_nsp);
979 #endif
980                 return(NULL);
981         }
982
983         if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
984         {
985 #ifdef DEBUG_IP_FIREWALL
986                 printk("ip_fw_ctl: dst range set but fw_ndp=%d\n",
987                         frwl->fw_ndp);
988 #endif
989                 return(NULL);
990         }
991
992         if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) )
993         {
994 #ifdef DEBUG_IP_FIREWALL
995                 printk("ip_fw_ctl: too many ports (%d+%d)\n",
996                         frwl->fw_nsp,frwl->fw_ndp);
997 #endif
998                 return(NULL);
999         }
1000
1001         return frwl;
1002 }
1003
1004
1005
1006
1007 #ifdef CONFIG_IP_ACCT
1008
1009 int ip_acct_ctl(int stage, void *m, int len)
1010 {
1011         if ( stage == IP_ACCT_FLUSH )
1012         {
1013                 free_fw_chain(&ip_acct_chain);
1014                 return(0);
1015         }
1016         if ( stage == IP_ACCT_ZERO )
1017         {
1018                 zero_fw_chain(ip_acct_chain);
1019                 return(0);
1020         }
1021         if ( stage == IP_ACCT_INSERT || stage == IP_ACCT_APPEND ||
1022                                         stage == IP_ACCT_DELETE )
1023         {
1024                 struct ip_fw *frwl;
1025
1026                 if (!(frwl=check_ipfw_struct(m,len)))
1027                         return (EINVAL);
1028
1029                 switch (stage)
1030                 {
1031                         case IP_ACCT_INSERT:
1032                                 return( insert_in_chain(&ip_acct_chain,frwl,len));
1033                         case IP_ACCT_APPEND:
1034                                 return( append_to_chain(&ip_acct_chain,frwl,len));
1035                         case IP_ACCT_DELETE:
1036                                 return( del_from_chain(&ip_acct_chain,frwl));
1037                         default:
1038                                 /*
1039                                  *      Should be panic but... (Why ??? - AC)
1040                                  */
1041 #ifdef DEBUG_IP_FIREWALL
1042                                 printk("ip_acct_ctl:  unknown request %d\n",stage);
1043 #endif
1044                                 return(EINVAL);
1045                 }
1046         }
1047 #ifdef DEBUG_IP_FIREWALL
1048         printk("ip_acct_ctl:  unknown request %d\n",stage);
1049 #endif
1050         return(EINVAL);
1051 }
1052 #endif
1053
1054 #ifdef CONFIG_IP_FIREWALL
1055 int ip_fw_ctl(int stage, void *m, int len)
1056 {
1057         int cmd, fwtype;
1058
1059         cmd = stage & IP_FW_COMMAND;
1060         fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1061
1062         if ( cmd == IP_FW_FLUSH )
1063         {
1064                 free_fw_chain(chains[fwtype]);
1065                 return(0);
1066         }
1067
1068         if ( cmd == IP_FW_ZERO )
1069         {
1070                 zero_fw_chain(*chains[fwtype]);
1071                 return(0);
1072         }
1073
1074         if ( cmd == IP_FW_POLICY )
1075         {
1076                 int *tmp_policy_ptr;
1077                 tmp_policy_ptr=(int *)m;
1078                 *policies[fwtype] = *tmp_policy_ptr;
1079                 return 0;
1080         }
1081
1082         if ( cmd == IP_FW_CHECK )
1083         {
1084                 struct sk_buff *tmp_skb;
1085                 struct net_device *viadev;
1086                 struct ip_fwpkt *ipfwp;
1087                 struct iphdr *ip;
1088                 int hdrlen, ret;
1089
1090                 hdrlen = sizeof(struct ip_fwpkt) -
1091                         sizeof(struct in_addr) -
1092                         IFNAMSIZ;
1093
1094                 if ( len != sizeof(struct ip_fwpkt) )
1095                 {
1096 #ifdef DEBUG_IP_FIREWALL
1097                         printk("ip_fw_ctl: length=%d, expected %d\n",
1098                                 len, sizeof(struct ip_fwpkt));
1099 #endif
1100                         return( EINVAL );
1101                 }
1102
1103                 ipfwp = (struct ip_fwpkt *)m;
1104                 ip = &(ipfwp->fwp_iph);
1105
1106                 if ( !(viadev = dev_get_by_name(ipfwp->fwp_vianame)) ) {
1107 #ifdef DEBUG_IP_FIREWALL
1108                         printk("ip_fw_ctl: invalid device \"%s\"\n", ipfwp->fwp_vianame);
1109 #endif
1110                         return(EINVAL);
1111                 } else if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) {
1112 #ifdef DEBUG_IP_FIREWALL
1113                         printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
1114                                         sizeof(struct iphdr)/sizeof(int));
1115 #endif
1116                         dev_put(viadev);
1117                         return(EINVAL);
1118                 }
1119
1120                 /* Fix this one up by hand, who knows how many
1121                  * tools will break if we start to barf on this.
1122                  */
1123                 if (ntohs(ip->tot_len) > hdrlen)
1124                         ip->tot_len = htons(hdrlen);
1125
1126                 if ((tmp_skb = alloc_skb(hdrlen, GFP_ATOMIC)) == NULL) {
1127 #ifdef DEBUG_IP_FIREWALL
1128                         printk("ip_fw_ctl: tmp_skb alloc failure\n");
1129 #endif
1130                         dev_put(viadev);
1131                         return(EFAULT);
1132                 }
1133                 skb_reserve(tmp_skb, hdrlen);
1134                 skb_push(tmp_skb, hdrlen);
1135                 memcpy(tmp_skb->data, ip, hdrlen);
1136
1137                 ret = ip_fw_chk(&tmp_skb, viadev, NULL, *chains[fwtype],
1138                                 *policies[fwtype], IP_FW_MODE_CHK);
1139
1140                 kfree_skb(tmp_skb);
1141                 dev_put(viadev);
1142
1143                 switch (ret) {
1144                         case FW_ACCEPT:
1145                                 return(0);
1146                         case FW_REDIRECT:
1147                                 return(ECONNABORTED);
1148                         case FW_MASQUERADE:
1149                                 return(ECONNRESET);
1150                         case FW_REJECT:
1151                                 return(ECONNREFUSED);
1152                         default: /* FW_BLOCK */
1153                                 return(ETIMEDOUT);
1154                 }
1155         }
1156
1157         if ( cmd == IP_FW_MASQ_TIMEOUTS )
1158                 return ip_fw_masq_timeouts(m, len);
1159
1160 /*
1161  *      Here we really working hard-adding new elements
1162  *      to blocking/forwarding chains or deleting 'em
1163  */
1164
1165         if ( cmd == IP_FW_INSERT || cmd == IP_FW_APPEND || cmd == IP_FW_DELETE )
1166         {
1167                 struct ip_fw *frwl;
1168                 int fwtype;
1169
1170                 frwl=check_ipfw_struct(m,len);
1171                 if (frwl==NULL)
1172                         return (EINVAL);
1173                 fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1174
1175                 switch (cmd)
1176                 {
1177                         case IP_FW_INSERT:
1178                                 return(insert_in_chain(chains[fwtype],frwl,len));
1179                         case IP_FW_APPEND:
1180                                 return(append_to_chain(chains[fwtype],frwl,len));
1181                         case IP_FW_DELETE:
1182                                 return(del_from_chain(chains[fwtype],frwl));
1183                         default:
1184                         /*
1185                          *      Should be panic but... (Why are BSD people panic obsessed ??)
1186                          */
1187 #ifdef DEBUG_IP_FIREWALL
1188                                 printk("ip_fw_ctl:  unknown request %d\n",stage);
1189 #endif
1190                                 return(EINVAL);
1191                 }
1192         }
1193
1194 #ifdef DEBUG_IP_FIREWALL
1195         printk("ip_fw_ctl:  unknown request %d\n",stage);
1196 #endif
1197         return(ENOPROTOOPT);
1198 }
1199 #endif /* CONFIG_IP_FIREWALL */
1200
1201 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
1202 static int ip_chain_procinfo(int stage, char *buffer, char **start,
1203                              off_t offset, int length)
1204 {
1205         off_t pos=0, begin=0;
1206         struct ip_fw *i;
1207         int len, p;
1208         int last_len = 0;
1209
1210
1211         switch(stage)
1212         {
1213 #ifdef CONFIG_IP_FIREWALL
1214                 case IP_FW_IN:
1215                         i = ip_fw_in_chain;
1216                         len=sprintf(buffer, "IP firewall input rules, default %d\n",
1217                                 ip_fw_in_policy);
1218                         break;
1219                 case IP_FW_OUT:
1220                         i = ip_fw_out_chain;
1221                         len=sprintf(buffer, "IP firewall output rules, default %d\n",
1222                                 ip_fw_out_policy);
1223                         break;
1224                 case IP_FW_FWD:
1225                         i = ip_fw_fwd_chain;
1226                         len=sprintf(buffer, "IP firewall forward rules, default %d\n",
1227                                 ip_fw_fwd_policy);
1228                         break;
1229 #endif
1230 #ifdef CONFIG_IP_ACCT
1231                 case IP_FW_ACCT:
1232                         i = ip_acct_chain;
1233                         len=sprintf(buffer,"IP accounting rules\n");
1234                         break;
1235 #endif
1236                 default:
1237                         /* this should never be reached, but safety first... */
1238                         i = NULL;
1239                         len=0;
1240                         break;
1241         }
1242
1243         READ_LOCK(&ip_fw_lock);
1244
1245         while(i!=NULL)
1246         {
1247                 len+=sprintf(buffer+len,"%08X/%08X->%08X/%08X %.16s %08X %X ",
1248                         ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
1249                         ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
1250                         (i->fw_vianame)[0] ? i->fw_vianame : "-",
1251                         ntohl(i->fw_via.s_addr), i->fw_flg);
1252                 /* 10 is enough for a 32 bit box but the counters are 64bit on
1253                    the Alpha and Ultrapenguin */
1254                 len+=sprintf(buffer+len,"%u %u %-20lu %-20lu",
1255                         i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
1256                 for (p = 0; p < IP_FW_MAX_PORTS; p++)
1257                         len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
1258                 len+=sprintf(buffer+len, " A%02X X%02X", i->fw_tosand, i->fw_tosxor);
1259                 buffer[len++]='\n';
1260                 buffer[len]='\0';
1261                 pos=begin+len;
1262                 if(pos<offset)
1263                 {
1264                         len=0;
1265                         begin=pos;
1266                 }
1267                 else if(pos>offset+length)
1268                 {
1269                         len = last_len;
1270                         break;
1271                 }
1272                 last_len = len;
1273                 i=i->fw_next;
1274         }
1275         READ_UNLOCK(&ip_fw_lock);
1276         *start=buffer+(offset-begin);
1277         len-=(offset-begin);
1278         if(len>length)
1279                 len=length;
1280         return len;
1281 }
1282 #endif
1283
1284 #ifdef CONFIG_IP_ACCT
1285 static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
1286                             int length)
1287 {
1288         return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length);
1289 }
1290 #endif
1291
1292 #ifdef CONFIG_IP_FIREWALL
1293 static int ip_fw_in_procinfo(char *buffer, char **start, off_t offset,
1294                               int length)
1295 {
1296         return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length);
1297 }
1298
1299 static int ip_fw_out_procinfo(char *buffer, char **start, off_t offset,
1300                               int length)
1301 {
1302         return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length);
1303 }
1304
1305 static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
1306                               int length)
1307 {
1308         return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length);
1309 }
1310 #endif
1311
1312
1313 #ifdef CONFIG_IP_FIREWALL
1314 /*
1315  *      Interface to the generic firewall chains.
1316  */
1317
1318 int ipfw_input_check(struct firewall_ops *this, int pf,
1319                      struct net_device *dev, void *arg,
1320                      struct sk_buff **pskb)
1321 {
1322         return ip_fw_chk(pskb, dev, arg, ip_fw_in_chain, ip_fw_in_policy,
1323                          IP_FW_MODE_FW);
1324 }
1325
1326 int ipfw_output_check(struct firewall_ops *this, int pf,
1327                       struct net_device *dev, void *arg,
1328                       struct sk_buff **pskb)
1329 {
1330         return ip_fw_chk(pskb, dev, arg, ip_fw_out_chain, ip_fw_out_policy,
1331                          IP_FW_MODE_FW);
1332 }
1333
1334 int ipfw_forward_check(struct firewall_ops *this, int pf,
1335                        struct net_device *dev, void *arg,
1336                        struct sk_buff **pskb)
1337 {
1338         return ip_fw_chk(pskb, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy,
1339                          IP_FW_MODE_FW);
1340 }
1341
1342 #ifdef CONFIG_IP_ACCT
1343 int ipfw_acct_in(struct firewall_ops *this, int pf, struct net_device *dev,
1344                  void *arg, struct sk_buff **pskb)
1345 {
1346         return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN);
1347 }
1348
1349 int ipfw_acct_out(struct firewall_ops *this, int pf, struct net_device *dev,
1350                   void *arg, struct sk_buff **pskb)
1351 {
1352         return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
1353 }
1354 #endif
1355
1356 struct firewall_ops ipfw_ops = {
1357         .fw_forward     =       ipfw_forward_check,
1358         .fw_input       =       ipfw_input_check,
1359         .fw_output      =       ipfw_output_check,
1360 #ifdef CONFIG_IP_ACCT
1361         .fw_acct_in     =       ipfw_acct_in,
1362         .fw_acct_out    =       ipfw_acct_out,
1363 #endif
1364 };
1365
1366 #endif
1367
1368 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
1369
1370 int ipfw_device_event(struct notifier_block *this, unsigned long event, void *ptr)
1371 {
1372         struct net_device *dev=ptr;
1373         char *devname = dev->name;
1374         struct ip_fw *fw;
1375         int chn;
1376
1377         WRITE_LOCK(&ip_fw_lock);
1378
1379         if (event == NETDEV_UP) {
1380                 for (chn = 0; chn < IP_FW_CHAINS; chn++)
1381                         for (fw = *chains[chn]; fw; fw = fw->fw_next)
1382                                 if ((fw->fw_vianame)[0] && !strncmp(devname,
1383                                             fw->fw_vianame, IFNAMSIZ)) {
1384                                         dev_hold(dev);
1385                                         fw->fw_viadev = dev;
1386                                 }
1387         } else if (event == NETDEV_DOWN) {
1388                 for (chn = 0; chn < IP_FW_CHAINS; chn++)
1389                         for (fw = *chains[chn]; fw; fw = fw->fw_next)
1390                                 /* we could compare just the pointers ... */
1391                                 if ((fw->fw_vianame)[0] && !strncmp(devname,
1392                                                     fw->fw_vianame, IFNAMSIZ)){
1393                                         if (fw->fw_viadev
1394                                             && fw->fw_viadev != (struct net_device *)-1)
1395                                                 dev_put(fw->fw_viadev);
1396                                         fw->fw_viadev = (struct net_device*)-1;
1397                                 }
1398         }
1399
1400         WRITE_UNLOCK(&ip_fw_lock);
1401         return NOTIFY_DONE;
1402 }
1403
1404 static struct notifier_block ipfw_dev_notifier = {
1405         .notifier_call  =       ipfw_device_event,
1406 };
1407
1408 #endif
1409
1410 int ipfw_init_or_cleanup(int init)
1411 {
1412         int ret = 0;
1413
1414         if (!init)
1415                 goto cleanup;
1416
1417         ret = register_firewall(PF_INET, &ipfw_ops);
1418         if (ret < 0)
1419                 goto cleanup_nothing;
1420
1421 #ifdef CONFIG_IP_ACCT
1422         proc_net_create("ip_acct", S_IFREG | S_IRUGO | S_IWUSR, ip_acct_procinfo);
1423 #endif
1424         proc_net_create("ip_input", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_in_procinfo);
1425         proc_net_create("ip_output", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_out_procinfo);
1426         proc_net_create("ip_forward", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_fwd_procinfo);
1427
1428         /* Register for device up/down reports */
1429         register_netdevice_notifier(&ipfw_dev_notifier);
1430
1431 #ifdef CONFIG_IP_FIREWALL_NETLINK
1432         ipfwsk = netlink_kernel_create(NETLINK_FIREWALL, NULL);
1433 #endif
1434         return ret;
1435
1436  cleanup:
1437 #ifdef CONFIG_IP_FIREWALL_NETLINK
1438         sock_release(ipfwsk->sk_socket);
1439 #endif
1440         unregister_netdevice_notifier(&ipfw_dev_notifier);
1441
1442 #ifdef CONFIG_IP_ACCT
1443         proc_net_remove("ip_acct");
1444 #endif
1445         proc_net_remove("ip_input");
1446         proc_net_remove("ip_output");
1447         proc_net_remove("ip_forward");
1448
1449         free_fw_chain(chains[IP_FW_FWD]);
1450         free_fw_chain(chains[IP_FW_IN]);
1451         free_fw_chain(chains[IP_FW_OUT]);
1452         free_fw_chain(chains[IP_FW_ACCT]);
1453
1454         unregister_firewall(PF_INET, &ipfw_ops);
1455
1456  cleanup_nothing:
1457         return ret;
1458 }