diff options
author | Niels Provos <provos@cvs.openbsd.org> | 1998-05-24 14:14:01 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 1998-05-24 14:14:01 +0000 |
commit | 9144f8bae2a4f36a26def0448257c96f8f235aa7 (patch) | |
tree | 51451fb497fb6d7c903d24a27d36e32c40986486 | |
parent | c2b7ebe6a032e384693542e22ac0ffa5e3411777 (diff) |
add support for Virtual Private Networks (VPN).
-rw-r--r-- | sys/net/encap.c | 88 | ||||
-rw-r--r-- | sys/net/encap.h | 7 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 31 |
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 */ |