version 1.93.2.2, 2000/11/22 16:06:10 |
version 1.130.2.3, 2001/08/24 00:12:25 |
|
|
#include "opt_pfil_hooks.h" |
#include "opt_pfil_hooks.h" |
#include "opt_ipsec.h" |
#include "opt_ipsec.h" |
#include "opt_mrouting.h" |
#include "opt_mrouting.h" |
|
#include "opt_inet_csum.h" |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
Line 211 struct pfil_head inet_pfil_hook; |
|
Line 212 struct pfil_head inet_pfil_hook; |
|
|
|
struct ipqhead ipq; |
struct ipqhead ipq; |
int ipq_locked; |
int ipq_locked; |
|
int ip_nfragpackets = 0; |
|
int ip_maxfragpackets = 200; |
|
|
static __inline int ipq_lock_try __P((void)); |
static __inline int ipq_lock_try __P((void)); |
static __inline void ipq_unlock __P((void)); |
static __inline void ipq_unlock __P((void)); |
|
|
{ |
{ |
int s; |
int s; |
|
|
s = splimp(); |
/* |
|
* Use splvm() -- we're bloking things that would cause |
|
* mbuf allocation. |
|
*/ |
|
s = splvm(); |
if (ipq_locked) { |
if (ipq_locked) { |
splx(s); |
splx(s); |
return (0); |
return (0); |
|
|
{ |
{ |
int s; |
int s; |
|
|
s = splimp(); |
s = splvm(); |
ipq_locked = 0; |
ipq_locked = 0; |
splx(s); |
splx(s); |
} |
} |
|
|
|
|
struct pool ipqent_pool; |
struct pool ipqent_pool; |
|
|
|
#ifdef INET_CSUM_COUNTERS |
|
#include <sys/device.h> |
|
|
|
struct evcnt ip_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
|
NULL, "inet", "hwcsum bad"); |
|
struct evcnt ip_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
|
NULL, "inet", "hwcsum ok"); |
|
struct evcnt ip_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
|
NULL, "inet", "swcsum"); |
|
|
|
#define INET_CSUM_COUNTER_INCR(ev) (ev)->ev_count++ |
|
|
|
#else |
|
|
|
#define INET_CSUM_COUNTER_INCR(ev) /* nothing */ |
|
|
|
#endif /* INET_CSUM_COUNTERS */ |
|
|
/* |
/* |
* We need to save the IP options in case a protocol wants to respond |
* We need to save the IP options in case a protocol wants to respond |
* to an incoming packet over the same route if the packet got here |
* to an incoming packet over the same route if the packet got here |
|
|
|
|
#ifdef PFIL_HOOKS |
#ifdef PFIL_HOOKS |
/* Register our Packet Filter hook. */ |
/* Register our Packet Filter hook. */ |
inet_pfil_hook.ph_key = (void *)(u_long) AF_INET; |
inet_pfil_hook.ph_type = PFIL_TYPE_AF; |
inet_pfil_hook.ph_dlt = DLT_RAW; |
inet_pfil_hook.ph_af = AF_INET; |
i = pfil_head_register(&inet_pfil_hook); |
i = pfil_head_register(&inet_pfil_hook); |
if (i != 0) |
if (i != 0) |
printf("ip_init: WARNING: unable to register pfil hook, " |
printf("ip_init: WARNING: unable to register pfil hook, " |
"error %d\n", i); |
"error %d\n", i); |
#endif /* PFIL_HOOKS */ |
#endif /* PFIL_HOOKS */ |
|
|
|
#ifdef INET_CSUM_COUNTERS |
|
evcnt_attach_static(&ip_hwcsum_bad); |
|
evcnt_attach_static(&ip_hwcsum_ok); |
|
evcnt_attach_static(&ip_swcsum); |
|
#endif /* INET_CSUM_COUNTERS */ |
} |
} |
|
|
struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; |
struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; |
|
|
struct mbuf *m; |
struct mbuf *m; |
|
|
while (1) { |
while (1) { |
s = splimp(); |
s = splnet(); |
IF_DEQUEUE(&ipintrq, m); |
IF_DEQUEUE(&ipintrq, m); |
splx(s); |
splx(s); |
if (m == 0) |
if (m == 0) |
Line 414 ip_input(struct mbuf *m) |
|
Line 445 ip_input(struct mbuf *m) |
|
* not allowed. |
* not allowed. |
*/ |
*/ |
if (IN_MULTICAST(ip->ip_src.s_addr)) { |
if (IN_MULTICAST(ip->ip_src.s_addr)) { |
/* XXX stat */ |
ipstat.ips_badaddr++; |
goto bad; |
goto bad; |
} |
} |
|
|
if (in_cksum(m, hlen) != 0) { |
/* 127/8 must not appear on wire - RFC1122 */ |
ipstat.ips_badsum++; |
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || |
goto bad; |
(ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { |
|
if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) { |
|
ipstat.ips_badaddr++; |
|
goto bad; |
|
} |
|
} |
|
|
|
switch (m->m_pkthdr.csum_flags & |
|
((m->m_pkthdr.rcvif->if_csum_flags & M_CSUM_IPv4) | |
|
M_CSUM_IPv4_BAD)) { |
|
case M_CSUM_IPv4|M_CSUM_IPv4_BAD: |
|
INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); |
|
goto badcsum; |
|
|
|
case M_CSUM_IPv4: |
|
/* Checksum was okay. */ |
|
INET_CSUM_COUNTER_INCR(&ip_hwcsum_ok); |
|
break; |
|
|
|
default: |
|
/* Must compute it ourselves. */ |
|
INET_CSUM_COUNTER_INCR(&ip_swcsum); |
|
if (in_cksum(m, hlen) != 0) |
|
goto bad; |
|
break; |
} |
} |
|
|
/* Retrieve the packet length. */ |
/* Retrieve the packet length. */ |
Line 471 ip_input(struct mbuf *m) |
|
Line 526 ip_input(struct mbuf *m) |
|
* Note that filters must _never_ set this flag, as another filter |
* Note that filters must _never_ set this flag, as another filter |
* in the list may have previously cleared it. |
* in the list may have previously cleared it. |
*/ |
*/ |
if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, |
/* |
PFIL_IN) != 0) |
* let ipfilter look at packet on the wire, |
return; |
* not the decapsulated packet. |
if (m == NULL) |
*/ |
|
#ifdef IPSEC |
|
if (!ipsec_getnhist(m)) |
|
#else |
|
if (1) |
|
#endif |
|
{ |
|
if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, |
|
PFIL_IN) != 0) |
return; |
return; |
ip = mtod(m, struct ip *); |
if (m == NULL) |
|
return; |
|
ip = mtod(m, struct ip *); |
|
} |
#endif /* PFIL_HOOKS */ |
#endif /* PFIL_HOOKS */ |
|
|
|
#ifdef ALTQ |
|
/* XXX Temporary until ALTQ is changed to use a pfil hook */ |
|
if (altq_input != NULL && (*altq_input)(m, AF_INET) == 0) { |
|
/* packet dropped by traffic conditioner */ |
|
return; |
|
} |
|
#endif |
|
|
/* |
/* |
* Convert fields to host representation. |
* Convert fields to host representation. |
*/ |
*/ |
|
|
IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
} |
} |
|
|
|
#ifdef IPSEC |
|
/* |
|
* enforce IPsec policy checking if we are seeing last header. |
|
* note that we do not visit this with protocols with pcb layer |
|
* code - like udp/tcp/raw ip. |
|
*/ |
|
if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 && |
|
ipsec4_in_reject(m, NULL)) { |
|
ipsecstat.in_polvio++; |
|
goto bad; |
|
} |
|
#endif |
|
|
/* |
/* |
* Switch out to protocol's input routine. |
* Switch out to protocol's input routine. |
*/ |
*/ |
#if IFA_STATS |
#if IFA_STATS |
ia->ia_ifa.ifa_data.ifad_inbytes += ip->ip_len; |
if (ia && ip) |
|
ia->ia_ifa.ifa_data.ifad_inbytes += ip->ip_len; |
#endif |
#endif |
ipstat.ips_delivered++; |
ipstat.ips_delivered++; |
{ |
{ |
|
|
} |
} |
bad: |
bad: |
m_freem(m); |
m_freem(m); |
|
return; |
|
|
|
badcsum: |
|
ipstat.ips_badsum++; |
|
m_freem(m); |
} |
} |
|
|
/* |
/* |
Line 739 ip_reass(ipqe, fp) |
|
Line 832 ip_reass(ipqe, fp) |
|
* If first fragment to arrive, create a reassembly queue. |
* If first fragment to arrive, create a reassembly queue. |
*/ |
*/ |
if (fp == 0) { |
if (fp == 0) { |
|
/* |
|
* Enforce upper bound on number of fragmented packets |
|
* for which we attempt reassembly; |
|
* If maxfrag is 0, never accept fragments. |
|
* If maxfrag is -1, accept all fragments without limitation. |
|
*/ |
|
if (ip_maxfragpackets < 0) |
|
; |
|
else if (ip_nfragpackets >= ip_maxfragpackets) |
|
goto dropfrag; |
|
ip_nfragpackets++; |
MALLOC(fp, struct ipq *, sizeof (struct ipq), |
MALLOC(fp, struct ipq *, sizeof (struct ipq), |
M_FTABLE, M_NOWAIT); |
M_FTABLE, M_NOWAIT); |
if (fp == NULL) |
if (fp == NULL) |
|
|
ip->ip_dst = fp->ipq_dst; |
ip->ip_dst = fp->ipq_dst; |
LIST_REMOVE(fp, ipq_q); |
LIST_REMOVE(fp, ipq_q); |
FREE(fp, M_FTABLE); |
FREE(fp, M_FTABLE); |
|
ip_nfragpackets--; |
m->m_len += (ip->ip_hl << 2); |
m->m_len += (ip->ip_hl << 2); |
m->m_data -= (ip->ip_hl << 2); |
m->m_data -= (ip->ip_hl << 2); |
/* some debugging cruft by sklower, below, will go away soon */ |
/* some debugging cruft by sklower, below, will go away soon */ |
|
|
} |
} |
LIST_REMOVE(fp, ipq_q); |
LIST_REMOVE(fp, ipq_q); |
FREE(fp, M_FTABLE); |
FREE(fp, M_FTABLE); |
|
ip_nfragpackets--; |
} |
} |
|
|
/* |
/* |
|
|
ip_freef(fp); |
ip_freef(fp); |
} |
} |
} |
} |
|
/* |
|
* If we are over the maximum number of fragments |
|
* (due to the limit being lowered), drain off |
|
* enough to get down to the new limit. |
|
*/ |
|
if (ip_maxfragpackets < 0) |
|
; |
|
else { |
|
while (ip_nfragpackets > ip_maxfragpackets && ipq.lh_first) |
|
ip_freef(ipq.lh_first); |
|
} |
IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
#ifdef GATEWAY |
#ifdef GATEWAY |
ipflow_slowtimo(); |
ipflow_slowtimo(); |
Line 1362 ip_forward(m, srcrt) |
|
Line 1479 ip_forward(m, srcrt) |
|
struct ifnet dummyifp; |
struct ifnet dummyifp; |
#endif |
#endif |
|
|
|
/* |
|
* Clear any in-bound checksum flags for this packet. |
|
*/ |
|
m->m_pkthdr.csum_flags = 0; |
|
|
dest = 0; |
dest = 0; |
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
if (ipprintfs) |
if (ipprintfs) |
Line 1442 ip_forward(m, srcrt) |
|
Line 1564 ip_forward(m, srcrt) |
|
} |
} |
|
|
#ifdef IPSEC |
#ifdef IPSEC |
/* Don't lookup socket in forwading case */ |
/* Don't lookup socket in forwarding case */ |
ipsec_setsocket(m, NULL); |
(void)ipsec_setsocket(m, NULL); |
#endif |
#endif |
error = ip_output(m, (struct mbuf *)0, &ipforward_rt, |
error = ip_output(m, (struct mbuf *)0, &ipforward_rt, |
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0); |
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0); |
Line 1749 ip_sysctl(name, namelen, oldp, oldlenp, |
|
Line 1871 ip_sysctl(name, namelen, oldp, oldlenp, |
|
return (error); |
return (error); |
#endif |
#endif |
|
|
|
case IPCTL_MAXFRAGPACKETS: |
|
return (sysctl_int(oldp, oldlenp, newp, newlen, |
|
&ip_maxfragpackets)); |
|
|
default: |
default: |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
} |
} |