Print this page
12694 race between write() and shutdown() for unix sockets
*** 23,33 ****
* Use is subject to license terms.
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
! * Copyright (c) 2018, Joyent, Inc.
*/
/*
* Multithreaded STREAMS Local Transport Provider.
*
--- 23,33 ----
* Use is subject to license terms.
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
! * Copyright 2020 Joyent, Inc.
*/
/*
* Multithreaded STREAMS Local Transport Provider.
*
*** 374,385 ****
*/
/*
* Local declarations
*/
- #define NEXTSTATE(EV, ST) ti_statetbl[EV][ST]
-
#define BADSEQNUM (-1) /* initial seq number used by T_DISCON_IND */
#define TL_BUFWAIT (10000) /* usecs to wait for allocb buffer timeout */
#define TL_TIDUSZ (64*1024) /* tidu size when "strmsgz" is unlimited (0) */
/*
* Hash tables size.
--- 374,383 ----
*** 415,433 ****
* LOCAL MACROS
*/
#define T_ALIGN(p) P2ROUNDUP((p), sizeof (t_scalar_t))
/*
- * EXTERNAL VARIABLE DECLARATIONS
- * -----------------------------
- */
- /*
- * state table defined in the OS space.c
- */
- extern char ti_statetbl[TE_NOEVENTS][TS_NOSTATES];
-
- /*
* STREAMS DRIVER ENTRY POINTS PROTOTYPES
*/
static int tl_open(queue_t *, dev_t *, int, int, cred_t *);
static int tl_close(queue_t *, int, cred_t *);
static int tl_wput(queue_t *, mblk_t *);
--- 413,422 ----
*** 821,830 ****
--- 810,895 ----
static int tl_disable_early_connect = 0;
static int tl_client_closing_when_accepting;
static int tl_serializer_noswitch;
+ #define nr 127 /* not reachable */
+
+ #define TE_NOEVENTS 28
+
+ static char nextstate[TE_NOEVENTS][TS_NOSTATES] = {
+ /* STATES */
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
+
+ /* Initialization events */
+
+ #define TE_BIND_REQ 0 /* bind request */
+ { 1, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_UNBIND_REQ 1 /* unbind request */
+ {nr, nr, nr, 2, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_OPTMGMT_REQ 2 /* manage options req */
+ {nr, nr, nr, 4, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_BIND_ACK 3 /* bind acknowledment */
+ {nr, 3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_OPTMGMT_ACK 4 /* manage options ack */
+ {nr, nr, nr, nr, 3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_ERROR_ACK 5 /* error acknowledgment */
+ {nr, 0, 3, nr, 3, 3, nr, nr, 7, nr, nr, nr, 6, 7, 9, 10, 11},
+ #define TE_OK_ACK1 6 /* ok ack seqcnt == 0 */
+ {nr, nr, 0, nr, nr, 6, nr, nr, nr, nr, nr, nr, 3, nr, 3, 3, 3},
+ #define TE_OK_ACK2 7 /* ok ack seqcnt == 1, q == resq */
+ {nr, nr, nr, nr, nr, nr, nr, nr, 9, nr, nr, nr, nr, 3, nr, nr, nr},
+ #define TE_OK_ACK3 8 /* ok ack seqcnt == 1, q != resq */
+ {nr, nr, nr, nr, nr, nr, nr, nr, 3, nr, nr, nr, nr, 3, nr, nr, nr},
+ #define TE_OK_ACK4 9 /* ok ack seqcnt > 1 */
+ {nr, nr, nr, nr, nr, nr, nr, nr, 7, nr, nr, nr, nr, 7, nr, nr, nr},
+
+ /* Connection oriented events */
+ #define TE_CONN_REQ 10 /* connection request */
+ {nr, nr, nr, 5, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_CONN_RES 11 /* connection response */
+ {nr, nr, nr, nr, nr, nr, nr, 8, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_DISCON_REQ 12 /* disconnect request */
+ {nr, nr, nr, nr, nr, nr, 12, 13, nr, 14, 15, 16, nr, nr, nr, nr, nr},
+ #define TE_DATA_REQ 13 /* data request */
+ {nr, nr, nr, nr, nr, nr, nr, nr, nr, 9, nr, 11, nr, nr, nr, nr, nr},
+ #define TE_EXDATA_REQ 14 /* expedited data request */
+ {nr, nr, nr, nr, nr, nr, nr, nr, nr, 9, nr, 11, nr, nr, nr, nr, nr},
+ #define TE_ORDREL_REQ 15 /* orderly release req */
+ {nr, nr, nr, nr, nr, nr, nr, nr, nr, 10, nr, 3, nr, nr, nr, nr, nr},
+ #define TE_CONN_IND 16 /* connection indication */
+ {nr, nr, nr, 7, nr, nr, nr, 7, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_CONN_CON 17 /* connection confirmation */
+ {nr, nr, nr, nr, nr, nr, 9, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_DATA_IND 18 /* data indication */
+ {nr, nr, nr, nr, nr, nr, nr, nr, nr, 9, 10, nr, nr, nr, nr, nr, nr},
+ #define TE_EXDATA_IND 19 /* expedited data indication */
+ {nr, nr, nr, nr, nr, nr, nr, nr, nr, 9, 10, nr, nr, nr, nr, nr, nr},
+ #define TE_ORDREL_IND 20 /* orderly release ind */
+ {nr, nr, nr, nr, nr, nr, nr, nr, nr, 11, 3, nr, nr, nr, nr, nr, nr},
+ #define TE_DISCON_IND1 21 /* disconnect indication seq == 0 */
+ {nr, nr, nr, nr, nr, nr, 3, nr, nr, 3, 3, 3, nr, nr, nr, nr, nr},
+ #define TE_DISCON_IND2 22 /* disconnect indication seq == 1 */
+ {nr, nr, nr, nr, nr, nr, nr, 3, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_DISCON_IND3 23 /* disconnect indication seq > 1 */
+ {nr, nr, nr, nr, nr, nr, nr, 7, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_PASS_CONN 24 /* pass connection */
+ {nr, nr, nr, 9, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+
+
+ /* Unit data events */
+
+ #define TE_UNITDATA_REQ 25 /* unitdata request */
+ {nr, nr, nr, 3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_UNITDATA_IND 26 /* unitdata indication */
+ {nr, nr, nr, 3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ #define TE_UDERROR_IND 27 /* unitdata error indication */
+ {nr, nr, nr, 3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
+ };
+
+
+
/*
* LOCAL FUNCTION PROTOTYPES
* -------------------------
*/
static boolean_t tl_eqaddr(tl_addr_t *, tl_addr_t *);
*** 1953,1964 ****
!peer_tep->te_closing &&
((tep->te_state == TS_DATA_XFER) ||
(tep->te_state == TS_WREQ_ORDREL)) &&
(tep->te_wq != NULL) &&
(tep->te_wq->q_first == NULL) &&
! ((peer_tep->te_state == TS_DATA_XFER) ||
! (peer_tep->te_state == TS_WREQ_ORDREL)) &&
((peer_rq = peer_tep->te_rq) != NULL) &&
(canputnext(peer_rq) || tep->te_closing)) {
putnext(peer_rq, mp);
} else if (tep->te_closing) {
/*
--- 2018,2030 ----
!peer_tep->te_closing &&
((tep->te_state == TS_DATA_XFER) ||
(tep->te_state == TS_WREQ_ORDREL)) &&
(tep->te_wq != NULL) &&
(tep->te_wq->q_first == NULL) &&
! (peer_tep->te_state == TS_DATA_XFER ||
! peer_tep->te_state == TS_WIND_ORDREL ||
! peer_tep->te_state == TS_WREQ_ORDREL) &&
((peer_rq = peer_tep->te_rq) != NULL) &&
(canputnext(peer_rq) || tep->te_closing)) {
putnext(peer_rq, mp);
} else if (tep->te_closing) {
/*
*** 2380,2390 ****
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
! tep->te_state = NEXTSTATE(TE_BIND_REQ, tep->te_state);
ASSERT((bind->PRIM_type == O_T_BIND_REQ) ||
(bind->PRIM_type == T_BIND_REQ));
alen = bind->ADDR_length;
--- 2446,2456 ----
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
! tep->te_state = nextstate[TE_BIND_REQ][tep->te_state];
ASSERT((bind->PRIM_type == O_T_BIND_REQ) ||
(bind->PRIM_type == T_BIND_REQ));
alen = bind->ADDR_length;
*** 2420,2430 ****
(aoff < 0) ||
(aoff + alen > msz)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: invalid socket addr"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
/* Copy address from message to local buffer. */
--- 2486,2496 ----
(aoff < 0) ||
(aoff + alen > msz)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: invalid socket addr"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
/* Copy address from message to local buffer. */
*** 2435,2465 ****
if ((ux_addr.soua_magic != SOU_MAGIC_EXPLICIT) &&
(ux_addr.soua_magic != SOU_MAGIC_IMPLICIT)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: invalid socket magic"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
if ((ux_addr.soua_magic == SOU_MAGIC_IMPLICIT) &&
(ux_addr.soua_vp != NULL)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: implicit addr non-empty"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
if ((ux_addr.soua_magic == SOU_MAGIC_EXPLICIT) &&
(ux_addr.soua_vp == NULL)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: explicit addr empty"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
} else {
--- 2501,2531 ----
if ((ux_addr.soua_magic != SOU_MAGIC_EXPLICIT) &&
(ux_addr.soua_magic != SOU_MAGIC_IMPLICIT)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: invalid socket magic"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
if ((ux_addr.soua_magic == SOU_MAGIC_IMPLICIT) &&
(ux_addr.soua_vp != NULL)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: implicit addr non-empty"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
if ((ux_addr.soua_magic == SOU_MAGIC_EXPLICIT) &&
(ux_addr.soua_vp == NULL)) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: explicit addr empty"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
} else {
*** 2467,2486 ****
((ssize_t)(aoff + alen) > msz) ||
((aoff + alen) < 0))) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: invalid message"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
if ((alen < 0) || (alen > (msz - sizeof (struct T_bind_req)))) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: bad addr in message"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tli_err = TBADADDR;
goto error;
}
#ifdef DEBUG
/*
--- 2533,2552 ----
((ssize_t)(aoff + alen) > msz) ||
((aoff + alen) < 0))) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: invalid message"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tli_err = TSYSERR;
unix_err = EINVAL;
goto error;
}
if ((alen < 0) || (alen > (msz - sizeof (struct T_bind_req)))) {
(void) (STRLOG(TL_ID, tep->te_minor,
1, SL_TRACE | SL_ERROR,
"tl_bind: bad addr in message"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tli_err = TBADADDR;
goto error;
}
#ifdef DEBUG
/*
*** 2642,2652 ****
tep->te_qlen = qlen;
if (qlen > 0)
tep->te_flag |= TL_LISTENER;
}
! tep->te_state = NEXTSTATE(TE_BIND_ACK, tep->te_state);
/*
* send T_BIND_ACK message
*/
(void) qreply(wq, bamp);
return;
--- 2708,2718 ----
tep->te_qlen = qlen;
if (qlen > 0)
tep->te_flag |= TL_LISTENER;
}
! tep->te_state = nextstate[TE_BIND_ACK][tep->te_state];
/*
* send T_BIND_ACK message
*/
(void) qreply(wq, bamp);
return;
*** 2659,2669 ****
*/
tep->te_state = save_state;
tl_memrecover(wq, mp, sizeof (struct T_error_ack));
return;
}
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tl_error_ack(wq, ackmp, tli_err, unix_err, save_prim_type);
}
/*
* Process T_UNBIND_REQ.
--- 2725,2735 ----
*/
tep->te_state = save_state;
tl_memrecover(wq, mp, sizeof (struct T_error_ack));
return;
}
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tl_error_ack(wq, ackmp, tli_err, unix_err, save_prim_type);
}
/*
* Process T_UNBIND_REQ.
*** 2705,2715 ****
"tl_wput:T_UNBIND_REQ:out of state, state=%d",
tep->te_state));
tl_error_ack(wq, ackmp, TOUTSTATE, 0, T_UNBIND_REQ);
return;
}
! tep->te_state = NEXTSTATE(TE_UNBIND_REQ, tep->te_state);
/*
* TPI says on T_UNBIND_REQ:
* send up a M_FLUSH to flush both
* read and write queues
--- 2771,2781 ----
"tl_wput:T_UNBIND_REQ:out of state, state=%d",
tep->te_state));
tl_error_ack(wq, ackmp, TOUTSTATE, 0, T_UNBIND_REQ);
return;
}
! tep->te_state = nextstate[TE_UNBIND_REQ][tep->te_state];
/*
* TPI says on T_UNBIND_REQ:
* send up a M_FLUSH to flush both
* read and write queues
*** 2725,2735 ****
* We allow rebind with a new qlen value.
*/
tl_addr_unbind(tep);
}
! tep->te_state = NEXTSTATE(TE_OK_ACK1, tep->te_state);
/*
* send T_OK_ACK
*/
tl_ok_ack(wq, ackmp, T_UNBIND_REQ);
}
--- 2791,2801 ----
* We allow rebind with a new qlen value.
*/
tl_addr_unbind(tep);
}
! tep->te_state = nextstate[TE_OK_ACK1][tep->te_state];
/*
* send T_OK_ACK
*/
tl_ok_ack(wq, ackmp, T_UNBIND_REQ);
}
*** 2963,2973 ****
tl_error_ack(wq, ackmp, TOUTSTATE, 0, T_CONN_REQ);
freemsg(mp);
return;
}
! tep->te_state = NEXTSTATE(TE_CONN_REQ, tep->te_state);
/*
* get endpoint to connect to
* check that peer with DEST addr is bound to addr
* and has CONIND_number > 0
*/
--- 3029,3039 ----
tl_error_ack(wq, ackmp, TOUTSTATE, 0, T_CONN_REQ);
freemsg(mp);
return;
}
! tep->te_state = nextstate[TE_CONN_REQ][tep->te_state];
/*
* get endpoint to connect to
* check that peer with DEST addr is bound to addr
* and has CONIND_number > 0
*/
*** 3001,3011 ****
*/
if (err != 0) {
if (peer_tep != NULL)
tl_refrele(peer_tep);
/* We are still expected to send T_OK_ACK */
! tep->te_state = NEXTSTATE(TE_OK_ACK1, tep->te_state);
tl_ok_ack(tep->te_wq, ackmp, T_CONN_REQ);
tl_closeok(tep);
dimp = tpi_ack_alloc(mp, sizeof (struct T_discon_ind),
M_PROTO, T_DISCON_IND);
if (dimp == NULL) {
--- 3067,3077 ----
*/
if (err != 0) {
if (peer_tep != NULL)
tl_refrele(peer_tep);
/* We are still expected to send T_OK_ACK */
! tep->te_state = nextstate[TE_OK_ACK1][tep->te_state];
tl_ok_ack(tep->te_wq, ackmp, T_CONN_REQ);
tl_closeok(tep);
dimp = tpi_ack_alloc(mp, sizeof (struct T_discon_ind),
M_PROTO, T_DISCON_IND);
if (dimp == NULL) {
*** 3222,3232 ****
*/
/*
* ack validity of request and send the peer credential in the ACK.
*/
! tep->te_state = NEXTSTATE(TE_OK_ACK1, tep->te_state);
if (peer_tep != NULL && peer_tep->te_credp != NULL &&
confmp != NULL) {
mblk_setcred(confmp, peer_tep->te_credp, peer_tep->te_cpid);
}
--- 3288,3298 ----
*/
/*
* ack validity of request and send the peer credential in the ACK.
*/
! tep->te_state = nextstate[TE_OK_ACK1][tep->te_state];
if (peer_tep != NULL && peer_tep->te_credp != NULL &&
confmp != NULL) {
mblk_setcred(confmp, peer_tep->te_credp, peer_tep->te_cpid);
}
*** 3296,3306 ****
tip->ti_tep = tep;
tip->ti_seqno = tep->te_seqno;
list_insert_tail(&peer_tep->te_iconp, tip);
peer_tep->te_nicon++;
! peer_tep->te_state = NEXTSTATE(TE_CONN_IND, peer_tep->te_state);
/*
* send the T_CONN_IND message
*/
putnext(peer_tep->te_rq, cimp);
--- 3362,3372 ----
tip->ti_tep = tep;
tip->ti_seqno = tep->te_seqno;
list_insert_tail(&peer_tep->te_iconp, tip);
peer_tep->te_nicon++;
! peer_tep->te_state = nextstate[TE_CONN_IND][peer_tep->te_state];
/*
* send the T_CONN_IND message
*/
putnext(peer_tep->te_rq, cimp);
*** 3307,3317 ****
/*
* Send a T_CONN_CON message for sockets.
* Disable the queues until we have reached the correct state!
*/
if (confmp != NULL) {
! tep->te_state = NEXTSTATE(TE_CONN_CON, tep->te_state);
noenable(wq);
putnext(tep->te_rq, confmp);
}
/*
* Now we need to increment tep reference because tep is referenced by
--- 3373,3383 ----
/*
* Send a T_CONN_CON message for sockets.
* Disable the queues until we have reached the correct state!
*/
if (confmp != NULL) {
! tep->te_state = nextstate[TE_CONN_CON][tep->te_state];
noenable(wq);
putnext(tep->te_rq, confmp);
}
/*
* Now we need to increment tep reference because tep is referenced by
*** 3427,3444 ****
tl_error_ack(wq, ackmp, TBADOPT, 0, prim);
freemsg(mp);
return;
}
! tep->te_state = NEXTSTATE(TE_CONN_RES, tep->te_state);
ASSERT(tep->te_state == TS_WACK_CRES);
if (cres->SEQ_number < TL_MINOR_START &&
cres->SEQ_number >= BADSEQNUM) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:remote endpoint sequence number bad"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tl_error_ack(wq, ackmp, TBADSEQ, 0, prim);
freemsg(mp);
return;
}
--- 3493,3510 ----
tl_error_ack(wq, ackmp, TBADOPT, 0, prim);
freemsg(mp);
return;
}
! tep->te_state = nextstate[TE_CONN_RES][tep->te_state];
ASSERT(tep->te_state == TS_WACK_CRES);
if (cres->SEQ_number < TL_MINOR_START &&
cres->SEQ_number >= BADSEQNUM) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:remote endpoint sequence number bad"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tl_error_ack(wq, ackmp, TBADSEQ, 0, prim);
freemsg(mp);
return;
}
*** 3448,3458 ****
if (mod_hash_find_cb(tep->te_transport->tr_ai_hash,
(mod_hash_key_t)(uintptr_t)cres->ACCEPTOR_id,
(mod_hash_val_t *)&acc_ep, tl_find_callback) != 0) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:bad accepting endpoint"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tl_error_ack(wq, ackmp, TBADF, 0, prim);
freemsg(mp);
return;
}
--- 3514,3524 ----
if (mod_hash_find_cb(tep->te_transport->tr_ai_hash,
(mod_hash_key_t)(uintptr_t)cres->ACCEPTOR_id,
(mod_hash_val_t *)&acc_ep, tl_find_callback) != 0) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:bad accepting endpoint"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tl_error_ack(wq, ackmp, TBADF, 0, prim);
freemsg(mp);
return;
}
*** 3460,3470 ****
* Prevent acceptor from closing.
*/
if (!tl_noclose(acc_ep)) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:bad accepting endpoint"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tl_error_ack(wq, ackmp, TBADF, 0, prim);
tl_refrele(acc_ep);
freemsg(mp);
return;
}
--- 3526,3536 ----
* Prevent acceptor from closing.
*/
if (!tl_noclose(acc_ep)) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:bad accepting endpoint"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tl_error_ack(wq, ackmp, TBADF, 0, prim);
tl_refrele(acc_ep);
freemsg(mp);
return;
}
*** 3478,3488 ****
*/
if ((tep != acc_ep) && (acc_ep->te_state != TS_IDLE)) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:accepting endpoint has no address bound,"
"state=%d", acc_ep->te_state));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tl_error_ack(wq, ackmp, TOUTSTATE, 0, prim);
freemsg(mp);
tl_closeok(acc_ep);
tl_refrele(acc_ep);
return;
--- 3544,3554 ----
*/
if ((tep != acc_ep) && (acc_ep->te_state != TS_IDLE)) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:accepting endpoint has no address bound,"
"state=%d", acc_ep->te_state));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tl_error_ack(wq, ackmp, TOUTSTATE, 0, prim);
freemsg(mp);
tl_closeok(acc_ep);
tl_refrele(acc_ep);
return;
*** 3494,3504 ****
*/
if ((tep == acc_ep) && (tep->te_nicon > 1)) {
(void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE | SL_ERROR,
"tl_conn_res: > 1 conn_ind on listener-acceptor"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tl_error_ack(wq, ackmp, TBADF, 0, prim);
freemsg(mp);
tl_closeok(acc_ep);
tl_refrele(acc_ep);
return;
--- 3560,3570 ----
*/
if ((tep == acc_ep) && (tep->te_nicon > 1)) {
(void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE | SL_ERROR,
"tl_conn_res: > 1 conn_ind on listener-acceptor"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tl_error_ack(wq, ackmp, TBADF, 0, prim);
freemsg(mp);
tl_closeok(acc_ep);
tl_refrele(acc_ep);
return;
*** 3512,3522 ****
*/
tip = tl_icon_find(tep, cres->SEQ_number);
if (tip == NULL) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:no client in listener list"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
tl_error_ack(wq, ackmp, TBADSEQ, 0, prim);
freemsg(mp);
tl_closeok(acc_ep);
tl_refrele(acc_ep);
return;
--- 3578,3588 ----
*/
tip = tl_icon_find(tep, cres->SEQ_number);
if (tip == NULL) {
(void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
"tl_conn_res:no client in listener list"));
! tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
tl_error_ack(wq, ackmp, TBADSEQ, 0, prim);
freemsg(mp);
tl_closeok(acc_ep);
tl_refrele(acc_ep);
return;
*** 3630,3644 ****
/*
* Now ack validity of request
*/
if (tep->te_nicon == 1) {
if (tep == acc_ep)
! tep->te_state = NEXTSTATE(TE_OK_ACK2, tep->te_state);
else
! tep->te_state = NEXTSTATE(TE_OK_ACK3, tep->te_state);
} else {
! tep->te_state = NEXTSTATE(TE_OK_ACK4, tep->te_state);
}
/*
* send T_DISCON_IND now if client state validation failed earlier
*/
--- 3696,3710 ----
/*
* Now ack validity of request
*/
if (tep->te_nicon == 1) {
if (tep == acc_ep)
! tep->te_state = nextstate[TE_OK_ACK2][tep->te_state];
else
! tep->te_state = nextstate[TE_OK_ACK3][tep->te_state];
} else {
! tep->te_state = nextstate[TE_OK_ACK4][tep->te_state];
}
/*
* send T_DISCON_IND now if client state validation failed earlier
*/
*** 3687,3697 ****
/*
* now start connecting the accepting endpoint
*/
if (tep != acc_ep)
! acc_ep->te_state = NEXTSTATE(TE_PASS_CONN, acc_ep->te_state);
if (cl_ep == NULL) {
/*
* The client has already closed. Send up any queued messages
* and change the state accordingly.
--- 3753,3763 ----
/*
* now start connecting the accepting endpoint
*/
if (tep != acc_ep)
! acc_ep->te_state = nextstate[TE_PASS_CONN][acc_ep->te_state];
if (cl_ep == NULL) {
/*
* The client has already closed. Send up any queued messages
* and change the state accordingly.
*** 3848,3858 ****
freemsg(ccmp);
} else {
/*
* change client state on TE_CONN_CON event
*/
! cl_ep->te_state = NEXTSTATE(TE_CONN_CON, cl_ep->te_state);
putnext(cl_ep->te_rq, ccmp);
}
/* Mark the both endpoints as accepted */
cl_ep->te_flag |= TL_ACCEPTED;
--- 3914,3924 ----
freemsg(ccmp);
} else {
/*
* change client state on TE_CONN_CON event
*/
! cl_ep->te_state = nextstate[TE_CONN_CON][cl_ep->te_state];
putnext(cl_ep->te_rq, ccmp);
}
/* Mark the both endpoints as accepted */
cl_ep->te_flag |= TL_ACCEPTED;
*** 3934,3950 ****
}
/*
* Defer committing the state change until it is determined if
* the message will be queued with the tl_icon or not.
*/
! new_state = NEXTSTATE(TE_DISCON_REQ, tep->te_state);
/* validate the message */
if (msz < sizeof (struct T_discon_req)) {
(void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
"tl_discon_req:invalid message"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, new_state);
tl_error_ack(wq, ackmp, TSYSERR, EINVAL, T_DISCON_REQ);
freemsg(mp);
return;
}
--- 4000,4016 ----
}
/*
* Defer committing the state change until it is determined if
* the message will be queued with the tl_icon or not.
*/
! new_state = nextstate[TE_DISCON_REQ][tep->te_state];
/* validate the message */
if (msz < sizeof (struct T_discon_req)) {
(void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
"tl_discon_req:invalid message"));
! tep->te_state = nextstate[TE_ERROR_ACK][new_state];
tl_error_ack(wq, ackmp, TSYSERR, EINVAL, T_DISCON_REQ);
freemsg(mp);
return;
}
*** 3960,3970 ****
tip = tl_icon_find(tep, dr->SEQ_number);
if (tip == NULL) {
(void) (STRLOG(TL_ID, tep->te_minor, 2,
SL_TRACE | SL_ERROR,
"tl_discon_req:no disconnect endpoint"));
! tep->te_state = NEXTSTATE(TE_ERROR_ACK, new_state);
tl_error_ack(wq, ackmp, TBADSEQ, 0, T_DISCON_REQ);
freemsg(mp);
return;
}
/*
--- 4026,4036 ----
tip = tl_icon_find(tep, dr->SEQ_number);
if (tip == NULL) {
(void) (STRLOG(TL_ID, tep->te_minor, 2,
SL_TRACE | SL_ERROR,
"tl_discon_req:no disconnect endpoint"));
! tep->te_state = nextstate[TE_ERROR_ACK][new_state];
tl_error_ack(wq, ackmp, TBADSEQ, 0, T_DISCON_REQ);
freemsg(mp);
return;
}
/*
*** 3990,4005 ****
/*
* prepare message to ack validity of request
*/
if (tep->te_nicon == 0) {
! new_state = NEXTSTATE(TE_OK_ACK1, new_state);
} else {
if (tep->te_nicon == 1)
! new_state = NEXTSTATE(TE_OK_ACK2, new_state);
else
! new_state = NEXTSTATE(TE_OK_ACK4, new_state);
}
/*
* Flushing queues according to TPI. Using the old state.
*/
--- 4056,4071 ----
/*
* prepare message to ack validity of request
*/
if (tep->te_nicon == 0) {
! new_state = nextstate[TE_OK_ACK1][new_state];
} else {
if (tep->te_nicon == 1)
! new_state = nextstate[TE_OK_ACK2][new_state];
else
! new_state = nextstate[TE_OK_ACK4][new_state];
}
/*
* Flushing queues according to TPI. Using the old state.
*/
*** 4095,4110 ****
if (tip != NULL) {
ASSERT(tep == tip->ti_tep);
save_state = peer_tep->te_state;
if (peer_tep->te_nicon == 1)
peer_tep->te_state =
! NEXTSTATE(TE_DISCON_IND2,
! peer_tep->te_state);
else
peer_tep->te_state =
! NEXTSTATE(TE_DISCON_IND3,
! peer_tep->te_state);
tl_freetip(peer_tep, tip);
}
ASSERT(tep->te_oconp != NULL);
TL_UNCONNECT(tep->te_oconp);
}
--- 4161,4176 ----
if (tip != NULL) {
ASSERT(tep == tip->ti_tep);
save_state = peer_tep->te_state;
if (peer_tep->te_nicon == 1)
peer_tep->te_state =
! nextstate[TE_DISCON_IND2]
! [peer_tep->te_state];
else
peer_tep->te_state =
! nextstate[TE_DISCON_IND3]
! [peer_tep->te_state];
tl_freetip(peer_tep, tip);
}
ASSERT(tep->te_oconp != NULL);
TL_UNCONNECT(tep->te_oconp);
}
*** 4563,4573 ****
"tl_data:cots:out of state"));
tl_merror(wq, mp, EPROTO);
return;
}
/*
! * tep->te_state = NEXTSTATE(TE_DATA_REQ, tep->te_state);
* (State stays same on this event)
*/
/*
* get connected endpoint
--- 4629,4639 ----
"tl_data:cots:out of state"));
tl_merror(wq, mp, EPROTO);
return;
}
/*
! * tep->te_state = nextstate[TE_DATA_REQ][tep->te_state];
* (State stays same on this event)
*/
/*
* get connected endpoint
*** 4613,4623 ****
prim->type = T_DATA_IND;
else
prim->type = T_OPTDATA_IND;
}
/*
! * peer_tep->te_state = NEXTSTATE(TE_DATA_IND, peer_tep->te_state);
* (peer state stays same on this event)
*/
/*
* send data to connected peer
*/
--- 4679,4689 ----
prim->type = T_DATA_IND;
else
prim->type = T_OPTDATA_IND;
}
/*
! * peer_tep->te_state = nextstate[TE_DATA_IND][peer_tep->te_state];
* (peer state stays same on this event)
*/
/*
* send data to connected peer
*/
*** 4730,4740 ****
tep->te_state));
tl_merror(wq, mp, EPROTO);
return;
}
/*
! * tep->te_state = NEXTSTATE(TE_EXDATA_REQ, tep->te_state);
* (state stays same on this event)
*/
/*
* get connected endpoint
--- 4796,4806 ----
tep->te_state));
tl_merror(wq, mp, EPROTO);
return;
}
/*
! * tep->te_state = nextstate[TE_EXDATA_REQ][tep->te_state];
* (state stays same on this event)
*/
/*
* get connected endpoint
*** 4772,4782 ****
"tl_exdata:rx side:invalid state"));
tl_merror(peer_tep->te_wq, mp, EPROTO);
return;
}
/*
! * peer_tep->te_state = NEXTSTATE(TE_DATA_IND, peer_tep->te_state);
* (peer state stays same on this event)
*/
/*
* reuse message block
*/
--- 4838,4848 ----
"tl_exdata:rx side:invalid state"));
tl_merror(peer_tep->te_wq, mp, EPROTO);
return;
}
/*
! * peer_tep->te_state = nextstate[TE_DATA_IND][peer_tep->te_state];
* (peer state stays same on this event)
*/
/*
* reuse message block
*/
*** 4856,4866 ****
} else {
freemsg(mp);
}
return;
}
! tep->te_state = NEXTSTATE(TE_ORDREL_REQ, tep->te_state);
/*
* get connected endpoint
*/
if (((peer_tep = tep->te_conp) == NULL) || peer_tep->te_closing) {
--- 4922,4932 ----
} else {
freemsg(mp);
}
return;
}
! tep->te_state = nextstate[TE_ORDREL_REQ][tep->te_state];
/*
* get connected endpoint
*/
if (((peer_tep = tep->te_conp) == NULL) || peer_tep->te_closing) {
*** 4895,4905 ****
(void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
"tl_ordrel:rx side:invalid state"));
tl_merror(peer_tep->te_wq, mp, EPROTO);
return;
}
! peer_tep->te_state = NEXTSTATE(TE_ORDREL_IND, peer_tep->te_state);
/*
* reuse message block
*/
prim->type = T_ORDREL_IND;
--- 4961,4971 ----
(void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
"tl_ordrel:rx side:invalid state"));
tl_merror(peer_tep->te_wq, mp, EPROTO);
return;
}
! peer_tep->te_state = nextstate[TE_ORDREL_IND][peer_tep->te_state];
/*
* reuse message block
*/
prim->type = T_ORDREL_IND;
*** 4980,4990 ****
freemsg(mp);
/*
* send indication message
*/
! tep->te_state = NEXTSTATE(TE_UDERROR_IND, tep->te_state);
qreply(wq, err_mp);
}
static void
--- 5046,5056 ----
freemsg(mp);
/*
* send indication message
*/
! tep->te_state = nextstate[TE_UDERROR_IND][tep->te_state];
qreply(wq, err_mp);
}
static void
*** 5038,5048 ****
"tl_wput:T_CONN_REQ:out of state"));
tl_merror(wq, mp, EPROTO);
return;
}
/*
! * tep->te_state = NEXTSTATE(TE_UNITDATA_REQ, tep->te_state);
* (state does not change on this event)
*/
/*
* validate the message
--- 5104,5114 ----
"tl_wput:T_CONN_REQ:out of state"));
tl_merror(wq, mp, EPROTO);
return;
}
/*
! * tep->te_state = nextstate[TE_UNITDATA_REQ][tep->te_state];
* (state does not change on this event)
*/
/*
* validate the message
*** 5337,5347 ****
mp = ui_mp;
}
/*
* send indication message
*/
! peer_tep->te_state = NEXTSTATE(TE_UNITDATA_IND, peer_tep->te_state);
putnext(peer_tep->te_rq, mp);
}
--- 5403,5413 ----
mp = ui_mp;
}
/*
* send indication message
*/
! peer_tep->te_state = nextstate[TE_UNITDATA_IND][peer_tep->te_state];
putnext(peer_tep->te_rq, mp);
}
*** 5659,5674 ****
/*
* Delete tip from the server list.
*/
if (srv_tep->te_nicon == 1) {
srv_tep->te_state =
! NEXTSTATE(TE_DISCON_IND2,
! srv_tep->te_state);
} else {
srv_tep->te_state =
! NEXTSTATE(TE_DISCON_IND3,
! srv_tep->te_state);
}
ASSERT(*(uint32_t *)(d_mp->b_rptr) ==
T_DISCON_IND);
putnext(srv_tep->te_rq, d_mp);
tl_freetip(srv_tep, tip);
--- 5725,5740 ----
/*
* Delete tip from the server list.
*/
if (srv_tep->te_nicon == 1) {
srv_tep->te_state =
! nextstate[TE_DISCON_IND2]
! [srv_tep->te_state];
} else {
srv_tep->te_state =
! nextstate[TE_DISCON_IND3]
! [srv_tep->te_state];
}
ASSERT(*(uint32_t *)(d_mp->b_rptr) ==
T_DISCON_IND);
putnext(srv_tep->te_rq, d_mp);
tl_freetip(srv_tep, tip);
*** 5692,5702 ****
* send ordrel ind
*/
(void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE,
"tl_co_unconnect:connected: ordrel_ind state %d->%d",
peer_tep->te_state,
! NEXTSTATE(TE_ORDREL_IND, peer_tep->te_state)));
d_mp = tl_ordrel_ind_alloc();
if (d_mp == NULL) {
(void) (STRLOG(TL_ID, tep->te_minor, 3,
SL_TRACE | SL_ERROR,
"tl_co_unconnect:connected:"
--- 5758,5768 ----
* send ordrel ind
*/
(void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE,
"tl_co_unconnect:connected: ordrel_ind state %d->%d",
peer_tep->te_state,
! nextstate[TE_ORDREL_IND][peer_tep->te_state]));
d_mp = tl_ordrel_ind_alloc();
if (d_mp == NULL) {
(void) (STRLOG(TL_ID, tep->te_minor, 3,
SL_TRACE | SL_ERROR,
"tl_co_unconnect:connected:"
*** 5707,5717 ****
*/
TL_QENABLE(peer_tep);
goto discon_peer;
}
peer_tep->te_state =
! NEXTSTATE(TE_ORDREL_IND, peer_tep->te_state);
putnext(peer_tep->te_rq, d_mp);
/*
* Handle flow control case. This will generate
* a t_discon_ind message with reason 0 if there
--- 5773,5783 ----
*/
TL_QENABLE(peer_tep);
goto discon_peer;
}
peer_tep->te_state =
! nextstate[TE_ORDREL_IND][peer_tep->te_state];
putnext(peer_tep->te_rq, d_mp);
/*
* Handle flow control case. This will generate
* a t_discon_ind message with reason 0 if there
*** 5951,5962 ****
case T_OPTDATA_IND:
case T_EXDATA_IND:
putnext(tep->te_rq, mp);
break;
case T_ORDREL_IND:
! tep->te_state = NEXTSTATE(TE_ORDREL_IND,
! tep->te_state);
putnext(tep->te_rq, mp);
break;
case T_DISCON_IND:
tep->te_state = TS_IDLE;
putnext(tep->te_rq, mp);
--- 6017,6028 ----
case T_OPTDATA_IND:
case T_EXDATA_IND:
putnext(tep->te_rq, mp);
break;
case T_ORDREL_IND:
! tep->te_state = nextstate[TE_ORDREL_IND]
! [tep->te_state];
putnext(tep->te_rq, mp);
break;
case T_DISCON_IND:
tep->te_state = TS_IDLE;
putnext(tep->te_rq, mp);