diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 3b2f9388320e..293f4697b3eb 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -24,25 +24,30 @@ #include #include #include -#include +#include #include #include #include + #include #include #include -#include -#include -#include #include +#include + #include +#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 + 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 == NULL ) { /* Is there a frwl chain? */ - return(1); + if (!chain) { + return(1); /* If no chain , always say Ok to packet */ } src = ip->ip_src; @@ -112,188 +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; - case IPPROTO_ICMP: - proto = IP_FW_F_ICMP; - break; - default: proto = IP_FW_F_ALL; -#ifdef DEBUG_IPFIREWALL - printf("non TCP/UDP packet\n"); -#endif - } - got_proto = 1; - } - - 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 - ) - ) - ) - ) { - -#ifdef IPFIREWALL_VERBOSE + /* + * 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 ( !(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); - } + 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; +#ifdef DEBUG_IPFIREWALL + printf("non TCP/UDP packet\n"); #endif - return( fptr->flags & IP_FW_F_ACCEPT); - } - - } - } + 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 we get here then none of the frwls matched. + * 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 ( !(ip_fw_policy) && - (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"); @@ -303,14 +268,147 @@ struct ip_fw *chain; printf(":%d ",ntohs(portptr[1])); } printf("\n"); - return(0); } + return(0); #endif - return(ip_fw_policy); - } +#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 (!chain) + return; + + 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) { + /* + * 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; + } + 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,133 +674,220 @@ struct ip_fw *frwl; else return(EINVAL); } -int -ip_fw_ctl(stage,m) -int stage; +struct ip_fw * +check_ipfw_struct(m) struct mbuf *m; { -int *tmp_policy_ptr; -if ( stage == IP_FW_FLUSH ) - { - free_fw_chain(&ip_fw_blk_chain); - free_fw_chain(&ip_fw_fwd_chain); - return(0); - } - - if ( m == 0 ) - { - printf("ip_fw_ctl: NULL mbuf ptr\n"); - return( EINVAL ); - } - -if ( stage == IP_FW_POLICY ) - { - tmp_policy_ptr=mtod(m,int *); - if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0) - return ( EINVAL ); - ip_fw_policy=*tmp_policy_ptr; - return 0; - } - - 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)); -#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)); -#endif - 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; +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)); + printf("ip_fw_ctl: len=%d, want %d\n",m->m_len, + sizeof(struct ip_fw)); #endif - return( EINVAL ); - } + 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); + printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n", + frwl->flags); #endif - return( EINVAL ); - } + 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); + printf("ip_fw_ctl: src range set but n_src_p=%d\n", + frwl->n_src_p); #endif - return( EINVAL ); + 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); + printf("ip_fw_ctl: dst range set but n_dst_p=%d\n", + frwl->n_dst_p); #endif - return( EINVAL ); + 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); + printf("ip_fw_ctl: too many ports (%d+%d)\n", + frwl->n_src_p,frwl->n_dst_p); #endif - return( EINVAL ); + 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; +{ +if ( stage == IP_FW_FLUSH ) + { + free_fw_chain(&ip_fw_blk_chain); + free_fw_chain(&ip_fw_fwd_chain); + return(0); + } + +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); + ip_fw_policy=*tmp_policy_ptr; + return 0; + } + +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)); #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)); +#endif + 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); + } + +/* + * 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); + if (frwl==NULL) + return (EINVAL); +#ifdef nenado + if (!(frwl=check_ipfw_struct(m))) + 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)); - } - } + + 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: unknown request %d\n",stage); +#endif + return(EINVAL); + } +} #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 ca999bc0e2ad..f9979b6a3be7 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 fd7eab658d80..085d0ff2d7af 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 @@ -59,6 +59,9 @@ #ifdef IPFIREWALL #include #endif +#ifdef IPACCT +#include +#endif #include struct socket *ip_rsvpd; @@ -353,6 +356,17 @@ ipintr() 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 358b42f8b23a..a734c4261c39 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 @@ -53,6 +53,13 @@ #include #include +#ifdef IPFIREWALL +#include +#endif +#ifdef IPACCT +#include +#endif + #ifdef vax #include #endif @@ -401,6 +408,15 @@ ip_output(m0, opt, ro, flags, imo) 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 949e427712d6..4b33614db72c 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -56,6 +56,9 @@ #ifdef IPFIREWALL #include #endif +#ifdef IPACCT +#include +#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);