fix conflicts from rcsids
This commit is contained in:
parent
5b4d40c638
commit
60b88d9681
@ -277,6 +277,16 @@ fr_info_t *fin;
|
||||
int minicmpsz = sizeof(struct icmp);
|
||||
icmphdr_t *icmp;
|
||||
|
||||
if (fin->fin_dlen > 1)
|
||||
fin->fin_data[0] = *(u_short *)tcp;
|
||||
|
||||
if ((!(plen >= hlen + minicmpsz) && !off) ||
|
||||
(off && off < sizeof(struct icmp))) {
|
||||
fi->fi_fl |= FI_SHORT;
|
||||
if (fin->fin_dlen < 2)
|
||||
break;
|
||||
}
|
||||
|
||||
icmp = (icmphdr_t *)tcp;
|
||||
|
||||
if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
|
||||
@ -294,11 +304,6 @@ fr_info_t *fin;
|
||||
icmp->icmp_type == ICMP_MASKREPLY))
|
||||
minicmpsz = 12;
|
||||
|
||||
if ((!(plen >= hlen + minicmpsz) && !off) ||
|
||||
(off && off < sizeof(struct icmp)))
|
||||
fi->fi_fl |= FI_SHORT;
|
||||
if (fin->fin_dlen > 1)
|
||||
fin->fin_data[0] = *(u_short *)tcp;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_TCP :
|
||||
@ -743,6 +748,7 @@ int out;
|
||||
|
||||
#ifdef _KERNEL
|
||||
mb_t *mc = NULL;
|
||||
int p, len;
|
||||
# if !defined(__SVR4) && !defined(__svr4__)
|
||||
# ifdef __sgi
|
||||
char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
|
||||
@ -767,13 +773,26 @@ int out;
|
||||
}
|
||||
# endif /* CSUM_DELAY_DATA */
|
||||
|
||||
# ifdef USE_INET6
|
||||
if (v == 6) {
|
||||
len = ntohs(((ip6_t*)ip)->ip6_plen);
|
||||
p = ((ip6_t *)ip)->ip6_nxt;
|
||||
} else
|
||||
# endif
|
||||
{
|
||||
p = ip->ip_p;
|
||||
len = ip->ip_len;
|
||||
}
|
||||
|
||||
if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
|
||||
ip->ip_p == IPPROTO_ICMP)) {
|
||||
if ((p == IPPROTO_TCP || p == IPPROTO_UDP || p == IPPROTO_ICMP
|
||||
# ifdef USE_INET6
|
||||
|| (v == 6 && p == IPPROTO_ICMPV6)
|
||||
# endif
|
||||
)) {
|
||||
int plen = 0;
|
||||
|
||||
if ((ip->ip_off & IP_OFFMASK) == 0)
|
||||
switch(ip->ip_p)
|
||||
if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0)
|
||||
switch(p)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
plen = sizeof(tcphdr_t);
|
||||
@ -783,10 +802,13 @@ int out;
|
||||
break;
|
||||
/* 96 - enough for complete ICMP error IP header */
|
||||
case IPPROTO_ICMP:
|
||||
# ifdef USE_INET6
|
||||
case IPPROTO_ICMPV6 :
|
||||
# endif
|
||||
plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
|
||||
break;
|
||||
}
|
||||
up = MIN(hlen + plen, ip->ip_len);
|
||||
up = MIN(hlen + plen, len);
|
||||
|
||||
if (up > m->m_len) {
|
||||
# ifdef __sgi
|
||||
@ -835,8 +857,8 @@ int out;
|
||||
#endif
|
||||
|
||||
changed = 0;
|
||||
fin->fin_v = v;
|
||||
fin->fin_ifp = ifp;
|
||||
fin->fin_v = v;
|
||||
fin->fin_out = out;
|
||||
fin->fin_mp = mp;
|
||||
fr_makefrip(hlen, ip, fin);
|
||||
@ -1383,7 +1405,7 @@ tcphdr_t *tcp;
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
|
||||
* $Id: fil.c,v 2.35.2.20 2000/08/13 04:15:43 darrenr Exp $
|
||||
* $Id: fil.c,v 2.35.2.26 2000/10/24 11:58:17 darrenr Exp $
|
||||
*/
|
||||
/*
|
||||
* Copy data from an mbuf chain starting "off" bytes from the beginning,
|
||||
@ -1862,7 +1884,7 @@ size_t c;
|
||||
int err;
|
||||
|
||||
#if SOLARIS
|
||||
if (copyin(a, &ca, sizeof(ca)))
|
||||
if (copyin(a, (char *)&ca, sizeof(ca)))
|
||||
return EFAULT;
|
||||
#else
|
||||
bcopy(a, &ca, sizeof(ca));
|
||||
@ -1882,7 +1904,7 @@ size_t c;
|
||||
int err;
|
||||
|
||||
#if SOLARIS
|
||||
if (copyin(b, &ca, sizeof(ca)))
|
||||
if (copyin(b, (char *)&ca, sizeof(ca)))
|
||||
return EFAULT;
|
||||
#else
|
||||
bcopy(b, &ca, sizeof(ca));
|
||||
@ -1976,6 +1998,15 @@ friostat_t *fiop;
|
||||
fiop->f_acctin6[1] = ipacct6[0][1];
|
||||
fiop->f_acctout6[0] = ipacct6[1][0];
|
||||
fiop->f_acctout6[1] = ipacct6[1][1];
|
||||
#else
|
||||
fiop->f_fin6[0] = NULL;
|
||||
fiop->f_fin6[1] = NULL;
|
||||
fiop->f_fout6[0] = NULL;
|
||||
fiop->f_fout6[1] = NULL;
|
||||
fiop->f_acctin6[0] = NULL;
|
||||
fiop->f_acctin6[1] = NULL;
|
||||
fiop->f_acctout6[0] = NULL;
|
||||
fiop->f_acctout6[1] = NULL;
|
||||
#endif
|
||||
fiop->f_active = fr_active;
|
||||
fiop->f_froute[0] = ipl_frouteok[0];
|
||||
|
@ -47,8 +47,6 @@ typedef struct fr_authstat {
|
||||
extern frentry_t *ipauth;
|
||||
extern struct fr_authstat fr_authstats;
|
||||
extern int fr_defaultauthage;
|
||||
extern int fr_authstart;
|
||||
extern int fr_authend;
|
||||
extern int fr_authsize;
|
||||
extern int fr_authused;
|
||||
extern int fr_auth_lock;
|
||||
|
@ -264,6 +264,12 @@ union i6addr {
|
||||
|
||||
|
||||
#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL))
|
||||
# ifdef IPFILTER_LKM
|
||||
# include <osreldate.h>
|
||||
# define ACTUALLY_LKM_NOT_KERNEL
|
||||
# else
|
||||
# include <sys/osreldate.h>
|
||||
# endif
|
||||
# if __FreeBSD__ < 3
|
||||
# include <machine/spl.h>
|
||||
# else
|
||||
@ -289,6 +295,19 @@ union i6addr {
|
||||
# define ATOMIC_DEC32 ATOMIC_DEC
|
||||
# define ATOMIC_DEC16 ATOMIC_DEC
|
||||
#endif
|
||||
#ifdef __sgi
|
||||
# define hz HZ
|
||||
# include <sys/ksynch.h>
|
||||
# define IPF_LOCK_PL plhi
|
||||
# include <sys/sema.h>
|
||||
#undef kmutex_t
|
||||
typedef struct {
|
||||
lock_t *l;
|
||||
int pl;
|
||||
} kmutex_t;
|
||||
# undef MUTEX_INIT
|
||||
# undef MUTEX_DESTROY
|
||||
#endif
|
||||
#ifdef KERNEL
|
||||
# if SOLARIS
|
||||
# if SOLARIS2 >= 6
|
||||
@ -338,8 +357,8 @@ union i6addr {
|
||||
# define MUTEX_DESTROY(x) mutex_destroy(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))
|
||||
# define IRCOPY(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
|
||||
# define IWCOPY(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
|
||||
# define IRCOPYPTR ircopyptr
|
||||
# define IWCOPYPTR iwcopyptr
|
||||
# define FREE_MB_T(m) freemsg(m)
|
||||
@ -384,15 +403,6 @@ extern ill_t *get_unit __P((char *, int));
|
||||
# define IFNAME(x) ((ill_t *)x)->ill_name
|
||||
# else /* SOLARIS */
|
||||
# if defined(__sgi)
|
||||
# define hz HZ
|
||||
# include <sys/ksynch.h>
|
||||
# define IPF_LOCK_PL plhi
|
||||
# include <sys/sema.h>
|
||||
#undef kmutex_t
|
||||
typedef struct {
|
||||
lock_t *l;
|
||||
int pl;
|
||||
} kmutex_t;
|
||||
# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \
|
||||
(x)++; MUTEX_EXIT(&ipf_rw); }
|
||||
# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \
|
||||
@ -405,8 +415,8 @@ typedef struct {
|
||||
# define MUTEX_DOWNGRADE(x) ;
|
||||
# define RWLOCK_EXIT(x) MUTEX_EXIT(x)
|
||||
# define MUTEX_EXIT(x) UNLOCK((x)->l, (x)->pl);
|
||||
# define MUTEX_INIT(x,y,z) (x).l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP)
|
||||
# define MUTEX_DESTROY(x) LOCK_DEALLOC((x).l)
|
||||
# define MUTEX_INIT(x,y,z) (x)->l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP)
|
||||
# define MUTEX_DESTROY(x) LOCK_DEALLOC((x)->l)
|
||||
# else /* __sgi */
|
||||
# define ATOMIC_INC(x) (x)++
|
||||
# define ATOMIC_DEC(x) (x)--
|
||||
|
@ -173,6 +173,9 @@ struct callout_handle ipfr_slowtimer_ch;
|
||||
# include <sys/callout.h>
|
||||
struct callout ipfr_slowtimer_ch;
|
||||
#endif
|
||||
#if defined(__sgi) && defined(_KERNEL)
|
||||
toid_t ipfr_slowtimer_ch;
|
||||
#endif
|
||||
|
||||
#if (_BSDI_VERSION >= 199510) && defined(_KERNEL)
|
||||
# include <sys/device.h>
|
||||
@ -322,7 +325,7 @@ int iplattach()
|
||||
callout_init(&ipfr_slowtimer_ch);
|
||||
callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL);
|
||||
# else
|
||||
# if (__FreeBSD_version >= 300000) && defined(_KERNEL)
|
||||
# if (__FreeBSD_version >= 300000) || defined(__sgi)
|
||||
ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
|
||||
# else
|
||||
timeout(ipfr_slowtimer, NULL, hz/2);
|
||||
@ -353,7 +356,7 @@ int ipldetach()
|
||||
untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch);
|
||||
# else
|
||||
# ifdef __sgi
|
||||
untimeout(ipfr_slowtimer);
|
||||
untimeout(ipfr_slowtimer_ch);
|
||||
# else
|
||||
untimeout(ipfr_slowtimer, NULL);
|
||||
# endif
|
||||
@ -980,8 +983,10 @@ fr_info_t *fin;
|
||||
if (m == NULL)
|
||||
return -1;
|
||||
|
||||
if (tcp->th_flags & TH_SYN)
|
||||
tlen = 1;
|
||||
tlen = oip->ip_len - fin->fin_hlen - (tcp->th_off << 2) +
|
||||
((tcp->th_flags & TH_SYN) ? 1 : 0) +
|
||||
((tcp->th_flags & TH_FIN) ? 1 : 0);
|
||||
|
||||
#ifdef USE_INET6
|
||||
hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
|
||||
#else
|
||||
@ -1002,11 +1007,16 @@ fr_info_t *fin;
|
||||
|
||||
tcp2->th_sport = tcp->th_dport;
|
||||
tcp2->th_dport = tcp->th_sport;
|
||||
tcp2->th_ack = ntohl(tcp->th_seq);
|
||||
tcp2->th_ack += tlen;
|
||||
tcp2->th_ack = htonl(tcp2->th_ack);
|
||||
if (tcp->th_flags & TH_ACK) {
|
||||
tcp2->th_seq = tcp->th_ack;
|
||||
tcp2->th_flags = TH_RST;
|
||||
} else {
|
||||
tcp2->th_ack = ntohl(tcp->th_seq);
|
||||
tcp2->th_ack += tlen;
|
||||
tcp2->th_ack = htonl(tcp2->th_ack);
|
||||
tcp2->th_flags = TH_RST|TH_ACK;
|
||||
}
|
||||
tcp2->th_off = sizeof(*tcp2) >> 2;
|
||||
tcp2->th_flags = TH_RST|TH_ACK;
|
||||
# ifdef USE_INET6
|
||||
if (fin->fin_v == 6) {
|
||||
ip6->ip6_plen = htons(sizeof(struct tcphdr));
|
||||
@ -1148,7 +1158,12 @@ int dst;
|
||||
m_freem(m);
|
||||
return ENOBUFS;
|
||||
}
|
||||
# ifdef M_TRAILINGSPACE
|
||||
m->m_len = 0;
|
||||
avail = M_TRAILINGSPACE(m);
|
||||
# else
|
||||
avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
|
||||
# endif
|
||||
xtra = MIN(ntohs(oip6->ip6_plen) + sizeof(ip6_t),
|
||||
avail - hlen - sizeof(*icmp) - max_linkhdr);
|
||||
if (dst == 0) {
|
||||
@ -1182,6 +1197,12 @@ int dst;
|
||||
icmp->icmp_type = type;
|
||||
icmp->icmp_code = fin->fin_icode;
|
||||
icmp->icmp_cksum = 0;
|
||||
#ifdef icmp_nextmtu
|
||||
if (type == ICMP_UNREACH &&
|
||||
fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp)
|
||||
icmp->icmp_nextmtu = htons(((struct ifnet *) ifp)->if_mtu);
|
||||
#endif
|
||||
|
||||
if (avail) {
|
||||
bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail));
|
||||
avail -= MIN(ohlen, avail);
|
||||
|
@ -215,7 +215,7 @@ u_int pass;
|
||||
ipfr_t *ipf;
|
||||
|
||||
if ((ip->ip_v != 4) || (fr_frag_lock))
|
||||
return NULL;
|
||||
return -1;
|
||||
WRITE_ENTER(&ipf_frag);
|
||||
ipf = ipfr_new(ip, fin, pass, ipfr_heads);
|
||||
RWLOCK_EXIT(&ipf_frag);
|
||||
@ -232,7 +232,7 @@ nat_t *nat;
|
||||
ipfr_t *ipf;
|
||||
|
||||
if ((ip->ip_v != 4) || (fr_frag_lock))
|
||||
return NULL;
|
||||
return -1;
|
||||
WRITE_ENTER(&ipf_natfrag);
|
||||
ipf = ipfr_new(ip, fin, pass, ipfr_nattab);
|
||||
if (ipf != NULL) {
|
||||
@ -329,13 +329,16 @@ fr_info_t *fin;
|
||||
ipf = ipfr_lookup(ip, fin, ipfr_nattab);
|
||||
if (ipf != NULL) {
|
||||
nat = ipf->ipfr_data;
|
||||
/*
|
||||
* This is the last fragment for this packet.
|
||||
*/
|
||||
if ((ipf->ipfr_ttl == 1) && (nat != NULL)) {
|
||||
nat->nat_data = NULL;
|
||||
ipf->ipfr_data = NULL;
|
||||
}
|
||||
if (nat->nat_ifp == fin->fin_ifp) {
|
||||
/*
|
||||
* This is the last fragment for this packet.
|
||||
*/
|
||||
if ((ipf->ipfr_ttl == 1) && (nat != NULL)) {
|
||||
nat->nat_data = NULL;
|
||||
ipf->ipfr_data = NULL;
|
||||
}
|
||||
} else
|
||||
nat = NULL;
|
||||
} else
|
||||
nat = NULL;
|
||||
RWLOCK_EXIT(&ipf_natfrag);
|
||||
|
@ -61,6 +61,6 @@ extern void ipfr_slowtimer __P((void *));
|
||||
# endif
|
||||
#else
|
||||
extern int ipfr_slowtimer __P((void));
|
||||
#endif
|
||||
#endif /* (BSD >= 199306) || SOLARIS */
|
||||
|
||||
#endif /* __IP_FIL_H__ */
|
||||
|
@ -145,6 +145,7 @@ int dlen;
|
||||
} else
|
||||
return 0;
|
||||
a5 >>= 8;
|
||||
a5 &= 0xff;
|
||||
/*
|
||||
* Calculate new address parts for PORT command
|
||||
*/
|
||||
@ -213,7 +214,7 @@ int dlen;
|
||||
sum2 -= sum1;
|
||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||
|
||||
fix_outcksum(&ip->ip_sum, sum2, 0);
|
||||
fix_outcksum(&ip->ip_sum, sum2);
|
||||
#endif
|
||||
ip->ip_len += inc;
|
||||
}
|
||||
@ -440,7 +441,7 @@ int dlen;
|
||||
sum2 -= sum1;
|
||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||
|
||||
fix_outcksum(&ip->ip_sum, sum2, 0);
|
||||
fix_outcksum(&ip->ip_sum, sum2);
|
||||
#endif /* SOLARIS || defined(__sgi) */
|
||||
ip->ip_len += inc;
|
||||
}
|
||||
@ -669,15 +670,18 @@ int rv;
|
||||
while ((rptr < wptr) && (*rptr != '\r'))
|
||||
rptr++;
|
||||
|
||||
if ((*rptr == '\r') && (rptr + 1 < wptr)) {
|
||||
if (*(rptr + 1) == '\n') {
|
||||
rptr += 2;
|
||||
f->ftps_junk = 0;
|
||||
if (*rptr == '\r') {
|
||||
if (rptr + 1 < wptr) {
|
||||
if (*(rptr + 1) == '\n') {
|
||||
rptr += 2;
|
||||
f->ftps_junk = 0;
|
||||
} else
|
||||
rptr++;
|
||||
} else
|
||||
rptr++;
|
||||
break;
|
||||
}
|
||||
f->ftps_rptr = rptr;
|
||||
}
|
||||
f->ftps_rptr = rptr;
|
||||
|
||||
if (rptr == wptr) {
|
||||
rptr = wptr = f->ftps_buf;
|
||||
@ -761,5 +765,7 @@ char **ptr;
|
||||
j += c - '0';
|
||||
}
|
||||
*ptr = s;
|
||||
i &= 0xff;
|
||||
j &= 0xff;
|
||||
return (i << 8) | j;
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ u_int ipf_nattable_sz = NAT_TABLE_SZ;
|
||||
u_int ipf_natrules_sz = NAT_SIZE;
|
||||
u_int ipf_rdrrules_sz = RDR_SIZE;
|
||||
u_int ipf_hostmap_sz = HOSTMAP_SIZE;
|
||||
int nat_wilds = 0;
|
||||
u_32_t nat_masks = 0;
|
||||
u_32_t rdr_masks = 0;
|
||||
ipnat_t **nat_rules = NULL;
|
||||
@ -144,6 +145,7 @@ static void nat_delnat __P((struct ipnat *));
|
||||
static int fr_natgetent __P((caddr_t));
|
||||
static int fr_natgetsz __P((caddr_t));
|
||||
static int fr_natputent __P((caddr_t));
|
||||
static void nat_tabmove __P((nat_t *, u_int));
|
||||
static int nat_match __P((fr_info_t *, ipnat_t *, ip_t *));
|
||||
static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr,
|
||||
struct in_addr));
|
||||
@ -301,10 +303,9 @@ struct hostmap *hm;
|
||||
}
|
||||
|
||||
|
||||
void fix_outcksum(sp, n , len)
|
||||
void fix_outcksum(sp, n)
|
||||
u_short *sp;
|
||||
u_32_t n;
|
||||
int len;
|
||||
{
|
||||
register u_short sumshort;
|
||||
register u_32_t sum1;
|
||||
@ -327,10 +328,9 @@ int len;
|
||||
}
|
||||
|
||||
|
||||
void fix_incksum(sp, n , len)
|
||||
void fix_incksum(sp, n)
|
||||
u_short *sp;
|
||||
u_32_t n;
|
||||
int len;
|
||||
{
|
||||
register u_short sumshort;
|
||||
register u_32_t sum1;
|
||||
@ -357,6 +357,38 @@ int len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fix_datacksum is used *only* for the adjustments of checksums in the data
|
||||
* section of an IP packet.
|
||||
*
|
||||
* The only situation in which you need to do this is when NAT'ing an
|
||||
* ICMP error message. Such a message, contains in its body the IP header
|
||||
* of the original IP packet, that causes the error.
|
||||
*
|
||||
* You can't use fix_incksum or fix_outcksum in that case, because for the
|
||||
* kernel the data section of the ICMP error is just data, and no special
|
||||
* processing like hardware cksum or ntohs processing have been done by the
|
||||
* kernel on the data section.
|
||||
*/
|
||||
void fix_datacksum(sp, n)
|
||||
u_short *sp;
|
||||
u_32_t n;
|
||||
{
|
||||
register u_short sumshort;
|
||||
register u_32_t sum1;
|
||||
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
sum1 = (~ntohs(*sp)) & 0xffff;
|
||||
sum1 += (n);
|
||||
sum1 = (sum1 >> 16) + (sum1 & 0xffff);
|
||||
/* Again */
|
||||
sum1 = (sum1 >> 16) + (sum1 & 0xffff);
|
||||
sumshort = ~(u_short)sum1;
|
||||
*(sp) = htons(sumshort);
|
||||
}
|
||||
|
||||
/*
|
||||
* How the NAT is organised and works.
|
||||
*
|
||||
@ -857,8 +889,8 @@ caddr_t data;
|
||||
/*
|
||||
* Initialize all these so that nat_delete() doesn't cause a crash.
|
||||
*/
|
||||
nat->nat_hstart[0] = NULL;
|
||||
nat->nat_hstart[1] = NULL;
|
||||
nat->nat_phnext[0] = NULL;
|
||||
nat->nat_phnext[1] = NULL;
|
||||
fr = nat->nat_fr;
|
||||
nat->nat_fr = NULL;
|
||||
aps = nat->nat_aps;
|
||||
@ -970,22 +1002,16 @@ caddr_t data;
|
||||
static void nat_delete(natd)
|
||||
struct nat *natd;
|
||||
{
|
||||
register struct nat **natp, *nat;
|
||||
struct ipnat *ipn;
|
||||
|
||||
for (natp = natd->nat_hstart[0]; natp && (nat = *natp);
|
||||
natp = &nat->nat_hnext[0])
|
||||
if (nat == natd) {
|
||||
*natp = nat->nat_hnext[0];
|
||||
break;
|
||||
}
|
||||
|
||||
for (natp = natd->nat_hstart[1]; natp && (nat = *natp);
|
||||
natp = &nat->nat_hnext[1])
|
||||
if (nat == natd) {
|
||||
*natp = nat->nat_hnext[1];
|
||||
break;
|
||||
}
|
||||
if (natd->nat_flags & FI_WILDP)
|
||||
nat_wilds--;
|
||||
if (natd->nat_hnext[0])
|
||||
natd->nat_hnext[0]->nat_phnext[0] = natd->nat_phnext[0];
|
||||
*natd->nat_phnext[0] = natd->nat_hnext[0];
|
||||
if (natd->nat_hnext[1])
|
||||
natd->nat_hnext[1]->nat_phnext[1] = natd->nat_phnext[1];
|
||||
*natd->nat_phnext[1] = natd->nat_hnext[1];
|
||||
|
||||
if (natd->nat_fr != NULL) {
|
||||
ATOMIC_DEC32(natd->nat_fr->fr_ref);
|
||||
@ -1030,7 +1056,7 @@ static int nat_flushtable()
|
||||
{
|
||||
register nat_t *nat, **natp;
|
||||
register int j = 0;
|
||||
|
||||
|
||||
/*
|
||||
* ALL NAT mappings deleted, so lets just make the deletions
|
||||
* quicker.
|
||||
@ -1122,6 +1148,8 @@ int direction;
|
||||
|
||||
bzero((char *)nat, sizeof(*nat));
|
||||
nat->nat_flags = flags;
|
||||
if (flags & FI_WILDP)
|
||||
nat_wilds++;
|
||||
/*
|
||||
* Search the current table for a match.
|
||||
*/
|
||||
@ -1444,16 +1472,22 @@ nat_t *nat;
|
||||
|
||||
nat->nat_next = nat_instances;
|
||||
nat_instances = nat;
|
||||
|
||||
hv = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport,
|
||||
ipf_nattable_sz);
|
||||
natp = &nat_table[0][hv];
|
||||
nat->nat_hstart[0] = natp;
|
||||
if (*natp)
|
||||
(*natp)->nat_phnext[0] = &nat->nat_hnext[0];
|
||||
nat->nat_phnext[0] = natp;
|
||||
nat->nat_hnext[0] = *natp;
|
||||
*natp = nat;
|
||||
|
||||
hv = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport,
|
||||
ipf_nattable_sz);
|
||||
natp = &nat_table[1][hv];
|
||||
nat->nat_hstart[1] = natp;
|
||||
if (*natp)
|
||||
(*natp)->nat_phnext[1] = &nat->nat_hnext[1];
|
||||
nat->nat_phnext[1] = natp;
|
||||
nat->nat_hnext[1] = *natp;
|
||||
*natp = nat;
|
||||
|
||||
@ -1561,12 +1595,16 @@ int dir;
|
||||
u_32_t sum1, sum2, sumd;
|
||||
struct in_addr in;
|
||||
icmphdr_t *icmp;
|
||||
udphdr_t *udp;
|
||||
nat_t *nat;
|
||||
ip_t *oip;
|
||||
int flags = 0;
|
||||
|
||||
if ((fin->fin_fi.fi_fl & FI_SHORT) || (ip->ip_off & IP_OFFMASK))
|
||||
return NULL;
|
||||
/*
|
||||
* nat_icmplookup() will return NULL for `defective' packets.
|
||||
*/
|
||||
if ((ip->ip_v != 4) || !(nat = nat_icmplookup(ip, fin, dir)))
|
||||
return NULL;
|
||||
*nflags = IPN_ICMPERR;
|
||||
@ -1576,16 +1614,33 @@ int dir;
|
||||
flags = IPN_TCP;
|
||||
else if (oip->ip_p == IPPROTO_UDP)
|
||||
flags = IPN_UDP;
|
||||
udp = (udphdr_t *)((((char *)oip) + (oip->ip_hl << 2)));
|
||||
/*
|
||||
* Need to adjust ICMP header to include the real IP#'s and
|
||||
* port #'s. Only apply a checksum change relative to the
|
||||
* IP address change is it will be modified again in ip_natout
|
||||
* IP address change as it will be modified again in ip_natout
|
||||
* for both address and port. Two checksum changes are
|
||||
* necessary for the two header address changes. Be careful
|
||||
* to only modify the checksum once for the port # and twice
|
||||
* for the IP#.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Step 1
|
||||
* Fix the IP addresses in the offending IP packet. You also need
|
||||
* to adjust the IP header checksum of that offending IP packet
|
||||
* and the ICMP checksum of the ICMP error message itself.
|
||||
*
|
||||
* Unfortunately, for UDP and TCP, the IP addresses are also contained
|
||||
* in the pseudo header that is used to compute the UDP resp. TCP
|
||||
* checksum. So, we must compensate that as well. Even worse, the
|
||||
* change in the UDP and TCP checksums require yet another
|
||||
* adjustment of the ICMP checksum of the ICMP error message.
|
||||
*
|
||||
* For the moment we forget about TCP, because that checksum is not
|
||||
* in the first 8 bytes, so it will not be available in most cases.
|
||||
*/
|
||||
|
||||
if (nat->nat_dir == NAT_OUTBOUND) {
|
||||
sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr));
|
||||
in = nat->nat_inip;
|
||||
@ -1601,19 +1656,117 @@ int dir;
|
||||
CALC_SUMD(sum1, sum2, sumd);
|
||||
|
||||
if (nat->nat_dir == NAT_OUTBOUND) {
|
||||
fix_incksum(&oip->ip_sum, sumd, 0);
|
||||
/*
|
||||
* 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);
|
||||
|
||||
sumd += (sumd & 0xffff);
|
||||
while (sumd > 0xffff)
|
||||
sumd = (sumd & 0xffff) + (sumd >> 16);
|
||||
fix_outcksum(&icmp->icmp_cksum, sumd, 0);
|
||||
/*
|
||||
* 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);
|
||||
fix_outcksum(&icmp->icmp_cksum, sumd);
|
||||
}
|
||||
|
||||
#if 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!).
|
||||
*/
|
||||
if (oip->ip_p == IPPROTO_TCP) {
|
||||
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
fix_outcksum(&oip->ip_sum, sumd, 0);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
sumd += (sumd & 0xffff);
|
||||
while (sumd > 0xffff)
|
||||
sumd = (sumd & 0xffff) + (sumd >> 16);
|
||||
fix_incksum(&icmp->icmp_cksum, sumd, 0);
|
||||
/*
|
||||
* 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);
|
||||
fix_incksum(&icmp->icmp_cksum, sumd);
|
||||
}
|
||||
|
||||
#if 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!).
|
||||
*/
|
||||
if (oip->ip_p == IPPROTO_TCP) {
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1624,23 +1777,98 @@ int dir;
|
||||
* XXX - what if this is bogus hl and we go off the end ?
|
||||
* In this case, nat_icmpinlookup() will have returned NULL.
|
||||
*/
|
||||
tcp = (tcphdr_t *)((((char *)oip) + (oip->ip_hl << 2)));
|
||||
tcp = (tcphdr_t *)udp;
|
||||
|
||||
/*
|
||||
* Step 2 :
|
||||
* For offending TCP/UDP IP packets, translate the ports as
|
||||
* well, based on the NAT specification. Of course such
|
||||
* a change must be reflected in the ICMP checksum as well.
|
||||
*
|
||||
* Advance notice : Now it becomes complicated :-)
|
||||
*
|
||||
* Since the port fields are part of the TCP/UDP checksum
|
||||
* of the offending IP packet, you need to adjust that checksum
|
||||
* as well... but, if you change, you must change the icmp
|
||||
* checksum *again*, to reflect that change.
|
||||
*
|
||||
* To further complicate: the TCP checksum is not in the first
|
||||
* 8 bytes of the offending ip packet, so it most likely is not
|
||||
* available (we might have to fix that if the encounter a
|
||||
* device that returns more than 8 data bytes on icmp error)
|
||||
*/
|
||||
|
||||
if (nat->nat_dir == NAT_OUTBOUND) {
|
||||
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);
|
||||
tcp->th_sport = nat->nat_inport;
|
||||
fix_outcksum(&icmp->icmp_cksum, sumd, 0);
|
||||
fix_outcksum(&icmp->icmp_cksum, sumd);
|
||||
|
||||
/*
|
||||
* 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 && udp->uh_sum) {
|
||||
|
||||
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_outcksum(&icmp->icmp_cksum, 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);
|
||||
tcp->th_dport = nat->nat_outport;
|
||||
fix_incksum(&icmp->icmp_cksum, sumd, 0);
|
||||
fix_incksum(&icmp->icmp_cksum, sumd);
|
||||
|
||||
/*
|
||||
* 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 && udp->uh_sum) {
|
||||
|
||||
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_incksum(&icmp->icmp_cksum, sumd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1665,30 +1893,92 @@ register u_int flags, p;
|
||||
struct in_addr src , mapdst;
|
||||
u_32_t ports;
|
||||
{
|
||||
register u_short sport, mapdport;
|
||||
register u_short sport, dport;
|
||||
register nat_t *nat;
|
||||
register int nflags;
|
||||
register u_32_t dst;
|
||||
u_int hv;
|
||||
|
||||
mapdport = ports >> 16;
|
||||
dst = mapdst.s_addr;
|
||||
dport = ports >> 16;
|
||||
sport = ports & 0xffff;
|
||||
flags &= IPN_TCPUDP;
|
||||
|
||||
hv = NAT_HASH_FN(mapdst.s_addr, mapdport, ipf_nattable_sz);
|
||||
hv = NAT_HASH_FN(dst, dport, ipf_nattable_sz);
|
||||
nat = nat_table[1][hv];
|
||||
for (; nat; nat = nat->nat_hnext[1]) {
|
||||
nflags = nat->nat_flags;
|
||||
if ((!ifp || ifp == nat->nat_ifp) &&
|
||||
nat->nat_oip.s_addr == src.s_addr &&
|
||||
nat->nat_outip.s_addr == mapdst.s_addr &&
|
||||
nat->nat_outip.s_addr == dst &&
|
||||
(((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP)))
|
||||
|| (p == nat->nat_p)) && (!flags ||
|
||||
(((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) &&
|
||||
((nat->nat_outport == mapdport) ||
|
||||
(nflags & FI_W_SPORT)))))
|
||||
((nat->nat_outport == dport) || (nflags & FI_W_SPORT)))))
|
||||
return nat;
|
||||
}
|
||||
return NULL;
|
||||
if (!nat_wilds || !(flags & IPN_TCPUDP))
|
||||
return NULL;
|
||||
RWLOCK_EXIT(&ipf_nat);
|
||||
hv = NAT_HASH_FN(dst, 0, ipf_nattable_sz);
|
||||
WRITE_ENTER(&ipf_nat);
|
||||
nat = nat_table[1][hv];
|
||||
for (; nat; nat = nat->nat_hnext[1]) {
|
||||
nflags = nat->nat_flags;
|
||||
if (ifp && ifp != nat->nat_ifp)
|
||||
continue;
|
||||
if (!(nflags & IPN_TCPUDP))
|
||||
continue;
|
||||
if (!(nflags & FI_WILDP))
|
||||
continue;
|
||||
if (nat->nat_oip.s_addr != src.s_addr ||
|
||||
nat->nat_outip.s_addr != dst)
|
||||
continue;
|
||||
if (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) &&
|
||||
((nat->nat_outport == dport) || (nflags & FI_W_SPORT))) {
|
||||
hv = NAT_HASH_FN(dst, dport, ipf_nattable_sz);
|
||||
nat_tabmove(nat, hv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MUTEX_DOWNGRADE(&ipf_nat);
|
||||
return nat;
|
||||
}
|
||||
|
||||
|
||||
static void nat_tabmove(nat, hv)
|
||||
nat_t *nat;
|
||||
u_int hv;
|
||||
{
|
||||
nat_t **natp;
|
||||
|
||||
/*
|
||||
* Remove the NAT entry from the old location
|
||||
*/
|
||||
if (nat->nat_hnext[0])
|
||||
nat->nat_hnext[0]->nat_phnext[0] = nat->nat_phnext[0];
|
||||
*nat->nat_phnext[0] = nat->nat_hnext[0];
|
||||
|
||||
if (nat->nat_hnext[1])
|
||||
nat->nat_hnext[0]->nat_phnext[1] = nat->nat_phnext[1];
|
||||
*nat->nat_phnext[1] = nat->nat_hnext[1];
|
||||
|
||||
natp = &nat_table[0][hv];
|
||||
if (*natp)
|
||||
(*natp)->nat_phnext[0] = &nat->nat_hnext[0];
|
||||
nat->nat_phnext[0] = natp;
|
||||
nat->nat_hnext[0] = *natp;
|
||||
*natp = nat;
|
||||
|
||||
/*
|
||||
* Add into the NAT table in the new position
|
||||
*/
|
||||
natp = &nat_table[1][hv];
|
||||
if (*natp)
|
||||
(*natp)->nat_phnext[1] = &nat->nat_hnext[1];
|
||||
nat->nat_phnext[1] = natp;
|
||||
nat->nat_hnext[1] = *natp;
|
||||
*natp = nat;
|
||||
}
|
||||
|
||||
|
||||
@ -1707,19 +1997,21 @@ u_32_t ports;
|
||||
register u_short sport, dport;
|
||||
register nat_t *nat;
|
||||
register int nflags;
|
||||
u_32_t srcip;
|
||||
u_int hv;
|
||||
|
||||
sport = ports & 0xffff;
|
||||
dport = ports >> 16;
|
||||
flags &= IPN_TCPUDP;
|
||||
srcip = src.s_addr;
|
||||
|
||||
hv = NAT_HASH_FN(src.s_addr, sport, ipf_nattable_sz);
|
||||
hv = NAT_HASH_FN(srcip, sport, ipf_nattable_sz);
|
||||
nat = nat_table[0][hv];
|
||||
for (; nat; nat = nat->nat_hnext[0]) {
|
||||
nflags = nat->nat_flags;
|
||||
|
||||
if ((!ifp || ifp == nat->nat_ifp) &&
|
||||
nat->nat_inip.s_addr == src.s_addr &&
|
||||
nat->nat_inip.s_addr == srcip &&
|
||||
nat->nat_oip.s_addr == dst.s_addr &&
|
||||
(((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP)))
|
||||
|| (p == nat->nat_p)) && (!flags ||
|
||||
@ -1727,7 +2019,32 @@ u_32_t ports;
|
||||
(nat->nat_oport == dport || nflags & FI_W_DPORT))))
|
||||
return nat;
|
||||
}
|
||||
return NULL;
|
||||
if (!nat_wilds || !(flags & IPN_TCPUDP))
|
||||
return NULL;
|
||||
RWLOCK_EXIT(&ipf_nat);
|
||||
hv = NAT_HASH_FN(srcip, 0, ipf_nattable_sz);
|
||||
WRITE_ENTER(&ipf_nat);
|
||||
nat = nat_table[0][hv];
|
||||
for (; nat; nat = nat->nat_hnext[0]) {
|
||||
nflags = nat->nat_flags;
|
||||
if (ifp && ifp != nat->nat_ifp)
|
||||
continue;
|
||||
if (!(nflags & IPN_TCPUDP))
|
||||
continue;
|
||||
if (!(nflags & FI_WILDP))
|
||||
continue;
|
||||
if ((nat->nat_inip.s_addr != srcip) ||
|
||||
(nat->nat_oip.s_addr != dst.s_addr))
|
||||
continue;
|
||||
if (((nat->nat_inport == sport) || (nflags & FI_W_DPORT)) &&
|
||||
((nat->nat_oport == dport) || (nflags & FI_W_SPORT))) {
|
||||
hv = NAT_HASH_FN(srcip, sport, ipf_nattable_sz);
|
||||
nat_tabmove(nat, hv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MUTEX_DOWNGRADE(&ipf_nat);
|
||||
return nat;
|
||||
}
|
||||
|
||||
|
||||
@ -1863,6 +2180,7 @@ fr_info_t *fin;
|
||||
nat->nat_outport = sport;
|
||||
nat->nat_flags &= ~(FI_W_DPORT|FI_W_SPORT);
|
||||
nflags = nat->nat_flags;
|
||||
nat_wilds--;
|
||||
}
|
||||
} else {
|
||||
RWLOCK_EXIT(&ipf_nat);
|
||||
@ -1943,16 +2261,16 @@ fr_info_t *fin;
|
||||
CALC_SUMD(s1, s2, sumd);
|
||||
|
||||
if (nat->nat_dir == NAT_OUTBOUND)
|
||||
fix_incksum(&ip->ip_sum, sumd, 0);
|
||||
fix_incksum(&ip->ip_sum, sumd);
|
||||
else
|
||||
fix_outcksum(&ip->ip_sum, sumd, 0);
|
||||
fix_outcksum(&ip->ip_sum, sumd);
|
||||
}
|
||||
#if SOLARIS || defined(__sgi)
|
||||
else {
|
||||
if (nat->nat_dir == NAT_OUTBOUND)
|
||||
fix_outcksum(&ip->ip_sum, nat->nat_ipsumd, 0);
|
||||
fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
|
||||
else
|
||||
fix_incksum(&ip->ip_sum, nat->nat_ipsumd, 0);
|
||||
fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
|
||||
}
|
||||
#endif
|
||||
ip->ip_src = nat->nat_outip;
|
||||
@ -1996,11 +2314,9 @@ fr_info_t *fin;
|
||||
|
||||
if (csump) {
|
||||
if (nat->nat_dir == NAT_OUTBOUND)
|
||||
fix_outcksum(csump, nat->nat_sumd[1],
|
||||
ip->ip_len);
|
||||
fix_outcksum(csump, nat->nat_sumd[1]);
|
||||
else
|
||||
fix_incksum(csump, nat->nat_sumd[1],
|
||||
ip->ip_len);
|
||||
fix_incksum(csump, nat->nat_sumd[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2077,6 +2393,7 @@ fr_info_t *fin;
|
||||
nat->nat_outport = dport;
|
||||
nat->nat_flags &= ~(FI_W_SPORT|FI_W_DPORT);
|
||||
nflags = nat->nat_flags;
|
||||
nat_wilds--;
|
||||
}
|
||||
} else {
|
||||
RWLOCK_EXIT(&ipf_nat);
|
||||
@ -2154,9 +2471,9 @@ fr_info_t *fin;
|
||||
*/
|
||||
#if SOLARIS || defined(__sgi)
|
||||
if (nat->nat_dir == NAT_OUTBOUND)
|
||||
fix_incksum(&ip->ip_sum, nat->nat_ipsumd, 0);
|
||||
fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
|
||||
else
|
||||
fix_outcksum(&ip->ip_sum, nat->nat_ipsumd, 0);
|
||||
fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
|
||||
#endif
|
||||
if (!(ip->ip_off & IP_OFFMASK) &&
|
||||
!(fin->fin_fi.fi_fl & FI_SHORT)) {
|
||||
@ -2197,11 +2514,9 @@ fr_info_t *fin;
|
||||
|
||||
if (csump) {
|
||||
if (nat->nat_dir == NAT_OUTBOUND)
|
||||
fix_incksum(csump, nat->nat_sumd[0],
|
||||
0);
|
||||
fix_incksum(csump, nat->nat_sumd[0]);
|
||||
else
|
||||
fix_outcksum(csump, nat->nat_sumd[0],
|
||||
0);
|
||||
fix_outcksum(csump, nat->nat_sumd[0]);
|
||||
}
|
||||
}
|
||||
ATOMIC_INCL(nat_stats.ns_mapped[0]);
|
||||
|
@ -82,7 +82,7 @@ typedef struct nat {
|
||||
struct hostmap *nat_hm;
|
||||
struct nat *nat_next;
|
||||
struct nat *nat_hnext[2];
|
||||
struct nat **nat_hstart[2];
|
||||
struct nat **nat_phnext[2];
|
||||
void *nat_ifp;
|
||||
int nat_dir;
|
||||
char nat_ifname[IFNAMSIZ];
|
||||
@ -142,6 +142,11 @@ typedef struct ipnat {
|
||||
#define NAT_REDIRECT 0x02
|
||||
#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT)
|
||||
#define NAT_MAPBLK 0x04
|
||||
/* 0x100 reserved for FI_W_SPORT */
|
||||
/* 0x200 reserved for FI_W_DPORT */
|
||||
/* 0x400 reserved for FI_W_SADDR */
|
||||
/* 0x800 reserved for FI_W_DADDR */
|
||||
/* 0x1000 reserved for FI_W_NEWFR */
|
||||
|
||||
#define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */
|
||||
#define USABLE_PORTS (65536 - MAPBLK_MINPORT)
|
||||
@ -294,7 +299,8 @@ extern int ip_natout __P((ip_t *, fr_info_t *));
|
||||
extern int ip_natin __P((ip_t *, fr_info_t *));
|
||||
extern void ip_natunload __P((void)), ip_natexpire __P((void));
|
||||
extern void nat_log __P((struct nat *, u_int));
|
||||
extern void fix_incksum __P((u_short *, u_32_t, int));
|
||||
extern void fix_outcksum __P((u_short *, u_32_t, int));
|
||||
extern void fix_incksum __P((u_short *, u_32_t));
|
||||
extern void fix_outcksum __P((u_short *, u_32_t));
|
||||
extern void fix_datacksum __P((u_short *, u_32_t));
|
||||
|
||||
#endif /* __IP_NAT_H__ */
|
||||
|
@ -171,8 +171,8 @@ nat_t *nat;
|
||||
tcphdr_t *tcp, tcph, *tcp2 = &tcph;
|
||||
raudio_t *rap = aps->aps_data;
|
||||
struct in_addr swa, swb;
|
||||
u_int a1, a2, a3, a4;
|
||||
int off, dlen, slen;
|
||||
int a1, a2, a3, a4;
|
||||
u_short sp, dp;
|
||||
fr_info_t fi;
|
||||
tcp_seq seq;
|
||||
|
@ -106,6 +106,7 @@ static const char rcsid[] = "@(#)$FreeBSD$";
|
||||
static ipstate_t **ips_table = NULL;
|
||||
static ipstate_t *ips_list = NULL;
|
||||
static int ips_num = 0;
|
||||
static int ips_wild = 0;
|
||||
static ips_stat_t ips_stats;
|
||||
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
|
||||
extern KRWLOCK_T ipf_state, ipf_mutex;
|
||||
@ -123,6 +124,7 @@ static int fr_state_flush __P((int));
|
||||
static ips_stat_t *fr_statetstats __P((void));
|
||||
static void fr_delstate __P((ipstate_t *));
|
||||
static int fr_state_remove __P((caddr_t));
|
||||
static void fr_ipsmove __P((ipstate_t **, ipstate_t *, u_int));
|
||||
int fr_stputent __P((caddr_t));
|
||||
int fr_stgetent __P((caddr_t));
|
||||
void fr_stinsert __P((ipstate_t *));
|
||||
@ -135,7 +137,8 @@ u_long fr_tcpidletimeout = FIVE_DAYS,
|
||||
fr_tcpclosewait = 2 * TCP_MSL,
|
||||
fr_tcplastack = 2 * TCP_MSL,
|
||||
fr_tcptimeout = 2 * TCP_MSL,
|
||||
fr_tcpclosed = 1,
|
||||
fr_tcpclosed = 120,
|
||||
fr_tcphalfclosed = 2 * 2 * 3600, /* 2 hours */
|
||||
fr_udptimeout = 240,
|
||||
fr_icmptimeout = 120;
|
||||
int fr_statemax = IPSTATE_MAX,
|
||||
@ -240,9 +243,12 @@ caddr_t data;
|
||||
|
||||
for (sp = ips_list; sp; sp = sp->is_next)
|
||||
if ((sp->is_p == st.is_p) && (sp->is_v == st.is_v) &&
|
||||
!bcmp(&sp->is_src, &st.is_src, sizeof(st.is_src)) &&
|
||||
!bcmp(&sp->is_dst, &st.is_src, sizeof(st.is_dst)) &&
|
||||
!bcmp(&sp->is_ps, &st.is_ps, sizeof(st.is_ps))) {
|
||||
!bcmp((char *)&sp->is_src, (char *)&st.is_src,
|
||||
sizeof(st.is_src)) &&
|
||||
!bcmp((char *)&sp->is_dst, (char *)&st.is_src,
|
||||
sizeof(st.is_dst)) &&
|
||||
!bcmp((char *)&sp->is_ps, (char *)&st.is_ps,
|
||||
sizeof(st.is_ps))) {
|
||||
WRITE_ENTER(&ipf_state);
|
||||
#ifdef IPFILTER_LOG
|
||||
ipstate_log(sp, ISL_REMOVE);
|
||||
@ -590,8 +596,8 @@ u_int flags;
|
||||
hv += tcp->th_dport;
|
||||
hv += tcp->th_sport;
|
||||
}
|
||||
is->is_send = ntohl(tcp->th_seq) + ip->ip_len -
|
||||
fin->fin_hlen - (tcp->th_off << 2) +
|
||||
is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen -
|
||||
(tcp->th_off << 2) +
|
||||
((tcp->th_flags & TH_SYN) ? 1 : 0) +
|
||||
((tcp->th_flags & TH_FIN) ? 1 : 0);
|
||||
is->is_maxsend = is->is_send;
|
||||
@ -660,6 +666,8 @@ u_int flags;
|
||||
is->is_flags = fin->fin_fi.fi_fl & FI_CMP;
|
||||
is->is_flags |= FI_CMP << 4;
|
||||
is->is_flags |= flags & (FI_WILDP|FI_WILDA);
|
||||
if (flags & (FI_WILDP|FI_WILDA))
|
||||
ips_wild++;
|
||||
is->is_ifp[1 - out] = NULL;
|
||||
is->is_ifp[out] = fin->fin_ifp;
|
||||
#ifdef _KERNEL
|
||||
@ -718,6 +726,7 @@ tcphdr_t *tcp;
|
||||
((tcp->th_flags & TH_SYN) ? 1 : 0) +
|
||||
((tcp->th_flags & TH_FIN) ? 1 : 0);
|
||||
|
||||
MUTEX_ENTER(&is->is_lock);
|
||||
if (fdata->td_end == 0) {
|
||||
/*
|
||||
* Must be a (outgoing) SYN-ACK in reply to a SYN.
|
||||
@ -783,12 +792,11 @@ tcphdr_t *tcp;
|
||||
/*
|
||||
* Nearing end of connection, start timeout.
|
||||
*/
|
||||
MUTEX_ENTER(&is->is_lock);
|
||||
/* source ? 0 : 1 -> !source */
|
||||
fr_tcp_age(&is->is_age, is->is_state, fin, !source);
|
||||
MUTEX_EXIT(&is->is_lock);
|
||||
ret = 1;
|
||||
}
|
||||
MUTEX_EXIT(&is->is_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -892,6 +900,7 @@ tcphdr_t *tcp;
|
||||
is->is_maxdend = is->is_dend + 1;
|
||||
}
|
||||
is->is_flags &= ~(FI_W_SPORT|FI_W_DPORT);
|
||||
ips_wild--;
|
||||
}
|
||||
|
||||
ret = -1;
|
||||
@ -983,7 +992,7 @@ fr_info_t *fin;
|
||||
* Only a basic IP header (no options) should be with
|
||||
* an ICMP error header.
|
||||
*/
|
||||
if (((ip->ip_v != 4) && (ip->ip_hl != 5)) ||
|
||||
if (((ip->ip_v != 4) || (ip->ip_hl != 5)) ||
|
||||
(fin->fin_plen < ICMPERR_MINPKTLEN))
|
||||
return NULL;
|
||||
ic = (struct icmp *)fin->fin_dp;
|
||||
@ -1037,8 +1046,8 @@ fr_info_t *fin;
|
||||
* the IP6EQ and IP6NEQ macros produce the wrong results because
|
||||
* of the 'junk' in the unused part of the union
|
||||
*/
|
||||
bzero(&src, sizeof(src));
|
||||
bzero(&dst, sizeof(dst));
|
||||
bzero((char *)&src, sizeof(src));
|
||||
bzero((char *)&dst, sizeof(dst));
|
||||
|
||||
if (oip->ip_p == IPPROTO_ICMP) {
|
||||
icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2));
|
||||
@ -1158,6 +1167,38 @@ fr_info_t *fin;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void fr_ipsmove(isp, is, hv)
|
||||
ipstate_t **isp, *is;
|
||||
u_int hv;
|
||||
{
|
||||
u_int hvm;
|
||||
|
||||
hvm = is->is_hv;
|
||||
/*
|
||||
* Remove the hash from the old location...
|
||||
*/
|
||||
if (is->is_hnext)
|
||||
is->is_hnext->is_phnext = isp;
|
||||
*isp = is->is_hnext;
|
||||
if (ips_table[hvm] == NULL)
|
||||
ips_stats.iss_inuse--;
|
||||
|
||||
/*
|
||||
* ...and put the hash in the new one.
|
||||
*/
|
||||
hvm = hv % fr_statesize;
|
||||
isp = &ips_table[hvm];
|
||||
if (*isp)
|
||||
(*isp)->is_phnext = &is->is_hnext;
|
||||
else
|
||||
ips_stats.iss_inuse++;
|
||||
is->is_phnext = isp;
|
||||
is->is_hnext = *isp;
|
||||
*isp = is;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if a packet has a registered state.
|
||||
*/
|
||||
@ -1240,7 +1281,7 @@ fr_info_t *fin;
|
||||
break;
|
||||
case IPPROTO_TCP :
|
||||
{
|
||||
register u_short dport = tcp->th_dport, sport = tcp->th_sport;
|
||||
register u_short dport, sport;
|
||||
register int i;
|
||||
|
||||
i = tcp->th_flags;
|
||||
@ -1250,57 +1291,42 @@ fr_info_t *fin;
|
||||
if ((i & TH_RST) &&
|
||||
((i & (TH_FIN|TH_SYN|TH_RST)) != TH_RST))
|
||||
break;
|
||||
tryagain = 0;
|
||||
retry_tcp:
|
||||
hvm = hv % fr_statesize;
|
||||
WRITE_ENTER(&ipf_state);
|
||||
for (isp = &ips_table[hvm]; (is = *isp);
|
||||
isp = &is->is_hnext)
|
||||
|
||||
|
||||
if ((is->is_p == pr) && (is->is_v == v) &&
|
||||
fr_matchsrcdst(is, src, dst, fin, tcp)) {
|
||||
if (fr_tcpstate(is, fin, ip, tcp))
|
||||
break;
|
||||
is = NULL;
|
||||
break;
|
||||
}
|
||||
if (is != NULL)
|
||||
break;
|
||||
RWLOCK_EXIT(&ipf_state);
|
||||
hv += dport;
|
||||
hv += sport;
|
||||
if (tryagain == 0) {
|
||||
tryagain = 1;
|
||||
goto retry_tcp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPPROTO_UDP :
|
||||
{
|
||||
register u_short dport = tcp->th_dport, sport = tcp->th_sport;
|
||||
|
||||
dport = tcp->th_dport;
|
||||
sport = tcp->th_sport;
|
||||
tryagain = 0;
|
||||
retry_udp:
|
||||
hvm = hv % fr_statesize;
|
||||
/*
|
||||
* Nothing else to match on but ports. and IP#'s
|
||||
*/
|
||||
READ_ENTER(&ipf_state);
|
||||
for (is = ips_table[hvm]; is; is = is->is_hnext)
|
||||
if ((is->is_p == pr) && (is->is_v == v) &&
|
||||
fr_matchsrcdst(is, src, dst, fin, tcp)) {
|
||||
is->is_age = fr_udptimeout;
|
||||
break;
|
||||
}
|
||||
if (is != NULL)
|
||||
break;
|
||||
RWLOCK_EXIT(&ipf_state);
|
||||
hv += dport;
|
||||
hv += sport;
|
||||
if (tryagain == 0) {
|
||||
READ_ENTER(&ipf_state);
|
||||
retry_tcpudp:
|
||||
hvm = hv % fr_statesize;
|
||||
for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext)
|
||||
if ((is->is_p == pr) && (is->is_v == v) &&
|
||||
fr_matchsrcdst(is, src, dst, fin, tcp)) {
|
||||
if ((pr == IPPROTO_TCP)) {
|
||||
if (!fr_tcpstate(is, fin, ip, tcp)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is != NULL) {
|
||||
if (tryagain &&
|
||||
!(is->is_flags & (FI_WILDP|FI_WILDA))) {
|
||||
hv += dport;
|
||||
hv += sport;
|
||||
fr_ipsmove(isp, is, hv);
|
||||
MUTEX_DOWNGRADE(&ipf_state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
RWLOCK_EXIT(&ipf_state);
|
||||
if (!tryagain && ips_wild) {
|
||||
hv -= dport;
|
||||
hv -= sport;
|
||||
tryagain = 1;
|
||||
goto retry_udp;
|
||||
WRITE_ENTER(&ipf_state);
|
||||
goto retry_tcpudp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1357,6 +1383,8 @@ ipstate_t *is;
|
||||
{
|
||||
frentry_t *fr;
|
||||
|
||||
if (is->is_flags & (FI_WILDP|FI_WILDA))
|
||||
ips_wild--;
|
||||
if (is->is_next)
|
||||
is->is_next->is_pnext = is->is_pnext;
|
||||
*is->is_pnext = is->is_next;
|
||||
@ -1566,7 +1594,7 @@ int dir;
|
||||
* SYN_RECEIVED -> FIN_WAIT_1
|
||||
*/
|
||||
state[dir] = TCPS_FIN_WAIT_1;
|
||||
*age = fr_tcpidletimeout; /* or fr_tcptimeout? */
|
||||
*age = fr_tcpidletimeout;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1578,7 +1606,7 @@ int dir;
|
||||
* ESTABLISHED -> FIN_WAIT_1
|
||||
*/
|
||||
state[dir] = TCPS_FIN_WAIT_1;
|
||||
*age = fr_tcpidletimeout;
|
||||
*age = fr_tcphalfclosed;
|
||||
} else if (flags & TH_ACK) {
|
||||
/* an ACK, should we exclude other flags here? */
|
||||
if (ostate == TCPS_FIN_WAIT_1) {
|
||||
@ -1590,7 +1618,7 @@ int dir;
|
||||
* a half-closed connection
|
||||
*/
|
||||
state[dir] = TCPS_CLOSE_WAIT;
|
||||
*age = fr_tcpidletimeout;
|
||||
*age = fr_tcphalfclosed;
|
||||
} else if (ostate < TCPS_CLOSE_WAIT)
|
||||
/*
|
||||
* Still a fully established connection,
|
||||
@ -1614,7 +1642,7 @@ int dir;
|
||||
* closed already and we did not close our side yet;
|
||||
* reset timeout
|
||||
*/
|
||||
*age = fr_tcpidletimeout;
|
||||
*age = fr_tcphalfclosed;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1638,7 +1666,7 @@ int dir;
|
||||
* other side is still active (ESTABLISHED/CLOSE_WAIT);
|
||||
* continue with this half-closed connection
|
||||
*/
|
||||
*age = fr_tcpidletimeout;
|
||||
*age = fr_tcphalfclosed;
|
||||
break;
|
||||
|
||||
case TCPS_CLOSING: /* 7 */
|
||||
|
@ -174,6 +174,7 @@ extern u_long fr_tcpclosewait;
|
||||
extern u_long fr_tcplastack;
|
||||
extern u_long fr_tcptimeout;
|
||||
extern u_long fr_tcpclosed;
|
||||
extern u_long fr_tcphalfclosed;
|
||||
extern u_long fr_udptimeout;
|
||||
extern u_long fr_icmptimeout;
|
||||
extern int fr_state_lock;
|
||||
|
@ -12,6 +12,6 @@
|
||||
#ifndef __IPL_H__
|
||||
#define __IPL_H__
|
||||
|
||||
#define IPL_VERSION "IP Filter: v3.4.9"
|
||||
#define IPL_VERSION "IP Filter: v3.4.12"
|
||||
|
||||
#endif
|
||||
|
@ -65,6 +65,8 @@ SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW,
|
||||
&fr_tcptimeout, 0, "");
|
||||
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW,
|
||||
&fr_tcpclosed, 0, "");
|
||||
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW,
|
||||
&fr_tcphalfclosed, 0, "");
|
||||
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW,
|
||||
&fr_udptimeout, 0, "");
|
||||
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW,
|
||||
|
Loading…
Reference in New Issue
Block a user