1 /**	$MirOS: src/sys/netisdn/i4b_capi_msgs.c,v 1.2 2005/03/06 21:28:24 tg Exp $	*/
2 /*	$NetBSD: i4b_capi_msgs.c,v 1.4 2003/10/03 16:46:32 pooka Exp $	*/
3 
4 /*
5  * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * capi/capi_msgs.c	The CAPI i4b message handlers.
29  *
30  * $FreeBSD: src/sys/i4b/capi/capi_msgs.c,v 1.2 2001/10/21 08:51:54 hm Exp $
31  */
32 
33 #include <sys/cdefs.h>
34 
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
38 #include <sys/mbuf.h>
39 #include <sys/socket.h>
40 #include <sys/timeout.h>
41 #include <net/if.h>
42 
43 #include <netisdn/i4b_debug.h>
44 #include <netisdn/i4b_ioctl.h>
45 #include <netisdn/i4b_cause.h>
46 #include <netisdn/i4b_l3l4.h>
47 #include <netisdn/i4b_mbuf.h>
48 #include <netisdn/i4b_global.h>
49 #include <netisdn/i4b_l4.h>
50 #include <netisdn/i4b_capi.h>
51 #include <netisdn/i4b_capi_msgs.h>
52 
53 /*
54 //  Administrative messages:
55 //  ------------------------
56 */
57 
capi_listen_req(capi_softc_t * sc,u_int32_t CIP)58 void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
59 {
60     struct mbuf *m = i4b_Dgetmbuf(8 + 18);
61     u_int8_t *msg;
62     u_int16_t msgid;
63 
64     if (!m) {
65 	printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
66 	return;
67     }
68 
69     msgid = sc->sc_msgid++;
70 
71     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
72     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
73     msg = capimsg_setu16(msg, CAPI_LISTEN_REQ);
74     msg = capimsg_setu16(msg, msgid);
75 
76     msg = capimsg_setu32(msg, 1); /* Controller */
77     msg = capimsg_setu32(msg, 0); /* Info mask */
78     msg = capimsg_setu32(msg, CIP);
79     msg = capimsg_setu32(msg, 0);
80     msg = capimsg_setu8(msg, 0);
81     msg = capimsg_setu8(msg, 0);
82 
83     sc->send(sc, m);
84 }
85 
capi_listen_conf(capi_softc_t * sc,struct mbuf * m_in)86 void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
87 {
88     struct isdn_l3_driver *l3drv;
89     u_int8_t *msg = mtod(m_in, u_int8_t*);
90     u_int16_t Info;
91 
92     capimsg_getu16(msg + 12, &Info);
93 
94     if (Info == 0) {
95 	/* We are now listening. */
96 
97 	sc->sc_state = C_UP;
98 	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
99 	l3drv->dl_est = DL_UP;
100 
101 	i4b_l4_l12stat(l3drv, 1, 1);
102 	i4b_l4_l12stat(l3drv, 2, 1);
103 
104     } else {
105 	/* XXX sc->sc_state = C_DOWN ? XXX */
106 	printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
107     }
108 }
109 
capi_info_ind(capi_softc_t * sc,struct mbuf * m_in)110 void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
111 {
112     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
113     u_int8_t *msg = mtod(m_in, u_int8_t*);
114     u_int16_t applid, msgid;
115     u_int32_t PLCI;
116 
117     if (!m) {
118 	printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
119 	return;
120     }
121 
122     msg = capimsg_getu16(msg + 2, &applid);
123     msg = capimsg_getu16(msg + 2, &msgid);
124     msg = capimsg_getu32(msg, &PLCI);
125 
126     /* i4b_l4_info_ind() */
127 
128     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
129     msg = capimsg_setu16(msg, applid);
130     msg = capimsg_setu16(msg, CAPI_INFO_RESP);
131     msg = capimsg_setu16(msg, msgid);
132 
133     msg = capimsg_setu32(msg, PLCI);
134 
135     sc->send(sc, m);
136 }
137 
capi_alert_req(capi_softc_t * sc,call_desc_t * cd)138 void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
139 {
140     struct mbuf *m = i4b_Dgetmbuf(8 + 5);
141     u_int8_t *msg;
142     u_int16_t msgid;
143     u_int32_t PLCI;
144 
145     if (!m) {
146 	printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
147 	return;
148     }
149 
150     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
151     PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
152 
153     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
154     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
155     msg = capimsg_setu16(msg, CAPI_ALERT_REQ);
156     msg = capimsg_setu16(msg, msgid);
157 
158     msg = capimsg_setu32(msg, PLCI);
159     msg = capimsg_setu8(msg, 0);
160 
161     sc->send(sc, m);
162 }
163 
capi_alert_conf(capi_softc_t * sc,struct mbuf * m_in)164 void capi_alert_conf(capi_softc_t *sc, struct mbuf *m_in)
165 {
166     u_int8_t *msg = mtod(m_in, u_int8_t*);
167     u_int16_t Info;
168 
169     msg = capimsg_getu16(msg + 12, &Info);
170 
171     if (Info) {
172 	printf("capi%d: can't alert, info=%04x\n", sc->sc_unit, Info);
173     }
174 }
175 
176 /*
177 //  Outgoing call setup:
178 //  --------------------
179 //
180 //             CAPI_CONNECT_REQ -->
181 //                              <-- CAPI_CONNECT_CONF
182 //                       (notify Layer 4)
183 //                              <-- CAPI_CONNECT_ACTIVE_IND
184 //     CAPI_CONNECT_ACTIVE_RESP -->
185 //          CAPI_CONNECT_B3_REQ -->
186 //                              <-- CAPI_CONNECT_B3_CONF
187 //                              <-- CAPI_CONNECT_B3_ACTIVE_IND
188 //  CAPI_CONNECT_B3_ACTIVE_RESP -->
189 //                       (notify Layer 4)
190 */
191 
capi_connect_req(capi_softc_t * sc,call_desc_t * cd)192 void capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
193 {
194     struct isdn_l3_driver *l3drv;
195     struct mbuf *m;
196     u_int8_t *msg;
197     u_int16_t msgid;
198     int slen = strlen(cd->src_telno);
199     int dlen = strlen(cd->dst_telno);
200 
201     m = i4b_Dgetmbuf(8 + 27 + slen + dlen);
202     if (!m) {
203 	printf("capi%d: can't get mbuf for connect_req\n", sc->sc_unit);
204 	return;
205     }
206 
207     l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
208 
209     cd->crflag = CRF_ORIG;
210 
211     sc->sc_bchan[cd->channelid].cdid = cd->cdid;
212     sc->sc_bchan[cd->channelid].bprot = cd->bprot;
213     sc->sc_bchan[cd->channelid].state = B_CONNECT_CONF;
214     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
215     l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
216 
217     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
218     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
219     msg = capimsg_setu16(msg, CAPI_CONNECT_REQ);
220     msg = capimsg_setu16(msg, msgid);
221 
222     msg = capimsg_setu32(msg, 1); /* Controller */
223 
224     switch (cd->bprot) {
225     case BPROT_NONE:
226 	msg = capimsg_setu16(msg, 0x0010); /* Telephony */
227 	break;
228 
229     case BPROT_RHDLC:
230 	msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
231 	break;
232 
233     default:
234 	msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
235     }
236 
237     msg = capimsg_setu8(msg, 1 + dlen);
238     msg = capimsg_setu8(msg, 0x80);
239     strncpy(msg, cd->dst_telno, dlen);
240 
241     msg = capimsg_setu8(msg + dlen, 2 + slen);
242     msg = capimsg_setu8(msg, 0x00);
243     msg = capimsg_setu8(msg, 0x80); /* Presentation and screening indicator */
244     strncpy(msg, cd->src_telno, slen);
245 
246     msg = capimsg_setu8(msg + slen, 0); /* Called & */
247     msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
248 
249     msg = capimsg_setu8(msg, 15); /* B protocol */
250     if (cd->bprot == BPROT_NONE)
251 	msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
252     else
253 	msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
254     msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
255     msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
256     msg = capimsg_setu8(msg, 0); /* B1 parameters */
257     msg = capimsg_setu8(msg, 0); /* B2 parameters */
258     msg = capimsg_setu8(msg, 0); /* B3 parameters */
259 
260     msg = capimsg_setu8(msg, 0); /* Bearer Capability */
261     msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
262     msg = capimsg_setu8(msg, 0); /* High Layer Compatibility */
263     msg = capimsg_setu8(msg, 0); /* Additional Info */
264 
265     sc->send(sc, m);
266 }
267 
capi_connect_conf(capi_softc_t * sc,struct mbuf * m_in)268 void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
269 {
270     u_int8_t *msg = mtod(m_in, u_int8_t*);
271     call_desc_t *cd;
272     u_int16_t msgid;
273     u_int32_t PLCI;
274     u_int16_t Info;
275     int bch;
276 
277     msg = capimsg_getu16(msg + 6, &msgid);
278     msg = capimsg_getu32(msg, &PLCI);
279     msg = capimsg_getu16(msg, &Info);
280 
281     for (bch = 0; bch < sc->sc_nbch; bch++)
282 	if ((sc->sc_bchan[bch].state == B_CONNECT_CONF) &&
283 	    (sc->sc_bchan[bch].msgid == msgid))
284 	    break;
285 
286     if ((bch == sc->sc_nbch) ||
287 	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
288 	printf("capi%d: can't find channel for connect_conf PLCI %x\n",
289 	       sc->sc_unit, PLCI);
290 	return;
291     }
292 
293     if (Info == 0) {
294 	sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
295 	sc->sc_bchan[bch].ncci = PLCI;
296 
297 	i4b_l4_proceeding_ind(cd);
298 
299     } else {
300 	struct isdn_l3_driver *l3drv;
301 
302 	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
303 	SET_CAUSE_TV(cd->cause_out, CAUSET_I4B, CAUSE_I4B_L1ERROR);
304 	i4b_l4_disconnect_ind(cd);
305 	freecd_by_cd(cd);
306 
307 	sc->sc_bchan[bch].state = B_FREE;
308 
309 	l3drv->bch_state[bch] = BCH_ST_FREE;
310 
311 	printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
312     }
313 }
314 
capi_connect_active_ind(capi_softc_t * sc,struct mbuf * m_in)315 void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
316 {
317     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
318     u_int8_t *msg = mtod(m_in, u_int8_t*);
319     call_desc_t *cd;
320     u_int16_t applid, msgid;
321     u_int32_t PLCI;
322     int bch;
323 
324     if (!m) {
325 	printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
326 	return;
327     }
328 
329     msg = capimsg_getu16(msg + 2, &applid);
330     msg = capimsg_getu16(msg + 2, &msgid);
331     msg = capimsg_getu32(msg, &PLCI);
332 
333     for (bch = 0; bch < sc->sc_nbch; bch++)
334 	if ((sc->sc_bchan[bch].state == B_CONNECT_ACTIVE_IND) &&
335 	    (sc->sc_bchan[bch].ncci == PLCI))
336 	    break;
337 
338     if ((bch == sc->sc_nbch) ||
339 	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
340 	printf("capi%d: can't find channel for active_resp, PLCI %x\n",
341 	       sc->sc_unit, PLCI);
342 	return;
343     }
344 
345     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
346     msg = capimsg_setu16(msg, applid);
347     msg = capimsg_setu16(msg, CAPI_CONNECT_ACTIVE_RESP);
348     msg = capimsg_setu16(msg, msgid);
349 
350     msg = capimsg_setu32(msg, PLCI);
351 
352     sc->send(sc, m);
353 
354     if (cd->crflag == CRF_ORIG) {
355 	capi_connect_b3_req(sc, cd);
356 
357     } else {
358 	sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
359     }
360 }
361 
capi_connect_b3_req(capi_softc_t * sc,call_desc_t * cd)362 void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
363 {
364     struct mbuf *m = i4b_Dgetmbuf(8 + 5);
365     u_int8_t *msg;
366     u_int16_t msgid;
367     u_int32_t PLCI;
368 
369     if (!m) {
370 	printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
371 	return;
372     }
373 
374     sc->sc_bchan[cd->channelid].state = B_CONNECT_B3_CONF;
375     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
376     PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
377 
378     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
379     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
380     msg = capimsg_setu16(msg, CAPI_CONNECT_B3_REQ);
381     msg = capimsg_setu16(msg, msgid);
382 
383     msg = capimsg_setu32(msg, PLCI);
384     msg = capimsg_setu8(msg, 0); /* NCPI */
385 
386     sc->send(sc, m);
387 }
388 
capi_connect_b3_conf(capi_softc_t * sc,struct mbuf * m_in)389 void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
390 {
391     u_int8_t *msg = mtod(m_in, u_int8_t*);
392     call_desc_t *cd;
393     u_int16_t msgid;
394     u_int32_t NCCI;
395     u_int16_t Info;
396     int bch;
397 
398     msg = capimsg_getu16(msg + 6, &msgid);
399     msg = capimsg_getu32(msg, &NCCI);
400     msg = capimsg_getu16(msg, &Info);
401 
402     for (bch = 0; bch < sc->sc_nbch; bch++)
403 	if ((sc->sc_bchan[bch].state == B_CONNECT_B3_CONF) &&
404 	    (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
405 	    break;
406 
407     if ((bch == sc->sc_nbch) ||
408 	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
409 	printf("capi%d: can't find channel for connect_b3_conf NCCI %x\n",
410 	       sc->sc_unit, NCCI);
411 	return;
412     }
413 
414     if (Info == 0) {
415 	sc->sc_bchan[bch].ncci = NCCI;
416 	sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
417 
418     } else {
419 	struct isdn_l3_driver *l3drv;
420 
421 	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
422 
423 	SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
424 	i4b_l4_disconnect_ind(cd);
425 	freecd_by_cd(cd);
426 
427 	l3drv->bch_state[bch] = BCH_ST_RSVD;
428 
429 	printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
430 
431 	capi_disconnect_req(sc, cd);
432     }
433 }
434 
capi_connect_b3_active_ind(capi_softc_t * sc,struct mbuf * m_in)435 void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
436 {
437     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
438     u_int8_t *msg = mtod(m_in, u_int8_t*);
439     call_desc_t *cd;
440     u_int16_t applid, msgid;
441     u_int32_t NCCI;
442     int bch;
443 
444     if (!m) {
445 	printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
446 	return;
447     }
448 
449     msg = capimsg_getu16(msg + 2, &applid);
450     msg = capimsg_getu16(msg + 2, &msgid);
451     msg = capimsg_getu32(msg, &NCCI);
452 
453     for (bch = 0; bch < sc->sc_nbch; bch++)
454 	if ((sc->sc_bchan[bch].state == B_CONNECT_B3_ACTIVE_IND) &&
455 	    (sc->sc_bchan[bch].ncci == NCCI))
456 	    break;
457 
458     if ((bch == sc->sc_nbch) ||
459 	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
460 	printf("capi%d: can't find channel for b3_active_resp NCCI %x\n",
461 	       sc->sc_unit, NCCI);
462 	return;
463     }
464 
465     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
466     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
467     msg = capimsg_setu16(msg, CAPI_CONNECT_B3_ACTIVE_RESP);
468     msg = capimsg_setu16(msg, msgid);
469 
470     msg = capimsg_setu32(msg, NCCI);
471 
472     sc->send(sc, m);
473 
474     sc->sc_bchan[bch].state = B_CONNECTED;
475 
476     i4b_l4_connect_active_ind(cd);
477 }
478 
479 /*
480 //  Incoming call setup:
481 //  --------------------
482 //
483 //                              <-- CAPI_CONNECT_IND
484 //                       (consult Layer 4)
485 //            CAPI_CONNECT_RESP -->
486 //                              <-- CAPI_CONNECT_ACTIVE_IND
487 //     CAPI_CONNECT_ACTIVE_RESP -->
488 //                              <-- CAPI_CONNECT_B3_IND
489 //         CAPI_CONNECT_B3_RESP -->
490 //                              <-- CAPI_CONNECT_B3_ACTIVE_IND
491 //  CAPI_CONNECT_B3_ACTIVE_RESP -->
492 //                       (notify Layer 4)
493 */
494 
capi_connect_ind(capi_softc_t * sc,struct mbuf * m_in)495 void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
496 {
497     u_int8_t *msg = mtod(m_in, u_int8_t*);
498     call_desc_t *cd;
499     u_int16_t applid, msgid;
500     u_int32_t PLCI;
501     u_int16_t CIP;
502     u_int8_t x, y, z;
503     int bch;
504 
505     if ((cd = reserve_cd()) == NULL) {
506 	printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
507 	return;
508     }
509 
510     cd->isdnif = sc->capi_isdnif;
511     cd->channelexcl = 0;
512     cd->l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
513 
514     for (bch = 0; bch < sc->sc_nbch; bch++)
515 	if (sc->sc_bchan[bch].state == B_FREE)
516 	    break;
517 
518     sc->sc_bchan[bch].state = B_CONNECT_IND;
519     cd->channelid = bch; /* XXX CHAN_ANY XXX */
520 
521     cd->crflag = CRF_DEST;
522     cd->cr = get_rand_cr(sc->sc_unit);
523     cd->scr_ind = SCR_NONE;
524     cd->prs_ind = PRS_NONE;
525     cd->bprot = BPROT_NONE;
526     cd->ilt = NULL;
527     cd->display[0] = '\0';
528     cd->datetime[0] = '\0';
529 
530     msg = capimsg_getu16(msg + 2, &applid);
531     msg = capimsg_getu16(msg + 2, &msgid);
532     msg = capimsg_getu32(msg, &PLCI);
533     msg = capimsg_getu16(msg, &CIP);
534 
535     cd->event = (int) msgid; /* XXX overload */
536     cd->Q931state = (int) PLCI; /* XXX overload */
537 
538     switch (CIP) {
539     case 0x0010:
540     case 0x0001: cd->bprot = BPROT_NONE; break;
541     case 0x0002: cd->bprot = BPROT_RHDLC; break;
542     default:
543 #if 0
544 	NDBGL4(L4_CAPIDBG, "capi%d: unknown CIP = %d", sc->sc_unit, CIP);
545 #endif
546 	cd->bprot = BPROT_NONE;
547     }
548 
549     msg = capimsg_getu8(msg, &x); /* Called party struct len */
550     if (x) {
551 	msg = capimsg_getu8(msg, &y); /* Numbering plan */
552 	z = x - 1;
553 	if (z >= TELNO_MAX) z = (TELNO_MAX-1);
554 	strncpy(cd->dst_telno, msg, z);
555 	msg += x;
556 	x = z;
557     }
558     cd->dst_telno[x] = '\0';
559 
560     msg = capimsg_getu8(msg, &x); /* Calling party struct len */
561     if (x) {
562 	msg = capimsg_getu8(msg, &y); /* Numbering plan */
563 	msg = capimsg_getu8(msg, &y); /* Screening/Presentation */
564 	if ((y & 0x80) == 0) { /* screening used */
565 	    cd->scr_ind = (y & 3) + SCR_USR_NOSC;
566 	    cd->prs_ind = ((y >> 5) & 3) + PRS_ALLOWED;
567 	}
568 	z = x - 2;
569 	if (z >= TELNO_MAX) z = (TELNO_MAX-1);
570 	strncpy(cd->src_telno, msg, z);
571 	msg += x;
572 	x = z;
573     }
574     cd->src_telno[x] = '\0';
575 
576     i4b_l4_connect_ind(cd);
577 }
578 
capi_connect_resp(capi_softc_t * sc,call_desc_t * cd)579 void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
580 {
581     struct isdn_l3_driver *l3drv;
582     struct mbuf *m;
583     u_int8_t *msg;
584     u_int16_t msgid;
585     u_int32_t PLCI;
586     int dlen = strlen(cd->dst_telno);
587 
588     m = i4b_Dgetmbuf(8 + 21 + dlen);
589     if (!m) {
590 	printf("capi%d: can't get mbuf for connect_resp\n", sc->sc_unit);
591 	return;
592     }
593 
594     l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
595 
596     msgid = (u_int16_t) cd->event;
597     PLCI = (u_int32_t) cd->Q931state;
598 
599     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
600     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
601     msg = capimsg_setu16(msg, CAPI_CONNECT_RESP);
602     msg = capimsg_setu16(msg, msgid);
603 
604     msg = capimsg_setu32(msg, PLCI);
605 
606     switch (cd->response) {
607     case SETUP_RESP_ACCEPT:
608 	sc->sc_bchan[cd->channelid].cdid = cd->cdid;
609 	sc->sc_bchan[cd->channelid].ncci = PLCI;
610 	sc->sc_bchan[cd->channelid].state = B_CONNECT_ACTIVE_IND;
611 	l3drv->bch_state[cd->channelid] = BCH_ST_USED;
612 	msg = capimsg_setu16(msg, 0); /* Accept the call */
613 	break;
614 
615     case SETUP_RESP_REJECT:
616 	sc->sc_bchan[cd->channelid].state = B_FREE;
617 	l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
618 	msg = capimsg_setu16(msg, 2); /* Reject, normal call clearing */
619 	break;
620 
621     case SETUP_RESP_DNTCRE:
622 	sc->sc_bchan[cd->channelid].state = B_FREE;
623 	l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
624 	if (sc->sc_nbch == 30) {
625 	    /* With PRI, we can't really ignore calls  -- normal clearing */
626 	    msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_NCCLR));
627 	} else {
628 	    msg = capimsg_setu16(msg, 1); /* Ignore */
629 	}
630 	break;
631 
632     default:
633 	sc->sc_bchan[cd->channelid].state = B_FREE;
634 	l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
635 	msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_CALLREJ));
636     }
637 
638     msg = capimsg_setu8(msg, 15); /* B protocol */
639     if (cd->bprot == BPROT_NONE)
640 	msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
641     else
642 	msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
643     msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
644     msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
645     msg = capimsg_setu8(msg, 0); /* B1 parameters */
646     msg = capimsg_setu8(msg, 0); /* B2 parameters */
647     msg = capimsg_setu8(msg, 0); /* B3 parameters */
648 
649     msg = capimsg_setu8(msg, 1 + dlen);
650     msg = capimsg_setu8(msg, 0x80); /* Numbering plan */
651     strncpy(msg, cd->dst_telno, dlen);
652     msg = capimsg_setu8(msg + dlen, 0); /* Connected subaddress */
653     msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
654     msg = capimsg_setu8(msg, 0); /* Additional Info */
655 
656     sc->send(sc, m);
657 }
658 
capi_connect_b3_ind(capi_softc_t * sc,struct mbuf * m_in)659 void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
660 {
661     struct mbuf *m = i4b_Dgetmbuf(8 + 7);
662     u_int8_t *msg = mtod(m_in, u_int8_t*);
663     u_int16_t applid, msgid;
664     u_int32_t NCCI;
665     int bch;
666 
667     if (!m) {
668 	printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
669 	return;
670     }
671 
672     msg = capimsg_getu16(msg + 2, &applid);
673     msg = capimsg_getu16(msg + 2, &msgid);
674     msg = capimsg_getu32(msg, &NCCI);
675 
676     for (bch = 0; bch < sc->sc_nbch; bch++)
677 	if ((sc->sc_bchan[bch].state == B_CONNECT_B3_IND) &&
678 	    (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
679 	    break;
680 
681     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
682     msg = capimsg_setu16(msg, applid);
683     msg = capimsg_setu16(msg, CAPI_CONNECT_B3_RESP);
684     msg = capimsg_setu16(msg, msgid);
685 
686     msg = capimsg_setu32(msg, NCCI);
687 
688     if (bch == sc->sc_nbch) {
689 	printf("capi%d: can't get cd for connect_b3_resp NCCI %x\n",
690 	       sc->sc_unit, NCCI);
691 	msg = capimsg_setu16(msg, 8); /* Reject, destination OOO */
692 
693     } else {
694 	sc->sc_bchan[bch].ncci = NCCI;
695 	sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
696 	msg = capimsg_setu16(msg, 0); /* Accept */
697     }
698 
699     msg = capimsg_setu8(msg, 0); /* NCPI */
700 
701     sc->send(sc, m);
702 }
703 
704 /*
705 //  Data transfer:
706 //  --------------
707 */
708 
capi_data_b3_req(capi_softc_t * sc,int chan,struct mbuf * m_b3)709 void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
710 {
711     struct mbuf *m = i4b_Dgetmbuf(8 + 14);
712     u_int8_t *msg;
713     u_int16_t msgid;
714 
715     if (!m) {
716 	printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
717 	return;
718     }
719 
720     msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
721     sc->sc_bchan[chan].busy = 1;
722 
723     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
724     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
725     msg = capimsg_setu16(msg, CAPI_DATA_B3_REQ);
726     msg = capimsg_setu16(msg, msgid);
727 
728     msg = capimsg_setu32(msg, sc->sc_bchan[chan].ncci);
729     msg = capimsg_setu32(msg, (u_int32_t) m_b3->m_data); /* Pointer */
730     msg = capimsg_setu16(msg, m_b3->m_len);
731     msg = capimsg_setu16(msg, chan);
732     msg = capimsg_setu16(msg, 0); /* Flags */
733 
734     m->m_next = m_b3;
735 
736     sc->send(sc, m);
737 }
738 
capi_data_b3_conf(capi_softc_t * sc,struct mbuf * m_in)739 void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
740 {
741     u_int8_t *msg = mtod(m_in, u_int8_t*);
742     u_int32_t NCCI;
743     u_int16_t handle;
744     u_int16_t Info;
745 
746     msg = capimsg_getu32(msg + 8, &NCCI);
747     msg = capimsg_getu16(msg, &handle);
748     msg = capimsg_getu16(msg, &Info);
749 
750     if (Info == 0) {
751 	sc->sc_bchan[handle].busy = 0;
752 	capi_start_tx(sc, handle);
753 
754     } else {
755 	printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
756 	       sc->sc_unit, NCCI, handle, Info);
757     }
758 }
759 
capi_data_b3_ind(capi_softc_t * sc,struct mbuf * m_in)760 void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
761 {
762     struct mbuf *m = i4b_Dgetmbuf(8 + 6);
763     u_int8_t *msg = mtod(m_in, u_int8_t*);
764     u_int16_t applid, msgid;
765     u_int32_t NCCI;
766     u_int16_t handle;
767     int bch;
768 
769     if (!m) {
770 	printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
771 	return;
772     }
773 
774     msg = capimsg_getu16(msg + 2, &applid);
775     msg = capimsg_getu16(msg + 2, &msgid);
776     msg = capimsg_getu32(msg, &NCCI);
777     msg = capimsg_getu16(msg + 6, &handle);
778 
779     for (bch = 0; bch < sc->sc_nbch; bch++)
780 	if ((sc->sc_bchan[bch].state == B_CONNECTED) &&
781 	    (sc->sc_bchan[bch].ncci == NCCI))
782 	    break;
783 
784     if (bch == sc->sc_nbch) {
785 	printf("capi%d: can't find channel for data_b3_ind NCCI %x\n",
786 	       sc->sc_unit, NCCI);
787 
788     } else {
789 	if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
790 	    /* HDLC drivers use rx_mbuf */
791 
792 	    sc->sc_bchan[bch].in_mbuf = m_in->m_next;
793 	    sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
794 	    m_in->m_next = NULL; /* driver frees */
795 
796 	    (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
797 		sc->sc_bchan[bch].l4_driver_softc);
798 
799 	} else {
800 	    /* Telephony drivers use rx_queue */
801 
802 	    if (!IF_QFULL(&sc->sc_bchan[bch].rx_queue)) {
803 		IF_ENQUEUE(&sc->sc_bchan[bch].rx_queue, m_in->m_next);
804 		sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
805 		m_in->m_next = NULL; /* driver frees */
806 	    }
807 
808 	    (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
809 		sc->sc_bchan[bch].l4_driver_softc);
810 	}
811     }
812 
813     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
814     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
815     msg = capimsg_setu16(msg, CAPI_DATA_B3_RESP);
816     msg = capimsg_setu16(msg, msgid);
817 
818     msg = capimsg_setu32(msg, NCCI);
819     msg = capimsg_setu16(msg, handle);
820 
821     sc->send(sc, m);
822 }
823 
824 /*
825 //  Connection teardown:
826 //  --------------------
827 */
828 
capi_disconnect_req(capi_softc_t * sc,call_desc_t * cd)829 void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
830 {
831     struct isdn_l3_driver *l3drv;
832     struct mbuf *m = i4b_Dgetmbuf(8 + 5);
833     u_int8_t *msg;
834     u_int16_t msgid;
835     u_int32_t PLCI;
836 
837     if (!m) {
838 	printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
839 	return;
840     }
841 
842     l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
843 
844     sc->sc_bchan[cd->channelid].state = B_DISCONNECT_CONF;
845     l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
846     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
847     PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
848 
849     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
850     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
851     msg = capimsg_setu16(msg, CAPI_DISCONNECT_REQ);
852     msg = capimsg_setu16(msg, msgid);
853 
854     msg = capimsg_setu32(msg, PLCI);
855     msg = capimsg_setu8(msg, 0); /* Additional Info */
856 
857     sc->send(sc, m);
858 }
859 
capi_disconnect_conf(capi_softc_t * sc,struct mbuf * m_in)860 void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
861 {
862     struct isdn_l3_driver *l3drv;
863     u_int8_t *msg = mtod(m_in, u_int8_t*);
864     call_desc_t *cd;
865     u_int32_t PLCI;
866     int bch;
867 
868     msg = capimsg_getu32(msg + 8, &PLCI);
869 
870     for (bch = 0; bch < sc->sc_nbch; bch++)
871 	if ((sc->sc_bchan[bch].state == B_DISCONNECT_CONF) &&
872 	    ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
873 	    break;
874 
875     if (bch == sc->sc_nbch) {
876 	printf("capi%d: can't find channel for disconnect_conf PLCI %x\n",
877 	       sc->sc_unit, PLCI);
878 	return;
879     }
880 
881     cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
882     if (!cd) {
883 	printf("capi%d: can't find cd for disconnect_conf PLCI %x\n",
884 	       sc->sc_unit, PLCI);
885     } else {
886 	i4b_l4_disconnect_ind(cd);
887 	freecd_by_cd(cd);
888     }
889 
890     l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
891 
892     sc->sc_bchan[bch].state = B_FREE;
893     l3drv->bch_state[bch] = BCH_ST_FREE;
894 }
895 
capi_disconnect_b3_ind(capi_softc_t * sc,struct mbuf * m_in)896 void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
897 {
898     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
899     u_int8_t *msg = mtod(m_in, u_int8_t*);
900     u_int16_t applid, msgid;
901     u_int32_t NCCI;
902 
903     if (!m) {
904 	printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
905 	return;
906     }
907 
908     msg = capimsg_getu16(msg + 2, &applid);
909     msg = capimsg_getu16(msg + 2, &msgid);
910     msg = capimsg_getu32(msg, &NCCI);
911 
912     /* XXX update bchan state? XXX */
913 
914     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
915     msg = capimsg_setu16(msg, applid);
916     msg = capimsg_setu16(msg, CAPI_DISCONNECT_B3_RESP);
917     msg = capimsg_setu16(msg, msgid);
918 
919     msg = capimsg_setu32(msg, NCCI);
920 
921     sc->send(sc, m);
922 }
923 
capi_disconnect_ind(capi_softc_t * sc,struct mbuf * m_in)924 void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
925 {
926     struct isdn_l3_driver *l3drv;
927     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
928     u_int8_t *msg = mtod(m_in, u_int8_t*);
929     call_desc_t *cd;
930     u_int16_t applid, msgid;
931     u_int32_t PLCI;
932     u_int16_t Reason;
933     int bch;
934 
935     if (!m) {
936 	printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
937 	return;
938     }
939 
940     msg = capimsg_getu16(msg + 2, &applid);
941     msg = capimsg_getu16(msg + 2, &msgid);
942     msg = capimsg_getu32(msg, &PLCI);
943     msg = capimsg_getu16(msg, &Reason);
944 
945     for (bch = 0; bch < sc->sc_nbch; bch++)
946 	if ((sc->sc_bchan[bch].state != B_FREE) &&
947 	    ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
948 	    break;
949 
950     if (bch < sc->sc_nbch) {
951 	/* We may not have a bchan assigned if call was ignored. */
952 
953 	cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
954 	sc->sc_bchan[bch].state = B_DISCONNECT_IND;
955     } else
956 	cd = NULL;
957 
958     if (cd) {
959 	if ((Reason & 0xff00) == 0x3400) {
960 	    SET_CAUSE_TV(cd->cause_in, CAUSET_Q850, (Reason & 0x7f));
961 	} else {
962 	    SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_NORMAL);
963 	}
964 
965 	i4b_l4_disconnect_ind(cd);
966 	freecd_by_cd(cd);
967 
968 	sc->sc_bchan[bch].state = B_FREE;
969 	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
970 	l3drv->bch_state[bch] = BCH_ST_FREE;
971     }
972 
973     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
974     msg = capimsg_setu16(msg, applid);
975     msg = capimsg_setu16(msg, CAPI_DISCONNECT_RESP);
976     msg = capimsg_setu16(msg, msgid);
977 
978     msg = capimsg_setu32(msg, PLCI);
979 
980     sc->send(sc, m);
981 }
982