diff options
-rw-r--r-- | sys/kern/uipc_domain.c | 17 | ||||
-rw-r--r-- | sys/net/pfkey.c | 30 | ||||
-rw-r--r-- | sys/net/pfkeyv2.c | 73 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 8 | ||||
-rw-r--r-- | sys/netinet/ip_spd.c | 91 |
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, |