Latest changes from Uben.

Submitted by:	uben
This commit is contained in:
Jordan K. Hubbard 1994-10-31 23:58:04 +00:00
parent beef52db54
commit 0a87b23329
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=4036
3 changed files with 219 additions and 52 deletions

View File

@ -53,10 +53,11 @@ typedef enum {
} ipf_kind;
int do_resolv=1;
int do_verbose=0;
show_usage()
{
fprintf(stderr,"ipfw: [-n] <command>\n");
fprintf(stderr,"ipfw: [-nv] <command>\n");
}
@ -744,6 +745,8 @@ add(ipf_kind kind, int socket_fd, char **argv)
if ( *argv == NULL ) {
firewall.flags = protocol | accept_firewall | src_range | dst_range;
if (do_verbose)
firewall.flags=firewall.flags | IP_FIREWALL_PRINT;
(void)do_setsockopt(
socket_fd, IPPROTO_IP,
kind == IPF_BLOCKING ? IP_FW_ADD_BLK : IP_FW_ADD_FWD,
@ -896,11 +899,11 @@ if (b!=0 && b!=1)
exit(1);
}
if (strncmp(argv[0],"deny",strlen(argv[0])))
p=1;
else
if (strncmp(argv[0],"accept",strlen(argv[0])))
if (!strncmp(argv[0],"deny",strlen(argv[0])))
p=0;
else
if (!strncmp(argv[0],"accept",strlen(argv[0])))
p=1;
else
{
fprintf(stderr,"usage: ipfw policy [deny|accept]\n");
@ -924,6 +927,9 @@ char **argv;
int socket_fd;
struct ip_firewall *data,*fdata;
char **str;
extern char *optarg;
extern int optind;
int ch;
socket_fd = socket( AF_INET, SOCK_RAW, IPPROTO_RAW );
@ -937,13 +943,20 @@ char **argv;
exit(1);
}
if (!strcmp(argv[1],"-n"))
{
str=&argv[2];
do_resolv=0;
}
else
str=&argv[1];
while ((ch = getopt(argc, argv, "vn")) != EOF)
switch(ch) {
case 'n':
do_resolv=0;
break;
case 'v':
do_verbose=1;
break;
case '?':
default:
show_usage();
}
str=argv+optind;
if (str[0]==NULL)
{
@ -959,6 +972,7 @@ char **argv;
(void)do_setsockopt( socket_fd, IPPROTO_IP,
IP_FW_FLUSH, NULL, 0, 0 );
printf("All entries flushed.\n");
} else if ( strlen(str[0]) >= strlen("checkb")
&& strncmp(str[0],"checkblocking",strlen(str[0])) == 0 ) {

View File

@ -89,12 +89,14 @@ int range_flag;
* Returns 0 if packet should be dropped, 1 if it should be accepted
*/
#ifdef old
int ip_firewall_check_print(ip,chain)
struct ip *ip;
struct ip_firewall *chain;
{
if ( !ip_firewall_check_noprint(ip,chain) ) {
struct ip_firewall *fwtmp;
if ( !ip_firewall_check_noprint(ip,chain,&fwtmp) ) {
u_short *portptr = (u_short *)&(((u_int *)ip)[ip->ip_hl]);
@ -121,7 +123,9 @@ struct ip_firewall *chain;
return(1);
}
int ip_firewall_check_noprint(ip,chain)
#endif
int ip_firewall_check(ip,chain)
struct ip *ip;
struct ip_firewall *chain;
{
@ -130,6 +134,9 @@ struct ip_firewall *chain;
int firewall_proto, proto = 0;
register struct ip_firewall *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 firewall chain? */
return(1);
@ -172,12 +179,31 @@ struct ip_firewall *chain;
#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 );
#ifdef IPFIREWALL_VERBOSE
if ( !(fptr->flags & IP_FIREWALL_ACCEPT) &&
(fptr->flags & IP_FIREWALL_PRINT)) {
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);
}
#endif
return( fptr->flags & IP_FIREWALL_ACCEPT );
} else {
/* Specific firewall - packet's protocol must match firewall's */
@ -234,12 +260,31 @@ struct ip_firewall *chain;
)
) {
#ifdef old
return( (fptr->flags & IP_FIREWALL_ACCEPT) == IP_FIREWALL_ACCEPT );
#else
return( fptr->flags & IP_FIREWALL_ACCEPT);
#ifdef IPFIREWALL_VERBOSE
if ( !(fptr->flags & IP_FIREWALL_ACCEPT) &&
(fptr->flags & IP_FIREWALL_PRINT)) {
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);
}
#endif
return( fptr->flags & IP_FIREWALL_ACCEPT);
}
}
@ -261,11 +306,31 @@ struct ip_firewall *chain;
* handles this case).
*/
#ifdef old
return( ((chain->flags) & IP_FIREWALL_ACCEPT) != IP_FIREWALL_ACCEPT );
#else
return(ip_fw_policy);
#ifdef IPFIREWALL_VERBOSE
if ( !(ip_fw_policy) &&
(fptr->flags & IP_FIREWALL_PRINT)) {
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);
}
#endif
return(ip_fw_policy);
}
@ -291,6 +356,12 @@ struct ip_firewall *firewall;
{
struct ip_firewall *ftmp;
struct ip_firewall *chaintmp=NULL;
struct ip_firewall *chaintmp_prev=NULL;
u_long m_src_mask,m_dst_mask;
u_long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
u_short oldkind,newkind;
int addb4=0;
int n_o,n_n;
ftmp = malloc( sizeof(struct ip_firewall), M_SOOPTS, M_DONTWAIT );
if ( ftmp == NULL ) {
@ -307,26 +378,108 @@ struct ip_firewall *firewall;
}
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;
chaintmp_prev=NULL;
for (chaintmp=*chainptr;chaintmp!=NULL;chaintmp=chaintmp->next) {
addb4=0;
newkind=ftmp->flags & IP_FIREWALL_KIND;
oldkind=chaintmp->flags & IP_FIREWALL_KIND;
if (newkind!=IP_FIREWALL_UNIVERSAL
&& oldkind!=IP_FIREWALL_UNIVERSAL
&& oldkind!=newkind)
continue;
/*
* Very very *UGLY* code...
* Sorry,but i had to do this....
*/
n_sa=ntohl(ftmp->src.s_addr);
n_da=ntohl(ftmp->dst.s_addr);
n_sm=ntohl(ftmp->src_mask.s_addr);
n_dm=ntohl(ftmp->dst_mask.s_addr);
o_sa=ntohl(chaintmp->src.s_addr);
o_da=ntohl(chaintmp->dst.s_addr);
o_sm=ntohl(chaintmp->src_mask.s_addr);
o_dm=ntohl(chaintmp->dst_mask.s_addr);
m_src_mask = o_sm & n_sm;
m_dst_mask = o_dm & n_dm;
if ((o_sa & m_src_mask) == (n_sa & m_src_mask)) {
if (n_sm > o_sm)
addb4++;
if (n_sm < o_sm)
addb4--;
}
if ((o_da & m_dst_mask) == (n_da & m_dst_mask)) {
if (n_dm > o_dm)
addb4++;
if (n_dm < o_dm)
addb4--;
}
if (((o_da & o_dm) == (n_da & n_dm))
&&((o_sa & o_sm) == (n_sa & n_sm)))
{
if (newkind!=IP_FIREWALL_UNIVERSAL &&
oldkind==IP_FIREWALL_UNIVERSAL)
addb4++;
if (newkind==oldkind && (oldkind==IP_FIREWALL_TCP
|| oldkind==IP_FIREWALL_UDP)) {
if ( (!(ftmp->flags & IP_FIREWALL_SRC_RANGE)
&& ftmp->num_src_ports>0)
|| (!(ftmp->flags & IP_FIREWALL_DST_RANGE)
&& ftmp->num_dst_ports>0))
addb4++;
if ((ftmp->flags & IP_FIREWALL_SRC_RANGE) &&
(chaintmp->flags & IP_FIREWALL_SRC_RANGE))
if ((ftmp->ports[1]-ftmp->ports[0])<
(chaintmp->ports[1]-chaintmp->ports[0]))
addb4++;
n_n=ftmp->num_src_ports;
n_o=chaintmp->num_src_ports;
if ((n_n>(IP_FIREWALL_MAX_PORTS-2)) ||
(n_o>(IP_FIREWALL_MAX_PORTS-2)))
goto skip_1_check;
/*
* Actually this cannot happen as the firewall control
* procedure checks for number of ports in source and
* destination range but we will try to be more safe.
*/
if ((ftmp->flags & IP_FIREWALL_DST_RANGE) &&
(chaintmp->flags & IP_FIREWALL_DST_RANGE))
if ((ftmp->ports[n_n+1]-ftmp->ports[n_n])<
(chaintmp->ports[n_o+1]-chaintmp->ports[n_o]))
addb4++;
skip_1_check:
}
}
if (addb4>0) {
if (chaintmp_prev) {
chaintmp_prev->next=ftmp;
ftmp->next=chaintmp;
} else {
*chainptr=ftmp;
ftmp->next=chaintmp;
}
return 0;
}
chaintmp_prev=chaintmp;
}
if (chaintmp_prev)
chaintmp_prev->next=ftmp;
else
#define wrong
#ifdef wrong
*chainptr=ftmp;
#else
chaintmp=*chainptr;
*chainptr=ftmp;
ftmp->next=chaintmp;
panic("Can't happen");
#endif
#undef wrong
}
return(0);
}
@ -422,6 +575,8 @@ if ( stage == IP_FW_FLUSH )
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;
}

View File

@ -19,6 +19,8 @@
* flags and num_*_ports are stored in host byte order (of course).
* Port numbers are stored in HOST byte order.
*/
#ifndef _IP_FW_H
#define _IP_FW_H
struct ip_firewall {
struct ip_firewall *next; /* Next firewall on chain */
@ -41,7 +43,8 @@ struct ip_firewall {
* order).
* (ports[0] <= port <= ports[1])
*/
#define IP_FIREWALL_FLAG_BITS 0x1f /* All possible flag bits */
#define IP_FIREWALL_PRINT 32 /* In verbos mode print this firewall */
#define IP_FIREWALL_FLAG_BITS 0x2f /* 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; */
@ -69,9 +72,4 @@ 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