aboutsummaryrefslogtreecommitdiff
path: root/pfinet/linux-inet/ip_fw.c
diff options
context:
space:
mode:
Diffstat (limited to 'pfinet/linux-inet/ip_fw.c')
-rw-r--r--pfinet/linux-inet/ip_fw.c1016
1 files changed, 0 insertions, 1016 deletions
diff --git a/pfinet/linux-inet/ip_fw.c b/pfinet/linux-inet/ip_fw.c
deleted file mode 100644
index 0572c8f1..00000000
--- a/pfinet/linux-inet/ip_fw.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * IP firewalling code. This is taken from 4.4BSD. Please note the
- * copyright message below. As per the GPL it must be maintained
- * and the licenses thus do not conflict. While this port is subject
- * to the GPL I also place my modifications under the original
- * license in recognition of the original copyright.
- * -- Alan Cox.
- *
- * Ported from BSD to Linux,
- * Alan Cox 22/Nov/1994.
- * Zeroing /proc and other additions
- * Jos Vos 4/Feb/1995.
- * Merged and included the FreeBSD-Current changes at Ugen's request
- * (but hey it's a lot cleaner now). Ugen would prefer in some ways
- * we waited for his final product but since Linux 1.2.0 is about to
- * appear it's not practical - Read: It works, it's not clean but please
- * don't consider it to be his standard of finished work.
- * Alan Cox 12/Feb/1995
- * Porting bidirectional entries from BSD, fixing accounting issues,
- * adding struct ip_fwpkt for checking packets with interface address
- * Jos Vos 5/Mar/1995.
- *
- * All the real work was done by .....
- */
-
-/*
- * Copyright (c) 1993 Daniel Boulet
- * Copyright (c) 1994 Ugen J.S.Antsilevich
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- */
-
-#include <linux/config.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/config.h>
-
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/icmp.h>
-#include <linux/udp.h>
-#include "ip.h"
-#include "protocol.h"
-#include "route.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "icmp.h"
-#include <linux/ip_fw.h>
-
-/*
- * Implement IP packet firewall
- */
-
-#ifdef CONFIG_IPFIREWALL_DEBUG
-#define dprintf1(a) printk(a)
-#define dprintf2(a1,a2) printk(a1,a2)
-#define dprintf3(a1,a2,a3) printk(a1,a2,a3)
-#define dprintf4(a1,a2,a3,a4) printk(a1,a2,a3,a4)
-#else
-#define dprintf1(a)
-#define dprintf2(a1,a2)
-#define dprintf3(a1,a2,a3)
-#define dprintf4(a1,a2,a3,a4)
-#endif
-
-#define print_ip(a) printf("%d.%d.%d.%d",(ntohl(a.s_addr)>>24)&0xFF,\
- (ntohl(a.s_addr)>>16)&0xFF,\
- (ntohl(a.s_addr)>>8)&0xFF,\
- (ntohl(a.s_addr))&0xFF);
-
-#ifdef IPFIREWALL_DEBUG
-#define dprint_ip(a) print_ip(a)
-#else
-#define dprint_ip(a)
-#endif
-
-#ifdef CONFIG_IP_FIREWALL
-struct ip_fw *ip_fw_fwd_chain;
-struct ip_fw *ip_fw_blk_chain;
-int ip_fw_blk_policy=IP_FW_F_ACCEPT;
-int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
-#endif
-#ifdef CONFIG_IP_ACCT
-struct ip_fw *ip_acct_chain;
-#endif
-
-#define IP_INFO_BLK 0
-#define IP_INFO_FWD 1
-#define IP_INFO_ACCT 2
-
-
-/*
- * Returns 1 if the port is matched by the vector, 0 otherwise
- */
-
-extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
-{
- if (!nports)
- return 1;
- if ( range_flag )
- {
- if ( portptr[0] <= port && port <= portptr[1] )
- {
- return( 1 );
- }
- nports -= 2;
- portptr += 2;
- }
- while ( nports-- > 0 )
- {
- if ( *portptr++ == port )
- {
- return( 1 );
- }
- }
- return(0);
-}
-
-#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
-
-
-/*
- * Returns 0 if packet should be dropped, 1 if it should be accepted,
- * and -1 if an ICMP host unreachable packet should be sent.
- * Also does accounting so you can feed it the accounting chain.
- * If opt is set to 1, it means that we do this for accounting
- * purposes (searches all entries and handles fragments different).
- * If opt is set to 2, it doesn't count a matching packet, which
- * is used when calling this for checking purposes (IP_FW_CHK_*).
- */
-
-
-int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
-{
- struct ip_fw *f;
- struct tcphdr *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
- struct udphdr *udp=(struct udphdr *)((unsigned long *)ip+ip->ihl);
- __u32 src, dst;
- __u16 src_port=0, dst_port=0;
- unsigned short f_prt=0, prt;
- char notcpsyn=1, frag1, match;
- unsigned short f_flag;
-
- /*
- * If the chain is empty follow policy. The BSD one
- * accepts anything giving you a time window while
- * flushing and rebuilding the tables.
- */
-
- src = ip->saddr;
- dst = ip->daddr;
-
- /*
- * This way we handle fragmented packets.
- * we ignore all fragments but the first one
- * so the whole packet can't be reassembled.
- * This way we relay on the full info which
- * stored only in first packet.
- *
- * Note that this theoretically allows partial packet
- * spoofing. Not very dangerous but paranoid people may
- * wish to play with this. It also allows the so called
- * "fragment bomb" denial of service attack on some types
- * of system.
- */
-
- frag1 = ((ntohs(ip->frag_off) & IP_OFFSET) == 0);
- if (!frag1 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
- ip->protocol == IPPROTO_UDP))
- return(1);
-
- src = ip->saddr;
- dst = ip->daddr;
-
- /*
- * If we got interface from which packet came
- * we can use the address directly. This is unlike
- * 4.4BSD derived systems that have an address chain
- * per device. We have a device per address with dummy
- * devices instead.
- */
-
- dprintf1("Packet ");
- switch(ip->protocol)
- {
- case IPPROTO_TCP:
- dprintf1("TCP ");
- /* ports stay 0 if it is not the first fragment */
- if (frag1) {
- src_port=ntohs(tcp->source);
- dst_port=ntohs(tcp->dest);
- if(tcp->syn && !tcp->ack)
- /* We *DO* have SYN, value FALSE */
- notcpsyn=0;
- }
- prt=IP_FW_F_TCP;
- break;
- case IPPROTO_UDP:
- dprintf1("UDP ");
- /* ports stay 0 if it is not the first fragment */
- if (frag1) {
- src_port=ntohs(udp->source);
- dst_port=ntohs(udp->dest);
- }
- prt=IP_FW_F_UDP;
- break;
- case IPPROTO_ICMP:
- dprintf2("ICMP:%d ",((char *)portptr)[0]&0xff);
- prt=IP_FW_F_ICMP;
- break;
- default:
- dprintf2("p=%d ",ip->protocol);
- prt=IP_FW_F_ALL;
- break;
- }
- dprint_ip(ip->saddr);
-
- if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
- /* This will print 0 when it is not the first fragment! */
- dprintf2(":%d ", src_port);
- dprint_ip(ip->daddr);
- if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
- /* This will print 0 when it is not the first fragment! */
- dprintf2(":%d ",dst_port);
- dprintf1("\n");
-
- for (f=chain;f;f=f->fw_next)
- {
- /*
- * This is a bit simpler as we don't have to walk
- * an interface chain as you do in BSD - same logic
- * however.
- */
-
- /*
- * Match can become 0x01 (a "normal" match was found),
- * 0x02 (a reverse match was found), and 0x03 (the
- * IP addresses match in both directions).
- * Now we know in which direction(s) we should look
- * for a match for the TCP/UDP ports. Both directions
- * might match (e.g., when both addresses are on the
- * same network for which an address/mask is given), but
- * the ports might only match in one direction.
- * This was obviously wrong in the original BSD code.
- */
- match = 0x00;
-
- if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
- && (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
- /* normal direction */
- match |= 0x01;
-
- if ((f->fw_flg & IP_FW_F_BIDIR) &&
- (dst&f->fw_smsk.s_addr)==f->fw_src.s_addr
- && (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
- /* reverse direction */
- match |= 0x02;
-
- if (match)
- {
- /*
- * Look for a VIA match
- */
- if(f->fw_via.s_addr && rif)
- {
- if(rif->pa_addr!=f->fw_via.s_addr)
- continue; /* Mismatch */
- }
- /*
- * Drop through - this is a match
- */
- }
- else
- continue;
-
- /*
- * Ok the chain addresses match.
- */
-
- f_prt=f->fw_flg&IP_FW_F_KIND;
- if (f_prt!=IP_FW_F_ALL)
- {
- /*
- * This is actually buggy as if you set SYN flag
- * on UDP or ICMP firewall it will never work,but
- * actually it is a concern of software which sets
- * firewall entries.
- */
-
- if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
- continue;
- /*
- * Specific firewall - packet's protocol
- * must match firewall's.
- */
-
- if(prt!=f_prt)
- continue;
-
- if(!(prt==IP_FW_F_ICMP || ((match & 0x01) &&
- port_match(&f->fw_pts[0], f->fw_nsp, src_port,
- f->fw_flg&IP_FW_F_SRNG) &&
- port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
- f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
- port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
- f->fw_flg&IP_FW_F_SRNG) &&
- port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
- f->fw_flg&IP_FW_F_DRNG))))
- {
- continue;
- }
- }
-#ifdef CONFIG_IP_FIREWALL_VERBOSE
- /*
- * VERY ugly piece of code which actually
- * makes kernel printf for denied packets...
- */
-
- if (f->fw_flg & IP_FW_F_PRN)
- {
- if(opt != 1) {
- if(f->fw_flg&IP_FW_F_ACCEPT)
- printk("Accept ");
- else if(f->fw_flg&IP_FW_F_ICMPRPL)
- printk("Reject ");
- else
- printk("Deny ");
- }
- switch(ip->protocol)
- {
- case IPPROTO_TCP:
- printk("TCP ");
- break;
- case IPPROTO_UDP:
- printk("UDP ");
- case IPPROTO_ICMP:
- printk("ICMP ");
- break;
- default:
- printk("p=%d ",ip->protocol);
- break;
- }
- print_ip(ip->saddr);
- if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%d", src_port);
- printk(" ");
- print_ip(ip->daddr);
- if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%d",dst_port);
- printk("\n");
- }
-#endif
- if (opt != 2) {
- f->fw_bcnt+=ntohs(ip->tot_len);
- f->fw_pcnt++;
- }
- if (opt != 1)
- break;
- } /* Loop */
-
- if(opt == 1)
- return 0;
-
- /*
- * We rely on policy defined in the rejecting entry or, if no match
- * was found, we rely on the general policy variable for this type
- * of firewall.
- */
-
- if(f!=NULL) /* A match was found */
- f_flag=f->fw_flg;
- else
- f_flag=policy;
- if(f_flag&IP_FW_F_ACCEPT)
- return 1;
- if(f_flag&IP_FW_F_ICMPRPL)
- return -1;
- return 0;
-}
-
-
-static void zero_fw_chain(struct ip_fw *chainptr)
-{
- struct ip_fw *ctmp=chainptr;
- while(ctmp)
- {
- ctmp->fw_pcnt=0L;
- ctmp->fw_bcnt=0L;
- ctmp=ctmp->fw_next;
- }
-}
-
-static void free_fw_chain(struct ip_fw *volatile* chainptr)
-{
- unsigned long flags;
- save_flags(flags);
- cli();
- while ( *chainptr != NULL )
- {
- struct ip_fw *ftmp;
- ftmp = *chainptr;
- *chainptr = ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- }
- restore_flags(flags);
-}
-
-/* Volatiles to keep some of the compiler versions amused */
-
-static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl)
-{
- struct ip_fw *ftmp;
- struct ip_fw *chtmp=NULL;
- struct ip_fw *volatile chtmp_prev=NULL;
- unsigned long flags;
- unsigned long m_src_mask,m_dst_mask;
- unsigned long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
- unsigned short n_sr,n_dr,o_sr,o_dr;
- unsigned short oldkind,newkind;
- int addb4=0;
- int n_o,n_n;
-
- save_flags(flags);
-
- ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
- if ( ftmp == NULL )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: malloc said no\n");
-#endif
- return( ENOMEM );
- }
-
- memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
-
- ftmp->fw_pcnt=0L;
- ftmp->fw_bcnt=0L;
-
- ftmp->fw_next = NULL;
-
- cli();
-
- if (*chainptr==NULL)
- {
- *chainptr=ftmp;
- }
- else
- {
- chtmp_prev=NULL;
- for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
- {
- addb4=0;
- newkind=ftmp->fw_flg & IP_FW_F_KIND;
- oldkind=chtmp->fw_flg & IP_FW_F_KIND;
-
- if (newkind!=IP_FW_F_ALL
- && oldkind!=IP_FW_F_ALL
- && oldkind!=newkind)
- {
- chtmp_prev=chtmp;
- continue;
- }
-
- /*
- * Very very *UGLY* code...
- * Sorry,but i had to do this....
- */
-
- n_sa=ntohl(ftmp->fw_src.s_addr);
- n_da=ntohl(ftmp->fw_dst.s_addr);
- n_sm=ntohl(ftmp->fw_smsk.s_addr);
- n_dm=ntohl(ftmp->fw_dmsk.s_addr);
-
- o_sa=ntohl(chtmp->fw_src.s_addr);
- o_da=ntohl(chtmp->fw_dst.s_addr);
- o_sm=ntohl(chtmp->fw_smsk.s_addr);
- o_dm=ntohl(chtmp->fw_dmsk.s_addr);
-
- m_src_mask = o_sm & n_sm;
- m_dst_mask = o_dm & n_dm;
-
- if ((o_sa & m_src_mask) == (n_sa & m_src_mask))
- {
- if (n_sm > o_sm)
- addb4++;
- if (n_sm < o_sm)
- addb4--;
- }
-
- if ((o_da & m_dst_mask) == (n_da & m_dst_mask))
- {
- if (n_dm > o_dm)
- addb4++;
- if (n_dm < o_dm)
- addb4--;
- }
-
- if (((o_da & o_dm) == (n_da & n_dm))
- &&((o_sa & o_sm) == (n_sa & n_sm)))
- {
- if (newkind!=IP_FW_F_ALL &&
- oldkind==IP_FW_F_ALL)
- addb4++;
- if (newkind==oldkind && (oldkind==IP_FW_F_TCP
- || oldkind==IP_FW_F_UDP))
- {
-
- /*
- * Here the main idea is to check the size
- * of port range which the frwl covers
- * We actually don't check their values but
- * just the wideness of range they have
- * so that less wide ranges or single ports
- * go first and wide ranges go later. No ports
- * at all treated as a range of maximum number
- * of ports.
- */
-
- if (ftmp->fw_flg & IP_FW_F_SRNG)
- n_sr=ftmp->fw_pts[1]-ftmp->fw_pts[0];
- else
- n_sr=(ftmp->fw_nsp)?
- ftmp->fw_nsp : 0xFFFF;
-
- if (chtmp->fw_flg & IP_FW_F_SRNG)
- o_sr=chtmp->fw_pts[1]-chtmp->fw_pts[0];
- else
- o_sr=(chtmp->fw_nsp)?chtmp->fw_nsp : 0xFFFF;
-
- if (n_sr<o_sr)
- addb4++;
- if (n_sr>o_sr)
- addb4--;
-
- n_n=ftmp->fw_nsp;
- n_o=chtmp->fw_nsp;
-
- /*
- * Actually this cannot happen as the frwl control
- * procedure checks for number of ports in source and
- * destination range but we will try to be more safe.
- */
-
- if ((n_n>(IP_FW_MAX_PORTS-2)) ||
- (n_o>(IP_FW_MAX_PORTS-2)))
- goto skip_check;
-
- if (ftmp->fw_flg & IP_FW_F_DRNG)
- n_dr=ftmp->fw_pts[n_n+1]-ftmp->fw_pts[n_n];
- else
- n_dr=(ftmp->fw_ndp)? ftmp->fw_ndp : 0xFFFF;
-
- if (chtmp->fw_flg & IP_FW_F_DRNG)
- o_dr=chtmp->fw_pts[n_o+1]-chtmp->fw_pts[n_o];
- else
- o_dr=(chtmp->fw_ndp)? chtmp->fw_ndp : 0xFFFF;
- if (n_dr<o_dr)
- addb4++;
- if (n_dr>o_dr)
- addb4--;
-skip_check:
- }
- /* finally look at the interface address */
- if ((addb4 == 0) && ftmp->fw_via.s_addr &&
- !(chtmp->fw_via.s_addr))
- addb4++;
- }
- if (addb4>0)
- {
- if (chtmp_prev)
- {
- chtmp_prev->fw_next=ftmp;
- ftmp->fw_next=chtmp;
- }
- else
- {
- *chainptr=ftmp;
- ftmp->fw_next=chtmp;
- }
- restore_flags(flags);
- return 0;
- }
- chtmp_prev=chtmp;
- }
- }
-
- if (chtmp_prev)
- chtmp_prev->fw_next=ftmp;
- else
- *chainptr=ftmp;
- restore_flags(flags);
- return(0);
-}
-
-static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
-{
- struct ip_fw *ftmp,*ltmp;
- unsigned short tport1,tport2,tmpnum;
- char matches,was_found;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- ftmp=*chainptr;
-
- if ( ftmp == NULL )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: chain is empty\n");
-#endif
- restore_flags(flags);
- return( EINVAL );
- }
-
- ltmp=NULL;
- was_found=0;
-
- while( ftmp != NULL )
- {
- matches=1;
- if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
- || ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
- || ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
- || ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
- || ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
- || ftmp->fw_flg!=frwl->fw_flg)
- matches=0;
-
- tport1=ftmp->fw_nsp+ftmp->fw_ndp;
- tport2=frwl->fw_nsp+frwl->fw_ndp;
- if (tport1!=tport2)
- matches=0;
- else if (tport1!=0)
- {
- for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
- if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
- matches=0;
- }
- if(matches)
- {
- was_found=1;
- if (ltmp)
- {
- ltmp->fw_next=ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- ftmp=ltmp->fw_next;
- }
- else
- {
- *chainptr=ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- ftmp=*chainptr;
- }
- }
- else
- {
- ltmp = ftmp;
- ftmp = ftmp->fw_next;
- }
- }
- restore_flags(flags);
- if (was_found)
- return 0;
- else
- return(EINVAL);
-}
-
-#endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
-
-struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
-{
-
- if ( len != sizeof(struct ip_fw) )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: len=%d, want %d\n",m->m_len,
- sizeof(struct ip_fw));
-#endif
- return(NULL);
- }
-
- if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
- frwl->fw_flg);
-#endif
- return(NULL);
- }
-
- if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: src range set but n_src_p=%d\n",
- frwl->fw_nsp);
-#endif
- return(NULL);
- }
-
- if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: dst range set but n_dst_p=%d\n",
- frwl->fw_ndp);
-#endif
- return(NULL);
- }
-
- if ( frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: too many ports (%d+%d)\n",
- frwl->fw_nsp,frwl->fw_ndp);
-#endif
- return(NULL);
- }
-
- return frwl;
-}
-
-
-
-
-#ifdef CONFIG_IP_ACCT
-
-void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
-{
- (void) ip_fw_chk(iph, dev, f, 0, 1);
- return;
-}
-
-int ip_acct_ctl(int stage, void *m, int len)
-{
- if ( stage == IP_ACCT_FLUSH )
- {
- free_fw_chain(&ip_acct_chain);
- return(0);
- }
- if ( stage == IP_ACCT_ZERO )
- {
- zero_fw_chain(ip_acct_chain);
- return(0);
- }
- if ( stage == IP_ACCT_ADD
- || stage == IP_ACCT_DEL
- )
- {
- struct ip_fw *frwl;
-
- if (!(frwl=check_ipfw_struct(m,len)))
- return (EINVAL);
-
- switch (stage)
- {
- case IP_ACCT_ADD:
- return( add_to_chain(&ip_acct_chain,frwl));
- case IP_ACCT_DEL:
- return( del_from_chain(&ip_acct_chain,frwl));
- default:
- /*
- * Should be panic but... (Why ??? - AC)
- */
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_acct_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
- }
- }
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_acct_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
-}
-#endif
-
-#ifdef CONFIG_IP_FIREWALL
-int ip_fw_ctl(int stage, void *m, int len)
-{
- int ret;
-
- if ( stage == IP_FW_FLUSH_BLK )
- {
- free_fw_chain(&ip_fw_blk_chain);
- return(0);
- }
-
- if ( stage == IP_FW_FLUSH_FWD )
- {
- free_fw_chain(&ip_fw_fwd_chain);
- return(0);
- }
-
- if ( stage == IP_FW_ZERO_BLK )
- {
- zero_fw_chain(ip_fw_blk_chain);
- return(0);
- }
-
- if ( stage == IP_FW_ZERO_FWD )
- {
- zero_fw_chain(ip_fw_fwd_chain);
- return(0);
- }
-
- if ( stage == IP_FW_POLICY_BLK || stage == IP_FW_POLICY_FWD )
- {
- int *tmp_policy_ptr;
- tmp_policy_ptr=(int *)m;
- if ( stage == IP_FW_POLICY_BLK )
- ip_fw_blk_policy=*tmp_policy_ptr;
- else
- ip_fw_fwd_policy=*tmp_policy_ptr;
- return 0;
- }
-
- if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
- {
- struct device viadev;
- struct ip_fwpkt *ipfwp;
- struct iphdr *ip;
-
- if ( len < sizeof(struct ip_fwpkt) )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: length=%d, expected %d\n",
- len, sizeof(struct ip_fwpkt));
-#endif
- return( EINVAL );
- }
-
- ipfwp = (struct ip_fwpkt *)m;
- ip = &(ipfwp->fwp_iph);
-
- if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
- sizeof(struct ip)/sizeof(int));
-#endif
- return(EINVAL);
- }
-
- viadev.pa_addr = ipfwp->fwp_via.s_addr;
-
- if ((ret = ip_fw_chk(ip, &viadev,
- stage == IP_FW_CHK_BLK ?
- ip_fw_blk_chain : ip_fw_fwd_chain,
- stage == IP_FW_CHK_BLK ?
- ip_fw_blk_policy : ip_fw_fwd_policy, 2 )) > 0
- )
- return(0);
- else if (ret == -1)
- return(ECONNREFUSED);
- else
- return(ETIMEDOUT);
- }
-
-/*
- * Here we really working hard-adding new elements
- * to blocking/forwarding chains or deleting 'em
- */
-
- if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
- || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
- )
- {
- struct ip_fw *frwl;
- frwl=check_ipfw_struct(m,len);
- if (frwl==NULL)
- return (EINVAL);
-
- switch (stage)
- {
- case IP_FW_ADD_BLK:
- return(add_to_chain(&ip_fw_blk_chain,frwl));
- case IP_FW_ADD_FWD:
- return(add_to_chain(&ip_fw_fwd_chain,frwl));
- case IP_FW_DEL_BLK:
- return(del_from_chain(&ip_fw_blk_chain,frwl));
- case IP_FW_DEL_FWD:
- return(del_from_chain(&ip_fw_fwd_chain,frwl));
- default:
- /*
- * Should be panic but... (Why are BSD people panic obsessed ??)
- */
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
- }
- }
-
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
-}
-#endif /* CONFIG_IP_FIREWALL */
-
-#if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
-
-static int ip_chain_procinfo(int stage, char *buffer, char **start,
- off_t offset, int length, int reset)
-{
- off_t pos=0, begin=0;
- struct ip_fw *i;
- unsigned long flags;
- int len, p;
-
-
- switch(stage)
- {
-#ifdef CONFIG_IP_FIREWALL
- case IP_INFO_BLK:
- i = ip_fw_blk_chain;
- len=sprintf(buffer, "IP firewall block rules, default %d\n",
- ip_fw_blk_policy);
- break;
- case IP_INFO_FWD:
- i = ip_fw_fwd_chain;
- len=sprintf(buffer, "IP firewall forward rules, default %d\n",
- ip_fw_fwd_policy);
- break;
-#endif
-#ifdef CONFIG_IP_ACCT
- case IP_INFO_ACCT:
- i = ip_acct_chain;
- len=sprintf(buffer,"IP accounting rules\n");
- break;
-#endif
- default:
- /* this should never be reached, but safety first... */
- i = NULL;
- len=0;
- break;
- }
-
- save_flags(flags);
- cli();
-
- while(i!=NULL)
- {
- len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %08lX %X ",
- ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
- ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
- ntohl(i->fw_via.s_addr),i->fw_flg);
- len+=sprintf(buffer+len,"%u %u %lu %lu",
- i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
- for (p = 0; p < IP_FW_MAX_PORTS; p++)
- len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
- buffer[len++]='\n';
- buffer[len]='\0';
- pos=begin+len;
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- else if(reset)
- {
- /* This needs to be done at this specific place! */
- i->fw_pcnt=0L;
- i->fw_bcnt=0L;
- }
- if(pos>offset+length)
- break;
- i=i->fw_next;
- }
- restore_flags(flags);
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- return len;
-}
-#endif
-
-#ifdef CONFIG_IP_ACCT
-
-int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
-{
- return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,reset);
-}
-
-#endif
-
-#ifdef CONFIG_IP_FIREWALL
-
-int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
-{
- return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,reset);
-}
-
-int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
-{
- return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,reset);
-}
-
-#endif