isdn: avoid races in capidrv
In several places, capidrv sends a CAPI message to the ISDN device and then updates its internal state accordingly. If the response message from the device arrives before the state is updated, it may be rejected or processed incorrectly. Avoid these races by updating the state before emitting the message. Impact: bugfix Signed-off-by: Tilman Schmidt <tilman@imap.cc> Acked-by: Karsten Keil <keil@b1-systems.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
812d73473a
commit
e48470217d
|
@ -671,8 +671,8 @@ static void n0(capidrv_contr * card, capidrv_ncci * ncci)
|
||||||
NULL, /* Useruserdata */ /* $$$$ */
|
NULL, /* Useruserdata */ /* $$$$ */
|
||||||
NULL /* Facilitydataarray */
|
NULL /* Facilitydataarray */
|
||||||
);
|
);
|
||||||
send_message(card, &cmsg);
|
|
||||||
plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
|
plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
|
||||||
|
send_message(card, &cmsg);
|
||||||
|
|
||||||
cmd.command = ISDN_STAT_BHUP;
|
cmd.command = ISDN_STAT_BHUP;
|
||||||
cmd.driver = card->myid;
|
cmd.driver = card->myid;
|
||||||
|
@ -924,8 +924,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
|
||||||
*/
|
*/
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
cmsg->Reject = 1; /* ignore */
|
cmsg->Reject = 1; /* ignore */
|
||||||
send_message(card, cmsg);
|
|
||||||
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
|
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
|
||||||
|
send_message(card, cmsg);
|
||||||
printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
|
printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
|
||||||
card->contrnr,
|
card->contrnr,
|
||||||
cmd.parm.setup.phone,
|
cmd.parm.setup.phone,
|
||||||
|
@ -974,8 +974,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
|
||||||
case 2: /* Call will be rejected. */
|
case 2: /* Call will be rejected. */
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
cmsg->Reject = 2; /* reject call, normal call clearing */
|
cmsg->Reject = 2; /* reject call, normal call clearing */
|
||||||
send_message(card, cmsg);
|
|
||||||
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
|
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
|
||||||
|
send_message(card, cmsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -983,8 +983,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
cmsg->Reject = 8; /* reject call,
|
cmsg->Reject = 8; /* reject call,
|
||||||
destination out of order */
|
destination out of order */
|
||||||
send_message(card, cmsg);
|
|
||||||
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
|
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
|
||||||
|
send_message(card, cmsg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1020,8 +1020,8 @@ static void handle_plci(_cmsg * cmsg)
|
||||||
card->bchans[plcip->chan].disconnecting = 1;
|
card->bchans[plcip->chan].disconnecting = 1;
|
||||||
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
|
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
send_message(card, cmsg);
|
|
||||||
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
|
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
|
||||||
|
send_message(card, cmsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPI_DISCONNECT_CONF: /* plci */
|
case CAPI_DISCONNECT_CONF: /* plci */
|
||||||
|
@ -1078,8 +1078,8 @@ static void handle_plci(_cmsg * cmsg)
|
||||||
|
|
||||||
if (card->bchans[plcip->chan].incoming) {
|
if (card->bchans[plcip->chan].incoming) {
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
send_message(card, cmsg);
|
|
||||||
plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
|
plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
|
||||||
|
send_message(card, cmsg);
|
||||||
} else {
|
} else {
|
||||||
capidrv_ncci *nccip;
|
capidrv_ncci *nccip;
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
|
@ -1098,13 +1098,14 @@ static void handle_plci(_cmsg * cmsg)
|
||||||
NULL /* NCPI */
|
NULL /* NCPI */
|
||||||
);
|
);
|
||||||
nccip->msgid = cmsg->Messagenumber;
|
nccip->msgid = cmsg->Messagenumber;
|
||||||
|
plci_change_state(card, plcip,
|
||||||
|
EV_PLCI_CONNECT_ACTIVE_IND);
|
||||||
|
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
|
||||||
send_message(card, cmsg);
|
send_message(card, cmsg);
|
||||||
cmd.command = ISDN_STAT_DCONN;
|
cmd.command = ISDN_STAT_DCONN;
|
||||||
cmd.driver = card->myid;
|
cmd.driver = card->myid;
|
||||||
cmd.arg = plcip->chan;
|
cmd.arg = plcip->chan;
|
||||||
card->interface.statcallb(&cmd);
|
card->interface.statcallb(&cmd);
|
||||||
plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
|
|
||||||
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1193,8 +1194,8 @@ static void handle_ncci(_cmsg * cmsg)
|
||||||
goto notfound;
|
goto notfound;
|
||||||
|
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
send_message(card, cmsg);
|
|
||||||
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
|
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
|
||||||
|
send_message(card, cmsg);
|
||||||
|
|
||||||
cmd.command = ISDN_STAT_BCONN;
|
cmd.command = ISDN_STAT_BCONN;
|
||||||
cmd.driver = card->myid;
|
cmd.driver = card->myid;
|
||||||
|
@ -1222,8 +1223,8 @@ static void handle_ncci(_cmsg * cmsg)
|
||||||
0, /* Reject */
|
0, /* Reject */
|
||||||
NULL /* NCPI */
|
NULL /* NCPI */
|
||||||
);
|
);
|
||||||
send_message(card, cmsg);
|
|
||||||
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
|
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
|
||||||
|
send_message(card, cmsg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
|
printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
|
||||||
|
@ -1299,8 +1300,8 @@ static void handle_ncci(_cmsg * cmsg)
|
||||||
card->bchans[nccip->chan].disconnecting = 1;
|
card->bchans[nccip->chan].disconnecting = 1;
|
||||||
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
|
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
|
||||||
capi_cmsg_answer(cmsg);
|
capi_cmsg_answer(cmsg);
|
||||||
send_message(card, cmsg);
|
|
||||||
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
|
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
|
||||||
|
send_message(card, cmsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPI_DISCONNECT_B3_CONF: /* ncci */
|
case CAPI_DISCONNECT_B3_CONF: /* ncci */
|
||||||
|
@ -2014,8 +2015,8 @@ static void send_listen(capidrv_contr *card)
|
||||||
card->cipmask,
|
card->cipmask,
|
||||||
card->cipmask2,
|
card->cipmask2,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
send_message(card, &cmdcmsg);
|
|
||||||
listen_change_state(card, EV_LISTEN_REQ);
|
listen_change_state(card, EV_LISTEN_REQ);
|
||||||
|
send_message(card, &cmdcmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void listentimerfunc(unsigned long x)
|
static void listentimerfunc(unsigned long x)
|
||||||
|
|
Loading…
Reference in New Issue