summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>1998-05-24 14:14:01 +0000
committerNiels Provos <provos@cvs.openbsd.org>1998-05-24 14:14:01 +0000
commit9144f8bae2a4f36a26def0448257c96f8f235aa7 (patch)
tree51451fb497fb6d7c903d24a27d36e32c40986486
parentc2b7ebe6a032e384693542e22ac0ffa5e3411777 (diff)
add support for Virtual Private Networks (VPN).
-rw-r--r--sys/net/encap.c88
-rw-r--r--sys/net/encap.h7
-rw-r--r--sys/netinet/ip_output.c31
3 files changed, 117 insertions, 9 deletions
diff --git a/sys/net/encap.c b/sys/net/encap.c
index 9b88b3b8c0b..2673e5fe839 100644
--- a/sys/net/encap.c
+++ b/sys/net/encap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: encap.c,v 1.22 1998/05/18 21:10:15 provos Exp $ */
+/* $OpenBSD: encap.c,v 1.23 1998/05/24 14:13:57 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -329,6 +329,35 @@ encap_enable_spi(u_int32_t spi, struct in_addr dst,
flow = flow2 = flow3 = flow4 = (struct flow *) NULL;
+ /* Retrieve source and destination masks from routing entry */
+ if (flags & ENABLE_FLAG_MODIFY) {
+ struct route_enc re0, *re = &re0;
+ struct sockaddr_encap *dest, *mask;
+
+ bzero((caddr_t) re, sizeof(*re));
+ dest = (struct sockaddr_encap *) &re->re_dst;
+ dest->sen_family = AF_ENCAP;
+ dest->sen_len = SENT_IP4_LEN;
+ dest->sen_type = SENT_IP4;
+ dest->sen_ip_src = tdbp->tdb_src;
+ dest->sen_ip_dst = dst;
+ dest->sen_proto = protocol;
+ dest->sen_sport = sport;
+ dest->sen_dport = dport;
+ rtalloc((struct route *) re);
+ if (re->re_rt == NULL)
+ return (ENOENT);
+
+ mask = (struct sockaddr_encap *) (rt_mask(re->re_rt));
+ if (mask == NULL)
+ return (ENOENT);
+
+ ismask.s_addr = mask->sen_ip_src.s_addr;
+ idmask.s_addr = mask->sen_ip_dst.s_addr;
+
+ RTFREE(re->re_rt);
+ }
+
isrc.s_addr &= ismask.s_addr;
idst.s_addr &= idmask.s_addr;
@@ -884,6 +913,35 @@ va_dcl
if (tdbp == NULL)
SENDERR(ENOENT);
+ /* Retrieve source and destination masks from routing entry */
+ if (emp->em_ena_flags & ENABLE_FLAG_MODIFY) {
+ struct route_enc re0, *re = &re0;
+ struct sockaddr_encap *dest, *mask;
+
+ bzero((caddr_t) re, sizeof(*re));
+ dest = (struct sockaddr_encap *) &re->re_dst;
+ dest->sen_family = AF_ENCAP;
+ dest->sen_len = SENT_IP4_LEN;
+ dest->sen_type = SENT_IP4;
+ dest->sen_ip_src = tdbp->tdb_src;
+ dest->sen_ip_dst = emp->em_ena_dst;
+ dest->sen_proto = emp->em_ena_protocol;
+ dest->sen_sport = emp->em_ena_sport;
+ dest->sen_dport = emp->em_ena_dport;
+ rtalloc((struct route *) re);
+ if (re->re_rt == NULL)
+ return (ENOENT);
+
+ mask = (struct sockaddr_encap *) (rt_mask(re->re_rt));
+ if (mask == NULL)
+ return (ENOENT);
+
+ emp->em_ena_ismask.s_addr = mask->sen_ip_src.s_addr;
+ emp->em_ena_idmask.s_addr = mask->sen_ip_dst.s_addr;
+
+ RTFREE(re->re_rt);
+ }
+
emp->em_ena_isrc.s_addr &= emp->em_ena_ismask.s_addr;
emp->em_ena_idst.s_addr &= emp->em_ena_idmask.s_addr;
@@ -941,6 +999,20 @@ va_dcl
(struct sockaddr *) 0,
(struct sockaddr *) &encapnetmask, 0,
(struct rtentry **) 0);
+
+ if (emp->em_ena_flags & ENABLE_FLAG_MODIFY) {
+ encapgw.sen_len = SENT_IPSP_LEN;
+ encapgw.sen_family = AF_ENCAP;
+ encapgw.sen_type = SENT_IPSP;
+ encapgw.sen_ipsp_dst.s_addr = emp->em_ena_dst.s_addr;
+ encapgw.sen_ipsp_spi = htonl(1);
+ encapgw.sen_ipsp_sproto = IPPROTO_ESP;
+ error = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst,
+ (struct sockaddr *) &encapgw,
+ (struct sockaddr *) &encapnetmask,
+ RTF_UP | RTF_GATEWAY | RTF_STATIC,
+ (struct rtentry **) 0);
+ }
if (emp->em_ena_flags & ENABLE_FLAG_LOCAL)
{
@@ -953,6 +1025,20 @@ va_dcl
(struct sockaddr *) &encapnetmask, 0,
(struct rtentry **) 0);
+ if (emp->em_ena_flags & ENABLE_FLAG_MODIFY) {
+ encapgw.sen_len = SENT_IPSP_LEN;
+ encapgw.sen_family = AF_ENCAP;
+ encapgw.sen_type = SENT_IPSP;
+ encapgw.sen_ipsp_dst.s_addr = emp->em_ena_dst.s_addr;
+ encapgw.sen_ipsp_spi = htonl(1);
+ encapgw.sen_ipsp_sproto = IPPROTO_ESP;
+ error = rtrequest(RTM_ADD,
+ (struct sockaddr *) &encapdst,
+ (struct sockaddr *) &encapgw,
+ (struct sockaddr *) &encapnetmask,
+ RTF_UP | RTF_GATEWAY | RTF_STATIC,
+ (struct rtentry **) 0);
+ }
delete_flow(flow2, tdbp);
}
diff --git a/sys/net/encap.h b/sys/net/encap.h
index 6eabab45ed2..23ac0370b7a 100644
--- a/sys/net/encap.h
+++ b/sys/net/encap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: encap.h,v 1.12 1998/05/18 21:10:18 provos Exp $ */
+/* $OpenBSD: encap.h,v 1.13 1998/05/24 14:13:59 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -261,8 +261,9 @@ struct encap_msghdr
} Eu;
};
-#define ENABLE_FLAG_REPLACE 1
-#define ENABLE_FLAG_LOCAL 2
+#define ENABLE_FLAG_REPLACE 1 /* Replace existing flow with new */
+#define ENABLE_FLAG_LOCAL 2 /* Add routes for 0.0.0.0 */
+#define ENABLE_FLAG_MODIFY 4 /* Keep routing masks */
#define ENCAP_MSG_FIXED_LEN (2 * sizeof(u_int32_t))
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index bcb20a3b076..bf09aadbe69 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.28 1998/05/19 18:42:01 deraadt Exp $ */
+/* $OpenBSD: ip_output.c,v 1.29 1998/05/24 14:14:00 provos Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -82,6 +82,7 @@ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
#endif
#ifdef IPSEC
+extern void encap_sendnotify __P((int, struct tdb *, void *));
extern int ipsec_auth_default_level;
extern int ipsec_esp_trans_default_level;
extern int ipsec_esp_network_default_level;
@@ -241,6 +242,28 @@ ip_output(m0, va_alist)
goto bad;
}
+ /*
+ * For VPNs a route with a reserved SPI of 1 is used to
+ * indicate the need for an SA when none is established.
+ */
+ if (ntohl(gw->sen_ipsp_spi) == 0x1) {
+ struct tdb tmptdb;
+
+ sa_require = NOTIFY_SATYPE_CONF | NOTIFY_SATYPE_AUTH |
+ NOTIFY_SATYPE_TUNNEL;
+ tmptdb.tdb_dst.s_addr = gw->sen_ipsp_dst.s_addr;
+ tmptdb.tdb_satype = sa_require;
+
+ /* Request SA with key management */
+ encap_sendnotify(NOTIFY_REQUEST_SA, &tmptdb, NULL);
+
+ /*
+ * When sa_require is set, the packet will be dropped
+ * at no_encap.
+ */
+ goto no_encap;
+ }
+
ip->ip_len = htons((u_short)ip->ip_len);
ip->ip_off = htons((u_short)ip->ip_off);
ip->ip_sum = 0;
@@ -432,11 +455,9 @@ no_encap:
/* This is for possible future use, don't move or delete */
if (re->re_rt)
RTFREE(re->re_rt);
- /* We did no IPSec encapsulation but the socket required it */
- if (sa_require) {
- error = EHOSTUNREACH;
+ /* No IPSec processing though it was required, drop packet */
+ if (sa_require)
goto done;
- }
}
#endif /* IPSEC */