From 91b3fcc1e2c982b1e7cb98c1dc637495fef116d9 Mon Sep 17 00:00:00 2001 From: phk Date: Sat, 24 Feb 1996 00:17:35 +0000 Subject: [PATCH] The new firewall functionality: Filter on the direction (in/out). Filter on fragment/not fragment. --- sys/netinet/ip_fw.c | 94 +++++++++++++++++++++-------------------- sys/netinet/ip_fw.h | 24 +++++++---- sys/netinet/ip_input.c | 5 ++- sys/netinet/ip_output.c | 4 +- 4 files changed, 70 insertions(+), 57 deletions(-) diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index b2cc241ca3fc..8a23930c83f8 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -11,7 +11,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.c,v 1.14.4.5 1996/02/23 20:10:52 phk Exp $ + * $Id: ip_fw.c,v 1.30 1996/02/23 20:11:37 phk Exp $ */ /* @@ -69,7 +69,7 @@ static int ipopts_match __P((struct ip *ip, struct ip_fw *f)); static int port_match __P((u_short *portptr, int nports, u_short port, int range_flag)); static int tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f)); -static void ipfw_report __P((char *txt, struct ip *ip)); +static void ipfw_report __P((char *txt, int rule, struct ip *ip)); /* * Returns 1 if the port is matched by the vector, 0 otherwise @@ -183,14 +183,14 @@ ipopts_match(ip, f) } static void -ipfw_report(char *txt, struct ip *ip) +ipfw_report(char *txt, int rule, struct ip *ip) { struct tcphdr *tcp = (struct tcphdr *) ((u_long *) ip + ip->ip_hl); struct udphdr *udp = (struct udphdr *) ((u_long *) ip + ip->ip_hl); struct icmp *icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl); if (!fw_verbose) return; - printf("ipfw: %s ",txt); + printf("ipfw: %d %s ",rule, txt); switch (ip->ip_p) { case IPPROTO_TCP: printf("TCP "); @@ -245,21 +245,14 @@ ip_fw_chk(m, ip, rif, dir) u_short src_port = 0, dst_port = 0; u_short f_prt = 0, prt, len = 0; - /* - * Handle fragmented packets, if the Fragment Offset is big enough - * to not harm essential stuff in the UDP/TCP header, even in the - * precense of IP options, we assume that it's OK. - */ - if ((ip->ip_off & IP_OFFMASK) > 1) - return 1; - /* * ... else if non-zero, highly unusual and interesting, but * we're not going to pass it... */ - if ((ip->ip_off & IP_OFFMASK)) { - ipfw_report("Refuse", ip); - goto bad_packet; + if ((ip->ip_off & IP_OFFMASK) == 1) { + ipfw_report("Refuse", -1, ip); + m_freem(m); + return 0; } src = ip->ip_src; @@ -297,15 +290,7 @@ ip_fw_chk(m, ip, rif, dir) break; } -#if 0 - /* - * If the fields are not valid, don't validate them - */ - if (len < ip->ip_len) { - ipfw_report("Too Short", ip); - /* goto bad_packet; */ - } -#endif + /* XXX Check that we have sufficient header for TCP analysis */ /* * Go down the chain, looking for enlightment @@ -313,6 +298,18 @@ ip_fw_chk(m, ip, rif, dir) for (chain=ip_fw_chain.lh_first; chain; chain = chain->chain.le_next) { f = chain->rule; + /* Check direction inbound */ + if (!dir && !(f->fw_flg & IP_FW_F_IN)) + continue; + + /* Check direction outbound */ + if (dir && !(f->fw_flg & IP_FW_F_OUT)) + continue; + + /* Fragments */ + if ((f->fw_flg & IP_FW_F_FRAG) && !(ip->ip_off & IP_OFFMASK)) + continue; + /* If src-addr doesn't match, not this rule. */ if ((src.s_addr & f->fw_smsk.s_addr) != f->fw_src.s_addr) continue; @@ -382,6 +379,10 @@ ip_fw_chk(m, ip, rif, dir) if (prt == IP_FW_F_ICMP) goto got_match; + /* Fragments can't match past this point */ + if (ip->ip_off & IP_OFFMASK) + continue; + /* TCP, a little more checking */ if (prt == IP_FW_F_TCP && (f->fw_tcpf != f->fw_tcpnf) && @@ -396,26 +397,25 @@ ip_fw_chk(m, ip, rif, dir) dst_port, f->fw_flg & IP_FW_F_DRNG)) continue; - goto got_match; - } - /* Just in case ... */ - goto bad_packet; - got_match: - f->fw_pcnt++; - f->fw_bcnt+=ip->ip_len; - - if (f->fw_flg & IP_FW_F_PRN) { + f->fw_pcnt++; + f->fw_bcnt+=ip->ip_len; + if (f->fw_flg & IP_FW_F_PRN) { + if (f->fw_flg & IP_FW_F_ACCEPT) + ipfw_report("Accept", f->fw_number, ip); + else if (f->fw_flg & IP_FW_F_COUNT) + ipfw_report("Count", f->fw_number, ip); + else + ipfw_report("Deny", f->fw_number, ip); + } if (f->fw_flg & IP_FW_F_ACCEPT) - ipfw_report("Accept", ip); - else - ipfw_report("Deny", ip); + return 1; + if (f->fw_flg & IP_FW_F_COUNT) + continue; + break; + } - if (f->fw_flg & IP_FW_F_ACCEPT) - return 1; - -bad_packet: /* * Don't icmp outgoing packets at all */ @@ -474,10 +474,9 @@ add_entry(chainptr, frwl) } else { nbr=0; for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) - if (ftmp->fw_number > fcp->rule->fw_number) { - LIST_INSERT_AFTER(fcp, fwc, chain); - break; - } else if (fcp->rule->fw_number == (u_short)-1) { + if (fcp->rule->fw_number == (u_short)-1 || + ( ftmp->fw_number && + fcp->rule->fw_number > ftmp->fw_number)) { if (!ftmp->fw_number) ftmp->fw_number = nbr + 100; if (fcpl) { @@ -516,7 +515,7 @@ del_entry(chainptr, frwl) splx(s); free(fcp->rule, M_IPFW); free(fcp, M_IPFW); - return 1; + return 0; } } splx(s); @@ -541,6 +540,11 @@ check_ipfw_struct(m) frwl->fw_flg)); return (NULL); } + + /* If neither In nor Out, then both */ + if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) + frwl->fw_flg |= IP_FW_F_IN | IP_FW_F_OUT; + if ((frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2) { dprintf(("ip_fw_ctl: src range set but n_src_p=%d\n", frwl->fw_nsp)); diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 3a2962fab641..f39688ca281a 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.11.4.2 1996/02/23 15:26:05 phk Exp $ + * $Id: ip_fw.h,v 1.15 1996/02/23 15:47:52 phk Exp $ */ /* @@ -66,21 +66,27 @@ struct ip_fw_chain { #define IP_FW_F_ICMP 0x003 /* This is a ICMP packet rule */ #define IP_FW_F_KIND 0x003 /* Mask to isolate rule kind */ -#define IP_FW_F_ACCEPT 0x004 /* This is an accept rule */ -#define IP_FW_F_PRN 0x008 /* Print if this rule matches */ -#define IP_FW_F_ICMPRPL 0x010 /* Send back icmp unreachable packet */ +#define IP_FW_F_IN 0x004 /* Inbound */ +#define IP_FW_F_OUT 0x008 /* Outboun */ + +#define IP_FW_F_ACCEPT 0x010 /* This is an accept rule */ +#define IP_FW_F_COUNT 0x020 /* This is an accept rule */ +#define IP_FW_F_PRN 0x040 /* Print if this rule matches */ +#define IP_FW_F_ICMPRPL 0x080 /* Send back icmp unreachable packet */ -#define IP_FW_F_SRNG 0x020 /* The first two src ports are a min * +#define IP_FW_F_SRNG 0x100 /* The first two src ports are a min * * and max range (stored in host byte * * order). */ -#define IP_FW_F_DRNG 0x040 /* The first two dst ports are a min * +#define IP_FW_F_DRNG 0x200 /* The first two dst ports are a min * * and max range (stored in host byte * * order). */ -#define IP_FW_F_IFNAME 0x080 /* Use interface name/unit (not IP) */ +#define IP_FW_F_IFNAME 0x400 /* Use interface name/unit (not IP) */ -#define IP_FW_F_MASK 0x0FF /* All possible flag bits mask */ +#define IP_FW_F_FRAG 0x800 /* Fragment */ + +#define IP_FW_F_MASK 0xFFF /* All possible flag bits mask */ /* * Definitions for IP option names. @@ -96,7 +102,7 @@ struct ip_fw_chain { #define IP_FW_TCPF_FIN TH_FIN #define IP_FW_TCPF_SYN TH_SYN #define IP_FW_TCPF_RST TH_RST -#define IP_FW_TCPF_PUSH TH_PUSH +#define IP_FW_TCPF_PSH TH_PUSH #define IP_FW_TCPF_ACK TH_ACK #define IP_FW_TCPF_URG TH_URG diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 6d6b464172e7..15d053a482f0 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * $Id: ip_input.c,v 1.35 1996/02/05 20:36:02 wollman Exp $ + * $Id: ip_input.c,v 1.36 1996/02/23 15:47:53 phk Exp $ */ #include @@ -172,6 +172,9 @@ ip_init() ipq.next = ipq.prev = &ipq; ip_id = time.tv_sec & 0xffff; ipintrq.ifq_maxlen = ipqmaxlen; +#ifdef IPFIREWALL + ip_fw_init(); +#endif } static struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 614ffc5806e6..d928ac7c8437 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 - * $Id: ip_output.c,v 1.28 1996/02/22 21:32:23 peter Exp $ + * $Id: ip_output.c,v 1.29 1996/02/23 15:47:55 phk Exp $ */ #include @@ -340,7 +340,7 @@ ip_output(m0, opt, ro, flags, imo) * Check with the firewall... */ if (!(*ip_fw_chk_ptr)(m,ip,ifp,1)) { - error = 0; + error = EACCES; goto done; }