Skip to content

Commit

Permalink
mISDN: Fix TEI and SAPI handling
Browse files Browse the repository at this point in the history
Added SAPI value to use SAPIs different than 0.

Now fixed TEIs work in NT mode. This allows PTP endpoint to be connected
to PTMP ports together with other PTMP endpoints.

New enhanced version, thanks to Sam Ravnborg <sam@ravnborg.org> for the
hints.

Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Andreas Eversberg authored and David S. Miller committed May 25, 2009
1 parent bc138ec commit 5b277b8
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 26 deletions.
13 changes: 7 additions & 6 deletions drivers/isdn/mISDN/layer2.c
Original file line number Diff line number Diff line change
Expand Up @@ -2068,7 +2068,8 @@ l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
}

struct layer2 *
create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei,
int sapi)
{
struct layer2 *l2;
struct channel_req rq;
Expand All @@ -2089,7 +2090,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
test_and_set_bit(FLG_LAPD, &l2->flag);
test_and_set_bit(FLG_LAPD_NET, &l2->flag);
test_and_set_bit(FLG_MOD128, &l2->flag);
l2->sapi = 0;
l2->sapi = sapi;
l2->maxlen = MAX_DFRAME_LEN;
if (test_bit(OPTION_L2_PMX, &options))
l2->window = 7;
Expand All @@ -2099,7 +2100,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
test_and_set_bit(FLG_PTP, &l2->flag);
if (test_bit(OPTION_L2_FIXEDTEI, &options))
test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
l2->tei = (u_int)arg;
l2->tei = tei;
l2->T200 = 1000;
l2->N200 = 3;
l2->T203 = 10000;
Expand All @@ -2114,7 +2115,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
test_and_set_bit(FLG_LAPD, &l2->flag);
test_and_set_bit(FLG_MOD128, &l2->flag);
test_and_set_bit(FLG_ORIG, &l2->flag);
l2->sapi = 0;
l2->sapi = sapi;
l2->maxlen = MAX_DFRAME_LEN;
if (test_bit(OPTION_L2_PMX, &options))
l2->window = 7;
Expand All @@ -2124,7 +2125,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
test_and_set_bit(FLG_PTP, &l2->flag);
if (test_bit(OPTION_L2_FIXEDTEI, &options))
test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
l2->tei = (u_int)arg;
l2->tei = tei;
l2->T200 = 1000;
l2->N200 = 3;
l2->T203 = 10000;
Expand Down Expand Up @@ -2180,7 +2181,7 @@ x75create(struct channel_req *crq)

if (crq->protocol != ISDN_P_B_X75SLP)
return -EPROTONOSUPPORT;
l2 = create_l2(crq->ch, crq->protocol, 0, 0);
l2 = create_l2(crq->ch, crq->protocol, 0, 0, 0);
if (!l2)
return -ENOMEM;
crq->ch = &l2->ch;
Expand Down
2 changes: 1 addition & 1 deletion drivers/isdn/mISDN/layer2.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ enum {
#define L2_STATE_COUNT (ST_L2_8+1)

extern struct layer2 *create_l2(struct mISDNchannel *, u_int,
u_long, u_long);
u_long, int, int);
extern int tei_l2(struct layer2 *, u_int, u_long arg);


Expand Down
40 changes: 21 additions & 19 deletions drivers/isdn/mISDN/tei.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ findtei(struct manager *mgr, int tei)
}

static void
put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei)
put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, int tei)
{
struct sk_buff *skb;
u_char bp[8];
Expand All @@ -440,9 +440,8 @@ put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei)
bp[4] = ri >> 8;
bp[5] = ri & 0xff;
bp[6] = m_id;
bp[7] = (tei << 1) | 1;
skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr),
8, bp, GFP_ATOMIC);
bp[7] = ((tei << 1) & 0xff) | 1;
skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr), 8, bp, GFP_ATOMIC);
if (!skb) {
printk(KERN_WARNING "%s: no skb for tei msg\n", __func__);
return;
Expand Down Expand Up @@ -777,7 +776,7 @@ tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len)
}

static struct layer2 *
create_new_tei(struct manager *mgr, int tei)
create_new_tei(struct manager *mgr, int tei, int sapi)
{
u_long opt = 0;
u_long flags;
Expand All @@ -786,12 +785,12 @@ create_new_tei(struct manager *mgr, int tei)

if (!mgr->up)
return NULL;
if (tei < 64)
if ((tei >= 0) && (tei < 64))
test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
if (mgr->ch.st->dev->Dprotocols
& ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
test_and_set_bit(OPTION_L2_PMX, &opt);
l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, (u_long)tei);
l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi);
if (!l2) {
printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
return NULL;
Expand Down Expand Up @@ -839,12 +838,17 @@ new_tei_req(struct manager *mgr, u_char *dp)
ri += dp[1];
if (!mgr->up)
goto denied;
tei = get_free_tei(mgr);
if (!(dp[3] & 1)) /* Extension bit != 1 */
goto denied;
if (dp[3] != 0xff)
tei = dp[3] >> 1; /* 3GPP TS 08.56 6.1.11.2 */
else
tei = get_free_tei(mgr);
if (tei < 0) {
printk(KERN_WARNING "%s:No free tei\n", __func__);
goto denied;
}
l2 = create_new_tei(mgr, tei);
l2 = create_new_tei(mgr, tei, CTRL_SAPI);
if (!l2)
goto denied;
else
Expand Down Expand Up @@ -976,8 +980,6 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
__func__, dev_name(&mgr->ch.st->dev->dev),
crq->protocol, crq->adr.dev, crq->adr.channel,
crq->adr.sapi, crq->adr.tei);
if (crq->adr.sapi != 0) /* not supported yet */
return -EINVAL;
if (crq->adr.tei > GROUP_TEI)
return -EINVAL;
if (crq->adr.tei < 64)
Expand Down Expand Up @@ -1024,8 +1026,8 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
}
return 0;
}
l2 = create_l2(crq->ch, crq->protocol, (u_int)opt,
(u_long)crq->adr.tei);
l2 = create_l2(crq->ch, crq->protocol, opt,
crq->adr.tei, crq->adr.sapi);
if (!l2)
return -ENOMEM;
l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
Expand Down Expand Up @@ -1166,7 +1168,7 @@ static int
check_data(struct manager *mgr, struct sk_buff *skb)
{
struct mISDNhead *hh = mISDN_HEAD_P(skb);
int ret, tei;
int ret, tei, sapi;
struct layer2 *l2;

if (*debug & DEBUG_L2_CTRL)
Expand All @@ -1178,18 +1180,18 @@ check_data(struct manager *mgr, struct sk_buff *skb)
return -ENOTCONN;
if (skb->len != 3)
return -ENOTCONN;
if (skb->data[0] != 0)
/* only SAPI 0 command */
return -ENOTCONN;
if (skb->data[0] & 3) /* EA0 and CR must be 0 */
return -EINVAL;
sapi = skb->data[0] >> 2;
if (!(skb->data[1] & 1)) /* invalid EA1 */
return -EINVAL;
tei = skb->data[1] >> 0;
tei = skb->data[1] >> 1;
if (tei > 63) /* not a fixed tei */
return -ENOTCONN;
if ((skb->data[2] & ~0x10) != SABME)
return -ENOTCONN;
/* We got a SABME for a fixed TEI */
l2 = create_new_tei(mgr, tei);
l2 = create_new_tei(mgr, tei, sapi);
if (!l2)
return -ENOMEM;
ret = l2->ch.send(&l2->ch, skb);
Expand Down

0 comments on commit 5b277b8

Please sign in to comment.