This patch affects both kernel and userland. Make sure you have both kenel and userland sources before applying this patch. Apply by doing: # cd /usr/src # patch -p0 < 023_ipf.patch now, build a kernel. Eg, for GENERIC: # cd sys/arch/i386/conf # config GENERIC # cd ../compile/GENERIC # make clean && make depend && make # cp /bsd /bsd.old # cp bsd /bsd Export headers to userland # cd /usr/src # make includes And now rebuild userland # cd /usr/src/sbin/ipf # make obj && make cleandir && make && make install # cd /usr/src/sbin/ipnat # make obj && make cleandir && make && make install # cd /usr/src/sbin/ipfstat # make obj && make cleandir && make && make install # cd /usr/src/usr.sbin/ipmon # make obj && make cleandir && make && make install # cd /usr/src/usr.sbin/ipftest # make obj && make cleandir && make && make install Reboot to activate the new ipf. To check that all was successful, do: # ipf -V You should see something like: ipf: IP Filter: v3.3.16 (184) Kernel: IP Filter: v3.3.16 Running: yes Log Flags: 0 = none set Default: pass all, Logging: available Active list: 0 Index: sys/netinet/ipl.h =================================================================== RCS file: ipl.h diff -N ipl.h --- /dev/null Wed May 24 17:02:20 2000 +++ sys/netinet/ipl.h Wed May 24 17:46:34 2000 @@ -0,0 +1,18 @@ +/* $OpenBSD: ipl.h,v 1.11 2000/05/24 21:59:11 kjell Exp $ */ + +/* + * Copyright (C) 1993-1999 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + * @(#)ipl.h 1.21 6/5/96 + */ + +#ifndef __IPL_H__ +#define __IPL_H__ + +#define IPL_VERSION "IP Filter: v3.3.16" + +#endif Index: sys/netinet/fil.c =================================================================== RCS file: /cvs/src/sys/netinet/fil.c,v retrieving revision 1.15 retrieving revision 1.25 diff -u -r1.15 -r1.25 --- sys/netinet/fil.c 1999/02/19 20:52:22 1.15 +++ sys/netinet/fil.c 2000/05/24 21:59:10 1.25 @@ -1,4 +1,5 @@ -/* $OpenBSD: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $ */ +/* $OpenBSD: fil.c,v 1.25 2000/05/24 21:59:10 kjell Exp $ */ + /* * Copyright (C) 1993-1998 by Darren Reed. * @@ -8,7 +9,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; -static const char rcsid[] = "@(#)$Id: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $"; +static const char rcsid[] = "@(#)$IPFilter: fil.c,v 2.3.2.20 2000/05/22 06:57:42 darrenr Exp $"; #endif #include @@ -16,7 +17,17 @@ #include #include #include -#include +#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ + defined(_KERNEL) +# include "opt_ipfilter_log.h" +#endif +#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \ + (__FreeBSD_version >= 220000) +# include +# include +#else +# include +#endif #if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) # include #else @@ -32,9 +43,9 @@ #else # include # if SOLARIS2 < 5 -# include +# include # endif -# include +# include #endif #ifndef linux # include @@ -51,14 +62,14 @@ #ifndef linux # include #endif +#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ +# include +# include +#endif #include #include #include -#if defined(__OpenBSD__) -# include -#else -# include -#endif +#include #include #include #include @@ -66,9 +77,16 @@ #include #include #include +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) +# include +# if defined(_KERNEL) && !defined(IPFILTER_LKM) +# include "opt_ipfilter.h" +# endif +# endif #ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) +# define MIN(a,b) (((a)<(b))?(a):(b)) #endif +#include #ifndef _KERNEL # include "ipf.h" @@ -81,14 +99,7 @@ second; } # define FR_VERBOSE(verb_pr) verbose verb_pr # define FR_DEBUG(verb_pr) debug verb_pr -# define SEND_RESET(ip, qif, if, m) send_reset(ip, if) # define IPLLOG(a, c, d, e) ipllog() -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip) -# if SOLARIS -# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(ip) -# else -# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(b, ip, if) -# endif #else /* #ifndef _KERNEL */ # define FR_IFVERBOSE(ex,second,verb_pr) ; # define FR_IFDEBUG(ex,second,verb_pr) ; @@ -96,39 +107,8 @@ # define FR_DEBUG(verb_pr) # define IPLLOG(a, c, d, e) ipflog(a, c, d, e) # if SOLARIS || defined(__sgi) -extern KRWLOCK_T ipf_mutex, ipf_auth; +extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat; extern kmutex_t ipf_rw; -# endif -# if SOLARIS -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \ - ip, qif) -# define SEND_RESET(ip, qif, if) send_reset(ip, qif) -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(ip, t, c, if, src) -# else /* SOLARIS */ -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip) -# ifdef linux -# define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip,\ - ifp) -# else -# define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip) -# endif -# ifdef __sgi -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(b, t, c, if, src, if) -# else -# if BSD < 199103 -# ifdef linux -# define ICMP_ERROR(b, ip, t, c, if, src) icmp_send(b,t,c,0,if) -# else -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(mtod(b, ip_t *), t, c, if, src) -# endif /* linux */ -# else -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(b, t, c, (src).s_addr, if) -# endif /* BSD < 199103 */ -# endif /* __sgi */ # endif /* SOLARIS || __sgi */ #endif /* _KERNEL */ @@ -143,12 +123,15 @@ #else int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH); #endif +char ipfilter_version[] = IPL_VERSION; fr_info_t frcache[2]; -static void fr_makefrip __P((int, ip_t *, fr_info_t *)); static int fr_tcpudpchk __P((frentry_t *, fr_info_t *)); -static int frflushlist __P((int, int, int *, frentry_t *, frentry_t **)); +static int frflushlist __P((int, minor_t, int *, frentry_t **)); +#ifdef _KERNEL +static void frsynclist __P((frentry_t *)); +#endif /* @@ -196,7 +179,7 @@ * compact the IP header into a structure which contains just the info. * which is useful for comparing IP headers with. */ -static void fr_makefrip(hlen, ip, fin) +void fr_makefrip(hlen, ip, fin) int hlen; ip_t *ip; fr_info_t *fin; @@ -208,6 +191,7 @@ int i, mv, ol, off; u_char *s, opt; + fin->fin_rev = 0; fin->fin_fr = NULL; fin->fin_tcpf = 0; fin->fin_data[0] = 0; @@ -225,8 +209,8 @@ tcp = (tcphdr_t *)((char *)ip + hlen); fin->fin_dp = (void *)tcp; (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); - (*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3)); - (*(((u_32_t *)fi) + 2)) = (*(((u_32_t *)ip) + 4)); + fi->fi_src.s_addr = ip->ip_src.s_addr; + fi->fi_dst.s_addr = ip->ip_dst.s_addr; fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; off = (ip->ip_off & IP_OFFMASK) << 3; @@ -244,6 +228,17 @@ if (!off && (icmp->icmp_type == ICMP_ECHOREPLY || icmp->icmp_type == ICMP_ECHO)) minicmpsz = ICMP_MINLEN; + + if (!off && (icmp->icmp_type == ICMP_TSTAMP || + icmp->icmp_type == ICMP_TSTAMPREPLY)) + minicmpsz = 20; +/* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */ + + if (!off && (icmp->icmp_type == ICMP_MASKREQ || + icmp->icmp_type == ICMP_MASKREPLY)) + minicmpsz = 12; +/* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */ + if ((!(ip->ip_len >= hlen + minicmpsz) && !off) || (off && off < sizeof(struct icmp))) fi->fi_fl |= FI_SHORT; @@ -275,12 +270,19 @@ } - for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) { - if (!(opt = *s)) - break; - ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1); - if (opt > 1 && (ol < 2 || ol > hlen)) + for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { + opt = *s; + if (opt == '\0') break; + else if (opt == IPOPT_NOP) + ol = 1; + else { + if (hlen < 2) + break; + ol = (int)*(s + 1); + if (ol < 2 || ol > hlen) + break; + } for (i = 9, mv = 4; mv >= 0; ) { op = ipopts + i; if (opt == (u_char)op->ol_val) { @@ -421,14 +423,15 @@ * kernel sauce. */ int fr_scanlist(pass, ip, fin, m) -int pass; +u_32_t pass; ip_t *ip; register fr_info_t *fin; void *m; { register struct frentry *fr; register fr_ip_t *fi = &fin->fin_fi; - int rulen, portcmp = 0, off, skip = 0; + int rulen, portcmp = 0, off, skip = 0, logged = 0; + u_32_t passt; fr = fin->fin_fr; fin->fin_fr = NULL; @@ -452,8 +455,16 @@ * check that we are working for the right interface */ #ifdef _KERNEL - if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) - continue; +# if BSD >= 199306 + if (fin->fin_out != 0) { + if ((fr->fr_oifa && + fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) || + (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)) + continue; + } else +# endif + if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) + continue; #else if (opts & (OPT_VERBOSE|OPT_DEBUG)) printf("\n"); @@ -473,10 +484,12 @@ i = ((lip[0] & lm[0]) != ld[0]); FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n", lip[0], lm[0], ld[0])); - i |= ((lip[1] & lm[1]) != ld[1]) << 21; + i |= ((lip[1] & lm[1]) != ld[1]) << 19; + i ^= (fr->fr_flags & FR_NOTSRCIP); FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n", lip[1], lm[1], ld[1])); - i |= ((lip[2] & lm[2]) != ld[2]) << 22; + i |= ((lip[2] & lm[2]) != ld[2]) << 20; + i ^= (fr->fr_flags & FR_NOTDSTIP); FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n", lip[2], lm[2], ld[2])); i |= ((lip[3] & lm[3]) != ld[3]); @@ -485,7 +498,6 @@ i |= ((lip[4] & lm[4]) != ld[4]); FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n", lip[4], lm[4], ld[4])); - i ^= (fi->fi_fl & (FR_NOTSRCIP|FR_NOTDSTIP)); if (i) continue; } @@ -515,18 +527,23 @@ /* * Just log this packet... */ - if (!(skip = fr->fr_skip)) - pass = fr->fr_flags; - if ((pass & FR_CALLNOW) && fr->fr_func) - pass = (*fr->fr_func)(pass, ip, fin); + passt = fr->fr_flags; + if ((passt & FR_CALLNOW) && fr->fr_func) + passt = (*fr->fr_func)(passt, ip, fin); + fin->fin_fr = fr; #ifdef IPFILTER_LOG - if ((pass & FR_LOGMASK) == FR_LOG) { - if (!IPLLOG(fr->fr_flags, ip, fin, m)) { + if ((passt & FR_LOGMASK) == FR_LOG) { + if (!IPLLOG(passt, ip, fin, m)) { + if (passt & FR_LOGORBLOCK) + passt |= FR_BLOCK|FR_QUICK; ATOMIC_INC(frstats[fin->fin_out].fr_skip); } ATOMIC_INC(frstats[fin->fin_out].fr_pkl); + logged = 1; } #endif /* IPFILTER_LOG */ + if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) + pass = passt; FR_DEBUG(("pass %#x\n", pass)); ATOMIC_INC(fr->fr_hits); if (pass & FR_ACCOUNT) @@ -535,7 +552,6 @@ fin->fin_icode = fr->fr_icode; fin->fin_rule = rulen; fin->fin_group = fr->fr_group; - fin->fin_fr = fr; if (fr->fr_grp) { fin->fin_fr = fr->fr_grp; pass = fr_scanlist(pass, ip, fin, m); @@ -544,10 +560,14 @@ fin->fin_group = fr->fr_group; fin->fin_fr = fr; } + if (pass & FR_DONTCACHE) + logged = 1; } if (pass & FR_QUICK) break; } + if (logged) + pass |= FR_DONTCACHE; return pass; } @@ -576,7 +596,8 @@ fr_info_t frinfo, *fc; register fr_info_t *fin = &frinfo; frentry_t *fr = NULL; - int pass, changed, apass, error = EHOSTUNREACH; + int changed, error = EHOSTUNREACH; + u_32_t pass, apass; #if !SOLARIS || !defined(_KERNEL) register mb_t *m = *mp; #endif @@ -597,7 +618,17 @@ */ m->m_flags &= ~M_CANFASTFWD; # endif /* M_CANFASTFWD */ +# ifdef CSUM_DELAY_DATA + /* + * disable delayed checksums. + */ + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } +# endif /* CSUM_DELAY_DATA */ + if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_ICMP)) { int plen = 0; @@ -611,8 +642,8 @@ case IPPROTO_UDP: plen = sizeof(udphdr_t); break; + /* 96 - enough for complete ICMP error IP header */ case IPPROTO_ICMP: - /* need enough for complete ICMP error IP header */ plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); break; } @@ -648,16 +679,30 @@ # if SOLARIS mb_t *m = qif->qf_m; + if ((u_int)ip & 0x3) + return 2; fin->fin_qfm = m; + fin->fin_qif = qif; # endif #endif /* _KERNEL */ + + /* + * Be careful here: ip_id is in network byte order when called + * from ip_output() + */ + if (out) + ip->ip_id = ntohs(ip->ip_id); fr_makefrip(hlen, ip, fin); fin->fin_ifp = ifp; fin->fin_out = out; fin->fin_mp = mp; + pass = fr_pass; READ_ENTER(&ipf_mutex); + if (fin->fin_fi.fi_fl & FI_SHORT) + ATOMIC_INC(frstats[out].fr_short); + /* * Check auth now. This, combined with the check below to see if apass * is 0 is to ensure that we don't count the packet twice, which can @@ -668,15 +713,15 @@ apass = fr_checkauth(ip, fin); if (!out) { - changed = ip_natin(ip, hlen, fin); + changed = ip_natin(ip, fin); if (!apass && (fin->fin_fr = ipacct[0][fr_active]) && - (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { + (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { ATOMIC_INC(frstats[0].fr_acct); } } - if (apass || (!(pass = ipfr_knownfrag(ip, fin)) && - !(pass = fr_checkstate(ip, fin)))) { + if (apass || (!(fr = ipfr_knownfrag(ip, fin)) && + !(fr = fr_checkstate(ip, fin)))) { /* * If a packet is found in the auth table, then skip checking * the access lists for permission but we do need to consider @@ -694,13 +739,13 @@ if ((fr = fin->fin_fr)) { ATOMIC_INC(fr->fr_hits); pass = fr->fr_flags; - } else - pass = fr_pass; + } } else { - pass = fr_pass; if ((fin->fin_fr = ipfilter[out][fr_active])) - pass = FR_SCANLIST(fr_pass, ip, fin, m); - bcopy((char *)fin, (char *)fc, FI_COPYSIZE); + pass = fr_scanlist(fr_pass, ip, fin, m); + if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE))) + bcopy((char *)fin, (char *)fc, + FI_COPYSIZE); if (pass & FR_NOMATCH) { ATOMIC_INC(frstats[out].fr_nom); } @@ -715,7 +760,7 @@ * then pretend we've dropped it already. */ if ((pass & FR_AUTH)) - if (FR_NEWAUTH(m, fin, ip, qif) != 0) + if (fr_newauth((mb_t *)m, fin, ip) != 0) #ifdef _KERNEL m = *mp = NULL; #else @@ -725,7 +770,7 @@ if (pass & FR_PREAUTH) { READ_ENTER(&ipf_auth); if ((fin->fin_fr = ipauth) && - (pass = FR_SCANLIST(0, ip, fin, m))) { + (pass = fr_scanlist(0, ip, fin, m))) { ATOMIC_INC(fr_authstats.fas_hits); } else { ATOMIC_INC(fr_authstats.fas_miss); @@ -733,7 +778,8 @@ RWLOCK_EXIT(&ipf_auth); } - if (pass & FR_KEEPFRAG) { + fin->fin_fr = fr; + if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { if (fin->fin_fi.fi_fl & FI_FRAG) { if (ipfr_newfrag(ip, fin, pass) == -1) { ATOMIC_INC(frstats[out].fr_bnfr); @@ -745,12 +791,16 @@ } } if (pass & FR_KEEPSTATE) { - if (fr_addstate(ip, fin, pass) == -1) { + if (fr_addstate(ip, fin, 0) == NULL) { ATOMIC_INC(frstats[out].fr_bads); } else { ATOMIC_INC(frstats[out].fr_ads); } } + } else if (fr != NULL) { + pass = fr->fr_flags; + if (pass & FR_LOGFIRST) + pass &= ~(FR_LOGFIRST|FR_LOG); } if (fr && fr->fr_func && !(pass & FR_CALLNOW)) @@ -762,13 +812,13 @@ */ if (out && (pass & FR_PASS)) { if ((fin->fin_fr = ipacct[1][fr_active]) && - (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { + (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { ATOMIC_INC(frstats[1].fr_acct); } - fin->fin_fr = NULL; - changed = ip_natout(ip, hlen, fin); - } - fin->fin_fr = fr; + fin->fin_fr = fr; + changed = ip_natout(ip, fin); + } else + fin->fin_fr = fr; RWLOCK_EXIT(&ipf_mutex); #ifdef IPFILTER_LOG @@ -798,6 +848,10 @@ } } #endif /* IPFILTER_LOG */ + + if (out) + ip->ip_id = htons(ip->ip_id); + #ifdef _KERNEL /* * Only allow FR_DUP to work if a rule matched - it makes no sense to @@ -830,27 +884,28 @@ if (!out) { #ifdef _KERNEL if (pass & FR_RETICMP) { -# if SOLARIS - ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode, - qif, ip->ip_src); -# else - ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode, - ifp, ip->ip_src); - m = *mp = NULL; /* freed by icmp_error() */ -# endif + struct in_addr dst; + if ((pass & FR_RETMASK) == FR_FAKEICMP) + dst = ip->ip_dst; + else + dst.s_addr = 0; + send_icmp_err(ip, ICMP_UNREACH, fin, dst); ATOMIC_INC(frstats[0].fr_ret); - } else if ((pass & FR_RETRST) && + } else if (((pass & FR_RETMASK) == FR_RETRST) && !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (SEND_RESET(ip, qif, ifp) == 0) { + if (send_reset(ip, fin) == 0) { ATOMIC_INC(frstats[1].fr_ret); } } #else - if (pass & FR_RETICMP) { + if ((pass & FR_RETMASK) == FR_RETICMP) { verbose("- ICMP unreachable sent\n"); ATOMIC_INC(frstats[0].fr_ret); - } else if ((pass & FR_RETRST) && + } else if ((pass & FR_RETMASK) == FR_FAKEICMP) { + verbose("- forged ICMP unreachable sent\n"); + ATOMIC_INC(frstats[0].fr_ret); + } else if (((pass & FR_RETMASK) == FR_RETRST) && !(fin->fin_fi.fi_fl & FI_SHORT)) { verbose("- TCP RST sent\n"); ATOMIC_INC(frstats[1].fr_ret); @@ -875,10 +930,10 @@ if (fr) { frdest_t *fdp = &fr->fr_tif; - if ((pass & FR_FASTROUTE) || + if (((pass & FR_FASTROUTE) && !out) || (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - ipfr_fastroute(m, fin, fdp); - m = *mp = NULL; + if (ipfr_fastroute(m, fin, fdp) == 0) + m = *mp = NULL; } if (mc) ipfr_fastroute(mc, fin, &fr->fr_dif); @@ -890,21 +945,20 @@ m_copyback(m, 0, up, hbuf); # endif # endif /* !linux */ - return (pass & FR_PASS) ? 0 : error; # else /* !SOLARIS */ if (fr) { frdest_t *fdp = &fr->fr_tif; - if ((pass & FR_FASTROUTE) || + if (((pass & FR_FASTROUTE) && !out) || (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - ipfr_fastroute(qif, ip, m, mp, fin, fdp); - m = *mp = NULL; + if (ipfr_fastroute(qif, ip, m, mp, fin, fdp) == 0) + m = *mp = NULL; } if (mc) ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif); } - return (pass & FR_PASS) ? changed : error; # endif /* !SOLARIS */ + return (pass & FR_PASS) ? 0 : error; #else /* _KERNEL */ if (pass & FR_NOMATCH) return 1; @@ -949,23 +1003,21 @@ * and the TCP header. We also assume that data blocks aren't allocated in * odd sizes. */ -u_short fr_tcpsum(m, ip, tcp, len) +u_short fr_tcpsum(m, ip, tcp) mb_t *m; ip_t *ip; tcphdr_t *tcp; -int len; { u_short *sp, slen, ts; u_int sum, sum2; int hlen; - /* * Add up IP Header portion */ hlen = ip->ip_hl << 2; slen = ip->ip_len - hlen; - sum = htons(ip->ip_p); + sum = htons((u_short)ip->ip_p); sum += htons(slen); sp = (u_short *)&ip->ip_src; sum += *sp++; /* ip_src */ @@ -976,7 +1028,7 @@ tcp->th_sum = 0; #ifdef KERNEL # if SOLARIS - sum2 = ip_cksum(m, hlen, sum); + sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ sum2 = (sum2 & 0xffff) + (sum2 >> 16); sum2 = ~sum2 & 0xffff; # else /* SOLARIS */ @@ -1003,13 +1055,11 @@ sum2 = (sum2 & 0xffff) + (sum2 >> 16); # else /* defined(BSD) || defined(sun) */ { - union { u_char c[2]; u_short s; } bytes; - u_32_t sum; - u_short *sp, slen; + u_short len = ip->ip_len; # if defined(__sgi) int add; # endif @@ -1020,7 +1070,7 @@ sp = (u_short *)&ip->ip_src; len -= (ip->ip_hl << 2); sum = ntohs(IPPROTO_TCP); - sum += htons((u_short)len); + sum += htons(len); sum += *sp++; /* ip_src */ sum += *sp++; sum += *sp++; /* ip_dst */ @@ -1034,8 +1084,8 @@ sum += *sp++; /* ack */ sum += *sp++; sum += *sp++; /* off */ - sum += *sp; /* win */ - sp += 2; /* Skip over checksum */ + sum += *sp++; /* win */ + sum += *sp++; /* Skip over checksum */ sum += *sp++; /* urp */ # ifdef __sgi @@ -1093,7 +1143,7 @@ sum = (sum & 0xffff) + (sum >> 16); sum2 = (u_short)(~sum & 0xffff); } -# endif /* defined(BSD) || defined(sun) */ +# endif /* defined(BSD) || defined(sun) */ # endif /* SOLARIS */ #else /* KERNEL */ sum2 = 0; @@ -1137,7 +1187,7 @@ * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $ + * $IPFilter: fil.c,v 2.3.2.20 2000/05/22 06:57:42 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -1237,9 +1287,10 @@ frgroup_t *fr_findgroup(num, flags, which, set, fgpp) -u_short num; +u_int num; u_32_t flags; -int which, set; +minor_t which; +int set; frgroup_t ***fgpp; { frgroup_t *fg, **fgp; @@ -1252,6 +1303,7 @@ fgp = &ipfgroups[0][set]; else return NULL; + num &= 0xffff; while ((fg = *fgp)) if (fg->fg_num == num) @@ -1265,18 +1317,19 @@ frgroup_t *fr_addgroup(num, fp, which, set) -u_short num; +u_int num; frentry_t *fp; -int which, set; +minor_t which; +int set; { frgroup_t *fg, **fgp; if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) return fg; - KMALLOC(fg, frgroup_t *, sizeof(*fg)); + KMALLOC(fg, frgroup_t *); if (fg) { - fg->fg_num = num; + fg->fg_num = num & 0xffff; fg->fg_next = *fgp; fg->fg_head = fp; fg->fg_start = &fp->fr_grp; @@ -1287,9 +1340,10 @@ void fr_delgroup(num, flags, which, set) -u_short num; +u_int num; u_32_t flags; -int which, set; +minor_t which; +int set; { frgroup_t *fg, **fgp; @@ -1307,63 +1361,257 @@ * encountered. if a rule is the head of a group and it has lost all its * group members, then also delete the group reference. */ -static int frflushlist(set, unit, nfreedp, list, listp) -int set, unit, *nfreedp; -frentry_t *list, **listp; +static int frflushlist(set, unit, nfreedp, listp) +int set; +minor_t unit; +int *nfreedp; +frentry_t **listp; { - register frentry_t *fp = list, *fpn; - register int freed = 0; + register int freed = 0, i; + register frentry_t *fp; - while (fp) { - fpn = fp->fr_next; + while ((fp = *listp)) { + *listp = fp->fr_next; if (fp->fr_grp) { - fp->fr_ref -= frflushlist(set, unit, nfreedp, - fp->fr_grp, &fp->fr_grp); + i = frflushlist(set, unit, nfreedp, &fp->fr_grp); + MUTEX_ENTER(&ipf_rw); + fp->fr_ref -= i; + MUTEX_EXIT(&ipf_rw); } - if (fp->fr_ref == 1) { - if (fp->fr_grhead) - fr_delgroup(fp->fr_grhead, fp->fr_flags, unit, - set); + ATOMIC_DEC(fp->fr_ref); + if (fp->fr_grhead) { + fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags, + unit, set); + fp->fr_grhead = NULL; + } + if (fp->fr_ref == 0) { KFREE(fp); - *listp = fpn; freed++; - } - fp = fpn; + } else + fp->fr_next = NULL; } *nfreedp += freed; return freed; } -void frflush(unit, result) -int unit; -int *result; +int frflush(unit, flags) +minor_t unit; +int flags; { - int flags = *result, flushed = 0, set = fr_active; + int flushed = 0, set; + if (unit != IPL_LOGIPF) + return 0; WRITE_ENTER(&ipf_mutex); bzero((char *)frcache, sizeof(frcache[0]) * 2); + set = fr_active; if (flags & FR_INACTIVE) set = 1 - set; + + if (flags & FR_OUTQUE) { + (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]); + (void) frflushlist(set, unit, &flushed, &ipacct[1][set]); + } + if (flags & FR_INQUE) { + (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]); + (void) frflushlist(set, unit, &flushed, &ipacct[0][set]); + } + RWLOCK_EXIT(&ipf_mutex); + return flushed; +} - if (unit == IPL_LOGIPF) { - if (flags & FR_OUTQUE) { - (void) frflushlist(set, unit, &flushed, - ipfilter[1][set], - &ipfilter[1][set]); - (void) frflushlist(set, unit, &flushed, - ipacct[1][set], &ipacct[1][set]); - } - if (flags & FR_INQUE) { - (void) frflushlist(set, unit, &flushed, - ipfilter[0][set], - &ipfilter[0][set]); - (void) frflushlist(set, unit, &flushed, - ipacct[0][set], &ipacct[0][set]); + +char *memstr(src, dst, slen, dlen) +char *src, *dst; +int slen, dlen; +{ + char *s = NULL; + + while (dlen >= slen) { + if (bcmp(src, dst, slen) == 0) { + s = dst; + break; + } + dst++; + dlen--; + } + return s; +} + + +void fixskip(listp, rp, addremove) +frentry_t **listp, *rp; +int addremove; +{ + frentry_t *fp; + int rules = 0, rn = 0; + + for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) + ; + + if (!fp) + return; + + for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) + if (fp->fr_skip && (rn + fp->fr_skip >= rules)) + fp->fr_skip += addremove; +} + + +#ifdef _KERNEL +/* + * count consecutive 1's in bit mask. If the mask generated by counting + * consecutive 1's is different to that passed, return -1, else return # + * of bits. + */ +int countbits(ip) +u_32_t ip; +{ + u_32_t ipn; + int cnt = 0, i, j; + + ip = ipn = ntohl(ip); + for (i = 32; i; i--, ipn *= 2) + if (ipn & 0x80000000) + cnt++; + else + break; + ipn = 0; + for (i = 32, j = cnt; i; i--, j--) { + ipn *= 2; + if (j > 0) + ipn++; + } + if (ipn == ip) + return cnt; + return -1; +} + + +/* + * return the first IP Address associated with an interface + */ +int fr_ifpaddr(ifptr, inp) +void *ifptr; +struct in_addr *inp; +{ +# if SOLARIS + ill_t *ill = ifptr; +# else + struct ifnet *ifp = ifptr; +# endif + struct in_addr in; + +# if SOLARIS + in.s_addr = ill->ill_ipif->ipif_local_addr; +# else /* SOLARIS */ +# if linux + ; +# else /* linux */ + struct ifaddr *ifa; + struct sockaddr_in *sin; + +# if (__FreeBSD_version >= 300000) + ifa = TAILQ_FIRST(&ifp->if_addrhead); +# else +# if defined(__NetBSD__) || defined(__OpenBSD__) + ifa = ifp->if_addrlist.tqh_first; +# else +# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ + ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; +# else + ifa = ifp->if_addrlist; +# endif +# endif /* __NetBSD__ || __OpenBSD__ */ +# endif /* __FreeBSD_version >= 300000 */ +# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) + sin = (struct sockaddr_in *)&ifa->ifa_addr; +# else + sin = (struct sockaddr_in *)ifa->ifa_addr; + while (sin && ifa && + sin->sin_family != AF_INET) { +# if (__FreeBSD_version >= 300000) + ifa = TAILQ_NEXT(ifa, ifa_link); +# else +# if defined(__NetBSD__) || defined(__OpenBSD__) + ifa = ifa->ifa_list.tqe_next; +# else + ifa = ifa->ifa_next; +# endif +# endif /* __FreeBSD_version >= 300000 */ + if (ifa) + sin = (struct sockaddr_in *)ifa->ifa_addr; + } + if (ifa == NULL) + sin = NULL; + if (sin == NULL) + return -1; +# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ + in = sin->sin_addr; +# endif /* linux */ +# endif /* SOLARIS */ + *inp = in; + return 0; +} + + +static void frsynclist(fr) +register frentry_t *fr; +{ + for (; fr; fr = fr->fr_next) { + if (fr->fr_ifa != NULL) { + fr->fr_ifa = GETUNIT(fr->fr_ifname); + if (fr->fr_ifa == NULL) + fr->fr_ifa = (void *)-1; } + if (fr->fr_grp) + frsynclist(fr->fr_grp); + } +} + + +void frsync() +{ + register struct ifnet *ifp; + +# if !SOLARIS +# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) +# if (NetBSD >= 199905) || defined(__OpenBSD__) + for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) +# else + for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) +# endif +# else + for (ifp = ifnet; ifp; ifp = ifp->if_next) +# endif + { + ip_natsync(ifp); + ip_statesync(ifp); } +# endif + + WRITE_ENTER(&ipf_mutex); + frsynclist(ipacct[0][fr_active]); + frsynclist(ipacct[1][fr_active]); + frsynclist(ipfilter[0][fr_active]); + frsynclist(ipfilter[1][fr_active]); RWLOCK_EXIT(&ipf_mutex); - *result = flushed; } + +#else + + +/* + * return the first IP Address associated with an interface + */ +int fr_ifpaddr(ifptr, inp) +void *ifptr; +struct in_addr *inp; +{ + return 0; +} +#endif Index: sys/netinet/ip_auth.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_auth.c,v retrieving revision 1.5 retrieving revision 1.14 diff -u -r1.5 -r1.14 --- sys/netinet/ip_auth.c 1999/02/05 05:58:49 1.5 +++ sys/netinet/ip_auth.c 2000/05/24 21:59:10 1.14 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_auth.c,v 1.5 1999/02/05 05:58:49 deraadt Exp $ */ +/* $OpenBSD: ip_auth.c,v 1.14 2000/05/24 21:59:10 kjell Exp $ */ + /* * Copyright (C) 1998 by Darren Reed & Guido van Rooij. * @@ -7,7 +8,7 @@ * to the original author and the contributors. */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.5 1999/02/05 05:58:49 deraadt Exp $"; +static const char rcsid[] = "@(#)$IPFilter: ip_auth.c,v 2.1.2.4 2000/05/22 06:57:45 darrenr Exp $"; #endif #include @@ -20,7 +21,7 @@ # include # include #endif -#if defined(KERNEL) && (__FreeBSD_version >= 220000) +#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) # include # include #else @@ -41,34 +42,39 @@ #else # include # include -# include +# ifdef _KERNEL +# include +# endif # include # include #endif +#if _BSDI_VERSION >= 199802 +# include +#endif #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) # include #endif #include #ifdef sun -#include +# include #endif #include #include #include #include #ifndef KERNEL -#define KERNEL -#define NOT_KERNEL +# define KERNEL +# define NOT_KERNEL #endif #ifndef linux # include #endif #ifdef NOT_KERNEL -#undef KERNEL +# undef KERNEL #endif #ifdef __sgi # ifdef IFF_DRVRLOCK /* IRIX6 */ -#include +# include # endif #endif #include @@ -76,17 +82,16 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #else # ifndef linux +# if __FreeBSD_version >= 300000 +# include +# endif # include # include # endif #endif #include #include -#if defined(__OpenBSD__) -# include -#else -# include -#endif +#include #include #include #include @@ -96,6 +101,14 @@ # include # endif #endif +#if (__FreeBSD_version >= 300000) +# include +# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM) +# include +# include +# endif +#endif + #if (SOLARIS || defined(__sgi)) && defined(_KERNEL) @@ -125,7 +138,7 @@ * authorization result and that would result in a feedback loop (i.e. it * will end up returning FR_AUTH) then return FR_BLOCK instead. */ -int fr_checkauth(ip, fin) +u_32_t fr_checkauth(ip, fin) ip_t *ip; fr_info_t *fin; { @@ -185,29 +198,27 @@ * If we do, store it and wake up any user programs which are waiting to * hear about these events. */ -int fr_newauth(m, fin, ip -#if defined(_KERNEL) && SOLARIS -, qif) -qif_t *qif; -#else -) -#endif +int fr_newauth(m, fin, ip) mb_t *m; fr_info_t *fin; ip_t *ip; { +#if defined(_KERNEL) && SOLARIS + qif_t *qif = fin->fin_qif; +#endif int i; WRITE_ENTER(&ipf_auth); - if ((fr_authstart > fr_authend) && (fr_authstart - fr_authend == -1)) { - fr_authstats.fas_nospace++; - RWLOCK_EXIT(&ipf_auth); - return 0; - } - if (fr_authend - fr_authstart == FR_NUMAUTH - 1) { + if (fr_authstart > fr_authend) { fr_authstats.fas_nospace++; RWLOCK_EXIT(&ipf_auth); return 0; + } else { + if ((fr_authstart == 0) && (fr_authend == FR_NUMAUTH - 1)) { + fr_authstats.fas_nospace++; + RWLOCK_EXIT(&ipf_auth); + return 0; + } } fr_authstats.fas_added++; @@ -304,24 +315,27 @@ KFREE(fae); } } else { - KMALLOC(fae, frauthent_t *, sizeof(*fae)); + KMALLOC(fae, frauthent_t *); if (fae != NULL) { IRCOPY((char *)data, (char *)&fae->fae_fr, sizeof(fae->fae_fr)); WRITE_ENTER(&ipf_auth); - if (!fae->fae_age) - fae->fae_age = fr_defaultauthage; + fae->fae_age = fr_defaultauthage; fae->fae_fr.fr_hits = 0; fae->fae_fr.fr_next = *frptr; *frptr = &fae->fae_fr; fae->fae_next = *faep; *faep = fae; + ipauth = &fae_list->fae_fr; RWLOCK_EXIT(&ipf_auth); } else error = ENOMEM; } break; case SIOCATHST: + READ_ENTER(&ipf_auth); + fr_authstats.fas_faelist = fae_list; + RWLOCK_EXIT(&ipf_auth); IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats)); break; case SIOCAUTHW: @@ -381,7 +395,12 @@ # if SOLARIS error = fr_qout(fr_auth[i].fra_q, m); # else /* SOLARIS */ +# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, + NULL); +# else error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); +# endif # endif /* SOLARIS */ if (error) fr_authstats.fas_sendfail++; @@ -471,6 +490,7 @@ *faep = fae->fae_next; KFREE(fae); } + ipauth = NULL; RWLOCK_EXIT(&ipf_auth); } @@ -502,13 +522,14 @@ } for (faep = &fae_list; (fae = *faep); ) { - if (!--fra->fra_age) { + if (!--fae->fae_age) { *faep = fae->fae_next; KFREE(fae); fr_authstats.fas_expire++; } else faep = &fae->fae_next; } + ipauth = &fae_list->fae_fr; RWLOCK_EXIT(&ipf_auth); SPL_X(s); } Index: sys/netinet/ip_auth.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_auth.h,v retrieving revision 1.3 retrieving revision 1.8 diff -u -r1.3 -r1.8 --- sys/netinet/ip_auth.h 1999/02/05 05:58:50 1.3 +++ sys/netinet/ip_auth.h 2000/05/24 21:59:11 1.8 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_auth.h,v 1.3 1999/02/05 05:58:50 deraadt Exp $ */ +/* $OpenBSD: ip_auth.h,v 1.8 2000/05/24 21:59:11 kjell Exp $ */ + /* * Copyright (C) 1997-1998 by Darren Reed & Guido Van Rooij. * @@ -6,7 +7,7 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * $Id: ip_auth.h,v 1.3 1999/02/05 05:58:50 deraadt Exp $ + * $IPFilter: ip_auth.h,v 2.1.2.1 2000/05/22 06:57:47 darrenr Exp $ * */ #ifndef __IP_AUTH_H__ @@ -14,18 +15,6 @@ #define FR_NUMAUTH 32 -typedef struct fr_authstat { - U_QUAD_T fas_hits; - U_QUAD_T fas_miss; - u_long fas_nospace; - u_long fas_added; - u_long fas_sendfail; - u_long fas_sendok; - u_long fas_queok; - u_long fas_quefail; - u_long fas_expire; -} fr_authstat_t; - typedef struct frauth { int fra_age; int fra_index; @@ -42,6 +31,19 @@ u_long fae_age; } frauthent_t; +typedef struct fr_authstat { + U_QUAD_T fas_hits; + U_QUAD_T fas_miss; + u_long fas_nospace; + u_long fas_added; + u_long fas_sendfail; + u_long fas_sendok; + u_long fas_queok; + u_long fas_quefail; + u_long fas_expire; + frauthent_t *fas_faelist; +} fr_authstat_t; + extern frentry_t *ipauth; extern struct fr_authstat fr_authstats; @@ -50,15 +52,11 @@ extern int fr_authend; extern int fr_authsize; extern int fr_authused; -extern int fr_checkauth __P((ip_t *, fr_info_t *)); +extern u_32_t fr_checkauth __P((ip_t *, fr_info_t *)); extern void fr_authexpire __P((void)); extern void fr_authunload __P((void)); extern mb_t *fr_authpkts[]; -#if defined(_KERNEL) && SOLARIS -extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *, qif_t *)); -#else extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *)); -#endif #if defined(__NetBSD__) || defined(__OpenBSD__) extern int fr_auth_ioctl __P((caddr_t, u_long, frentry_t *, frentry_t **)); #else Index: sys/netinet/ip_fil_compat.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_fil_compat.h,v retrieving revision 1.10 retrieving revision 1.16 diff -u -r1.10 -r1.16 --- sys/netinet/ip_fil_compat.h 1999/02/05 05:58:51 1.10 +++ sys/netinet/ip_fil_compat.h 2000/05/01 06:16:47 1.16 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_fil_compat.h,v 1.10 1999/02/05 05:58:51 deraadt Exp $ */ +/* $OpenBSD: ip_fil_compat.h,v 1.16 2000/05/01 06:16:47 kjell Exp $ */ + /* * Copyright (C) 1993-1998 by Darren Reed. * @@ -7,7 +8,7 @@ * to the original author and the contributors. * * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_fil_compat.h,v 1.10 1999/02/05 05:58:51 deraadt Exp $ + * $IPFilter: ip_compat.h,v 2.1.2.6 2000/04/25 16:21:11 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -18,9 +19,12 @@ # define __P(x) x # else # define __P(x) () -# define const # endif #endif +#ifndef __STDC__ +# undef const +# define const +#endif #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) @@ -73,6 +77,7 @@ #endif #if SOLARIS # define MTYPE(m) ((m)->b_datap->db_type) +# include # include # include # include @@ -87,15 +92,30 @@ # ifndef KERNEL # define _KERNEL # undef RES_INIT +# if SOLARIS2 >= 8 +# include +# endif # include # include # include # undef _KERNEL # else /* _KERNEL */ +# if SOLARIS2 >= 8 +# include +# endif # include # include # include # endif /* _KERNEL */ +# if SOLARIS2 >= 8 +# define ipif_local_addr ipif_lcl_addr +/* Only defined in private include file */ +# define V4_PART_OF_V6(v6) v6.s6_addr32[3] +# endif +#else +# if !defined(__sgi) +typedef int minor_t; +#endif #endif /* SOLARIS */ #define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) @@ -122,7 +142,7 @@ /* * Really, any arch where sizeof(long) != sizeof(int). */ -# if defined(__alpha__) || defined(__alpha) +# if defined(__alpha__) || defined(__alpha) || defined(_LP64) typedef unsigned int u_32_t; # else typedef unsigned long u_32_t; @@ -190,7 +210,7 @@ #define IPOPT_FINN 205 /* FINN */ -#if defined(__FreeBSD__) && defined(KERNEL) +#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL)) # if __FreeBSD__ < 3 # include # endif @@ -214,6 +234,10 @@ # define KRWLOCK_T krwlock_t # define READ_ENTER(x) rw_enter(x, RW_READER) # define WRITE_ENTER(x) rw_enter(x, RW_WRITER) +# define RW_UPGRADE(x) { if (rw_tryupgrade(x) == 0) { \ + rw_exit(x); \ + rw_enter(x, RW_WRITER); } \ + } # define MUTEX_DOWNGRADE(x) rw_downgrade(x) # define RWLOCK_INIT(x, y, z) rw_init((x), (y), RW_DRIVER, (z)) # define RWLOCK_EXIT(x) rw_exit(x) @@ -242,7 +266,8 @@ # define htons(x) (x) # define htonl(x) (x) # endif /* sparc */ -# define KMALLOC(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) +# define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) +# define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) # define GET_MINOR(x) getminor(x) typedef struct qif { struct qif *qf_next; @@ -258,18 +283,20 @@ struct qinit qf_rqinit; mblk_t *qf_m; /* These three fields are for passing data up from */ queue_t *qf_q; /* fr_qin and fr_qout to the packet processing. */ - int qf_off; - int qf_len; /* this field is used for in ipfr_fastroute */ + size_t qf_off; + size_t qf_len; /* this field is used for in ipfr_fastroute */ char qf_name[8]; /* * in case the ILL has disappeared... */ - int qf_hl; /* header length */ + size_t qf_hl; /* header length */ } qif_t; extern ill_t *get_unit __P((char *)); # define GETUNIT(n) get_unit((n)) +# define IFNAME(x) ((ill_t *)x)->ill_name # else /* SOLARIS */ # if defined(__sgi) +# define hz HZ # include # define IPF_LOCK_PL plhi # include @@ -286,6 +313,7 @@ # define KRWLOCK_T kmutex_t # define READ_ENTER(x) MUTEX_ENTER(x) # define WRITE_ENTER(x) MUTEX_ENTER(x) +# define RW_UPGRADE(x) ; # define MUTEX_DOWNGRADE(x) ; # define RWLOCK_EXIT(x) MUTEX_EXIT(x) # define MUTEX_EXIT(x) UNLOCK((x)->l, (x)->pl); @@ -295,6 +323,7 @@ # define MUTEX_ENTER(x) ; # define READ_ENTER(x) ; # define WRITE_ENTER(x) ; +# define RW_UPGRADE(x) ; # define MUTEX_DOWNGRADE(x) ; # define RWLOCK_EXIT(x) ; # define MUTEX_EXIT(x) ; @@ -311,10 +340,17 @@ # if !SOLARIS # include # define GETUNIT(n) ifunit((n), IFNAMSIZ) +# define IFNAME(x) ((struct ifnet *)x)->if_name # endif # else # ifndef linux # define GETUNIT(n) ifunit((n)) +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) +# define IFNAME(x) ((struct ifnet *)x)->if_xname +# else +# define IFNAME(x) ((struct ifnet *)x)->if_name +# endif # endif # endif /* sun */ @@ -331,11 +367,14 @@ # ifdef __sgi # include # include -# define KMALLOC(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) +# define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) +# define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) # define GET_MINOR(x) getminor(x) # else # if !SOLARIS -# define KMALLOC(a,b,c) (a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP) +# define KMALLOC(a,b) (a) = (b)new_kmem_alloc(sizeof(*(a)), \ + KMEM_NOSLEEP) +# define KMALLOCS(a,b,c) (a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP) # endif /* SOLARIS */ # endif /* __sgi */ # endif /* sun && !linux */ @@ -352,11 +391,13 @@ # include # endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ # ifdef M_PFIL -# define KMALLOC(a, b, c) MALLOC((a), b, (c), M_PFIL, M_NOWAIT) +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFIL, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFIL, M_NOWAIT) # define KFREE(x) FREE((x), M_PFIL) # define KFREES(x,s) FREE((x), M_PFIL) # else -# define KMALLOC(a, b, c) MALLOC((a), b, (c), M_TEMP, M_NOWAIT) +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, M_NOWAIT) # define KFREE(x) FREE((x), M_TEMP) # define KFREES(x,s) FREE((x), M_TEMP) # endif /* M_PFIL */ @@ -384,6 +425,7 @@ # define MUTEX_ENTER(x) ; # define READ_ENTER(x) ; # define WRITE_ENTER(x) ; +# define RW_UPGRADE(x) ; # define MUTEX_DOWNGRADE(x) ; # define RWLOCK_EXIT(x) ; # define MUTEX_EXIT(x) ; @@ -391,7 +433,8 @@ # define SPL_IMP(x) ; # undef SPL_X # define SPL_X(x) ; -# define KMALLOC(a,b,c) (a) = (b)malloc(c) +# define KMALLOC(a,b) (a) = (b)malloc(sizeof(*a)) +# define KMALLOCS(a,b,c) (a) = (b)malloc(c) # define KFREE(x) free(x) # define KFREES(x,s) free(x) # define GETUNIT(x) get_unit(x) @@ -401,6 +444,15 @@ #if SOLARIS typedef mblk_t mb_t; +# if SOLARIS2 >= 7 +# ifdef lint +# define ALIGN32(ptr) (ptr ? 0L : 0L) +# define ALIGN16(ptr) (ptr ? 0L : 0L) +# else +# define ALIGN32(ptr) (ptr) +# define ALIGN16(ptr) (ptr) +# endif +# endif #else # ifdef linux # ifndef kernel @@ -619,8 +671,8 @@ __u8 ip_hl:4; __u8 ip_v:4; # else - __u8 ip_hl:4; __u8 ip_v:4; + __u8 ip_hl:4; # endif __u8 ip_tos; __u16 ip_len; @@ -727,7 +779,8 @@ # define UNITNAME(n) dev_get((n)) -# define KMALLOC(a,b,c) (a) = (b)kmalloc((c), GFP_ATOMIC) +# define KMALLOC(a,b) (a) = (b)kmalloc(sizeof(*(a)), GFP_ATOMIC) +# define KMALLOCS(a,b,c) (a) = (b)kmalloc((c), GFP_ATOMIC) # define KFREE(x) kfree_s((x), sizeof(*(x))) # define KFREES(x,s) kfree_s((x), (s)) # define IRCOPY(a,b,c) { \ @@ -791,7 +844,9 @@ * another IP header and then 64 bits of data, totalling 56. Of course, * the last 64 bits is dependant on that being available. */ -#define ICMPERR_MINPKTLEN (20 + 8 + 20) -#define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) +#define ICMPERR_ICMPHLEN 8 +#define ICMPERR_IPICMPHLEN (20 + 8) +#define ICMPERR_MINPKTLEN (20 + 8 + 20) +#define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) #endif /* __IP_COMPAT_H__ */ Index: sys/netinet/ip_fil.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_fil.h,v retrieving revision 1.12 retrieving revision 1.20 diff -u -r1.12 -r1.20 --- sys/netinet/ip_fil.h 1999/02/05 05:58:50 1.12 +++ sys/netinet/ip_fil.h 2000/05/24 21:59:11 1.20 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_fil.h,v 1.12 1999/02/05 05:58:50 deraadt Exp $ */ +/* $OpenBSD: ip_fil.h,v 1.20 2000/05/24 21:59:11 kjell Exp $ */ + /* * Copyright (C) 1993-1998 by Darren Reed. * @@ -7,16 +8,12 @@ * to the original author and the contributors. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_fil.h,v 1.12 1999/02/05 05:58:50 deraadt Exp $ + * $IPFilter: ip_fil.h,v 2.3.2.11 2000/05/22 06:57:50 darrenr Exp $ */ #ifndef __IP_FIL_H__ #define __IP_FIL_H__ -#if defined(__NetBSD__) && defined(PFIL_HOOKS) -#include "opt_pfil_hooks.h" -#endif - /* * Pathnames for various IP Filter control devices. Used by LKM * and userland, so defined here. @@ -26,11 +23,11 @@ #define IPAUTH_NAME "/dev/ipauth" #ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif #if defined(KERNEL) && !defined(_KERNEL) -#define _KERNEL +# define _KERNEL #endif #ifndef __P @@ -42,45 +39,45 @@ #endif #if defined(__STDC__) || defined(__GNUC__) -#define SIOCADAFR _IOW('r', 60, struct frentry) -#define SIOCRMAFR _IOW('r', 61, struct frentry) -#define SIOCSETFF _IOW('r', 62, u_int) -#define SIOCGETFF _IOR('r', 63, u_int) -#define SIOCGETFS _IOR('r', 64, struct friostat) -#define SIOCIPFFL _IOWR('r', 65, int) -#define SIOCIPFFB _IOR('r', 66, int) -#define SIOCADIFR _IOW('r', 67, struct frentry) -#define SIOCRMIFR _IOW('r', 68, struct frentry) -#define SIOCSWAPA _IOR('r', 69, u_int) -#define SIOCINAFR _IOW('r', 70, struct frentry) -#define SIOCINIFR _IOW('r', 71, struct frentry) -#define SIOCFRENB _IOW('r', 72, u_int) -#define SIOCFRSYN _IOW('r', 73, u_int) -#define SIOCFRZST _IOWR('r', 74, struct friostat) -#define SIOCZRLST _IOWR('r', 75, struct frentry) -#define SIOCAUTHW _IOWR('r', 76, struct fr_info) -#define SIOCAUTHR _IOWR('r', 77, struct fr_info) -#define SIOCATHST _IOWR('r', 78, struct fr_authstat) +# define SIOCADAFR _IOW('r', 60, struct frentry) +# define SIOCRMAFR _IOW('r', 61, struct frentry) +# define SIOCSETFF _IOW('r', 62, u_int) +# define SIOCGETFF _IOR('r', 63, u_int) +# define SIOCGETFS _IOR('r', 64, struct friostat) +# define SIOCIPFFL _IOWR('r', 65, int) +# define SIOCIPFFB _IOR('r', 66, int) +# define SIOCADIFR _IOW('r', 67, struct frentry) +# define SIOCRMIFR _IOW('r', 68, struct frentry) +# define SIOCSWAPA _IOR('r', 69, u_int) +# define SIOCINAFR _IOW('r', 70, struct frentry) +# define SIOCINIFR _IOW('r', 71, struct frentry) +# define SIOCFRENB _IOW('r', 72, u_int) +# define SIOCFRSYN _IOW('r', 73, u_int) +# define SIOCFRZST _IOWR('r', 74, struct friostat) +# define SIOCZRLST _IOWR('r', 75, struct frentry) +# define SIOCAUTHW _IOWR('r', 76, struct fr_info) +# define SIOCAUTHR _IOWR('r', 77, struct fr_info) +# define SIOCATHST _IOWR('r', 78, struct fr_authstat) #else -#define SIOCADAFR _IOW(r, 60, struct frentry) -#define SIOCRMAFR _IOW(r, 61, struct frentry) -#define SIOCSETFF _IOW(r, 62, u_int) -#define SIOCGETFF _IOR(r, 63, u_int) -#define SIOCGETFS _IOR(r, 64, struct friostat) -#define SIOCIPFFL _IOWR(r, 65, int) -#define SIOCIPFFB _IOR(r, 66, int) -#define SIOCADIFR _IOW(r, 67, struct frentry) -#define SIOCRMIFR _IOW(r, 68, struct frentry) -#define SIOCSWAPA _IOR(r, 69, u_int) -#define SIOCINAFR _IOW(r, 70, struct frentry) -#define SIOCINIFR _IOW(r, 71, struct frentry) -#define SIOCFRENB _IOW(r, 72, u_int) -#define SIOCFRSYN _IOW(r, 73, u_int) -#define SIOCFRZST _IOWR(r, 74, struct friostat) -#define SIOCZRLST _IOWR(r, 75, struct frentry) -#define SIOCAUTHW _IOWR(r, 76, struct fr_info) -#define SIOCAUTHR _IOWR(r, 77, struct fr_info) -#define SIOCATHST _IOWR(r, 78, struct fr_authstat) +# define SIOCADAFR _IOW(r, 60, struct frentry) +# define SIOCRMAFR _IOW(r, 61, struct frentry) +# define SIOCSETFF _IOW(r, 62, u_int) +# define SIOCGETFF _IOR(r, 63, u_int) +# define SIOCGETFS _IOR(r, 64, struct friostat) +# define SIOCIPFFL _IOWR(r, 65, int) +# define SIOCIPFFB _IOR(r, 66, int) +# define SIOCADIFR _IOW(r, 67, struct frentry) +# define SIOCRMIFR _IOW(r, 68, struct frentry) +# define SIOCSWAPA _IOR(r, 69, u_int) +# define SIOCINAFR _IOW(r, 70, struct frentry) +# define SIOCINIFR _IOW(r, 71, struct frentry) +# define SIOCFRENB _IOW(r, 72, u_int) +# define SIOCFRSYN _IOW(r, 73, u_int) +# define SIOCFRZST _IOWR(r, 74, struct friostat) +# define SIOCZRLST _IOWR(r, 75, struct frentry) +# define SIOCAUTHW _IOWR(r, 76, struct fr_info) +# define SIOCAUTHR _IOWR(r, 77, struct fr_info) +# define SIOCATHST _IOWR(r, 78, struct fr_authstat) #endif #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR @@ -103,32 +100,43 @@ #define FI_TCPUDP (FF_TCPUDP >> 24) /* TCP/UCP implied comparison*/ #define FI_FRAG (FF_FRAG >> 24) #define FI_SHORT (FF_SHORT >> 24) +#define FI_CMP (FI_OPTIONS|FI_TCPUDP|FI_SHORT) + +/* + * These are both used by the state and NAT code to indicate that one port or + * the other should be treated as a wildcard. + */ +#define FI_W_SPORT 0x00000100 +#define FI_W_DPORT 0x00000200 +#define FI_WILD (FI_W_SPORT|FI_W_DPORT) typedef struct fr_info { + void *fin_ifp; /* interface packet is `on' */ struct fr_ip fin_fi; /* IP Packet summary */ u_short fin_data[2]; /* TCP/UDP ports, ICMP code/type */ - u_short fin_out; /* in or out ? 1 == out, 0 == in */ + u_char fin_out; /* in or out ? 1 == out, 0 == in */ + u_char fin_rev; /* state only: 1 = reverse */ u_short fin_hlen; /* length of IP header in bytes */ u_char fin_tcpf; /* TCP header flags (SYN, ACK, etc) */ /* From here on is packet specific */ u_char fin_icode; /* ICMP error to return */ u_short fin_rule; /* rule # last matched */ u_short fin_group; /* group number, -1 for none */ - u_short fin_dlen; /* length of data portion of packet */ - u_short fin_id; /* IP packet id field */ - void *fin_ifp; /* interface packet is `on' */ struct frentry *fin_fr; /* last matching rule */ char *fin_dp; /* start of data past IP header */ + u_short fin_dlen; /* length of data portion of packet */ + u_short fin_id; /* IP packet id field */ void *fin_mp; /* pointer to pointer to mbuf */ #if SOLARIS && defined(_KERNEL) void *fin_qfm; /* pointer to mblk where pkt starts */ + void *fin_qif; #endif } fr_info_t; /* * Size for compares on fr_info structures */ -#define FI_CSIZE offsetof(fr_info_t, fin_icode) +#define FI_CSIZE offsetof(fr_info_t, fin_icode) /* * Size for copying cache fr_info structure @@ -148,6 +156,9 @@ struct frentry *fr_grp; int fr_ref; /* reference count - for grouping */ void *fr_ifa; +#if BSD >= 199306 + void *fr_oifa; +#endif /* * These are only incremented when a packet matches this rule and * it is the last match @@ -173,10 +184,14 @@ u_short fr_stop; /* top port for <> and >< */ u_short fr_dtop; /* top port for <> and >< */ u_32_t fr_flags; /* per-rule flags && options (see below) */ - int fr_skip; /* # of rules to skip */ + u_short fr_skip; /* # of rules to skip */ + u_short fr_loglevel; /* syslog log facility + priority */ int (*fr_func) __P((int, ip_t *, fr_info_t *)); /* call this function */ - char fr_icode; /* return ICMP code */ + u_char fr_icode; /* return ICMP code */ char fr_ifname[IFNAMSIZ]; +#if BSD >= 199306 + char fr_oifname[IFNAMSIZ]; +#endif struct frdest fr_tif; /* "to" interface */ struct frdest fr_dif; /* duplicate packet interfaces */ } frentry_t; @@ -208,6 +223,7 @@ #define FR_LOGFIRST 0x00040 /* Log the first byte if state held */ #define FR_RETRST 0x00080 /* Return TCP RST packet - reset connection */ #define FR_RETICMP 0x00100 /* Return ICMP unreachable packet */ +#define FR_FAKEICMP 0x00180 /* Return ICMP unreachable with fake source */ #define FR_NOMATCH 0x00200 /* no match occured */ #define FR_ACCOUNT 0x00400 /* count packet bytes */ #define FR_KEEPFRAG 0x00800 /* keep fragment information */ @@ -222,8 +238,10 @@ #define FR_NOTDSTIP 0x100000 /* not the dst IP# */ #define FR_AUTH 0x200000 /* use authentication */ #define FR_PREAUTH 0x400000 /* require preauthentication */ +#define FR_DONTCACHE 0x800000 /* don't cache the result */ #define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB) +#define FR_RETMASK (FR_RETICMP|FR_RETRST|FR_FAKEICMP) /* * These correspond to #define's for FI_* and are stored in fr_flags @@ -255,6 +273,7 @@ u_long fr_pass; /* packets allowed */ u_long fr_block; /* packets denied */ u_long fr_nom; /* packets which don't match any rule */ + u_long fr_short; /* packets which are short */ u_long fr_ppkl; /* packets allowed and logged */ u_long fr_bpkl; /* packets denied and logged */ u_long fr_npkl; /* packets unmatched and logged */ @@ -276,6 +295,7 @@ u_long fr_bad; /* bad IP packets to the filter */ u_long fr_notip; /* packets passed through no on ip queue */ u_long fr_drop; /* packets dropped - no info for them! */ + u_long fr_copy; /* messages copied due to db_ref > 1 */ #endif } filterstats_t; @@ -289,8 +309,17 @@ struct frentry *f_acctin[2]; struct frentry *f_acctout[2]; struct frentry *f_auth; + struct frgroup *f_groups[3][2]; u_long f_froute[2]; - int f_active; + int f_defpass; /* default pass - from fr_pass */ + char f_active; /* 1 or 0 - active rule set */ + char f_running; /* 1 if running, else 0 */ + char f_logging; /* 1 if enabled, else 0 */ +#if !SOLARIS && defined(sun) + char f_version[17]; /* version string */ +#else + char f_version[32]; /* version string */ +#endif } friostat_t; typedef struct optlist { @@ -316,11 +345,10 @@ * structure which is then followed by any packet data. */ typedef struct iplog { - u_long ipl_magic; + u_32_t ipl_magic; + u_int ipl_count; u_long ipl_sec; u_long ipl_usec; - u_int ipl_len; - u_int ipl_count; size_t ipl_dsize; struct iplog *ipl_next; } iplog_t; @@ -339,7 +367,9 @@ u_char fl_hlen; /* length of IP headers saved */ u_short fl_rule; /* assume never more than 64k rules, total */ u_short fl_group; + u_short fl_loglevel; /* syslog log level */ u_32_t fl_flags; + u_32_t fl_lflags; } ipflog_t; @@ -352,7 +382,6 @@ #ifndef IPF_LOGGING # define IPF_LOGGING 0 #endif - #ifndef IPF_DEFAULT_PASS # define IPF_DEFAULT_PASS FR_PASS #endif @@ -386,16 +415,32 @@ # define CDEV_MAJOR 79 #endif +/* + * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns + * on those hooks. We don't need any special mods in non-IP Filter code + * with this! + */ +#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \ + (defined(NetBSD1_2) && NetBSD1_2 > 1) +# if (NetBSD >= 199905) +# define PFIL_HOOKS +# endif +# ifdef PFIL_HOOKS +# define NETBSD_PF +# endif +#endif + + #ifndef _KERNEL extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); extern int send_reset __P((ip_t *, struct ifnet *)); extern int icmp_error __P((ip_t *, struct ifnet *)); extern int ipf_log __P((void)); -extern void ipfr_fastroute __P((ip_t *, fr_info_t *, frdest_t *)); +extern int ipfr_fastroute __P((ip_t *, fr_info_t *, frdest_t *)); extern struct ifnet *get_unit __P((char *)); -# define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m) -# if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701) +# if defined(__NetBSD__) || defined(__OpenBSD__) || \ + (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) extern int iplioctl __P((dev_t, u_long, caddr_t, int)); # else extern int iplioctl __P((dev_t, int, caddr_t, int)); @@ -404,39 +449,34 @@ extern int iplclose __P((dev_t, int)); #else /* #ifndef _KERNEL */ # if defined(__NetBSD__) && defined(PFIL_HOOKS) -extern int ipfilterattach __P((int)); +extern void ipfilterattach __P((int)); # endif - -#if !defined(__OpenBSD__) -/* - * OpenBSD has this call in the kernel but doesn't export it to userland. - * See ip_fil.c for actual hook and more details. - */ extern int iplattach __P((void)); -#endif - extern int ipl_enable __P((void)); extern int ipl_disable __P((void)); extern void ipflog_init __P((void)); -extern int ipflog_clear __P((int)); -extern int ipflog_read __P((int, struct uio *)); +extern int ipflog_clear __P((minor_t)); +extern int ipflog_read __P((minor_t, struct uio *)); extern int ipflog __P((u_int, ip_t *, fr_info_t *, mb_t *)); -extern int ipllog __P((int, u_long, void **, size_t *, int *, int)); +extern int ipllog __P((int, fr_info_t *, void **, size_t *, int *, int)); +extern int send_icmp_err __P((ip_t *, int, fr_info_t *, struct in_addr)); +extern int send_reset __P((ip_t *, fr_info_t *)); # if SOLARIS extern int fr_check __P((ip_t *, int, void *, int, qif_t *, mb_t **)); extern int (*fr_checkp) __P((ip_t *, int, void *, int, qif_t *, mb_t **)); -extern int icmp_error __P((ip_t *, int, int, qif_t *, - struct in_addr)); -extern int iplioctl __P((dev_t, int, int, int, cred_t *, int *)); +# if SOLARIS2 >= 7 +extern int iplioctl __P((dev_t, int, intptr_t, int, cred_t *, int *)); +# else +extern int iplioctl __P((dev_t, int, int *, int, cred_t *, int *)); +# endif extern int iplopen __P((dev_t *, int, int, cred_t *)); extern int iplclose __P((dev_t, int, int, cred_t *)); extern int ipfsync __P((void)); -extern int send_reset __P((ip_t *, qif_t *)); extern int ipfr_fastroute __P((qif_t *, ip_t *, mblk_t *, mblk_t **, fr_info_t *, frdest_t *)); -extern void copyin_mblk __P((mblk_t *, int, int, char *)); -extern void copyout_mblk __P((mblk_t *, int, int, char *)); +extern void copyin_mblk __P((mblk_t *, size_t, size_t, char *)); +extern void copyout_mblk __P((mblk_t *, size_t, size_t, char *)); extern int fr_qin __P((queue_t *, mblk_t *)); extern int fr_qout __P((queue_t *, mblk_t *)); # ifdef IPFILTER_LOG @@ -445,12 +485,7 @@ # else /* SOLARIS */ extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); -# ifdef linux -extern int send_reset __P((tcpiphdr_t *, struct ifnet *)); -# else -extern int send_reset __P((tcpiphdr_t *)); -# endif -extern void ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *)); +extern int ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *)); extern size_t mbufchainlen __P((mb_t *)); # ifdef __sgi # include @@ -468,67 +503,65 @@ # endif # if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 220000) || \ (NetBSD >= 199511) || defined(__OpenBSD__) -# if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || defined(__OpenBSD__) +# if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \ + defined(__OpenBSD__) || (__FreeBSD_version >= 300000) extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -# else /* FreeBSD v2.2+ or BSDI >= 199510 and < 199701 */ +# else extern int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); -# endif /* NetBSD, modern BSDI and OpenBSD */ +# endif extern int iplopen __P((dev_t, int, int, struct proc *)); extern int iplclose __P((dev_t, int, int, struct proc *)); -# else /* everybody else */ -# ifdef linux -extern int iplioctl(struct inode *, struct file *, u_int, u_long); -extern int iplopen __P((struct inode *, struct file *)); -extern void iplclose __P((struct inode *, struct file *)); - else -extern int iplioctl __P((dev_t, int, caddr_t, int)); +# else +# ifndef linux extern int iplopen __P((dev_t, int)); extern int iplclose __P((dev_t, int)); -# endif /* linux */ +extern int iplioctl __P((dev_t, int, caddr_t, int)); +# else +extern int iplioctl(struct inode *, struct file *, u_int, u_long); +extern int iplopen __P((struct inode *, struct file *)); +extern void iplclose __P((struct inode *, struct file *)); +# endif /* !linux */ # endif /* (_BSDI_VERSION >= 199510) */ # if BSD >= 199306 extern int iplread __P((dev_t, struct uio *, int)); # else -# ifdef linux -extern int iplread(struct inode *, struct file *, char *, int); - else +# ifndef linux extern int iplread __P((dev_t, struct uio *)); -# endif /* linux */ +# else +extern int iplread(struct inode *, struct file *, char *, int); +# endif /* !linux */ # endif /* BSD >= 199306 */ # endif /* __ sgi */ # endif /* SOLARIS */ #endif /* #ifndef _KERNEL */ - -/* - * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns - * on those hooks. We don't need any special mods in non-IP Filter code - * with this! - */ -#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \ - (defined(NetBSD1_2) && NetBSD1_2 > 1) -# define NETBSD_PF -#endif +extern void fixskip __P((frentry_t **, frentry_t *, int)); +extern int countbits __P((u_32_t)); extern int ipldetach __P((void)); -extern u_short fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *, int)); -#define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m) -extern int fr_scanlist __P((int, ip_t *, fr_info_t *, void *)); +extern u_short fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *)); +extern int fr_scanlist __P((u_32_t, ip_t *, fr_info_t *, void *)); extern u_short ipf_cksum __P((u_short *, int)); extern int fr_copytolog __P((int, char *, int)); -extern void frflush __P((int, int *)); -extern frgroup_t *fr_addgroup __P((u_short, frentry_t *, int, int)); -extern frgroup_t *fr_findgroup __P((u_short, u_32_t, int, int, frgroup_t ***)); -extern void fr_delgroup __P((u_short, u_32_t, int, int)); +extern void fr_forgetifp __P((void *)); +extern int frflush __P((minor_t, int)); +extern void frsync __P((void)); +extern frgroup_t *fr_addgroup __P((u_int, frentry_t *, minor_t, int)); +extern frgroup_t *fr_findgroup __P((u_int, u_32_t, minor_t, int, frgroup_t ***)); +extern void fr_delgroup __P((u_int, u_32_t, minor_t, int)); +extern void fr_makefrip __P((int, ip_t *, fr_info_t *)); +extern int fr_ifpaddr __P((void *, struct in_addr *)); +extern char *memstr __P((char *, char *, int, int)); extern int ipl_unreach; -extern int ipl_inited; +extern int fr_running; extern u_long ipl_frouteok[2]; extern int fr_pass; extern int fr_flags; extern int fr_active; extern fr_info_t frcache[2]; +extern char ipfilter_version[]; #ifdef IPFILTER_LOG extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; -extern int iplused[IPL_LOGMAX + 1]; +extern size_t iplused[IPL_LOGMAX + 1]; #endif extern struct frentry *ipfilter[2][2], *ipacct[2][2]; extern struct frgroup *ipfgroups[3][2]; Index: sys/netinet/ip_fil.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_fil.c,v retrieving revision 1.24 retrieving revision 1.35 diff -u -r1.24 -r1.35 --- sys/netinet/ip_fil.c 1999/06/07 22:00:32 1.24 +++ sys/netinet/ip_fil.c 2000/05/24 21:59:11 1.35 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_fil.c,v 1.24 1999/06/07 22:00:32 deraadt Exp $ */ +/* $OpenBSD: ip_fil.c,v 1.35 2000/05/24 21:59:11 kjell Exp $ */ + /* * Copyright (C) 1993-1998 by Darren Reed. * @@ -8,7 +9,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.24 1999/06/07 22:00:32 deraadt Exp $"; +static const char rcsid[] = "@(#)$IPFilter: ip_fil.c,v 2.4.2.21 2000/05/22 06:57:47 darrenr Exp $"; #endif #ifndef SOLARIS @@ -18,6 +19,11 @@ #if defined(KERNEL) && !defined(_KERNEL) # define _KERNEL #endif +#include +#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ + defined(_KERNEL) +# include "opt_ipfilter_log.h" +#endif #ifdef __FreeBSD__ # if defined(_KERNEL) && !defined(IPFILTER_LKM) # include @@ -30,10 +36,10 @@ # include # include # include +# include #endif #include #include -#include #include #if __FreeBSD_version >= 220000 && defined(_KERNEL) # include @@ -47,7 +53,7 @@ #endif #include #if !SOLARIS -# if (NetBSD > 199609) || (OpenBSD > 199603) +# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) # include # else # include @@ -65,6 +71,9 @@ #endif #if __FreeBSD_version >= 300000 # include +# if defined(_KERNEL) && !defined(IPFILTER_LKM) +# include "opt_ipfilter.h" +# endif #endif #ifdef __sgi #include @@ -75,7 +84,7 @@ #include #include #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ -#include +# include #endif #include #include @@ -85,23 +94,24 @@ #include #include #ifndef _KERNEL +# include # include #endif -#if defined(__OpenBSD__) #include -#else -#include -#endif #include #include #include #include #include #include +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) +# include +#endif #ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) +# define MIN(a,b) (((a)<(b))?(a):(b)) #endif -#if !SOLARIS && defined(_KERNEL) +#if !SOLARIS && defined(_KERNEL) && !defined(__sgi) +# include extern int ip_optcopy __P((struct ip *, struct ip *)); #endif @@ -113,27 +123,20 @@ static struct ifnet **ifneta = NULL; static int nifs = 0; #else -# if (BSD < 199306) && !defined(__sgi) -static int (*fr_saveslowtimo) __P((void)); -# else -static void (*fr_saveslowtimo) __P((void)); -# endif # if (BSD < 199306) || defined(__sgi) extern int tcp_ttl; # endif #endif -int ipl_inited = 0; -#if defined(__OpenBSD__) +# if defined (__OpenBSD__) int ipl_unreach = ICMP_UNREACH_FILTER_PROHIB; -#else +# else int ipl_unreach = ICMP_UNREACH_FILTER; -#endif +# endif + u_long ipl_frouteok[2] = {0, 0}; -static void fixskip __P((frentry_t **, frentry_t *, int)); static void frzerostats __P((caddr_t)); -static void frsync __P((void)); #if defined(__NetBSD__) || defined(__OpenBSD__) static int frrequest __P((int, u_long, caddr_t, int)); #else @@ -141,8 +144,10 @@ #endif #ifdef _KERNEL static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); +static int send_ip __P((ip_t *, fr_info_t *, struct mbuf *)); # ifdef __sgi extern kmutex_t ipf_rw; +extern KRWLOCK_T ipf_mutex; # endif #else int ipllog __P((void)); @@ -159,7 +164,12 @@ struct sockaddr *, struct rtentry *)); # endif #endif +int fr_running = 0; +#if (__FreeBSD_version >= 300000) && defined(_KERNEL) +struct callout_handle ipfr_slowtimer_ch; +#endif + #if (_BSDI_VERSION >= 199510) && defined(_KERNEL) # include # include @@ -207,61 +217,68 @@ ipfilterattach(count) int count; { - iplattach(); + if (iplattach() != 0) + printf("IP Filter failed to attach\n"); } # endif -#if defined( __OpenBSD__) -/* - * Since iplattach() is called by main() at boot time, we put in a - * fake stub so that none of the machinery is initialized till explicitly - * enabled via ipf -E. Therefore we rename the real iplattach() to - * ipl_enable(). See also skeleton iplinit() later in this file. - */ -void iplattach __P((int)); -void iplattach(int dummy) {}; -int ipl_enable() -# else int iplattach() -# endif /* OpenBSD */ { char *defpass; int s; -# ifdef __sgi - int error; +# if defined(__sgi) || (defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)) + int error = 0; # endif SPL_NET(s); - if (ipl_inited || (fr_checkp == fr_check)) { + if (fr_running || (fr_checkp == fr_check)) { printf("IP Filter: already initialized\n"); SPL_X(s); return EBUSY; } +# ifdef IPFILTER_LOG + ipflog_init(); +# endif + if (nat_init() == -1) + return -1; + if (fr_stateinit() == -1) + return -1; + if (appr_init() == -1) + return -1; + # ifdef NETBSD_PF +# if __NetBSD_Version__ >= 104200000 + error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); + if (error) { + appr_unload(); + ip_natunload(); + fr_stateunload(); + return error; + } +# else pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); +# endif # endif # ifdef __sgi error = ipfilter_sgi_attach(); if (error) { SPL_X(s); + appr_unload(); + ip_natunload(); + fr_stateunload(); return error; } # endif - ipl_inited = 1; bzero((char *)frcache, sizeof(frcache)); - bzero((char *)nat_table, sizeof(nat_table)); fr_savep = fr_checkp; fr_checkp = fr_check; - fr_saveslowtimo = inetsw[0].pr_slowtimo; - inetsw[0].pr_slowtimo = ipfr_slowtimer; + fr_running = 1; -# ifdef IPFILTER_LOG - ipflog_init(); -# endif SPL_X(s); if (fr_pass & FR_PASS) defpass = "pass"; @@ -270,6 +287,7 @@ else defpass = "no-match -> block"; +#if !defined(__OpenBSD__) printf("IP Filter: initialized. Default = %s all, Logging = %s\n", defpass, # ifdef IPFILTER_LOG @@ -277,6 +295,16 @@ # else "disabled"); # endif + printf("%s\n", ipfilter_version); +#endif + +#ifdef _KERNEL +# if (__FreeBSD_version >= 300000) && defined(_KERNEL) + ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); +# else + timeout(ipfr_slowtimer, NULL, hz/2); +# endif +#endif return 0; } @@ -285,16 +313,26 @@ * Disable the filter by removing the hooks from the IP input/output * stream. */ -# if defined(__OpenBSD__) -int ipl_disable() -# else int ipldetach() -# endif { int s, i = FR_INQUE|FR_OUTQUE; +#if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) + int error = 0; +#endif +#ifdef _KERNEL +# if (__FreeBSD_version >= 300000) + untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch); +# else +# ifdef __sgi + untimeout(ipfr_slowtimer); +# else + untimeout(ipfr_slowtimer, NULL); +# endif +# endif +#endif SPL_NET(s); - if (!ipl_inited) + if (!fr_running) { printf("IP Filter: not initialized\n"); SPL_X(s); @@ -302,18 +340,25 @@ } fr_checkp = fr_savep; - inetsw[0].pr_slowtimo = fr_saveslowtimo; - frflush(IPL_LOGIPF, &i); - ipl_inited = 0; + i = frflush(IPL_LOGIPF, i); + fr_running = 0; # ifdef NETBSD_PF +# if __NetBSD_Version__ >= 104200000 + error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); + if (error) + return error; +# else pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); +# endif # endif # ifdef __sgi ipfilter_sgi_detach(); # endif + appr_unload(); ipfr_unload(); ip_natunload(); fr_stateunload(); @@ -328,7 +373,7 @@ static void frzerostats(data) caddr_t data; { - struct friostat fio; + friostat_t fio; bcopy((char *)frstats, (char *)fio.f_st, sizeof(struct filterstats) * 2); @@ -367,7 +412,8 @@ ) #endif dev_t dev; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701) +#if defined(__NetBSD__) || defined(__OpenBSD__) || \ + (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) u_long cmd; #else int cmd; @@ -381,12 +427,17 @@ #endif int error = 0, unit = 0, tmp; +#if (BSD >= 199306) && defined(_KERNEL) + if ((securelevel >= 2) && (mode & FWRITE)) + return EPERM; +#endif #ifdef _KERNEL unit = GET_MINOR(dev); if ((IPL_LOGMAX < unit) || (unit < 0)) return ENXIO; # if defined(__OpenBSD__) + /* Prevent IPF and NAT changes when securelevel > 1 */ if (securelevel > 1) { switch (cmd) { # ifndef IPFILTER_LKM @@ -414,17 +465,26 @@ } } # endif /* OpenBSD */ -#endif /* _KERNEL */ +#else /* _KERNEL */ + unit = dev; +#endif SPL_NET(s); if (unit == IPL_LOGNAT) { - error = nat_ioctl(data, cmd, mode); + if (fr_running) + error = nat_ioctl(data, cmd, mode); + else + error = EIO; SPL_X(s); return error; } + if (unit == IPL_LOGSTATE) { - error = fr_state_ioctl(data, cmd, mode); + if (fr_running) + error = fr_state_ioctl(data, cmd, mode); + else + error = EIO; SPL_X(s); return error; } @@ -446,15 +506,9 @@ else { IRCOPY(data, (caddr_t)&enable, sizeof(enable)); if (enable) -# if defined(__OpenBSD__) - error = ipl_enable(); - else - error = ipl_disable(); -# else error = iplattach(); else error = ipldetach(); -# endif /* OpenBSD */ } break; } @@ -512,6 +566,21 @@ fio.f_active = fr_active; fio.f_froute[0] = ipl_frouteok[0]; fio.f_froute[1] = ipl_frouteok[1]; + fio.f_running = fr_running; + fio.f_groups[0][0] = ipfgroups[0][0]; + fio.f_groups[0][1] = ipfgroups[0][1]; + fio.f_groups[1][0] = ipfgroups[1][0]; + fio.f_groups[1][1] = ipfgroups[1][1]; + fio.f_groups[2][0] = ipfgroups[2][0]; + fio.f_groups[2][1] = ipfgroups[2][1]; +#ifdef IPFILTER_LOG + fio.f_logging = 1; +#else + fio.f_logging = 0; +#endif + fio.f_defpass = fr_pass; + strncpy(fio.f_version, ipfilter_version, + sizeof(fio.f_version)); IWCOPY((caddr_t)&fio, data, sizeof(fio)); break; } @@ -526,7 +595,7 @@ error = EPERM; else { IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); - frflush(unit, &tmp); + tmp = frflush(unit, tmp); IWCOPY((caddr_t)&tmp, data, sizeof(tmp)); } break; @@ -568,38 +637,27 @@ return error; } - -static void frsync() -{ -#ifdef _KERNEL - struct ifnet *ifp; - -# if defined(__OpenBSD__) || (NetBSD >= 199511) - for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) -# else - for (ifp = ifnet; ifp; ifp = ifp->if_next) -# endif - ip_natsync(ifp); -#endif -} - -static void fixskip(listp, rp, addremove) -frentry_t **listp, *rp; -int addremove; +void fr_forgetifp(ifp) +void *ifp; { - frentry_t *fp; - int rules = 0, rn = 0; + register frentry_t *f; - for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) - ; - - if (!fp) - return; - - for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) - if (fp->fr_skip && (rn + fp->fr_skip >= rules)) - fp->fr_skip += addremove; + WRITE_ENTER(&ipf_mutex); + for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) + if (f->fr_ifa == ifp) + f->fr_ifa = (void *)-1; + for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) + if (f->fr_ifa == ifp) + f->fr_ifa = (void *)-1; + for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) + if (f->fr_ifa == ifp) + f->fr_ifa = (void *)-1; + for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) + if (f->fr_ifa == ifp) + f->fr_ifa = (void *)-1; + RWLOCK_EXIT(&ipf_mutex); + ip_natsync(ifp); } @@ -618,20 +676,22 @@ frentry_t frd; frdest_t *fdp; frgroup_t *fg = NULL; - int error = 0, in, group; + int error = 0, in; + u_int group; fp = &frd; IRCOPY(data, (caddr_t)fp, sizeof(*fp)); + fp->fr_ref = 0; /* * Check that the group number does exist and that if a head group * has been specified, doesn't exist. */ - if (fp->fr_grhead && - fr_findgroup(fp->fr_grhead, fp->fr_flags, unit, set, NULL)) + if ((req != SIOCZRLST) && fp->fr_grhead && + fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL)) return EEXIST; - if (fp->fr_group && - !fr_findgroup(fp->fr_group, fp->fr_flags, unit, set, NULL)) + if ((req != SIOCZRLST) && fp->fr_group && + !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL)) return ESRCH; in = (fp->fr_flags & FR_INQUE) ? 0 : 1; @@ -658,6 +718,13 @@ if (!fp->fr_ifa) fp->fr_ifa = (void *)-1; } +#if BSD >= 199306 + if (*fp->fr_oifname) { + fp->fr_oifa = GETUNIT(fp->fr_oifname); + if (!fp->fr_oifa) + fp->fr_oifa = (void *)-1; + } +#endif fdp = &fp->fr_dif; fp->fr_flags &= ~FR_DUP; @@ -698,14 +765,14 @@ } if (!f) { - ftail = fprev; - if (req != SIOCINAFR && req != SIOCINIFR) - while ((f = *ftail)) - ftail = &f->fr_next; - else if (fp->fr_hits) - while (--fp->fr_hits && (f = *ftail)) - ftail = &f->fr_next; - f = NULL; + if (req == SIOCINAFR || req == SIOCINIFR) { + ftail = fprev; + if (fp->fr_hits) { + while (--fp->fr_hits && (f = *ftail)) + ftail = &f->fr_next; + } + f = NULL; + } } if (req == SIOCDELFR || req == SIOCRMIFR) { @@ -719,8 +786,8 @@ if (unit == IPL_LOGAUTH) return fr_auth_ioctl(data, req, f, ftail); if (f->fr_grhead) - fr_delgroup(f->fr_grhead, fp->fr_flags, unit, - set); + fr_delgroup((u_int)f->fr_grhead, fp->fr_flags, + unit, set); fixskip(fprev, f, -1); *ftail = f->fr_next; KFREE(f); @@ -730,8 +797,8 @@ error = EEXIST; else { if (unit == IPL_LOGAUTH) - return fr_auth_ioctl(data, req, f, ftail); - KMALLOC(f, frentry_t *, sizeof(*f)); + return fr_auth_ioctl(data, req, fp, ftail); + KMALLOC(f, frentry_t *); if (f != NULL) { if (fg && fg->fg_head) fg->fg_head->fr_ref++; @@ -757,33 +824,33 @@ /* * routines below for saving IP headers to buffer */ -#ifdef __sgi -# ifdef _KERNEL +# ifdef __sgi +# ifdef _KERNEL int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp) -# else +# else int IPL_EXTERN(open)(dev_t dev, int flags) -# endif -#else +# endif +# else int IPL_EXTERN(open)(dev, flags -# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ +# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL) , devtype, p) int devtype; struct proc *p; -# else +# else ) -# endif +# endif dev_t dev; int flags; -#endif /* __sgi */ +# endif /* __sgi */ { -#if defined(__sgi) && defined(_KERNEL) +# if defined(__sgi) && defined(_KERNEL) u_int min = geteminor(*pdev); -#else +# else u_int min = GET_MINOR(dev); -#endif +# endif - if (2 < min) + if (IPL_LOGMAX < min) min = ENXIO; else min = 0; @@ -791,25 +858,25 @@ } -#ifdef __sgi +# ifdef __sgi int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp) #else int IPL_EXTERN(close)(dev, flags -# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ +# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL) , devtype, p) int devtype; struct proc *p; -# else +# else ) -# endif +# endif dev_t dev; int flags; -#endif /* __sgi */ +# endif /* __sgi */ { u_int min = GET_MINOR(dev); - if (2 < min) + if (IPL_LOGMAX < min) min = ENXIO; else min = 0; @@ -822,9 +889,9 @@ * called during packet processing and cause an inconsistancy to appear in * the filter lists. */ -#ifdef __sgi +# ifdef __sgi int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp) -#else +# else # if BSD >= 199306 int IPL_EXTERN(read)(dev, uio, ioflag) int ioflag; @@ -833,13 +900,13 @@ # endif dev_t dev; register struct uio *uio; -#endif /* __sgi */ +# endif /* __sgi */ { -# ifdef IPFILTER_LOG +# ifdef IPFILTER_LOG return ipflog_read(GET_MINOR(dev), uio); -# else +# else return ENXIO; -# endif +# endif } @@ -847,77 +914,155 @@ * send_reset - this could conceivably be a call to tcp_respond(), but that * requires a large amount of setting up and isn't any more efficient. */ -int send_reset(ti) -struct tcpiphdr *ti; +int send_reset(oip, fin) +struct ip *oip; +fr_info_t *fin; { - struct tcpiphdr *tp; - struct tcphdr *tcp; + struct tcphdr *tcp, *tcp2; struct mbuf *m; - int tlen = 0, err; + int tlen = 0; ip_t *ip; -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) - struct route ro; -# endif - if (ti->ti_flags & TH_RST) + tcp = (struct tcphdr *)fin->fin_dp; + if (tcp->th_flags & TH_RST) return -1; /* feedback loop */ # if (BSD < 199306) || defined(__sgi) m = m_get(M_DONTWAIT, MT_HEADER); # else m = m_gethdr(M_DONTWAIT, MT_HEADER); - m->m_data += max_linkhdr; # endif if (m == NULL) + return ENOBUFS; + if (m == NULL) return -1; - if (ti->ti_flags & TH_SYN) + if (tcp->th_flags & TH_SYN) tlen = 1; - m->m_len = sizeof (struct tcpiphdr); + m->m_len = sizeof(*tcp2) + sizeof(*ip); # if BSD >= 199306 - m->m_pkthdr.len = sizeof (struct tcpiphdr); + m->m_data += max_linkhdr; + m->m_pkthdr.len = sizeof(*tcp2) + sizeof(*ip); m->m_pkthdr.rcvif = (struct ifnet *)0; # endif - bzero(mtod(m, char *), sizeof(struct tcpiphdr)); ip = mtod(m, struct ip *); - tp = mtod(m, struct tcpiphdr *); - tcp = (struct tcphdr *)((char *)ip + sizeof(struct ip)); + bzero((char *)ip, sizeof(*tcp2) + sizeof(*ip)); + tcp2 = (struct tcphdr *)(ip + 1); + + ip->ip_src.s_addr = oip->ip_dst.s_addr; + ip->ip_dst.s_addr = oip->ip_src.s_addr; + tcp2->th_dport = tcp->th_sport; + tcp2->th_sport = tcp->th_dport; + tcp2->th_ack = ntohl(tcp->th_seq); + tcp2->th_ack += tlen; + tcp2->th_ack = htonl(tcp2->th_ack); + tcp2->th_off = sizeof(*tcp2) >> 2; + tcp2->th_flags = TH_RST|TH_ACK; + ip->ip_p = IPPROTO_TCP; + ip->ip_len = htons(sizeof(struct tcphdr)); + tcp2->th_sum = in_cksum(m, sizeof(*ip) + sizeof(*tcp2)); + + ip->ip_id = oip->ip_id; + ip->ip_tos = oip->ip_tos; + ip->ip_len = sizeof(*ip) + sizeof(*tcp2); + + return send_ip(ip, fin, m); +} + - ip->ip_src.s_addr = ti->ti_dst.s_addr; - ip->ip_dst.s_addr = ti->ti_src.s_addr; - tcp->th_dport = ti->ti_sport; - tcp->th_sport = ti->ti_dport; - tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen); - tcp->th_off = sizeof(struct tcphdr) >> 2; - tcp->th_flags = TH_RST|TH_ACK; - tp->ti_pr = ((struct ip *)ti)->ip_p; - tp->ti_len = htons(sizeof(struct tcphdr)); - tcp->th_sum = in_cksum(m, sizeof(struct tcpiphdr)); - - ip->ip_tos = ((struct ip *)ti)->ip_tos; - ip->ip_p = ((struct ip *)ti)->ip_p; - ip->ip_len = sizeof (struct tcpiphdr); +static int send_ip(ip, fin, m) +fr_info_t *fin; +struct mbuf *m; +ip_t *ip; +{ + ip->ip_v = IPVERSION; + ip->ip_hl = (sizeof(*ip) >> 2); # if (BSD < 199306) || defined(__sgi) ip->ip_ttl = tcp_ttl; # else ip->ip_ttl = ip_defttl; # endif + +# ifdef IPSEC + m->m_pkthdr.rcvif = NULL; +# endif + return ipfr_fastroute(m, fin, NULL); +} + + +int send_icmp_err(oip, type, fin, dst) +ip_t *oip; +int type; +fr_info_t *fin; +struct in_addr dst; +{ + struct icmp *icmp; + struct mbuf *m; + ip_t *nip; + int code; + + if ((oip->ip_p == IPPROTO_ICMP) && !(fin->fin_fi.fi_fl & FI_SHORT)) + switch (ntohs(fin->fin_data[0]) >> 8) + { + case ICMP_ECHO : + case ICMP_TSTAMP : + case ICMP_IREQ : + case ICMP_MASKREQ : + break; + default : + return 0; + } -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) - bzero((char *)&ro, sizeof(ro)); - err = ip_output(m, (struct mbuf *)0, &ro, 0, 0); - if (ro.ro_rt) - RTFREE(ro.ro_rt); + code = fin->fin_icode; +# if (BSD < 199306) || defined(__sgi) + m = m_get(M_DONTWAIT, MT_HEADER); # else - /* - * extra 0 in case of multicast - */ -# ifdef __OpenBSD__ - err = ip_output(m, (struct mbuf *)0, 0, 0, 0, 0); -# else - err = ip_output(m, (struct mbuf *)0, 0, 0, 0); -# endif + m = m_gethdr(M_DONTWAIT, MT_HEADER); +# endif + if (m == NULL) + return ENOBUFS; + m->m_len = sizeof(*nip) + sizeof(*icmp) + 8; +# if BSD >= 199306 + m->m_data += max_linkhdr; + m->m_pkthdr.len = sizeof(*nip) + sizeof(*icmp) + 8; + m->m_pkthdr.rcvif = (struct ifnet *)0; +# endif + + bzero(mtod(m, char *), (size_t)sizeof(*nip) + sizeof(*icmp) + 8); + nip = mtod(m, ip_t *); + icmp = (struct icmp *)(nip + 1); + + nip->ip_p = IPPROTO_ICMP; + nip->ip_id = oip->ip_id; + nip->ip_sum = 0; + nip->ip_ttl = 60; + nip->ip_tos = oip->ip_tos; + nip->ip_len = sizeof(*nip) + sizeof(*icmp) + 8; + if (dst.s_addr == 0) { + if (fr_ifpaddr(fin->fin_ifp, &dst) == -1) + return -1; + } + nip->ip_src = dst; + nip->ip_dst = oip->ip_src; + + icmp->icmp_type = type; + icmp->icmp_code = code; + icmp->icmp_cksum = 0; + bcopy((char *)oip, (char *)&icmp->icmp_ip, sizeof(*oip)); + bcopy((char *)oip + (oip->ip_hl << 2), + (char *)&icmp->icmp_ip + sizeof(*oip), 8); /* 64 bits */ +# ifndef sparc + { + register u_short __iplen, __ipoff; + ip_t *ip = &icmp->icmp_ip; + + __iplen = ip->ip_len; + __ipoff = ip->ip_off; + ip->ip_len = htons(__iplen); + ip->ip_off = htons(__ipoff); + } # endif - return err; + icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8); + return send_ip(nip, fin, m); } @@ -933,15 +1078,11 @@ # endif iplinit() { -# if defined(__OpenBSD__) - /* must explicitly enable with 'ipf -E' - * which invokes ipl_enable(); */ -# else - (void) iplattach(); -# endif + if (iplattach() != 0) + printf("IP Filter failed to attach\n"); ip_init(); } -# endif /* !LKM, !sgi, FreeBSD < 3 */ +# endif /* ! __NetBSD__ */ size_t mbufchainlen(m0) @@ -955,7 +1096,7 @@ } -void ipfr_fastroute(m0, fin, fdp) +int ipfr_fastroute(m0, fin, fdp) struct mbuf *m0; fr_info_t *fin; frdest_t *fdp; @@ -963,12 +1104,13 @@ register struct ip *ip, *mhip; register struct mbuf *m = m0; register struct route *ro; - struct ifnet *ifp = fdp->fd_ifp; - int len, off, error = 0; - int hlen = fin->fin_hlen; - struct route iproute; + int len, off, error = 0, hlen, code; + struct ifnet *ifp, *sifp; struct sockaddr_in *dst; + struct route iproute; + frentry_t *fr; + hlen = fin->fin_hlen; ip = mtod(m0, struct ip *); /* * Route packet. @@ -977,13 +1119,32 @@ bzero((caddr_t)ro, sizeof (*ro)); dst = (struct sockaddr_in *)&ro->ro_dst; dst->sin_family = AF_INET; - dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst; -# ifdef __bsdi__ + + fr = fin->fin_fr; + if (fdp) + ifp = fdp->fd_ifp; + else { + ifp = fin->fin_ifp; + dst->sin_addr = ip->ip_dst; + } + + /* + * In case we're here due to "to " being used with "keep state", + * check that we're going in the correct direction. + */ + if ((fr != NULL) && (fin->fin_rev != 0)) { + if ((ifp != NULL) && (fdp == &fr->fr_tif)) + return -1; + dst->sin_addr = ip->ip_dst; + } else if (fdp) + dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst; + +# if BSD >= 199306 dst->sin_len = sizeof(*dst); # endif # if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ !defined(__OpenBSD__) -# ifdef RTF_CLONING +# ifdef RTF_CLONING rtalloc_ign(ro, RTF_CLONING); # else rtalloc_ign(ro, RTF_PRCLONING); @@ -992,7 +1153,7 @@ rtalloc(ro); # endif if (!ifp) { - if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) { + if (!fr || !(fr->fr_flags & FR_FASTROUTE)) { error = -2; goto bad; } @@ -1014,15 +1175,19 @@ * go back through output filtering and miss their chance to get * NAT'd and counted. */ + fin->fin_ifp = ifp; if (fin->fin_out == 0) { + fin->fin_out = 1; if ((fin->fin_fr = ipacct[1][fr_active]) && - (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { + (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { ATOMIC_INC(frstats[1].fr_acct); } fin->fin_fr = NULL; - (void) ip_natout(ip, hlen, fin); - } - if (fin->fin_out) + if (!fr || !(fr->fr_flags & FR_RETMASK)) { + (void) fr_checkstate(ip, fin); + (void) ip_natout(ip, fin); + } + } else ip->ip_sum = 0; /* * If small enough for interface, can just send directly. @@ -1066,7 +1231,11 @@ m0 = m; mhlen = sizeof (struct ip); for (off = hlen + len; off < ip->ip_len; off += len) { +# ifdef MGETHDR + MGETHDR(m, M_DONTWAIT, MT_HEADER); +# else MGET(m, M_DONTWAIT, MT_HEADER); +# endif if (m == 0) { error = ENOBUFS; goto bad; @@ -1096,6 +1265,10 @@ error = ENOBUFS; /* ??? */ goto sendorfree; } +# if BSD >= 199306 + m->m_pkthdr.len = mhlen + len; + m->m_pkthdr.rcvif = NULL; +# endif mhip->ip_off = htons((u_short)mhip->ip_off); mhip->ip_sum = 0; mhip->ip_sum = in_cksum(m, mhlen); @@ -1135,50 +1308,56 @@ if (ro->ro_rt) RTFREE(ro->ro_rt); - return; + return 0; bad: + if (error == EMSGSIZE) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; + code = fin->fin_icode; + fin->fin_icode = ICMP_UNREACH_NEEDFRAG; + (void) send_icmp_err(ip, ICMP_UNREACH, fin, ip->ip_dst); + fin->fin_ifp = sifp; + fin->fin_icode = code; + } m_freem(m); goto done; } #else /* #ifdef _KERNEL */ -#ifdef __sgi +# ifdef __sgi static int no_output __P((struct ifnet *ifp, struct mbuf *m, struct sockaddr *s)) -#else +# else static int no_output __P((struct ifnet *ifp, struct mbuf *m, struct sockaddr *s, struct rtentry *rt)) -#endif +# endif { return 0; } # ifdef __STDC__ -#ifdef __sgi +# ifdef __sgi static int write_output __P((struct ifnet *ifp, struct mbuf *m, struct sockaddr *s)) -#else +# else static int write_output __P((struct ifnet *ifp, struct mbuf *m, struct sockaddr *s, struct rtentry *rt)) -#endif +# endif { -# if !(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) ip_t *ip = (ip_t *)m; -# endif # else static int write_output(ifp, ip) struct ifnet *ifp; ip_t *ip; { # endif - FILE *fp; char fname[32]; + FILE *fp; # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) + (defined(OpenBSD) && (OpenBSD >= 199603)) # if defined __OpenBSD__ sprintf(fname, "/var/run/%s", ifp->if_xname); # else @@ -1258,7 +1437,6 @@ void init_ifp() { - struct ifnet *ifp, **ifa; char fname[32]; int fd; @@ -1271,8 +1449,11 @@ sprintf(fname, "/var/run/%s", ifp->if_xname); # else sprintf(fname, "/tmp/%s", ifp->if_xname); -#endif - if ((fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0600)) != -1) +# endif + fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); + if (fd == -1) + perror("open"); + else close(fd); } # else @@ -1280,14 +1461,17 @@ for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { ifp->if_output = write_output; sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); - if ((fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0600)) != -1) + fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); + if (fd == -1) + perror("open"); + else close(fd); } # endif } -void ipfr_fastroute(ip, fin, fdp) +int ipfr_fastroute(ip, fin, fdp) ip_t *ip; fr_info_t *fin; frdest_t *fdp; @@ -1295,7 +1479,7 @@ struct ifnet *ifp = fdp->fd_ifp; if (!ifp) - return; /* no routing table out here */ + return 0; /* no routing table out here */ ip->ip_len = htons((u_short)ip->ip_len); ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); @@ -1305,6 +1489,7 @@ #else (*ifp->if_output)(ifp, (void *)ip, NULL, 0); #endif + return 0; } @@ -1330,5 +1515,11 @@ { verbose("- TCP RST sent\n"); return 0; +} + + +void frsync() +{ + return; } #endif /* _KERNEL */ Index: sys/netinet/ip_frag.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_frag.c,v retrieving revision 1.11 retrieving revision 1.17 diff -u -r1.11 -r1.17 --- sys/netinet/ip_frag.c 1999/02/05 05:58:51 1.11 +++ sys/netinet/ip_frag.c 2000/03/13 23:40:18 1.17 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $ */ +/* $OpenBSD: ip_frag.c,v 1.17 2000/03/13 23:40:18 kjell Exp $ */ + /* * Copyright (C) 1993-1998 by Darren Reed. * @@ -8,7 +9,11 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $"; +static const char rcsid[] = "@(#)$IPFilter: ip_frag.c,v 2.4.2.4 1999/11/28 04:52:10 darrenr Exp $"; +#endif + +#if defined(KERNEL) && !defined(_KERNEL) +# define _KERNEL #endif #include @@ -22,49 +27,49 @@ # include #endif #if defined(KERNEL) && (__FreeBSD_version >= 220000) -#include -#include +# include +# include #else -#include +# include #endif #include #ifndef linux -#include +# include #endif #include #if defined(_KERNEL) && !defined(linux) # include #endif #if !defined(__SVR4) && !defined(__svr4__) +# if defined(_KERNEL) && !defined(__sgi) +# include +# endif # ifndef linux # include # endif #else # include -# include +# ifdef _KERNEL +# include +# endif # include # include #endif - #include #ifdef sun -#include +# include #endif #include #include #include #include #ifndef linux -#include +# include #endif #include #include #include -#if defined(__OpenBSD__) -# include -#else -# include -#endif +#include #include #include #include @@ -72,6 +77,17 @@ #include #include #include +#if (__FreeBSD_version >= 300000) +# include +# if (defined(KERNEL) || defined(_KERNEL)) +# ifndef IPFILTER_LKM +# include +# include +# endif +extern struct callout_handle ipfr_slowtimer_ch; +# endif +#endif + ipfr_t *ipfr_heads[IPFT_SIZE]; ipfr_t *ipfr_nattab[IPFT_SIZE]; @@ -79,16 +95,26 @@ int ipfr_inuse = 0, fr_ipfrttl = 120; /* 60 seconds */ #ifdef _KERNEL +# if SOLARIS2 >= 7 +extern timeout_id_t ipfr_timer_id; +# else extern int ipfr_timer_id; +# endif #endif #if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern KRWLOCK_T ipf_frag, ipf_natfrag, ipf_nat; +extern KRWLOCK_T ipf_frag, ipf_natfrag, ipf_nat, ipf_mutex; +# if SOLARIS +extern KRWLOCK_T ipf_solaris; +# else +KRWLOCK_T ipf_solaris; +# endif extern kmutex_t ipf_rw; #endif -static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, int, ipfr_t **)); +static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, u_int, ipfr_t **)); static ipfr_t *ipfr_lookup __P((ip_t *, fr_info_t *, ipfr_t **)); +static void ipfr_delete __P((ipfr_t *)); ipfrstat_t *ipfr_fragstats() @@ -107,10 +133,10 @@ static ipfr_t *ipfr_new(ip, fin, pass, table) ip_t *ip; fr_info_t *fin; -int pass; +u_int pass; ipfr_t *table[]; { - ipfr_t **fp, *fr, frag; + ipfr_t **fp, *fra, frag; u_int idx; frag.ipfr_p = ip->ip_p; @@ -128,8 +154,8 @@ /* * first, make sure it isn't already there... */ - for (fp = &table[idx]; (fr = *fp); fp = &fr->ipfr_next) - if (!bcmp((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, + for (fp = &table[idx]; (fra = *fp); fp = &fra->ipfr_next) + if (!bcmp((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, IPFR_CMPSZ)) { ATOMIC_INC(ipfr_stats.ifs_exists); return NULL; @@ -139,39 +165,43 @@ * allocate some memory, if possible, if not, just record that we * failed to do so. */ - KMALLOC(fr, ipfr_t *, sizeof(*fr)); - if (fr == NULL) { + KMALLOC(fra, ipfr_t *); + if (fra == NULL) { ATOMIC_INC(ipfr_stats.ifs_nomem); return NULL; } + if ((fra->ipfr_rule = fin->fin_fr) != NULL) { + ATOMIC_INC(fin->fin_fr->fr_ref); + } + + /* * Instert the fragment into the fragment table, copy the struct used * in the search using bcopy rather than reassign each field. * Set the ttl to the default and mask out logging from "pass" */ - if ((fr->ipfr_next = table[idx])) - table[idx]->ipfr_prev = fr; - fr->ipfr_prev = NULL; - fr->ipfr_data = NULL; - table[idx] = fr; - bcopy((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, IPFR_CMPSZ); - fr->ipfr_ttl = fr_ipfrttl; - fr->ipfr_pass = pass & ~(FR_LOGFIRST|FR_LOG); + if ((fra->ipfr_next = table[idx])) + table[idx]->ipfr_prev = fra; + fra->ipfr_prev = NULL; + fra->ipfr_data = NULL; + table[idx] = fra; + bcopy((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, IPFR_CMPSZ); + fra->ipfr_ttl = fr_ipfrttl; /* * Compute the offset of the expected start of the next packet. */ - fr->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3); + fra->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3); ATOMIC_INC(ipfr_stats.ifs_new); ATOMIC_INC(ipfr_inuse); - return fr; + return fra; } int ipfr_newfrag(ip, fin, pass) ip_t *ip; fr_info_t *fin; -int pass; +u_int pass; { ipfr_t *ipf; @@ -185,7 +215,7 @@ int ipfr_nat_newfrag(ip, fin, pass, nat) ip_t *ip; fr_info_t *fin; -int pass; +u_int pass; nat_t *nat; { ipfr_t *ipf; @@ -251,14 +281,14 @@ f->ipfr_prev = NULL; table[idx] = f; } - off = ip->ip_off; + off = ip->ip_off & IP_OFFMASK; atoff = off + (fin->fin_dlen >> 3); /* * If we've follwed the fragments, and this is the * last (in order), shrink expiration time. */ - if ((off & IP_OFFMASK) == f->ipfr_off) { - if (!(off & IP_MF)) + if (off == f->ipfr_off) { + if (!(ip->ip_off & IP_MF)) f->ipfr_ttl = 1; else f->ipfr_off = atoff; @@ -301,18 +331,19 @@ /* * functional interface for normal lookups of the fragment cache */ -int ipfr_knownfrag(ip, fin) +frentry_t *ipfr_knownfrag(ip, fin) ip_t *ip; fr_info_t *fin; { - int ret; - ipfr_t *ipf; + frentry_t *fr = NULL; + ipfr_t *fra; READ_ENTER(&ipf_frag); - ipf = ipfr_lookup(ip, fin, ipfr_heads); - ret = ipf ? ipf->ipfr_pass : 0; + fra = ipfr_lookup(ip, fin, ipfr_heads); + if (fra != NULL) + fr = fra->ipfr_rule; RWLOCK_EXIT(&ipf_frag); - return ret; + return fr; } @@ -335,34 +366,53 @@ } +static void ipfr_delete(fra) +ipfr_t *fra; +{ + frentry_t *fr; + + fr = fra->ipfr_rule; + if (fr != NULL) { + ATOMIC_DEC(fr->fr_ref); + if (fr->fr_ref == 0) + KFREE(fr); + } + if (fra->ipfr_prev) + fra->ipfr_prev->ipfr_next = fra->ipfr_next; + if (fra->ipfr_next) + fra->ipfr_next->ipfr_prev = fra->ipfr_prev; + KFREE(fra); +} + + /* * Free memory in use by fragment state info. kept. */ void ipfr_unload() { - ipfr_t **fp, *fr; + ipfr_t **fp, *fra; nat_t *nat; int idx; WRITE_ENTER(&ipf_frag); for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_heads[idx]; (fr = *fp); ) { - *fp = fr->ipfr_next; - KFREE(fr); + for (fp = &ipfr_heads[idx]; (fra = *fp); ) { + *fp = fra->ipfr_next; + ipfr_delete(fra); } RWLOCK_EXIT(&ipf_frag); WRITE_ENTER(&ipf_nat); WRITE_ENTER(&ipf_natfrag); for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_nattab[idx]; (fr = *fp); ) { - *fp = fr->ipfr_next; - nat = (nat_t *)fr->ipfr_data; + for (fp = &ipfr_nattab[idx]; (fra = *fp); ) { + *fp = fra->ipfr_next; + nat = fra->ipfr_data; if (nat != NULL) { - if (nat->nat_data == fr) + if (nat->nat_data == fra) nat->nat_data = NULL; } - KFREE(fr); + ipfr_delete(fra); } RWLOCK_EXIT(&ipf_natfrag); RWLOCK_EXIT(&ipf_nat); @@ -375,15 +425,30 @@ * of this being called twice per second. */ # if (BSD >= 199306) || SOLARIS || defined(__sgi) +# if defined(SOLARIS2) && (SOLARIS2 < 7) void ipfr_slowtimer() +# else +void ipfr_slowtimer __P((void *ptr)) +# endif # else int ipfr_slowtimer() # endif { - ipfr_t **fp, *fr; + ipfr_t **fp, *fra; nat_t *nat; - int s, idx; + int idx; +#if defined(_KERNEL) +# if !SOLARIS + int s; +# else + extern int fr_running; + + if (fr_running <= 0) + return; +# endif +#endif + READ_ENTER(&ipf_solaris); #ifdef __sgi ipfilter_sgi_intfsync(); #endif @@ -397,21 +462,15 @@ * remove it from the chain and free it. */ for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_heads[idx]; (fr = *fp); ) { - --fr->ipfr_ttl; - if (fr->ipfr_ttl == 0) { - if (fr->ipfr_prev) - fr->ipfr_prev->ipfr_next = - fr->ipfr_next; - if (fr->ipfr_next) - fr->ipfr_next->ipfr_prev = - fr->ipfr_prev; - *fp = fr->ipfr_next; + for (fp = &ipfr_heads[idx]; (fra = *fp); ) { + --fra->ipfr_ttl; + if (fra->ipfr_ttl == 0) { + *fp = fra->ipfr_next; + ipfr_delete(fra); ATOMIC_INC(ipfr_stats.ifs_expire); ATOMIC_DEC(ipfr_inuse); - KFREE(fr); } else - fp = &fr->ipfr_next; + fp = &fra->ipfr_next; } RWLOCK_EXIT(&ipf_frag); @@ -425,26 +484,20 @@ WRITE_ENTER(&ipf_nat); WRITE_ENTER(&ipf_natfrag); for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_nattab[idx]; (fr = *fp); ) { - --fr->ipfr_ttl; - if (fr->ipfr_ttl == 0) { - if (fr->ipfr_prev) - fr->ipfr_prev->ipfr_next = - fr->ipfr_next; - if (fr->ipfr_next) - fr->ipfr_next->ipfr_prev = - fr->ipfr_prev; - *fp = fr->ipfr_next; + for (fp = &ipfr_nattab[idx]; (fra = *fp); ) { + --fra->ipfr_ttl; + if (fra->ipfr_ttl == 0) { ATOMIC_INC(ipfr_stats.ifs_expire); ATOMIC_DEC(ipfr_inuse); - nat = (nat_t *)fr->ipfr_data; + nat = fra->ipfr_data; if (nat != NULL) { - if (nat->nat_data == fr) + if (nat->nat_data == fra) nat->nat_data = NULL; } - KFREE(fr); + *fp = fra->ipfr_next; + ipfr_delete(fra); } else - fp = &fr->ipfr_next; + fp = &fra->ipfr_next; } RWLOCK_EXIT(&ipf_natfrag); RWLOCK_EXIT(&ipf_nat); @@ -456,11 +509,16 @@ ipfr_timer_id = timeout(ipfr_slowtimer, NULL, drv_usectohz(500000)); # else # ifndef linux - ip_slowtimo(); +# if (__FreeBSD_version >= 300000) + ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); +# else + timeout(ipfr_slowtimer, NULL, hz/2); +# endif # endif # if (BSD < 199306) && !defined(__sgi) return 0; # endif # endif + RWLOCK_EXIT(&ipf_solaris); } #endif /* defined(_KERNEL) */ Index: sys/netinet/ip_frag.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_frag.h,v retrieving revision 1.8 retrieving revision 1.12 diff -u -r1.8 -r1.12 --- sys/netinet/ip_frag.h 1999/02/05 05:58:51 1.8 +++ sys/netinet/ip_frag.h 2000/03/13 23:40:18 1.12 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_frag.h,v 1.8 1999/02/05 05:58:51 deraadt Exp $ */ +/* $OpenBSD: ip_frag.h,v 1.12 2000/03/13 23:40:18 kjell Exp $ */ + /* * Copyright (C) 1993-1998 by Darren Reed. * @@ -7,7 +8,7 @@ * to the original author and the contributors. * * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 1.8 1999/02/05 05:58:51 deraadt Exp $ + * $IPFilter: ip_frag.h,v 2.2 1999/08/06 06:26:38 darrenr Exp $ */ #ifndef __IP_FRAG_H__ @@ -25,7 +26,7 @@ u_char ipfr_tos; u_short ipfr_off; u_short ipfr_ttl; - u_char ipfr_pass; + frentry_t *ipfr_rule; } ipfr_t; @@ -44,16 +45,21 @@ extern int fr_ipfrttl; extern ipfrstat_t *ipfr_fragstats __P((void)); -extern int ipfr_newfrag __P((ip_t *, fr_info_t *, int)); -extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, int, struct nat *)); +extern int ipfr_newfrag __P((ip_t *, fr_info_t *, u_int)); +extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, u_int, struct nat *)); extern nat_t *ipfr_nat_knownfrag __P((ip_t *, fr_info_t *)); -extern int ipfr_knownfrag __P((ip_t *, fr_info_t *)); +extern frentry_t *ipfr_knownfrag __P((ip_t *, fr_info_t *)); extern void ipfr_forget __P((void *)); extern void ipfr_unload __P((void)); #if (BSD >= 199306) || SOLARIS || defined(__sgi) +# if defined(SOLARIS2) && (SOLARIS2 < 7) extern void ipfr_slowtimer __P((void)); +# else +extern void ipfr_slowtimer __P((void *)); +# endif #else extern int ipfr_slowtimer __P((void)); #endif + #endif /* __IP_FIL_H__ */ Index: sys/netinet/ip_ftp_pxy.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_ftp_pxy.c,v retrieving revision 1.4 retrieving revision 1.10 diff -u -r1.4 -r1.10 --- sys/netinet/ip_ftp_pxy.c 1999/02/05 05:58:52 1.4 +++ sys/netinet/ip_ftp_pxy.c 2000/04/12 21:32:39 1.10 @@ -1,5 +1,6 @@ -/* $OpenBSD: ip_ftp_pxy.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $ - * $Id: ip_ftp_pxy.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $ +/* $OpenBSD: ip_ftp_pxy.c,v 1.10 2000/04/12 21:32:39 kjell Exp $ */ + +/* * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. */ @@ -8,6 +9,7 @@ #endif #define isdigit(x) ((x) >= '0' && (x) <= '9') +#define isupper(x) ((unsigned)((x) - 'A') <= 'Z' - 'A') #define IPF_FTP_PROXY @@ -15,29 +17,115 @@ #define IPF_MAXPORTLEN 30 #define IPF_MIN227LEN 39 #define IPF_MAX227LEN 51 +#define IPF_FTPBUFSZ MAX(96,IPF_MAX227LEN) /* This *MUST* be >= 51! */ -int ippr_ftp_init __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); +int ippr_ftp_init __P((void)); +int ippr_ftp_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); int ippr_ftp_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); int ippr_ftp_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_ftp_portmsg __P((fr_info_t *, ip_t *, nat_t *nat)); -int ippr_ftp_pasvmsg __P((fr_info_t *, ip_t *, tcphdr_t *, nat_t *)); +int ippr_ftp_portmsg __P((fr_info_t *, ip_t *, nat_t *)); +int ippr_ftp_pasvmsg __P((fr_info_t *, ip_t *, nat_t *)); +int ippr_ftp_complete __P((char *, size_t)); + u_short ipf_ftp_atoi __P((char **)); +static frentry_t natfr; +int ippr_ftp_pasvonly = 0; + /* - * FTP application proxy initialization. + * Initialize local structures. */ -int ippr_ftp_init(fin, ip, aps, nat) +int ippr_ftp_init() +{ + bzero((char *)&natfr, sizeof(natfr)); + natfr.fr_ref = 1; + natfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; + return 0; +} + + +int ippr_ftp_complete(buf, len) +char *buf; +size_t len; +{ + register char *s, c; + register size_t i; + + if (len < 5) + return -1; + s = buf; + c = *s++; + i = len - 1; + + if (isdigit(c)) { + c = *s++; + i--; + if (isdigit(c)) { + c = *s++; + i--; + if (isdigit(c)) { + c = *s++; + i--; + if (c != '-' && c != ' ') + return -1; + } else + return -1; + } else + return -1; + } else if (isupper(c)) { + c = *s++; + i--; + if (isupper(c)) { + c = *s++; + i--; + if (isupper(c)) { + c = *s++; + i--; + if (isupper(c)) { + c = *s++; + i--; + if (c != ' ') + return -1; + } else + return -1; + } else + return -1; + } else + return -1; + } else + return -1; + + for (; i && (c = *s); i--, s++) { + if ((c == '\r') && (i != 2)) + return -1; + if ((c == '\n') && (i != 1)) + return -1; + else if ((i == 2) && (c != '\r')) + return -1; + else if ((i == 1) && (c != '\n')) + return -1; + } + return i; +} + + +int ippr_ftp_new(fin, ip, aps, nat) fr_info_t *fin; ip_t *ip; ap_session_t *aps; nat_t *nat; { - tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; + ftpinfo_t *ftp; + + KMALLOC(ftp, ftpinfo_t *); + if (ftp == NULL) + return -1; + aps->aps_data = ftp; + aps->aps_psiz = sizeof(ftpinfo_t); - aps->aps_sport = tcp->th_sport; - aps->aps_dport = tcp->th_dport; + ftp->ftp_passok = 0; return 0; } @@ -76,12 +164,14 @@ ip_t *ip; nat_t *nat; { - char portbuf[IPF_MAXPORTLEN + 1], newbuf[IPF_MAXPORTLEN + 1], *s; - int off, olen, dlen, nlen = 0, inc = 0; - u_int a1, a2, a3, a4; + char portbuf[IPF_FTPBUFSZ], newbuf[IPF_FTPBUFSZ], *s; tcphdr_t *tcp, tcph, *tcp2 = &tcph; - struct in_addr swip; + size_t nlen = 0, dlen, olen; u_short a5, a6, sp, dp; + u_int a1, a2, a3, a4; + struct in_addr swip; + int off, inc = 0; + ftpinfo_t *ftp; fr_info_t fi; nat_t *ipn; mb_t *m; @@ -90,24 +180,51 @@ #endif tcp = (tcphdr_t *)fin->fin_dp; + bzero(portbuf, sizeof(portbuf)); off = (ip->ip_hl << 2) + (tcp->th_off << 2); - m = *(mb_t **)fin->fin_mp; #if SOLARIS m = fin->fin_qfm; dlen = msgdsize(m) - off; - bzero(portbuf, sizeof(portbuf)); - copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf); + if (dlen > 0) + copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf); #else + m = *(mb_t **)fin->fin_mp; + dlen = mbufchainlen(m) - off; - bzero(portbuf, sizeof(portbuf)); - m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf); + if (dlen > 0) + m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf); #endif + if (dlen == 0) + return 0; portbuf[sizeof(portbuf) - 1] = '\0'; *newbuf = '\0'; - if (!strncmp(portbuf, "PORT ", 5)) { + /* + * Check that a user is progressing through the login ok. + */ + if (ippr_ftp_complete(portbuf, dlen)) + return 0; + + ftp = nat->nat_aps->aps_data; + switch (ftp->ftp_passok) + { + case 0 : + if (!strncmp(portbuf, "USER ", 5)) + ftp->ftp_passok = 1; + break; + case 2 : + if (!strncmp(portbuf, "PASS ", 5)) + ftp->ftp_passok = 3; + break; + } + if (ftp->ftp_passok != 4) + return 0; + /* + * Check for client sending out PORT message. + */ + if (!ippr_ftp_pasvonly && !strncmp(portbuf, "PORT ", 5)) { if (dlen < IPF_MINPORTLEN) return 0; } else @@ -128,9 +245,9 @@ return 0; /* - * check that IP address in the PORT/PASV reply is the same as the - * sender of the command - prevents using PORT for port scanning. - */ + * check that IP address in the PORT/PASV reply is the same as the + * sender of the command - prevents using PORT for port scanning. + */ a1 <<= 16; a1 |= a2; if (a1 != ntohl(nat->nat_inip.s_addr)) @@ -139,14 +256,18 @@ a5 = ipf_ftp_atoi(&s); if (!s) return 0; + if (*s == ')') + s++; /* * check for CR-LF at the end. */ - if (((*s == '\r') && (*(s + 1) == '\n')) || - ((*(s - 1) == '\r') && (*s == '\n'))) + if (*s == '\n') + s--; + if ((*s == '\r') && (*(s + 1) == '\n')) { + s += 2; a6 = a5 & 0xff; - else + } else return 0; a5 >>= 8; /* @@ -157,8 +278,9 @@ a3 = (a1 >> 8) & 0xff; a4 = a1 & 0xff; a1 >>= 24; - olen = s - portbuf + 1; - (void) sprintf(newbuf, "%s %d,%d,%d,%d,%d,%d\r\n", + olen = s - portbuf; + /* DO NOT change this to sprintf! */ + (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", "PORT", a1, a2, a3, a4, a5, a6); nlen = strlen(newbuf); @@ -182,6 +304,9 @@ linkb(m1, nm); } else { + if (m1->b_datap->db_struiolim == m1->b_wptr) + m1->b_datap->db_struiolim += inc; + m1->b_datap->db_struioflag &= ~STRUIO_IP; m1->b_wptr += inc; } copyin_mblk(m, off, nlen, newbuf); @@ -191,7 +316,7 @@ /* the mbuf chain will be extended if necessary by m_copyback() */ m_copyback(m, off, nlen, newbuf); #endif - if (inc) { + if (inc != 0) { #if SOLARIS || defined(__sgi) register u_32_t sum1, sum2; @@ -204,32 +329,46 @@ sum2 -= sum1; sum2 = (sum2 & 0xffff) + (sum2 >> 16); - fix_outcksum(&ip->ip_sum, sum2); + fix_outcksum(&ip->ip_sum, sum2, 0); #endif ip->ip_len += inc; } /* - * Add skeleton NAT entry for connection which will come back the - * other way. - */ + * Add skeleton NAT entry for connection which will come back the + * other way. + */ sp = htons(a5 << 8 | a6); + /* + * Don't allow the PORT command to specify a port < 1024 due to + * security crap. + */ + if (ntohs(sp) < 1024) + return 0; + /* + * The server may not make the connection back from port 20, but + * it is the most likely so use it here to check for a conflicting + * mapping. + */ dp = htons(fin->fin_data[1] - 1); - ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_inip, sp, - ip->ip_dst, dp); + ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, + ip->ip_dst, (dp << 16) | sp); if (ipn == NULL) { bcopy((char *)fin, (char *)&fi, sizeof(fi)); bzero((char *)tcp2, sizeof(*tcp2)); + tcp2->th_win = htons(8192); tcp2->th_sport = sp; - tcp2->th_dport = dp; + tcp2->th_dport = 0; /* XXX - don't specify remote port */ + fi.fin_data[0] = ntohs(sp); + fi.fin_data[1] = 0; fi.fin_dp = (char *)tcp2; swip = ip->ip_src; ip->ip_src = nat->nat_inip; - ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP, NAT_OUTBOUND); + ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_DPORT, + NAT_OUTBOUND); if (ipn != NULL) { ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FR_INQUE|FR_PASS| - FR_QUICK|FR_KEEPSTATE); + (void) fr_addstate(ip, &fi, FI_W_DPORT); } ip->ip_src = swip; } @@ -247,18 +386,19 @@ } -int ippr_ftp_pasvmsg(fin, ip, tcp, nat) +int ippr_ftp_pasvmsg(fin, ip, nat) fr_info_t *fin; ip_t *ip; -tcphdr_t *tcp; nat_t *nat; { - char portbuf[IPF_MAX227LEN + 1], newbuf[IPF_MAX227LEN + 1], *s; + char portbuf[IPF_FTPBUFSZ], newbuf[IPF_FTPBUFSZ], *s; int off, olen, dlen, nlen = 0, inc = 0; - u_int a1, a2, a3, a4; tcphdr_t tcph, *tcp2 = &tcph; - struct in_addr swip; - u_short a5, a6; + struct in_addr swip, swip2; + u_short a5, a6, dp, sp; + u_int a1, a2, a3, a4; + ftpinfo_t *ftp; + tcphdr_t *tcp; fr_info_t fi; nat_t *ipn; mb_t *m; @@ -266,43 +406,72 @@ mb_t *m1; #endif + tcp = (tcphdr_t *)fin->fin_dp; off = (ip->ip_hl << 2) + (tcp->th_off << 2); m = *(mb_t **)fin->fin_mp; + bzero(portbuf, sizeof(portbuf)); #if SOLARIS m = fin->fin_qfm; dlen = msgdsize(m) - off; - bzero(portbuf, sizeof(portbuf)); - copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf); + if (dlen > 0) + copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf); #else dlen = mbufchainlen(m) - off; - bzero(portbuf, sizeof(portbuf)); - m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf); + if (dlen > 0) + m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf); #endif + if (dlen == 0) + return 0; portbuf[sizeof(portbuf) - 1] = '\0'; *newbuf = '\0'; + /* + * Check that a user is progressing through the login ok. + * Don't put the switch in one common function because one side + * should only see numeric responses and the other commands. + */ + + ftp = nat->nat_aps->aps_data; + switch (ftp->ftp_passok) + { + case 1 : + if (!strncmp(portbuf, "331", 3)) + ftp->ftp_passok = 2; + else if (!strncmp(portbuf, "530", 3)) + ftp->ftp_passok = 0; + break; + case 3 : + if (!strncmp(portbuf, "230", 3)) + ftp->ftp_passok = 4; + break; + default : + break; + } + + if (ippr_ftp_complete(portbuf, dlen) || (ftp->ftp_passok != 4)) + return 0; + + /* + * Check for PASV reply message. + */ if (!strncmp(portbuf, "227 ", 4)) { if (dlen < IPF_MIN227LEN) return 0; else if (strncmp(portbuf, "227 Entering Passive Mode", 25)) return 0; -#ifndef notyet - return 0; -#endif } else return 0; - /* - * Skip the PORT command + space - */ + * Skip the PORT command + space + */ s = portbuf + 25; while (*s && !isdigit(*s)) s++; /* - * Pick out the address components, two at a time. - */ + * Pick out the address components, two at a time. + */ a1 = ipf_ftp_atoi(&s); if (!s) return 0; @@ -311,9 +480,9 @@ return 0; /* - * check that IP address in the PORT/PASV reply is the same as the - * sender of the command - prevents using PORT for port scanning. - */ + * check that IP address in the PORT/PASV reply is the same as the + * sender of the command - prevents using PORT for port scanning. + */ a1 <<= 16; a1 |= a2; if (a1 != ntohl(nat->nat_oip.s_addr)) @@ -323,25 +492,29 @@ if (!s) return 0; + if (*s == ')') + s++; + if (*s == '\n') + s--; /* - * check for CR-LF at the end. - */ - if (((*s == '\r') && (*(s + 1) == '\n')) || - ((*(s - 1) == '\r') && (*s == '\n'))) + * check for CR-LF at the end. + */ + if ((*s == '\r') && (*(s + 1) == '\n')) { + s += 2; a6 = a5 & 0xff; - else + } else return 0; a5 >>= 8; /* - * Calculate new address parts for 227 reply - */ - a1 = ntohl(nat->nat_inip.s_addr); + * Calculate new address parts for 227 reply + */ + a1 = ntohl(ip->ip_src.s_addr); a2 = (a1 >> 16) & 0xff; a3 = (a1 >> 8) & 0xff; a4 = a1 & 0xff; a1 >>= 24; - olen = s - portbuf + 1; - (void) sprintf(newbuf, "%s %d,%d,%d,%d,%d,%d\r\n", + olen = s - portbuf; + (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", "227 Entering Passive Mode", a1, a2, a3, a4, a5, a6); nlen = strlen(newbuf); @@ -374,7 +547,7 @@ /* the mbuf chain will be extended if necessary by m_copyback() */ m_copyback(m, off, nlen, newbuf); #endif - if (inc) { + if (inc != 0) { #if SOLARIS || defined(__sgi) register u_32_t sum1, sum2; @@ -387,7 +560,7 @@ sum2 -= sum1; sum2 = (sum2 & 0xffff) + (sum2 >> 16); - fix_outcksum(&ip->ip_sum, sum2); + fix_outcksum(&ip->ip_sum, sum2, 0); #endif ip->ip_len += inc; } @@ -396,27 +569,42 @@ * Add skeleton NAT entry for connection which will come back the * other way. */ - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_sport = htons(a5 << 8 | a6); - fi.fin_dp = (char *)tcp2; - swip = ip->ip_src; - ip->ip_src = nat->nat_oip; - ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP, NAT_INBOUND); - if (ipn != NULL) - ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE); - ip->ip_src = swip; + sp = 0; + dp = htons(fin->fin_data[1] - 1); + ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, + ip->ip_dst, (dp << 16) | sp); + if (ipn == NULL) { + bcopy((char *)fin, (char *)&fi, sizeof(fi)); + bzero((char *)tcp2, sizeof(*tcp2)); + tcp2->th_win = htons(8192); + tcp2->th_sport = 0; /* XXX - fake it for nat_new */ + fi.fin_data[0] = a5 << 8 | a6; + tcp2->th_dport = htons(fi.fin_data[0]); + fi.fin_data[1] = 0; + fi.fin_dp = (char *)tcp2; + swip = ip->ip_src; + swip2 = ip->ip_dst; + ip->ip_dst = ip->ip_src; + ip->ip_src = nat->nat_inip; + ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_SPORT, + NAT_OUTBOUND); + if (ipn != NULL) { + ipn->nat_age = fr_defnatage; + (void) fr_addstate(ip, &fi, FI_W_SPORT); + } + ip->ip_src = swip; + ip->ip_dst = swip2; + } return inc; } + int ippr_ftp_in(fin, ip, aps, nat) fr_info_t *fin; ip_t *ip; ap_session_t *aps; nat_t *nat; { - tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; - return ippr_ftp_pasvmsg(fin, ip, tcp, nat); + return ippr_ftp_pasvmsg(fin, ip, nat); } Index: sys/netinet/ip_log.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_log.c,v retrieving revision 1.4 retrieving revision 1.8 diff -u -r1.4 -r1.8 --- sys/netinet/ip_log.c 1999/02/05 05:58:52 1.4 +++ sys/netinet/ip_log.c 2000/03/13 23:40:18 1.8 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_log.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $ */ +/* $OpenBSD: ip_log.c,v 1.8 2000/03/13 23:40:18 kjell Exp $ */ + /* * Copyright (C) 1997-1998 by Darren Reed. * @@ -6,23 +7,29 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * $Id: ip_log.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $ + * $IPFilter: ip_log.c,v 2.1.2.2 1999/09/21 11:55:44 darrenr Exp $ */ +#include +#if defined(KERNEL) && !defined(_KERNEL) +# define _KERNEL +#endif +#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) +# include "opt_ipfilter_log.h" +#endif +#ifdef __FreeBSD__ +# if defined(_KERNEL) && !defined(IPFILTER_LKM) +# include +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) +# include "opt_ipfilter.h" +# endif +# else +# include +# endif +#endif #ifdef IPFILTER_LOG # ifndef SOLARIS # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) # endif - -# if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -# endif -# ifdef __FreeBSD__ -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# include -# else -# include -# endif -# endif # ifndef _KERNEL # include # include @@ -31,7 +38,6 @@ # endif # include # include -# include # include # if __FreeBSD_version >= 220000 && defined(_KERNEL) # include @@ -45,7 +51,7 @@ # endif # include # if !SOLARIS -# if (NetBSD > 199609) || (OpenBSD > 199603) +# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) # include # else # include @@ -97,12 +103,8 @@ # endif # ifndef _KERNEL # include -# endif -# if defined(__OpenBSD__) -# include -# else -# include # endif +# include # include # include # include @@ -110,6 +112,10 @@ # include # include # include +# if (__FreeBSD_version >= 300000) +# include +# endif + # ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) # endif @@ -122,10 +128,9 @@ # endif # endif -iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; -int iplused[IPL_LOGMAX+1]; -u_long iplcrc[IPL_LOGMAX+1]; -u_long iplcrcinit; +iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1], *ipll[IPL_LOGMAX+1]; +size_t iplused[IPL_LOGMAX+1]; +fr_info_t iplcrc[IPL_LOGMAX+1]; # ifdef linux static struct wait_queue *iplwait[IPL_LOGMAX+1]; # endif @@ -137,20 +142,15 @@ */ void ipflog_init() { - struct timeval tv; int i; for (i = IPL_LOGMAX; i >= 0; i--) { iplt[i] = NULL; + ipll[i] = NULL; iplh[i] = &iplt[i]; iplused[i] = 0; + bzero((char *)&iplcrc[i], sizeof(iplcrc[i])); } -# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) - microtime(&tv); -# else - uniqtime(&tv); -# endif - iplcrcinit = tv.tv_sec ^ (tv.tv_usec << 8) ^ tv.tv_usec; } @@ -169,8 +169,7 @@ mb_t *m; { ipflog_t ipfl; - register int mlen, hlen; - u_long crc; + register size_t mlen, hlen; size_t sizes[2]; void *ptrs[2]; int types[2]; @@ -193,12 +192,12 @@ struct icmp *icmp; icmp = (struct icmp *)((char *)ip + hlen); - + /* - * For ICMP, if the packet is an error packet, also - * include the information about the packet which - * caused the error. - */ + * For ICMP, if the packet is an error packet, also + * include the information about the packet which + * caused the error. + */ switch (icmp->icmp_type) { case ICMP_UNREACH : @@ -243,11 +242,15 @@ ipfl.fl_hlen = (u_char)hlen; ipfl.fl_rule = fin->fin_rule; ipfl.fl_group = fin->fin_group; + if (fin->fin_fr != NULL) + ipfl.fl_loglevel = fin->fin_fr->fr_loglevel; + else + ipfl.fl_loglevel = 0xffff; ipfl.fl_flags = flags; ptrs[0] = (void *)&ipfl; sizes[0] = sizeof(ipfl); types[0] = 0; -#if SOLARIS +# if SOLARIS /* * Are we copied from the mblk or an aligned array ? */ @@ -260,45 +263,47 @@ sizes[1] = hlen + mlen; types[1] = 0; } -#else +# else ptrs[1] = m; sizes[1] = hlen + mlen; types[1] = 1; -#endif - crc = (ipf_cksum((u_short *)fin, FI_CSIZE) << 8) + iplcrcinit; - return ipllog(IPL_LOGIPF, crc, ptrs, sizes, types, 2); +# endif + return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2); } /* * ipllog */ -int ipllog(dev, crc, items, itemsz, types, cnt) +int ipllog(dev, fin, items, itemsz, types, cnt) int dev; -u_long crc; +fr_info_t *fin; void **items; size_t *itemsz; int *types, cnt; { - iplog_t *ipl; caddr_t buf, s; - int len, i; + iplog_t *ipl; + size_t len; + int i; /* * Check to see if this log record has a CRC which matches the last * record logged. If it does, just up the count on the previous one * rather than create a new one. */ - if (crc) { - MUTEX_ENTER(&ipl_mutex); - if ((iplcrc[dev] == crc) && *iplh[dev]) { - (*iplh[dev])->ipl_count++; + MUTEX_ENTER(&ipl_mutex); + if (fin != NULL) { + if ((ipll[dev] != NULL) && + bcmp((char *)fin, (char *)&iplcrc[dev], FI_CSIZE) == 0) { + ipll[dev]->ipl_count++; MUTEX_EXIT(&ipl_mutex); return 1; } - iplcrc[dev] = crc; - MUTEX_EXIT(&ipl_mutex); - } + bcopy((char *)fin, (char *)&iplcrc[dev], FI_CSIZE); + } else + bzero((char *)&iplcrc[dev], FI_CSIZE); + MUTEX_EXIT(&ipl_mutex); /* * Get the total amount of data to be logged. @@ -310,7 +315,7 @@ * check that we have space to record this information and can * allocate that much. */ - KMALLOC(buf, caddr_t, len); + KMALLOCS(buf, caddr_t, len); if (!buf) return 0; MUTEX_ENTER(&ipl_mutex); @@ -356,6 +361,7 @@ s += itemsz[i]; } MUTEX_ENTER(&ipl_mutex); + ipll[dev] = ipl; *iplh[dev] = ipl; iplh[dev] = &ipl->ipl_next; # if SOLARIS @@ -374,11 +380,12 @@ int ipflog_read(unit, uio) -int unit; +minor_t unit; struct uio *uio; { + size_t dlen, copied; + int error = 0; iplog_t *ipl; - int error = 0, dlen, copied; # if defined(_KERNEL) && !SOLARIS int s; # endif @@ -387,7 +394,7 @@ * Sanity checks. Make sure the minor # is valid and we're copying * a valid chunk of data. */ - if ((IPL_LOGMAX < unit) || (unit < 0)) + if (IPL_LOGMAX < unit) return ENXIO; if (!uio->uio_resid) return 0; @@ -431,43 +438,48 @@ for (copied = 0; (ipl = iplt[unit]); copied += dlen) { dlen = ipl->ipl_dsize; - if (dlen + sizeof(iplog_t) > uio->uio_resid) + if (dlen > uio->uio_resid) break; /* * Don't hold the mutex over the uiomove call. */ iplt[unit] = ipl->ipl_next; + iplused[unit] -= dlen; MUTEX_EXIT(&ipl_mutex); SPL_X(s); - error = UIOMOVE((caddr_t)ipl, ipl->ipl_dsize, UIO_READ, uio); - KFREES((caddr_t)ipl, ipl->ipl_dsize); - if (error) + error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); + if (error) { + SPL_NET(s); + MUTEX_ENTER(&ipl_mutex); + ipl->ipl_next = iplt[unit]; + iplt[unit] = ipl; + iplused[unit] += dlen; break; + } + KFREES((caddr_t)ipl, dlen); SPL_NET(s); MUTEX_ENTER(&ipl_mutex); - iplused[unit] -= dlen; } - if (!ipl) { + if (!iplt[unit]) { iplused[unit] = 0; iplh[unit] = &iplt[unit]; + ipll[unit] = NULL; } - if (!error) { - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - } -#ifdef linux + MUTEX_EXIT(&ipl_mutex); + SPL_X(s); +# ifdef linux if (!error) - return copied; + return (int)copied; return -error; -#else +# else return error; -#endif +# endif } int ipflog_clear(unit) -int unit; +minor_t unit; { iplog_t *ipl; int used; @@ -478,9 +490,10 @@ KFREES((caddr_t)ipl, ipl->ipl_dsize); } iplh[unit] = &iplt[unit]; + ipll[unit] = NULL; used = iplused[unit]; iplused[unit] = 0; - iplcrc[unit] = 0; + bzero((char *)&iplcrc[unit], FI_CSIZE); MUTEX_EXIT(&ipl_mutex); return used; } Index: sys/netinet/ip_nat.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_nat.c,v retrieving revision 1.22 retrieving revision 1.32 diff -u -r1.22 -r1.32 --- sys/netinet/ip_nat.c 1999/08/08 00:43:00 1.22 +++ sys/netinet/ip_nat.c 2000/05/24 21:59:11 1.32 @@ -1,4 +1,5 @@ -/* $OpenBSD: ip_nat.c,v 1.22 1999/08/08 00:43:00 niklas Exp $ */ +/* $OpenBSD: ip_nat.c,v 1.32 2000/05/24 21:59:11 kjell Exp $ */ + /* * Copyright (C) 1995-1998 by Darren Reed. * @@ -10,7 +11,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_nat.c,v 1.22 1999/08/08 00:43:00 niklas Exp $"; +static const char rcsid[] = "@(#)$IPFilter: ip_nat.c,v 2.2.2.18 2000/05/19 15:52:29 darrenr Exp $"; #endif #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) @@ -22,12 +23,16 @@ #include #include #include +#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ + defined(_KERNEL) +# include "opt_ipfilter_log.h" +#endif #if !defined(_KERNEL) && !defined(KERNEL) # include # include # include #endif -#if defined(KERNEL) && (__FreeBSD_version >= 220000) +#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) # include # include #else @@ -49,7 +54,9 @@ #else # include # include -# include +# ifdef _KERNEL +# include +# endif # include # include #endif @@ -59,9 +66,12 @@ #include #if __FreeBSD_version >= 300000 # include +# if defined(_KERNEL) && !defined(IPFILTER_LKM) +# include "opt_ipfilter.h" +# endif #endif #ifdef sun -#include +# include #endif #include #include @@ -76,8 +86,8 @@ #endif #ifdef RFC1825 -#include -#include +# include +# include extern struct ifnet vpnif; #endif @@ -87,27 +97,35 @@ #include #include #include -#if defined(__OpenBSD__) #include -#else -#include -#endif #include #include #include #include #include #include +#if (__FreeBSD_version >= 300000) +# include +#endif #ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) +# define MIN(a,b) (((a)<(b))?(a):(b)) #endif #undef SOCKADDR_IN #define SOCKADDR_IN struct sockaddr_in -nat_t *nat_table[2][NAT_SIZE], *nat_instances = NULL; +nat_t **nat_table[2] = { NULL, NULL }, + *nat_instances = NULL; ipnat_t *nat_list = NULL; -u_long fr_defnatage = 1200, /* 10 minutes (600 seconds) */ - fr_defnaticmpage = 6; /* 3 seconds */ +u_int ipf_nattable_sz = NAT_TABLE_SZ; +u_int ipf_natrules_sz = NAT_SIZE; +u_int ipf_rdrrules_sz = RDR_SIZE; +u_32_t nat_masks = 0; +u_32_t rdr_masks = 0; +ipnat_t **nat_rules = NULL; +ipnat_t **rdr_rules = NULL; + +u_long fr_defnatage = DEF_NAT_AGE, + fr_defnaticmpage = 6; /* 3 seconds */ natstat_t nat_stats; #if (SOLARIS || defined(__sgi)) && defined(_KERNEL) extern kmutex_t ipf_rw; @@ -117,31 +135,87 @@ static int nat_flushtable __P((void)); static int nat_clearlist __P((void)); static void nat_delete __P((struct nat *)); -static int nat_ifpaddr __P((nat_t *, void *, struct in_addr *)); +static void nat_delrdr __P((struct ipnat *)); +static void nat_delnat __P((struct ipnat *)); + + +int nat_init() +{ + KMALLOCS(nat_table[0], nat_t **, sizeof(nat_t *) * ipf_nattabl