Ugen J.S.Antsilevich's latest, happiest, IP firewall code.

Poul:  Please take this into BETA.  It's non-intrusive, and a rather
substantial improvement over what was there before.
This commit is contained in:
Jordan K. Hubbard 1994-11-16 10:17:11 +00:00
parent f3ac09ee9a
commit 63f8d699ac
5 changed files with 526 additions and 271 deletions

View File

@ -24,25 +24,30 @@
#include <sys/protosw.h> #include <sys/protosw.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <net/if.h> #include <net/if.h>
#include <net/route.h> #include <net/route.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/in_systm.h> #include <netinet/in_systm.h>
#include <netinet/ip.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 <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netinet/ip_fw.h> #include <netinet/ip_fw.h>
#ifdef IPFIREWALL
struct ip_fw *ip_fw_fwd_chain; struct ip_fw *ip_fw_fwd_chain;
struct ip_fw *ip_fw_blk_chain; struct ip_fw *ip_fw_blk_chain;
int ip_fw_policy=1; int ip_fw_policy=1;
#endif
#ifdef IPACCT
struct ip_fw *ip_acct_chain;
#endif
inline inline
@ -61,7 +66,6 @@ struct in_addr xaddr;
/* /*
* Returns 1 if the port is matched by the vector, 0 otherwise * Returns 1 if the port is matched by the vector, 0 otherwise
*/ */
inline inline
int port_match(portptr,nports,port,range_flag) int port_match(portptr,nports,port,range_flag)
u_short *portptr; u_short *portptr;
@ -69,6 +73,8 @@ int nports;
u_short port; u_short port;
int range_flag; int range_flag;
{ {
if (!nports)
return 1;
if ( range_flag ) { if ( range_flag ) {
if ( portptr[0] <= port && port <= portptr[1] ) { if ( portptr[0] <= port && port <= portptr[1] ) {
return( 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 * Returns 0 if packet should be dropped, 1 or more if it should be accepted
*/ */
#ifdef IPFIREWALL
int ip_fw_chk(ip,chain) int ip_fw_chk(ip,chain)
struct ip *ip; struct ip *ip;
struct ip_fw *chain; struct ip_fw *chain;
{ {
struct in_addr src, dst; struct in_addr src, dst;
char got_proto = 0; char got_proto=0;
int frwl_proto, proto = 0; int frwl_proto, proto=0;
register struct ip_fw *fptr; register struct ip_fw *f;
u_short src_port = 0, dst_port = 0; u_short src_port=0, dst_port=0;
#ifdef IPFIREWALL_VERBOSE u_short *portptr=(u_short *)&(((u_int *)ip)[ip->ip_hl]);
u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]);
#endif
if ( chain == NULL ) { /* Is there a frwl chain? */ if (!chain) {
return(1); return(1); /* If no chain , always say Ok to packet */
} }
src = ip->ip_src; src = ip->ip_src;
@ -112,188 +116,149 @@ struct ip_fw *chain;
#ifdef DEBUG_IPFIREWALL #ifdef DEBUG_IPFIREWALL
{ {
u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]);
printf("packet "); printf("packet ");
switch(ip->ip_p) { switch(ip->ip_p) {
case IPPROTO_TCP: printf("TCP "); break; case IPPROTO_TCP:
case IPPROTO_UDP: printf("UDP "); break; printf("TCP ");
case IPPROTO_ICMP: printf("ICMP:%d ",((char *)portptr)[0]&0xff); break; break;
default: printf("p=%d ",ip->ip_p); 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); 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])); printf(":%d ",ntohs(portptr[0]));
} }
print_ip(ip->ip_dst); 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(":%d ",ntohs(portptr[1]));
} }
printf("\n"); printf("\n");
} }
#endif #endif
for ( fptr = chain; fptr != NULL; fptr = fptr->next ) { for (f=chain;f;f=f->next)
if ((src.s_addr&f->src_mask.s_addr)==f->src.s_addr
if ( (src.s_addr & fptr->src_mask.s_addr) == fptr->src.s_addr && (dst.s_addr&f->dst_mask.s_addr)==f->dst.s_addr) {
&& (dst.s_addr & fptr->dst_mask.s_addr) == fptr->dst.s_addr ) { frwl_proto=f->flags&IP_FW_F_KIND;
if (frwl_proto==IP_FW_F_ALL) {
if ( (frwl_proto = fptr->flags & IP_FW_F_KIND) /* Universal frwl - we've got a match! */
== IP_FW_F_ALL ) {
/* Universal frwl - we've got a match! */
#ifdef DEBUG_IPFIREWALL #ifdef DEBUG_IPFIREWALL
printf("universal frwl match\n"); printf("universal frwl match\n");
#endif #endif
#ifdef IPFIREWALL_VERBOSE #ifdef IPFIREWALL_VERBOSE
/* if (!(f->flags & IP_FW_F_ACCEPT))
* VERY ugly piece of code which actually goto bad_packet;
* makes kernel printf for denyed packets... return 1;
* This thingy will be added in more places... #else
*/ return( f->flags & IP_FW_F_ACCEPT );
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);
}
#endif #endif
return( fptr->flags & IP_FW_F_ACCEPT );
} else { } else {
/*
/* Specific frwl - packet's protocol must match frwl's */ * Specific firewall - packet's
* protocol must match firewall's
if ( !got_proto ) { */
u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]); if (!got_proto) {
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
/* /*
* VERY ugly piece of code which actually * We still had not determined the protocol
* makes kernel printf for denyed packets... * of this packet,now the time to do so.
* This thingy will be added in more places...
*/ */
if ( !(fptr->flags & IP_FW_F_ACCEPT) && switch(ip->ip_p) {
(fptr->flags & IP_FW_F_PRN)) { case IPPROTO_TCP:
printf("ip_fw_chk says no to "); /*
switch(ip->ip_p) { * First two shorts in TCP are src/dst ports
case IPPROTO_TCP: printf("TCP "); break; */
case IPPROTO_UDP: printf("UDP "); break; proto=IP_FW_F_TCP;
case IPPROTO_ICMP: printf("ICMP:%d ",((char *)portptr)[0]&0xff); break; src_port=ntohs(portptr[0]);
default: printf("p=%d ",ip->ip_p); break; dst_port=ntohs(portptr[1]);
} break;
print_ip(ip->ip_src); case IPPROTO_UDP:
if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { /*
printf(":%d ",ntohs(portptr[0])); * First two shorts in UDP are src/dst ports
} else { */
printf("\n"); proto = IP_FW_F_UDP;
} src_port = ntohs(portptr[0]);
print_ip(ip->ip_dst); dst_port = ntohs(portptr[1]);
if ( ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ) { break;
printf(":%d ",ntohs(portptr[1])); case IPPROTO_ICMP:
} proto=IP_FW_F_ICMP;
printf("\n"); break;
return(0); default:
} proto=IP_FW_F_ALL;
#ifdef DEBUG_IPFIREWALL
printf("non TCP/UDP packet\n");
#endif #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 * So now we relay on policy defined by user-unmatched packet can
* be ever accepted or rejected... * be ever accepted or rejected...
*/ */
#ifdef IPFIREWALL_VERBOSE #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 * VERY ugly piece of code which actually
* makes kernel printf for denyed packets... * makes kernel printf for denied packets...
* This thingy will be added in more places...
*/ */
if ( !(ip_fw_policy) && if (f->flags&IP_FW_F_PRN) {
(fptr->flags & IP_FW_F_PRN)) {
printf("ip_fw_chk says no to "); printf("ip_fw_chk says no to ");
switch(ip->ip_p) { switch(ip->ip_p) {
case IPPROTO_TCP: printf("TCP "); break; case IPPROTO_TCP:
case IPPROTO_UDP: printf("UDP "); break; printf("TCP ");
case IPPROTO_ICMP: printf("ICMP:%d ",((char *)portptr)[0]&0xff); break; break;
default: printf("p=%d ",ip->ip_p); 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); 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])); printf(":%d ",ntohs(portptr[0]));
} else { } else {
printf("\n"); printf("\n");
@ -303,14 +268,147 @@ struct ip_fw *chain;
printf(":%d ",ntohs(portptr[1])); printf(":%d ",ntohs(portptr[1]));
} }
printf("\n"); printf("\n");
return(0);
} }
return(0);
#endif #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 static
void void
free_fw_chain(chainptr) free_fw_chain(chainptr)
@ -353,6 +451,9 @@ struct ip_fw *frwl;
} }
bcopy( frwl, ftmp, sizeof( struct ip_fw ) ); bcopy( frwl, ftmp, sizeof( struct ip_fw ) );
ftmp->p_cnt=0L;
ftmp->b_cnt=0L;
ftmp->next = NULL; ftmp->next = NULL;
if (*chainptr==NULL) if (*chainptr==NULL)
@ -371,8 +472,10 @@ struct ip_fw *frwl;
if (newkind!=IP_FW_F_ALL if (newkind!=IP_FW_F_ALL
&& oldkind!=IP_FW_F_ALL && oldkind!=IP_FW_F_ALL
&& oldkind!=newkind) && oldkind!=newkind) {
continue; chtmp_prev=chtmp;
continue;
}
/* /*
* Very very *UGLY* code... * Very very *UGLY* code...
* Sorry,but i had to do this.... * Sorry,but i had to do this....
@ -459,7 +562,7 @@ struct ip_fw *frwl;
ftmp->n_dst_p : USHRT_MAX; ftmp->n_dst_p : USHRT_MAX;
if (chtmp->flags & IP_FW_F_DRNG) 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 else
o_dr=(chtmp->n_dst_p)? o_dr=(chtmp->n_dst_p)?
chtmp->n_dst_p : USHRT_MAX; chtmp->n_dst_p : USHRT_MAX;
@ -571,133 +674,220 @@ struct ip_fw *frwl;
else return(EINVAL); else return(EINVAL);
} }
int struct ip_fw *
ip_fw_ctl(stage,m) check_ipfw_struct(m)
int stage;
struct mbuf *m; struct mbuf *m;
{ {
int *tmp_policy_ptr; struct ip_fw *frwl;
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;
if ( m->m_len != sizeof(struct ip_fw) ) { if ( m->m_len != sizeof(struct ip_fw) ) {
#ifdef DEBUG_IPFIREWALL #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 #endif
return( EINVAL ); return(NULL);
} }
frwl = mtod(m,struct ip_fw*); frwl = mtod(m,struct ip_fw*);
if ( (frwl->flags & ~IP_FW_F_MASK) != 0 ) { if ( (frwl->flags & ~IP_FW_F_MASK) != 0 ) {
#ifdef DEBUG_IPFIREWALL #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 #endif
return( EINVAL ); return(NULL);
} }
if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) { if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) {
#ifdef DEBUG_IPFIREWALL #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 #endif
return( EINVAL ); return(NULL);
} }
if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) { if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) {
#ifdef DEBUG_IPFIREWALL #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 #endif
return( EINVAL ); return(NULL);
} }
if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) { if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) {
#ifdef DEBUG_IPFIREWALL #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 #endif
return( EINVAL ); return(NULL);
} }
#if 0 #if 0
if ( (frwl->flags & IP_FW_F_KIND) == IP_FW_F_ICMP ) { if ( (frwl->flags & IP_FW_F_KIND) == IP_FW_F_ICMP ) {
#ifdef DEBUG_IPFIREWALL #ifdef DEBUG_IPFIREWALL
printf("ip_fw_ctl: request for unsupported ICMP frwling\n"); 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 #endif
return( EINVAL ); 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 #endif
if ( stage == IP_FW_ADD_BLK )
{ switch (stage) {
return( add_to_chain(&ip_fw_blk_chain,frwl)); case IP_FW_ADD_BLK:
} return(add_to_chain(&ip_fw_blk_chain,frwl));
if ( stage == IP_FW_ADD_FWD ) case IP_FW_ADD_FWD:
{ return(add_to_chain(&ip_fw_fwd_chain,frwl));
return( add_to_chain(&ip_fw_fwd_chain,frwl)); case IP_FW_DEL_BLK:
} return(del_from_chain(&ip_fw_blk_chain,frwl));
if ( stage == IP_FW_DEL_BLK ) case IP_FW_DEL_FWD:
{ return(del_from_chain(&ip_fw_fwd_chain,frwl));
return( del_from_chain(&ip_fw_blk_chain,frwl)); default:
} /*
if ( stage == IP_FW_DEL_FWD ) * Should be panic but...
{ */
return( del_from_chain(&ip_fw_fwd_chain,frwl)); #ifdef DEBUG_IPFIREWALL
} printf("ip_fw_ctl: unknown request %d\n",stage);
} #endif
return(EINVAL);
}
}
#ifdef DEBUG_IPFIREWALL #ifdef DEBUG_IPFIREWALL
printf("ip_fw_ctl: unknown request %d\n",stage); printf("ip_fw_ctl: unknown request %d\n",stage);
#endif #endif
return(EINVAL); return(EINVAL);
} }
#endif /* IPFIREWALL */

