diff options
| author | Poul-Henning Kamp <phk@FreeBSD.org> | 1996-02-23 15:26:13 +0000 |
|---|---|---|
| committer | Poul-Henning Kamp <phk@FreeBSD.org> | 1996-02-23 15:26:13 +0000 |
| commit | 0440c9042c46527d38b05ca2fc1e96f12c838d79 (patch) | |
| tree | 633355ebdba40aadf1ec6beb5fae4eb9c1d20792 | |
| parent | 4c61726feac9a31202ae9e90211e90cee05c0323 (diff) | |
Notes
| -rw-r--r-- | sys/conf/files | 2 | ||||
| -rw-r--r-- | sys/i386/conf/LINT | 7 | ||||
| -rw-r--r-- | sys/netinet/ip_fw.c | 1075 | ||||
| -rw-r--r-- | sys/netinet/ip_fw.h | 124 | ||||
| -rw-r--r-- | sys/netinet/ip_fwdef.c | 57 | ||||
| -rw-r--r-- | sys/netinet/ip_input.c | 42 | ||||
| -rw-r--r-- | sys/netinet/ip_output.c | 20 | ||||
| -rw-r--r-- | sys/netinet/raw_ip.c | 23 |
8 files changed, 477 insertions, 873 deletions
diff --git a/sys/conf/files b/sys/conf/files index 5654d471231b..020e46e58298 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -198,9 +198,7 @@ netinet/ip_input.c optional inet netinet/ip_mroute.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet -netinet/ip_fwdef.c optional inet netinet/ip_fw.c optional ipfirewall -netinet/ip_fw.c optional ipacct netinet/tcp_debug.c optional tcpdebug netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index c4787ac78372..481ba408b303 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.184.4.10 1996/01/04 08:51:07 gibbs Exp $ +# $Id: LINT,v 1.184.4.11 1996/02/12 14:33:55 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -187,9 +187,6 @@ options HDLC #X.25 link layer for serial lines # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE does # the obvious thing. -# IPFIREWALL_ORDER_RULES makes the ipfw code sort the rules. You -# don't want that, it's only there to be backward compatible. -# IPACCT enables IP accounting. # # ARP_PROXYALL enables global proxy ARP. Beware! This can burn # your house down! See netinet/if_ether.c for the gory details. @@ -200,8 +197,6 @@ options GATEWAY #internetwork gateway options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about -options IPFIREWALL_ORDER_RULES # bogusly sort rules. -options IPACCT #ipaccounting # dropped packets options ARP_PROXYALL # global proxy ARP diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 3d4925b35c25..d7bc0c3d055f 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -11,27 +11,22 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.c,v 1.14.4.2 1995/08/25 01:58:04 davidg Exp $ + * $Id: ip_fw.c,v 1.28 1996/02/03 11:47:51 phk Exp $ */ /* * Implement IP packet firewall */ - #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/mbuf.h> -#include <sys/domain.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <sys/time.h> +#include <sys/queue.h> +#if 0 /* XXX -current, but not -stable */ #include <sys/kernel.h> - +#include <sys/sysctl.h> +#endif #include <net/if.h> -#include <net/route.h> - #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -40,42 +35,46 @@ #include <netinet/ip_icmp.h> #include <netinet/ip_fw.h> -#ifdef IPFIREWALL_DEBUG -#define dprintf1(a) printf(a) -#define dprintf2(a1,a2) printf(a1,a2) -#define dprintf3(a1,a2,a3) printf(a1,a2,a3) -#define dprintf4(a1,a2,a3,a4) printf(a1,a2,a3,a4) +static int fw_debug = 1; +#ifdef IPFIREWALL_VERBOSE +static int fw_verbose = 1; #else -#define dprintf1(a) -#define dprintf2(a1,a2) -#define dprintf3(a1,a2,a3) -#define dprintf4(a1,a2,a3,a4) +static int fw_verbose = 0; #endif -#ifndef TRUE -#define TRUE 1 -#endif +u_short ip_fw_policy = IP_FW_P_DENY; + +LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain; -#ifndef FALSE -#define FALSE 0 +#ifdef SYSCTL_NODE +SYSCTL_NODE(net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall"); +SYSCTL_INT(net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, &fw_debug, 0, ""); +SYSCTL_INT(net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw_verbose, 0, ""); #endif +#define dprintf(a) if (!fw_debug); else printf a + #define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\ (ntohl(a.s_addr)>>16)&0xFF,\ (ntohl(a.s_addr)>>8)&0xFF,\ (ntohl(a.s_addr))&0xFF); -#ifdef IPFIREWALL_DEBUG -#define dprint_ip(a) print_ip(a) -#else -#define dprint_ip(a) -#endif +#define dprint_ip(a) if (!fw_debug); else print_ip(a) +static int add_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl)); +static int del_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl)); +static struct ip_fw * + check_ipfw_struct __P(( struct mbuf *m)); +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)); /* - * Returns TRUE if the port is matched by the vector, FALSE otherwise + * Returns 1 if the port is matched by the vector, 0 otherwise */ -inline int +static inline int port_match(portptr, nports, port, range_flag) u_short *portptr; int nports; @@ -83,59 +82,185 @@ port_match(portptr, nports, port, range_flag) int range_flag; { if (!nports) - return TRUE; + return 1; if (range_flag) { if (portptr[0] <= port && port <= portptr[1]) { - return TRUE; + return 1; } nports -= 2; portptr += 2; } while (nports-- > 0) { if (*portptr++ == port) { - return TRUE; + return 1; + } + } + return 0; +} + +static int +tcpflg_match(tcp, f) + struct tcphdr *tcp; + struct ip_fw *f; +{ + u_char flg_set, flg_clr; + + flg_set = tcp->th_flags & f->fw_tcpf; + flg_clr = tcp->th_flags & f->fw_tcpnf; + + if (flg_set != f->fw_tcpf) + return 0; + if (flg_clr) + return 0; + + return 1; +} + + +static int +ipopts_match(ip, f) + struct ip *ip; + struct ip_fw *f; +{ + register u_char *cp; + int opt, optlen, cnt; + u_char opts, nopts, nopts_sve; + + cp = (u_char *)(ip + 1); + cnt = (ip->ip_hl << 2) - sizeof (struct ip); + opts = f->fw_ipopt; + nopts = nopts_sve = f->fw_ipnopt; + + for (; cnt > 0; cnt -= optlen, cp += optlen) { + opt = cp[IPOPT_OPTVAL]; + if (opt == IPOPT_EOL) + break; + if (opt == IPOPT_NOP) + optlen = 1; + else { + optlen = cp[IPOPT_OLEN]; + if (optlen <= 0 || optlen > cnt) { + goto bad; + } + } + switch (opt) { + + default: + break; + + case IPOPT_LSRR: + opts &= ~IP_FW_IPOPT_LSRR; + nopts &= ~IP_FW_IPOPT_LSRR; + break; + + case IPOPT_SSRR: + opts &= ~IP_FW_IPOPT_SSRR; + nopts &= ~IP_FW_IPOPT_SSRR; + break; + + case IPOPT_RR: + opts &= ~IP_FW_IPOPT_RR; + nopts &= ~IP_FW_IPOPT_RR; + break; + case IPOPT_TS: + opts &= ~IP_FW_IPOPT_TS; + nopts &= ~IP_FW_IPOPT_TS; + break; } + if (opts == nopts) + break; } - return FALSE; + if (opts == 0 && nopts == nopts_sve) + return 1; + else + return 0; +bad: + if (ip_fw_policy & IP_FW_P_MBIPO) + return 1; + else + return 0; + } +static void +ipfw_report(char *txt, 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); + switch (ip->ip_p) { + case IPPROTO_TCP: + printf("TCP "); + print_ip(ip->ip_src); + printf(":%d ", ntohs(tcp->th_sport)); + print_ip(ip->ip_dst); + printf(":%d", ntohs(tcp->th_dport)); + break; + case IPPROTO_UDP: + printf("UDP "); + print_ip(ip->ip_src); + printf(":%d ", ntohs(udp->uh_sport)); + print_ip(ip->ip_dst); + printf(":%d", ntohs(udp->uh_dport)); + break; + case IPPROTO_ICMP: + printf("ICMP:%u ", icmp->icmp_type); + print_ip(ip->ip_src); + printf(" "); + print_ip(ip->ip_dst); + break; + default: + printf("P:%d ", ip->ip_p); + print_ip(ip->ip_src); + printf(" "); + print_ip(ip->ip_dst); + break; + } + if ((ip->ip_off & IP_OFFMASK)) + printf(" Fragment = %d",ip->ip_off & IP_OFFMASK); + printf("\n"); +} /* - * Returns TRUE if it should be accepted, FALSE otherwise. + * Returns 1 if it should be accepted, 0 otherwise. */ -#ifdef IPFIREWALL int -ip_fw_chk(m, ip, rif, chain) +ip_fw_chk(m, ip, rif, dir) struct mbuf *m; struct ip *ip; struct ifnet *rif; - struct ip_fw *chain; + int dir; { - register struct ip_fw *f; + struct ip_fw_chain *chain; + register struct ip_fw *f = NULL; 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); 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; - char notcpsyn = 1; + u_short f_prt = 0, prt, len = 0; /* - * If the chain is empty allow any packet-this is equal to disabling - * firewall. + * 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 (chain == NULL) - return TRUE; + if ((ip->ip_off & IP_OFFMASK) > 1) + return 1; /* - * This way we handle fragmented packets. we ignore all fragments but - * the first one so the whole packet can't be reassembled. This way we - * relay on the full info which stored only in first packet. + * ... else if non-zero, highly unusual and interesting, but + * we're not going to pass it... */ - if (ip->ip_off & IP_OFFMASK) - return TRUE; + if ((ip->ip_off & IP_OFFMASK)) { + ipfw_report("Refuse", ip); + goto bad_packet; + } src = ip->ip_src; dst = ip->ip_dst; @@ -147,787 +272,349 @@ ip_fw_chk(m, ip, rif, chain) if (rif != NULL) ia = rif->if_addrlist; - dprintf1("Packet "); + /* + * Determine the protocol and extract some useful stuff + */ switch (ip->ip_p) { case IPPROTO_TCP: - dprintf1("TCP "); src_port = ntohs(tcp->th_sport); dst_port = ntohs(tcp->th_dport); - if ((tcp->th_flags & TH_SYN) && !(tcp->th_flags & TH_ACK)) - notcpsyn = 0; /* We *DO* have SYN ,value FALSE */ prt = IP_FW_F_TCP; + len = sizeof (*tcp); break; case IPPROTO_UDP: - dprintf1("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: - dprintf2("ICMP:%u ", icmp->icmp_type); prt = IP_FW_F_ICMP; + len = sizeof (*icmp); break; default: - dprintf2("p=%d ", ip->ip_p); prt = IP_FW_F_ALL; break; } - dprint_ip(ip->ip_src); - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { - dprintf2(":%d ", src_port); - } - dprint_ip(ip->ip_dst); - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { - dprintf2(":%d ", dst_port); - } - dprintf1("\n"); - - - for (f = chain; f != NULL; f = f->fw_next) - if ((src.s_addr & f->fw_smsk.s_addr) == f->fw_src.s_addr && - (dst.s_addr & f->fw_dmsk.s_addr) == f->fw_dst.s_addr) { - if (rif == NULL) - goto via_match; - - if (f->fw_flg & IP_FW_F_IFNAME) { - /* - * No name/unit set so - * match any. - */ - if (!f->fw_via_name[0]) - goto via_match; - - if (rif->if_unit == f->fw_via_unit && - !strncmp(rif->if_name, f->fw_via_name, FW_IFNLEN)) - goto via_match; - } else { - /* - * No via ip set so match - * any. - */ - if (!f->fw_via_ip.s_addr) - goto via_match; - - for (ia_p = ia; ia_p != NULL; ia_p = ia_p->ifa_next) { - if ((ia_p->ifa_addr == NULL) || - (ia_p->ifa_addr->sa_family != AF_INET)) - continue; - ia_i.s_addr = - ((struct sockaddr_in *)(ia_p->ifa_addr))->sin_addr.s_addr; - if (ia_i.s_addr == f->fw_via_ip.s_addr) - goto via_match; - } - } - /* - * If we got here,no "via"'s matched,so we should - * continue to the next firewall entry. - */ - continue; - via_match: - f_prt = f->fw_flg & IP_FW_F_KIND; - if (f_prt == IP_FW_F_ALL) { - /* Universal frwl - we've got a match! */ - goto got_match; - } else { - /* - * This is actually buggy as if you set SYN - * flag on UDp or ICMP firewall it will never - * work,but actually it is a concern of - * software which sets firewall entries. - */ - if (f->fw_flg & IP_FW_F_TCPSYN && notcpsyn) - continue; - - /* - * Specific firewall - packet's protocol must - * match firewall's - */ - if (prt == f_prt) { - if (prt == IP_FW_F_ICMP || - (port_match(&f->fw_pts[0], f->fw_nsp, src_port, - f->fw_flg & IP_FW_F_SRNG) && - port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port, - f->fw_flg & IP_FW_F_DRNG))) { - goto got_match; - } /* Ports match */ - } /* Proto matches */ - } /* ALL/Specific */ - } /* IP addr/mask matches */ +#if 0 /* - * If we get here then none of the firewalls matched. So now we relay - * on policy defined by user-unmatched packet can be ever accepted or - * rejected... + * If the fields are not valid, don't validate them */ - if (ip_fw_policy & IP_FW_P_DENY) { - f = (struct ip_fw *) NULL; - goto bad_packet; + if (len < ip->ip_len) { + ipfw_report("Too Short", ip); + /* goto bad_packet; */ } - return TRUE; +#endif -got_match: -#ifdef IPFIREWALL_VERBOSE /* - * VERY ugly piece of code which actually makes kernel printf for - * denied packets... + * Go down the chain, looking for enlightment */ - if (f->fw_flg & IP_FW_F_PRN) { - if (f->fw_flg & IP_FW_F_ACCEPT) - printf("Accept "); - else - printf("Deny "); - switch (ip->ip_p) { - case IPPROTO_TCP: - printf("TCP "); - break; - case IPPROTO_UDP: - printf("UDP "); - break; - case IPPROTO_ICMP: - printf("ICMP:%u ", icmp->icmp_type); - 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", src_port); - printf(" "); - print_ip(ip->ip_dst); - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) - printf(":%d", dst_port); - printf("\n"); - } -#endif - if (f->fw_flg & IP_FW_F_ACCEPT) - return TRUE; + for (chain=ip_fw_chain.lh_first; chain; chain = chain->chain.le_next) { + f = chain->rule; -bad_packet: - if (f != NULL) { - /* - * Do not ICMP reply to icmp packets....:) or to packets - * rejected by entry without the special ICMP reply flag. - */ - if ((f_prt == IP_FW_F_ICMP) || - !(f->fw_flg & IP_FW_F_ICMPRPL)) { - m_freem(m); - return FALSE; - } - 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); - return FALSE; - } - m_freem(m); - return FALSE; -} -#endif /* IPFIREWALL */ - -#ifdef IPACCT -void -ip_acct_cnt(ip, rif, chain, nh_conv) - struct ip *ip; - struct ifnet *rif; - struct ip_fw *chain; - int nh_conv; -{ - register struct ip_fw *f; - struct tcphdr *tcp = (struct tcphdr *) ((u_long *) ip + ip->ip_hl); - struct udphdr *udp = (struct udphdr *) ((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, prt = 0; - char rev = 0; - - if (chain == NULL) - return; + /* If src-addr doesn't match, not this rule. */ + if ((src.s_addr & f->fw_smsk.s_addr) != f->fw_src.s_addr) + continue; - if (ip->ip_off & IP_OFFMASK) - return; + /* If dest-addr doesn't match, not this rule. */ + if ((dst.s_addr & f->fw_dmsk.s_addr) != f->fw_dst.s_addr) + continue; - src = ip->ip_src; - dst = ip->ip_dst; + /* If a i/f name was specified, and we don't know */ + if ((f->fw_flg & IP_FW_F_IFNAME) && !rif) + continue; - if (rif != NULL) - ia = rif->if_addrlist; + /* If a i/f name was specified, check it */ + if ((f->fw_flg & IP_FW_F_IFNAME) && f->fw_via_name[0]) { - switch (ip->ip_p) { - case IPPROTO_TCP: - src_port = ntohs(tcp->th_sport); - dst_port = ntohs(tcp->th_dport); - prt = IP_FW_F_TCP; - break; - case IPPROTO_UDP: - src_port = ntohs(udp->uh_sport); - dst_port = ntohs(udp->uh_dport); - prt = IP_FW_F_UDP; - break; - case IPPROTO_ICMP: - prt = IP_FW_F_ICMP; - break; - default: - prt = IP_FW_F_ALL; - break; - } + /* Not same unit, don't match */ + if (rif->if_unit != f->fw_via_unit) + continue; - for (f = chain; f != NULL; f = f->fw_next) { - if ((src.s_addr & f->fw_smsk.s_addr) == f->fw_src.s_addr - && (dst.s_addr & f->fw_dmsk.s_addr) == f->fw_dst.s_addr) { - rev = 0; - goto addr_match; - } - if ((f->fw_flg & IP_FW_F_BIDIR) && - ((src.s_addr & f->fw_smsk.s_addr) == f->fw_dst.s_addr - && (dst.s_addr & f->fw_dmsk.s_addr) == f->fw_src.s_addr)) { - rev = 1; - goto addr_match; + /* Not same name */ + if (strncmp(rif->if_name, f->fw_via_name, FW_IFNLEN)) + continue; } - continue; -addr_match: - /* - * We use here same code for "via" matching as in - * firewall.This is wrong and does not do much use,because in - * most cases instead of interface passed NULL pointer.Need to - * be completely rewritten. - */ - if (rif == NULL) - goto via_match; - - if (f->fw_flg & IP_FW_F_IFNAME) { - if (!f->fw_via_name[0]) - goto via_match; /* No name/unit set,match any */ - - if (rif->if_unit == f->fw_via_unit && - !strncmp(rif->if_name, f->fw_via_name, FW_IFNLEN)) - goto via_match; - } else { - - /* - * No via ip set so - * match any? - */ - if (!f->fw_via_ip.s_addr) - goto via_match; + /* If a i/f addr was specified, check it */ + if ((f->fw_flg & IP_FW_F_IFNAME) && f->fw_via_ip.s_addr) { for (ia_p = ia; ia_p != NULL; ia_p = ia_p->ifa_next) { - if (!ia_p->ifa_addr || ia_p->ifa_addr->sa_family != AF_INET) + if ((ia_p->ifa_addr == NULL)) + continue; + if (ia_p->ifa_addr->sa_family != AF_INET) continue; - ia_i.s_addr = - ((struct sockaddr_in *) (ia_p->ifa_addr))->sin_addr.s_addr; - if (ia_i.s_addr == f->fw_via_ip.s_addr) - goto via_match; + ((struct sockaddr_in *) + (ia_p->ifa_addr))->sin_addr.s_addr; + if (ia_i.s_addr != f->fw_via_ip.s_addr) + continue; } - } + + /* + * Check IP options + */ + if (f->fw_ipopt != f->fw_ipnopt) + if (!ipopts_match(ip, f)) + continue; + /* - * If we got here,no "via"'s matched,so we should continue to - * the next firewall entry. + * Check protocol */ - continue; -via_match: f_prt = f->fw_flg & IP_FW_F_KIND; - if (f_prt == IP_FW_F_ALL) { - /* Universal frwl - we've got a match! */ + + /* If wildcard, match */ + if (f_prt == IP_FW_F_ALL) + goto got_match; - f->fw_pcnt++; /* Rise packet count */ + /* If different, dont match */ + if (prt != f_prt) + continue; - /* - * Rise byte count, if need to convert from host to - * network byte order,do it. - */ - if (nh_conv) - f->fw_bcnt += ntohs(ip->ip_len); - else - f->fw_bcnt += ip->ip_len; - } else { - /* - * Specific firewall - packet's protocol must match - * firewall's - */ - if (prt == f_prt) { - - if ((prt == IP_FW_F_ICMP || - (port_match(&f->fw_pts[0], f->fw_nsp, src_port, - f->fw_flg & IP_FW_F_SRNG) && - port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port, - f->fw_flg & IP_FW_F_DRNG))) || - ((rev) && (port_match(&f->fw_pts[0], f->fw_nsp, dst_port, - f->fw_flg & IP_FW_F_SRNG) && - port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port, - f->fw_flg & IP_FW_F_DRNG)))) { - f->fw_pcnt++; /* Rise packet count */ - /* - * Rise byte count, if need to convert - * from host to network byte order,do - * it. - */ - if (nh_conv) - f->fw_bcnt += ntohs(ip->ip_len); - else - f->fw_bcnt += ip->ip_len; - } /* Ports match */ - } /* Proto matches */ - } /* ALL/Specific */ - } /* IP addr/mask matches */ -} -#endif /* IPACCT */ + /* ICMP, done */ + if (prt == IP_FW_F_ICMP) + goto got_match; -static void -zero_fw_chain(chainptr) - struct ip_fw *chainptr; -{ - struct ip_fw *ctmp = chainptr; + /* TCP, a little more checking */ + if (prt == IP_FW_F_TCP && + (f->fw_tcpf != f->fw_tcpnf) && + (!tcpflg_match(tcp, f))) + continue; + + if (!port_match(&f->fw_pts[0], f->fw_nsp, + src_port, f->fw_flg & IP_FW_F_SRNG)) + continue; - while (ctmp != NULL) { - ctmp->fw_pcnt = 0l; - ctmp->fw_bcnt = 0l; - ctmp = ctmp->fw_next; + if (!port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, + dst_port, f->fw_flg & IP_FW_F_DRNG)) + continue; + + goto got_match; } -} + /* Just in case ... */ + goto bad_packet; -static void -free_fw_chain(chainptr) - struct ip_fw **chainptr; -{ - int s; +got_match: + f->fw_pcnt++; + f->fw_bcnt+=ip->ip_len; - s = splnet(); - while (*chainptr != NULL) { - struct ip_fw *ftmp; + if (f->fw_flg & IP_FW_F_PRN) { + if (f->fw_flg & IP_FW_F_ACCEPT) + ipfw_report("Accept", ip); + else + ipfw_report("Deny", ip); + } + + if (f->fw_flg & IP_FW_F_ACCEPT) + return 1; - ftmp = *chainptr; - *chainptr = ftmp->fw_next; - free(ftmp, M_IPFW); +bad_packet: + /* + * Don't icmp outgoing packets at all + */ + if (f != NULL && !dir) { + /* + * Do not ICMP reply to icmp packets....:) or to packets + * rejected by entry without the special ICMP reply flag. + */ + if ((f_prt != IP_FW_F_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); + return 0; + } } - splx(s); + m_freem(m); + return 0; } static int add_entry(chainptr, frwl) - struct ip_fw **chainptr; + struct ip_fw_head *chainptr; struct ip_fw *frwl; { - struct ip_fw *ftmp; - struct ip_fw *chtmp = NULL; - struct ip_fw *chtmp_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 n_sr, n_dr, o_sr, o_dr; - u_short oldkind, newkind; - int addb4 = 0; - int n_o, n_n; + struct ip_fw *ftmp = 0; + struct ip_fw_chain *fwc = 0, *fcp, *fcpl = 0; + u_short nbr = 0; int s; s = splnet(); - ftmp = malloc(sizeof(struct ip_fw), M_IPFW, M_DONTWAIT); - if (ftmp == NULL) { - dprintf1("ip_fw_ctl: malloc said no\n"); + fwc = malloc(sizeof *fwc, M_IPFW, M_DONTWAIT); + ftmp = malloc(sizeof *ftmp, M_IPFW, M_DONTWAIT); + if (!fwc || !ftmp) { + dprintf(("ip_fw_ctl: malloc said no\n")); + if (fwc) free(fwc, M_IPFW); + if (ftmp) free(ftmp, M_IPFW); splx(s); return (ENOSPC); } bcopy(frwl, ftmp, sizeof(struct ip_fw)); ftmp->fw_pcnt = 0L; ftmp->fw_bcnt = 0L; - - ftmp->fw_next = NULL; - - if (*chainptr == NULL) { - *chainptr = ftmp; - } else { - chtmp_prev = NULL; - for (chtmp = *chainptr; chtmp != NULL; chtmp = chtmp->fw_next) { -#ifdef IPFIREWALL_ORDER_RULES - addb4 = 0; - - newkind = ftmp->fw_flg & IP_FW_F_KIND; - oldkind = chtmp->fw_flg & IP_FW_F_KIND; - - if (newkind != IP_FW_F_ALL && - oldkind != IP_FW_F_ALL && - oldkind != newkind) { - chtmp_prev = chtmp; - continue; - } - /* - * Very very *UGLY* code... Sorry,but i had to do - * this.... - */ - n_sa = ntohl(ftmp->fw_src.s_addr); - n_da = ntohl(ftmp->fw_dst.s_addr); - n_sm = ntohl(ftmp->fw_smsk.s_addr); - n_dm = ntohl(ftmp->fw_dmsk.s_addr); - - o_sa = ntohl(chtmp->fw_src.s_addr); - o_da = ntohl(chtmp->fw_dst.s_addr); - o_sm = ntohl(chtmp->fw_smsk.s_addr); - o_dm = ntohl(chtmp->fw_dmsk.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_FW_F_ALL && - oldkind == IP_FW_F_ALL) - addb4++; - if (newkind == oldkind && (oldkind == IP_FW_F_TCP || - oldkind == IP_FW_F_UDP)) { - /* - * Here the main idea is to check the - * size of port range which the frwl - * covers We actually don't check - * their values but just the wideness - * of range they have so that less - * wide ranges or single ports go - * first and wide ranges go later. No - * ports at all treated as a range of - * maximum number of ports. - */ - - if (ftmp->fw_flg & IP_FW_F_SRNG) - n_sr = ftmp->fw_pts[1] - ftmp->fw_pts[0]; - else - n_sr = (ftmp->fw_nsp) ? - ftmp->fw_nsp : USHRT_MAX; - - if (chtmp->fw_flg & IP_FW_F_SRNG) - o_sr = chtmp->fw_pts[1] - chtmp->fw_pts[0]; - else - o_sr = (chtmp->fw_nsp) ? - chtmp->fw_nsp : USHRT_MAX; - - if (n_sr < o_sr) - addb4++; - if (n_sr > o_sr) - addb4--; - - n_n = ftmp->fw_nsp; - n_o = chtmp->fw_nsp; - /* - * Actually this cannot happen as the - * frwl control procedure checks for - * number of ports in source and - * destination range but we will try - * to be more safe. - */ - if ((n_n > (IP_FW_MAX_PORTS - 2)) || - (n_o > (IP_FW_MAX_PORTS - 2))) - goto skip_check; - - if (ftmp->fw_flg & IP_FW_F_DRNG) - n_dr = ftmp->fw_pts[n_n + 1] - ftmp->fw_pts[n_n]; - else - n_dr = (ftmp->fw_ndp) ? - ftmp->fw_ndp : USHRT_MAX; - - if (chtmp->fw_flg & IP_FW_F_DRNG) - o_dr = chtmp->fw_pts[n_o + 1] - chtmp->fw_pts[n_o]; - else - o_dr = (chtmp->fw_ndp) ? - chtmp->fw_ndp : USHRT_MAX; - if (n_dr < o_dr) - addb4++; - if (n_dr > o_dr) - addb4--; - - skip_check: - } - } - if (addb4 > 0) { - if (chtmp_prev != NULL) { - chtmp_prev->fw_next = ftmp; - ftmp->fw_next = chtmp; + fwc->rule = ftmp; + + if (!chainptr->lh_first) { + LIST_INSERT_HEAD(chainptr, fwc, chain); + } else if (ftmp->fw_number == (u_short)-1) { + if (fwc) free(fwc, M_IPFW); + if (ftmp) free(ftmp, M_IPFW); + splx(s); + return (EINVAL); + } 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 (!ftmp->fw_number) + ftmp->fw_number = nbr + 100; + if (fcpl) { + LIST_INSERT_AFTER(fcpl, fwc, chain); } else { - *chainptr = ftmp; - ftmp->fw_next = chtmp; + LIST_INSERT_HEAD(chainptr, fwc, chain); } - splx(s); - return 0; + break; + } else { + nbr=fcp->rule->fw_number; + fcpl = fcp; } -#endif /* IPFIREWALL_ORDER_RULES */ - chtmp_prev = chtmp; - } - if (chtmp_prev != NULL) - chtmp_prev->fw_next = ftmp; - else -#ifdef DIAGNOSTIC - panic("Can't happen"); -#else - *chainptr = ftmp; -#endif } + splx(s); return (0); } static int del_entry(chainptr, frwl) - struct ip_fw **chainptr; + struct ip_fw_head *chainptr; struct ip_fw *frwl; { - struct ip_fw *ftmp, *ltmp; - u_short tport1, tport2, tmpnum; - char matches, was_found; + struct ip_fw_chain *fcp; int s; s = splnet(); - ftmp = *chainptr; - - if (ftmp == NULL) { - dprintf1("ip_fw_ctl: chain is empty\n"); - splx(s); + fcp = chainptr->lh_first; + if (fcp->rule->fw_number == (u_short)-1) return (EINVAL); - } - ltmp = NULL; - was_found = 0; - - while (ftmp != NULL) { - matches = 1; - if (ftmp->fw_src.s_addr != frwl->fw_src.s_addr || - ftmp->fw_dst.s_addr != frwl->fw_dst.s_addr || - ftmp->fw_smsk.s_addr != frwl->fw_smsk.s_addr || - ftmp->fw_dmsk.s_addr != frwl->fw_dmsk.s_addr || - ftmp->fw_via_ip.s_addr != frwl->fw_via_ip.s_addr || - ftmp->fw_flg != frwl->fw_flg) - matches = 0; - tport1 = ftmp->fw_nsp + ftmp->fw_ndp; - tport2 = frwl->fw_nsp + frwl->fw_ndp; - if (tport1 != tport2) - matches = 0; - else if (tport1 != 0) { - for (tmpnum = 0; tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS; tmpnum++) - if (ftmp->fw_pts[tmpnum] != frwl->fw_pts[tmpnum]) - matches = 0; - } - if (matches) { - was_found = 1; - if (ltmp != NULL) { - ltmp->fw_next = ftmp->fw_next; - free(ftmp, M_IPFW); - ftmp = ltmp->fw_next; - } else { - *chainptr = ftmp->fw_next; - free(ftmp, M_IPFW); - ftmp = *chainptr; - } - } else { - ltmp = ftmp; - ftmp = ftmp->fw_next; + for (; fcp; fcp = fcp->chain.le_next) { + if (fcp->rule->fw_number == frwl->fw_number) { + LIST_REMOVE(fcp, chain); + splx(s); + free(fcp->rule, M_IPFW); + free(fcp, M_IPFW); + return 1; } } splx(s); - - if (was_found) - return 0; - else - return (EINVAL); -} - -static int -clr_entry(chainptr, frwl) - struct ip_fw **chainptr; - struct ip_fw *frwl; -{ - struct ip_fw *ftmp, *ltmp; - u_short tport1, tport2, tmpnum; - char matches, was_found; - - ftmp = *chainptr; - - if (ftmp == NULL) { - dprintf1("ip_fw_ctl: chain is empty\n"); - return (EINVAL); - } - was_found = 0; - - while (ftmp != NULL) { - matches = 1; - if (ftmp->fw_src.s_addr != frwl->fw_src.s_addr || - ftmp->fw_dst.s_addr != frwl->fw_dst.s_addr || - ftmp->fw_smsk.s_addr != frwl->fw_smsk.s_addr || - ftmp->fw_dmsk.s_addr != frwl->fw_dmsk.s_addr || - ftmp->fw_via_ip.s_addr != frwl->fw_via_ip.s_addr || - ftmp->fw_flg != frwl->fw_flg) - matches = 0; - tport1 = ftmp->fw_nsp + ftmp->fw_ndp; - tport2 = frwl->fw_nsp + frwl->fw_ndp; - if (tport1 != tport2) - matches = 0; - else if (tport1 != 0) { - for (tmpnum = 0; tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS; tmpnum++) - if (ftmp->fw_pts[tmpnum] != frwl->fw_pts[tmpnum]) - matches = 0; - } - if (matches) { - was_found = 1; - ftmp->fw_pcnt = 0L; - ftmp->fw_bcnt = 0L; - } - ftmp = ftmp->fw_next; - } - if (was_found) - return 0; - else - return (EINVAL); + return (EINVAL); } -struct ip_fw * +static struct ip_fw * check_ipfw_struct(m) struct mbuf *m; { struct ip_fw *frwl; if (m->m_len != sizeof(struct ip_fw)) { - dprintf3("ip_fw_ctl: len=%d, want %d\n", m->m_len, - sizeof(struct ip_fw)); + dprintf(("ip_fw_ctl: len=%d, want %d\n", m->m_len, + sizeof(struct ip_fw))); return (NULL); } frwl = mtod(m, struct ip_fw *); if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) { - dprintf2("ip_fw_ctl: undefined flag bits set (flags=%x)\n", - frwl->fw_flg); + dprintf(("ip_fw_ctl: undefined flag bits set (flags=%x)\n", + frwl->fw_flg)); return (NULL); } if ((frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2) { - dprintf2("ip_fw_ctl: src range set but n_src_p=%d\n", - frwl->fw_nsp); + dprintf(("ip_fw_ctl: src range set but n_src_p=%d\n", + frwl->fw_nsp)); return (NULL); } if ((frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2) { - dprintf2("ip_fw_ctl: dst range set but n_dst_p=%d\n", - frwl->fw_ndp); + dprintf(("ip_fw_ctl: dst range set but n_dst_p=%d\n", + frwl->fw_ndp)); return (NULL); } if (frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS) { - dprintf3("ip_fw_ctl: too many ports (%d+%d)\n", - frwl->fw_nsp, frwl->fw_ndp); + dprintf(("ip_fw_ctl: too many ports (%d+%d)\n", + frwl->fw_nsp, frwl->fw_ndp)); return (NULL); } #if 0 if ((frwl->fw_flg & IP_FW_F_KIND) == IP_FW_F_ICMP) { - dprintf1("ip_fw_ctl: request for unsupported ICMP frwling\n"); + dprintf(("ip_fw_ctl: request for unsupported ICMP frwling\n")); return (NULL); } #endif return frwl; } -#ifdef IPACCT -int -ip_acct_ctl(stage, m) - int stage; - struct mbuf *m; -{ - if (stage == IP_ACCT_FLUSH) { - free_fw_chain(&ip_acct_chain); - return (0); - } - if (stage == IP_ACCT_ZERO) { - zero_fw_chain(ip_acct_chain); - return (0); - } - if (stage == IP_ACCT_ADD || - stage == IP_ACCT_DEL || - stage == IP_ACCT_CLR) { - - struct ip_fw *frwl; - - if ((frwl = check_ipfw_struct(m)) == NULL) - return (EINVAL); - - switch (stage) { - case IP_ACCT_ADD: - return (add_entry(&ip_acct_chain, frwl)); - case IP_ACCT_DEL: - return (del_entry(&ip_acct_chain, frwl)); - case IP_ACCT_CLR: - return (clr_entry(&ip_acct_chain, frwl)); - default: -#ifdef DIAGNOSTIC - panic("Can't happen"); -#else - dprintf2("ip_acct_ctl: unknown request %d\n", stage); - return (EINVAL); -#endif - } - } - dprintf2("ip_acct_ctl: unknown request %d\n", stage); - return (EINVAL); -} -#endif - -#ifdef IPFIREWALL int ip_fw_ctl(stage, m) int stage; struct mbuf *m; { if (stage == IP_FW_FLUSH) { - free_fw_chain(&ip_fw_chain); + while (ip_fw_chain.lh_first != NULL && + ip_fw_chain.lh_first->rule->fw_number != (u_short)-1) { + struct ip_fw_chain *fcp = ip_fw_chain.lh_first; + LIST_REMOVE(ip_fw_chain.lh_first, chain); + free(fcp->rule, M_IPFW); + free(fcp, M_IPFW); + } + return (0); + } + if (stage == IP_FW_ZERO) { + struct ip_fw_chain *fcp; + for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next) + fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0; return (0); } if (m == NULL) { printf("ip_fw_ctl: NULL mbuf ptr\n"); return (EINVAL); } - if (stage == IP_FW_POLICY) { - u_short *tmp_policy_ptr; - - tmp_policy_ptr = mtod(m, u_short *); - if ((*tmp_policy_ptr) & ~IP_FW_P_MASK) - return (EINVAL); - ip_fw_policy = *tmp_policy_ptr; - return 0; - } - /* - * Here we really working hard-adding new elements - * to firewall chain or deleting'em - */ - if (stage == IP_FW_ADD || - stage == IP_FW_DEL) { + if (stage == IP_FW_ADD || stage == IP_FW_DEL) { + struct ip_fw *frwl = check_ipfw_struct(m); - struct ip_fw *frwl; - - if ((frwl = check_ipfw_struct(m)) == NULL) + if (!frwl) return (EINVAL); - switch (stage) { - case IP_FW_ADD: + if (stage == IP_FW_ADD) return (add_entry(&ip_fw_chain, frwl)); - case IP_FW_DEL: + else return (del_entry(&ip_fw_chain, frwl)); - default: -#ifdef DIAGNOSTIC - panic("Can't happen"); -#else - dprintf2("ip_fw_ctl: unknown request %d\n", stage); - return (EINVAL); -#endif - } } - dprintf2("ip_fw_ctl: unknown request %d\n", stage); + dprintf(("ip_fw_ctl: unknown request %d\n", stage)); return (EINVAL); } -#endif /* IPFIREWALL */ + +void +ip_fw_init(void) +{ + struct ip_fw deny; + + ip_fw_chk_ptr=&ip_fw_chk; + ip_fw_ctl_ptr=&ip_fw_ctl; + LIST_INIT(&ip_fw_chain); + + bzero(&deny, sizeof deny); + deny.fw_flg = IP_FW_F_ALL; + deny.fw_number = (u_short)-1; + + add_entry(&ip_fw_chain, &deny); + + printf("IP firewall initialized\n"); +} diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index f488181713bc..c528e69bbfa3 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.13 1995/07/23 05:36:30 davidg Exp $ + * $Id: ip_fw.h,v 1.14 1995/10/01 21:52:50 ugen Exp $ */ /* @@ -25,14 +25,9 @@ #define _IP_FW_H struct ip_fw { - struct ip_fw *fw_next; /* Next firewall on chain */ + u_long fw_pcnt,fw_bcnt; /* Packet and byte counters */ struct in_addr fw_src, fw_dst; /* Source and destination IP addr */ struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */ - /* - * This union keeps all "via" information. - * If ever fu_via_ip is 0,or IP_FW_F_IFNAME set and - * fu_via_name[0] is 0 - match any packet. - */ union { struct in_addr fu_via_ip; struct { @@ -41,6 +36,10 @@ struct ip_fw { short fu_via_unit; } fu_via_if; } fu_via_un; +#define fw_via_ip fu_via_un.fu_via_ip +#define fw_via_name fu_via_un.fu_via_if.fu_via_name +#define fw_via_unit fu_via_un.fu_via_if.fu_via_unit + u_short fw_number; u_short fw_flg; /* Flags word */ u_short fw_nsp, fw_ndp; /* N'of src ports and # of dst ports */ /* in ports array (dst ports follow */ @@ -48,68 +47,76 @@ struct ip_fw { /* count of 0 means match all ports) */ #define IP_FW_MAX_PORTS 10 /* A reasonable maximum */ u_short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */ - u_long fw_pcnt,fw_bcnt; /* Packet and byte counters */ + u_char fw_ipopt,fw_ipnopt; /* IP options set/unset */ + u_char fw_tcpf,fw_tcpnf; /* TCP flags sen/unset */ }; - -/* - * Definitions to make expressions - * for "via" stuff shorter. - */ -#define fw_via_ip fu_via_un.fu_via_ip -#define fw_via_name fu_via_un.fu_via_if.fu_via_name -#define fw_via_unit fu_via_un.fu_via_if.fu_via_unit +struct ip_fw_chain { + LIST_ENTRY(ip_fw_chain) chain; + struct ip_fw *rule; +}; /* * Values for "flags" field . */ -#define IP_FW_F_ALL 0x000 /* This is a universal packet firewall*/ -#define IP_FW_F_TCP 0x001 /* This is a TCP packet firewall */ -#define IP_FW_F_UDP 0x002 /* This is a UDP packet firewall */ -#define IP_FW_F_ICMP 0x003 /* This is a ICMP packet firewall */ -#define IP_FW_F_KIND 0x003 /* Mask to isolate firewall kind */ -#define IP_FW_F_ACCEPT 0x004 /* This is an accept firewall (as * - * opposed to a deny firewall)* - * */ -#define IP_FW_F_SRNG 0x008 /* The first two src ports are a min * +#define IP_FW_F_ALL 0x000 /* This is a universal packet rule */ +#define IP_FW_F_TCP 0x001 /* This is a TCP packet rule */ +#define IP_FW_F_UDP 0x002 /* This is a UDP packet rule */ +#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_SRNG 0x020 /* The first two src ports are a min * * and max range (stored in host byte * - * order). * - * */ -#define IP_FW_F_DRNG 0x010 /* The first two dst ports are a min * + * order). */ + +#define IP_FW_F_DRNG 0x040 /* The first two dst ports are a min * * and max range (stored in host byte * - * order). * - * (ports[0] <= port <= ports[1]) * - * */ -#define IP_FW_F_PRN 0x020 /* In verbose mode print this firewall*/ -#define IP_FW_F_BIDIR 0x040 /* For accounting-count two way */ -#define IP_FW_F_TCPSYN 0x080 /* For tcp packets-check SYN only */ -#define IP_FW_F_ICMPRPL 0x100 /* Send back icmp unreachable packet */ -#define IP_FW_F_IFNAME 0x200 /* Use interface name/unit (not IP) */ -#define IP_FW_F_MASK 0x3FF /* All possible flag bits mask */ + * order). */ + +#define IP_FW_F_IFNAME 0x080 /* Use interface name/unit (not IP) */ + +#define IP_FW_F_MASK 0x0FF /* All possible flag bits mask */ /* - * New IP firewall options for [gs]etsockopt at the RAW IP level. + * Definitions for IP option names. */ -#define IP_FW_BASE_CTL 53 +#define IP_FW_IPOPT_LSRR 0x01 +#define IP_FW_IPOPT_SSRR 0x02 +#define IP_FW_IPOPT_RR 0x04 +#define IP_FW_IPOPT_TS 0x08 -#define IP_FW_ADD (IP_FW_BASE_CTL) -#define IP_FW_DEL (IP_FW_BASE_CTL+4) -#define IP_FW_FLUSH (IP_FW_BASE_CTL+6) -#define IP_FW_POLICY (IP_FW_BASE_CTL+7) +/* + * Definitions for TCP flags. + */ +#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_ACK TH_ACK +#define IP_FW_TCPF_URG TH_URG + +/* + * New IP firewall options for [gs]etsockopt at the RAW IP level. + */ +#define IP_FW_BASE_CTL 50 -#define IP_ACCT_ADD (IP_FW_BASE_CTL+10) -#define IP_ACCT_DEL (IP_FW_BASE_CTL+11) -#define IP_ACCT_FLUSH (IP_FW_BASE_CTL+12) -#define IP_ACCT_ZERO (IP_FW_BASE_CTL+13) -#define IP_ACCT_CLR (IP_FW_BASE_CTL+14) +#define IP_FW_ADD (IP_FW_BASE_CTL+0) +#define IP_FW_DEL (IP_FW_BASE_CTL+1) +#define IP_FW_FLUSH (IP_FW_BASE_CTL+2) +#define IP_FW_ZERO (IP_FW_BASE_CTL+3) /* * Policy flags... */ #define IP_FW_P_DENY 0x01 #define IP_FW_P_ICMP 0x02 -#define IP_FW_P_MASK 0x03 +#define IP_FW_P_MBIPO 0x04 +#define IP_FW_P_MASK 0x07 /* @@ -118,30 +125,15 @@ struct ip_fw { #ifdef KERNEL /* - * Variables/chain. - */ -extern struct ip_fw *ip_fw_chain; -extern u_short ip_fw_policy; - -extern struct ip_fw *ip_acct_chain; - -/* * Function pointers. */ -extern int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *,struct ifnet *,struct ip_fw *); +extern int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *,struct ifnet *, int dir); extern int (*ip_fw_ctl_ptr)(int,struct mbuf *); -extern void (*ip_acct_cnt_ptr)(struct ip *,struct ifnet *,struct ip_fw *,int); -extern int (*ip_acct_ctl_ptr)(int,struct mbuf *); - /* * Function definitions. */ -int ip_fw_chk(struct mbuf *, struct ip *,struct ifnet *,struct ip_fw *); -int ip_fw_ctl(int,struct mbuf *); - -void ip_acct_cnt(struct ip *,struct ifnet *,struct ip_fw *,int); -int ip_acct_ctl(int,struct mbuf *); +void ip_fw_init(void); #endif /* KERNEL */ diff --git a/sys/netinet/ip_fwdef.c b/sys/netinet/ip_fwdef.c deleted file mode 100644 index 8af86ba54783..000000000000 --- a/sys/netinet/ip_fwdef.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 1993 Daniel Boulet - * Copyright (c) 1994 Ugen J.S.Antsilevich - * - * Redistribution and use in source forms, with and without modification, - * are permitted provided that this entire comment appears intact. - * - * Redistribution in binary form may occur without any restrictions. - * Obviously, it would be nice if you gave credit where credit is due - * but requiring it would be too onerous. - * - * This software is provided ``AS IS'' without any warranties of any kind. - * - * $Id: ip_fwdef.c,v 1.6 1995/07/23 05:36:31 davidg Exp $ - */ - -/* - * Dumb definitions which needed when - * firewall/accounting module is not loaded. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/domain.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <sys/time.h> -#include <sys/kernel.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_fw.h> - -u_short ip_fw_policy; -struct ip_fw *ip_fw_chain; -struct ip_fw *ip_acct_chain; - -#ifdef IPFIREWALL -int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *, struct ifnet *, struct ip_fw *) = &ip_fw_chk; -int (*ip_fw_ctl_ptr)(int, struct mbuf *) = &ip_fw_ctl; -#else -int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *, struct ifnet *, struct ip_fw *); -int (*ip_fw_ctl_ptr)(int, struct mbuf *); -#endif - - -#ifdef IPACCT -void (*ip_acct_cnt_ptr)(struct ip *, struct ifnet *, struct ip_fw *, int) = &ip_acct_cnt; -int (*ip_acct_ctl_ptr)(int, struct mbuf *) = &ip_acct_ctl; -#else -void (*ip_acct_cnt_ptr)(struct ip *, struct ifnet *, struct ip_fw *, int); -int (*ip_acct_ctl_ptr)(int, struct mbuf *); -#endif diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 6f107515d09d..2ea53655ddd7 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.25 1995/07/09 14:29:46 davidg Exp $ + * $Id: ip_input.c,v 1.22.4.2 1995/09/06 10:31:35 davidg Exp $ */ #include <sys/param.h> @@ -97,6 +97,25 @@ struct ifqueue ipintrq; struct ipstat ipstat; struct ipq ipq; + +/* + * The dummy IP-firewall function, and the pointer we access it through + */ +static int +dummy_ip_fw_chk(m, ip, rif, dir) + struct mbuf *m; + struct ip *ip; + struct ifnet *rif; + int dir; +{ + return 1; +} + +int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *, struct ifnet *, int dir) = + dummy_ip_fw_chk; + +int (*ip_fw_ctl_ptr)(int, struct mbuf *); + /* * We need to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here @@ -136,6 +155,9 @@ ip_init() ipq.next = ipq.prev = &ipq; ip_id = time.tv_sec & 0xffff; ipintrq.ifq_maxlen = ipqmaxlen; +#if defined(IPFIREWALL) || defined(IPACCT) + ip_fw_init(); +#endif /* IPFIREWALL */ } struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; @@ -241,10 +263,9 @@ next: * - Encapsulate: put it in another IP and send out. <unimp.> */ - if (ip_fw_chk_ptr!=NULL) - if (!(*ip_fw_chk_ptr)(m,ip,m->m_pkthdr.rcvif,ip_fw_chain) ) { - goto next; - } + if (!(*ip_fw_chk_ptr)(m,ip,m->m_pkthdr.rcvif,0) ) { + goto next; + } /* * Process options and, if not destined for us, @@ -356,17 +377,6 @@ next: goto next; ours: - - /* - * If packet came to us we count it... - * This way we count all incoming packets which has - * not been forwarded... - * Do not convert ip_len to host byte order when - * counting,ppl already made it for us before.. - */ - if (ip_acct_cnt_ptr!=NULL) - (*ip_acct_cnt_ptr)(ip,m->m_pkthdr.rcvif,ip_acct_chain,0); - /* * If offset or IP_MF are set, must reassemble. * Otherwise, nothing need be done. diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index b5f1e974a87d..64bfcb86084c 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.23 1995/07/26 18:05:13 wollman Exp $ + * $Id: ip_output.c,v 1.19.4.2 1995/09/06 10:31:40 davidg Exp $ */ #include <sys/param.h> @@ -314,6 +314,14 @@ ip_output(m0, opt, ro, flags, imo) sendit: /* + * Check with the firewall... + */ + if (!(*ip_fw_chk_ptr)(m,ip,ifp,1)) { + error = 0; + goto done; + } + + /* * If small enough for interface, can just send directly. */ if ((u_short)ip->ip_len <= ifp->if_mtu) { @@ -417,16 +425,6 @@ sendorfree: done: if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) RTFREE(ro->ro_rt); - /* - * Count outgoing packet,here we count both our packets and - * those we forward. - * Here we want to convert ip_len to host byte order when counting - * so we set 3rd arg to 1. - * This is locally generated packet so it has not - * incoming interface. - */ - if (ip_acct_cnt_ptr!=NULL) - (*ip_acct_cnt_ptr)(ip,NULL,ip_acct_chain,1); return (error); bad: diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 616ef748ab0c..81acff46ecd6 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 - * $Id: raw_ip.c,v 1.19.4.2 1995/10/07 20:17:31 davidg Exp $ + * $Id: raw_ip.c,v 1.19.4.3 1995/10/21 03:02:54 davidg Exp $ */ #include <sys/param.h> @@ -222,6 +222,7 @@ rip_ctloutput(op, so, level, optname, m) case IP_FW_DEL: case IP_FW_FLUSH: case IP_FW_POLICY: + case IP_FW_ZERO: if (ip_fw_ctl_ptr==NULL) { if (*m) (void)m_free(*m); @@ -237,26 +238,6 @@ rip_ctloutput(op, so, level, optname, m) error=EINVAL; return(error); - case IP_ACCT_DEL: - case IP_ACCT_ADD: - case IP_ACCT_CLR: - case IP_ACCT_FLUSH: - case IP_ACCT_ZERO: - if (ip_acct_ctl_ptr==NULL) { - if (*m) - (void)m_free(*m); - return(EINVAL); - } - - if (op == PRCO_SETOPT) { - error=(*ip_acct_ctl_ptr)(optname, *m); - if (*m) - (void)m_free(*m); - } - else - error=EINVAL; - return(error); - case IP_RSVP_ON: return ip_rsvp_init(so); break; |
