# HG changeset patch # User Mychaela Falconia # Date 1691126021 28800 # Node ID 9d6e8d99d2b1a86308ef9574388515c1343cf7c2 # Parent e1d7db9d734c1e1cf7b5e571d340f16c7dbe853c smpp-trx-sa: new program diff -r e1d7db9d734c -r 9d6e8d99d2b1 .hgignore --- a/.hgignore Thu Aug 03 10:00:33 2023 -0800 +++ b/.hgignore Thu Aug 03 21:13:41 2023 -0800 @@ -16,6 +16,8 @@ ^sip-out/themwi-sip-out$ +^smpp-trx-sa/smpp-trx-sa$ + ^utils/rtp-alloc-test$ ^utils/sip-out-test$ ^utils/sip-rx-test$ diff -r e1d7db9d734c -r 9d6e8d99d2b1 Makefile --- a/Makefile Thu Aug 03 10:00:33 2023 -0800 +++ b/Makefile Thu Aug 03 21:13:41 2023 -0800 @@ -1,7 +1,7 @@ CC= gcc CFLAGS= -O2 -PROGDIR=mgw mncc mtctest rtp-mgr sip-in sip-manual-out sip-out utils +PROGDIR=mgw mncc mtctest rtp-mgr sip-in sip-manual-out sip-out smpp-trx-sa utils LIBDIR= libnumdb liboutrt librtpalloc libsip libutil SUBDIR= ${PROGDIR} ${LIBDIR} @@ -14,6 +14,7 @@ sip-in: libnumdb libsip libutil sip-manual-out: librtpalloc libsip libutil sip-out: liboutrt libsip libutil +smpp-trx-sa: libutil utils: libnumdb librtpalloc libsip libutil ${SUBDIR}: FRC diff -r e1d7db9d734c -r 9d6e8d99d2b1 smpp-trx-sa/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smpp-trx-sa/Makefile Thu Aug 03 21:13:41 2023 -0800 @@ -0,0 +1,17 @@ +CC= gcc +CFLAGS= -O2 +PROG= smpp-trx-sa +OBJS= localsock.o log.o main.o pdu_out.o tcpconn.o +LIBS= ../libutil/libutil.a +INSTBIN=/usr/local/bin + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBS} + ${CC} ${CFLAGS} -o $@ ${OBJS} ${LIBS} + +install: + install -c -o bin -g bin -m 755 ${PROG} ${INSTBIN} + +clean: + rm -f *.o ${PROG} errs diff -r e1d7db9d734c -r 9d6e8d99d2b1 smpp-trx-sa/localsock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smpp-trx-sa/localsock.c Thu Aug 03 21:13:41 2023 -0800 @@ -0,0 +1,60 @@ +/* + * This module implements the local socket part of smpp-trx-sa. + */ + +#include +#include +#include +#include +#include +#include + +int localsock; + +void +create_local_socket(pathname) + char *pathname; +{ + struct sockaddr_un sa; + unsigned sa_len; + int rc; + + localsock = socket(AF_UNIX, SOCK_DGRAM, 0); + if (localsock < 0) { + perror("socket(AF_UNIX, SOCK_DGRAM, 0)"); + exit(1); + } + unlink(pathname); + fill_sockaddr_un(pathname, &sa, &sa_len); + rc = bind(localsock, (struct sockaddr *) &sa, sa_len); + if (rc < 0) { + fprintf(stderr, "bind error on %s\n", pathname); + perror("bind"); + exit(1); + } +} + +void +localsock_select_handler() +{ + u_char buf[0x10000]; + int cc; + unsigned pdu_len; + + cc = recv(localsock, buf, sizeof buf, 0); + if (cc <= 0) { + perror("read from local socket"); + log_fatal_error("error reading from local socket"); + exit(1); + } + if (cc < 16) { +inv_pdu: log_fatal_error("Received invalid PDU on local socket"); + return; + } + if (buf[0] || buf[1]) + goto inv_pdu; + pdu_len = (buf[2] << 8) | buf[3]; + if (pdu_len != cc) + goto inv_pdu; + send_pdu_from_localsock(buf, pdu_len); +} diff -r e1d7db9d734c -r 9d6e8d99d2b1 smpp-trx-sa/log.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smpp-trx-sa/log.c Thu Aug 03 21:13:41 2023 -0800 @@ -0,0 +1,88 @@ +/* + * This module implements smpp-trx-sa log file output. + */ + +#include +#include +#include +#include +#include +#include + +extern FILE *logF; +extern time_t curtime; +extern int init_done; + +static char fmt_time[32]; + +static void +format_time() +{ + struct tm *tm; + + tm = gmtime(&curtime); + sprintf(fmt_time, "%d-%02d-%02dT%02d:%02d:%02dZ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +void +log_fatal_error(cause) + char *cause; +{ + if (!init_done) + return; + format_time(); + fprintf(logF, "\n%s %s\n", fmt_time, cause); +} + +static void +pdu_hexdump(pdu, pdulen) + u_char *pdu; + unsigned pdulen; +{ + unsigned off, chunk; + int i, c; + + for (off = 0; off < pdulen; off += chunk) { + fprintf(logF, "%04X: ", off); + chunk = pdulen - off; + if (chunk > 16) + chunk = 16; + for (i = 0; i < 16; i++) { + if (i < chunk) + fprintf(logF, "%02X ", pdu[off + i]); + else + fputs(" ", logF); + if (i == 7 || i == 15) + putc(' ', logF); + } + for (i = 0; i < chunk; i++) { + c = pdu[off + i]; + if (c < ' ' || c > '~') + c = '.'; + putc(c, logF); + } + putc('\n', logF); + } +} + +void +log_rx_pdu(pdu, pdulen) + u_char *pdu; + unsigned pdulen; +{ + format_time(); + fprintf(logF, "\n%s Received PDU:\n", fmt_time); + pdu_hexdump(pdu, pdulen); +} + +void +log_sent_pdu(pdu, pdulen) + u_char *pdu; + unsigned pdulen; +{ + format_time(); + fprintf(logF, "\n%s Sent PDU:\n", fmt_time); + pdu_hexdump(pdu, pdulen); +} diff -r e1d7db9d734c -r 9d6e8d99d2b1 smpp-trx-sa/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smpp-trx-sa/main.c Thu Aug 03 21:13:41 2023 -0800 @@ -0,0 +1,88 @@ +/* + * This C file is the main module for smpp-trx-sa - a standalone bind_trx + * client (ESME role) that writes all incoming messages into a log file + * and also allows outgoing messages to be sent via a UNIX domain local + * socket (datagram). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int tcpsock, localsock; + +FILE *logF; +time_t curtime; +int init_done; + +main(argc, argv) + char **argv; +{ + struct sockaddr_in server_sin; + fd_set fds; + int max_fd, rc; + + if (argc != 6) { + fprintf(stderr, + "usage: %s server-ip system-id password log-file socket-pathname\n", + argv[0]); + exit(1); + } + server_sin.sin_family = AF_INET; + server_sin.sin_addr.s_addr = inet_addr(argv[1]); + if (server_sin.sin_addr.s_addr == INADDR_NONE) { + fprintf(stderr, "error: invalid IP address argument \"%s\"\n", + argv[1]); + exit(1); + } + server_sin.sin_port = htons(2775); + if (strlen(argv[2]) > 15) { + fprintf(stderr, "error: system-id string is too long\n"); + exit(1); + } + if (strlen(argv[3]) > 8) { + fprintf(stderr, "error: password string is too long\n"); + exit(1); + } + logF = fopen(argv[4], "a"); + if (!logF) { + perror(argv[4]); + exit(1); + } + create_local_socket(argv[5]); + max_fd = localsock; + open_tcp_conn(&server_sin); + if (tcpsock > max_fd) + max_fd = tcpsock; + time(&curtime); + send_bind_req(argv[2], argv[3]); + init_done = 1; + /* main select loop */ + for (;;) { + FD_ZERO(&fds); + FD_SET(tcpsock, &fds); + FD_SET(localsock, &fds); + rc = select(max_fd+1, &fds, 0, 0, 0); + if (rc < 0) { + if (errno == EINTR) + continue; + perror("select"); + log_fatal_error("select syscall error"); + exit(1); + } + time(&curtime); + if (FD_ISSET(tcpsock, &fds)) + tcpsock_select_handler(); + if (FD_ISSET(localsock, &fds)) + localsock_select_handler(); + fflush(logF); + } +} diff -r e1d7db9d734c -r 9d6e8d99d2b1 smpp-trx-sa/pdu_out.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smpp-trx-sa/pdu_out.c Thu Aug 03 21:13:41 2023 -0800 @@ -0,0 +1,162 @@ +/* + * This module implements all functions related to sending outgoing PDUs + * to the SMPP server. + */ + +#include +#include +#include +#include +#include +#include + +extern int tcpsock; + +static unsigned req_out_seq = 1; + +static void +pdu_to_tcp(pdu, pdulen) + u_char *pdu; + unsigned pdulen; +{ + int cc; + + cc = write(tcpsock, pdu, pdulen); + if (cc != pdulen) { + perror("write to TCP socket"); + log_fatal_error("error writing to TCP socket"); + exit(1); + } +} + +void +send_bind_req(system_id, password) + char *system_id, *password; +{ + u_char bind_req[64], *dp; + unsigned bind_req_len, slen; + + dp = bind_req + 4; /* length will be filled last */ + /* command_id */ + *dp++ = 0; + *dp++ = 0; + *dp++ = 0; + *dp++ = 0x09; /* bind_transceiver */ + /* empty command_status */ + *dp++ = 0; + *dp++ = 0; + *dp++ = 0; + *dp++ = 0; + /* sequence_number */ + *dp++ = 0; + *dp++ = 0; + *dp++ = 0; + *dp++ = 1; + /* system_id */ + slen = strlen(system_id) + 1; + bcopy(system_id, dp, slen); + dp += slen; + /* password */ + slen = strlen(password) + 1; + bcopy(password, dp, slen); + dp += slen; + /* system_type */ + strcpy(dp, "SMPP"); + dp += 5; + /* interface_version */ + *dp++ = 0x34; + /* addr_ton */ + *dp++ = 0; + /* addr_npi */ + *dp++ = 0; + /* address_range */ + *dp++ = 0; + bind_req_len = dp - bind_req; + bind_req[0] = bind_req_len >> 24; + bind_req[1] = bind_req_len >> 16; + bind_req[2] = bind_req_len >> 8; + bind_req[3] = bind_req_len; + pdu_to_tcp(bind_req, bind_req_len); + log_sent_pdu(bind_req, bind_req_len); +} + +void +send_enq_link_resp(rx_hdr) + u_char *rx_hdr; +{ + u_char resp[16]; + + /* command_length */ + resp[0] = 0; + resp[1] = 0; + resp[2] = 0; + resp[3] = 16; + /* command_id */ + resp[4] = rx_hdr[4] | 0x80; + resp[5] = rx_hdr[5]; + resp[6] = rx_hdr[6]; + resp[7] = rx_hdr[7]; + /* command_status */ + resp[8] = 0; + resp[9] = 0; + resp[10] = 0; + resp[11] = 0; + /* sequence_number */ + resp[12] = rx_hdr[12]; + resp[13] = rx_hdr[13]; + resp[14] = rx_hdr[14]; + resp[15] = rx_hdr[15]; + /* good to go */ + pdu_to_tcp(resp, 16); +} + +void +send_message_resp(rx_hdr) + u_char *rx_hdr; +{ + u_char resp[17]; + + /* command_length */ + resp[0] = 0; + resp[1] = 0; + resp[2] = 0; + resp[3] = 17; + /* command_id */ + resp[4] = rx_hdr[4] | 0x80; + resp[5] = rx_hdr[5]; + resp[6] = rx_hdr[6]; + resp[7] = rx_hdr[7]; + /* command_status */ + resp[8] = 0; + resp[9] = 0; + resp[10] = 0; + resp[11] = 0; + /* sequence_number */ + resp[12] = rx_hdr[12]; + resp[13] = rx_hdr[13]; + resp[14] = rx_hdr[14]; + resp[15] = rx_hdr[15]; + /* empty message_id */ + resp[16] = 0; + /* good to go */ + pdu_to_tcp(resp, 17); + log_sent_pdu(resp, 17); +} + +void +send_pdu_from_localsock(pdu, pdulen) + u_char *pdu; + unsigned pdulen; +{ + /* assign incrementing sequence number */ + req_out_seq++; + if (req_out_seq > 0x7FFFFFFF) + req_out_seq = 1; + pdu[12] = req_out_seq >> 24; + pdu[13] = req_out_seq >> 16; + pdu[14] = req_out_seq >> 8; + pdu[15] = req_out_seq; + /* good to go */ + pdu_to_tcp(pdu, pdulen); + log_sent_pdu(pdu, pdulen); +} diff -r e1d7db9d734c -r 9d6e8d99d2b1 smpp-trx-sa/tcpconn.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smpp-trx-sa/tcpconn.c Thu Aug 03 21:13:41 2023 -0800 @@ -0,0 +1,106 @@ +/* + * This module implements the part of smpp-trx-sa that handles + * the TCP connection to the SMPP server. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern FILE *logF; + +int tcpsock; + +static u_char rx_buf[0x10000]; +static unsigned rx_accum, rx_pdu_len; +static int rx_body; + +void +open_tcp_conn(server_sin) + struct sockaddr_in *server_sin; +{ + int rc; + + tcpsock = socket(AF_INET, SOCK_STREAM, 0); + if (tcpsock < 0) { + perror("socket(AF_INET, SOCK_STREAM, 0)"); + exit(1); + } + rc = connect(tcpsock, (struct sockaddr *) server_sin, + sizeof(struct sockaddr_in)); + if (rc < 0) { + perror("TCP connect"); + exit(1); + } +} + +static void +got_full_pdu() +{ + unsigned command_id; + + /* prepare for next PDU Rx */ + rx_body = 0; + rx_accum = 0; + /* back to the one we just got */ + command_id = (rx_buf[4] << 24) | (rx_buf[5] << 16) | (rx_buf[6] << 8) | + rx_buf[7]; + if (command_id == 0x15 && rx_pdu_len == 16) { + send_enq_link_resp(rx_buf); + return; + } + log_rx_pdu(rx_buf, rx_pdu_len); + if (command_id == 0x05 || command_id == 0x103) + send_message_resp(rx_buf); +} + +void +tcpsock_select_handler() +{ + unsigned goal; + int cc; + + if (rx_body) + goal = rx_pdu_len; + else + goal = 16; + cc = read(tcpsock, rx_buf + rx_accum, goal - rx_accum); + if (cc < 0) { + perror("read from TCP socket"); + log_fatal_error("error reading from TCP socket"); + exit(1); + } + if (cc == 0) { + log_fatal_error("Server closed TCP connection"); + exit(1); + } + rx_accum += cc; + if (rx_accum < goal) + return; + if (rx_body) { + got_full_pdu(); + return; + } + if (rx_buf[0] || rx_buf[1]) { + log_rx_pdu(rx_buf, 16); + fprintf(logF, "Fatal error: length exceeds limit\n"); + exit(1); + } + rx_pdu_len = (rx_buf[2] << 8) | rx_buf[3]; + if (rx_pdu_len < 16) { + log_rx_pdu(rx_buf, 16); + fprintf(logF, "Fatal error: length below 16\n"); + exit(1); + } + if (rx_pdu_len == 16) { + got_full_pdu(); + return; + } + rx_body = 1; +}