diff options
Diffstat (limited to 'drivers/isdn/mISDN/tei.c')
-rw-r--r-- | drivers/isdn/mISDN/tei.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index c75af762a067..55a7c3dac3c2 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c | |||
@@ -426,7 +426,7 @@ done: | |||
426 | } | 426 | } |
427 | 427 | ||
428 | static void | 428 | static void |
429 | put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei) | 429 | put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, int tei) |
430 | { | 430 | { |
431 | struct sk_buff *skb; | 431 | struct sk_buff *skb; |
432 | u_char bp[8]; | 432 | u_char bp[8]; |
@@ -440,9 +440,8 @@ put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei) | |||
440 | bp[4] = ri >> 8; | 440 | bp[4] = ri >> 8; |
441 | bp[5] = ri & 0xff; | 441 | bp[5] = ri & 0xff; |
442 | bp[6] = m_id; | 442 | bp[6] = m_id; |
443 | bp[7] = (tei << 1) | 1; | 443 | bp[7] = ((tei << 1) & 0xff) | 1; |
444 | skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr), | 444 | skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr), 8, bp, GFP_ATOMIC); |
445 | 8, bp, GFP_ATOMIC); | ||
446 | if (!skb) { | 445 | if (!skb) { |
447 | printk(KERN_WARNING "%s: no skb for tei msg\n", __func__); | 446 | printk(KERN_WARNING "%s: no skb for tei msg\n", __func__); |
448 | return; | 447 | return; |
@@ -777,7 +776,7 @@ tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len) | |||
777 | } | 776 | } |
778 | 777 | ||
779 | static struct layer2 * | 778 | static struct layer2 * |
780 | create_new_tei(struct manager *mgr, int tei) | 779 | create_new_tei(struct manager *mgr, int tei, int sapi) |
781 | { | 780 | { |
782 | u_long opt = 0; | 781 | u_long opt = 0; |
783 | u_long flags; | 782 | u_long flags; |
@@ -786,12 +785,12 @@ create_new_tei(struct manager *mgr, int tei) | |||
786 | 785 | ||
787 | if (!mgr->up) | 786 | if (!mgr->up) |
788 | return NULL; | 787 | return NULL; |
789 | if (tei < 64) | 788 | if ((tei >= 0) && (tei < 64)) |
790 | test_and_set_bit(OPTION_L2_FIXEDTEI, &opt); | 789 | test_and_set_bit(OPTION_L2_FIXEDTEI, &opt); |
791 | if (mgr->ch.st->dev->Dprotocols | 790 | if (mgr->ch.st->dev->Dprotocols |
792 | & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1))) | 791 | & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1))) |
793 | test_and_set_bit(OPTION_L2_PMX, &opt); | 792 | test_and_set_bit(OPTION_L2_PMX, &opt); |
794 | l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, (u_long)tei); | 793 | l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi); |
795 | if (!l2) { | 794 | if (!l2) { |
796 | printk(KERN_WARNING "%s:no memory for layer2\n", __func__); | 795 | printk(KERN_WARNING "%s:no memory for layer2\n", __func__); |
797 | return NULL; | 796 | return NULL; |
@@ -839,12 +838,17 @@ new_tei_req(struct manager *mgr, u_char *dp) | |||
839 | ri += dp[1]; | 838 | ri += dp[1]; |
840 | if (!mgr->up) | 839 | if (!mgr->up) |
841 | goto denied; | 840 | goto denied; |
842 | tei = get_free_tei(mgr); | 841 | if (!(dp[3] & 1)) /* Extension bit != 1 */ |
842 | goto denied; | ||
843 | if (dp[3] != 0xff) | ||
844 | tei = dp[3] >> 1; /* 3GPP TS 08.56 6.1.11.2 */ | ||
845 | else | ||
846 | tei = get_free_tei(mgr); | ||
843 | if (tei < 0) { | 847 | if (tei < 0) { |
844 | printk(KERN_WARNING "%s:No free tei\n", __func__); | 848 | printk(KERN_WARNING "%s:No free tei\n", __func__); |
845 | goto denied; | 849 | goto denied; |
846 | } | 850 | } |
847 | l2 = create_new_tei(mgr, tei); | 851 | l2 = create_new_tei(mgr, tei, CTRL_SAPI); |
848 | if (!l2) | 852 | if (!l2) |
849 | goto denied; | 853 | goto denied; |
850 | else | 854 | else |
@@ -976,8 +980,6 @@ create_teimgr(struct manager *mgr, struct channel_req *crq) | |||
976 | __func__, dev_name(&mgr->ch.st->dev->dev), | 980 | __func__, dev_name(&mgr->ch.st->dev->dev), |
977 | crq->protocol, crq->adr.dev, crq->adr.channel, | 981 | crq->protocol, crq->adr.dev, crq->adr.channel, |
978 | crq->adr.sapi, crq->adr.tei); | 982 | crq->adr.sapi, crq->adr.tei); |
979 | if (crq->adr.sapi != 0) /* not supported yet */ | ||
980 | return -EINVAL; | ||
981 | if (crq->adr.tei > GROUP_TEI) | 983 | if (crq->adr.tei > GROUP_TEI) |
982 | return -EINVAL; | 984 | return -EINVAL; |
983 | if (crq->adr.tei < 64) | 985 | if (crq->adr.tei < 64) |
@@ -1024,8 +1026,8 @@ create_teimgr(struct manager *mgr, struct channel_req *crq) | |||
1024 | } | 1026 | } |
1025 | return 0; | 1027 | return 0; |
1026 | } | 1028 | } |
1027 | l2 = create_l2(crq->ch, crq->protocol, (u_int)opt, | 1029 | l2 = create_l2(crq->ch, crq->protocol, opt, |
1028 | (u_long)crq->adr.tei); | 1030 | crq->adr.tei, crq->adr.sapi); |
1029 | if (!l2) | 1031 | if (!l2) |
1030 | return -ENOMEM; | 1032 | return -ENOMEM; |
1031 | l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL); | 1033 | l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL); |
@@ -1166,7 +1168,7 @@ static int | |||
1166 | check_data(struct manager *mgr, struct sk_buff *skb) | 1168 | check_data(struct manager *mgr, struct sk_buff *skb) |
1167 | { | 1169 | { |
1168 | struct mISDNhead *hh = mISDN_HEAD_P(skb); | 1170 | struct mISDNhead *hh = mISDN_HEAD_P(skb); |
1169 | int ret, tei; | 1171 | int ret, tei, sapi; |
1170 | struct layer2 *l2; | 1172 | struct layer2 *l2; |
1171 | 1173 | ||
1172 | if (*debug & DEBUG_L2_CTRL) | 1174 | if (*debug & DEBUG_L2_CTRL) |
@@ -1178,18 +1180,18 @@ check_data(struct manager *mgr, struct sk_buff *skb) | |||
1178 | return -ENOTCONN; | 1180 | return -ENOTCONN; |
1179 | if (skb->len != 3) | 1181 | if (skb->len != 3) |
1180 | return -ENOTCONN; | 1182 | return -ENOTCONN; |
1181 | if (skb->data[0] != 0) | 1183 | if (skb->data[0] & 3) /* EA0 and CR must be 0 */ |
1182 | /* only SAPI 0 command */ | 1184 | return -EINVAL; |
1183 | return -ENOTCONN; | 1185 | sapi = skb->data[0] >> 2; |
1184 | if (!(skb->data[1] & 1)) /* invalid EA1 */ | 1186 | if (!(skb->data[1] & 1)) /* invalid EA1 */ |
1185 | return -EINVAL; | 1187 | return -EINVAL; |
1186 | tei = skb->data[1] >> 0; | 1188 | tei = skb->data[1] >> 1; |
1187 | if (tei > 63) /* not a fixed tei */ | 1189 | if (tei > 63) /* not a fixed tei */ |
1188 | return -ENOTCONN; | 1190 | return -ENOTCONN; |
1189 | if ((skb->data[2] & ~0x10) != SABME) | 1191 | if ((skb->data[2] & ~0x10) != SABME) |
1190 | return -ENOTCONN; | 1192 | return -ENOTCONN; |
1191 | /* We got a SABME for a fixed TEI */ | 1193 | /* We got a SABME for a fixed TEI */ |
1192 | l2 = create_new_tei(mgr, tei); | 1194 | l2 = create_new_tei(mgr, tei, sapi); |
1193 | if (!l2) | 1195 | if (!l2) |
1194 | return -ENOMEM; | 1196 | return -ENOMEM; |
1195 | ret = l2->ch.send(&l2->ch, skb); | 1197 | ret = l2->ch.send(&l2->ch, skb); |