some sip fixes
[lcr.git] / gsm_bs.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN gsm (BS mode)                                                       **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13 #include "mncc.h"
14
15 struct lcr_gsm *gsm_bs_first = NULL;
16
17 #define PAYLOAD_TYPE_GSM 3
18
19 /*
20  * DTMF stuff
21  */
22 unsigned char dtmf_samples[16][8000];
23 static int dtmf_x[4] = { 1209, 1336, 1477, 1633 };
24 static int dtmf_y[4] = { 697, 770, 852, 941 };
25
26 void generate_dtmf(void)
27 {
28         double fx, fy, sample;
29         int i, x, y;
30         unsigned char *law;
31
32         for (y = 0; y < 4; y++) {
33                 fy = 2 * 3.1415927 * ((double)dtmf_y[y]) / 8000.0;
34                 for (x = 0; x < 4; x++) {
35                         fx = 2 * 3.1415927 * ((double)dtmf_x[x]) / 8000.0;
36                         law = dtmf_samples[y << 2 | x];
37                         for (i = 0; i < 8000; i++) {
38                                 sample = sin(fy * ((double)i)) * 0.251 * 32767.0; /* -6 dB */
39                                 sample += sin(fx * ((double)i)) * 0.158 * 32767.0; /* -8 dB */
40                                 *law++ = audio_s16_to_law[(int)sample & 0xffff];
41                         }
42                 }
43         }
44 }
45
46
47 /*
48  * constructor
49  */
50 Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
51 {
52         struct lcr_gsm *gsm_bs = gsm_bs_first;
53
54         p_g_lcr_gsm = NULL;
55         SCPY(p_g_bs_name, interface->gsm_bs_name);
56
57         while (gsm_bs) {
58                 if (gsm_bs->type == LCR_GSM_TYPE_NETWORK && !strcmp(gsm_bs->name, p_g_bs_name)) {
59                         p_g_lcr_gsm = gsm_bs;
60                         break;
61                 }
62                 gsm_bs = gsm_bs->gsm_next;
63         }
64
65         p_g_dtmf = NULL;
66         p_g_dtmf_index = 0;
67
68         PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s %s).\n", portname, p_g_bs_name);
69 }
70
71 /*
72  * destructor
73  */
74 Pgsm_bs::~Pgsm_bs()
75 {
76         PDEBUG(DEBUG_GSM, "Destroyed GSM BS process(%s).\n", p_name);
77 }
78
79 static const char *media_type2name(unsigned char media_type) {
80         switch (media_type) {
81         case MEDIA_TYPE_ULAW:
82                 return "PCMU";
83         case MEDIA_TYPE_ALAW:
84                 return "PCMA";
85         case MEDIA_TYPE_GSM:
86                 return "GSM";
87         case MEDIA_TYPE_GSM_HR:
88                 return "GSM-HR";
89         case MEDIA_TYPE_GSM_EFR:
90                 return "GSM-EFR";
91         case MEDIA_TYPE_AMR:
92                 return "AMR";
93         }
94
95         return "UKN";
96 }
97
98 /* PROCEEDING INDICATION (from MS) */
99 void Pgsm_bs::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
100 {
101         int media_types[8];
102         unsigned char payload_types[8];
103         int payloads = 0;
104
105         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
106         if (mncc->fields & MNCC_F_CAUSE) {
107                 add_trace("cause", "coding", "%d", mncc->cause.coding);
108                 add_trace("cause", "location", "%", mncc->cause.location);
109                 add_trace("cause", "value", "%", mncc->cause.value);
110         }
111         end_trace();
112
113         new_state(PORT_STATE_OUT_PROCEEDING);
114
115         /* get list of offered payload types
116          * if list ist empty, the FR V1 is selected */
117         select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
118         /* if no given payload type is supported, we select from channel type */
119         if (!payloads) {
120                 switch (mncc->lchan_type) {
121                 case GSM_LCHAN_TCH_F:
122                         media_types[0] = MEDIA_TYPE_GSM;
123                         payload_types[0] = PAYLOAD_TYPE_GSM;
124                         payloads = 1;
125                         break;
126                 case GSM_LCHAN_TCH_H:
127                         media_types[0] = MEDIA_TYPE_GSM_HR;
128                         payload_types[0] = 96; /* dynamic */
129                         payloads = 1;
130                         break;
131                 default:
132                         mncc = create_mncc(MNCC_REL_REQ, callref);
133                         gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
134                         mncc->fields |= MNCC_F_CAUSE;
135                         mncc->cause.coding = 3;
136                         mncc->cause.location = 1;
137                         mncc->cause.value = 65;
138                         add_trace("cause", "coding", "%d", mncc->cause.coding);
139                         add_trace("cause", "location", "%d", mncc->cause.location);
140                         add_trace("cause", "value", "%d", mncc->cause.value);
141                         add_trace("reason", NULL, "Given lchan not supported");
142                         end_trace();
143                         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
144                         new_state(PORT_STATE_RELEASE);
145                         trigger_work(&p_g_delete);
146                         return;
147                 }
148         }
149
150         /* select first payload type that matches the rtp list */
151         if (p_g_rtp_bridge) {
152                 int i, j;
153
154                 for (i = 0; i < p_g_rtp_payloads; i++) {
155                         for (j = 0; j < payloads; j++) {
156                                 if (p_g_rtp_media_types[i] == media_types[j])
157                                         break;
158                         }
159                         if (j < payloads)
160                                 break;
161                 }
162                 if (i == p_g_rtp_payloads) {
163                         struct lcr_msg *message;
164
165                         /* payload offered by remote RTP is not supported */
166                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
167                         message->param.disconnectinfo.cause = 65;
168                         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
169                         message_put(message);
170                         /* send release */
171                         mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
172                         gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
173                         mncc->fields |= MNCC_F_CAUSE;
174                         mncc->cause.coding = 3;
175                         mncc->cause.location = LOCATION_PRIVATE_LOCAL;
176                         mncc->cause.value = 65;
177                         add_trace("cause", "coding", "%d", mncc->cause.coding);
178                         add_trace("cause", "location", "%d", mncc->cause.location);
179                         add_trace("cause", "value", "%d", mncc->cause.value);
180                         add_trace("reason", NULL, "None of the payload types are supported by MS");
181                         end_trace();
182                         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
183                         new_state(PORT_STATE_RELEASE);
184                         trigger_work(&p_g_delete);
185
186                         return;
187                 }
188                 modify_lchan(p_g_rtp_media_types[i]);
189                 /* use the payload type from received rtp list, not from locally generated payload types */
190                 p_g_payload_type = p_g_rtp_payload_types[i];
191         } else {
192                 /* modify to first given payload */
193                 modify_lchan(media_types[0]);
194                 p_g_payload_type = payload_types[0];
195         }
196
197         if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
198                 struct gsm_mncc *frame;
199                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
200                 end_trace();
201                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
202                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
203                 p_g_tch_connected = 1;
204         }
205 }
206
207 /* DTMF INDICATION */
208 void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
209 {
210         struct gsm_mncc *resp;
211
212         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
213         add_trace("keypad", NULL, "%c", mncc->keypad);
214         end_trace();
215         SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
216         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
217
218         /* send resp */
219         gsm_trace_header(p_interface_name, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
220         add_trace("keypad", NULL, "%c", mncc->keypad);
221         end_trace();
222         resp = create_mncc(MNCC_START_DTMF_RSP, p_g_callref);
223         resp->fields |= MNCC_F_KEYPAD;
224         resp->keypad = mncc->keypad;
225         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
226
227         if (p_g_rtp_bridge) {
228                 /* if two members are bridged */
229                 if (p_bridge && p_bridge->first && p_bridge->first->next && !p_bridge->first->next->next) {
230                         class Port *remote = NULL;
231
232                         /* select other member */
233                         if (p_bridge->first->port == this)
234                                 remote = p_bridge->first->next->port;
235                         if (p_bridge->first->next->port == this)
236                                 remote = p_bridge->first->port;
237
238                         if (remote) {
239                                 struct lcr_msg *message;
240
241                                 /* send dtmf information, because we bridge RTP directly */
242                                 message = message_create(0, remote->p_serial, EPOINT_TO_PORT, MESSAGE_DTMF);
243                                 message->param.dtmf = mncc->keypad;
244                                 message_put(message);
245                         }
246                 }
247         } else {
248                 /* generate DTMF tones, since we do audio forwarding inside LCR */
249                 switch (mncc->keypad) {
250                         case '1': p_g_dtmf = dtmf_samples[0]; break;
251                         case '2': p_g_dtmf = dtmf_samples[1]; break;
252                         case '3': p_g_dtmf = dtmf_samples[2]; break;
253                         case 'a':
254                         case 'A': p_g_dtmf = dtmf_samples[3]; break;
255                         case '4': p_g_dtmf = dtmf_samples[4]; break;
256                         case '5': p_g_dtmf = dtmf_samples[5]; break;
257                         case '6': p_g_dtmf = dtmf_samples[6]; break;
258                         case 'b':
259                         case 'B': p_g_dtmf = dtmf_samples[7]; break;
260                         case '7': p_g_dtmf = dtmf_samples[8]; break;
261                         case '8': p_g_dtmf = dtmf_samples[9]; break;
262                         case '9': p_g_dtmf = dtmf_samples[10]; break;
263                         case 'c':
264                         case 'C': p_g_dtmf = dtmf_samples[11]; break;
265                         case '*': p_g_dtmf = dtmf_samples[12]; break;
266                         case '0': p_g_dtmf = dtmf_samples[13]; break;
267                         case '#': p_g_dtmf = dtmf_samples[14]; break;
268                         case 'd':
269                         case 'D': p_g_dtmf = dtmf_samples[15]; break;
270                 }
271                 p_g_dtmf_index = 0;
272         }
273 }
274 void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
275 {
276         struct gsm_mncc *resp;
277
278         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
279         add_trace("keypad", NULL, "%c", mncc->keypad);
280         end_trace();
281
282         /* send resp */
283         gsm_trace_header(p_interface_name, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
284         add_trace("keypad", NULL, "%c", mncc->keypad);
285         end_trace();
286         resp = create_mncc(MNCC_STOP_DTMF_RSP, p_g_callref);
287         resp->keypad = mncc->keypad;
288         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
289         
290         /* stop DTMF */
291         p_g_dtmf = NULL;
292 }
293
294 /* HOLD INDICATION */
295 void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
296 {
297         struct lcr_msg *message;
298         struct gsm_mncc *resp, *frame;
299
300         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
301         end_trace();
302
303         /* notify the hold of call */
304         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
305         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
306         message->param.notifyinfo.local = 1; /* call is held by supplementary service */
307         message_put(message);
308
309         /* acknowledge hold */
310         gsm_trace_header(p_interface_name, this, MNCC_HOLD_CNF, DIRECTION_OUT);
311         end_trace();
312         resp = create_mncc(MNCC_HOLD_CNF, p_g_callref);
313         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
314
315         /* disable audio */
316         if (p_g_tch_connected) { /* it should be true */
317                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_DROP, DIRECTION_OUT);
318                 end_trace();
319                 frame = create_mncc(MNCC_FRAME_DROP, p_g_callref);
320                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
321                 p_g_tch_connected = 0;
322         }
323 }
324
325
326 /* RETRIEVE INDICATION */
327 void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
328 {
329         struct lcr_msg *message;
330         struct gsm_mncc *resp, *frame;
331
332         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
333         end_trace();
334
335         /* notify the retrieve of call */
336         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
337         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
338         message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
339         message_put(message);
340
341         /* acknowledge retr */
342         gsm_trace_header(p_interface_name, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
343         end_trace();
344         resp = create_mncc(MNCC_RETRIEVE_CNF, p_g_callref);
345         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
346
347         /* enable audio */
348         if (!p_g_tch_connected) { /* it should be true */
349                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
350                 end_trace();
351                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
352                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
353                 p_g_tch_connected = 1;
354         }
355 }
356
357 /*
358  * select payload type by given list or GSM V1 FR 
359  * return the payload type or 0 if not given 
360  */
361
362 void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_types, int *media_types, int *payloads, int max_payloads)
363 {
364         int media_type;
365         unsigned char payload_type;
366         int half;
367         void *encoder, *decoder;
368
369         *payloads = 0;
370
371         gsm_trace_header(p_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
372         if ((mncc->fields & MNCC_F_BEARER_CAP)) {
373                 /* select preferred payload type from list */
374                 int i;
375                 unsigned char dynamic_type = 96;
376
377                 add_trace("bearer", "capa", "given by MS");
378                 for (i = 0; mncc->bearer_cap.speech_ver[i] >= 0; i++) {
379                         half = 0;
380                         /* select payload type we support */
381                         switch (mncc->bearer_cap.speech_ver[i]) {
382                         case 0:
383                                 add_trace("speech", "version", "Full Rate given");
384                                 media_type = MEDIA_TYPE_GSM;
385                                 payload_type = PAYLOAD_TYPE_GSM;
386                                 encoder = p_g_fr_encoder;
387                                 decoder = p_g_fr_decoder;
388                                 break;
389                         case 2:
390                                 add_trace("speech", "version", "EFR given");
391                                 media_type = MEDIA_TYPE_GSM_EFR;
392                                 payload_type = dynamic_type++;
393                                 encoder = p_g_amr_encoder;
394                                 decoder = p_g_amr_decoder;
395                                 break;
396                         case 4:
397                                 add_trace("speech", "version", "AMR given");
398                                 media_type = MEDIA_TYPE_AMR;
399                                 payload_type = dynamic_type++;
400                                 encoder = p_g_amr_encoder;
401                                 decoder = p_g_amr_decoder;
402                                 break;
403                         case 1:
404                                 add_trace("speech", "version", "Half Rate given");
405                                 media_type = MEDIA_TYPE_GSM_HR;
406                                 payload_type = dynamic_type++;
407                                 encoder = p_g_hr_encoder;
408                                 decoder = p_g_hr_decoder;
409                                 half = 1;
410                                 break;
411                         case 5:
412                                 add_trace("speech", "version", "AMR Half Rate given");
413                                 media_type = MEDIA_TYPE_AMR;
414                                 payload_type = dynamic_type++;
415                                 encoder = p_g_amr_encoder;
416                                 decoder = p_g_amr_decoder;
417                                 half = 1;
418                                 break;
419                         case 0x80:
420                                 add_trace("speech", "version", "Analog 8000Hz given");
421                                 media_type = MEDIA_TYPE_ANALOG;
422                                 payload_type = dynamic_type++;
423                                 encoder = (void *)1;
424                                 decoder = (void *)1;
425                                 break;
426                         default:
427                                 add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]);
428                                 media_type = 0;
429                                 payload_type = 0;
430                         }
431                         /* wen don't support it, so we check the next */
432                         if (!media_type) {
433                                 add_trace("speech", "ignored", "Not supported by LCR");
434                                 continue;
435                         }
436                         if (!half && mncc->lchan_type != GSM_LCHAN_TCH_F) {
437                                 add_trace("speech", "ignored", "Not TCH/F");
438                                 continue;
439                         }
440                         if (half && mncc->lchan_type != GSM_LCHAN_TCH_H) {
441                                 add_trace("speech", "ignored", "Not TCH/H");
442                                 continue;
443                         }
444                         if (!p_g_rtp_bridge) {
445                                 if (!encoder || !decoder) {
446                                         add_trace("speech", "ignored", "Codec not supported");
447                                         continue;
448                                 }
449                         }
450                         if (*payloads <= max_payloads) {
451                                 media_types[*payloads] = media_type;
452                                 payload_types[*payloads] = payload_type;
453                                 (*payloads)++;
454                         }
455                 }
456         } else {
457                 add_trace("bearer", "capa", "not given by MS");
458                 add_trace("speech", "version", "Full Rate given");
459                 media_types[0] = MEDIA_TYPE_GSM;
460                 payload_types[0] = PAYLOAD_TYPE_GSM;
461                 *payloads = 1;
462         }
463         if (!(*payloads))
464                 add_trace("error", "", "All given payload types unsupported");
465         end_trace();
466 }
467
468 /*
469  * handles all indications
470  */
471 /* SETUP INDICATION */
472 void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
473 {
474         class Endpoint *epoint;
475         struct lcr_msg *message;
476         struct gsm_mncc *proceeding, *frame;
477         struct interface *interface;
478         int media_types[8];
479         unsigned char payload_types[8];
480         int payloads = 0;
481
482         interface = getinterfacebyname(p_interface_name);
483         if (!interface) {
484                 PERROR("Cannot find interface %s.\n", p_interface_name);
485                 return;
486         }
487
488         /* process given callref */
489         gsm_trace_header(p_interface_name, this, 0, DIRECTION_IN);
490         add_trace("callref", "new", "0x%x", callref);
491         if (p_g_callref) {
492                 /* release in case the ID is already in use */
493                 add_trace("error", NULL, "callref already in use");
494 reject:
495                 end_trace();
496                 mncc = create_mncc(MNCC_REJ_REQ, callref);
497                 gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
498                 mncc->fields |= MNCC_F_CAUSE;
499                 mncc->cause.coding = 3;
500                 mncc->cause.location = 1;
501                 mncc->cause.value = 47;
502                 add_trace("cause", "coding", "%d", mncc->cause.coding);
503                 add_trace("cause", "location", "%d", mncc->cause.location);
504                 add_trace("cause", "value", "%d", mncc->cause.value);
505                 add_trace("reason", NULL, "callref already in use");
506                 end_trace();
507                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
508                 new_state(PORT_STATE_RELEASE);
509                 trigger_work(&p_g_delete);
510                 return;
511         }
512         if (callref < 0x40000000) {
513                 /* release in case the ID is invalid */
514                 add_trace("error", NULL, "callref invalid, not of BSC type");
515                 goto reject;
516         }
517         p_g_callref = callref;
518         end_trace();
519
520         /* caller info */
521         if (mncc->clir.inv)
522                 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
523         else
524                 p_callerinfo.present = INFO_PRESENT_ALLOWED;
525         if (mncc->calling.number[0])
526                 SCPY(p_callerinfo.id, mncc->calling.number);
527         else
528                 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
529         SCPY(p_callerinfo.imsi, mncc->imsi);
530         p_callerinfo.screen = INFO_SCREEN_NETWORK;
531         switch (mncc->calling.type) {
532                 case 0x1:
533                 p_callerinfo.ntype = INFO_NTYPE_INTERNATIONAL;
534                 break;
535                 case 0x2:
536                 p_callerinfo.ntype = INFO_NTYPE_NATIONAL;
537                 break;
538                 case 0x4:
539                 p_callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
540                 break;
541                 default:
542                 p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
543                 break;
544         }
545         SCPY(p_callerinfo.interface, p_interface_name);
546
547         /* dialing information */
548         SCAT(p_dialinginfo.id, mncc->called.number);
549         switch (mncc->called.type) {
550                 case 0x1:
551                 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
552                 break;
553                 case 0x2:
554                 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
555                 break;
556                 case 0x4:
557                 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
558                 break;
559                 default:
560                 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
561                 break;
562         }
563         if (mncc->emergency) {
564                 SCPY(p_dialinginfo.id, "emergency");
565         }
566         p_dialinginfo.sending_complete = 1;
567
568         /* bearer capability */
569         p_capainfo.bearer_capa = INFO_BC_SPEECH;
570         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
571         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
572         p_capainfo.source_mode = B_MODE_TRANSPARENT;
573         p_g_mode = p_capainfo.source_mode;
574
575         /* get list of offered payload types
576          * if list ist empty, the FR V1 is selected */
577         select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
578         /* if no given payload type is supported, we select from channel type */
579         if (!payloads) {
580                 switch (mncc->lchan_type) {
581                 case GSM_LCHAN_TCH_F:
582                         media_types[0] = MEDIA_TYPE_GSM;
583                         payload_types[0] = PAYLOAD_TYPE_GSM;
584                         payloads = 1;
585                         break;
586                 case GSM_LCHAN_TCH_H:
587                         media_types[0] = MEDIA_TYPE_GSM_HR;
588                         payload_types[0] = 96; /* dynamic */
589                         payloads = 1;
590                         break;
591                 default:
592                         mncc = create_mncc(MNCC_REJ_REQ, callref);
593                         gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
594                         mncc->fields |= MNCC_F_CAUSE;
595                         mncc->cause.coding = 3;
596                         mncc->cause.location = 1;
597                         mncc->cause.value = 65;
598                         add_trace("cause", "coding", "%d", mncc->cause.coding);
599                         add_trace("cause", "location", "%d", mncc->cause.location);
600                         add_trace("cause", "value", "%d", mncc->cause.value);
601                         add_trace("reason", NULL, "Given lchan not supported");
602                         end_trace();
603                         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
604                         new_state(PORT_STATE_RELEASE);
605                         trigger_work(&p_g_delete);
606                         return;
607                 }
608         }
609 #if 0
610         /* if no given payload type is supported, we reject the call */
611         if (!payloads) {
612         }
613 #endif
614
615         /* useruser */
616
617         /* what infos did we got ... */
618         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
619         if (p_callerinfo.id[0])
620                 add_trace("calling", "number", "%s", p_callerinfo.id);
621         else if (p_callerinfo.imsi[0])
622                 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
623         add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
624         add_trace("dialing", "number", "%s", p_dialinginfo.id);
625         end_trace();
626
627         /* create endpoint */
628         if (p_epointlist)
629                 FATAL("Incoming call but already got an endpoint.\n");
630         if (!(epoint = new Endpoint(p_serial, 0)))
631                 FATAL("No memory for Endpoint instance\n");
632         epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
633         epointlist_new(epoint->ep_serial);
634
635         /* modify lchan in case of no rtp bridge */
636         if (!p_g_rtp_bridge)
637                 modify_lchan(media_types[0]);
638
639         /* send call proceeding */
640         gsm_trace_header(p_interface_name, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
641         proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_g_callref);
642         if (p_g_tones) {
643                 proceeding->fields |= MNCC_F_PROGRESS;
644                 proceeding->progress.coding = 3; /* GSM */
645                 proceeding->progress.location = 1;
646                 proceeding->progress.descr = 8;
647                 add_trace("progress", "coding", "%d", proceeding->progress.coding);
648                 add_trace("progress", "location", "%d", proceeding->progress.location);
649                 add_trace("progress", "descr", "%d", proceeding->progress.descr);
650         }
651         end_trace();
652         send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
653
654         new_state(PORT_STATE_IN_PROCEEDING);
655
656         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
657                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
658                 end_trace();
659                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
660                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
661                 p_g_tch_connected = 1;
662         }
663
664         /* send setup message to endpoit */
665         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
666         message->param.setup.port_type = p_type;
667 //      message->param.setup.dtmf = 0;
668         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
669         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
670         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
671         SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
672         message->param.setup.useruser.len = strlen(mncc->useruser.info);
673         message->param.setup.useruser.protocol = mncc->useruser.proto;
674         if (p_g_rtp_bridge) {
675                 struct gsm_mncc_rtp *rtp;
676                 int i;
677
678                 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding setup\n");
679                 p_g_setup_pending = message;
680                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
681                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
682
683                 for (i = 0; i < (int)sizeof(message->param.setup.rtpinfo.payload_types) && i < payloads; i++) {
684                         message->param.setup.rtpinfo.media_types[i] = media_types[i];
685                         message->param.setup.rtpinfo.payload_types[i] = payload_types[i];
686                         message->param.setup.rtpinfo.payloads++;
687                 }
688
689         } else
690                 message_put(message);
691
692 }
693
694 /*
695  * BSC sends message to port
696  */
697 int message_bsc(class Pgsm_bs *pgsm_bs, struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
698 {
699         struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
700         unsigned int callref = mncc->callref;
701         char name[64];
702
703         /* Special messages */
704         switch(msg_type) {
705         }
706
707         if (msg_type == GSM_TCHF_FRAME
708          || msg_type == GSM_TCHF_FRAME_EFR
709          || msg_type == GSM_TCHH_FRAME
710          || msg_type == GSM_TCH_FRAME_AMR
711          || msg_type == ANALOG_8000HZ
712          || msg_type == GSM_BAD_FRAME) {
713                 if (pgsm_bs) {
714                         /* inject DTMF, if enabled */
715                         if (pgsm_bs->p_g_dtmf) {
716                                 unsigned char data[160];
717                                 int i;
718
719                                 for (i = 0; i < 160; i++) {
720                                         data[i] = pgsm_bs->p_g_dtmf[pgsm_bs->p_g_dtmf_index++];
721                                         if (pgsm_bs->p_g_dtmf_index == 8000)
722                                                 pgsm_bs->p_g_dtmf_index = 0;
723                                 }
724                                 /* send */
725                                 pgsm_bs->bridge_tx(data, 160);
726                         } else
727                                 pgsm_bs->frame_receive(arg);
728                         /* if we do not bridge we need to inject audio, if available */
729                         if (!pgsm_bs->p_bridge || pgsm_bs->p_tone_name[0]) {
730                                 unsigned char data[160];
731                                 int i;
732
733                                 i = pgsm_bs->read_audio(data, 160);
734                                 if (i)
735                                         pgsm_bs->audio_send(data, i);
736                         }
737                 }
738                 return 0;
739         }
740
741         if (!pgsm_bs) {
742                 struct interface *interface;
743
744                 if (msg_type != MNCC_SETUP_IND)
745                         return(0);
746
747                 interface = getinterfacebyname(lcr_gsm->interface_name);
748                 if (!interface) {
749                         struct gsm_mncc *rej;
750
751                         rej = create_mncc(MNCC_REJ_REQ, callref);
752                         rej->fields |= MNCC_F_CAUSE;
753                         rej->cause.coding = 3;
754                         rej->cause.location = 1;
755                         rej->cause.value = 27;
756                         gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
757                         add_trace("cause", "coding", "%d", rej->cause.coding);
758                         add_trace("cause", "location", "%d", rej->cause.location);
759                         add_trace("cause", "value", "%d", rej->cause.value);
760                         add_trace("reason", NULL, "interface %s not found", lcr_gsm->interface_name);
761                         end_trace();
762                         send_and_free_mncc(lcr_gsm, rej->msg_type, rej);
763                         return 0;
764                 }
765                 /* creating port object, transparent until setup with hdlc */
766                 SPRINT(name, "%s-%d-in", interface->name, 0);
767                 if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, name, NULL, interface)))
768                         FATAL("Cannot create Port instance.\n");
769         }
770
771         switch(msg_type) {
772                 case MNCC_SETUP_IND:
773                 pgsm_bs->setup_ind(msg_type, callref, mncc);
774                 break;
775
776                 case MNCC_RTP_CREATE:
777                 pgsm_bs->rtp_create_ind(msg_type, callref, mncc);
778                 break;
779
780                 case MNCC_RTP_CONNECT:
781                 pgsm_bs->rtp_connect_ind(msg_type, callref, mncc);
782                 break;
783
784                 case MNCC_START_DTMF_IND:
785                 pgsm_bs->start_dtmf_ind(msg_type, callref, mncc);
786                 break;
787
788                 case MNCC_STOP_DTMF_IND:
789                 pgsm_bs->stop_dtmf_ind(msg_type, callref, mncc);
790                 break;
791
792                 case MNCC_CALL_CONF_IND:
793                 pgsm_bs->call_conf_ind(msg_type, callref, mncc);
794                 break;
795
796                 case MNCC_ALERT_IND:
797                 pgsm_bs->alert_ind(msg_type, callref, mncc);
798                 break;
799
800                 case MNCC_SETUP_CNF:
801                 pgsm_bs->setup_cnf(msg_type, callref, mncc);
802                 break;
803
804                 case MNCC_SETUP_COMPL_IND:
805                 pgsm_bs->setup_compl_ind(msg_type, callref, mncc);
806                 break;
807
808                 case MNCC_DISC_IND:
809                 pgsm_bs->disc_ind(msg_type, callref, mncc);
810                 break;
811
812                 case MNCC_REL_IND:
813                 case MNCC_REL_CNF:
814                 case MNCC_REJ_IND:
815                 pgsm_bs->rel_ind(msg_type, callref, mncc);
816                 break;
817
818                 case MNCC_NOTIFY_IND:
819                 pgsm_bs->notify_ind(msg_type, callref, mncc);
820                 break;
821
822                 case MNCC_HOLD_IND:
823                 pgsm_bs->hold_ind(msg_type, callref, mncc);
824                 break;
825
826                 case MNCC_RETRIEVE_IND:
827                 pgsm_bs->retr_ind(msg_type, callref, mncc);
828                 break;
829
830                 default:
831                 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm_bs->p_name, pgsm_bs->p_callerinfo.id, msg_type);
832         }
833         return(0);
834 }
835
836 /* MESSAGE_SETUP */
837 void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
838 {
839         struct lcr_msg *message;
840         struct epoint_list *epointlist;
841         struct gsm_mncc *mncc;
842         struct interface *interface;
843
844         interface = getinterfacebyname(p_interface_name);
845         if (!interface) {
846                 PERROR("Cannot find interface %s.\n", p_interface_name);
847                 return;
848         }
849
850         /* copy setup infos to port */
851         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
852         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
853         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
854         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
855
856         /* no GSM MNCC connection */
857         if (p_g_lcr_gsm->mncc_lfd.fd < 0) {
858                 gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
859                 add_trace("failure", NULL, "No MNCC connection.");
860                 end_trace();
861                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
862                 message->param.disconnectinfo.cause = 41; // temp. failure.
863                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
864                 message_put(message);
865                 new_state(PORT_STATE_RELEASE);
866                 trigger_work(&p_g_delete);
867                 return;
868         }
869
870         /* no number */
871         if (!p_dialinginfo.id[0]) {
872                 gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
873                 add_trace("failure", NULL, "No dialed subscriber given.");
874                 end_trace();
875                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
876                 message->param.disconnectinfo.cause = 28;
877                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
878                 message_put(message);
879                 new_state(PORT_STATE_RELEASE);
880                 trigger_work(&p_g_delete);
881                 return;
882         }
883
884         /* unsupported codec for RTP bridge */
885         if (param->setup.rtpinfo.port) {
886                 int i;
887
888                 p_g_rtp_payloads = 0;
889                 gsm_trace_header(p_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
890                 for (i = 0; i < param->setup.rtpinfo.payloads; i++) {
891                         switch (param->setup.rtpinfo.media_types[i]) {
892                         case MEDIA_TYPE_GSM:
893                         case MEDIA_TYPE_GSM_EFR:
894                         case MEDIA_TYPE_AMR:
895                         case MEDIA_TYPE_GSM_HR:
896                                 add_trace("rtp", "payload", "%s:%d supported", media_type2name(param->setup.rtpinfo.media_types[i]), param->setup.rtpinfo.payload_types[i]);
897                                 if (p_g_rtp_payloads < (int)sizeof(p_g_rtp_payload_types)) {
898                                         p_g_rtp_media_types[p_g_rtp_payloads] = param->setup.rtpinfo.media_types[i];
899                                         p_g_rtp_payload_types[p_g_rtp_payloads] = param->setup.rtpinfo.payload_types[i];
900                                         p_g_rtp_payloads++;
901                                 }
902                                 break;
903                         default:
904                                 add_trace("rtp", "payload", "%s:%d unsupported", media_type2name(param->setup.rtpinfo.media_types[i]), param->setup.rtpinfo.payload_types[i]);
905                         }
906                 }
907                 end_trace();
908                 if (!p_g_rtp_payloads) {
909                         gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
910                         add_trace("failure", NULL, "No payload given that is supported by GSM");
911                         end_trace();
912                         message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
913                         message->param.disconnectinfo.cause = 65;
914                         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
915                         message_put(message);
916                         new_state(PORT_STATE_RELEASE);
917                         trigger_work(&p_g_delete);
918                         return;
919                 }
920         }
921
922 //              SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
923         /* screen outgoing caller id */
924         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_interface_name);
925
926         /* attach only if not already */
927         epointlist = p_epointlist;
928         while(epointlist) {
929                 if (epointlist->epoint_id == epoint_id)
930                         break;
931                 epointlist = epointlist->next;
932         }
933         if (!epointlist)
934                 epointlist_new(epoint_id);
935
936         /* creating l3id */
937         gsm_trace_header(p_interface_name, this, 0, DIRECTION_OUT);
938         p_g_callref = new_callref++;
939         add_trace("callref", "new", "0x%x", p_g_callref);
940         end_trace();
941
942         gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
943         mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
944         /* caller information */
945         mncc->fields |= MNCC_F_CALLING;
946         mncc->calling.plan = 1;
947         switch (p_callerinfo.ntype) {
948                 case INFO_NTYPE_UNKNOWN:
949                 mncc->calling.type = 0x0;
950                 break;
951                 case INFO_NTYPE_INTERNATIONAL:
952                 mncc->calling.type = 0x1;
953                 break;
954                 case INFO_NTYPE_NATIONAL:
955                 mncc->calling.type = 0x2;
956                 break;
957                 case INFO_NTYPE_SUBSCRIBER:
958                 mncc->calling.type = 0x4;
959                 break;
960                 default: /* INFO_NTYPE_NOTPRESENT */
961                 mncc->fields &= ~MNCC_F_CALLING;
962                 break;
963         }
964         switch (p_callerinfo.screen) {
965                 case INFO_SCREEN_USER:
966                 mncc->calling.screen = 0;
967                 break;
968                 default: /* INFO_SCREEN_NETWORK */
969                 mncc->calling.screen = 3;
970                 break;
971         }
972         switch (p_callerinfo.present) {
973                 case INFO_PRESENT_ALLOWED:
974                 mncc->calling.present = 0;
975                 break;
976                 case INFO_PRESENT_RESTRICTED:
977                 mncc->calling.present = 1;
978                 break;
979                 default: /* INFO_PRESENT_NOTAVAIL */
980                 mncc->calling.present = 2;
981                 break;
982         }
983         if (mncc->fields & MNCC_F_CALLING) {
984                 SCPY(mncc->calling.number, p_callerinfo.id);
985                 add_trace("calling", "type", "%d", mncc->calling.type);
986                 add_trace("calling", "plan", "%d", mncc->calling.plan);
987                 add_trace("calling", "present", "%d", mncc->calling.present);
988                 add_trace("calling", "screen", "%d", mncc->calling.screen);
989                 add_trace("calling", "number", "%s", mncc->calling.number);
990         }
991         /* dialing information */
992         mncc->fields |= MNCC_F_CALLED;
993         if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
994                 SCPY(mncc->imsi, p_dialinginfo.id+5);
995                 add_trace("dialing", "imsi", "%s", mncc->imsi);
996         } else {
997                 SCPY(mncc->called.number, p_dialinginfo.id);
998                 add_trace("dialing", "number", "%s", mncc->called.number);
999         }
1000         
1001         /* sending user-user */
1002
1003         /* redirecting number */
1004         mncc->fields |= MNCC_F_REDIRECTING;
1005         mncc->redirecting.plan = 1;
1006         switch (p_redirinfo.ntype) {
1007                 case INFO_NTYPE_UNKNOWN:
1008                 mncc->redirecting.type = 0x0;
1009                 break;
1010                 case INFO_NTYPE_INTERNATIONAL:
1011                 mncc->redirecting.type = 0x1;
1012                 break;
1013                 case INFO_NTYPE_NATIONAL:
1014                 mncc->redirecting.type = 0x2;
1015                 break;
1016                 case INFO_NTYPE_SUBSCRIBER:
1017                 mncc->redirecting.type = 0x4;
1018                 break;
1019                 default: /* INFO_NTYPE_NOTPRESENT */
1020                 mncc->fields &= ~MNCC_F_REDIRECTING;
1021                 break;
1022         }
1023         switch (p_redirinfo.screen) {
1024                 case INFO_SCREEN_USER:
1025                 mncc->redirecting.screen = 0;
1026                 break;
1027                 default: /* INFO_SCREE_NETWORK */
1028                 mncc->redirecting.screen = 3;
1029                 break;
1030         }
1031         switch (p_redirinfo.present) {
1032                 case INFO_PRESENT_ALLOWED:
1033                 mncc->redirecting.present = 0;
1034                 break;
1035                 case INFO_PRESENT_RESTRICTED:
1036                 mncc->redirecting.present = 1;
1037                 break;
1038                 default: /* INFO_PRESENT_NOTAVAIL */
1039                 mncc->redirecting.present = 2;
1040                 break;
1041         }
1042         /* sending redirecting number only in ntmode */
1043         if (mncc->fields & MNCC_F_REDIRECTING) {
1044                 SCPY(mncc->redirecting.number, p_redirinfo.id);
1045                 add_trace("redir", "type", "%d", mncc->redirecting.type);
1046                 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
1047                 add_trace("redir", "present", "%d", mncc->redirecting.present);
1048                 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
1049                 add_trace("redir", "number", "%s", mncc->redirecting.number);
1050         }
1051
1052         if (interface->gsm_bs_hr) {
1053                 add_trace("lchan", "type", "TCH/H or TCH/F");
1054                 mncc->lchan_type = GSM_LCHAN_TCH_H;
1055         } else {
1056                 add_trace("lchan", "type", "TCH/F");
1057                 mncc->lchan_type = GSM_LCHAN_TCH_F;
1058         }
1059
1060         end_trace();
1061         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
1062
1063         new_state(PORT_STATE_OUT_SETUP);
1064
1065         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1066         message_put(message);
1067
1068         /* RTP bridge */
1069         if (param->setup.rtpinfo.port) {
1070                 p_g_rtp_bridge = 1;
1071                 p_g_rtp_ip_remote = param->setup.rtpinfo.ip;
1072                 p_g_rtp_port_remote = param->setup.rtpinfo.port;
1073         } else
1074                 p_g_rtp_bridge = 0;
1075 }
1076
1077 /*
1078  * endpoint sends messages to the port
1079  */
1080 int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1081 {
1082         if (Pgsm::message_epoint(epoint_id, message_id, param))
1083                 return(1);
1084
1085         switch(message_id) {
1086                 case MESSAGE_SETUP: /* dial-out command received from epoint */
1087                 if (p_state!=PORT_STATE_IDLE)
1088                         break;
1089                 message_setup(epoint_id, message_id, param);
1090                 break;
1091
1092                 default:
1093                 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
1094         }
1095
1096         return(1);
1097 }
1098
1099 int gsm_bs_exit(int rc)
1100 {
1101         /* destroy all instances */
1102         while (gsm_bs_first)
1103                 gsm_bs_delete(gsm_bs_first->name);
1104
1105         return rc;
1106 }
1107
1108 int gsm_bs_init(void)
1109 {
1110         return 0;
1111 }
1112
1113 /* add a new GSM base station instance */
1114 int gsm_bs_new(struct interface *interface)
1115 {
1116         struct lcr_gsm *gsm_bs = gsm_bs_first, **gsm_bs_p = &gsm_bs_first;
1117
1118         while (gsm_bs) {
1119                 gsm_bs_p = &gsm_bs->gsm_next;
1120                 gsm_bs = gsm_bs->gsm_next;
1121         }
1122
1123         PDEBUG(DEBUG_GSM, "GSM: interface for BS '%s' is created\n", interface->gsm_bs_name);
1124
1125         /* create gsm instance */
1126         gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1127
1128         SCPY(gsm_bs->interface_name, interface->name);
1129         gsm_bs->type = LCR_GSM_TYPE_NETWORK;
1130         SCPY(gsm_bs->name, interface->gsm_bs_name);
1131         gsm_bs->sun.sun_family = AF_UNIX;
1132         if (gsm_bs->name[0])
1133                 SPRINT(gsm_bs->sun.sun_path, "/tmp/bsc_mncc_%s", gsm_bs->name);
1134         else
1135                 SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
1136
1137         memset(&gsm_bs->socket_retry, 0, sizeof(gsm_bs->socket_retry));
1138         add_timer(&gsm_bs->socket_retry, mncc_socket_retry_cb, gsm_bs, 0);
1139
1140         /* do the initial connect */
1141         mncc_socket_retry_cb(&gsm_bs->socket_retry, gsm_bs, 0);
1142
1143         generate_dtmf();
1144
1145         *gsm_bs_p = gsm_bs;
1146
1147         return 0;
1148 }
1149
1150 int gsm_bs_delete(const char *name)
1151 {
1152         struct lcr_gsm *gsm_bs = gsm_bs_first, **gsm_bs_p = &gsm_bs_first;
1153
1154         PDEBUG(DEBUG_GSM, "GSM: interface for BS '%s' is deleted\n", name);
1155         
1156         while (gsm_bs) {
1157                 if (gsm_bs->type == LCR_GSM_TYPE_NETWORK && !strcmp(gsm_bs->name, name))
1158                         break;
1159                 gsm_bs_p = &gsm_bs->gsm_next;
1160                 gsm_bs = gsm_bs->gsm_next;
1161         }
1162
1163         if (!gsm_bs)
1164                 return 0;
1165         
1166         if (gsm_bs->mncc_lfd.fd > -1) {
1167                 close(gsm_bs->mncc_lfd.fd);
1168                 unregister_fd(&gsm_bs->mncc_lfd);
1169         }
1170         del_timer(&gsm_bs->socket_retry);
1171
1172         /* remove instance from list */
1173         *gsm_bs_p = gsm_bs->gsm_next;
1174         FREE(gsm_bs, sizeof(struct lcr_gsm));
1175
1176         return 0;
1177 }
1178