summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2003-12-02 23:16:30 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2003-12-02 23:16:30 +0000
commit7827007d3935fef762fc37ed47e44956982e543a (patch)
tree32503217eaf3f477211d64e2f795e83f59c1a618
parentefce987ff534832e2def76f49222eb98d59aefaa (diff)
UDP encapsulation for ESP in transport mode (draft-ietf-ipsec-udp-encaps-XX.txt)
ok deraadt@
-rw-r--r--sbin/ipsecadm/ipsecadm.87
-rw-r--r--sbin/ipsecadm/ipsecadm.c30
-rw-r--r--sbin/ipsecadm/pfkdump.c12
-rw-r--r--sbin/sysctl/sysctl.84
-rw-r--r--sys/net/pfkeyv2.c29
-rw-r--r--sys/net/pfkeyv2.h15
-rw-r--r--sys/net/pfkeyv2_convert.c25
-rw-r--r--sys/net/pfkeyv2_parsemessage.c18
-rw-r--r--sys/netinet/ip_esp.h15
-rw-r--r--sys/netinet/ip_ipsp.c9
-rw-r--r--sys/netinet/ip_ipsp.h6
-rw-r--r--sys/netinet/ipsec_input.c32
-rw-r--r--sys/netinet/ipsec_output.c31
-rw-r--r--sys/netinet/udp_usrreq.c43
-rw-r--r--usr.bin/netstat/inet.c7
15 files changed, 250 insertions, 33 deletions
diff --git a/sbin/ipsecadm/ipsecadm.8 b/sbin/ipsecadm/ipsecadm.8
index 75a09c0fe88..948efd103d0 100644
--- a/sbin/ipsecadm/ipsecadm.8
+++ b/sbin/ipsecadm/ipsecadm.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ipsecadm.8,v 1.62 2003/07/24 08:03:19 itojun Exp $
+.\" $OpenBSD: ipsecadm.8,v 1.63 2003/12/02 23:16:29 markus Exp $
.\"
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
.\" All rights reserved.
@@ -90,6 +90,7 @@ modifiers are:
.Fl authkey ,
.Fl authkeyfile ,
.Fl forcetunnel ,
+.Fl udpencap ,
.Fl key ,
and
.Fl keyfile .
@@ -382,6 +383,10 @@ and
options.
Notice that the IPsec stack will perform IP-inside-IP encapsulation
when deemed necessary, even if this flag has not been set.
+.It Fl udpencap
+Enable ESP-inside-UDP encapsulation.
+The UDP destination port must be specified on the command line.
+This port will be used for sending encapsulated UDP packets.
.It Fl enc
The encryption algorithm to be used with the SA.
Possible values are:
diff --git a/sbin/ipsecadm/ipsecadm.c b/sbin/ipsecadm/ipsecadm.c
index 08e24e36d67..f12c49e0896 100644
--- a/sbin/ipsecadm/ipsecadm.c
+++ b/sbin/ipsecadm/ipsecadm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecadm.c,v 1.70 2003/09/23 18:09:20 itojun Exp $ */
+/* $OpenBSD: ipsecadm.c,v 1.71 2003/12/02 23:16:29 markus Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -286,6 +286,7 @@ usage(void)
"\t -src <ip>\t\t\tsource address to be used\n"
"\t -halfiv\t\t\tuse 4-byte IV in old ESP\n"
"\t -forcetunnel\t\t\tforce IP-in-IP encapsulation\n"
+ "\t -udpencap <port>\t\tenable ESP-in-UDP encapsulation\n"
"\t -dst <ip>\t\t\tdestination address to be used\n"
"\t -proto <val>\t\t\tsecurity protocol\n"
"\t -proxy <ip>\t\t\tproxy address to be used\n"
@@ -309,7 +310,7 @@ usage(void)
"\t -dontacq\t\t\trequire, without using key mgmt.\n"
"\t -in\t\t\t\tspecify incoming-packet policy\n"
"\t -out\t\t\t\tspecify outgoing-packet policy\n"
- "\t -[ah|esp|ip4|ipcomp]\t\t\tflush a particular protocol\n"
+ "\t -[ah|esp|ip4|ipcomp]\t\tflush a particular protocol\n"
"\t -srcid\t\t\tsource identity for flows\n"
"\t -dstid\t\t\tdestination identity for flows\n"
"\t -srcid_type\t\t\tsource identity type\n"
@@ -345,6 +346,7 @@ main(int argc, char *argv[])
struct sadb_ident sid1, sid2;
struct sadb_key skey1, skey2;
struct sadb_protocol sprotocol, sprotocol2;
+ struct sadb_x_udpencap udpencap; /* Peer UDP Port */
u_char realkey[8192], realakey[8192];
struct iovec iov[30];
struct addrinfo hints, *res;
@@ -375,6 +377,7 @@ main(int argc, char *argv[])
memset(realakey, 0, sizeof(realakey));
memset(&sid1, 0, sizeof(sid1));
memset(&sid2, 0, sizeof(sid2));
+ memset(&udpencap, 0, sizeof(udpencap));
src = (union sockaddr_union *) srcbuf;
dst = (union sockaddr_union *) dstbuf;
@@ -921,6 +924,24 @@ main(int argc, char *argv[])
sa.sadb_sa_flags |= SADB_X_SAFLAGS_TUNNEL;
continue;
}
+ if (!strcmp(argv[i] + 1, "udpencap") &&
+ udpencap.sadb_x_udpencap_port == 0 && (i + 1 < argc)) {
+ if (!(mode & ESP_NEW)) {
+ fprintf(stderr, "%s: option udpencap can "
+ "be used only with new ESP\n", argv[0]);
+ exit(1);
+ }
+ sa.sadb_sa_flags |= SADB_X_SAFLAGS_UDPENCAP;
+ udpencap.sadb_x_udpencap_exttype = SADB_X_EXT_UDPENCAP;
+ udpencap.sadb_x_udpencap_len = sizeof(udpencap) / 8;
+ udpencap.sadb_x_udpencap_port =
+ strtoul(argv[i + 1], NULL, 10);
+ udpencap.sadb_x_udpencap_port =
+ htons(udpencap.sadb_x_udpencap_port);
+ udpencap.sadb_x_udpencap_reserved = 0;
+ i++;
+ continue;
+ }
if (!strcmp(argv[i] + 1, "halfiv")) {
if (!(mode & ESP_OLD)) {
fprintf(stderr,
@@ -1520,6 +1541,11 @@ argfail:
skey2.sadb_key_bits = 8 * alen;
smsg.sadb_msg_len += skey2.sadb_key_len;
}
+ if (sa.sadb_sa_flags & SADB_X_SAFLAGS_UDPENCAP) {
+ iov[cnt].iov_base = &udpencap;
+ iov[cnt++].iov_len = sizeof(udpencap);
+ smsg.sadb_msg_len += udpencap.sadb_x_udpencap_len;
+ }
} else {
switch (mode & CMD_MASK) {
case GRP_SPI:
diff --git a/sbin/ipsecadm/pfkdump.c b/sbin/ipsecadm/pfkdump.c
index 08853fe3655..3e9532a936a 100644
--- a/sbin/ipsecadm/pfkdump.c
+++ b/sbin/ipsecadm/pfkdump.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkdump.c,v 1.8 2003/07/29 18:38:36 deraadt Exp $ */
+/* $OpenBSD: pfkdump.c,v 1.9 2003/12/02 23:16:29 markus Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
@@ -52,6 +52,7 @@ void print_ident(struct sadb_ext *, struct sadb_msg *);
void print_policy(struct sadb_ext *, struct sadb_msg *);
void print_cred(struct sadb_ext *, struct sadb_msg *);
void print_auth(struct sadb_ext *, struct sadb_msg *);
+void print_udpenc(struct sadb_ext *, struct sadb_msg *);
struct idname *lookup(struct idname [], u_int8_t);
char *lookup_name(struct idname [], u_int8_t);
@@ -104,6 +105,7 @@ struct idname ext_types[] = {
{ SADB_X_EXT_LOCAL_AUTH, "x_local_auth", print_auth },
{ SADB_X_EXT_REMOTE_AUTH, "x_remote_auth", print_auth },
{ SADB_X_EXT_SUPPORTED_COMP, "x_supported_comp", print_supp },
+ { SADB_X_EXT_UDPENCAP, "x_udpencap", print_udpenc },
{ 0, NULL, NULL }
};
@@ -533,6 +535,14 @@ print_auth(struct sadb_ext *ext, struct sadb_msg *msg)
}
void
+print_udpenc(struct sadb_ext *ext, struct sadb_msg *msg)
+{
+ struct sadb_x_udpencap *x_udpencap = (struct sadb_x_udpencap *) ext;
+
+ printf("udpencap port %u\n", ntohs(x_udpencap->sadb_x_udpencap_port));
+}
+
+void
msg_send(int pfkey, u_int8_t satype, u_int8_t mtype)
{
struct sadb_msg msg;
diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8
index 32f748a6ee0..84737672388 100644
--- a/sbin/sysctl/sysctl.8
+++ b/sbin/sysctl/sysctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sysctl.8,v 1.109 2003/10/17 21:04:57 mcbride Exp $
+.\" $OpenBSD: sysctl.8,v 1.110 2003/12/02 23:16:29 markus Exp $
.\" $NetBSD: sysctl.8,v 1.4 1995/09/30 07:12:49 thorpej Exp $
.\"
.\" Copyright (c) 1993
@@ -240,6 +240,8 @@ privilege can change the value.
.It net.inet.gre.allow integer yes
.It net.inet.gre.wccp integer yes
.It net.inet.esp.enable integer yes
+.It net.inet.esp.udpencap integer yes
+.It net.inet.esp.udpencap_port integer yes
.It net.inet.ah.enable integer yes
.It net.inet.mobileip.allow integer yes
.It net.inet.etherip.allow integer yes
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index adb21e2f068..91ffab60299 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.89 2003/07/24 09:59:02 itojun Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.90 2003/12/02 23:16:29 markus Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
@@ -542,6 +542,9 @@ pfkeyv2_get(struct tdb *sa, void **headers, void **buffer)
if (sa->tdb_emxkey)
i+= PADUP(sa->tdb_emxkeylen) + sizeof(struct sadb_key);
+ if (sa->tdb_udpencap_port)
+ i+= sizeof(struct sadb_x_udpencap);
+
if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
rval = ENOMEM;
goto ret;
@@ -630,6 +633,12 @@ pfkeyv2_get(struct tdb *sa, void **headers, void **buffer)
export_key(&p, sa, PFKEYV2_ENCRYPTION_KEY);
}
+ /* Export UDP encapsulation port, if present */
+ if (sa->tdb_udpencap_port) {
+ headers[SADB_X_EXT_UDPENCAP] = p;
+ export_udpencap(&p, sa);
+ }
+
rval = 0;
ret:
@@ -895,6 +904,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
rval = EINVAL;
goto ret;
}
+ /* UDP encapsulation is only supported for ESP */
+ if (smsg->sadb_msg_satype != SADB_SATYPE_ESP &&
+ headers[SADB_X_EXT_UDPENCAP]) {
+ rval = EINVAL;
+ goto ret;
+ }
s = spltdb();
@@ -965,6 +980,8 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
headers[SADB_X_EXT_DST_MASK],
headers[SADB_X_EXT_PROTOCOL],
headers[SADB_X_EXT_FLOW_TYPE]);
+ import_udpencap(newsa,
+ headers[SADB_X_EXT_UDPENCAP]);
headers[SADB_EXT_KEY_AUTH] = NULL;
headers[SADB_EXT_KEY_ENCRYPT] = NULL;
@@ -1010,6 +1027,8 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
PFKEYV2_LIFETIME_SOFT);
import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD],
PFKEYV2_LIFETIME_HARD);
+ import_udpencap(sa2,
+ headers[SADB_X_EXT_UDPENCAP]);
}
splx(s);
@@ -1035,6 +1054,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
rval = EINVAL;
goto ret;
}
+ /* UDP encapsulation is only supported for ESP */
+ if (smsg->sadb_msg_satype != SADB_SATYPE_ESP &&
+ headers[SADB_X_EXT_UDPENCAP]) {
+ rval = EINVAL;
+ goto ret;
+ }
s = spltdb();
@@ -1111,6 +1136,8 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
headers[SADB_X_EXT_DST_MASK],
headers[SADB_X_EXT_PROTOCOL],
headers[SADB_X_EXT_FLOW_TYPE]);
+ import_udpencap(newsa,
+ headers[SADB_X_EXT_UDPENCAP]);
headers[SADB_EXT_KEY_AUTH] = NULL;
headers[SADB_EXT_KEY_ENCRYPT] = NULL;
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 152061fcc2b..91aed8ba4e5 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.h,v 1.48 2003/07/24 09:59:02 itojun Exp $ */
+/* $OpenBSD: pfkeyv2.h,v 1.49 2003/12/02 23:16:29 markus Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) January 1998
*
@@ -205,6 +205,13 @@ struct sadb_x_cred {
uint16_t sadb_x_cred_reserved;
};
+struct sadb_x_udpencap {
+ uint16_t sadb_x_udpencap_len;
+ uint16_t sadb_x_udpencap_exttype;
+ uint16_t sadb_x_udpencap_port;
+ uint16_t sadb_x_udpencap_reserved;
+};
+
#ifdef _KERNEL
#define SADB_X_GETSPROTO(x) \
( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
@@ -243,7 +250,8 @@ struct sadb_x_cred {
#define SADB_X_EXT_LOCAL_AUTH 28
#define SADB_X_EXT_REMOTE_AUTH 29
#define SADB_X_EXT_SUPPORTED_COMP 30
-#define SADB_EXT_MAX 30
+#define SADB_X_EXT_UDPENCAP 31
+#define SADB_EXT_MAX 31
/* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
#define SADB_SATYPE_UNSPEC 0
@@ -304,6 +312,7 @@ struct sadb_x_cred {
#define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */
#define SADB_X_SAFLAGS_RANDOMPADDING 0x080 /* Random ESP padding */
#define SADB_X_SAFLAGS_NOREPLAY 0x100 /* No replay counter */
+#define SADB_X_SAFLAGS_UDPENCAP 0x200 /* ESP in UDP */
#define SADB_X_POLICYFLAGS_POLICY 0x0001 /* This is a static policy */
@@ -421,6 +430,7 @@ void export_credentials(void **, struct tdb *, int);
void export_sa(void **, struct tdb *);
void export_key(void **, struct tdb *, int);
void export_auth(void **, struct tdb *, int);
+void export_udpencap(void **, struct tdb *);
void import_auth(struct tdb *, struct sadb_x_cred *, int);
void import_address(struct sockaddr *, struct sadb_address *);
@@ -432,5 +442,6 @@ void import_sa(struct tdb *, struct sadb_sa *, struct ipsecinit *);
void import_flow(struct sockaddr_encap *, struct sockaddr_encap *,
struct sadb_address *, struct sadb_address *, struct sadb_address *,
struct sadb_address *, struct sadb_protocol *, struct sadb_protocol *);
+void import_udpencap(struct tdb *, struct sadb_x_udpencap *);
#endif /* _KERNEL */
#endif /* _NET_PFKEY_V2_H_ */
diff --git a/sys/net/pfkeyv2_convert.c b/sys/net/pfkeyv2_convert.c
index b0026c9fd9a..14415c99eca 100644
--- a/sys/net/pfkeyv2_convert.c
+++ b/sys/net/pfkeyv2_convert.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2_convert.c,v 1.17 2003/07/24 09:59:02 itojun Exp $ */
+/* $OpenBSD: pfkeyv2_convert.c,v 1.18 2003/12/02 23:16:29 markus Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@keromytis.org)
*
@@ -135,6 +135,9 @@ import_sa(struct tdb *tdb, struct sadb_sa *sadb_sa, struct ipsecinit *ii)
if (sadb_sa->sadb_sa_flags & SADB_X_SAFLAGS_NOREPLAY)
tdb->tdb_flags |= TDBF_NOREPLAY;
+
+ if (sadb_sa->sadb_sa_flags & SADB_X_SAFLAGS_UDPENCAP)
+ tdb->tdb_flags |= TDBF_UDPENCAP;
}
if (sadb_sa->sadb_sa_state != SADB_SASTATE_MATURE)
@@ -794,3 +797,23 @@ export_key(void **p, struct tdb *tdb, int type)
*p += PADUP(tdb->tdb_amxkeylen);
}
}
+
+/* Import/Export remote port for UDP Encapsulation */
+void
+import_udpencap(struct tdb *tdb, struct sadb_x_udpencap *sadb_udpencap)
+{
+ if (sadb_udpencap)
+ tdb->tdb_udpencap_port = sadb_udpencap->sadb_x_udpencap_port;
+}
+
+void
+export_udpencap(void **p, struct tdb *tdb)
+{
+ struct sadb_x_udpencap *sadb_udpencap = (struct sadb_x_udpencap *) *p;
+
+ sadb_udpencap->sadb_x_udpencap_port = tdb->tdb_udpencap_port;
+ sadb_udpencap->sadb_x_udpencap_reserved = 0;
+ sadb_udpencap->sadb_x_udpencap_len =
+ sizeof(struct sadb_x_udpencap) / sizeof(uint64_t);
+ *p += sizeof(struct sadb_x_udpencap);
+}
diff --git a/sys/net/pfkeyv2_parsemessage.c b/sys/net/pfkeyv2_parsemessage.c
index 2659832b0d8..762d1159f75 100644
--- a/sys/net/pfkeyv2_parsemessage.c
+++ b/sys/net/pfkeyv2_parsemessage.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2_parsemessage.c,v 1.36 2003/02/16 21:30:13 deraadt Exp $ */
+/* $OpenBSD: pfkeyv2_parsemessage.c,v 1.37 2003/12/02 23:16:29 markus Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
@@ -121,6 +121,7 @@ extern int encdebug;
#define BITMAP_X_CREDENTIALS (BITMAP_X_LOCAL_CREDENTIALS | BITMAP_X_REMOTE_CREDENTIALS | BITMAP_X_LOCAL_AUTH | BITMAP_X_REMOTE_AUTH)
#define BITMAP_X_FLOW (BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE)
#define BITMAP_X_SUPPORTED_COMP (1 << SADB_X_EXT_SUPPORTED_COMP)
+#define BITMAP_X_UDPENCAP (1 << SADB_X_EXT_UDPENCAP)
uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
{
@@ -129,9 +130,9 @@ uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
/* GETSPI */
BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE,
/* UPDATE */
- BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW,
+ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP,
/* ADD */
- BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW,
+ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP,
/* DELETE */
BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
/* GET */
@@ -201,9 +202,9 @@ uint32_t sadb_exts_allowed_out[SADB_MAX+1] =
/* GETSPI */
BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
/* UPDATE */
- BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW,
+ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP,
/* ADD */
- BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW,
+ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP,
/* DELETE */
BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
/* GET */
@@ -919,6 +920,13 @@ pfkeyv2_parsemessage(void *p, int len, void **headers)
}
}
break;
+ case SADB_X_EXT_UDPENCAP:
+ if (i != sizeof(struct sadb_x_udpencap)) {
+ DPRINTF(("pfkeyv2_parsemessage: bad UDPENCAP "
+ "header length\n"));
+ return (EINVAL);
+ }
+ break;
default:
DPRINTF(("pfkeyv2_parsemessage: unknown extension "
"header type %d\n",
diff --git a/sys/netinet/ip_esp.h b/sys/netinet/ip_esp.h
index 6be3aafcf23..ba1098adaf7 100644
--- a/sys/netinet/ip_esp.h
+++ b/sys/netinet/ip_esp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.h,v 1.38 2003/02/12 14:41:07 jason Exp $ */
+/* $OpenBSD: ip_esp.h,v 1.39 2003/12/02 23:16:28 markus Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -61,21 +61,30 @@ struct espstat
u_int32_t esps_toobig; /* Packet got larger than IP_MAXPACKET */
u_int32_t esps_pdrops; /* Packet blocked due to policy */
u_int32_t esps_crypto; /* Crypto processing failure */
+ u_int32_t esps_udpencin; /* Input ESP-in-UDP packets */
+ u_int32_t esps_udpencout; /* Output ESP-in-UDP packets */
+ u_int32_t esps_udpinval; /* Invalid input ESP-in-UDP packets */
};
/*
* Names for ESP sysctl objects
*/
-#define ESPCTL_ENABLE 1 /* Enable ESP processing */
-#define ESPCTL_MAXID 2
+#define ESPCTL_ENABLE 1 /* Enable ESP processing */
+#define ESPCTL_UDPENCAP_ENABLE 2 /* Enable ESP over UDP */
+#define ESPCTL_UDPENCAP_PORT 3 /* UDP port for encapsulation */
+#define ESPCTL_MAXID 4
#define ESPCTL_NAMES { \
{ 0, 0 }, \
{ "enable", CTLTYPE_INT }, \
+ { "udpencap", CTLTYPE_INT }, \
+ { "udpencap_port", CTLTYPE_INT }, \
}
#ifdef _KERNEL
extern int esp_enable;
+extern int udpencap_enable;
+extern int udpencap_port;
extern struct espstat espstat;
#endif /* _KERNEL */
#endif /* _NETINET_IP_ESP_H_ */
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 74ce2e6af27..a8f7e85aea5 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.152 2003/05/09 14:59:19 deraadt Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.153 2003/12/02 23:16:28 markus Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -860,6 +860,7 @@ ipsp_print_tdb(struct tdb *tdb, char *buffer, size_t buflen)
{ "random padding", TDBF_RANDOMPADDING },
{ "skipcrypto", TDBF_SKIPCRYPTO },
{ "usedtunnel", TDBF_USEDTUNNEL },
+ { "udpencap", TDBF_UDPENCAP },
};
int l, i, k;
@@ -946,6 +947,12 @@ ipsp_print_tdb(struct tdb *tdb, char *buffer, size_t buflen)
"\tCrypto ID: %llu\n", tdb->tdb_cryptoid);
l += strlen(buffer + l);
+ if (tdb->tdb_udpencap_port) {
+ snprintf(buffer + l, buflen - l,
+ "\tudpencap_port = <%u>\n", ntohs(tdb->tdb_udpencap_port));
+ l += strlen(buffer + l);
+ }
+
if (tdb->tdb_xform) {
snprintf(buffer + l, buflen - l,
"\txform = <%s>\n",
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index dddb531052e..da6d442f186 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.123 2003/07/24 08:03:20 itojun Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.124 2003/12/02 23:16:29 markus Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -300,6 +300,7 @@ struct tdb { /* tunnel descriptor block */
#define TDBF_RANDOMPADDING 0x04000 /* Random data in the ESP padding */
#define TDBF_SKIPCRYPTO 0x08000 /* Skip actual crypto processing */
#define TDBF_USEDTUNNEL 0x10000 /* Appended a tunnel header in past */
+#define TDBF_UDPENCAP 0x20000 /* UDP encapsulation */
u_int32_t tdb_flags; /* Flags related to this TDB */
@@ -363,6 +364,8 @@ struct tdb { /* tunnel descriptor block */
u_int32_t tdb_mtu; /* MTU at this point in the chain */
u_int64_t tdb_mtutimeout; /* When to ignore this entry */
+ u_int16_t tdb_udpencap_port; /* Peer UDP port */
+
struct sockaddr_encap tdb_filter; /* What traffic is acceptable */
struct sockaddr_encap tdb_filtermask; /* And the mask */
@@ -646,6 +649,7 @@ extern struct tdb *ipsp_spd_lookup(struct mbuf *, int, int, int *, int,
struct tdb *, struct inpcb *);
extern struct tdb *ipsp_spd_inp(struct mbuf *, int, int, int *, int,
struct tdb *, struct inpcb *, struct ipsec_policy *);
+extern int ipsec_common_input(struct mbuf *, int, int, int, int, int);
extern int ipsec_common_input_cb(struct mbuf *, struct tdb *, int, int,
struct m_tag *);
extern int ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *,
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c
index d4282c826ab..39e7b157821 100644
--- a/sys/netinet/ipsec_input.c
+++ b/sys/netinet/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec_input.c,v 1.69 2003/07/28 10:10:16 markus Exp $ */
+/* $OpenBSD: ipsec_input.c,v 1.70 2003/12/02 23:16:29 markus Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -74,7 +74,6 @@
#include "bpfilter.h"
-int ipsec_common_input(struct mbuf *, int, int, int, int);
void *ipsec_common_ctlinput(int, struct sockaddr *, void *, int);
#ifdef ENCDEBUG
@@ -100,7 +99,8 @@ extern u_char ip6_protox[];
* filtering).
*/
int
-ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
+ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto,
+ int udpencap)
{
#define IPSEC_ISTAT(x,y,z) (sproto == IPPROTO_ESP ? (x)++ : \
sproto == IPPROTO_AH ? (y)++ : (z)++)
@@ -210,6 +210,14 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
return EINVAL;
}
+ if (udpencap && !(tdbp->tdb_flags & TDBF_UDPENCAP)) {
+ splx(s);
+ DPRINTF(("ipsec_common_input(): attempted to use non-udpencap SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
+ m_freem(m);
+ espstat.esps_udpinval++;
+ return EINVAL;
+ }
+
if (tdbp->tdb_xform == NULL) {
splx(s);
DPRINTF(("ipsec_common_input(): attempted to use uninitialized SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
@@ -227,7 +235,7 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
*/
m->m_pkthdr.rcvif = &encif[0].sc_if;
}
-
+
/* Register first use, setup expiration timer. */
if (tdbp->tdb_first_use == 0) {
int pri;
@@ -642,6 +650,10 @@ esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlen, void *newp,
switch (name[0]) {
case ESPCTL_ENABLE:
return sysctl_int(oldp, oldlen, newp, newlen, &esp_enable);
+ case ESPCTL_UDPENCAP_ENABLE:
+ return sysctl_int(oldp, oldlen, newp, newlen, &udpencap_enable);
+ case ESPCTL_UDPENCAP_PORT:
+ return sysctl_int(oldp, oldlen, newp, newlen, &udpencap_port);
default:
return ENOPROTOOPT;
}
@@ -695,7 +707,7 @@ ah4_input(struct mbuf *m, ...)
va_end(ap);
ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
- IPPROTO_AH);
+ IPPROTO_AH, 0);
return;
}
@@ -751,7 +763,7 @@ esp4_input(struct mbuf *m, ...)
va_end(ap);
ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
- IPPROTO_ESP);
+ IPPROTO_ESP, 0);
}
/* IPv4 ESP callback. */
@@ -793,7 +805,7 @@ ipcomp4_input(struct mbuf *m, ...)
va_end(ap);
ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
- IPPROTO_IPCOMP);
+ IPPROTO_IPCOMP, 0);
}
/* IPv4 IPCOMP callback */
@@ -940,7 +952,7 @@ ah6_input(struct mbuf **mp, int *offp, int proto)
}
protoff += offsetof(struct ip6_ext, ip6e_nxt);
}
- ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto);
+ ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
return IPPROTO_DONE;
}
@@ -1026,7 +1038,7 @@ esp6_input(struct mbuf **mp, int *offp, int proto)
}
protoff += offsetof(struct ip6_ext, ip6e_nxt);
}
- ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto);
+ ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
return IPPROTO_DONE;
}
@@ -1080,7 +1092,7 @@ ipcomp6_input(struct mbuf **mp, int *offp, int proto)
protoff += offsetof(struct ip6_ext, ip6e_nxt);
}
- ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto);
+ ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
return IPPROTO_DONE;
}
diff --git a/sys/netinet/ipsec_output.c b/sys/netinet/ipsec_output.c
index 95ea1b9a330..da7dcfb47b6 100644
--- a/sys/netinet/ipsec_output.c
+++ b/sys/netinet/ipsec_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec_output.c,v 1.27 2003/07/09 22:03:16 itojun Exp $ */
+/* $OpenBSD: ipsec_output.c,v 1.28 2003/12/02 23:16:29 markus Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
*
@@ -44,6 +44,7 @@
#include <netinet6/in6_var.h>
#endif /* INET6 */
+#include <netinet/udp.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ah.h>
#include <netinet/ip_esp.h>
@@ -56,6 +57,9 @@
#define DPRINTF(x)
#endif
+int udpencap_enable = 0; /* disabled by default */
+int udpencap_port = 4500; /* triggers decapsulation */
+
/*
* Loop over a tdb chain, taking into consideration protocol tunneling. The
* fourth argument is set if the first encapsulation header is already in
@@ -336,12 +340,35 @@ ipsp_process_done(struct mbuf *m, struct tdb *tdb)
tdb->tdb_last_used = time.tv_sec;
+ if (udpencap_enable && udpencap_port &&
+ (tdb->tdb_flags & TDBF_UDPENCAP) != 0) {
+ struct mbuf *mi;
+ struct udphdr *uh;
+
+ mi = m_inject(m, sizeof(struct ip), sizeof(struct udphdr),
+ M_DONTWAIT);
+ if (mi == NULL) {
+ m_freem(m);
+ return ENOMEM;
+ }
+ uh = mtod(mi, struct udphdr *);
+ uh->uh_sport = uh->uh_dport = htons(udpencap_port);
+ if (tdb->tdb_udpencap_port)
+ uh->uh_dport = tdb->tdb_udpencap_port;
+
+ uh->uh_ulen = htons(m->m_pkthdr.len - sizeof(struct ip));
+ uh->uh_sum = 0;
+ espstat.esps_udpencout++;
+ }
+
switch (tdb->tdb_dst.sa.sa_family) {
#ifdef INET
case AF_INET:
/* Fix the header length, for AH processing. */
ip = mtod(m, struct ip *);
ip->ip_len = htons(m->m_pkthdr.len);
+ if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
+ ip->ip_p = IPPROTO_UDP;
break;
#endif /* INET */
@@ -359,6 +386,8 @@ ipsp_process_done(struct mbuf *m, struct tdb *tdb)
}
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
+ if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
+ ip6->ip6_nxt = IPPROTO_UDP;
break;
#endif /* INET6 */
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 6a36106dafc..2d5aed4bbec 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.92 2003/11/04 21:43:16 markus Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.93 2003/12/02 23:16:29 markus Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -89,6 +89,11 @@
#include <netinet/udp.h>
#include <netinet/udp_var.h>
+#ifdef IPSEC
+#include <netinet/ip_ipsp.h>
+#include <netinet/ip_esp.h>
+#endif
+
#ifdef INET6
#ifndef INET
#include <netinet/in.h>
@@ -299,6 +304,42 @@ udp_input(struct mbuf *m, ...)
} else
udpstat.udps_nosum++;
+#ifdef IPSEC
+ if (udpencap_enable && udpencap_port &&
+ uh->uh_dport == htons(udpencap_port)) {
+ u_int32_t spi;
+ int skip = iphlen + sizeof(struct udphdr);
+
+ if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) {
+ /* packet too short */
+ m_freem(m);
+ return;
+ }
+ m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
+ /*
+ * decapsulate if the SPI is not zero, otherwise pass
+ * to userland
+ */
+ if (spi != 0) {
+ if ((m = m_pullup2(m, skip)) == NULL) {
+ udpstat.udps_hdrops++;
+ return;
+ }
+
+ /* remove the UDP header */
+ bcopy(mtod(m, u_char *),
+ mtod(m, u_char *) + sizeof(struct udphdr), iphlen);
+ m_adj(m, sizeof(struct udphdr));
+ skip -= sizeof(struct udphdr);
+
+ espstat.esps_udpencin++;
+ ipsec_common_input(m, skip, offsetof(struct ip, ip_p),
+ srcsa.sa.sa_family, IPPROTO_ESP, 1);
+ return;
+ }
+ }
+#endif
+
switch (srcsa.sa.sa_family) {
case AF_INET:
bzero(&srcsa, sizeof(struct sockaddr_in));
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index f21ac74069e..84b6ec9bd35 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inet.c,v 1.73 2003/11/07 23:38:48 mcbride Exp $ */
+/* $OpenBSD: inet.c,v 1.74 2003/12/02 23:16:29 markus Exp $ */
/* $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $ */
/*
@@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
#else
-static char *rcsid = "$OpenBSD: inet.c,v 1.73 2003/11/07 23:38:48 mcbride Exp $";
+static char *rcsid = "$OpenBSD: inet.c,v 1.74 2003/12/02 23:16:29 markus Exp $";
#endif
#endif /* not lint */
@@ -817,6 +817,9 @@ esp_stats(u_long off, char *name)
p(esps_invalid, "\t%u packet%s attempted to use an invalid TDB\n");
p(esps_toobig, "\t%u packet%s got larger than max IP packet size\n");
p(esps_crypto, "\t%u packet%s that failed crypto processing\n");
+ p(esps_udpencin, "\t%u input UDP encapsulated ESP packet%s\n");
+ p(esps_udpencout, "\t%u output UDP encapsulated ESP packet%s\n");
+ p(esps_udpinval, "\t%u UDP packet%s for non-encapsulating TDB received\n");
p(esps_ibytes, "\t%qu input byte%s\n");
p(esps_obytes, "\t%qu output byte%s\n");