1 #warning ipfwadm is obsolete, and will be removed soon.
3 /* Minor modifications to fit on compatibility framework:
4 Rusty.Russell@rustcorp.com.au
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
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.
25 * $Id: ipfwadm_core.c,v 1.11 2002/01/24 15:50:31 davem Exp $
27 * Ported from BSD to Linux,
28 * Alan Cox 22/Nov/1994.
29 * Zeroing /proc and other additions
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
40 * Established connections (ACK check), ACK check on bidirectional rules,
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
62 * Masquerading functionality
64 * Copyright (c) 1994 Pauline Middelink
66 * The pieces which added masquerading functionality are totally
67 * my responsibility and have nothing to with the original authors
70 * Parts distributed under GPL.
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
80 * Juan Jose Ciarlante : Masquerading code moved to ip_masq.c
81 * Andi Kleen : Print frag_offsets and the ip flags properly.
83 * All the real work was done by .....
89 * Copyright (c) 1993 Daniel Boulet
90 * Copyright (c) 1994 Ugen J.S.Antsilevich
92 * Redistribution and use in source forms, with and without modification,
93 * are permitted provided that this entire comment appears intact.
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.
99 * This software is provided ``AS IS'' without any warranties of any kind.
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>
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>
119 #include <net/protocol.h>
120 #include <net/route.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>
133 #include <net/checksum.h>
134 #include <linux/proc_fs.h>
135 #include <linux/stat.h>
137 MODULE_LICENSE("Dual BSD/GPL");
138 MODULE_DESCRIPTION("ipfwadm backwards compatibility layer");
141 * Implement IP packet firewall
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)
151 #define dprintf2(a1,a2)
152 #define dprintf3(a1,a2,a3)
153 #define dprintf4(a1,a2,a3,a4)
156 #define print_ip(a) printk("%u.%u.%u.%u", NIPQUAD(a));
158 #ifdef DEBUG_IP_FIREWALL
159 #define dprint_ip(a) print_ip(a)
164 static DECLARE_RWLOCK(ip_fw_lock);
166 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
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;
174 static struct ip_fw **chains[] =
175 {&ip_fw_fwd_chain, &ip_fw_in_chain, &ip_fw_out_chain, &ip_acct_chain,
178 #endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
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;
185 static int *policies[] =
186 {&ip_fw_fwd_policy, &ip_fw_in_policy, &ip_fw_out_policy};
190 #ifdef CONFIG_IP_FIREWALL_NETLINK
195 * Returns 1 if the port is matched by the vector, 0 otherwise
198 extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
204 if ( portptr[0] <= port && port <= portptr[1] )
211 while ( nports-- > 0 )
213 if ( *portptr++ == port )
221 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
223 #ifdef CONFIG_IP_FIREWALL_VERBOSE
226 * VERY ugly piece of code which actually makes kernel printf for
230 static char *chain_name(struct ip_fw *chain, int mode)
233 case IP_FW_MODE_ACCT_IN: return "acct in";
234 case IP_FW_MODE_ACCT_OUT: return "acct out";
236 if (chain == ip_fw_fwd_chain)
238 else if (chain == ip_fw_in_chain)
245 static char *rule_name(struct ip_fw *f, int mode, char *buf)
247 if (mode == IP_FW_MODE_ACCT_IN || mode == IP_FW_MODE_ACCT_OUT)
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]);
254 } else if(f->fw_flg&IP_FW_F_MASQ)
258 } else if(f->fw_flg&IP_FW_F_ICMPRPL) {
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)
269 __u32 *opt = (__u32 *) ((*pskb)->nh.iph + 1);
271 __u16 foff = ntohs((*pskb)->nh.iph->frag_off);
272 int protocol = (*pskb)->nh.iph->protocol;
274 printk(KERN_INFO "IP %s %s%s", chain, rule, devname);
284 printk(" ICMP/%d ", icmp_type);
287 printk(" PROTO=%d ", protocol);
291 print_ip((*pskb)->nh.iph->saddr);
292 if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
293 printk(":%hu", src_port);
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),
303 (*pskb)->nh.iph->ttl);
308 for (opti = 0; opti < ((*pskb)->nh.iph->ihl - sizeof(struct iphdr) / 4); opti++)
309 printk(" O=0x%8.8X", *opt++);
315 * Returns one of the generic firewall policies, like FW_ACCEPT.
316 * Also does accounting so you can feed it the accounting chain.
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).
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)
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;
337 unsigned char tosand, tosxor;
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.
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.
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
360 offset = ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET;
361 protocol = (*pskb)->nh.iph->protocol;
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
370 if (offset == 1 && protocol == IPPROTO_TCP)
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))
380 * Header fragment for TCP is too small to check the bits.
383 if (protocol == IPPROTO_TCP &&
384 ((*pskb)->nh.iph->ihl<<2)+16 > ntohs((*pskb)->nh.iph->tot_len))
390 * But only too short for a packet with ports...
393 else if ((ntohs((*pskb)->nh.iph->tot_len) <
394 8 + ((*pskb)->nh.iph->ihl << 2)) &&
395 (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP))
398 src = (*pskb)->nh.iph->saddr;
399 dst = (*pskb)->nh.iph->daddr;
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
413 /* ports stay 0xFFFF if it is not the first fragment */
415 struct tcphdr _tcph, *th;
417 th = skb_header_pointer(*pskb,
418 (*pskb)->nh.iph->ihl*4,
419 sizeof(_tcph), &_tcph);
423 src_port = ntohs(th->source);
424 dst_port = ntohs(th->dest);
426 if(!th->ack && !th->rst)
427 /* We do NOT have ACK, value TRUE */
429 if(!th->syn || !notcpack)
430 /* We do NOT have SYN, value TRUE */
437 /* ports stay 0xFFFF if it is not the first fragment */
439 struct udphdr _udph, *uh;
441 uh = skb_header_pointer(*pskb,
442 (*pskb)->nh.iph->ihl*4,
443 sizeof(_udph), &_udph);
447 src_port = ntohs(uh->source);
448 dst_port = ntohs(uh->dest);
453 /* icmp_type stays 255 if it is not the first fragment */
455 struct icmphdr _icmph, *ic;
457 ic = skb_header_pointer(*pskb,
458 (*pskb)->nh.iph->ihl*4,
464 icmp_type = (__u16) ic->type;
466 dprintf2("ICMP:%d ", icmp_type);
470 dprintf2("p=%d ", protocol);
474 #ifdef DEBUG_IP_FIREWALL
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);
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);
487 if (mode == IP_FW_MODE_CHK)
488 READ_LOCK(&ip_fw_lock);
490 WRITE_LOCK(&ip_fw_lock);
492 for (f = chain; f; f = f->fw_next) {
494 * This is a bit simpler as we don't have to walk
495 * an interface chain as you do in BSD - same logic
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.
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 */
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 */
527 * Look for a VIA device match
530 if (rif != f->fw_viadev)
531 continue; /* Mismatch */
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).
539 It will not affect performance if you will follow
540 the following simple rules:
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.
546 - avoid using fw_via.s_addr if fw_via.s_addr is owned
547 by an aliased interface.
551 if (f->fw_via.s_addr && rif) {
552 struct in_ifaddr *ifa;
554 if (rif->ip_ptr == NULL)
555 continue; /* Mismatch */
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)
562 continue; /* Mismatch */
568 * Ok the chain addresses match.
571 #ifdef CONFIG_IP_ACCT
573 * See if we're in accounting mode and only want to
574 * count incoming or outgoing packets.
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)))
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.
590 if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
593 if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
596 f_prt=f->fw_flg&IP_FW_F_KIND;
597 if (f_prt != IP_FW_F_ALL) {
599 * Specific firewall - packet's protocol
600 * must match firewall's.
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))))
623 #ifdef CONFIG_IP_FIREWALL_VERBOSE
624 if (f->fw_flg & IP_FW_F_PRN)
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 : "-");
634 if (mode != IP_FW_MODE_CHK) {
635 f->fw_bcnt += ntohs((*pskb)->nh.iph->tot_len);
638 if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)))
642 if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) {
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
652 tosand = f->fw_tosand;
653 tosxor = f->fw_tosxor;
659 if (policy & IP_FW_F_ACCEPT) {
660 /* Adjust priority and recompute checksum */
661 __u8 tos = (*pskb)->nh.iph->tos;
663 if (((tos & tosand) ^ tosxor) != tos) {
664 if (!skb_ip_make_writable(pskb,
665 offsetof(struct iphdr, tos)+1))
668 (*pskb)->nh.iph->tos = (tos & tosand) ^ tosxor;
669 ip_send_check((*pskb)->nh.iph);
672 #ifdef CONFIG_IP_TRANSPARENT_PROXY
673 if (policy & IP_FW_F_REDIR) {
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.
680 *redirport = htons(dst_port);
682 answer = FW_REDIRECT;
685 #ifdef CONFIG_IP_MASQUERADE
686 if (policy & IP_FW_F_MASQ)
687 answer = FW_MASQUERADE;
692 } else if (policy & IP_FW_F_ICMPRPL)
699 #ifdef CONFIG_IP_FIREWALL_NETLINK
700 if ((policy & IP_FW_F_PRN) && (answer == FW_REJECT || answer == FW_BLOCK))
702 struct sk_buff *skb = alloc_skb(128,
703 (mode == IP_FW_MODE_CHK) ?
704 GFP_KERNEL : GFP_ATOMIC);
706 int len = min_t(unsigned int,
708 ntohs((*pskb)->nh.iph->tot_len));
712 ((char *)(*pskb)->nh.iph -
713 (char *)(*pskb)->data),
715 if (netlink_post(NETLINK_FIREWALL, skb))
721 /* we're doing accounting, always ok */
724 if (mode == IP_FW_MODE_CHK)
725 READ_UNLOCK(&ip_fw_lock);
727 WRITE_UNLOCK(&ip_fw_lock);
733 static void zero_fw_chain(struct ip_fw *chainptr)
735 struct ip_fw *ctmp=chainptr;
737 WRITE_LOCK(&ip_fw_lock);
744 WRITE_UNLOCK(&ip_fw_lock);
747 static void free_fw_chain(struct ip_fw *volatile* chainptr)
749 WRITE_LOCK(&ip_fw_lock);
750 while ( *chainptr != NULL )
754 *chainptr = ftmp->fw_next;
756 && ftmp->fw_viadev != (struct net_device *)-1)
757 dev_put(ftmp->fw_viadev);
759 /* We will block in cleanup's unregister sockopt if unloaded,
761 module_put(THIS_MODULE);
763 WRITE_UNLOCK(&ip_fw_lock);
766 /* Volatiles to keep some of the compiler versions amused */
768 static int insert_in_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
772 /* Are we unloading now? We will block on nf_unregister_sockopt */
773 if (!try_module_get(THIS_MODULE))
776 ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL );
779 #ifdef DEBUG_IP_FIREWALL
780 printk("ip_fw_ctl: malloc said no\n");
785 memcpy(ftmp, frwl, len);
787 * Allow the more recent "minimise cost" flag to be
788 * set. [Rob van Nieuwkerk]
790 ftmp->fw_tosand |= 0x01;
791 ftmp->fw_tosxor &= 0xFE;
795 WRITE_LOCK(&ip_fw_lock);
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;
801 ftmp->fw_viadev = NULL;
803 ftmp->fw_next = *chainptr;
805 WRITE_UNLOCK(&ip_fw_lock);
809 static int append_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
812 struct ip_fw *chtmp=NULL;
813 struct ip_fw *volatile chtmp_prev=NULL;
815 /* Are we unloading now? We will block on nf_unregister_sockopt */
816 if (!try_module_get(THIS_MODULE))
819 ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL );
822 #ifdef DEBUG_IP_FIREWALL
823 printk("ip_fw_ctl: malloc said no\n");
828 memcpy(ftmp, frwl, len);
830 * Allow the more recent "minimise cost" flag to be
831 * set. [Rob van Nieuwkerk]
833 ftmp->fw_tosand |= 0x01;
834 ftmp->fw_tosxor &= 0xFE;
838 ftmp->fw_next = NULL;
840 WRITE_LOCK(&ip_fw_lock);
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;
846 ftmp->fw_viadev = NULL;
849 for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
853 chtmp_prev->fw_next=ftmp;
856 WRITE_UNLOCK(&ip_fw_lock);
860 static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
862 struct ip_fw *ftmp,*ltmp;
863 unsigned short tport1,tport2,tmpnum;
864 char matches,was_found;
866 WRITE_LOCK(&ip_fw_lock);
872 #ifdef DEBUG_IP_FIREWALL
873 printk("ip_fw_ctl: chain is empty\n");
875 WRITE_UNLOCK(&ip_fw_lock);
882 while( !was_found && ftmp != NULL )
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)
893 tport1=ftmp->fw_nsp+ftmp->fw_ndp;
894 tport2=frwl->fw_nsp+frwl->fw_ndp;
899 for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
900 if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
903 if (strncmp(ftmp->fw_vianame, frwl->fw_vianame, IFNAMSIZ))
909 && ftmp->fw_viadev != (struct net_device *)-1)
910 dev_put(ftmp->fw_viadev);
913 ltmp->fw_next=ftmp->fw_next;
919 *chainptr=ftmp->fw_next;
927 ftmp = ftmp->fw_next;
930 WRITE_UNLOCK(&ip_fw_lock);
932 /* We will block in cleanup's unregister sockopt if unloaded,
934 module_put(THIS_MODULE);
940 #endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
942 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
945 if ( len != sizeof(struct ip_fw) )
947 #ifdef DEBUG_IP_FIREWALL
948 printk("ip_fw_ctl: len=%d, want %d\n",len, sizeof(struct ip_fw));
953 if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
955 #ifdef DEBUG_IP_FIREWALL
956 printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
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");
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");
980 if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
982 #ifdef DEBUG_IP_FIREWALL
983 printk("ip_fw_ctl: src range set but fw_nsp=%d\n",
989 if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
991 #ifdef DEBUG_IP_FIREWALL
992 printk("ip_fw_ctl: dst range set but fw_ndp=%d\n",
998 if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) )
1000 #ifdef DEBUG_IP_FIREWALL
1001 printk("ip_fw_ctl: too many ports (%d+%d)\n",
1002 frwl->fw_nsp,frwl->fw_ndp);
1013 #ifdef CONFIG_IP_ACCT
1015 int ip_acct_ctl(int stage, void *m, int len)
1017 if ( stage == IP_ACCT_FLUSH )
1019 free_fw_chain(&ip_acct_chain);
1022 if ( stage == IP_ACCT_ZERO )
1024 zero_fw_chain(ip_acct_chain);
1027 if ( stage == IP_ACCT_INSERT || stage == IP_ACCT_APPEND ||
1028 stage == IP_ACCT_DELETE )
1032 if (!(frwl=check_ipfw_struct(m,len)))
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));
1045 * Should be panic but... (Why ??? - AC)
1047 #ifdef DEBUG_IP_FIREWALL
1048 printk("ip_acct_ctl: unknown request %d\n",stage);
1053 #ifdef DEBUG_IP_FIREWALL
1054 printk("ip_acct_ctl: unknown request %d\n",stage);
1060 #ifdef CONFIG_IP_FIREWALL
1061 int ip_fw_ctl(int stage, void *m, int len)
1065 cmd = stage & IP_FW_COMMAND;
1066 fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1068 if ( cmd == IP_FW_FLUSH )
1070 free_fw_chain(chains[fwtype]);
1074 if ( cmd == IP_FW_ZERO )
1076 zero_fw_chain(*chains[fwtype]);
1080 if ( cmd == IP_FW_POLICY )
1082 int *tmp_policy_ptr;
1083 tmp_policy_ptr=(int *)m;
1084 *policies[fwtype] = *tmp_policy_ptr;
1088 if ( cmd == IP_FW_CHECK )
1090 struct sk_buff *tmp_skb;
1091 struct net_device *viadev;
1092 struct ip_fwpkt *ipfwp;
1096 hdrlen = sizeof(struct ip_fwpkt) -
1097 sizeof(struct in_addr) -
1100 if ( len != sizeof(struct ip_fwpkt) )
1102 #ifdef DEBUG_IP_FIREWALL
1103 printk("ip_fw_ctl: length=%d, expected %d\n",
1104 len, sizeof(struct ip_fwpkt));
1109 ipfwp = (struct ip_fwpkt *)m;
1110 ip = &(ipfwp->fwp_iph);
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);
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));
1126 /* Fix this one up by hand, who knows how many
1127 * tools will break if we start to barf on this.
1129 if (ntohs(ip->tot_len) > hdrlen)
1130 ip->tot_len = htons(hdrlen);
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");
1139 skb_reserve(tmp_skb, hdrlen);
1140 skb_push(tmp_skb, hdrlen);
1141 memcpy(tmp_skb->data, ip, hdrlen);
1143 ret = ip_fw_chk(&tmp_skb, viadev, NULL, *chains[fwtype],
1144 *policies[fwtype], IP_FW_MODE_CHK);
1153 return(ECONNABORTED);
1157 return(ECONNREFUSED);
1158 default: /* FW_BLOCK */
1163 if ( cmd == IP_FW_MASQ_TIMEOUTS )
1164 return ip_fw_masq_timeouts(m, len);
1167 * Here we really working hard-adding new elements
1168 * to blocking/forwarding chains or deleting 'em
1171 if ( cmd == IP_FW_INSERT || cmd == IP_FW_APPEND || cmd == IP_FW_DELETE )
1176 frwl=check_ipfw_struct(m,len);
1179 fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1184 return(insert_in_chain(chains[fwtype],frwl,len));
1186 return(append_to_chain(chains[fwtype],frwl,len));
1188 return(del_from_chain(chains[fwtype],frwl));
1191 * Should be panic but... (Why are BSD people panic obsessed ??)
1193 #ifdef DEBUG_IP_FIREWALL
1194 printk("ip_fw_ctl: unknown request %d\n",stage);
1200 #ifdef DEBUG_IP_FIREWALL
1201 printk("ip_fw_ctl: unknown request %d\n",stage);
1203 return(ENOPROTOOPT);
1205 #endif /* CONFIG_IP_FIREWALL */
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)
1211 off_t pos=0, begin=0;
1219 #ifdef CONFIG_IP_FIREWALL
1222 len=sprintf(buffer, "IP firewall input rules, default %d\n",
1226 i = ip_fw_out_chain;
1227 len=sprintf(buffer, "IP firewall output rules, default %d\n",
1231 i = ip_fw_fwd_chain;
1232 len=sprintf(buffer, "IP firewall forward rules, default %d\n",
1236 #ifdef CONFIG_IP_ACCT
1239 len=sprintf(buffer,"IP accounting rules\n");
1243 /* this should never be reached, but safety first... */
1249 READ_LOCK(&ip_fw_lock);
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);
1273 else if(pos>offset+length)
1281 READ_UNLOCK(&ip_fw_lock);
1282 *start=buffer+(offset-begin);
1283 len-=(offset-begin);
1290 #ifdef CONFIG_IP_ACCT
1291 static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
1294 return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length);
1298 #ifdef CONFIG_IP_FIREWALL
1299 static int ip_fw_in_procinfo(char *buffer, char **start, off_t offset,
1302 return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length);
1305 static int ip_fw_out_procinfo(char *buffer, char **start, off_t offset,
1308 return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length);
1311 static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
1314 return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length);
1319 #ifdef CONFIG_IP_FIREWALL
1321 * Interface to the generic firewall chains.
1324 int ipfw_input_check(struct firewall_ops *this, int pf,
1325 struct net_device *dev, void *arg,
1326 struct sk_buff **pskb)
1328 return ip_fw_chk(pskb, dev, arg, ip_fw_in_chain, ip_fw_in_policy,
1332 int ipfw_output_check(struct firewall_ops *this, int pf,
1333 struct net_device *dev, void *arg,
1334 struct sk_buff **pskb)
1336 return ip_fw_chk(pskb, dev, arg, ip_fw_out_chain, ip_fw_out_policy,
1340 int ipfw_forward_check(struct firewall_ops *this, int pf,
1341 struct net_device *dev, void *arg,
1342 struct sk_buff **pskb)
1344 return ip_fw_chk(pskb, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy,
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)
1352 return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN);
1355 int ipfw_acct_out(struct firewall_ops *this, int pf, struct net_device *dev,
1356 void *arg, struct sk_buff **pskb)
1358 return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
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,
1374 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
1376 int ipfw_device_event(struct notifier_block *this, unsigned long event, void *ptr)
1378 struct net_device *dev=ptr;
1379 char *devname = dev->name;
1383 WRITE_LOCK(&ip_fw_lock);
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)) {
1391 fw->fw_viadev = dev;
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)){
1400 && fw->fw_viadev != (struct net_device *)-1)
1401 dev_put(fw->fw_viadev);
1402 fw->fw_viadev = (struct net_device*)-1;
1406 WRITE_UNLOCK(&ip_fw_lock);
1410 static struct notifier_block ipfw_dev_notifier = {
1411 .notifier_call = ipfw_device_event,
1416 int ipfw_init_or_cleanup(int init)
1423 ret = register_firewall(PF_INET, &ipfw_ops);
1425 goto cleanup_nothing;
1427 #ifdef CONFIG_IP_ACCT
1428 proc_net_create("ip_acct", S_IFREG | S_IRUGO | S_IWUSR, ip_acct_procinfo);
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);
1434 /* Register for device up/down reports */
1435 register_netdevice_notifier(&ipfw_dev_notifier);
1437 #ifdef CONFIG_IP_FIREWALL_NETLINK
1438 ipfwsk = netlink_kernel_create(NETLINK_FIREWALL, NULL);
1443 #ifdef CONFIG_IP_FIREWALL_NETLINK
1444 sock_release(ipfwsk->sk_socket);
1446 unregister_netdevice_notifier(&ipfw_dev_notifier);
1448 #ifdef CONFIG_IP_ACCT
1449 proc_net_remove("ip_acct");
1451 proc_net_remove("ip_input");
1452 proc_net_remove("ip_output");
1453 proc_net_remove("ip_forward");
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]);
1460 unregister_firewall(PF_INET, &ipfw_ops);