summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/igmp.c7
-rw-r--r--sys/netinet/igmp_var.h2
-rw-r--r--sys/netinet/in.c253
-rw-r--r--sys/netinet/in.h2
-rw-r--r--sys/netinet/in_gif.c38
-rw-r--r--sys/netinet/in_gif.h2
-rw-r--r--sys/netinet/in_pcb.c1
-rw-r--r--sys/netinet/in_proto.c37
-rw-r--r--sys/netinet/ip.h4
-rw-r--r--sys/netinet/ip_divert.c21
-rw-r--r--sys/netinet/ip_dummynet.c10
-rw-r--r--sys/netinet/ip_dummynet.h3
-rw-r--r--sys/netinet/ip_ecn.c149
-rw-r--r--sys/netinet/ip_ecn.h44
-rw-r--r--sys/netinet/ip_icmp.c50
-rw-r--r--sys/netinet/ip_icmp.h2
-rw-r--r--sys/netinet/ip_input.c142
-rw-r--r--sys/netinet/ip_mroute.c27
-rw-r--r--sys/netinet/ip_output.c237
-rw-r--r--sys/netinet/ip_var.h11
-rw-r--r--sys/netinet/ipprotosw.h103
-rw-r--r--sys/netinet/raw_ip.c41
-rw-r--r--sys/netinet/tcp_input.c5
-rw-r--r--sys/netinet/tcp_reass.c5
-rw-r--r--sys/netinet/tcp_usrreq.c12
-rw-r--r--sys/netinet/tcp_var.h2
-rw-r--r--sys/netinet/udp_usrreq.c4
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) {
OpenPOWER on IntegriCloud