Skip to content

Commit

Permalink
gsm_sms: Display the full SCTS timestamp string
Browse files Browse the repository at this point in the history
Display the full TP-Service-Centre-Time-Stamp string.
Add separate fields for TP-Validity-Period and TP-Discharge-Time.
  • Loading branch information
stigbjorlykke committed Nov 21, 2024
1 parent 650186c commit 6061784
Showing 1 changed file with 211 additions and 55 deletions.
266 changes: 211 additions & 55 deletions epan/dissectors/packet-gsm_sms.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include <epan/proto_data.h>
#include "packet-e164.h"
#include <epan/asn1.h>
#include <epan/to_str.h>
#include <wsutil/time_util.h>
#include "packet-gsm_sms.h"
#include "packet-gsm_map.h"
#include "packet-sip.h"
Expand Down Expand Up @@ -190,16 +192,30 @@ static int hf_gsm_sms_formatting_mode_style_italic;
static int hf_gsm_sms_formatting_mode_style_underlined;
static int hf_gsm_sms_formatting_mode_style_strikethrough;
static int hf_gsm_sms_ie_identifier;
static int hf_gsm_sms_scts;
static int hf_gsm_sms_scts_year;
static int hf_gsm_sms_scts_month;
static int hf_gsm_sms_scts_day;
static int hf_gsm_sms_scts_hour;
static int hf_gsm_sms_scts_minutes;
static int hf_gsm_sms_scts_seconds;
static int hf_gsm_sms_scts_timezone;
static int hf_gsm_sms_vp_validity_period_absolute;
static int hf_gsm_sms_vp_validity_period_year;
static int hf_gsm_sms_vp_validity_period_month;
static int hf_gsm_sms_vp_validity_period_day;
static int hf_gsm_sms_vp_validity_period_hour;
static int hf_gsm_sms_vp_validity_period_minutes;
static int hf_gsm_sms_vp_validity_period_seconds;
static int hf_gsm_sms_vp_validity_period_timezone;
static int hf_gsm_sms_discharge_time;
static int hf_gsm_sms_discharge_time_year;
static int hf_gsm_sms_discharge_time_month;
static int hf_gsm_sms_discharge_time_day;
static int hf_gsm_sms_discharge_time_hour;
static int hf_gsm_sms_discharge_time_minutes;
static int hf_gsm_sms_discharge_time_seconds;
static int hf_gsm_sms_discharge_time_timezone;

/* Generated from convert_proto_tree_add_text.pl */
static int hf_gsm_sms_dis_field_udh_user_data_header_length;
Expand Down Expand Up @@ -919,53 +935,140 @@ dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, uint32_t offset, uint8_t oct,
}
}

static void
dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, uint32_t offset)
static char *
tp_scts_values(tvbuff_t *tvb, packet_info *pinfo, uint32_t offset, struct tm *tm_time,
nstime_t *abs_time, char *gmtoff_sign, uint16_t *gmtoff_hour, uint16_t *gmtoff_min)
{
char *time_str;
uint8_t oct;
uint16_t value;
char sign;

oct = tvb_get_uint8(tvb, offset);
value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
proto_tree_add_uint(tree, hf_gsm_sms_scts_year, tvb, offset, 1, value);
offset++;
oct = tvb_get_uint8(tvb, offset);
value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
proto_tree_add_uint(tree, hf_gsm_sms_scts_month, tvb, offset, 1, value);
offset++;
oct = tvb_get_uint8(tvb, offset);
value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
proto_tree_add_uint(tree, hf_gsm_sms_scts_day, tvb, offset, 1, value);
offset++;
oct = tvb_get_uint8(tvb, offset);
value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
proto_tree_add_uint(tree, hf_gsm_sms_scts_hour, tvb, offset, 1, value);
offset++;
oct = tvb_get_uint8(tvb, offset);
value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
proto_tree_add_uint(tree, hf_gsm_sms_scts_minutes, tvb, offset, 1, value);
offset++;
oct = tvb_get_uint8(tvb, offset);
value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
proto_tree_add_uint(tree, hf_gsm_sms_scts_seconds, tvb, offset, 1, value);
offset++;
memset(tm_time, 0, sizeof(struct tm));

oct = tvb_get_uint8(tvb, offset++);
tm_time->tm_year = 100 + (oct & 0x0f) * 10 + ((oct & 0xf0) >> 4);
oct = tvb_get_uint8(tvb, offset++);
tm_time->tm_mon = (oct & 0x0f) * 10 + ((oct & 0xf0) >> 4) - 1;
oct = tvb_get_uint8(tvb, offset++);
tm_time->tm_mday = (oct & 0x0f) * 10 + ((oct & 0xf0) >> 4);
oct = tvb_get_uint8(tvb, offset++);
tm_time->tm_hour = (oct & 0x0f) * 10 + ((oct & 0xf0) >> 4);
oct = tvb_get_uint8(tvb, offset++);
tm_time->tm_min = (oct & 0x0f) * 10 + ((oct & 0xf0) >> 4);
oct = tvb_get_uint8(tvb, offset++);
tm_time->tm_sec = (oct & 0x0f) * 10 + ((oct & 0xf0) >> 4);

tm_time->tm_isdst = -1;

oct = tvb_get_uint8(tvb, offset++);
*gmtoff_sign = (oct & 0x08) ? '-' : '+';
oct = (oct >> 4) + (oct & 0x07) * 10;
*gmtoff_hour = oct / 4;
*gmtoff_min = oct % 4 * 15;

oct = tvb_get_uint8(tvb, offset);
time_str = wmem_strdup_printf(pinfo->pool, "%04d-%02d-%02d %02d:%02d:%02d GMT%c%02d:%02d",
1900 + tm_time->tm_year, tm_time->tm_mon + 1, tm_time->tm_mday,
tm_time->tm_hour, tm_time->tm_min, tm_time->tm_sec,
*gmtoff_sign, *gmtoff_hour, *gmtoff_min);

sign = (oct & 0x08)?'-':'+';
oct = (oct >> 4) + (oct & 0x07) * 10;
abs_time->secs = mktime_utc(tm_time);
if (*gmtoff_sign == '+') {
abs_time->secs -= (*gmtoff_hour * 3600) + (*gmtoff_min * 60);
} else {
abs_time->secs += (*gmtoff_hour * 3600) + (*gmtoff_min * 60);
}
abs_time->nsecs = 0;

proto_tree_add_uint_format_value(tree, hf_gsm_sms_scts_timezone, tvb, offset, 1,
oct, "GMT %c %d hours %d minutes",
sign, oct / 4, oct % 4 * 15);
return time_str;
}

static uint32_t
dis_field_scts_aux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset)
{
proto_item *item;
proto_tree *subtree;
uint16_t gmtoff_hour, gmtoff_minute;
nstime_t abs_time;
struct tm tm_time;
char gmtoff_sign, *time_str;

time_str = tp_scts_values(tvb, pinfo, offset, &tm_time, &abs_time, &gmtoff_sign, &gmtoff_hour, &gmtoff_minute);
item = proto_tree_add_time_format_value(tree, hf_gsm_sms_scts, tvb, offset, 7, &abs_time, "%s", time_str);
subtree = proto_item_add_subtree(item, ett_scts);

proto_tree_add_uint(subtree, hf_gsm_sms_scts_year, tvb, offset++, 1, tm_time.tm_year - 100);
proto_tree_add_uint(subtree, hf_gsm_sms_scts_month, tvb, offset++, 1, tm_time.tm_mon + 1);
proto_tree_add_uint(subtree, hf_gsm_sms_scts_day, tvb, offset++, 1, tm_time.tm_mday);
proto_tree_add_uint(subtree, hf_gsm_sms_scts_hour, tvb, offset++, 1, tm_time.tm_hour);
proto_tree_add_uint(subtree, hf_gsm_sms_scts_minutes, tvb, offset++, 1, tm_time.tm_min);
proto_tree_add_uint(subtree, hf_gsm_sms_scts_seconds, tvb, offset++, 1, tm_time.tm_sec);

uint8_t tz = tvb_get_uint8(tvb, offset);
proto_tree_add_uint_format_value(subtree, hf_gsm_sms_scts_timezone, tvb, offset++, 1, tz,
"GMT %c %d hours %d minutes", gmtoff_sign, gmtoff_hour, gmtoff_minute);

return offset;
}

