| version 1.189, 2003/12/04 19:38:24 |
version 1.190, 2003/12/06 23:56:10 |
|
|
| struct pfil_head inet_pfil_hook; |
struct pfil_head inet_pfil_hook; |
| #endif |
#endif |
| |
|
| struct ipqhead ipq; |
/* IP datagram reassembly queues (hashed) */ |
| |
#define IPREASS_NHASH_LOG2 6 |
| |
#define IPREASS_NHASH (1 << IPREASS_NHASH_LOG2) |
| |
#define IPREASS_HMASK (IPREASS_NHASH - 1) |
| |
#define IPREASS_HASH(x,y) \ |
| |
(((((x) & 0xF) | ((((x) >> 8) & 0xF) << 4)) ^ (y)) & IPREASS_HMASK) |
| |
struct ipqhead ipq[IPREASS_NHASH]; |
| |
#ifdef notyet |
| |
static int nipq = 0; /* total # of reass queues */ |
| |
#endif |
| int ipq_locked; |
int ipq_locked; |
| int ip_nfragpackets = 0; |
int ip_nfragpackets = 0; |
| int ip_maxfragpackets = 200; |
int ip_maxfragpackets = 200; |
|
|
| if (pr->pr_domain->dom_family == PF_INET && |
if (pr->pr_domain->dom_family == PF_INET && |
| pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) |
pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) |
| ip_protox[pr->pr_protocol] = pr - inetsw; |
ip_protox[pr->pr_protocol] = pr - inetsw; |
| LIST_INIT(&ipq); |
for (i = 0; i < IPREASS_NHASH; i++) |
| |
LIST_INIT(&ipq[i]); |
| |
|
| ip_id = time.tv_sec & 0xfffff; |
ip_id = time.tv_sec & 0xfffff; |
| ipintrq.ifq_maxlen = ipqmaxlen; |
ipintrq.ifq_maxlen = ipqmaxlen; |
| TAILQ_INIT(&in_ifaddrhead); |
TAILQ_INIT(&in_ifaddrhead); |
| Line 437 ip_input(struct mbuf *m) |
|
| Line 448 ip_input(struct mbuf *m) |
|
| int downmatch; |
int downmatch; |
| int checkif; |
int checkif; |
| int srcrt = 0; |
int srcrt = 0; |
| |
u_int hash; |
| #ifdef FAST_IPSEC |
#ifdef FAST_IPSEC |
| struct m_tag *mtag; |
struct m_tag *mtag; |
| struct tdb_ident *tdbi; |
struct tdb_ident *tdbi; |
|
|
| * of this datagram. |
* of this datagram. |
| */ |
*/ |
| IPQ_LOCK(); |
IPQ_LOCK(); |
| LIST_FOREACH(fp, &ipq, ipq_q) |
hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); |
| |
/* XXX LIST_FOREACH(fp, &ipq[hash], ipq_q) */ |
| |
for (fp = LIST_FIRST(&ipq[hash]); fp != NULL; |
| |
fp = LIST_NEXT(fp, ipq_q)) { |
| if (ip->ip_id == fp->ipq_id && |
if (ip->ip_id == fp->ipq_id && |
| in_hosteq(ip->ip_src, fp->ipq_src) && |
in_hosteq(ip->ip_src, fp->ipq_src) && |
| in_hosteq(ip->ip_dst, fp->ipq_dst) && |
in_hosteq(ip->ip_dst, fp->ipq_dst) && |
| ip->ip_p == fp->ipq_p) |
ip->ip_p == fp->ipq_p) |
| goto found; |
goto found; |
| |
|
| |
} |
| fp = 0; |
fp = 0; |
| found: |
found: |
| |
|
|
|
| ipqe->ipqe_mff = mff; |
ipqe->ipqe_mff = mff; |
| ipqe->ipqe_m = m; |
ipqe->ipqe_m = m; |
| ipqe->ipqe_ip = ip; |
ipqe->ipqe_ip = ip; |
| m = ip_reass(ipqe, fp); |
m = ip_reass(ipqe, fp, &ipq[hash]); |
| if (m == 0) { |
if (m == 0) { |
| IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
| return; |
return; |
|
|
| * is given as fp; otherwise have to make a chain. |
* is given as fp; otherwise have to make a chain. |
| */ |
*/ |
| struct mbuf * |
struct mbuf * |
| ip_reass(ipqe, fp) |
ip_reass(ipqe, fp, ipqhead) |
| struct ipqent *ipqe; |
struct ipqent *ipqe; |
| struct ipq *fp; |
struct ipq *fp; |
| |
struct ipqhead *ipqhead; |
| { |
{ |
| struct mbuf *m = ipqe->ipqe_m; |
struct mbuf *m = ipqe->ipqe_m; |
| struct ipqent *nq, *p, *q; |
struct ipqent *nq, *p, *q; |
| Line 1005 ip_reass(ipqe, fp) |
|
| Line 1023 ip_reass(ipqe, fp) |
|
| M_FTABLE, M_NOWAIT); |
M_FTABLE, M_NOWAIT); |
| if (fp == NULL) |
if (fp == NULL) |
| goto dropfrag; |
goto dropfrag; |
| LIST_INSERT_HEAD(&ipq, fp, ipq_q); |
LIST_INSERT_HEAD(ipqhead, fp, ipq_q); |
| fp->ipq_ttl = IPFRAGTTL; |
fp->ipq_ttl = IPFRAGTTL; |
| fp->ipq_p = ipqe->ipqe_ip->ip_p; |
fp->ipq_p = ipqe->ipqe_ip->ip_p; |
| fp->ipq_id = ipqe->ipqe_ip->ip_id; |
fp->ipq_id = ipqe->ipqe_ip->ip_id; |
|
|
| void |
void |
| ip_slowtimo() |
ip_slowtimo() |
| { |
{ |
| |
static unsigned dropscanidx = 0; |
| |
unsigned i; |
| struct ipq *fp, *nfp; |
struct ipq *fp, *nfp; |
| int s = splsoftnet(); |
int s = splsoftnet(); |
| |
|
| IPQ_LOCK(); |
IPQ_LOCK(); |
| for (fp = LIST_FIRST(&ipq); fp != NULL; fp = nfp) { |
for (i = 0; i < IPREASS_NHASH; i++) { |
| nfp = LIST_NEXT(fp, ipq_q); |
for (fp = LIST_FIRST(&ipq[i]); fp != NULL; fp = nfp) { |
| if (--fp->ipq_ttl == 0) { |
nfp = LIST_NEXT(fp, ipq_q); |
| ipstat.ips_fragtimeout++; |
if (--fp->ipq_ttl == 0) { |
| ip_freef(fp); |
ipstat.ips_fragtimeout++; |
| |
ip_freef(fp); |
| |
} |
| } |
} |
| } |
} |
| /* |
/* |
| * If we are over the maximum number of fragments |
* If we are over the maximum number of fragments |
| * (due to the limit being lowered), drain off |
* (due to the limit being lowered), drain off |
| * enough to get down to the new limit. |
* enough to get down to the new limit. Start draining |
| |
* from the reassembly hashqueue most recently drained. |
| */ |
*/ |
| if (ip_maxfragpackets < 0) |
if (ip_maxfragpackets < 0) |
| ; |
; |
| else { |
else { |
| while (ip_nfragpackets > ip_maxfragpackets && LIST_FIRST(&ipq)) |
int wrapped = 0; |
| ip_freef(LIST_FIRST(&ipq)); |
|
| |
i = dropscanidx; |
| |
while (ip_nfragpackets > ip_maxfragpackets && wrapped == 0) { |
| |
while (LIST_FIRST(&ipq[i]) != NULL) |
| |
ip_freef(LIST_FIRST(&ipq[i])); |
| |
if (++i >= IPREASS_NHASH) { |
| |
i = 0; |
| |
} |
| |
/* |
| |
* Dont scan forever even if fragment counters are |
| |
* wrong: stop after scanning entire reassembly queue. |
| |
*/ |
| |
if (i == dropscanidx) |
| |
wrapped = 1; |
| |
} |
| |
dropscanidx = i; |
| } |
} |
| IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
| #ifdef GATEWAY |
#ifdef GATEWAY |
|
|
| void |
void |
| ip_drain() |
ip_drain() |
| { |
{ |
| |
int i; |
| |
|
| /* |
/* |
| * We may be called from a device's interrupt context. If |
* We may be called from a device's interrupt context. If |
|
|
| if (ipq_lock_try() == 0) |
if (ipq_lock_try() == 0) |
| return; |
return; |
| |
|
| while (LIST_FIRST(&ipq) != NULL) { |
for (i = 0; i < IPREASS_NHASH; i++) { |
| ipstat.ips_fragdropped++; |
struct ipqhead *ipqh = &ipq[i]; |
| ip_freef(LIST_FIRST(&ipq)); |
struct ipq *fp, *nfp; |
| |
for (fp = LIST_FIRST(ipqh); fp != NULL; fp = nfp) { |
| |
nfp = LIST_NEXT(fp, ipq_q); |
| |
ip_freef(fp); |
| |
ipstat.ips_fragdropped++; |
| |
} |
| } |
} |
| |
|
| IPQ_UNLOCK(); |
IPQ_UNLOCK(); |