# HG changeset patch # User Mychaela Falconia # Date 1691221425 0 # Node ID 003660a57f99900c43ad73ec40add672539456ab # Parent 265b8103530c06cac88df00d8b604c2f18e6401a new program sms-gen-tpdu diff -r 265b8103530c -r 003660a57f99 .hgignore --- a/.hgignore Sat Aug 05 06:40:50 2023 +0000 +++ b/.hgignore Sat Aug 05 07:43:45 2023 +0000 @@ -3,3 +3,4 @@ \.[oa]$ ^enc-text/sms-encode-text$ +^gen-pdu/sms-gen-tpdu$ diff -r 265b8103530c -r 003660a57f99 Makefile --- a/Makefile Sat Aug 05 06:40:50 2023 +0000 +++ b/Makefile Sat Aug 05 07:43:45 2023 +0000 @@ -1,6 +1,6 @@ CC= gcc CFLAGS= -O2 -PROGDIR=enc-text +PROGDIR=enc-text gen-pdu LIBDIR= libcoding SUBDIR= ${PROGDIR} ${LIBDIR} @@ -9,6 +9,7 @@ all: ${SUBDIR} enc-text: libcoding +gen-pdu: libcoding ${SUBDIR}: FRC cd $@; ${MAKE} ${MFLAGS} CC=${CC} CFLAGS="${CFLAGS}" diff -r 265b8103530c -r 003660a57f99 gen-pdu/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen-pdu/Makefile Sat Aug 05 07:43:45 2023 +0000 @@ -0,0 +1,21 @@ +CC= gcc +CFLAGS= -O2 +PROG= sms-gen-tpdu +OBJS= auto_scts.o input.o main.o message.o settings.o +LIBS= ../libcoding/libcoding.a + +INSTALL_PREFIX= /opt/freecalypso + +INSTBIN=${INSTALL_PREFIX}/bin + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBS} + ${CC} ${CFLAGS} -o $@ ${OBJS} ${LIBS} + +install: ${PROG} + mkdir -p ${INSTBIN} + install -c ${PROG} ${INSTBIN} + +clean: + rm -f *.o *.out *errs ${PROG} diff -r 265b8103530c -r 003660a57f99 gen-pdu/auto_scts.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen-pdu/auto_scts.c Sat Aug 05 07:43:45 2023 +0000 @@ -0,0 +1,27 @@ +/* + * This module implements automatic generation of SC-Timestamp + * based on the current time. + */ + +#include +#include +#include + +extern u_char scts_buf[7]; +extern int scts_is_set; + +void +set_auto_scts() +{ + time_t unixtime; + struct tm *tm; + char timestr[32]; + + time(&unixtime); + tm = localtime(&unixtime); + sprintf(timestr, "%02d/%02d/%02d,%02d:%02d:%02d%+03d", + tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_gmtoff / (15*60)); + encode_gsm_sms_abstime(timestr, scts_buf); + scts_is_set = 1; +} diff -r 265b8103530c -r 003660a57f99 gen-pdu/error.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen-pdu/error.h Sat Aug 05 07:43:45 2023 +0000 @@ -0,0 +1,3 @@ +/* some definitions for error handling */ + +#define ERR_PREFIX "sms-gen-tpdu input line %d: " diff -r 265b8103530c -r 003660a57f99 gen-pdu/input.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen-pdu/input.c Sat Aug 05 07:43:45 2023 +0000 @@ -0,0 +1,113 @@ +/* + * This module implements input handling for sms-gen-tpdu. + */ + +#include +#include +#include +#include +#include +#include "error.h" + +extern char input_line[]; +extern int input_lineno; + +extern void set_sc_addr(); +extern void set_user_addr(); +extern void set_mr_byte(); +extern void set_pid_byte(); +extern void set_dcs(); +extern void set_scts(); +extern void cmd_msg_plain(); +extern void cmd_msg_udh(); + +static struct cmdtab { + char *cmd; + int minargs; + int maxargs; + void (*func)(); +} cmdtab[] = { + {"sc-addr", 1, 1, set_sc_addr}, + {"user-addr", 1, 1, set_user_addr}, + {"mr", 1, 1, set_mr_byte}, + {"pid", 1, 1, set_pid_byte}, + {"dcs", 2, 2, set_dcs}, + {"sc-ts", 1, 1, set_scts}, + {"msg", 1, 1, cmd_msg_plain}, + {"msg-udh", 1, 1, cmd_msg_udh}, + /* table search terminator */ + {0, 0, 0, 0} +}; + +void +process_input_line() +{ + char *argv[10]; + char *cp, **ap; + struct cmdtab *tp; + + cp = index(input_line, '\n'); + if (!cp) { + fprintf(stderr, ERR_PREFIX "missing newline\n", input_lineno); + exit(1); + } + for (cp = input_line; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + return; + argv[0] = cp; + while (*cp && !isspace(*cp)) + cp++; + if (*cp) + *cp++ = '\0'; + for (tp = cmdtab; tp->cmd; tp++) + if (!strcmp(tp->cmd, argv[0])) + break; + if (!tp->func) { + fprintf(stderr, ERR_PREFIX "invalid command \"%s\"\n", + input_lineno, argv[0]); + exit(1); + } + for (ap = argv + 1; ; ) { + while (isspace(*cp)) + cp++; + if (!*cp || *cp == '#') + break; + if (ap - argv - 1 >= tp->maxargs) { + fprintf(stderr, ERR_PREFIX "too many arguments\n", + input_lineno); + exit(1); + } + if (*cp == '"') { + *ap++ = ++cp; + for (;;) { + if (!*cp) { +unterm_qstring: fprintf(stderr, ERR_PREFIX + "unterminated quoted string\n", + input_lineno); + exit(1); + } + if (*cp == '"') + break; + if (*cp++ == '\\') { + if (!*cp) + goto unterm_qstring; + cp++; + } + } + *cp++ = '\0'; + } else { + *ap++ = cp; + while (*cp && !isspace(*cp)) + cp++; + if (*cp) + *cp++ = '\0'; + } + } + if (ap - argv - 1 < tp->minargs) { + fprintf(stderr, ERR_PREFIX "too few arguments\n", input_lineno); + exit(1); + } + *ap = 0; + tp->func(ap - argv, argv); +} diff -r 265b8103530c -r 003660a57f99 gen-pdu/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen-pdu/main.c Sat Aug 05 07:43:45 2023 +0000 @@ -0,0 +1,58 @@ +/* + * This C file is the main module for sms-gen-tpdu utility. + */ + +#include +#include +#include +#include +#include + +int dir_mo, include_sca; +u_char sc_addr[12], user_addr[12]; +u_char mr_byte, pid_byte, dcs_byte; +u_char scts_buf[7]; +int is_septet, scts_is_set; + +char input_line[512]; +int input_lineno; + +static void +init_defaults() +{ + sc_addr[0] = 0; + user_addr[0] = 0; + user_addr[1] = 0x80; + mr_byte = 0xFF; + pid_byte = 0; + dcs_byte = 0; + is_septet = 1; +} + +main(argc, argv) + char **argv; +{ + if (argc != 2) { +usage: fprintf(stderr, "usage: %s mo|mt|sc-mo|sc-mt\n", argv[0]); + exit(1); + } + if (!strcmp(argv[1], "mo")) { + dir_mo = 1; + include_sca = 0; + } else if (!strcmp(argv[1], "mt")) { + dir_mo = 0; + include_sca = 0; + } else if (!strcmp(argv[1], "sc-mo")) { + dir_mo = 1; + include_sca = 1; + } else if (!strcmp(argv[1], "sc-mt")) { + dir_mo = 0; + include_sca = 1; + } else + goto usage; + init_defaults(); + for (input_lineno = 1; fgets(input_line, sizeof input_line, stdin); + input_lineno++) + process_input_line(); + exit(0); +} diff -r 265b8103530c -r 003660a57f99 gen-pdu/message.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen-pdu/message.c Sat Aug 05 07:43:45 2023 +0000 @@ -0,0 +1,142 @@ +/* + * This module implements TPDU encoding of actual messages, after all + * settings have been captured. + */ + +#include +#include +#include +#include +#include +#include +#include "error.h" + +extern int dir_mo, include_sca; +extern u_char sc_addr[12], user_addr[12]; +extern u_char mr_byte, pid_byte, dcs_byte; +extern u_char scts_buf[7]; +extern int is_septet, scts_is_set; + +extern int input_lineno; + +static void +emit_first_octet(udhi) +{ + u_char fo; + + if (dir_mo) + fo = 1; + else + fo = 0; + if (udhi) + fo |= 0x40; + printf("%02X", fo); +} + +static void +make_pdu(udl, ud_buf, ud_octets, udhi) + u_char *ud_buf; + unsigned udl, ud_octets; +{ + if (include_sca) + emit_hex_out(sc_addr, sc_addr[0] + 1, stdout); + emit_first_octet(udhi); + if (dir_mo) + printf("%02X", mr_byte); + emit_hex_out(user_addr, ((user_addr[0] + 1) >> 1) + 2, stdout); + printf("%02X", pid_byte); + printf("%02X", dcs_byte); + if (!dir_mo) { + if (!scts_is_set) + set_auto_scts(); + emit_hex_out(scts_buf, 7, stdout); + } + printf("%02X", udl); + emit_hex_out(ud_buf, ud_octets, stdout); + putchar('\n'); +} + +static void +cmd_msg_common(arg, udhi) + char *arg; +{ + u_char input[160], ud7[160], octbuf[140]; + unsigned input_len, udhl, udhl1, udh_chars, plain_chars; + unsigned udl, udl_octets; + + for (input_len = 0; ; input_len++) { + while (isspace(*arg)) + arg++; + if (!*arg) + break; + if (!isxdigit(arg[0]) || !isxdigit(arg[1])) { + fprintf(stderr, ERR_PREFIX "invalid hex string\n", + input_lineno); + exit(1); + } + if (input_len >= 160) { +toolong: fprintf(stderr, ERR_PREFIX "hex string is too long\n", + input_lineno); + exit(1); + } + input[input_len] = (decode_hex_digit(arg[0]) << 4) | + decode_hex_digit(arg[1]); + arg += 2; + } + if (!is_septet && input_len > 140) + goto toolong; + if (udhi) { + if (!input_len) { + fprintf(stderr, ERR_PREFIX + "empty message is invalid with UDHI\n", + input_lineno); + exit(1); + } + udhl = input[0]; + udhl1 = udhl + 1; + if (udhl1 > input_len) { + fprintf(stderr, ERR_PREFIX "UDHL exceeds UD length\n", + input_lineno); + exit(1); + } + } + if (!is_septet) { + make_pdu(input_len, input, input_len, udhi); + return; + } + if (udhi) + udh_chars = (udhl1 * 8 + 6) / 7; + else { + udhl1 = 0; + udh_chars = 0; + } + plain_chars = input_len - udhl1; + udl = udh_chars + plain_chars; + if (udl > 160) { + fprintf(stderr, ERR_PREFIX + "message exceeds 160 septets after UDH\n", + input_lineno); + exit(1); + } + udl_octets = (udl * 7 + 7) / 8; + bzero(ud7, 160); + bcopy(input + udhl1, ud7 + udh_chars, plain_chars); + gsm7_pack(ud7, octbuf, udl_octets); + if (udhi) + bcopy(input, octbuf, udhl1); + make_pdu(udl, ud7, udl_octets, udhi); +} + +void +cmd_msg_plain(argc, argv) + char **argv; +{ + cmd_msg_common(argv[1], 0); +} + +void +cmd_msg_udh(argc, argv) + char **argv; +{ + cmd_msg_common(argv[1], 1); +} diff -r 265b8103530c -r 003660a57f99 gen-pdu/settings.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen-pdu/settings.c Sat Aug 05 07:43:45 2023 +0000 @@ -0,0 +1,129 @@ +/* + * This module implements functions for various settings that come before + * msg or msg-udh lines. + */ + +#include +#include +#include +#include +#include +#include "error.h" + +extern int dir_mo, include_sca; +extern u_char sc_addr[12], user_addr[12]; +extern u_char mr_byte, pid_byte, dcs_byte; +extern u_char scts_buf[7]; +extern int is_septet, scts_is_set; + +extern int input_lineno; + +void +set_sc_addr(argc, argv) + char **argv; +{ + int rc; + + if (!include_sca) { + fprintf(stderr, ERR_PREFIX + "sc-addr is not allowed in bare TPDU mode\n", + input_lineno); + exit(1); + } + rc = encode_phone_number_arg(argv[1], sc_addr, 0); + if (rc < 0) { + fprintf(stderr, ERR_PREFIX "invalid phone number argument\n", + input_lineno); + exit(1); + } +} + +void +set_user_addr(argc, argv) + char **argv; +{ + int rc; + + rc = encode_phone_number_arg(argv[1], user_addr, 1); + if (rc < 0) { + fprintf(stderr, ERR_PREFIX "invalid phone number argument\n", + input_lineno); + exit(1); + } +} + +void +set_mr_byte(argc, argv) + char **argv; +{ + char *endp; + + if (!dir_mo) { + fprintf(stderr, ERR_PREFIX "mr is not allowed in MT mode\n", + input_lineno); + exit(1); + } + mr_byte = strtoul(argv[1], &endp, 0); + if (*endp) { + fprintf(stderr, ERR_PREFIX "invalid byte value argument\n", + input_lineno); + exit(1); + } +} + +void +set_pid_byte(argc, argv) + char **argv; +{ + char *endp; + + pid_byte = strtoul(argv[1], &endp, 0); + if (*endp) { + fprintf(stderr, ERR_PREFIX "invalid byte value argument\n", + input_lineno); + exit(1); + } +} + +void +set_dcs(argc, argv) + char **argv; +{ + char *endp; + + dcs_byte = strtoul(argv[1], &endp, 0); + if (*endp) { + fprintf(stderr, ERR_PREFIX "invalid byte value argument\n", + input_lineno); + exit(1); + } + if (!strcmp(argv[2], "septet")) + is_septet = 1; + else if (!strcmp(argv[2], "octet")) + is_septet = 0; + else { + fprintf(stderr, ERR_PREFIX "invalid septet/octet mode kw\n", + input_lineno); + exit(1); + } +} + +void +set_scts(argc, argv) + char **argv; +{ + int rc; + + if (dir_mo) { + fprintf(stderr, ERR_PREFIX "sc-ts is not allowed in MO mode\n", + input_lineno); + exit(1); + } + rc = encode_gsm_sms_abstime(argv[1], scts_buf); + if (rc < 0) { + fprintf(stderr, ERR_PREFIX "invalid timestamp argument\n", + input_lineno); + exit(1); + } + scts_is_set = 1; +}