Update ipfilter from 3.4.31 -> 3.4.35. Some important changes:

* block packets that fail to create state table entries
* only allow non-fragmented packets to influence whether or not a logged
  packet is the same as the one logged before.
* correct the ICMP packet checksum fixing up when processing ICMP errors for NAT
* implement a maximum for the number of entries in the NAT table (NAT_TABLE_MAX
  and ipf_nattable_max)
* frsynclist() wasn't paying attention to all the places where interface
  names are, like it should.
* fix comparing ICMP packets with established TCP state where only 8 bytes
  of header are returned in the ICMP error.

MFC after:	1 week
This commit is contained in:
Darren Reed 2004-06-21 22:46:36 +00:00
parent c38dd4b6bd
commit 7b807523f4
16 changed files with 695 additions and 395 deletions

View File

@ -42,6 +42,7 @@
# include <sys/mbuf.h>
# endif
#else
# include <sys/cmn_err.h>
# include <sys/byteorder.h>
# if SOLARIS2 < 5
# include <sys/dditypes.h>
@ -146,6 +147,9 @@ fr_info_t frcache[2];
static int frflushlist __P((int, minor_t, int *, frentry_t **));
#ifdef _KERNEL
static void frsynclist __P((frentry_t *));
# ifndef __sgi
static void *ipf_pullup __P((mb_t *, fr_info_t *, int, void *));
# endif
#endif
@ -194,19 +198,27 @@ struct optlist secopt[8] = {
* compact the IP header into a structure which contains just the info.
* which is useful for comparing IP headers with.
*/
void fr_makefrip(hlen, ip, fin)
int fr_makefrip(hlen, ip, fin)
int hlen;
ip_t *ip;
fr_info_t *fin;
{
u_short optmsk = 0, secmsk = 0, auth = 0;
int i, mv, ol, off, p, plen, v;
#if defined(_KERNEL)
# if SOLARIS
mb_t *m = fin->fin_qfm;
# else
mb_t *m = fin->fin_mp ? *fin->fin_mp : NULL;
# endif
#endif
fr_ip_t *fi = &fin->fin_fi;
struct optlist *op;
u_char *s, opt;
tcphdr_t *tcp;
fin->fin_rev = 0;
fin->fin_dp = NULL;
fin->fin_fr = NULL;
fin->fin_tcpf = 0;
fin->fin_data[0] = 0;
@ -220,8 +232,10 @@ fr_info_t *fin;
if (v == 4) {
fin->fin_id = ip->ip_id;
fi->fi_tos = ip->ip_tos;
#if (OpenBSD >= 200311) && defined(_KERNEL)
ip->ip_off = ntohs(ip->ip_off);
#endif
off = (ip->ip_off & IP_OFFMASK);
tcp = (tcphdr_t *)((char *)ip + hlen);
(*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
fi->fi_src.i6[1] = 0;
fi->fi_src.i6[2] = 0;
@ -235,6 +249,9 @@ fr_info_t *fin;
fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
if (ip->ip_off & (IP_MF|IP_OFFMASK))
fi->fi_fl |= FI_FRAG;
#if (OpenBSD >= 200311) && defined(_KERNEL)
ip->ip_len = ntohs(ip->ip_len);
#endif
plen = ip->ip_len;
fin->fin_dlen = plen - hlen;
}
@ -246,7 +263,6 @@ fr_info_t *fin;
p = ip6->ip6_nxt;
fi->fi_p = p;
fi->fi_ttl = ip6->ip6_hlim;
tcp = (tcphdr_t *)(ip6 + 1);
fi->fi_src.in6 = ip6->ip6_src;
fi->fi_dst.in6 = ip6->ip6_dst;
fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff);
@ -258,14 +274,23 @@ fr_info_t *fin;
}
#endif
else
return;
return -1;
fin->fin_off = off;
fin->fin_plen = plen;
fin->fin_dp = (char *)tcp;
tcp = (tcphdr_t *)((char *)ip + hlen);
fin->fin_misc = 0;
off <<= 3;
/*
* For both ICMPV6 & ICMP, we attempt to pullup the entire packet into
* a single buffer for recognised error return packets. Why? Because
* the entire data section of the ICMP payload is considered to be of
* significance and maybe required in NAT/state processing, so rather
* than be careful later, attempt to get it all in one buffeer first.
* For TCP we just make sure the _entire_ TCP header is in the first
* buffer for convienience.
*/
switch (p)
{
#ifdef USE_INET6
@ -274,7 +299,7 @@ fr_info_t *fin;
int minicmpsz = sizeof(struct icmp6_hdr);
struct icmp6_hdr *icmp6;
if (fin->fin_dlen > 1) {
if (!(fin->fin_fl & FI_SHORT) && (fin->fin_dlen > 1)) {
fin->fin_data[0] = *(u_short *)tcp;
icmp6 = (struct icmp6_hdr *)tcp;
@ -289,6 +314,14 @@ fr_info_t *fin;
case ICMP6_PACKET_TOO_BIG :
case ICMP6_TIME_EXCEEDED :
case ICMP6_PARAM_PROB :
# if defined(KERNEL) && !defined(__sgi)
if ((m != NULL) && (M_BLEN(m) < plen)) {
ip = ipf_pullup(m, fin, plen, ip);
if (ip == NULL)
return -1;
tcp = (tcphdr_t *)((char *)ip + hlen);
}
# endif /* KERNEL && !__sgi */
minicmpsz = ICMP6ERR_IPICMPHLEN;
break;
default :
@ -296,22 +329,27 @@ fr_info_t *fin;
}
}
if (!(plen >= minicmpsz))
if (!(fin->fin_dlen >= minicmpsz))
fi->fi_fl |= FI_SHORT;
break;
}
#endif
#endif /* USE_INET6 */
case IPPROTO_ICMP :
{
int minicmpsz = sizeof(struct icmp);
icmphdr_t *icmp;
if (!off && (fin->fin_dlen > 1)) {
if (!off && (fin->fin_dlen > 1) && !(fin->fin_fl & FI_SHORT)) {
fin->fin_data[0] = *(u_short *)tcp;
icmp = (icmphdr_t *)tcp;
/*
* Minimum ICMP packet is type(1) code(1) cksum(2)
* plus 4 bytes following, totalling 8 bytes.
*/
switch (icmp->icmp_type)
{
case ICMP_ECHOREPLY :
@ -327,7 +365,7 @@ fr_info_t *fin;
*/
case ICMP_TSTAMP :
case ICMP_TSTAMPREPLY :
minicmpsz = 20;
minicmpsz = ICMP_MINLEN + 12;
break;
/*
* type(1) + code(1) + cksum(2) + id(2) seq(2) +
@ -335,9 +373,28 @@ fr_info_t *fin;
*/
case ICMP_MASKREQ :
case ICMP_MASKREPLY :
minicmpsz = 12;
minicmpsz = ICMP_MINLEN + 4;
break;
/*
* type(1) + code(1) + cksum(2) + arg(4) ip(20+)
*/
case ICMP_UNREACH :
case ICMP_SOURCEQUENCH :
case ICMP_REDIRECT :
case ICMP_TIMXCEED :
case ICMP_PARAMPROB :
#if defined(KERNEL) && !defined(__sgi)
if ((m != NULL) && (M_BLEN(m) < plen)) {
ip = ipf_pullup(m, fin, plen, ip);
if (ip == NULL)
return -1;
tcp = (tcphdr_t *)((char *)ip + hlen);
}
#endif /* KERNEL && !__sgi */
minicmpsz = ICMPERR_MINPKTLEN - sizeof(ip_t);
break;
default :
minicmpsz = ICMP_MINLEN;
break;
}
}
@ -345,9 +402,9 @@ fr_info_t *fin;
if ((!(plen >= hlen + minicmpsz) && !off) ||
(off && off < sizeof(struct icmp)))
fi->fi_fl |= FI_SHORT;
break;
}
case IPPROTO_TCP :
fi->fi_fl |= FI_TCPUDP;
#ifdef USE_INET6
@ -361,6 +418,20 @@ fr_info_t *fin;
(off && off < sizeof(struct tcphdr)))
fi->fi_fl |= FI_SHORT;
}
#if defined(KERNEL) && !defined(__sgi)
if (!off && !(fi->fi_fl & FI_SHORT)) {
int tlen = hlen + (tcp->th_off << 2);
if ((m != NULL) && (M_BLEN(m) < tlen)) {
ip = ipf_pullup(m, fin, tlen, ip);
if (ip == NULL)
return -1;
tcp = (tcphdr_t *)((char *)ip + hlen);
}
}
#endif /* _KERNEL && !_sgi */
if (!(fi->fi_fl & FI_SHORT) && !off)
fin->fin_tcpf = tcp->th_flags;
goto getports;
@ -400,12 +471,14 @@ getports:
break;
}
fin->fin_dp = (char *)tcp;
#ifdef USE_INET6
if (v == 6) {
fi->fi_optmsk = 0;
fi->fi_secmsk = 0;
fi->fi_auth = 0;
return;
return 0;
}
#endif
@ -462,6 +535,7 @@ getports:
fi->fi_optmsk = optmsk;
fi->fi_secmsk = secmsk;
fi->fi_auth = auth;
return 0;
}
@ -749,7 +823,7 @@ void *m;
#endif /* IPFILTER_LOG */
ATOMIC_INCL(fr->fr_hits);
if (passt & FR_ACCOUNT)
fr->fr_bytes += (U_QUAD_T)ip->ip_len;
fr->fr_bytes += (U_QUAD_T)fin->fin_plen;
else
fin->fin_icode = fr->fr_icode;
fin->fin_rule = rulen;
@ -812,12 +886,17 @@ int out;
int p, len, drop = 0, logit = 0;
mb_t *mc = NULL;
# if !defined(__SVR4) && !defined(__svr4__)
/*
* We don't do this section for Solaris because fr_precheck() does a
* pullupmsg() instead, effectively achieving the same result as here
* so no need to duplicate it.
*/
# ifdef __sgi
char hbuf[128];
# endif
int up;
# if !SOLARIS && !defined(NETBSD_PF) && \
# if !defined(NETBSD_PF) && \
((defined(__FreeBSD__) && (__FreeBSD_version < 500011)) || \
defined(__OpenBSD__) || defined(_BSDI_VERSION))
if (fr_checkp != fr_check && fr_running > 0) {
@ -855,7 +934,7 @@ int out;
}
# endif /* CSUM_DELAY_DATA */
# ifdef USE_INET6
# ifdef USE_INET6
if (v == 6) {
len = ntohs(((ip6_t*)ip)->ip6_plen);
if (!len)
@ -863,17 +942,20 @@ int out;
len += sizeof(ip6_t);
p = ((ip6_t *)ip)->ip6_nxt;
} else
# endif
# endif
{
p = ip->ip_p;
len = ip->ip_len;
}
fin->fin_mp = mp;
fin->fin_out = out;
if ((p == IPPROTO_TCP || p == IPPROTO_UDP ||
(v == 4 && p == IPPROTO_ICMP)
# ifdef USE_INET6
# ifdef USE_INET6
|| (v == 6 && p == IPPROTO_ICMPV6)
# endif
# endif
)) {
int plen = 0;
@ -893,7 +975,7 @@ int out;
case IPPROTO_ESP:
plen = 8;
break;
# ifdef USE_INET6
# ifdef USE_INET6
case IPPROTO_ICMPV6 :
/*
* XXX does not take intermediate header
@ -901,8 +983,10 @@ int out;
*/
plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t);
break;
# endif
# endif
}
if ((plen > 0) && (len < hlen + plen))
fin->fin_fl |= FI_SHORT;
up = MIN(hlen + plen, len);
if (up > m->m_len) {
@ -917,14 +1001,34 @@ int out;
ip = (ip_t *)hbuf;
# else /* __ sgi */
# ifndef linux
if ((*mp = m_pullup(m, up)) == 0) {
ATOMIC_INCL(frstats[out].fr_pull[1]);
/*
* Having determined that we need to pullup some data,
* try to bring as much of the packet up into a single
* buffer with the first pullup. This hopefully means
* less need for doing futher pullups. Not needed for
* Solaris because fr_precheck() does it anyway.
*
* The main potential for trouble here is if MLEN/MHLEN
* become quite small, lets say < 64 bytes...but if
* that did happen, BSD networking as a whole would be
* slow/inefficient.
*/
# ifdef MHLEN
/*
* Assume that M_PKTHDR is set and just work with what
* is left rather than check.. Should not make any
* real difference, anyway.
*/
if ((MHLEN > up) && (len > up))
up = MIN(len, MHLEN);
# else
if ((MLEN > up) && (len > up))
up = MIN(len, MLEN);
# endif
ip = ipf_pullup(m, fin, up, ip);
if (ip == NULL)
return -1;
} else {
ATOMIC_INCL(frstats[out].fr_pull[0]);
m = *mp;
ip = mtod(m, ip_t *);
}
m = *mp;
# endif /* !linux */
# endif /* __sgi */
} else
@ -937,9 +1041,14 @@ int out;
if ((u_int)ip & 0x3)
return 2;
fin->fin_mp = mp;
fin->fin_out = out;
fin->fin_qfm = m;
fin->fin_qif = qif;
# endif
#else
fin->fin_mp = mp;
fin->fin_out = out;
#endif /* _KERNEL */
#ifndef __FreeBSD__
@ -952,11 +1061,10 @@ int out;
#endif
changed = 0;
fin->fin_ifp = ifp;
fin->fin_v = v;
fin->fin_out = out;
fin->fin_mp = mp;
fr_makefrip(hlen, ip, fin);
fin->fin_ifp = ifp;
if (fr_makefrip(hlen, ip, fin) == -1)
return -1;
#ifdef _KERNEL
# ifdef USE_INET6
@ -1120,6 +1228,10 @@ int out;
if (pass & FR_KEEPSTATE) {
if (fr_addstate(ip, fin, NULL, 0) == NULL) {
ATOMIC_INCL(frstats[out].fr_bads);
if (pass & FR_PASS) {
pass &= ~FR_PASS;
pass |= FR_BLOCK;
}
} else {
ATOMIC_INCL(frstats[out].fr_ads);
}
@ -1306,6 +1418,12 @@ logit:
(void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif);
}
# endif /* !SOLARIS */
#if (OpenBSD >= 200311) && defined(_KERNEL)
if (pass & FR_PASS) {
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
}
#endif
return (pass & FR_PASS) ? 0 : error;
#else /* _KERNEL */
if (pass & FR_NOMATCH)
@ -1403,10 +1521,10 @@ tcphdr_t *tcp;
/*
* Both sum and sum2 are partial sums, so combine them together.
*/
sum = (sum & 0xffff) + (sum >> 16);
sum = ~sum & 0xffff;
sum2 += sum;
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
sum += ~sum2 & 0xffff;
while (sum > 0xffff)
sum = (sum & 0xffff) + (sum >> 16);
sum2 = ~sum & 0xffff;
# else /* defined(BSD) || defined(sun) */
{
union {
@ -1543,7 +1661,7 @@ nodata:
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
* $Id: fil.c,v 2.35.2.67 2002/12/06 13:28:05 darrenr Exp $
* $Id: fil.c,v 2.35.2.82 2004/06/20 10:27:47 darrenr Exp $
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
@ -1975,12 +2093,40 @@ struct in_addr *inp;
static void frsynclist(fr)
register frentry_t *fr;
{
frdest_t *fdp;
int i;
for (; fr; fr = fr->fr_next) {
if (fr->fr_ifa != NULL) {
fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v);
if (fr->fr_ifa == NULL)
fr->fr_ifa = (void *)-1;
for (i = 0; i < 4; i++) {
if ((fr->fr_ifnames[i][1] == '\0') &&
((fr->fr_ifnames[i][0] == '-') ||
(fr->fr_ifnames[i][0] == '*'))) {
fr->fr_ifas[i] = NULL;
} else if (*fr->fr_ifnames[i]) {
fr->fr_ifas[i] = GETUNIT(fr->fr_ifnames[i],
fr->fr_v);
if (!fr->fr_ifas[i])
fr->fr_ifas[i] = (void *)-1;
}
}
fdp = &fr->fr_dif;
fr->fr_flags &= ~FR_DUP;
if (*fdp->fd_ifname) {
fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fr->fr_v);
if (!fdp->fd_ifp)
fdp->fd_ifp = (struct ifnet *)-1;
else
fr->fr_flags |= FR_DUP;
}
fdp = &fr->fr_tif;
if (*fdp->fd_ifname) {
fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fr->fr_v);
if (!fdp->fd_ifp)
fdp->fd_ifp = (struct ifnet *)-1;
}
if (fr->fr_grp)
frsynclist(fr->fr_grp);
}
@ -2013,6 +2159,9 @@ void frsync()
IFNET_RUNLOCK();
# endif
ip_natsync((struct ifnet *)-1);
# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043)
IFNET_RUNLOCK();
# endif
# endif /* !SOLARIS */
WRITE_ENTER(&ipf_mutex);
@ -2241,3 +2390,64 @@ mb_t *buf;
return ip->ip_len;
}
#endif
#if defined(_KERNEL) && !defined(__sgi)
void *ipf_pullup(m, fin, len, ipin)
mb_t *m;
fr_info_t *fin;
int len;
void *ipin;
{
# if SOLARIS
qif_t *qf = fin->fin_qif;
# endif
int out = fin->fin_out, dpoff, ipoff;
char *ip;
if (m == NULL)
return NULL;
ipoff = (char *)ipin - MTOD(m, char *);
if (fin->fin_dp != NULL)
dpoff = (char *)fin->fin_dp - (char *)ipin;
else
dpoff = 0;
if (M_BLEN(m) < len) {
# if SOLARIS
qif_t *qf = fin->fin_qif;
int inc = 0;
if (ipoff > 0) {
if ((ipoff & 3) != 0) {
inc = 4 - (ipoff & 3);
if (m->b_rptr - inc >= m->b_datap->db_base)
m->b_rptr -= inc;
else
inc = 0;
}
}
if (!pullupmsg(m, len + ipoff + inc)) {
ATOMIC_INCL(frstats[out].fr_pull[1]);
return NULL;
}
m->b_rptr += inc;
ATOMIC_INCL(frstats[out].fr_pull[0]);
qf->qf_data = MTOD(m, char *) + ipoff;
# else
m = m_pullup(m, len);
*fin->fin_mp = m;
if (m == NULL) {
ATOMIC_INCL(frstats[out].fr_pull[1]);
return NULL;
}
ATOMIC_INCL(frstats[out].fr_pull[0]);
# endif /* SOLARIS */
}
ip = MTOD(m, char *) + ipoff;
if (fin->fin_dp != NULL)
fin->fin_dp = (char *)ip + dpoff;
return ip;
}
#endif /* _KERNEL */

