summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/uipc_domain.c17
-rw-r--r--sys/net/pfkey.c30
-rw-r--r--sys/net/pfkeyv2.c73
-rw-r--r--sys/netinet/ip_ipsp.h8
-rw-r--r--sys/netinet/ip_spd.c91
5 files changed, 116 insertions, 103 deletions
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 5ec1a8d3c1c..65cf5eadea0 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_domain.c,v 1.40 2015/03/14 03:38:51 jsg Exp $ */
+/* $OpenBSD: uipc_domain.c,v 1.41 2015/07/17 18:31:08 blambert Exp $ */
/* $NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $ */
/*
@@ -51,10 +51,6 @@ void pffasttimo(void *);
void pfslowtimo(void *);
struct domain * pffinddomain(int);
-#if defined (KEY) || defined (IPSEC) || defined (TCP_SIGNATURE)
-int pfkey_init(void);
-#endif /* KEY || IPSEC || TCP_SIGNATURE */
-
#define ADDDOMAIN(x) { \
extern struct domain __CONCAT(x,domain); \
__CONCAT(x,domain.dom_next) = domains; \
@@ -80,15 +76,10 @@ domaininit(void)
ADDDOMAIN(inet6);
#endif /* INET6 */
#if defined (KEY) || defined (IPSEC) || defined (TCP_SIGNATURE)
- pfkey_init();
-#endif /* KEY || IPSEC */
-#ifdef MPLS
- ADDDOMAIN(mpls);
-#endif
-#ifdef IPSEC
-#ifdef __KAME__
- ADDDOMAIN(key);
+ ADDDOMAIN(pfkey);
#endif
+#ifdef MPLS
+ ADDDOMAIN(mpls);
#endif
ADDDOMAIN(route);
diff --git a/sys/net/pfkey.c b/sys/net/pfkey.c
index fbced37f738..41ebf76d95a 100644
--- a/sys/net/pfkey.c
+++ b/sys/net/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.24 2014/12/09 07:05:06 doug Exp $ */
+/* $OpenBSD: pfkey.c,v 1.25 2015/07/17 18:31:08 blambert Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
@@ -90,7 +90,7 @@ static struct pfkey_version *pfkey_versions[PFKEY_PROTOCOL_MAX+1] =
struct sockaddr pfkey_addr = { 2, PF_KEY, };
-/* static struct domain pfkey_domain; */
+/* static struct domain pfkeydomain; */
static int pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
struct mbuf *nam, struct mbuf *control, struct proc *);
static int pfkey_output(struct mbuf *mbuf, struct socket *socket);
@@ -261,23 +261,23 @@ pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
return (rval);
}
-static struct domain pfkey_domain = {
+struct domain pfkeydomain = {
PF_KEY,
"PF_KEY",
- NULL, /* init */
+ pfkey_init, /* init */
NULL, /* externalize */
NULL, /* dispose */
NULL, /* protosw */
NULL, /* protoswNPROTOSW */
NULL, /* dom_next */
- rn_inithead, /* dom_rtattach */
+ NULL, /* dom_rtattach */
16, /* rtoffset */
sizeof(struct sockaddr_encap) /* maxrtkey */
};
static struct protosw pfkey_protosw_template = {
SOCK_RAW,
- &pfkey_domain,
+ &pfkeydomain,
-1, /* protocol */
PR_ATOMIC | PR_ADDR,
(void *) raw_input,
@@ -316,11 +316,11 @@ pfkey_buildprotosw(void)
p++;
}
- if (pfkey_domain.dom_protosw)
- free(pfkey_domain.dom_protosw, M_PFKEY, 0);
+ if (pfkeydomain.dom_protosw)
+ free(pfkeydomain.dom_protosw, M_PFKEY, 0);
- pfkey_domain.dom_protosw = protosw;
- pfkey_domain.dom_protoswNPROTOSW = p;
+ pfkeydomain.dom_protosw = protosw;
+ pfkeydomain.dom_protoswNPROTOSW = p;
} else {
if (!(protosw = malloc(sizeof(struct protosw), M_PFKEY,
M_DONTWAIT)))
@@ -329,11 +329,11 @@ pfkey_buildprotosw(void)
bcopy(&pfkey_protosw_template, protosw,
sizeof(struct protosw));
- if (pfkey_domain.dom_protosw)
- free(pfkey_domain.dom_protosw, M_PFKEY, 0);
+ if (pfkeydomain.dom_protosw)
+ free(pfkeydomain.dom_protosw, M_PFKEY, 0);
- pfkey_domain.dom_protosw = protosw;
- pfkey_domain.dom_protoswNPROTOSW = protosw;
+ pfkeydomain.dom_protosw = protosw;
+ pfkeydomain.dom_protoswNPROTOSW = protosw;
}
return (0);
@@ -345,7 +345,5 @@ pfkey_init(void)
if (pfkey_buildprotosw() != 0)
return;
- pfkey_domain.dom_next = domains;
- domains = &pfkey_domain;
pfkeyv2_init();
}
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index 54114e961dc..f7c0b261e10 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.144 2015/05/23 12:38:53 markus Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.145 2015/07/17 18:31:08 blambert Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
@@ -81,6 +81,7 @@
#include <net/route.h>
#include <netinet/ip_ipsp.h>
#include <net/pfkeyv2.h>
+#include <net/radix.h>
#include <netinet/ip_ah.h>
#include <netinet/ip_esp.h>
#include <netinet/ip_ipcomp.h>
@@ -92,7 +93,6 @@
#endif
#define PFKEYV2_PROTOCOL 2
-#define GETSPI_TRIES 10
/* Static globals */
static struct pfkeyv2_socket *pfkeyv2_sockets = NULL;
@@ -130,6 +130,8 @@ extern uint64_t sadb_exts_required_out[SADB_MAX+1];
extern struct pool ipsec_policy_pool;
+extern struct radix_node_head **spd_tables;
+
/*
* Wrapper around m_devget(); copy data from contiguous buffer to mbuf
* chain.
@@ -783,9 +785,11 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
{
int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST;
int delflag = 0, s;
- struct sockaddr_encap encapdst, encapnetmask, encapgw;
+ struct sockaddr_encap encapdst, encapnetmask;
struct ipsec_policy *ipo, *tmpipo;
struct ipsec_acquire *ipa;
+ struct radix_node_head *rnh;
+ struct radix_node *rn = NULL;
struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL;
@@ -1430,9 +1434,13 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
{
struct sadb_protocol *sab;
union sockaddr_union *ssrc;
- struct rtentry *rt;
int exists = 0;
+ if ((rnh = spd_table_add(rdomain)) == NULL) {
+ rval = ENOMEM;
+ goto ret;
+ }
+
sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE];
if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN) &&
@@ -1465,14 +1473,9 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]);
/* Determine whether the exact same SPD entry already exists. */
- bzero(&encapgw, sizeof(struct sockaddr_encap));
-
s = splsoftnet();
- rt = rtalloc((struct sockaddr *)&encapdst, RT_REPORT|RT_RESOLVE,
- rdomain);
- if (rt != NULL) {
- ipo = ((struct sockaddr_encap *)rt->rt_gateway)->sen_ipsp;
- rtfree(rt);
+ if ((rn = rn_match(&encapdst, rnh)) != NULL) {
+ ipo = (struct ipsec_policy *)rn;
/* Verify that the entry is identical */
if (bcmp(&ipo->ipo_addr, &encapdst,
@@ -1520,33 +1523,15 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
}
/* Allocate policy entry */
- ipo = pool_get(&ipsec_policy_pool, PR_NOWAIT);
+ ipo = pool_get(&ipsec_policy_pool, PR_NOWAIT|PR_ZERO);
if (ipo == NULL) {
splx(s);
rval = ENOMEM;
goto ret;
}
-
- bzero(ipo, sizeof(struct ipsec_policy));
- ipo->ipo_ref_count = 1;
- TAILQ_INIT(&ipo->ipo_acquires);
-
- /* Finish initialization of SPD entry */
- encapgw.sen_len = SENT_LEN;
- encapgw.sen_family = PF_KEY;
- encapgw.sen_type = SENT_IPSP;
- encapgw.sen_ipsp = ipo;
-
- /* Initialize policy entry */
- bcopy(&encapdst, &ipo->ipo_addr,
- sizeof(struct sockaddr_encap));
- bcopy(&encapnetmask, &ipo->ipo_mask,
- sizeof(struct sockaddr_encap));
-
- ipo->ipo_rdomain = rdomain;
}
- switch (((struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE])->sadb_protocol_proto) {
+ switch (sab->sadb_protocol_proto) {
case SADB_X_FLOW_TYPE_USE:
ipo->ipo_type = IPSP_IPSEC_USE;
break;
@@ -1620,18 +1605,21 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
/* Flow type */
if (!exists) {
+ /* Initialize policy entry */
+ bcopy(&encapdst, &ipo->ipo_addr,
+ sizeof(struct sockaddr_encap));
+ bcopy(&encapnetmask, &ipo->ipo_mask,
+ sizeof(struct sockaddr_encap));
+
+ TAILQ_INIT(&ipo->ipo_acquires);
+ ipo->ipo_rdomain = rdomain;
+ ipo->ipo_ref_count = 1;
+
/* Add SPD entry */
- struct rt_addrinfo info;
-
- bzero(&info, sizeof(info));
- info.rti_info[RTAX_DST] = (struct sockaddr *)&encapdst;
- info.rti_info[RTAX_GATEWAY] =
- (struct sockaddr *)&encapgw;
- info.rti_info[RTAX_NETMASK] =
- (struct sockaddr *)&encapnetmask;
- info.rti_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
- if ((rval = rtrequest1(RTM_ADD, &info, RTP_DEFAULT,
- NULL, rdomain)) != 0) {
+ if ((rnh = spd_table_get(rdomain)) == NULL ||
+ (rn = rn_addroute((caddr_t)&ipo->ipo_addr,
+ (caddr_t)&ipo->ipo_mask, rnh,
+ ipo->ipo_nodes, 0)) == NULL) {
/* Remove from linked list of policies on TDB */
if (ipo->ipo_tdb)
TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
@@ -1644,7 +1632,6 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
splx(s);
goto ret;
}
-
TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list);
ipsec_in_use++;
} else {
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 3ff6c2d64a5..27a3118ca5f 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.170 2015/05/23 12:38:53 markus Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.171 2015/07/17 18:31:08 blambert Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -51,6 +51,7 @@ struct m_tag;
#endif
#include <sys/queue.h>
#include <netinet/in.h>
+#include <net/radix.h>
union sockaddr_union {
struct sockaddr sa;
@@ -197,6 +198,7 @@ struct ipsec_acquire {
};
struct ipsec_policy {
+ struct radix_node ipo_nodes[2]; /* radix tree glue */
struct sockaddr_encap ipo_addr;
struct sockaddr_encap ipo_mask;
@@ -453,6 +455,10 @@ extern TAILQ_HEAD(ipsec_acquire_head, ipsec_acquire) ipsec_acquire_head;
const char *ipsp_address(union sockaddr_union *, char *, socklen_t);
#endif /* ENCDEBUG */
+/* SPD tables */
+struct radix_node_head *spd_table_add(unsigned int);
+struct radix_node_head *spd_table_get(unsigned int);
+
/* TDB management routines */
uint32_t reserve_spi(u_int, u_int32_t, u_int32_t, union sockaddr_union *,
union sockaddr_union *, u_int8_t, int *);
diff --git a/sys/netinet/ip_spd.c b/sys/netinet/ip_spd.c
index 1bd87d097e7..4bb02782ac1 100644
--- a/sys/netinet/ip_spd.c
+++ b/sys/netinet/ip_spd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_spd.c,v 1.85 2015/05/23 12:38:53 markus Exp $ */
+/* $OpenBSD: ip_spd.c,v 1.86 2015/07/17 18:31:08 blambert Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
*
@@ -26,6 +26,7 @@
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/socketvar.h>
+#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/pool.h>
#include <sys/timeout.h>
@@ -61,6 +62,55 @@ struct pool ipsec_acquire_pool;
int ipsec_policy_pool_initialized = 0;
int ipsec_acquire_pool_initialized = 0;
+struct radix_node_head **spd_tables;
+unsigned int spd_table_max;
+
+struct radix_node_head *
+spd_table_get(unsigned int rtableid)
+{
+ unsigned int rdomain;
+
+ if (spd_tables == NULL)
+ return (NULL);
+
+ rdomain = rtable_l2(rtableid);
+ if (rdomain > spd_table_max)
+ return (NULL);
+
+ return (spd_tables[rdomain]);
+}
+
+struct radix_node_head *
+spd_table_add(unsigned int rtableid)
+{
+ extern struct domain pfkeydomain;
+ struct radix_node_head *rnh = NULL;
+ unsigned int rdomain;
+ void *p;
+
+ rdomain = rtable_l2(rtableid);
+ if (spd_tables == NULL || rdomain > spd_table_max) {
+ if ((p = mallocarray(rdomain + 1, sizeof(*rnh),
+ M_RTABLE, M_NOWAIT|M_ZERO)) == NULL)
+ return (NULL);
+
+ if (spd_tables != NULL) {
+ bcopy(spd_tables, p, sizeof(*rnh) * (spd_table_max+1));
+ free(spd_tables, M_RTABLE, 0);
+ }
+ spd_tables = p;
+ spd_table_max = rdomain;
+ }
+
+ if (spd_tables[rdomain] == NULL) {
+ if (rn_inithead((void **)&rnh, pfkeydomain.dom_rtoffset) == 0)
+ rnh = NULL;
+ spd_tables[rdomain] = rnh;
+ }
+
+ return (spd_tables[rdomain]);
+}
+
/*
* Lookup at the SPD based on the headers contained on the mbuf. The second
* argument indicates what protocol family the header at the beginning of
@@ -80,7 +130,8 @@ struct tdb *
ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
struct tdb *tdbp, struct inpcb *inp, u_int32_t ipsecflowinfo)
{
- struct rtentry *rt;
+ struct radix_node_head *rnh;
+ struct radix_node *rn;
union sockaddr_union sdst, ssrc;
struct sockaddr_encap *ddst, dst;
struct ipsec_policy *ipo;
@@ -231,8 +282,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
}
/* Actual SPD lookup. */
- rt = rtalloc((struct sockaddr *)&dst, RT_REPORT|RT_RESOLVE, rdomain);
- if (rt == NULL) {
+ if ((rnh = spd_table_get(rdomain)) == NULL ||
+ (rn = rn_match((caddr_t)&dst, rnh)) == NULL) {
/*
* Return whatever the socket requirements are, there are no
* system-wide policies.
@@ -241,24 +292,7 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
return ipsp_spd_inp(m, af, hlen, error, direction,
tdbp, inp, NULL);
}
-
- /* Sanity check. */
- if ((rt->rt_gateway == NULL) ||
- (((struct sockaddr_encap *)rt->rt_gateway)->sen_type !=
- SENT_IPSP)) {
- rtfree(rt);
- *error = EHOSTUNREACH;
- DPRINTF(("ip_spd_lookup: no gateway in SPD entry!"));
- return NULL;
- }
-
- ipo = ((struct sockaddr_encap *)(rt->rt_gateway))->sen_ipsp;
- rtfree(rt);
- if (ipo == NULL) {
- *error = EHOSTUNREACH;
- DPRINTF(("ip_spd_lookup: no policy attached to SPD entry!"));
- return NULL;
- }
+ ipo = (struct ipsec_policy *)rn;
switch (ipo->ipo_type) {
case IPSP_PERMIT:
@@ -552,21 +586,18 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
int
ipsec_delete_policy(struct ipsec_policy *ipo)
{
- struct rt_addrinfo info;
struct ipsec_acquire *ipa;
+ struct radix_node_head *rnh;
+ struct radix_node *rn = (struct radix_node *)ipo;
int err = 0;
if (--ipo->ipo_ref_count > 0)
return 0;
/* Delete from SPD. */
- memset(&info, 0, sizeof(info));
- info.rti_info[RTAX_DST] = (struct sockaddr *)&ipo->ipo_addr;
- info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&ipo->ipo_mask;
-
- /* XXX other tables? */
- err = rtrequest1(RTM_DELETE, &info, RTP_DEFAULT, NULL,
- ipo->ipo_rdomain);
+ if ((rnh = spd_table_get(ipo->ipo_rdomain)) == NULL ||
+ rn_delete(&ipo->ipo_addr, &ipo->ipo_mask, rnh, rn) == NULL)
+ return (ESRCH);
if (ipo->ipo_tdb != NULL)
TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,