update to 2.6.9-rc1
[linux-flexiantxendom0-3.2.10.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, *th;
414
415                                 th = skb_header_pointer(*pskb,
416                                                         (*pskb)->nh.iph->ihl*4,
417                                                         sizeof(_tcph), &_tcph);
418                                 if (th == NULL)
419                                         return FW_BLOCK;
420
421                                 src_port = ntohs(th->source);
422                                 dst_port = ntohs(th->dest);
423
424                                 if(!th->ack && !th->rst)
425                                         /* We do NOT have ACK, value TRUE */
426                                         notcpack = 1;
427                                 if(!th->syn || !notcpack)
428                                         /* We do NOT have SYN, value TRUE */
429                                         notcpsyn = 1;
430                         }
431                         prt = IP_FW_F_TCP;
432                         break;
433                 case IPPROTO_UDP:
434                         dprintf1("UDP ");
435                         /* ports stay 0xFFFF if it is not the first fragment */
436                         if (!offset) {
437                                 struct udphdr _udph, *uh;
438
439                                 uh = skb_header_pointer(*pskb,
440                                                         (*pskb)->nh.iph->ihl*4,
441                                                         sizeof(_udph), &_udph);
442                                 if (uh == NULL)
443                                         return FW_BLOCK;
444
445                                 src_port = ntohs(uh->source);
446                                 dst_port = ntohs(uh->dest);
447                         }
448                         prt = IP_FW_F_UDP;
449                         break;
450                 case IPPROTO_ICMP:
451                         /* icmp_type stays 255 if it is not the first fragment */
452                         if (!offset) {
453                                 struct icmphdr _icmph, *ic;
454
455                                 ic = skb_header_pointer(*pskb,
456                                                         (*pskb)->nh.iph->ihl*4,
457                                                         sizeof(_icmph),
458                                                         &_icmph);
459                                 if (ic == NULL)
460                                         return FW_BLOCK;
461
462                                 icmp_type = (__u16) ic->type;
463                         }
464                         dprintf2("ICMP:%d ", icmp_type);
465                         prt = IP_FW_F_ICMP;
466                         break;
467                 default:
468                         dprintf2("p=%d ", protocol);
469                         prt = IP_FW_F_ALL;
470                         break;
471         }
472 #ifdef DEBUG_IP_FIREWALL
473         dprint_ip(src);
474
475         if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
476                 /* This will print 65535 when it is not the first fragment! */
477                 dprintf2(":%d ", src_port);
478         dprint_ip(dst);
479         if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
480                 /* This will print 65535 when it is not the first fragment! */
481                 dprintf2(":%d ", dst_port);
482         dprintf1("\n");
483 #endif
484
485         if (mode == IP_FW_MODE_CHK)
486                 READ_LOCK(&ip_fw_lock);
487         else
488                 WRITE_LOCK(&ip_fw_lock);
489         
490         for (f = chain; f; f = f->fw_next) {
491                 /*
492                  *      This is a bit simpler as we don't have to walk
493                  *      an interface chain as you do in BSD - same logic
494                  *      however.
495                  */
496
497                 /*
498                  *      Match can become 0x01 (a "normal" match was found),
499                  *      0x02 (a reverse match was found), and 0x03 (the
500                  *      IP addresses match in both directions).
501                  *      Now we know in which direction(s) we should look
502                  *      for a match for the TCP/UDP ports.  Both directions
503                  *      might match (e.g., when both addresses are on the
504                  *      same network for which an address/mask is given), but
505                  *      the ports might only match in one direction.
506                  *      This was obviously wrong in the original BSD code.
507                  */
508                 match = 0x00;
509
510                 if ((src & f->fw_smsk.s_addr) == f->fw_src.s_addr &&
511                     (dst & f->fw_dmsk.s_addr) == f->fw_dst.s_addr)
512                         /* normal direction */
513                         match |= 0x01;
514
515                 if ((f->fw_flg & IP_FW_F_BIDIR) &&
516                     (dst & f->fw_smsk.s_addr) == f->fw_src.s_addr &&
517                     (src & f->fw_dmsk.s_addr) == f->fw_dst.s_addr)
518                         /* reverse direction */
519                         match |= 0x02;
520
521                 if (!match)
522                         continue;
523
524                 /*
525                  *      Look for a VIA device match
526                  */
527                 if (f->fw_viadev) {
528                         if (rif != f->fw_viadev)
529                                 continue;       /* Mismatch */
530                 }
531
532                 /* This looks stupid, because we scan almost static
533                    list, searching for static key. However, this way seems
534                    to be only reasonable way of handling fw_via rules
535                    (btw bsd makes the same thing).
536
537                    It will not affect performance if you will follow
538                    the following simple rules:
539
540                    - if interface is aliased, ALWAYS specify fw_viadev,
541                      so that previous check will guarantee, that we will
542                      not waste time when packet arrive on another interface.
543
544                    - avoid using fw_via.s_addr if fw_via.s_addr is owned
545                      by an aliased interface.
546
547                                                                        --ANK
548                  */
549                 if (f->fw_via.s_addr && rif) {
550                         struct in_ifaddr *ifa;
551
552                         if (rif->ip_ptr == NULL)
553                                 continue;       /* Mismatch */
554
555                         for (ifa = ((struct in_device*)(rif->ip_ptr))->ifa_list;
556                              ifa; ifa = ifa->ifa_next) {
557                                 if (ifa->ifa_local == f->fw_via.s_addr)
558                                         goto ifa_ok;
559                         }
560                         continue;       /* Mismatch */
561
562                 ifa_ok:;
563                 }
564
565                 /*
566                  *      Ok the chain addresses match.
567                  */
568
569 #ifdef CONFIG_IP_ACCT
570                 /*
571                  *      See if we're in accounting mode and only want to
572                  *      count incoming or outgoing packets.
573                  */
574
575                 if (mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT) &&
576                    ((mode == IP_FW_MODE_ACCT_IN && f->fw_flg&IP_FW_F_ACCTOUT) ||
577                     (mode == IP_FW_MODE_ACCT_OUT && f->fw_flg&IP_FW_F_ACCTIN)))
578                         continue;
579
580 #endif
581                 /*
582                  * For all non-TCP packets and/or non-first fragments,
583                  * notcpsyn and notcpack will always be FALSE,
584                  * so the IP_FW_F_TCPSYN and IP_FW_F_TCPACK flags
585                  * are actually ignored for these packets.
586                  */
587
588                 if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
589                         continue;
590
591                 if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
592                         continue;
593
594                 f_prt=f->fw_flg&IP_FW_F_KIND;
595                 if (f_prt != IP_FW_F_ALL) {
596                         /*
597                          *      Specific firewall - packet's protocol
598                          *      must match firewall's.
599                          */
600
601                         if (prt != f_prt)
602                                 continue;
603
604                         if((prt==IP_FW_F_ICMP &&
605                                 ! port_match(&f->fw_pts[0], f->fw_nsp,
606                                         icmp_type,f->fw_flg&IP_FW_F_SRNG)) ||
607                             !(prt==IP_FW_F_ICMP || ((match & 0x01) &&
608                                 port_match(&f->fw_pts[0], f->fw_nsp, src_port,
609                                         f->fw_flg&IP_FW_F_SRNG) &&
610                                 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
611                                         f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
612                                 port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
613                                         f->fw_flg&IP_FW_F_SRNG) &&
614                                 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
615                                         f->fw_flg&IP_FW_F_DRNG))))
616                         {
617                                 continue;
618                         }
619                 }
620
621 #ifdef CONFIG_IP_FIREWALL_VERBOSE
622                 if (f->fw_flg & IP_FW_F_PRN)
623                 {
624                         char buf[16];
625
626                         print_packet(pskb, src_port, dst_port, icmp_type,
627                                      chain_name(chain, mode),
628                                      rule_name(f, mode, buf),
629                                      rif ? rif->name : "-");
630                 }
631 #endif
632                 if (mode != IP_FW_MODE_CHK) {
633                         f->fw_bcnt += ntohs((*pskb)->nh.iph->tot_len);
634                         f->fw_pcnt++;
635                 }
636                 if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)))
637                         break;
638         } /* Loop */
639
640         if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) {
641
642                 /*
643                  * We rely on policy defined in the rejecting entry or, if no match
644                  * was found, we rely on the general policy variable for this type
645                  * of firewall.
646                  */
647
648                 if (f != NULL) {
649                         policy = f->fw_flg;
650                         tosand = f->fw_tosand;
651                         tosxor = f->fw_tosxor;
652                 } else {
653                         tosand = 0xFF;
654                         tosxor = 0x00;
655                 }
656
657                 if (policy & IP_FW_F_ACCEPT) {
658                         /* Adjust priority and recompute checksum */
659                         __u8 tos = (*pskb)->nh.iph->tos;
660
661                         if (((tos & tosand) ^ tosxor) != tos) {
662                                 if (!skb_ip_make_writable(pskb,
663                                           offsetof(struct iphdr, tos)+1))
664                                         goto drop_it;
665
666                                 (*pskb)->nh.iph->tos = (tos & tosand) ^ tosxor;
667                                 ip_send_check((*pskb)->nh.iph);
668                         }
669
670 #ifdef CONFIG_IP_TRANSPARENT_PROXY
671                         if (policy & IP_FW_F_REDIR) {
672                                 if (redirport)
673                                         if ((*redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp])) == 0) {
674                                                 /* Wildcard redirection.
675                                                  * Note that redirport will become
676                                                  * 0xFFFF for non-TCP/UDP packets.
677                                                  */
678                                                 *redirport = htons(dst_port);
679                                         }
680                                 answer = FW_REDIRECT;
681                         } else
682 #endif
683 #ifdef CONFIG_IP_MASQUERADE
684                         if (policy & IP_FW_F_MASQ)
685                                 answer = FW_MASQUERADE;
686                         else
687 #endif
688                                 answer = FW_ACCEPT;
689
690                 } else if (policy & IP_FW_F_ICMPRPL)
691                         answer = FW_REJECT;
692                 else {
693                 drop_it:
694                         answer = FW_BLOCK;
695                 }
696
697 #ifdef CONFIG_IP_FIREWALL_NETLINK
698                 if ((policy & IP_FW_F_PRN) && (answer == FW_REJECT || answer == FW_BLOCK))
699                 {
700                         struct sk_buff *skb = alloc_skb(128,
701                                         (mode == IP_FW_MODE_CHK) ?
702                                         GFP_KERNEL : GFP_ATOMIC);
703                         if (skb) {
704                                 int len = min_t(unsigned int,
705                                         128,
706                                         ntohs((*pskb)->nh.iph->tot_len));
707
708                                 skb_put(skb, len);
709                                 skb_copy_bits(*pskb,
710                                         ((char *)(*pskb)->nh.iph -
711                                          (char *)(*pskb)->data),
712                                         skb->data, len);
713                                 if (netlink_post(NETLINK_FIREWALL, skb))
714                                         kfree_skb(skb);
715                         }
716                 }
717 #endif
718         } else
719                 /* we're doing accounting, always ok */
720                 answer = 0;
721         
722         if (mode == IP_FW_MODE_CHK)
723                 READ_UNLOCK(&ip_fw_lock);
724         else
725                 WRITE_UNLOCK(&ip_fw_lock);
726
727         return answer;
728 }
729
730
731 static void zero_fw_chain(struct ip_fw *chainptr)
732 {
733         struct ip_fw *ctmp=chainptr;
734         
735         WRITE_LOCK(&ip_fw_lock);
736         while(ctmp)
737         {
738                 ctmp->fw_pcnt=0L;
739                 ctmp->fw_bcnt=0L;
740                 ctmp=ctmp->fw_next;
741         }
742         WRITE_UNLOCK(&ip_fw_lock);
743 }
744
745 static void free_fw_chain(struct ip_fw *volatile* chainptr)
746 {
747         WRITE_LOCK(&ip_fw_lock);
748         while ( *chainptr != NULL )
749         {
750                 struct ip_fw *ftmp;
751                 ftmp = *chainptr;
752                 *chainptr = ftmp->fw_next;
753                 if (ftmp->fw_viadev
754                     && ftmp->fw_viadev != (struct net_device *)-1)
755                         dev_put(ftmp->fw_viadev);
756                 kfree(ftmp);
757                 /* We will block in cleanup's unregister sockopt if unloaded,
758                    so this is safe. */
759                 module_put(THIS_MODULE);
760         }
761         WRITE_UNLOCK(&ip_fw_lock);
762 }
763
764 /* Volatiles to keep some of the compiler versions amused */
765
766 static int insert_in_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
767 {
768         struct ip_fw *ftmp;
769
770         /* Are we unloading now?  We will block on nf_unregister_sockopt */
771         if (!try_module_get(THIS_MODULE))
772                 return ENOPROTOOPT;
773
774         ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL );
775         if ( ftmp == NULL )
776         {
777 #ifdef DEBUG_IP_FIREWALL
778                 printk("ip_fw_ctl:  malloc said no\n");
779 #endif
780                 return( ENOMEM );
781         }
782
783         memcpy(ftmp, frwl, len);
784         /*
785          *      Allow the more recent "minimise cost" flag to be
786          *      set. [Rob van Nieuwkerk]
787          */
788         ftmp->fw_tosand |= 0x01;
789         ftmp->fw_tosxor &= 0xFE;
790         ftmp->fw_pcnt=0L;
791         ftmp->fw_bcnt=0L;
792
793         WRITE_LOCK(&ip_fw_lock);
794
795         if ((ftmp->fw_vianame)[0]) {
796                 if (!(ftmp->fw_viadev = dev_get_by_name(ftmp->fw_vianame)))
797                         ftmp->fw_viadev = (struct net_device *) -1;
798         } else
799                 ftmp->fw_viadev = NULL;
800
801         ftmp->fw_next = *chainptr;
802         *chainptr=ftmp;
803         WRITE_UNLOCK(&ip_fw_lock);
804         return(0);
805 }
806
807 static int append_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
808 {
809         struct ip_fw *ftmp;
810         struct ip_fw *chtmp=NULL;
811         struct ip_fw *volatile chtmp_prev=NULL;
812
813         /* Are we unloading now?  We will block on nf_unregister_sockopt */
814         if (!try_module_get(THIS_MODULE))
815                 return ENOPROTOOPT;
816
817         ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL );
818         if ( ftmp == NULL )
819         {
820 #ifdef DEBUG_IP_FIREWALL
821                 printk("ip_fw_ctl:  malloc said no\n");
822 #endif
823                 return( ENOMEM );
824         }
825
826         memcpy(ftmp, frwl, len);
827         /*
828          *      Allow the more recent "minimise cost" flag to be
829          *      set. [Rob van Nieuwkerk]
830          */
831         ftmp->fw_tosand |= 0x01;
832         ftmp->fw_tosxor &= 0xFE;
833         ftmp->fw_pcnt=0L;
834         ftmp->fw_bcnt=0L;
835
836         ftmp->fw_next = NULL;
837
838         WRITE_LOCK(&ip_fw_lock);
839
840         if ((ftmp->fw_vianame)[0]) {
841                 if (!(ftmp->fw_viadev = dev_get_by_name(ftmp->fw_vianame)))
842                         ftmp->fw_viadev = (struct net_device *) -1;
843         } else
844                 ftmp->fw_viadev = NULL;
845
846         chtmp_prev=NULL;
847         for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
848                 chtmp_prev=chtmp;
849
850         if (chtmp_prev)
851                 chtmp_prev->fw_next=ftmp;
852         else
853                 *chainptr=ftmp;
854         WRITE_UNLOCK(&ip_fw_lock);
855         return(0);
856 }
857
858 static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
859 {
860         struct ip_fw    *ftmp,*ltmp;
861         unsigned short  tport1,tport2,tmpnum;
862         char            matches,was_found;
863
864         WRITE_LOCK(&ip_fw_lock);
865
866         ftmp=*chainptr;
867
868         if ( ftmp == NULL )
869         {
870 #ifdef DEBUG_IP_FIREWALL
871                 printk("ip_fw_ctl:  chain is empty\n");
872 #endif
873                 WRITE_UNLOCK(&ip_fw_lock);
874                 return( EINVAL );
875         }
876
877         ltmp=NULL;
878         was_found=0;
879
880         while( !was_found && ftmp != NULL )
881         {
882                 matches=1;
883                 if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
884                      ||  ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
885                      ||  ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
886                      ||  ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
887                      ||  ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
888                      ||  ftmp->fw_flg!=frwl->fw_flg)
889                         matches=0;
890
891                 tport1=ftmp->fw_nsp+ftmp->fw_ndp;
892                 tport2=frwl->fw_nsp+frwl->fw_ndp;
893                 if (tport1!=tport2)
894                         matches=0;
895                 else if (tport1!=0)
896                 {
897                         for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
898                         if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
899                                 matches=0;
900                 }
901                 if (strncmp(ftmp->fw_vianame, frwl->fw_vianame, IFNAMSIZ))
902                         matches=0;
903                 if(matches)
904                 {
905                         was_found=1;
906                         if (ftmp->fw_viadev
907                             && ftmp->fw_viadev != (struct net_device *)-1)
908                                 dev_put(ftmp->fw_viadev);
909                         if (ltmp)
910                         {
911                                 ltmp->fw_next=ftmp->fw_next;
912                                 kfree(ftmp);
913                                 ftmp=ltmp->fw_next;
914                         }
915                         else
916                         {
917                                 *chainptr=ftmp->fw_next;
918                                 kfree(ftmp);
919                                 ftmp=*chainptr;
920                         }
921                 }
922                 else
923                 {
924                         ltmp = ftmp;
925                         ftmp = ftmp->fw_next;
926                  }
927         }
928         WRITE_UNLOCK(&ip_fw_lock);
929         if (was_found) {
930                 /* We will block in cleanup's unregister sockopt if unloaded,
931                    so this is safe. */
932                 module_put(THIS_MODULE);
933                 return 0;
934         } else
935                 return(EINVAL);
936 }
937
938 #endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
939
940 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
941 {
942
943         if ( len != sizeof(struct ip_fw) )
944         {
945 #ifdef DEBUG_IP_FIREWALL
946                 printk("ip_fw_ctl: len=%d, want %d\n",len, sizeof(struct ip_fw));
947 #endif
948                 return(NULL);
949         }
950
951         if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
952         {
953 #ifdef DEBUG_IP_FIREWALL
954                 printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
955                         frwl->fw_flg);
956 #endif
957                 return(NULL);
958         }
959
960 #ifndef CONFIG_IP_TRANSPARENT_PROXY
961         if (frwl->fw_flg & IP_FW_F_REDIR) {
962 #ifdef DEBUG_IP_FIREWALL
963                 printk("ip_fw_ctl: unsupported flag IP_FW_F_REDIR\n");
964 #endif
965                 return(NULL);
966         }
967 #endif
968
969 #ifndef CONFIG_IP_MASQUERADE
970         if (frwl->fw_flg & IP_FW_F_MASQ) {
971 #ifdef DEBUG_IP_FIREWALL
972                 printk("ip_fw_ctl: unsupported flag IP_FW_F_MASQ\n");
973 #endif
974                 return(NULL);
975         }
976 #endif
977
978         if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
979         {
980 #ifdef DEBUG_IP_FIREWALL
981                 printk("ip_fw_ctl: src range set but fw_nsp=%d\n",
982                         frwl->fw_nsp);
983 #endif
984                 return(NULL);
985         }
986
987         if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
988         {
989 #ifdef DEBUG_IP_FIREWALL
990                 printk("ip_fw_ctl: dst range set but fw_ndp=%d\n",
991                         frwl->fw_ndp);
992 #endif
993                 return(NULL);
994         }
995
996         if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) )
997         {
998 #ifdef DEBUG_IP_FIREWALL
999                 printk("ip_fw_ctl: too many ports (%d+%d)\n",
1000                         frwl->fw_nsp,frwl->fw_ndp);
1001 #endif
1002                 return(NULL);
1003         }
1004
1005         return frwl;
1006 }
1007
1008
1009
1010
1011 #ifdef CONFIG_IP_ACCT
1012
1013 int ip_acct_ctl(int stage, void *m, int len)
1014 {
1015         if ( stage == IP_ACCT_FLUSH )
1016         {
1017                 free_fw_chain(&ip_acct_chain);
1018                 return(0);
1019         }
1020         if ( stage == IP_ACCT_ZERO )
1021         {
1022                 zero_fw_chain(ip_acct_chain);
1023                 return(0);
1024         }
1025         if ( stage == IP_ACCT_INSERT || stage == IP_ACCT_APPEND ||
1026                                         stage == IP_ACCT_DELETE )
1027         {
1028                 struct ip_fw *frwl;
1029
1030                 if (!(frwl=check_ipfw_struct(m,len)))
1031                         return (EINVAL);
1032
1033                 switch (stage)
1034                 {
1035                         case IP_ACCT_INSERT:
1036                                 return( insert_in_chain(&ip_acct_chain,frwl,len));
1037                         case IP_ACCT_APPEND:
1038                                 return( append_to_chain(&ip_acct_chain,frwl,len));
1039                         case IP_ACCT_DELETE:
1040                                 return( del_from_chain(&ip_acct_chain,frwl));
1041                         default:
1042                                 /*
1043                                  *      Should be panic but... (Why ??? - AC)
1044                                  */
1045 #ifdef DEBUG_IP_FIREWALL
1046                                 printk("ip_acct_ctl:  unknown request %d\n",stage);
1047 #endif
1048                                 return(EINVAL);
1049                 }
1050         }
1051 #ifdef DEBUG_IP_FIREWALL
1052         printk("ip_acct_ctl:  unknown request %d\n",stage);
1053 #endif
1054         return(EINVAL);
1055 }
1056 #endif
1057
1058 #ifdef CONFIG_IP_FIREWALL
1059 int ip_fw_ctl(int stage, void *m, int len)
1060 {
1061         int cmd, fwtype;
1062
1063         cmd = stage & IP_FW_COMMAND;
1064         fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1065
1066         if ( cmd == IP_FW_FLUSH )
1067         {
1068                 free_fw_chain(chains[fwtype]);
1069                 return(0);
1070         }
1071
1072         if ( cmd == IP_FW_ZERO )
1073         {
1074                 zero_fw_chain(*chains[fwtype]);
1075                 return(0);
1076         }
1077
1078         if ( cmd == IP_FW_POLICY )
1079         {
1080                 int *tmp_policy_ptr;
1081                 tmp_policy_ptr=(int *)m;
1082                 *policies[fwtype] = *tmp_policy_ptr;
1083                 return 0;
1084         }
1085
1086         if ( cmd == IP_FW_CHECK )
1087         {
1088                 struct sk_buff *tmp_skb;
1089                 struct net_device *viadev;
1090                 struct ip_fwpkt *ipfwp;
1091                 struct iphdr *ip;
1092                 int hdrlen, ret;
1093
1094                 hdrlen = sizeof(struct ip_fwpkt) -
1095                         sizeof(struct in_addr) -
1096                         IFNAMSIZ;
1097
1098                 if ( len != sizeof(struct ip_fwpkt) )
1099                 {
1100 #ifdef DEBUG_IP_FIREWALL
1101                         printk("ip_fw_ctl: length=%d, expected %d\n",
1102                                 len, sizeof(struct ip_fwpkt));
1103 #endif
1104                         return( EINVAL );
1105                 }
1106
1107                 ipfwp = (struct ip_fwpkt *)m;
1108                 ip = &(ipfwp->fwp_iph);
1109
1110                 if ( !(viadev = dev_get_by_name(ipfwp->fwp_vianame)) ) {
1111 #ifdef DEBUG_IP_FIREWALL
1112                         printk("ip_fw_ctl: invalid device \"%s\"\n", ipfwp->fwp_vianame);
1113 #endif
1114                         return(EINVAL);
1115                 } else if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) {
1116 #ifdef DEBUG_IP_FIREWALL
1117                         printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
1118                                         sizeof(struct iphdr)/sizeof(int));
1119 #endif
1120                         dev_put(viadev);
1121                         return(EINVAL);
1122                 }
1123
1124                 /* Fix this one up by hand, who knows how many
1125                  * tools will break if we start to barf on this.
1126                  */
1127                 if (ntohs(ip->tot_len) > hdrlen)
1128                         ip->tot_len = htons(hdrlen);
1129
1130                 if ((tmp_skb = alloc_skb(hdrlen, GFP_ATOMIC)) == NULL) {
1131 #ifdef DEBUG_IP_FIREWALL
1132                         printk("ip_fw_ctl: tmp_skb alloc failure\n");
1133 #endif
1134                         dev_put(viadev);
1135                         return(EFAULT);
1136                 }
1137                 skb_reserve(tmp_skb, hdrlen);
1138                 skb_push(tmp_skb, hdrlen);
1139                 memcpy(tmp_skb->data, ip, hdrlen);
1140
1141                 ret = ip_fw_chk(&tmp_skb, viadev, NULL, *chains[fwtype],
1142                                 *policies[fwtype], IP_FW_MODE_CHK);
1143
1144                 kfree_skb(tmp_skb);
1145                 dev_put(viadev);
1146
1147                 switch (ret) {
1148                         case FW_ACCEPT:
1149                                 return(0);
1150                         case FW_REDIRECT:
1151                                 return(ECONNABORTED);
1152                         case FW_MASQUERADE:
1153                                 return(ECONNRESET);
1154                         case FW_REJECT:
1155                                 return(ECONNREFUSED);
1156                         default: /* FW_BLOCK */
1157                                 return(ETIMEDOUT);
1158                 }
1159         }
1160
1161         if ( cmd == IP_FW_MASQ_TIMEOUTS )
1162                 return ip_fw_masq_timeouts(m, len);
1163
1164 /*
1165  *      Here we really working hard-adding new elements
1166  *      to blocking/forwarding chains or deleting 'em
1167  */
1168
1169         if ( cmd == IP_FW_INSERT || cmd == IP_FW_APPEND || cmd == IP_FW_DELETE )
1170         {
1171                 struct ip_fw *frwl;
1172                 int fwtype;
1173
1174                 frwl=check_ipfw_struct(m,len);
1175                 if (frwl==NULL)
1176                         return (EINVAL);
1177                 fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1178
1179                 switch (cmd)
1180                 {
1181                         case IP_FW_INSERT:
1182                                 return(insert_in_chain(chains[fwtype],frwl,len));
1183                         case IP_FW_APPEND:
1184                                 return(append_to_chain(chains[fwtype],frwl,len));
1185                         case IP_FW_DELETE:
1186                                 return(del_from_chain(chains[fwtype],frwl));
1187                         default:
1188                         /*
1189                          *      Should be panic but... (Why are BSD people panic obsessed ??)
1190                          */
1191 #ifdef DEBUG_IP_FIREWALL
1192                                 printk("ip_fw_ctl:  unknown request %d\n",stage);
1193 #endif
1194                                 return(EINVAL);
1195                 }
1196         }
1197
1198 #ifdef DEBUG_IP_FIREWALL
1199         printk("ip_fw_ctl:  unknown request %d\n",stage);
1200 #endif
1201         return(ENOPROTOOPT);
1202 }
1203 #endif /* CONFIG_IP_FIREWALL */
1204
1205 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
1206 static int ip_chain_procinfo(int stage, char *buffer, char **start,
1207                              off_t offset, int length)
1208 {
1209         off_t pos=0, begin=0;
1210         struct ip_fw *i;
1211         int len, p;
1212         int last_len = 0;
1213
1214
1215         switch(stage)
1216         {
1217 #ifdef CONFIG_IP_FIREWALL
1218                 case IP_FW_IN:
1219                         i = ip_fw_in_chain;
1220                         len=sprintf(buffer, "IP firewall input rules, default %d\n",
1221                                 ip_fw_in_policy);
1222                         break;
1223                 case IP_FW_OUT:
1224                         i = ip_fw_out_chain;
1225                         len=sprintf(buffer, "IP firewall output rules, default %d\n",
1226                                 ip_fw_out_policy);
1227                         break;
1228                 case IP_FW_FWD:
1229                         i = ip_fw_fwd_chain;
1230                         len=sprintf(buffer, "IP firewall forward rules, default %d\n",
1231                                 ip_fw_fwd_policy);
1232                         break;
1233 #endif
1234 #ifdef CONFIG_IP_ACCT
1235                 case IP_FW_ACCT:
1236                         i = ip_acct_chain;
1237                         len=sprintf(buffer,"IP accounting rules\n");
1238                         break;
1239 #endif
1240                 default:
1241                         /* this should never be reached, but safety first... */
1242                         i = NULL;
1243                         len=0;
1244                         break;
1245         }
1246
1247         READ_LOCK(&ip_fw_lock);
1248
1249         while(i!=NULL)
1250         {
1251                 len+=sprintf(buffer+len,"%08X/%08X->%08X/%08X %.16s %08X %X ",
1252                         ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
1253                         ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
1254                         (i->fw_vianame)[0] ? i->fw_vianame : "-",
1255                         ntohl(i->fw_via.s_addr), i->fw_flg);
1256                 /* 10 is enough for a 32 bit box but the counters are 64bit on
1257                    the Alpha and Ultrapenguin */
1258                 len+=sprintf(buffer+len,"%u %u %-20lu %-20lu",
1259                         i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
1260                 for (p = 0; p < IP_FW_MAX_PORTS; p++)
1261                         len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
1262                 len+=sprintf(buffer+len, " A%02X X%02X", i->fw_tosand, i->fw_tosxor);
1263                 buffer[len++]='\n';
1264                 buffer[len]='\0';
1265                 pos=begin+len;
1266                 if(pos<offset)
1267                 {
1268                         len=0;
1269                         begin=pos;
1270                 }
1271                 else if(pos>offset+length)
1272                 {
1273                         len = last_len;
1274                         break;
1275                 }
1276                 last_len = len;
1277                 i=i->fw_next;
1278         }
1279         READ_UNLOCK(&ip_fw_lock);
1280         *start=buffer+(offset-begin);
1281         len-=(offset-begin);
1282         if(len>length)
1283                 len=length;
1284         return len;
1285 }
1286 #endif
1287
1288 #ifdef CONFIG_IP_ACCT
1289 static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
1290                             int length)
1291 {
1292         return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length);
1293 }
1294 #endif
1295
1296 #ifdef CONFIG_IP_FIREWALL
1297 static int ip_fw_in_procinfo(char *buffer, char **start, off_t offset,
1298                               int length)
1299 {
1300         return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length);
1301 }
1302
1303 static int ip_fw_out_procinfo(char *buffer, char **start, off_t offset,
1304                               int length)
1305 {
1306         return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length);
1307 }
1308
1309 static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
1310                               int length)
1311 {
1312         return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length);
1313 }
1314 #endif
1315
1316
1317 #ifdef CONFIG_IP_FIREWALL
1318 /*
1319  *      Interface to the generic firewall chains.
1320  */
1321
1322 int ipfw_input_check(struct firewall_ops *this, int pf,
1323                      struct net_device *dev, void *arg,
1324                      struct sk_buff **pskb)
1325 {
1326         return ip_fw_chk(pskb, dev, arg, ip_fw_in_chain, ip_fw_in_policy,
1327                          IP_FW_MODE_FW);
1328 }
1329
1330 int ipfw_output_check(struct firewall_ops *this, int pf,
1331                       struct net_device *dev, void *arg,
1332                       struct sk_buff **pskb)
1333 {
1334         return ip_fw_chk(pskb, dev, arg, ip_fw_out_chain, ip_fw_out_policy,
1335                          IP_FW_MODE_FW);
1336 }
1337
1338 int ipfw_forward_check(struct firewall_ops *this, int pf,
1339                        struct net_device *dev, void *arg,
1340                        struct sk_buff **pskb)
1341 {
1342         return ip_fw_chk(pskb, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy,
1343                          IP_FW_MODE_FW);
1344 }
1345
1346 #ifdef CONFIG_IP_ACCT
1347 int ipfw_acct_in(struct firewall_ops *this, int pf, struct net_device *dev,
1348                  void *arg, struct sk_buff **pskb)
1349 {
1350         return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN);
1351 }
1352
1353 int ipfw_acct_out(struct firewall_ops *this, int pf, struct net_device *dev,
1354                   void *arg, struct sk_buff **pskb)
1355 {
1356         return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
1357 }
1358 #endif
1359
1360 struct firewall_ops ipfw_ops = {
1361         .fw_forward     =       ipfw_forward_check,
1362         .fw_input       =       ipfw_input_check,
1363         .fw_output      =       ipfw_output_check,
1364 #ifdef CONFIG_IP_ACCT
1365         .fw_acct_in     =       ipfw_acct_in,
1366         .fw_acct_out    =       ipfw_acct_out,
1367 #endif
1368 };
1369
1370 #endif
1371
1372 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
1373
1374 int ipfw_device_event(struct notifier_block *this, unsigned long event, void *ptr)
1375 {
1376         struct net_device *dev=ptr;
1377         char *devname = dev->name;
1378         struct ip_fw *fw;
1379         int chn;
1380
1381         WRITE_LOCK(&ip_fw_lock);
1382
1383         if (event == NETDEV_UP) {
1384                 for (chn = 0; chn < IP_FW_CHAINS; chn++)
1385                         for (fw = *chains[chn]; fw; fw = fw->fw_next)
1386                                 if ((fw->fw_vianame)[0] && !strncmp(devname,
1387                                             fw->fw_vianame, IFNAMSIZ)) {
1388                                         dev_hold(dev);
1389                                         fw->fw_viadev = dev;
1390                                 }
1391         } else if (event == NETDEV_DOWN) {
1392                 for (chn = 0; chn < IP_FW_CHAINS; chn++)
1393                         for (fw = *chains[chn]; fw; fw = fw->fw_next)
1394                                 /* we could compare just the pointers ... */
1395                                 if ((fw->fw_vianame)[0] && !strncmp(devname,
1396                                                     fw->fw_vianame, IFNAMSIZ)){
1397                                         if (fw->fw_viadev
1398                                             && fw->fw_viadev != (struct net_device *)-1)
1399                                                 dev_put(fw->fw_viadev);
1400                                         fw->fw_viadev = (struct net_device*)-1;
1401                                 }
1402         }
1403
1404         WRITE_UNLOCK(&ip_fw_lock);
1405         return NOTIFY_DONE;
1406 }
1407
1408 static struct notifier_block ipfw_dev_notifier = {
1409         .notifier_call  =       ipfw_device_event,
1410 };
1411
1412 #endif
1413
1414 int ipfw_init_or_cleanup(int init)
1415 {
1416         int ret = 0;
1417
1418         if (!init)
1419                 goto cleanup;
1420
1421         ret = register_firewall(PF_INET, &ipfw_ops);
1422         if (ret < 0)
1423                 goto cleanup_nothing;
1424
1425 #ifdef CONFIG_IP_ACCT
1426         proc_net_create("ip_acct", S_IFREG | S_IRUGO | S_IWUSR, ip_acct_procinfo);
1427 #endif
1428         proc_net_create("ip_input", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_in_procinfo);
1429         proc_net_create("ip_output", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_out_procinfo);
1430         proc_net_create("ip_forward", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_fwd_procinfo);
1431
1432         /* Register for device up/down reports */
1433         register_netdevice_notifier(&ipfw_dev_notifier);
1434
1435 #ifdef CONFIG_IP_FIREWALL_NETLINK
1436         ipfwsk = netlink_kernel_create(NETLINK_FIREWALL, NULL);
1437 #endif
1438         return ret;
1439
1440  cleanup:
1441 #ifdef CONFIG_IP_FIREWALL_NETLINK
1442         sock_release(ipfwsk->sk_socket);
1443 #endif
1444         unregister_netdevice_notifier(&ipfw_dev_notifier);
1445
1446 #ifdef CONFIG_IP_ACCT
1447         proc_net_remove("ip_acct");
1448 #endif
1449         proc_net_remove("ip_input");
1450         proc_net_remove("ip_output");
1451         proc_net_remove("ip_forward");
1452
1453         free_fw_chain(chains[IP_FW_FWD]);
1454         free_fw_chain(chains[IP_FW_IN]);
1455         free_fw_chain(chains[IP_FW_OUT]);
1456         free_fw_chain(chains[IP_FW_ACCT]);
1457
1458         unregister_firewall(PF_INET, &ipfw_ops);
1459
1460  cleanup_nothing:
1461         return ret;
1462 }