diff options
-rw-r--r-- | sys/netinet/ip_fw.c | 678 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 45 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 21 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 18 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 19 |
5 files changed, 518 insertions, 263 deletions
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 3b2f938..293f469 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -24,25 +24,30 @@ #include <sys/protosw.h> #include <sys/socket.h> #include <sys/errno.h> -#include <sys/time.h> +#include <sys/time.h> #include <sys/kernel.h> #include <net/if.h> #include <net/route.h> + #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> #include <netinet/ip_icmp.h> +#include <arpa/inet.h> + #include <netinet/ip_fw.h> +#ifdef IPFIREWALL struct ip_fw *ip_fw_fwd_chain; struct ip_fw *ip_fw_blk_chain; int ip_fw_policy=1; +#endif +#ifdef IPACCT +struct ip_fw *ip_acct_chain; +#endif inline @@ -61,7 +66,6 @@ struct in_addr xaddr; /* * Returns 1 if the port is matched by the vector, 0 otherwise */ - inline int port_match(portptr,nports,port,range_flag) u_short *portptr; @@ -69,6 +73,8 @@ int nports; u_short port; int range_flag; { + if (!nports) + return 1; if ( range_flag ) { if ( portptr[0] <= port && port <= portptr[1] ) { return( 1 ); @@ -89,22 +95,20 @@ int range_flag; * Returns 0 if packet should be dropped, 1 or more if it should be accepted */ - +#ifdef IPFIREWALL int ip_fw_chk(ip,chain) struct ip *ip; struct ip_fw *chain; { struct in_addr src, dst; - char got_proto = 0; - int frwl_proto, proto = 0; - register struct ip_fw *fptr; - u_short src_port = 0, dst_port = 0; -#ifdef IPFIREWALL_VERBOSE - u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]); -#endif - - if ( chain == NULL ) { /* Is there a frwl chain? */ - return(1); + char got_proto=0; + int frwl_proto, proto=0; + register struct ip_fw *f; + u_short src_port=0, dst_port=0; + u_short *portptr=(u_short *)&(((u_int *)ip)[ip->ip_hl]); + + if (!chain) { + return(1); /* If no chain , always say Ok to packet */ } src = ip->ip_src; @@ -112,142 +116,149 @@ struct ip_fw *chain; #ifdef DEBUG_IPFIREWALL { - u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]); printf("packet "); switch(ip->ip_p) { - case IPPROTO_TCP: printf("TCP "); break; - case IPPROTO_UDP: printf("UDP "); break; - case IPPROTO_ICMP: printf("ICMP:%d ",((char *)portptr)[0]&0xff); break; - default: printf("p=%d ",ip->ip_p); break; + case IPPROTO_TCP: + printf("TCP "); + break; + case IPPROTO_UDP: + printf("UDP "); + break; + case IPPROTO_ICMP: + printf("ICMP:%d ",((char *)portptr)[0]&0xff); + break; + default: + printf("p=%d ",ip->ip_p); + break; } print_ip(ip->ip_src); - if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { + if (ip->ip_p==IPPROTO_TCP || ip->ip_p==IPPROTO_UDP) { printf(":%d ",ntohs(portptr[0])); } print_ip(ip->ip_dst); - if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { + if ( ip->ip_p==IPPROTO_TCP || ip->ip_p==IPPROTO_UDP) { printf(":%d ",ntohs(portptr[1])); } printf("\n"); } #endif - for ( fptr = chain; fptr != NULL; fptr = fptr->next ) { - - if ( (src.s_addr & fptr->src_mask.s_addr) == fptr->src.s_addr - && (dst.s_addr & fptr->dst_mask.s_addr) == fptr->dst.s_addr ) { - - if ( (frwl_proto = fptr->flags & IP_FW_F_KIND) - == IP_FW_F_ALL ) { - - /* Universal frwl - we've got a match! */ + for (f=chain;f;f=f->next) + if ((src.s_addr&f->src_mask.s_addr)==f->src.s_addr + && (dst.s_addr&f->dst_mask.s_addr)==f->dst.s_addr) { + frwl_proto=f->flags&IP_FW_F_KIND; + if (frwl_proto==IP_FW_F_ALL) { + /* Universal frwl - we've got a match! */ #ifdef DEBUG_IPFIREWALL printf("universal frwl match\n"); #endif #ifdef IPFIREWALL_VERBOSE - /* - * VERY ugly piece of code which actually - * makes kernel printf for denyed packets... - * This thingy will be added in more places... - */ - if ( !(fptr->flags & IP_FW_F_ACCEPT) && - (fptr->flags & IP_FW_F_PRN)) { - printf("ip_fw_chk says no to "); - switch(ip->ip_p) { - case IPPROTO_TCP: printf("TCP "); break; - case IPPROTO_UDP: printf("UDP "); break; - case IPPROTO_ICMP: printf("ICMP:%d ",((char *)portptr)[0]&0xff); break; - default: printf("p=%d ",ip->ip_p); break; - } - print_ip(ip->ip_src); - if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { - printf(":%d ",ntohs(portptr[0])); - } else { - printf("\n"); - } - print_ip(ip->ip_dst); - if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { - printf(":%d ",ntohs(portptr[1])); - } - printf("\n"); - return(0); - } + if (!(f->flags & IP_FW_F_ACCEPT)) + goto bad_packet; + return 1; +#else + return( f->flags & IP_FW_F_ACCEPT ); #endif - return( fptr->flags & IP_FW_F_ACCEPT ); } else { - - /* Specific frwl - packet's protocol must match frwl's */ - - if ( !got_proto ) { - u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]); - switch( ip->ip_p ) { - case IPPROTO_TCP: - proto = IP_FW_F_TCP; - src_port = ntohs(portptr[0]); /* first two shorts in TCP */ - dst_port = ntohs(portptr[1]); /* are src and dst ports */ - break; - case IPPROTO_UDP: - proto = IP_FW_F_UDP; - src_port = ntohs(portptr[0]); /* first two shorts in UDP */ - dst_port = ntohs(portptr[1]); /* are src and dst ports */ - break; + /* + * Specific firewall - packet's + * protocol must match firewall's + */ + if (!got_proto) { + /* + * We still had not determined the protocol + * of this packet,now the time to do so. + */ + switch(ip->ip_p) { + case IPPROTO_TCP: + /* + * First two shorts in TCP are src/dst ports + */ + proto=IP_FW_F_TCP; + src_port=ntohs(portptr[0]); + dst_port=ntohs(portptr[1]); + break; + case IPPROTO_UDP: + /* + * First two shorts in UDP are src/dst ports + */ + proto = IP_FW_F_UDP; + src_port = ntohs(portptr[0]); + dst_port = ntohs(portptr[1]); + break; case IPPROTO_ICMP: - proto = IP_FW_F_ICMP; - break; - default: proto = IP_FW_F_ALL; + proto=IP_FW_F_ICMP; + break; + default: + proto=IP_FW_F_ALL; #ifdef DEBUG_IPFIREWALL - printf("non TCP/UDP packet\n"); + printf("non TCP/UDP packet\n"); #endif - } - got_proto = 1; - } + } + got_proto=1; + } + /* + * At this moment we surely know the protocol of this + * packet and we'll check if it matches,then proceed futher.. + */ + if (proto==frwl_proto) { + + if (proto==IP_FW_F_ICMP || + (port_match(&f->ports[0],f->n_src_p,src_port, + f->flags&IP_FW_F_SRNG) && + port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port, + f->flags&IP_FW_F_DRNG))) { +#ifdef IPFIREWALL_VERBOSE + if (!(f->flags & IP_FW_F_ACCEPT)) + goto bad_packet; + return 1; +#else + return( f->flags & IP_FW_F_ACCEPT); +#endif + } /* Ports match */ + } /* Proto matches */ + } /* ALL/Specific */ +} /* IP addr/mask matches */ - if ( proto == frwl_proto ) { - - if ( - proto == IP_FW_F_ICMP - || - ( - ( - fptr->n_src_p == 0 - || - port_match( &fptr->ports[0], - fptr->n_src_p, - src_port, - fptr->flags & IP_FW_F_SRNG - ) - ) - && - ( - fptr->n_dst_p == 0 - || - port_match( &fptr->ports[fptr->n_src_p], - fptr->n_dst_p, - dst_port, - fptr->flags & IP_FW_F_DRNG - ) - ) - ) - ) { + /* + * If we get here then none of the firewalls matched. + * So now we relay on policy defined by user-unmatched packet can + * be ever accepted or rejected... + */ + +#ifdef IPFIREWALL_VERBOSE + if (!(ip_fw_policy)) + goto bad_packet; + return 1; +#else + return(ip_fw_policy); +#endif #ifdef IPFIREWALL_VERBOSE +bad_packet: /* * VERY ugly piece of code which actually - * makes kernel printf for denyed packets... - * This thingy will be added in more places... + * makes kernel printf for denied packets... */ - if ( !(fptr->flags & IP_FW_F_ACCEPT) && - (fptr->flags & IP_FW_F_PRN)) { + if (f->flags&IP_FW_F_PRN) { printf("ip_fw_chk says no to "); switch(ip->ip_p) { - case IPPROTO_TCP: printf("TCP "); break; - case IPPROTO_UDP: printf("UDP "); break; - case IPPROTO_ICMP: printf("ICMP:%d ",((char *)portptr)[0]&0xff); break; - default: printf("p=%d ",ip->ip_p); break; + case IPPROTO_TCP: + printf("TCP "); + break; + case IPPROTO_UDP: + printf("UDP "); + break; + case IPPROTO_ICMP: + printf("ICMP:%d ",((char *)portptr)[0]&0xff); + break; + default: + printf("p=%d ",ip->ip_p); + break; } print_ip(ip->ip_src); - if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { + if (ip->ip_p==IPPROTO_TCP || ip->ip_p==IPPROTO_UDP) { printf(":%d ",ntohs(portptr[0])); } else { printf("\n"); @@ -257,60 +268,147 @@ struct ip_fw *chain; printf(":%d ",ntohs(portptr[1])); } printf("\n"); - return(0); } + return(0); #endif - return( fptr->flags & IP_FW_F_ACCEPT); - } +} +#endif /* IPFIREWALL */ - } - } - } - } +#ifdef IPACCT +void ip_acct_cnt(ip,chain,nh_conv) +struct ip *ip; +struct ip_fw *chain; +int nh_conv; +{ + struct in_addr src, dst; + char got_proto=0,rev=0; + int frwl_proto, proto=0; + register struct ip_fw *f; + u_short src_port=0, dst_port=0; + u_short *portptr=(u_short *)&(((u_int *)ip)[ip->ip_hl]); - /* - * If we get here then none of the frwls matched. - * So now we relay on policy defined by user-unmatched packet can - * be ever accepted or rejected... - */ + if (!chain) + return; -#ifdef IPFIREWALL_VERBOSE + src = ip->ip_src; + dst = ip->ip_dst; + + for (f=chain;f;f=f->next) { + if ((src.s_addr&f->src_mask.s_addr)==f->src.s_addr + && (dst.s_addr&f->dst_mask.s_addr)==f->dst.s_addr) { + rev=0; + goto addr_match; + } + if ((f->flags&IP_FW_F_BIDIR) && + ((src.s_addr&f->src_mask.s_addr)==f->dst.s_addr + && (dst.s_addr&f->dst_mask.s_addr)==f->src.s_addr)) { + rev=1; + goto addr_match; + } + continue; +addr_match: + frwl_proto=f->flags&IP_FW_F_KIND; + if (frwl_proto==IP_FW_F_ALL) { + /* Universal frwl - we've got a match! */ + + f->p_cnt++; /* Rise packet count */ + + /* + * Rise byte count, + * if need to convert from + * host to network byte + * order,do it. + */ + if (nh_conv) + f->b_cnt+=ntohs(ip->ip_len); + else + f->b_cnt+=ip->ip_len; + } else { + /* + * Specific firewall - packet's + * protocol must match firewall's + */ + if (!got_proto) { /* - * VERY ugly piece of code which actually - * makes kernel printf for denyed packets... - * This thingy will be added in more places... + * We still had not determined the protocol + * of this packet,now the time to do so. */ - if ( !(ip_fw_policy) && - (fptr->flags & IP_FW_F_PRN)) { - printf("ip_fw_chk says no to "); - switch(ip->ip_p) { - case IPPROTO_TCP: printf("TCP "); break; - case IPPROTO_UDP: printf("UDP "); break; - case IPPROTO_ICMP: printf("ICMP:%d ",((char *)portptr)[0]&0xff); break; - default: printf("p=%d ",ip->ip_p); break; - } - print_ip(ip->ip_src); - if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { - printf(":%d ",ntohs(portptr[0])); - } else { - printf("\n"); - } - print_ip(ip->ip_dst); - if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { - printf(":%d ",ntohs(portptr[1])); - } - printf("\n"); - return(0); - } -#endif - return(ip_fw_policy); + switch(ip->ip_p) { + case IPPROTO_TCP: + /* + * First two shorts in TCP are src/dst ports + */ + proto=IP_FW_F_TCP; + src_port=ntohs(portptr[0]); + dst_port=ntohs(portptr[1]); + break; + case IPPROTO_UDP: + /* + * First two shorts in UDP are src/dst ports + */ + proto = IP_FW_F_UDP; + src_port = ntohs(portptr[0]); + dst_port = ntohs(portptr[1]); + break; + case IPPROTO_ICMP: + proto=IP_FW_F_ICMP; + break; + default: + proto=IP_FW_F_ALL; + } + got_proto=1; + } + /* + * At this moment we surely know the protocol of this + * packet and we'll check if it matches,then proceed futher.. + */ + if (proto==frwl_proto) { + + if ((proto==IP_FW_F_ICMP || + (port_match(&f->ports[0],f->n_src_p,src_port, + f->flags&IP_FW_F_SRNG) && + port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port, + f->flags&IP_FW_F_DRNG))) + || ((rev) + && (port_match(&f->ports[0],f->n_src_p,dst_port, + f->flags&IP_FW_F_SRNG) + && port_match(&f->ports[f->n_src_p],f->n_dst_p,src_port, + f->flags&IP_FW_F_DRNG)))) + { + f->p_cnt++; /* Rise packet count */ + /* + * Rise byte count, + * if need to convert from + * host to network byte + * order,do it. + */ + if (nh_conv) + f->b_cnt+=ntohs(ip->ip_len); + else + f->b_cnt+=ip->ip_len; + } /* Ports match */ + } /* Proto matches */ + } /* ALL/Specific */ +} /* IP addr/mask matches */ +} /* End of whole function */ +#endif /* IPACCT */ +static +void +zero_fw_chain(chainptr) +struct ip_fw *chainptr; +{ +struct ip_fw *ctmp=chainptr; + while(ctmp) { + ctmp->p_cnt=0l; + ctmp->b_cnt=0l; + ctmp=ctmp->next; + } } - static void free_fw_chain(chainptr) @@ -353,6 +451,9 @@ struct ip_fw *frwl; } bcopy( frwl, ftmp, sizeof( struct ip_fw ) ); + ftmp->p_cnt=0L; + ftmp->b_cnt=0L; + ftmp->next = NULL; if (*chainptr==NULL) @@ -371,8 +472,10 @@ struct ip_fw *frwl; if (newkind!=IP_FW_F_ALL && oldkind!=IP_FW_F_ALL - && oldkind!=newkind) - continue; + && oldkind!=newkind) { + chtmp_prev=chtmp; + continue; + } /* * Very very *UGLY* code... * Sorry,but i had to do this.... @@ -459,7 +562,7 @@ struct ip_fw *frwl; ftmp->n_dst_p : USHRT_MAX; if (chtmp->flags & IP_FW_F_DRNG) - o_dr=chtmp->ports[n_o+1]-chtmp->ports[n_o]; + o_dr=chtmp->ports[n_o+1]-chtmp->ports[n_o]; else o_dr=(chtmp->n_dst_p)? chtmp->n_dst_p : USHRT_MAX; @@ -571,12 +674,121 @@ struct ip_fw *frwl; else return(EINVAL); } +struct ip_fw * +check_ipfw_struct(m) +struct mbuf *m; +{ +struct ip_fw *frwl; + + if ( m->m_len != sizeof(struct ip_fw) ) { +#ifdef DEBUG_IPFIREWALL + printf("ip_fw_ctl: len=%d, want %d\n",m->m_len, + sizeof(struct ip_fw)); +#endif + return(NULL); + } + + frwl = mtod(m,struct ip_fw*); + + if ( (frwl->flags & ~IP_FW_F_MASK) != 0 ) { +#ifdef DEBUG_IPFIREWALL + printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n", + frwl->flags); +#endif + return(NULL); + } + + if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) { +#ifdef DEBUG_IPFIREWALL + printf("ip_fw_ctl: src range set but n_src_p=%d\n", + frwl->n_src_p); +#endif + return(NULL); + } + + if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) { +#ifdef DEBUG_IPFIREWALL + printf("ip_fw_ctl: dst range set but n_dst_p=%d\n", + frwl->n_dst_p); +#endif + return(NULL); + } + + if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) { +#ifdef DEBUG_IPFIREWALL + printf("ip_fw_ctl: too many ports (%d+%d)\n", + frwl->n_src_p,frwl->n_dst_p); +#endif + return(NULL); + } + +#if 0 + if ( (frwl->flags & IP_FW_F_KIND) == IP_FW_F_ICMP ) { +#ifdef DEBUG_IPFIREWALL + printf("ip_fw_ctl: request for unsupported ICMP frwling\n"); +#endif + return(NULL); + } +#endif +return frwl; +} + + + + +#ifdef IPACCT +int +ip_acct_ctl(stage,m) +int stage; +struct mbuf *m; +{ +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))) + 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... + */ +#ifdef DEBUG_IPFIREWALL + printf("ip_acct_ctl: unknown request %d\n",stage); +#endif + return(EINVAL); + } + } +#ifdef DEBUG_IPFIREWALL + printf("ip_acct_ctl: unknown request %d\n",stage); +#endif + return(EINVAL); +} +#endif + +#ifdef IPFIREWALL int ip_fw_ctl(stage,m) int stage; struct mbuf *m; { -int *tmp_policy_ptr; if ( stage == IP_FW_FLUSH ) { free_fw_chain(&ip_fw_blk_chain); @@ -584,120 +796,98 @@ if ( stage == IP_FW_FLUSH ) return(0); } - if ( m == 0 ) - { - printf("ip_fw_ctl: NULL mbuf ptr\n"); - return( EINVAL ); - } +if ( m == 0 ) + { + printf("ip_fw_ctl: NULL mbuf ptr\n"); + return(EINVAL); + } if ( stage == IP_FW_POLICY ) { + int *tmp_policy_ptr; tmp_policy_ptr=mtod(m,int *); if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0) - return ( EINVAL ); + return (EINVAL); ip_fw_policy=*tmp_policy_ptr; return 0; } - if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD ) { +if ( stage == IP_FW_CHK_BLK + || stage == IP_FW_CHK_FWD ) { struct ip *ip; + if ( m->m_len < sizeof(struct ip) + 2 * sizeof(u_short) ) { #ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: mbuf len=%d, want at least %d\n",m->m_len,sizeof(struct ip) + 2 * sizeof(u_short)); + printf("ip_fw_ctl: mbuf len=%d, want at least %d\n", + m->m_len,sizeof(struct ip) + 2 * sizeof(u_short)); #endif return( EINVAL ); - } + } + ip = mtod(m,struct ip *); + if ( ip->ip_hl != sizeof(struct ip) / sizeof(int) ) { #ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: ip->ip_hl=%d, want %d\n",ip->ip_hl,sizeof(struct ip)/sizeof(int)); + printf("ip_fw_ctl: ip->ip_hl=%d, want %d\n",ip->ip_hl, + sizeof(struct ip)/sizeof(int)); #endif - return( EINVAL ); - } + return(EINVAL); + } + if ( ip_fw_chk(ip, stage == IP_FW_CHK_BLK ? ip_fw_blk_chain : ip_fw_fwd_chain ) ) - return(0); - else { - return(EACCES); - } - - } else 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; - - if ( m->m_len != sizeof(struct ip_fw) ) { -#ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: len=%d, want %d\n",m->m_len,sizeof(struct ip_fw)); -#endif - return( EINVAL ); - } - - frwl = mtod(m,struct ip_fw*); - if ( (frwl->flags & ~IP_FW_F_MASK) != 0 ) { -#ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n",frwl->flags); -#endif - return( EINVAL ); - } + return(0); + else + return(EACCES); + } - if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) { -#ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: src range set but n_src_p=%d\n",frwl->n_src_p); -#endif - return( EINVAL ); - } +/* + * Here we really working hard-adding new elements + * to blocking/forwarding chains or deleting'em + */ - if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) { -#ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: dst range set but n_dst_p=%d\n",frwl->n_dst_p); -#endif - return( EINVAL ); - } +if ( stage == IP_FW_ADD_BLK + || stage == IP_FW_ADD_FWD + || stage == IP_FW_DEL_BLK + || stage == IP_FW_DEL_FWD + ) { - if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) { -#ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: too many ports (%d+%d)\n",frwl->n_src_p,frwl->n_dst_p); + struct ip_fw *frwl; + + frwl=check_ipfw_struct(m); + if (frwl==NULL) + return (EINVAL); +#ifdef nenado + if (!(frwl=check_ipfw_struct(m))) + return (EINVAL); #endif - return( EINVAL ); - } -#if 0 - if ( (frwl->flags & IP_FW_F_KIND) == IP_FW_F_ICMP ) { + 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... + */ #ifdef DEBUG_IPFIREWALL - printf("ip_fw_ctl: request for unsupported ICMP frwling\n"); + printf("ip_fw_ctl: unknown request %d\n",stage); #endif - return( EINVAL ); + return(EINVAL); } - -#endif - if ( stage == IP_FW_ADD_BLK ) - { - return( add_to_chain(&ip_fw_blk_chain,frwl)); - } - if ( stage == IP_FW_ADD_FWD ) - { - return( add_to_chain(&ip_fw_fwd_chain,frwl)); - } - if ( stage == IP_FW_DEL_BLK ) - { - return( del_from_chain(&ip_fw_blk_chain,frwl)); - } - if ( stage == IP_FW_DEL_FWD ) - { - return( del_from_chain(&ip_fw_fwd_chain,frwl)); - } - } +} #ifdef DEBUG_IPFIREWALL printf("ip_fw_ctl: unknown request %d\n",stage); #endif return(EINVAL); - } +#endif /* IPFIREWALL */ diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index ca999bc..f9979b6 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -26,39 +26,40 @@ struct ip_fw { struct ip_fw *next; /* Next firewall on chain */ struct in_addr src, dst; /* Source and destination IP addr */ struct in_addr src_mask, dst_mask; /* Mask for src and dest IP addr */ - u_short flags; - - u_short n_src_p, n_dst_p; /* # of src ports and # of dst ports */ + u_short flags; /* Flags word */ + u_short n_src_p, n_dst_p; /* # of src ports and # of dst ports */ /* in ports array (dst ports follow */ /* src ports; max of 10 ports in all; */ /* count of 0 means match all ports) */ -#define IP_FW_MAX_PORTS 10 /* A reasonable maximum */ - u_short ports[IP_FW_MAX_PORTS]; /* Array of port numbers to match */ +#define IP_FW_MAX_PORTS 10 /* A reasonable maximum */ + u_short ports[IP_FW_MAX_PORTS]; /* Array of port numbers to match */ + u_long p_cnt,b_cnt; /* Packet and byte counters */ }; /* * Values for "flags" field . */ -#define IP_FW_F_ALL 0 /* This is a universal packet firewall*/ -#define IP_FW_F_TCP 1 /* This is a TCP packet firewall */ -#define IP_FW_F_UDP 2 /* This is a UDP packet firewall */ -#define IP_FW_F_ICMP 3 /* This is a ICMP packet firewall */ -#define IP_FW_F_KIND 3 /* Mask to isolate firewall kind */ -#define IP_FW_F_ACCEPT 4 /* This is an accept firewall (as * +#define IP_FW_F_ALL 0x00 /* This is a universal packet firewall*/ +#define IP_FW_F_TCP 0x01 /* This is a TCP packet firewall */ +#define IP_FW_F_UDP 0x02 /* This is a UDP packet firewall */ +#define IP_FW_F_ICMP 0x03 /* This is a ICMP packet firewall */ +#define IP_FW_F_KIND 0x03 /* Mask to isolate firewall kind */ +#define IP_FW_F_ACCEPT 0x04 /* This is an accept firewall (as * * opposed to a deny firewall)* * */ -#define IP_FW_F_SRNG 8 /* The first two src ports are a min * +#define IP_FW_F_SRNG 0x08 /* The first two src ports are a min * * and max range (stored in host byte * * order). * * */ -#define IP_FW_F_DRNG 16 /* The first two dst ports are a min * +#define IP_FW_F_DRNG 0x10 /* The first two dst ports are a min * * and max range (stored in host byte * * order). * * (ports[0] <= port <= ports[1]) * * */ -#define IP_FW_F_PRN 32 /* In verbose mode print this firewall*/ -#define IP_FW_F_MASK 0x3F /* All possible flag bits mask */ +#define IP_FW_F_PRN 0x20 /* In verbose mode print this firewall*/ +#define IP_FW_F_BIDIR 0x40 /* For accounting-count two way */ +#define IP_FW_F_MASK 0x7F /* All possible flag bits mask */ /* * New IP firewall options for [gs]etsockopt at the RAW IP level. @@ -74,12 +75,24 @@ struct ip_fw { #define IP_FW_FLUSH (IP_FW_BASE_CTL+6) #define IP_FW_POLICY (IP_FW_BASE_CTL+7) +#define IP_ACCT_ADD (IP_FW_BASE_CTL+10) +#define IP_ACCT_DEL (IP_FW_BASE_CTL+11) +#define IP_ACCT_FLUSH (IP_FW_BASE_CTL+12) +#define IP_ACCT_ZERO (IP_FW_BASE_CTL+13) + /* * Main firewall chains definitions and global var's definitions. */ +#ifdef KERNEL +#ifdef IPFIREWALL extern struct ip_fw *ip_fw_blk_chain; extern struct ip_fw *ip_fw_fwd_chain; extern int ip_fw_policy; - #endif +#ifdef IPACCT +extern struct ip_fw *ip_acct_chain; +#endif +#endif /* KERNEL */ + +#endif /* _IP_FW_H */ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index fd7eab6..085d0ff 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * $Id: ip_input.c,v 1.9 1994/10/28 15:09:48 jkh Exp $ + * $Id: ip_input.c,v 1.10 1994/11/08 12:47:29 jkh Exp $ */ #include <sys/param.h> @@ -59,6 +59,9 @@ #ifdef IPFIREWALL #include <netinet/ip_fw.h> #endif +#ifdef IPACCT +#include <netinet/ip_fw.h> +#endif #include <sys/socketvar.h> struct socket *ip_rsvpd; @@ -353,6 +356,17 @@ next: ours: +#ifdef IPACCT + /* + * If packet came to us we count it... + * This way we count all incoming packets which has + * not been forwarded... + * Do not convert ip_len to host byte order when + * counting,ppl already made it for us before.. + */ + ip_acct_cnt(ip,ip_acct_chain,0); +#endif + /* * If offset or IP_MF are set, must reassemble. * Otherwise, nothing need be done. @@ -1125,6 +1139,11 @@ ip_forward(m, srcrt) if (error) ipstat.ips_cantforward++; else { +#ifdef wrong +#ifdef IPACCT + ip_acct_cnt(ip,ip_acct_chain); +#endif +#endif ipstat.ips_forward++; if (type) ipstat.ips_redirectsent++; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 358b42f..a734c42 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 - * $Id: ip_output.c,v 1.7 1994/09/09 22:05:02 wollman Exp $ + * $Id: ip_output.c,v 1.8 1994/09/14 03:10:13 wollman Exp $ */ #include <sys/param.h> @@ -53,6 +53,13 @@ #include <netinet/in_var.h> #include <netinet/ip_var.h> +#ifdef IPFIREWALL +#include <netinet/ip_fw.h> +#endif +#ifdef IPACCT +#include <netinet/ip_fw.h> +#endif + #ifdef vax #include <machine/mtpr.h> #endif @@ -401,6 +408,15 @@ sendorfree: done: if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) RTFREE(ro->ro_rt); +#ifdef IPACCT + /* + * Count outgoing packet,here we count both our packets and + * those we forward. + * Here we want to convert ip_len to host byte order when counting + * so we set 3rd arg to 1. + */ + ip_acct_cnt(ip,ip_acct_chain,1); +#endif return (error); bad: m_freem(m0); diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 949e427..4b33614 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -56,6 +56,9 @@ #ifdef IPFIREWALL #include <netinet/ip_fw.h> #endif +#ifdef IPACCT +#include <netinet/ip_fw.h> +#endif struct inpcb rawinpcb; @@ -227,7 +230,21 @@ rip_ctloutput(op, so, level, optname, m) error=EINVAL; return(error); #endif - +#ifdef IPACCT + case IP_ACCT_DEL: + case IP_ACCT_ADD: + case IP_ACCT_FLUSH: + case IP_ACCT_ZERO: + + if (op = PRCO_SETOPT) { + error=ip_acct_ctl(optname, *m); + if (*m) + (void)m_free(*m); + } + else + error=EINVAL; + return(error); +#endif case IP_RSVP_ON: error = ip_rsvp_init(so); |