Kannel: Open Source WAP and SMS gateway  svn-r5335
wapbox.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * wapbox.c - main program for wapbox
59  *
60  * This module contains the main program for the WAP box of the WAP gateway.
61  * See the architecture documentation for details.
62  */
63 
64 #include <stdlib.h>
65 #include <time.h>
66 #include <unistd.h>
67 #include <signal.h>
68 
69 #include "gwlib/gwlib.h"
70 #include "shared.h"
71 #include "wml_compiler.h"
72 #include "heartbeat.h"
73 #include "wap/wap.h"
74 #include "wap-appl.h"
75 #include "wap-maps.h"
76 #include "wap_push_ota.h"
77 #include "wap_push_ppg.h"
78 #include "gw/msg.h"
79 #include "bb.h"
80 #include "sms.h"
81 #ifdef HAVE_WTLS_OPENSSL
82 #include <openssl/x509.h>
83 #include "wap/wtls.h"
84 #include "gwlib/pki.h"
85 #endif
86 #include "radius/radius_acct.h"
87 
88 static void config_reload(int reload);
89 static long logfilelevel=-1;
90 
91 enum {
96 };
97 
98 enum { DEFAULT_TIMER_FREQ = 1};
99 
102 static int bearerbox_ssl = 0;
103 static Counter *sequence_counter = NULL;
106 
107 /* use strict XML parsing or relaxed */
108 static int wml_xml_strict = 1;
109 
110 /* smart error messaging related globals */
113 
114 /* Controlling segmentation of sms messages sent by wapbox (push related).*/
116 long max_messages = 10;
117 
118 #ifdef HAVE_WTLS_OPENSSL
119 extern RSA* private_key;
120 extern X509* x509_cert;
121 extern void wtls_secmgr_init();
122 #endif
123 
125 {
126  CfgGroup *grp;
127  Octstr *s;
128  Octstr *logfile;
129  int lf, m;
130  long value;
131 
132  lf = m = 1;
133 
134  cfg_dump(cfg);
135 
136  /*
137  * Extract info from the core group.
138  */
139  grp = cfg_get_single_group(cfg, octstr_imm("core"));
140  if (grp == NULL)
141  panic(0, "No 'core' group in configuration.");
142 
143  if (cfg_get_integer(&bearerbox_port,grp,octstr_imm("wapbox-port")) == -1)
144  panic(0, "No 'wapbox-port' in core group");
145 #ifdef HAVE_LIBSSL
146  cfg_get_bool(&bearerbox_ssl, grp, octstr_imm("wapbox-port-ssl"));
147 #endif /* HAVE_LIBSSL */
148 
149  /* load parameters that could be later reloaded */
150  config_reload(0);
151 
152  conn_config_ssl(grp);
153 
154  /*
155  * And the rest of the pull info comes from the wapbox group.
156  */
157  grp = cfg_get_single_group(cfg, octstr_imm("wapbox"));
158  if (grp == NULL)
159  panic(0, "No 'wapbox' group in configuration.");
160 
161  bearerbox_host = cfg_get(grp, octstr_imm("bearerbox-host"));
162  if (cfg_get_integer(&timer_freq, grp, octstr_imm("timer-freq")) == -1)
164 
165  logfile = cfg_get(grp, octstr_imm("log-file"));
166  if (logfile != NULL) {
168  info(0, "Starting to log to file %s level %ld",
169  octstr_get_cstr(logfile), logfilelevel);
170  }
171  octstr_destroy(logfile);
172 
173  if ((s = cfg_get(grp, octstr_imm("syslog-level"))) != NULL) {
174  long level;
175  Octstr *facility;
176  if ((facility = cfg_get(grp, octstr_imm("syslog-facility"))) != NULL) {
178  octstr_destroy(facility);
179  }
180  if (octstr_compare(s, octstr_imm("none")) == 0) {
181  log_set_syslog(NULL, 0);
182  debug("wap", 0, "syslog parameter is none");
183  } else if (octstr_parse_long(&level, s, 0, 10) > 0) {
184  log_set_syslog("wapbox", level);
185  debug("wap", 0, "syslog parameter is %ld", level);
186  }
187  octstr_destroy(s);
188  } else {
189  log_set_syslog(NULL, 0);
190  debug("wap", 0, "no syslog parameter");
191  }
192 
193  /* determine which timezone we use for access logging */
194  if ((s = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) {
195  lf = (octstr_case_compare(s, octstr_imm("gmt")) == 0) ? 0 : 1;
196  octstr_destroy(s);
197  }
198 
199  /* should predefined markers be used, ie. prefixing timestamp */
200  cfg_get_bool(&m, grp, octstr_imm("access-log-clean"));
201 
202  /* open access-log file */
203  if ((s = cfg_get(grp, octstr_imm("access-log"))) != NULL) {
204  info(0, "Logging accesses to '%s'.", octstr_get_cstr(s));
205  alog_open(octstr_get_cstr(s), lf, m ? 0 : 1);
206  octstr_destroy(s);
207  }
208 
209  if (cfg_get_integer(&value, grp, octstr_imm("http-timeout")) == 0)
211 
212  /* configure the 'wtls' group */
213 #if (HAVE_WTLS_OPENSSL)
214  /* Load up the necessary keys */
215  grp = cfg_get_single_group(cfg, octstr_imm("wtls"));
216 
217  if (grp != NULL) {
218  if ((s = cfg_get(grp, octstr_imm("certificate-file"))) != NULL) {
219  if (octstr_compare(s, octstr_imm("none")) == 0) {
220  debug("bbox", 0, "certificate file not set");
221  } else {
222  /* Load the certificate into the necessary parameter */
223  get_cert_from_file(s, &x509_cert);
224  gw_assert(x509_cert != NULL);
225  debug("bbox", 0, "certificate parameter is %s",
226  octstr_get_cstr(s));
227  }
228  octstr_destroy(s);
229  } else
230  panic(0, "No 'certificate-file' in wtls group");
231 
232  if ((s = cfg_get(grp, octstr_imm("privatekey-file"))) != NULL) {
233  Octstr *password;
234  password = cfg_get(grp, octstr_imm("privatekey-password"));
235  if (octstr_compare(s, octstr_imm("none")) == 0) {
236  debug("bbox", 0, "privatekey-file not set");
237  } else {
238  /* Load the private key into the necessary parameter */
239  get_privkey_from_file(s, &private_key, password);
240  gw_assert(private_key != NULL);
241  debug("bbox", 0, "certificate parameter is %s",
242  octstr_get_cstr(s));
243  }
244  if (password != NULL)
246  octstr_destroy(s);
247  } else
248  panic(0, "No 'privatekey-file' in wtls group");
249  }
250 #endif
251 
252  /*
253  * Check if we have a 'radius-acct' proxy group and start the
254  * corresponding thread for the proxy.
255  */
256  grp = cfg_get_single_group(cfg, octstr_imm("radius-acct"));
257  if (grp) {
258  radius_acct_init(grp);
259  }
260 
261  /*
262  * We pass ppg configuration groups to the ppg module.
263  */
264  grp = cfg_get_single_group(cfg, octstr_imm("ppg"));
265  if (grp == NULL) {
266  cfg_destroy(cfg);
267  return NULL;
268  }
269 
270  return cfg;
271 }
272 
273 
274 static void signal_handler(int signum)
275 {
276  /*
277  * On some implementations (i.e. linuxthreads), signals are delivered
278  * to all threads. We only want to handle each signal once for the
279  * entire box, and we let the gwthread wrapper take care of choosing
280  * one. */
281  if (!gwthread_shouldhandlesignal(signum))
282  return;
283 
284  switch (signum) {
285  case SIGINT:
286  case SIGTERM:
287  if (program_status != shutting_down) {
288  error(0, "SIGINT or SIGTERM received, let's die.");
290  break;
291  }
292  break;
293 
294  case SIGHUP:
295  warning(0, "SIGHUP received, catching and re-opening logs");
296  config_reload(1);
297  log_reopen();
298  alog_reopen();
299  break;
300 
301  /*
302  * It would be more proper to use SIGUSR1 for this, but on some
303  * platforms that's reserved by the pthread support.
304  */
305  case SIGQUIT:
306  warning(0, "SIGQUIT received, reporting memory usage.");
307  gw_check_leaks();
308  break;
309  }
310 }
311 
312 
313 static void setup_signal_handlers(void)
314 {
315  struct sigaction act;
316 
317  act.sa_handler = signal_handler;
318  sigemptyset(&act.sa_mask);
319  act.sa_flags = 0;
320  sigaction(SIGINT, &act, NULL);
321  sigaction(SIGQUIT, &act, NULL);
322  sigaction(SIGHUP, &act, NULL);
323  sigaction(SIGPIPE, &act, NULL);
324 }
325 
326 /*
327  * We create wdp_datagram for IP traffic and sms for SMS traffic.
328  */
330 {
331  Msg *msg;
332  WAPAddrTuple *tuple;
333 
334  msg = msg_create(wdp_datagram);
335  tuple = dgram->u.T_DUnitdata_Req.addr_tuple;
336  msg->wdp_datagram.source_address =
337  octstr_duplicate(tuple->local->address);
338  msg->wdp_datagram.source_port =
339  dgram->u.T_DUnitdata_Req.addr_tuple->local->port;
340  msg->wdp_datagram.destination_address =
342  msg->wdp_datagram.destination_port =
343  dgram->u.T_DUnitdata_Req.addr_tuple->remote->port;
344  msg->wdp_datagram.user_data =
345  octstr_duplicate(dgram->u.T_DUnitdata_Req.user_data);
346 
347  return msg;
348 }
349 
350 /*
351  * Format for port UDH is defined in wdp, appendix A. It is %06%05%04
352  * %dest port high hex%dest port low%hex source port high hex%source port low
353  * hex. (Unsecure) push client port itself is 2948.
354  */
356 {
357  int source_port,
358  dest_port;
359  Octstr *udh;
360 
361  source_port = tuple->local->port;
362  dest_port = tuple->remote->port;
363 
364  udh = octstr_create("");
365  octstr_format_append(udh, "%c", 6);
366  octstr_format_append(udh, "%c", 5);
367  octstr_format_append(udh, "%c", 4);
368  octstr_format_append(udh, "%c", (dest_port >> 8) & 0xff);
369  octstr_format_append(udh, "%c", dest_port & 0xff);
370  octstr_format_append(udh, "%c", (source_port >> 8) & 0xff);
371  octstr_format_append(udh, "%c", source_port & 0xff);
372 
373  return udh;
374 }
375 
376 /*
377  * We send a normal 8-bit unconcatenated binary message with an udh. Caller
378  * must do segmentation before calling this function.
379  *
380  * Note: we have hardcoded validity period here. We must eventually use push
381  * control document to fill this field.
382  */
384 {
385  Msg *msg;
386  WAPAddrTuple *tuple;
387 
388  msg = msg_create(sms);
389  tuple = dgram->u.T_DUnitdata_Req.addr_tuple;
390  msg->sms.sender = octstr_duplicate(tuple->local->address);
391  msg->sms.receiver = octstr_duplicate(tuple->remote->address);
392  msg->sms.udhdata = pack_udhdata(tuple);
393  msg->sms.msgdata = octstr_duplicate(dgram->u.T_DUnitdata_Req.user_data);
394  msg->sms.time = time(NULL);
395  if (dgram->u.T_DUnitdata_Req.smsc_id != NULL)
396  msg->sms.smsc_id = octstr_duplicate(dgram->u.T_DUnitdata_Req.smsc_id);
397  else
398  msg->sms.smsc_id = NULL;
399  msg->sms.dlr_mask = dgram->u.T_DUnitdata_Req.dlr_mask;
400  if (dgram->u.T_DUnitdata_Req.smsbox_id != NULL)
401  msg->sms.boxc_id = octstr_duplicate(dgram->u.T_DUnitdata_Req.smsbox_id);
402  else
403  msg->sms.boxc_id = NULL;
404  if (dgram->u.T_DUnitdata_Req.dlr_url != NULL)
405  msg->sms.dlr_url = octstr_duplicate(dgram->u.T_DUnitdata_Req.dlr_url);
406  else
407  msg->sms.dlr_url = NULL;
408  msg->sms.sms_type = mt_push;
409  msg->sms.mwi = MWI_UNDEF;
410  msg->sms.coding = DC_8BIT;
411  msg->sms.mclass = MC_UNDEF;
412  msg->sms.validity = time(NULL) + 1440;
413  msg->sms.deferred = SMS_PARAM_UNDEFINED;
414  if (dgram->u.T_DUnitdata_Req.service_name != NULL)
415  msg->sms.service = octstr_duplicate(dgram->u.T_DUnitdata_Req.service_name);
416 
417  return msg;
418 }
419 
420 /*
421  * Possible address types
422  */
423 
424 enum {
430 };
431 
432 /*
433  * Send IP datagram as it is, segment SMS datagram if necessary.
434  */
435 static void dispatch_datagram(WAPEvent *dgram)
436 {
437  Msg *msg, *part;
438  List *sms_datagrams;
439  static unsigned long msg_sequence = 0L; /* Used only by this function */
440 
441  msg = part = NULL;
442  sms_datagrams = NULL;
443 
444  if (dgram == NULL) {
445  error(0, "WDP: dispatch_datagram received empty datagram, ignoring.");
446  }
447  else if (dgram->type != T_DUnitdata_Req) {
448  warning(0, "WDP: dispatch_datagram received event of unexpected type.");
449  wap_event_dump(dgram);
450  }
451  else if (dgram->u.T_DUnitdata_Req.address_type == ADDR_IPV4) {
452 #ifdef HAVE_WTLS_OPENSSL
453  if (dgram->u.T_DUnitdata_Req.addr_tuple->local->port >= WTLS_CONNECTIONLESS_PORT)
454  wtls_dispatch_resp(dgram);
455  else
456 #endif /* HAVE_WTLS_OPENSSL */
457  {
458  msg = pack_ip_datagram(dgram);
460  }
461  } else {
462  msg_sequence = counter_increase(sequence_counter) & 0xff;
463  msg = pack_sms_datagram(dgram);
464  sms_datagrams = sms_split(msg, NULL, NULL, NULL, NULL, concatenation,
465  msg_sequence, max_messages, MAX_SMS_OCTETS);
466  debug("wap",0,"WDP (wapbox): delivering %ld segments to bearerbox",
467  gwlist_len(sms_datagrams));
468  while ((part = gwlist_extract_first(sms_datagrams)) != NULL) {
469  write_to_bearerbox(part);
470  }
471 
472  gwlist_destroy(sms_datagrams, NULL);
473  msg_destroy(msg);
474  }
475  wap_event_destroy(dgram);
476 
477 }
478 
479 
480 /*
481  * Reloading functions
482  */
483 
484 static void reload_int(int reload, Octstr *desc, long *o, long *n)
485 {
486  if (reload && *o != *n) {
487  info(0, "Reloading int '%s' from %ld to %ld",
488  octstr_get_cstr(desc), *o, *n);
489  *o = *n;
490  }
491 }
492 
493 static void reload_bool(int reload, Octstr *desc, int *o, int *n)
494 {
495  if (reload && *o != *n) {
496  info(0, "Reloading bool '%s' from %s to %s",
497  octstr_get_cstr(desc),
498  (*o ? "yes" : "no"), (*n ? "yes" : "no"));
499  *o = *n;
500  }
501 }
502 
503 
504 /*
505  * Read all reloadable configuration directives
506  */
507 static void config_reload(int reload) {
508  Cfg *cfg;
509  CfgGroup *grp;
510  List *groups;
511  long map_url_max;
512  Octstr *s;
513  long i;
514  long new_value;
515  int new_bool;
516  Octstr *http_proxy_host;
517  Octstr *http_interface_name;
518  long http_proxy_port;
519  int http_proxy_ssl = 0;
520  List *http_proxy_exceptions;
521  Octstr *http_proxy_username;
522  Octstr *http_proxy_password;
523  Octstr *http_proxy_exceptions_regex;
524  int warn_map_url = 0;
525 
526  /* XXX TO-DO: if(reload) implement wapbox.suspend/mutex.lock */
527 
528  if (reload)
529  debug("config_reload", 0, "Reloading configuration");
530 
531  /*
532  * NOTE: we could lstat config file and only reload if it was modified,
533  * but as we have a include directive, we don't know every file's
534  * timestamp at this point
535  */
536 
538 
539  if (cfg_read(cfg) == -1) {
540  warning(0, "Couldn't %sload configuration from `%s'.",
541  (reload ? "re" : ""), octstr_get_cstr(config_filename));
542  return;
543  }
544 
545  grp = cfg_get_single_group(cfg, octstr_imm("core"));
546 
547  http_proxy_host = cfg_get(grp, octstr_imm("http-proxy-host"));
548  http_proxy_port = -1;
549  cfg_get_integer(&http_proxy_port, grp, octstr_imm("http-proxy-port"));
550 #ifdef HAVE_LIBSSL
551  cfg_get_bool(&http_proxy_ssl, grp, octstr_imm("http-proxy-ssl"));
552 #endif /* HAVE_LIBSSL */
553  http_proxy_username = cfg_get(grp, octstr_imm("http-proxy-username"));
554  http_proxy_password = cfg_get(grp, octstr_imm("http-proxy-password"));
555  http_proxy_exceptions = cfg_get_list(grp, octstr_imm("http-proxy-exceptions"));
556  http_proxy_exceptions_regex = cfg_get(grp, octstr_imm("http-proxy-exceptions-regex"));
557  if (http_proxy_host != NULL && http_proxy_port > 0) {
558  http_use_proxy(http_proxy_host, http_proxy_port, http_proxy_ssl,
559  http_proxy_exceptions, http_proxy_username,
560  http_proxy_password, http_proxy_exceptions_regex);
561  }
562  octstr_destroy(http_proxy_host);
563  octstr_destroy(http_proxy_username);
564  octstr_destroy(http_proxy_password);
565  octstr_destroy(http_proxy_exceptions_regex);
566  gwlist_destroy(http_proxy_exceptions, octstr_destroy_item);
567 
568  grp = cfg_get_single_group(cfg, octstr_imm("wapbox"));
569  if (grp == NULL) {
570  warning(0, "No 'wapbox' group in configuration.");
571  return;
572  }
573 
574  if (cfg_get_integer(&new_value, grp, octstr_imm("log-level")) != -1) {
575  reload_int(reload, octstr_imm("log level"), &logfilelevel, &new_value);
576  logfilelevel = new_value;
577  log_set_log_level(new_value);
578  }
579 
580  /* Configure interface name for http requests */
581  http_interface_name = cfg_get(grp, octstr_imm("http-interface-name"));
582  if (http_interface_name != NULL) {
583  http_set_interface(http_interface_name);
584  octstr_destroy(http_interface_name);
585  }
586 
587  /*
588  * users may define 'smart-errors' to have WML decks returned with
589  * error information instead of signaling using the HTTP reply codes
590  */
591  cfg_get_bool(&new_bool, grp, octstr_imm("smart-errors"));
592  reload_bool(reload, octstr_imm("smart error messaging"), &wsp_smart_errors, &new_bool);
593 
594  /* decide if our XML parser within WML compiler is strict or relaxed */
595  cfg_get_bool(&new_bool, grp, octstr_imm("wml-strict"));
596  reload_bool(reload, octstr_imm("XML within WML has to be strict"),
597  &wml_xml_strict, &new_bool);
598  if (!wml_xml_strict)
599  warning(0, "'wml-strict' config directive has been set to no, "
600  "this may make you vulnerable against XML bogus input.");
601 
602  if (cfg_get_bool(&new_bool, grp, octstr_imm("concatenation")) == 1)
603  reload_bool(reload, octstr_imm("concatenation"), &concatenation, &new_bool);
604  else
605  concatenation = 1;
606 
607  if (cfg_get_integer(&new_value, grp, octstr_imm("max-messages")) != -1) {
608  max_messages = new_value;
609  reload_int(reload, octstr_imm("max messages"), &max_messages, &new_value);
610  }
611 
612  /* configure URL mappings */
613  map_url_max = -1;
614  cfg_get_integer(&map_url_max, grp, octstr_imm("map-url-max"));
615  if (map_url_max > 0)
616  warn_map_url = 1;
617 
618  if (reload) { /* clear old map */
619  wap_map_destroy();
621  }
622 
623  if ((device_home = cfg_get(grp, octstr_imm("device-home"))) != NULL) {
625  }
626  if ((s = cfg_get(grp, octstr_imm("map-url"))) != NULL) {
627  warn_map_url = 1;
629  octstr_destroy(s);
630  }
631  debug("wap", 0, "map_url_max = %ld", map_url_max);
632 
633  for (i = 0; i <= map_url_max; i++) {
634  Octstr *name;
635  name = octstr_format("map-url-%d", i);
636  if ((s = cfg_get(grp, name)) != NULL)
639  }
640 
641  /* warn the user that he/she should use the new wap-url-map groups */
642  if (warn_map_url)
643  warning(0, "'map-url' config directive and related are deprecated, "
644  "please use wap-url-map group");
645 
646  /* configure wap-url-map */
647  groups = cfg_get_multi_group(cfg, octstr_imm("wap-url-map"));
648  while (groups && (grp = gwlist_extract_first(groups)) != NULL) {
649  Octstr *name, *url, *map_url, *send_msisdn_query;
650  Octstr *send_msisdn_header, *send_msisdn_format;
651  int accept_cookies;
652 
653  name = cfg_get(grp, octstr_imm("name"));
654  url = cfg_get(grp, octstr_imm("url"));
655  map_url = cfg_get(grp, octstr_imm("map-url"));
656  send_msisdn_query = cfg_get(grp, octstr_imm("send-msisdn-query"));
657  send_msisdn_header = cfg_get(grp, octstr_imm("send-msisdn-header"));
658  send_msisdn_format = cfg_get(grp, octstr_imm("send-msisdn-format"));
659  accept_cookies = -1;
660  cfg_get_bool(&accept_cookies, grp, octstr_imm("accept-cookies"));
661 
662  wap_map_add_url(name, url, map_url, send_msisdn_query, send_msisdn_header,
663  send_msisdn_format, accept_cookies);
664 
665  info(0, "Added wap-url-map <%s> with url <%s>, map-url <%s>, "
666  "send-msisdn-query <%s>, send-msisdn-header <%s>, "
667  "send-msisdn-format <%s>, accept-cookies <%s>",
669  octstr_get_cstr(map_url), octstr_get_cstr(send_msisdn_query),
670  octstr_get_cstr(send_msisdn_header),
671  octstr_get_cstr(send_msisdn_format), (accept_cookies ? "yes" : "no"));
672  }
673  gwlist_destroy(groups, NULL);
674 
675  /* configure wap-user-map */
676  groups = cfg_get_multi_group(cfg, octstr_imm("wap-user-map"));
677  while (groups && (grp = gwlist_extract_first(groups)) != NULL) {
678  Octstr *name, *user, *pass, *msisdn;
679 
680  name = cfg_get(grp, octstr_imm("name"));
681  user = cfg_get(grp, octstr_imm("user"));
682  pass = cfg_get(grp, octstr_imm("pass"));
683  msisdn = cfg_get(grp, octstr_imm("msisdn"));
684 
685  wap_map_add_user(name, user, pass, msisdn);
686 
687  info(0,"Added wap-user-map <%s> with credentials <%s:%s> "
688  "and MSISDN <%s>", octstr_get_cstr(name),
689  octstr_get_cstr(user), octstr_get_cstr(pass),
690  octstr_get_cstr(msisdn));
691  }
692  gwlist_destroy(groups, NULL);
693 
694  cfg_destroy(cfg);
695  /* XXX TO-DO: if(reload) implement wapbox.resume/mutex.unlock */
696 }
697 
698 int main(int argc, char **argv)
699 {
700  int cf_index;
701  int restart = 0;
702  Msg *msg;
703  Cfg *cfg;
704  double heartbeat_freq = DEFAULT_HEARTBEAT;
705 
706  gwlib_init();
707  cf_index = get_and_set_debugs(argc, argv, NULL);
708 
710 
711  if (argv[cf_index] == NULL)
712  config_filename = octstr_create("kannel.conf");
713  else
714  config_filename = octstr_create(argv[cf_index]);
716 
717  if (cfg_read(cfg) == -1)
718  panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(config_filename));
719 
720  report_versions("wapbox");
721 
722  cfg = init_wapbox(cfg);
723 
724  info(0, "------------------------------------------------------------");
725  info(0, GW_NAME " wapbox version %s starting up.", GW_VERSION);
726 
735 
736  if (cfg)
738  timer_freq);
739 
743 
744 #if (HAVE_WTLS_OPENSSL)
745  wtls_secmgr_init();
747 #endif
748 
749  if (cfg) {
753  cfg);
754  }
755 
757 
758  if (bearerbox_host == NULL)
761  /* bearerbox_our_port */);
762 
763  if (cfg)
765 
767  if (0 > heartbeat_start(write_to_bearerbox, heartbeat_freq,
769  info(0, GW_NAME "Could not start heartbeat.");
770  }
771 
772  while (program_status != shutting_down) {
773  WAPEvent *dgram;
774  int ret;
775 
776  /* block infinite for reading messages */
778  if (ret == -1) {
779  error(0, "Bearerbox is gone, restarting");
781  restart = 1;
782  break;
783  } else if (ret == 1) /* timeout */
784  continue;
785  else if (msg == NULL) /* just to be sure, may not happens */
786  break;
787  if (msg_type(msg) == admin) {
788  if (msg->admin.command == cmd_shutdown) {
789  info(0, "Bearerbox told us to die");
791  } else if (msg->admin.command == cmd_restart) {
792  info(0, "Bearerbox told us to restart");
793  restart = 1;
795  }
796  /*
797  * XXXX here should be suspend/resume, add RSN
798  */
799  } else if (msg_type(msg) == wdp_datagram) {
800  switch (msg->wdp_datagram.destination_port) {
801  case CONNECTIONLESS_PORT:
803  dgram = wap_event_create(T_DUnitdata_Ind);
804  dgram->u.T_DUnitdata_Ind.addr_tuple = wap_addr_tuple_create(
805  msg->wdp_datagram.source_address,
806  msg->wdp_datagram.source_port,
807  msg->wdp_datagram.destination_address,
808  msg->wdp_datagram.destination_port);
809  dgram->u.T_DUnitdata_Ind.user_data = msg->wdp_datagram.user_data;
810  msg->wdp_datagram.user_data = NULL;
811 
812  wap_dispatch_datagram(dgram);
813  break;
816 #if (HAVE_WTLS_OPENSSL)
817  dgram = wtls_unpack_wdp_datagram(msg);
818  if (dgram != NULL)
819  wtls_dispatch_event(dgram);
820 #endif
821  break;
822  default:
823  panic(0,"Bad packet received! This shouldn't happen!");
824  break;
825  }
826  } else {
827  warning(0, "Received other message than wdp/admin, ignoring!");
828  }
829  msg_destroy(msg);
830  }
831 
832  info(0, GW_NAME " wapbox terminating.");
833 
837 
838  if (cfg)
840 
847 
848  if (cfg) {
851  }
852 
853  wml_shutdown();
855  alog_close();
856  wap_map_destroy();
861 
862  /*
863  * Just sleep for a while to get bearerbox chance to restart.
864  * Otherwise we will fail while trying to connect to bearerbox!
865  */
866  if (restart) {
867  gwthread_sleep(10.0);
868  /* now really restart */
869  restart_box(argv);
870  }
871 
872  log_close_all();
873  gwlib_shutdown();
874 
875  return 0;
876 }
877 
void wtp_initiator_init(wap_dispatch_func_t *datagram_dispatch, wap_dispatch_func_t *session_dispatch, long timer_freq)
Definition: wtp_init.c:168
static void dispatch_datagram(WAPEvent *dgram)
Definition: wapbox.c:435
void error(int err, const char *fmt,...)
Definition: log.c:648
static void reload_int(int reload, Octstr *desc, long *o, long *n)
Definition: wapbox.c:484
static Cfg * init_wapbox(Cfg *cfg)
Definition: wapbox.c:124
void info(int err, const char *fmt,...)
Definition: log.c:672
void wsp_session_shutdown(void)
Definition: wsp_session.c:211
#define MWI_UNDEF
Definition: sms.h:99
#define MAX_SMS_OCTETS
Definition: sms.h:129
void wap_push_ota_dispatch_event(WAPEvent *e)
Definition: wap_push_ota.c:193
static void config_reload(int reload)
Definition: wapbox.c:507
void wap_map_url_config_device_home(char *to)
Definition: wap-maps.c:201
int concatenation
Definition: wapbox.c:115
gw_assert(wtls_machine->packet_to_send !=NULL)
void counter_destroy(Counter *counter)
Definition: counter.c:110
void wml_shutdown()
Definition: wml_compiler.c:479
Definition: shared.h:81
static Msg * pack_ip_datagram(WAPEvent *dgram)
Definition: wapbox.c:329
List * cfg_get_list(CfgGroup *grp, Octstr *varname)
Definition: cfg.c:790
void log_reopen(void)
Definition: log.c:297
static Octstr * pack_udhdata(WAPAddrTuple *tuple)
Definition: wapbox.c:355
long gwlist_len(List *list)
Definition: list.c:166
int restart_box(char **argv)
Definition: shared.c:279
program_status
Definition: shared.h:79
void wtp_resp_shutdown(void)
Definition: wtp_resp.c:235
int read_from_bearerbox(Msg **msg, double seconds)
Definition: shared.c:220
void wtls_dispatch_event(WAPEvent *event)
static Octstr * bearerbox_host
Definition: wapbox.c:100
#define BB_DEFAULT_HOST
Definition: bb.h:67
msg_type
Definition: msg.h:73
Octstr * address
Definition: wap_addr.h:68
#define cfg_get(grp, varname)
Definition: cfg.h:86
void wsp_push_client_init(wap_dispatch_func_t *dispatch_self, wap_dispatch_func_t *dispatch_wtp_resp)
#define DC_8BIT
Definition: sms.h:111
int main(int argc, char **argv)
Definition: wapbox.c:698
void wsp_push_client_dispatch_event(WAPEvent *e)
#define msg_create(type)
Definition: msg.h:136
void get_cert_from_file(Octstr *s, X509 **x509)
int gwthread_shouldhandlesignal(int signal)
static Cfg * cfg
Definition: opensmppbox.c:95
void radius_acct_init(CfgGroup *grp)
Definition: radius_acct.c:384
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
List * sms_split(Msg *orig, Octstr *header, Octstr *footer, Octstr *nonlast_suffix, Octstr *split_chars, int catenate, unsigned long msg_sequence, int max_messages, int max_octets)
Definition: sms.c:309
void wap_event_dump(WAPEvent *event)
Definition: wap_events.c:181
int wsp_smart_errors
Definition: wapbox.c:111
static Msg * pack_sms_datagram(WAPEvent *dgram)
Definition: wapbox.c:383
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
static int restart
Definition: opensmppbox.c:109
#define BB_DEFAULT_WAPBOX_PORT
Definition: bb.h:69
Cfg * cfg_create(Octstr *filename)
Definition: cfg.c:318
void wsp_unit_dispatch_event(WAPEvent *event)
Definition: wsp_unit.c:124
void heartbeat_stop(long hb_thread)
Definition: heartbeat.c:160
int cfg_read(Cfg *cfg)
Definition: cfg.c:452
void wap_map_add_user(Octstr *name, Octstr *user, Octstr *pass, Octstr *msisdn)
Definition: wap-maps.c:136
void wap_map_add_url(Octstr *name, Octstr *url, Octstr *map_url, Octstr *send_msisdn_query, Octstr *send_msisdn_header, Octstr *send_msisdn_format, int accept_cookies)
Definition: wap-maps.c:101
void wap_appl_shutdown(void)
Definition: wap-appl.c:268
static void reload_bool(int reload, Octstr *desc, int *o, int *n)
Definition: wapbox.c:493
WAPAddr * local
Definition: wap_addr.h:74
void get_privkey_from_file(Octstr *s, RSA **priv_key, Octstr *password)
static void signal_handler(int signum)
Definition: wapbox.c:274
Definition: msg.h:108
#define INFINITE_TIME
Definition: shared.h:73
void wtls_init(wtls_dispatch_func_t *responder_dispatch)
unsigned char * password
Definition: test_cimd2.c:100
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
void wap_push_ota_init(wap_dispatch_func_t *wsp_dispatch, wap_dispatch_func_t *wsp_unit_dispatch)
Definition: wap_push_ota.c:166
Definition: msg.h:79
void log_close_all(void)
Definition: log.c:341
Definition: cfg.c:164
Counter * counter_create(void)
Definition: counter.c:94
void cfg_destroy(Cfg *cfg)
Definition: cfg.c:331
void * gwlist_extract_first(List *list)
Definition: list.c:305
void wtls_dispatch_resp(WAPEvent *event)
void conn_config_ssl(CfgGroup *grp)
Definition: conn.c:1546
void connect_to_bearerbox(Octstr *host, int port, int ssl, Octstr *our_host)
Definition: shared.c:108
void wap_map_url_config(char *s)
Definition: wap-maps.c:185
long max_messages
Definition: wapbox.c:116
static int bearerbox_ssl
Definition: wapbox.c:102
void log_set_log_level(enum output_level level)
Definition: log.c:265
void cfg_dump(Cfg *cfg)
Definition: cfg.c:835
#define octstr_duplicate(ostr)
Definition: octstr.h:187
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:645
void wap_map_user_destroy(void)
Definition: wap-maps.c:174
static Counter * sequence_counter
Definition: wapbox.c:103
void wtp_initiator_shutdown(void)
Definition: wtp_init.c:188
void wap_push_ppg_init(wap_dispatch_func_t *ota_dispatch, wap_dispatch_func_t *appl_dispatch, Cfg *cfg)
Definition: wap_push_ppg.c:397
void msg_destroy(Msg *msg)
Definition: msg.c:132
char * name
Definition: smsc_cimd2.c:212
static void setup_signal_handlers(void)
Definition: wapbox.c:313
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:903
#define wap_event_create(type)
Definition: wap_events.h:107
void warning(int err, const char *fmt,...)
Definition: log.c:660
void log_set_syslog_facility(char *facility)
Definition: log.c:278
void alog_open(char *fname, int use_localtm, int use_markers)
Definition: accesslog.c:129
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
void http_set_interface(const Octstr *our_host)
Definition: http.c:1746
#define octstr_create(cstr)
Definition: octstr.h:125
long port
Definition: wap_addr.h:70
void octstr_destroy_item(void *os)
Definition: octstr.c:336
void radius_acct_shutdown(void)
Definition: radius_acct.c:432
void wap_dispatch_datagram(WAPEvent *dgram)
Definition: wap.c:68
void gwthread_sleep(double seconds)
Octstr * device_home
Definition: wapbox.c:112
static Octstr * config_filename
Definition: wapbox.c:105
void log_set_syslog(const char *ident, int syslog_level)
Definition: log.c:284
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
void wsp_unit_shutdown(void)
Definition: wsp_unit.c:113
WAPAddr * remote
Definition: wap_addr.h:74
#define ALL_HEARTBEATS
Definition: heartbeat.h:68
void close_connection_to_bearerbox(void)
Definition: shared.c:122
void alog_reopen(void)
Definition: accesslog.c:85
void report_versions(const char *boxname)
Definition: utils.c:539
int log_open(char *filename, int level, enum excl_state excl)
Definition: log.c:375
void wap_map_destroy(void)
Definition: wap-maps.c:152
static long bearerbox_port
Definition: wapbox.c:101
void wtp_resp_dispatch_event(WAPEvent *event)
Definition: wtp_resp.c:253
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:759
#define DEFAULT_HEARTBEAT
Definition: heartbeat.h:67
#define MC_UNDEF
Definition: sms.h:93
void write_to_bearerbox(Msg *pmsg)
Definition: shared.c:142
void wsp_session_dispatch_event(WAPEvent *event)
Definition: wsp_session.c:228
Definition: octstr.c:118
long heartbeat_start(hb_send_func_t *send_func, double freq, hb_load_func_t *load_func)
Definition: heartbeat.c:126
void http_use_proxy(Octstr *hostname, int port, int ssl, List *exceptions, Octstr *username, Octstr *password, Octstr *exceptions_regex)
Definition: http.c:268
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
long wap_appl_get_load(void)
Definition: wap-appl.c:295
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
#define panic
Definition: log.h:87
void wsp_push_client_shutdown(void)
void wap_push_ppg_shutdown(void)
Definition: wap_push_ppg.c:433
Definition: cfg.c:73
void wtp_resp_init(wap_dispatch_func_t *datagram_dispatch, wap_dispatch_func_t *session_dispatch, wap_dispatch_func_t *push_dispatch, long timer_freq)
Definition: wtp_resp.c:211
void wsp_session_init(wap_dispatch_func_t *responder_dispatch, wap_dispatch_func_t *initiator_dispatch, wap_dispatch_func_t *application_dispatch, wap_dispatch_func_t *ota_dispatch)
Definition: wsp_session.c:193
WAPAddrTuple * wap_addr_tuple_create(Octstr *rmt_addr, long rmt_port, Octstr *lcl_addr, long lcl_port)
Definition: wap_addr.c:96
WAPEventName type
Definition: wap_events.h:88
static int wml_xml_strict
Definition: wapbox.c:108
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
Definition: octstr.c:749
void wap_push_ppg_dispatch_event(WAPEvent *e)
Definition: wap_push_ppg.c:476
void alog_close(void)
Definition: accesslog.c:111
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2507
void gwlib_shutdown(void)
Definition: gwlib.c:94
void wap_push_ota_shutdown(void)
Definition: wap_push_ota.c:182
void wap_appl_init(Cfg *cfg)
Definition: wap-appl.c:249
static long logfilelevel
Definition: wapbox.c:89
void gwlib_init(void)
Definition: gwlib.c:78
WAPEvent * wtls_unpack_wdp_datagram(Msg *msg)
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:639
union WAPEvent::@87 u
void http_set_client_timeout(long timeout)
Definition: http.c:1751
static Octstr * url
Definition: test_xmlrpc.c:84
void wap_push_ota_bb_address_set(Octstr *in)
Definition: wap_push_ota.c:203
int get_and_set_debugs(int argc, char **argv, int(*find_own)(int index, int argc, char **argv))
Definition: utils.c:626
Definition: list.c:102
static Octstr * lf
Definition: smsc_smasi.c:222
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void wtp_initiator_dispatch_event(WAPEvent *event)
Definition: wtp_init.c:204
void wml_init(int wml_xml_strict)
Definition: wml_compiler.c:429
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102
void wsp_unit_init(wap_dispatch_func_t *datagram_dispatch, wap_dispatch_func_t *application_dispatch)
Definition: wsp_unit.c:100
void wap_appl_dispatch(WAPEvent *event)
Definition: wap-appl.c:288
static long timer_freq
Definition: wapbox.c:104
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.