diff options
author | shin <shin@FreeBSD.org> | 1999-12-22 19:13:38 +0000 |
---|---|---|
committer | shin <shin@FreeBSD.org> | 1999-12-22 19:13:38 +0000 |
commit | 50ba589c666f7d356304339b9cfc7fc9d173ad8d (patch) | |
tree | 46d6ae7c9680a93ce1c3a13378cef283df9f6544 /sys/netinet | |
parent | e396740391e7e60805bda6799ac3397d1fc8c539 (diff) | |
download | FreeBSD-src-50ba589c666f7d356304339b9cfc7fc9d173ad8d.zip FreeBSD-src-50ba589c666f7d356304339b9cfc7fc9d173ad8d.tar.gz |
IPSEC support in the kernel.
pr_input() routines prototype is also changed to support IPSEC and IPV6
chained protocol headers.
Reviewed by: freebsd-arch, cvs-committers
Obtained from: KAME project
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/igmp.c | 7 | ||||
-rw-r--r-- | sys/netinet/igmp_var.h | 2 | ||||
-rw-r--r-- | sys/netinet/in.c | 253 | ||||
-rw-r--r-- | sys/netinet/in.h | 2 | ||||
-rw-r--r-- | sys/netinet/in_gif.c | 38 | ||||
-rw-r--r-- | sys/netinet/in_gif.h | 2 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 1 | ||||
-rw-r--r-- | sys/netinet/in_proto.c | 37 | ||||
-rw-r--r-- | sys/netinet/ip.h | 4 | ||||
-rw-r--r-- | sys/netinet/ip_divert.c | 21 | ||||
-rw-r--r-- | sys/netinet/ip_dummynet.c | 10 | ||||
-rw-r--r-- | sys/netinet/ip_dummynet.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_ecn.c | 149 | ||||
-rw-r--r-- | sys/netinet/ip_ecn.h | 44 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 50 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.h | 2 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 142 | ||||
-rw-r--r-- | sys/netinet/ip_mroute.c | 27 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 237 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 11 | ||||
-rw-r--r-- | sys/netinet/ipprotosw.h | 103 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 41 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 5 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 5 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 12 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 2 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 4 |
27 files changed, 1121 insertions, 93 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 83cc650..37f2cc7 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -146,10 +146,11 @@ find_rti(ifp) } void -igmp_input(m, iphlen) +igmp_input(m, off, proto) register struct mbuf *m; - register int iphlen; + int off, proto; { + register int iphlen = off; register struct igmp *igmp; register struct ip *ip; register int igmplen; @@ -335,7 +336,7 @@ igmp_input(m, iphlen) * Pass all valid IGMP packets up to any process(es) listening * on a raw IGMP socket. */ - rip_input(m, iphlen); + rip_input(m, off, proto); } void diff --git a/sys/netinet/igmp_var.h b/sys/netinet/igmp_var.h index 0dd330fb..d22cd51 100644 --- a/sys/netinet/igmp_var.h +++ b/sys/netinet/igmp_var.h @@ -86,7 +86,7 @@ struct igmpstat { #define IGMP_AGE_THRESHOLD 540 void igmp_init __P((void)); -void igmp_input __P((struct mbuf *, int)); +void igmp_input __P((struct mbuf *, int, int)); void igmp_joingroup __P((struct in_multi *)); void igmp_leavegroup __P((struct in_multi *)); void igmp_fasttimo __P((void)); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 4562672..b638143 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -44,6 +44,7 @@ #include <sys/sysctl.h> #include <net/if.h> +#include <net/if_types.h> #include <net/route.h> #include <netinet/in.h> @@ -51,8 +52,18 @@ #include <netinet/igmp_var.h> +#include "gif.h" +#if NGIF > 0 +#include <net/if_gif.h> +#endif + static MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address"); +static int in_mask2len __P((struct in_addr *)); +static void in_len2mask __P((struct in_addr *, int)); +static int in_lifaddr_ioctl __P((struct socket *, u_long, caddr_t, + struct ifnet *, struct proc *)); + static void in_socktrim __P((struct sockaddr_in *)); static int in_ifinit __P((struct ifnet *, struct in_ifaddr *, struct sockaddr_in *, int)); @@ -130,6 +141,44 @@ struct sockaddr_in *ap; } } +static int +in_mask2len(mask) + struct in_addr *mask; +{ + int x, y; + u_char *p; + + p = (u_char *)mask; + for (x = 0; x < sizeof(*mask); x++) { + if (p[x] != 0xff) + break; + } + y = 0; + if (x < sizeof(*mask)) { + for (y = 0; y < 8; y++) { + if ((p[x] & (0x80 >> y)) == 0) + break; + } + } + return x * 8 + y; +} + +static void +in_len2mask(mask, len) + struct in_addr *mask; + int len; +{ + int i; + u_char *p; + + p = (u_char *)mask; + bzero(mask, sizeof(*mask)); + for (i = 0; i < len / 8; i++) + p[i] = 0xff; + if (len % 8) + p[i] = (0xff00 >> (len % 8)) & 0xff; +} + static int in_interfaces; /* number of external internet interfaces */ /* @@ -154,6 +203,32 @@ in_control(so, cmd, data, ifp, p) int error, hostIsNew, maskIsNew, s; u_long i; +#if NGIF > 0 + if (ifp && ifp->if_type == IFT_GIF) { + switch (cmd) { + case SIOCSIFPHYADDR: + if (p && + (error = suser(p)) != 0) + return(error); + case SIOCGIFPSRCADDR: + case SIOCGIFPDSTADDR: + return gif_ioctl(ifp, cmd, data); + } + } +#endif + + switch (cmd) { + case SIOCALIFADDR: + case SIOCDLIFADDR: + if (p && (error = suser(p)) != 0) + return error; + /*fall through*/ + case SIOCGLIFADDR: + if (!ifp) + return EINVAL; + return in_lifaddr_ioctl(so, cmd, data, ifp, p); + } + /* * Find address for this interface, if it exists. * @@ -364,6 +439,184 @@ in_control(so, cmd, data, ifp, p) } /* + * SIOC[GAD]LIFADDR. + * SIOCGLIFADDR: get first address. (?!?) + * SIOCGLIFADDR with IFLR_PREFIX: + * get first address that matches the specified prefix. + * SIOCALIFADDR: add the specified address. + * SIOCALIFADDR with IFLR_PREFIX: + * EINVAL since we can't deduce hostid part of the address. + * SIOCDLIFADDR: delete the specified address. + * SIOCDLIFADDR with IFLR_PREFIX: + * delete the first address that matches the specified prefix. + * return values: + * EINVAL on invalid parameters + * EADDRNOTAVAIL on prefix match failed/specified address not found + * other values may be returned from in_ioctl() + */ +static int +in_lifaddr_ioctl(so, cmd, data, ifp, p) + struct socket *so; + u_long cmd; + caddr_t data; + struct ifnet *ifp; + struct proc *p; +{ + struct if_laddrreq *iflr = (struct if_laddrreq *)data; + struct ifaddr *ifa; + + /* sanity checks */ + if (!data || !ifp) { + panic("invalid argument to in_lifaddr_ioctl"); + /*NOTRECHED*/ + } + + switch (cmd) { + case SIOCGLIFADDR: + /* address must be specified on GET with IFLR_PREFIX */ + if ((iflr->flags & IFLR_PREFIX) == 0) + break; + /*FALLTHROUGH*/ + case SIOCALIFADDR: + case SIOCDLIFADDR: + /* address must be specified on ADD and DELETE */ + if (iflr->addr.__ss_family != AF_INET) + return EINVAL; + if (iflr->addr.__ss_len != sizeof(struct sockaddr_in)) + return EINVAL; + /* XXX need improvement */ + if (iflr->dstaddr.__ss_family + && iflr->dstaddr.__ss_family != AF_INET) + return EINVAL; + if (iflr->dstaddr.__ss_family + && iflr->dstaddr.__ss_len != sizeof(struct sockaddr_in)) + return EINVAL; + break; + default: /*shouldn't happen*/ + return EOPNOTSUPP; + } + if (sizeof(struct in_addr) * 8 < iflr->prefixlen) + return EINVAL; + + switch (cmd) { + case SIOCALIFADDR: + { + struct in_aliasreq ifra; + + if (iflr->flags & IFLR_PREFIX) + return EINVAL; + + /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */ + bzero(&ifra, sizeof(ifra)); + bcopy(iflr->iflr_name, ifra.ifra_name, + sizeof(ifra.ifra_name)); + + bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.__ss_len); + + if (iflr->dstaddr.__ss_family) { /*XXX*/ + bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr, + iflr->dstaddr.__ss_len); + } + + ifra.ifra_mask.sin_family = AF_INET; + ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in); + in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen); + + return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p); + } + case SIOCGLIFADDR: + case SIOCDLIFADDR: + { + struct in_ifaddr *ia; + struct in_addr mask, candidate, match; + struct sockaddr_in *sin; + int cmp; + + bzero(&mask, sizeof(mask)); + if (iflr->flags & IFLR_PREFIX) { + /* lookup a prefix rather than address. */ + in_len2mask(&mask, iflr->prefixlen); + + sin = (struct sockaddr_in *)&iflr->addr; + match.s_addr = sin->sin_addr.s_addr; + match.s_addr &= mask.s_addr; + + /* if you set extra bits, that's wrong */ + if (match.s_addr != sin->sin_addr.s_addr) + return EINVAL; + + cmp = 1; + } else { + if (cmd == SIOCGLIFADDR) { + /* on getting an address, take the 1st match */ + cmp = 0; /*XXX*/ + } else { + /* on deleting an address, do exact match */ + in_len2mask(&mask, 32); + sin = (struct sockaddr_in *)&iflr->addr; + match.s_addr = sin->sin_addr.s_addr; + + cmp = 1; + } + } + + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + if (!cmp) + break; + candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr; + candidate.s_addr &= mask.s_addr; + if (candidate.s_addr == match.s_addr) + break; + } + if (!ifa) + return EADDRNOTAVAIL; + ia = (struct in_ifaddr *)ifa; + + if (cmd == SIOCGLIFADDR) { + /* fill in the if_laddrreq structure */ + bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len); + + if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { + bcopy(&ia->ia_dstaddr, &iflr->dstaddr, + ia->ia_dstaddr.sin_len); + } else + bzero(&iflr->dstaddr, sizeof(iflr->dstaddr)); + + iflr->prefixlen = + in_mask2len(&ia->ia_sockmask.sin_addr); + + iflr->flags = 0; /*XXX*/ + + return 0; + } else { + struct in_aliasreq ifra; + + /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */ + bzero(&ifra, sizeof(ifra)); + bcopy(iflr->iflr_name, ifra.ifra_name, + sizeof(ifra.ifra_name)); + + bcopy(&ia->ia_addr, &ifra.ifra_addr, + ia->ia_addr.sin_len); + if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { + bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr, + ia->ia_dstaddr.sin_len); + } + bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr, + ia->ia_sockmask.sin_len); + + return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, + ifp, p); + } + } + } + + return EOPNOTSUPP; /*just for safety*/ +} + +/* * Delete any existing route for an interface. */ void diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 9e8a652..15a182c 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -419,7 +419,7 @@ struct ip_mreq { #define IPCTL_STATS 12 /* ipstat structure */ #define IPCTL_ACCEPTSOURCEROUTE 13 /* may accept source routed packets */ #define IPCTL_FASTFORWARDING 14 /* use fast IP forwarding code */ -#define IPCTL_KEEPFAITH 15 +#define IPCTL_KEEPFAITH 15 /* FAITH IPv4->IPv6 translater ctl */ #define IPCTL_GIF_TTL 16 /* default TTL for gif encap packet */ #define IPCTL_MAXID 17 diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c index 6aa3673..021c800 100644 --- a/sys/netinet/in_gif.c +++ b/sys/netinet/in_gif.c @@ -52,11 +52,14 @@ #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> +#ifdef INET6 +#include <netinet/ip6.h> +#endif #include <netinet/ip_var.h> #include <netinet/in_gif.h> - +#include <netinet/ip_ecn.h> #ifdef INET6 -#include <netinet/ip6.h> +#include <netinet6/ip6_ecn.h> #endif #ifdef MROUTING @@ -168,6 +171,8 @@ in_gif_output(ifp, family, m, rt) /* version will be set in ip_output() */ iphdr.ip_ttl = ip_gif_ttl; iphdr.ip_len = m->m_pkthdr.len + sizeof(struct ip); + if (ifp->if_flags & IFF_LINK1) + ip_ecn_ingress(ECN_ALLOWED, &iphdr.ip_tos, &tos); /* prepend new IP header */ M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); @@ -200,33 +205,18 @@ in_gif_output(ifp, family, m, rt) } } -#ifdef IPSEC - m->m_pkthdr.rcvif = NULL; -#endif /*IPSEC*/ error = ip_output(m, 0, &sc->gif_ro, 0, 0); return(error); } void -#if __STDC__ -in_gif_input(struct mbuf *m, ...) -#else -in_gif_input(m, va_alist) - struct mbuf *m; - va_dcl -#endif +in_gif_input(struct mbuf *m, int off, int proto) { - int off, proto; struct gif_softc *sc; struct ifnet *gifp = NULL; struct ip *ip; int i, af; - va_list ap; - - va_start(ap, m); - off = va_arg(ap, int); - proto = va_arg(ap, int); - va_end(ap); + u_int8_t otos; ip = mtod(m, struct ip *); @@ -262,7 +252,7 @@ in_gif_input(m, va_alist) #ifdef MROUTING /* for backward compatibility */ if (proto == IPPROTO_IPV4) { - ipip_input(m, off); + ipip_input(m, off, proto); return; } #endif /*MROUTING*/ @@ -271,6 +261,7 @@ in_gif_input(m, va_alist) return; } + otos = ip->ip_tos; m_adj(m, off); switch (proto) { @@ -284,12 +275,15 @@ in_gif_input(m, va_alist) return; } ip = mtod(m, struct ip *); + if (gifp->if_flags & IFF_LINK1) + ip_ecn_egress(ECN_ALLOWED, &otos, &ip->ip_tos); break; } #ifdef INET6 case IPPROTO_IPV6: { struct ip6_hdr *ip6; + u_int8_t itos; af = AF_INET6; if (m->m_len < sizeof(*ip6)) { m = m_pullup(m, sizeof(*ip6)); @@ -297,7 +291,11 @@ in_gif_input(m, va_alist) return; } ip6 = mtod(m, struct ip6_hdr *); + itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; + if (gifp->if_flags & IFF_LINK1) + ip_ecn_egress(ECN_ALLOWED, &otos, &itos); ip6->ip6_flow &= ~htonl(0xff << 20); + ip6->ip6_flow |= htonl((u_int32_t)itos << 20); break; } #endif /* INET6 */ diff --git a/sys/netinet/in_gif.h b/sys/netinet/in_gif.h index b874524..dcba361 100644 --- a/sys/netinet/in_gif.h +++ b/sys/netinet/in_gif.h @@ -36,7 +36,7 @@ extern int ip_gif_ttl; -void in_gif_input __P((struct mbuf *, ...)); +void in_gif_input __P((struct mbuf *, int off, int proto)); int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *)); #endif /*_NETINET_IN_GIF_H_*/ diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index b3f6d61..2ac79ef 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -34,6 +34,7 @@ * $FreeBSD$ */ +#include "opt_ipsec.h" #include "opt_inet6.h" #include <sys/param.h> diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index b9a9e4a..e3243f8 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -36,6 +36,8 @@ #include "opt_ipdivert.h" #include "opt_ipx.h" +#include "opt_ipsec.h" +#include "opt_inet6.h" #include <sys/param.h> #include <sys/kernel.h> @@ -59,10 +61,21 @@ #include <netinet/tcp_var.h> #include <netinet/udp.h> #include <netinet/udp_var.h> + +#include <netinet/ipprotosw.h> + /* * TCP/IP protocol family: IP, ICMP, UDP, TCP. */ +#ifdef IPSEC +#include <netinet6/ipsec.h> +#include <netinet6/ah.h> +#ifdef IPSEC_ESP +#include <netinet6/esp.h> +#endif +#endif /* IPSEC */ + #include "gif.h" #if NGIF > 0 #include <netinet/in_gif.h> @@ -80,7 +93,7 @@ extern struct domain inetdomain; static struct pr_usrreqs nousrreqs; -struct protosw inetsw[] = { +struct ipprotosw inetsw[] = { { 0, &inetdomain, 0, 0, 0, 0, 0, 0, 0, @@ -124,6 +137,22 @@ struct protosw inetsw[] = { 0, 0, 0, 0, &rip_usrreqs }, +#ifdef IPSEC +{ SOCK_RAW, &inetdomain, IPPROTO_AH, PR_ATOMIC|PR_ADDR, + ah4_input, 0, 0, 0, + 0, + 0, 0, 0, 0, + &nousrreqs +}, +#ifdef IPSEC_ESP +{ SOCK_RAW, &inetdomain, IPPROTO_ESP, PR_ATOMIC|PR_ADDR, + esp4_input, 0, 0, 0, + 0, + 0, 0, 0, 0, + &nousrreqs +}, +#endif +#endif /* IPSEC */ #if NGIF > 0 { SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR, in_gif_input, 0, 0, 0, @@ -199,7 +228,8 @@ extern int in_inithead __P((void **, int)); struct domain inetdomain = { AF_INET, "internet", 0, 0, 0, - inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0, + (struct protosw *)inetsw, + (struct protosw *)&inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0, in_inithead, 32, sizeof(struct sockaddr_in) }; @@ -213,6 +243,9 @@ SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp, CTLFLAG_RW, 0, "ICMP"); SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp, CTLFLAG_RW, 0, "UDP"); SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW, 0, "TCP"); SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp, CTLFLAG_RW, 0, "IGMP"); +#ifdef IPSEC +SYSCTL_NODE(_net_inet, IPPROTO_AH, ipsec, CTLFLAG_RW, 0, "IPSEC"); +#endif /* IPSEC */ SYSCTL_NODE(_net_inet, IPPROTO_RAW, raw, CTLFLAG_RW, 0, "RAW"); #ifdef IPDIVERT SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, div, CTLFLAG_RW, 0, "DIVERT"); diff --git a/sys/netinet/ip.h b/sys/netinet/ip.h index 0b6f1b6..7f92ba7 100644 --- a/sys/netinet/ip.h +++ b/sys/netinet/ip.h @@ -89,6 +89,10 @@ struct ip { #define IPTOS_THROUGHPUT 0x08 #define IPTOS_RELIABILITY 0x04 #define IPTOS_MINCOST 0x02 +/* ECN bits proposed by Sally Floyd */ +#define IPTOS_CE 0x01 /* congestion experienced */ +#define IPTOS_ECT 0x02 /* ECN-capable transport */ + /* * Definitions for IP precedence (also in ip_tos) (hopefully unused) diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index a2b76b3..5c2cd76 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -36,6 +36,7 @@ #include "opt_inet.h" #include "opt_ipfw.h" #include "opt_ipdivert.h" +#include "opt_ipsec.h" #ifndef INET #error "IPDIVERT requires INET." @@ -126,7 +127,7 @@ div_init(void) * with that protocol number to enter the system from the outside. */ void -div_input(struct mbuf *m, int hlen) +div_input(struct mbuf *m, int off, int proto) { ipstat.ips_noproto++; m_freem(m); @@ -296,7 +297,8 @@ div_output(so, m, addr, control) ipstat.ips_rawout++; /* XXX */ error = ip_output(m, inp->inp_options, &inp->inp_route, (so->so_options & SO_DONTROUTE) | - IP_ALLOWBROADCAST | IP_RAWOUTPUT, inp->inp_moptions); + IP_ALLOWBROADCAST | IP_RAWOUTPUT | IP_SOCKINMRCVIF, + inp->inp_moptions); } else { struct ifaddr *ifa; @@ -344,20 +346,27 @@ div_attach(struct socket *so, int proto, struct proc *p) if (p && (error = suser(p)) != 0) return error; + error = soreserve(so, div_sendspace, div_recvspace); + if (error) + return error; s = splnet(); error = in_pcballoc(so, &divcbinfo, p); splx(s); if (error) return error; - error = soreserve(so, div_sendspace, div_recvspace); - if (error) - return error; inp = (struct inpcb *)so->so_pcb; inp->inp_ip_p = proto; inp->inp_flags |= INP_HDRINCL; /* The socket is always "connected" because we always know "where" to send the packet */ so->so_state |= SS_ISCONNECTED; +#ifdef IPSEC + error = ipsec_init_policy(so, &inp->inp_sp); + if (error != 0) { + in_pcbdetach(inp); + return error; + } +#endif /*IPSEC*/ return 0; } @@ -414,7 +423,7 @@ div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct proc *p) { /* Packet must have a header (but that's about it) */ - if (m->m_len < sizeof (struct ip) || + if (m->m_len < sizeof (struct ip) && (m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; m_freem(m); diff --git a/sys/netinet/ip_dummynet.c b/sys/netinet/ip_dummynet.c index 401e24d..9791a7f 100644 --- a/sys/netinet/ip_dummynet.c +++ b/sys/netinet/ip_dummynet.c @@ -220,7 +220,7 @@ dn_move(struct dn_pipe *pipe, int immediate) struct route *ro = &(pkt->ro) ; (void)ip_output((struct mbuf *)pkt, (struct mbuf *)pkt->ifp, - ro, pkt->dn_dst, NULL); + ro, pkt->flags, NULL); rt_unref (ro->ro_rt) ; } break ; @@ -290,7 +290,7 @@ int dummynet_io(int pipe_nr, int dir, struct mbuf *m, struct ifnet *ifp, struct route *ro, struct sockaddr_in *dst, - struct ip_fw_chain *rule) + struct ip_fw_chain *rule, int flags) { struct dn_pkt *pkt; struct dn_pipe *pipe; @@ -359,6 +359,12 @@ dummynet_io(int pipe_nr, int dir, dst = (struct sockaddr_in *)&(pkt->ro.ro_dst) ; pkt->dn_dst = dst; /* XXX this can't be right! */ + /* + * 'flags' also need to be kept for later packet treatment + * such as IPSEC. IPSEC consider sending packet's m->m_pkthdr.rcvif + * as 'socket *' at ip_output(), if IP_SOCKINMRCVIF is set. + */ + pkt->flags = flags; } if (pipe->r.head == NULL) pipe->r.head = pkt; diff --git a/sys/netinet/ip_dummynet.h b/sys/netinet/ip_dummynet.h index 55d9614..2c0e8b9 100644 --- a/sys/netinet/ip_dummynet.h +++ b/sys/netinet/ip_dummynet.h @@ -44,6 +44,7 @@ struct dn_pkt { int delay; /* stays queued until delay=0 */ struct ifnet *ifp; /* interface, for ip_output */ struct route ro; /* route, for ip_output. MUST COPY */ + int flags; /* flags, for ip_output */ #ifdef DUMMYNET_DEBUG struct timeval beg, mid; /* testing only */ @@ -109,7 +110,7 @@ void dn_rule_delete(void *r); /* used in ip_fw.c */ int dummynet_io(int pipe, int dir, struct mbuf *m, struct ifnet *ifp, struct route *ro, struct sockaddr_in * dst, - struct ip_fw_chain *rule); + struct ip_fw_chain *rule, int flags); #endif /* KERNEL */ #endif /* _IP_DUMMYNET_H */ diff --git a/sys/netinet/ip_ecn.c b/sys/netinet/ip_ecn.c new file mode 100644 index 0000000..7a1657f --- /dev/null +++ b/sys/netinet/ip_ecn.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ip_ecn.c,v 1.2 1999/07/30 12:17:15 itojun Exp $ + * $FreeBSD$ + */ +/* + * ECN consideration on tunnel ingress/egress operation. + * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt + */ + +#include "opt_inet.h" +#include "opt_inet6.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#endif + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <netinet/ip6.h> +#endif + +#include <netinet/ip_ecn.h> +#ifdef INET6 +#include <netinet6/ip6_ecn.h> +#endif + +/* + * modify outer ECN (TOS) field on ingress operation (tunnel encapsulation). + * call it after you've done the default initialization/copy for the outer. + */ +void +ip_ecn_ingress(mode, outer, inner) + int mode; + u_int8_t *outer; + u_int8_t *inner; +{ + if (!outer || !inner) + panic("NULL pointer passed to ip_ecn_ingress"); + + switch (mode) { + case ECN_ALLOWED: /* ECN allowed */ + *outer &= ~IPTOS_CE; + break; + case ECN_FORBIDDEN: /* ECN forbidden */ + *outer &= ~(IPTOS_ECT | IPTOS_CE); + break; + case ECN_NOCARE: /* no consideration to ECN */ + break; + } +} + +/* + * modify inner ECN (TOS) field on egress operation (tunnel decapsulation). + * call it after you've done the default initialization/copy for the inner. + */ +void +ip_ecn_egress(mode, outer, inner) + int mode; + u_int8_t *outer; + u_int8_t *inner; +{ + if (!outer || !inner) + panic("NULL pointer passed to ip_ecn_egress"); + + switch (mode) { + case ECN_ALLOWED: + if (*outer & IPTOS_CE) + *inner |= IPTOS_CE; + break; + case ECN_FORBIDDEN: /* ECN forbidden */ + case ECN_NOCARE: /* no consideration to ECN */ + break; + } +} + +#ifdef INET6 +void +ip6_ecn_ingress(mode, outer, inner) + int mode; + u_int32_t *outer; + u_int32_t *inner; +{ + u_int8_t outer8, inner8; + + if (!outer || !inner) + panic("NULL pointer passed to ip6_ecn_ingress"); + + outer8 = (ntohl(*outer) >> 20) & 0xff; + inner8 = (ntohl(*inner) >> 20) & 0xff; + ip_ecn_ingress(mode, &outer8, &inner8); + *outer &= ~htonl(0xff << 20); + *outer |= htonl((u_int32_t)outer8 << 20); +} + +void +ip6_ecn_egress(mode, outer, inner) + int mode; + u_int32_t *outer; + u_int32_t *inner; +{ + u_int8_t outer8, inner8; + + if (!outer || !inner) + panic("NULL pointer passed to ip6_ecn_egress"); + + outer8 = (ntohl(*outer) >> 20) & 0xff; + inner8 = (ntohl(*inner) >> 20) & 0xff; + ip_ecn_egress(mode, &outer8, &inner8); + *inner &= ~htonl(0xff << 20); + *inner |= htonl((u_int32_t)inner8 << 20); +} +#endif diff --git a/sys/netinet/ip_ecn.h b/sys/netinet/ip_ecn.h new file mode 100644 index 0000000..4a0bfd5 --- /dev/null +++ b/sys/netinet/ip_ecn.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ip_ecn.h,v 1.2 1999/08/19 12:57:44 itojun Exp $ + * $FreeBSD$ + */ +/* + * ECN consideration on tunnel ingress/egress operation. + * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt + */ + +#define ECN_ALLOWED 1 /* ECN allowed */ +#define ECN_FORBIDDEN 0 /* ECN forbidden */ +#define ECN_NOCARE (-1) /* no consideration to ECN */ + +#if defined(KERNEL) || defined(_KERNEL) +extern void ip_ecn_ingress __P((int, u_int8_t *, u_int8_t *)); +extern void ip_ecn_egress __P((int, u_int8_t *, u_int8_t *)); +#endif diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 145699b..76ff004 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -34,6 +34,8 @@ * $FreeBSD$ */ +#include "opt_ipsec.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> @@ -55,6 +57,16 @@ #include <netinet/ip_var.h> #include <netinet/icmp_var.h> +#ifdef IPSEC +#include <netinet6/ipsec.h> +#include <netkey/key.h> +#endif + +#include "faith.h" +#if defined(NFAITH) && NFAITH > 0 +#include <net/if_types.h> +#endif + /* * ICMP routines: error generation, receive packet processing, and * routines to turnaround packets back to the originator, and @@ -219,10 +231,11 @@ static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; * Process a received ICMP message. */ void -icmp_input(m, hlen) +icmp_input(m, off, proto) register struct mbuf *m; - int hlen; + int off, proto; { + int hlen = off; register struct icmp *icp; register struct ip *ip = mtod(m, struct ip *); int icmplen = ip->ip_len; @@ -263,12 +276,36 @@ icmp_input(m, hlen) m->m_len += hlen; m->m_data -= hlen; +#if defined(NFAITH) && 0 < NFAITH + if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { + /* + * Deliver very specific ICMP type only. + */ + switch (icp->icmp_type) { + case ICMP_UNREACH: + case ICMP_TIMXCEED: + break; + default: + goto freeit; + } + } +#endif + #ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_input, type %d code %d\n", icp->icmp_type, icp->icmp_code); #endif +#ifdef IPSEC + /* drop it if it does not match the policy */ + /* XXX Is there meaning of check in here ? */ + if (ipsec4_in_reject(m, NULL)) { + ipsecstat.in_polvio++; + goto freeit; + } +#endif + /* * Message type specific processing. */ @@ -394,6 +431,10 @@ icmp_input(m, hlen) } #endif + /* + * XXX if the packet contains [IPv4 AH TCP], we can't make a + * notification to TCP layer. + */ ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; if (ctlfunc) (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, @@ -518,6 +559,9 @@ reflect: (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, (struct sockaddr *)&icmpgw, (struct rtentry **)0); pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc); +#ifdef IPSEC + key_sa_routechange((struct sockaddr *)&icmpsrc); +#endif break; /* @@ -535,7 +579,7 @@ reflect: } raw: - rip_input(m, hlen); + rip_input(m, off, proto); return; freeit: diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h index c8fd55f..201c3fc 100644 --- a/sys/netinet/ip_icmp.h +++ b/sys/netinet/ip_icmp.h @@ -186,7 +186,7 @@ struct icmp { #ifdef KERNEL void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *)); -void icmp_input __P((struct mbuf *, int)); +void icmp_input __P((struct mbuf *, int, int)); #endif #endif diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index a202a8b..be6d25d 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -42,6 +42,7 @@ #include "opt_ipdivert.h" #include "opt_ipfilter.h" #include "opt_ipstealth.h" +#include "opt_ipsec.h" #include <stddef.h> @@ -72,10 +73,27 @@ #include <netinet/ip_icmp.h> #include <machine/in_cksum.h> +#include <netinet/ipprotosw.h> + #include <sys/socketvar.h> #include <netinet/ip_fw.h> +#ifdef IPSEC +#include <netinet6/ipsec.h> +#include <netkey/key.h> +#ifdef IPSEC_DEBUG +#include <netkey/key_debug.h> +#else +#define KEYDEBUG(lev,arg) +#endif +#endif + +#include "faith.h" +#if defined(NFAITH) && NFAITH > 0 +#include <net/if_types.h> +#endif + #ifdef DUMMYNET #include <netinet/ip_dummynet.h> #endif @@ -104,12 +122,18 @@ static int ip_acceptsourceroute = 0; SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute, CTLFLAG_RW, &ip_acceptsourceroute, 0, "Enable accepting source routed IP packets"); + +static int ip_keepfaith = 0; +SYSCTL_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_RW, + &ip_keepfaith, 0, + "Enable packet capture for FAITH IPv4->IPv6 translater daemon"); + #ifdef DIAGNOSTIC static int ipprintfs = 0; #endif extern struct domain inetdomain; -extern struct protosw inetsw[]; +extern struct ipprotosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; static int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddrhead in_ifaddrhead; /* first inet address */ @@ -181,10 +205,10 @@ static int ip_dooptions __P((struct mbuf *)); static void ip_forward __P((struct mbuf *, int)); static void ip_freef __P((struct ipq *)); #ifdef IPDIVERT -static struct ip *ip_reass __P((struct mbuf *, +static struct mbuf *ip_reass __P((struct mbuf *, struct ipq *, struct ipq *, u_int32_t *, u_int16_t *)); #else -static struct ip *ip_reass __P((struct mbuf *, struct ipq *, struct ipq *)); +static struct mbuf *ip_reass __P((struct mbuf *, struct ipq *, struct ipq *)); #endif static struct in_ifaddr *ip_rtaddr __P((struct in_addr)); static void ipintr __P((void)); @@ -196,17 +220,17 @@ static void ipintr __P((void)); void ip_init() { - register struct protosw *pr; + register struct ipprotosw *pr; register int i; TAILQ_INIT(&in_ifaddrhead); - pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); + pr = (struct ipprotosw *)pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == 0) panic("ip_init"); for (i = 0; i < IPPROTO_MAX; i++) ip_protox[i] = pr - inetsw; - for (pr = inetdomain.dom_protosw; - pr < inetdomain.dom_protoswNPROTOSW; pr++) + for (pr = (struct ipprotosw *)inetdomain.dom_protosw; + pr < (struct ipprotosw *)inetdomain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) ip_protox[pr->pr_protocol] = pr - inetsw; @@ -387,7 +411,8 @@ iphack: #ifdef DUMMYNET if ((i & IP_FW_PORT_DYNT_FLAG) != 0) { /* Send packet to the appropriate pipe */ - dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule); + dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule, + 0); return; } #endif @@ -523,6 +548,19 @@ pass: if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; +#if defined(NFAITH) && 0 < NFAITH + /* + * FAITH(Firewall Aided Internet Translator) + */ + if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { + if (ip_keepfaith) { + if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_ICMP) + goto ours; + } + m_freem(m); + return; + } +#endif /* * Not for us; forward if possible and desirable. */ @@ -546,6 +584,11 @@ ours: * but it's not worth the time; just let them time out.) */ if (ip->ip_off & (IP_MF | IP_OFFMASK | IP_RF)) { + +#if 0 /* + * Reassembly should be able to treat a mbuf cluster, for later + * operation of contiguous protocol headers on the cluster. (KAME) + */ if (m->m_flags & M_EXT) { /* XXX */ if ((m = m_pullup(m, hlen)) == 0) { ipstat.ips_toosmall++; @@ -556,6 +599,7 @@ ours: } ip = mtod(m, struct ip *); } +#endif sum = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); /* * Look for queue of fragments @@ -616,12 +660,12 @@ found: ipstat.ips_fragments++; m->m_pkthdr.header = ip; #ifdef IPDIVERT - ip = ip_reass(m, + m = ip_reass(m, fp, &ipq[sum], &divert_info, &divert_cookie); #else - ip = ip_reass(m, fp, &ipq[sum]); + m = ip_reass(m, fp, &ipq[sum]); #endif - if (ip == 0) { + if (m == 0) { #ifdef IPFIREWALL_FORWARD ip_fw_fwd_addr = NULL; #endif @@ -630,7 +674,7 @@ found: /* Get the length of the reassembled packets header */ hlen = IP_VHL_HL(ip->ip_vhl) << 2; ipstat.ips_reassembled++; - m = dtom(ip); + ip = mtod(m, struct ip *); #ifdef IPDIVERT /* Restore original checksum before diverting packet */ if (divert_info != 0) { @@ -689,11 +733,15 @@ found: * Switch out to protocol's input routine. */ ipstat.ips_delivered++; - (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); + { + int off = hlen, nh = ip->ip_p; + + (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, off, nh); #ifdef IPFIREWALL_FORWARD ip_fw_fwd_addr = NULL; /* tcp needed it */ #endif return; + } bad: #ifdef IPFIREWALL_FORWARD ip_fw_fwd_addr = NULL; @@ -731,7 +779,7 @@ NETISR_SET(NETISR_IP, ipintr); * tells us if we need to divert or tee the packet we're building. */ -static struct ip * +static struct mbuf * #ifdef IPDIVERT ip_reass(m, fp, where, divinfo, divcookie) #else @@ -801,7 +849,7 @@ ip_reass(m, fp, where) if (i > 0) { if (i >= ip->ip_len) goto dropfrag; - m_adj(dtom(ip), i); + m_adj(m, i); ip->ip_off += i; ip->ip_len -= i; } @@ -908,11 +956,11 @@ inserted: /* some debugging cruft by sklower, below, will go away soon */ if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */ register int plen = 0; - for (t = m; m; m = m->m_next) - plen += m->m_len; - t->m_pkthdr.len = plen; + for (t = m; t; t = t->m_next) + plen += t->m_len; + m->m_pkthdr.len = plen; } - return (ip); + return (m); dropfrag: #ifdef IPDIVERT @@ -1399,6 +1447,9 @@ ip_forward(m, srcrt) struct mbuf *mcopy; n_long dest; struct ifnet *destifp; +#ifdef IPSEC + struct ifnet dummyifp; +#endif dest = 0; #ifdef DIAGNOSTIC @@ -1523,8 +1574,61 @@ ip_forward(m, srcrt) case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; +#ifndef IPSEC if (ipforward_rt.ro_rt) destifp = ipforward_rt.ro_rt->rt_ifp; +#else + /* + * If the packet is routed over IPsec tunnel, tell the + * originator the tunnel MTU. + * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz + * XXX quickhack!!! + */ + if (ipforward_rt.ro_rt) { + struct secpolicy *sp = NULL; + int ipsecerror; + int ipsechdr; + struct route *ro; + + sp = ipsec4_getpolicybyaddr(mcopy, + IPSEC_DIR_OUTBOUND, + IP_FORWARDING, + &ipsecerror); + + if (sp == NULL) + destifp = ipforward_rt.ro_rt->rt_ifp; + else { + /* count IPsec header size */ + ipsechdr = ipsec4_hdrsiz(mcopy, + IPSEC_DIR_OUTBOUND, + NULL); + + /* + * find the correct route for outer IPv4 + * header, compute tunnel MTU. + * + * XXX BUG ALERT + * The "dummyifp" code relies upon the fact + * that icmp_error() touches only ifp->if_mtu. + */ + /*XXX*/ + destifp = NULL; + if (sp->req != NULL + && sp->req->sav != NULL + && sp->req->sav->sah != NULL) { + ro = &sp->req->sav->sah->sa_route; + if (ro->ro_rt && ro->ro_rt->rt_ifp) { + dummyifp.if_mtu = + ro->ro_rt->rt_ifp->if_mtu; + dummyifp.if_mtu -= ipsechdr; + destifp = &dummyifp; + } + } + + key_freesp(sp); + } + } +#endif /*IPSEC*/ ipstat.ips_cantfrag++; break; diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 20aa381..378102d 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -117,9 +117,10 @@ _mrt_ioctl(int req, caddr_t data, struct proc *p) int (*mrt_ioctl)(int, caddr_t, struct proc *) = _mrt_ioctl; void -rsvp_input(m, iphlen) /* XXX must fixup manually */ +rsvp_input(m, off, proto) /* XXX must fixup manually */ struct mbuf *m; - int iphlen; + int off; + int proto; { /* Can still get packets with rsvp_on = 0 if there is a local member * of the group to which the RSVP packet is addressed. But in this @@ -133,15 +134,15 @@ rsvp_input(m, iphlen) /* XXX must fixup manually */ if (ip_rsvpd != NULL) { if (rsvpdebug) printf("rsvp_input: Sending packet up old-style socket\n"); - rip_input(m, iphlen); + rip_input(m, off, proto); return; } /* Drop the packet */ m_freem(m); } -void ipip_input(struct mbuf *m, int iphlen) { /* XXX must fixup manually */ - rip_input(m, iphlen); +void ipip_input(struct mbuf *m, int off, int proto) { /* XXX must fixup manually */ + rip_input(m, off, proto); } int (*legal_vif_num)(int) = 0; @@ -1609,12 +1610,13 @@ encap_send(ip, vifp, m) */ void #ifdef MROUTE_LKM -X_ipip_input(m, iphlen) +X_ipip_input(m, off, proto) #else -ipip_input(m, iphlen) +ipip_input(m, off, proto) #endif register struct mbuf *m; - int iphlen; + int off; + int proto; { struct ifnet *ifp = m->m_pkthdr.rcvif; register struct ip *ip = mtod(m, struct ip *); @@ -1624,7 +1626,7 @@ ipip_input(m, iphlen) register struct vif *vifp; if (!have_encap_tunnel) { - rip_input(m, iphlen); + rip_input(m, off, proto); return; } /* @@ -2119,9 +2121,10 @@ ip_rsvp_force_done(so) } void -rsvp_input(m, iphlen) +rsvp_input(m, off, proto) struct mbuf *m; - int iphlen; + int off; + int proto; { int vifi; register struct ip *ip = mtod(m, struct ip *); @@ -2147,7 +2150,7 @@ rsvp_input(m, iphlen) if (ip_rsvpd != NULL) { if (rsvpdebug) printf("rsvp_input: Sending packet up old-style socket\n"); - rip_input(m, iphlen); + rip_input(m, off, proto); /* xxx */ return; } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 2ed22e6..52bfdb9 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -40,6 +40,7 @@ #include "opt_ipdn.h" #include "opt_ipdivert.h" #include "opt_ipfilter.h" +#include "opt_ipsec.h" #include <sys/param.h> #include <sys/systm.h> @@ -49,6 +50,7 @@ #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> +#include <sys/proc.h> #include <net/if.h> #include <net/route.h> @@ -60,6 +62,8 @@ #include <netinet/in_var.h> #include <netinet/ip_var.h> +#include "faith.h" + #ifdef vax #include <machine/mtpr.h> #endif @@ -67,6 +71,16 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options"); +#ifdef IPSEC +#include <netinet6/ipsec.h> +#include <netkey/key.h> +#ifdef IPSEC_DEBUG +#include <netkey/key_debug.h> +#else +#define KEYDEBUG(lev,arg) +#endif +#endif /*IPSEC*/ + #include <netinet/ip_fw.h> #ifdef DUMMYNET @@ -123,6 +137,11 @@ ip_output(m0, opt, ro, flags, imo) struct sockaddr_in *dst; struct in_ifaddr *ia; int isbroadcast; +#ifdef IPSEC + struct route iproute; + struct socket *so; + struct secpolicy *sp = NULL; +#endif u_int16_t divert_cookie; /* firewall cookie */ #ifdef IPFIREWALL_FORWARD int fwd_rewrite_src = 0; @@ -136,6 +155,32 @@ ip_output(m0, opt, ro, flags, imo) #else divert_cookie = 0; #endif + +#ifdef IPSEC + /* + * NOTE: If IP_SOCKINMRCVIF flag is set, 'socket *' is kept in + * m->m_pkthdr.rcvif for later IPSEC check. In this case, + * m->m_pkthdr will be NULL cleared after the contents is saved in + * 'so'. + * NULL clearance of rcvif should be natural because the packet should + * have been sent from my own socket and has no rcvif in this case. + * It is also necessary because someone might consider it as + * 'ifnet *', and cause SEGV. + */ + if ((flags & IP_SOCKINMRCVIF) != 0) { +#if defined(IPFIREWALL) && defined(DUMMYNET) + if (m->m_type == MT_DUMMYNET) { + so = (struct socket *)m->m_next->m_pkthdr.rcvif; + m->m_next->m_pkthdr.rcvif = NULL; + } else +#endif + { + so = (struct socket *)m->m_pkthdr.rcvif; + m->m_pkthdr.rcvif = NULL; + } + } else + so = NULL; +#endif /*IPSEC*/ #if defined(IPFIREWALL) && defined(DUMMYNET) /* @@ -151,13 +196,12 @@ ip_output(m0, opt, ro, flags, imo) * they are used to hold ifp, dst and NULL, respectively. */ rule = (struct ip_fw_chain *)(m->m_data) ; + dst = (struct sockaddr_in *)((struct dn_pkt *)m)->dn_dst; m0 = m = m->m_next ; ip = mtod(m, struct ip *); - dst = (struct sockaddr_in *)flags ; ifp = (struct ifnet *)opt; hlen = IP_VHL_HL(ip->ip_vhl) << 2 ; opt = NULL ; - flags = 0 ; /* XXX is this correct ? */ goto sendit; } else rule = NULL ; @@ -455,7 +499,8 @@ sendit: * XXX note: if the ifp or ro entry are deleted * while a pkt is in dummynet, we are in trouble! */ - dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,dst,rule); + dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,dst,rule, + flags); goto done; } #endif @@ -597,6 +642,125 @@ sendit: } pass: +#ifdef IPSEC + /* get SP for this packet */ + if (so == NULL) + sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error); + else + sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); + + if (sp == NULL) { + ipsecstat.out_inval++; + goto bad; + } + + error = 0; + + /* check policy */ + switch (sp->policy) { + case IPSEC_POLICY_DISCARD: + /* + * This packet is just discarded. + */ + ipsecstat.out_polvio++; + goto bad; + + case IPSEC_POLICY_BYPASS: + case IPSEC_POLICY_NONE: + /* no need to do IPsec. */ + goto skip_ipsec; + + case IPSEC_POLICY_IPSEC: + if (sp->req == NULL) { + /* XXX should be panic ? */ + printf("ip_output: No IPsec request specified.\n"); + error = EINVAL; + goto bad; + } + break; + + case IPSEC_POLICY_ENTRUST: + default: + printf("ip_output: Invalid policy found. %d\n", sp->policy); + } + + ip->ip_len = htons((u_short)ip->ip_len); + ip->ip_off = htons((u_short)ip->ip_off); + ip->ip_sum = 0; + + { + struct ipsec_output_state state; + bzero(&state, sizeof(state)); + state.m = m; + if (flags & IP_ROUTETOIF) { + state.ro = &iproute; + bzero(&iproute, sizeof(iproute)); + } else + state.ro = ro; + state.dst = (struct sockaddr *)dst; + + error = ipsec4_output(&state, sp, flags); + + m = state.m; + if (flags & IP_ROUTETOIF) { + /* + * if we have tunnel mode SA, we may need to ignore + * IP_ROUTETOIF. + */ + if (state.ro != &iproute || state.ro->ro_rt != NULL) { + flags &= ~IP_ROUTETOIF; + ro = state.ro; + } + } else + ro = state.ro; + dst = (struct sockaddr_in *)state.dst; + if (error) { + /* mbuf is already reclaimed in ipsec4_output. */ + m0 = NULL; + switch (error) { + case EHOSTUNREACH: + case ENETUNREACH: + case EMSGSIZE: + case ENOBUFS: + case ENOMEM: + break; + default: + printf("ip4_output (ipsec): error code %d\n", error); + /*fall through*/ + case ENOENT: + /* don't show these error codes to the user */ + error = 0; + break; + } + goto bad; + } + } + + /* be sure to update variables that are affected by ipsec4_output() */ + ip = mtod(m, struct ip *); +#ifdef _IP_VHL + hlen = IP_VHL_HL(ip->ip_vhl) << 2; +#else + hlen = ip->ip_hl << 2; +#endif + if (ro->ro_rt == NULL) { + if ((flags & IP_ROUTETOIF) == 0) { + printf("ip_output: " + "can't update route after IPsec processing\n"); + error = EHOSTUNREACH; /*XXX*/ + goto bad; + } + } else { + /* nobody uses ia beyond here */ + ifp = ro->ro_rt->rt_ifp; + } + + /* make it flipped, again. */ + ip->ip_len = ntohs((u_short)ip->ip_len); + ip->ip_off = ntohs((u_short)ip->ip_off); +skip_ipsec: +#endif /*IPSEC*/ + /* * If small enough for interface, can just send directly. */ @@ -724,6 +888,17 @@ sendorfree: ipstat.ips_fragmented++; } done: +#ifdef IPSEC + if (ro == &iproute && ro->ro_rt) { + RTFREE(ro->ro_rt); + ro->ro_rt = NULL; + } + if (sp != NULL) { + KEYDEBUG(KEYDEBUG_IPSEC_STAMP, + printf("DP ip_output call free SP:%p\n", sp)); + key_freesp(sp); + } +#endif /* IPSEC */ return (error); bad: m_freem(m0); @@ -868,6 +1043,9 @@ ip_ctloutput(so, sopt) case IP_RECVRETOPTS: case IP_RECVDSTADDR: case IP_RECVIF: +#if defined(NFAITH) && NFAITH > 0 + case IP_FAITH: +#endif error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) @@ -902,6 +1080,12 @@ ip_ctloutput(so, sopt) case IP_RECVIF: OPTSET(INP_RECVIF); break; + +#if defined(NFAITH) && NFAITH > 0 + case IP_FAITH: + OPTSET(INP_FAITH); + break; +#endif } break; #undef OPTSET @@ -943,6 +1127,28 @@ ip_ctloutput(so, sopt) } break; +#ifdef IPSEC + case IP_IPSEC_POLICY: + { + caddr_t req; + int priv; + struct mbuf *m; + int optname; + + if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */ + break; + if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */ + break; + priv = (sopt->sopt_p != NULL && + suser(sopt->sopt_p) != 0) ? 0 : 1; + req = mtod(m, caddr_t); + optname = sopt->sopt_name; + error = ipsec4_set_policy(inp, optname, req, priv); + m_freem(m); + break; + } +#endif /*IPSEC*/ + default: error = ENOPROTOOPT; break; @@ -969,6 +1175,9 @@ ip_ctloutput(so, sopt) case IP_RECVDSTADDR: case IP_RECVIF: case IP_PORTRANGE: +#if defined(NFAITH) && NFAITH > 0 + case IP_FAITH: +#endif switch (sopt->sopt_name) { case IP_TOS: @@ -1005,6 +1214,12 @@ ip_ctloutput(so, sopt) else optval = 0; break; + +#if defined(NFAITH) && NFAITH > 0 + case IP_FAITH: + optval = OPTBIT(INP_FAITH); + break; +#endif } error = sooptcopyout(sopt, &optval, sizeof optval); break; @@ -1018,6 +1233,22 @@ ip_ctloutput(so, sopt) error = ip_getmoptions(sopt, inp->inp_moptions); break; +#ifdef IPSEC + case IP_IPSEC_POLICY: + { + struct mbuf *m; + caddr_t req = NULL; + + if (m != 0) + req = mtod(m, caddr_t); + error = ipsec4_get_policy(sotoinpcb(so), req, &m); + if (error == 0) + error = soopt_mcopyout(sopt, m); /* XXX */ + m_freem(m); + break; + } +#endif /*IPSEC*/ + default: error = ENOPROTOOPT; break; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index c56a340..2c438d6 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -131,6 +131,9 @@ struct ipstat { #define IP_RAWOUTPUT 0x2 /* raw ip header exists */ #define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */ #define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ +#define IP_SOCKINMRCVIF 0x100 /* IPSEC hack; + * socket pointer in sending + * packet's m_pkthdr.rcvif */ struct ip; struct inpcb; @@ -166,10 +169,10 @@ void ip_stripoptions __P((struct mbuf *, struct mbuf *)); int rip_ctloutput __P((struct socket *, struct sockopt *)); void rip_ctlinput __P((int, struct sockaddr *, void *)); void rip_init __P((void)); -void rip_input __P((struct mbuf *, int)); +void rip_input __P((struct mbuf *, int, int)); int rip_output __P((struct mbuf *, struct socket *, u_long)); -void ipip_input __P((struct mbuf *, int)); -void rsvp_input __P((struct mbuf *, int)); +void ipip_input __P((struct mbuf *, int, int)); +void rsvp_input __P((struct mbuf *, int, int)); int ip_rsvp_init __P((struct socket *)); int ip_rsvp_done __P((void)); int ip_rsvp_vif_init __P((struct socket *, struct sockopt *)); @@ -178,7 +181,7 @@ void ip_rsvp_force_done __P((struct socket *)); #ifdef IPDIVERT void div_init __P((void)); -void div_input __P((struct mbuf *, int)); +void div_input __P((struct mbuf *, int, int)); void divert_packet __P((struct mbuf *, int, int)); extern struct pr_usrreqs div_usrreqs; extern u_int16_t ip_divert_cookie; diff --git a/sys/netinet/ipprotosw.h b/sys/netinet/ipprotosw.h new file mode 100644 index 0000000..0ecb64d --- /dev/null +++ b/sys/netinet/ipprotosw.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)protosw.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD$ + */ + +#ifndef _NETINET_IPPROTOSW_H_ +#define _NETINET_IPPROTOSW_H_ + +/* Forward declare these structures referenced from prototypes below. */ +struct mbuf; +struct proc; +struct sockaddr; +struct socket; +struct sockopt; + +struct ipprotosw { + short pr_type; /* socket type used for */ + struct domain *pr_domain; /* domain protocol a member of */ + short pr_protocol; /* protocol number */ + short pr_flags; /* see below */ +/* protocol-protocol hooks */ + void (*pr_input) __P((struct mbuf *, int off, int proto)); + /* input to protocol (from below) */ + int (*pr_output) __P((struct mbuf *m, struct socket *so)); + /* output to protocol (from above) */ + void (*pr_ctlinput)__P((int, struct sockaddr *, void *)); + /* control input (from below) */ + int (*pr_ctloutput)__P((struct socket *, struct sockopt *)); + /* control output (from above) */ +/* user-protocol hook */ + void *pr_ousrreq; +/* utility hooks */ + void (*pr_init) __P((void)); /* initialization hook */ + void (*pr_fasttimo) __P((void)); + /* fast timeout (200ms) */ + void (*pr_slowtimo) __P((void)); + /* slow timeout (500ms) */ + void (*pr_drain) __P((void)); + /* flush any excess space possible */ + struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */ +}; + +#endif /* !_NETINET_IPPROTOSW_H_ */ diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index ba36bd3..a3ddb23 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -34,6 +34,9 @@ * $FreeBSD$ */ +#include "opt_inet6.h" +#include "opt_ipsec.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -61,6 +64,10 @@ #include <netinet/ip_fw.h> +#ifdef IPSEC +#include <netinet6/ipsec.h> +#endif /*IPSEC*/ + #include "opt_ipdn.h" #ifdef DUMMYNET #include <netinet/ip_dummynet.h> @@ -105,9 +112,9 @@ static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; * mbuf chain. */ void -rip_input(m, iphlen) +rip_input(m, off, proto) struct mbuf *m; - int iphlen; + int off, proto; { register struct ip *ip = mtod(m, struct ip *); register struct inpcb *inp; @@ -115,8 +122,12 @@ rip_input(m, iphlen) struct mbuf *opts = 0; ripsrc.sin_addr = ip->ip_src; - for (inp = ripcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { - if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p) + LIST_FOREACH(inp, &ripcb, inp_list) { +#ifdef INET6 + if ((inp->inp_vflag & INP_IPV4) == 0) + continue; +#endif + if (inp->inp_ip_p && inp->inp_ip_p != proto) continue; if (inp->inp_laddr.s_addr && inp->inp_laddr.s_addr != ip->ip_dst.s_addr) @@ -215,7 +226,13 @@ rip_output(m, so, dst) flags |= IP_RAWOUTPUT; ipstat.ips_rawout++; } - return (ip_output(m, inp->inp_options, &inp->inp_route, flags, + +#ifdef IPSEC + m->m_pkthdr.rcvif = (struct ifnet *)so; /*XXX*/ +#endif /*IPSEC*/ + + return (ip_output(m, inp->inp_options, &inp->inp_route, + flags | IP_SOCKINMRCVIF, inp->inp_moptions)); } @@ -431,16 +448,24 @@ rip_attach(struct socket *so, int proto, struct proc *p) if (p && (error = suser(p)) != 0) return error; + error = soreserve(so, rip_sendspace, rip_recvspace); + if (error) + return error; s = splnet(); error = in_pcballoc(so, &ripcbinfo, p); splx(s); if (error) return error; - error = soreserve(so, rip_sendspace, rip_recvspace); - if (error) - return error; inp = (struct inpcb *)so->so_pcb; + inp->inp_vflag |= INP_IPV4; inp->inp_ip_p = proto; +#ifdef IPSEC + error = ipsec_init_policy(so, &inp->inp_sp); + if (error != 0) { + in_pcbdetach(inp); + return error; + } +#endif /*IPSEC*/ return 0; } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 33a478c..9605f7f 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -273,10 +273,11 @@ present: * protocol specification dated September, 1981 very closely. */ void -tcp_input(m, iphlen) +tcp_input(m, off0, proto) register struct mbuf *m; - int iphlen; + int off0, proto; { + int iphlen = off0; register struct tcpiphdr *ti; register struct inpcb *inp; u_char *optp = NULL; diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 33a478c..9605f7f 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -273,10 +273,11 @@ present: * protocol specification dated September, 1981 very closely. */ void -tcp_input(m, iphlen) +tcp_input(m, off0, proto) register struct mbuf *m; - int iphlen; + int off0, proto; { + int iphlen = off0; register struct tcpiphdr *ti; register struct inpcb *inp; u_char *optp = NULL; diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 7d7f71f..d3aea36 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -34,6 +34,7 @@ * $FreeBSD$ */ +#include "opt_ipsec.h" #include "opt_tcpdebug.h" #include <sys/param.h> @@ -63,6 +64,10 @@ #include <netinet/tcp_debug.h> #endif +#ifdef IPSEC +#include <netinet6/ipsec.h> +#endif /*IPSEC*/ + /* * TCP protocol interface to socket abstraction. */ @@ -731,6 +736,13 @@ tcp_attach(so, p) if (error) return (error); inp = sotoinpcb(so); +#ifdef IPSEC + error = ipsec_init_policy(so, &inp->inp_sp); + if (error) { + in_pcbdetach(inp); + return (error); + } +#endif /*IPSEC*/ inp->inp_vflag |= INP_IPV4; tp = tcp_newtcpcb(inp); if (tp == 0) { diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 0258b77..9c24732 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -361,7 +361,7 @@ void tcp_fasttimo __P((void)); struct rmxp_tao * tcp_gettaocache __P((struct inpcb *)); void tcp_init __P((void)); -void tcp_input __P((struct mbuf *, int)); +void tcp_input __P((struct mbuf *, int, int)); void tcp_mss __P((struct tcpcb *, int)); int tcp_mssopt __P((struct tcpcb *)); void tcp_mtudisc __P((struct inpcb *, int)); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index bc854de..2ed9a36 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -34,6 +34,7 @@ * $FreeBSD$ */ +#include "opt_ipsec.h" #include "opt_inet6.h" #include <sys/param.h> @@ -705,7 +706,8 @@ udp_output(inp, m, addr, control, p) #endif /*IPSEC*/ error = ip_output(m, inp->inp_options, &inp->inp_route, - inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), + (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)) + | IP_SOCKINMRCVIF, inp->inp_moptions); if (addr) { |