View File

@ -320,7 +320,9 @@ int cmd;
#endif
{
mb_t *m;
#if defined(_KERNEL) && !SOLARIS
#if defined(_KERNEL) && !SOLARIS && \
(!defined(__FreeBSD_version) || (__FreeBSD_version < 501000))
struct ifqueue *ifq;
int s;
#endif
frauth_t auth, *au = &auth, *fra;
@ -423,8 +425,8 @@ fr_authioctlloop:
bzero((char *)&ro, sizeof(ro));
# if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \
defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) || \
(__FreeBSD_version >= 500042)
defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) || \
(__FreeBSD_version >= 470102)
error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL,
NULL);
# else
@ -442,8 +444,22 @@ fr_authioctlloop:
# if SOLARIS
error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0;
# else /* SOLARIS */
if (! netisr_queue(NETISR_IP, m))
# if __FreeBSD_version >= 501104
if (! netisr_dispatch(NETISR_IP, m))
error = ENOBUFS;
# else
ifq = &ipintrq;
if (IF_QFULL(ifq)) {
IF_DROP(ifq);
m_freem(m);
error = ENOBUFS;
} else {
IF_ENQUEUE(ifq, m);
# if IRIX < 605
schednetisr(NETISR_IP);
# endif
}
# endif
# endif /* SOLARIS */
if (error)
fr_authstats.fas_quefail++;