static uint32_t
dis_field_validity_period_aux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset)
{
proto_item *item;
proto_tree *subtree;
uint16_t gmtoff_hour, gmtoff_minute;
nstime_t abs_time;
struct tm tm_time;
char gmtoff_sign, *time_str;

time_str = tp_scts_values(tvb, pinfo, offset, &tm_time, &abs_time, &gmtoff_sign, &gmtoff_hour, &gmtoff_minute);
item = proto_tree_add_time_format_value(tree, hf_gsm_sms_vp_validity_period_absolute, tvb, offset, 7, &abs_time, "%s", time_str);
subtree = proto_item_add_subtree(item, ett_vp);

proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_year, tvb, offset++, 1, tm_time.tm_year - 100);
proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_month, tvb, offset++, 1, tm_time.tm_mon + 1);
proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_day, tvb, offset++, 1, tm_time.tm_mday);
proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_hour, tvb, offset++, 1, tm_time.tm_hour);
proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_minutes, tvb, offset++, 1, tm_time.tm_min);
proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_seconds, tvb, offset++, 1, tm_time.tm_sec);

uint8_t tz = tvb_get_uint8(tvb, offset);
proto_tree_add_uint_format_value(subtree, hf_gsm_sms_vp_validity_period_timezone, tvb, offset++, 1, tz,
"GMT %c %d hours %d minutes", gmtoff_sign, gmtoff_hour, gmtoff_minute);

return offset;
}

static uint32_t
dis_field_discharge_time_aux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset)
{
proto_item *item;
proto_tree *subtree;
uint16_t gmtoff_hour, gmtoff_minute;
nstime_t abs_time;
struct tm tm_time;
char gmtoff_sign, *time_str;

time_str = tp_scts_values(tvb, pinfo, offset, &tm_time, &abs_time, &gmtoff_sign, &gmtoff_hour, &gmtoff_minute);
item = proto_tree_add_time_format_value(tree, hf_gsm_sms_discharge_time, tvb, offset, 7, &abs_time, "%s", time_str);
subtree = proto_item_add_subtree(item, ett_dt);

proto_tree_add_uint(subtree, hf_gsm_sms_discharge_time_year, tvb, offset++, 1, tm_time.tm_year - 100);
proto_tree_add_uint(subtree, hf_gsm_sms_discharge_time_month, tvb, offset++, 1, tm_time.tm_mon + 1);
proto_tree_add_uint(subtree, hf_gsm_sms_discharge_time_day, tvb, offset++, 1, tm_time.tm_mday);
proto_tree_add_uint(subtree, hf_gsm_sms_discharge_time_hour, tvb, offset++, 1, tm_time.tm_hour);
proto_tree_add_uint(subtree, hf_gsm_sms_discharge_time_minutes, tvb, offset++, 1, tm_time.tm_min);
proto_tree_add_uint(subtree, hf_gsm_sms_discharge_time_seconds, tvb, offset++, 1, tm_time.tm_sec);

uint8_t tz = tvb_get_uint8(tvb, offset);
proto_tree_add_uint_format_value(subtree, hf_gsm_sms_discharge_time_timezone, tvb, offset++, 1, tz,
"GMT %c %d hours %d minutes", gmtoff_sign, gmtoff_hour, gmtoff_minute);

return offset;
}

