From 37afa1e829192e31953f3a6603c4b65c0fdb94a1 Mon Sep 17 00:00:00 2001 From: "Ugen J.S. Antsilevich" Date: Sun, 1 Oct 1995 21:52:50 +0000 Subject: [PATCH] Well..finally..this is the first part..it should take care of matching IP options..Check and test this - i made only a couple of rough tests and this could be buggy.. Ipaccounting can't use IP Options (and i don't see any need to cound packets with specific options either..) More to come... --- sys/netinet/ip_fw.c | 107 +++++++++++++++++++++++++++++++++++++------- sys/netinet/ip_fw.h | 26 +++++++++-- 2 files changed, 114 insertions(+), 19 deletions(-) diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index b15dc9741105..a40506d8817e 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.21 1995/07/23 05:36:29 davidg Exp $ + * $Id: ip_fw.c,v 1.22 1995/07/31 13:58:35 gpalmer Exp $ */ /* @@ -100,6 +100,77 @@ port_match(portptr, nports, port, range_flag) } +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; + +printf("Here\n"); + + cp = (u_char *)(ip + 1); + cnt = (ip->ip_hl << 2) - sizeof (struct ip); + opts = f->fw_ipopt; + nopts = nopts_sve = f->fw_ipnopt; +printf("opts = %x, nopts = %x\n", opts, nopts); +printf("Cnt = %d\n", cnt); + 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: +printf("Has LSRR\n"); + 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; + } +printf("opts = %x, nopts = %x\n", opts, nopts); + 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; + +} + + /* * Returns TRUE if it should be accepted, FALSE otherwise. */ @@ -120,7 +191,6 @@ ip_fw_chk(m, ip, rif, chain) struct in_addr src, dst, ia_i; u_short src_port = 0, dst_port = 0; u_short f_prt = 0, prt; - char notcpsyn = 1; /* * If the chain is empty allow any packet-this is equal to disabling @@ -153,8 +223,6 @@ ip_fw_chk(m, ip, rif, chain) 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; break; case IPPROTO_UDP: @@ -174,11 +242,12 @@ ip_fw_chk(m, ip, rif, chain) } dprint_ip(ip->ip_src); if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { - dprintf2(":%d ", src_port); - } + dprintf2(":%d", src_port); + } + dprintf1(" "); dprint_ip(ip->ip_dst); if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { - dprintf2(":%d ", dst_port); + dprintf2(":%d", dst_port); } dprintf1("\n"); @@ -225,20 +294,22 @@ ip_fw_chk(m, ip, rif, chain) */ continue; via_match: + /* + * If we get matching IP options, we may continue + * checking ,else we have nothing to do here. + * We DO check options only if some are set in + * the entry definition. If both set and unset + * options equal - nothing to check. + */ + if (f->fw_ipopt != f->fw_ipnopt) + if (!ipopts_match(ip, f)) + continue; + 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 @@ -650,6 +721,10 @@ add_entry(chainptr, frwl) skip_check: } + if (ftmp->fw_ipopt != 0 && chtmp->fw_ipopt == 0) + addb4++; + if (ftmp->fw_ipnopt != 0 && chtmp->fw_ipnopt == 0) + addb4++; } if (addb4 > 0) { if (chtmp_prev != NULL) { diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index f32bd19de3ce..bc2dfc528533 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$ + * $Id: ip_fw.h,v 1.13 1995/07/23 05:36:30 davidg Exp $ */ /* @@ -49,6 +49,8 @@ struct ip_fw { #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 */ }; @@ -83,11 +85,28 @@ struct ip_fw { * */ #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 */ +/* + * Definitions for IP option names. + */ +#define IP_FW_IPOPT_LSRR 0x01 +#define IP_FW_IPOPT_SSRR 0x02 +#define IP_FW_IPOPT_RR 0x04 +#define IP_FW_IPOPT_TS 0x08 + +/* + * 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. */ @@ -109,7 +128,8 @@ struct ip_fw { */ #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 /*