aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/mISDN/tei.c
diff options
context:
space:
mode:
authorAndreas Eversberg <andreas@eversberg.eu>2009-05-25 03:50:02 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-25 03:51:35 -0400
commit5b277b8605f4c8fbd13302df33ab4570f844c1ff (patch)
treed8613c050f53bb694c1d59e2ee5f82b0564ad7b6 /drivers/isdn/mISDN/tei.c
parentbc138ec4ac58bb83e2d9d5c12328d5452294c1f0 (diff)
mISDN: Fix TEI and SAPI handling
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>
Diffstat (limited to 'drivers/isdn/mISDN/tei.c')
-rw-r--r--drivers/isdn/mISDN/tei.c40
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
428static void 428static void
429put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei) 429put_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
779static struct layer2 * 778static struct layer2 *
780create_new_tei(struct manager *mgr, int tei) 779create_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
1166check_data(struct manager *mgr, struct sk_buff *skb) 1168check_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);