Splitted GSM support into BS (network) and MS (mobile) part.
[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
14 #ifndef _GNU_SOURCE
15 #define _GNU_SOURCE
16 #endif
17 extern "C" {
18 #include <getopt.h>
19
20 #include <openbsc/db.h>
21 #include <osmocore/select.h>
22 #include <openbsc/debug.h>
23 #include <openbsc/e1_input.h>
24 #include <osmocore/talloc.h>
25 #include <openbsc/mncc.h>
26 #include <openbsc/trau_frame.h>
27 struct gsm_network *bsc_gsmnet = 0;
28 extern int ipacc_rtp_direct;
29 extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
30                                  const char *cfg_file);
31 extern int bsc_shutdown_net(struct gsm_network *net);
32 void talloc_ctx_init(void);
33 void on_dso_load_token(void);
34 void on_dso_load_rrlp(void);
35 void on_dso_load_ho_dec(void);
36 int bts_model_unknown_init(void);
37 int bts_model_bs11_init(void);
38 int bts_model_nanobts_init(void);
39 static struct log_target *stderr_target;
40
41 /* timer to store statistics */
42 #define DB_SYNC_INTERVAL        60, 0
43 static struct timer_list db_sync_timer;
44 }
45
46 /* timer handling */
47 static int _db_store_counter(struct counter *counter, void *data)
48 {
49         return db_store_counter(counter);
50 }
51
52 static void db_sync_timer_cb(void *data)
53 {
54         /* store counters to database and re-schedule */
55         counters_for_each(_db_store_counter, NULL);
56         bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
57 }
58
59 /*
60  * constructor
61  */
62 Pgsm_bs::Pgsm_bs(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
63 {
64         p_m_g_instance = gsm->network;
65         PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
66 }
67
68 /*
69  * destructor
70  */
71 Pgsm_bs::~Pgsm_bs()
72 {
73         PDEBUG(DEBUG_GSM, "Destroyed GSM BS process(%s).\n", p_name);
74 }
75
76 /* DTMF INDICATION */
77 void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
78 {
79         struct lcr_msg *message;
80         struct gsm_mncc *resp;
81
82         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
83         add_trace("keypad", NULL, "%c", mncc->keypad);
84         end_trace();
85         SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
86         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
87
88         /* send resp */
89         gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
90         add_trace("keypad", NULL, "%c", mncc->keypad);
91         end_trace();
92         resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
93         resp->keypad = mncc->keypad;
94         send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
95
96         /* send dialing information */
97         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
98         memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
99         message_put(message);
100 }
101 void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
102 {
103         struct gsm_mncc *resp;
104
105         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
106         add_trace("keypad", NULL, "%c", mncc->keypad);
107         end_trace();
108
109         /* send resp */
110         gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
111         add_trace("keypad", NULL, "%c", mncc->keypad);
112         end_trace();
113         resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
114         resp->keypad = mncc->keypad;
115         send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
116 }
117
118 /* HOLD INDICATION */
119 void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
120 {
121         struct lcr_msg *message;
122         struct gsm_mncc *resp, *frame;
123
124         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
125         end_trace();
126
127         /* notify the hold of call */
128         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
129         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
130         message->param.notifyinfo.local = 1; /* call is held by supplementary service */
131         message_put(message);
132
133         /* acknowledge hold */
134         gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
135         end_trace();
136         resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
137         send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
138
139         /* disable audio */
140         if (p_m_g_tch_connected) { /* it should be true */
141                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
142                 end_trace();
143                 frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
144                 send_and_free_mncc(p_m_g_instance, frame->msg_type, frame);
145                 p_m_g_tch_connected = 0;
146         }
147 }
148
149
150 /* RETRIEVE INDICATION */
151 void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
152 {
153         struct lcr_msg *message;
154         struct gsm_mncc *resp, *frame;
155
156         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
157         end_trace();
158
159         /* notify the retrieve of call */
160         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
161         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
162         message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
163         message_put(message);
164
165         /* acknowledge retr */
166         gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
167         end_trace();
168         resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
169         send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
170
171         /* enable audio */
172         if (!p_m_g_tch_connected) { /* it should be true */
173                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
174                 end_trace();
175                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
176                 send_and_free_mncc(p_m_g_instance, frame->msg_type, frame);
177                 p_m_g_tch_connected = 1;
178         }
179 }
180
181 /*
182  * handles all indications
183  */
184 /* SETUP INDICATION */
185 void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
186 {
187         int ret;
188         class Endpoint *epoint;
189         struct lcr_msg *message;
190         int channel;
191         struct gsm_mncc *mode, *proceeding, *frame;
192
193         /* process given callref */
194         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
195         add_trace("callref", "new", "0x%x", callref);
196         if (p_m_g_callref) {
197                 /* release in case the ID is already in use */
198                 add_trace("error", NULL, "callref already in use");
199                 end_trace();
200                 mncc = create_mncc(MNCC_REJ_REQ, callref);
201                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
202                 mncc->fields |= MNCC_F_CAUSE;
203                 mncc->cause.coding = 3;
204                 mncc->cause.location = 1;
205                 mncc->cause.value = 47;
206                 add_trace("cause", "coding", "%d", mncc->cause.coding);
207                 add_trace("cause", "location", "%d", mncc->cause.location);
208                 add_trace("cause", "value", "%d", mncc->cause.value);
209                 add_trace("reason", NULL, "callref already in use");
210                 end_trace();
211                 send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
212                 new_state(PORT_STATE_RELEASE);
213                 trigger_work(&p_m_g_delete);
214                 return;
215         }
216         p_m_g_callref = callref;
217         end_trace();
218
219         /* if blocked, release call with MT_RELEASE_COMPLETE */
220         if (p_m_mISDNport->ifport->block) {
221                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
222                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
223                 mncc->fields |= MNCC_F_CAUSE;
224                 mncc->cause.coding = 3;
225                 mncc->cause.location = 1;
226                 mncc->cause.value = 27;
227                 add_trace("cause", "coding", "%d", mncc->cause.coding);
228                 add_trace("cause", "location", "%d", mncc->cause.location);
229                 add_trace("cause", "value", "%d", mncc->cause.value);
230                 add_trace("reason", NULL, "port is blocked");
231                 end_trace();
232                 send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
233                 new_state(PORT_STATE_RELEASE);
234                 trigger_work(&p_m_g_delete);
235                 return;
236         }
237
238         /* caller info */
239         if (mncc->clir.inv)
240                 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
241         else
242                 p_callerinfo.present = INFO_PRESENT_ALLOWED;
243         if (mncc->calling.number[0])
244                 SCPY(p_callerinfo.id, mncc->calling.number);
245         else
246                 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
247         SCPY(p_callerinfo.imsi, mncc->imsi);
248         p_callerinfo.screen = INFO_SCREEN_NETWORK;
249         p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
250         p_callerinfo.isdn_port = p_m_portnum;
251         SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
252
253         /* dialing information */
254         SCAT(p_dialinginfo.id, mncc->called.number);
255         switch (mncc->called.type) {
256                 case 0x1:
257                 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
258                 break;
259                 case 0x2:
260                 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
261                 break;
262                 case 0x4:
263                 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
264                 break;
265                 default:
266                 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
267                 break;
268         }
269         if (mncc->emergency) {
270                 SCPY(p_dialinginfo.id, "emergency");
271         }
272         p_dialinginfo.sending_complete = 1;
273
274         /* bearer capability */
275         // todo
276         p_capainfo.bearer_capa = INFO_BC_SPEECH;
277         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
278         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
279         p_capainfo.source_mode = B_MODE_TRANSPARENT;
280         p_m_g_mode = p_capainfo.source_mode;
281
282         /* useruser */
283
284         /* hunt channel */
285         ret = channel = hunt_bchannel();
286         if (ret < 0)
287                 goto no_channel;
288
289         /* open channel */
290         ret = seize_bchannel(channel, 1);
291         if (ret < 0) {
292                 no_channel:
293                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
294                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
295                 mncc->fields |= MNCC_F_CAUSE;
296                 mncc->cause.coding = 3;
297                 mncc->cause.location = 1;
298                 mncc->cause.value = 34;
299                 add_trace("cause", "coding", "%d", mncc->cause.coding);
300                 add_trace("cause", "location", "%d", mncc->cause.location);
301                 add_trace("cause", "value", "%d", mncc->cause.value);
302                 add_trace("reason", NULL, "no channel");
303                 end_trace();
304                 send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
305                 new_state(PORT_STATE_RELEASE);
306                 trigger_work(&p_m_g_delete);
307                 return;
308         }
309         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
310         if (bchannel_open(p_m_b_index))
311                 goto no_channel;
312
313         /* what infos did we got ... */
314         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
315         if (p_callerinfo.id[0])
316                 add_trace("calling", "number", "%s", p_callerinfo.id);
317         else
318                 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
319         add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
320         add_trace("dialing", "number", "%s", p_dialinginfo.id);
321         end_trace();
322
323         /* create endpoint */
324         if (p_epointlist)
325                 FATAL("Incoming call but already got an endpoint.\n");
326         if (!(epoint = new Endpoint(p_serial, 0)))
327                 FATAL("No memory for Endpoint instance\n");
328         if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
329                 FATAL("No memory for Endpoint Application instance\n");
330         epointlist_new(epoint->ep_serial);
331
332         /* modify lchan to GSM codec V1 */
333         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
334         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
335         mode->lchan_mode = 0x01; /* GSM V1 */
336         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
337         end_trace();
338         send_and_free_mncc(p_m_g_instance, mode->msg_type, mode);
339
340         /* send call proceeding */
341         gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
342         proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
343         if (p_m_mISDNport->tones) {
344                 proceeding->fields |= MNCC_F_PROGRESS;
345                 proceeding->progress.coding = 3; /* GSM */
346                 proceeding->progress.location = 1;
347                 proceeding->progress.descr = 8;
348                 add_trace("progress", "coding", "%d", proceeding->progress.coding);
349                 add_trace("progress", "location", "%d", proceeding->progress.location);
350                 add_trace("progress", "descr", "%d", proceeding->progress.descr);
351         }
352         end_trace();
353         send_and_free_mncc(p_m_g_instance, proceeding->msg_type, proceeding);
354
355         new_state(PORT_STATE_IN_PROCEEDING);
356
357         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
358                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
359                 end_trace();
360                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
361                 send_and_free_mncc(p_m_g_instance, frame->msg_type, frame);
362                 p_m_g_tch_connected = 1;
363         }
364
365         /* send setup message to endpoit */
366         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
367         message->param.setup.isdn_port = p_m_portnum;
368         message->param.setup.port_type = p_type;
369 //      message->param.setup.dtmf = 0;
370         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
371         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
372         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
373         SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
374         message->param.setup.useruser.len = strlen(mncc->useruser.info);
375         message->param.setup.useruser.protocol = mncc->useruser.proto;
376         message_put(message);
377 }
378
379 /*
380  * BSC sends message to port
381  */
382 static int message_bsc(struct gsm_network *net, int msg_type, void *arg)
383 {
384         struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
385         unsigned int callref = mncc->callref;
386         class Port *port;
387         class Pgsm_bs *pgsm_bs = NULL;
388         char name[64];
389         struct mISDNport *mISDNport;
390
391         /* Special messages */
392         switch(msg_type) {
393         }
394
395         /* find callref */
396         callref = mncc->callref;
397         port = port_first;
398         while(port) {
399                 if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
400                         pgsm_bs = (class Pgsm_bs *)port;
401                         if (pgsm_bs->p_m_g_callref == callref) {
402                                 break;
403                         }
404                 }
405                 port = port->next;
406         }
407
408         if (msg_type == GSM_TCHF_FRAME) {
409                 if (port)
410                         pgsm_bs->frame_receive((struct gsm_trau_frame *)arg);
411                 return 0;
412         }
413
414         if (!port) {
415                 if (msg_type != MNCC_SETUP_IND)
416                         return(0);
417                 /* find gsm port */
418                 mISDNport = mISDNport_first;
419                 while(mISDNport) {
420                         if (mISDNport->gsm_bs)
421                                 break;
422                         mISDNport = mISDNport->next;
423                 }
424                 if (!mISDNport) {
425                         struct gsm_mncc *rej;
426
427                         rej = create_mncc(MNCC_REJ_REQ, callref);
428                         rej->fields |= MNCC_F_CAUSE;
429                         rej->cause.coding = 3;
430                         rej->cause.location = 1;
431                         rej->cause.value = 27;
432                         gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
433                         add_trace("cause", "coding", "%d", rej->cause.coding);
434                         add_trace("cause", "location", "%d", rej->cause.location);
435                         add_trace("cause", "value", "%d", rej->cause.value);
436                         end_trace();
437                         send_and_free_mncc(gsm->network, rej->msg_type, rej);
438                         return 0;
439                 }
440                 /* creating port object, transparent until setup with hdlc */
441                 SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
442                 if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
443
444                         FATAL("Cannot create Port instance.\n");
445         }
446
447         switch(msg_type) {
448                 case MNCC_SETUP_IND:
449                 pgsm_bs->setup_ind(msg_type, callref, mncc);
450                 break;
451
452                 case MNCC_START_DTMF_IND:
453                 pgsm_bs->start_dtmf_ind(msg_type, callref, mncc);
454                 break;
455
456                 case MNCC_STOP_DTMF_IND:
457                 pgsm_bs->stop_dtmf_ind(msg_type, callref, mncc);
458                 break;
459
460                 case MNCC_CALL_CONF_IND:
461                 pgsm_bs->call_conf_ind(msg_type, callref, mncc);
462                 break;
463
464                 case MNCC_ALERT_IND:
465                 pgsm_bs->alert_ind(msg_type, callref, mncc);
466                 break;
467
468                 case MNCC_SETUP_CNF:
469                 pgsm_bs->setup_cnf(msg_type, callref, mncc);
470                 break;
471
472                 case MNCC_SETUP_COMPL_IND:
473                 pgsm_bs->setup_compl_ind(msg_type, callref, mncc);
474                 break;
475
476                 case MNCC_DISC_IND:
477                 pgsm_bs->disc_ind(msg_type, callref, mncc);
478                 break;
479
480                 case MNCC_REL_IND:
481                 case MNCC_REL_CNF:
482                 case MNCC_REJ_IND:
483                 pgsm_bs->rel_ind(msg_type, callref, mncc);
484                 break;
485
486                 case MNCC_NOTIFY_IND:
487                 pgsm_bs->notify_ind(msg_type, callref, mncc);
488                 break;
489
490                 case MNCC_HOLD_IND:
491                 pgsm_bs->hold_ind(msg_type, callref, mncc);
492                 break;
493
494                 case MNCC_RETRIEVE_IND:
495                 pgsm_bs->retr_ind(msg_type, callref, mncc);
496                 break;
497
498                 default:
499                 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);
500         }
501         return(0);
502 }
503
504 /* MESSAGE_SETUP */
505 void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
506 {
507         struct lcr_msg *message;
508         int ret;
509         struct epoint_list *epointlist;
510         struct gsm_mncc *mncc;
511         int channel;
512
513         /* copy setup infos to port */
514         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
515         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
516         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
517         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
518
519         /* no number */
520         if (!p_dialinginfo.id[0]) {
521                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
522                 add_trace("failure", NULL, "No dialed subscriber given.");
523                 end_trace();
524                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
525                 message->param.disconnectinfo.cause = 28;
526                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
527                 message_put(message);
528                 new_state(PORT_STATE_RELEASE);
529                 trigger_work(&p_m_g_delete);
530                 return;
531         }
532         
533         /* release if port is blocked */
534         if (p_m_mISDNport->ifport->block) {
535                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
536                 add_trace("failure", NULL, "Port blocked.");
537                 end_trace();
538                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
539                 message->param.disconnectinfo.cause = 27; // temp. unavail.
540                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
541                 message_put(message);
542                 new_state(PORT_STATE_RELEASE);
543                 trigger_work(&p_m_g_delete);
544                 return;
545         }
546
547         /* hunt channel */
548         ret = channel = hunt_bchannel();
549         if (ret < 0)
550                 goto no_channel;
551         /* open channel */
552         ret = seize_bchannel(channel, 1);
553         if (ret < 0) {
554                 no_channel:
555                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
556                 add_trace("failure", NULL, "No internal audio channel available.");
557                 end_trace();
558                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
559                 message->param.disconnectinfo.cause = 34;
560                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
561                 message_put(message);
562                 new_state(PORT_STATE_RELEASE);
563                 trigger_work(&p_m_g_delete);
564                 return;
565         }
566         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
567         if (bchannel_open(p_m_b_index))
568                 goto no_channel;
569
570 //              SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
571         /* screen outgoing caller id */
572         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
573
574         /* attach only if not already */
575         epointlist = p_epointlist;
576         while(epointlist) {
577                 if (epointlist->epoint_id == epoint_id)
578                         break;
579                 epointlist = epointlist->next;
580         }
581         if (!epointlist)
582                 epointlist_new(epoint_id);
583
584         /* creating l3id */
585         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
586         p_m_g_callref = new_callref++;
587         add_trace("callref", "new", "0x%x", p_m_g_callref);
588         end_trace();
589
590         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
591         mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
592         /* caller information */
593         mncc->fields |= MNCC_F_CALLING;
594         mncc->calling.plan = 1;
595         switch (p_callerinfo.ntype) {
596                 case INFO_NTYPE_UNKNOWN:
597                 mncc->calling.type = 0x0;
598                 break;
599                 case INFO_NTYPE_INTERNATIONAL:
600                 mncc->calling.type = 0x1;
601                 break;
602                 case INFO_NTYPE_NATIONAL:
603                 mncc->calling.type = 0x2;
604                 break;
605                 case INFO_NTYPE_SUBSCRIBER:
606                 mncc->calling.type = 0x4;
607                 break;
608                 default: /* INFO_NTYPE_NOTPRESENT */
609                 mncc->fields &= ~MNCC_F_CALLING;
610                 break;
611         }
612         switch (p_callerinfo.screen) {
613                 case INFO_SCREEN_USER:
614                 mncc->calling.screen = 0;
615                 break;
616                 default: /* INFO_SCREEN_NETWORK */
617                 mncc->calling.screen = 3;
618                 break;
619         }
620         switch (p_callerinfo.present) {
621                 case INFO_PRESENT_ALLOWED:
622                 mncc->calling.present = 0;
623                 break;
624                 case INFO_PRESENT_RESTRICTED:
625                 mncc->calling.present = 1;
626                 break;
627                 default: /* INFO_PRESENT_NOTAVAIL */
628                 mncc->calling.present = 2;
629                 break;
630         }
631         if (mncc->fields & MNCC_F_CALLING) {
632                 SCPY(mncc->calling.number, p_callerinfo.id);
633                 add_trace("calling", "type", "%d", mncc->calling.type);
634                 add_trace("calling", "plan", "%d", mncc->calling.plan);
635                 add_trace("calling", "present", "%d", mncc->calling.present);
636                 add_trace("calling", "screen", "%d", mncc->calling.screen);
637                 add_trace("calling", "number", "%s", mncc->calling.number);
638         }
639         /* dialing information */
640         mncc->fields |= MNCC_F_CALLED;
641         if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
642                 SCPY(mncc->imsi, p_dialinginfo.id+5);
643                 add_trace("dialing", "imsi", "%s", mncc->imsi);
644         } else {
645                 SCPY(mncc->called.number, p_dialinginfo.id);
646                 add_trace("dialing", "number", "%s", mncc->called.number);
647         }
648         
649         /* sending user-user */
650
651         /* redirecting number */
652         mncc->fields |= MNCC_F_REDIRECTING;
653         mncc->redirecting.plan = 1;
654         switch (p_redirinfo.ntype) {
655                 case INFO_NTYPE_UNKNOWN:
656                 mncc->redirecting.type = 0x0;
657                 break;
658                 case INFO_NTYPE_INTERNATIONAL:
659                 mncc->redirecting.type = 0x1;
660                 break;
661                 case INFO_NTYPE_NATIONAL:
662                 mncc->redirecting.type = 0x2;
663                 break;
664                 case INFO_NTYPE_SUBSCRIBER:
665                 mncc->redirecting.type = 0x4;
666                 break;
667                 default: /* INFO_NTYPE_NOTPRESENT */
668                 mncc->fields &= ~MNCC_F_REDIRECTING;
669                 break;
670         }
671         switch (p_redirinfo.screen) {
672                 case INFO_SCREEN_USER:
673                 mncc->redirecting.screen = 0;
674                 break;
675                 default: /* INFO_SCREE_NETWORK */
676                 mncc->redirecting.screen = 3;
677                 break;
678         }
679         switch (p_redirinfo.present) {
680                 case INFO_PRESENT_ALLOWED:
681                 mncc->redirecting.present = 0;
682                 break;
683                 case INFO_PRESENT_RESTRICTED:
684                 mncc->redirecting.present = 1;
685                 break;
686                 default: /* INFO_PRESENT_NOTAVAIL */
687                 mncc->redirecting.present = 2;
688                 break;
689         }
690         /* sending redirecting number only in ntmode */
691         if (mncc->fields & MNCC_F_REDIRECTING) {
692                 SCPY(mncc->redirecting.number, p_redirinfo.id);
693                 add_trace("redir", "type", "%d", mncc->redirecting.type);
694                 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
695                 add_trace("redir", "present", "%d", mncc->redirecting.present);
696                 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
697                 add_trace("redir", "number", "%s", mncc->redirecting.number);
698         }
699         /* bearer capability */
700         //todo
701
702         end_trace();
703         send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
704
705         new_state(PORT_STATE_OUT_SETUP);
706
707         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
708         message_put(message);
709
710         new_state(PORT_STATE_OUT_PROCEEDING);
711 }
712
713 /*
714  * endpoint sends messages to the port
715  */
716 int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
717 {
718         if (Pgsm::message_epoint(epoint_id, message_id, param))
719                 return(1);
720
721         switch(message_id) {
722                 case MESSAGE_SETUP: /* dial-out command received from epoint */
723                 if (p_state!=PORT_STATE_IDLE)
724                         break;
725                 message_setup(epoint_id, message_id, param);
726                 break;
727
728                 default:
729                 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
730         }
731
732         return(1);
733 }
734
735 int gsm_bs_exit(int rc)
736 {
737         /* free gsm instance */
738         if (gsm) {
739                 /* shutdown network */
740                 if (gsm->network)
741                         bsc_shutdown_net((struct gsm_network *)gsm->network);
742                 /* free network */
743 //              if (gsm->network) {
744 //                      free((struct gsm_network *)gsm->network); /* TBD */
745 //              }
746         }
747
748         return(rc);
749 }
750
751 int gsm_bs_init(void)
752 {
753         char hlr[128], cfg[128], filename[128];
754         mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
755         int pcapfd, rc;
756
757         log_init(&log_info);
758         tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
759         talloc_ctx_init();
760         on_dso_load_token();
761         on_dso_load_rrlp();
762         on_dso_load_ho_dec();
763         stderr_target = log_target_create_stderr();
764         log_add_target(stderr_target);
765
766         bts_model_unknown_init();
767         bts_model_bs11_init();
768         bts_model_nanobts_init();
769
770         /* enable filters */
771         log_set_all_filter(stderr_target, 1);
772
773         /* set debug */
774         if (gsm->conf.debug[0])
775                 log_parse_category_mask(stderr_target, gsm->conf.debug);
776
777         /* open pcap file */
778         if (gsm->conf.pcapfile[0]) {
779                 if (gsm->conf.pcapfile[0] == '/')
780                         SCPY(filename, gsm->conf.pcapfile);
781                 else
782                         SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile);
783                 pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
784                 if (pcapfd < 0) {
785                         PERROR("Failed to open file for pcap\n");
786                         return gsm_exit(-1);
787                 }
788                 e1_set_pcap_fd(pcapfd);
789         }
790
791         /* use RTP proxy for audio streaming */
792         ipacc_rtp_direct = 0;
793
794         /* init database */
795         if (gsm->conf.hlr[0] == '/')
796                 SCPY(hlr, gsm->conf.hlr);
797         else
798                 SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
799         if (db_init(hlr)) {
800                 PERROR("GSM DB: Failed to init database '%s'. Please check the option settings.\n", hlr);
801                 return gsm_exit(-1);
802         }
803         printf("DB: Database initialized.\n");
804         if (db_prepare()) {
805                 PERROR("GSM DB: Failed to prepare database.\n");
806                 return gsm_exit(-1);
807         }
808         printf("DB: Database prepared.\n");
809
810         /* setup the timer */
811         db_sync_timer.cb = db_sync_timer_cb;
812         db_sync_timer.data = NULL;
813         bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
814
815         /* bootstrap network */
816         if (gsm->conf.openbsc_cfg[0] == '/')
817                 SCPY(cfg, gsm->conf.openbsc_cfg);
818         else
819                 SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg);
820         rc = bsc_bootstrap_network(&message_bsc, cfg);
821         if (rc < 0) {
822                 PERROR("Failed to bootstrap GSM network.\n");
823                 return gsm_exit(-1);
824         }
825         gsm->network = bsc_gsmnet;
826
827         return 0;
828 }
829
830 /*
831  * handles bsc select function within LCR's main loop
832  */
833 int handle_gsm_bs(void)
834 {
835         int ret1, ret2;
836
837         ret1 = bsc_upqueue((struct gsm_network *)gsm->network);
838         log_reset_context();
839         ret2 = bsc_select_main(1); /* polling */
840         if (ret1 || ret2)
841                 return 1;
842         return 0;
843 }
844