IP Firewall code from Daniel Boulet and J.S.Antsilevich
Submitted by: danny ugen
This commit is contained in:
parent
b877c0f37e
commit
100ba1a617
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=3969
@ -4,7 +4,7 @@
|
||||
#
|
||||
# This kernel is NOT MEANT to be runnable!
|
||||
#
|
||||
# $Id: LINT,v 1.100 1994/10/26 19:20:27 jkh Exp $
|
||||
# $Id: LINT,v 1.101 1994/10/26 21:10:13 wollman Exp $
|
||||
#
|
||||
|
||||
#
|
||||
@ -41,6 +41,12 @@ options MATH_EMULATE #Support for x87 emulation
|
||||
#options GPL_MATH_EMULATE #Support for x87 emualtion via
|
||||
#new math emulator
|
||||
|
||||
# Enable the following (IPFIREWALL_VERBOSE optional) to enable the IP firewall
|
||||
# code. This is used in conjunction with the ipfw(1) command. See the
|
||||
# man page for more details.
|
||||
options IPFIREWALL #firewall test
|
||||
options IPFIREWALL_VERBOSE #print information about dropped packets
|
||||
|
||||
#
|
||||
# This directive defines a number of things:
|
||||
# - The compiled kernel is to be called `kernel'
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This file tells config what files go into building a kernel,
|
||||
# files marked standard are always included.
|
||||
#
|
||||
# $Id: files.i386,v 1.55 1994/10/26 19:19:12 jkh Exp $
|
||||
# $Id: files.i386,v 1.56 1994/10/27 20:44:27 jkh Exp $
|
||||
#
|
||||
i386/apm/apm.c optional apm device-driver
|
||||
i386/apm/apm_setup.s optional apm
|
||||
@ -158,3 +158,4 @@ gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate
|
||||
gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate
|
||||
gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate
|
||||
gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate
|
||||
netinet/ip_fw.c optional ipfirewall
|
||||
|
100
sys/i386/conf/IPFIREWALL
Normal file
100
sys/i386/conf/IPFIREWALL
Normal file
@ -0,0 +1,100 @@
|
||||
#
|
||||
# IPFIREWALL -- Sample Generic kernel suitable for building an IP firewall.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
machine "i386"
|
||||
cpu "I386_CPU"
|
||||
cpu "I486_CPU"
|
||||
cpu "I586_CPU"
|
||||
ident GENERIC
|
||||
maxusers 10
|
||||
|
||||
options INET #InterNETworking
|
||||
options FFS #Berkeley Fast File System
|
||||
options NFS #Network File system
|
||||
options PROCFS #Process filesystem
|
||||
options "COMPAT_43" #Compatible with BSD 4.3
|
||||
options UCONSOLE #X Console support
|
||||
options "FAT_CURSOR" #block cursor in syscons or pccons
|
||||
options "SCSI_DELAY=15" #Be pessimistic about Joe SCSI device
|
||||
options "NCONS=4" #4 virtual consoles
|
||||
options BOUNCE_BUFFERS #include support for DMA bounce buffers
|
||||
options USERCONFIG #Allow user configuration with -c
|
||||
options GATEWAY #Pass packets
|
||||
options IPFIREWALL #firewall code
|
||||
options IPFIREWALL_VERBOSE #print information about dropped packets
|
||||
options IPBROADCASTECHO=1 #send reply to broadcast pings
|
||||
options IPMASKAGENT=1 #send reply to icmp mask requests
|
||||
|
||||
config kernel root on wd0 swap on wd0 and wd1 and sd0 and sd1 dumps on wd0
|
||||
|
||||
controller isa0
|
||||
controller pci0
|
||||
|
||||
controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr
|
||||
disk fd0 at fdc0 drive 0
|
||||
disk fd1 at fdc0 drive 1
|
||||
#tape ft0 at fdc0 drive 2
|
||||
|
||||
controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr
|
||||
disk wd0 at wdc0 drive 0
|
||||
disk wd1 at wdc0 drive 1
|
||||
|
||||
controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr
|
||||
disk wd2 at wdc1 drive 0
|
||||
disk wd3 at wdc1 drive 1
|
||||
|
||||
controller ncr0
|
||||
|
||||
controller bt0 at isa? port "IO_BT0" bio irq ? vector btintr
|
||||
controller ahb0 at isa? bio irq ? vector ahbintr
|
||||
controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr
|
||||
controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr
|
||||
controller aic0 at isa? port 0x340 bio irq 11 vector aicintr
|
||||
controller pas0 at isa? port 0x1f88 bio
|
||||
controller sea0 at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr
|
||||
controller scbus0
|
||||
|
||||
device sd0
|
||||
device sd1
|
||||
device sd2
|
||||
device sd3
|
||||
|
||||
device st0
|
||||
device st1
|
||||
|
||||
device cd0 #Only need one of these, the code dynamically grows
|
||||
|
||||
device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr
|
||||
device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr
|
||||
device mcd1 at isa? port 0x340 bio irq 11 vector mcdintr
|
||||
|
||||
device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr
|
||||
device npx0 at isa? port "IO_NPX" irq 13 vector npxintr
|
||||
|
||||
device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr
|
||||
device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr
|
||||
device sio2 at isa? port "IO_COM3" tty irq 5 vector siointr
|
||||
device sio3 at isa? port "IO_COM4" tty irq 9 vector siointr
|
||||
|
||||
device lpt0 at isa? port? tty irq 7 vector lptintr
|
||||
device lpt1 at isa? port? tty
|
||||
device lpt2 at isa? port? tty
|
||||
|
||||
device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr
|
||||
device ed1 at isa? port 0x300 net irq 5 iomem 0xd8000 vector edintr
|
||||
device ed2 at isa? port 0x300 net irq 10 iomem 0xcc000 vector edintr
|
||||
device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr
|
||||
device is0 at isa? port 0x280 net irq 10 drq 7 vector isintr
|
||||
|
||||
pseudo-device loop
|
||||
pseudo-device ether
|
||||
pseudo-device log
|
||||
pseudo-device ppp 2
|
||||
pseudo-device sl 2
|
||||
pseudo-device pty 16
|
||||
pseudo-device speaker
|
||||
pseudo-device gzip # Exec gzipped a.out's
|
||||
pseudo-device bpfilter 1
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# This kernel is NOT MEANT to be runnable!
|
||||
#
|
||||
# $Id: LINT,v 1.100 1994/10/26 19:20:27 jkh Exp $
|
||||
# $Id: LINT,v 1.101 1994/10/26 21:10:13 wollman Exp $
|
||||
#
|
||||
|
||||
#
|
||||
@ -41,6 +41,12 @@ options MATH_EMULATE #Support for x87 emulation
|
||||
#options GPL_MATH_EMULATE #Support for x87 emualtion via
|
||||
#new math emulator
|
||||
|
||||
# Enable the following (IPFIREWALL_VERBOSE optional) to enable the IP firewall
|
||||
# code. This is used in conjunction with the ipfw(1) command. See the
|
||||
# man page for more details.
|
||||
options IPFIREWALL #firewall test
|
||||
options IPFIREWALL_VERBOSE #print information about dropped packets
|
||||
|
||||
#
|
||||
# This directive defines a number of things:
|
||||
# - The compiled kernel is to be called `kernel'
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# This kernel is NOT MEANT to be runnable!
|
||||
#
|
||||
# $Id: LINT,v 1.100 1994/10/26 19:20:27 jkh Exp $
|
||||
# $Id: LINT,v 1.101 1994/10/26 21:10:13 wollman Exp $
|
||||
#
|
||||
|
||||
#
|
||||
@ -41,6 +41,12 @@ options MATH_EMULATE #Support for x87 emulation
|
||||
#options GPL_MATH_EMULATE #Support for x87 emualtion via
|
||||
#new math emulator
|
||||
|
||||
# Enable the following (IPFIREWALL_VERBOSE optional) to enable the IP firewall
|
||||
# code. This is used in conjunction with the ipfw(1) command. See the
|
||||
# man page for more details.
|
||||
options IPFIREWALL #firewall test
|
||||
options IPFIREWALL_VERBOSE #print information about dropped packets
|
||||
|
||||
#
|
||||
# This directive defines a number of things:
|
||||
# - The compiled kernel is to be called `kernel'
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This file tells config what files go into building a kernel,
|
||||
# files marked standard are always included.
|
||||
#
|
||||
# $Id: files.i386,v 1.55 1994/10/26 19:19:12 jkh Exp $
|
||||
# $Id: files.i386,v 1.56 1994/10/27 20:44:27 jkh Exp $
|
||||
#
|
||||
i386/apm/apm.c optional apm device-driver
|
||||
i386/apm/apm_setup.s optional apm
|
||||
@ -158,3 +158,4 @@ gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate
|
||||
gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate
|
||||
gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate
|
||||
gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate
|
||||
netinet/ip_fw.c optional ipfirewall
|
||||
|
512
sys/netinet/ip_fw.c
Normal file
512
sys/netinet/ip_fw.c
Normal file
@ -0,0 +1,512 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implement IP packet firewall
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/errno.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 <netinet/ip_fw.h>
|
||||
|
||||
struct ip_firewall *ip_fw_fwd_chain;
|
||||
struct ip_firewall *ip_fw_blk_chain;
|
||||
int ip_fw_policy=1;
|
||||
|
||||
|
||||
inline
|
||||
void
|
||||
print_ip(xaddr)
|
||||
struct in_addr xaddr;
|
||||
{
|
||||
u_long addr = ntohl(xaddr.s_addr);
|
||||
printf("%d.%d.%d.%d",(addr>>24) & 0xff,
|
||||
(addr>>16)&0xff,
|
||||
(addr>>8)&0xff,
|
||||
addr&0xFF);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns 1 if the port is matched by the vector, 0 otherwise
|
||||
*/
|
||||
|
||||
inline
|
||||
int port_match(portptr,nports,port,range_flag)
|
||||
u_short *portptr;
|
||||
int nports;
|
||||
u_short port;
|
||||
int range_flag;
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns 0 if packet should be dropped, 1 if it should be accepted
|
||||
*/
|
||||
|
||||
|
||||
int ip_firewall_check_print(ip,chain)
|
||||
struct ip *ip;
|
||||
struct ip_firewall *chain;
|
||||
{
|
||||
if ( !ip_firewall_check_noprint(ip,chain) ) {
|
||||
|
||||
u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]);
|
||||
|
||||
printf("ip_firewall_check 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);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
int ip_firewall_check_noprint(ip,chain)
|
||||
struct ip *ip;
|
||||
struct ip_firewall *chain;
|
||||
{
|
||||
struct in_addr src, dst;
|
||||
char got_proto = 0;
|
||||
int firewall_proto, proto = 0;
|
||||
register struct ip_firewall *fptr;
|
||||
u_short src_port = 0, dst_port = 0;
|
||||
|
||||
if ( chain == NULL ) { /* Is there a firewall chain? */
|
||||
return(1);
|
||||
}
|
||||
|
||||
src = ip->ip_src;
|
||||
dst = ip->ip_dst;
|
||||
|
||||
#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;
|
||||
}
|
||||
print_ip(ip->ip_src);
|
||||
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 ) {
|
||||
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 ( (firewall_proto = fptr->flags & IP_FIREWALL_KIND) == IP_FIREWALL_UNIVERSAL ) {
|
||||
|
||||
/* Universal firewall - we've got a match! */
|
||||
|
||||
#ifdef DEBUG_IPFIREWALL
|
||||
printf("universal firewall match\n");
|
||||
#endif
|
||||
#ifdef olf
|
||||
return( (fptr->flags & IP_FIREWALL_ACCEPT) == IP_FIREWALL_ACCEPT );
|
||||
#else
|
||||
return( fptr->flags & IP_FIREWALL_ACCEPT );
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
/* Specific firewall - packet's protocol must match firewall's */
|
||||
|
||||
if ( !got_proto ) {
|
||||
u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]);
|
||||
switch( ip->ip_p ) {
|
||||
case IPPROTO_TCP:
|
||||
proto = IP_FIREWALL_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_FIREWALL_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_FIREWALL_ICMP;
|
||||
break;
|
||||
default: proto = IP_FIREWALL_UNIVERSAL;
|
||||
#ifdef DEBUG_IPFIREWALL
|
||||
printf("non TCP/UDP packet\n");
|
||||
#endif
|
||||
}
|
||||
got_proto = 1;
|
||||
}
|
||||
|
||||
if ( proto == firewall_proto ) {
|
||||
|
||||
if (
|
||||
proto == IP_FIREWALL_ICMP
|
||||
||
|
||||
(
|
||||
(
|
||||
fptr->num_src_ports == 0
|
||||
||
|
||||
port_match( &fptr->ports[0],
|
||||
fptr->num_src_ports,
|
||||
src_port,
|
||||
fptr->flags & IP_FIREWALL_SRC_RANGE
|
||||
)
|
||||
)
|
||||
&&
|
||||
(
|
||||
fptr->num_dst_ports == 0
|
||||
||
|
||||
port_match( &fptr->ports[fptr->num_src_ports],
|
||||
fptr->num_dst_ports,
|
||||
dst_port,
|
||||
fptr->flags & IP_FIREWALL_DST_RANGE
|
||||
)
|
||||
)
|
||||
)
|
||||
) {
|
||||
|
||||
#ifdef old
|
||||
return( (fptr->flags & IP_FIREWALL_ACCEPT) == IP_FIREWALL_ACCEPT );
|
||||
|
||||
#else
|
||||
return( fptr->flags & IP_FIREWALL_ACCEPT);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here then none of the firewalls matched.
|
||||
* If the first firewall was an accept firewall then reject the packet.
|
||||
* If the first firewall was a deny firewall then accept the packet.
|
||||
*
|
||||
* The basic idea is that there is a virtual final firewall which is
|
||||
* the exact complement of the first firewall (this idea is a slight
|
||||
* variant of the way that the Telebit's Netblazer IP filtering scheme
|
||||
* handles this case).
|
||||
*/
|
||||
|
||||
#ifdef old
|
||||
return( ((chain->flags) & IP_FIREWALL_ACCEPT) != IP_FIREWALL_ACCEPT );
|
||||
#else
|
||||
return(ip_fw_policy);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
free_firewall_chain(chainptr)
|
||||
struct ip_firewall **chainptr;
|
||||
{
|
||||
while ( *chainptr != NULL ) {
|
||||
struct ip_firewall *ftmp;
|
||||
ftmp = *chainptr;
|
||||
*chainptr = ftmp->next;
|
||||
free(ftmp,M_SOOPTS);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
add_to_chain(chainptr,firewall)
|
||||
struct ip_firewall **chainptr;
|
||||
struct ip_firewall *firewall;
|
||||
{
|
||||
struct ip_firewall *ftmp;
|
||||
struct ip_firewall *chaintmp=NULL;
|
||||
|
||||
ftmp = malloc( sizeof(struct ip_firewall), M_SOOPTS, M_DONTWAIT );
|
||||
if ( ftmp == NULL ) {
|
||||
printf("ip_firewall_ctl: malloc said no\n");
|
||||
return( ENOSPC );
|
||||
}
|
||||
|
||||
bcopy( firewall, ftmp, sizeof( struct ip_firewall ) );
|
||||
ftmp->next = NULL;
|
||||
|
||||
if (*chainptr==NULL)
|
||||
{
|
||||
*chainptr=ftmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This made so to get firewall behavior more *human* oriented-
|
||||
* as to speed up the packet check the first firewall matching
|
||||
* the packet used to determine ALLOW/DENY condition,and one
|
||||
* tends to set up more specific firewall later then more general
|
||||
* this change allows adding firewalls to the head of chain so
|
||||
* that the first matching is last added in line of matching
|
||||
* firewalls.This change is not real turn in behavior but helps
|
||||
* to use firewall efficiently.
|
||||
*/
|
||||
#ifdef old
|
||||
chaintmp=*chainptr;
|
||||
while(chaintmp->next!=NULL)
|
||||
chaintmp=chaintmp->next;
|
||||
chaintmp->next=ftmp;
|
||||
#else
|
||||
chaintmp=*chainptr;
|
||||
*chainptr=ftmp;
|
||||
ftmp->next=chaintmp;
|
||||
#endif
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
del_from_chain(chainptr,firewall)
|
||||
struct ip_firewall **chainptr;
|
||||
struct ip_firewall *firewall;
|
||||
{
|
||||
struct ip_firewall *ftmp,*ltmp;
|
||||
u_short tport1,tport2,tmpnum;
|
||||
char matches,was_found;
|
||||
|
||||
ftmp=*chainptr;
|
||||
|
||||
if ( ftmp == NULL ) {
|
||||
printf("ip_firewall_ctl: chain is empty\n");
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
ltmp=NULL;
|
||||
was_found=0;
|
||||
|
||||
while( ftmp != NULL )
|
||||
{
|
||||
matches=1;
|
||||
if ((bcmp(&ftmp->src,&firewall->src,sizeof(struct in_addr)))
|
||||
|| (bcmp(&ftmp->src_mask,&firewall->src_mask,sizeof(struct in_addr)))
|
||||
|| (bcmp(&ftmp->dst,&firewall->dst,sizeof(struct in_addr)))
|
||||
|| (bcmp(&ftmp->dst_mask,&firewall->dst_mask,sizeof(struct in_addr)))
|
||||
|| (ftmp->flags!=firewall->flags))
|
||||
matches=0;
|
||||
tport1=ftmp->num_src_ports+ftmp->num_dst_ports;
|
||||
tport2=firewall->num_src_ports+firewall->num_dst_ports;
|
||||
if (tport1!=tport2)
|
||||
matches=0;
|
||||
else
|
||||
if (tport1!=0)
|
||||
{
|
||||
for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FIREWALL_MAX_PORTS;tmpnum++)
|
||||
if (ftmp->ports[tmpnum]!=firewall->ports[tmpnum])
|
||||
matches=0;
|
||||
}
|
||||
if(matches)
|
||||
{
|
||||
was_found=1;
|
||||
if (ltmp)
|
||||
{
|
||||
ltmp->next=ftmp->next;
|
||||
free(ftmp,M_SOOPTS);
|
||||
ftmp=ltmp->next;
|
||||
/* return 0; */
|
||||
}
|
||||
else
|
||||
{
|
||||
*chainptr=ftmp->next;
|
||||
free(ftmp,M_SOOPTS);
|
||||
ftmp=*chainptr;
|
||||
/* return 0; */
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ltmp = ftmp;
|
||||
ftmp = ftmp->next;
|
||||
}
|
||||
}
|
||||
if (was_found) return 0;
|
||||
else return(EINVAL);
|
||||
}
|
||||
|
||||
int
|
||||
ip_firewall_ctl(stage,m)
|
||||
int stage;
|
||||
struct mbuf *m;
|
||||
{
|
||||
int *tmp_policy_ptr;
|
||||
if ( stage == IP_FW_FLUSH )
|
||||
{
|
||||
free_firewall_chain(&ip_fw_blk_chain);
|
||||
free_firewall_chain(&ip_fw_fwd_chain);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if ( m == 0 )
|
||||
{
|
||||
printf("ip_firewall_ctl: NULL mbuf ptr\n");
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
if ( stage == IP_FW_POLICY )
|
||||
{
|
||||
tmp_policy_ptr=mtod(m,int *);
|
||||
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) ) {
|
||||
printf("ip_firewall_ctl: mbuf len=%d, want at least %d\n",m->m_len,sizeof(struct ip) + 2 * sizeof(u_short));
|
||||
return( EINVAL );
|
||||
}
|
||||
ip = mtod(m,struct ip *);
|
||||
if ( ip->ip_hl != sizeof(struct ip) / sizeof(int) ) {
|
||||
printf("ip_firewall_ctl: ip->ip_hl=%d, want %d\n",ip->ip_hl,sizeof(struct ip)/sizeof(int));
|
||||
return( EINVAL );
|
||||
}
|
||||
if ( ip_firewall_check(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_firewall *firewall;
|
||||
|
||||
if ( m->m_len != sizeof(struct ip_firewall) ) {
|
||||
printf("ip_firewall_ctl: len=%d, want %d\n",m->m_len,sizeof(struct ip_firewall));
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
firewall = mtod(m,struct ip_firewall*);
|
||||
if ( (firewall->flags & ~IP_FIREWALL_FLAG_BITS) != 0 ) {
|
||||
printf("ip_firewall_ctl: undefined flag bits set (flags=%x)\n",firewall->flags);
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
if ( (firewall->flags & IP_FIREWALL_SRC_RANGE) && firewall->num_src_ports < 2 ) {
|
||||
printf("ip_firewall_ctl: SRC_RANGE set but num_src_ports=%d\n",firewall->num_src_ports);
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
if ( (firewall->flags & IP_FIREWALL_DST_RANGE) && firewall->num_dst_ports < 2 ) {
|
||||
printf("ip_firewall_ctl: DST_RANGE set but num_dst_ports=%d\n",firewall->num_dst_ports);
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
if ( firewall->num_src_ports + firewall->num_dst_ports > IP_FIREWALL_MAX_PORTS ) {
|
||||
printf("ip_firewall_ctl: too many ports (%d+%d)\n",firewall->num_src_ports,firewall->num_dst_ports);
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( (firewall->flags & IP_FIREWALL_KIND) == IP_FIREWALL_ICMP ) {
|
||||
printf("ip_firewall_ctl: request for unsupported ICMP firewalling\n");
|
||||
return( EINVAL );
|
||||
}
|
||||
|
||||
#endif
|
||||
if ( stage == IP_FW_ADD_BLK )
|
||||
{
|
||||
return( add_to_chain(&ip_fw_blk_chain,firewall));
|
||||
}
|
||||
if ( stage == IP_FW_ADD_FWD )
|
||||
{
|
||||
return( add_to_chain(&ip_fw_fwd_chain,firewall));
|
||||
}
|
||||
if ( stage == IP_FW_DEL_BLK )
|
||||
{
|
||||
return( del_from_chain(&ip_fw_blk_chain,firewall));
|
||||
}
|
||||
if ( stage == IP_FW_DEL_FWD )
|
||||
{
|
||||
return( del_from_chain(&ip_fw_fwd_chain,firewall));
|
||||
}
|
||||
}
|
||||
|
||||
printf("ip_firewall_ctl: unknown request %d\n",stage);
|
||||
return(EINVAL);
|
||||
|
||||
}
|
77
sys/netinet/ip_fw.h
Normal file
77
sys/netinet/ip_fw.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Format of an IP firewall descriptor
|
||||
*
|
||||
* src, dst, src_mask, dst_mask are always stored in network byte order.
|
||||
* flags and num_*_ports are stored in host byte order (of course).
|
||||
* Port numbers are stored in HOST byte order.
|
||||
*/
|
||||
|
||||
struct ip_firewall {
|
||||
struct ip_firewall *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;
|
||||
#define IP_FIREWALL_UNIVERSAL 0 /* This is a universal packet firewall*/
|
||||
#define IP_FIREWALL_TCP 1 /* This is a TCP packet firewall */
|
||||
#define IP_FIREWALL_UDP 2 /* This is a UDP packet firewall */
|
||||
#define IP_FIREWALL_ICMP 3 /* This is a ICMP packet firewall */
|
||||
#define IP_FIREWALL_KIND 3 /* Mask to isolate firewall kind */
|
||||
#define IP_FIREWALL_ACCEPT 4 /* This is an accept firewall (as */
|
||||
/* opposed to a deny firewall) */
|
||||
#define IP_FIREWALL_SRC_RANGE 8 /* The first two src ports are a min
|
||||
* and max range (stored in host byte
|
||||
* order).
|
||||
*/
|
||||
#define IP_FIREWALL_DST_RANGE 16 /* The first two dst ports are a min
|
||||
* and max range (stored in host byte
|
||||
* order).
|
||||
* (ports[0] <= port <= ports[1])
|
||||
*/
|
||||
#define IP_FIREWALL_FLAG_BITS 0x1f /* All possible flag bits */
|
||||
u_short num_src_ports, num_dst_ports;/* # 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_FIREWALL_MAX_PORTS 10 /* A reasonable maximum */
|
||||
u_short ports[IP_FIREWALL_MAX_PORTS]; /* Array of port numbers to match */
|
||||
};
|
||||
|
||||
/*
|
||||
* New IP firewall options for [gs]etsockopt at the RAW IP level.
|
||||
*/
|
||||
#define IP_FW_BASE_CTL 53
|
||||
|
||||
#define IP_FW_ADD_BLK (IP_FW_BASE_CTL)
|
||||
#define IP_FW_ADD_FWD (IP_FW_BASE_CTL+1)
|
||||
#define IP_FW_CHK_BLK (IP_FW_BASE_CTL+2)
|
||||
#define IP_FW_CHK_FWD (IP_FW_BASE_CTL+3)
|
||||
#define IP_FW_DEL_BLK (IP_FW_BASE_CTL+4)
|
||||
#define IP_FW_DEL_FWD (IP_FW_BASE_CTL+5)
|
||||
#define IP_FW_FLUSH (IP_FW_BASE_CTL+6)
|
||||
#define IP_FW_POLICY (IP_FW_BASE_CTL+7)
|
||||
|
||||
|
||||
extern struct ip_firewall *ip_fw_blk_chain;
|
||||
extern struct ip_firewall *ip_fw_fwd_chain;
|
||||
extern int ip_fw_policy;
|
||||
|
||||
#ifdef IPFIREWALL_VERBOSE
|
||||
#define ip_firewall_check ip_firewall_check_print
|
||||
#else
|
||||
#define ip_firewall_check ip_firewall_check_noprint
|
||||
#endif
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
|
||||
* $Id: ip_input.c,v 1.7 1994/10/02 17:48:39 phk Exp $
|
||||
* $Id: ip_input.c,v 1.8 1994/10/10 07:56:07 phk Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -56,6 +56,10 @@
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
|
||||
#ifdef IPFIREWALL
|
||||
#include <netinet/ip_fw.h>
|
||||
#endif
|
||||
|
||||
#include <sys/socketvar.h>
|
||||
struct socket *ip_rsvpd;
|
||||
|
||||
@ -231,6 +235,13 @@ ipintr()
|
||||
m_adj(m, ip->ip_len - m->m_pkthdr.len);
|
||||
}
|
||||
|
||||
#ifdef IPFIREWALL
|
||||
if ( ((char *)&(ip->ip_dst.s_addr))[0] != 127
|
||||
&& !ip_firewall_check(ip,ip_fw_blk_chain) ) {
|
||||
goto bad;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Process options and, if not destined for us,
|
||||
* ship it on. ip_dooptions returns 1 when an
|
||||
@ -341,6 +352,7 @@ ipintr()
|
||||
goto next;
|
||||
|
||||
ours:
|
||||
|
||||
/*
|
||||
* If offset or IP_MF are set, must reassemble.
|
||||
* Otherwise, nothing need be done.
|
||||
@ -1019,9 +1031,19 @@ ip_forward(m, srcrt)
|
||||
dest = 0;
|
||||
#ifdef DIAGNOSTIC
|
||||
if (ipprintfs)
|
||||
printf("forward: src %lx dst %lx ttl %x\n",
|
||||
printf("forward: src %lx dst %lx ttl %x\n",
|
||||
ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl);
|
||||
#endif
|
||||
|
||||
#ifdef IPFIREWALL
|
||||
if ( ((char *)&(ip->ip_dst.s_addr))[0] != 127
|
||||
&& !ip_firewall_check(ip,ip_fw_fwd_chain) ) {
|
||||
ipstat.ips_cantforward++;
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
|
||||
ipstat.ips_cantforward++;
|
||||
m_freem(m);
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
|
||||
* $Id: raw_ip.c,v 1.4 1994/09/14 03:10:15 wollman Exp $
|
||||
* $Id: raw_ip.c,v 1.5 1994/10/02 17:48:42 phk Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -53,6 +53,10 @@
|
||||
#include <netinet/ip_mroute.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
|
||||
#ifdef IPFIREWALL
|
||||
#include <netinet/ip_fw.h>
|
||||
#endif
|
||||
|
||||
struct inpcb rawinpcb;
|
||||
|
||||
/*
|
||||
@ -204,6 +208,24 @@ rip_ctloutput(op, so, level, optname, m)
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef IPFIREWALL
|
||||
case IP_FW_ADD_BLK:
|
||||
case IP_FW_ADD_FWD:
|
||||
case IP_FW_CHK_BLK:
|
||||
case IP_FW_CHK_FWD:
|
||||
case IP_FW_DEL_BLK:
|
||||
case IP_FW_DEL_FWD:
|
||||
case IP_FW_FLUSH:
|
||||
case IP_FW_POLICY:
|
||||
|
||||
if (op == PRCO_SETOPT)
|
||||
error=ip_firewall_ctl(optname, *m);
|
||||
else
|
||||
error=EINVAL;
|
||||
return(error);
|
||||
#endif
|
||||
|
||||
|
||||
case IP_RSVP_ON:
|
||||
error = ip_rsvp_init(so);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user