FreeCalypso > hg > themwi-system-sw
comparison utils/smpp-test2.c @ 221:e1d7db9d734c
smpp-test2 program written
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Thu, 03 Aug 2023 10:00:33 -0800 |
| parents | utils/smpp-test1.c@c798a1762c7c |
| children |
comparison
equal
deleted
inserted
replaced
| 220:c798a1762c7c | 221:e1d7db9d734c |
|---|---|
| 1 /* | |
| 2 * This program connects to an SMPP server in the role of a client, | |
| 3 * sends a bind_transceiver request, and then goes into a receiving loop, | |
| 4 * dumping everything that comes back from the server. Received packets | |
| 5 * are also checked for some command opcodes to which we need to generate | |
| 6 * a response, and simple auto-responses are generated. | |
| 7 */ | |
| 8 | |
| 9 #include <sys/types.h> | |
| 10 #include <sys/socket.h> | |
| 11 #include <netinet/in.h> | |
| 12 #include <arpa/inet.h> | |
| 13 #include <stdio.h> | |
| 14 #include <stdlib.h> | |
| 15 #include <string.h> | |
| 16 #include <strings.h> | |
| 17 #include <unistd.h> | |
| 18 | |
| 19 static int tcpsock; | |
| 20 static struct sockaddr_in server_sin; | |
| 21 static u_char bind_req[64]; | |
| 22 static unsigned bind_req_len; | |
| 23 static char system_id[16], password[9]; | |
| 24 static u_char rx_hdr[16]; | |
| 25 static unsigned rx_pkt_len, rx_command_id; | |
| 26 | |
| 27 static void | |
| 28 construct_bind_req() | |
| 29 { | |
| 30 u_char *dp; | |
| 31 unsigned slen; | |
| 32 | |
| 33 dp = bind_req + 4; /* length will be filled last */ | |
| 34 /* command_id */ | |
| 35 *dp++ = 0; | |
| 36 *dp++ = 0; | |
| 37 *dp++ = 0; | |
| 38 *dp++ = 0x09; /* bind_transceiver */ | |
| 39 /* empty command_status */ | |
| 40 *dp++ = 0; | |
| 41 *dp++ = 0; | |
| 42 *dp++ = 0; | |
| 43 *dp++ = 0; | |
| 44 /* sequence_number */ | |
| 45 *dp++ = 0; | |
| 46 *dp++ = 0; | |
| 47 *dp++ = 0; | |
| 48 *dp++ = 1; | |
| 49 /* system_id */ | |
| 50 slen = strlen(system_id) + 1; | |
| 51 bcopy(system_id, dp, slen); | |
| 52 dp += slen; | |
| 53 /* password */ | |
| 54 slen = strlen(password) + 1; | |
| 55 bcopy(password, dp, slen); | |
| 56 dp += slen; | |
| 57 /* system_type */ | |
| 58 strcpy(dp, "SMPP"); | |
| 59 dp += 5; | |
| 60 /* interface_version */ | |
| 61 *dp++ = 0x34; | |
| 62 /* addr_ton */ | |
| 63 *dp++ = 0; | |
| 64 /* addr_npi */ | |
| 65 *dp++ = 0; | |
| 66 /* address_range */ | |
| 67 *dp++ = 0; | |
| 68 bind_req_len = dp - bind_req; | |
| 69 bind_req[0] = bind_req_len >> 24; | |
| 70 bind_req[1] = bind_req_len >> 16; | |
| 71 bind_req[2] = bind_req_len >> 8; | |
| 72 bind_req[3] = bind_req_len; | |
| 73 } | |
| 74 | |
| 75 static void | |
| 76 print_bind_req() | |
| 77 { | |
| 78 unsigned off, chunk; | |
| 79 int i, c; | |
| 80 | |
| 81 printf("Constructed bind request of %u bytes\n", bind_req_len); | |
| 82 for (off = 0; off < bind_req_len; off += chunk) { | |
| 83 chunk = bind_req_len - off; | |
| 84 if (chunk > 16) | |
| 85 chunk = 16; | |
| 86 printf("%02X: ", off); | |
| 87 for (i = 0; i < 16; i++) { | |
| 88 if (i < chunk) | |
| 89 printf("%02X ", bind_req[off + i]); | |
| 90 else | |
| 91 fputs(" ", stdout); | |
| 92 if (i == 7 || i == 15) | |
| 93 putchar(' '); | |
| 94 } | |
| 95 for (i = 0; i < chunk; i++) { | |
| 96 c = bind_req[off + i]; | |
| 97 if (c < ' ' || c > '~') | |
| 98 c = '.'; | |
| 99 putchar(c); | |
| 100 } | |
| 101 putchar('\n'); | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 static void | |
| 106 init_stage() | |
| 107 { | |
| 108 int rc; | |
| 109 | |
| 110 rc = connect(tcpsock, (struct sockaddr *) &server_sin, | |
| 111 sizeof(struct sockaddr_in)); | |
| 112 if (rc < 0) { | |
| 113 perror("connect"); | |
| 114 exit(1); | |
| 115 } | |
| 116 rc = write(tcpsock, bind_req, bind_req_len); | |
| 117 if (rc != bind_req_len) { | |
| 118 perror("write"); | |
| 119 exit(1); | |
| 120 } | |
| 121 } | |
| 122 | |
| 123 static void | |
| 124 rx_bytes(buf, need_len) | |
| 125 u_char *buf; | |
| 126 unsigned need_len; | |
| 127 { | |
| 128 int cc; | |
| 129 unsigned remain; | |
| 130 | |
| 131 for (remain = need_len; remain; remain -= cc) { | |
| 132 cc = read(tcpsock, buf, remain); | |
| 133 if (cc <= 0) { | |
| 134 perror("read"); | |
| 135 exit(1); | |
| 136 } | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 static void | |
| 141 print_hdr() | |
| 142 { | |
| 143 int i, j, pos; | |
| 144 | |
| 145 fputs("Got header:", stdout); | |
| 146 pos = 0; | |
| 147 for (i = 0; i < 4; i++) { | |
| 148 putchar(' '); | |
| 149 for (j = 0; j < 4; j++) | |
| 150 printf("%02X", rx_hdr[pos++]); | |
| 151 } | |
| 152 putchar('\n'); | |
| 153 } | |
| 154 | |
| 155 static void | |
| 156 preen_rx_hdr() | |
| 157 { | |
| 158 rx_pkt_len = (rx_hdr[0] << 24) | (rx_hdr[1] << 16) | (rx_hdr[2] << 8) | | |
| 159 rx_hdr[3]; | |
| 160 printf("Rx packet length: %u bytes\n", rx_pkt_len); | |
| 161 if (rx_pkt_len < 16) { | |
| 162 printf("Error: packet length is too short\n"); | |
| 163 exit(1); | |
| 164 } | |
| 165 rx_command_id = (rx_hdr[4] << 24) | (rx_hdr[5] << 16) | | |
| 166 (rx_hdr[6] << 8) | rx_hdr[7]; | |
| 167 } | |
| 168 | |
| 169 static void | |
| 170 read_and_dump_body() | |
| 171 { | |
| 172 u_char buf[16]; | |
| 173 unsigned offset, chunk; | |
| 174 int i, c; | |
| 175 | |
| 176 for (offset = 16; offset < rx_pkt_len; offset += chunk) { | |
| 177 chunk = rx_pkt_len - offset; | |
| 178 if (chunk > 16) | |
| 179 chunk = 16; | |
| 180 rx_bytes(buf, chunk); | |
| 181 printf("%08X: ", offset); | |
| 182 for (i = 0; i < 16; i++) { | |
| 183 if (i < chunk) | |
| 184 printf("%02X ", buf[i]); | |
| 185 else | |
| 186 fputs(" ", stdout); | |
| 187 if (i == 7 || i == 15) | |
| 188 putchar(' '); | |
| 189 } | |
| 190 for (i = 0; i < chunk; i++) { | |
| 191 c = buf[i]; | |
| 192 if (c < ' ' || c > '~') | |
| 193 c = '.'; | |
| 194 putchar(c); | |
| 195 } | |
| 196 putchar('\n'); | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 static void | |
| 201 resp_hdr_only() | |
| 202 { | |
| 203 u_char resp[16]; | |
| 204 int rc; | |
| 205 | |
| 206 /* command_length */ | |
| 207 resp[0] = 0; | |
| 208 resp[1] = 0; | |
| 209 resp[2] = 0; | |
| 210 resp[3] = 16; | |
| 211 /* command_id */ | |
| 212 resp[4] = rx_hdr[4] | 0x80; | |
| 213 resp[5] = rx_hdr[5]; | |
| 214 resp[6] = rx_hdr[6]; | |
| 215 resp[7] = rx_hdr[7]; | |
| 216 /* command_status */ | |
| 217 resp[8] = 0; | |
| 218 resp[9] = 0; | |
| 219 resp[10] = 0; | |
| 220 resp[11] = 0; | |
| 221 /* sequence_number */ | |
| 222 resp[12] = rx_hdr[12]; | |
| 223 resp[13] = rx_hdr[13]; | |
| 224 resp[14] = rx_hdr[14]; | |
| 225 resp[15] = rx_hdr[15]; | |
| 226 /* good to go */ | |
| 227 rc = write(tcpsock, resp, 16); | |
| 228 if (rc != 16) { | |
| 229 perror("write"); | |
| 230 exit(1); | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 static void | |
| 235 resp_dummy_msgid() | |
| 236 { | |
| 237 u_char resp[17]; | |
| 238 int rc; | |
| 239 | |
| 240 /* command_length */ | |
| 241 resp[0] = 0; | |
| 242 resp[1] = 0; | |
| 243 resp[2] = 0; | |
| 244 resp[3] = 17; | |
| 245 /* command_id */ | |
| 246 resp[4] = rx_hdr[4] | 0x80; | |
| 247 resp[5] = rx_hdr[5]; | |
| 248 resp[6] = rx_hdr[6]; | |
| 249 resp[7] = rx_hdr[7]; | |
| 250 /* command_status */ | |
| 251 resp[8] = 0; | |
| 252 resp[9] = 0; | |
| 253 resp[10] = 0; | |
| 254 resp[11] = 0; | |
| 255 /* sequence_number */ | |
| 256 resp[12] = rx_hdr[12]; | |
| 257 resp[13] = rx_hdr[13]; | |
| 258 resp[14] = rx_hdr[14]; | |
| 259 resp[15] = rx_hdr[15]; | |
| 260 /* empty message_id */ | |
| 261 resp[16] = 0; | |
| 262 /* good to go */ | |
| 263 rc = write(tcpsock, resp, 17); | |
| 264 if (rc != 17) { | |
| 265 perror("write"); | |
| 266 exit(1); | |
| 267 } | |
| 268 } | |
| 269 | |
| 270 static void | |
| 271 auto_resp_logic() | |
| 272 { | |
| 273 switch (rx_command_id) { | |
| 274 case 0x005: | |
| 275 printf("Got deliver_sm, responding with deliver_sm_resp\n"); | |
| 276 resp_dummy_msgid(); | |
| 277 return; | |
| 278 case 0x103: | |
| 279 printf("Got data_sm, responding with data_sm_resp\n"); | |
| 280 resp_dummy_msgid(); | |
| 281 return; | |
| 282 case 0x015: | |
| 283 printf("Got enquire_link, responding with enquire_link_resp\n"); | |
| 284 resp_hdr_only(); | |
| 285 return; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 main(argc, argv) | |
| 290 char **argv; | |
| 291 { | |
| 292 if (argc < 3 || argc > 4) { | |
| 293 fprintf(stderr, "usage: %s server-ip system-id [password]\n", | |
| 294 argv[0]); | |
| 295 exit(1); | |
| 296 } | |
| 297 server_sin.sin_family = AF_INET; | |
| 298 server_sin.sin_addr.s_addr = inet_addr(argv[1]); | |
| 299 if (server_sin.sin_addr.s_addr == INADDR_NONE) { | |
| 300 fprintf(stderr, "error: invalid IP address argument \"%s\"\n", | |
| 301 argv[1]); | |
| 302 exit(1); | |
| 303 } | |
| 304 server_sin.sin_port = htons(2775); | |
| 305 if (strlen(argv[2]) > 15) { | |
| 306 fprintf(stderr, "error: system-id string is too long\n"); | |
| 307 exit(1); | |
| 308 } | |
| 309 strcpy(system_id, argv[2]); | |
| 310 if (argv[3]) { | |
| 311 if (strlen(argv[3]) > 8) { | |
| 312 fprintf(stderr, "error: password string is too long\n"); | |
| 313 exit(1); | |
| 314 } | |
| 315 strcpy(password, argv[3]); | |
| 316 } | |
| 317 construct_bind_req(); | |
| 318 setlinebuf(stdout); | |
| 319 print_bind_req(); | |
| 320 tcpsock = socket(AF_INET, SOCK_STREAM, 0); | |
| 321 if (tcpsock < 0) { | |
| 322 perror("socket"); | |
| 323 exit(1); | |
| 324 } | |
| 325 init_stage(); | |
| 326 for (;;) { | |
| 327 rx_bytes(rx_hdr, 16); | |
| 328 print_hdr(); | |
| 329 preen_rx_hdr(); | |
| 330 read_and_dump_body(); | |
| 331 auto_resp_logic(); | |
| 332 } | |
| 333 } |
