diff options
author | pst <pst@FreeBSD.org> | 1996-08-13 19:43:41 +0000 |
---|---|---|
committer | pst <pst@FreeBSD.org> | 1996-08-13 19:43:41 +0000 |
commit | cebbb4d75dc810dc5b828857e106d0047dc14d1e (patch) | |
tree | 28ebdb76530100a06ba37e266e30010da1624268 /sys/netinet | |
parent | ec444da95fd9d19755af5b5e1f976423bc345a7b (diff) | |
download | FreeBSD-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.c | 133 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 10 |
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 */ |