Index: head/lib/libipsec/pfkey_dump.c =================================================================== --- head/lib/libipsec/pfkey_dump.c +++ head/lib/libipsec/pfkey_dump.c @@ -35,8 +35,9 @@ #include #include #include -#include +#include #include +#include #include #include @@ -204,6 +205,13 @@ { -1, NULL, }, }; +static struct val2str str_sp_scope[] = { + { IPSEC_POLICYSCOPE_GLOBAL, "global" }, + { IPSEC_POLICYSCOPE_IFNET, "ifnet" }, + { IPSEC_POLICYSCOPE_PCB, "pcb"}, + { -1, NULL }, +}; + /* * dump SADB_MSG formated. For debugging, you should use kdebug_sadb(). */ @@ -398,8 +406,7 @@ } void -pfkey_spdump(m) - struct sadb_msg *m; +pfkey_spdump(struct sadb_msg *m) { char pbuf[NI_MAXSERV]; caddr_t mhp[SADB_EXT_MAX + 1]; @@ -507,10 +514,15 @@ } - printf("\tspid=%ld seq=%ld pid=%ld\n", + printf("\tspid=%ld seq=%ld pid=%ld scope=", (u_long)m_xpl->sadb_x_policy_id, (u_long)m->sadb_msg_seq, (u_long)m->sadb_msg_pid); + GETMSGV2S(str_sp_scope, m_xpl->sadb_x_policy_scope); + if (m_xpl->sadb_x_policy_scope == IPSEC_POLICYSCOPE_IFNET && + if_indextoname(m_xpl->sadb_x_policy_ifindex, pbuf) != NULL) + printf("ifname=%s", pbuf); + printf("\n"); /* XXX TEST */ printf("\trefcnt=%u\n", m->sadb_msg_reserved); Index: head/sbin/setkey/setkey.8 =================================================================== --- head/sbin/setkey/setkey.8 +++ head/sbin/setkey/setkey.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 27, 2017 +.Dd March 7, 2017 .Dt SETKEY 8 .Os .\" @@ -45,7 +45,7 @@ .Op Fl v .Fl f Ar filename .Nm -.Op Fl aPlv +.Op Fl Pgltv .Fl D .Nm .Op Fl Pv @@ -81,18 +81,21 @@ If with .Fl P , the SPD entries are flushed. -.It Fl a -The -.Nm -utility -usually does not display dead SAD entries with -.Fl D . -If with -.Fl a , -the dead SAD entries will be displayed as well. -A dead SAD entry means that -it has been expired but remains in the system -because it is referenced by some SPD entries. +.It Fl g +Only SPD entries with global scope are dumped with +.Fl D +and +.Fl P +flags. +.It Fl t +Only SPD entries with ifnet scope are dumped with +.Fl D +and +.Fl P +flags. +Such SPD entries are linked to the corresponding +.Xr if_ipsec 4 +virtual tunneling interface. .It Fl h Add hexadecimal dump on .Fl x @@ -697,6 +700,7 @@ .\" .Sh SEE ALSO .Xr ipsec_set_policy 3 , +.Xr if_ipsec 4 , .Xr racoon 8 , .Xr sysctl 8 .Rs Index: head/sbin/setkey/setkey.c =================================================================== --- head/sbin/setkey/setkey.c +++ head/sbin/setkey/setkey.c @@ -56,7 +56,7 @@ void usage(void); int main(int, char **); int get_supported(void); -void sendkeyshort(u_int); +void sendkeyshort(u_int, uint8_t); void promisc(void); int sendkeymsg(char *, size_t); int postproc(struct sadb_msg *, int); @@ -81,6 +81,7 @@ int f_policy = 0; int f_hexdump = 0; int f_tflag = 0; +int f_scope = 0; static time_t thiszone; extern int lineno; @@ -93,7 +94,7 @@ printf("usage: setkey [-v] -c\n"); printf(" setkey [-v] -f filename\n"); - printf(" setkey [-Palv] -D\n"); + printf(" setkey [-Pagltv] -D\n"); printf(" setkey [-Pv] -F\n"); printf(" setkey [-h] -x\n"); exit(1); @@ -114,7 +115,7 @@ thiszone = gmt2local(0); - while ((c = getopt(ac, av, "acdf:hlvxDFP")) != -1) { + while ((c = getopt(ac, av, "acdf:ghltvxDFP")) != -1) { switch (c) { case 'c': f_mode = MODE_SCRIPT; @@ -149,6 +150,12 @@ case 'P': f_policy = 1; break; + case 'g': /* global */ + f_scope |= IPSEC_POLICYSCOPE_GLOBAL; + break; + case 't': /* tunnel */ + f_scope |= IPSEC_POLICYSCOPE_IFNET; + break; case 'v': f_verbose = 1; break; @@ -166,10 +173,12 @@ switch (f_mode) { case MODE_CMDDUMP: - sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP); + sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP, + f_policy ? f_scope: SADB_SATYPE_UNSPEC); break; case MODE_CMDFLUSH: - sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); + sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH, + SADB_SATYPE_UNSPEC); break; case MODE_SCRIPT: if (get_supported() < 0) { @@ -204,15 +213,14 @@ } void -sendkeyshort(type) - u_int type; +sendkeyshort(u_int type, uint8_t satype) { struct sadb_msg msg; msg.sadb_msg_version = PF_KEY_V2; msg.sadb_msg_type = type; msg.sadb_msg_errno = 0; - msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; + msg.sadb_msg_satype = satype; msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); msg.sadb_msg_reserved = 0; msg.sadb_msg_seq = 0; Index: head/sys/net/if_ipsec.c =================================================================== --- head/sys/net/if_ipsec.c +++ head/sys/net/if_ipsec.c @@ -717,7 +717,7 @@ * ipsec esp/tunnel/LocalIP-RemoteIP/unique:reqid */ static int -ipsec_newpolicies(struct secpolicy *sp[IPSEC_SPCOUNT], +ipsec_newpolicies(struct ipsec_softc *sc, struct secpolicy *sp[IPSEC_SPCOUNT], const struct sockaddr *src, const struct sockaddr *dst, uint32_t reqid) { struct ipsecrequest *isr; @@ -734,6 +734,8 @@ sp[i]->state = IPSEC_SPSTATE_DEAD; sp[i]->req[sp[i]->tcount++] = isr; sp[i]->created = time_second; + /* Use priority field to store if_index */ + sp[i]->priority = sc->ifp->if_index; isr->level = IPSEC_LEVEL_UNIQUE; isr->saidx.proto = IPPROTO_ESP; isr->saidx.mode = IPSEC_MODE_TUNNEL; @@ -936,7 +938,7 @@ sx_assert(&ipsec_ioctl_sx, SA_XLOCKED); /* Allocate SP with new addresses. */ - if (ipsec_newpolicies(sp, src, dst, reqid) == 0) { + if (ipsec_newpolicies(sc, sp, src, dst, reqid) == 0) { /* Add new policies to SPDB */ if (key_register_ifnet(sp, IPSEC_SPCOUNT) != 0) { for (i = 0; i < IPSEC_SPCOUNT; i++) Index: head/sys/net/pfkeyv2.h =================================================================== --- head/sys/net/pfkeyv2.h +++ head/sys/net/pfkeyv2.h @@ -223,9 +223,12 @@ u_int16_t sadb_x_policy_exttype; u_int16_t sadb_x_policy_type; /* See policy type of ipsec.h */ u_int8_t sadb_x_policy_dir; /* direction, see ipsec.h */ - u_int8_t sadb_x_policy_reserved; + u_int8_t sadb_x_policy_scope; /* scope, see ipsec.h */ u_int32_t sadb_x_policy_id; u_int32_t sadb_x_policy_priority; +#define sadb_x_policy_reserved sadb_x_policy_scope +/* Policy with ifnet scope uses priority field to store ifindex */ +#define sadb_x_policy_ifindex sadb_x_policy_priority }; _Static_assert(sizeof(struct sadb_x_policy) == 16, "struct size mismatch"); Index: head/sys/netipsec/ipsec.h =================================================================== --- head/sys/netipsec/ipsec.h +++ head/sys/netipsec/ipsec.h @@ -179,6 +179,12 @@ #define IPSEC_POLICY_ENTRUST 3 /* consulting SPD if present. */ #define IPSEC_POLICY_BYPASS 4 /* only for privileged socket. */ +/* Policy scope */ +#define IPSEC_POLICYSCOPE_ANY 0x00 /* unspecified */ +#define IPSEC_POLICYSCOPE_GLOBAL 0x01 /* global scope */ +#define IPSEC_POLICYSCOPE_IFNET 0x02 /* if_ipsec(4) scope */ +#define IPSEC_POLICYSCOPE_PCB 0x04 /* PCB scope */ + /* Security protocol level */ #define IPSEC_LEVEL_DEFAULT 0 /* reference to system default */ #define IPSEC_LEVEL_USE 1 /* use SA if present. */ Index: head/sys/netipsec/key.c =================================================================== --- head/sys/netipsec/key.c +++ head/sys/netipsec/key.c @@ -1660,6 +1660,16 @@ xpl->sadb_x_policy_dir = sp->spidx.dir; xpl->sadb_x_policy_id = sp->id; xpl->sadb_x_policy_priority = sp->priority; + switch (sp->state) { + case IPSEC_SPSTATE_IFNET: + xpl->sadb_x_policy_scope = IPSEC_POLICYSCOPE_IFNET; + break; + case IPSEC_SPSTATE_PCB: + xpl->sadb_x_policy_scope = IPSEC_POLICYSCOPE_PCB; + break; + default: + xpl->sadb_x_policy_scope = IPSEC_POLICYSCOPE_GLOBAL; + } /* if is the policy for ipsec ? */ if (sp->policy == IPSEC_POLICY_IPSEC) { @@ -2388,16 +2398,25 @@ return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); } +static uint8_t +key_satype2scopemask(uint8_t satype) +{ + + if (satype == IPSEC_POLICYSCOPE_ANY) + return (0xff); + return (satype); +} /* * SADB_SPDDUMP processing * receive * - * from the user, and dump all SP leaves - * and send, + * from the user, and dump all SP leaves and send, * ..... * to the ikmpd. * - * m will always be freed. + * NOTE: + * sadb_msg_satype is considered as mask of policy scopes. + * m will always be freed. */ static int key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) @@ -2406,7 +2425,7 @@ struct secpolicy *sp; struct mbuf *n; int cnt; - u_int dir; + u_int dir, scope; IPSEC_ASSERT(so != NULL, ("null socket")); IPSEC_ASSERT(m != NULL, ("null mbuf")); @@ -2415,13 +2434,16 @@ /* search SPD entry and get buffer size. */ cnt = 0; + scope = key_satype2scopemask(mhp->msg->sadb_msg_satype); SPTREE_RLOCK(); for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - TAILQ_FOREACH(sp, &V_sptree[dir], chain) { - cnt++; - } - TAILQ_FOREACH(sp, &V_sptree_ifnet[dir], chain) { - cnt++; + if (scope & IPSEC_POLICYSCOPE_GLOBAL) { + TAILQ_FOREACH(sp, &V_sptree[dir], chain) + cnt++; + } + if (scope & IPSEC_POLICYSCOPE_IFNET) { + TAILQ_FOREACH(sp, &V_sptree_ifnet[dir], chain) + cnt++; } } @@ -2431,21 +2453,25 @@ } for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - TAILQ_FOREACH(sp, &V_sptree[dir], chain) { - --cnt; - n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, - mhp->msg->sadb_msg_pid); - - if (n) - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } - TAILQ_FOREACH(sp, &V_sptree_ifnet[dir], chain) { - --cnt; - n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, - mhp->msg->sadb_msg_pid); + if (scope & IPSEC_POLICYSCOPE_GLOBAL) { + TAILQ_FOREACH(sp, &V_sptree[dir], chain) { + --cnt; + n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, + mhp->msg->sadb_msg_pid); + + if (n != NULL) + key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + } + } + if (scope & IPSEC_POLICYSCOPE_IFNET) { + TAILQ_FOREACH(sp, &V_sptree_ifnet[dir], chain) { + --cnt; + n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, + mhp->msg->sadb_msg_pid); - if (n) - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + if (n != NULL) + key_sendup_mbuf(so, n, KEY_SENDUP_ONE); + } } } @@ -7659,64 +7685,79 @@ msg = mh.msg; - /* check SA type */ - switch (msg->sadb_msg_satype) { - case SADB_SATYPE_UNSPEC: - switch (msg->sadb_msg_type) { - case SADB_GETSPI: - case SADB_UPDATE: - case SADB_ADD: - case SADB_DELETE: - case SADB_GET: - case SADB_ACQUIRE: - case SADB_EXPIRE: - ipseclog((LOG_DEBUG, "%s: must specify satype " - "when msg type=%u.\n", __func__, - msg->sadb_msg_type)); + /* We use satype as scope mask for spddump */ + if (msg->sadb_msg_type == SADB_X_SPDDUMP) { + switch (msg->sadb_msg_satype) { + case IPSEC_POLICYSCOPE_ANY: + case IPSEC_POLICYSCOPE_GLOBAL: + case IPSEC_POLICYSCOPE_IFNET: + case IPSEC_POLICYSCOPE_PCB: + break; + default: + ipseclog((LOG_DEBUG, "%s: illegal satype=%u\n", + __func__, msg->sadb_msg_type)); PFKEYSTAT_INC(out_invsatype); error = EINVAL; goto senderror; } - break; - case SADB_SATYPE_AH: - case SADB_SATYPE_ESP: - case SADB_X_SATYPE_IPCOMP: - case SADB_X_SATYPE_TCPSIGNATURE: - switch (msg->sadb_msg_type) { - case SADB_X_SPDADD: - case SADB_X_SPDDELETE: - case SADB_X_SPDGET: - case SADB_X_SPDDUMP: - case SADB_X_SPDFLUSH: - case SADB_X_SPDSETIDX: - case SADB_X_SPDUPDATE: - case SADB_X_SPDDELETE2: - ipseclog((LOG_DEBUG, "%s: illegal satype=%u\n", - __func__, msg->sadb_msg_type)); + } else { + switch (msg->sadb_msg_satype) { /* check SA type */ + case SADB_SATYPE_UNSPEC: + switch (msg->sadb_msg_type) { + case SADB_GETSPI: + case SADB_UPDATE: + case SADB_ADD: + case SADB_DELETE: + case SADB_GET: + case SADB_ACQUIRE: + case SADB_EXPIRE: + ipseclog((LOG_DEBUG, "%s: must specify satype " + "when msg type=%u.\n", __func__, + msg->sadb_msg_type)); + PFKEYSTAT_INC(out_invsatype); + error = EINVAL; + goto senderror; + } + break; + case SADB_SATYPE_AH: + case SADB_SATYPE_ESP: + case SADB_X_SATYPE_IPCOMP: + case SADB_X_SATYPE_TCPSIGNATURE: + switch (msg->sadb_msg_type) { + case SADB_X_SPDADD: + case SADB_X_SPDDELETE: + case SADB_X_SPDGET: + case SADB_X_SPDFLUSH: + case SADB_X_SPDSETIDX: + case SADB_X_SPDUPDATE: + case SADB_X_SPDDELETE2: + ipseclog((LOG_DEBUG, "%s: illegal satype=%u\n", + __func__, msg->sadb_msg_type)); + PFKEYSTAT_INC(out_invsatype); + error = EINVAL; + goto senderror; + } + break; + case SADB_SATYPE_RSVP: + case SADB_SATYPE_OSPFV2: + case SADB_SATYPE_RIPV2: + case SADB_SATYPE_MIP: + ipseclog((LOG_DEBUG, "%s: type %u isn't supported.\n", + __func__, msg->sadb_msg_satype)); + PFKEYSTAT_INC(out_invsatype); + error = EOPNOTSUPP; + goto senderror; + case 1: /* XXX: What does it do? */ + if (msg->sadb_msg_type == SADB_X_PROMISC) + break; + /*FALLTHROUGH*/ + default: + ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n", + __func__, msg->sadb_msg_satype)); PFKEYSTAT_INC(out_invsatype); error = EINVAL; goto senderror; } - break; - case SADB_SATYPE_RSVP: - case SADB_SATYPE_OSPFV2: - case SADB_SATYPE_RIPV2: - case SADB_SATYPE_MIP: - ipseclog((LOG_DEBUG, "%s: type %u isn't supported.\n", - __func__, msg->sadb_msg_satype)); - PFKEYSTAT_INC(out_invsatype); - error = EOPNOTSUPP; - goto senderror; - case 1: /* XXX: What does it do? */ - if (msg->sadb_msg_type == SADB_X_PROMISC) - break; - /*FALLTHROUGH*/ - default: - ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n", - __func__, msg->sadb_msg_satype)); - PFKEYSTAT_INC(out_invsatype); - error = EINVAL; - goto senderror; } /* check field of upper layer protocol and address family */