/* 9.2.3.11 */
static void
dis_field_scts(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offset_p)
{
proto_tree *subtree;
uint32_t offset;
uint32_t length;

Expand All @@ -984,13 +1087,7 @@ dis_field_scts(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *of
return;
}

subtree = proto_tree_add_subtree(tree, tvb,
offset, 7, ett_scts, NULL,
"TP-Service-Centre-Time-Stamp");

dis_field_scts_aux(tvb, subtree, *offset_p);

*offset_p += 7;
*offset_p = dis_field_scts_aux(tvb, pinfo, tree, *offset_p);
}

/* 9.2.3.12 */
Expand Down Expand Up @@ -1160,11 +1257,7 @@ dis_field_vp(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offs
return;
}

subtree = proto_tree_add_subtree(tree, tvb,
offset, 7, ett_vp, NULL,
"TP-Validity-Period: absolute");

dis_field_scts_aux(tvb, subtree, *offset_p);
dis_field_validity_period_aux(tvb, pinfo, tree, *offset_p);

done = true;
break;
Expand All @@ -1186,7 +1279,6 @@ dis_field_vp(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offs
static void
dis_field_dt(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offset_p)
{
proto_tree *subtree;
uint32_t offset;
uint32_t length;

Expand All @@ -1205,13 +1297,7 @@ dis_field_dt(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offs
return;
}

subtree = proto_tree_add_subtree(tree, tvb,
offset, 7, ett_dt, NULL,
"TP-Discharge-Time");

dis_field_scts_aux(tvb, subtree, *offset_p);

*offset_p += 7;
*offset_p = dis_field_discharge_time_aux(tvb, pinfo, tree, *offset_p);
}

/* 9.2.3.14 */
Expand Down Expand Up @@ -3474,6 +3560,11 @@ proto_register_gsm_sms(void)
FT_UINT8, BASE_HEX, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_scts,
{ "TP-Service-Centre-Time-Stamp", "gsm_sms.scts",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_scts_year,
{ "Year", "gsm_sms.scts.year",
FT_UINT8, BASE_DEC, NULL, 0x0,
Expand Down Expand Up @@ -3509,6 +3600,26 @@ proto_register_gsm_sms(void)
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_vp_validity_period_absolute,
{ "TP-Validity-Period", "gsm_sms.vp.validity_period.absolute",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_vp_validity_period_year,
{ "Year", "gsm_sms.vp.validity_period.year",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_vp_validity_period_month,
{ "Month", "gsm_sms.vp.validity_period.month",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_vp_validity_period_day,
{ "Day", "gsm_sms.vp.validity_period.day",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_vp_validity_period_hour,
{ "Hour", "gsm_sms.vp.validity_period.hour",
FT_UINT8, BASE_DEC, NULL, 0x0,
Expand All @@ -3524,6 +3635,51 @@ proto_register_gsm_sms(void)
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_vp_validity_period_timezone,
{ "Timezone", "gsm_sms.vp.validity_period.timezone",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time,
{ "TP-Discharge-Time", "gsm_sms.discharge_time",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time_year,
{ "Year", "gsm_sms.discharge_time.year",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time_month,
{ "Month", "gsm_sms.discharge_time.month",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time_day,
{ "Day", "gsm_sms.discharge_time.day",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time_hour,
{ "Hour", "gsm_sms.discharge_time.hour",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time_minutes,
{ "Minutes", "gsm_sms.discharge_time.minutes",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time_seconds,
{ "Seconds", "gsm_sms.discharge_time.seconds",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_gsm_sms_discharge_time_timezone,
{ "Timezone", "gsm_sms.discharge_time.timezone",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},

/* Generated from convert_proto_tree_add_text.pl */
{ &hf_gsm_sms_dis_field_addr_length, { "Length", "gsm_sms.dis_field_addr.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
Expand Down

0 comments on commit 6061784

Please sign in to comment.