aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
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
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')
-rw-r--r--drivers/isdn/mISDN/layer2.c13
-rw-r--r--drivers/isdn/mISDN/layer2.h2
-rw-r--r--drivers/isdn/mISDN/tei.c40
3 files changed, 29 insertions, 26 deletions
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index d6e2863f224a..2d2f58195477 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -2068,7 +2068,8 @@ l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
2068} 2068}
2069 2069
2070struct layer2 * 2070struct layer2 *
2071create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg) 2071create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei,
2072 int sapi)
2072{ 2073{
2073 struct layer2 *l2; 2074 struct layer2 *l2;
2074 struct channel_req rq; 2075 struct channel_req rq;
@@ -2089,7 +2090,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
2089 test_and_set_bit(FLG_LAPD, &l2->flag); 2090 test_and_set_bit(FLG_LAPD, &l2->flag);
2090 test_and_set_bit(FLG_LAPD_NET, &l2->flag); 2091 test_and_set_bit(FLG_LAPD_NET, &l2->flag);
2091 test_and_set_bit(FLG_MOD128, &l2->flag); 2092 test_and_set_bit(FLG_MOD128, &l2->flag);
2092 l2->sapi = 0; 2093 l2->sapi = sapi;
2093 l2->maxlen = MAX_DFRAME_LEN; 2094 l2->maxlen = MAX_DFRAME_LEN;
2094 if (test_bit(OPTION_L2_PMX, &options)) 2095 if (test_bit(OPTION_L2_PMX, &options))
2095 l2->window = 7; 2096 l2->window = 7;
@@ -2099,7 +2100,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
2099 test_and_set_bit(FLG_PTP, &l2->flag); 2100 test_and_set_bit(FLG_PTP, &l2->flag);
2100 if (test_bit(OPTION_L2_FIXEDTEI, &options)) 2101 if (test_bit(OPTION_L2_FIXEDTEI, &options))
2101 test_and_set_bit(FLG_FIXED_TEI, &l2->flag); 2102 test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
2102 l2->tei = (u_int)arg; 2103 l2->tei = tei;
2103 l2->T200 = 1000; 2104 l2->T200 = 1000;
2104 l2->N200 = 3; 2105 l2->N200 = 3;
2105 l2->T203 = 10000; 2106 l2->T203 = 10000;
@@ -2114,7 +2115,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
2114 test_and_set_bit(FLG_LAPD, &l2->flag); 2115 test_and_set_bit(FLG_LAPD, &l2->flag);
2115 test_and_set_bit(FLG_MOD128, &l2->flag); 2116 test_and_set_bit(FLG_MOD128, &l2->flag);
2116 test_and_set_bit(FLG_ORIG, &l2->flag); 2117 test_and_set_bit(FLG_ORIG, &l2->flag);
2117 l2->sapi = 0; 2118 l2->sapi = sapi;
2118 l2->maxlen = MAX_DFRAME_LEN; 2119 l2->maxlen = MAX_DFRAME_LEN;
2119 if (test_bit(OPTION_L2_PMX, &options)) 2120 if (test_bit(OPTION_L2_PMX, &options))
2120 l2->window = 7; 2121 l2->window = 7;
@@ -2124,7 +2125,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
2124 test_and_set_bit(FLG_PTP, &l2->flag); 2125 test_and_set_bit(FLG_PTP, &l2->flag);
2125 if (test_bit(OPTION_L2_FIXEDTEI, &options)) 2126 if (test_bit(OPTION_L2_FIXEDTEI, &options))
2126 test_and_set_bit(FLG_FIXED_TEI, &l2->flag); 2127 test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
2127 l2->tei = (u_int)arg; 2128 l2->tei = tei;
2128 l2->T200 = 1000; 2129 l2->T200 = 1000;
2129 l2->N200 = 3; 2130 l2->N200 = 3;
2130 l2->T203 = 10000; 2131 l2->T203 = 10000;
@@ -2180,7 +2181,7 @@ x75create(struct channel_req *crq)
2180 2181
2181 if (crq->protocol != ISDN_P_B_X75SLP) 2182 if (crq->protocol != ISDN_P_B_X75SLP)
2182 return -EPROTONOSUPPORT; 2183 return -EPROTONOSUPPORT;
2183 l2 = create_l2(crq->ch, crq->protocol, 0, 0); 2184 l2 = create_l2(crq->ch, crq->protocol, 0, 0, 0);
2184 if (!l2) 2185 if (!l2)
2185 return -ENOMEM; 2186 return -ENOMEM;
2186 crq->ch = &l2->ch; 2187 crq->ch = &l2->ch;
diff --git a/drivers/isdn/mISDN/layer2.h b/drivers/isdn/mISDN/layer2.h
index 6293f80dc2d3..9547fb3707a3 100644
--- a/drivers/isdn/mISDN/layer2.h
+++ b/drivers/isdn/mISDN/layer2.h
@@ -90,7 +90,7 @@ enum {
90#define L2_STATE_COUNT (ST_L2_8+1) 90#define L2_STATE_COUNT (ST_L2_8+1)
91 91
92extern struct layer2 *create_l2(struct mISDNchannel *, u_int, 92extern struct layer2 *create_l2(struct mISDNchannel *, u_int,
93 u_long, u_long); 93 u_long, int, int);
94extern int tei_l2(struct layer2 *, u_int, u_long arg); 94extern int tei_l2(struct layer2 *, u_int, u_long arg);
95 95
96 96
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);