diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-05-16 21:48:38 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-05-16 21:48:38 +0000 |
commit | fa7bc152efa100d5d1d9f1d773f4d4128756a1a8 (patch) | |
tree | f140c66f26582a93ecb15f4b9336f7e7c4746763 | |
parent | 60416e45015c3b4729c79c59c1322d58b4146410 (diff) |
spltdb introduced, protection for tdb lists and related structures, so
they won't disappear behind our back by an expiration. Cleanup expiration
logic too.
-rw-r--r-- | sys/net/pfkeyv2.c | 468 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_ah.c | 7 | ||||
-rw-r--r-- | sys/netinet/ip_ah_new.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_ah_old.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_esp.c | 7 | ||||
-rw-r--r-- | sys/netinet/ip_esp_new.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_esp_old.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 585 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 22 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 59 |
11 files changed, 652 insertions, 524 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 767ad1936da..a958c59af9a 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -286,7 +286,7 @@ import_lifetime(struct tdb *tdb, struct sadb_lifetime *sadb_lifetime, int type) } /* Setup/update our position in the expiration queue. */ - tdb_expiration(tdb, 0); + tdb_expiration(tdb, TDBEXP_TIMEOUT); } void @@ -675,8 +675,8 @@ int pfkeyv2_send(struct socket *socket, void *message, int len) { void *headers[SADB_EXT_MAX + 1]; - int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST, delflag = 0; - struct pfkeyv2_socket *pfkeyv2_socket, *s = NULL; + int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST, delflag = 0, s; + struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL; void *freeme = NULL, *bckptr = NULL; struct tdb sa, *sa2 = NULL; struct flow *flow = NULL; @@ -716,9 +716,9 @@ pfkeyv2_send(struct socket *socket, void *message, int len) &packet)) != 0) goto ret; - for (s = pfkeyv2_sockets; s; s = s->next) - if (s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) - pfkey_sendup(s->socket, packet, 1); + for (so = pfkeyv2_sockets; so; so = so->next) + if (so->flags & PFKEYV2_SOCKETFLAGS_PROMISC) + pfkey_sendup(so->socket, packet, 1); m_zero(packet); m_freem(packet); @@ -737,44 +737,44 @@ pfkeyv2_send(struct socket *socket, void *message, int len) switch (((struct sadb_msg *)headers[0])->sadb_msg_satype) { case SADB_SATYPE_AH: - if (!ah_enable) { - rval = EOPNOTSUPP; - goto ret; - } - sa.tdb_sproto = IPPROTO_AH; - break; + if (!ah_enable) { + rval = EOPNOTSUPP; + goto ret; + } + sa.tdb_sproto = IPPROTO_AH; + break; case SADB_SATYPE_ESP: - if (!esp_enable) { - rval = EOPNOTSUPP; - goto ret; - } - sa.tdb_sproto = IPPROTO_ESP; - break; + if (!esp_enable) { + rval = EOPNOTSUPP; + goto ret; + } + sa.tdb_sproto = IPPROTO_ESP; + break; case SADB_SATYPE_X_AH_OLD: - if (!ah_enable) { - rval = EOPNOTSUPP; - goto ret; - } - sa.tdb_sproto = IPPROTO_AH; - break; + if (!ah_enable) { + rval = EOPNOTSUPP; + goto ret; + } + sa.tdb_sproto = IPPROTO_AH; + break; case SADB_SATYPE_X_ESP_OLD: - if (!esp_enable) { - rval = EOPNOTSUPP; - goto ret; - } - sa.tdb_sproto = IPPROTO_ESP; - break; + if (!esp_enable) { + rval = EOPNOTSUPP; + goto ret; + } + sa.tdb_sproto = IPPROTO_ESP; + break; case SADB_SATYPE_X_IPIP: - sa.tdb_sproto = IPPROTO_IPIP; - break; + sa.tdb_sproto = IPPROTO_IPIP; + break; default: /* Nothing else supported */ - rval = EOPNOTSUPP; - goto ret; + rval = EOPNOTSUPP; + goto ret; } import_address((struct sockaddr *)&sa.tdb_src, @@ -799,139 +799,140 @@ pfkeyv2_send(struct socket *socket, void *message, int len) break; case SADB_UPDATE: + s = spltdb(); sa2 = 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 (sa2 == NULL) { rval = ESRCH; - goto ret; + goto splxret; } if (sa2->tdb_flags & TDBF_INVALID) { + struct tdb *newsa; + struct ipsecinit ii; + int alg; + MALLOC(freeme, struct tdb *, sizeof(struct tdb), M_TDB, M_WAITOK); bzero(freeme, sizeof(struct tdb)); - - { - struct tdb *newsa = (struct tdb *)freeme; - struct ipsecinit ii; - int alg; - - bzero(&ii, sizeof(struct ipsecinit)); - switch (((struct sadb_msg *)headers[0])->sadb_msg_satype) { - case SADB_SATYPE_AH: - if (!ah_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_AH; - alg = XF_NEW_AH; - break; - - case SADB_SATYPE_ESP: - if (!esp_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_ESP; - alg = XF_NEW_ESP; - break; - - case SADB_SATYPE_X_AH_OLD: - if (!ah_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_AH; - alg = XF_OLD_AH; - break; + newsa = (struct tdb *)freeme; + bzero(&ii, sizeof(struct ipsecinit)); + switch (((struct sadb_msg *)headers[0])->sadb_msg_satype) { + case SADB_SATYPE_AH: + if (!ah_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_AH; + alg = XF_NEW_AH; + break; - case SADB_SATYPE_X_ESP_OLD: - if (!esp_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_ESP; - alg = XF_OLD_ESP; - break; - - case SADB_SATYPE_X_IPIP: - newsa->tdb_sproto = IPPROTO_IPIP; - alg = XF_IP4; - break; + case SADB_SATYPE_ESP: + if (!esp_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_ESP; + alg = XF_NEW_ESP; + break; + + case SADB_SATYPE_X_AH_OLD: + if (!ah_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_AH; + alg = XF_OLD_AH; + break; + + case SADB_SATYPE_X_ESP_OLD: + if (!esp_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_ESP; + alg = XF_OLD_ESP; + break; + + case SADB_SATYPE_X_IPIP: + newsa->tdb_sproto = IPPROTO_IPIP; + alg = XF_IP4; + break; - default: /* Nothing else supported */ - rval = EOPNOTSUPP; - goto ret; - } - - import_sa(newsa, headers[SADB_EXT_SA], &ii); - import_address((struct sockaddr *)&newsa->tdb_src, - headers[SADB_EXT_ADDRESS_SRC]); - import_address((struct sockaddr *)&newsa->tdb_dst, - headers[SADB_EXT_ADDRESS_DST]); - import_address((struct sockaddr *)&newsa->tdb_proxy, - headers[SADB_EXT_ADDRESS_PROXY]); - - import_lifetime(newsa, headers[SADB_EXT_LIFETIME_CURRENT], 2); - import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT], 1); - import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD], 0); - import_key(&ii, headers[SADB_EXT_KEY_AUTH], 1); - import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT], 0); - import_identity(newsa, headers[SADB_EXT_IDENTITY_SRC], 0); - import_identity(newsa, headers[SADB_EXT_IDENTITY_DST], 1); - - headers[SADB_EXT_KEY_AUTH] = NULL; - headers[SADB_EXT_KEY_ENCRYPT] = NULL; - - rval = tdb_init(newsa, alg, &ii); - if (rval) { - rval = EINVAL; - tdb_delete(freeme, 0); - freeme = NULL; - goto ret; - } - newsa->tdb_flow = sa2->tdb_flow; - newsa->tdb_cur_allocations = sa2->tdb_cur_allocations; - for (flow = newsa->tdb_flow; flow != NULL; flow = flow->flow_next) - flow->flow_sa = newsa; - sa2->tdb_flow = NULL; + default: /* Nothing else supported */ + rval = EOPNOTSUPP; + goto splxret; } + + import_sa(newsa, headers[SADB_EXT_SA], &ii); + import_address((struct sockaddr *)&newsa->tdb_src, + headers[SADB_EXT_ADDRESS_SRC]); + import_address((struct sockaddr *)&newsa->tdb_dst, + headers[SADB_EXT_ADDRESS_DST]); + import_address((struct sockaddr *)&newsa->tdb_proxy, + headers[SADB_EXT_ADDRESS_PROXY]); - tdb_delete(sa2, 0); - puttdb((struct tdb *) freeme); - sa2 = freeme = NULL; + import_lifetime(newsa, headers[SADB_EXT_LIFETIME_CURRENT], 2); + import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT], 1); + import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD], 0); + import_key(&ii, headers[SADB_EXT_KEY_AUTH], 1); + import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT], 0); + import_identity(newsa, headers[SADB_EXT_IDENTITY_SRC], 0); + import_identity(newsa, headers[SADB_EXT_IDENTITY_DST], 1); + + headers[SADB_EXT_KEY_AUTH] = NULL; + headers[SADB_EXT_KEY_ENCRYPT] = NULL; + + rval = tdb_init(newsa, alg, &ii); + if (rval) { + rval = EINVAL; + tdb_delete(freeme, 0, TDBEXP_TIMEOUT); + freeme = NULL; + goto splxret; + } + newsa->tdb_flow = sa2->tdb_flow; + newsa->tdb_cur_allocations = sa2->tdb_cur_allocations; + for (flow = newsa->tdb_flow; flow != NULL; flow = flow->flow_next) + flow->flow_sa = newsa; + sa2->tdb_flow = NULL; + + tdb_delete(sa2, 0, TDBEXP_TIMEOUT); + puttdb((struct tdb *) freeme); + sa2 = freeme = NULL; } else { - if (headers[SADB_EXT_ADDRESS_PROXY] || - headers[SADB_EXT_KEY_AUTH] || - headers[SADB_EXT_KEY_ENCRYPT] || - headers[SADB_EXT_IDENTITY_SRC] || - headers[SADB_EXT_IDENTITY_DST] || - headers[SADB_EXT_SENSITIVITY]) { - rval = EINVAL; - goto ret; - } + if (headers[SADB_EXT_ADDRESS_PROXY] || + headers[SADB_EXT_KEY_AUTH] || + headers[SADB_EXT_KEY_ENCRYPT] || + headers[SADB_EXT_IDENTITY_SRC] || + headers[SADB_EXT_IDENTITY_DST] || + headers[SADB_EXT_SENSITIVITY]) { + rval = EINVAL; + goto splxret; + } - import_sa(sa2, headers[SADB_EXT_SA], NULL); - import_lifetime(sa2, headers[SADB_EXT_LIFETIME_CURRENT], 2); - import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT], 1); - import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD], 0); + import_sa(sa2, headers[SADB_EXT_SA], NULL); + import_lifetime(sa2, headers[SADB_EXT_LIFETIME_CURRENT], 2); + import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT], 1); + import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD], 0); } + splx(s); break; case SADB_ADD: + s = spltdb(); sa2 = 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 (sa2 != NULL) { rval = EEXIST; - goto ret; + goto splxret; } if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { rval = EINVAL; - goto ret; + goto splxret; } MALLOC(freeme, struct tdb *, sizeof(struct tdb), M_TDB, M_WAITOK); @@ -944,50 +945,50 @@ pfkeyv2_send(struct socket *socket, void *message, int len) bzero(&ii, sizeof(struct ipsecinit)); switch (((struct sadb_msg *)headers[0])->sadb_msg_satype) { - case SADB_SATYPE_AH: - if (!ah_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_AH; - alg = XF_NEW_AH; - break; - - case SADB_SATYPE_ESP: - if (!esp_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_ESP; - alg = XF_NEW_ESP; - break; - - case SADB_SATYPE_X_AH_OLD: - if (!ah_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_AH; - alg = XF_OLD_AH; - break; + case SADB_SATYPE_AH: + if (!ah_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_AH; + alg = XF_NEW_AH; + break; - case SADB_SATYPE_X_ESP_OLD: - if (!esp_enable) { - rval = EOPNOTSUPP; - goto ret; - } - newsa->tdb_sproto = IPPROTO_ESP; - alg = XF_OLD_ESP; - break; - - case SADB_SATYPE_X_IPIP: - newsa->tdb_sproto = IPPROTO_IPIP; - alg = XF_IP4; - break; - - default: /* Nothing else supported */ - rval = EOPNOTSUPP; - goto ret; + case SADB_SATYPE_ESP: + if (!esp_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_ESP; + alg = XF_NEW_ESP; + break; + + case SADB_SATYPE_X_AH_OLD: + if (!ah_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_AH; + alg = XF_OLD_AH; + break; + + case SADB_SATYPE_X_ESP_OLD: + if (!esp_enable) { + rval = EOPNOTSUPP; + goto splxret; + } + newsa->tdb_sproto = IPPROTO_ESP; + alg = XF_OLD_ESP; + break; + + case SADB_SATYPE_X_IPIP: + newsa->tdb_sproto = IPPROTO_IPIP; + alg = XF_IP4; + break; + + default: /* Nothing else supported */ + rval = EOPNOTSUPP; + goto splxret; } import_sa(newsa, headers[SADB_EXT_SA], &ii); @@ -1012,43 +1013,48 @@ pfkeyv2_send(struct socket *socket, void *message, int len) rval = tdb_init(newsa, alg, &ii); if (rval) { rval = EINVAL; - tdb_delete(freeme, 0); + tdb_delete(freeme, 0, TDBEXP_TIMEOUT); freeme = NULL; - goto ret; + goto splxret; } } puttdb((struct tdb *)freeme); + splx(s); freeme = NULL; break; case SADB_DELETE: - sa2 = 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 (sa2 == NULL) { - rval = ESRCH; - goto ret; - } + s = spltdb(); + sa2 = 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 (sa2 == NULL) { + rval = ESRCH; + goto splxret; + } - tdb_delete(sa2, ((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_flags & SADB_SAFLAGS_X_CHAINDEL); - sa2 = NULL; - break; + tdb_delete(sa2, ((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_flags & SADB_SAFLAGS_X_CHAINDEL, TDBEXP_TIMEOUT); + splx(s); + sa2 = NULL; + break; case SADB_GET: + s = spltdb(); sa2 = 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 (sa2 == NULL) { rval = ESRCH; - goto ret; + goto splxret; } rval = pfkeyv2_get(sa2, headers, &freeme); if (rval) mode = PFKEYV2_SENDMESSAGE_UNICAST; + splx(s); break; case SADB_REGISTER: @@ -1137,13 +1143,14 @@ pfkeyv2_send(struct socket *socket, void *message, int len) goto ret; } + s = spltdb(); if (!delflag) { sa2 = 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 (sa2 == NULL) { rval = ESRCH; - goto ret; + goto splxret; } } @@ -1173,7 +1180,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) ((delflag && (flow == NULL)) || (!delflag && (flow != NULL)))) { rval = delflag ? ESRCH : EEXIST; - goto ret; + goto splxret; } /* Check for 0.0.0.0/255.255.255.255 if the flow is local */ @@ -1190,7 +1197,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) (!delflag && (flow2 != NULL)))) { rval = delflag ? ESRCH : EEXIST; - goto ret; + goto splxret; } } @@ -1280,7 +1287,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) delete_flow(flow, sa2); if (flow2) delete_flow(flow2, sa2); - goto ret; + goto splxret; } ipsec_in_use++; @@ -1303,7 +1310,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) delete_flow(flow, sa2); if (flow2) delete_flow(flow2, sa2); - goto ret; + goto splxret; } ipsec_in_use++; } @@ -1313,7 +1320,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) delete_flow(flow, sa2); if (flow2) delete_flow(flow2, sa2); - goto ret; + goto splxret; } sa2->tdb_cur_allocations++; @@ -1357,7 +1364,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) delete_flow(flow, sa2); delete_flow(flow2, sa2); ipsec_in_use--; - goto ret; + goto splxret; } ipsec_in_use++; @@ -1387,7 +1394,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if (old_flow) delete_flow(old_flow, old_flow->flow_sa); delete_flow(flow2, sa2); - goto ret; + goto splxret; } ipsec_in_use++; } @@ -1402,7 +1409,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if (old_flow) delete_flow(old_flow, old_flow->flow_sa); delete_flow(flow2, sa2); - goto ret; + goto splxret; } sa2->tdb_cur_allocations++; @@ -1423,8 +1430,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) (sa2->tdb_cur_allocations > sa2->tdb_exp_allocations)) { /* XXX expiration notification */ - tdb_delete(sa2, 0); - break; + tdb_delete(sa2, 0, TDBEXP_TIMEOUT); } else if ((sa2->tdb_flags & TDBF_SOFT_ALLOCATIONS) && (sa2->tdb_cur_allocations > sa2->tdb_soft_allocations)) { @@ -1433,30 +1439,31 @@ pfkeyv2_send(struct socket *socket, void *message, int len) } } } - - break; + splx(s); + break; case SADB_X_GRPSPIS: { struct tdb *tdb1, *tdb2, *tdb3; - + + s = spltdb(); 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)); + (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; + goto splxret; } 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)); + (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; + goto splxret; } /* Detect cycles */ @@ -1464,7 +1471,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if (tdb3 == tdb1) { rval = ESRCH; - goto ret; + goto splxret; } /* Maintenance */ @@ -1479,27 +1486,28 @@ pfkeyv2_send(struct socket *socket, void *message, int len) /* Link them */ tdb1->tdb_onext = tdb2; tdb2->tdb_inext = tdb1; + splx(s); } - - break; + break; case SADB_X_BINDSA: { struct tdb *tdb1, *tdb2; - + + s = spltdb(); 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; + goto splxret; } if (TAILQ_FIRST(&tdb1->tdb_bind_in)) { /* Incoming SA has not list of referencing incoming SAs */ rval = EINVAL; - goto ret; + goto splxret; } tdb2 = gettdb(((struct sadb_sa *)headers[SADB_EXT_X_SA2])->sadb_sa_spi, @@ -1509,13 +1517,13 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if (tdb2 == NULL) { rval = ESRCH; - goto ret; + goto splxret; } if (tdb2->tdb_bind_out) { /* Outgoing SA has no pointer to an outgoing SA */ rval = EINVAL; - goto ret; + goto splxret; } /* Maintenance */ @@ -1527,8 +1535,8 @@ pfkeyv2_send(struct socket *socket, void *message, int len) tdb1->tdb_bind_out = tdb2; TAILQ_INSERT_TAIL(&tdb2->tdb_bind_in, tdb1, tdb_bind_in_next); } - - break; + splx(s); + break; case SADB_X_PROMISC: if (len >= 2 * sizeof(struct sadb_msg)) { @@ -1537,12 +1545,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if ((rval = pfdatatopacket(message, len, &packet)) != 0) goto ret; - for (s = pfkeyv2_sockets; s; s = s->next) - if ((s != pfkeyv2_socket) && + for (so = pfkeyv2_sockets; so; so = so->next) + if ((so != pfkeyv2_socket) && (!((struct sadb_msg *)headers[0])->sadb_msg_seq || (((struct sadb_msg *)headers[0])->sadb_msg_seq == pfkeyv2_socket->pid))) - pfkey_sendup(s->socket, packet, 1); + pfkey_sendup(so->socket, packet, 1); m_freem(packet); } else { @@ -1602,6 +1610,10 @@ realret: free(message, M_TEMP); return rval; + + splxret: + splx(s); + goto ret; } int diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 60b95862e0e..91b157519d6 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.33 1999/04/28 09:28:16 art Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.34 1999/05/16 21:48:29 niklas Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -529,8 +529,10 @@ in_pcbdetach(v) ip_freemoptions(inp->inp_moptions); #ifdef IPSEC /* XXX IPsec cleanup here */ + s = spltdb(); if (inp->inp_tdb) TAILQ_REMOVE(&inp->inp_tdb->tdb_inp, inp, inp_tdb_next); + splx(s); #endif s = splnet(); LIST_REMOVE(inp, inp_hash); diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c index b2b2e347729..85f2e2fbe7f 100644 --- a/sys/netinet/ip_ah.c +++ b/sys/netinet/ip_ah.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah.c,v 1.22 1999/05/14 23:36:16 niklas Exp $ */ +/* $OpenBSD: ip_ah.c,v 1.23 1999/05/16 21:48:30 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -179,7 +179,7 @@ ah_input(m, va_alist) if (tdbp->tdb_first_use == 0) { tdbp->tdb_first_use = time.tv_sec; - tdb_expiration(tdbp, 0); + tdb_expiration(tdbp, TDBEXP_TIMEOUT); } ipn = *ipo; @@ -239,6 +239,8 @@ ah_input(m, va_alist) if (ipo->ip_p == IPPROTO_TCP || ipo->ip_p == IPPROTO_UDP) { struct tdb_ident *tdbi = NULL; + int s = spltdb(); + if (tdbp->tdb_bind_out) { tdbi = m->m_pkthdr.tdbi; @@ -259,6 +261,7 @@ ah_input(m, va_alist) no_mem: m->m_pkthdr.tdbi = tdbi; + splx(s); } else m->m_pkthdr.tdbi = NULL; diff --git a/sys/netinet/ip_ah_new.c b/sys/netinet/ip_ah_new.c index c3531efeea1..5c9078c53fc 100644 --- a/sys/netinet/ip_ah_new.c +++ b/sys/netinet/ip_ah_new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah_new.c,v 1.25 1999/03/24 17:00:44 niklas Exp $ */ +/* $OpenBSD: ip_ah_new.c,v 1.26 1999/05/16 21:48:31 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -274,7 +274,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); m_freem(m); return NULL; } @@ -501,7 +501,7 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); m_freem(m); return EINVAL; } diff --git a/sys/netinet/ip_ah_old.c b/sys/netinet/ip_ah_old.c index 2bd432332f2..f087c8b26ae 100644 --- a/sys/netinet/ip_ah_old.c +++ b/sys/netinet/ip_ah_old.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah_old.c,v 1.22 1999/03/24 17:00:45 niklas Exp $ */ +/* $OpenBSD: ip_ah_old.c,v 1.23 1999/05/16 21:48:32 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -239,7 +239,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); m_freem(m); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); return NULL; } @@ -428,7 +428,7 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); m_freem(m); return EINVAL; } diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c index 609cd7b883a..23628b67367 100644 --- a/sys/netinet/ip_esp.c +++ b/sys/netinet/ip_esp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp.c,v 1.22 1999/05/14 23:36:17 niklas Exp $ */ +/* $OpenBSD: ip_esp.c,v 1.23 1999/05/16 21:48:33 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -178,7 +178,7 @@ esp_input(m, va_alist) if (tdbp->tdb_first_use == 0) { tdbp->tdb_first_use = time.tv_sec; - tdb_expiration(tdbp, 0); + tdb_expiration(tdbp, TDBEXP_TIMEOUT); } ipn = *ipo; @@ -238,6 +238,8 @@ esp_input(m, va_alist) if (ipo->ip_p == IPPROTO_TCP || ipo->ip_p == IPPROTO_UDP) { struct tdb_ident *tdbi = NULL; + int s = spltdb(); + if (tdbp->tdb_bind_out) { tdbi = m->m_pkthdr.tdbi; @@ -258,6 +260,7 @@ esp_input(m, va_alist) no_mem: m->m_pkthdr.tdbi = tdbi; + splx(s); } else m->m_pkthdr.tdbi = NULL; diff --git a/sys/netinet/ip_esp_new.c b/sys/netinet/ip_esp_new.c index b725edacc72..8bad035922e 100644 --- a/sys/netinet/ip_esp_new.c +++ b/sys/netinet/ip_esp_new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp_new.c,v 1.42 1999/05/12 22:58:47 ho Exp $ */ +/* $OpenBSD: ip_esp_new.c,v 1.43 1999/05/16 21:48:35 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -495,7 +495,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); m_freem(m); return NULL; } @@ -866,7 +866,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); m_freem(m); return EINVAL; } diff --git a/sys/netinet/ip_esp_old.c b/sys/netinet/ip_esp_old.c index af389a112b8..b797313e87f 100644 --- a/sys/netinet/ip_esp_old.c +++ b/sys/netinet/ip_esp_old.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp_old.c,v 1.33 1999/05/12 22:58:48 ho Exp $ */ +/* $OpenBSD: ip_esp_old.c,v 1.34 1999/05/16 21:48:33 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -292,7 +292,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); m_freem(m); return NULL; } @@ -608,7 +608,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, TDBEXP_TIMEOUT); m_freem(m); return EINVAL; } diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c index 0dca0bc9f39..e70ce40d2ac 100644 --- a/sys/netinet/ip_ipsp.c +++ b/sys/netinet/ip_ipsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.c,v 1.41 1999/05/14 23:36:18 niklas Exp $ */ +/* $OpenBSD: ip_ipsp.c,v 1.42 1999/05/16 21:48:35 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -189,7 +189,7 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr) struct route_enc re0, *re = &re0; struct sockaddr_encap *dst; u_int8_t sa_require, sa_have; - int error, i; + int error, i, s; struct tdb *tdb = NULL; if (inp == NULL || ((so = inp->inp_socket) == 0)) @@ -198,7 +198,8 @@ 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; - + + s = spltdb(); if (!inp->inp_tdb) { bzero((caddr_t) re, sizeof(*re)); @@ -232,22 +233,23 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr) 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; + 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); + tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion, + gw->sen_ipsp_sproto); } RTFREE(re->re_rt); } } else tdb = inp->inp_tdb; - if (tdb) { - SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb); - } else - sa_have = 0; + if (tdb) + SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb); + else + sa_have = 0; + splx(s); /* Check if our requirements are met */ if (!(sa_require & ~sa_have)) @@ -304,15 +306,22 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr) 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); + int s = spltdb(); + + if (inp->inp_tdb) + { + if (inp->inp_tdb == tdb) + { + splx(s); + return; } - inp->inp_tdb = tdb; - TAILQ_INSERT_TAIL(&tdb->tdb_inp, inp, inp_tdb_next); + 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); + splx(s); - DPRINTF(("tdb_add_inp: tdb: %p, inp: %p\n", tdb, inp)); + DPRINTF(("tdb_add_inp: tdb: %p, inp: %p\n", tdb, inp)); } /* @@ -399,19 +408,21 @@ gettdb(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto) u_int8_t *ptr = (u_int8_t *) dst; u_int32_t hashval = proto + spi; struct tdb *tdbp; - int i; + int i, s; for (i = 0; i < SA_LEN(&dst->sa); i++) hashval += ptr[i]; hashval %= TDB_HASHMOD; + s = spltdb(); for (tdbp = tdbh[hashval]; tdbp; tdbp = tdbp->tdb_hnext) if ((tdbp->tdb_spi == spi) && !bcmp(&tdbp->tdb_dst, dst, SA_LEN(&dst->sa)) && (tdbp->tdb_sproto == proto)) break; - + splx(s); + return tdbp; } @@ -426,11 +437,15 @@ get_flow(void) return flow; } +/* + * Called at splsoftclock(). + */ + void handle_expirations(void *arg) { struct tdb *tdb; - + for (tdb = LIST_FIRST(&explist); tdb && tdb->tdb_timeout <= time.tv_sec; tdb = LIST_FIRST(&explist)) @@ -440,7 +455,7 @@ handle_expirations(void *arg) (tdb->tdb_exp_timeout <= time.tv_sec)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, 0); continue; } else @@ -448,7 +463,7 @@ handle_expirations(void *arg) (tdb->tdb_first_use + tdb->tdb_exp_first_use <= time.tv_sec)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); + tdb_delete(tdb, 0, 0); continue; } @@ -458,7 +473,7 @@ handle_expirations(void *arg) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); tdb->tdb_flags &= ~TDBF_SOFT_TIMER; - tdb_expiration(tdb, 1); + tdb_expiration(tdb, TDBEXP_EARLY); } else if ((tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) && @@ -467,7 +482,7 @@ handle_expirations(void *arg) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE; - tdb_expiration(tdb, 1); + tdb_expiration(tdb, TDBEXP_EARLY); } } @@ -481,10 +496,11 @@ handle_expirations(void *arg) * Ensure the tdb is in the right place in the expiration list. */ void -tdb_expiration(struct tdb *tdb, int early) +tdb_expiration(struct tdb *tdb, int flags) { u_int64_t next_timeout = 0; - struct tdb *t; + struct tdb *t, *former_expirer, *next_expirer; + int will_be_first, sole_reason, early, s; /* Find the earliest expiration. */ if ((tdb->tdb_flags & TDBF_FIRSTUSE) && tdb->tdb_first_use != 0 && @@ -506,30 +522,70 @@ tdb_expiration(struct tdb *tdb, int early) if (next_timeout == tdb->tdb_timeout) return; + s = spltdb(); + + /* + * Find out some useful facts: Will we our tdb be first to expire? + * Was our tdb the sole reason for the old timeout? + */ + former_expirer = TAILQ_FIRST(&expclusterlist); + next_expirer = LIST_NEXT(tdb, tdb_explink); + will_be_first = (next_timeout != 0 && + (former_expirer == NULL || + next_timeout < former_expirer->tdb_timeout)); + sole_reason = (tdb == former_expirer && + (next_expirer == NULL || + tdb->tdb_timeout != next_expirer->tdb_timeout)); + + /* + * We need to untimeout if either: + * - there is an expiration pending and the new timeout is earlier than + * what already exists or + * - the existing first expiration is due to our old timeout value solely + */ + if ((former_expirer != NULL && will_be_first) || sole_reason) + untimeout(handle_expirations, (void *) NULL); + + /* + * We need to timeout if we've been asked to and if either + * - our tdb has a timeout and no former expiration exist or + * - the new timeout is earlier than what already exists or + * - the existing first expiration is due to our old timeout value solely + * and another expiration is in the pipe. + */ + if ((flags & TDBEXP_TIMEOUT) && + (will_be_first || (sole_reason && next_expirer != NULL))) + timeout(handle_expirations, (void *) NULL, + hz * ((will_be_first ? next_timeout : + next_expirer->tdb_timeout) - time.tv_sec)); + /* Our old position, if any, is not relevant anymore. */ if (tdb->tdb_timeout != 0) { if (tdb->tdb_expnext.tqe_prev) { - if (LIST_NEXT(tdb, tdb_explink) && - tdb->tdb_timeout == LIST_NEXT(tdb, tdb_explink)->tdb_timeout) - TAILQ_INSERT_BEFORE(tdb, LIST_NEXT(tdb, tdb_explink), - tdb_expnext); + if (next_expirer && tdb->tdb_timeout == next_expirer->tdb_timeout) + TAILQ_INSERT_BEFORE(tdb, next_expirer, tdb_expnext); TAILQ_REMOVE(&expclusterlist, tdb, tdb_expnext); tdb->tdb_expnext.tqe_prev = NULL; } LIST_REMOVE(tdb, tdb_explink); } + tdb->tdb_timeout = next_timeout; + if (next_timeout == 0) + { + splx(s); return; + } /* - * Search fron-to-back if we believe we will end up early, otherwise + * Search front-to-back if we believe we will end up early, otherwise * back-to-front. */ - tdb->tdb_timeout = next_timeout; - for (t = (early ? TAILQ_FIRST(&expclusterlist) : + early = will_be_first || (flags & TDBEXP_EARLY); + for (t = (early ? former_expirer : TAILQ_LAST(&expclusterlist, expclusterlist_head)); t && (early ? (t->tdb_timeout <= next_timeout) : (t->tdb_timeout > next_timeout)); @@ -538,11 +594,7 @@ tdb_expiration(struct tdb *tdb, int early) ; if (early ? t == TAILQ_FIRST(&expclusterlist) : !t) { - /* - * We are to become the first expiration, remove old timer, if any. - */ - if (TAILQ_FIRST(&expclusterlist)) - untimeout(handle_expirations, (void *) NULL); + /* We are to become the first expiration. */ TAILQ_INSERT_HEAD(&expclusterlist, tdb, tdb_expnext); LIST_INSERT_HEAD(&explist, tdb, tdb_explink); } @@ -555,10 +607,13 @@ tdb_expiration(struct tdb *tdb, int early) TAILQ_INSERT_AFTER(&expclusterlist, t, tdb, tdb_expnext); LIST_INSERT_AFTER(t, tdb, tdb_explink); } - timeout(handle_expirations, (void *) NULL, - hz * (next_timeout - time.tv_sec)); + splx(s); } +/* + * Caller is responsible for setting at least spltdb(). + */ + struct flow * find_flow(union sockaddr_union *src, union sockaddr_union *srcmask, union sockaddr_union *dst, union sockaddr_union *dstmask, @@ -577,6 +632,10 @@ find_flow(union sockaddr_union *src, union sockaddr_union *srcmask, return (struct flow *) NULL; } +/* + * Caller is responsible for setting at least spltdb(). + */ + struct flow * find_global_flow(union sockaddr_union *src, union sockaddr_union *srcmask, union sockaddr_union *dst, union sockaddr_union *dstmask, @@ -587,11 +646,12 @@ find_global_flow(union sockaddr_union *src, union sockaddr_union *srcmask, int i; for (i = 0; i < TDB_HASHMOD; i++) - for (tdb = tdbh[i]; tdb; tdb = tdb->tdb_hnext) - if ((flow = find_flow(src, srcmask, dst, dstmask, proto, tdb)) != - (struct flow *) NULL) - return flow; - + { + for (tdb = tdbh[i]; tdb; tdb = tdb->tdb_hnext) + if ((flow = find_flow(src, srcmask, dst, dstmask, proto, tdb)) != + (struct flow *) NULL) + return flow; + } return (struct flow *) NULL; } @@ -600,15 +660,22 @@ puttdb(struct tdb *tdbp) { u_int8_t *ptr = (u_int8_t *) &tdbp->tdb_dst; u_int32_t hashval = tdbp->tdb_sproto + tdbp->tdb_spi, i; + int s; for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++) hashval += ptr[i]; hashval %= TDB_HASHMOD; + s = spltdb(); tdbp->tdb_hnext = tdbh[hashval]; tdbh[hashval] = tdbp; + splx(s); } +/* + * Caller is responsible for setting at least spltdb(). + */ + void put_flow(struct flow *flow, struct tdb *tdb) { @@ -623,6 +690,10 @@ put_flow(struct flow *flow, struct tdb *tdb) flow->flow_next->flow_prev = flow; } +/* + * Caller is responsible for setting at least spltdb(). + */ + void delete_flow(struct flow *flow, struct tdb *tdb) { @@ -645,19 +716,21 @@ delete_flow(struct flow *flow, struct tdb *tdb) FREE(flow, M_TDB); } -int -tdb_delete(struct tdb *tdbp, int delchain) +void +tdb_delete(struct tdb *tdbp, int delchain, int expflags) { 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; + int s; for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++) hashval += ptr[i]; hashval %= TDB_HASHMOD; + s = spltdb(); if (tdbh[hashval] == tdbp) { tdbpp = tdbp; @@ -716,18 +789,12 @@ tdb_delete(struct tdb *tdbp, int delchain) if (tdbp->tdb_bind_out) TAILQ_REMOVE(&tdbp->tdb_bind_out->tdb_bind_in, tdbp, tdb_bind_in_next); + /* Remove us from the expiration lists. */ if (tdbp->tdb_timeout != 0) { - if (tdbp->tdb_expnext.tqe_prev) - { - if (LIST_NEXT(tdbp, tdb_explink) && - tdbp->tdb_timeout == LIST_NEXT(tdbp, tdb_explink)->tdb_timeout) - TAILQ_INSERT_BEFORE(tdbp, LIST_NEXT(tdbp, tdb_explink), - tdb_expnext); - TAILQ_REMOVE(&expclusterlist, tdbp, tdb_expnext); - tdbp->tdb_expnext.tqe_prev = NULL; - } - LIST_REMOVE(tdbp, tdb_explink); + tdbp->tdb_flags &= ~(TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE | TDBF_TIMER | + TDBF_SOFT_TIMER); + tdb_expiration(tdbp, expflags); } if (tdbp->tdb_srcid) @@ -739,9 +806,8 @@ tdb_delete(struct tdb *tdbp, int delchain) FREE(tdbp, M_TDB); if (delchain && tdbpp) - return tdb_delete(tdbpp, delchain); - else - return 0; + tdb_delete(tdbpp, delchain, expflags); + splx(s); } int @@ -777,7 +843,7 @@ ipsp_kern(int off, char **bufp, int len) static char buffer[IPSEC_KERNFS_BUFSIZE]; struct flow *flow; struct tdb *tdb, *tdbp; - int l, i; + int l, i, s; if (off == 0) kernfs_epoch++; @@ -790,216 +856,225 @@ ipsp_kern(int off, char **bufp, int len) *bufp = buffer; for (i = 0; i < TDB_HASHMOD; i++) - for (tdb = tdbh[i]; tdb; tdb = tdb->tdb_hnext) - if (tdb->tdb_epoch != kernfs_epoch) - { - tdb->tdb_epoch = kernfs_epoch; - - l = sprintf(buffer, "SPI = %08x, Destination = %s, Sproto = %u\n", - ntohl(tdb->tdb_spi), - ipsp_address(tdb->tdb_dst), tdb->tdb_sproto); - - l += sprintf(buffer + l, "\tEstablished %d seconds ago\n", - time.tv_sec - tdb->tdb_established); - - l += sprintf(buffer + l, "\tSource = %s", - ipsp_address(tdb->tdb_src)); - - if (tdb->tdb_proxy.sa.sa_family) - l += sprintf(buffer + l, ", Proxy = %s\n", - ipsp_address(tdb->tdb_proxy)); - else - l += sprintf(buffer + l, "\n"); - - l += sprintf(buffer + l, "\tFlags (%08x) = <", tdb->tdb_flags); - - if ((tdb->tdb_flags & ~(TDBF_TIMER | TDBF_BYTES | - TDBF_ALLOCATIONS | TDBF_FIRSTUSE | - TDBF_SOFT_TIMER | TDBF_SOFT_BYTES | - TDBF_SOFT_FIRSTUSE | - TDBF_SOFT_ALLOCATIONS)) == 0) - l += sprintf(buffer + l, "none>\n"); - else - { - /* We can reuse variable 'i' here, since we're not looping */ - i = 0; - - if (tdb->tdb_flags & TDBF_UNIQUE) - { - if (i) - l += sprintf(buffer + l, ", "); - else - i = 1; - - l += sprintf(buffer + l, "unique"); - i = 1; - } - - if (tdb->tdb_flags & TDBF_INVALID) - { - if (i) - l += sprintf(buffer + l, ", "); - else - i = 1; - - l += sprintf(buffer + l, "invalid"); - } - - if (tdb->tdb_flags & TDBF_HALFIV) - { - if (i) - l += sprintf(buffer + l, ", "); - else - i = 1; - - l += sprintf(buffer + l, "halfiv"); - } - - if (tdb->tdb_flags & TDBF_PFS) - { - if (i) - l += sprintf(buffer + l, ", "); - else + { + s = spltdb(); + for (tdb = tdbh[i]; tdb; tdb = tdb->tdb_hnext) + if (tdb->tdb_epoch != kernfs_epoch) + { + tdb->tdb_epoch = kernfs_epoch; + + l = sprintf(buffer, + "SPI = %08x, Destination = %s, Sproto = %u\n", + ntohl(tdb->tdb_spi), + ipsp_address(tdb->tdb_dst), tdb->tdb_sproto); + + l += sprintf(buffer + l, "\tEstablished %d seconds ago\n", + time.tv_sec - tdb->tdb_established); + + l += sprintf(buffer + l, "\tSource = %s", + ipsp_address(tdb->tdb_src)); + + if (tdb->tdb_proxy.sa.sa_family) + l += sprintf(buffer + l, ", Proxy = %s\n", + ipsp_address(tdb->tdb_proxy)); + else + l += sprintf(buffer + l, "\n"); + + l += sprintf(buffer + l, "\tFlags (%08x) = <", tdb->tdb_flags); + + if ((tdb->tdb_flags & ~(TDBF_TIMER | TDBF_BYTES | + TDBF_ALLOCATIONS | TDBF_FIRSTUSE | + TDBF_SOFT_TIMER | TDBF_SOFT_BYTES | + TDBF_SOFT_FIRSTUSE | + TDBF_SOFT_ALLOCATIONS)) == 0) + l += sprintf(buffer + l, "none>\n"); + else + { + /* We can reuse variable 'i' here, since we're not looping */ + i = 0; + + if (tdb->tdb_flags & TDBF_UNIQUE) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "unique"); i = 1; + } + + if (tdb->tdb_flags & TDBF_INVALID) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "invalid"); + } + + if (tdb->tdb_flags & TDBF_HALFIV) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "halfiv"); + } + + if (tdb->tdb_flags & TDBF_PFS) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "pfs"); + } + + if (tdb->tdb_flags & TDBF_TUNNELING) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "tunneling"); + } + + l += sprintf(buffer + l, ">\n"); + } + + if (tdb->tdb_xform) + l += sprintf(buffer + l, "\txform = <%s>\n", + tdb->tdb_xform->xf_name); + + if (tdb->tdb_encalgxform) + l += sprintf(buffer + l, "\t\tEncryption = <%s>\n", + tdb->tdb_encalgxform->name); + + if (tdb->tdb_authalgxform) + 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"); - l += sprintf(buffer + l, "pfs"); - } + if (tdb->tdb_onext) + l += sprintf(buffer + l, + "\tNext SA: SPI = %08x, " + "Destination = %s, Sproto = %u\n", + ntohl(tdb->tdb_onext->tdb_spi), + ipsp_address(tdb->tdb_onext->tdb_dst), + tdb->tdb_onext->tdb_sproto); - if (tdb->tdb_flags & TDBF_TUNNELING) - { - if (i) - l += sprintf(buffer + l, ", "); - else - i = 1; + if (tdb->tdb_inext) + l += sprintf(buffer + l, + "\tPrevious SA: SPI = %08x, " + "Destination = %s, Sproto = %u\n", + ntohl(tdb->tdb_inext->tdb_spi), + ipsp_address(tdb->tdb_inext->tdb_dst), + tdb->tdb_inext->tdb_sproto); - l += sprintf(buffer + l, "tunneling"); - } + for (i = 0, flow = tdb->tdb_flow; flow; flow = flow->flow_next) + i++; - l += sprintf(buffer + l, ">\n"); - } + l+= sprintf(buffer + l, "\tCurrently used by %d flows\n", i); - if (tdb->tdb_xform) - l += sprintf(buffer + l, "\txform = <%s>\n", - tdb->tdb_xform->xf_name); - - if (tdb->tdb_encalgxform) - l += sprintf(buffer + l, "\t\tEncryption = <%s>\n", - tdb->tdb_encalgxform->name); - - if (tdb->tdb_authalgxform) - 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, " - "Destination = %s, Sproto = %u\n", - ntohl(tdb->tdb_onext->tdb_spi), - ipsp_address(tdb->tdb_onext->tdb_dst), - tdb->tdb_onext->tdb_sproto); - - if (tdb->tdb_inext) - l += sprintf(buffer + l, - "\tPrevious SA: SPI = %08x, " - "Destination = %s, Sproto = %u\n", - ntohl(tdb->tdb_inext->tdb_spi), - ipsp_address(tdb->tdb_inext->tdb_dst), - tdb->tdb_inext->tdb_sproto); - - for (i = 0, flow = tdb->tdb_flow; flow; flow = flow->flow_next) - i++; - - l+= sprintf(buffer + l, "\tCurrently used by %d flows\n", i); - - l += sprintf(buffer + l, "\t%u flows have used this SA\n", - tdb->tdb_cur_allocations); + l += sprintf(buffer + l, "\t%u flows have used this SA\n", + tdb->tdb_cur_allocations); - l += sprintf(buffer + l, "\t%qu bytes processed by this SA\n", + l += sprintf(buffer + l, "\t%qu bytes processed by this SA\n", tdb->tdb_cur_bytes); - l += sprintf(buffer + l, "\tExpirations:\n"); + l += sprintf(buffer + l, "\tExpirations:\n"); - if (tdb->tdb_flags & TDBF_TIMER) - l += sprintf(buffer + l, - "\t\tHard expiration(1) in %qu seconds\n", - tdb->tdb_exp_timeout - time.tv_sec); - - if (tdb->tdb_flags & TDBF_SOFT_TIMER) - l += sprintf(buffer + l, - "\t\tSoft expiration(1) in %qu seconds\n", - tdb->tdb_soft_timeout - time.tv_sec); + if (tdb->tdb_flags & TDBF_TIMER) + l += sprintf(buffer + l, + "\t\tHard expiration(1) in %qu seconds\n", + tdb->tdb_exp_timeout - time.tv_sec); - if (tdb->tdb_flags & TDBF_BYTES) - l += sprintf(buffer + l, "\t\tHard expiration after %qu bytes\n", - tdb->tdb_exp_bytes); + if (tdb->tdb_flags & TDBF_SOFT_TIMER) + l += sprintf(buffer + l, + "\t\tSoft expiration(1) in %qu seconds\n", + tdb->tdb_soft_timeout - time.tv_sec); - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - l += sprintf(buffer + l, "\t\tSoft expiration after %qu bytes\n", - tdb->tdb_soft_bytes); - - if (tdb->tdb_flags & TDBF_ALLOCATIONS) - l += sprintf(buffer + l, - "\t\tHard expiration after %u flows\n", - tdb->tdb_exp_allocations); + if (tdb->tdb_flags & TDBF_BYTES) + l += sprintf(buffer + l, + "\t\tHard expiration after %qu bytes\n", + tdb->tdb_exp_bytes); - if (tdb->tdb_flags & TDBF_SOFT_ALLOCATIONS) - l += sprintf(buffer + l, - "\t\tSoft expiration after %u flows\n", - tdb->tdb_soft_allocations); + if (tdb->tdb_flags & TDBF_SOFT_BYTES) + l += sprintf(buffer + l, + "\t\tSoft expiration after %qu bytes\n", + tdb->tdb_soft_bytes); - if (tdb->tdb_flags & TDBF_FIRSTUSE) - { - if (tdb->tdb_first_use) + if (tdb->tdb_flags & TDBF_ALLOCATIONS) l += sprintf(buffer + l, - "\t\tHard expiration(2) in %qu seconds\n", - (tdb->tdb_first_use + tdb->tdb_exp_first_use) - - time.tv_sec); - else + "\t\tHard expiration after %u flows\n", + tdb->tdb_exp_allocations); + + if (tdb->tdb_flags & TDBF_SOFT_ALLOCATIONS) l += sprintf(buffer + l, - "\t\tHard expiration in %qu seconds after first " - "use\n", tdb->tdb_exp_first_use); - } - - if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) - { - if (tdb->tdb_first_use) - l += sprintf(buffer + l, - "\t\tSoft expiration(2) in %qu seconds\n", - (tdb->tdb_first_use + tdb->tdb_soft_first_use) - - time.tv_sec); - else - l += sprintf(buffer + l, - "\t\tSoft expiration in %qu seconds after first " - "use\n", tdb->tdb_soft_first_use); - } + "\t\tSoft expiration after %u flows\n", + tdb->tdb_soft_allocations); + + if (tdb->tdb_flags & TDBF_FIRSTUSE) + { + if (tdb->tdb_first_use) + l += sprintf(buffer + l, + "\t\tHard expiration(2) in %qu seconds\n", + (tdb->tdb_first_use + + tdb->tdb_exp_first_use) - time.tv_sec); + else + l += sprintf(buffer + l, + "\t\tHard expiration in %qu seconds " + "after first use\n", + tdb->tdb_exp_first_use); + } + + if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) + { + if (tdb->tdb_first_use) + l += sprintf(buffer + l, + "\t\tSoft expiration(2) in %qu seconds\n", + (tdb->tdb_first_use + + tdb->tdb_soft_first_use) - time.tv_sec); + else + l += sprintf(buffer + l, + "\t\tSoft expiration in %qu seconds " + "after first use\n", + tdb->tdb_soft_first_use); + } + + if (!(tdb->tdb_flags & + (TDBF_TIMER | TDBF_SOFT_TIMER | TDBF_BYTES | + TDBF_SOFT_ALLOCATIONS | TDBF_ALLOCATIONS | + TDBF_SOFT_BYTES | TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE))) + l += sprintf(buffer + l, "\t\t(none)\n"); - if (!(tdb->tdb_flags & (TDBF_TIMER | TDBF_SOFT_TIMER | TDBF_BYTES | - TDBF_SOFT_ALLOCATIONS | TDBF_ALLOCATIONS | - TDBF_SOFT_BYTES | TDBF_FIRSTUSE | - TDBF_SOFT_FIRSTUSE))) - l += sprintf(buffer + l, "\t\t(none)\n"); + l += sprintf(buffer + l, "\n"); - l += sprintf(buffer + l, "\n"); - - return l; - } - + splx(s); + return l; + } + splx(s); + } return 0; } diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index 931f32a0ba3..6add9b5721a 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.31 1999/05/14 23:36:21 niklas Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.32 1999/05/16 21:48:37 niklas Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -376,6 +376,13 @@ htonq(u_int64_t q) #endif #ifdef _KERNEL + +/* + * Protects all tdb lists. + * Must at least be splsoftclock. + */ +#define spltdb splsoftclock + extern int encdebug; extern int ipsec_in_use; extern u_int8_t hmac_ipad_buffer[64]; @@ -392,17 +399,19 @@ extern struct xformsw xformsw[], *xformswNXFORMSW; /* Traverse spi chain and get attributes */ -#define SPI_CHAIN_ATTRIB(have, TDB_DIR, TDBP) {\ +#define SPI_CHAIN_ATTRIB(have, TDB_DIR, TDBP) do {\ + int s = spltdb(); \ struct tdb *tmptdb = (TDBP); \ - (have) = 0; \ \ + (have) = 0; \ while (tmptdb && tmptdb->tdb_xform) { \ if (tmptdb == NULL || tmptdb->tdb_flags & TDBF_INVALID) \ break; \ (have) |= TDB_ATTRIB(tmptdb); \ tmptdb = tmptdb->TDB_DIR; \ } \ -} + splx(s); \ +} while (0) /* Misc. */ extern char *inet_ntoa4(struct in_addr); @@ -414,9 +423,12 @@ 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); extern void puttdb(struct tdb *); -extern int tdb_delete(struct tdb *, int); +extern void tdb_delete(struct tdb *, int, int); extern int tdb_init (struct tdb *, u_int16_t, struct ipsecinit *); extern void tdb_expiration(struct tdb *, int); +/* Flag values for the last argument of tdb_expiration(). */ +#define TDBEXP_EARLY 1 /* The tdb is likely to end up early. */ +#define TDBEXP_TIMEOUT 2 /* Maintain expiration timeout. */ extern void handle_expirations(void *); /* Flow management routines */ diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 5d76c833c39..54d28859028 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.46 1999/05/14 23:36:20 niklas Exp $ */ +/* $OpenBSD: ip_output.c,v 1.47 1999/05/16 21:48:36 niklas Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -175,6 +175,7 @@ ip_output(m0, va_alist) struct route_enc re0, *re = &re0; struct sockaddr_encap *ddst, *gw; struct tdb *tdb, *t; + int s; u_int8_t sa_require, sa_have = 0; if (inp == NULL) @@ -184,6 +185,11 @@ ip_output(m0, va_alist) bzero((caddr_t) re, sizeof(*re)); + /* + * splnet is chosen over spltdb because we are not allowed to + * lower the level, and udp_output calls us in splnet(). + */ + s = splnet(); /* Check if there was a bound outgoing SA */ if (inp && inp->inp_tdb && (inp->inp_tdb->tdb_dst.sin.sin_addr.s_addr == @@ -194,8 +200,10 @@ ip_output(m0, va_alist) goto have_tdb; } - if (!ipsec_in_use) + if (!ipsec_in_use) { + splx(s); goto no_encap; + } ddst = (struct sockaddr_encap *) &re->re_dst; ddst->sen_family = PF_KEY; @@ -236,8 +244,10 @@ ip_output(m0, va_alist) } rtalloc((struct route *) re); - if (re->re_rt == NULL) + if (re->re_rt == NULL) { + splx(s); goto no_encap; + } gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway); @@ -248,10 +258,13 @@ ip_output(m0, va_alist) */ if ((gw != NULL) && (gw->sen_ipsp_dst.s_addr == 0) && - (gw->sen_ipsp_sproto == 0) && (gw->sen_ipsp_spi == 0)) + (gw->sen_ipsp_sproto == 0) && (gw->sen_ipsp_spi == 0)) { + splx(s); goto no_encap; + } if (gw == NULL || gw->sen_type != SENT_IPSP) { + splx(s); DPRINTF(("ip_output(): no gw or gw data not IPSP\n")); if (re->re_rt) @@ -272,6 +285,8 @@ ip_output(m0, va_alist) /* XXX PF_KEYv2 notification message */ + splx(s); + /* * When sa_require is set, the packet will be dropped * at no_encap. @@ -309,6 +324,7 @@ ip_output(m0, va_alist) goto no_encap; if (tdb == NULL) { + splx(s); DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto)); if (re->re_rt) @@ -364,6 +380,7 @@ ip_output(m0, va_alist) } if (ro->ro_rt == 0) { + splx(s); ipstat.ips_noroute++; error = EHOSTUNREACH; m_freem(m); @@ -379,6 +396,7 @@ ip_output(m0, va_alist) while (tdb && tdb->tdb_xform) { /* Check if the SPI is invalid */ if (tdb->tdb_flags & TDBF_INVALID) { + splx(s); 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); if (re->re_rt) @@ -389,7 +407,7 @@ ip_output(m0, va_alist) /* Register first use, setup expiration timer */ if (tdb->tdb_first_use == 0) { tdb->tdb_first_use = time.tv_sec; - tdb_expiration(tdb, 0); + tdb_expiration(tdb, TDBEXP_TIMEOUT); } /* Check for tunneling */ @@ -411,6 +429,7 @@ ip_output(m0, va_alist) if (mp == NULL) error = EFAULT; if (error) { + splx(s); if (re->re_rt) RTFREE(re->re_rt); return error; @@ -433,6 +452,7 @@ ip_output(m0, va_alist) if (!error && mp == NULL) error = EFAULT; if (error) { + splx(s); if (mp != NULL) m_freem(mp); if (re->re_rt) @@ -447,6 +467,7 @@ ip_output(m0, va_alist) tdb = tdb->tdb_onext; } + splx(s); /* * At this point, m is pointing to an mbuf chain with the @@ -866,6 +887,9 @@ ip_ctloutput(op, so, level, optname, mp) register int optval = 0; #ifdef IPSEC struct proc *p = curproc; /* XXX */ + struct tdb *tdb; + struct tdb_ident *tdbip, tdbi; + int s; #endif int error = 0; @@ -967,22 +991,19 @@ ip_ctloutput(op, so, level, optname, mp) #ifndef IPSEC error = EINVAL; #else + s = spltdb(); 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) { + tdbip = mtod(m, struct tdb_ident *); + tdb = gettdb(tdbip->spi, &tdbip->dst, + tdbip->proto); + if (tdb == NULL) error = ESRCH; - break; - } - tdb_add_inp(tdb, inp); + else + tdb_add_inp(tdb, inp); } + splx(s); #endif /* IPSEC */ break; @@ -1118,19 +1139,19 @@ ip_ctloutput(op, so, level, optname, mp) #ifndef IPSEC error = EINVAL; #else + s = spltdb(); 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); + (unsigned)m->m_len); } + splx(s); #endif /* IPSEC */ break; |