summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1994-10-31 23:58:04 +0000
committerjkh <jkh@FreeBSD.org>1994-10-31 23:58:04 +0000
commit7add8247a95fce1bb4338181aa85418680ef8718 (patch)
tree85f75e2dbf68ce15174a8e346cd56d55f3969749 /sys
parent08c34cf73fe7d9e913d0bd19c2b7439b2cea671a (diff)
downloadFreeBSD-src-7add8247a95fce1bb4338181aa85418680ef8718.zip
FreeBSD-src-7add8247a95fce1bb4338181aa85418680ef8718.tar.gz
Latest changes from Uben.
Submitted by: uben
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/ip_fw.c223
-rw-r--r--sys/netinet/ip_fw.h10
2 files changed, 193 insertions, 40 deletions
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index a1f9355..2f4b5e5 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -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;
}
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index f1ecfc7..fa2c36b 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -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
-
OpenPOWER on IntegriCloud