diff options
author | ugen <ugen@FreeBSD.org> | 1994-12-12 17:20:55 +0000 |
---|---|---|
committer | ugen <ugen@FreeBSD.org> | 1994-12-12 17:20:55 +0000 |
commit | dd9e9b49e3773143f680ad0f18ead7b8023682cc (patch) | |
tree | 773d863fe59cc745780c988f947286cd83a89acb /sys | |
parent | d3899ce8a10f936258877e027e9db900c9076e68 (diff) | |
download | FreeBSD-src-dd9e9b49e3773143f680ad0f18ead7b8023682cc.zip FreeBSD-src-dd9e9b49e3773143f680ad0f18ead7b8023682cc.tar.gz |
Add match by interface from which packet arrived (via)
Handle right fragmented packets. Remove checking option
from kernel..
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_fw.c | 180 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 13 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 6 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 4 |
5 files changed, 128 insertions, 78 deletions
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 155a49e..c93ed56 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -124,26 +124,51 @@ int range_flag; */ #ifdef IPFIREWALL -int ip_fw_chk(ip,chain) -struct ip *ip; -struct ip_fw *chain; +int ip_fw_chk(ip,rif,chain) +struct ip *ip; +struct ifnet *rif; +struct ip_fw *chain; { - struct in_addr src, dst; - char notcpsyn=1; - int frwl_proto=0, proto; - struct mbuf *m; register struct ip_fw *f; - u_short src_port=0, dst_port=0; 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; + struct mbuf *m; + 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 firewall. + */ if (!chain) - return(1); /* If no chain , always say Ok to packet */ + 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. + */ + if (ip->ip_off&IP_OFFMASK) + return(1); src = ip->ip_src; dst = ip->ip_dst; + /* + * If we got interface from + * which packet came-store + * pointer to it's first adress + */ + if (rif) + ia=rif->if_addrlist; + dprintf1("Packet "); switch(ip->ip_p) { case IPPROTO_TCP: @@ -152,21 +177,21 @@ struct ip_fw *chain; dst_port=ntohs(tcp->th_dport); if (tcp->th_flags&TH_SYN) notcpsyn=0; /* We *DO* have SYN ,value FALSE */ - proto=IP_FW_F_TCP; + prt=IP_FW_F_TCP; break; case IPPROTO_UDP: dprintf1("UDP "); src_port=ntohs(udp->uh_sport); dst_port=ntohs(udp->uh_dport); - proto=IP_FW_F_UDP; + prt=IP_FW_F_UDP; break; case IPPROTO_ICMP: dprintf2("ICMP:%u ",icmp->icmp_type); - proto=IP_FW_F_ICMP; + prt=IP_FW_F_ICMP; break; default: dprintf2("p=%d ",ip->ip_p); - proto=IP_FW_F_ALL; + prt=IP_FW_F_ALL; break; } dprint_ip(ip->ip_src); @@ -183,8 +208,43 @@ struct ip_fw *chain; for (f=chain;f;f=f->next) if ((src.s_addr&f->src_mask.s_addr)==f->src.s_addr && (dst.s_addr&f->dst_mask.s_addr)==f->dst.s_addr) { - frwl_proto=f->flags&IP_FW_F_KIND; - if (frwl_proto==IP_FW_F_ALL) { + if (f->via.s_addr && rif) { + for (ia_p=ia;ia_p;ia_p=ia_p->ifa_next) { + if (!ia_p->ifa_addr || + ia_p->ifa_addr->sa_family!=AF_INET) + /* + * Next interface adress. + * This is continue for + * local "for" + */ + continue; + ia_i.s_addr=(((struct sockaddr_in *)\ + (ia_p->ifa_addr))->sin_addr.s_addr); + if (ia_i.s_addr==f->via.s_addr) + goto via_match; + } + /* + * Next interface adress. + * This is continue for + * local "for" + */ + continue; + } else { + /* + * No special "via" adress set + * or interface from which packet + * came unknown so match anyway + */ + goto via_match; + } + /* + * Skip to next firewall entry - via + * address did not matched. + */ + continue; +via_match: + f_prt=f->flags&IP_FW_F_KIND; + if (f_prt==IP_FW_F_ALL) { /* Universal frwl - we've got a match! */ goto got_match; } else { @@ -201,9 +261,9 @@ struct ip_fw *chain; * Specific firewall - packet's * protocol must match firewall's */ - if (proto==frwl_proto) { + if (prt==f_prt) { - if (proto==IP_FW_F_ICMP || + if (prt==IP_FW_F_ICMP || (port_match(&f->ports[0],f->n_src_p,src_port, f->flags&IP_FW_F_SRNG) && port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port, @@ -273,7 +333,7 @@ bad_packet: * Do not ICMP reply to icmp * packets....:) */ - if (frwl_proto==IP_FW_F_ICMP) + if (f_prt==IP_FW_F_ICMP) return 0; /* * Reply to packets rejected @@ -292,7 +352,7 @@ bad_packet: return 0; m->m_len = sizeof(struct ip)+64; bcopy((caddr_t)ip,mtod(m, caddr_t),(unsigned)m->m_len); - if (frwl_proto=IP_FW_F_ALL) + 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); @@ -313,41 +373,49 @@ good_packet: #ifdef IPACCT -void ip_acct_cnt(ip,chain,nh_conv) -struct ip *ip; -struct ip_fw *chain; +void ip_acct_cnt(ip,rif,chain,nh_conv) +struct ip *ip; +struct ifnet *rif; +struct ip_fw *chain; int nh_conv; { - struct in_addr src, dst; - char rev=0; - int frwl_proto, proto=0; register struct ip_fw *f; - u_short src_port=0, dst_port=0; 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) return; + if (ip->ip_off&IP_OFFMASK) + return; + src = ip->ip_src; dst = ip->ip_dst; + if (rif) + ia=rif->if_addrlist; + switch(ip->ip_p) { case IPPROTO_TCP: src_port=ntohs(tcp->th_sport); dst_port=ntohs(tcp->th_dport); - proto=IP_FW_F_TCP; + prt=IP_FW_F_TCP; break; case IPPROTO_UDP: src_port=ntohs(udp->uh_sport); dst_port=ntohs(udp->uh_dport); - proto=IP_FW_F_UDP; + prt=IP_FW_F_UDP; break; case IPPROTO_ICMP: - proto=IP_FW_F_ICMP; + prt=IP_FW_F_ICMP; break; default: - proto=IP_FW_F_ALL; + prt=IP_FW_F_ALL; break; } @@ -365,8 +433,24 @@ int nh_conv; } continue; addr_match: - frwl_proto=f->flags&IP_FW_F_KIND; - if (frwl_proto==IP_FW_F_ALL) { + if (f->via.s_addr && rif) { + for (ia_p=ia;ia_p;ia_p=ia_p->ifa_next) { + if (!ia_p->ifa_addr || + 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->via.s_addr) + goto via_match; + } + continue; + } else { + goto via_match; + } + continue; +via_match: + f_prt=f->flags&IP_FW_F_KIND; + if (f_prt==IP_FW_F_ALL) { /* Universal frwl - we've got a match! */ f->p_cnt++; /* Rise packet count */ @@ -386,9 +470,9 @@ addr_match: * Specific firewall - packet's * protocol must match firewall's */ - if (proto==frwl_proto) { + if (prt==f_prt) { - if ((proto==IP_FW_F_ICMP || + if ((prt==IP_FW_F_ICMP || (port_match(&f->ports[0],f->n_src_p,src_port, f->flags&IP_FW_F_SRNG) && port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port, @@ -813,34 +897,6 @@ if ( stage == IP_FW_POLICY ) return 0; } -if ( stage == IP_FW_CHK_BLK - || stage == IP_FW_CHK_FWD ) { - - struct ip *ip; - - if ( m->m_len < sizeof(struct ip) + 2 * sizeof(u_short) ) { - dprintf3("ip_fw_ctl: mbuf len=%d, want at least %d\n", - m->m_len,sizeof(struct ip) + 2 * sizeof(u_short)); - return( EINVAL ); - } - - ip = mtod(m,struct ip *); - - if ( ip->ip_hl != sizeof(struct ip) / sizeof(int) ) { - dprintf3("ip_fw_ctl: ip->ip_hl=%d, want %d\n",ip->ip_hl, - sizeof(struct ip)/sizeof(int)); - return(EINVAL); - } - - if ( ip_fw_chk(ip, - stage == IP_FW_CHK_BLK ? - ip_fw_blk_chain : ip_fw_fwd_chain ) - ) - return(0); - else - return(EACCES); - } - /* * Here we really working hard-adding new elements * to blocking/forwarding chains or deleting'em diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 9c30210..ecae108 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -26,6 +26,7 @@ struct ip_fw { struct ip_fw *next; /* Next firewall on chain */ struct in_addr src, dst; /* Source and destination IP addr */ struct in_addr src_mask, dst_mask; /* Mask for src and dest IP addr */ + struct in_addr via; /* IP addr of interface "via" */ u_short flags; /* Flags word */ u_short n_src_p, n_dst_p; /* # of src ports and # of dst ports */ /* in ports array (dst ports follow */ @@ -70,8 +71,6 @@ struct ip_fw { #define IP_FW_ADD_BLK (IP_FW_BASE_CTL) #define IP_FW_ADD_FWD (IP_FW_BASE_CTL+1) -#define IP_FW_CHK_BLK (IP_FW_BASE_CTL+2) -#define IP_FW_CHK_FWD (IP_FW_BASE_CTL+3) #define IP_FW_DEL_BLK (IP_FW_BASE_CTL+4) #define IP_FW_DEL_FWD (IP_FW_BASE_CTL+5) #define IP_FW_FLUSH (IP_FW_BASE_CTL+6) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 085d0ff..3b2678c 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.10 1994/11/08 12:47:29 jkh Exp $ + * $Id: ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp $ */ #include <sys/param.h> @@ -240,7 +240,7 @@ next: #ifdef IPFIREWALL if ( ((char *)&(ip->ip_dst.s_addr))[0] != 127 - && !ip_fw_chk(ip,ip_fw_blk_chain) ) { + && !ip_fw_chk(ip,m->m_pkthdr.rcvif,ip_fw_blk_chain) ) { goto bad; } #endif @@ -364,7 +364,7 @@ ours: * Do not convert ip_len to host byte order when * counting,ppl already made it for us before.. */ - ip_acct_cnt(ip,ip_acct_chain,0); + ip_acct_cnt(ip,m->m_pkthdr.rcvif,ip_acct_chain,0); #endif /* @@ -1051,7 +1051,7 @@ ip_forward(m, srcrt) #ifdef IPFIREWALL if ( ((char *)&(ip->ip_dst.s_addr))[0] != 127 - && !ip_fw_chk(ip,ip_fw_fwd_chain) ) { + && !ip_fw_chk(ip,m->m_pkthdr.rcvif,ip_fw_fwd_chain) ) { ipstat.ips_cantforward++; m_freem(m); return; @@ -1139,11 +1139,6 @@ ip_forward(m, srcrt) if (error) ipstat.ips_cantforward++; else { -#ifdef wrong -#ifdef IPACCT - ip_acct_cnt(ip,ip_acct_chain); -#endif -#endif ipstat.ips_forward++; if (type) ipstat.ips_redirectsent++; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index a734c42..986f9dd 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.8 1994/09/14 03:10:13 wollman Exp $ + * $Id: ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp $ */ #include <sys/param.h> @@ -414,8 +414,10 @@ done: * 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. */ - ip_acct_cnt(ip,ip_acct_chain,1); + ip_acct_cnt(ip,NULL,ip_acct_chain,1); #endif return (error); bad: diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 4b33614..bbba46e 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 - * $Id: raw_ip.c,v 1.6 1994/10/28 15:09:49 jkh Exp $ + * $Id: raw_ip.c,v 1.8 1994/11/16 10:17:11 jkh Exp $ */ #include <sys/param.h> @@ -214,8 +214,6 @@ rip_ctloutput(op, so, level, optname, m) #ifdef IPFIREWALL case IP_FW_ADD_BLK: case IP_FW_ADD_FWD: - case IP_FW_CHK_BLK: - case IP_FW_CHK_FWD: case IP_FW_DEL_BLK: case IP_FW_DEL_FWD: case IP_FW_FLUSH: |