summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1999-05-16 21:48:38 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1999-05-16 21:48:38 +0000
commitfa7bc152efa100d5d1d9f1d773f4d4128756a1a8 (patch)
treef140c66f26582a93ecb15f4b9336f7e7c4746763
parent60416e45015c3b4729c79c59c1322d58b4146410 (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.c468
-rw-r--r--sys/netinet/in_pcb.c4
-rw-r--r--sys/netinet/ip_ah.c7
-rw-r--r--sys/netinet/ip_ah_new.c6
-rw-r--r--sys/netinet/ip_ah_old.c6
-rw-r--r--sys/netinet/ip_esp.c7
-rw-r--r--sys/netinet/ip_esp_new.c6
-rw-r--r--sys/netinet/ip_esp_old.c6
-rw-r--r--sys/netinet/ip_ipsp.c585
-rw-r--r--sys/netinet/ip_ipsp.h22
-rw-r--r--sys/netinet/ip_output.c59
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;