/* * Mbuni - Open Source MMS Gateway * * MMSC CFG: MMC configuration and misc. functions * * Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com * * Paul Bagyenda * * This program is free software, distributed under the terms of * the GNU General Public License, with a few exceptions granted (see LICENSE) */ #include #include #include #include #include #include #include #include #include #include "mmsc_cfg.h" #include "mms_queue.h" #define MAXQTRIES 100 #define BACKOFF_FACTOR 5*60 /* In seconds */ #define QUEUERUN_INTERVAL 15*60 /* 15 minutes. */ #define DEFAULT_EXPIRE 3600*24*7 /* One week */ #define MMS_PORT 8191 /* Default content fetch port. */ static void *load_module(CfgGroup *grp, char *config_key, char *symbolname) { Octstr *s; void *retval = NULL; s = cfg_get(grp, octstr_imm(config_key)); if (s) { void *x = dlopen(octstr_get_cstr(s), RTLD_LAZY); void *y = NULL; #ifdef __APPLE__ char sbuf[512]; sprintf(sbuf, "_%s", symbolname); #endif if (x == NULL || ((y = dlsym(x, symbolname)) == NULL #ifdef __APPLE__ /* fink version of dlsym has issues it seems. */ && (y = dlsym(x, sbuf)) == NULL #endif )) panic(0, "Error, unable to load dynamic libary (%s): " "libhandle is %s, funcs is %s, err=%s", octstr_get_cstr(s), x ? "OK" : "Not OK", y ? "OK" : "Not OK", dlerror()); else retval = y; octstr_destroy(s); } return retval; } MmscSettings *mms_load_mmsc_settings(Cfg *cfg, List **proxyrelays) { Octstr *s; List *l; CfgGroup *grp = cfg_get_single_group(cfg, octstr_imm("mmsbox")); CfgGroup *cgrp = cfg_get_single_group(cfg, octstr_imm("core")); MmscSettings *m = gw_malloc(sizeof *m); long port = -1; Octstr *from, *user, *pass; Octstr *qdir = NULL; int i, n; memset(m, 0, sizeof *m); mms_load_core_settings(cgrp); if (proxyrelays) *proxyrelays = mms_proxy_relays(cfg); s = _mms_cfg_getx(grp, octstr_imm("local-mmsc-domains")); if (s) { l = octstr_split(s, octstr_imm(",")); octstr_destroy(s); } else l = list_create(); m->local_domains = l; if (cfg_get_integer(&m->maxthreads, grp, octstr_imm("max-send-threads")) == -1) m->maxthreads = 10; m->unified_prefix = _mms_cfg_getx(grp, octstr_imm("unified-prefix")); m->local_prefix = _mms_cfg_getx(grp, octstr_imm("local-prefixes")); m->hostname = _mms_cfg_getx(grp, octstr_imm("hostname")); if (m->hostname == NULL || octstr_len(m->hostname) == 0) m->hostname = octstr_create("localhost"); m->name = _mms_cfg_getx(grp, octstr_imm("name")); m->host_alias = _mms_cfg_getx(grp, octstr_imm("host-alias")); m->sendmail = _mms_cfg_getx(grp, octstr_imm("send-mail-prog")); qdir = _mms_cfg_getx(grp, octstr_imm("storage-directory")); 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)); m->global_queuedir = octstr_format("%S/global", qdir); m->mm1_queuedir = octstr_format("%S/mm1", qdir); m->mm4_queuedir = octstr_format("%S/mm4", qdir); if (mms_init_queuedir(m->mm1_queuedir) < 0) panic(0, "Failed to initialise local queue directory: %s - %s!", octstr_get_cstr(m->mm1_queuedir), strerror(errno)); else if (mms_init_queuedir(m->global_queuedir) < 0) panic(0, "Failed to initialise global queue directory: %s - %s!", octstr_get_cstr(m->global_queuedir), strerror(errno)); else if (mms_init_queuedir(m->mm4_queuedir) < 0) panic(0, "Failed to initialise global queue directory: %s - %s!", octstr_get_cstr(m->mm4_queuedir), strerror(errno)); m->mmbox_rootdir = octstr_format("%S/mmbox", qdir); 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)); if (cfg_get_integer(&m->maxsendattempts, grp, octstr_imm("maximum-send-attempts")) == -1) m->maxsendattempts = MAXQTRIES; if (cfg_get_integer(&m->default_msgexpiry, grp, octstr_imm("default-message-expiry")) == -1) m->default_msgexpiry = DEFAULT_EXPIRE; s = _mms_cfg_getx(grp, octstr_imm("queue-run-interval")); if (!s || (m->queue_interval = atof(octstr_get_cstr(s))) <= 0) m->queue_interval = QUEUERUN_INTERVAL; if (cfg_get_integer(&m->send_back_off, grp, octstr_imm("send-attempt-back-off")) == -1) m->send_back_off = BACKOFF_FACTOR; /* Make send sms url. */ m->sendsms_url = _mms_cfg_getx(grp, octstr_imm("sendsms-url")); user = _mms_cfg_getx(grp, octstr_imm("sendsms-username")); pass = _mms_cfg_getx(grp, octstr_imm("sendsms-password")); from = cfg_get(grp, octstr_imm("sendsms-global-sender")); if (user && octstr_len(user) > 1) octstr_url_encode(user); if (pass && octstr_len(pass) > 1) octstr_url_encode(pass); if (from && octstr_len(from) > 1) octstr_url_encode(from); octstr_format_append(m->sendsms_url, (from && octstr_len(from) > 1) ? "?username=%S&password=%S&from=%S" : "?username=%S&password=%S", user, pass,from); m->system_user = octstr_format("system-user@%S", m->hostname); octstr_destroy(user); octstr_destroy(pass); if (from) octstr_destroy(from); cfg_get_integer(&port, grp, octstr_imm("mms-port")); m->port = (port > 0) ? port : MMS_PORT; m->mm7port = -1; cfg_get_integer(&m->mm7port, grp, octstr_imm("mm7-port")); m->allow_ip = _mms_cfg_getx(grp, octstr_imm("allow-ip")); m->deny_ip = _mms_cfg_getx(grp, octstr_imm("deny-ip")); m->email2mmsrelay_prefixes = _mms_cfg_getx(grp, octstr_imm("email2mms-relay-prefixes")); m->prov_notify = _mms_cfg_getx(grp,octstr_imm("prov-server-notify-script")); m->prov_getstatus = _mms_cfg_getx(grp,octstr_imm("prov-server-sub-status-script")); m->mms_notify_txt = _mms_cfg_getx(grp, octstr_imm("mms-notify-text")); m->mms_notify_unprov_txt = _mms_cfg_getx(grp, octstr_imm("mms-notify-unprovisioned-text")); m->mms_email_txt = _mms_cfg_getx(grp, octstr_imm("mms-to-email-txt")); m->mms_email_html = _mms_cfg_getx(grp, octstr_imm("mms-to-email-html")); m->mms_toolarge = _mms_cfg_getx(grp, octstr_imm("mms-message-too-large-txt")); m->wap_gw_msisdn_header = cfg_get(grp, octstr_imm("mms-client-msisdn-header")); if (!m->wap_gw_msisdn_header) m->wap_gw_msisdn_header = octstr_imm(XMSISDN_HEADER); m->wap_gw_ip_header = cfg_get(grp, octstr_imm("mms-client-ip-header")); if (!m->wap_gw_ip_header) m->wap_gw_ip_header = octstr_imm(XIP_HEADER); cfg_get_bool(&m->notify_unprovisioned, grp, octstr_imm("notify-unprovisioned")); m->billing_params = _mms_cfg_getx(grp, octstr_imm("billing-module-parameters")); /* Get and load the billing lib if any. */ if ((m->mms_billfuncs = load_module(grp, "billing-library", "mms_billfuncs"))) { 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)); m->resolver_params = _mms_cfg_getx(grp, octstr_imm("resolver-module-parameters")); /* Get and load the resolver lib if any. */ if ((m->mms_resolvefuncs = load_module(grp, "resolver-library", "mms_resolvefuncs"))) { 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)); m->detokenizer_params = _mms_cfg_getx(grp, octstr_imm("detokenizer-module-parameters")); /* Get and load the detokenizer lib if any. */ if ((m->mms_detokenizefuncs = load_module(grp, "detokenizer-library", "mms_detokenizefuncs"))) { 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!"); if (m->mms_detokenizefuncs->mms_detokenizer_init(octstr_get_cstr(m->detokenizer_params))) panic(0, "Detokenizer module failed to initialize"); } else m->mms_detokenizefuncs = NULL; if (cfg_get_bool(&m->allow_ip_type, grp, octstr_imm("allow-ip-type")) < 0) m->allow_ip_type = 1; cfg_get_bool(&m->optimize_notification_size, grp, octstr_imm("optimize-notification-size")); if (cfg_get_bool(&m->content_adaptation, grp, octstr_imm("content-adaptation")) < 0) m->content_adaptation = 1; if (qdir) octstr_destroy(qdir); /* Now load the VASP list. */ l = cfg_get_multi_group(cfg, octstr_imm("mms-vasp")); m->vasp_list = list_create(); for (i=0, n=list_len(l); iid = _mms_cfg_getx(grp, octstr_imm("vasp-id")); mv->short_code = -1; cfg_get_integer(&mv->short_code, grp, octstr_imm("short-code")); mv->vasp_username = _mms_cfg_getx(grp, octstr_imm("vasp-username")); mv->vasp_password = _mms_cfg_getx(grp, octstr_imm("vasp-password")); mv->vasp_url = _mms_cfg_getx(grp, octstr_imm("vasp-url")); mv->mmsc_username = _mms_cfg_getx(grp, octstr_imm("mmsc-username")); mv->mmsc_password = _mms_cfg_getx(grp, octstr_imm("mmsc-password")); s = _mms_cfg_getx(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); list_append(m->vasp_list, mv); } list_destroy(l, NULL); return m; } List *mms_proxy_relays(Cfg *cfg) { List *gl = cfg_get_multi_group(cfg, octstr_imm("mmsproxy")); int i, n; List *l = list_create(); for (i = 0, n = list_len(gl); i < n; i++) { CfgGroup *grp = list_get(gl, i); MmsProxyRelay *m = gw_malloc(sizeof *m); m->host = _mms_cfg_getx(grp, octstr_imm("host")); m->name = _mms_cfg_getx(grp, octstr_imm("name")); m->allowed_prefix = _mms_cfg_getx(grp, octstr_imm("allowed-prefix")); m->denied_prefix = _mms_cfg_getx(grp, octstr_imm("denied-prefix")); list_append(l, m); } list_destroy(gl, NULL); 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; } Octstr *mms_find_sender_msisdn(Octstr *send_url, List *request_hdrs, Octstr *msisdn_header, 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. */ Octstr *phonenum = http_header_value(request_hdrs, msisdn_header); if (!phonenum || octstr_len(phonenum) == 0) { List *l = octstr_split(send_url, octstr_imm("/")); if (l && list_len(l) > 1) { if (detokenizerfuncs) phonenum = detokenizerfuncs->mms_detokenize(list_get(l, list_len(l) - 1)); } if (l) list_destroy(l, (list_item_destructor_t *)octstr_destroy); } return phonenum; }