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 } |