View File

@ -26,39 +26,40 @@ struct ip_fw {
struct ip_fw *next; /* Next firewall on chain */ struct ip_fw *next; /* Next firewall on chain */
struct in_addr src, dst; /* Source and destination IP addr */ struct in_addr src, dst; /* Source and destination IP addr */
struct in_addr src_mask, dst_mask; /* Mask for src and dest IP addr */ struct in_addr src_mask, dst_mask; /* Mask for src and dest IP addr */
u_short flags; u_short flags; /* Flags word */
u_short n_src_p, n_dst_p; /* # of src ports and # of dst ports */
u_short n_src_p, n_dst_p; /* # of src ports and # of dst ports */
/* in ports array (dst ports follow */ /* in ports array (dst ports follow */
/* src ports; max of 10 ports in all; */ /* src ports; max of 10 ports in all; */
/* count of 0 means match all ports) */ /* count of 0 means match all ports) */
#define IP_FW_MAX_PORTS 10 /* A reasonable maximum */ #define IP_FW_MAX_PORTS 10 /* A reasonable maximum */
u_short ports[IP_FW_MAX_PORTS]; /* Array of port numbers to match */ 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 . * Values for "flags" field .
*/ */
#define IP_FW_F_ALL 0 /* This is a universal packet firewall*/ #define IP_FW_F_ALL 0x00 /* This is a universal packet firewall*/
#define IP_FW_F_TCP 1 /* This is a TCP packet firewall */ #define IP_FW_F_TCP 0x01 /* This is a TCP packet firewall */
#define IP_FW_F_UDP 2 /* This is a UDP packet firewall */ #define IP_FW_F_UDP 0x02 /* This is a UDP packet firewall */
#define IP_FW_F_ICMP 3 /* This is a ICMP packet firewall */ #define IP_FW_F_ICMP 0x03 /* This is a ICMP packet firewall */
#define IP_FW_F_KIND 3 /* Mask to isolate firewall kind */ #define IP_FW_F_KIND 0x03 /* Mask to isolate firewall kind */
#define IP_FW_F_ACCEPT 4 /* This is an accept firewall (as * #define IP_FW_F_ACCEPT 0x04 /* This is an accept firewall (as *
* opposed to a deny firewall)* * 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 * * and max range (stored in host byte *
* order). * * 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 * * and max range (stored in host byte *
* order). * * order). *
* (ports[0] <= port <= ports[1]) * * (ports[0] <= port <= ports[1]) *
* */ * */
#define IP_FW_F_PRN 32 /* In verbose mode print this firewall*/ #define IP_FW_F_PRN 0x20 /* In verbose mode print this firewall*/
#define IP_FW_F_MASK 0x3F /* All possible flag bits mask */ #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. * 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_FLUSH (IP_FW_BASE_CTL+6)
#define IP_FW_POLICY (IP_FW_BASE_CTL+7) #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. * 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_blk_chain;
extern struct ip_fw *ip_fw_fwd_chain; extern struct ip_fw *ip_fw_fwd_chain;
extern int ip_fw_policy; extern int ip_fw_policy;
#endif #endif
#ifdef IPACCT
extern struct ip_fw *ip_acct_chain;
#endif
#endif /* KERNEL */
#endif /* _IP_FW_H */

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94 * @(#)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> #include <sys/param.h>
@ -59,6 +59,9 @@
#ifdef IPFIREWALL #ifdef IPFIREWALL
#include <netinet/ip_fw.h> #include <netinet/ip_fw.h>
#endif #endif
#ifdef IPACCT
#include <netinet/ip_fw.h>
#endif
#include <sys/socketvar.h> #include <sys/socketvar.h>
struct socket *ip_rsvpd; struct socket *ip_rsvpd;
@ -353,6 +356,17 @@ ipintr()
ours: 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. * If offset or IP_MF are set, must reassemble.
* Otherwise, nothing need be done. * Otherwise, nothing need be done.
@ -1125,6 +1139,11 @@ ip_forward(m, srcrt)
if (error) if (error)
ipstat.ips_cantforward++; ipstat.ips_cantforward++;
else { else {
#ifdef wrong
#ifdef IPACCT
ip_acct_cnt(ip,ip_acct_chain);
#endif
#endif
ipstat.ips_forward++; ipstat.ips_forward++;
if (type) if (type)
ipstat.ips_redirectsent++; ipstat.ips_redirectsent++;

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94 * @(#)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> #include <sys/param.h>
@ -53,6 +53,13 @@
#include <netinet/in_var.h> #include <netinet/in_var.h>
#include <netinet/ip_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 #ifdef vax
#include <machine/mtpr.h> #include <machine/mtpr.h>
#endif #endif
@ -401,6 +408,15 @@ ip_output(m0, opt, ro, flags, imo)
done: done:
if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
RTFREE(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); return (error);
bad: bad:
m_freem(m0); m_freem(m0);

View File

@ -56,6 +56,9 @@
#ifdef IPFIREWALL #ifdef IPFIREWALL
#include <netinet/ip_fw.h> #include <netinet/ip_fw.h>
#endif #endif
#ifdef IPACCT
#include <netinet/ip_fw.h>
#endif
struct inpcb rawinpcb; struct inpcb rawinpcb;
@ -227,7 +230,21 @@ rip_ctloutput(op, so, level, optname, m)
error=EINVAL; error=EINVAL;
return(error); return(error);
#endif #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: case IP_RSVP_ON:
error = ip_rsvp_init(so); error = ip_rsvp_init(so);