Fixes and improves parsing of config file.
[lcr.git] / gsm.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN gsm                                                                 **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 #ifndef _GNU_SOURCE
15 #define _GNU_SOURCE
16 #endif
17 extern "C" {
18 #include <getopt.h>
19
20 #include <openbsc/db.h>
21 #include <openbsc/select.h>
22 #include <openbsc/debug.h>
23 #include <openbsc/e1_input.h>
24 #include <openbsc/talloc.h>
25 #include <openbsc/mncc.h>
26 #include <openbsc/trau_frame.h>
27 struct gsm_network *bsc_gsmnet = 0;
28 extern int ipacc_rtp_direct;
29 extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
30                                  const char *cfg_file);
31 extern int bsc_shutdown_net(struct gsm_network *net);
32 void talloc_ctx_init(void);
33 void on_dso_load_token(void);
34 void on_dso_load_rrlp(void);
35
36 #include "gsm_audio.h"
37
38 #undef AF_ISDN
39 #undef PF_ISDN
40 extern  int     AF_ISDN;
41 #define PF_ISDN AF_ISDN
42 }
43
44
45 struct lcr_gsm *gsm = NULL;
46
47 static unsigned int new_callref = 1;
48
49
50 /*
51  * create and send mncc message
52  */
53 static struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
54 {
55         struct gsm_mncc *mncc;
56
57         mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
58         mncc->msg_type = msg_type;
59         mncc->callref = callref;
60         return (mncc);
61 }
62 static int send_and_free_mncc(struct gsm_network *net, unsigned int msg_type, void *data)
63 {
64         int ret;
65
66         ret = mncc_send(net, msg_type, data);
67         free(data);
68
69         return ret;
70 }
71
72
73 /*
74  * constructor
75  */
76 Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
77 {
78         p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
79         p_m_g_callref = 0;
80         p_m_g_mode = 0;
81         p_m_g_gsm_b_sock = -1;
82         p_m_g_gsm_b_index = -1;
83         p_m_g_gsm_b_active = 0;
84         p_m_g_notify_pending = NULL;
85         p_m_g_decoder = gsm_audio_create();
86         p_m_g_encoder = gsm_audio_create();
87         if (!p_m_g_encoder || !p_m_g_decoder) {
88                 PERROR("Failed to create GSM audio codec instance\n");
89                 p_m_delete = 1;
90         }
91         p_m_g_rxpos = 0;
92         p_m_g_tch_connected = 0;
93
94         PDEBUG(DEBUG_GSM, "Created new mISDNPort(%s).\n", portname);
95 }
96
97 /*
98  * destructor
99  */
100 Pgsm::~Pgsm()
101 {
102         PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
103
104         /* remove queued message */
105         if (p_m_g_notify_pending)
106                 message_free(p_m_g_notify_pending);
107
108         /* close audio transfer socket */
109         if (p_m_g_gsm_b_sock > -1)
110                 bchannel_close();
111
112         /* close codec */
113         if (p_m_g_encoder)
114                 gsm_audio_destroy(p_m_g_encoder);
115         if (p_m_g_decoder)
116                 gsm_audio_destroy(p_m_g_decoder);
117 }
118
119
120 /* close bsc side bchannel */
121 void Pgsm::bchannel_close(void)
122 {
123         if (p_m_g_gsm_b_sock > -1)
124                 close(p_m_g_gsm_b_sock);
125         p_m_g_gsm_b_sock = -1;
126         p_m_g_gsm_b_index = -1;
127         p_m_g_gsm_b_active = 0;
128 }
129
130 /* open bsc side bchannel */
131 int Pgsm::bchannel_open(int index)
132 {
133         int ret;
134         unsigned int on = 1;
135         struct sockaddr_mISDN addr;
136         struct mISDNhead act;
137
138         if (p_m_g_gsm_b_sock > -1) {
139                 PERROR("Socket already created for index %d\n", index);
140                 return(-EIO);
141         }
142
143         /* open socket */
144         ret = p_m_g_gsm_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
145         if (ret < 0) {
146                 PERROR("Failed to open bchannel-socket for index %d\n", index);
147                 bchannel_close();
148                 return(ret);
149         }
150         
151         /* set nonblocking io */
152         ret = ioctl(p_m_g_gsm_b_sock, FIONBIO, &on);
153         if (ret < 0) {
154                 PERROR("Failed to set bchannel-socket index %d into nonblocking IO\n", index);
155                 bchannel_close();
156                 return(ret);
157         }
158
159         /* bind socket to bchannel */
160         addr.family = AF_ISDN;
161         addr.dev = gsm->gsm_port;
162         addr.channel = index+1+(index>15);
163         ret = bind(p_m_g_gsm_b_sock, (struct sockaddr *)&addr, sizeof(addr));
164         if (ret < 0) {
165                 PERROR("Failed to bind bchannel-socket for index %d\n", index);
166                 bchannel_close();
167                 return(ret);
168         }
169         /* activate bchannel */
170         PDEBUG(DEBUG_GSM, "Activating GSM side channel index %i.\n", index);
171         act.prim = PH_ACTIVATE_REQ; 
172         act.id = 0;
173         ret = sendto(p_m_g_gsm_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
174         if (ret < 0) {
175                 PERROR("Failed to activate index %d\n", index);
176                 bchannel_close();
177                 return(ret);
178         }
179
180         p_m_g_gsm_b_index = index;
181
182         return(0);
183 }
184
185 /* receive from bchannel */
186 void Pgsm::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
187 {
188         int i, j, k;
189         unsigned char frame[33];
190         struct decoded_trau_frame tf;
191
192         /* encoder init failed */
193         if (!p_m_g_encoder)
194                 return;
195
196         /* (currently) not connected, so don't flood tch! */
197         if (!p_m_g_tch_connected)
198                 return;
199
200         /* write to rx buffer */
201         while(len--) {
202                 p_m_g_rxdata[p_m_g_rxpos++] = audio_law_to_s32[*data++];
203                 if (p_m_g_rxpos == 160) {
204                         p_m_g_rxpos = 0;
205
206                         /* encode data */
207                         gsm_audio_encode(p_m_g_encoder, p_m_g_rxdata, frame);
208
209                         /* set c-bits and t-bits */
210                         tf.c_bits[0] = 1;
211                         tf.c_bits[1] = 1;
212                         tf.c_bits[2] = 1;
213                         tf.c_bits[3] = 0;
214                         tf.c_bits[4] = 0;
215                         memset(&tf.c_bits[5], 0, 6);
216                         memset(&tf.c_bits[11], 1, 10);
217                         memset(&tf.t_bits[0], 1, 4);
218
219                         /* reassemble d-bits */
220                         i = 0;
221                         j = 0;
222                         k = 0;
223                         while(i < 260) {
224                                 tf.d_bits[i] = (frame[j] >> k) & 1;
225                                 if (++k == 8) {
226                                         k = 0;
227                                         j++;
228                                 }
229                                 i++;
230                         }
231
232                         trau_send(&tf);
233                 }
234         }
235 }
236
237 /* transmit to bchannel */
238 void Pgsm::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
239 {
240         unsigned char buf[MISDN_HEADER_LEN+len];
241         struct mISDNhead *hh = (struct mISDNhead *)buf;
242         int ret;
243
244         if (!p_m_g_gsm_b_active)
245                 return;
246
247         /* make and send frame */
248         hh->prim = PH_DATA_REQ;
249         hh->id = 0;
250         memcpy(buf+MISDN_HEADER_LEN, data, len);
251         ret = sendto(p_m_g_gsm_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
252         if (ret <= 0)
253                 PERROR("Failed to send to socket index %d\n", index);
254 }
255
256 void Pgsm::trau_send(void *_tf)
257 {
258         struct decoded_trau_frame *tf = (struct decoded_trau_frame *)_tf;
259         unsigned char data[sizeof(struct gsm_trau_frame) + sizeof(struct decoded_trau_frame)];
260         struct gsm_trau_frame *frame = (struct gsm_trau_frame *)data;
261         
262         frame->msg_type = GSM_TRAU_FRAME;
263         frame->callref = p_m_g_callref;
264         memcpy(frame->data, tf, sizeof(struct decoded_trau_frame));
265         mncc_send((struct gsm_network *)gsm->network, frame->msg_type, frame);
266 }
267
268
269 void Pgsm::trau_receive(void *_frame)
270 {
271         struct gsm_trau_frame *frm = (struct gsm_trau_frame *)_frame;
272         struct decoded_trau_frame *tf = (struct decoded_trau_frame *)frm->data;
273 //struct decoded_trau_frame *tf = (struct decoded_trau_frame *)_frame;
274         unsigned char frame[33];
275         signed short samples[160];
276         unsigned char data[160];
277         int i, j, k;
278
279         if (!p_m_g_decoder)
280                 return;
281
282 //      printf("got trau %d %d %d %d %d\n", tf->c_bits[0], tf->c_bits[1], tf->c_bits[2], tf->c_bits[3], tf->c_bits[4]);
283         if (tf->c_bits[0]!=0 || tf->c_bits[1]!=0 || tf->c_bits[2]!=0 || tf->c_bits[3]!=1 || tf->c_bits[4]!=0)
284                 PERROR("illegal trau (C1-C5) %d %d %d %d %d\n", tf->c_bits[0], tf->c_bits[1], tf->c_bits[2], tf->c_bits[3], tf->c_bits[4]);
285
286         /* set GSM_MAGIC */
287         memset(&frame, 0, sizeof(frame));
288 //      frame[0] = 0xd << 4;
289
290         /* reassemble bits */
291         i = 0;
292         j = 0;
293         k = 0;
294         while(i < 260) {
295                 if (tf->d_bits[i] > 1)
296                         PERROR("fix!\n");
297                 frame[j] |= (tf->d_bits[i] << k);
298                 if (++k == 8) {
299                         k = 0;
300                         j++;
301                 }
302                 i++;
303         }
304         
305         /* decode */
306         gsm_audio_decode(p_m_g_decoder, frame, samples);
307         for (i = 0; i < 160; i++) {
308                 data[i] = audio_s16_to_law[samples[i] & 0xffff];
309         }
310
311         /* send */
312         bchannel_send(PH_DATA_REQ, 0, data, 160);
313 }
314
315
316 /*
317  * create trace
318  **/
319 static void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction)
320 {
321         char msgtext[64];
322
323         /* select message and primitive text */
324         SCPY(msgtext, get_mncc_name(msg_type));
325
326         /* add direction */
327         if (direction == DIRECTION_OUT)
328                 SCAT(msgtext, " MSC->BSC");
329         else
330                 SCAT(msgtext, " MSC<-BSC");
331
332         /* init trace with given values */
333         start_trace(mISDNport?mISDNport->portnum:-1,
334                     mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
335                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
336                     port?port->p_dialinginfo.id:NULL,
337                     direction,
338                     CATEGORY_CH,
339                     port?port->p_serial:0,
340                     msgtext);
341 }
342
343
344
345 /* select bchannel */
346 int Pgsm::hunt_bchannel(void)
347 {
348         int channel;
349         int i;
350
351         chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (setup)", DIRECTION_NONE);
352         add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved);
353         if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) { // of out chan..
354                 add_trace("conclusion", NULL, "all channels are reserved");
355                 end_trace();
356                 return(-34); // no channel
357         }
358         /* find channel */
359         i = 0;
360         channel = 0;
361         while(i < p_m_mISDNport->b_num) {
362                 if (p_m_mISDNport->b_port[i] == NULL) {
363                         channel = i+1+(i>=15);
364                         break;
365                 }
366                 i++;
367         }
368         if (!channel) {
369                 add_trace("conclusion", NULL, "no channel available");
370                 end_trace();
371                 return(-6); // channel unacceptable
372         }
373         add_trace("conclusion", NULL, "channel available");
374         add_trace("connect", "channel", "%d", channel);
375         end_trace();
376         return(channel);
377 }
378
379
380 /*
381  * handles all indications
382  */
383 /* SETUP INDICATION */
384 void Pgsm::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
385 {
386         int ret;
387         class Endpoint *epoint;
388         struct lcr_msg *message;
389         int channel;
390         struct gsm_mncc *mode, *proceeding, *frame;
391
392         /* emergency shutdown */
393         printf("%d %d\n", mncc->emergency, !gsm->conf.noemergshut);
394         if (mncc->emergency && !gsm->conf.noemergshut) {
395                 start_trace(p_m_mISDNport->portnum,
396                         p_m_mISDNport->ifport->interface,
397                         NULL,
398                         NULL,
399                         DIRECTION_NONE,
400                         CATEGORY_CH,
401                         0,
402                         "EMERGENCY SHUTDOWN (due to received emergency call)");
403                 end_trace();
404                 quit = 1;
405         }
406         /* process given callref */
407         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
408         add_trace("callref", "new", "0x%x", callref);
409         if (p_m_g_callref) {
410                 /* release in case the ID is already in use */
411                 add_trace("error", NULL, "callref already in use");
412                 end_trace();
413                 mncc = create_mncc(MNCC_REJ_REQ, callref);
414                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
415                 mncc->fields |= MNCC_F_CAUSE;
416                 mncc->cause.coding = 3;
417                 mncc->cause.location = 1;
418                 mncc->cause.value = 47;
419                 add_trace("cause", "coding", "%d", mncc->cause.coding);
420                 add_trace("cause", "location", "%d", mncc->cause.location);
421                 add_trace("cause", "value", "%d", mncc->cause.value);
422                 add_trace("reason", NULL, "callref already in use");
423                 end_trace();
424                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
425                 new_state(PORT_STATE_RELEASE);
426                 p_m_delete = 1;
427                 return;
428         }
429         p_m_g_callref = callref;
430         end_trace();
431
432         /* if blocked, release call with MT_RELEASE_COMPLETE */
433         if (p_m_mISDNport->ifport->block) {
434                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
435                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
436                 mncc->fields |= MNCC_F_CAUSE;
437                 mncc->cause.coding = 3;
438                 mncc->cause.location = 1;
439                 mncc->cause.value = 27;
440                 add_trace("cause", "coding", "%d", mncc->cause.coding);
441                 add_trace("cause", "location", "%d", mncc->cause.location);
442                 add_trace("cause", "value", "%d", mncc->cause.value);
443                 add_trace("reason", NULL, "port is blocked");
444                 end_trace();
445                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
446                 new_state(PORT_STATE_RELEASE);
447                 p_m_delete = 1;
448                 return;
449         }
450
451         /* caller info */
452         if (mncc->clir.inv)
453                 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
454         else
455                 p_callerinfo.present = INFO_PRESENT_ALLOWED;
456         if (mncc->calling.number[0])
457                 SCPY(p_callerinfo.id, mncc->calling.number);
458         else
459                 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
460         SCPY(p_callerinfo.imsi, mncc->imsi);
461         p_callerinfo.screen = INFO_SCREEN_NETWORK;
462         p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
463         p_callerinfo.isdn_port = p_m_portnum;
464         SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
465
466         /* dialing information */
467         SCAT(p_dialinginfo.id, mncc->called.number);
468         switch (mncc->called.type) {
469                 case 0x1:
470                 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
471                 break;
472                 case 0x2:
473                 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
474                 break;
475                 case 0x4:
476                 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
477                 break;
478                 default:
479                 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
480                 break;
481         }
482         if (mncc->emergency) {
483                 SCPY(p_dialinginfo.id, "emergency");
484         }
485         p_dialinginfo.sending_complete = 1;
486
487         /* bearer capability */
488         // todo
489         p_capainfo.bearer_capa = INFO_BC_SPEECH;
490         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
491         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
492         p_capainfo.source_mode = B_MODE_TRANSPARENT;
493         p_m_g_mode = p_capainfo.source_mode;
494
495         /* useruser */
496
497         /* hunt channel */
498         ret = channel = hunt_bchannel();
499         if (ret < 0)
500                 goto no_channel;
501
502         /* open channel */
503         ret = seize_bchannel(channel, 1);
504         if (ret < 0) {
505                 no_channel:
506                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
507                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
508                 mncc->fields |= MNCC_F_CAUSE;
509                 mncc->cause.coding = 3;
510                 mncc->cause.location = 1;
511                 mncc->cause.value = 34;
512                 add_trace("cause", "coding", "%d", mncc->cause.coding);
513                 add_trace("cause", "location", "%d", mncc->cause.location);
514                 add_trace("cause", "value", "%d", mncc->cause.value);
515                 add_trace("reason", NULL, "no channel");
516                 end_trace();
517                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
518                 new_state(PORT_STATE_RELEASE);
519                 p_m_delete = 1;
520                 return;
521         }
522         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
523         if (bchannel_open(p_m_b_index))
524                 goto no_channel;
525
526         /* what infos did we got ... */
527         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
528         if (p_callerinfo.id[0])
529                 add_trace("calling", "number", "%s", p_callerinfo.id);
530         else
531                 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
532         add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
533         add_trace("dialing", "number", "%s", p_dialinginfo.id);
534         end_trace();
535
536         /* create endpoint */
537         if (p_epointlist)
538                 FATAL("Incoming call but already got an endpoint.\n");
539         if (!(epoint = new Endpoint(p_serial, 0)))
540                 FATAL("No memory for Endpoint instance\n");
541         if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
542                 FATAL("No memory for Endpoint Application instance\n");
543         epointlist_new(epoint->ep_serial);
544
545         /* modify lchan to GSM codec V1 */
546         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
547         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
548         mode->lchan_mode = 0x01; /* GSM V1 */
549         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
550         end_trace();
551         send_and_free_mncc((struct gsm_network *)gsm->network, mode->msg_type, mode);
552
553         /* send call proceeding */
554         gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
555         proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
556         if (p_m_mISDNport->tones) {
557                 proceeding->fields |= MNCC_F_PROGRESS;
558                 proceeding->progress.coding = 3; /* GSM */
559                 proceeding->progress.location = 1;
560                 proceeding->progress.descr = 8;
561                 add_trace("progress", "coding", "%d", proceeding->progress.coding);
562                 add_trace("progress", "location", "%d", proceeding->progress.location);
563                 add_trace("progress", "descr", "%d", proceeding->progress.descr);
564         }
565         end_trace();
566         send_and_free_mncc((struct gsm_network *)gsm->network, proceeding->msg_type, proceeding);
567
568         new_state(PORT_STATE_IN_PROCEEDING);
569
570         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
571                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
572                 end_trace();
573                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
574                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
575                 p_m_g_tch_connected = 1;
576         }
577
578         /* send setup message to endpoit */
579         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
580         message->param.setup.isdn_port = p_m_portnum;
581         message->param.setup.port_type = p_type;
582 //      message->param.setup.dtmf = 0;
583         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
584         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
585         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
586         SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
587         message->param.setup.useruser.len = strlen(mncc->useruser.info);
588         message->param.setup.useruser.protocol = mncc->useruser.proto;
589         message_put(message);
590 }
591
592 /* DTMF INDICATION */
593 void Pgsm::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
594 {
595         struct lcr_msg *message;
596         struct gsm_mncc *resp;
597
598         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
599         add_trace("keypad", NULL, "%c", mncc->keypad);
600         end_trace();
601         SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
602         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
603
604         /* send resp */
605         gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
606         add_trace("keypad", NULL, "%c", mncc->keypad);
607         end_trace();
608         resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
609         resp->keypad = mncc->keypad;
610         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
611
612         /* send dialing information */
613         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
614         memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
615         message_put(message);
616 }
617 void Pgsm::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
618 {
619         struct gsm_mncc *resp;
620
621         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
622         add_trace("keypad", NULL, "%c", mncc->keypad);
623         end_trace();
624
625         /* send resp */
626         gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
627         add_trace("keypad", NULL, "%c", mncc->keypad);
628         end_trace();
629         resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
630         resp->keypad = mncc->keypad;
631         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
632 }
633
634 /* PROCEEDING INDICATION */
635 void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
636 {
637         struct gsm_mncc *mode;
638
639         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
640         if (mncc->fields & MNCC_F_CAUSE) {
641                 add_trace("cause", "coding", "%d", mncc->cause.coding);
642                 add_trace("cause", "location", "%", mncc->cause.location);
643                 add_trace("cause", "value", "%", mncc->cause.value);
644         }
645         end_trace();
646
647         /* modify lchan to GSM codec V1 */
648         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
649         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
650         mode->lchan_mode = 0x01; /* GSM V1 */
651         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
652         end_trace();
653         send_and_free_mncc((struct gsm_network *)gsm->network, mode->msg_type, mode);
654
655 }
656
657 /* ALERTING INDICATION */
658 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
659 {
660         struct lcr_msg *message;
661
662         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
663         end_trace();
664
665         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
666         message_put(message);
667
668         new_state(PORT_STATE_OUT_ALERTING);
669
670 }
671
672 /* CONNECT INDICATION */
673 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
674 {
675         struct gsm_mncc *resp, *frame;
676         struct lcr_msg *message;
677
678         SCPY(p_connectinfo.id, mncc->connected.number);
679         SCPY(p_connectinfo.imsi, mncc->imsi);
680         p_connectinfo.present = INFO_PRESENT_ALLOWED;
681         p_connectinfo.screen = INFO_SCREEN_NETWORK;
682         p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
683         p_connectinfo.isdn_port = p_m_portnum;
684         SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
685
686         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
687         if (p_connectinfo.id[0])
688                 add_trace("connect", "number", "%s", p_connectinfo.id);
689         else if (mncc->imsi[0])
690                 SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
691         if (mncc->imsi[0])
692                 add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
693         end_trace();
694
695         /* send resp */
696         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
697         resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
698         end_trace();
699         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
700
701         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
702         memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
703         message_put(message);
704
705         new_state(PORT_STATE_CONNECT);
706
707         if (!p_m_g_tch_connected) { /* only if ... */
708                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
709                 end_trace();
710                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
711                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
712                 p_m_g_tch_connected = 1;
713         }
714 }
715
716 /* CONNECT ACK INDICATION */
717 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
718 {
719         struct gsm_mncc *frame;
720
721         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
722         end_trace();
723
724         new_state(PORT_STATE_CONNECT);
725
726         if (!p_m_g_tch_connected) { /* only if ... */
727                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
728                 end_trace();
729                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
730                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
731                 p_m_g_tch_connected = 1;
732         }
733 }
734
735 /* DISCONNECT INDICATION */
736 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
737 {
738         struct lcr_msg *message;
739         int cause = 16, location = 0;
740         struct gsm_mncc *resp;
741
742         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
743         if (mncc->fields & MNCC_F_CAUSE) {
744                 location = mncc->cause.location;
745                 cause = mncc->cause.value;
746                 add_trace("cause", "coding", "%d", mncc->cause.coding);
747                 add_trace("cause", "location", "%d", location);
748                 add_trace("cause", "value", "%d", cause);
749         }
750         end_trace();
751
752         /* send release */
753         resp = create_mncc(MNCC_REL_REQ, p_m_g_callref);
754         gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
755 #if 0
756         resp->fields |= MNCC_F_CAUSE;
757         resp->cause.coding = 3;
758         resp->cause.location = 1;
759         resp->cause.value = cause;
760         add_trace("cause", "coding", "%d", resp->cause.coding);
761         add_trace("cause", "location", "%d", resp->cause.location);
762         add_trace("cause", "value", "%d", resp->cause.value);
763 #endif
764         end_trace();
765         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
766
767         /* sending release to endpoint */
768         while(p_epointlist) {
769                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
770                 message->param.disconnectinfo.cause = cause;
771                 message->param.disconnectinfo.location = location;
772                 message_put(message);
773                 /* remove epoint */
774                 free_epointlist(p_epointlist);
775         }
776         new_state(PORT_STATE_RELEASE);
777         p_m_delete = 1;
778 }
779
780 /* CC_RELEASE INDICATION */
781 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
782 {
783         int location = 0, cause = 16;
784         struct lcr_msg *message;
785
786         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
787         if (mncc->fields & MNCC_F_CAUSE) {
788                 location = mncc->cause.location;
789                 cause = mncc->cause.value;
790                 add_trace("cause", "coding", "%d", mncc->cause.coding);
791                 add_trace("cause", "location", "%d", mncc->cause.location);
792                 add_trace("cause", "value", "%d", mncc->cause.value);
793         }
794         end_trace();
795
796         /* sending release to endpoint */
797         while(p_epointlist) {
798                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
799                 message->param.disconnectinfo.cause = cause;
800                 message->param.disconnectinfo.location = location;
801                 message_put(message);
802                 /* remove epoint */
803                 free_epointlist(p_epointlist);
804         }
805         new_state(PORT_STATE_RELEASE);
806         p_m_delete = 1;
807 }
808
809 /* NOTIFY INDICATION */
810 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
811 {
812         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
813         end_trace();
814 }
815
816
817 /* HOLD INDICATION */
818 void Pgsm::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
819 {
820         struct lcr_msg *message;
821         struct gsm_mncc *resp, *frame;
822
823         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
824         end_trace();
825
826         /* notify the hold of call */
827         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
828         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
829         message->param.notifyinfo.local = 1; /* call is held by supplementary service */
830         message_put(message);
831
832         /* acknowledge hold */
833         gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
834         end_trace();
835         resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
836         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
837
838         /* disable audio */
839         if (p_m_g_tch_connected) { /* it should be true */
840                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
841                 end_trace();
842                 frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
843                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
844                 p_m_g_tch_connected = 0;
845         }
846 }
847
848
849 /* RETRIEVE INDICATION */
850 void Pgsm::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
851 {
852         struct lcr_msg *message;
853         struct gsm_mncc *resp, *frame;
854
855         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
856         end_trace();
857
858         /* notify the retrieve of call */
859         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
860         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
861         message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
862         message_put(message);
863
864         /* acknowledge retr */
865         gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
866         end_trace();
867         resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
868         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
869
870         /* enable audio */
871         if (!p_m_g_tch_connected) { /* it should be true */
872                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
873                 end_trace();
874                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
875                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
876                 p_m_g_tch_connected = 1;
877         }
878 }
879
880 /*
881  * BSC sends message to port
882  */
883 static int message_bsc(struct gsm_network *net, int msg_type, void *arg)
884 {
885         struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
886         unsigned int callref = mncc->callref;
887         class Port *port;
888         class Pgsm *pgsm = NULL;
889         char name[64];
890         struct mISDNport *mISDNport;
891
892         /* Special messages */
893         switch(msg_type) {
894         }
895
896         /* find callref */
897         callref = mncc->callref;
898         port = port_first;
899         while(port) {
900                 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_GSM) {
901                         pgsm = (class Pgsm *)port;
902                         if (pgsm->p_m_g_callref == callref) {
903                                 break;
904                         }
905                 }
906                 port = port->next;
907         }
908
909         if (msg_type == GSM_TRAU_FRAME) {
910                 if (port)
911                         pgsm->trau_receive((struct gsm_trau_frame *)arg);
912                 return 0;
913         }
914
915         if (!port) {
916                 if (msg_type != MNCC_SETUP_IND)
917                         return(0);
918                 /* find gsm port */
919                 mISDNport = mISDNport_first;
920                 while(mISDNport) {
921                         if (mISDNport->gsm)
922                                 break;
923                         mISDNport = mISDNport->next;
924                 }
925                 if (!mISDNport) {
926                         struct gsm_mncc *rej;
927
928                         rej = create_mncc(MNCC_REJ_REQ, callref);
929                         rej->fields |= MNCC_F_CAUSE;
930                         rej->cause.coding = 3;
931                         rej->cause.location = 1;
932                         rej->cause.value = 27;
933                         gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
934                         add_trace("cause", "coding", "%d", rej->cause.coding);
935                         add_trace("cause", "location", "%d", rej->cause.location);
936                         add_trace("cause", "value", "%d", rej->cause.value);
937                         end_trace();
938                         send_and_free_mncc((struct gsm_network *)gsm->network, rej->msg_type, rej);
939                         return 0;
940                 }
941                 /* creating port object, transparent until setup with hdlc */
942                 SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
943                 if (!(pgsm = new Pgsm(PORT_TYPE_GSM_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
944
945                         FATAL("Cannot create Port instance.\n");
946         }
947
948         switch(msg_type) {
949                 case MNCC_SETUP_IND:
950                 pgsm->setup_ind(msg_type, callref, mncc);
951                 break;
952
953                 case MNCC_START_DTMF_IND:
954                 pgsm->start_dtmf_ind(msg_type, callref, mncc);
955                 break;
956
957                 case MNCC_STOP_DTMF_IND:
958                 pgsm->stop_dtmf_ind(msg_type, callref, mncc);
959                 break;
960
961                 case MNCC_CALL_CONF_IND:
962                 pgsm->call_conf_ind(msg_type, callref, mncc);
963                 break;
964
965                 case MNCC_ALERT_IND:
966                 pgsm->alert_ind(msg_type, callref, mncc);
967                 break;
968
969                 case MNCC_SETUP_CNF:
970                 pgsm->setup_cnf(msg_type, callref, mncc);
971                 break;
972
973                 case MNCC_SETUP_COMPL_IND:
974                 pgsm->setup_compl_ind(msg_type, callref, mncc);
975                 break;
976
977                 case MNCC_DISC_IND:
978                 pgsm->disc_ind(msg_type, callref, mncc);
979                 break;
980
981                 case MNCC_REL_IND:
982                 case MNCC_REL_CNF:
983                 case MNCC_REJ_IND:
984                 pgsm->rel_ind(msg_type, callref, mncc);
985                 break;
986
987                 case MNCC_NOTIFY_IND:
988                 pgsm->notify_ind(msg_type, callref, mncc);
989                 break;
990
991                 case MNCC_HOLD_IND:
992                 pgsm->hold_ind(msg_type, callref, mncc);
993                 break;
994
995                 case MNCC_RETRIEVE_IND:
996                 pgsm->retr_ind(msg_type, callref, mncc);
997                 break;
998
999                 default:
1000                 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm->p_name, pgsm->p_callerinfo.id, msg_type);
1001         }
1002         return(0);
1003 }
1004
1005 /* MESSAGE_SETUP */
1006 void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
1007 {
1008         struct lcr_msg *message;
1009         int ret;
1010         struct epoint_list *epointlist;
1011         struct gsm_mncc *mncc;
1012         int channel;
1013
1014         /* copy setup infos to port */
1015         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
1016         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
1017         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
1018         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
1019
1020         /* no number */
1021         if (!p_dialinginfo.id[0]) {
1022                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1023                 add_trace("failure", NULL, "No dialed subscriber given.");
1024                 end_trace();
1025                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1026                 message->param.disconnectinfo.cause = 28;
1027                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1028                 message_put(message);
1029                 new_state(PORT_STATE_RELEASE);
1030                 p_m_delete = 1;
1031                 return;
1032         }
1033         
1034         /* release if port is blocked */
1035         if (p_m_mISDNport->ifport->block) {
1036                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1037                 add_trace("failure", NULL, "Port blocked.");
1038                 end_trace();
1039                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1040                 message->param.disconnectinfo.cause = 27; // temp. unavail.
1041                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1042                 message_put(message);
1043                 new_state(PORT_STATE_RELEASE);
1044                 p_m_delete = 1;
1045                 return;
1046         }
1047
1048         /* hunt channel */
1049         ret = channel = hunt_bchannel();
1050         if (ret < 0)
1051                 goto no_channel;
1052         /* open channel */
1053         ret = seize_bchannel(channel, 1);
1054         if (ret < 0) {
1055                 no_channel:
1056                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1057                 add_trace("failure", NULL, "No internal audio channel available.");
1058                 end_trace();
1059                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1060                 message->param.disconnectinfo.cause = 34;
1061                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1062                 message_put(message);
1063                 new_state(PORT_STATE_RELEASE);
1064                 p_m_delete = 1;
1065                 return;
1066         }
1067         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
1068         if (bchannel_open(p_m_b_index))
1069                 goto no_channel;
1070
1071 //              SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
1072         /* screen outgoing caller id */
1073         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
1074
1075         /* attach only if not already */
1076         epointlist = p_epointlist;
1077         while(epointlist) {
1078                 if (epointlist->epoint_id == epoint_id)
1079                         break;
1080                 epointlist = epointlist->next;
1081         }
1082         if (!epointlist)
1083                 epointlist_new(epoint_id);
1084
1085         /* creating l3id */
1086         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
1087         p_m_g_callref = new_callref++;
1088         add_trace("callref", "new", "0x%x", p_m_g_callref);
1089         end_trace();
1090
1091         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1092         mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
1093         /* caller information */
1094         mncc->fields |= MNCC_F_CALLING;
1095         mncc->calling.plan = 1;
1096         switch (p_callerinfo.ntype) {
1097                 case INFO_NTYPE_UNKNOWN:
1098                 mncc->calling.type = 0x0;
1099                 break;
1100                 case INFO_NTYPE_INTERNATIONAL:
1101                 mncc->calling.type = 0x1;
1102                 break;
1103                 case INFO_NTYPE_NATIONAL:
1104                 mncc->calling.type = 0x2;
1105                 break;
1106                 case INFO_NTYPE_SUBSCRIBER:
1107                 mncc->calling.type = 0x4;
1108                 break;
1109                 default: /* INFO_NTYPE_NOTPRESENT */
1110                 mncc->fields &= ~MNCC_F_CALLING;
1111                 break;
1112         }
1113         switch (p_callerinfo.screen) {
1114                 case INFO_SCREEN_USER:
1115                 mncc->calling.screen = 0;
1116                 break;
1117                 default: /* INFO_SCREEN_NETWORK */
1118                 mncc->calling.screen = 3;
1119                 break;
1120         }
1121         switch (p_callerinfo.present) {
1122                 case INFO_PRESENT_ALLOWED:
1123                 mncc->calling.present = 0;
1124                 break;
1125                 case INFO_PRESENT_RESTRICTED:
1126                 mncc->calling.present = 1;
1127                 break;
1128                 default: /* INFO_PRESENT_NOTAVAIL */
1129                 mncc->calling.present = 2;
1130                 break;
1131         }
1132         if (mncc->fields & MNCC_F_CALLING) {
1133                 SCPY(mncc->calling.number, p_callerinfo.id);
1134                 add_trace("calling", "type", "%d", mncc->calling.type);
1135                 add_trace("calling", "plan", "%d", mncc->calling.plan);
1136                 add_trace("calling", "present", "%d", mncc->calling.present);
1137                 add_trace("calling", "screen", "%d", mncc->calling.screen);
1138                 add_trace("calling", "number", "%s", mncc->calling.number);
1139         }
1140         /* dialing information */
1141         mncc->fields |= MNCC_F_CALLED;
1142         if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
1143                 SCPY(mncc->imsi, p_dialinginfo.id+5);
1144                 add_trace("dialing", "imsi", "%s", mncc->imsi);
1145         } else {
1146                 SCPY(mncc->called.number, p_dialinginfo.id);
1147                 add_trace("dialing", "number", "%s", mncc->called.number);
1148         }
1149         
1150         /* sending user-user */
1151
1152         /* redirecting number */
1153         mncc->fields |= MNCC_F_REDIRECTING;
1154         mncc->redirecting.plan = 1;
1155         switch (p_redirinfo.ntype) {
1156                 case INFO_NTYPE_UNKNOWN:
1157                 mncc->redirecting.type = 0x0;
1158                 break;
1159                 case INFO_NTYPE_INTERNATIONAL:
1160                 mncc->redirecting.type = 0x1;
1161                 break;
1162                 case INFO_NTYPE_NATIONAL:
1163                 mncc->redirecting.type = 0x2;
1164                 break;
1165                 case INFO_NTYPE_SUBSCRIBER:
1166                 mncc->redirecting.type = 0x4;
1167                 break;
1168                 default: /* INFO_NTYPE_NOTPRESENT */
1169                 mncc->fields &= ~MNCC_F_REDIRECTING;
1170                 break;
1171         }
1172         switch (p_redirinfo.screen) {
1173                 case INFO_SCREEN_USER:
1174                 mncc->redirecting.screen = 0;
1175                 break;
1176                 default: /* INFO_SCREE_NETWORK */
1177                 mncc->redirecting.screen = 3;
1178                 break;
1179         }
1180         switch (p_redirinfo.present) {
1181                 case INFO_PRESENT_ALLOWED:
1182                 mncc->redirecting.present = 0;
1183                 break;
1184                 case INFO_PRESENT_RESTRICTED:
1185                 mncc->redirecting.present = 1;
1186                 break;
1187                 default: /* INFO_PRESENT_NOTAVAIL */
1188                 mncc->redirecting.present = 2;
1189                 break;
1190         }
1191         /* sending redirecting number only in ntmode */
1192         if (mncc->fields & MNCC_F_REDIRECTING) {
1193                 SCPY(mncc->redirecting.number, p_redirinfo.id);
1194                 add_trace("redir", "type", "%d", mncc->redirecting.type);
1195                 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
1196                 add_trace("redir", "present", "%d", mncc->redirecting.present);
1197                 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
1198                 add_trace("redir", "number", "%s", mncc->redirecting.number);
1199         }
1200         /* bearer capability */
1201         //todo
1202
1203         end_trace();
1204         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1205
1206         new_state(PORT_STATE_OUT_SETUP);
1207
1208         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1209         message_put(message);
1210
1211         new_state(PORT_STATE_OUT_PROCEEDING);
1212 }
1213
1214 /* MESSAGE_NOTIFY */
1215 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
1216 {
1217         struct gsm_mncc *mncc;
1218         int notify;
1219
1220 //      printf("if = %d\n", param->notifyinfo.notify);
1221         if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
1222                 notify = param->notifyinfo.notify & 0x7f;
1223                 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
1224                         /* queue notification */
1225                         if (p_m_g_notify_pending)
1226                                 message_free(p_m_g_notify_pending);
1227                         p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
1228                         memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
1229                 } else {
1230                         /* sending notification */
1231                         gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
1232                         add_trace("notify", NULL, "%d", notify);
1233                         end_trace();
1234                         mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
1235                         mncc->notify = notify;
1236                         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1237                 }
1238         }
1239 }
1240
1241 /* MESSAGE_ALERTING */
1242 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
1243 {
1244         struct gsm_mncc *mncc;
1245
1246         /* send alert */
1247         gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
1248         mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
1249         if (p_m_mISDNport->tones) {
1250                 mncc->fields |= MNCC_F_PROGRESS;
1251                 mncc->progress.coding = 3; /* GSM */
1252                 mncc->progress.location = 1;
1253                 mncc->progress.descr = 8;
1254                 add_trace("progress", "coding", "%d", mncc->progress.coding);
1255                 add_trace("progress", "location", "%d", mncc->progress.location);
1256                 add_trace("progress", "descr", "%d", mncc->progress.descr);
1257         }
1258         end_trace();
1259         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1260
1261         new_state(PORT_STATE_IN_ALERTING);
1262
1263         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1264                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1265                 end_trace();
1266                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1267                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1268                 p_m_g_tch_connected = 1;
1269         }
1270 }
1271
1272 /* MESSAGE_CONNECT */
1273 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
1274 {
1275         struct gsm_mncc *mncc;
1276
1277         /* copy connected information */
1278         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
1279         /* screen outgoing caller id */
1280         do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
1281
1282         /* send connect */
1283         mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
1284         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
1285         /* caller information */
1286         mncc->fields |= MNCC_F_CONNECTED;
1287         mncc->connected.plan = 1;
1288         switch (p_callerinfo.ntype) {
1289                 case INFO_NTYPE_UNKNOWN:
1290                 mncc->connected.type = 0x0;
1291                 break;
1292                 case INFO_NTYPE_INTERNATIONAL:
1293                 mncc->connected.type = 0x1;
1294                 break;
1295                 case INFO_NTYPE_NATIONAL:
1296                 mncc->connected.type = 0x2;
1297                 break;
1298                 case INFO_NTYPE_SUBSCRIBER:
1299                 mncc->connected.type = 0x4;
1300                 break;
1301                 default: /* INFO_NTYPE_NOTPRESENT */
1302                 mncc->fields &= ~MNCC_F_CONNECTED;
1303                 break;
1304         }
1305         switch (p_callerinfo.screen) {
1306                 case INFO_SCREEN_USER:
1307                 mncc->connected.screen = 0;
1308                 break;
1309                 default: /* INFO_SCREEN_NETWORK */
1310                 mncc->connected.screen = 3;
1311                 break;
1312         }
1313         switch (p_callerinfo.present) {
1314                 case INFO_PRESENT_ALLOWED:
1315                 mncc->connected.present = 0;
1316                 break;
1317                 case INFO_PRESENT_RESTRICTED:
1318                 mncc->connected.present = 1;
1319                 break;
1320                 default: /* INFO_PRESENT_NOTAVAIL */
1321                 mncc->connected.present = 2;
1322                 break;
1323         }
1324         if (mncc->fields & MNCC_F_CONNECTED) {
1325                 SCPY(mncc->connected.number, p_connectinfo.id);
1326                 add_trace("connected", "type", "%d", mncc->connected.type);
1327                 add_trace("connected", "plan", "%d", mncc->connected.plan);
1328                 add_trace("connected", "present", "%d", mncc->connected.present);
1329                 add_trace("connected", "screen", "%d", mncc->connected.screen);
1330                 add_trace("connected", "number", "%s", mncc->connected.number);
1331         }
1332         end_trace();
1333         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1334
1335         new_state(PORT_STATE_CONNECT_WAITING);
1336 }
1337
1338 /* MESSAGE_DISCONNECT */
1339 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1340 {
1341         struct gsm_mncc *mncc;
1342
1343         /* send disconnect */
1344         mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
1345         gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
1346         if (p_m_mISDNport->tones) {
1347                 mncc->fields |= MNCC_F_PROGRESS;
1348                 mncc->progress.coding = 3; /* GSM */
1349                 mncc->progress.location = 1;
1350                 mncc->progress.descr = 8;
1351                 add_trace("progress", "coding", "%d", mncc->progress.coding);
1352                 add_trace("progress", "location", "%d", mncc->progress.location);
1353                 add_trace("progress", "descr", "%d", mncc->progress.descr);
1354         }
1355         mncc->fields |= MNCC_F_CAUSE;
1356         mncc->cause.coding = 3;
1357         mncc->cause.location = param->disconnectinfo.location;
1358         mncc->cause.value = param->disconnectinfo.cause;
1359         add_trace("cause", "coding", "%d", mncc->cause.coding);
1360         add_trace("cause", "location", "%d", mncc->cause.location);
1361         add_trace("cause", "value", "%d", mncc->cause.value);
1362         end_trace();
1363         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1364
1365         new_state(PORT_STATE_OUT_DISCONNECT);
1366
1367         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1368                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1369                 end_trace();
1370                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1371                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1372                 p_m_g_tch_connected = 1;
1373         }
1374 }
1375
1376
1377 /* MESSAGE_RELEASE */
1378 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1379 {
1380         struct gsm_mncc *mncc;
1381
1382         /* send release */
1383         mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
1384         gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
1385         mncc->fields |= MNCC_F_CAUSE;
1386         mncc->cause.coding = 3;
1387         mncc->cause.location = param->disconnectinfo.location;
1388         mncc->cause.value = param->disconnectinfo.cause;
1389         add_trace("cause", "coding", "%d", mncc->cause.coding);
1390         add_trace("cause", "location", "%d", mncc->cause.location);
1391         add_trace("cause", "value", "%d", mncc->cause.value);
1392         end_trace();
1393         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1394
1395         new_state(PORT_STATE_RELEASE);
1396         p_m_delete = 1;
1397         return;
1398 }
1399
1400
1401 /*
1402  * endpoint sends messages to the port
1403  */
1404 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1405 {
1406         if (PmISDN::message_epoint(epoint_id, message_id, param))
1407                 return(1);
1408
1409         switch(message_id) {
1410                 case MESSAGE_SETUP: /* dial-out command received from epoint */
1411                 if (p_state!=PORT_STATE_IDLE)
1412                         break;
1413                 message_setup(epoint_id, message_id, param);
1414                 break;
1415
1416                 case MESSAGE_NOTIFY: /* display and notifications */
1417                 message_notify(epoint_id, message_id, param);
1418                 break;
1419
1420 //              case MESSAGE_FACILITY: /* facility message */
1421 //              message_facility(epoint_id, message_id, param);
1422 //              break;
1423
1424                 case MESSAGE_PROCEEDING: /* message not handles */
1425                 break;
1426
1427                 case MESSAGE_ALERTING: /* call of endpoint is ringing */
1428                 if (p_state!=PORT_STATE_IN_PROCEEDING)
1429                         break;
1430                 message_alerting(epoint_id, message_id, param);
1431                 if (p_m_g_notify_pending) {
1432                         /* send pending notify message during connect */
1433                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1434                         message_free(p_m_g_notify_pending);
1435                         p_m_g_notify_pending = NULL;
1436                 }
1437                 break;
1438
1439                 case MESSAGE_CONNECT: /* call of endpoint is connected */
1440                 if (p_state!=PORT_STATE_IN_PROCEEDING
1441                  && p_state!=PORT_STATE_IN_ALERTING)
1442                         break;
1443                 message_connect(epoint_id, message_id, param);
1444                 if (p_m_g_notify_pending) {
1445                         /* send pending notify message during connect */
1446                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1447                         message_free(p_m_g_notify_pending);
1448                         p_m_g_notify_pending = NULL;
1449                 }
1450                 break;
1451
1452                 case MESSAGE_DISCONNECT: /* call has been disconnected */
1453                 if (p_state!=PORT_STATE_IN_PROCEEDING
1454                  && p_state!=PORT_STATE_IN_ALERTING
1455                  && p_state!=PORT_STATE_OUT_SETUP
1456                  && p_state!=PORT_STATE_OUT_OVERLAP
1457                  && p_state!=PORT_STATE_OUT_PROCEEDING
1458                  && p_state!=PORT_STATE_OUT_ALERTING
1459                  && p_state!=PORT_STATE_CONNECT
1460                  && p_state!=PORT_STATE_CONNECT_WAITING)
1461                         break;
1462                 message_disconnect(epoint_id, message_id, param);
1463                 break;
1464
1465                 case MESSAGE_RELEASE: /* release isdn port */
1466                 if (p_state==PORT_STATE_RELEASE)
1467                         break;
1468                 message_release(epoint_id, message_id, param);
1469                 break;
1470
1471                 default:
1472                 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
1473         }
1474
1475         return(1);
1476 }
1477
1478
1479 /*
1480  * handler
1481  */
1482 int Pgsm::handler(void)
1483 {
1484         int ret;
1485         int work = 0;
1486         unsigned char buffer[2048+MISDN_HEADER_LEN];
1487         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1488
1489         if ((ret = PmISDN::handler()))
1490                 return(ret);
1491
1492         /* handle destruction */
1493         if (p_m_delete) {
1494                 delete this;
1495                 return(-1);
1496         }
1497
1498         /* handle message from bchannel */
1499         if (p_m_g_gsm_b_sock > -1) {
1500                 ret = recv(p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
1501                 if (ret >= (int)MISDN_HEADER_LEN) {
1502                         switch(hh->prim) {
1503                                 /* we don't care about confirms, we use rx data to sync tx */
1504                                 case PH_DATA_CNF:
1505                                 break;
1506                                 /* we receive audio data, we respond to it AND we send tones */
1507                                 case PH_DATA_IND:
1508                                 bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
1509                                 break;
1510                                 case PH_ACTIVATE_IND:
1511                                 p_m_g_gsm_b_active = 1;
1512                                 break;
1513                                 case PH_DEACTIVATE_IND:
1514                                 p_m_g_gsm_b_active = 0;
1515                                 break;
1516                         }
1517                         work = 1;
1518                 } else {
1519                         if (ret < 0 && errno != EWOULDBLOCK)
1520                                 PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
1521                 }
1522         }
1523
1524         return(work);
1525 }
1526
1527
1528 /*
1529  * handles bsc select function within LCR's main loop
1530  */
1531 int handle_gsm(void)
1532 {
1533         int ret1, ret2;
1534
1535         ret1 = bsc_upqueue((struct gsm_network *)gsm->network);
1536         ret2 = bsc_select_main(1); /* polling */
1537         if (ret1 || ret2)
1538                 return 1;
1539         return 0;
1540 }
1541
1542 static void gsm_sock_close(void)
1543 {
1544         if (gsm->gsm_sock > -1)
1545                 close(gsm->gsm_sock);
1546         gsm->gsm_sock = -1;
1547 }
1548
1549 static int gsm_sock_open(char *portname)
1550 {
1551         int ret;
1552         int cnt;
1553         unsigned long on = 1;
1554         struct sockaddr_mISDN addr;
1555         struct mISDN_devinfo devinfo;
1556         int pri, bri;
1557
1558         /* check port counts */
1559         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
1560         if (ret < 0) {
1561                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
1562                 return(ret);
1563         }
1564
1565         if (cnt <= 0) {
1566                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
1567                 return -EIO;
1568         }
1569         gsm->gsm_port = mISDN_getportbyname(mISDNsocket, cnt, portname);
1570         if (gsm->gsm_port < 0) {
1571                 PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname);
1572                 return gsm->gsm_port;
1573         }
1574         /* get protocol */
1575         bri = pri = 0;
1576         devinfo.id = gsm->gsm_port;
1577         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
1578         if (ret < 0) {
1579                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", gsm->gsm_port, ret);
1580                 return ret;
1581         }
1582         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
1583                 bri = 1;
1584         }
1585         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
1586                 pri = 1;
1587         }
1588         if (!pri && !pri) {
1589                 PERROR_RUNTIME("GSM port %d does not support TE PRI or TE BRI.\n", gsm->gsm_port);
1590         }
1591         /* open socket */
1592         if ((gsm->gsm_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_TE_S0)) < 0) {
1593                 PERROR_RUNTIME("GSM port %d failed to open socket.\n", gsm->gsm_port);
1594                 gsm_sock_close();
1595                 return gsm->gsm_sock;
1596         }
1597         /* set nonblocking io */
1598         if ((ret = ioctl(gsm->gsm_sock, FIONBIO, &on)) < 0) {
1599                 PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", gsm->gsm_port);
1600                 gsm_sock_close();
1601                 return ret;
1602         }
1603         /* bind socket to dchannel */
1604         memset(&addr, 0, sizeof(addr));
1605         addr.family = AF_ISDN;
1606         addr.dev = gsm->gsm_port;
1607         addr.channel = 0;
1608         if ((ret = bind(gsm->gsm_sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
1609                 PERROR_RUNTIME("GSM port %d failed to bind socket. (name = %s errno=%d)\n", gsm->gsm_port, portname, errno);
1610                 gsm_sock_close();
1611                 return (ret);
1612         }
1613
1614         return 0;
1615 }
1616
1617
1618 int gsm_exit(int rc)
1619 {
1620         /* free gsm instance */
1621         if (gsm) {
1622                 if (gsm->gsm_sock > -1)
1623                         gsm_sock_close();
1624                 /* shutdown network */
1625                 if (gsm->network)
1626                         bsc_shutdown_net((struct gsm_network *)gsm->network);
1627                 /* free network */
1628 //              if (gsm->network) {
1629 //                      free((struct gsm_network *)gsm->network); /* TBD */
1630 //              }
1631                 free(gsm);
1632                 gsm = NULL;
1633         }
1634
1635         return(rc);
1636 }
1637
1638 int gsm_init(void)
1639 {
1640         char hlr[128], cfg[128], filename[128];
1641         mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1642         int pcapfd, rc;
1643
1644         tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
1645         talloc_ctx_init();
1646         on_dso_load_token();
1647         on_dso_load_rrlp();
1648
1649         /* seed the PRNG */
1650         srand(time(NULL));
1651
1652         /* create gsm instance */
1653         gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1654         gsm->gsm_sock = -1;
1655
1656         /* parse options */
1657         if (!gsm_conf(&gsm->conf)) {
1658                 PERROR("%s", gsm_conf_error);
1659                 return gsm_exit(-EINVAL);
1660         }
1661
1662         /* set debug */
1663         if (gsm->conf.debug[0])
1664                 debug_parse_category_mask(gsm->conf.debug);
1665
1666         /* open pcap file */
1667         if (gsm->conf.pcapfile[0]) {
1668                 if (gsm->conf.pcapfile[0] == '/')
1669                         SCPY(filename, gsm->conf.pcapfile);
1670                 else
1671                         SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile);
1672                 pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
1673                 if (pcapfd < 0) {
1674                         PERROR("Failed to open file for pcap\n");
1675                         return gsm_exit(-1);
1676                 }
1677                 e1_set_pcap_fd(pcapfd);
1678         }
1679
1680         /* set reject cause */
1681         if (gsm->conf.reject_cause)
1682                 gsm0408_set_reject_cause(gsm->conf.reject_cause);
1683
1684         /* use RTP proxy for audio streaming */
1685         if (gsm->conf.rtp_proxy)
1686                 ipacc_rtp_direct = 0;
1687
1688         /* init database */
1689         if (gsm->conf.hlr[0] == '/')
1690                 SCPY(hlr, gsm->conf.hlr);
1691         else
1692                 SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
1693         if (db_init(hlr)) {
1694                 PERROR("GSM DB: Failed to init database '%s'. Please check the option settings.\n", hlr);
1695                 return gsm_exit(-1);
1696         }
1697         printf("DB: Database initialized.\n");
1698         if (db_prepare()) {
1699                 PERROR("GSM DB: Failed to prepare database.\n");
1700                 return gsm_exit(-1);
1701         }
1702         printf("DB: Database prepared.\n");
1703
1704         /* bootstrap network */
1705         if (gsm->conf.openbsc_cfg[0] == '/')
1706                 SCPY(cfg, gsm->conf.openbsc_cfg);
1707         else
1708                 SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg);
1709         rc = bsc_bootstrap_network(&message_bsc, cfg);
1710         if (rc < 0) {
1711                 PERROR("Failed to bootstrap GSM network.\n");
1712                 return gsm_exit(-1);
1713         }
1714         gsm->network = bsc_gsmnet;
1715
1716         /* open gsm loop interface */
1717         if (gsm_sock_open(gsm->conf.interface_bsc)) {
1718                 return gsm_exit(-1);
1719         }
1720
1721         return 0;
1722 }
1723