diff options
author | dm <dm@cvs.openbsd.org> | 1996-07-18 05:01:10 +0000 |
---|---|---|
committer | dm <dm@cvs.openbsd.org> | 1996-07-18 05:01:10 +0000 |
commit | 746e8c40786f598f5da99fed9714ae7961393281 (patch) | |
tree | 7fa485ff1f4c0076948de7742853326232fa0cc1 /sys | |
parent | 6764f712dd3ffd42fd940f9e87d2a9109743c72d (diff) |
ipfilter 3.1.0
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/fil.c | 135 | ||||
-rw-r--r-- | sys/netinet/in_proto.c | 7 | ||||
-rw-r--r-- | sys/netinet/ip_fil.c | 339 | ||||
-rw-r--r-- | sys/netinet/ip_fil.h | 271 | ||||
-rw-r--r-- | sys/netinet/ip_fil_compat.h | 216 | ||||
-rw-r--r-- | sys/netinet/ip_frag.c | 2 | ||||
-rw-r--r-- | sys/netinet/ip_frag.h | 6 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_nat.c | 89 | ||||
-rw-r--r-- | sys/netinet/ip_nat.h | 5 | ||||
-rw-r--r-- | sys/netinet/ip_state.c | 27 | ||||
-rw-r--r-- | sys/netinet/ip_state.h | 6 |
12 files changed, 750 insertions, 359 deletions
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c index f84114c3239..4cba4d8af2d 100644 --- a/sys/netinet/fil.c +++ b/sys/netinet/fil.c @@ -6,7 +6,8 @@ * to the original author and the contributors. */ #ifndef lint -static char sccsid[] = "@(#)fil.c 1.32 4/10/96 (C) 1993-1996 Darren Reed"; +static char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; +static char rcsid[] = "$Id: fil.c,v 1.5 1996/07/18 05:00:55 dm Exp $"; #endif #include <sys/errno.h> @@ -45,6 +46,7 @@ static char sccsid[] = "@(#)fil.c 1.32 4/10/96 (C) 1993-1996 Darren Reed"; #include <netinet/tcpip.h> #include <netinet/ip_icmp.h> #include "ip_fil.h" +#include "ip_fil_compat.h" #include "ip_nat.h" #include "ip_frag.h" #include "ip_state.h" @@ -151,7 +153,7 @@ struct optlist secopt[8] = { * compact the IP header into a structure which contains just the info. * which is useful for comparing IP headers with. */ -fr_info_t *fr_makefrip(hlen, ip, fin) +void fr_makefrip(hlen, ip, fin) int hlen; ip_t *ip; fr_info_t *fin; @@ -163,9 +165,7 @@ fr_info_t *fin; int i, mv, ol, off; u_char *s, opt; - fin->fin_dp = ((char *)ip + hlen); - tcp = (tcphdr_t *)fin->fin_dp; - fi->fi_fl = 0; + fin->fin_fr = NULL; fin->fin_tcpf = 0; fin->fin_data[0] = 0; fin->fin_data[1] = 0; @@ -177,12 +177,13 @@ fr_info_t *fin; fi->fi_tos = ip->ip_tos; fin->fin_hlen = hlen; fin->fin_dlen = ip->ip_len - hlen; + tcp = (tcphdr_t *)((char *)ip + hlen); + fin->fin_dp = (void *)tcp; (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); (*(((u_long *)fi) + 1)) = (*(((u_long *)ip) + 3)); (*(((u_long *)fi) + 2)) = (*(((u_long *)ip) + 4)); - if (hlen > sizeof(struct ip)) - fi->fi_fl |= FI_OPTIONS; + fi->fi_fl = (hlen > sizeof(struct ip)) ? FI_OPTIONS : 0; off = (ip->ip_off & 0x1fff) << 3; if (ip->ip_off & 0x3fff) fi->fi_fl |= FI_FRAG; @@ -202,21 +203,22 @@ fr_info_t *fin; fi->fi_fl |= FI_SHORT; if (!(fi->fi_fl & FI_SHORT) && !off) fin->fin_tcpf = tcp->th_flags; - break; + goto getports; case IPPROTO_UDP : fi->fi_fl |= FI_TCPUDP; if ((!IPMINLEN(ip, udphdr) && !off) || (off && off < sizeof(struct udphdr))) fi->fi_fl |= FI_SHORT; +getports: + if (!off && (fin->fin_dlen > 3)) { + fin->fin_data[0] = ntohs(tcp->th_sport); + fin->fin_data[1] = ntohs(tcp->th_dport); + } break; default : break; } - if ((fi->fi_fl & FI_TCPUDP) && !off && (fin->fin_dlen > 3)) { - fin->fin_data[0] = ntohs(tcp->th_sport); - fin->fin_data[1] = ntohs(tcp->th_dport); - } for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) { if (!(opt = *s)) @@ -264,7 +266,6 @@ fr_info_t *fin; fi->fi_optmsk = optmsk; fi->fi_secmsk = secmsk; fi->fi_auth = auth; - return fin; } @@ -438,10 +439,10 @@ void *m; continue; } else if (fi->fi_p == IPPROTO_ICMP) { if (!off && (fin->fin_dlen > 1)) { - if ((*(u_short *)fin->fin_dp & fr->fr_icmpm) != + if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) { FR_DEBUG(("i. %#x & %#x != %#x\n", - *(u_short *)fin->fin_dp, + fin->fin_data[0], fr->fr_icmpm, fr->fr_icmp)); continue; } @@ -453,8 +454,10 @@ void *m; * Just log this packet... */ pass = fr->fr_flags; + if ((pass & FR_CALLNOW) && fr->fr_func) + pass = (*fr->fr_func)(ip, fin); #ifdef IPFILTER_LOG - if (pass & FR_LOG) { + if ((pass & FR_LOGMASK) == FR_LOG) { if (!IPLLOG(fr->fr_flags, ip, fin, m)) frstats[fin->fin_out].fr_skip++; frstats[fin->fin_out].fr_pkl++; @@ -462,8 +465,6 @@ void *m; #endif /* IPFILTER_LOG */ FR_DEBUG(("pass %#x\n", pass)); fr->fr_hits++; - fin->fin_fr = fr; - fin->fin_rule = rulen; if (pass & FR_ACCOUNT) fr->fr_bytes += ip->ip_len; else @@ -471,6 +472,8 @@ void *m; if (pass & FR_QUICK) break; } + fin->fin_rule = rulen; + fin->fin_fr = fr; return pass; } @@ -483,9 +486,10 @@ void *m; int fr_check(ip, hlen, ifp, out #ifdef _KERNEL # if SOLARIS -, qif, q) +, qif, q, mb) qif_t *qif; queue_t *q; +mblk_t *mb; # else , mp) struct mbuf **mp; @@ -501,12 +505,14 @@ int out; /* * The above really sucks, but short of writing a diff */ - register fr_info_t *fin; fr_info_t frinfo, *fc; + register fr_info_t *fin = &frinfo; + frentry_t *fr; int pass; #if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL) register struct mbuf *m = *mp; + struct mbuf *mc = NULL; if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_ICMP)) { @@ -522,7 +528,10 @@ int out; } } #endif - fin = fr_makefrip(hlen, ip, &frinfo); +#if SOLARIS + mblk_t *mc = NULL; +#endif + fr_makefrip(hlen, ip, fin); fin->fin_ifp = ifp; fin->fin_out = out; @@ -552,9 +561,13 @@ int out; frstats[out].fr_cfr++; } } else { - fc = frcache+out; + fc = frcache + out; if (fc->fin_fr && !bcmp((char *)fin, (char *)fc, FI_CSIZE)) { - fin = fc; + /* + * copy cached data so we can unlock the mutex + * earlier. + */ + bcopy((char *)fc, (char *)fin, sizeof(*fin)); frstats[out].fr_chit++; pass = fin->fin_fr->fr_flags; } else { @@ -580,13 +593,18 @@ int out; frstats[out].fr_cfr++; } if (pass & FR_KEEPSTATE) { - if (fr_addstate(ip, hlen, pass) == -1) + if (fr_addstate(ip, fin, pass) == -1) frstats[out].fr_bads++; else frstats[out].fr_ads++; } } + fr = fin->fin_fr; + + if (fr && fr->fr_func) + pass = (*fr->fr_func)(pass, ip, fin); + if (out) { if ((fin->fin_fr = ipacct[1][fr_active]) && (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) @@ -596,25 +614,26 @@ int out; MUTEX_EXIT(&ipf_mutex); #ifdef IPFILTER_LOG - if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { - pass |= FF_LOGNOMATCH; - if (!IPLLOG(pass, ip, fin, m)) - frstats[out].fr_skip++; - frstats[out].fr_npkl++; - } else if (((pass & FR_LOGP) == FR_LOGP) || - ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) { - if ((pass & FR_LOGP) != FR_LOGP) - pass |= FF_LOGPASS; - if (!IPLLOG(pass, ip, fin, m)) - frstats[out].fr_skip++; - frstats[out].fr_ppkl++; - } else if (((pass & FR_LOGB) == FR_LOGB) || - ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) { - if ((pass & FR_LOGB) != FR_LOGB) - pass |= FF_LOGBLOCK; - if (!IPLLOG(pass, ip, fin, m)) - frstats[out].fr_skip++; - frstats[out].fr_bpkl++; + if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { + if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { + pass |= FF_LOGNOMATCH; + frstats[out].fr_npkl++; + goto logit; + } else if (((pass & FR_LOGMASK) == FR_LOGP) || + ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) { + if ((pass & FR_LOGMASK) != FR_LOGP) + pass |= FF_LOGPASS; + frstats[out].fr_ppkl++; + goto logit; + } else if (((pass & FR_LOGMASK) == FR_LOGB) || + ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) { + if ((pass & FR_LOGMASK) != FR_LOGB) + pass |= FF_LOGBLOCK; + frstats[out].fr_bpkl++; +logit: + if (!IPLLOG(pass, ip, fin, m)) + frstats[out].fr_skip++; + } } #endif /* IPFILTER_LOG */ @@ -638,7 +657,7 @@ int out; # endif frstats[0].fr_ret++; - } else if (pass & FR_RETRST && + } else if ((pass & FR_RETRST) && !(fin->fin_fi.fi_fl & FI_SHORT)) { if (SEND_RESET(ip, qif, q) == 0) frstats[1].fr_ret++; @@ -647,7 +666,8 @@ int out; if (pass & FR_RETICMP) { verbose("- ICMP unreachable sent\n"); frstats[0].fr_ret++; - } else if (pass & FR_RETRST && IPMINLEN(ip, tcphdr)) { + } else if ((pass & FR_RETRST) && + !(fin->fin_fi.fi_fl & FI_SHORT)) { verbose("- TCP RST sent\n"); frstats[1].fr_ret++; } @@ -655,8 +675,33 @@ int out; } #ifdef _KERNEL # if !SOLARIS + if (pass & FR_DUP) + mc = m_copy(m, 0, M_COPYALL); + if (fr) { + frdest_t *fdp = &fr->fr_tif; + + if ((pass & FR_FASTROUTE) || + (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) + ipfr_fastroute(m, fin, fdp); + if (mc) + ipfr_fastroute(mc, fin, &fr->fr_dif); + } if (!(pass & FR_PASS) && m) m_freem(m); +# else + /* + if (pass & FR_DUP) + mc = dupmsg(mb); + if (fr) { + frdest_t *fdp = &fr->fr_tif; + + if ((pass & FR_FASTROUTE) || + (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) + ipfr_fastroute(mb, fin, fdp); + if (mc) + ipfr_fastroute(mc, fin, &fr->fr_dif); + } + */ # endif return (pass & FR_PASS) ? 0 : -1; #else diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 28cca9a2fae..56387aaa7ca 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_proto.c,v 1.4 1996/04/24 06:00:43 mickey Exp $ */ +/* $OpenBSD: in_proto.c,v 1.5 1996/07/18 05:00:57 dm Exp $ */ /* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */ /* @@ -89,6 +89,11 @@ #include <netinet/ip_mroute.h> #endif /* MROUTING */ +#ifdef IPFILTER +void iplinit(); +#define ip_init iplinit +#endif + extern struct domain inetdomain; struct protosw inetsw[] = { diff --git a/sys/netinet/ip_fil.c b/sys/netinet/ip_fil.c index 9964e1ca030..14379a2c868 100644 --- a/sys/netinet/ip_fil.c +++ b/sys/netinet/ip_fil.c @@ -6,7 +6,8 @@ * to the original author and the contributors. */ #ifndef lint -static char sccsid[] = "@(#)ip_fil.c 2.37 4/10/96 (C) 1993-1995 Darren Reed"; +static char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed"; +static char rcsid[] = "$Id: ip_fil.c,v 1.4 1996/07/18 05:00:58 dm Exp $"; #endif #ifndef linux @@ -28,6 +29,7 @@ static char sccsid[] = "@(#)ip_fil.c 2.37 4/10/96 (C) 1993-1995 Darren Reed"; #endif #include <net/route.h> #include <netinet/in.h> +#include <netinet/in_var.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/ip_var.h> @@ -38,6 +40,7 @@ static char sccsid[] = "@(#)ip_fil.c 2.37 4/10/96 (C) 1993-1995 Darren Reed"; #include <syslog.h> #endif #include "ip_fil.h" +#include "ip_fil_compat.h" #include "ip_frag.h" #include "ip_nat.h" #include "ip_state.h" @@ -62,7 +65,7 @@ int ipl_unreach = ICMP_UNREACH_FILTER; int send_reset(); #ifdef IPFILTER_LOG -#define LOGSIZE 8192 +# define LOGSIZE 8192 int ipllog(); static char iplbuf[LOGSIZE]; static caddr_t iplh = iplbuf, iplt = iplbuf; @@ -74,17 +77,17 @@ static int iplbusy = 0; static int (*fr_savep)(); #if _BSDI_VERSION >= 199510 -#include <sys/device.h> -#include <sys/conf.h> +# include <sys/device.h> +# include <sys/conf.h> int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); int iplopen __P((dev_t, int, int, struct proc *)); int iplclose __P((dev_t, int, int, struct proc *)); -#ifdef IPFILTER_LOG +# ifdef IPFILTER_LOG int iplread __P((dev_t, struct uio *, int)); -#else -#define iplread noread -#endif +# else +# define iplread noread +# endif int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); struct cfdriver iplcd = { @@ -97,7 +100,7 @@ struct devsw iplsw = { nostrat, nodump, nopsize, 0, nostop }; -#endif +#endif /* _BSDI_VERSION >= 199510 */ #ifdef IPFILTER_LKM int iplidentify(s) @@ -243,23 +246,32 @@ int mode; SPLNET(s); switch (cmd) { case FIONREAD : +#ifdef IPFILTER_LOG *(int *)data = iplused; +#endif break; #ifndef IPFILTER_LKM case SIOCFRENB : { u_int enable; - IRCOPY(data, (caddr_t)&enable, sizeof(enable)); - if (enable) - error = iplattach(); - else - error = ipldetach(); + if (!(mode & FWRITE)) + error = EPERM; + else { + IRCOPY(data, (caddr_t)&enable, sizeof(enable)); + if (enable) + error = iplattach(); + else + error = ipldetach(); + } break; } #endif case SIOCSETFF : - IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags)); + if (!(mode & FWRITE)) + error = EPERM; + else + IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags)); break; case SIOCGETFF : IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags)); @@ -267,17 +279,28 @@ int mode; case SIOCINAFR : case SIOCRMAFR : case SIOCADAFR : - error = frrequest(cmd, (struct frentry *)data, fr_active); + case SIOCZRLST : + if (!(mode & FWRITE)) + error = EPERM; + else + error = frrequest(cmd, data, fr_active); break; case SIOCINIFR : case SIOCRMIFR : case SIOCADIFR : - error = frrequest(cmd, (struct frentry *)data, 1-fr_active); + if (!(mode & FWRITE)) + error = EPERM; + else + error = frrequest(cmd, data, 1 - fr_active); break; case SIOCSWAPA : - bzero((char *)frcache, sizeof(frcache[0]) * 2); - *(u_int *)data = fr_active; - fr_active = 1 - fr_active; + if (!(mode & FWRITE)) + error = EPERM; + else { + bzero((char *)frcache, sizeof(frcache[0]) * 2); + *(u_int *)data = fr_active; + fr_active = 1 - fr_active; + } break; case SIOCGETFS : { @@ -298,23 +321,35 @@ int mode; break; } case SIOCFRZST : - frzerostats(data); + if (!(mode & FWRITE)) + error = EPERM; + else + frzerostats(data); break; case SIOCIPFFL : - frflush(data); + if (!(mode & FWRITE)) + error = EPERM; + else + frflush(data); break; #ifdef IPFILTER_LOG case SIOCIPFFB : - *(int *)data = iplused; - iplh = iplt = iplbuf; - iplused = 0; + if (!(mode & FWRITE)) + error = EPERM; + else { + *(int *)data = iplused; + iplh = iplt = iplbuf; + iplused = 0; + } break; #endif /* IPFILTER_LOG */ case SIOCADNAT : case SIOCRMNAT : case SIOCGNATS : case SIOCGNATL : - error = nat_ioctl(data, cmd); + case SIOCFLNAT : + case SIOCCNATL : + error = nat_ioctl(data, cmd, mode); break; case SIOCGFRST : IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t)); @@ -323,7 +358,7 @@ int mode; IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t)); break; default : - error = -EINVAL; + error = EINVAL; break; } SPLX(s); @@ -331,15 +366,20 @@ int mode; } -static int frrequest(req, fp, set) +static int frrequest(req, data, set) int req, set; -register struct frentry *fp; +caddr_t data; { - register struct frentry *f, **fprev; - register struct frentry **ftail; + register frentry_t *fp, *f, **fprev; + register frentry_t **ftail; + frentry_t fr; + frdest_t *fdp; struct frentry frd; int error = 0, in; + fp = &fr; + IRCOPY(data, (caddr_t)fp, sizeof(*fp)); + bzero((char *)frcache, sizeof(frcache[0]) * 2); in = (fp->fr_flags & FR_INQUE) ? 0 : 1; @@ -357,6 +397,24 @@ register struct frentry *fp; if (!fp->fr_ifa) fp->fr_ifa = (struct ifnet *)-1; } + + fdp = &fp->fr_dif; + fp->fr_flags &= ~FR_DUP; + if (*fdp->fd_ifname) { + fdp->fd_ifp = GETUNIT(fdp->fd_ifname); + if (!fdp->fd_ifp) + fdp->fd_ifp = (struct ifnet *)-1; + else + fp->fr_flags |= FR_DUP; + } + + fdp = &fp->fr_tif; + if (*fdp->fd_ifname) { + fdp->fd_ifp = GETUNIT(fdp->fd_ifname); + if (!fdp->fd_ifp) + fdp->fd_ifp = (struct ifnet *)-1; + } + /* * Look for a matching filter rule, but don't include the next or * interface pointer in the comparison (fr_next, fr_ifa). @@ -365,6 +423,19 @@ register struct frentry *fp; if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip, FR_CMPSIZ) == 0) break; + + /* + * If zero'ing statistics, copy current to caller and zero. + */ + if (req == SIOCZRLST) { + if (!f) + return ESRCH; + IWCOPY((caddr_t)f, data, sizeof(*f)); + f->fr_hits = 0; + f->fr_bytes = 0; + return 0; + } + if (!f) { ftail = fprev; if (req != SIOCINAFR && req != SIOCINIFR) @@ -417,10 +488,8 @@ int flags; { u_int min = minor(dev); - if ((flags & FWRITE) || min) + if (min) min = ENXIO; - else - iplbusy++; return min; } @@ -440,8 +509,6 @@ int flags; if (min) min = ENXIO; - else if (iplbusy > 0) - iplbusy--; return min; } @@ -467,12 +534,14 @@ register struct uio *uio; if (!uio->uio_resid) return 0; + iplbusy++; while (!iplused) { error = SLEEP(iplbuf, "ipl sleep"); - if (error) + if (error) { + iplbusy--; return error; + } } - SPLNET(s); sx = sz = MIN(uio->uio_resid, iplused); @@ -499,6 +568,7 @@ register struct uio *uio; iplh = iplt = iplbuf; } SPLX(s); + iplbusy--; return ret; } # endif /* IPFILTER_LOG */ @@ -553,16 +623,15 @@ struct mbuf *m; iplci.hlen = (u_char)hlen; iplci.plen = (flags & FR_LOGBODY) ? (u_char)mlen : 0 ; iplci.rule = fin->fin_rule; -#if !defined (__OpenBSD__) && !defined (__NetBSD__) +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) + strcpy(iplci.ifname, ifp->if_xname); +# else iplci.unit = (u_char)ifp->if_unit; - iplci.ifname[0] = ifp->if_name[0]; - iplci.ifname[1] = ifp->if_name[1]; - iplci.ifname[2] = ifp->if_name[2]; - iplci.ifname[3] = ifp->if_name[3]; -#else /* OpenBSD or NetBSD */ - bcopy (ifp->if_xname, iplci.ifname, IFNAMSIZ); -#endif /* OpenBSD or NetBSD */ - + if ((iplci.ifname[0] = ifp->if_name[0])) + if ((iplci.ifname[1] = ifp->if_name[1])) + if ((iplci.ifname[2] = ifp->if_name[2])) + iplci.ifname[3] = ifp->if_name[3]; +# endif if (iplh == iplbuf + LOGSIZE) iplh = iplbuf; tail = (iplh >= iplt) ? (iplbuf + LOGSIZE - iplh) : (iplt - iplh); @@ -665,11 +734,7 @@ struct tcpiphdr *ti; tp->ti_len = htons(sizeof(struct tcphdr)); tcp->th_sum = in_cksum(m, sizeof(struct tcpiphdr)); - ip->ip_hl = sizeof(struct ip) >> 2; - ip->ip_v = IPVERSION; ip->ip_tos = ((struct ip *)ti)->ip_tos; - ip->ip_id = ((struct ip *)ti)->ip_id; - ip->ip_off = ((struct ip *)ti)->ip_off; ip->ip_p = ((struct ip *)ti)->ip_p; ip->ip_len = sizeof (struct tcpiphdr); #if BSD < 199306 @@ -681,7 +746,7 @@ struct tcpiphdr *ti; /* * extra 0 in case of multicast */ - (void) ip_output(m, (struct mbuf *)0, 0, IP_FORWARDING, 0); + (void) ip_output(m, (struct mbuf *)0, 0, 0, 0); return 0; } @@ -689,7 +754,175 @@ struct tcpiphdr *ti; #ifndef IPFILTER_LKM iplinit() { - (void) iplattach(); + /* (void) iplattach(); */ ip_init(); } #endif + + +void ipfr_fastroute(m0, fin, fdp) +struct mbuf *m0; +fr_info_t *fin; +frdest_t *fdp; +{ + 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, s; + int hlen = fin->fin_hlen; + struct route iproute; + struct sockaddr_in *dst; + + ip = mtod(m0, struct ip *); + /* + * Route packet. + */ + ro = &iproute; + 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; +#if BSD >= 199306 && !(defined(__NetBSD__)) +# ifdef RTF_CLONING + rtalloc_ign(ro, RTF_CLONING); +# else + rtalloc_ign(ro, RTF_PRCLONING); +# endif +#else + rtalloc(ro); +#endif + if (!ifp) { + if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) { + error = -2; + goto bad; + } + if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { + if (in_localaddr(ip->ip_dst)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; + } + ro->ro_rt->rt_use++; + + /* + * If small enough for interface, can just send directly. + */ + if (ip->ip_len <= ifp->if_mtu) { +#ifndef sparc + ip->ip_id = htons(ip->ip_id); + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); +#endif + if (!ip->ip_sum) + ip->ip_sum = in_cksum(m, hlen); +#if BSD >= 199306 + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, + ro->ro_rt); + +#else + error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); +#endif + goto done; + } + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ + if (ip->ip_off & IP_DF) { + error = EMSGSIZE; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_act; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < ip->ip_len; off += len) { + MGET(m, M_DONTWAIT, MT_HEADER); + if (m == 0) { + error = ENOBUFS; + goto bad; + } +#if BSD >= 199306 + m->m_data += max_linkhdr; +#else + m->m_off = MMAXOFF - hlen; +#endif + mhip = mtod(m, struct ip *); + bcopy((char *)ip, (char *)mhip, sizeof(*ip)); + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + mhip->ip_hl = mhlen >> 2; + } + m->m_len = mhlen; + mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); + if (ip->ip_off & IP_MF) + mhip->ip_off |= IP_MF; + if (off + len >= ip->ip_len) + len = ip->ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((u_short)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + goto sendorfree; + } +#ifndef sparc + mhip->ip_off = htons((u_short)mhip->ip_off); +#endif + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + *mnext = m; + mnext = &m->m_act; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m_adj(m0, hlen + firstlen - ip->ip_len); + ip->ip_len = htons((u_short)(hlen + firstlen)); + ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m0, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_act; + m->m_act = 0; + if (error == 0) +#if BSD >= 199306 + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst, ro->ro_rt); +#else + error = (*ifp->if_output)(ifp, m, + (struct sockaddr *)dst); +#endif + else + m_freem(m); + } + } +done: + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + } + return; +bad: + m_freem(m); + goto done; +} diff --git a/sys/netinet/ip_fil.h b/sys/netinet/ip_fil.h index e80d977445e..29b5a1df2aa 100644 --- a/sys/netinet/ip_fil.h +++ b/sys/netinet/ip_fil.h @@ -5,7 +5,8 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * @(#)ip_fil.h 1.32 3/24/96 + * @(#)ip_fil.h 1.35 6/5/96 + * $Id: ip_fil.h,v 1.4 1996/07/18 05:00:59 dm Exp $ */ #ifndef __IP_FIL_H__ @@ -18,207 +19,6 @@ #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) - -#ifndef IP_OFFMASK -#define IP_OFFMASK 0x1fff -#endif - -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifdef _KERNEL -# if SOLARIS -# define MUTEX_ENTER(x) mutex_enter(x) -# define MUTEX_EXIT(x) mutex_exit(x) -# define MTOD(m,t) (t)((m)->b_rptr) -# define IRCOPY(a,b,c) copyin((a), (b), (c)) -# define IWCOPY(a,b,c) copyout((a), (b), (c)) -# else -# define MUTEX_ENTER(x) ; -# define MUTEX_EXIT(x) ; -# ifndef linux -# define MTOD(m,t) mtod(m,t) -# define IRCOPY(a,b,c) bcopy((a), (b), (c)) -# define IWCOPY(a,b,c) bcopy((a), (b), (c)) -# endif -# endif /* SOLARIS */ - -# ifdef sun -# if defined(__svr4__) || defined(__SVR4) -# define GETUNIT(n) get_unit((n)) -# else -# include <sys/kmem_alloc.h> -# define GETUNIT(n) ifunit((n), IFNAMSIZ) -# endif -# else -# define GETUNIT(n) ifunit((n)) -# endif /* sun */ - -# if defined(sun) && !defined(linux) -# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d) -# define SLEEP(id, n) sleep((id), PZERO+1) -# define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) -# if SOLARIS -typedef struct qif { - struct qif *qf_next; - ill_t *qf_ill; - kmutex_t qf_lock; - void *qf_iptr; - void *qf_optr; - queue_t *qf_in; - queue_t *qf_out; - void *qf_wqinfo; - void *qf_rqinfo; - char qf_name[8]; - int (*qf_inp)(); - int (*qf_outp)(); - /* - * in case the ILL has disappeared... - */ - int qf_hl; /* header length */ -} qif_t; -# define SPLNET(x) ; -# undef SPLX -# define SPLX(x) ; -# ifdef sparc -# define ntohs(x) (x) -# define ntohl(x) (x) -# define htons(x) (x) -# define htonl(x) (x) -# endif -# define KMALLOC(x) kmem_alloc((x), KM_SLEEP) -# define GET_MINOR(x) getminor(x) -# else -# define KMALLOC(x) new_kmem_alloc((x), KMEM_SLEEP) -# endif /* __svr4__ */ -# endif /* sun && !linux */ -# ifndef GET_MINOR -# define GET_MINOR(x) minor(x) -# endif -# if BSD >= 199306 || defined(__FreeBSD__) -# include <vm/vm.h> -# if !defined(__FreeBSD__) -# include <vm/vm_extern.h> -# include <sys/proc.h> -extern vm_map_t kmem_map; -# else -# include <vm/vm_kern.h> -# endif /* __FreeBSD__ */ -# define KMALLOC(x) kmem_alloc(kmem_map, (x)) -# define KFREE(x) kmem_free(kmem_map, (vm_offset_t)(x), \ - sizeof(*(x))) -# define UIOMOVE(a,b,c,d) uiomove(a,b,d) -# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) -# endif /* BSD */ -# if defined(NetBSD1_0) && (NetBSD1_0 > 1) -# define SPLNET(x) x = splsoftnet() -# else -# if !SOLARIS -# define SPLNET(x) x = splnet() -# define SPLX(x) (void) splx(x) -# endif -# endif -#else -# define MUTEX_ENTER(x) ; -# define MUTEX_EXIT(x) ; -# define SPLNET(x) ; -# define SPLX(x) ; -# define KMALLOC(x) malloc(x) -# define KFREE(x) free(x) -# define GETUNIT(x) (x) -# define IRCOPY(a,b,c) bcopy((a), (b), (c)) -# define IWCOPY(a,b,c) bcopy((a), (b), (c)) -#endif /* KERNEL */ - -#ifdef linux -# define ICMP_UNREACH ICMP_DEST_UNREACH -# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH -# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED -# define ICMP_PARAMPROB ICMP_PARAMETERPROB -# define icmp icmphdr -# define icmp_type type -# define icmp_code code - -# define TH_FIN 0x01 -# define TH_SYN 0x02 -# define TH_RST 0x04 -# define TH_PUSH 0x08 -# define TH_ACK 0x10 -# define TH_URG 0x20 - -typedef struct { - __u16 th_sport; - __u16 th_dport; - __u32 th_seq; - __u32 th_ack; - __u8 th_x; - __u8 th_flags; - __u16 th_win; - __u16 th_sum; - __u16 th_urp; -} tcphdr_t; - -typedef struct { - __u16 uh_sport; - __u16 uh_dport; - __u16 uh_ulen; - __u16 uh_sun; -} udphdr_t; - -typedef struct { -# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) - __u8 ip_hl:4; - __u8 ip_v:4; -# else - __u8 ip_hl:4; - __u8 ip_v:4; -# endif - __u8 ip_tos; - __u16 ip_len; - __u16 ip_id; - __u16 ip_off; - __u8 ip_ttl; - __u8 ip_p; - __u16 ip_sum; - __u32 ip_src; - __u32 ip_dst; -} ip_t; - -# define SPLX(x) (void) -# define SPLNET(x) (void) - -# define bcopy(a,b,c) memmove(b,a,c) -# define bcmp(a,b,c) memcmp(a,b,c) - -# define UNITNAME(n) dev_get((n)) -# define ifnet device - -# define KMALLOC(x) kmalloc((x), GFP_ATOMIC) -# define KFREE(x) kfree_s((x), sizeof(*(x))) -# define IRCOPY(a,b,c) { \ - error = verify_area(VERIFY_READ, \ - (b) ,sizeof((b))); \ - if (!error) \ - memcpy_fromfs((b), (a), (c)); \ - } -# define IWCOPY(a,b,c) { \ - error = verify_area(VERIFY_WRITE, \ - (b) ,sizeof((b))); \ - if (!error) \ - memcpy_tofs((b), (a), (c)); \ - } -#else -typedef struct tcphdr tcphdr_t; -typedef struct udphdr udphdr_t; -typedef struct ip ip_t; -#endif /* linux */ - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif #if defined(KERNEL) && !defined(_KERNEL) #define _KERNEL @@ -256,6 +56,9 @@ typedef struct ip ip_t; #define SIOCFRENB _IOW('r', 72, u_int) #define SIOCFRSYN _IOW('r', 73, u_int) #define SIOCFRZST _IOWR('r', 74, struct friostat) +#define SIOCFLNAT _IOWR('r', 75, int) +#define SIOCCNATL _IOWR('r', 76, int) +#define SIOCZRLST _IOWR('r', 77, struct frentry) #else #define SIOCADAFR _IOW(r, 60, struct frentry) #define SIOCRMAFR _IOW(r, 61, struct frentry) @@ -272,6 +75,9 @@ typedef struct ip ip_t; #define SIOCFRENB _IOW(r, 72, u_int) #define SIOCFRSYN _IOW(r, 73, u_int) #define SIOCFRZST _IOWR(r, 74, struct friostat) +#define SIOCFLNAT _IOWR(r, 75, int) +#define SIOCCNATL _IOWR(r, 76, int) +#define SIOCZRLST _IOWR(r, 77, struct frentry) #endif #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR @@ -311,6 +117,12 @@ typedef struct fr_info { #define FI_CSIZE (sizeof(struct fr_ip) + 11) +typedef struct frdest { + void *fd_ifp; + struct in_addr fd_ip; + char fd_ifname[IFNAMSIZ]; +} frdest_t; + typedef struct frentry { struct frentry *fr_next; struct ifnet *fr_ifa; @@ -336,8 +148,11 @@ typedef struct frentry { u_short fr_stop; /* top port for <> and >< */ u_short fr_dtop; /* top port for <> and >< */ u_long fr_flags; /* per-rule flags && options (see below) */ + int (*fr_func)(); /* call this function */ char fr_icode; /* return ICMP code */ char fr_ifname[IFNAMSIZ]; + struct frdest fr_tif; /* "to" interface */ + struct frdest fr_dif; /* duplicate packet interfaces */ } frentry_t; #define fr_proto fr_ip.fi_p @@ -356,29 +171,35 @@ typedef struct frentry { /* * fr_flags */ -#define FR_BLOCK 0x0001 -#define FR_PASS 0x0002 -#define FR_OUTQUE 0x0004 -#define FR_INQUE 0x0008 -#define FR_LOG 0x0010 /* Log */ -#define FR_LOGB 0x0021 /* Log-fail */ -#define FR_LOGP 0x0022 /* Log-pass */ -#define FR_LOGBODY 0x0040 /* Log the body */ -#define FR_LOGFIRST 0x0080 -#define FR_RETRST 0x0100 -#define FR_RETICMP 0x0200 -#define FR_NOMATCH 0x0400 -#define FR_ACCOUNT 0x0800 /* count packet bytes */ -#define FR_KEEPFRAG 0x1000 -#define FR_KEEPSTATE 0x2000 -#define FR_INACTIVE 0x4000 -#define FR_QUICK 0x8000 +#define FR_BLOCK 0x00001 +#define FR_PASS 0x00002 +#define FR_OUTQUE 0x00004 +#define FR_INQUE 0x00008 +#define FR_LOG 0x00010 /* Log */ +#define FR_LOGB 0x00011 /* Log-fail */ +#define FR_LOGP 0x00012 /* Log-pass */ +#define FR_LOGBODY 0x00020 /* Log the body */ +#define FR_LOGFIRST 0x00040 +#define FR_RETRST 0x00080 +#define FR_RETICMP 0x00100 +#define FR_NOMATCH 0x00200 +#define FR_ACCOUNT 0x00400 /* count packet bytes */ +#define FR_KEEPFRAG 0x00800 +#define FR_KEEPSTATE 0x01000 +#define FR_INACTIVE 0x02000 +#define FR_QUICK 0x04000 +#define FR_FASTROUTE 0x08000 +#define FR_CALLNOW 0x10000 +#define FR_DUP 0x20000 + +#define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB) /* * recognized flags for SIOCGETFF and SIOCSETFF */ #define FF_LOGPASS 0x100000 #define FF_LOGBLOCK 0x200000 #define FF_LOGNOMATCH 0x400000 +#define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH) #define FR_NONE 0 #define FR_EQUAL 1 @@ -437,14 +258,14 @@ typedef struct ipl_ci { u_char hlen; u_char plen; u_short rule; - u_long flags:24; -#if !defined (__OpenBSD__) && !defined (__NetBSD__) + u_long flags:24; /* XXX FIXME do we care about the extra bytes? */ +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) + u_long filler:8; /* XXX FIXME do we care? */ + u_char ifname[IFNAMSIZ]; +#else u_long unit:8; u_char ifname[4]; -#else /* OpenBSD or NetBSD */ - u_long : 0; - u_char ifname[IFNAMSIZ]; -#endif /* OpenBSD or NetBSD */ +#endif } ipl_ci_t; diff --git a/sys/netinet/ip_fil_compat.h b/sys/netinet/ip_fil_compat.h new file mode 100644 index 00000000000..70e30d11d8f --- /dev/null +++ b/sys/netinet/ip_fil_compat.h @@ -0,0 +1,216 @@ +/* + * (C)opyright 1993, 1994, 1995 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. + * + * @(#)ip_fil_compat.h 1.8 1/14/96 + * $Id: ip_fil_compat.h,v 1.1 1996/07/18 05:01:00 dm Exp $ + */ + +#ifndef __IP_COMPAT_H_ +#define __IP_COMPAT_H__ + +#ifndef SOLARIS +#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif +#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) + +#ifndef IP_OFFMASK +#define IP_OFFMASK 0x1fff +#endif + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifdef _KERNEL +# if SOLARIS +# define MUTEX_ENTER(x) mutex_enter(x) +# define MUTEX_EXIT(x) mutex_exit(x) +# define MTOD(m,t) (t)((m)->b_rptr) +# define IRCOPY(a,b,c) copyin((a), (b), (c)) +# define IWCOPY(a,b,c) copyout((a), (b), (c)) +# else +# define MUTEX_ENTER(x) ; +# define MUTEX_EXIT(x) ; +# ifndef linux +# define MTOD(m,t) mtod(m,t) +# define IRCOPY(a,b,c) bcopy((a), (b), (c)) +# define IWCOPY(a,b,c) bcopy((a), (b), (c)) +# endif +# endif /* SOLARIS */ + +# ifdef sun +# if defined(__svr4__) || defined(__SVR4) +# define GETUNIT(n) get_unit((n)) +# else +# include <sys/kmem_alloc.h> +# define GETUNIT(n) ifunit((n), IFNAMSIZ) +# endif +# else +# define GETUNIT(n) ifunit((n)) +# endif /* sun */ + +# if defined(sun) && !defined(linux) +# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d) +# define SLEEP(id, n) sleep((id), PZERO+1) +# define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) +# if SOLARIS +typedef struct qif { + struct qif *qf_next; + ill_t *qf_ill; + kmutex_t qf_lock; + void *qf_iptr; + void *qf_optr; + queue_t *qf_in; + queue_t *qf_out; + void *qf_wqinfo; + void *qf_rqinfo; + char qf_name[8]; + int (*qf_inp)(); + int (*qf_outp)(); + /* + * in case the ILL has disappeared... + */ + int qf_hl; /* header length */ +} qif_t; +# define SPLNET(x) ; +# undef SPLX +# define SPLX(x) ; +# ifdef sparc +# define ntohs(x) (x) +# define ntohl(x) (x) +# define htons(x) (x) +# define htonl(x) (x) +# endif +# define KMALLOC(x) kmem_alloc((x), KM_SLEEP) +# define GET_MINOR(x) getminor(x) +# else +# define KMALLOC(x) new_kmem_alloc((x), KMEM_SLEEP) +# endif /* __svr4__ */ +# endif /* sun && !linux */ +# ifndef GET_MINOR +# define GET_MINOR(x) minor(x) +# endif +# if BSD >= 199306 || defined(__FreeBSD__) +# include <vm/vm.h> +# if !defined(__FreeBSD__) +# include <vm/vm_extern.h> +# include <sys/proc.h> +extern vm_map_t kmem_map; +# else +# include <vm/vm_kern.h> +# endif /* __FreeBSD__ */ +# define KMALLOC(x) kmem_alloc(kmem_map, (x)) +# define KFREE(x) kmem_free(kmem_map, (vm_offset_t)(x), \ + sizeof(*(x))) +# define UIOMOVE(a,b,c,d) uiomove(a,b,d) +# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) +# endif /* BSD */ +# if defined(NetBSD1_0) && (NetBSD1_0 > 1) +# define SPLNET(x) x = splsoftnet() +# else +# if !SOLARIS +# define SPLNET(x) x = splnet() +# define SPLX(x) (void) splx(x) +# endif +# endif +#else +# define MUTEX_ENTER(x) ; +# define MUTEX_EXIT(x) ; +# define SPLNET(x) ; +# define SPLX(x) ; +# define KMALLOC(x) malloc(x) +# define KFREE(x) free(x) +# define GETUNIT(x) (x) +# define IRCOPY(a,b,c) bcopy((a), (b), (c)) +# define IWCOPY(a,b,c) bcopy((a), (b), (c)) +#endif /* KERNEL */ + +#ifdef linux +# define ICMP_UNREACH ICMP_DEST_UNREACH +# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH +# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED +# define ICMP_PARAMPROB ICMP_PARAMETERPROB +# define icmp icmphdr +# define icmp_type type +# define icmp_code code + +# define TH_FIN 0x01 +# define TH_SYN 0x02 +# define TH_RST 0x04 +# define TH_PUSH 0x08 +# define TH_ACK 0x10 +# define TH_URG 0x20 + +typedef struct { + __u16 th_sport; + __u16 th_dport; + __u32 th_seq; + __u32 th_ack; + __u8 th_x; + __u8 th_flags; + __u16 th_win; + __u16 th_sum; + __u16 th_urp; +} tcphdr_t; + +typedef struct { + __u16 uh_sport; + __u16 uh_dport; + __u16 uh_ulen; + __u16 uh_sun; +} udphdr_t; + +typedef struct { +# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ + defined(vax) + __u8 ip_hl:4; + __u8 ip_v:4; +# else + __u8 ip_hl:4; + __u8 ip_v:4; +# endif + __u8 ip_tos; + __u16 ip_len; + __u16 ip_id; + __u16 ip_off; + __u8 ip_ttl; + __u8 ip_p; + __u16 ip_sum; + __u32 ip_src; + __u32 ip_dst; +} ip_t; + +# define SPLX(x) (void) +# define SPLNET(x) (void) + +# define bcopy(a,b,c) memmove(b,a,c) +# define bcmp(a,b,c) memcmp(a,b,c) + +# define UNITNAME(n) dev_get((n)) +# define ifnet device + +# define KMALLOC(x) kmalloc((x), GFP_ATOMIC) +# define KFREE(x) kfree_s((x), sizeof(*(x))) +# define IRCOPY(a,b,c) { \ + error = verify_area(VERIFY_READ, \ + (b) ,sizeof((b))); \ + if (!error) \ + memcpy_fromfs((b), (a), (c)); \ + } +# define IWCOPY(a,b,c) { \ + error = verify_area(VERIFY_WRITE, \ + (b) ,sizeof((b))); \ + if (!error) \ + memcpy_tofs((b), (a), (c)); \ + } +#else +typedef struct tcphdr tcphdr_t; +typedef struct udphdr udphdr_t; +typedef struct ip ip_t; +#endif /* linux */ + +#endif /* __IP_COMPAT_H__ */ diff --git a/sys/netinet/ip_frag.c b/sys/netinet/ip_frag.c index 243448177f3..b193febd3e1 100644 --- a/sys/netinet/ip_frag.c +++ b/sys/netinet/ip_frag.c @@ -7,6 +7,7 @@ */ #ifndef lint static char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed"; +static char rcsid[] = "$Id: ip_frag.c,v 1.3 1996/07/18 05:01:02 dm Exp $"; #endif #if !defined(_KERNEL) && !defined(KERNEL) @@ -46,6 +47,7 @@ static char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed"; #include <netinet/ip_icmp.h> #include <syslog.h> #include "ip_fil.h" +#include "ip_fil_compat.h" #include "ip_frag.h" #include "ip_nat.h" #include "ip_state.h" diff --git a/sys/netinet/ip_frag.h b/sys/netinet/ip_frag.h index 61c79af3f72..6780071aa6c 100644 --- a/sys/netinet/ip_frag.h +++ b/sys/netinet/ip_frag.h @@ -6,6 +6,7 @@ * to the original author and the contributors. * * @(#)ip_frag.h 1.5 3/24/96 + * $Id: ip_frag.h,v 1.3 1996/07/18 05:01:03 dm Exp $ */ #ifndef __IP_FRAG_H_ @@ -25,11 +26,6 @@ typedef struct ipfr { u_char ipfr_pass; } ipfr_t; -#if defined(__STDC__) || defined(__GNUC__) -#define SIOCGFRST _IOR('r', 76, struct ipfrstat) -#else -#define SIOCGFRST _IOR(r, 76, struct ipfrstat) -#endif typedef struct ipfrstat { u_long ifs_exists; /* add & already exists */ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 94e0050aa85..5b8b0ba031f 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.12 1996/05/07 15:20:25 mickey Exp $ */ +/* $OpenBSD: ip_input.c,v 1.13 1996/07/18 05:01:04 dm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -100,8 +100,8 @@ int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddrhead in_ifaddr; struct ifqueue ipintrq; #if defined(IPFILTER) || defined(IPFILTER_LKM) -int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **) -); +int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, + struct mbuf **)); #endif diff --git a/sys/netinet/ip_nat.c b/sys/netinet/ip_nat.c index 34c91987124..b8b42874db4 100644 --- a/sys/netinet/ip_nat.c +++ b/sys/netinet/ip_nat.c @@ -17,9 +17,13 @@ * easy solution) * 2) There needs to be a way to flush the NATs table completely. Either * an ioctl, or an easy way of doing it from ipnat.c. + * + * Missing from RFC 1631: ICMP header checksum recalculations. + * */ #ifndef lint -static char sccsid[] = "@(#)ip_nat.c 1.9 4/10/96 (C) 1995 Darren Reed"; +static char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; +static char rcsid[] = "$Id: ip_nat.c,v 1.4 1996/07/18 05:01:05 dm Exp $"; #endif #if !defined(_KERNEL) && !defined(KERNEL) @@ -60,6 +64,7 @@ static char sccsid[] = "@(#)ip_nat.c 1.9 4/10/96 (C) 1995 Darren Reed"; #include <netinet/ip_icmp.h> #include <syslog.h> #include "ip_fil.h" +#include "ip_fil_compat.h" #include "ip_nat.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -103,19 +108,21 @@ extern kmutex_t ipf_nat; /* * Handle ioctls which manipulate the NAT. */ -int nat_ioctl(data, cmd) +int nat_ioctl(data, cmd, mode) caddr_t data; -int cmd; +int cmd, mode; { register ipnat_t *nat, *n, **np; - int error = 0; + ipnat_t natd; + int error = 0, ret; /* * For add/delete, look to see if the NAT entry is already present */ MUTEX_ENTER(&ipf_nat); if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) { - nat = (ipnat_t *)data; + IRCOPY(data, &natd, sizeof(natd)); + nat = &natd; for (np = &nat_list; (n = *np); np = &n->in_next) if (!bcmp((char *)&nat->in_port, (char *)&n->in_port, IPN_CMPSIZ)) @@ -125,6 +132,10 @@ int cmd; switch (cmd) { case SIOCADNAT : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } if (n) { error = EEXIST; break; @@ -148,6 +159,10 @@ int cmd; *np = n; break; case SIOCRMNAT : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } if (!n) { error = ESRCH; break; @@ -165,11 +180,7 @@ int cmd; { natlookup_t nl; nat_t *na; -#if !SOLARIS && defined(_KERNEL) - int s; -#endif - SPLNET(s); IRCOPY((char *)data, (char *)&nl, sizeof(nl)); if ((na = nat_lookupredir(&nl))) { nl.nl_inip = na->nat_outip; @@ -177,9 +188,24 @@ int cmd; IWCOPY((char *)&nl, (char *)data, sizeof(nl)); } else error = ESRCH; - SPLX(s); break; } + case SIOCFLNAT : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } + ret = flush_nattable(); + IWCOPY((caddr_t)&ret, data, sizeof(ret)); + break; + case SIOCCNATL : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } + ret = clear_natlist(); + IWCOPY((caddr_t)&ret, data, sizeof(ret)); + break; } MUTEX_EXIT(&ipf_nat); return error; @@ -187,9 +213,49 @@ int cmd; /* - * Create a new NAT table entry. + * flush_nattable - clear the NAT table of all mapping entries. + */ +int flush_nattable() +{ + nat_t *nat, **natp; + int i, j = 0; + + for (natp = &nat_table[0][0], i = NAT_SIZE - 1; i >= 0; i--, natp++) + while ((nat = *natp)) { + *natp = nat->nat_next; + KFREE((caddr_t)nat); + j++; + } + + for (natp = &nat_table[1][0], i = NAT_SIZE - 1; i >= 0; i--, natp++) + while ((nat = *natp)) { + *natp = nat->nat_next; + KFREE((caddr_t)nat); + j++; + } + return j; +} + + +/* + * clear_natlist - delete all entries in the active NAT mapping list. */ +int clear_natlist() +{ + register ipnat_t *n, **np; + int i = 0; + for (np = &nat_list; (n = *np); i++) { + *np = n->in_next; + KFREE(n); + } + return i; +} + + +/* + * Create a new NAT table entry. + */ nat_t *nat_new(np, ip, hlen, flags, direction) ipnat_t *np; ip_t *ip; @@ -213,7 +279,6 @@ int direction; if (!(nat = (nat_t *)KMALLOC(sizeof(*nat)))) return NULL; - /* * Search the current table for a match. */ diff --git a/sys/netinet/ip_nat.h b/sys/netinet/ip_nat.h index e3785d421d7..19ce04caa5a 100644 --- a/sys/netinet/ip_nat.h +++ b/sys/netinet/ip_nat.h @@ -6,6 +6,7 @@ * to the original author and the contributors. * * @(#)ip_nat.h 1.5 2/4/96 + * $Id: ip_nat.h,v 1.3 1996/07/18 05:01:06 dm Exp $ */ #ifndef __IP_NAT_H_ @@ -20,11 +21,15 @@ #define SIOCRMNAT _IOW('r', 81, struct ipnat) #define SIOCGNATS _IOR('r', 82, struct natstat) #define SIOCGNATL _IOWR('r', 83, struct natlookup) +#define SIOCGFRST _IOR('r', 84, struct ipfrstat) +#define SIOCGIPST _IOR('r', 85, struct ips_stat) #else #define SIOCADNAT _IOW(r, 80, struct ipnat) #define SIOCRMNAT _IOW(r, 81, struct ipnat) #define SIOCGNATS _IOR(r, 82, struct natstat) #define SIOCGNATL _IOWR(r, 83, struct natlookup) +#define SIOCGFRST _IOR(r, 84, struct ipfrstat) +#define SIOCGIPST _IOR(r, 85, struct ips_stat) #endif #define NAT_SIZE 367 diff --git a/sys/netinet/ip_state.c b/sys/netinet/ip_state.c index c6d1eff2d5f..946312cf4d7 100644 --- a/sys/netinet/ip_state.c +++ b/sys/netinet/ip_state.c @@ -6,7 +6,8 @@ * to the original author and the contributors. */ #ifndef lint -static char sccsid[] = "@(#)ip_state.c 1.6 3/24/96 (C) 1993-1995 Darren Reed"; +static char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-1995 Darren Reed"; +static char rcsid[] = "$Id: ip_state.c,v 1.3 1996/07/18 05:01:08 dm Exp $"; #endif #if !defined(_KERNEL) && !defined(KERNEL) @@ -48,6 +49,7 @@ static char sccsid[] = "@(#)ip_state.c 1.6 3/24/96 (C) 1993-1995 Darren Reed"; #include <syslog.h> #endif #include "ip_fil.h" +#include "ip_fil_compat.h" #include "ip_state.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -82,9 +84,9 @@ ips_stat_t *fr_statetstats() /* * Create a new ipstate structure and hang it off the hash table. */ -int fr_addstate(ip, hlen, pass) +int fr_addstate(ip, fin, pass) ip_t *ip; -int hlen; +fr_info_t *fin; u_int pass; { ipstate_t ips; @@ -106,7 +108,7 @@ u_int pass; { case IPPROTO_ICMP : { - struct icmp *ic = (struct icmp *)((char *)ip + hlen); + struct icmp *ic = (struct icmp *)fin->fin_dp; switch (ic->icmp_type) { @@ -129,7 +131,7 @@ u_int pass; } case IPPROTO_TCP : { - register tcphdr_t *tcp = (tcphdr_t *)((char *)ip + hlen); + register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; /* * The endian of the ports doesn't matter, but the ack and @@ -154,7 +156,7 @@ u_int pass; } case IPPROTO_UDP : { - register tcphdr_t *tcp = (tcphdr_t *)((char *)ip + hlen); + register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; hv += (is->is_dport = tcp->th_dport); hv += (is->is_sport = tcp->th_sport); @@ -175,7 +177,9 @@ u_int pass; MUTEX_ENTER(&ipf_state); is->is_next = ips_table[hv]; ips_table[hv] = is; - is->is_pass = pass & ~(FR_LOGFIRST|FR_LOG); + is->is_pass = pass; + if (pass & FR_LOGFIRST) + is->is_pass &= ~(FR_LOGFIRST|FR_LOG); ips_num++; MUTEX_EXIT(&ipf_state); return 0; @@ -303,9 +307,12 @@ fr_info_t *fin; * timeout. */ #ifdef _KERNEL - if ((tcp->th_flags & TCP_CLOSE) && - !is->is_age) - is->is_age = 120; + if (!is->is_age) { + if (tcp->th_flags & TH_FIN) + is->is_age = 120; + if (tcp->th_flags & TH_RST) + is->is_age = 1; + } MUTEX_EXIT(&ipf_state); return is->is_pass; #else diff --git a/sys/netinet/ip_state.h b/sys/netinet/ip_state.h index d22c930504d..b4aee7a4e14 100644 --- a/sys/netinet/ip_state.h +++ b/sys/netinet/ip_state.h @@ -6,6 +6,7 @@ * to the original author and the contributors. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed + * $Id: ip_state.h,v 1.2 1996/07/18 05:01:09 dm Exp $ */ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ @@ -55,11 +56,6 @@ typedef struct ipstate { #define is_sport is_tcp.ts_sport #define is_dport is_tcp.ts_dport -#if defined(__STDC__) || defined(__GNUC__) -#define SIOCGIPST _IOR('r', 75, struct ips_stat) -#else -#define SIOCGIPST _IOR(r, 75, struct ips_stat) -#endif typedef struct ips_stat { u_long iss_hits; |