version 1.282, 2009/07/16 04:09:51 |
version 1.287, 2010/07/09 18:42:46 |
Line 231 u_long in_multihash; /* size of hash |
|
Line 231 u_long in_multihash; /* size of hash |
|
int in_multientries; /* total number of addrs */ |
int in_multientries; /* total number of addrs */ |
struct in_multihashhead *in_multihashtbl; |
struct in_multihashhead *in_multihashtbl; |
struct ifqueue ipintrq; |
struct ifqueue ipintrq; |
|
|
uint16_t ip_id; |
uint16_t ip_id; |
|
|
percpu_t *ipstat_percpu; |
percpu_t *ipstat_percpu; |
Line 383 struct mowner ip_rx_mowner = MOWNER_INIT |
|
Line 384 struct mowner ip_rx_mowner = MOWNER_INIT |
|
struct mowner ip_tx_mowner = MOWNER_INIT("internet", "tx"); |
struct mowner ip_tx_mowner = MOWNER_INIT("internet", "tx"); |
#endif |
#endif |
|
|
|
static void sysctl_net_inet_ip_setup(struct sysctllog **); |
|
|
/* |
/* |
* Compute IP limits derived from the value of nmbclusters. |
* Compute IP limits derived from the value of nmbclusters. |
*/ |
*/ |
|
|
const struct protosw *pr; |
const struct protosw *pr; |
int i; |
int i; |
|
|
|
sysctl_net_inet_ip_setup(NULL); |
|
|
pool_init(&inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl", |
pool_init(&inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl", |
NULL, IPL_SOFTNET); |
NULL, IPL_SOFTNET); |
pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", |
pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", |
|
|
{ |
{ |
int s; |
int s; |
struct mbuf *m; |
struct mbuf *m; |
|
struct ifqueue lcl_intrq; |
|
|
|
memset(&lcl_intrq, 0, sizeof(lcl_intrq)); |
|
ipintrq.ifq_maxlen = ipqmaxlen; |
|
|
mutex_enter(softnet_lock); |
mutex_enter(softnet_lock); |
KERNEL_LOCK(1, NULL); |
KERNEL_LOCK(1, NULL); |
while (!IF_IS_EMPTY(&ipintrq)) { |
if (!IF_IS_EMPTY(&ipintrq)) { |
s = splnet(); |
s = splnet(); |
IF_DEQUEUE(&ipintrq, m); |
|
|
/* Take existing queue onto stack */ |
|
lcl_intrq = ipintrq; |
|
|
|
/* Zero out global queue, preserving maxlen and drops */ |
|
ipintrq.ifq_head = NULL; |
|
ipintrq.ifq_tail = NULL; |
|
ipintrq.ifq_len = 0; |
|
ipintrq.ifq_maxlen = lcl_intrq.ifq_maxlen; |
|
ipintrq.ifq_drops = lcl_intrq.ifq_drops; |
|
|
splx(s); |
splx(s); |
|
} |
|
KERNEL_UNLOCK_ONE(NULL); |
|
while (!IF_IS_EMPTY(&lcl_intrq)) { |
|
IF_DEQUEUE(&lcl_intrq, m); |
if (m == NULL) |
if (m == NULL) |
break; |
break; |
ip_input(m); |
ip_input(m); |
} |
} |
KERNEL_UNLOCK_ONE(NULL); |
|
mutex_exit(softnet_lock); |
mutex_exit(softnet_lock); |
} |
} |
|
|
|
|
* but it's not worth the time; just let them time out.) |
* but it's not worth the time; just let them time out.) |
*/ |
*/ |
if (ip->ip_off & ~htons(IP_DF|IP_RF)) { |
if (ip->ip_off & ~htons(IP_DF|IP_RF)) { |
uint16_t off; |
u_int off; |
/* |
/* |
* Prevent TCP blind data attacks by not allowing non-initial |
* Prevent TCP blind data attacks by not allowing non-initial |
* fragments to start at less than 68 bytes (minimal fragment |
* fragments to start at less than 68 bytes (minimal fragment |
|
|
IP_STATINC(IP_STAT_BADFRAGS); |
IP_STATINC(IP_STAT_BADFRAGS); |
goto bad; |
goto bad; |
} |
} |
/* |
|
* Look for queue of fragments |
|
* of this datagram. |
|
*/ |
|
IPQ_LOCK(); |
|
hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); |
|
LIST_FOREACH(fp, &ipq[hash], ipq_q) { |
|
if (ip->ip_id == fp->ipq_id && |
|
in_hosteq(ip->ip_src, fp->ipq_src) && |
|
in_hosteq(ip->ip_dst, fp->ipq_dst) && |
|
ip->ip_p == fp->ipq_p) { |
|
/* |
|
* Make sure the TOS is matches previous |
|
* fragments. |
|
*/ |
|
if (ip->ip_tos != fp->ipq_tos) { |
|
IP_STATINC(IP_STAT_BADFRAGS); |
|
IPQ_UNLOCK(); |
|
goto bad; |
|
} |
|
goto found; |
|
} |
|
} |
|
fp = 0; |
|
found: |
|
|
|
/* |
/* |
* Adjust ip_len to not reflect header, |
* Adjust ip_len to not reflect header, |
|
|
ip->ip_len = htons(ntohs(ip->ip_len) - hlen); |
ip->ip_len = htons(ntohs(ip->ip_len) - hlen); |
mff = (ip->ip_off & htons(IP_MF)) != 0; |
mff = (ip->ip_off & htons(IP_MF)) != 0; |
if (mff) { |
if (mff) { |
/* |
/* |
* Make sure that fragments have a data length |
* Make sure that fragments have a data length |
* that's a non-zero multiple of 8 bytes. |
* that's a non-zero multiple of 8 bytes. |
*/ |
*/ |
if (ntohs(ip->ip_len) == 0 || |
if (ntohs(ip->ip_len) == 0 || |
(ntohs(ip->ip_len) & 0x7) != 0) { |
(ntohs(ip->ip_len) & 0x7) != 0) { |
IP_STATINC(IP_STAT_BADFRAGS); |
IP_STATINC(IP_STAT_BADFRAGS); |
IPQ_UNLOCK(); |
|
goto bad; |
goto bad; |
} |
} |
} |
} |
ip->ip_off = htons((ntohs(ip->ip_off) & IP_OFFMASK) << 3); |
ip->ip_off = htons((ntohs(ip->ip_off) & IP_OFFMASK) << 3); |
|
|
/* |
/* |
|
* Look for queue of fragments of this datagram. |
|
*/ |
|
IPQ_LOCK(); |
|
hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); |
|
LIST_FOREACH(fp, &ipq[hash], ipq_q) { |
|
if (ip->ip_id != fp->ipq_id) |
|
continue; |
|
if (!in_hosteq(ip->ip_src, fp->ipq_src)) |
|
continue; |
|
if (!in_hosteq(ip->ip_dst, fp->ipq_dst)) |
|
continue; |
|
if (ip->ip_p != fp->ipq_p) |
|
continue; |
|
/* |
|
* Make sure the TOS is matches previous fragments. |
|
*/ |
|
if (ip->ip_tos != fp->ipq_tos) { |
|
IP_STATINC(IP_STAT_BADFRAGS); |
|
IPQ_UNLOCK(); |
|
goto bad; |
|
} |
|
break; |
|
} |
|
|
|
/* |
* If datagram marked as having more fragments |
* If datagram marked as having more fragments |
* or if this is not the first fragment, |
* or if this is not the first fragment, |
* attempt reassembly; if it succeeds, proceed. |
* attempt reassembly; if it succeeds, proceed. |
|
|
ipqe->ipqe_m = m; |
ipqe->ipqe_m = m; |
ipqe->ipqe_ip = ip; |
ipqe->ipqe_ip = ip; |
m = ip_reass(ipqe, fp, &ipq[hash]); |
m = ip_reass(ipqe, fp, &ipq[hash]); |
if (m == 0) { |
if (m == NULL) { |
IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
return; |
return; |
} |
} |
|
|
ip = mtod(m, struct ip *); |
ip = mtod(m, struct ip *); |
hlen = ip->ip_hl << 2; |
hlen = ip->ip_hl << 2; |
ip->ip_len = htons(ntohs(ip->ip_len) + hlen); |
ip->ip_len = htons(ntohs(ip->ip_len) + hlen); |
} else |
} else if (fp) { |
if (fp) |
ip_freef(fp); |
ip_freef(fp); |
} |
IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
} |
} |
|
|
Line 2057 ip_savecontrol(struct inpcb *inp, struct |
|
Line 2078 ip_savecontrol(struct inpcb *inp, struct |
|
struct mbuf *m) |
struct mbuf *m) |
{ |
{ |
|
|
if (inp->inp_socket->so_options & SO_TIMESTAMP |
if (inp->inp_socket->so_options & SO_TIMESTAMP |
#ifdef SO_OTIMESTAMP |
#ifdef SO_OTIMESTAMP |
|| inp->inp_socket->so_options & SO_OTIMESTAMP |
|| inp->inp_socket->so_options & SO_OTIMESTAMP |
#endif |
#endif |
) { |
) { |
struct timeval tv; |
struct timeval tv; |
Line 2207 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
Line 2228 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
|
|
static int |
static int |
sysctl_net_inet_ip_hashsize(SYSCTLFN_ARGS) |
sysctl_net_inet_ip_hashsize(SYSCTLFN_ARGS) |
{ |
{ |
int error, tmp; |
int error, tmp; |
struct sysctlnode node; |
struct sysctlnode node; |
|
|
Line 2235 sysctl_net_inet_ip_hashsize(SYSCTLFN_ARG |
|
Line 2256 sysctl_net_inet_ip_hashsize(SYSCTLFN_ARG |
|
* EINVAL if not a power of 2 |
* EINVAL if not a power of 2 |
*/ |
*/ |
error = EINVAL; |
error = EINVAL; |
} |
} |
|
|
return error; |
return error; |
} |
} |
Line 2248 sysctl_net_inet_ip_stats(SYSCTLFN_ARGS) |
|
Line 2269 sysctl_net_inet_ip_stats(SYSCTLFN_ARGS) |
|
return (NETSTAT_SYSCTL(ipstat_percpu, IP_NSTATS)); |
return (NETSTAT_SYSCTL(ipstat_percpu, IP_NSTATS)); |
} |
} |
|
|
SYSCTL_SETUP(sysctl_net_inet_ip_setup, "sysctl net.inet.ip subtree setup") |
static void |
|
sysctl_net_inet_ip_setup(struct sysctllog **clog) |
{ |
{ |
extern int subnetsarelocal, hostzeroisbroadcast; |
extern int subnetsarelocal, hostzeroisbroadcast; |
|
|