diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-09-19 03:19:40 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-09-19 03:19:40 +0000 |
commit | af73df8e49a73ae51c26612cdf39434cf2ae6a75 (patch) | |
tree | 35973a72331245a21b88055374040b9758c65b7f /sys/net | |
parent | 5534a5937914c47ce35c34ef3e6aeba61aa79e11 (diff) |
SPD-driven IPsec.
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/pfkey.c | 1 | ||||
-rw-r--r-- | sys/net/pfkeyv2.c | 942 | ||||
-rw-r--r-- | sys/net/pfkeyv2.h | 31 | ||||
-rw-r--r-- | sys/net/pfkeyv2_parsemessage.c | 43 |
4 files changed, 400 insertions, 617 deletions
diff --git a/sys/net/pfkey.c b/sys/net/pfkey.c index 4c78bcb2401..8ece8974018 100644 --- a/sys/net/pfkey.c +++ b/sys/net/pfkey.c @@ -27,6 +27,7 @@ you didn't get a copy, you may request one from <license@inner.net>. #include <sys/proc.h> #include <net/route.h> #include <netinet/in.h> +#include <netinet/ip_ipsp.h> #include <net/pfkeyv2.h> #include <sys/protosw.h> diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 76b707eafd7..d89afc980d9 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.c,v 1.38 2000/08/24 22:51:29 fgsch Exp $ */ +/* $OpenBSD: pfkeyv2.c,v 1.39 2000/09/19 03:19:39 angelos Exp $ */ /* %%% copyright-nrl-97 This software is Copyright 1997-1998 by Randall Atkinson, Ronald Lee, @@ -28,8 +28,8 @@ you didn't get a copy, you may request one from <license@inner.net>. #include <sys/proc.h> #include <net/route.h> #include <netinet/in.h> -#include <net/pfkeyv2.h> #include <netinet/ip_ipsp.h> +#include <net/pfkeyv2.h> #include <netinet/ip_ah.h> #include <netinet/ip_esp.h> #include <crypto/blf.h> @@ -50,9 +50,9 @@ static struct sadb_alg ealgs[] = { { SADB_EALG_DESCBC, 64, 64, 64 }, { SADB_EALG_3DESCBC, 64, 192, 192 }, - { SADB_X_EALG_BLF, 64, 5, BLF_MAXKEYLEN}, - { SADB_X_EALG_CAST, 64, 5, 16}, - { SADB_X_EALG_SKIPJACK, 64, 10, 10}, + { SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8}, + { SADB_X_EALG_CAST, 64, 40, 128}, + { SADB_X_EALG_SKIPJACK, 64, 80, 80}, }; static struct sadb_alg aalgs[] = @@ -66,6 +66,7 @@ void export_address(void **, struct sockaddr *); void export_identity(void **, struct tdb *, int); void export_lifetime(void **, struct tdb *, int); void export_sa(void **, struct tdb *); +void export_key(void **, struct tdb *, int); void import_address(struct sockaddr *, struct sadb_address *); void import_identity(struct tdb *, struct sadb_ident *, int); @@ -492,7 +493,7 @@ import_identity(struct tdb *tdb, struct sadb_ident *sadb_ident, int type) tdb->tdb_srcid_type = sadb_ident->sadb_ident_type; MALLOC(tdb->tdb_srcid, u_int8_t *, tdb->tdb_srcid_len, M_XDATA, M_WAITOK); - bcopy((void *)sadb_ident + sizeof(struct sadb_ident), + bcopy((void *) sadb_ident + sizeof(struct sadb_ident), tdb->tdb_srcid, tdb->tdb_srcid_len); } else @@ -502,7 +503,7 @@ import_identity(struct tdb *tdb, struct sadb_ident *sadb_ident, int type) tdb->tdb_dstid_type = sadb_ident->sadb_ident_type; MALLOC(tdb->tdb_dstid, u_int8_t *, tdb->tdb_dstid_len, M_XDATA, M_WAITOK); - bcopy((void *)sadb_ident + sizeof(struct sadb_ident), + bcopy((void *) sadb_ident + sizeof(struct sadb_ident), tdb->tdb_dstid, tdb->tdb_dstid_len); } } @@ -553,6 +554,33 @@ import_key(struct ipsecinit *ii, struct sadb_key *sadb_key, int type) } } +void +export_key(void **p, struct tdb *tdb, int type) +{ + struct sadb_key *sadb_key = (struct sadb_key *) *p; + + if (type == PFKEYV2_ENCRYPTION_KEY) + { + sadb_key->sadb_key_len = (sizeof(struct sadb_key) + + PADUP(tdb->tdb_emxkeylen)) / + sizeof(uint64_t); + sadb_key->sadb_key_bits = tdb->tdb_emxkeylen * 8; + *p += sizeof(struct sadb_key); + bcopy(tdb->tdb_emxkey, *p, tdb->tdb_emxkeylen); + *p += PADUP(tdb->tdb_emxkeylen); + } + else + { + sadb_key->sadb_key_len = (sizeof(struct sadb_key) + + PADUP(tdb->tdb_amxkeylen)) / + sizeof(uint64_t); + sadb_key->sadb_key_bits = tdb->tdb_amxkeylen * 8; + *p += sizeof(struct sadb_key); + bcopy(tdb->tdb_amxkey, *p, tdb->tdb_amxkeylen); + *p += PADUP(tdb->tdb_amxkeylen); + } +} + /* * Send a PFKEYv2 message, possibly to many receivers, based on the * satype of the socket (which is set by the REGISTER message), and the @@ -654,11 +682,10 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket, { /* Check for specified satype */ if ((1 << satype) & s->registration) - if (count-- == 0) - { /* Done */ - pfkey_sendup(s->socket, packet, 1); - break; - } + { /* Done */ + pfkey_sendup(s->socket, packet, 1); + break; + } } } @@ -804,7 +831,19 @@ pfkeyv2_get(struct tdb *sa, void **headers, void **buffer) export_identity(&p, sa, PFKEYV2_IDENTITY_DST); } - /* XXX Export keys ? */ + /* Export authentication key, if present */ + if (sa->tdb_amxkey) + { + headers[SADB_EXT_KEY_AUTH] = p; + export_key(&p, sa, PFKEYV2_AUTHENTICATION_KEY); + } + + /* Export encryption key, if present */ + if (sa->tdb_emxkey) + { + headers[SADB_EXT_KEY_ENCRYPT] = p; + export_key(&p, sa, PFKEYV2_ENCRYPTION_KEY); + } rval = 0; @@ -853,7 +892,7 @@ pfkeyv2_flush_walker(struct tdb *sa, void *satype_vp) { if (!(*((u_int8_t *) satype_vp)) || sa->tdb_satype == *((u_int8_t *) satype_vp)) - tdb_delete(sa, 0, 0); + tdb_delete(sa, 0); return 0; } @@ -874,7 +913,7 @@ pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg) *sproto = IPPROTO_AH; - if(alg != NULL) + if(alg != NULL) *alg = satype = XF_AH; break; @@ -922,6 +961,8 @@ int pfkeyv2_send(struct socket *socket, void *message, int len) { int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST, delflag = 0, s; + struct sockaddr_encap encapdst, encapnetmask, encapgw; + struct ipsec_policy *ipo; struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL; @@ -931,7 +972,6 @@ pfkeyv2_send(struct socket *socket, void *message, int len) union sockaddr_union *sunionp; struct tdb sa, *sa2 = NULL; - struct flow *flow = NULL; struct sadb_msg *smsg; struct sadb_spirange *sprng; @@ -1109,33 +1149,15 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if (rval) { rval = EINVAL; - tdb_delete(freeme, 0, TDBEXP_TIMEOUT); + tdb_delete(freeme, TDBEXP_TIMEOUT); freeme = NULL; goto splxret; } newsa->tdb_cur_allocations = sa2->tdb_cur_allocations; - /* Copy outgoing flows and ACL */ - newsa->tdb_flow = sa2->tdb_flow; - newsa->tdb_access = sa2->tdb_access; - - /* Fix flow backpointers to the TDB */ - for (flow = newsa->tdb_flow; - flow != NULL; - flow = flow->flow_next) - flow->flow_sa = newsa; - - for (flow = newsa->tdb_access; - flow != NULL; - flow = flow->flow_next) - flow->flow_sa = newsa; - - sa2->tdb_access = NULL; - sa2->tdb_flow = NULL; - /* Delete old version of the SA, insert new one */ - tdb_delete(sa2, 0, TDBEXP_TIMEOUT); + tdb_delete(sa2, TDBEXP_TIMEOUT); puttdb((struct tdb *) freeme); sa2 = freeme = NULL; } @@ -1241,7 +1263,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if (rval) { rval = EINVAL; - tdb_delete(freeme, 0, TDBEXP_TIMEOUT); + tdb_delete(freeme, TDBEXP_TIMEOUT); freeme = NULL; goto splxret; } @@ -1269,8 +1291,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) goto splxret; } - tdb_delete(sa2, ssa->sadb_sa_flags & SADB_X_SAFLAGS_CHAINDEL, - TDBEXP_TIMEOUT); + tdb_delete(sa2, TDBEXP_TIMEOUT); splx(s); @@ -1343,28 +1364,14 @@ pfkeyv2_send(struct socket *socket, void *message, int len) case SADB_FLUSH: rval = 0; + s = spltdb(); + while ((ipo = TAILQ_FIRST(&ipsec_policy_head)) != NULL) + ipsec_delete_policy(ipo); + splx(s); + switch(smsg->sadb_msg_satype) { case SADB_SATYPE_UNSPEC: - case SADB_X_SATYPE_BYPASS: - { - union sockaddr_union dst; - /* XXX IPv4 dependency -- does it matter though ? */ - dst.sin.sin_family = AF_INET; - dst.sin.sin_len = sizeof(struct sockaddr_in); - dst.sin.sin_addr.s_addr = INADDR_ANY; - - s = spltdb(); - - sa2 = gettdb(SPI_LOCAL_USE, &dst, IPPROTO_IP); - if (sa2 != NULL) - tdb_delete(sa2, 0, 0); - - if (smsg->sadb_msg_satype == SADB_X_SATYPE_BYPASS) - break; - /* for SADB_SATYPE_UNSPEC, fall through */ - } - case SADB_SATYPE_AH: case SADB_SATYPE_ESP: case SADB_X_SATYPE_IPIP: @@ -1375,15 +1382,14 @@ pfkeyv2_send(struct socket *socket, void *message, int len) tdb_walk(pfkeyv2_flush_walker, (u_int8_t *) &(smsg->sadb_msg_satype)); + + splx(s); break; default: rval = EINVAL; /* Unknown/unsupported type */ } - if (rval == 0) - goto splxret; - break; case SADB_DUMP: @@ -1407,14 +1413,27 @@ pfkeyv2_send(struct socket *socket, void *message, int len) case SADB_X_ADDFLOW: { - struct sockaddr_encap encapdst, encapgw, encapnetmask; - struct flow *flow2 = NULL, *old_flow = NULL, *old_flow2 = NULL; - union sockaddr_union *src, *dst, *srcmask, *dstmask; - u_int8_t sproto = 0, replace, ingress ; - struct rtentry *rt; - + union sockaddr_union *src, *dst, *srcmask, *dstmask, *ssrc; + struct route_enc re; + u_int8_t transproto = 0; + u_int8_t direction; + int exists = 0; + struct tdb *ktdb; + + direction = (((struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE])->sadb_protocol_direction); + if ((direction != IPSP_DIRECTION_IN) && + (direction != IPSP_DIRECTION_OUT)) + { + rval = EINVAL; + goto ret; + } + ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; + /* If the security protocol wasn't specified, pretend it was ESP */ + if (smsg->sadb_msg_satype == 0) + smsg->sadb_msg_satype = SADB_SATYPE_ESP; + if (headers[SADB_EXT_ADDRESS_DST]) sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] + @@ -1422,18 +1441,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len) else sunionp = NULL; - /* - * SADB_X_SAFLAGS_REPLACEFLOW set means we should remove any - * potentially conflicting egress flow while we are adding this - * new one. - */ - replace = ssa->sadb_sa_flags & SADB_X_SAFLAGS_REPLACEFLOW; - ingress = ssa->sadb_sa_flags & SADB_X_SAFLAGS_INGRESS_FLOW; - if ((replace && delflag) || (replace && ingress)) - { - rval = EINVAL; - goto ret; - } + if (headers[SADB_EXT_ADDRESS_SRC]) + ssrc = (union sockaddr_union *) + (headers[SADB_EXT_ADDRESS_SRC] + + sizeof(struct sadb_address)); + else + ssrc = NULL; src = (union sockaddr_union *) (headers[SADB_X_EXT_SRC_FLOW] + sizeof(struct sadb_address)); @@ -1453,415 +1466,250 @@ pfkeyv2_send(struct socket *socket, void *message, int len) (src->sa.sa_family != dstmask->sa.sa_family)) { rval = EINVAL; - goto splxret; + goto ret; } bzero(&encapdst, sizeof(struct sockaddr_encap)); bzero(&encapnetmask, sizeof(struct sockaddr_encap)); bzero(&encapgw, sizeof(struct sockaddr_encap)); - + + /* Transport protocol specified ? */ if (headers[SADB_X_EXT_PROTOCOL]) - sproto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL])->sadb_protocol_proto; - else - sproto = 0; + transproto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL])->sadb_protocol_proto; /* Generic netmask handling, works for IPv4 and IPv6 */ rt_maskedcopy(&src->sa, &src->sa, &srcmask->sa); rt_maskedcopy(&dst->sa, &dst->sa, &dstmask->sa); - s = spltdb(); - - if (!delflag || ingress) - { - if ((ssa == NULL) || (sunionp == NULL)) - { - rval = EINVAL; - goto splxret; - } - - /* Find the relevant SA */ - sa2 = gettdb(ssa->sadb_sa_spi, sunionp, - SADB_GETSPROTO(smsg->sadb_msg_satype)); - - if (sa2 == NULL) - { - rval = ESRCH; - goto splxret; - } - } - - /* For non-ingress flows... */ - if (!ingress) - { - /* - * ...if the requested flow already exists and we aren't - * asked to replace or delete it, or if it doesn't exist - * and we're asked to delete it, fail. - */ - flow = find_global_flow(src, srcmask, dst, dstmask, sproto); - if (!replace && - ((delflag && (flow == NULL)) || - (!delflag && (flow != NULL)))) - { - rval = delflag ? ESRCH : EEXIST; - goto splxret; - } - } - - /* If we're not deleting a flow, add in the TDB */ - if (!delflag) - { - if (replace) - old_flow = flow; - - flow = get_flow(); - bcopy(src, &flow->flow_src, src->sa.sa_len); - bcopy(dst, &flow->flow_dst, dst->sa.sa_len); - bcopy(srcmask, &flow->flow_srcmask, srcmask->sa.sa_len); - bcopy(dstmask, &flow->flow_dstmask, dstmask->sa.sa_len); - flow->flow_proto = sproto; - put_flow(flow, sa2, ingress); - - /* If this is an ACL entry, we're done */ - if (ingress) - { - splx(s); - break; - } - } - else - if (ingress) - { - /* If we're deleting an ingress flow... */ - flow = find_flow(src, srcmask, dst, dstmask, sproto, - sa2, FLOW_INGRESS); - if (flow == NULL) - { - rval = ESRCH; - goto splxret; - } - - delete_flow(flow, sa2, FLOW_INGRESS); - splx(s); - break; - } - /* Setup the encap fields */ - encapdst.sen_family = PF_KEY; - switch (flow->flow_src.sa.sa_family) + encapdst.sen_family = encapnetmask.sen_family = PF_KEY; + encapdst.sen_len = encapnetmask.sen_len = SENT_LEN; + + switch (src->sa.sa_family) { #ifdef INET case AF_INET: - encapdst.sen_len = SENT_IP4_LEN; encapdst.sen_type = SENT_IP4; - encapdst.sen_ip_src = flow->flow_src.sin.sin_addr; - encapdst.sen_ip_dst = flow->flow_dst.sin.sin_addr; - encapdst.sen_proto = flow->flow_proto; - encapdst.sen_sport = flow->flow_src.sin.sin_port; - encapdst.sen_dport = flow->flow_dst.sin.sin_port; - - encapnetmask.sen_len = SENT_IP4_LEN; - encapnetmask.sen_family = PF_KEY; - encapnetmask.sen_type = SENT_IP4; - encapnetmask.sen_ip_src = flow->flow_srcmask.sin.sin_addr; - encapnetmask.sen_ip_dst = flow->flow_dstmask.sin.sin_addr; - if (flow->flow_proto) - { - encapnetmask.sen_proto = 0xff; - - if (flow->flow_src.sin.sin_port) - encapnetmask.sen_sport = 0xffff; + encapdst.sen_direction = direction; + encapdst.sen_ip_src = src->sin.sin_addr; + encapdst.sen_ip_dst = dst->sin.sin_addr; + encapdst.sen_proto = transproto; + encapdst.sen_sport = src->sin.sin_port; + encapdst.sen_dport = dst->sin.sin_port; - if (flow->flow_dst.sin.sin_port) - encapnetmask.sen_dport = 0xffff; - } + encapnetmask.sen_type = SENT_IP4; + encapnetmask.sen_direction = 0xff; + encapnetmask.sen_ip_src = srcmask->sin.sin_addr; + encapnetmask.sen_ip_dst = dstmask->sin.sin_addr; + encapnetmask.sen_sport = srcmask->sin.sin_port; + encapnetmask.sen_dport = dstmask->sin.sin_port; + if (transproto) + encapnetmask.sen_proto = 0xff; break; #endif /* INET */ #ifdef INET6 case AF_INET6: - encapdst.sen_len = SENT_IP6_LEN; encapdst.sen_type = SENT_IP6; - encapdst.sen_ip6_src = flow->flow_src.sin6.sin6_addr; - encapdst.sen_ip6_dst = flow->flow_dst.sin6.sin6_addr; - encapdst.sen_ip6_proto = flow->flow_proto; - encapdst.sen_ip6_sport = flow->flow_src.sin6.sin6_port; - encapdst.sen_ip6_dport = flow->flow_dst.sin6.sin6_port; - - encapnetmask.sen_len = SENT_IP6_LEN; - encapnetmask.sen_family = PF_KEY; - encapnetmask.sen_type = SENT_IP6; - encapnetmask.sen_ip6_src = - flow->flow_srcmask.sin6.sin6_addr; - encapnetmask.sen_ip6_dst = - flow->flow_dstmask.sin6.sin6_addr; - if (flow->flow_proto) - { - encapnetmask.sen_ip6_proto = 0xff; + encapdst.sen_ip6_direction = direction; + encapdst.sen_ip6_src = src->sin6.sin6_addr; + encapdst.sen_ip6_dst = dst->sin6.sin6_addr; + encapdst.sen_ip6_proto = transproto; + encapdst.sen_ip6_sport = src->sin6.sin6_port; + encapdst.sen_ip6_dport = dst->sin6.sin6_port; - if (flow->flow_src.sin6.sin6_port) - encapnetmask.sen_ip6_sport = 0xffff; - - if (flow->flow_dst.sin6.sin6_port) - encapnetmask.sen_ip6_dport = 0xffff; - } + encapnetmask.sen_type = SENT_IP6; + encapnetmask.sen_ip6_direction = 0xff; + encapnetmask.sen_ip6_src = srcmask->sin6.sin6_addr; + encapnetmask.sen_ip6_dst = dstmask->sin6.sin6_addr; + encapnetmask.sen_ip6_sport = srcmask->sin6.sin6_port; + encapnetmask.sen_ip6_dport = dstmask->sin6.sin6_port; + if (transproto) + encapnetmask.sen_ip6_proto = 0xff; break; #endif /* INET6 */ } - if (!delflag) - { - switch (sa2->tdb_dst.sa.sa_family) - { -#ifdef INET - case AF_INET: - encapgw.sen_len = SENT_IPSP_LEN; - encapgw.sen_family = PF_KEY; - encapgw.sen_type = SENT_IPSP; - encapgw.sen_ipsp_dst = sa2->tdb_dst.sin.sin_addr; - encapgw.sen_ipsp_spi = sa2->tdb_spi; - encapgw.sen_ipsp_sproto = sa2->tdb_sproto; - - break; -#endif /* INET */ + /* Determine whether the exact same SPD entry already exists. */ + bzero(&re, sizeof(struct route_enc)); + bcopy(&encapdst, &re.re_dst, sizeof(struct sockaddr_encap)); + rtalloc((struct route *) &re); -#if INET6 - case AF_INET6: - encapgw.sen_len = SENT_IPSP6_LEN; - encapgw.sen_family = PF_KEY; - encapgw.sen_type = SENT_IPSP6; - encapgw.sen_ipsp6_dst = sa2->tdb_dst.sin6.sin6_addr; - encapgw.sen_ipsp6_spi = sa2->tdb_spi; - encapgw.sen_ipsp6_sproto = sa2->tdb_sproto; - - break; -#endif /* INET6 */ - - default: - /* - * This shouldn't ever happen really, as SAs - * should be checked at establishment time. - */ - rval = EPFNOSUPPORT; - delete_flow(flow, flow->flow_sa, FLOW_EGRESS); - goto splxret; - } + if (re.re_rt != NULL) + { + ipo = ((struct sockaddr_encap *) re.re_rt->rt_gateway)->sen_ipsp; + RTFREE(re.re_rt); + + /* Verify that the entry is identical */ + if (bcmp(&ipo->ipo_addr, &encapdst, + sizeof(struct sockaddr_encap)) || + bcmp(&ipo->ipo_mask, &encapnetmask, + sizeof(struct sockaddr_encap))) + ipo = NULL; /* Fall through */ + else + exists = 1; } + else + ipo = NULL; - /* Add the entry in the routing table */ + /* Delete ? */ if (delflag) { - rtrequest(RTM_DELETE, (struct sockaddr *) &encapdst, - (struct sockaddr *) 0, - (struct sockaddr *) &encapnetmask, - 0, (struct rtentry **) 0); - - delete_flow(flow, flow->flow_sa, FLOW_EGRESS); - } - else if (!replace) - { - rval = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst, - (struct sockaddr *) &encapgw, - (struct sockaddr *) &encapnetmask, - RTF_UP | RTF_GATEWAY | RTF_STATIC, - (struct rtentry **) 0); - - if (rval) + if (exists) { - delete_flow(flow, sa2, FLOW_EGRESS); - - if (flow2) - delete_flow(flow2, sa2, FLOW_EGRESS); - - goto splxret; + s = spltdb(); + rval = ipsec_delete_policy(ipo); + splx(s); + goto ret; } - sa2->tdb_cur_allocations++; + /* If we were asked to delete something non-existant, error */ + rval = ESRCH; + break; } - else - { - rt = (struct rtentry *) rn_lookup(&encapdst, &encapnetmask, - rt_tables[PF_KEY]); - if (rt == NULL) - { - rval = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst, - (struct sockaddr *) &encapgw, - (struct sockaddr *) &encapnetmask, - RTF_UP | RTF_GATEWAY | RTF_STATIC, - (struct rtentry **) 0); - - if (rval) - { - delete_flow(flow, sa2, FLOW_EGRESS); - if (flow2) - delete_flow(flow2, sa2, FLOW_EGRESS); - - goto splxret; - } - } - else if (rt_setgate(rt, rt_key(rt), - (struct sockaddr *) &encapgw)) + if (!exists) + { + /* Allocate policy entry */ + MALLOC(ipo, struct ipsec_policy *, sizeof(struct ipsec_policy), + M_TDB, M_NOWAIT); + if (ipo == NULL) { rval = ENOMEM; - delete_flow(flow, sa2, FLOW_EGRESS); - - if (flow2) - delete_flow(flow2, sa2, FLOW_EGRESS); - - goto splxret; + goto ret; } - sa2->tdb_cur_allocations++; - } + bzero(ipo, sizeof(struct ipsec_policy)); - if (replace) - { - if (old_flow != NULL) - delete_flow(old_flow, old_flow->flow_sa, FLOW_EGRESS); + /* Finish initialization of SPD entry */ + encapgw.sen_len = SENT_LEN; + encapgw.sen_family = PF_KEY; + encapgw.sen_type = SENT_IPSP; + encapgw.sen_ipsp = ipo; - if (old_flow2 != NULL) - delete_flow(old_flow2, old_flow2->flow_sa, FLOW_EGRESS); + /* Initialize policy entry */ + bcopy(&encapdst, &ipo->ipo_addr, + sizeof(struct sockaddr_encap)); + bcopy(&encapnetmask, &ipo->ipo_mask, + sizeof(struct sockaddr_encap)); } - /* If we are adding flows, check for allocation expirations */ - if (!delflag && !(replace && old_flow != NULL)) + /* + * A direct "hint" was provided, try to locate TDB. If we + * don't find it, return an error, since it was expected + * that we'd be able to find the TDB. Be careful with any + * previously pointed to TDB. + */ + if (ssa && ssa->sadb_sa_spi && sunionp) { - if ((sa2->tdb_flags & TDBF_ALLOCATIONS) && - (sa2->tdb_cur_allocations >= sa2->tdb_exp_allocations)) + ktdb = ipo->ipo_tdb; /* Hold for now */ + + s = spltdb(); + ipo->ipo_tdb = gettdb(ssa->sadb_sa_spi, sunionp, + SADB_GETSPROTO(smsg->sadb_msg_satype)); + if (ipo->ipo_tdb == NULL) { - pfkeyv2_expire(sa2, SADB_EXT_LIFETIME_HARD); - tdb_delete(sa2, 0, TDBEXP_TIMEOUT); + ipo->ipo_tdb = ktdb; /* Reset */ + rval = ESRCH; + goto splxret; + } + else + { + if (ktdb) + TAILQ_REMOVE(&ktdb->tdb_policy_head, ipo, ipo_tdb_next); + TAILQ_INSERT_HEAD(&ipo->ipo_tdb->tdb_policy_head, ipo, + ipo_tdb_next); } - else - if ((sa2->tdb_flags & TDBF_SOFT_ALLOCATIONS) && - (sa2->tdb_cur_allocations >= sa2->tdb_soft_allocations)) - { - pfkeyv2_expire(sa2, SADB_EXT_LIFETIME_SOFT); - sa2->tdb_flags &= ~TDBF_SOFT_ALLOCATIONS; - } - } - } - - splx(s); - break; - - case SADB_X_GRPSPIS: - { - struct tdb *tdb1, *tdb2, *tdb3; - struct sadb_protocol *sa_proto; - - ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; - sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] + - sizeof(struct sadb_address)); - - s = spltdb(); - tdb1 = gettdb(ssa->sadb_sa_spi, sunionp, - SADB_GETSPROTO(smsg->sadb_msg_satype)); - if (tdb1 == NULL) - { - rval = ESRCH; - goto splxret; + splx(s); } - ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2]; - sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] + - sizeof(struct sadb_address)); - sa_proto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL]); - - tdb2 = gettdb(ssa->sadb_sa_spi, sunionp, - SADB_GETSPROTO(sa_proto->sadb_protocol_proto)); - if (tdb2 == NULL) + if (sunionp) + bcopy(sunionp, &ipo->ipo_dst, sizeof(union sockaddr_union)); + else + { + bzero(&ipo->ipo_dst, sizeof(union sockaddr_union)); + ipo->ipo_dst.sa.sa_family = src->sa.sa_family; + ipo->ipo_dst.sa.sa_len = src->sa.sa_len; + } + + if (ssrc) + bcopy(ssrc, &ipo->ipo_src, sizeof(union sockaddr_union)); + else { - rval = ESRCH; - goto splxret; + bzero(&ipo->ipo_src, sizeof(union sockaddr_union)); + ipo->ipo_src.sa.sa_family = src->sa.sa_family; + ipo->ipo_src.sa.sa_len = src->sa.sa_len; } - /* Detect cycles */ - for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext) - if (tdb3 == tdb1) - { - rval = ESRCH; - goto splxret; - } + ipo->ipo_sproto = SADB_GETSPROTO(smsg->sadb_msg_satype); - /* Maintenance */ - if ((tdb1->tdb_onext) && - (tdb1->tdb_onext->tdb_inext == tdb1)) - tdb1->tdb_onext->tdb_inext = NULL; - - if ((tdb2->tdb_inext) && - (tdb2->tdb_inext->tdb_onext == tdb2)) - tdb2->tdb_inext->tdb_onext = NULL; + /* Flow type */ + switch (((struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE])->sadb_protocol_proto) + { + case FLOW_X_TYPE_USE: + ipo->ipo_type = IPSP_IPSEC_USE; + break; - /* Link them */ - tdb1->tdb_onext = tdb2; - tdb2->tdb_inext = tdb1; + case FLOW_X_TYPE_ACQUIRE: + ipo->ipo_type = IPSP_IPSEC_ACQUIRE; + break; - splx(s); - } + case FLOW_X_TYPE_REQUIRE: + ipo->ipo_type = IPSP_IPSEC_REQUIRE; + break; - break; - - case SADB_X_BINDSA: - { - struct tdb *tdb1, *tdb2; - struct sadb_protocol *sa_proto; + case FLOW_X_TYPE_DENY: + ipo->ipo_type = IPSP_DENY; + break; - ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; - sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] + - sizeof(struct sadb_address)); + case FLOW_X_TYPE_BYPASS: + ipo->ipo_type = IPSP_PERMIT; + break; - s = spltdb(); + case FLOW_X_TYPE_DONTACQ: + ipo->ipo_type = IPSP_IPSEC_DONTACQ; + break; - tdb1 = gettdb(ssa->sadb_sa_spi, sunionp, - SADB_GETSPROTO(smsg->sadb_msg_satype)); - if (tdb1 == NULL) - { - rval = ESRCH; - goto splxret; + default: + FREE(ipo, M_TDB); + rval = EINVAL; + goto ret; } - if (TAILQ_FIRST(&tdb1->tdb_bind_in)) + if (!exists) { - /* Incoming SA has not list of referencing incoming SAs */ - rval = EINVAL; - goto splxret; - } + /* Add SPD entry */ + if ((rval = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst, + (struct sockaddr *) &encapgw, + (struct sockaddr *) &encapnetmask, + RTF_UP | RTF_GATEWAY | RTF_STATIC, + (struct rtentry **) 0)) != 0) + { + /* Remove from linked list of policies on TDB */ + if (ipo->ipo_tdb) + { + s = spltdb(); + TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, + ipo_tdb_next); + splx(s); + } - ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2]; - sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] + - sizeof(struct sadb_address)); - sa_proto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL]); + FREE(ipo, M_TDB); /* Free policy entry */ + goto ret; + } - tdb2 = gettdb(ssa->sadb_sa_spi, sunionp, - SADB_GETSPROTO(sa_proto->sadb_protocol_proto)); - if (tdb2 == NULL) - { - rval = ESRCH; - goto splxret; - } + s = spltdb(); + TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list); + splx(s); - if (tdb2->tdb_bind_out) + ipsec_in_use++; + } + else { - /* Outgoing SA has no pointer to an outgoing SA */ - rval = EINVAL; - goto splxret; + ipo->ipo_last_searched = ipo->ipo_flags = 0; } - - /* 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); - - splx(s); - } - + } break; case SADB_X_PROMISC: @@ -1960,14 +1808,14 @@ splxret: * Send an ACQUIRE message to key management, to get a new SA. */ int -pfkeyv2_acquire(struct tdb *tdb, int rekey) +pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw, + union sockaddr_union *laddr) { - void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL; + void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL; + struct sadb_comb *sadb_comb; struct sadb_address *sadd; - struct sadb_msg *smsg; - struct sadb_ident *sa_ident; struct sadb_prop *sa_prop; - struct sadb_comb *sadb_comb; + struct sadb_msg *smsg; int rval = 0; int i, j; @@ -1978,14 +1826,11 @@ pfkeyv2_acquire(struct tdb *tdb, int rekey) } /* How large a buffer do we need... XXX we only do one proposal for now */ - i = sizeof(struct sadb_msg) + sizeof(struct sadb_address) + - PADUP(SA_LEN(&tdb->tdb_src.sa)) + sizeof(struct sadb_address) + - PADUP(SA_LEN(&tdb->tdb_dst.sa)) + sizeof(struct sadb_prop) + - 1 * sizeof(struct sadb_comb) + - 2 * sizeof(struct sadb_ident); - - if (rekey) - i += PADUP(tdb->tdb_srcid_len) + PADUP(tdb->tdb_dstid_len); + i = sizeof(struct sadb_msg) + + (laddr == NULL ? 0 : sizeof(struct sadb_address) + + PADUP(SA_LEN(&ipo->ipo_src.sa))) + + sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa)) + + sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb); /* Allocate */ if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) @@ -2007,188 +1852,139 @@ pfkeyv2_acquire(struct tdb *tdb, int rekey) smsg->sadb_msg_type = SADB_ACQUIRE; smsg->sadb_msg_len = i / sizeof(uint64_t); smsg->sadb_msg_seq = pfkeyv2_seq++; - smsg->sadb_msg_satype = tdb->tdb_satype; - headers[SADB_EXT_ADDRESS_SRC] = p; - p += sizeof(struct sadb_address) + PADUP(SA_LEN(&tdb->tdb_src.sa)); - sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC]; - sadd->sadb_address_len = (sizeof(struct sadb_address) + - SA_LEN(&tdb->tdb_src.sa) + - sizeof(uint64_t) - 1) / sizeof(uint64_t); - bcopy(&tdb->tdb_src, - headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address), - SA_LEN(&tdb->tdb_src.sa)); + if (ipo->ipo_sproto == IPPROTO_ESP) + smsg->sadb_msg_satype = SADB_SATYPE_ESP; + else + smsg->sadb_msg_satype = SADB_SATYPE_AH; + + if (laddr) + { + headers[SADB_EXT_ADDRESS_SRC] = p; + p += sizeof(struct sadb_address) + PADUP(SA_LEN(&laddr->sa)); + sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC]; + sadd->sadb_address_len = (sizeof(struct sadb_address) + + SA_LEN(&laddr->sa) + + sizeof(uint64_t) - 1) / sizeof(uint64_t); + bcopy(laddr, + headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address), + SA_LEN(&laddr->sa)); + } headers[SADB_EXT_ADDRESS_DST] = p; - p += sizeof(struct sadb_address) + PADUP(SA_LEN(&tdb->tdb_dst.sa)); + p += sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa)); sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST]; sadd->sadb_address_len = (sizeof(struct sadb_address) + - SA_LEN(&tdb->tdb_dst.sa) + + SA_LEN(&gw->sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t); - bcopy(&tdb->tdb_dst, - headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address), - SA_LEN(&tdb->tdb_dst.sa)); - - headers[SADB_EXT_IDENTITY_SRC] = p; - p += sizeof(struct sadb_ident); - sa_ident = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_SRC]; - sa_ident->sadb_ident_type = tdb->tdb_srcid_type; - - /* XXX some day we'll have to deal with real ident_ids for users */ - sa_ident->sadb_ident_id = 0; - - if (rekey) - { - sa_ident->sadb_ident_len = (sizeof(struct sadb_ident) + - PADUP(tdb->tdb_srcid_len)) / - sizeof(uint64_t); - bcopy(tdb->tdb_srcid, p, tdb->tdb_srcid_len); - p += PADUP(tdb->tdb_srcid_len); - } - else - sa_ident->sadb_ident_len = sizeof(struct sadb_ident) / sizeof(uint64_t); - - headers[SADB_EXT_IDENTITY_DST] = p; - p += sizeof(struct sadb_ident); - sa_ident = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_DST]; - sa_ident->sadb_ident_type = tdb->tdb_dstid_type; - - /* XXX some day we'll have to deal with real ident_ids for users */ - sa_ident->sadb_ident_id = 0; - - if (rekey) - { - sa_ident->sadb_ident_len = (sizeof(struct sadb_ident) + - PADUP(tdb->tdb_dstid_len)) / - sizeof(uint64_t); - bcopy(tdb->tdb_dstid, p, tdb->tdb_dstid_len); - p += PADUP(tdb->tdb_dstid_len); - } - else - sa_ident->sadb_ident_len = sizeof(struct sadb_ident) / sizeof(uint64_t); + bcopy(gw, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address), + SA_LEN(&gw->sa)); headers[SADB_EXT_PROPOSAL] = p; p += sizeof(struct sadb_prop); sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL]; - sa_prop->sadb_prop_num = 1; /* XXX Only 1 proposal supported for now */ + sa_prop->sadb_prop_num = 1; /* XXX One proposal only */ sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) + (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) / sizeof(uint64_t); sadb_comb = p; + /* XXX Should actually ask the crypto layer what's supported */ for (j = 0; j < sa_prop->sadb_prop_num; j++) { sadb_comb->sadb_comb_flags = 0; - if (tdb->tdb_flags & TDBF_PFS) + if (ipsec_require_pfs) sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS; - if (tdb->tdb_flags & TDBF_HALFIV) - sadb_comb->sadb_comb_flags |= SADB_X_SAFLAGS_HALFIV; - - if (tdb->tdb_flags & TDBF_TUNNELING) - sadb_comb->sadb_comb_flags |= SADB_X_SAFLAGS_TUNNEL; - - if (tdb->tdb_authalgxform) + /* Set the encryption algorithm */ + if (ipo->ipo_sproto == IPPROTO_ESP) { - switch (tdb->tdb_authalgxform->type) + if (!strncasecmp(ipsec_def_enc, "3des", sizeof("3des"))) { - case CRYPTO_MD5_HMAC96: - sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC96; - break; - - case CRYPTO_SHA1_HMAC96: - sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC96; - break; - - case CRYPTO_RIPEMD160_HMAC96: - sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC96; - break; - - case CRYPTO_MD5_KPDK: - sadb_comb->sadb_comb_auth = SADB_X_AALG_MD5; - break; - - case CRYPTO_SHA1_KPDK: - sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA1; - break; + sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC; + sadb_comb->sadb_comb_encrypt_minbits = 192; + sadb_comb->sadb_comb_encrypt_maxbits = 192; } - - sadb_comb->sadb_comb_auth_minbits = - tdb->tdb_authalgxform->keysize * 8; - sadb_comb->sadb_comb_auth_maxbits = - tdb->tdb_authalgxform->keysize * 8; - } - else - { - sadb_comb->sadb_comb_auth = 0; - sadb_comb->sadb_comb_auth_minbits = 0; - sadb_comb->sadb_comb_auth_maxbits = 0; + else + if (!strncasecmp(ipsec_def_enc, "des", sizeof("des"))) + { + sadb_comb->sadb_comb_encrypt = SADB_EALG_DESCBC; + sadb_comb->sadb_comb_encrypt_minbits = 64; + sadb_comb->sadb_comb_encrypt_maxbits = 64; + } + else + if (!strncasecmp(ipsec_def_enc, "blowfish", + sizeof("blowfish"))) + { + sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF; + sadb_comb->sadb_comb_encrypt_minbits = 40; + sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN * 8; + } + else + if (!strncasecmp(ipsec_def_enc, "skipjack", + sizeof("skipjack"))) + { + sadb_comb->sadb_comb_encrypt = SADB_X_EALG_SKIPJACK; + sadb_comb->sadb_comb_encrypt_minbits = 80; + sadb_comb->sadb_comb_encrypt_maxbits = 80; + } + else + if (!strncasecmp(ipsec_def_enc, "cast128", + sizeof("cast128"))) + { + sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST; + sadb_comb->sadb_comb_encrypt_minbits = 40; + sadb_comb->sadb_comb_encrypt_maxbits = 128; + } } - if (tdb->tdb_encalgxform) + /* Set the authentication algorithm */ + if (!strncasecmp(ipsec_def_auth, "hmac-sha1", sizeof("hmac-sha1"))) { - switch (tdb->tdb_encalgxform->type) - { - case CRYPTO_DES_CBC: - sadb_comb->sadb_comb_encrypt = SADB_EALG_DESCBC; - break; - - case CRYPTO_3DES_CBC: - sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC; - break; - - case CRYPTO_CAST_CBC: - sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST; - break; - - case CRYPTO_BLF_CBC: - sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF; - break; - - case CRYPTO_SKIPJACK_CBC: - sadb_comb->sadb_comb_encrypt = SADB_X_EALG_SKIPJACK; - break; - } - - sadb_comb->sadb_comb_encrypt_minbits = - tdb->tdb_encalgxform->minkey * 8; - sadb_comb->sadb_comb_encrypt_maxbits = - tdb->tdb_encalgxform->maxkey * 8; + sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC96; + sadb_comb->sadb_comb_auth_minbits = 160; + sadb_comb->sadb_comb_auth_maxbits = 160; } else - { - sadb_comb->sadb_comb_encrypt = 0; - sadb_comb->sadb_comb_encrypt_minbits = 0; - sadb_comb->sadb_comb_encrypt_maxbits = 0; - } - - sadb_comb->sadb_comb_soft_allocations = tdb->tdb_soft_allocations; - sadb_comb->sadb_comb_hard_allocations = tdb->tdb_exp_allocations; + if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160", + sizeof("hmac_ripemd160"))) + { + sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC96; + sadb_comb->sadb_comb_auth_minbits = 160; + sadb_comb->sadb_comb_auth_maxbits = 160; + } + else + if (!strncasecmp(ipsec_def_auth, "hmac-md5", sizeof("hmac-md5"))) + { + sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC96; + sadb_comb->sadb_comb_auth_minbits = 128; + sadb_comb->sadb_comb_auth_maxbits = 128; + } + + sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations; + sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations; - sadb_comb->sadb_comb_soft_bytes = tdb->tdb_soft_bytes; - sadb_comb->sadb_comb_hard_bytes = tdb->tdb_exp_bytes; + sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes; + sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes; - sadb_comb->sadb_comb_soft_addtime = tdb->tdb_soft_timeout; - sadb_comb->sadb_comb_hard_addtime = tdb->tdb_exp_timeout; + sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout; + sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout; - sadb_comb->sadb_comb_soft_usetime = tdb->tdb_soft_first_use; - sadb_comb->sadb_comb_hard_usetime = tdb->tdb_exp_first_use; + sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use; + sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use; sadb_comb++; } - /* - * Send the ACQUIRE message to all compliant registered listeners. - * XXX We only send it to the first compliant registered - * listener (as specified by the last argument) - */ + /* XXX How to externalize the policy itself ? */ + + /* Send the ACQUIRE message to all compliant registered listeners. */ if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_REGISTERED, - NULL, smsg->sadb_msg_satype, 1)) != 0) + NULL, smsg->sadb_msg_satype, 0)) != 0) goto ret; rval = 0; - ret: if (buffer != NULL) { diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h index 1952b82a05b..9a6fcb9a300 100644 --- a/sys/net/pfkeyv2.h +++ b/sys/net/pfkeyv2.h @@ -28,9 +28,7 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #define SADB_X_PROMISC 11 #define SADB_X_ADDFLOW 12 #define SADB_X_DELFLOW 13 -#define SADB_X_GRPSPIS 14 -#define SADB_X_BINDSA 15 -#define SADB_MAX 15 +#define SADB_MAX 13 struct sadb_msg { uint8_t sadb_msg_version; @@ -155,14 +153,13 @@ struct sadb_protocol { uint16_t sadb_protocol_len; uint16_t sadb_protocol_exttype; uint8_t sadb_protocol_proto; - uint8_t sadb_protocol_reserved1; + uint8_t sadb_protocol_direction; uint16_t sadb_protocol_reserved2; }; #define SADB_GETSPROTO(x) ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\ (x) == SADB_SATYPE_ESP ? IPPROTO_ESP :\ - (x) == SADB_X_SATYPE_BYPASS ? IPPROTO_IP :\ - IPPROTO_IPIP ) + IPPROTO_IPIP ) #define SADB_EXT_RESERVED 0 #define SADB_EXT_SA 1 @@ -183,11 +180,10 @@ struct sadb_protocol { #define SADB_X_EXT_SRC_MASK 16 #define SADB_X_EXT_DST_MASK 17 #define SADB_X_EXT_PROTOCOL 18 -#define SADB_X_EXT_SA2 19 +#define SADB_X_EXT_FLOW_TYPE 19 #define SADB_X_EXT_SRC_FLOW 20 #define SADB_X_EXT_DST_FLOW 21 -#define SADB_X_EXT_DST2 22 -#define SADB_EXT_MAX 22 +#define SADB_EXT_MAX 21 /* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */ #define SADB_SATYPE_UNSPEC 0 @@ -199,8 +195,7 @@ struct sadb_protocol { #define SADB_SATYPE_MIP 6 #define SADB_X_SATYPE_IPIP 7 #define SADB_X_SATYPE_TCPSIGNATURE 8 -#define SADB_X_SATYPE_BYPASS 9 -#define SADB_SATYPE_MAX 9 +#define SADB_SATYPE_MAX 8 #define SADB_SASTATE_LARVAL 0 #define SADB_SASTATE_MATURE 1 @@ -230,8 +225,6 @@ struct sadb_protocol { #define SADB_X_SAFLAGS_HALFIV 0x002 /* Used for ESP-old */ #define SADB_X_SAFLAGS_TUNNEL 0x004 /* Force tunneling */ #define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */ -#define SADB_X_SAFLAGS_REPLACEFLOW 0x020 /* Replace existing flow */ -#define SADB_X_SAFLAGS_INGRESS_FLOW 0x040 /* Ingress ACL entry */ #define SADB_X_SAFLAGS_RANDOMPADDING 0x080 /* Random ESP padding */ #define SADB_X_SAFLAGS_NOREPLAY 0x100 /* No replay counter */ @@ -261,6 +254,15 @@ struct sadb_protocol { #define PFKEYV2_SENDMESSAGE_REGISTERED 2 #define PFKEYV2_SENDMESSAGE_BROADCAST 3 +#define FLOW_X_TYPE_USE 1 +#define FLOW_X_TYPE_ACQUIRE 2 +#define FLOW_X_TYPE_REQUIRE 3 +#define FLOW_X_TYPE_BYPASS 4 +#define FLOW_X_TYPE_DENY 5 +#define FLOW_X_TYPE_DONTACQ 6 + +#define OPENBSD_IPSEC_API_VERSION 1 + #ifdef _KERNEL struct tdb; struct socket; @@ -293,7 +295,8 @@ int pfkeyv2_init(void); int pfkeyv2_cleanup(void); int pfkeyv2_parsemessage(void *, int, void **); int pfkeyv2_expire(struct tdb *, u_int16_t); -int pfkeyv2_acquire(struct tdb *, int); +int pfkeyv2_acquire(struct ipsec_policy *, union sockaddr_union *, + union sockaddr_union *); int pfkey_register(struct pfkey_version *version); int pfkey_unregister(struct pfkey_version *version); diff --git a/sys/net/pfkeyv2_parsemessage.c b/sys/net/pfkeyv2_parsemessage.c index abd123d9696..907c26cfb61 100644 --- a/sys/net/pfkeyv2_parsemessage.c +++ b/sys/net/pfkeyv2_parsemessage.c @@ -27,6 +27,7 @@ you didn't get a copy, you may request one from <license@inner.net>. #include <sys/proc.h> #include <net/route.h> #include <netinet/in.h> +#include <netinet/ip_ipsp.h> #include <net/pfkeyv2.h> #define BITMAP_SA (1 << SADB_EXT_SA) @@ -52,10 +53,9 @@ you didn't get a copy, you may request one from <license@inner.net>. #define BITMAP_X_SRC_MASK (1 << SADB_X_EXT_SRC_MASK) #define BITMAP_X_DST_MASK (1 << SADB_X_EXT_DST_MASK) #define BITMAP_X_PROTOCOL (1 << SADB_X_EXT_PROTOCOL) -#define BITMAP_X_SA2 (1 << SADB_X_EXT_SA2) #define BITMAP_X_SRC_FLOW (1 << SADB_X_EXT_SRC_FLOW) #define BITMAP_X_DST_FLOW (1 << SADB_X_EXT_DST_FLOW) -#define BITMAP_X_DST2 (1 << SADB_X_EXT_DST2) +#define BITMAP_X_FLOW_TYPE (1 << SADB_X_EXT_FLOW_TYPE) uint32_t sadb_exts_allowed_in[SADB_MAX+1] = { @@ -72,7 +72,7 @@ uint32_t sadb_exts_allowed_in[SADB_MAX+1] = /* GET */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, /* ACQUIRE */ - BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, + BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK, /* REGISTER */ 0, /* EXPIRE */ @@ -84,13 +84,9 @@ uint32_t sadb_exts_allowed_in[SADB_MAX+1] = /* X_PROMISC */ 0, /* X_ADDFLOW */ - BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW, + BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* X_DELFLOW */ - BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST, - /* 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 + BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST | BITMAP_X_FLOW_TYPE, }; uint32_t sadb_exts_required_in[SADB_MAX+1] = @@ -120,13 +116,9 @@ uint32_t sadb_exts_required_in[SADB_MAX+1] = /* X_PROMISC */ 0, /* X_ADDFLOW */ - BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW, + BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* 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 + BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, }; uint32_t sadb_exts_allowed_out[SADB_MAX+1] = @@ -144,7 +136,7 @@ uint32_t sadb_exts_allowed_out[SADB_MAX+1] = /* GET */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY, /* ACQUIRE */ - BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, + BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK, /* REGISTER */ BITMAP_SUPPORTED, /* EXPIRE */ @@ -156,13 +148,9 @@ uint32_t sadb_exts_allowed_out[SADB_MAX+1] = /* X_PROMISC */ 0, /* X_ADDFLOW */ - BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW, + BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* X_DELFLOW */ - BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST, - /* 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 + BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST | BITMAP_X_FLOW_TYPE, }; uint32_t sadb_exts_required_out[SADB_MAX+1] = @@ -192,13 +180,9 @@ uint32_t sadb_exts_required_out[SADB_MAX+1] = /* X_PROMISC */ 0, /* X_ADDFLOW */ - BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW, + BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* 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 + BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, }; int pfkeyv2_parsemessage(void *, int, void **); @@ -274,7 +258,6 @@ pfkeyv2_parsemessage(void *p, int len, void **headers) seen |= (1 << sadb_ext->sadb_ext_type); switch (sadb_ext->sadb_ext_type) { - case SADB_X_EXT_SA2: case SADB_EXT_SA: { struct sadb_sa *sadb_sa = (struct sadb_sa *)p; @@ -299,6 +282,7 @@ pfkeyv2_parsemessage(void *p, int len, void **headers) } break; case SADB_X_EXT_PROTOCOL: + case SADB_X_EXT_FLOW_TYPE: if (i != sizeof(struct sadb_protocol)) return EINVAL; break; @@ -312,7 +296,6 @@ pfkeyv2_parsemessage(void *p, int len, void **headers) break; case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: - case SADB_X_EXT_DST2: case SADB_X_EXT_SRC_MASK: case SADB_X_EXT_DST_MASK: case SADB_X_EXT_SRC_FLOW: |