summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>1999-03-27 21:04:22 +0000
committerNiels Provos <provos@cvs.openbsd.org>1999-03-27 21:04:22 +0000
commitdefd96f785a6fc79d07307a2e69e27c048f432af (patch)
tree22a5f004782330ad329e92ec854e4f9bb9d51b5c
parentbdf0fa84baff8b71398e2760eb959d794df83839 (diff)
add SADB_X_BINDSA to pfkey allowing incoming SAs to refer to an outgoing
SA to be used, use this SA in ip_output if available. allow mobile road warriors for bind SAs with wildcard dst and src addresses. check IPSEC AUTH and ESP level when receiving packets, drop them if protection is insufficient. add stats to show dropped packets because of insufficient IPSEC protection. -- phew. this was all done in canada. dugsong and linh provided the ride and company.
-rw-r--r--sbin/ipsecadm/ipsecadm.c75
-rw-r--r--sys/net/pfkeyv2.c47
-rw-r--r--sys/net/pfkeyv2.h3
-rw-r--r--sys/net/pfkeyv2_parsemessage.c8
-rw-r--r--sys/netinet/in.h4
-rw-r--r--sys/netinet/in_pcb.c4
-rw-r--r--sys/netinet/in_pcb.h5
-rw-r--r--sys/netinet/ip_ah.c30
-rw-r--r--sys/netinet/ip_esp.c30
-rw-r--r--sys/netinet/ip_ipsp.c149
-rw-r--r--sys/netinet/ip_ipsp.h15
-rw-r--r--sys/netinet/ip_output.c85
-rw-r--r--sys/netinet/tcp_input.c52
-rw-r--r--sys/netinet/tcp_var.h3
-rw-r--r--sys/netinet/udp_usrreq.c39
-rw-r--r--sys/netinet/udp_var.h3
-rw-r--r--sys/sys/mbuf.h4
-rw-r--r--usr.bin/netstat/inet.c6
18 files changed, 461 insertions, 101 deletions
diff --git a/sbin/ipsecadm/ipsecadm.c b/sbin/ipsecadm/ipsecadm.c
index 9569cd0c9e0..3bea6f5f325 100644
--- a/sbin/ipsecadm/ipsecadm.c
+++ b/sbin/ipsecadm/ipsecadm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecadm.c,v 1.14 1999/03/15 15:37:02 deraadt Exp $ */
+/* $OpenBSD: ipsecadm.c,v 1.15 1999/03/27 21:04:18 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -72,6 +72,7 @@
#define DEL_SPI 0x30
#define GRP_SPI 0x40
#define FLOW 0x50
+#define BINDSA 0x60
#define ENC_IP 0x80
#define CMD_MASK 0xf0
@@ -176,7 +177,8 @@ void
usage()
{
fprintf(stderr, "usage: ipsecadm [command] <modifier...>\n"
- "\tCommands: new esp, old esp, new ah, old ah, group, delspi, ip4, flow\n"
+ "\tCommands: new esp, old esp, new ah, old ah, group, delspi, ip4\n"
+ "\t\t flow, bind\n"
"\tPossible modifiers:\n"
"\t -enc <alg>\t\t\t encryption algorithm\n"
"\t -auth <alg>\t\t\t authentication algorithm\n"
@@ -206,6 +208,7 @@ main(int argc, char **argv)
int dport = -1, sport = -1, tproto = -1;
u_int32_t spi = 0, spi2 = 0;
union sockaddr_union src, dst, dst2, osrc, odst, osmask, odmask, proxy;
+ int srcset = 0, dstset = 0, dst2set = 0;
u_char *keyp = NULL, *authp = NULL;
struct protoent *tp;
struct servent *svp;
@@ -346,28 +349,36 @@ main(int argc, char **argv)
i++;
}
else
- if (!strcmp(argv[1], "flow"))
+ if (!strcmp(argv[1], "bind"))
{
- /* It may not be ADDFLOW, but never mind that for now */
- smsg.sadb_msg_type = SADB_X_ADDFLOW;
- smsg.sadb_msg_satype = SADB_SATYPE_ESP;
- mode = FLOW;
+ smsg.sadb_msg_type = SADB_X_BINDSA;
+ smsg.sadb_msg_satype = SADB_SATYPE_ESP;
+ mode = BINDSA;
i++;
}
else
- if (!strcmp(argv[1], "ip4"))
+ if (!strcmp(argv[1], "flow"))
{
- mode = ENC_IP;
- smsg.sadb_msg_type = SADB_ADD;
- smsg.sadb_msg_satype = SADB_SATYPE_X_IPIP;
+ /* It may not be ADDFLOW, but never mind that for now */
+ smsg.sadb_msg_type = SADB_X_ADDFLOW;
+ smsg.sadb_msg_satype = SADB_SATYPE_ESP;
+ mode = FLOW;
i++;
}
else
- {
- fprintf(stderr, "%s: unknown command: %s", argv[0], argv[1]);
- exit(1);
- }
-
+ if (!strcmp(argv[1], "ip4"))
+ {
+ mode = ENC_IP;
+ smsg.sadb_msg_type = SADB_ADD;
+ smsg.sadb_msg_satype = SADB_SATYPE_X_IPIP;
+ i++;
+ }
+ else
+ {
+ fprintf(stderr, "%s: unknown command: %s", argv[0], argv[1]);
+ exit(1);
+ }
+
for (i++; i < argc; i++)
{
if (argv[i][0] != '-')
@@ -472,7 +483,7 @@ main(int argc, char **argv)
}
if (!strcmp(argv[i] + 1, "spi2") && spi2 == 0 &&
- iscmd(mode, GRP_SPI) && (i + 1 < argc))
+ (iscmd(mode, GRP_SPI) || iscmd(mode, BINDSA) && (i + 1 < argc))
{
if ((spi2 = htonl(strtoul(argv[i + 1], NULL, 16))) == 0)
{
@@ -489,7 +500,7 @@ main(int argc, char **argv)
{
src.sin.sin_family = AF_INET;
src.sin.sin_len = sizeof(struct sockaddr_in);
- src.sin.sin_addr.s_addr = inet_addr(argv[i + 1]);
+ srcset = inet_aton(argv[i + 1], &src.sin.sin_addr) != -1 ? 1 : 0;
sad1.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
sad1.sadb_address_len = 1 + sizeof(struct sockaddr_in) / 8;
i++;
@@ -674,27 +685,27 @@ main(int argc, char **argv)
sizeof(struct sockaddr_in)) / 8;
dst.sin.sin_family = AF_INET;
dst.sin.sin_len = sizeof(struct sockaddr_in);
- dst.sin.sin_addr.s_addr = inet_addr(argv[i + 1]);
+ dstset = inet_aton(argv[i + 1], &dst.sin.sin_addr) != -1 ? 1 : 0;
i++;
continue;
}
if (!strcmp(argv[i] + 1, "dst2") &&
- iscmd(mode, GRP_SPI) && (i + 1 < argc))
+ (iscmd(mode, GRP_SPI) || iscmd(mode, BINDSA) && (i + 1 < argc))
{
sad8.sadb_address_len = (sizeof(sad8) +
sizeof(struct sockaddr_in)) / 8;
sad8.sadb_address_exttype = SADB_EXT_X_DST2;
dst2.sin.sin_family = AF_INET;
dst2.sin.sin_len = sizeof(struct sockaddr_in);
- dst2.sin.sin_addr.s_addr = inet_addr(argv[i + 1]);
+ dst2set = inet_aton(argv[i + 1], &dst2.sin.sin_addr) != -1 ? 1 : 0;
i++;
continue;
}
if (!strcmp(argv[i] + 1, "proto") && (i + 1 < argc) &&
(iscmd(mode, FLOW) || iscmd(mode, GRP_SPI) ||
- iscmd(mode, DEL_SPI)))
+ iscmd(mode, DEL_SPI) || iscmd(mode, BINDSA)))
{
if (isalpha(argv[i + 1][0]))
{
@@ -855,36 +866,37 @@ main(int argc, char **argv)
exit(1);
}
- if (iscmd(mode, GRP_SPI) && spi2 == 0)
+ if ((iscmd(mode, GRP_SPI) || iscmd(mode, BINDSA)) && spi2 == 0)
{
fprintf(stderr, "%s: no SPI2 specified\n", argv[0]);
exit(1);
}
- if ((isencauth(mode) || iscmd(mode, ENC_IP)) &&
- src.sin.sin_addr.s_addr == 0)
+ if ((isencauth(mode) || iscmd(mode, ENC_IP)) && !srcset)
{
fprintf(stderr, "%s: no source address specified\n", argv[0]);
exit(1);
}
- if ((iscmd(mode, DEL_SPI) || iscmd(mode, GRP_SPI) || iscmd(mode, FLOW)) &&
- proto != IPPROTO_ESP && proto != IPPROTO_AH && proto != IPPROTO_IPIP)
+ if ((iscmd(mode, DEL_SPI) || iscmd(mode, GRP_SPI) || iscmd(mode, FLOW) ||
+ iscmd(mode, BINDSA)) && proto != IPPROTO_ESP &&
+ proto != IPPROTO_AH && proto != IPPROTO_IPIP)
{
fprintf(stderr, "%s: security protocol is none of AH, ESP or IPIP\n",
argv[0]);
exit(1);
}
- if (iscmd(mode, GRP_SPI) && proto2 != IPPROTO_ESP &&
- proto2 != IPPROTO_AH && proto2 != IPPROTO_IPIP)
+ if ((iscmd(mode, GRP_SPI) || iscmd(mode, BINDSA)) &&
+ proto2 != IPPROTO_ESP && proto2 != IPPROTO_AH &&
+ proto2 != IPPROTO_IPIP)
{
fprintf(stderr, "%s: security protocol2 is none of AH, ESP or IPIP\n",
argv[0]);
exit(1);
}
- if (dst.sin.sin_addr.s_addr == 0)
+ if (!dstset)
{
fprintf(stderr, "%s: no destination address for the SA specified\n",
argv[0]);
@@ -907,7 +919,7 @@ main(int argc, char **argv)
exit(1);
}
- if (iscmd(mode, GRP_SPI) && dst2.sin.sin_addr.s_addr == 0)
+ if ((iscmd(mode, GRP_SPI) || iscmd(mode, BINDSA)) && !dst2set)
{
fprintf(stderr, "%s: no destination address2 specified\n", argv[0]);
exit(1);
@@ -1005,6 +1017,7 @@ main(int argc, char **argv)
switch(mode & CMD_MASK)
{
case GRP_SPI:
+ case BINDSA:
/* SA header */
iov[cnt].iov_base = &sa;
iov[cnt++].iov_len = sizeof(sa);
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index b57ff0f9903..f0879bb1a96 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1339,6 +1339,53 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
break;
+ case SADB_X_BINDSA:
+ {
+ struct tdb *tdb1, *tdb2;
+
+ tdb1 = gettdb(((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_spi,
+ (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
+ sizeof(struct sadb_address)),
+ SADB_GETSPROTO(((struct sadb_msg *)headers[0])->sadb_msg_satype));
+ if (tdb1 == NULL) {
+ rval = ESRCH;
+ goto ret;
+ }
+
+ if (TAILQ_FIRST(&tdb1->tdb_bind_in)) {
+ /* Incoming SA has not list of referencing incoming SAs */
+ rval = EINVAL;
+ goto ret;
+ }
+
+ tdb2 = gettdb(((struct sadb_sa *)headers[SADB_EXT_X_SA2])->sadb_sa_spi,
+ (union sockaddr_union *)(headers[SADB_EXT_X_DST2] +
+ sizeof(struct sadb_address)),
+ SADB_GETSPROTO(((struct sadb_protocol *)headers[SADB_EXT_X_PROTOCOL])->sadb_protocol_proto));
+
+ if (tdb2 == NULL) {
+ rval = ESRCH;
+ goto ret;
+ }
+
+ if (tdb2->tdb_bind_out) {
+ /* Outgoing SA has no pointer to an outgoing SA */
+ rval = EINVAL;
+ goto ret;
+ }
+
+ /* Maintenance */
+ if (tdb1->tdb_bind_out)
+ TAILQ_REMOVE(&tdb1->tdb_bind_out->tdb_bind_in, tdb1,
+ tdb_bind_in_next);
+
+ /* Link them */
+ tdb1->tdb_bind_out = tdb2;
+ TAILQ_INSERT_TAIL(&tdb2->tdb_bind_in, tdb1, tdb_bind_in_next);
+ }
+
+ break;
+
case SADB_X_PROMISC:
if (len >= 2 * sizeof(struct sadb_msg)) {
struct mbuf *packet;
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 6945f81951e..7051fca9696 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -29,7 +29,8 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#define SADB_X_ADDFLOW 12
#define SADB_X_DELFLOW 13
#define SADB_X_GRPSPIS 14
-#define SADB_MAX 14
+#define SADB_X_BINDSA 15
+#define SADB_MAX 15
struct sadb_msg {
uint8_t sadb_msg_version;
diff --git a/sys/net/pfkeyv2_parsemessage.c b/sys/net/pfkeyv2_parsemessage.c
index 7c56c9823f5..46b83dedadf 100644
--- a/sys/net/pfkeyv2_parsemessage.c
+++ b/sys/net/pfkeyv2_parsemessage.c
@@ -88,6 +88,8 @@ uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
/* X_DELFLOW */
BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA,
/* X_GRPSPIS */
+ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_BINDSA */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
};
@@ -122,6 +124,8 @@ uint32_t sadb_exts_required_in[SADB_MAX+1] =
/* X_DELFLOW */
BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
/* X_GRPSPIS */
+ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_BINDSA */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
};
@@ -156,6 +160,8 @@ uint32_t sadb_exts_allowed_out[SADB_MAX+1] =
/* X_DELFLOW */
BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA,
/* X_GRPSPIS */
+ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_BINDSA */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
};
@@ -190,6 +196,8 @@ uint32_t sadb_exts_required_out[SADB_MAX+1] =
/* X_DELFLOW */
BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
/* X_GRPSPIS */
+ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_BINDSA */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
};
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 38bd73db826..d58c46f1bc5 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.20 1999/03/24 02:31:03 cmetz Exp $ */
+/* $OpenBSD: in.h,v 1.21 1999/03/27 21:04:21 provos Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -379,6 +379,8 @@ struct ip_opts {
#define ICMPV6_FILTER 38 /* struct icmpv6_filter; get/set filter */
#define ICMP6_FILTER ICMP6_FILTER
+#define IPSEC_OUTSA 39 /* set the outbound SA for a socket */
+
/*
* Security levels - IPsec, not IPSO
*/
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 23c656d635b..66fc00db939 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.31 1999/03/24 02:28:21 cmetz Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.32 1999/03/27 21:04:18 provos Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -529,6 +529,8 @@ in_pcbdetach(v)
ip_freemoptions(inp->inp_moptions);
#ifdef IPSEC
/* XXX IPsec cleanup here */
+ if (inp->inp_tdb)
+ TAILQ_REMOVE(&inp->inp_tdb->tdb_inp, inp, inp_tdb_next);
#endif
s = splnet();
LIST_REMOVE(inp, inp_hash);
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 176ce07a742..cb753c3ae82 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.h,v 1.16 1999/03/24 02:33:02 cmetz Exp $ */
+/* $OpenBSD: in_pcb.h,v 1.17 1999/03/27 21:04:19 provos Exp $ */
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */
/*
@@ -40,6 +40,7 @@
#include <netinet6/ipv6.h>
#include <netinet6/ipv6_var.h>
#include <netinet6/icmpv6.h>
+#include <netinet/ip_ipsp.h>
union inpaddru {
struct in6_addr iau_addr6;
@@ -99,6 +100,8 @@ struct inpcb {
#define SR_FAILED 1 /* Negotiation failed permanently */
#define SR_SUCCESS 2 /* SA successfully established */
#define SR_WAIT 3 /* Waiting for SA */
+ TAILQ_ENTRY(inpcb) inp_tdb_next;
+ struct tdb *inp_tdb; /* If tdb_dst matches our dst, use */
int inp_fflowinfo; /* Foreign flowlabel & priority */
int inp_csumoffset;
struct icmpv6_filter inp_filter;
diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c
index afa4cbe472b..4fdb5d29813 100644
--- a/sys/netinet/ip_ah.c
+++ b/sys/netinet/ip_ah.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.c,v 1.18 1999/02/24 23:45:46 angelos Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.19 1999/03/27 21:04:19 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -238,6 +238,32 @@ ah_input(register struct mbuf *m, int iphlen)
return;
}
+ if (ipo->ip_p == IPPROTO_TCP || ipo->ip_p == IPPROTO_UDP)
+ {
+ struct tdb_ident *tdbi = NULL;
+ if (tdbp->tdb_bind_out)
+ {
+ tdbi = m->m_pkthdr.tdbi;
+ if (!(m->m_flags & M_PKTHDR))
+ {
+ DPRINTF(("ah_input(): mbuf is not a packet header!\n"));
+ }
+ if (!tdbi || !(m->m_flags & (M_CONF|M_AUTH)))
+ MALLOC(tdbi, struct tdb_ident *, sizeof(struct tdb_ident),
+ M_TEMP, M_NOWAIT);
+
+ if (!tdbi)
+ goto no_mem;
+
+ tdbi->spi = tdbp->tdb_bind_out->tdb_spi;
+ tdbi->dst = tdbp->tdb_bind_out->tdb_dst;
+ tdbi->proto = tdbp->tdb_bind_out->tdb_sproto;
+ }
+
+ m->m_pkthdr.tdbi = tdbi;
+ no_mem:
+ }
+
/* Packet is authentic */
m->m_flags |= M_AUTH;
@@ -277,6 +303,8 @@ ah_input(register struct mbuf *m, int iphlen)
if (IF_QFULL(ifq))
{
IF_DROP(ifq);
+ if (m->m_pkthdr.tdbi)
+ free(m->m_pkthdr.tdbi, M_TEMP);
m_freem(m);
ahstat.ahs_qfull++;
splx(s);
diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c
index f2da8435264..b099bdd1579 100644
--- a/sys/netinet/ip_esp.c
+++ b/sys/netinet/ip_esp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.c,v 1.18 1999/02/24 23:45:49 angelos Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.19 1999/03/27 21:04:19 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -237,6 +237,32 @@ esp_input(register struct mbuf *m, int iphlen)
return;
}
+ if (ipo->ip_p == IPPROTO_TCP || ipo->ip_p == IPPROTO_UDP)
+ {
+ struct tdb_ident *tdbi = NULL;
+ if (tdbp->tdb_bind_out)
+ {
+ tdbi = m->m_pkthdr.tdbi;
+ if (!(m->m_flags & M_PKTHDR))
+ {
+ DPRINTF(("esp_input(): mbuf is not a packet header!\n"));
+ }
+ if (!tdbi || !(m->m_flags & (M_CONF|M_AUTH)))
+ MALLOC(tdbi, struct tdb_ident *, sizeof(struct tdb_ident),
+ M_TEMP, M_NOWAIT);
+
+ if (!tdbi)
+ goto no_mem;
+
+ tdbi->spi = tdbp->tdb_bind_out->tdb_spi;
+ tdbi->dst = tdbp->tdb_bind_out->tdb_dst;
+ tdbi->proto = tdbp->tdb_bind_out->tdb_sproto;
+ }
+
+ m->m_pkthdr.tdbi = tdbi;
+ no_mem:
+ }
+
/* Packet is confidental */
m->m_flags |= M_CONF;
@@ -276,6 +302,8 @@ esp_input(register struct mbuf *m, int iphlen)
if (IF_QFULL(ifq))
{
IF_DROP(ifq);
+ if (m->m_pkthdr.tdbi)
+ free(m->m_pkthdr.tdbi, M_TEMP);
m_freem(m);
espstat.esps_qfull++;
splx(s);
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 21ba455bca3..a6eef7e135a 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.38 1999/03/24 17:00:47 niklas Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.39 1999/03/27 21:04:19 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -184,6 +184,7 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr)
struct sockaddr_encap *dst;
u_int8_t sa_require, sa_have;
int error, i;
+ struct tdb *tdb = NULL;
if (inp == NULL || ((so = inp->inp_socket) == 0))
return (EINVAL);
@@ -191,59 +192,60 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr)
/* If IPSEC is not required just use what we got */
if (!(sa_require = inp->inp_secrequire))
return 0;
-
- bzero((caddr_t) re, sizeof(*re));
- dst = (struct sockaddr_encap *) &re->re_dst;
- dst->sen_family = PF_KEY;
- dst->sen_len = SENT_IP4_LEN;
- dst->sen_type = SENT_IP4;
- dst->sen_ip_src = inp->inp_laddr;
- dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ?
- inp->inp_faddr.s_addr : daddr;
- dst->sen_proto = so->so_proto->pr_protocol;
- switch (dst->sen_proto)
+
+ if (!inp->inp_tdb)
{
- case IPPROTO_UDP:
- case IPPROTO_TCP:
+ bzero((caddr_t) re, sizeof(*re));
+ dst = (struct sockaddr_encap *) &re->re_dst;
+ dst->sen_family = PF_KEY;
+ dst->sen_len = SENT_IP4_LEN;
+ dst->sen_type = SENT_IP4;
+ dst->sen_ip_src = inp->inp_laddr;
+ dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ?
+ inp->inp_faddr.s_addr : daddr;
+ dst->sen_proto = so->so_proto->pr_protocol;
+ switch (dst->sen_proto)
+ {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
dst->sen_sport = inp->inp_lport;
dst->sen_dport = inp->inp_fport;
break;
- default:
+ default:
dst->sen_sport = 0;
dst->sen_dport = 0;
- }
+ }
- /* Try to find a flow */
- rtalloc((struct route *) re);
+ /* Try to find a flow */
+ rtalloc((struct route *) re);
- if (re->re_rt != NULL)
- {
- struct tdb *tdb;
- struct sockaddr_encap *gw;
-
- gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway);
-
- if (gw->sen_type == SENT_IPSP) {
- sunion.sin.sin_family = AF_INET;
- sunion.sin.sin_len = sizeof(struct sockaddr_in);
- sunion.sin.sin_addr = gw->sen_ipsp_dst;
+ if (re->re_rt != NULL)
+ {
+ struct sockaddr_encap *gw;
- tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
- gw->sen_ipsp_sproto);
-
- SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb);
+ gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway);
+
+ if (gw->sen_type == SENT_IPSP) {
+ sunion.sin.sin_family = AF_INET;
+ sunion.sin.sin_len = sizeof(struct sockaddr_in);
+ sunion.sin.sin_addr = gw->sen_ipsp_dst;
+
+ tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
+ gw->sen_ipsp_sproto);
+ }
+ RTFREE(re->re_rt);
}
- else
- sa_have = 0;
-
- RTFREE(re->re_rt);
-
- /* Check if our requirements are met */
- if (!(sa_require & ~sa_have))
- return 0;
- }
- else
- sa_have = 0;
+ } else
+ tdb = inp->inp_tdb;
+
+ if (tdb) {
+ SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb);
+ } else
+ sa_have = 0;
+
+ /* Check if our requirements are met */
+ if (!(sa_require & ~sa_have))
+ return 0;
error = i = 0;
@@ -290,6 +292,24 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr)
}
/*
+ * Add an inpcb to the list of inpcb which reference this tdb directly.
+ */
+
+void
+tdb_add_inp(struct tdb *tdb, struct inpcb *inp)
+{
+ if (inp->inp_tdb) {
+ if (inp->inp_tdb == tdb)
+ return;
+ TAILQ_REMOVE(&inp->inp_tdb->tdb_inp, inp, inp_tdb_next);
+ }
+ inp->inp_tdb = tdb;
+ TAILQ_INSERT_TAIL(&tdb->tdb_inp, inp, inp_tdb_next);
+
+ DPRINTF(("tdb_add_inp: tdb: %p, inp: %p\n", tdb, inp));
+}
+
+/*
* Reserve an SPI; the SA is not valid yet though. Zero is reserved as
* an error return value. If tspi is not zero, we try to allocate that
* SPI.
@@ -659,6 +679,7 @@ tdb_delete(struct tdb *tdbp, int delchain)
{
u_int8_t *ptr = (u_int8_t *) &tdbp->tdb_dst;
struct tdb *tdbpp;
+ struct inpcb *inp;
u_int32_t hashval = tdbp->tdb_sproto + tdbp->tdb_spi, i;
for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++)
@@ -706,6 +727,24 @@ tdb_delete(struct tdb *tdbp, int delchain)
ipsec_in_use--;
}
+ /* Cleanup SA-Bindings */
+ for (tdbpp = TAILQ_FIRST(&tdbp->tdb_bind_in); tdbpp;
+ tdbpp = TAILQ_FIRST(&tdbp->tdb_bind_in))
+ {
+ TAILQ_REMOVE(&tdbpp->tdb_bind_in, tdbpp, tdb_bind_in_next);
+ tdbpp->tdb_bind_out = NULL;
+ }
+ /* Cleanup inp references */
+ for (inp = TAILQ_FIRST(&tdbp->tdb_inp); inp;
+ inp = TAILQ_FIRST(&tdbp->tdb_inp))
+ {
+ TAILQ_REMOVE(&tdbp->tdb_inp, inp, inp_tdb_next);
+ inp->inp_tdb = NULL;
+ }
+
+ if (tdbp->tdb_bind_out)
+ TAILQ_REMOVE(&tdbp->tdb_bind_out->tdb_bind_in, tdbp, tdb_bind_in_next);
+
/* removal of a larval SA should not remove the mature SA's expirations */
if ((tdbp->tdb_flags & TDBF_INVALID) == 0)
cleanup_expirations(&tdbp->tdb_dst, tdbp->tdb_spi, tdbp->tdb_sproto);
@@ -733,6 +772,10 @@ tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii)
tdbp->tdb_established = time.tv_sec;
tdbp->tdb_epoch = kernfs_epoch - 1;
+ /* Init Incoming SA-Binding Queues */
+ TAILQ_INIT(&tdbp->tdb_bind_in);
+ TAILQ_INIT(&tdbp->tdb_inp);
+
for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++)
if (xsp->xf_type == alg)
return (*(xsp->xf_init))(tdbp, xsp, ii);
@@ -752,7 +795,7 @@ ipsp_kern(int off, char **bufp, int len)
{
static char buffer[IPSEC_KERNFS_BUFSIZE];
struct flow *flow;
- struct tdb *tdb;
+ struct tdb *tdb, *tdbp;
int l, i;
if (off == 0)
@@ -866,6 +909,22 @@ ipsp_kern(int off, char **bufp, int len)
l += sprintf(buffer + l, "\t\tAuthentication = <%s>\n",
tdb->tdb_authalgxform->name);
+ if (tdb->tdb_bind_out)
+ l += sprintf(buffer + l,
+ "\tBound SA: SPI = %08x, "
+ "Destination = %s, Sproto = %u\n",
+ ntohl(tdb->tdb_bind_out->tdb_spi),
+ ipsp_address(tdb->tdb_bind_out->tdb_dst),
+ tdb->tdb_bind_out->tdb_sproto);
+ for (i = 0, tdbp = TAILQ_FIRST(&tdb->tdb_bind_in); tdbp;
+ tdbp = TAILQ_NEXT(tdbp, tdb_bind_in_next))
+ i++;
+
+ if (i > 0)
+ l += sprintf(buffer + l,
+ "\tReferenced by %d incoming SA%s\n",
+ i, i == 1 ? "" : "s");
+
if (tdb->tdb_onext)
l += sprintf(buffer + l,
"\tNext SA: SPI = %08x, "
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index f0048366b3c..e963410849f 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.27 1999/02/25 01:30:49 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.28 1999/03/27 21:04:19 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -43,6 +43,7 @@
*/
#include <sys/types.h>
+#include <sys/queue.h>
#include <netinet/in.h>
#include <sys/md5k.h>
#include <netinet/ip_sha1.h>
@@ -283,10 +284,21 @@ struct tdb /* tunnel descriptor block */
u_int16_t tdb_dstid_type;
struct flow *tdb_flow; /* Which flows use this SA */
+
+ struct tdb *tdb_bind_out; /* Outgoing SA to use */
+ TAILQ_HEAD(tdb_bind_head, tdb) tdb_bind_in;
+ TAILQ_ENTRY(tdb) tdb_bind_in_next; /* Refering Incoming SAs */
+ TAILQ_HEAD(tdb_inp_head, inpcb) tdb_inp;
};
#define TDB_HASHMOD 257
+struct tdb_ident {
+ u_int32_t spi;
+ union sockaddr_union dst;
+ u_int8_t proto;
+};
+
struct auth_hash {
int type;
char *name;
@@ -418,6 +430,7 @@ extern char *inet_ntoa4(struct in_addr);
extern char *ipsp_address(union sockaddr_union);
/* TDB management routines */
+extern void tdb_add_inp(struct tdb *tdb, struct inpcb *inp);
extern u_int32_t reserve_spi(u_int32_t, u_int32_t, union sockaddr_union *,
union sockaddr_union *, u_int8_t, int *);
extern struct tdb *gettdb(u_int32_t, union sockaddr_union *, u_int8_t);
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 311806ea3d8..0c0400c0c1a 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.43 1999/03/24 17:00:47 niklas Exp $ */
+/* $OpenBSD: ip_output.c,v 1.44 1999/03/27 21:04:20 provos Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -167,8 +167,7 @@ ip_output(m0, va_alist)
/*
* Check if the packet needs encapsulation
*/
- if ((ipsec_in_use != 0) &&
- !(flags & IP_ENCAPSULATED) &&
+ if (!(flags & IP_ENCAPSULATED) &&
(inp == NULL ||
(inp->inp_seclevel[SL_AUTH] != IPSEC_LEVEL_BYPASS ||
inp->inp_seclevel[SL_ESP_TRANS] != IPSEC_LEVEL_BYPASS ||
@@ -184,6 +183,20 @@ ip_output(m0, va_alist)
sa_require = inp->inp_secrequire;
bzero((caddr_t) re, sizeof(*re));
+
+ /* Check if there was a bound outgoing SA */
+ if (inp && inp->inp_tdb &&
+ (inp->inp_tdb->tdb_dst.sin.sin_addr.s_addr ==
+ INADDR_ANY ||
+ !bcmp(&inp->inp_tdb->tdb_dst.sin.sin_addr,
+ &ip->ip_dst, sizeof(ip->ip_dst)))) {
+ tdb = inp->inp_tdb;
+ goto have_tdb;
+ }
+
+ if (!ipsec_in_use)
+ goto no_encap;
+
ddst = (struct sockaddr_encap *) &re->re_dst;
ddst->sen_family = PF_KEY;
ddst->sen_len = SENT_IP4_LEN;
@@ -266,10 +279,6 @@ ip_output(m0, va_alist)
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;
-
/*
* At this point we have an IPSP "gateway" (tunnel) spec.
* Use the destination of the tunnel and the SPI to
@@ -284,6 +293,12 @@ ip_output(m0, va_alist)
tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
gw->sen_ipsp_sproto);
+ have_tdb:
+
+ ip->ip_len = htons((u_short)ip->ip_len);
+ ip->ip_off = htons((u_short)ip->ip_off);
+ ip->ip_sum = 0;
+
/*
* Now we check if this tdb has all the transforms which
* are requried by the socket or our default policy.
@@ -354,7 +369,8 @@ ip_output(m0, va_alist)
if (tdb->tdb_flags & TDBF_INVALID) {
DPRINTF(("ip_output(): attempt to use invalid SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), tdb->tdb_sproto));
m_freem(m);
- RTFREE(re->re_rt);
+ if (re->re_rt)
+ RTFREE(re->re_rt);
return ENXIO;
}
@@ -389,6 +405,8 @@ ip_output(m0, va_alist)
/* Check for tunneling */
if (((tdb->tdb_dst.sin.sin_addr.s_addr !=
+ INADDR_ANY &&
+ tdb->tdb_dst.sin.sin_addr.s_addr !=
ip->ip_dst.s_addr) ||
(tdb->tdb_flags & TDBF_TUNNELING)) &&
(tdb->tdb_xform->xf_type != XF_IP4))
@@ -404,7 +422,8 @@ ip_output(m0, va_alist)
if (mp == NULL)
error = EFAULT;
if (error) {
- RTFREE(re->re_rt);
+ if (re->re_rt)
+ RTFREE(re->re_rt);
return error;
}
m = mp;
@@ -427,7 +446,8 @@ ip_output(m0, va_alist)
if (error) {
if (mp != NULL)
m_freem(mp);
- RTFREE(re->re_rt);
+ if (re->re_rt)
+ RTFREE(re->re_rt);
return error;
}
@@ -444,7 +464,8 @@ ip_output(m0, va_alist)
* processed packet. Call ourselves recursively, but
* bypass the encap code.
*/
- RTFREE(re->re_rt);
+ if (re->re_rt)
+ RTFREE(re->re_rt);
ip = mtod(m, struct ip *);
NTOHS(ip->ip_len);
NTOHS(ip->ip_off);
@@ -953,6 +974,28 @@ ip_ctloutput(op, so, level, optname, mp)
}
}
break;
+ case IPSEC_OUTSA:
+#ifndef IPSEC
+ error = EINVAL;
+#else
+ if (m == 0 || m->m_len != sizeof(struct tdb_ident)) {
+ error = EINVAL;
+ break;
+ } else {
+ struct tdb *tdb;
+ struct tdb_ident *tdbi;
+
+ tdbi = mtod(m, struct tdb_ident *);
+ tdb = gettdb(tdbi->spi, &tdbi->dst,
+ tdbi->proto);
+ if (tdb == NULL) {
+ error = ESRCH;
+ break;
+ }
+ tdb_add_inp(tdb, inp);
+ }
+#endif /* IPSEC */
+ break;
case IP_AUTH_LEVEL:
case IP_ESP_TRANS_LEVEL:
@@ -1082,6 +1125,26 @@ ip_ctloutput(op, so, level, optname, mp)
*mtod(m, int *) = optval;
break;
+ case IPSEC_OUTSA:
+#ifndef IPSEC
+ error = EINVAL;
+#else
+ if (inp->inp_tdb == NULL) {
+ error = ENOENT;
+ break;
+ } else {
+ struct tdb_ident tdbi;
+ tdbi.spi = inp->inp_tdb->tdb_spi;
+ tdbi.dst = inp->inp_tdb->tdb_dst;
+ tdbi.proto = inp->inp_tdb->tdb_sproto;
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(tdbi);
+ bcopy((caddr_t)&tdbi, mtod(m, caddr_t),
+ (unsigned)m->m_len);
+ }
+#endif /* IPSEC */
+ break;
+
case IP_AUTH_LEVEL:
case IP_ESP_TRANS_LEVEL:
case IP_ESP_NETWORK_LEVEL:
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 1bb0da1d16e..59086ee521b 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.32 1999/02/15 02:39:02 provos Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.33 1999/03/27 21:04:20 provos Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -77,6 +77,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <machine/stdarg.h>
#include <sys/md5k.h>
+#ifdef IPSEC
+#include <netinet/ip_ipsp.h>
+#endif /* IPSEC */
+
#ifdef INET6
#include <sys/domain.h>
#include <netinet6/in6_var.h>
@@ -437,6 +441,9 @@ tcp_input(m, va_alist)
int iphlen;
va_list ap;
register struct tcphdr *th;
+#ifdef IPSEC
+ struct tdb *tdb = NULL;
+#endif /* IPSEC */
#ifdef INET6
struct in6_addr laddr6;
unsigned short is_ipv6; /* Type of incoming datagram. */
@@ -449,6 +456,15 @@ tcp_input(m, va_alist)
tcpstat.tcps_rcvtotal++;
+#ifdef IPSEC
+ /* Save the last SA which was used to process the mbuf */
+ if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) {
+ struct tdb_ident *tdbi = m->m_pkthdr.tdbi;
+ tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
+ free(m->m_pkthdr.tdbi, M_TEMP);
+ m->m_pkthdr.tdbi = NULL;
+ }
+#endif /* IPSEC */
#ifdef INET6
/*
* Before we do ANYTHING, we have to figure out if it's TCP/IPv6 or
@@ -683,6 +699,18 @@ findpcb:
* we're committed to it below in TCPS_LISTEN.
*/
dropsocket++;
+#ifdef IPSEC
+ /*
+ * We need to copy the required security levels
+ * from the old pcb.
+ */
+ {
+ struct inpcb *newinp = (struct inpcb *)so->so_pcb;
+ bcopy(inp->inp_seclevel, newinp->inp_seclevel,
+ sizeof(inp->inp_seclevel));
+ newinp->inp_secrequire = inp->inp_secrequire;
+ }
+#endif /* IPSEC */
#ifdef INET6
/*
* inp still has the OLD in_pcb stuff, set the
@@ -748,6 +776,28 @@ findpcb:
}
}
+#ifdef IPSEC
+ /* Check if this socket requires security for incoming packets */
+ if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE &&
+ !(m->m_flags & M_AUTH)) ||
+ (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE &&
+ !(m->m_flags & M_CONF))) {
+#ifdef notyet
+#ifdef INET6
+ if (is_ipv6)
+ ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0);
+ else
+#endif /* INET6 */
+ icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0);
+#endif /* notyet */
+ tcpstat.tcps_rcvnosec++;
+ goto drop;
+ }
+ /* Use tdb_bind_out for this inp's outbound communication */
+ if (tdb)
+ tdb_add_inp(tdb, inp);
+#endif /*IPSEC */
+
/*
* Segment received on connection.
* Reset idle time and keep-alive timer.
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index c4c1b2213ec..f7ac9a841b3 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.18 1999/02/04 16:12:13 deraadt Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.19 1999/03/27 21:04:21 provos Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -244,6 +244,7 @@ struct tcpstat {
u_int32_t tcps_rcvbadsum; /* packets received with ccksum errs */
u_int32_t tcps_rcvbadoff; /* packets received with bad offset */
u_int32_t tcps_rcvmemdrop; /* packets dropped for lack of memory */
+ u_int32_t tcps_rcvnosec; /* packets dropped for lack of ipsec */
u_int32_t tcps_rcvshort; /* packets received too short */
u_int32_t tcps_rcvduppack; /* duplicate-only packets received */
u_int64_t tcps_rcvdupbyte; /* duplicate-only bytes received */
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 48805a76134..ce04a080ad8 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.24 1999/03/24 02:59:06 cmetz Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.25 1999/03/27 21:04:20 provos Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -76,6 +76,8 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet/udp_var.h>
#ifdef IPSEC
+#include <netinet/ip_ipsp.h>
+
extern int check_ipsec_policy __P((struct inpcb *, u_int32_t));
#endif
@@ -147,6 +149,9 @@ udp_input(m, va_alist)
struct ipv6 *ipv6;
struct sockaddr_in6 src_v4mapped;
#endif /* INET6 */
+#ifdef IPSEC
+ struct tdb *tdb = NULL;
+#endif /* IPSEC */
va_start(ap, m);
iphlen = va_arg(ap, int);
@@ -154,6 +159,16 @@ udp_input(m, va_alist)
udpstat.udps_ipackets++;
+#ifdef IPSEC
+ /* Save the last SA which was used to process the mbuf */
+ if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) {
+ struct tdb_ident *tdbi = m->m_pkthdr.tdbi;
+ tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
+ free(m->m_pkthdr.tdbi, M_TEMP);
+ m->m_pkthdr.tdbi = NULL;
+ }
+#endif /* IPSEC */
+
switch (mtod(m, struct ip *)->ip_v) {
case 4:
ip = mtod(m, struct ip *);
@@ -485,6 +500,28 @@ udp_input(m, va_alist)
}
}
+#ifdef IPSEC
+ /* Check if this socket requires security for incoming packets */
+ if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE &&
+ !(m->m_flags & M_AUTH)) ||
+ (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE &&
+ !(m->m_flags & M_CONF))) {
+#ifdef notyet
+#ifdef INET6
+ if (ipv6)
+ ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0);
+ else
+#endif /* INET6 */
+ icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0);
+#endif /* notyet */
+ udpstat.udps_nosec++;
+ goto bad;
+ }
+ /* Use tdb_bind_out for this inp's outbound communication */
+ if (tdb)
+ tdb_add_inp(tdb, inp);
+#endif /*IPSEC */
+
if (inp->inp_flags & INP_CONTROLOPTS) {
struct mbuf **mp = &opts;
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index f41b8aa10b5..afc23036d32 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_var.h,v 1.7 1999/02/04 16:05:02 deraadt Exp $ */
+/* $OpenBSD: udp_var.h,v 1.8 1999/03/27 21:04:21 provos Exp $ */
/* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */
/*
@@ -62,6 +62,7 @@ struct udpstat {
u_long udps_badlen; /* data length larger than packet */
u_long udps_noport; /* no socket on port */
u_long udps_noportbcast; /* of above, arrived as broadcast */
+ u_long udps_nosec; /* dropped for lack of ipsec */
u_long udps_fullsock; /* not delivered, input socket full */
u_long udps_pcbhashmiss; /* input packets missing pcb hash */
/* output statistics: */
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index e02ebf70f95..62ba4bdc873 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mbuf.h,v 1.9 1999/01/07 22:33:31 deraadt Exp $ */
+/* $OpenBSD: mbuf.h,v 1.10 1999/03/27 21:04:21 provos Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
@@ -80,6 +80,8 @@ struct m_hdr {
struct pkthdr {
struct ifnet *rcvif; /* rcv interface */
int len; /* total packet length */
+ void *tdbi; /* pointer to struct tdb_ident */
+ /* XXX - pull in ip_ipsp.h */
};
/* description of external storage mapped into mbuf, valid if M_EXT set */
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 2ce10641a2d..9f56f9f41c0 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inet.c,v 1.30 1999/02/24 22:57:34 angelos Exp $ */
+/* $OpenBSD: inet.c,v 1.31 1999/03/27 21:04:21 provos Exp $ */
/* $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
#else
-static char *rcsid = "$OpenBSD: inet.c,v 1.30 1999/02/24 22:57:34 angelos Exp $";
+static char *rcsid = "$OpenBSD: inet.c,v 1.31 1999/03/27 21:04:21 provos Exp $";
#endif
#endif /* not lint */
@@ -226,6 +226,7 @@ tcp_stats(off, name)
p(tcps_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n");
p(tcps_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n");
p(tcps_rcvshort, "\t\t%ld discarded because packet too short\n");
+ p(tcps_rcvnosec, "\t\t%ld discarded for missing IPSec protection\n");
p(tcps_connattempt, "\t%ld connection request%s\n");
p(tcps_accepts, "\t%ld connection accept%s\n");
p(tcps_connects, "\t%ld connection%s established (including accepts)\n");
@@ -273,6 +274,7 @@ udp_stats(off, name)
p(udps_nosum, "\t%lu with no checksum\n");
p(udps_noport, "\t%lu dropped due to no socket\n");
p(udps_noportbcast, "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
+ p(udps_nosec, "\t%lu dropped due to missing IPSec protection\n");
p(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
delivered = udpstat.udps_ipackets -
udpstat.udps_hdrops -