smpp: Parse and use SMPP-provided validity period
Before this patch, we always ignored any SMPP-provided validity period and used '0' which is now, and means it expires immediately. As SMPP allows for validity_period of NULL, use 7 days as SMSC default in such situations. Change-Id: Iad9f2697f045ed3bc0eb74c3a9730861f82e6c48 Closes: OS#5567
This commit is contained in:
parent
53e2e5fe70
commit
e6f1160046
|
@ -48,6 +48,8 @@ PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 1.5.0)
|
||||||
PKG_CHECK_MODULES(LIBOSMOMGCPCLIENT, libosmo-mgcp-client >= 1.9.0)
|
PKG_CHECK_MODULES(LIBOSMOMGCPCLIENT, libosmo-mgcp-client >= 1.9.0)
|
||||||
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.4.0)
|
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.4.0)
|
||||||
|
|
||||||
|
AC_CHECK_FUNC([timegm], [AC_DEFINE(HAVE_TIMEGM, 1, Define if libc implements timegm)])
|
||||||
|
|
||||||
old_LIBS=$LIBS
|
old_LIBS=$LIBS
|
||||||
AC_SEARCH_LIBS([sctp_send], [sctp], [
|
AC_SEARCH_LIBS([sctp_send], [sctp], [
|
||||||
AC_DEFINE(HAVE_LIBSCTP, 1, [Define 1 to enable SCTP support])
|
AC_DEFINE(HAVE_LIBSCTP, 1, [Define 1 to enable SCTP support])
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* OpenBSC SMPP 3.4 interface, SMSC-side implementation */
|
/* OpenBSC SMPP 3.4 interface, SMSC-side implementation */
|
||||||
|
|
||||||
/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
|
/* (C) 2012-2022 by Harald Welte <laforge@gnumonks.org>
|
||||||
*
|
*
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*
|
*
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <smpp34.h>
|
#include <smpp34.h>
|
||||||
#include <smpp34_structs.h>
|
#include <smpp34_structs.h>
|
||||||
|
@ -122,6 +123,8 @@ static int smpp34_submit_tlv_msg_payload(const struct tlv_t *t,
|
||||||
static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
|
static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
|
||||||
const struct submit_sm_t *submit)
|
const struct submit_sm_t *submit)
|
||||||
{
|
{
|
||||||
|
time_t t_now = time(NULL);
|
||||||
|
time_t t_validity_absolute;
|
||||||
const uint8_t *sms_msg = NULL;
|
const uint8_t *sms_msg = NULL;
|
||||||
unsigned int sms_msg_len = 0;
|
unsigned int sms_msg_len = 0;
|
||||||
struct vlr_subscr *dest;
|
struct vlr_subscr *dest;
|
||||||
|
@ -258,6 +261,12 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
|
||||||
sms->user_data_len = sms_msg_len;
|
sms->user_data_len = sms_msg_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_validity_absolute = smpp_parse_time_format((const char *) submit->validity_period, &t_now);
|
||||||
|
if (!t_validity_absolute)
|
||||||
|
sms->validity_minutes = 7 * 24 * 60; /* default: 7 days */
|
||||||
|
else
|
||||||
|
sms->validity_minutes = (t_validity_absolute - t_now) / 60;
|
||||||
|
|
||||||
*psms = sms;
|
*psms = sms;
|
||||||
return ESME_ROK;
|
return ESME_ROK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,7 @@ int smpp_vty_init(void);
|
||||||
|
|
||||||
int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode);
|
int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode);
|
||||||
|
|
||||||
|
time_t smpp_parse_time_format(const char *vp, time_t *t_now);
|
||||||
|
|
||||||
|
|
||||||
struct gsm_sms;
|
struct gsm_sms;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
|
/* (C) 2012-2022 by Harald Welte <laforge@gnumonks.org>
|
||||||
*
|
*
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*
|
*
|
||||||
|
@ -17,6 +17,9 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "smpp_smsc.h"
|
#include "smpp_smsc.h"
|
||||||
#include <osmocom/core/logging.h>
|
#include <osmocom/core/logging.h>
|
||||||
|
@ -59,3 +62,105 @@ unknown_mo:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* convert a 'struct tm' holding relative time to an absolute one by adding it to t_now */
|
||||||
|
static void relative2absolute(struct tm *tm, time_t t_now)
|
||||||
|
{
|
||||||
|
struct tm tm_now;
|
||||||
|
|
||||||
|
localtime_r(&t_now, &tm_now);
|
||||||
|
|
||||||
|
tm->tm_year += tm_now.tm_year;
|
||||||
|
tm->tm_mon += tm_now.tm_mon;
|
||||||
|
tm->tm_mday += tm_now.tm_mday;
|
||||||
|
tm->tm_hour += tm_now.tm_hour;
|
||||||
|
tm->tm_min += tm_now.tm_min;
|
||||||
|
tm->tm_sec += tm_now.tm_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_TIMEGM
|
||||||
|
/* for systems without a timegm() function, provide a reimplementation */
|
||||||
|
static time_t timegm(struct tm *tm)
|
||||||
|
{
|
||||||
|
const char *orig_tz = getenv("TZ");
|
||||||
|
time_t ret;
|
||||||
|
|
||||||
|
setenv("TZ", "UTC", 1);
|
||||||
|
|
||||||
|
ret = mktime(tm);
|
||||||
|
|
||||||
|
if (orig_tz)
|
||||||
|
setenv("TZ", orig_tz, 1);
|
||||||
|
else
|
||||||
|
unsetenv("TZ");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*! Parse a SMPP time format as defined in SMPP v3.4 7.1.1.
|
||||||
|
* \param[in] vp string containing the time as encoded in SMPP v3.4
|
||||||
|
* \param[in] t_now pointer to a time value for 'now'. Can be NULL, then we call time() ourselves.
|
||||||
|
* \returns time_t value in seconds since the epoch of the absolute decoded time */
|
||||||
|
time_t smpp_parse_time_format(const char *vp, time_t *t_now)
|
||||||
|
{
|
||||||
|
unsigned int year, month, day, hour, minute, second, tenth, gmt_off_quarter;
|
||||||
|
char plus_minus_relative;
|
||||||
|
int gmt_off_minutes;
|
||||||
|
struct tm tm;
|
||||||
|
time_t ret;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(&tm, 0, sizeof(tm));
|
||||||
|
|
||||||
|
if (vp[0] == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* YYMMDDhhmmsstnnp (where p can be -, + or R) */
|
||||||
|
rc = sscanf(vp, "%2u%2u%2u%2u%2u%2u%1u%2u%c", &year, &month, &day, &hour, &minute,
|
||||||
|
&second, &tenth, &gmt_off_quarter, &plus_minus_relative);
|
||||||
|
if (rc != 9)
|
||||||
|
return (time_t) -1;
|
||||||
|
|
||||||
|
tm.tm_year = year;
|
||||||
|
/* month handling differs between absolute/relative below... */
|
||||||
|
tm.tm_mday = day;
|
||||||
|
tm.tm_hour = hour;
|
||||||
|
tm.tm_min = minute;
|
||||||
|
tm.tm_sec = second;
|
||||||
|
tm.tm_isdst = 0;
|
||||||
|
|
||||||
|
switch (plus_minus_relative) {
|
||||||
|
case '+': /* time is in quarter hours advanced compared to UTC */
|
||||||
|
if (year < 70)
|
||||||
|
tm.tm_year += 100;
|
||||||
|
tm.tm_mon = month - 1;
|
||||||
|
gmt_off_minutes = 15 * gmt_off_quarter;
|
||||||
|
tm.tm_min -= gmt_off_minutes;
|
||||||
|
ret = timegm(&tm);
|
||||||
|
break;
|
||||||
|
case '-': /* time is in quarter hours retared compared to UTC */
|
||||||
|
if (year < 70)
|
||||||
|
tm.tm_year += 100;
|
||||||
|
tm.tm_mon = month - 1;
|
||||||
|
gmt_off_minutes = 15 * gmt_off_quarter;
|
||||||
|
tm.tm_min += gmt_off_minutes;
|
||||||
|
ret = timegm(&tm);
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
/* relative time */
|
||||||
|
tm.tm_mon = month;
|
||||||
|
if (t_now)
|
||||||
|
relative2absolute(&tm, *t_now);
|
||||||
|
else
|
||||||
|
relative2absolute(&tm, time(NULL));
|
||||||
|
/* here we do want local time, as we're passing local time in above! */
|
||||||
|
ret = mktime(&tm);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (time_t) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* (C) 2013 by Holger Hans Peter Freyther
|
* (C) 2013 by Holger Hans Peter Freyther
|
||||||
|
* (C) 2022 by Harald Welte <laforge@osmocom.org>
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -62,6 +63,41 @@ static void test_coding_scheme(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *smpp_time_tests[] = {
|
||||||
|
"\0",
|
||||||
|
"220517175524000+",
|
||||||
|
"220517175524000-",
|
||||||
|
"220517175524004+", /* 1 hour advanced compared to GMT */
|
||||||
|
"220517175524004-", /* 1 hour retarded compared to GMT */
|
||||||
|
"000000010000000R", /* 1 hour */
|
||||||
|
"000001000000000R", /* 1 day */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_smpp_parse_time_format(void)
|
||||||
|
{
|
||||||
|
time_t t_now = 1652745600; /* 2022-05-17 00:00:00 UTC */
|
||||||
|
char *orig_tz;
|
||||||
|
|
||||||
|
printf("Testing SMPP time format parser\n");
|
||||||
|
|
||||||
|
/* relative time format conversion depends on the local time */
|
||||||
|
orig_tz = getenv("TZ");
|
||||||
|
setenv("TZ", "UTC", 1);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ARRAY_SIZE(smpp_time_tests); i++) {
|
||||||
|
time_t t = smpp_parse_time_format(smpp_time_tests[i], &t_now);
|
||||||
|
char buf[32];
|
||||||
|
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", gmtime(&t));
|
||||||
|
printf("'%s': %ld == %s\n", smpp_time_tests[i], t, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orig_tz)
|
||||||
|
setenv("TZ", orig_tz, 1);
|
||||||
|
else
|
||||||
|
unsetenv("TZ");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static const struct log_info_cat smpp_mirror_default_categories[] = {
|
static const struct log_info_cat smpp_mirror_default_categories[] = {
|
||||||
[DSMPP] = {
|
[DSMPP] = {
|
||||||
.name = "DSMPP",
|
.name = "DSMPP",
|
||||||
|
@ -85,5 +121,7 @@ int main(int argc, char **argv)
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
log_set_print_category_hex(osmo_stderr_target, 0);
|
||||||
|
|
||||||
test_coding_scheme();
|
test_coding_scheme();
|
||||||
|
test_smpp_parse_time_format();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,9 @@
|
||||||
Testing coding scheme support
|
Testing coding scheme support
|
||||||
|
Testing SMPP time format parser
|
||||||
|
'': 0 == 1970-01-01 00:00:00
|
||||||
|
'220517175524000+': 1652810124 == 2022-05-17 17:55:24
|
||||||
|
'220517175524000-': 1652810124 == 2022-05-17 17:55:24
|
||||||
|
'220517175524004+': 1652806524 == 2022-05-17 16:55:24
|
||||||
|
'220517175524004-': 1652813724 == 2022-05-17 18:55:24
|
||||||
|
'000000010000000R': 1652749200 == 2022-05-17 01:00:00
|
||||||
|
'000001000000000R': 1652832000 == 2022-05-18 00:00:00
|
||||||
|
|
Loading…
Reference in New Issue