version 1.82.2.2.2.2, 1999/07/01 23:47:01 |
version 1.107, 2000/03/10 22:39:03 |
|
|
|
|
#include "opt_gateway.h" |
#include "opt_gateway.h" |
#include "opt_pfil_hooks.h" |
#include "opt_pfil_hooks.h" |
|
#include "opt_ipsec.h" |
#include "opt_mrouting.h" |
#include "opt_mrouting.h" |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
|
|
|
|
#ifdef IPSEC |
#ifdef IPSEC |
#include <netinet6/ipsec.h> |
#include <netinet6/ipsec.h> |
#include <netinet6/ah.h> |
|
#ifdef IPSEC_ESP |
|
#include <netinet6/esp.h> |
|
#endif |
|
#include <netkey/key.h> |
#include <netkey/key.h> |
#include <netkey/key_debug.h> |
#include <netkey/key_debug.h> |
#endif |
#endif |
Line 197 int ipprintfs = 0; |
|
Line 194 int ipprintfs = 0; |
|
struct rttimer_queue *ip_mtudisc_timeout_q = NULL; |
struct rttimer_queue *ip_mtudisc_timeout_q = NULL; |
|
|
extern struct domain inetdomain; |
extern struct domain inetdomain; |
extern struct protosw inetsw[]; |
|
u_char ip_protox[IPPROTO_MAX]; |
|
int ipqmaxlen = IFQ_MAXLEN; |
int ipqmaxlen = IFQ_MAXLEN; |
struct in_ifaddrhead in_ifaddr; |
struct in_ifaddrhead in_ifaddr; |
struct in_ifaddrhashhead *in_ifaddrhashtbl; |
struct in_ifaddrhashhead *in_ifaddrhashtbl; |
Line 351 ip_input(struct mbuf *m) |
|
Line 346 ip_input(struct mbuf *m) |
|
register struct ifaddr *ifa; |
register struct ifaddr *ifa; |
struct ipqent *ipqe; |
struct ipqent *ipqe; |
int hlen = 0, mff, len; |
int hlen = 0, mff, len; |
|
int downmatch; |
#ifdef PFIL_HOOKS |
#ifdef PFIL_HOOKS |
struct packet_filter_hook *pfh; |
struct packet_filter_hook *pfh; |
struct mbuf *m0; |
struct mbuf *m0; |
Line 400 ip_input(struct mbuf *m) |
|
Line 396 ip_input(struct mbuf *m) |
|
} |
} |
ip = mtod(m, struct ip *); |
ip = mtod(m, struct ip *); |
} |
} |
|
|
/* |
/* |
* we drop packets that have a multicast address as source |
* RFC1122: packets with a multicast source address are |
* as wanted by rfc 1112 |
* not allowed. |
*/ |
*/ |
if (IN_MULTICAST(ip->ip_src.s_addr)) { |
if (IN_MULTICAST(ip->ip_src.s_addr)) { |
|
/* XXX stat */ |
goto bad; |
goto bad; |
} |
} |
|
|
Line 446 ip_input(struct mbuf *m) |
|
Line 444 ip_input(struct mbuf *m) |
|
m_adj(m, len - m->m_pkthdr.len); |
m_adj(m, len - m->m_pkthdr.len); |
} |
} |
|
|
|
#ifdef IPSEC |
|
/* ipflow (IP fast fowarding) is not compatible with IPsec. */ |
|
m->m_flags &= ~M_CANFASTFWD; |
|
#else |
/* |
/* |
* Assume that we can create a fast-forward IP flow entry |
* Assume that we can create a fast-forward IP flow entry |
* based on this packet. |
* based on this packet. |
*/ |
*/ |
m->m_flags |= M_CANFASTFWD; |
m->m_flags |= M_CANFASTFWD; |
|
#endif |
|
|
#ifdef PFIL_HOOKS |
#ifdef PFIL_HOOKS |
/* |
/* |
Line 461 ip_input(struct mbuf *m) |
|
Line 464 ip_input(struct mbuf *m) |
|
* in the list may have previously cleared it. |
* in the list may have previously cleared it. |
*/ |
*/ |
m0 = m; |
m0 = m; |
for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.tqe_next) |
pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); |
|
for (; pfh; pfh = pfh->pfil_link.tqe_next) |
if (pfh->pfil_func) { |
if (pfh->pfil_func) { |
rv = pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 0, &m0); |
rv = pfh->pfil_func(ip, hlen, |
|
m->m_pkthdr.rcvif, 0, &m0); |
if (rv) |
if (rv) |
return; |
return; |
m = m0; |
m = m0; |
Line 485 ip_input(struct mbuf *m) |
|
Line 490 ip_input(struct mbuf *m) |
|
|
|
/* |
/* |
* Check our list of addresses, to see if the packet is for us. |
* Check our list of addresses, to see if the packet is for us. |
*/ |
* |
INADDR_TO_IA(ip->ip_dst, ia); |
* Traditional 4.4BSD did not consult IFF_UP at all. |
|
* The behavior here is to treat addresses on !IFF_UP interface |
|
* as not mine. |
|
*/ |
|
downmatch = 0; |
|
for (ia = IN_IFADDR_HASH(ip->ip_dst.s_addr).lh_first; |
|
ia != NULL; |
|
ia = ia->ia_hash.le_next) { |
|
if (in_hosteq(ia->ia_addr.sin_addr, ip->ip_dst)) { |
|
if ((ia->ia_ifp->if_flags & IFF_UP) != 0) |
|
break; |
|
else |
|
downmatch++; |
|
} |
|
} |
if (ia != NULL) |
if (ia != NULL) |
goto ours; |
goto ours; |
if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { |
if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { |
Line 575 ip_input(struct mbuf *m) |
|
Line 594 ip_input(struct mbuf *m) |
|
if (ipforwarding == 0) { |
if (ipforwarding == 0) { |
ipstat.ips_cantforward++; |
ipstat.ips_cantforward++; |
m_freem(m); |
m_freem(m); |
} else |
} else { |
|
/* |
|
* If ip_dst matched any of my address on !IFF_UP interface, |
|
* and there's no IFF_UP interface that matches ip_dst, |
|
* send icmp unreach. Forwarding it will result in in-kernel |
|
* forwarding loop till TTL goes to 0. |
|
*/ |
|
if (downmatch) { |
|
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); |
|
ipstat.ips_cantforward++; |
|
return; |
|
} |
ip_forward(m, 0); |
ip_forward(m, 0); |
|
} |
return; |
return; |
|
|
ours: |
ours: |
|
|
* Make header visible. |
* Make header visible. |
*/ |
*/ |
ip->ip_len = next; |
ip->ip_len = next; |
ip->ip_ttl = 0; /* xxx */ |
|
ip->ip_sum = 0; |
|
ip->ip_src = fp->ipq_src; |
ip->ip_src = fp->ipq_src; |
ip->ip_dst = fp->ipq_dst; |
ip->ip_dst = fp->ipq_dst; |
LIST_REMOVE(fp, ipq_q); |
LIST_REMOVE(fp, ipq_q); |
|
|
struct mbuf *m; |
struct mbuf *m; |
{ |
{ |
register struct ip *ip = mtod(m, struct ip *); |
register struct ip *ip = mtod(m, struct ip *); |
register u_char *cp; |
register u_char *cp, *cp0; |
register struct ip_timestamp *ipt; |
register struct ip_timestamp *ipt; |
register struct in_ifaddr *ia; |
register struct in_ifaddr *ia; |
int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; |
int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; |
struct in_addr *sin, dst; |
struct in_addr dst; |
n_time ntime; |
n_time ntime; |
|
|
dst = ip->ip_dst; |
dst = ip->ip_dst; |
|
Line 1022 ip_dooptions(m) |
|
*/ |
*/ |
bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, |
bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, |
sizeof(ipaddr.sin_addr)); |
sizeof(ipaddr.sin_addr)); |
if (opt == IPOPT_SSRR) { |
if (opt == IPOPT_SSRR) |
#define INA struct in_ifaddr * |
ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))); |
#define SA struct sockaddr * |
else |
ia = (INA)ifa_ifwithladdr((SA)&ipaddr); |
|
} else |
|
ia = ip_rtaddr(ipaddr.sin_addr); |
ia = ip_rtaddr(ipaddr.sin_addr); |
if (ia == 0) { |
if (ia == 0) { |
type = ICMP_UNREACH; |
type = ICMP_UNREACH; |
Line 1031 ip_dooptions(m) |
|
Line 1058 ip_dooptions(m) |
|
* locate outgoing interface; if we're the destination, |
* locate outgoing interface; if we're the destination, |
* use the incoming interface (should be same). |
* use the incoming interface (should be same). |
*/ |
*/ |
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && |
if ((ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)))) |
(ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { |
== NULL && |
|
(ia = ip_rtaddr(ipaddr.sin_addr)) == NULL) { |
type = ICMP_UNREACH; |
type = ICMP_UNREACH; |
code = ICMP_UNREACH_HOST; |
code = ICMP_UNREACH_HOST; |
goto bad; |
goto bad; |
Line 1052 ip_dooptions(m) |
|
Line 1080 ip_dooptions(m) |
|
goto bad; |
goto bad; |
break; |
break; |
} |
} |
sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); |
cp0 = (cp + ipt->ipt_ptr - 1); |
switch (ipt->ipt_flg) { |
switch (ipt->ipt_flg) { |
|
|
case IPOPT_TS_TSONLY: |
case IPOPT_TS_TSONLY: |
Line 1063 ip_dooptions(m) |
|
Line 1091 ip_dooptions(m) |
|
sizeof(struct in_addr) > ipt->ipt_len) |
sizeof(struct in_addr) > ipt->ipt_len) |
goto bad; |
goto bad; |
ipaddr.sin_addr = dst; |
ipaddr.sin_addr = dst; |
ia = (INA)ifaof_ifpforaddr((SA)&ipaddr, |
ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr), |
m->m_pkthdr.rcvif); |
m->m_pkthdr.rcvif)); |
if (ia == 0) |
if (ia == 0) |
continue; |
continue; |
bcopy((caddr_t)&ia->ia_addr.sin_addr, |
bcopy(&ia->ia_addr.sin_addr, |
(caddr_t)sin, sizeof(struct in_addr)); |
cp0, sizeof(struct in_addr)); |
ipt->ipt_ptr += sizeof(struct in_addr); |
ipt->ipt_ptr += sizeof(struct in_addr); |
break; |
break; |
|
|
Line 1076 ip_dooptions(m) |
|
Line 1104 ip_dooptions(m) |
|
if (ipt->ipt_ptr - 1 + sizeof(n_time) + |
if (ipt->ipt_ptr - 1 + sizeof(n_time) + |
sizeof(struct in_addr) > ipt->ipt_len) |
sizeof(struct in_addr) > ipt->ipt_len) |
goto bad; |
goto bad; |
bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, |
bcopy(cp0, &ipaddr.sin_addr, |
sizeof(struct in_addr)); |
sizeof(struct in_addr)); |
if (ifa_ifwithaddr((SA)&ipaddr) == 0) |
if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))) |
|
== NULL) |
continue; |
continue; |
ipt->ipt_ptr += sizeof(struct in_addr); |
ipt->ipt_ptr += sizeof(struct in_addr); |
break; |
break; |
Line 1087 ip_dooptions(m) |
|
Line 1116 ip_dooptions(m) |
|
goto bad; |
goto bad; |
} |
} |
ntime = iptime(); |
ntime = iptime(); |
bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, |
cp0 = (u_char *) &ntime; /* XXX grumble, GCC... */ |
|
bcopy(cp0, (caddr_t)cp + ipt->ipt_ptr - 1, |
sizeof(n_time)); |
sizeof(n_time)); |
ipt->ipt_ptr += sizeof(n_time); |
ipt->ipt_ptr += sizeof(n_time); |
} |
} |
Line 1302 ip_forward(m, srcrt) |
|
Line 1332 ip_forward(m, srcrt) |
|
ntohl(ip->ip_src.s_addr), |
ntohl(ip->ip_src.s_addr), |
ntohl(ip->ip_dst.s_addr), ip->ip_ttl); |
ntohl(ip->ip_dst.s_addr), ip->ip_ttl); |
#endif |
#endif |
if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) { |
if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) { |
ipstat.ips_cantforward++; |
ipstat.ips_cantforward++; |
m_freem(m); |
m_freem(m); |
return; |
return; |
Line 1372 ip_forward(m, srcrt) |
|
Line 1402 ip_forward(m, srcrt) |
|
} |
} |
|
|
#ifdef IPSEC |
#ifdef IPSEC |
m->m_pkthdr.rcvif = NULL; |
/* Don't lookup socket in forwading case */ |
#endif /*IPSEC*/ |
ipsec_setsocket(m, NULL); |
|
#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); |
if (error) |
if (error) |
Line 1428 ip_forward(m, srcrt) |
|
Line 1459 ip_forward(m, srcrt) |
|
if (ipforward_rt.ro_rt) { |
if (ipforward_rt.ro_rt) { |
struct secpolicy *sp; |
struct secpolicy *sp; |
int ipsecerror; |
int ipsecerror; |
int ipsechdr; |
size_t ipsechdr; |
struct route *ro; |
struct route *ro; |
|
|
sp = ipsec4_getpolicybyaddr(mcopy, |
sp = ipsec4_getpolicybyaddr(mcopy, |
IP_FORWARDING, |
IPSEC_DIR_OUTBOUND, |
&ipsecerror); |
IP_FORWARDING, |
|
&ipsecerror); |
|
|
if (sp == NULL) |
if (sp == NULL) |
destifp = ipforward_rt.ro_rt->rt_ifp; |
destifp = ipforward_rt.ro_rt->rt_ifp; |
else { |
else { |
/* count IPsec header size */ |
/* count IPsec header size */ |
ipsechdr = ipsec4_hdrsiz(mcopy, NULL); |
ipsechdr = ipsec4_hdrsiz(mcopy, |
|
IPSEC_DIR_OUTBOUND, |
|
NULL); |
|
|
/* |
/* |
* find the correct route for outer IPv4 |
* find the correct route for outer IPv4 |
Line 1452 ip_forward(m, srcrt) |
|
Line 1486 ip_forward(m, srcrt) |
|
/*XXX*/ |
/*XXX*/ |
destifp = NULL; |
destifp = NULL; |
if (sp->req != NULL |
if (sp->req != NULL |
&& sp->req->sa != NULL) { |
&& sp->req->sav != NULL |
ro = &sp->req->sa->saidx->sa_route; |
&& sp->req->sav->sah != NULL) { |
|
ro = &sp->req->sav->sah->sa_route; |
if (ro->ro_rt && ro->ro_rt->rt_ifp) { |
if (ro->ro_rt && ro->ro_rt->rt_ifp) { |
dummyifp.if_mtu = |
dummyifp.if_mtu = |
ro->ro_rt->rt_ifp->if_mtu; |
ro->ro_rt->rt_ifp->if_mtu; |
Line 1638 ip_sysctl(name, namelen, oldp, oldlenp, |
|
Line 1673 ip_sysctl(name, namelen, oldp, oldlenp, |
|
return (error); |
return (error); |
} |
} |
#endif |
#endif |
|
case IPCTL_HOSTZEROBROADCAST: |
|
return (sysctl_int(oldp, oldlenp, newp, newlen, |
|
&hostzeroisbroadcast)); |
#if NGIF > 0 |
#if NGIF > 0 |
case IPCTL_GIF_TTL: |
case IPCTL_GIF_TTL: |
return(sysctl_int(oldp, oldlenp, newp, newlen, |
return(sysctl_int(oldp, oldlenp, newp, newlen, |
&gif_ttl)); |
&ip_gif_ttl)); |
#endif |
#endif |
case IPCTL_HOSTZEROBROADCAST: |
|
return (sysctl_int(oldp, oldlenp, newp, newlen, |
|
&hostzeroisbroadcast)); |
|
|
|
default: |
default: |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |