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