in capi/capi.c [405:477]
static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
{
unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data);
struct tty_struct *tty;
struct sk_buff *nskb;
u16 errcode, datahandle;
struct tty_ldisc *ld;
int ret = -1;
tty = tty_port_tty_get(&mp->port);
if (!tty) {
pr_debug("capi: currently no receiver\n");
return -1;
}
ld = tty_ldisc_ref(tty);
if (!ld) {
/* fatal error, do not requeue */
ret = 0;
kfree_skb(skb);
goto deref_tty;
}
if (ld->ops->receive_buf == NULL) {
pr_debug("capi: ldisc has no receive_buf function\n");
/* fatal error, do not requeue */
goto free_skb;
}
if (mp->ttyinstop) {
pr_debug("capi: recv tty throttled\n");
goto deref_ldisc;
}
if (tty->receive_room < datalen) {
pr_debug("capi: no room in tty\n");
goto deref_ldisc;
}
nskb = gen_data_b3_resp_for(mp, skb);
if (!nskb) {
printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
goto deref_ldisc;
}
datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4);
errcode = capi20_put_message(mp->ap, nskb);
if (errcode == CAPI_NOERROR) {
skb_pull(skb, CAPIMSG_LEN(skb->data));
pr_debug("capi: DATA_B3_RESP %u len=%d => ldisc\n",
datahandle, skb->len);
ld->ops->receive_buf(tty, skb->data, NULL, skb->len);
} else {
printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
errcode);
kfree_skb(nskb);
if (errcode == CAPI_SENDQUEUEFULL)
goto deref_ldisc;
}
free_skb:
ret = 0;
kfree_skb(skb);
deref_ldisc:
tty_ldisc_deref(ld);
deref_tty:
tty_kref_put(tty);
return ret;
}