📄 wapbox.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * wapbox.c - main program for wapbox * * This module contains the main program for the WAP box of the WAP gateway. * See the architecture documentation for details. */#include <stdlib.h>#include <time.h>#include <unistd.h>#include <signal.h>#include "gwlib/gwlib.h"#include "shared.h"#include "wml_compiler.h"#include "heartbeat.h"#include "wap/wap.h"#include "wap-appl.h"#include "wap-maps.h"#include "wap_push_ota.h"#include "wap_push_ppg.h"#include "gw/msg.h"#include "bb.h"#include "sms.h"#ifdef HAVE_WTLS_OPENSSL#include <openssl/x509.h>#include "wap/wtls.h"#include "gwlib/pki.h"#endif#include "radius/radius_acct.h"static void config_reload(int reload);static long logfilelevel=-1;enum { CONNECTIONLESS_PORT = 9200, CONNECTION_ORIENTED_PORT = 9201, WTLS_CONNECTIONLESS_PORT = 9202, WTLS_CONNECTION_ORIENTED_PORT = 9203};enum { DEFAULT_TIMER_FREQ = 1};static Octstr *bearerbox_host;static long bearerbox_port = BB_DEFAULT_WAPBOX_PORT;static int bearerbox_ssl = 0;static Counter *sequence_counter = NULL;static long timer_freq = DEFAULT_TIMER_FREQ;static Octstr *config_filename;/* smart error messaging related globals */int wsp_smart_errors = 0;Octstr *device_home = NULL;/* Controlling segmentation of sms messages sent by wapbox (push related).*/int concatenation = 1;long max_messages = 10;#ifdef HAVE_WTLS_OPENSSLRSA* private_key = NULL;X509* x509_cert = NULL;#endifstatic Cfg *init_wapbox(Cfg *cfg){ CfgGroup *grp; Octstr *s; Octstr *logfile; int lf, m; lf = m = 1; cfg_dump(cfg); /* * Extract info from the core group. */ grp = cfg_get_single_group(cfg, octstr_imm("core")); if (grp == NULL) panic(0, "No 'core' group in configuration."); if (cfg_get_integer(&bearerbox_port,grp,octstr_imm("wapbox-port")) == -1) panic(0, "No 'wapbox-port' in core group");#ifdef HAVE_LIBSSL cfg_get_bool(&bearerbox_ssl, grp, octstr_imm("wapbox-port-ssl"));#endif /* HAVE_LIBSSL */ /* load parameters that could be later reloaded */ config_reload(0); conn_config_ssl(grp); /* * And the rest of the pull info comes from the wapbox group. */ grp = cfg_get_single_group(cfg, octstr_imm("wapbox")); if (grp == NULL) panic(0, "No 'wapbox' group in configuration."); bearerbox_host = cfg_get(grp, octstr_imm("bearerbox-host")); if (cfg_get_integer(&timer_freq, grp, octstr_imm("timer-freq")) == -1) timer_freq = DEFAULT_TIMER_FREQ; logfile = cfg_get(grp, octstr_imm("log-file")); if (logfile != NULL) { log_open(octstr_get_cstr(logfile), logfilelevel, GW_NON_EXCL); info(0, "Starting to log to file %s level %ld", octstr_get_cstr(logfile), logfilelevel); } octstr_destroy(logfile); if ((s = cfg_get(grp, octstr_imm("syslog-level"))) != NULL) { long level; if (octstr_compare(s, octstr_imm("none")) == 0) { log_set_syslog(NULL, 0); debug("wap", 0, "syslog parameter is none"); } else if (octstr_parse_long(&level, s, 0, 0) == -1) { log_set_syslog("wapbox", level); debug("wap", 0, "syslog parameter is %ld", level); } octstr_destroy(s); } else { log_set_syslog(NULL, 0); debug("wap", 0, "no syslog parameter"); } /* determine which timezone we use for access logging */ if ((s = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) { lf = (octstr_case_compare(s, octstr_imm("gmt")) == 0) ? 0 : 1; octstr_destroy(s); } /* should predefined markers be used, ie. prefixing timestamp */ cfg_get_bool(&m, grp, octstr_imm("access-log-clean")); /* open access-log file */ if ((s = cfg_get(grp, octstr_imm("access-log"))) != NULL) { info(0, "Logging accesses to '%s'.", octstr_get_cstr(s)); alog_open(octstr_get_cstr(s), lf, m ? 0 : 1); octstr_destroy(s); } /* configure the 'wtls' group */#if (HAVE_WTLS_OPENSSL) /* Load up the necessary keys */ grp = cfg_get_single_group(cfg, octstr_imm("wtls")); if (grp != NULL) { if ((s = cfg_get(grp, octstr_imm("certificate-file"))) != NULL) { if (octstr_compare(s, octstr_imm("none")) == 0) { debug("bbox", 0, "certificate file not set"); } else { /* Load the certificate into the necessary parameter */ get_cert_from_file(s, &x509_cert); gw_assert(x509_cert != NULL); debug("bbox", 0, "certificate parameter is %s", s); } octstr_destroy(s); } else panic(0, "No 'certificate-file' in wtls group"); if ((s = cfg_get(grp, octstr_imm("privatekey-file"))) != NULL) { Octstr *password; password = cfg_get(grp, octstr_imm("privatekey-password")); if (octstr_compare(s, octstr_imm("none")) == 0) { debug("bbox", 0, "privatekey-file not set"); } else { /* Load the private key into the necessary parameter */ get_privkey_from_file(s, &private_key, password); gw_assert(private_key != NULL); debug("bbox", 0, "certificate parameter is %s", s); } if (password != NULL) octstr_destroy(password); octstr_destroy(s); } else panic(0, "No 'privatekey-file' in wtls group"); }#endif /* * Check if we have a 'radius-acct' proxy group and start the * corresponding thread for the proxy. */ grp = cfg_get_single_group(cfg, octstr_imm("radius-acct")); if (grp) { radius_acct_init(grp); } /* * We pass ppg configuration groups to the ppg module. */ grp = cfg_get_single_group(cfg, octstr_imm("ppg")); if (grp == NULL) { cfg_destroy(cfg); return NULL; } return cfg;}static void signal_handler(int signum) { /* * On some implementations (i.e. linuxthreads), signals are delivered * to all threads. We only want to handle each signal once for the * entire box, and we let the gwthread wrapper take care of choosing * one. */ if (!gwthread_shouldhandlesignal(signum)) return; switch (signum) { case SIGINT: if (program_status != shutting_down) { error(0, "SIGINT received, let's die."); program_status = shutting_down; break; } break; case SIGHUP: warning(0, "SIGHUP received, catching and re-opening logs"); config_reload(1); log_reopen(); alog_reopen(); break; /* * It would be more proper to use SIGUSR1 for this, but on some * platforms that's reserved by the pthread support. */ case SIGQUIT: warning(0, "SIGQUIT received, reporting memory usage."); gw_check_leaks(); break; }}static void setup_signal_handlers(void) { struct sigaction act; act.sa_handler = signal_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGPIPE, &act, NULL);}/* * We create wdp_datagram for IP traffic and sms for SMS traffic. */static Msg *pack_ip_datagram(WAPEvent *dgram){ Msg *msg; WAPAddrTuple *tuple; msg = msg_create(wdp_datagram); tuple = dgram->u.T_DUnitdata_Req.addr_tuple; msg->wdp_datagram.source_address = octstr_duplicate(tuple->local->address); msg->wdp_datagram.source_port = dgram->u.T_DUnitdata_Req.addr_tuple->local->port; msg->wdp_datagram.destination_address = octstr_duplicate(tuple->remote->address); msg->wdp_datagram.destination_port = dgram->u.T_DUnitdata_Req.addr_tuple->remote->port; msg->wdp_datagram.user_data = octstr_duplicate(dgram->u.T_DUnitdata_Req.user_data); return msg;}/* * Format for port UDH is defined in wdp, appendix A. It is %06%05%04 * %dest port high hex%dest port low%hex source port high hex%source port low * hex. (Unsecure) push client port itself is 2948. */static Octstr *pack_udhdata(WAPAddrTuple *tuple){ int source_port, dest_port; Octstr *udh; source_port = tuple->local->port; dest_port = tuple->remote->port; udh = octstr_create(""); octstr_format_append(udh, "%c", 6); octstr_format_append(udh, "%c", 5); octstr_format_append(udh, "%c", 4); octstr_format_append(udh, "%c", (dest_port >> 8) & 0xff); octstr_format_append(udh, "%c", dest_port & 0xff); octstr_format_append(udh, "%c", (source_port >> 8) & 0xff); octstr_format_append(udh, "%c", source_port & 0xff); return udh;}/* * We send a normal 8-bit unconcatenated binary message with an udh. Caller * must do segmentation before calling this function. * * Note: we have hardcoded validity period here. We must eventually use push * control document to fill this field. */static Msg *pack_sms_datagram(WAPEvent *dgram){ Msg *msg; WAPAddrTuple *tuple; msg = msg_create(sms); tuple = dgram->u.T_DUnitdata_Req.addr_tuple; msg->sms.sender = octstr_duplicate(tuple->local->address); msg->sms.receiver = octstr_duplicate(tuple->remote->address); msg->sms.udhdata = pack_udhdata(tuple); msg->sms.msgdata = octstr_duplicate(dgram->u.T_DUnitdata_Req.user_data); msg->sms.time = time(NULL); if (dgram->u.T_DUnitdata_Req.smsc_id != NULL) msg->sms.smsc_id = octstr_duplicate(dgram->u.T_DUnitdata_Req.smsc_id); else msg->sms.smsc_id = NULL; msg->sms.dlr_mask = dgram->u.T_DUnitdata_Req.dlr_mask; if (dgram->u.T_DUnitdata_Req.smsbox_id != NULL) msg->sms.boxc_id = octstr_duplicate(dgram->u.T_DUnitdata_Req.smsbox_id); else msg->sms.boxc_id = NULL; if (dgram->u.T_DUnitdata_Req.dlr_url != NULL) msg->sms.dlr_url = octstr_duplicate(dgram->u.T_DUnitdata_Req.dlr_url); else msg->sms.dlr_url = NULL; msg->sms.sms_type = mt_push; msg->sms.mwi = MWI_UNDEF; msg->sms.coding = DC_8BIT; msg->sms.mclass = MC_UNDEF; msg->sms.validity = 1440; msg->sms.deferred = -1; if (dgram->u.T_DUnitdata_Req.service_name != NULL) msg->sms.service = octstr_duplicate(dgram->u.T_DUnitdata_Req.service_name); return msg; }/* * Possible address types */enum { ADDR_IPV4 = 0, ADDR_PLMN = 1, ADDR_USER = 2, ADDR_IPV6 = 3, ADDR_WINA = 4};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -