summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorpst <pst@FreeBSD.org>1996-08-13 19:43:41 +0000
committerpst <pst@FreeBSD.org>1996-08-13 19:43:41 +0000
commitcebbb4d75dc810dc5b828857e106d0047dc14d1e (patch)
tree28ebdb76530100a06ba37e266e30010da1624268 /sys/netinet
parentec444da95fd9d19755af5b5e1f976423bc345a7b (diff)
downloadFreeBSD-src-cebbb4d75dc810dc5b828857e106d0047dc14d1e.zip
FreeBSD-src-cebbb4d75dc810dc5b828857e106d0047dc14d1e.tar.gz
Completely rewrite handling of protocol field for firewalls, things are
now completely consistent across all IP protocols and should be quite a bit faster. Discussed with: fenner & alex
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_fw.c133
-rw-r--r--sys/netinet/ip_fw.h10
2 files changed, 45 insertions, 98 deletions
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index 3261f69..2109035 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -12,7 +12,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.c,v 1.46 1996/07/14 21:12:52 alex Exp $
+ * $Id: ip_fw.c,v 1.47 1996/08/05 02:35:04 alex Exp $
*/
/*
@@ -287,21 +287,7 @@ ip_fw_chk(struct ip **pip, int hlen,
struct icmp *icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl);
struct ifaddr *ia = NULL, *ia_p;
struct in_addr src, dst, ia_i;
- u_short src_port = 0, dst_port = 0;
- u_short f_prt = 0, prt, len = 0;
-
- /*
- * ... else if non-zero, highly unusual and interesting, but
- * we're not going to pass it...
- */
- if ((ip->ip_off & IP_OFFMASK) == 1) {
- static int frag_counter = 0;
-
- ++frag_counter;
- ipfw_report("Refuse", -1, ip, frag_counter);
- m_freem(*m);
- return -1;
- }
+ u_short src_port, dst_port, offset;
src = ip->ip_src;
dst = ip->ip_dst;
@@ -314,33 +300,6 @@ ip_fw_chk(struct ip **pip, int hlen,
ia = rif->if_addrlist;
/*
- * Determine the protocol and extract some useful stuff
- */
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- src_port = ntohs(tcp->th_sport);
- dst_port = ntohs(tcp->th_dport);
- prt = IP_FW_F_TCP;
- len = sizeof (*tcp);
- break;
- case IPPROTO_UDP:
- src_port = ntohs(udp->uh_sport);
- dst_port = ntohs(udp->uh_dport);
- prt = IP_FW_F_UDP;
- len = sizeof (*udp);
- break;
- case IPPROTO_ICMP:
- prt = IP_FW_F_ICMP;
- len = sizeof (*icmp);
- break;
- default:
- prt = IP_FW_F_ALL;
- break;
- }
-
- /* XXX Check that we have sufficient header for TCP analysis */
-
- /*
* Go down the chain, looking for enlightment
*/
for (chain=ip_fw_chain.lh_first; chain; chain = chain->chain.le_next) {
@@ -410,52 +369,53 @@ ip_fw_chk(struct ip **pip, int hlen,
if (!ipopts_match(ip, f))
continue;
- /*
- * Check protocol
- */
- f_prt = f->fw_flg & IP_FW_F_KIND;
-
/* If wildcard, match */
- if (f_prt == IP_FW_F_ALL) {
- int pnum;
-
- if (f->fw_nsp == 0)
- goto got_match;
- /* Look for a matching IP protocol */
- for (pnum = 0; pnum < f->fw_nsp; pnum++)
- if (ip->ip_p == f->fw_pts[pnum])
- goto got_match;
-
- continue;
- }
+ if (f->fw_prot == IPPROTO_IP)
+ goto got_match;
/* If different, dont match */
- if (prt != f_prt)
+ if (ip->ip_p != f->fw_prot)
continue;
- /* ICMP, done */
- if (prt == IP_FW_F_ICMP) {
- if (!icmptype_match(icmp, f))
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ offset = ip->ip_off & IP_OFFMASK;
+ if (offset == 1) {
+ static int frag_counter = 0;
+ ++frag_counter;
+ ipfw_report("Refuse", -1, ip, frag_counter);
+ m_freem(*m);
+ return -1;
+ }
+ if ((offset == 0) &&
+ (f->fw_tcpf != f->fw_tcpnf) &&
+ !tcpflg_match(tcp, f))
continue;
- goto got_match;
- }
+ src_port = ntohs(tcp->th_sport);
+ dst_port = ntohs(tcp->th_dport);
+ goto check_ports;
- /* Check TCP flags and TCP/UDP ports only if packet is not fragment */
- if (!(ip->ip_off & IP_OFFMASK)) {
- /* TCP, a little more checking */
- if (prt == IP_FW_F_TCP &&
- (f->fw_tcpf != f->fw_tcpnf) &&
- (!tcpflg_match(tcp, f)))
- continue;
+ case IPPROTO_UDP:
+ src_port = ntohs(udp->uh_sport);
+ dst_port = ntohs(udp->uh_dport);
+check_ports:
if (!port_match(&f->fw_pts[0], f->fw_nsp,
- src_port, f->fw_flg & IP_FW_F_SRNG))
+ src_port, f->fw_flg & IP_FW_F_SRNG))
continue;
-
if (!port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp,
- dst_port, f->fw_flg & IP_FW_F_DRNG))
+ dst_port, f->fw_flg & IP_FW_F_DRNG))
continue;
+ break;
+
+ case IPPROTO_ICMP:
+ if (!icmptype_match(icmp, f))
+ continue;
+ goto got_match;
+
+ default:
+ break;
}
got_match:
@@ -512,12 +472,9 @@ got_match:
*/
if (dirport >= 0
&& (f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_DENY
- && (prt != IP_FW_F_ICMP)
+ && (ip->ip_p != IPPROTO_ICMP)
&& (f->fw_flg & IP_FW_F_ICMPRPL)) {
- if (f_prt == IP_FW_F_ALL)
- icmp_error(*m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0L, 0);
- else
- icmp_error(*m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0L, 0);
+ icmp_error(*m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0L, 0);
return -1;
}
m_freem(*m);
@@ -688,17 +645,13 @@ check_ipfw_struct(struct mbuf *m)
err_prefix, frwl->fw_nsp, frwl->fw_ndp));
return (NULL);
}
- if ((frwl->fw_flg & IP_FW_F_ALL) &&
- (frwl->fw_flg & (IP_FW_F_SRNG | IP_FW_F_DRNG))) {
- dprintf(("%s proto ranges not allowed", err_prefix));
- }
-
/*
* ICMP protocol doesn't use port range
*/
- if ((frwl->fw_flg & IP_FW_F_KIND) == IP_FW_F_ICMP &&
- (frwl->fw_nsp || frwl->fw_ndp)) {
- dprintf(("%s port(s) specified for ICMP rule\n",
+ if ((frwl->fw_prot != IPPROTO_TCP) &&
+ (frwl->fw_prot != IPPROTO_UDP) &&
+ (frwl->fw_nsp || frwl->fw_ndp)) {
+ dprintf(("%s port(s) specified for non TCP/UDP rule\n",
err_prefix));
return(NULL);
}
@@ -800,7 +753,7 @@ ip_fw_init(void)
LIST_INIT(&ip_fw_chain);
bzero(&deny, sizeof deny);
- deny.fw_flg = IP_FW_F_ALL;
+ deny.fw_prot = IPPROTO_IP;
deny.fw_number = (u_short)-1;
add_entry(&ip_fw_chain, &deny);
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index b63bc74..6efa66b 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -11,7 +11,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.h,v 1.20 1996/06/09 23:46:21 alex Exp $
+ * $Id: ip_fw.h,v 1.21 1996/07/10 19:44:24 julian Exp $
*/
/*
@@ -53,6 +53,7 @@ struct ip_fw {
unsigned fw_icmptypes[IP_FW_ICMPTYPES_DIM]; /* ICMP types bitmap */
long timestamp; /* timestamp (tv_sec) of last match */
u_short fw_divert_port; /* Divert port (options IPDIVERT) */
+ u_char fw_prot; /* IP protocol */
};
struct ip_fw_chain {
@@ -63,13 +64,6 @@ struct ip_fw_chain {
/*
* Values for "flags" field .
*/
-
-#define IP_FW_F_ALL 0x0000 /* This is a universal packet rule */
-#define IP_FW_F_TCP 0x0001 /* This is a TCP packet rule */
-#define IP_FW_F_UDP 0x0002 /* This is a UDP packet rule */
-#define IP_FW_F_ICMP 0x0003 /* This is a ICMP packet rule */
-#define IP_FW_F_KIND 0x0003 /* Mask to isolate rule kind */
-
#define IP_FW_F_IN 0x0004 /* Inbound */
#define IP_FW_F_OUT 0x0008 /* Outbound */
OpenPOWER on IntegriCloud