View File

@ -66,7 +66,7 @@
#if defined(__sgi) || defined(bsdi)
struct ether_addr {
u_char ether_addr_octet[6];
u_char ether_addr_octet[6];
};
#endif
@ -164,6 +164,7 @@ struct file;
# define V4_PART_OF_V6(v6) v6.s6_addr32[3]
# endif
# endif
# define M_BLEN(m) ((m)->b_wptr - (m)->b_rptr)
typedef struct qif {
struct qif *qf_next;
@ -173,6 +174,7 @@ typedef struct qif {
void *qf_optr;
queue_t *qf_in;
queue_t *qf_out;
void *qf_data; /* layer 3 header pointer */
struct qinit *qf_wqinfo;
struct qinit *qf_rqinfo;
struct qinit qf_wqinit;
@ -525,6 +527,7 @@ extern ill_t *get_unit __P((char *, int));
# ifndef linux
# define FREE_MB_T(m) m_freem(m)
# define MTOD(m,t) mtod(m,t)
# define M_BLEN(m) (m)->m_len
# define IRCOPY(a,b,c) (bcopy((a), (b), (c)), 0)
# define IWCOPY(a,b,c) (bcopy((a), (b), (c)), 0)
# define IRCOPYPTR ircopyptr
@ -963,7 +966,7 @@ typedef struct {
__u32 th_seq;
__u32 th_ack;
# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
defined(vax)
defined(__vax__)
__u8 th_res:4;
__u8 th_off:4;
#else
@ -985,7 +988,7 @@ typedef struct {
typedef struct {
# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
defined(vax)
defined(__vax__)
__u8 ip_hl:4;
__u8 ip_v:4;
# else
@ -1209,8 +1212,8 @@ struct ether_addr {
#define ICMPERR_MINPKTLEN (20 + 8 + 20)
#define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8)
#define ICMP6_MINLEN 8
#define ICMP6ERR_MINPKTLEN (40 + 8)
#define ICMP6ERR_IPICMPHLEN (40 + 8 + 40)
#define ICMP6ERR_IPICMPHLEN (40 + 8)
#define ICMP6ERR_MINPKTLEN (40 + 8 + 40)
#ifndef ICMP6_DST_UNREACH
# define ICMP6_DST_UNREACH 1

View File

@ -537,7 +537,7 @@ int ipldetach()
# if (__NetBSD_Version__ >= 105150000) || (__FreeBSD_version >= 501108)
struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
# ifdef USE_INET6
struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
# endif
# endif
#endif
@ -1055,8 +1055,8 @@ caddr_t data;
while ((f = *ftail))
ftail = &f->fr_next;
else {
ftail = fprev;
if (fp->fr_hits) {
ftail = fprev;
while (--fp->fr_hits && (f = *ftail))
ftail = &f->fr_next;
}
@ -1310,7 +1310,7 @@ struct mbuf **mp;
frn.fin_ifp = fin->fin_ifp;
frn.fin_v = fin->fin_v;
frn.fin_out = fin->fin_out;
frn.fin_mp = fin->fin_mp;
frn.fin_mp = mp;
ip = mtod(m, ip_t *);
hlen = sizeof(*ip);
@ -1354,9 +1354,10 @@ struct mbuf **mp;
m->m_pkthdr.rcvif = NULL;
# endif
fr_makefrip(hlen, ip, &frn);
error = ipfr_fastroute(m, mp, &frn, NULL);
if (fr_makefrip(hlen, ip, &frn) == 0)
error = ipfr_fastroute(m, mp, &frn, NULL);
else
error = EINVAL;
return error;
}
@ -1489,7 +1490,13 @@ int dst;
#endif
if (avail) {
slen = oip->ip_len;
oip->ip_len = htons(oip->ip_len);
soff = oip->ip_off;
oip->ip_off = htons(oip->ip_off);
bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail));
oip->ip_len = slen;
oip->ip_off = soff;
avail -= MIN(ohlen, avail);
}
@ -1510,10 +1517,6 @@ int dst;
} else
#endif
{
slen = oip->ip_len;
oip->ip_len = htons(oip->ip_len);
soff = oip->ip_off;
oip->ip_off = htons(ip->ip_off);
ip->ip_src.s_addr = dst4.s_addr;
ip->ip_dst.s_addr = oip->ip_src.s_addr;
@ -1533,13 +1536,7 @@ int dst;
fin->fin_hlen = hlen;
err = send_ip(oip, fin, &m);
fin->fin_hlen = shlen;
#ifdef USE_INET6
if (fin->fin_v == 4)
#endif
{
oip->ip_len = slen;
oip->ip_off = soff;
}
return err;
}
@ -1597,7 +1594,7 @@ frdest_t *fdp;
register struct ip *ip, *mhip;
register struct mbuf *m = m0;
register struct route *ro;
int len, off, error = 0, hlen, code;
int len, off, error = 0, hlen, code, sout;
struct ifnet *ifp, *sifp;
struct sockaddr_in *dst;
struct route iproute;
@ -1663,7 +1660,7 @@ frdest_t *fdp;
/*
* Route packet.
*/
#if defined(__sgi) && (IRIX >= 605)
#if (defined(IRIX) && (IRIX >= 605))
ROUTE_RDLOCK();
#endif
bzero((caddr_t)ro, sizeof (*ro));
@ -1682,8 +1679,12 @@ frdest_t *fdp;
* check that we're going in the correct direction.
*/
if ((fr != NULL) && (fin->fin_rev != 0)) {
if ((ifp != NULL) && (fdp == &fr->fr_tif))
if ((ifp != NULL) && (fdp == &fr->fr_tif)) {
# if (defined(IRIX) && (IRIX >= 605))
ROUTE_UNLOCK();
# endif
return 0;
}
} else if (fdp != NULL) {
if (fdp->fd_ip.s_addr != 0)
dst->sin_addr = fdp->fd_ip;
@ -1703,13 +1704,12 @@ frdest_t *fdp;
rtalloc(ro);
# endif
#if defined(__sgi) && (IRIX > 602)
ROUTE_UNLOCK();
#endif
if (!ifp) {
if (!fr || !(fr->fr_flags & FR_FASTROUTE)) {
error = -2;
# if (defined(IRIX) && (IRIX >= 605))
ROUTE_UNLOCK();
# endif
goto bad;
}
}
@ -1722,11 +1722,14 @@ frdest_t *fdp;
error = EHOSTUNREACH;
else
error = ENETUNREACH;
# if (defined(IRIX) && (IRIX >= 605))
ROUTE_UNLOCK();
# endif
goto bad;
}
if (ro->ro_rt->rt_flags & RTF_GATEWAY) {
#if BSD >= 199306
#if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
#else
dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
@ -1734,6 +1737,10 @@ frdest_t *fdp;
}
ro->ro_rt->rt_use++;
#if (defined(IRIX) && (IRIX > 602))
ROUTE_UNLOCK();
#endif
/*
* For input packets which are being "fastrouted", they won't
* go back through output filtering and miss their chance to get
@ -1741,6 +1748,7 @@ frdest_t *fdp;
*/
if (fin->fin_out == 0) {
sifp = fin->fin_ifp;
sout = fin->fin_out;
fin->fin_ifp = ifp;
fin->fin_out = 1;
if ((fin->fin_fr = ipacct[1][fr_active]) &&
@ -1750,10 +1758,25 @@ frdest_t *fdp;
fin->fin_fr = NULL;
if (!fr || !(fr->fr_flags & FR_RETMASK))
(void) fr_checkstate(ip, fin);
(void) ip_natout(ip, fin);
switch (ip_natout(ip, fin))
{
case 0 :
break;
case 1 :
ip->ip_sum = 0;
break;
case -1 :
error = EINVAL;
goto done;
break;
}
fin->fin_ifp = sifp;
fin->fin_out = sout;
} else
ip->ip_sum = 0;
/*
* If small enough for interface, can just send directly.
*/
@ -1783,8 +1806,14 @@ frdest_t *fdp;
ip->ip_sum = in_cksum(m, hlen);
# endif /* __NetBSD__ && M_CSUM_IPv4 */
# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
# ifdef IRIX
IFNET_UPPERLOCK(ifp);
# endif
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro->ro_rt);
# ifdef IRIX
IFNET_UPPERUNLOCK(ifp);
# endif
# else
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
# endif
@ -1930,7 +1959,7 @@ void *ifp;
dst->sin_family = AF_INET;
dst->sin_addr = ipa;
# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
!defined(__OpenBSD__)
!defined(__OpenBSD__)
# ifdef RTF_CLONING
rtalloc_ign(&iproute, RTF_CLONING);
# else
@ -1982,17 +2011,18 @@ frdest_t *fdp;
u_long mtu;
int error;
ifp = NULL;
ro = &ip6route;
fr = fin->fin_fr;
bzero((caddr_t)ro, sizeof(*ro));
dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
dst6->sin6_family = AF_INET6;
dst6->sin6_len = sizeof(struct sockaddr_in6);
dst6->sin6_addr = fin->fin_fi.fi_src.in6;
dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
if (fdp != NULL)
ifp = fdp->fd_ifp;
else
ifp = fin->fin_ifp;
if ((fr != NULL) && (fin->fin_rev != 0)) {
if ((ifp != NULL) && (fdp == &fr->fr_tif))
@ -2001,9 +2031,14 @@ frdest_t *fdp;
if (IP6_NOTZERO(&fdp->fd_ip6))
dst6->sin6_addr = fdp->fd_ip6.in6;
}
if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE)))
if (ifp == NULL)
return -2;
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
/* KAME */
if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
#endif
rtalloc((struct route *)ro);
if ((ifp == NULL) && (ro->ro_rt != NULL))
@ -2024,10 +2059,15 @@ frdest_t *fdp;
error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu);
if (error == 0) {
#else
#ifdef ND_IFINFO
# ifdef IN6_LINKMTU
mtu = IN6_LINKMTU(ifp);
# else
# ifdef ND_IFINFO
mtu = ND_IFINFO(ifp)->linkmtu;
#else
# else
mtu = nd_ifinfo[ifp->if_index].linkmtu;
# endif
# endif
#endif
#endif
if (m0->m_pkthdr.len <= mtu)

View File

@ -152,7 +152,7 @@ typedef struct fr_info {
u_short fin_dlen; /* length of data portion of packet */
u_short fin_id; /* IP packet id field */
u_int fin_misc;
void *fin_mp; /* pointer to pointer to mbuf */
mb_t **fin_mp; /* pointer to pointer to mbuf */
#if SOLARIS
void *fin_qfm; /* pointer to mblk where pkt starts */
void *fin_qif;
@ -630,7 +630,7 @@ extern void fr_forgetifp __P((void *));
extern void fr_getstat __P((struct friostat *));
extern int fr_ifpaddr __P((int, void *, struct in_addr *));
extern int fr_lock __P((caddr_t, int *));
extern void fr_makefrip __P((int, ip_t *, fr_info_t *));
extern int fr_makefrip __P((int, ip_t *, fr_info_t *));
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 int fr_tcpudpchk __P((frtuc_t *, fr_info_t *));

View File

@ -195,7 +195,7 @@ ipfr_t *table[];
/*
* Instert the fragment into the fragment table, copy the struct used
* Insert 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.
*/
@ -423,7 +423,26 @@ fr_info_t *fin;
/*
* forget any references to this external object.
*/
void ipfr_forget(nat)
void ipfr_forget(ptr)
void *ptr;
{
ipfr_t *fr;
int idx;
WRITE_ENTER(&ipf_frag);
for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next)
if (fr->ipfr_data == ptr)
fr->ipfr_data = NULL;
RWLOCK_EXIT(&ipf_frag);
}
/*
* forget any references to this external object.
*/
void ipfr_forgetnat(nat)
void *nat;
{
ipfr_t *fr;
@ -431,7 +450,7 @@ void *nat;
WRITE_ENTER(&ipf_natfrag);
for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next)
for (fr = ipfr_nattab[idx]; fr; fr = fr->ipfr_next)
if (fr->ipfr_data == nat)
fr->ipfr_data = NULL;

View File

@ -54,6 +54,7 @@ extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, struct nat *));
extern nat_t *ipfr_nat_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_forgetnat __P((void *));
extern void ipfr_unload __P((void));
extern void ipfr_fragexpire __P((void));

