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 }