autoconf: Fixed detection of mISDN headers
[lcr.git] / gsm.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **            MNCC-Interface: Harald Welte                                   **
8 **                                                                           **
9 ** mISDN gsm                                                                 **
10 **                                                                           **
11 \*****************************************************************************/ 
12
13 #include "main.h"
14 #include "mncc.h"
15
16 #ifndef _GNU_SOURCE
17 #define _GNU_SOURCE
18 #endif
19 extern "C" {
20 #include "gsm_audio.h"
21 }
22
23 #include <mISDN/mISDNcompat.h>
24 #include <assert.h>
25
26 #define SOCKET_RETRY_TIMER      5
27
28 //struct lcr_gsm *gsm = NULL;
29
30 #define RTP_PT_GSM_HALF 96
31 #define RTP_PT_GSM_EFR 97
32 #define RTP_PT_GSM_AMR 98
33
34 int new_callref = 1;
35
36 /* names of MNCC-SAP */
37 static const struct _value_string {
38         int msg_type;
39         const char *name;
40 } mncc_names[] = {
41         { 0,                    "New call ref" },
42         { 1,                    "Codec negotiation" },
43         { MNCC_SETUP_REQ,       "MNCC_SETUP_REQ" },
44         { MNCC_SETUP_IND,       "MNCC_SETUP_IND" },
45         { MNCC_SETUP_RSP,       "MNCC_SETUP_RSP" },
46         { MNCC_SETUP_CNF,       "MNCC_SETUP_CNF" },
47         { MNCC_SETUP_COMPL_REQ, "MNCC_SETUP_COMPL_REQ" },
48         { MNCC_SETUP_COMPL_IND, "MNCC_SETUP_COMPL_IND" },
49         { MNCC_CALL_CONF_IND,   "MNCC_CALL_CONF_IND" },
50         { MNCC_CALL_PROC_REQ,   "MNCC_CALL_PROC_REQ" },
51         { MNCC_PROGRESS_REQ,    "MNCC_PROGRESS_REQ" },
52         { MNCC_ALERT_REQ,       "MNCC_ALERT_REQ" },
53         { MNCC_ALERT_IND,       "MNCC_ALERT_IND" },
54         { MNCC_NOTIFY_REQ,      "MNCC_NOTIFY_REQ" },
55         { MNCC_NOTIFY_IND,      "MNCC_NOTIFY_IND" },
56         { MNCC_DISC_REQ,        "MNCC_DISC_REQ" },
57         { MNCC_DISC_IND,        "MNCC_DISC_IND" },
58         { MNCC_REL_REQ,         "MNCC_REL_REQ" },
59         { MNCC_REL_IND,         "MNCC_REL_IND" },
60         { MNCC_REL_CNF,         "MNCC_REL_CNF" },
61         { MNCC_FACILITY_REQ,    "MNCC_FACILITY_REQ" },
62         { MNCC_FACILITY_IND,    "MNCC_FACILITY_IND" },
63         { MNCC_START_DTMF_IND,  "MNCC_START_DTMF_IND" },
64         { MNCC_START_DTMF_RSP,  "MNCC_START_DTMF_RSP" },
65         { MNCC_START_DTMF_REJ,  "MNCC_START_DTMF_REJ" },
66         { MNCC_STOP_DTMF_IND,   "MNCC_STOP_DTMF_IND" },
67         { MNCC_STOP_DTMF_RSP,   "MNCC_STOP_DTMF_RSP" },
68         { MNCC_MODIFY_REQ,      "MNCC_MODIFY_REQ" },
69         { MNCC_MODIFY_IND,      "MNCC_MODIFY_IND" },
70         { MNCC_MODIFY_RSP,      "MNCC_MODIFY_RSP" },
71         { MNCC_MODIFY_CNF,      "MNCC_MODIFY_CNF" },
72         { MNCC_MODIFY_REJ,      "MNCC_MODIFY_REJ" },
73         { MNCC_HOLD_IND,        "MNCC_HOLD_IND" },
74         { MNCC_HOLD_CNF,        "MNCC_HOLD_CNF" },
75         { MNCC_HOLD_REJ,        "MNCC_HOLD_REJ" },
76         { MNCC_RETRIEVE_IND,    "MNCC_RETRIEVE_IND" },
77         { MNCC_RETRIEVE_CNF,    "MNCC_RETRIEVE_CNF" },
78         { MNCC_RETRIEVE_REJ,    "MNCC_RETRIEVE_REJ" },
79         { MNCC_USERINFO_REQ,    "MNCC_USERINFO_REQ" },
80         { MNCC_USERINFO_IND,    "MNCC_USERINFO_IND" },
81         { MNCC_REJ_REQ,         "MNCC_REJ_REQ" },
82         { MNCC_REJ_IND,         "MNCC_REJ_IND" },
83         { MNCC_PROGRESS_IND,    "MNCC_PROGRESS_IND" },
84         { MNCC_CALL_PROC_IND,   "MNCC_CALL_PROC_IND" },
85         { MNCC_CALL_CONF_REQ,   "MNCC_CALL_CONF_REQ" },
86         { MNCC_START_DTMF_REQ,  "MNCC_START_DTMF_REQ" },
87         { MNCC_STOP_DTMF_REQ,   "MNCC_STOP_DTMF_REQ" },
88         { MNCC_HOLD_REQ,        "MNCC_HOLD_REQ " },
89         { MNCC_RETRIEVE_REQ,    "MNCC_RETRIEVE_REQ" },
90         { MNCC_LCHAN_MODIFY,    "MNCC_LCHAN_MODIFY" },
91         { 0,                    NULL }
92 };
93
94 const char *mncc_name(int value)
95 {
96         int i = 0;
97
98         while (mncc_names[i].name) {
99                 if (mncc_names[i].msg_type == value)
100                         return mncc_names[i].name;
101                 i++;
102         }
103         return "unknown";
104 }
105
106 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data);
107
108 /*
109  * create and send mncc message
110  */
111 struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
112 {
113         struct gsm_mncc *mncc;
114
115         mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
116         mncc->msg_type = msg_type;
117         mncc->callref = callref;
118         return (mncc);
119 }
120 int send_and_free_mncc(struct lcr_gsm *lcr_gsm, unsigned int msg_type, void *data)
121 {
122         int ret = 0;
123
124         if (lcr_gsm) {
125                 ret = mncc_send(lcr_gsm, msg_type, data);
126         }
127         free(data);
128
129         return ret;
130 }
131
132 static int delete_event(struct lcr_work *work, void *instance, int index);
133
134 /*
135  * constructor
136  */
137 Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings)
138 {
139         p_g_tones = 0;
140         if (interface->is_tones == IS_YES)
141                 p_g_tones = 1;
142         p_g_earlyb = 0;
143         if (interface->is_earlyb == IS_YES)
144                 p_g_earlyb = 1;
145         p_g_rtp_bridge = 0;
146         if (interface->rtp_bridge)
147                 p_g_rtp_bridge = 1;
148         p_g_rtp_payloads = 0;
149         memset(&p_g_samples, 0, sizeof(p_g_samples));
150         SCPY(p_g_interface_name, interface->name); 
151         p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
152         memset(&p_g_delete, 0, sizeof(p_g_delete));
153         add_work(&p_g_delete, delete_event, this, 0);
154         p_g_lcr_gsm = NULL;
155         p_g_callref = 0;
156         p_g_mode = 0;
157         p_g_gsm_b_sock = -1;
158         p_g_gsm_b_index = -1;
159         p_g_gsm_b_active = 0;
160         p_g_notify_pending = NULL;
161         p_g_setup_pending = NULL;
162         p_g_connect_pending = NULL;
163         p_g_decoder = gsm_audio_create();
164         p_g_encoder = gsm_audio_create();
165         if (!p_g_encoder || !p_g_decoder) {
166                 PERROR("Failed to create GSM audio codec instance\n");
167                 trigger_work(&p_g_delete);
168         }
169         p_g_rxpos = 0;
170         p_g_tch_connected = 0;
171         p_g_payload_type = -1;
172
173         PDEBUG(DEBUG_GSM, "Created new GSMPort(%s).\n", portname);
174 }
175
176 /*
177  * destructor
178  */
179 Pgsm::~Pgsm()
180 {
181         PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
182
183         del_work(&p_g_delete);
184
185         /* remove queued message */
186         if (p_g_notify_pending)
187                 message_free(p_g_notify_pending);
188         if (p_g_setup_pending)
189                 message_free(p_g_setup_pending);
190         if (p_g_connect_pending)
191                 message_free(p_g_connect_pending);
192
193         /* close codec */
194         if (p_g_encoder)
195                 gsm_audio_destroy(p_g_encoder);
196         if (p_g_decoder)
197                 gsm_audio_destroy(p_g_decoder);
198 }
199
200
201 /* receive encoded frame from gsm */
202 void Pgsm::frame_receive(void *arg)
203 {
204         struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
205         unsigned char data[160];
206         int i;
207
208         if (!p_g_decoder)
209                 return;
210
211         if (frame->msg_type != GSM_TCHF_BAD_FRAME) {
212                 if ((frame->data[0]>>4) != 0xd)
213                         PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
214         
215                 /* decode */
216                 gsm_audio_decode(p_g_decoder, frame->data, p_g_samples);
217                 for (i = 0; i < 160; i++) {
218                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
219                 }
220         } else if (p_echotest) {
221                 /* beep on bad frame */
222                 for (i = 0; i < 160; i++) {
223                         if ((i & 3) > 2)
224                                 p_g_samples[i] = 15000;
225                         else
226                                 p_g_samples[i] = -15000;
227                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
228                 }
229         } else {
230                 /* repeat on bad frame */
231                 for (i = 0; i < 160; i++) {
232                         p_g_samples[i] = (p_g_samples[i] * 14) >> 4;
233                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
234                 }
235         }
236
237         /* local echo */
238         if (p_echotest)
239                 bridge_rx(data, 160);
240
241         /* send to remote*/
242         bridge_tx(data, 160);
243 }
244
245 /* send traffic to gsm */
246 int Pgsm::bridge_rx(unsigned char *data, int len)
247 {
248         if (p_tone_name[0])
249                 return -EINVAL;
250
251         return audio_send(data, len);
252 }
253
254 int Pgsm::audio_send(unsigned char *data, int len)
255 {
256         unsigned char frame[33];
257
258         /* encoder init failed */
259         if (!p_g_encoder)
260                 return -EINVAL;
261
262         /* (currently) not connected, so don't flood tch! */
263         if (!p_g_tch_connected)
264                 return -EINVAL;
265
266         /* write to rx buffer */
267         while(len--) {
268                 p_g_rxdata[p_g_rxpos++] = audio_law_to_s32[*data++];
269                 if (p_g_rxpos == 160) {
270                         p_g_rxpos = 0;
271
272                         /* encode data */
273                         gsm_audio_encode(p_g_encoder, p_g_rxdata, frame);
274                         frame_send(frame);
275                 }
276         }
277
278         return 0;
279 }
280
281 void Pgsm::frame_send(void *_frame)
282 {
283         unsigned char buffer[sizeof(struct gsm_data_frame) + 33];
284         struct gsm_data_frame *frame = (struct gsm_data_frame *)buffer;
285         
286         frame->msg_type = GSM_TCHF_FRAME;
287         frame->callref = p_g_callref;
288         memcpy(frame->data, _frame, 33);
289
290         if (p_g_lcr_gsm) {
291                 mncc_send(p_g_lcr_gsm, frame->msg_type, frame);
292         }
293 }
294
295 /*
296  * create trace
297  */
298 void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction)
299 {
300         char msgtext[64];
301         struct interface *interface = interface_first;
302
303         interface = getinterfacebyname(interface_name);
304         if (!interface)
305                 return;
306
307         /* select message and primitive text */
308         SCPY(msgtext, mncc_name(msg_type));
309
310         /* add direction */
311         if (port) {
312                 switch(port->p_type) {
313                 case PORT_TYPE_GSM_BS_OUT:
314                 case PORT_TYPE_GSM_BS_IN:
315                         SCAT(msgtext, " LCR<->BSC");
316                         break;
317                 case PORT_TYPE_GSM_MS_OUT:
318                 case PORT_TYPE_GSM_MS_IN:
319                         SCAT(msgtext, " LCR<->MS");
320                         break;
321                 }
322         } else
323                 SCAT(msgtext, " ----");
324
325         /* init trace with given values */
326         start_trace(-1,
327                     interface,
328                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
329                     port?port->p_dialinginfo.id:NULL,
330                     direction,
331                     CATEGORY_CH,
332                     port?port->p_serial:0,
333                     msgtext);
334 }
335
336 /* modify lchan to given payload type */
337 void Pgsm::modify_lchan(unsigned char payload_type)
338 {
339         struct gsm_mncc *mode;
340
341         /* already modified to that payload type */
342         if (p_g_payload_type == payload_type)
343                 return;
344
345         p_g_payload_type = payload_type;
346         gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
347         mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
348         switch (payload_type) {
349         case RTP_PT_GSM_EFR:
350                 add_trace("speech", "version", "EFR given");
351                 mode->lchan_mode = 0x21; /* GSM V2 */
352                 break;
353         case RTP_PT_GSM_AMR:
354                 add_trace("speech", "version", "AMR given");
355                 mode->lchan_mode = 0x41; /* GSM V3 */
356                 break;
357         case RTP_PT_GSM_HALF:
358                 add_trace("speech", "version", "Half Rate given");
359                 mode->lchan_mode = 0x05; /* GSM V1 */
360                 break;
361         default:
362                 add_trace("speech", "version", "Full Rate given");
363                 mode->lchan_mode = 0x01; /* GSM V1 HR */
364         }
365         mode->lchan_type = 0x02; /* FIXME: unused */
366         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
367         end_trace();
368         send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
369 }
370
371 /* CALL PROCEEDING INDICATION (from network) */
372 void Pgsm::call_proc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
373 {
374         struct lcr_msg *message;
375         struct gsm_mncc *frame;
376
377         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
378         end_trace();
379
380         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
381         message_put(message);
382
383         new_state(PORT_STATE_OUT_PROCEEDING);
384
385         if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
386                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
387                 end_trace();
388                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
389                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
390                 p_g_tch_connected = 1;
391         }
392 }
393
394 /* ALERTING INDICATION */
395 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
396 {
397         struct lcr_msg *message;
398         struct gsm_mncc *frame;
399
400         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
401         end_trace();
402
403         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
404         message_put(message);
405
406         new_state(PORT_STATE_OUT_ALERTING);
407
408         if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
409                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
410                 end_trace();
411                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
412                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
413                 p_g_tch_connected = 1;
414         }
415 }
416
417 /* CONNECT INDICATION */
418 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
419 {
420         struct gsm_mncc *resp, *frame;
421         struct lcr_msg *message;
422
423         SCPY(p_connectinfo.id, mncc->connected.number);
424         SCPY(p_connectinfo.imsi, mncc->imsi);
425         p_connectinfo.present = INFO_PRESENT_ALLOWED;
426         p_connectinfo.screen = INFO_SCREEN_NETWORK;
427         p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
428         SCPY(p_connectinfo.interface, p_g_interface_name);
429
430         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
431         if (p_connectinfo.id[0])
432                 add_trace("connect", "number", "%s", p_connectinfo.id);
433         else if (mncc->imsi[0])
434                 SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
435         if (mncc->imsi[0])
436                 add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
437         end_trace();
438
439         /* send resp */
440         gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
441         resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_g_callref);
442         end_trace();
443         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
444
445         new_state(PORT_STATE_CONNECT);
446
447         if (!p_g_tch_connected) { /* only if ... */
448                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
449                 end_trace();
450                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
451                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
452                 p_g_tch_connected = 1;
453         }
454
455         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
456         memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
457
458         /* if we have a bridge, but not yet modified, the phone accepts out requested payload.
459          * we force the first in list */
460         if (p_g_rtp_bridge) {
461                 if (p_g_payload_type < 0) {
462                         /* modify to first given payload */
463                         modify_lchan(p_g_rtp_payload_types[0]);
464                 }
465                 message->param.connectinfo.rtpinfo.payload_types[0] = p_g_payload_type;
466                 message->param.connectinfo.rtpinfo.payloads = 1;
467         }
468
469         if (p_g_rtp_bridge) {
470                 struct gsm_mncc_rtp *rtp;
471
472                 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding connect msg\n");
473                 p_g_connect_pending = message;
474                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
475                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
476         } else
477                 message_put(message);
478 }
479
480 /* CONNECT ACK INDICATION */
481 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
482 {
483         struct gsm_mncc *frame;
484
485         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
486         end_trace();
487
488         new_state(PORT_STATE_CONNECT);
489
490         if (!p_g_tch_connected) { /* only if ... */
491                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
492                 end_trace();
493                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
494                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
495                 p_g_tch_connected = 1;
496         }
497 }
498
499 /* DISCONNECT INDICATION */
500 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
501 {
502         struct lcr_msg *message;
503         int cause = 16, location = 0;
504         struct gsm_mncc *resp;
505
506         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
507         if (mncc->fields & MNCC_F_CAUSE) {
508                 location = mncc->cause.location;
509                 cause = mncc->cause.value;
510                 add_trace("cause", "coding", "%d", mncc->cause.coding);
511                 add_trace("cause", "location", "%d", location);
512                 add_trace("cause", "value", "%d", cause);
513         }
514         end_trace();
515
516         /* send release */
517         resp = create_mncc(MNCC_REL_REQ, p_g_callref);
518         gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
519 #if 0
520         resp->fields |= MNCC_F_CAUSE;
521         resp->cause.coding = 3;
522         resp->cause.location = 1;
523         resp->cause.value = cause;
524         add_trace("cause", "coding", "%d", resp->cause.coding);
525         add_trace("cause", "location", "%d", resp->cause.location);
526         add_trace("cause", "value", "%d", resp->cause.value);
527 #endif
528         end_trace();
529         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
530
531         /* sending release to endpoint */
532         while(p_epointlist) {
533                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
534                 message->param.disconnectinfo.cause = cause;
535                 message->param.disconnectinfo.location = location;
536                 message_put(message);
537                 /* remove epoint */
538                 free_epointlist(p_epointlist);
539         }
540         new_state(PORT_STATE_RELEASE);
541         trigger_work(&p_g_delete);
542 }
543
544 /* CC_RELEASE INDICATION */
545 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
546 {
547         int location = 0, cause = 16;
548         struct lcr_msg *message;
549
550         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
551         if (mncc->fields & MNCC_F_CAUSE) {
552                 location = mncc->cause.location;
553                 cause = mncc->cause.value;
554                 add_trace("cause", "coding", "%d", mncc->cause.coding);
555                 add_trace("cause", "location", "%d", mncc->cause.location);
556                 add_trace("cause", "value", "%d", mncc->cause.value);
557         }
558         end_trace();
559
560         /* sending release to endpoint */
561         while(p_epointlist) {
562                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
563                 message->param.disconnectinfo.cause = cause;
564                 message->param.disconnectinfo.location = location;
565                 message_put(message);
566                 /* remove epoint */
567                 free_epointlist(p_epointlist);
568         }
569         new_state(PORT_STATE_RELEASE);
570         trigger_work(&p_g_delete);
571 }
572
573 /* NOTIFY INDICATION */
574 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
575 {
576         struct lcr_msg *message;
577
578         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
579         add_trace("notify", NULL, "%d", mncc->notify);
580         end_trace();
581
582         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
583         message->param.notifyinfo.notify = mncc->notify;
584         message_put(message);
585 }
586
587 /* MESSAGE_NOTIFY */
588 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
589 {
590         struct gsm_mncc *mncc;
591         int notify;
592
593 //      printf("if = %d\n", param->notifyinfo.notify);
594         if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
595                 notify = param->notifyinfo.notify & 0x7f;
596                 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
597                         /* queue notification */
598                         if (p_g_notify_pending)
599                                 message_free(p_g_notify_pending);
600                         p_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
601                         memcpy(&p_g_notify_pending->param, param, sizeof(union parameter));
602                 } else {
603                         /* sending notification */
604                         gsm_trace_header(p_g_interface_name, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
605                         add_trace("notify", NULL, "%d", notify);
606                         end_trace();
607                         mncc = create_mncc(MNCC_NOTIFY_REQ, p_g_callref);
608                         mncc->notify = notify;
609                         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
610                 }
611         }
612 }
613
614 /* RTP create indication */
615 void Pgsm::rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
616 {
617         struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
618
619         /* send queued setup, as we received remote RTP info */
620         if (p_g_setup_pending) {
621                 struct lcr_msg *message;
622
623                 message = p_g_setup_pending;
624                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding setup\n", rtp->ip, rtp->port);
625                 message->param.setup.rtpinfo.ip = rtp->ip;
626                 message->param.setup.rtpinfo.port = rtp->port;
627                 message_put(message);
628                 p_g_setup_pending = NULL;
629         }
630         if (p_g_connect_pending) {
631                 struct gsm_mncc_rtp *nrtp;
632
633                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) connecting RTP... \n", rtp->ip, rtp->port);
634                 nrtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
635                 nrtp->ip = p_g_rtp_ip_remote;
636                 nrtp->port = p_g_rtp_port_remote;
637                 send_and_free_mncc(p_g_lcr_gsm, nrtp->msg_type, nrtp);
638         }
639 }
640
641 /* RTP connect indication */
642 void Pgsm::rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
643 {
644         struct lcr_msg *message;
645         struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
646
647         if (p_g_connect_pending) {
648                 message = p_g_connect_pending;
649                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding connect\n", rtp->ip, rtp->port);
650                 message->param.connectinfo.rtpinfo.ip = rtp->ip;
651                 message->param.connectinfo.rtpinfo.port = rtp->port;
652                 message_put(message);
653                 p_g_connect_pending = NULL;
654         }
655 }
656
657 /* MESSAGE_PROGRESS */
658 void Pgsm::message_progress(unsigned int epoint_id, int message_id, union parameter *param)
659 {
660         if (param->progressinfo.progress == 8) {
661                 PDEBUG(DEBUG_GSM, "Remote provides tones for us\n");
662                 p_g_tones = 1;
663         }
664
665         if (param->progressinfo.rtpinfo.port) {
666                 struct gsm_mncc_rtp *rtp;
667
668                 PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->progressinfo.rtpinfo.ip, param->progressinfo.rtpinfo.port);
669                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
670                 rtp->ip = param->progressinfo.rtpinfo.ip;
671                 rtp->port = param->progressinfo.rtpinfo.port;
672                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
673
674                 /* modify channel to accepted payload type */
675                 modify_lchan(param->progressinfo.rtpinfo.payload_types[0]);
676         }
677 }
678
679 /* MESSAGE_ALERTING */
680 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
681 {
682         struct gsm_mncc *mncc;
683
684         /* send alert */
685         gsm_trace_header(p_g_interface_name, this, MNCC_ALERT_REQ, DIRECTION_OUT);
686         mncc = create_mncc(MNCC_ALERT_REQ, p_g_callref);
687         if (p_g_tones) {
688                 mncc->fields |= MNCC_F_PROGRESS;
689                 mncc->progress.coding = 3; /* GSM */
690                 mncc->progress.location = 1;
691                 mncc->progress.descr = 8;
692                 add_trace("progress", "coding", "%d", mncc->progress.coding);
693                 add_trace("progress", "location", "%d", mncc->progress.location);
694                 add_trace("progress", "descr", "%d", mncc->progress.descr);
695         }
696         end_trace();
697         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
698
699         new_state(PORT_STATE_IN_ALERTING);
700
701         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
702                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
703                 end_trace();
704                 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
705                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
706                 p_g_tch_connected = 1;
707         }
708 }
709
710 /* MESSAGE_CONNECT */
711 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
712 {
713         struct gsm_mncc *mncc;
714
715         /* copy connected information */
716         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
717         /* screen outgoing caller id */
718         do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_g_interface_name);
719
720         /* send connect */
721         mncc = create_mncc(MNCC_SETUP_RSP, p_g_callref);
722         gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_RSP, DIRECTION_OUT);
723         /* caller information */
724         mncc->fields |= MNCC_F_CONNECTED;
725         mncc->connected.plan = 1;
726         switch (p_callerinfo.ntype) {
727                 case INFO_NTYPE_UNKNOWN:
728                 mncc->connected.type = 0x0;
729                 break;
730                 case INFO_NTYPE_INTERNATIONAL:
731                 mncc->connected.type = 0x1;
732                 break;
733                 case INFO_NTYPE_NATIONAL:
734                 mncc->connected.type = 0x2;
735                 break;
736                 case INFO_NTYPE_SUBSCRIBER:
737                 mncc->connected.type = 0x4;
738                 break;
739                 default: /* INFO_NTYPE_NOTPRESENT */
740                 mncc->fields &= ~MNCC_F_CONNECTED;
741                 break;
742         }
743         switch (p_callerinfo.screen) {
744                 case INFO_SCREEN_USER:
745                 mncc->connected.screen = 0;
746                 break;
747                 default: /* INFO_SCREEN_NETWORK */
748                 mncc->connected.screen = 3;
749                 break;
750         }
751         switch (p_callerinfo.present) {
752                 case INFO_PRESENT_ALLOWED:
753                 mncc->connected.present = 0;
754                 break;
755                 case INFO_PRESENT_RESTRICTED:
756                 mncc->connected.present = 1;
757                 break;
758                 default: /* INFO_PRESENT_NOTAVAIL */
759                 mncc->connected.present = 2;
760                 break;
761         }
762         if (mncc->fields & MNCC_F_CONNECTED) {
763                 SCPY(mncc->connected.number, p_connectinfo.id);
764                 add_trace("connected", "type", "%d", mncc->connected.type);
765                 add_trace("connected", "plan", "%d", mncc->connected.plan);
766                 add_trace("connected", "present", "%d", mncc->connected.present);
767                 add_trace("connected", "screen", "%d", mncc->connected.screen);
768                 add_trace("connected", "number", "%s", mncc->connected.number);
769         }
770         end_trace();
771         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
772
773         new_state(PORT_STATE_CONNECT_WAITING);
774
775         if (param->connectinfo.rtpinfo.port) {
776                 struct gsm_mncc_rtp *rtp;
777
778                 PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->connectinfo.rtpinfo.ip, param->connectinfo.rtpinfo.port);
779                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
780                 rtp->ip = param->connectinfo.rtpinfo.ip;
781                 rtp->port = param->connectinfo.rtpinfo.port;
782                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
783
784                 /* modify channel to accepted payload type */
785                 modify_lchan(param->connectinfo.rtpinfo.payload_types[0]);
786         }
787 }
788
789 /* MESSAGE_DISCONNECT */
790 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
791 {
792         struct gsm_mncc *mncc;
793
794         /* send disconnect */
795         mncc = create_mncc(MNCC_DISC_REQ, p_g_callref);
796         gsm_trace_header(p_g_interface_name, this, MNCC_DISC_REQ, DIRECTION_OUT);
797         if (p_g_tones) {
798                 mncc->fields |= MNCC_F_PROGRESS;
799                 mncc->progress.coding = 3; /* GSM */
800                 mncc->progress.location = 1;
801                 mncc->progress.descr = 8;
802                 add_trace("progress", "coding", "%d", mncc->progress.coding);
803                 add_trace("progress", "location", "%d", mncc->progress.location);
804                 add_trace("progress", "descr", "%d", mncc->progress.descr);
805         }
806         mncc->fields |= MNCC_F_CAUSE;
807         mncc->cause.coding = 3;
808         mncc->cause.location = param->disconnectinfo.location;
809         mncc->cause.value = param->disconnectinfo.cause;
810         add_trace("cause", "coding", "%d", mncc->cause.coding);
811         add_trace("cause", "location", "%d", mncc->cause.location);
812         add_trace("cause", "value", "%d", mncc->cause.value);
813         end_trace();
814         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
815
816         new_state(PORT_STATE_OUT_DISCONNECT);
817
818         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
819                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
820                 end_trace();
821                 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
822                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
823                 p_g_tch_connected = 1;
824         }
825 }
826
827
828 /* MESSAGE_RELEASE */
829 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
830 {
831         struct gsm_mncc *mncc;
832
833         /* send release */
834         mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
835         gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
836         mncc->fields |= MNCC_F_CAUSE;
837         mncc->cause.coding = 3;
838         mncc->cause.location = param->disconnectinfo.location;
839         mncc->cause.value = param->disconnectinfo.cause;
840         add_trace("cause", "coding", "%d", mncc->cause.coding);
841         add_trace("cause", "location", "%d", mncc->cause.location);
842         add_trace("cause", "value", "%d", mncc->cause.value);
843         end_trace();
844         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
845
846         new_state(PORT_STATE_RELEASE);
847         trigger_work(&p_g_delete);
848         return;
849 }
850
851 /*
852  * endpoint sends messages to the port
853  */
854 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
855 {
856         int ret = 0;
857
858         if (Port::message_epoint(epoint_id, message_id, param))
859                 return 1;
860
861         switch(message_id) {
862                 case MESSAGE_NOTIFY: /* display and notifications */
863                 ret = 1;
864                 message_notify(epoint_id, message_id, param);
865                 break;
866
867 //              case MESSAGE_FACILITY: /* facility message */
868 //              message_facility(epoint_id, message_id, param);
869 //              break;
870
871                 case MESSAGE_PROCEEDING: /* message not handles */
872                 ret = 1;
873                 break;
874
875                 case MESSAGE_PROGRESS:
876                 ret = 1;
877                 message_progress(epoint_id, message_id, param);
878                 break;
879
880                 case MESSAGE_ALERTING: /* call of endpoint is ringing */
881                 ret = 1;
882                 if (p_state!=PORT_STATE_IN_PROCEEDING)
883                         break;
884                 message_alerting(epoint_id, message_id, param);
885                 if (p_g_notify_pending) {
886                         /* send pending notify message during connect */
887                         message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
888                         message_free(p_g_notify_pending);
889                         p_g_notify_pending = NULL;
890                 }
891                 break;
892
893                 case MESSAGE_CONNECT: /* call of endpoint is connected */
894                 ret = 1;
895                 if (p_state!=PORT_STATE_IN_PROCEEDING
896                  && p_state!=PORT_STATE_IN_ALERTING)
897                         break;
898                 message_connect(epoint_id, message_id, param);
899                 if (p_g_notify_pending) {
900                         /* send pending notify message during connect */
901                         message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
902                         message_free(p_g_notify_pending);
903                         p_g_notify_pending = NULL;
904                 }
905                 break;
906
907                 case MESSAGE_DISCONNECT: /* call has been disconnected */
908                 ret = 1;
909                 if (p_state!=PORT_STATE_IN_PROCEEDING
910                  && p_state!=PORT_STATE_IN_ALERTING
911                  && p_state!=PORT_STATE_OUT_SETUP
912                  && p_state!=PORT_STATE_OUT_OVERLAP
913                  && p_state!=PORT_STATE_OUT_PROCEEDING
914                  && p_state!=PORT_STATE_OUT_ALERTING
915                  && p_state!=PORT_STATE_CONNECT
916                  && p_state!=PORT_STATE_CONNECT_WAITING)
917                         break;
918                 message_disconnect(epoint_id, message_id, param);
919                 break;
920
921                 case MESSAGE_RELEASE: /* release isdn port */
922                 ret = 1;
923                 if (p_state==PORT_STATE_RELEASE)
924                         break;
925                 message_release(epoint_id, message_id, param);
926                 break;
927
928         }
929
930         return ret;
931 }
932
933 /* deletes only if l3id is release, otherwhise it will be triggered then */
934 static int delete_event(struct lcr_work *work, void *instance, int index)
935 {
936         class Pgsm *gsmport = (class Pgsm *)instance;
937
938         delete gsmport;
939
940         return 0;
941 }
942
943 int gsm_exit(int rc)
944 {
945         return(rc);
946 }
947
948 int gsm_init(void)
949 {
950         /* seed the PRNG */
951         srand(time(NULL));
952
953         return 0;
954 }
955
956 /*
957  * MNCC interface
958  */
959
960 static int mncc_q_enqueue(struct lcr_gsm *lcr_gsm, struct gsm_mncc *mncc, unsigned int len)
961 {
962         struct mncc_q_entry *qe;
963
964         qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len);
965         if (!qe)
966                 return -ENOMEM;
967
968         qe->next = NULL;
969         qe->len = len;
970         memcpy(qe->data, mncc, len);
971
972         /* in case of empty list ... */
973         if (!lcr_gsm->mncc_q_hd && !lcr_gsm->mncc_q_tail) {
974                 /* the list head and tail both point to the new qe */
975                 lcr_gsm->mncc_q_hd = lcr_gsm->mncc_q_tail = qe;
976         } else {
977                 /* append to tail of list */
978                 lcr_gsm->mncc_q_tail->next = qe;
979                 lcr_gsm->mncc_q_tail = qe;
980         }
981
982         lcr_gsm->mncc_lfd.when |= LCR_FD_WRITE;
983
984         return 0;
985 }
986
987 static struct mncc_q_entry *mncc_q_dequeue(struct lcr_gsm *lcr_gsm)
988 {
989         struct mncc_q_entry *qe = lcr_gsm->mncc_q_hd;
990         if (!qe)
991                 return NULL;
992
993         /* dequeue the successfully sent message */
994         lcr_gsm->mncc_q_hd = qe->next;
995         if (!qe)
996                 return NULL;
997         if (qe == lcr_gsm->mncc_q_tail)
998                 lcr_gsm->mncc_q_tail = NULL;
999
1000         return qe;
1001 }
1002
1003 /* routine called by LCR code if it wants to send a message to OpenBSC */
1004 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data)
1005 {
1006         int len = 0;
1007
1008         /* FIXME: the caller should provide this */
1009         switch (msg_type) {
1010         case GSM_TCHF_FRAME:
1011                 len = sizeof(struct gsm_data_frame) + 33;
1012                 break;
1013         default:
1014                 len = sizeof(struct gsm_mncc);
1015                 break;
1016         }
1017                 
1018         return mncc_q_enqueue(lcr_gsm, (struct gsm_mncc *)data, len);
1019 }
1020
1021 /* close MNCC socket */
1022 static int mncc_fd_close(struct lcr_gsm *lcr_gsm, struct lcr_fd *lfd)
1023 {
1024         class Port *port;
1025         class Pgsm *pgsm = NULL;
1026         struct lcr_msg *message;
1027
1028         PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER);
1029         close(lfd->fd);
1030         unregister_fd(lfd);
1031         lfd->fd = -1;
1032
1033         /* free all the calls that were running through the MNCC interface */
1034         port = port_first;
1035         while(port) {
1036                 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_GSM) {
1037                         pgsm = (class Pgsm *)port;
1038                         if (pgsm->p_g_lcr_gsm == lcr_gsm) {
1039                                 message = message_create(pgsm->p_serial, ACTIVE_EPOINT(pgsm->p_epointlist), 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                                 pgsm->new_state(PORT_STATE_RELEASE);
1044                                 trigger_work(&pgsm->p_g_delete);
1045                         }
1046                 }
1047                 port = port->next;
1048         }
1049
1050         /* flush the queue */
1051         while (mncc_q_dequeue(lcr_gsm))
1052                 ;
1053
1054         /* start the re-connect timer */
1055         schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1056
1057         return 0;
1058 }
1059
1060 /* write to OpenBSC via MNCC socket */
1061 static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx)
1062 {
1063         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1064         struct mncc_q_entry *qe, *qe2;
1065         int rc;
1066
1067         while (1) {
1068                 qe = lcr_gsm->mncc_q_hd;
1069                 if (!qe) {
1070                         lfd->when &= ~LCR_FD_WRITE;
1071                         break;
1072                 }
1073                 rc = write(lfd->fd, qe->data, qe->len);
1074                 if (rc == 0)
1075                         return mncc_fd_close(lcr_gsm, lfd);
1076                 if (rc < 0)
1077                         return rc;
1078                 if (rc < (int)qe->len)
1079                         return -1;
1080                 /* dequeue the successfully sent message */
1081                 qe2 = mncc_q_dequeue(lcr_gsm);
1082                 assert(qe == qe2);
1083                 free(qe);
1084         }
1085         return 0;
1086 }
1087
1088 /* read from OpenBSC via MNCC socket */
1089 static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
1090 {
1091         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1092         int rc;
1093         static char buf[sizeof(struct gsm_mncc)+1024];
1094         struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
1095
1096         memset(buf, 0, sizeof(buf));
1097         rc = recv(lfd->fd, buf, sizeof(buf), 0);
1098         if (rc == 0)
1099                 return mncc_fd_close(lcr_gsm, lfd);
1100         if (rc < 0)
1101                 return rc;
1102
1103         /* Hand the MNCC message into LCR */
1104         switch (lcr_gsm->type) {
1105 #ifdef WITH_GSM_BS
1106         case LCR_GSM_TYPE_NETWORK:
1107                 return message_bsc(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1108 #endif
1109 #ifdef WITH_GSM_MS
1110         case LCR_GSM_TYPE_MS:
1111                 return message_ms(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1112 #endif
1113         default:
1114                 return 0;
1115         }
1116 }
1117
1118 /* file descriptor callback if we can read or write form MNCC socket */
1119 static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *inst, int idx)
1120 {
1121         int rc = 0;
1122
1123         if (what & LCR_FD_READ)
1124                 rc = mncc_fd_read(lfd, inst, idx);
1125         if (rc < 0)
1126                 return rc;
1127
1128         if (what & LCR_FD_WRITE)
1129                 rc = mncc_fd_write(lfd, inst, idx);
1130
1131         return rc;
1132 }
1133
1134 int mncc_socket_retry_cb(struct lcr_timer *timer, void *inst, int index)
1135 {
1136         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1137         int fd, rc;
1138
1139         lcr_gsm->mncc_lfd.fd = -1;
1140
1141         fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1142         if (fd < 0) {
1143                 PERROR("Cannot create SEQPACKET socket, giving up!\n");
1144                 return fd;
1145         }
1146
1147         rc = connect(fd, (struct sockaddr *) &lcr_gsm->sun,
1148                      sizeof(lcr_gsm->sun));
1149         if (rc < 0) {
1150                 PERROR("Could not connect to MNCC socket %s, "
1151                         "retrying in %u seconds\n", lcr_gsm->sun.sun_path,
1152                         SOCKET_RETRY_TIMER);
1153                 close(fd);
1154                 schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1155         } else {
1156                 PDEBUG(DEBUG_GSM, "Connected to MNCC socket %s!\n", lcr_gsm->sun.sun_path);
1157                 lcr_gsm->mncc_lfd.fd = fd;
1158                 register_fd(&lcr_gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, lcr_gsm, 0);
1159         }
1160
1161         return 0;
1162 }
1163