View File

@ -121,7 +121,7 @@ int dlen;
int inc, off;
nat_t *ipn;
mb_t *m;
#if SOLARIS
#if SOLARIS && defined(_KERNEL)
mb_t *m1;
#endif
@ -207,8 +207,13 @@ int dlen;
a1 >>= 24;
olen = s - f->ftps_rptr;
/* DO NOT change this to snprintf! */
#if defined(OpenBSD) && (200311 >= 200311)
(void) snprintf(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n",
"PORT", a1, a2, a3, a4, a5, a6);
#else
(void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n",
"PORT", a1, a2, a3, a4, a5, a6);
#endif
nlen = strlen(newbuf);
inc = nlen - olen;
@ -221,7 +226,7 @@ int dlen;
}
#if !defined(_KERNEL)
m = *((mb_t **)fin->fin_mp);
m = *fin->fin_mp;
bcopy(newbuf, (char *)m + off, nlen);
#else
# if SOLARIS
@ -251,7 +256,7 @@ int dlen;
}
copyin_mblk(m, off, nlen, newbuf);
# else
m = *((mb_t **)fin->fin_mp);
m = *fin->fin_mp;
if (inc < 0)
m_adj(m, inc);
/* the mbuf chain will be extended if necessary by m_copyback() */
@ -263,7 +268,7 @@ int dlen;
# endif
#endif
if (inc != 0) {
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
#if ((SOLARIS || defined(__sgi)) && defined(_KERNEL)) || !defined(_KERNEL)
register u_32_t sum1, sum2;
sum1 = ip->ip_len;
@ -542,7 +547,7 @@ int dlen;
return 0;
#if !defined(_KERNEL)
m = *((mb_t **)fin->fin_mp);
m = *fin->fin_mp;
m_copyback(m, off, nlen, newbuf);
#else
# if SOLARIS
@ -569,7 +574,7 @@ int dlen;
}
/*copyin_mblk(m, off, nlen, newbuf);*/
# else /* SOLARIS */
m = *((mb_t **)fin->fin_mp);
m = *fin->fin_mp;
if (inc < 0)
m_adj(m, inc);
/* the mbuf chain will be extended if necessary by m_copyback() */
@ -577,7 +582,7 @@ int dlen;
# endif /* SOLARIS */
#endif /* _KERNEL */
if (inc != 0) {
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
#if ((SOLARIS || defined(__sgi)) && defined(_KERNEL)) || !defined(_KERNEL)
register u_32_t sum1, sum2;
sum1 = ip->ip_len;
@ -714,7 +719,8 @@ size_t len;
if (i < 5) {
#if !defined(_KERNEL) && !defined(KERNEL)
fprintf(stdout, "ippr_ftp_client_valid:i(%d) < 5\n", i);
fprintf(stdout, "ippr_ftp_client_valid:i(%lu) < 5\n",
(u_long)i);
#endif
return 2;
}
@ -750,8 +756,8 @@ size_t len;
bad_client_command:
#if !defined(_KERNEL) && !defined(KERNEL)
fprintf(stdout,
"ippr_ftp_client_valid:bad cmd:len %d i %d c 0x%x\n",
i, len, c);
"ippr_ftp_client_valid:bad cmd:len %lu i %lu c 0x%x\n",
(u_long)i, (u_long)len, c);
#endif
return 1;
}
@ -812,8 +818,8 @@ size_t len;
bad_server_command:
#if !defined(_KERNEL) && !defined(KERNEL)
fprintf(stdout,
"ippr_ftp_server_valid:bad cmd:len %d i %d c 0x%x\n",
i, len, c);
"ippr_ftp_server_valid:bad cmd:len %lu i %lu c 0x%x\n",
(u_long)i, (u_long)len, c);
#endif
return 1;
}
@ -875,7 +881,7 @@ int rv;
#if SOLARIS && defined(_KERNEL)
m = fin->fin_qfm;
#else
m = *((mb_t **)fin->fin_mp);
m = *fin->fin_mp;
#endif
#ifndef _KERNEL
@ -1025,9 +1031,9 @@ int rv;
printf("inc %d sel %d rv %d\n", inc, sel, rv);
printf("th_seq %x ftps_seq %x/%x\n", thseq, f->ftps_seq[0],
f->ftps_seq[1]);
printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel],
printf("ackmin %x ackoff %d\n", (u_int)aps->aps_ackmin[sel],
aps->aps_ackoff[sel]);
printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel],
printf("seqmin %x seqoff %d\n", (u_int)aps->aps_seqmin[sel],
aps->aps_seqoff[sel]);
#endif

View File

@ -247,17 +247,17 @@ mb_t *m;
*/
bzero((char *)ipfl.fl_ifname, sizeof(ipfl.fl_ifname));
# if SOLARIS && defined(_KERNEL)
ipfl.fl_unit = (u_char)ifp->ill_ppa;
ipfl.fl_unit = (u_int)ifp->ill_ppa;
bcopy(ifp->ill_name, ipfl.fl_ifname,
MIN(ifp->ill_name_length, sizeof(ipfl.fl_ifname)));
mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0;
# else
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
(defined(OpenBSD) && (OpenBSD >= 199603)) || \
(defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
(defined(OpenBSD) && (OpenBSD >= 199603)) || \
(defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ);
# else
ipfl.fl_unit = (u_char)ifp->if_unit;
ipfl.fl_unit = (u_int)ifp->if_unit;
strncpy(ipfl.fl_ifname, ifp->if_name, MIN(sizeof(ipfl.fl_ifname),
sizeof(ifp->if_name)));
# endif
@ -319,7 +319,7 @@ int *types, cnt;
* rather than create a new one.
*/
MUTEX_ENTER(&ipl_mutex);
if (fin != NULL) {
if ((fin != NULL) && (fin->fin_off == 0)) {
if ((ipll[dev] != NULL) &&
bcmp((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE) == 0) {
ipll[dev]->ipl_count++;
@ -435,7 +435,7 @@ struct uio *uio;
SPL_NET(s);
MUTEX_ENTER(&ipl_mutex);
while (!iplused[unit] || !iplt[unit]) {
while (iplt[unit] == NULL) {
# if SOLARIS && defined(_KERNEL)
if (!cv_wait_sig(&iplwait, &ipl_mutex)) {
MUTEX_EXIT(&ipl_mutex);

View File

@ -117,6 +117,7 @@ static const char rcsid[] = "@(#)$FreeBSD$";
nat_t **nat_table[2] = { NULL, NULL },
*nat_instances = NULL;
ipnat_t *nat_list = NULL;
u_int ipf_nattable_max = NAT_TABLE_MAX;
u_int ipf_nattable_sz = NAT_TABLE_SZ;
u_int ipf_natrules_sz = NAT_SIZE;
u_int ipf_rdrrules_sz = RDR_SIZE;
@ -780,6 +781,8 @@ caddr_t data;
if ((aps != NULL) && (aps->aps_data != 0)) {
ng.ng_sz += sizeof(ap_session_t);
ng.ng_sz += aps->aps_psiz;
if (aps->aps_psiz > 4) /* XXX - sizeof(ipn_data) */
ng.ng_sz -= 4;
}
error = IWCOPY((caddr_t)&ng, data, sizeof(ng));
@ -795,6 +798,7 @@ caddr_t data;
nat_save_t ipn, *ipnp, *ipnn = NULL;
register nat_t *n, *nat;
ap_session_t *aps;
size_t dsz;
int error;
error = IRCOPY(data, (caddr_t)&ipnp, sizeof(ipnp));
@ -826,7 +830,6 @@ caddr_t data;
}
ipn.ipn_next = nat->nat_next;
ipn.ipn_dsize = 0;
bcopy((char *)nat, (char *)&ipn.ipn_nat, sizeof(ipn.ipn_nat));
ipn.ipn_nat.nat_data = NULL;
@ -840,10 +843,13 @@ caddr_t data;
sizeof(ipn.ipn_rule));
if ((aps = nat->nat_aps)) {
ipn.ipn_dsize = sizeof(*aps);
dsz = sizeof(*aps);
if (aps->aps_data)
ipn.ipn_dsize += aps->aps_psiz;
KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + ipn.ipn_dsize);
dsz += aps->aps_psiz;
ipn.ipn_dsize = dsz;
if (dsz > sizeof(ipn.ipn_data))
dsz -= sizeof(ipn.ipn_data);
KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + dsz);
if (ipnn == NULL)
return ENOMEM;
bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn));
@ -852,14 +858,14 @@ caddr_t data;
if (aps->aps_data) {
bcopy(aps->aps_data, ipnn->ipn_data + sizeof(*aps),
aps->aps_psiz);
ipnn->ipn_dsize += aps->aps_psiz;
}
error = IWCOPY((caddr_t)ipnn, ipnp,
sizeof(ipn) + ipn.ipn_dsize);
sizeof(ipn) + dsz);
if (error)
error = EFAULT;
KFREES(ipnn, sizeof(*ipnn) + ipn.ipn_dsize);
KFREES(ipnn, sizeof(*ipnn) + dsz);
} else {
ipn.ipn_dsize = 0;
error = IWCOPY((caddr_t)&ipn, ipnp, sizeof(ipn));
if (error)
error = EFAULT;
@ -887,12 +893,12 @@ caddr_t data;
return EFAULT;
nat = NULL;
if (ipn.ipn_dsize) {
KMALLOCS(ipnn, nat_save_t *, sizeof(ipn) + ipn.ipn_dsize);
KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + ipn.ipn_dsize);
if (ipnn == NULL)
return ENOMEM;
bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn));
error = IRCOPY((caddr_t)ipnp, (caddr_t)ipn.ipn_data,
ipn.ipn_dsize);
error = IRCOPY((caddr_t)ipnp + offsetof(nat_save_t, ipn_data),
(caddr_t)ipnn->ipn_data, ipn.ipn_dsize);
if (error) {
error = EFAULT;
goto junkput;
@ -1067,7 +1073,7 @@ struct nat *natd;
* If there's a fragment table entry too for this nat entry, then
* dereference that as well.
*/
ipfr_forget((void *)natd);
ipfr_forgetnat((void *)natd);
aps_free(natd->nat_aps);
nat_stats.ns_inuse--;
KFREE(natd);
@ -1165,6 +1171,11 @@ int direction;
qif_t *qf = fin->fin_qif;
#endif
if (nat_stats.ns_inuse >= ipf_nattable_max) {
nat_stats.ns_memfail++;
return NULL;
}
nflags = flags & np->in_flags;
if (flags & IPN_TCPUDP) {
tcp = (tcphdr_t *)fin->fin_dp;
@ -1176,6 +1187,17 @@ int direction;
KMALLOC(nat, nat_t *);
if (nat == NULL) {
nat_stats.ns_memfail++;
/*
* Try to automatically tune the max # of entries in the
* table allowed to be less than what will cause kmem_alloc()
* to fail and try to eliminate panics due to out of memory
* conditions arising.
*/
if (ipf_nattable_max > ipf_nattable_sz) {
ipf_nattable_max = nat_stats.ns_inuse - 100;
printf("ipf_nattable_max reduced to %d\n",
ipf_nattable_max);
}
return NULL;
}
@ -1432,7 +1454,7 @@ int direction;
CALC_SUMD(sum1, sum2, sumd);
nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16);
#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
if ((flags & IPN_TCPUDP) && dohwcksum &&
if ((flags & IPN_TCP) && dohwcksum &&
(qf->qf_ill->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) {
if (direction == NAT_OUTBOUND)
sum1 = LONG_SUM(ntohl(in.s_addr));
@ -1684,6 +1706,7 @@ int dir;
return NULL;
flags = 0;
sumd2 = 0;
*nflags = IPN_ICMPERR;
icmp = (icmphdr_t *)fin->fin_dp;
oip = (ip_t *)&icmp->icmp_ip;
@ -1737,137 +1760,75 @@ int dir;
CALC_SUMD(sum1, sum2, sumd);
if (nat->nat_dir == NAT_OUTBOUND) {
/*
* Fix IP checksum of the offending IP packet to adjust for
* the change in the IP address.
*
* Normally, you would expect that the ICMP checksum of the
* ICMP error message needs to be adjusted as well for the
* IP address change in oip.
* However, this is a NOP, because the ICMP checksum is
* calculated over the complete ICMP packet, which includes the
* changed oip IP addresses and oip->ip_sum. However, these
* two changes cancel each other out (if the delta for
* the IP address is x, then the delta for ip_sum is minus x),
* so no change in the icmp_cksum is necessary.
*
* Be careful that nat_dir refers to the direction of the
* offending IP packet (oip), not to its ICMP response (icmp)
*/
fix_datacksum(&oip->ip_sum, sumd);
/* Fix icmp cksum : IP Addr + Cksum */
/*
* Fix UDP pseudo header checksum to compensate for the
* IP address change.
*/
if ((oip->ip_p == IPPROTO_UDP) && (dlen >= 8) && udp->uh_sum) {
/*
* Fix IP checksum of the offending IP packet to adjust for
* the change in the IP address.
*
* Normally, you would expect that the ICMP checksum of the
* ICMP error message needs to be adjusted as well for the
* IP address change in oip.
* However, this is a NOP, because the ICMP checksum is
* calculated over the complete ICMP packet, which includes the
* changed oip IP addresses and oip->ip_sum. However, these
* two changes cancel each other out (if the delta for
* the IP address is x, then the delta for ip_sum is minus x),
* so no change in the icmp_cksum is necessary.
*
* Be careful that nat_dir refers to the direction of the
* offending IP packet (oip), not to its ICMP response (icmp)
* The UDP checksum is optional, only adjust it
* if it has been set.
*/
fix_datacksum(&oip->ip_sum, sumd);
sum1 = ntohs(udp->uh_sum);
fix_datacksum(&udp->uh_sum, sumd);
sum2 = ntohs(udp->uh_sum);
/*
* Fix UDP pseudo header checksum to compensate for the
* IP address change.
* Fix ICMP checksum to compensate the UDP
* checksum adjustment.
*/
if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
/*
* The UDP checksum is optional, only adjust it
* if it has been set.
*/
sum1 = ntohs(udp->uh_sum);
fix_datacksum(&udp->uh_sum, sumd);
sum2 = ntohs(udp->uh_sum);
/*
* Fix ICMP checksum to compensate the UDP
* checksum adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 = sumd;
}
/*
* Fix TCP pseudo header checksum to compensate for the
* IP address change. Before we can do the change, we
* must make sure that oip is sufficient large to hold
* the TCP checksum (normally it does not!).
*/
if (oip->ip_p == IPPROTO_TCP && dlen >= 18) {
sum1 = ntohs(tcp->th_sum);
fix_datacksum(&tcp->th_sum, sumd);
sum2 = ntohs(tcp->th_sum);
/*
* Fix ICMP checksum to compensate the TCP
* checksum adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 = sumd;
}
} else {
/*
* Fix IP checksum of the offending IP packet to adjust for
* the change in the IP address.
*
* Normally, you would expect that the ICMP checksum of the
* ICMP error message needs to be adjusted as well for the
* IP address change in oip.
* However, this is a NOP, because the ICMP checksum is
* calculated over the complete ICMP packet, which includes the
* changed oip IP addresses and oip->ip_sum. However, these
* two changes cancel each other out (if the delta for
* the IP address is x, then the delta for ip_sum is minus x),
* so no change in the icmp_cksum is necessary.
*
* Be careful that nat_dir refers to the direction of the
* offending IP packet (oip), not to its ICMP response (icmp)
*/
fix_datacksum(&oip->ip_sum, sumd);
/* XXX FV : without having looked at Solaris source code, it seems unlikely
* that SOLARIS would compensate this in the kernel (a body of an IP packet
* in the data section of an ICMP packet). I have the feeling that this should
* be unconditional, but I'm not in a position to check.
*/
#if !SOLARIS && !defined(__sgi)
/*
* Fix UDP pseudo header checksum to compensate for the
* IP address change.
*/
if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
/*
* The UDP checksum is optional, only adjust it
* if it has been set
*/
sum1 = ntohs(udp->uh_sum);
fix_datacksum(&udp->uh_sum, sumd);
sum2 = ntohs(udp->uh_sum);
/*
* Fix ICMP checksum to compensate the UDP
* checksum adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 = sumd;
}
/*
* Fix TCP pseudo header checksum to compensate for the
* IP address change. Before we can do the change, we
* must make sure that oip is sufficient large to hold
* the TCP checksum (normally it does not!).
*/
if (oip->ip_p == IPPROTO_TCP && dlen >= 18) {
sum1 = ntohs(tcp->th_sum);
fix_datacksum(&tcp->th_sum, sumd);
sum2 = ntohs(tcp->th_sum);
/*
* Fix ICMP checksum to compensate the TCP
* checksum adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 = sumd;
}
#endif
sumd2 = sumd << 1;
CALC_SUMD(sum1, sum2, sumd);
sumd2 += sumd;
}
if ((flags & IPN_TCPUDP) != 0) {
/*
* Fix TCP pseudo header checksum to compensate for the
* IP address change. Before we can do the change, we
* must make sure that oip is sufficient large to hold
* the TCP checksum (normally it does not!).
*/
else if ((oip->ip_p == IPPROTO_TCP) && (dlen >= 18)) {
sum1 = ntohs(tcp->th_sum);
fix_datacksum(&tcp->th_sum, sumd);
sum2 = ntohs(tcp->th_sum);
/*
* Fix ICMP checksum to compensate the TCP
* checksum adjustment.
*/
sumd2 = sumd << 1;
CALC_SUMD(sum1, sum2, sumd);
sumd2 += sumd;
} else {
sumd2 = (sumd >> 16);
if (nat->nat_dir == NAT_OUTBOUND)
sumd2 = ~sumd2;
else
sumd2 = ~sumd2 + 1;
}
if (((flags & IPN_TCPUDP) != 0) && (dlen >= 4)) {
/*
* Step 2 :
* For offending TCP/UDP IP packets, translate the ports as
@ -1887,17 +1848,14 @@ int dir;
* include the TCP checksum. So we have to check if the
* ip->ip_len actually holds the TCP checksum of the oip!
*/
if (nat->nat_oport == tcp->th_dport) {
if (tcp->th_sport != nat->nat_inport) {
/*
* Fix ICMP checksum to compensate port
* adjustment.
*/
sum1 = ntohs(tcp->th_sport);
sum2 = ntohs(nat->nat_inport);
CALC_SUMD(sum1, sum2, sumd);
sumd2 += sumd;
sum1 = ntohs(nat->nat_inport);
sum2 = ntohs(tcp->th_sport);
tcp->th_sport = nat->nat_inport;
/*
@ -1909,16 +1867,18 @@ int dir;
* The UDP checksum is optional, only adjust
* it if it has been set.
*/
if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
if ((oip->ip_p == IPPROTO_UDP) &&
(dlen >= 8) && udp->uh_sum) {
sumd = sum1 - sum2;
sumd2 += sumd;
sum1 = ntohs(udp->uh_sum);
fix_datacksum(&udp->uh_sum, sumd);
sum2 = ntohs(udp->uh_sum);
/*
* Fix ICMP checksum to
* compensate UDP checksum
* adjustment.
* Fix ICMP checksum to compensate
* UDP checksum adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 += sumd;
@ -1930,63 +1890,73 @@ int dir;
* packet flows the other direction compared to
* the ICMP message.
*/
if (oip->ip_p == IPPROTO_TCP && dlen >= 18) {
if (oip->ip_p == IPPROTO_TCP) {
if (dlen >= 18) {
sumd = sum1 - sum2;
sumd2 += sumd;
sum1 = ntohs(tcp->th_sum);
fix_datacksum(&tcp->th_sum, sumd);
sum2 = ntohs(tcp->th_sum);
sum1 = ntohs(tcp->th_sum);
fix_datacksum(&tcp->th_sum,
sumd);
sum2 = ntohs(tcp->th_sum);
/*
* Fix ICMP checksum to
* compensate TCP checksum
* adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 += sumd;
/*
* Fix ICMP checksum to
* compensate TCP checksum
* adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 += sumd;
} else {
sumd = sum2 - sum1 + 1;
sumd2 += sumd;
}
}
}
} else {
if (tcp->th_dport != nat->nat_outport) {
/*
* Fix ICMP checksum to compensate port
* adjustment.
*/
sum1 = ntohs(tcp->th_dport);
sum2 = ntohs(nat->nat_outport);
CALC_SUMD(sum1, sum2, sumd);
} else if (tcp->th_dport != nat->nat_outport) {
/*
* Fix ICMP checksum to compensate port
* adjustment.
*/
sum1 = ntohs(nat->nat_outport);
sum2 = ntohs(tcp->th_dport);
tcp->th_dport = nat->nat_outport;
/*
* Fix udp checksum to compensate port
* adjustment. NOTE : the offending IP
* packet flows the other direction compared
* to the ICMP message.
*
* The UDP checksum is optional, only adjust
* it if it has been set.
*/
if ((oip->ip_p == IPPROTO_UDP) &&
(dlen >= 8) && udp->uh_sum) {
sumd = sum1 - sum2;
sumd2 += sumd;
tcp->th_dport = nat->nat_outport;
sum1 = ntohs(udp->uh_sum);
fix_datacksum(&udp->uh_sum, sumd);
sum2 = ntohs(udp->uh_sum);
/*
* Fix udp checksum to compensate port
* adjustment. NOTE : the offending IP
* packet flows the other direction compared
* to the ICMP message.
*
* The UDP checksum is optional, only adjust
* it if it has been set.
* Fix ICMP checksum to compensate
* UDP checksum adjustment.
*/
if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
CALC_SUMD(sum1, sum2, sumd);
}
sum1 = ntohs(udp->uh_sum);
fix_datacksum(&udp->uh_sum, sumd);
sum2 = ntohs(udp->uh_sum);
/*
* Fix ICMP checksum to compensate
* UDP checksum adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
/*
* Fix tcp checksum (if present) to compensate
* port adjustment. NOTE : the offending IP
* packet flows the other direction compared to
* the ICMP message.
*/
if (oip->ip_p == IPPROTO_TCP) {
if (dlen >= 18) {
sumd = sum1 - sum2;
sumd2 += sumd;
}
/*
* Fix tcp checksum (if present) to compensate
* port adjustment. NOTE : the offending IP
* packet flows the other direction compared to
* the ICMP message.
*/
if (oip->ip_p == IPPROTO_TCP && dlen >= 18) {
sum1 = ntohs(tcp->th_sum);
fix_datacksum(&tcp->th_sum, sumd);
@ -1997,18 +1967,18 @@ int dir;
* UDP checksum adjustment.
*/
CALC_SUMD(sum1, sum2, sumd);
sumd2 += sumd;
} else {
sumd = sum2 - sum1;
if (nat->nat_dir == NAT_OUTBOUND)
sumd++;
}
}
sumd2 += sumd;
}
if (sumd2) {
sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16);
sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16);
if (nat->nat_dir == NAT_OUTBOUND) {
fix_outcksum(fin, &icmp->icmp_cksum, sumd2);
} else {
fix_incksum(fin, &icmp->icmp_cksum, sumd2);
}
fix_incksum(fin, &icmp->icmp_cksum, sumd2);
}
}
if (oip->ip_p == IPPROTO_ICMP)
@ -2478,13 +2448,9 @@ maskloop:
s1 = LONG_SUM(ntohl(fin->fin_saddr));
s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr));
CALC_SUMD(s1, s2, sumd);
if (nat->nat_dir == NAT_OUTBOUND)
fix_outcksum(fin, &ip->ip_sum, sumd);
else
fix_incksum(fin, &ip->ip_sum, sumd);
fix_outcksum(fin, &ip->ip_sum, sumd);
}
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
#if (SOLARIS || defined(__sgi)) || !defined(_KERNEL)
else {
if (nat->nat_dir == NAT_OUTBOUND)
fix_outcksum(fin, &ip->ip_sum, nat->nat_ipsumd);
@ -2512,7 +2478,8 @@ maskloop:
if (nat->nat_age < fr_defnaticmpage)
nat->nat_age = fr_defnaticmpage;
#ifdef LARGE_NAT
else if (nat->nat_age > fr_defnatage)
else if ((!np || !np->in_age[1]) &&
(nat->nat_age > fr_defnatage))
nat->nat_age = fr_defnatage;
#endif
/*
@ -2705,19 +2672,19 @@ maskloop:
nat->nat_bytes += ip->ip_len;
nat->nat_pkts++;
MUTEX_EXIT(&nat->nat_lock);
ip->ip_dst = nat->nat_inip;
fin->fin_fi.fi_daddr = nat->nat_inip.s_addr;
/*
* Fix up checksums, not by recalculating them, but
* simply computing adjustments.
*/
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
if (nat->nat_dir == NAT_OUTBOUND)
fix_incksum(fin, &ip->ip_sum, nat->nat_ipsumd);
else
fix_outcksum(fin, &ip->ip_sum, nat->nat_ipsumd);
#endif
ip->ip_dst = nat->nat_inip;
fin->fin_fi.fi_daddr = nat->nat_inip.s_addr;
if ((fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT)) {
if ((nat->nat_inport != 0) && (tcp != NULL)) {
@ -2733,7 +2700,8 @@ maskloop:
if (nat->nat_age < fr_defnaticmpage)
nat->nat_age = fr_defnaticmpage;
#ifdef LARGE_NAT
else if (nat->nat_age > fr_defnatage)
else if ((!np || !np->in_age[0]) &&
(nat->nat_age > fr_defnatage))
nat->nat_age = fr_defnatage;
#endif
/*
@ -2985,7 +2953,7 @@ u_short *csump;
if (&cp[1] >= ep)
break;
advance = cp[1];
if (&cp[advance] >= ep)
if (&cp[advance] > ep)
break;
switch (opt) {
case TCPOPT_MAXSEG:

View File

@ -35,26 +35,39 @@
* a setup with 1000-2000 networks to NAT.
*/
#ifndef NAT_SIZE
# define NAT_SIZE 127
# ifdef LARGE_NAT
# define NAT_SIZE 2047
# else
# define NAT_SIZE 127
# endif
#endif
#ifndef RDR_SIZE
# define RDR_SIZE 127
# ifdef LARGE_NAT
# define RDR_SIZE 2047
# else
# define RDR_SIZE 127
# endif
#endif
#ifndef HOSTMAP_SIZE
# define HOSTMAP_SIZE 127
# ifdef LARGE_NAT
# define HOSTMAP_SIZE 8191
# else
# define HOSTMAP_SIZE 2047
# endif
#endif
#ifndef NAT_TABLE_MAX
# ifdef LARGE_NAT
# define NAT_TABLE_MAX 180000
# else
# define NAT_TABLE_MAX 30000
# endif
#endif
#ifndef NAT_TABLE_SZ
# define NAT_TABLE_SZ 127
#endif
#ifdef LARGE_NAT
#undef NAT_SIZE
#undef RDR_SIZE
#undef NAT_TABLE_SZ
#undef HOSTMAP_SIZE 127
#define NAT_SIZE 2047
#define RDR_SIZE 2047
#define NAT_TABLE_SZ 16383
#define HOSTMAP_SIZE 8191
# ifdef LARGE_NAT
# define NAT_TABLE_SZ 16383
# else
# define NAT_TABLE_SZ 2047
# endif
#endif
#ifndef APR_LABELLEN
#define APR_LABELLEN 16

View File

@ -66,9 +66,6 @@ nat_t *nat;
tcphdr_t *tcp;
int len = 0;
mb_t *m;
#if SOLARIS
mb_t *m1;
#endif
/*
* If we've already processed the start messages, then nothing left
@ -181,9 +178,6 @@ nat_t *nat;
nat_t *ipn;
u_char swp;
mb_t *m;
#if SOLARIS
mb_t *m1;
#endif
/*
* Wait until we've seen the end of the start messages and even then

View File

@ -1,5 +1,5 @@
/*
* $Id: ip_rcmd_pxy.c,v 1.4.2.6 2002/10/01 15:24:59 darrenr Exp $
* $Id: ip_rcmd_pxy.c,v 1.4.2.7 2003/04/26 05:59:39 darrenr Exp $
*/
/*
* Simple RCMD transparent proxy for in-kernel use. For use with the NAT
@ -89,9 +89,6 @@ nat_t *nat;
u_short sp;
nat_t *ipn;
mb_t *m;
#if SOLARIS
mb_t *m1;
#endif
tcp = (tcphdr_t *)fin->fin_dp;

View File

@ -923,7 +923,8 @@ tcphdr_t *tcp;
fdata->td_wscale = wscale;
else if (wscale == -2)
fdata->td_wscale = tdata->td_wscale = 0;
win <<= fdata->td_wscale;
if (!(tcp->th_flags & TH_SYN))
win <<= fdata->td_wscale;
if ((fdata->td_end == 0) &&
(!is->is_fsm || ((tcp->th_flags & TH_OPENING) == TH_OPENING))) {
@ -957,14 +958,15 @@ tcphdr_t *tcp;
(SEQ_GE(seq, fdata->td_end - maxwin)) &&
/* XXX what about big packets */
#define MAXACKWINDOW 66000
(ackskew >= -MAXACKWINDOW) &&
(ackskew <= MAXACKWINDOW)) {
/* if ackskew < 0 then this should be due to fragented
(-ackskew <= (MAXACKWINDOW << tdata->td_wscale)) &&
( ackskew <= (MAXACKWINDOW << tdata->td_wscale))) {
/* if ackskew < 0 then this should be due to fragmented
* packets. There is no way to know the length of the
* total packet in advance.
* We do know the total length from the fragment cache though.
* Note however that there might be more sessions with
* exactly the same source and destination paramters in the
* exactly the same source and destination parameters in the
* state cache (and source and destination is the only stuff
* that is saved in the fragment cache). Note further that
* some TCP connections in the state cache are hashed with
@ -1211,6 +1213,10 @@ fr_info_t *fin;
oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN);
ohlen = oip->ip_hl << 2;
/*
* Check if the at least the old IP header (with options) and
* 8 bytes of payload is present.
*/
if (fin->fin_plen < ICMPERR_MAXPKTLEN + ohlen - sizeof(*oip))
return NULL;
@ -1227,7 +1233,7 @@ fr_info_t *fin;
* may be too big to be in this buffer but not so big that it's
* outside the ICMP packet, leading to TCP deref's causing problems.
* This is possible because we don't know how big oip_hl is when we
* do the pullup early in fr_check() and thus can't gaurantee it is
* do the pullup early in fr_check() and thus can't guarantee it is
* all here now.
*/
#ifdef _KERNEL
@ -1254,9 +1260,43 @@ fr_info_t *fin;
bzero((char *)&src, sizeof(src));
bzero((char *)&dst, sizeof(dst));
bzero((char *)&ofin, sizeof(ofin));
/*
* We make an fin entry to be able to feed it to
* matchsrcdst. Note that not all fields are encessary
* but this is the cleanest way. Note further that we
* fill in fin_mp such that if someone uses it we'll get
* a kernel panic. fr_matchsrcdst does not use this.
*/
ofin.fin_ifp = fin->fin_ifp;
ofin.fin_out = !fin->fin_out;
ofin.fin_mp = NULL;
ofin.fin_v = 4;
/*
* watch out here, as ip is in host order and oip in network
* order. Any change we make must be undone afterwards, like
* oip->ip_off - it is still in network byte order so fix it.
*/
savelen = oip->ip_len;
oip->ip_len = len;
oip->ip_off = ntohs(oip->ip_off);
(void) fr_makefrip(ohlen, oip, &ofin);
/*
* Reset the short flag here because in fr_matchsrcdst() the flags
* for the current packet (fin_fl) are compared against * those for
* the existing session.
*/
ofin.fin_fl &= ~FI_SHORT;
/*
* Put old values of ip_len and ip_off back as we don't know
* if we have to forward the packet (or process it again.
*/
oip->ip_len = savelen;
oip->ip_off = htons(oip->ip_off);
#if SOLARIS
ofin.fin_qfm = NULL;
#endif
fr = NULL;
switch (oip->ip_p)
@ -1265,7 +1305,7 @@ fr_info_t *fin;
icmp = (icmphdr_t *)((char *)oip + ohlen);
/*
* a ICMP error can only be generated as a result of an
* an ICMP error can only be generated as a result of an
* ICMP query, not as the response on an ICMP error
*
* XXX theoretically ICMP_ECHOREP and the other reply's are
@ -1289,18 +1329,15 @@ fr_info_t *fin;
hv += icmp->icmp_seq;
hv %= fr_statesize;
savelen = oip->ip_len;
oip->ip_len = len;
fr_makefrip(ohlen, oip, &ofin);
oip->ip_len = savelen;
READ_ENTER(&ipf_state);
for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext)
if ((is->is_p == pr) && (is->is_v == 4) &&
(is->is_icmppkts < is->is_pkts) &&
fr_matchsrcdst(is, src, dst, &ofin, NULL) &&
fr_matchicmpqueryreply(is->is_v, is, icmp, fin->fin_rev)) {
fr_matchicmpqueryreply(is->is_v, is, icmp,
fin->fin_rev)) {
ips_stats.iss_hits++;
is->is_pkts++;
is->is_icmppkts++;
is->is_bytes += ip->ip_len;
fr = is->is_rule;
break;
@ -1329,20 +1366,7 @@ fr_info_t *fin;
hv += dport;
hv += sport;
hv %= fr_statesize;
/*
* we make an fin entry to be able to feed it to
* matchsrcdst note that not all fields are encessary
* but this is the cleanest way. Note further we fill
* in fin_mp such that if someone uses it we'll get
* a kernel panic. fr_matchsrcdst does not use this.
*
* watch out here, as ip is in host order and oip in network
* order. Any change we make must be undone afterwards.
*/
savelen = oip->ip_len;
oip->ip_len = len;
fr_makefrip(ohlen, oip, &ofin);
oip->ip_len = savelen;
READ_ENTER(&ipf_state);
for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) {
/*
@ -1350,13 +1374,16 @@ fr_info_t *fin;
* encapsulated packet was allowed through the
* other way around. Note that the minimal amount
* of info present does not allow for checking against
* tcp internals such as seq and ack numbers.
* tcp internals such as seq and ack numbers. Only the
* ports are known to be present and can be even if the
* short flag is set.
*/
if ((is->is_p == pr) && (is->is_v == 4) &&
(is->is_icmppkts < is->is_pkts) &&
fr_matchsrcdst(is, src, dst, &ofin, tcp)) {
fr = is->is_rule;
ips_stats.iss_hits++;
is->is_pkts++;
is->is_icmppkts++;
is->is_bytes += fin->fin_plen;
/*
* we deliberately do not touch the timeouts
@ -2083,7 +2110,7 @@ u_int type;
int types[1];
ipsl.isl_type = type;
ipsl.isl_pkts = is->is_pkts;
ipsl.isl_pkts = is->is_pkts + is->is_icmppkts;
ipsl.isl_bytes = is->is_bytes;
ipsl.isl_src = is->is_src;
ipsl.isl_dst = is->is_dst;
@ -2111,7 +2138,11 @@ u_int type;
sizes[0] = sizeof(ipsl);
types[0] = 0;
(void) ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1);
if (ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1)) {
ATOMIC_INCL(ips_stats.iss_logged);
} else {
ATOMIC_INCL(ips_stats.iss_logfail);
}
}
#endif
@ -2161,12 +2192,30 @@ fr_info_t *fin;
bzero((char *)&ofin, sizeof(ofin));
ofin.fin_out = !fin->fin_out;
ofin.fin_ifp = fin->fin_ifp;
ofin.fin_mp = NULL;
ofin.fin_v = 6;
#if SOLARIS
ofin.fin_qfm = NULL;
#endif
/*
* We make a fin entry to be able to feed it to
* matchsrcdst. Note that not all fields are necessary
* but this is the cleanest way. Note further we fill
* in fin_mp such that if someone uses it we'll get
* a kernel panic. fr_matchsrcdst does not use this.
*
* watch out here, as ip is in host order and oip in network
* order. Any change we make must be undone afterwards.
*/
savelen = oip->ip6_plen;
oip->ip6_plen = ip->ip6_plen - sizeof(*ip) - ICMPERR_ICMPHLEN;
fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin);
oip->ip6_plen = savelen;
if (oip->ip6_nxt == IPPROTO_ICMPV6) {
oic = (struct icmp6_hdr *)(oip + 1);
/*
* a ICMP error can only be generated as a result of an
* an ICMP error can only be generated as a result of an
* ICMP query, not as the response on an ICMP error
*
* XXX theoretically ICMP_ECHOREP and the other reply's are
@ -2187,10 +2236,6 @@ fr_info_t *fin;
hv += oic->icmp6_seq;
hv %= fr_statesize;
oip->ip6_plen = ntohs(oip->ip6_plen);
fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin);
oip->ip6_plen = htons(oip->ip6_plen);
READ_ENTER(&ipf_state);
for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext)
if ((is->is_p == pr) &&
@ -2234,20 +2279,7 @@ fr_info_t *fin;
hv += dport;
hv += sport;
hv %= fr_statesize;
/*
* we make an fin entry to be able to feed it to
* matchsrcdst note that not all fields are encessary
* but this is the cleanest way. Note further we fill
* in fin_mp such that if someone uses it we'll get
* a kernel panic. fr_matchsrcdst does not use this.
*
* watch out here, as ip is in host order and oip in network
* order. Any change we make must be undone afterwards.
*/
savelen = oip->ip6_plen;
oip->ip6_plen = ip->ip6_plen - sizeof(*ip) - ICMPERR_ICMPHLEN;
fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin);
oip->ip6_plen = savelen;
READ_ENTER(&ipf_state);
for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) {
/*

View File

@ -63,6 +63,7 @@ typedef struct ipstate {
frentry_t *is_rule;
U_QUAD_T is_pkts;
U_QUAD_T is_bytes;
U_QUAD_T is_icmppkts;
union i6addr is_src;
union i6addr is_dst;
void *is_ifp[4];

View File

@ -10,6 +10,6 @@
#ifndef __IPL_H__
#define __IPL_H__
#define IPL_VERSION "IP Filter: v3.4.31"
#define IPL_VERSION "IP Filter: v3.4.35"
#endif