2005-09-01 10:26:36 +00:00
|
|
|
/*
|
|
|
|
* Mbuni - Open Source MMS Gateway
|
|
|
|
*
|
2005-09-02 11:41:28 +00:00
|
|
|
* MMSC CFG: MMC configuration and misc. functions
|
2005-09-01 10:26:36 +00:00
|
|
|
*
|
2008-07-10 09:46:58 +00:00
|
|
|
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
2005-09-01 10:26:36 +00:00
|
|
|
*
|
|
|
|
* Paul Bagyenda <bagyenda@dsmagic.com>
|
|
|
|
*
|
|
|
|
* This program is free software, distributed under the terms of
|
|
|
|
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
|
|
|
*/
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "mmsc_cfg.h"
|
2005-09-02 11:41:28 +00:00
|
|
|
#include "mms_queue.h"
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2006-10-27 14:27:30 +00:00
|
|
|
|
2005-09-01 10:26:36 +00:00
|
|
|
#define MMS_PORT 8191 /* Default content fetch port. */
|
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
static void free_vasp(MmsVasp *m);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
static void delete_stale_vasps(MmscSettings *settings, int delete_all);
|
|
|
|
static void admin_handler(MmscSettings *settings);
|
2007-08-22 11:41:57 +00:00
|
|
|
void mms_cleanup_mmsc_settings(MmscSettings *settings)
|
|
|
|
{
|
2008-09-08 11:50:24 +00:00
|
|
|
/* eventually we will destroy the object. */
|
2008-09-04 17:20:42 +00:00
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
if (settings->admin_port > 0) {
|
|
|
|
http_close_port(settings->admin_port);
|
|
|
|
|
|
|
|
if (settings->admin_thread >= 0)
|
|
|
|
gwthread_join(settings->admin_thread);
|
|
|
|
|
|
|
|
mms_info(0, "mmsc", NULL,"Admin port on %d, shutdown", (int)settings->admin_port);
|
|
|
|
}
|
2008-09-11 09:03:59 +00:00
|
|
|
mms_cfg_destroy(settings->cfg);
|
2008-09-08 11:50:24 +00:00
|
|
|
settings->qfs->mms_cleanup_queue_module();
|
2008-09-11 09:03:59 +00:00
|
|
|
if (settings->mm5)
|
|
|
|
settings->mm5->cleanup();
|
2008-09-08 11:50:24 +00:00
|
|
|
delete_stale_vasps(settings, 1);
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_event_logger_cleanup();
|
2007-08-22 11:41:57 +00:00
|
|
|
}
|
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
MmscSettings *mms_load_mmsc_settings(Octstr *fname, List **proxyrelays)
|
2005-09-01 10:26:36 +00:00
|
|
|
{
|
2008-09-08 11:50:24 +00:00
|
|
|
mCfg *cfg;
|
2005-09-01 10:26:36 +00:00
|
|
|
Octstr *s;
|
|
|
|
List *l;
|
2008-09-08 11:50:24 +00:00
|
|
|
mCfgGrp *grp;
|
|
|
|
mCfgGrp *cgrp;
|
|
|
|
MmscSettings *m;
|
2005-09-01 10:26:36 +00:00
|
|
|
long port = -1;
|
2005-09-02 11:41:28 +00:00
|
|
|
Octstr *from, *user, *pass;
|
2005-09-01 10:26:36 +00:00
|
|
|
Octstr *qdir = NULL;
|
2008-09-08 11:50:24 +00:00
|
|
|
int i, n, xx = 0, ssl = 0;
|
2008-09-04 17:20:42 +00:00
|
|
|
void *x;
|
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
|
|
|
|
cfg = mms_cfg_read(fname);
|
|
|
|
|
|
|
|
if (cfg == NULL)
|
|
|
|
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
|
|
|
|
|
|
|
|
|
|
|
|
cgrp = mms_cfg_get_single(cfg, octstr_imm("core"));
|
|
|
|
grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
|
|
|
|
|
|
|
|
m = gw_malloc(sizeof *m);
|
2005-09-01 10:26:36 +00:00
|
|
|
memset(m, 0, sizeof *m);
|
|
|
|
|
2006-03-10 05:38:29 +00:00
|
|
|
if (grp == NULL)
|
|
|
|
panic(0,"Missing required group `mbuni' in config file!");
|
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
m->cfg = cfg; /* store it since admin thread needs it. */
|
|
|
|
m->vasp_del_list = gwlist_create();
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
mms_load_core_settings(cfg, cgrp);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-09-04 17:20:42 +00:00
|
|
|
if ((x = _mms_load_module(cfg, grp, "event-logger-module", "event_logger", NULL)) != NULL) {
|
|
|
|
Octstr *s = mms_cfg_get(cfg, grp, octstr_imm("event-logger-module"));
|
|
|
|
|
|
|
|
if (mms_event_logger_init(x, s) != 0)
|
|
|
|
panic(0, "Mmsc: Failed to initialise event logger module!");
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
|
2008-09-11 09:03:59 +00:00
|
|
|
if ((m->mm5 = _mms_load_module(cfg, grp, "mm5-module", "mm5_funcs", shell_mm5)) != NULL) {
|
|
|
|
Octstr *s = mms_cfg_get(cfg, grp, octstr_imm("mm5-module"));
|
|
|
|
|
|
|
|
if (m->mm5->init(octstr_get_cstr(s)) != 0)
|
|
|
|
panic(0, "Mmsc: Failed to initialise MM5 module!");
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->hostname = mms_cfg_get(cfg, grp, octstr_imm("hostname"));
|
2007-03-20 16:43:44 +00:00
|
|
|
|
2008-07-07 06:35:43 +00:00
|
|
|
if (octstr_len(m->hostname) == 0)
|
|
|
|
m->hostname = octstr_create("localhost");
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if ((m->host_alias = mms_cfg_get(cfg, grp, octstr_imm("host-alias"))) == NULL)
|
2008-07-07 06:35:43 +00:00
|
|
|
m->host_alias = octstr_duplicate(m->hostname);
|
|
|
|
|
2005-09-01 10:26:36 +00:00
|
|
|
if (proxyrelays)
|
2007-03-20 16:43:44 +00:00
|
|
|
*proxyrelays = mms_proxy_relays(cfg, m->hostname);
|
2005-09-02 11:41:28 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if (mms_cfg_get_int(cfg, grp, octstr_imm("max-send-threads"), &m->maxthreads) == -1)
|
2005-09-01 10:26:36 +00:00
|
|
|
m->maxthreads = 10;
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->unified_prefix = _mms_cfg_getx(cfg, grp, octstr_imm("unified-prefix"));
|
|
|
|
m->local_prefix = _mms_cfg_getx(cfg, grp, octstr_imm("local-prefixes"));
|
2008-05-05 19:29:49 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("strip-prefixes"))) != NULL) {
|
2008-05-05 19:29:49 +00:00
|
|
|
m->strip_prefixes = octstr_split(s, octstr_imm(";"));
|
|
|
|
octstr_destroy(s);
|
|
|
|
} else
|
|
|
|
m->strip_prefixes = NULL;
|
|
|
|
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->name = _mms_cfg_getx(cfg, grp, octstr_imm("name"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->sendmail = _mms_cfg_getx(cfg, grp, octstr_imm("send-mail-prog"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
qdir = _mms_cfg_getx(cfg, grp, octstr_imm("storage-directory"));
|
2005-12-12 04:46:46 +00:00
|
|
|
if (qdir && octstr_len(qdir) >= QFNAMEMAX)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mmsc", NULL,"storage-directory name too long. Max length is %d", QFNAMEMAX);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
|
|
|
if (mkdir(octstr_get_cstr(qdir),
|
|
|
|
S_IRWXU|S_IRWXG) < 0 &&
|
|
|
|
errno != EEXIST)
|
|
|
|
panic(0, "Failed to create queue directory: %s - %s!",
|
|
|
|
octstr_get_cstr(qdir), strerror(errno));
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if ((m->qfs = _mms_load_module(cfg, grp, "queue-manager-module", "qfuncs", NULL)) == NULL) {
|
2007-08-22 11:41:57 +00:00
|
|
|
m->qfs = &default_qfuncs; /* default queue handler. */
|
2008-11-14 08:52:15 +00:00
|
|
|
m->qfs->mms_init_queue_module(qdir,
|
|
|
|
octstr_get_cstr(qdir),
|
|
|
|
(2 + 2 + 2)*m->maxthreads); /* We expect 2 max for each mmsrelay component (= 4)
|
2008-09-01 15:18:43 +00:00
|
|
|
* + 2 for mmsproxy (on for mm1proxy, one for mm7proxy
|
|
|
|
*/
|
2007-08-20 11:49:30 +00:00
|
|
|
} else {
|
2008-08-28 16:07:31 +00:00
|
|
|
Octstr *s = _mms_cfg_getx(cfg, grp, octstr_imm("queue-module-init-data"));
|
2008-11-14 08:52:15 +00:00
|
|
|
if (m->qfs->mms_init_queue_module(s, octstr_get_cstr(qdir),
|
|
|
|
(2 + 2 + 2)*m->maxthreads) != 0)
|
2007-08-20 11:49:30 +00:00
|
|
|
panic(0, "failed to initialise queue module, with data: %s",
|
|
|
|
octstr_get_cstr(s));
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((m->global_queuedir = m->qfs->mms_init_queue_dir("global", &xx)) == NULL ||
|
|
|
|
xx != 0)
|
|
|
|
panic(0, "Failed to initialise global queue directory: %s - %s!",
|
|
|
|
octstr_get_cstr(m->global_queuedir), strerror(errno));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2007-08-20 11:49:30 +00:00
|
|
|
if ((m->mm1_queuedir = m->qfs->mms_init_queue_dir("mm1", &xx)) == NULL ||
|
|
|
|
xx != 0)
|
2005-09-01 10:26:36 +00:00
|
|
|
panic(0, "Failed to initialise local queue directory: %s - %s!",
|
|
|
|
octstr_get_cstr(m->mm1_queuedir), strerror(errno));
|
|
|
|
|
2007-08-20 11:49:30 +00:00
|
|
|
m->mmbox_rootdir = octstr_format("%S/mmbox", qdir);
|
2005-09-01 10:26:36 +00:00
|
|
|
if (mmbox_root_init(octstr_get_cstr(m->mmbox_rootdir)) != 0)
|
|
|
|
panic(0, "Failed to initialise mmbox root directory, error: %s!",
|
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
m->ua_profile_cache_dir = octstr_format("%S/UserAgent_Profiles", qdir);
|
|
|
|
|
|
|
|
if (mkdir(octstr_get_cstr(m->ua_profile_cache_dir),
|
|
|
|
S_IRWXU|S_IRWXG) < 0 &&
|
|
|
|
errno != EEXIST)
|
|
|
|
panic(0, "Failed to initialise UA Profile directory, error: %s!",
|
|
|
|
strerror(errno));
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if (mms_cfg_get_int(cfg, grp, octstr_imm("maximum-send-attempts"), &m->maxsendattempts) == -1)
|
2005-09-01 10:26:36 +00:00
|
|
|
m->maxsendattempts = MAXQTRIES;
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if (mms_cfg_get_int(cfg, grp, octstr_imm("default-message-expiry"), &m->default_msgexpiry) == -1)
|
2005-09-01 10:26:36 +00:00
|
|
|
m->default_msgexpiry = DEFAULT_EXPIRE;
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
s = _mms_cfg_getx(cfg, grp, octstr_imm("queue-run-interval"));
|
2005-09-01 10:26:36 +00:00
|
|
|
if (!s || (m->queue_interval = atof(octstr_get_cstr(s))) <= 0)
|
|
|
|
m->queue_interval = QUEUERUN_INTERVAL;
|
2005-09-07 10:10:41 +00:00
|
|
|
|
2008-04-20 08:11:40 +00:00
|
|
|
|
|
|
|
octstr_destroy(s);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if (mms_cfg_get_int(cfg, grp, octstr_imm("send-attempt-back-off"), &m->send_back_off) == -1)
|
2005-09-01 10:26:36 +00:00
|
|
|
m->send_back_off = BACKOFF_FACTOR;
|
|
|
|
|
|
|
|
/* Make send sms url. */
|
2008-08-28 16:07:31 +00:00
|
|
|
m->sendsms_url = _mms_cfg_getx(cfg, grp, octstr_imm("sendsms-url"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
user = mms_cfg_get(cfg, grp, octstr_imm("sendsms-username"));
|
|
|
|
pass = mms_cfg_get(cfg, grp, octstr_imm("sendsms-password"));
|
|
|
|
from = mms_cfg_get(cfg, grp, octstr_imm("sendsms-global-sender"));
|
2006-07-13 12:01:24 +00:00
|
|
|
|
|
|
|
i = octstr_search_char(m->sendsms_url, '?', 0); /* If ? is in there, omit below. */
|
2007-06-20 06:47:05 +00:00
|
|
|
|
2005-09-01 10:26:36 +00:00
|
|
|
octstr_format_append(m->sendsms_url,
|
|
|
|
(from && octstr_len(from) > 1) ?
|
2007-06-20 06:47:05 +00:00
|
|
|
"%sfrom=%E" : "%s_dummy=x",
|
|
|
|
(i >= 0) ? "" : "?", from);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2007-06-20 06:47:05 +00:00
|
|
|
if (user && octstr_len(user) > 0)
|
|
|
|
octstr_format_append(m->sendsms_url,
|
|
|
|
"&username=%E&password=%E",
|
|
|
|
user, pass);
|
2005-09-01 10:26:36 +00:00
|
|
|
m->system_user = octstr_format("system-user@%S",
|
|
|
|
m->hostname);
|
|
|
|
octstr_destroy(user);
|
|
|
|
octstr_destroy(pass);
|
2007-06-20 06:47:05 +00:00
|
|
|
octstr_destroy(from);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
mms_cfg_get_int(cfg, grp, octstr_imm("mms-port"), &port);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
|
|
|
m->port = (port > 0) ? port : MMS_PORT;
|
|
|
|
|
|
|
|
m->mm7port = -1;
|
2008-08-28 16:07:31 +00:00
|
|
|
mms_cfg_get_int(cfg, grp, octstr_imm("mm7-port"), &m->mm7port);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->allow_ip = _mms_cfg_getx(cfg, grp, octstr_imm("allow-ip"));
|
|
|
|
m->deny_ip = _mms_cfg_getx(cfg, grp, octstr_imm("deny-ip"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->email2mmsrelay_hosts = _mms_cfg_getx(cfg, grp,
|
2006-02-28 10:36:36 +00:00
|
|
|
octstr_imm("email2mms-relay-hosts"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->prov_notify = _mms_cfg_getx(cfg, grp,octstr_imm("prov-server-notify-script"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->prov_getstatus = _mms_cfg_getx(cfg, grp,octstr_imm("prov-server-sub-status-script"));
|
|
|
|
m->mms_notify_txt = _mms_cfg_getx(cfg, grp, octstr_imm("mms-notify-text"));
|
|
|
|
m->mms_notify_unprov_txt = _mms_cfg_getx(cfg, grp, octstr_imm("mms-notify-unprovisioned-text"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->mms_email_txt = _mms_cfg_getx(cfg, grp, octstr_imm("mms-to-email-txt"));
|
|
|
|
m->mms_email_html = _mms_cfg_getx(cfg, grp, octstr_imm("mms-to-email-html"));
|
|
|
|
m->mms_email_subject = mms_cfg_get(cfg, grp, octstr_imm("mms-to-email-default-subject"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->mms_toolarge = _mms_cfg_getx(cfg, grp, octstr_imm("mms-message-too-large-txt"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-12-09 03:35:26 +00:00
|
|
|
|
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mms-client-msisdn-header"))) == NULL)
|
|
|
|
s = octstr_imm(XMSISDN_HEADER);
|
2008-12-10 06:00:43 +00:00
|
|
|
m->wap_gw_msisdn_header = octstr_split(s, octstr_imm(","));
|
2008-12-09 03:35:26 +00:00
|
|
|
octstr_destroy(s);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-12-09 03:35:26 +00:00
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mms-client-ip-header"))) == NULL)
|
|
|
|
s = octstr_imm(XIP_HEADER);
|
2008-12-10 06:00:43 +00:00
|
|
|
m->wap_gw_ip_header = octstr_split(s, octstr_imm(","));
|
2008-12-09 03:35:26 +00:00
|
|
|
octstr_destroy(s);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
mms_cfg_get_bool(cfg, grp, octstr_imm("notify-unprovisioned"), &m->notify_unprovisioned);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->billing_params = _mms_cfg_getx(cfg, grp,
|
2005-09-01 10:26:36 +00:00
|
|
|
octstr_imm("billing-module-parameters"));
|
|
|
|
/* Get and load the billing lib if any. */
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if ((m->mms_billfuncs = _mms_load_module(cfg, grp, "billing-library", "mms_billfuncs",
|
2006-10-27 14:27:30 +00:00
|
|
|
&mms_billfuncs_shell)) != NULL) {
|
2005-09-01 10:26:36 +00:00
|
|
|
if (m->mms_billfuncs->mms_billingmodule_init == NULL ||
|
|
|
|
m->mms_billfuncs->mms_billmsg == NULL ||
|
|
|
|
m->mms_billfuncs->mms_billingmodule_fini == NULL ||
|
|
|
|
m->mms_billfuncs->mms_logcdr == NULL)
|
|
|
|
panic(0, "Missing or NULL functions in billing module!");
|
|
|
|
} else
|
|
|
|
m->mms_billfuncs = &mms_billfuncs; /* The default one. */
|
|
|
|
|
|
|
|
m->mms_bill_module_data = m->mms_billfuncs->mms_billingmodule_init(octstr_get_cstr(m->billing_params));
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->resolver_params = _mms_cfg_getx(cfg, grp,
|
2005-09-01 10:26:36 +00:00
|
|
|
octstr_imm("resolver-module-parameters"));
|
|
|
|
|
|
|
|
/* Get and load the resolver lib if any. */
|
2008-08-28 16:07:31 +00:00
|
|
|
if ((m->mms_resolvefuncs = _mms_load_module(cfg, grp, "resolver-library",
|
2006-10-27 14:27:30 +00:00
|
|
|
"mms_resolvefuncs",
|
|
|
|
&mms_resolvefuncs_shell)) != NULL) {
|
2005-09-01 10:26:36 +00:00
|
|
|
if (m->mms_resolvefuncs->mms_resolvermodule_init == NULL ||
|
|
|
|
m->mms_resolvefuncs->mms_resolve == NULL ||
|
|
|
|
m->mms_resolvefuncs->mms_resolvermodule_fini == NULL)
|
|
|
|
panic(0, "Missing or NULL functions in resolver module!");
|
|
|
|
} else
|
|
|
|
m->mms_resolvefuncs = &mms_resolvefuncs; /* The default one. */
|
|
|
|
|
|
|
|
m->mms_resolver_module_data = m->mms_resolvefuncs->mms_resolvermodule_init(octstr_get_cstr(m->resolver_params));
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->detokenizer_params = _mms_cfg_getx(cfg, grp, octstr_imm("detokenizer-module-parameters"));
|
2005-09-01 10:26:36 +00:00
|
|
|
|
|
|
|
/* Get and load the detokenizer lib if any. */
|
2008-08-28 16:07:31 +00:00
|
|
|
if ((m->mms_detokenizefuncs = _mms_load_module(cfg, grp, "detokenizer-library",
|
2006-10-27 14:27:30 +00:00
|
|
|
"mms_detokenizefuncs",
|
|
|
|
&mms_detokenizefuncs_shell)) != NULL) {
|
2005-09-01 10:26:36 +00:00
|
|
|
if (m->mms_detokenizefuncs->mms_detokenizer_init == NULL ||
|
|
|
|
m->mms_detokenizefuncs->mms_detokenize == NULL ||
|
|
|
|
m->mms_detokenizefuncs->mms_gettoken == NULL ||
|
|
|
|
m->mms_detokenizefuncs->mms_detokenizer_fini == NULL)
|
|
|
|
panic(0, "Missing or NULL functions in detokenizer module!");
|
2007-09-10 08:36:39 +00:00
|
|
|
if (m->mms_detokenizefuncs->mms_detokenizer_init(octstr_get_cstr(m->detokenizer_params)) != 0)
|
2005-09-01 10:26:36 +00:00
|
|
|
panic(0, "Detokenizer module failed to initialize");
|
|
|
|
} else
|
|
|
|
m->mms_detokenizefuncs = NULL;
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if (mms_cfg_get_bool(cfg, grp, octstr_imm("allow-ip-type"), &m->allow_ip_type) < 0)
|
2005-09-01 10:26:36 +00:00
|
|
|
m->allow_ip_type = 1;
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
mms_cfg_get_bool(cfg, grp, octstr_imm("optimize-notification-size"),
|
2006-02-17 11:48:33 +00:00
|
|
|
&m->optimize_notification_size);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if (mms_cfg_get_bool(cfg, grp, octstr_imm("content-adaptation"), &m->content_adaptation) < 0)
|
2005-09-01 10:26:36 +00:00
|
|
|
m->content_adaptation = 1;
|
2007-08-09 09:32:49 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
if (mms_cfg_get_bool(cfg, grp, octstr_imm("send-dlr-on-fetch"), &m->dlr_on_fetch) < 0)
|
2007-08-09 09:32:49 +00:00
|
|
|
m->dlr_on_fetch = 0;
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-04-20 08:11:40 +00:00
|
|
|
|
|
|
|
octstr_destroy(qdir);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
|
|
|
/* Now load the VASP list. */
|
2006-02-17 11:48:33 +00:00
|
|
|
l = mms_cfg_get_multi(cfg, octstr_imm("mms-vasp"));
|
2008-09-08 11:50:24 +00:00
|
|
|
m->vasp_list = dict_create(53, NULL);
|
|
|
|
for (i=0, n=gwlist_len(l); i<n; i++) {
|
|
|
|
List *e = gwlist_create();
|
|
|
|
List *w = gwlist_create();
|
|
|
|
Octstr *x;
|
2008-11-12 16:48:47 +00:00
|
|
|
mCfgGrp *xgrp = gwlist_get(l, i);
|
|
|
|
mmsc_load_vasp_from_conf(m, xgrp, e, w);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
while ((x = gwlist_extract_first(e)) != NULL) {
|
|
|
|
mms_error(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
|
|
|
|
octstr_destroy(x);
|
|
|
|
}
|
2007-04-10 09:56:46 +00:00
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
while ((x = gwlist_extract_first(w)) != NULL) {
|
|
|
|
mms_warning(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
|
|
|
|
octstr_destroy(x);
|
2007-04-10 09:56:46 +00:00
|
|
|
}
|
2008-09-08 11:50:24 +00:00
|
|
|
gwlist_destroy(e, NULL);
|
|
|
|
gwlist_destroy(w, NULL);
|
2008-11-12 16:48:47 +00:00
|
|
|
|
|
|
|
mms_cfg_destroy_grp(cfg, xgrp);
|
2008-09-08 11:50:24 +00:00
|
|
|
}
|
|
|
|
gwlist_destroy(l, NULL);
|
2007-06-21 12:56:29 +00:00
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
/* Now load & start admin interface. */
|
|
|
|
|
|
|
|
mms_cfg_get_int(cfg, grp, octstr_imm("mmsc-admin-port"), &m->admin_port);
|
|
|
|
#ifdef HAVE_LIBSSL
|
|
|
|
mms_cfg_get_bool(cfg, grp, octstr_imm("admin-port-ssl"), &ssl);
|
|
|
|
#endif
|
|
|
|
m->admin_pass = mms_cfg_get(cfg, grp, octstr_imm("admin-password"));
|
|
|
|
|
|
|
|
m->admin_allow_ip = mms_cfg_get(cfg, grp, octstr_imm("admin-allow-ip"));
|
|
|
|
m->admin_deny_ip = mms_cfg_get(cfg, grp, octstr_imm("admin-deny-ip"));
|
|
|
|
|
|
|
|
if (m->admin_port > 0 &&
|
|
|
|
http_open_port(m->admin_port, ssl)< 0) {
|
|
|
|
mms_error(0, "mmsc", NULL, "Failed to start admin server on port %d: %s",
|
|
|
|
(int)m->admin_port, strerror(errno));
|
|
|
|
m->admin_port = -1;
|
|
|
|
} else if (m->admin_port > 0 &&
|
|
|
|
(m->admin_thread = gwthread_create((gwthread_func_t *)admin_handler, m)) < 0) {
|
|
|
|
mms_error(0, "mmsc", NULL, "Failed to start admin server thread: %s",
|
|
|
|
strerror(errno));
|
|
|
|
http_close_port(m->admin_port);
|
|
|
|
m->admin_port = -1;
|
|
|
|
} else if (m->admin_pass == NULL)
|
|
|
|
mms_warning(0, "mmsc", NULL, "Empty or no password supplied for admin port. All requests will be allowed!");
|
|
|
|
|
2008-11-12 16:48:47 +00:00
|
|
|
|
|
|
|
mms_cfg_destroy_grp(cfg, cgrp);
|
|
|
|
mms_cfg_destroy_grp(cfg, grp);
|
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mmsc_unload_vasp(MmscSettings *m, Octstr *id)
|
|
|
|
{
|
|
|
|
|
|
|
|
MmsVasp *mv = dict_remove(m->vasp_list, id);
|
|
|
|
|
|
|
|
if (mv == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (m->mms2email == mv)
|
|
|
|
m->mms2email = NULL;
|
|
|
|
|
|
|
|
if (m->mms2mobile == mv)
|
|
|
|
m->mms2mobile = NULL;
|
|
|
|
|
|
|
|
mv->delete_after = time(NULL) + DEFAULT_DELETE_AGE;
|
|
|
|
gwlist_append(m->vasp_del_list, mv);
|
|
|
|
|
|
|
|
delete_stale_vasps(m, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ERROR(fmt,...) do {if (errors) gwlist_append(errors, octstr_format((fmt), ##__VA_ARGS__));} while(0)
|
|
|
|
#define WARNING(fmt,...) do {if (warnings) gwlist_append(warnings, octstr_format((fmt), ##__VA_ARGS__));}while(0)
|
|
|
|
|
|
|
|
MmsVasp *mmsc_load_vasp_from_conf(MmscSettings *m, mCfgGrp *grp, List *errors, List *warnings)
|
|
|
|
{
|
|
|
|
mCfg *cfg = m->cfg;
|
|
|
|
MmsVasp *mv = gw_malloc(sizeof *mv), *ret = NULL;
|
|
|
|
Octstr *s;
|
|
|
|
int ibool = 0;
|
|
|
|
long short_code;
|
|
|
|
|
|
|
|
memset(mv, 0, sizeof mv[0]);
|
|
|
|
|
|
|
|
mv->throughput = -1;
|
|
|
|
mv->num_short_codes = 0;
|
|
|
|
|
|
|
|
mv->id = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-id"));
|
|
|
|
|
|
|
|
if (mms_cfg_get_int(cfg, grp, octstr_imm("short-code"), &short_code) == 0) {
|
|
|
|
WARNING("'short-code' is deprecated, please use 'short-codes'");
|
|
|
|
mv->num_short_codes = 1;
|
|
|
|
mv->short_codes = gw_malloc(sizeof mv->short_codes[0]);
|
|
|
|
mv->short_codes[0] = short_code;
|
|
|
|
} else if ((s = mms_cfg_get(cfg, grp, octstr_imm("short-codes"))) != NULL) {
|
|
|
|
List *l = octstr_split(s, octstr_imm(";"));
|
|
|
|
Octstr *x;
|
|
|
|
mv->short_codes = gw_malloc((gwlist_len(l) + 1) * sizeof mv->short_codes[0]);
|
|
|
|
|
|
|
|
while ((x = gwlist_extract_first(l)) != NULL) {
|
|
|
|
if ((short_code = strtoul(octstr_get_cstr(x), NULL, 10)) == 0 &&
|
|
|
|
(errno == EINVAL || errno == ERANGE))
|
|
|
|
ERROR("Invalid short-code format: %S", x);
|
|
|
|
else
|
|
|
|
mv->short_codes[mv->num_short_codes++] = short_code;
|
|
|
|
octstr_destroy(x);
|
2005-10-25 10:55:01 +00:00
|
|
|
}
|
2008-09-08 11:50:24 +00:00
|
|
|
gwlist_destroy(l, NULL);
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mv->num_short_codes == 0) {
|
|
|
|
ERROR("No valid short codes defined, VASP cannot be loaded");
|
|
|
|
free_vasp(mv);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("throughput"))) != NULL) {
|
|
|
|
mv->throughput = atof(octstr_get_cstr(s));
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
mv->vasp_username = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-username"));
|
|
|
|
mv->vasp_password = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-password"));
|
|
|
|
|
|
|
|
mv->vasp_url = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-url"));
|
|
|
|
|
|
|
|
s = _mms_cfg_getx(cfg, grp, octstr_imm("type"));
|
|
|
|
|
|
|
|
if (octstr_case_compare(s, octstr_imm("soap")) == 0)
|
|
|
|
mv->type = SOAP_VASP;
|
|
|
|
else if (octstr_case_compare(s, octstr_imm("eaif")) == 0)
|
|
|
|
mv->type = EAIF_VASP;
|
|
|
|
else
|
|
|
|
mv->type = NONE_VASP;
|
|
|
|
octstr_destroy(s);
|
|
|
|
|
|
|
|
mv->ver.major = mv->ver.minor1 = mv->ver.minor2 = 0;
|
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mm7-version"))) != NULL &&
|
|
|
|
octstr_len(s) > 0)
|
|
|
|
sscanf(octstr_get_cstr(s), "%d.%d.%d", &mv->ver.major, &mv->ver.minor1, &mv->ver.minor2);
|
|
|
|
else {
|
|
|
|
if (mv->type == SOAP_VASP) {
|
|
|
|
mv->ver.major = MAJOR_VERSION(DEFAULT_MM7_VERSION);
|
|
|
|
mv->ver.minor1 = MINOR1_VERSION(DEFAULT_MM7_VERSION);
|
|
|
|
mv->ver.minor2 = MINOR2_VERSION(DEFAULT_MM7_VERSION);
|
|
|
|
} else if (mv->type == EAIF_VASP) {
|
|
|
|
mv->ver.major = 3;
|
|
|
|
mv->ver.minor1 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
octstr_destroy(s);
|
|
|
|
|
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mm7-soap-xmlns"))) != NULL) {
|
|
|
|
strncpy(mv->ver.xmlns, octstr_get_cstr(s), sizeof mv->ver.xmlns);
|
2007-08-06 11:57:15 +00:00
|
|
|
|
2008-09-08 11:50:24 +00:00
|
|
|
mv->ver.xmlns[-1 + sizeof mv->ver.xmlns] = 0; /* NULL terminate, just in case. */
|
|
|
|
octstr_destroy(s);
|
|
|
|
} else
|
|
|
|
mv->ver.xmlns[0] = 0;
|
|
|
|
|
|
|
|
mv->ver.use_mm7_namespace = 1;
|
|
|
|
mms_cfg_get_bool(cfg, grp, octstr_imm("use-mm7-soap-namespace-prefix"), &mv->ver.use_mm7_namespace);
|
|
|
|
|
|
|
|
/* Set the handler vasp accounts. */
|
|
|
|
if (mms_cfg_get_bool(cfg, grp, octstr_imm("mms-to-email-handler"), &ibool) == 0 &&
|
|
|
|
ibool) {
|
|
|
|
if (m->mms2email)
|
|
|
|
WARNING("mms-to-email handler VASP res-et!.");
|
|
|
|
m->mms2email = mv;
|
|
|
|
}
|
|
|
|
if (mms_cfg_get_bool(cfg, grp, octstr_imm("mms-to-local-copy-handler"), &ibool) == 0 &&
|
|
|
|
ibool) {
|
|
|
|
if (m->mms2mobile)
|
|
|
|
WARNING("mms-to-mobile copy handler VASP re-set.");
|
|
|
|
m->mms2mobile = mv;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("send-uaprof"))) != NULL){
|
|
|
|
if (octstr_str_case_compare(s, "url") == 0)
|
|
|
|
mv->send_uaprof = UAProf_URL;
|
|
|
|
else if (octstr_str_case_compare(s, "ua") == 0)
|
|
|
|
mv->send_uaprof = UAProf_UA;
|
|
|
|
else {
|
|
|
|
WARNING("unknown send-uaprof value '%s'. Must be \"ua\" or \"url\"!",
|
|
|
|
octstr_get_cstr(s));
|
|
|
|
mv->send_uaprof = UAProf_None;
|
2007-08-06 11:57:15 +00:00
|
|
|
}
|
2008-09-08 11:50:24 +00:00
|
|
|
octstr_destroy(s);
|
2005-09-01 10:26:36 +00:00
|
|
|
}
|
2008-09-08 11:50:24 +00:00
|
|
|
mv->stats.start_time = time(NULL);
|
|
|
|
|
|
|
|
if (dict_put_once(m->vasp_list, mv->id, mv) == 0) {
|
2009-01-12 15:12:02 +00:00
|
|
|
ERROR("Failed to load vasp [%S]. ID is not unique!", mv->id);
|
2008-09-08 11:50:24 +00:00
|
|
|
free_vasp(mv);
|
|
|
|
} else
|
|
|
|
ret = mv;
|
|
|
|
|
|
|
|
done:
|
|
|
|
return ret;
|
2005-09-01 10:26:36 +00:00
|
|
|
}
|
|
|
|
|
2007-03-20 16:43:44 +00:00
|
|
|
List *mms_proxy_relays(mCfg *cfg, Octstr *myhostname)
|
2005-09-01 10:26:36 +00:00
|
|
|
{
|
2006-02-17 11:48:33 +00:00
|
|
|
List *gl = mms_cfg_get_multi(cfg, octstr_imm("mmsproxy"));
|
2005-09-01 10:26:36 +00:00
|
|
|
int i, n;
|
2006-10-12 15:21:46 +00:00
|
|
|
List *l = gwlist_create();
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0, n = gwlist_len(gl); i < n; i++) {
|
|
|
|
mCfgGrp *grp = gwlist_get(gl, i);
|
2005-09-01 10:26:36 +00:00
|
|
|
MmsProxyRelay *m = gw_malloc(sizeof *m);
|
2008-05-13 10:53:01 +00:00
|
|
|
Octstr *s;
|
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->host = _mms_cfg_getx(cfg, grp, octstr_imm("host"));
|
|
|
|
m->name = _mms_cfg_getx(cfg, grp, octstr_imm("name"));
|
|
|
|
m->allowed_prefix = _mms_cfg_getx(cfg, grp, octstr_imm("allowed-prefix"));
|
|
|
|
m->denied_prefix = _mms_cfg_getx(cfg, grp, octstr_imm("denied-prefix"));
|
|
|
|
if (mms_cfg_get_bool(cfg, grp, octstr_imm("confirmed-delivery"), &m->confirmed_mm4) < 0)
|
2007-03-20 16:43:44 +00:00
|
|
|
m->confirmed_mm4 = 1;
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2008-08-28 16:07:31 +00:00
|
|
|
m->sendmail = mms_cfg_get(cfg, grp, octstr_imm("send-mail-prog"));
|
|
|
|
m->unified_prefix = mms_cfg_get(cfg, grp, octstr_imm("unified-prefix"));
|
|
|
|
if ((s = mms_cfg_get(cfg, grp, octstr_imm("strip-prefixes"))) != NULL) {
|
2008-05-13 10:53:01 +00:00
|
|
|
m->strip_prefixes = octstr_split(s, octstr_imm(";"));
|
|
|
|
octstr_destroy(s);
|
|
|
|
} else
|
|
|
|
m->strip_prefixes = NULL;
|
|
|
|
|
2007-03-20 16:43:44 +00:00
|
|
|
if (octstr_compare(m->host, myhostname) == 0)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mmsc", NULL,"MMSC Config: Found MM4 Proxy %s with same hostname as local host!",
|
2007-03-20 16:43:44 +00:00
|
|
|
octstr_get_cstr(m->name));
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(l, m);
|
2008-11-12 16:48:47 +00:00
|
|
|
|
|
|
|
mms_cfg_destroy_grp(cfg, grp);
|
2005-09-01 10:26:36 +00:00
|
|
|
}
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(gl, NULL);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
Octstr *mms_makefetchurl(char *qf, Octstr *token, int loc,
|
|
|
|
Octstr *to,
|
|
|
|
MmscSettings *settings)
|
|
|
|
{
|
|
|
|
Octstr *url = octstr_create("");
|
|
|
|
Octstr *host_alias = settings->host_alias;
|
|
|
|
Octstr *hstr;
|
|
|
|
Octstr *endtoken, *x;
|
|
|
|
|
|
|
|
MmsDetokenizerFuncStruct *tfs = settings->mms_detokenizefuncs;
|
|
|
|
|
|
|
|
if (host_alias && octstr_len(host_alias) > 0)
|
|
|
|
hstr = octstr_duplicate(host_alias);
|
|
|
|
else
|
|
|
|
hstr = octstr_format("%S:%d",
|
|
|
|
settings->hostname, settings->port);
|
|
|
|
|
|
|
|
octstr_format_append(url, "http://%S/%s@%d",
|
|
|
|
hstr,
|
|
|
|
qf, loc);
|
|
|
|
|
|
|
|
if (tfs && tfs->mms_gettoken) { /* we append the recipient token or we append the message token. */
|
|
|
|
endtoken = tfs->mms_gettoken(to);
|
|
|
|
if (!endtoken)
|
|
|
|
endtoken = octstr_imm("x");
|
|
|
|
} else {
|
|
|
|
if (!token)
|
|
|
|
endtoken = octstr_imm("x");
|
|
|
|
else
|
|
|
|
endtoken = octstr_duplicate(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
x = octstr_duplicate(endtoken); /* might be immutable, so we duplicate it. */
|
|
|
|
octstr_url_encode(x);
|
|
|
|
octstr_format_append(url, "/%S", x);
|
|
|
|
|
|
|
|
octstr_destroy(endtoken);
|
|
|
|
octstr_destroy(x);
|
|
|
|
octstr_destroy(hstr);
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2008-12-09 03:35:26 +00:00
|
|
|
static Octstr *xfind_one_header(List *req_hdrs, List *hdr_names)
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i<gwlist_len(hdr_names); i++) {
|
|
|
|
Octstr *s = gwlist_get(hdr_names, i);
|
|
|
|
Octstr *x = s ? http_header_value(req_hdrs, s) : NULL;
|
|
|
|
|
|
|
|
if (x)
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2006-05-08 11:19:38 +00:00
|
|
|
Octstr *mms_find_sender_msisdn(Octstr *send_url,
|
|
|
|
Octstr *ip,
|
|
|
|
List *request_hdrs,
|
2008-12-09 03:35:26 +00:00
|
|
|
List *msisdn_header,
|
|
|
|
List *requestip_header,
|
2005-09-01 10:26:36 +00:00
|
|
|
MmsDetokenizerFuncStruct* detokenizerfuncs)
|
|
|
|
{
|
|
|
|
/* Either we have a WAP gateway header as defined, or we look for
|
|
|
|
* last part of url, pass it to detokenizer lib if defined, and back comes our number.
|
|
|
|
*/
|
|
|
|
|
2008-12-09 03:35:26 +00:00
|
|
|
Octstr *phonenum = xfind_one_header(request_hdrs,
|
|
|
|
msisdn_header);
|
2005-09-01 10:26:36 +00:00
|
|
|
|
2007-09-10 08:36:39 +00:00
|
|
|
if (phonenum == NULL || octstr_len(phonenum) == 0) {
|
2005-09-01 10:26:36 +00:00
|
|
|
List *l = octstr_split(send_url, octstr_imm("/"));
|
2007-09-10 08:36:39 +00:00
|
|
|
int len = gwlist_len(l);
|
2008-12-09 03:35:26 +00:00
|
|
|
Octstr *xip = xfind_one_header(request_hdrs,
|
|
|
|
requestip_header);
|
2006-05-08 11:19:38 +00:00
|
|
|
if (xip == NULL)
|
|
|
|
xip = ip ? octstr_duplicate(ip) : NULL;
|
2007-08-30 16:35:45 +00:00
|
|
|
if (detokenizerfuncs && (len > 1 || xip))
|
2007-09-10 08:36:39 +00:00
|
|
|
phonenum = detokenizerfuncs->mms_detokenize(len > 1 ? gwlist_get(l, len - 1) : send_url,
|
2006-05-08 13:25:02 +00:00
|
|
|
xip);
|
2007-08-29 13:33:11 +00:00
|
|
|
|
|
|
|
gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy);
|
|
|
|
octstr_destroy(xip);
|
2005-09-01 10:26:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return phonenum;
|
|
|
|
}
|
2006-05-08 11:19:38 +00:00
|
|
|
|
2008-12-09 03:35:26 +00:00
|
|
|
Octstr *mms_find_sender_ip(List *request_hdrs, List *ip_header, Octstr *ip, int *isv6)
|
2006-05-08 11:19:38 +00:00
|
|
|
{
|
|
|
|
Octstr *xip;
|
|
|
|
/* Look in the headers, if none is defined, return actual IP */
|
2008-12-09 03:35:26 +00:00
|
|
|
Octstr *client_ip = xfind_one_header(request_hdrs, ip_header);
|
2006-05-08 11:19:38 +00:00
|
|
|
char *s;
|
|
|
|
|
|
|
|
xip = client_ip ? client_ip : octstr_duplicate(ip);
|
|
|
|
|
|
|
|
s = octstr_get_cstr(xip);
|
|
|
|
|
|
|
|
/* Crude test for ipv6 */
|
|
|
|
*isv6 = (index(s, ':') != NULL);
|
|
|
|
return xip;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mms_decodefetchurl(Octstr *fetch_url,
|
|
|
|
Octstr **qf, Octstr **token, int *loc)
|
|
|
|
{
|
|
|
|
Octstr *xfurl = octstr_duplicate(fetch_url);
|
|
|
|
int i, j, n;
|
|
|
|
char *s, *p;
|
|
|
|
|
|
|
|
for (i = 0, n = 0, s = octstr_get_cstr(xfurl);
|
|
|
|
i < octstr_len(xfurl); i++)
|
|
|
|
if (s[i] == '/')
|
|
|
|
n++;
|
|
|
|
if (n < 2) /* We need at least two slashes. */
|
|
|
|
octstr_append_char(xfurl, '/');
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
n = octstr_len(xfurl);
|
|
|
|
s = octstr_get_cstr(xfurl);
|
|
|
|
|
|
|
|
p = strrchr(s, '/'); /* Find last slash. */
|
|
|
|
if (p)
|
|
|
|
i = (p - s) - 1;
|
|
|
|
else
|
|
|
|
i = n-1;
|
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
while (i>0 && s[i] != '/')
|
|
|
|
i--; /* Go back, find first slash */
|
|
|
|
if (i>=0 && s[i] == '/')
|
|
|
|
i++;
|
|
|
|
|
|
|
|
/* Now we have qf, find its end. */
|
|
|
|
|
|
|
|
j = i;
|
|
|
|
while (j<n && s[j] != '/')
|
|
|
|
j++; /* Skip to next slash. */
|
|
|
|
|
|
|
|
*qf = octstr_copy(fetch_url, i, j-i);
|
|
|
|
|
|
|
|
if (j<n)
|
|
|
|
*token = octstr_copy(fetch_url, j + 1, n - (j+1));
|
|
|
|
else
|
|
|
|
*token = octstr_create("");
|
|
|
|
octstr_destroy(xfurl);
|
|
|
|
|
|
|
|
/* Now get loc out of qf. */
|
|
|
|
*loc = MMS_LOC_MQUEUE;
|
|
|
|
i = octstr_search_char(*qf, '@', 0);
|
|
|
|
if (i >= 0) {
|
|
|
|
long l;
|
|
|
|
int j = octstr_parse_long(&l, *qf, i+1, 10);
|
|
|
|
if (j > 0)
|
|
|
|
*loc = l;
|
|
|
|
octstr_delete(*qf, i, octstr_len(*qf));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int mms_ind_send(Octstr *prov_cmd, Octstr *to)
|
|
|
|
{
|
|
|
|
Octstr *tmp;
|
|
|
|
Octstr *s;
|
|
|
|
int res = 1;
|
|
|
|
|
|
|
|
if (prov_cmd == NULL ||
|
|
|
|
octstr_len(prov_cmd) == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
tmp = octstr_duplicate(to);
|
|
|
|
escape_shell_chars(tmp);
|
|
|
|
s = octstr_format("%S %S", prov_cmd, tmp);
|
|
|
|
octstr_destroy(tmp);
|
|
|
|
|
|
|
|
if (s) {
|
|
|
|
int x = system(octstr_get_cstr(s));
|
|
|
|
int y = WEXITSTATUS(x);
|
|
|
|
|
|
|
|
if (x < 0) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_error(0, "mmsc", NULL, "Checking MMS Ind.Send: Failed to run command %s!",
|
2006-05-08 11:19:38 +00:00
|
|
|
octstr_get_cstr(s));
|
|
|
|
res = 1;
|
|
|
|
} else if (y != 0 && y != 1)
|
|
|
|
res = -1;
|
|
|
|
else
|
|
|
|
res = y;
|
|
|
|
octstr_destroy(s);
|
|
|
|
} else
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mmsc", NULL, "Checking MMS Ind.Send: Failed call to compose command [%s] ",
|
2006-05-08 11:19:38 +00:00
|
|
|
octstr_get_cstr(prov_cmd));
|
|
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2007-08-08 05:38:20 +00:00
|
|
|
void notify_prov_server(char *cmd, char *from, char *event, char *arg, Octstr *msgid,
|
|
|
|
Octstr *ua, Octstr *uaprof)
|
2006-05-08 11:19:38 +00:00
|
|
|
{
|
|
|
|
Octstr *s;
|
2007-08-08 05:38:20 +00:00
|
|
|
Octstr *tmp, *tmp2, *tmp3, *tmp4;
|
2006-05-08 11:19:38 +00:00
|
|
|
|
|
|
|
if (cmd == NULL || cmd[0] == '\0')
|
|
|
|
return;
|
2007-08-08 05:38:20 +00:00
|
|
|
|
|
|
|
gw_assert(from);
|
|
|
|
gw_assert(cmd);
|
|
|
|
gw_assert(event);
|
|
|
|
|
|
|
|
tmp = octstr_create(from);
|
|
|
|
tmp2 = msgid ? octstr_duplicate(msgid) : octstr_create("");
|
|
|
|
tmp3 = ua ? octstr_duplicate(ua) : octstr_create("");
|
|
|
|
tmp4 = uaprof ? octstr_duplicate(uaprof) : octstr_create("");
|
|
|
|
|
2006-05-08 11:19:38 +00:00
|
|
|
escape_shell_chars(tmp);
|
2006-07-27 10:37:10 +00:00
|
|
|
escape_shell_chars(tmp2);
|
2007-08-08 05:38:20 +00:00
|
|
|
escape_shell_chars(tmp3);
|
|
|
|
escape_shell_chars(tmp4);
|
|
|
|
|
|
|
|
s = octstr_format("%s '%s' '%S' '%s' '%S' '%S' '%S'", cmd, event,
|
|
|
|
tmp, arg, tmp2, tmp3, tmp4);
|
|
|
|
|
|
|
|
system(octstr_get_cstr(s));
|
2006-07-27 10:37:10 +00:00
|
|
|
|
2007-08-08 05:38:20 +00:00
|
|
|
octstr_destroy(s);
|
2006-05-08 11:19:38 +00:00
|
|
|
octstr_destroy(tmp);
|
2006-07-27 10:37:10 +00:00
|
|
|
octstr_destroy(tmp2);
|
2007-08-08 05:38:20 +00:00
|
|
|
octstr_destroy(tmp3);
|
|
|
|
octstr_destroy(tmp4);
|
2006-05-08 11:19:38 +00:00
|
|
|
}
|
2008-09-08 11:50:24 +00:00
|
|
|
|
|
|
|
static void free_vasp(MmsVasp *m)
|
|
|
|
{
|
|
|
|
if (m == NULL)
|
|
|
|
return;
|
|
|
|
octstr_destroy(m->id);
|
|
|
|
octstr_destroy(m->vasp_username);
|
|
|
|
octstr_destroy(m->vasp_password);
|
|
|
|
octstr_destroy(m->vasp_url);
|
|
|
|
|
|
|
|
if (m->short_codes)
|
|
|
|
gw_free(m->short_codes);
|
|
|
|
|
|
|
|
gw_free(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void delete_stale_vasps(MmscSettings *settings, int delete_all)
|
|
|
|
{
|
|
|
|
MmsVasp *mv;
|
|
|
|
int n = gwlist_len(settings->vasp_del_list);
|
|
|
|
|
|
|
|
while (n-- > 0 &&
|
|
|
|
(mv = gwlist_extract_first(settings->vasp_del_list)) != NULL)
|
|
|
|
if (delete_all ||
|
|
|
|
mv->delete_after <= time(NULL))
|
|
|
|
free_vasp(mv);
|
|
|
|
else
|
|
|
|
gwlist_append(settings->vasp_del_list, mv); /* put it back. */
|
|
|
|
|
|
|
|
if (delete_all) {
|
|
|
|
gwlist_destroy(settings->vasp_del_list, NULL);
|
|
|
|
settings->vasp_del_list = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void append_vasp_status(Octstr *rbody, MmsVasp *m, List *warnings)
|
|
|
|
{
|
|
|
|
time_t t = time(NULL);
|
|
|
|
int i, n;
|
|
|
|
unsigned long tdiff;
|
|
|
|
char lbuf[128], ubuf[128], tmp[64], mm7ver[64] = "n/a";
|
|
|
|
|
|
|
|
char *typ;
|
|
|
|
|
|
|
|
|
|
|
|
if (m->type == SOAP_VASP) {
|
|
|
|
typ = "SOAP";
|
|
|
|
sprintf(mm7ver, "%d.%d.%d", m->ver.major, m->ver.minor1, m->ver.minor2);
|
|
|
|
} else if (m->type == EAIF_VASP) {
|
|
|
|
typ = "EAIF";
|
|
|
|
sprintf(mm7ver, EAIF_VERSION, m->ver.major, m->ver.minor1);
|
|
|
|
} else
|
|
|
|
typ = "none";
|
|
|
|
|
|
|
|
if (m->stats.last_pdu > 0) {
|
|
|
|
struct tm tm = gw_localtime(m->stats.last_pdu);
|
|
|
|
gw_strftime(lbuf,sizeof lbuf, "%x %X", &tm);
|
|
|
|
} else
|
|
|
|
strcpy(lbuf, "n/a");
|
|
|
|
|
|
|
|
/* Compute uptime */
|
|
|
|
tdiff = t - m->stats.start_time;
|
|
|
|
if (tdiff >= 24*3600) {/* we have some days */
|
|
|
|
sprintf(ubuf, "%ld days", tdiff/(24*3600));
|
|
|
|
|
|
|
|
tdiff %= 24*3600;
|
|
|
|
} else
|
|
|
|
ubuf[0] = 0;
|
|
|
|
|
|
|
|
if (tdiff >= 3600) {
|
|
|
|
long x = tdiff/3600;
|
|
|
|
sprintf(tmp, "%s%ld hrs", ubuf[0] ? " " : "", x);
|
|
|
|
strcat(ubuf, tmp);
|
|
|
|
tdiff %= 3600;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tdiff >= 60) {
|
|
|
|
sprintf(tmp, "%s%ld mins", ubuf[0] ? " " : "", tdiff/60);
|
|
|
|
strcat(ubuf, tmp);
|
|
|
|
tdiff %= 60;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tdiff > 0) {
|
|
|
|
sprintf(tmp, "%s%ld secs", ubuf[0] ? " " : "", tdiff);
|
|
|
|
strcat(ubuf, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m->throughput > 0)
|
|
|
|
sprintf(tmp, "%.2f", m->throughput);
|
|
|
|
else
|
|
|
|
sprintf(tmp, "n/a");
|
|
|
|
octstr_format_append(rbody, "<vasp id=\"%S\" type=\"%s\">\n "
|
|
|
|
"<vasp-url>%S</vasp-url>\n"
|
|
|
|
"<incoming-username>%S</incoming-username>\n"
|
|
|
|
"<throughput>%s</throughput>\n"
|
|
|
|
"<mm7-version>%s</mm7-version>\n"
|
|
|
|
"<send-ua-prof>%s</send-ua-prof>\n"
|
|
|
|
"<stats>\n"
|
|
|
|
"<uptime>%s</uptime>\n"
|
|
|
|
"<last-pdu>%s</last-pdu>\n"
|
|
|
|
"<outgoing><pdus>%ld</pdus><errors>%ld</errors></outgoing>\n"
|
|
|
|
"<incoming><pdus>%ld</pdus><errors>%ld</errors></incoming>\n"
|
|
|
|
"</stats>\n"
|
|
|
|
"<short-codes>\n" ,
|
|
|
|
m->id,
|
|
|
|
typ,
|
|
|
|
m->vasp_url,
|
|
|
|
m->vasp_username,
|
|
|
|
tmp,
|
|
|
|
mm7ver,
|
|
|
|
m->send_uaprof == UAProf_URL ?
|
|
|
|
"url" : (m->send_uaprof == UAProf_UA ? "user-agent" : "n/a"),
|
|
|
|
ubuf,
|
|
|
|
lbuf,
|
|
|
|
(long)m->stats.mt_pdus, (long)m->stats.mt_errors,
|
|
|
|
(long)m->stats.mo_pdus, (long)m->stats.mo_errors);
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i<m->num_short_codes; i++)
|
|
|
|
octstr_format_append(rbody, "<short-code>%ld</short-code>\n", m->short_codes[i]);
|
|
|
|
|
|
|
|
octstr_append_cstr(rbody, "</short-codes>\n");
|
|
|
|
|
|
|
|
for (i = 0, n = gwlist_len(warnings); i<n; i++)
|
|
|
|
octstr_format_append(rbody, "<warning>%S</warning>\n", gwlist_get(warnings, i));
|
|
|
|
|
|
|
|
octstr_append_cstr(rbody, "</vasp>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void admin_handler(MmscSettings *settings)
|
|
|
|
{
|
|
|
|
|
|
|
|
HTTPClient *client;
|
|
|
|
Octstr *ip;
|
|
|
|
List *headers;
|
|
|
|
Octstr *url;
|
|
|
|
Octstr *body;
|
|
|
|
List *cgivars;
|
|
|
|
Octstr *pass;
|
|
|
|
|
|
|
|
mms_info(0, "mmsc", NULL,"Admin Interface -- startup on port %d", (int)settings->admin_port);
|
|
|
|
|
|
|
|
while((client = http_accept_request(settings->admin_port,
|
|
|
|
&ip, &url, &headers,
|
|
|
|
&body, &cgivars)) != NULL) {
|
|
|
|
int flg = -1;
|
|
|
|
Octstr *rbody = NULL;
|
|
|
|
int rstatus = HTTP_OK;
|
|
|
|
|
|
|
|
if (!(flg = is_allowed_ip(settings->admin_allow_ip, settings->admin_deny_ip, ip)) ||
|
|
|
|
((pass = http_cgi_variable(cgivars, "password")) == NULL &&
|
|
|
|
settings->admin_pass != NULL) ||
|
|
|
|
(settings->admin_pass && octstr_compare(pass, settings->admin_pass) != 0)) {
|
|
|
|
mms_error(0, "mmsc", NULL, "Improper access to mmsbox admin interface from IP[%s]: %s",
|
|
|
|
octstr_get_cstr(ip),
|
|
|
|
flg ? "Invalid/empty password" : "IP not allowed");
|
|
|
|
if (flg) {/* means it is allowed by IP */
|
|
|
|
rstatus = HTTP_UNAUTHORIZED;
|
2009-01-12 15:12:02 +00:00
|
|
|
rbody = octstr_imm("<error>Auth failed</error>");
|
2008-09-08 11:50:24 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Octstr *vasp_id = http_cgi_variable(cgivars, "vasp-id");
|
|
|
|
List *l = NULL;
|
|
|
|
|
2008-10-01 13:33:15 +00:00
|
|
|
rbody = octstr_create("<?xml version='1.0'?>\n<mmsc>\n");
|
2008-09-08 11:50:24 +00:00
|
|
|
/* Command URI is one of: /status, /start, /stop.
|
|
|
|
* vasp-id is either empty (meaning ALL) or an ID of an existing VASPs connection.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (octstr_str_case_compare(url, "/start") == 0) {
|
|
|
|
mCfgGrp *m;
|
|
|
|
if (vasp_id == NULL)
|
|
|
|
l = mms_cfg_get_multi(settings->cfg, octstr_imm("mms-vasp"));
|
|
|
|
else if ((m = mms_get_multi_by_field(settings->cfg,
|
|
|
|
octstr_imm("mms-vasp"),
|
|
|
|
octstr_imm("vasp-id"),
|
|
|
|
vasp_id)) != NULL) {
|
|
|
|
l = gwlist_create();
|
|
|
|
gwlist_append(l, m);
|
|
|
|
}
|
|
|
|
/* Start MMS VASPs. */
|
|
|
|
|
|
|
|
while ((m = gwlist_extract_first(l)) != NULL) {
|
|
|
|
Octstr *x;
|
|
|
|
List *e = gwlist_create();
|
|
|
|
List *w = gwlist_create();
|
|
|
|
MmsVasp *mv = mmsc_load_vasp_from_conf(settings, m, e, w);
|
|
|
|
|
|
|
|
if (mv != NULL)
|
|
|
|
append_vasp_status(rbody, mv, w);
|
|
|
|
else if (gwlist_len(e) > 0)
|
|
|
|
while ((x = gwlist_extract_first(e)) != NULL) {
|
|
|
|
octstr_format_append(rbody,
|
2008-10-01 13:33:15 +00:00
|
|
|
"<load-vasp><error>%S</error></load-vasp>\n",
|
2008-09-08 11:50:24 +00:00
|
|
|
x);
|
|
|
|
octstr_destroy(x);
|
|
|
|
}
|
|
|
|
gwlist_destroy(e, (void *)octstr_destroy);
|
|
|
|
gwlist_destroy(w, (void *)octstr_destroy);
|
2008-11-12 16:48:47 +00:00
|
|
|
|
|
|
|
mms_cfg_destroy_grp(settings->cfg, m);
|
2008-09-08 11:50:24 +00:00
|
|
|
}
|
|
|
|
} else if (octstr_str_case_compare(url, "/stop") == 0) {
|
|
|
|
Octstr *x;
|
|
|
|
if (vasp_id == NULL)
|
|
|
|
l = dict_keys(settings->vasp_list);
|
|
|
|
else {
|
|
|
|
l = gwlist_create();
|
|
|
|
gwlist_append(l, octstr_duplicate(vasp_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((x = gwlist_extract_first(l)) != NULL) {
|
|
|
|
int ret = mmsc_unload_vasp(settings, x);
|
|
|
|
octstr_format_append(rbody,
|
|
|
|
"<unload-vasp><%s/></unload-vasp>\n",
|
|
|
|
ret == 0 ? "Success" : "Failed");
|
|
|
|
octstr_destroy(x);
|
|
|
|
}
|
|
|
|
} else if (octstr_str_case_compare(url, "/status") == 0) {
|
|
|
|
Octstr *x;
|
|
|
|
MmsVasp *mv;
|
|
|
|
if (vasp_id == NULL)
|
|
|
|
l = dict_keys(settings->vasp_list);
|
|
|
|
else {
|
|
|
|
l = gwlist_create();
|
|
|
|
gwlist_append(l, octstr_duplicate(vasp_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((x = gwlist_extract_first(l)) != NULL) {
|
|
|
|
if ((mv = dict_get(settings->vasp_list, x)) != NULL)
|
|
|
|
append_vasp_status(rbody, mv, NULL);
|
|
|
|
octstr_destroy(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gwlist_destroy(l, NULL);
|
2008-10-01 13:33:15 +00:00
|
|
|
|
|
|
|
octstr_append_cstr(rbody, "\n</mmsc>\n");
|
2008-09-08 11:50:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (rbody) {
|
|
|
|
List *rh = http_create_empty_headers();
|
|
|
|
http_header_add(rh, "Content-Type", "text/xml");
|
|
|
|
http_send_reply(client, rstatus, rh, rbody);
|
|
|
|
|
|
|
|
http_destroy_headers(rh);
|
|
|
|
|
|
|
|
} else
|
|
|
|
http_close_client(client);
|
|
|
|
|
|
|
|
octstr_destroy(rbody);
|
|
|
|
octstr_destroy(ip);
|
|
|
|
octstr_destroy(url);
|
|
|
|
octstr_destroy(body);
|
|
|
|
http_destroy_cgiargs(cgivars);
|
|
|
|
http_destroy_headers(headers);
|
|
|
|
}
|
|
|
|
|
|
|
|
mms_info(0, "mmsbox", NULL,"Admin Interface -- shuttind down on port %d", (int)settings->admin_port);
|
|
|
|
}
|