1 /* ====================================================================
2 * The Kannel Software License, Version 1.0
3 *
4 * Copyright (c) 2001-2014 Kannel Group
5 * Copyright (c) 1998-2001 WapIT Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution,
21 * if any, must include the following acknowledgment:
22 * "This product includes software developed by the
23 * Kannel Group (http://www.kannel.org/)."
24 * Alternately, this acknowledgment may appear in the software itself,
25 * if and wherever such third-party acknowledgments normally appear.
26 *
27 * 4. The names "Kannel" and "Kannel Group" must not be used to
28 * endorse or promote products derived from this software without
29 * prior written permission. For written permission, please
30 * contact org@kannel.org.
31 *
32 * 5. Products derived from this software may not be called "Kannel",
33 * nor may "Kannel" appear in their name, without prior written
34 * permission of the Kannel Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Kannel Group. For more information on
51 * the Kannel Group, please see <http://www.kannel.org/>.
52 *
53 * Portions of this software are based upon software originally written at
54 * WapIT Ltd., Helsinki, Finland for the Kannel project.
55 */
56
57 /* Driver for CIMD 2 SMS centres.
58 * Copyright 2000 WapIT Oy Ltd.
59 * Author: Richard Braakman
60 *
61 * Upgrade to SMSCConn API: 2002 Kalle Marjola / 2003 Angel Fradejas
62 */
63
64 /* TODO: Check checksums on incoming packets */
65 /* TODO: Leading or trailing spaces are not allowed on parameters
66 * "user identity" and "password". Check this. */
67 /* TODO: Try to use the "More messages to send" flag */
68
69 /* This code is based on the CIMD 2 spec, version 2-0 en.
70 * All USSD-specific parts have been left out, since we only want to
71 * communicate with SMSC's.
72 *
73 * I found one contradiction in the spec:
74 *
75 * - The definition of Integer parameters specifies decimal digits only,
76 * but at least one Integer parameter (Validity Period Relative) can
77 * be negative. I assume that this means a leading - is valid.
78 */
79
80 #include <ctype.h>
81 #include <time.h>
82 #include <errno.h>
83 #include <limits.h>
84 #include <string.h>
85
86 #include <unistd.h>
87
88 #include "gwlib/gwlib.h"
89 #include "smscconn.h"
90 #include "smscconn_p.h"
91 #include "bb_smscconn_cb.h"
92
93 #include "shared.h"
94 #include "sms.h"
95 #include "dlr.h"
96
97
98 typedef struct privdata {
99 Octstr *username;
100 Octstr *password;
101 Octstr *host;
102 long port;
103 long our_port;
104 long keepalive;
105 Octstr *my_number;
106 int no_dlr;
107
108 int socket;
109 int send_seq;
110 int receive_seq;
111
112 Octstr *inbuffer;
113 List *received;
114
115 time_t next_ping;
116
117 List *outgoing_queue;
118 SMSCConn *conn;
119 int io_thread;
120 int quitting;
121 List *stopped; /* list-trick for suspend/isolate */
122
123 } PrivData;
124
125
126
127 /* Microseconds before giving up on a request */
128 #define RESPONSE_TIMEOUT (60 * 1000000)
129
130 /* Textual names for the operation codes defined by the CIMD 2 spec. */
131 /* If you make changes here, also change the operation table. */
132 enum {
133 /* Requests from client */
134 LOGIN = 1,
135 LOGOUT = 2,
136 SUBMIT_MESSAGE = 3,
137 ENQUIRE_MESSAGE_STATUS = 4,
138 DELIVERY_REQUEST = 5,
139 CANCEL_MESSAGE = 6,
140 SET_REQ = 8,
141 GET_REQ = 9,
142
143 /* Requests from server */
144 DELIVER_MESSAGE = 20,
145 DELIVER_STATUS_REPORT = 23,
146
147 /* Requests from either */
148 ALIVE = 40,
149
150 /* Not a request; add to any request to make it a response */
151 RESPONSE = 50,
152
153 /* Responses not related to requests */
154 GENERAL_ERROR_RESPONSE = 98,
155 NACK = 99
156 };
157
158 /* Textual names for the parameters defined by the CIMD 2 spec. */
159 /* If you make changes here, also change the parameter table. */
160 enum {
161 P_USER_IDENTITY = 10,
162 P_PASSWORD = 11,
163 P_DESTINATION_ADDRESS = 21,
164 P_ORIGINATING_ADDRESS = 23,
165 P_ORIGINATING_IMSI = 26,
166 P_ALPHANUMERIC_ORIGINATING_ADDRESS = 27,
167 P_ORIGINATED_VISITED_MSC = 28,
168 P_DATA_CODING_SCHEME = 30,
169 P_USER_DATA_HEADER = 32,
170 P_USER_DATA = 33,
171 P_USER_DATA_BINARY = 34,
172 P_MORE_MESSAGES_TO_SEND = 44,
173 P_VALIDITY_PERIOD_RELATIVE = 50,
174 P_VALIDITY_PERIOD_ABSOLUTE = 51,
175 P_PROTOCOL_IDENTIFIER = 52,
176 P_FIRST_DELIVERY_TIME_RELATIVE = 53,
177 P_FIRST_DELIVERY_TIME_ABSOLUTE = 54,
178 P_REPLY_PATH = 55,
179 P_STATUS_REPORT_REQUEST = 56,
180 P_CANCEL_ENABLED = 58,
181 P_CANCEL_MODE = 59,
182 P_MC_TIMESTAMP = 60,
183 P_STATUS_CODE = 61,
184 P_STATUS_ERROR_CODE = 62,
185 P_DISCHARGE_TIME = 63,
186 P_TARIFF_CLASS = 64,
187 P_SERVICE_DESCRIPTION = 65,
188 P_MESSAGE_COUNT = 66,
189 P_PRIORITY = 67,
190 P_DELIVERY_REQUEST_MODE = 68,
191 P_SERVICE_CENTER_ADDRESS = 69,
192 P_GET_PARAMETER = 500,
193 P_MC_TIME = 501,
194 P_ERROR_CODE = 900,
195 P_ERROR_TEXT = 901
196 };
197
198 /***************************************************************************/
199 /* Table of properties of the parameters defined by CIMD 2, and some */
200 /* functions to look up fields. */
201 /***************************************************************************/
202
203 /* Parameter types, internal. CIMD 2 spec considers P_TIME to be "Integer"
204 * and P_SMS to be "User Data". */
205 enum { P_INT, P_STRING, P_ADDRESS, P_TIME, P_HEX, P_SMS };
206
207 /* Information about the parameters defined by the CIMD 2 spec.
208 * Used for warning about invalid incoming messages, and for validating
209 * outgoing messages. */
210 static const struct
211 {
212 char *name;
213 int number;
214 int maxlen;
215 int type; /* P_ values */
216 int minval, maxval; /* For P_INT */
217 }
218 parameters[] = {
219 { "user identity", P_USER_IDENTITY, 32, P_STRING },
220 { "password", P_PASSWORD, 32, P_STRING },
221 { "destination address", P_DESTINATION_ADDRESS, 20, P_ADDRESS },
222 { "originating address", P_ORIGINATING_ADDRESS, 20, P_ADDRESS },
223 /* IMSI is International Mobile Subscriber Identity number */
224 { "originating IMSI", P_ORIGINATING_IMSI, 20, P_ADDRESS },
225 { "alphanumeric originating address", P_ALPHANUMERIC_ORIGINATING_ADDRESS, 11, P_STRING },
226 { "originated visited MSC", P_ORIGINATED_VISITED_MSC, 20, P_ADDRESS },
227 { "data coding scheme", P_DATA_CODING_SCHEME, 3, P_INT, 0, 255 },
228 { "user data header", P_USER_DATA_HEADER, 280, P_HEX },
229 { "user data", P_USER_DATA, 480, P_SMS },
230 { "user data binary", P_USER_DATA_BINARY, 280, P_HEX },
231 { "more messages to send", P_MORE_MESSAGES_TO_SEND, 1, P_INT, 0, 1 },
232 { "validity period relative", P_VALIDITY_PERIOD_RELATIVE, 3, P_INT, -1, 255 },
233 { "validity period absolute", P_VALIDITY_PERIOD_ABSOLUTE, 12, P_TIME },
234 { "protocol identifier", P_PROTOCOL_IDENTIFIER, 3, P_INT, 0, 255 },
235 { "first delivery time relative", P_FIRST_DELIVERY_TIME_RELATIVE, 3, P_INT, -1, 255 },
236 { "first delivery time absolute", P_FIRST_DELIVERY_TIME_ABSOLUTE, 12, P_TIME },
237 { "reply path", P_REPLY_PATH, 1, P_INT, 0, 1 },
238 { "status report request", P_STATUS_REPORT_REQUEST, 2, P_INT, 0, 63 },
239 { "cancel enabled", P_CANCEL_ENABLED, 1, P_INT, 0, 1 },
240 { "cancel mode", P_CANCEL_MODE, 1, P_INT, 0, 2 },
241 { "service centre timestamp", P_MC_TIMESTAMP, 12, P_TIME },
242 { "status code", P_STATUS_CODE, 2, P_INT, 0, 9 },
243 { "status error code", P_STATUS_ERROR_CODE, 3, P_INT, 0, 999 },
244 { "discharge time", P_DISCHARGE_TIME, 12, P_TIME },
245 { "tariff class", P_TARIFF_CLASS, 2, P_INT, 0, 99 },
246 { "service description", P_SERVICE_DESCRIPTION, 2, P_INT, 0, 9 },
247 { "message count", P_MESSAGE_COUNT, 3, P_INT, 0, 999 },
248 { "priority", P_PRIORITY, 1, P_INT, 1, 9 },
249 { "delivery request mode", P_DELIVERY_REQUEST_MODE, 1, P_INT, 0, 2 },
250 { "service center address", P_SERVICE_CENTER_ADDRESS, 20, P_ADDRESS },
251 { "get parameter", P_GET_PARAMETER, 3, P_INT, 501, 999 },
252 { "MC time", P_MC_TIME, 12, P_TIME },
253 { "error code", P_ERROR_CODE, 3, P_INT, 0, 999 },
254 { "error text", P_ERROR_TEXT, 64, P_STRING },
255 { NULL }
256 };
257
258 /* Return the index in the parameters array for this parameter id.
259 * Return -1 if it is not found. */
parm_index(int parmno)260 static int parm_index(int parmno)
261 {
262 int i;
263
264 for (i = 0; parameters[i].name != NULL; i++) {
265 if (parameters[i].number == parmno)
266 return i;
267 }
268
269 return -1;
270 }
271
272 #ifndef NO_GWASSERT
273 /* Return the type of this parameter id. Return -1 if the id is unknown. */
parm_type(int parmno)274 static int parm_type(int parmno)
275 {
276 int i = parm_index(parmno);
277
278 if (i < 0)
279 return -1;
280
281 return parameters[i].type;
282 }
283 #endif
284
285 /* Return the max length for this parameter id.
286 * Return -1 if the id is unknown. */
parm_maxlen(int parmno)287 static int parm_maxlen(int parmno)
288 {
289 int i = parm_index(parmno);
290
291 if (i < 0)
292 return -1;
293
294 return parameters[i].maxlen;
295 }
296
parm_name(int parmno)297 static const char *parm_name(int parmno)
298 {
299 int i = parm_index(parmno);
300
301 if (i < 0)
302 return NULL;
303
304 return parameters[i].name;
305 }
306
307 #ifndef NO_GWASSERT
308 /* Return 1 if the value for this (Integer) parameter is in range.
309 * Return 0 otherwise. Return -1 if the parameter was not found. */
parm_in_range(int parmno,long value)310 static int parm_in_range(int parmno, long value)
311 {
312 int i;
313
314 i = parm_index(parmno);
315
316 if (i < 0)
317 return -1;
318
319 return (value >= parameters[i].minval && value <= parameters[i].maxval);
320 }
321 #endif
322
323 /* Helper function to check P_ADDRESS type */
isphonedigit(int c)324 static int isphonedigit(int c)
325 {
326 return isdigit(c) || c == '+' || c == '-';
327 }
328
parm_valid_address(Octstr * value)329 static int parm_valid_address(Octstr *value)
330 {
331 return octstr_check_range(value, 0, octstr_len(value), isphonedigit);
332 }
333
334 /***************************************************************************/
335 /* Some functions to look up information about operation codes */
336 /***************************************************************************/
337
338 static int operation_find(int operation);
339 static Octstr *operation_name(int operation);
340 static int operation_can_send(int operation);
341 static int operation_can_receive(int operation);
342
343 static const struct
344 {
345 char *name;
346 int code;
347 int can_send;
348 int can_receive;
349 }
350 operations[] = {
351 { "Login", LOGIN, 1, 0 },
352 { "Logout", LOGOUT, 1, 0 },
353 { "Submit message", SUBMIT_MESSAGE, 1, 0 },
354 { "Enquire message status", ENQUIRE_MESSAGE_STATUS, 1, 0 },
355 { "Delivery request", DELIVERY_REQUEST, 1, 0 },
356 { "Cancel message", CANCEL_MESSAGE, 1, 0 },
357 { "Set parameter", SET_REQ, 1, 0 },
358 { "Get parameter", GET_REQ, 1, 0 },
359
360 { "Deliver message", DELIVER_MESSAGE, 0, 1 },
361 { "Deliver status report", DELIVER_STATUS_REPORT, 0, 1 },
362
363 { "Alive", ALIVE, 1, 1 },
364
365 { "NACK", NACK, 1, 1 },
366 { "General error response", GENERAL_ERROR_RESPONSE, 0, 1 },
367
368 { NULL, 0, 0, 0 }
369 };
370
operation_find(int operation)371 static int operation_find(int operation)
372 {
373 int i;
374
375 for (i = 0; operations[i].name != NULL; i++) {
376 if (operations[i].code == operation)
377 return i;
378 }
379
380 return -1;
381 }
382
383 /* Return a human-readable representation of this operation code */
operation_name(int operation)384 static Octstr *operation_name(int operation)
385 {
386 int i;
387
388 i = operation_find(operation);
389 if (i >= 0)
390 return octstr_create(operations[i].name);
391
392 if (operation >= RESPONSE) {
393 i = operation_find(operation - RESPONSE);
394 if (i >= 0) {
395 Octstr *name = octstr_create(operations[i].name);
396 octstr_append_cstr(name, " response");
397 return name;
398 }
399 }
400
401 /* Put the operation number here when we have octstr_format */
402 return octstr_create("(unknown)");
403 }
404
405 /* Return true if a CIMD2 client may send this operation */
operation_can_send(int operation)406 static int operation_can_send(int operation)
407 {
408 int i = operation_find(operation);
409
410 if (i >= 0)
411 return operations[i].can_send;
412
413 /* If we can receive the request, then we can send the response. */
414 if (operation >= RESPONSE)
415 return operation_can_receive(operation - RESPONSE);
416
417 return 0;
418 }
419
420
421 /* Return true if a CIMD2 server may send this operation */
operation_can_receive(int operation)422 static int operation_can_receive(int operation)
423 {
424 int i = operation_find(operation);
425
426 if (i >= 0)
427 return operations[i].can_receive;
428
429 /* If we can send the request, then we can receive the response. */
430 if (operation >= RESPONSE)
431 return operation_can_send(operation - RESPONSE);
432
433 return 0;
434 }
435
436 /***************************************************************************/
437 /* Packet encoding/decoding functions. They handle packets at the octet */
438 /* level, and know nothing of the network. */
439 /***************************************************************************/
440
441 struct packet
442 {
443 /* operation and seq are -1 if their value could not be parsed */
444 int operation;
445 int seq; /* Sequence number */
446 Octstr *data; /* Encoded packet */
447 /* CIMD 2 packet structure is so simple that packet information is
448 * stored as a valid encoded packet, and decoded as necessary.
449 * Exceptions: operation code and sequence number are also stored
450 * as ints for speed, and the checksum is not added until the packet
451 * is about to be sent. Since checksums are optional, the packet
452 * is still valid without a checksum.
453 *
454 * The sequence number is kept at 0 until it's time to actually
455 * send the packet, so that the send functions have control over
456 * the sequence numbers.
457 */
458 };
459
460 /* These are the separators defined by the CIMD 2 spec */
461 #define STX 2 /* Start of packet */
462 #define ETX 3 /* End of packet */
463 #define TAB 9 /* End of parameter */
464
465 /* The same separators, in string form */
466 #define STX_str "\02"
467 #define ETX_str "\03"
468 #define TAB_str "\011"
469
470 /* A reminder that packets are created without a valid sequence number */
471 #define BOGUS_SEQUENCE 0
472
473 static Msg *cimd2_accept_delivery_report_message(struct packet *request,
474 SMSCConn *conn);
475 /* Look for the STX OO:SSS TAB header defined by CIMD 2, where OO is the
476 * operation code in two decimals and SSS is the sequence number in three
477 * decimals. Leave the results in the proper fields of the packet.
478 * Try to make sense of headers that don't fit this pattern; validating
479 * the packet format is not our job. */
packet_parse_header(struct packet * packet)480 static void packet_parse_header(struct packet *packet)
481 {
482 int pos;
483 long number;
484
485 /* Set default values, in case we can't parse the fields */
486 packet->operation = -1;
487 packet->seq = -1;
488
489 pos = octstr_parse_long(&number, packet->data, 1, 10);
490 if (pos < 0)
491 return;
492 packet->operation = number;
493
494 if (octstr_get_char(packet->data, pos++) != ':')
495 return;
496
497 pos = octstr_parse_long(&number, packet->data, pos, 10);
498 if (pos < 0)
499 return;
500 packet->seq = number;
501 }
502
503
504 /* Accept an Octstr containing one packet, build a struct packet around
505 * it, and return that struct. The Octstr is stored in the struct.
506 * No error checking is done here yet. */
packet_parse(Octstr * packet_data)507 static struct packet *packet_parse(Octstr *packet_data)
508 {
509 struct packet *packet;
510
511 packet = gw_malloc(sizeof(*packet));
512 packet->data = packet_data;
513
514 /* Fill in packet->operation and packet->seq */
515 packet_parse_header(packet);
516
517 return packet;
518 }
519
520 /* Deallocate this packet */
packet_destroy(struct packet * packet)521 static void packet_destroy(struct packet *packet)
522 {
523 if (packet != NULL) {
524 octstr_destroy(packet->data);
525 gw_free(packet);
526 }
527 }
528
529 /* Find the first packet in "in", delete it from "in", and return it as
530 * a struct. Return NULL if "in" contains no packet. Always delete
531 * leading non-packet data from "in". (The CIMD 2 spec says we should
532 * ignore any data between the packet markers). */
packet_extract(Octstr * in,SMSCConn * conn)533 static struct packet *packet_extract(Octstr *in, SMSCConn *conn)
534 {
535 int stx, etx;
536 Octstr *packet;
537
538 /* Find STX, and delete everything up to it */
539 stx = octstr_search_char(in, STX, 0);
540 if (stx < 0) {
541 octstr_delete(in, 0, octstr_len(in));
542 return NULL;
543 } else {
544 octstr_delete(in, 0, stx);
545 }
546
547 /* STX is now in position 0. Find ETX. */
548 etx = octstr_search_char(in, ETX, 1);
549 if (etx < 0)
550 return NULL;
551
552 /* What shall we do with STX data... STX data... ETX?
553 * Either skip to the second STX, or assume an ETX marker before
554 * the STX. Doing the latter has a chance of succeeding, and
555 * will at least allow good logging of the error. */
556 stx = octstr_search_char(in, STX, 1);
557 if (stx >= 0 && stx < etx) {
558 warning(0, "CIMD2[%s]: packet without end marker",
559 octstr_get_cstr(conn->id));
560 packet = octstr_copy(in, 0, stx);
561 octstr_delete(in, 0, stx);
562 octstr_append_cstr(packet, ETX_str);
563 } else {
564 /* Normal case. Copy packet, and cut it from the source. */
565 packet = octstr_copy(in, 0, etx + 1);
566 octstr_delete(in, 0, etx + 1);
567 }
568
569 return packet_parse(packet);
570 }
571
572 /* The get_parm functions always return the first parameter with the
573 * correct id. There is only one case where the spec allows multiple
574 * parameters with the same id, and that is when an SMS has multiple
575 * destination addresses. We only support one destination address anyway. */
576
577 /* Look for the first parameter with id 'parmno' and return its value.
578 * Return NULL if the parameter was not found. */
packet_get_parm(struct packet * packet,int parmno)579 static Octstr *packet_get_parm(struct packet *packet, int parmno)
580 {
581 long pos, next;
582 long valuepos;
583 long number;
584
585 gw_assert(packet != NULL);
586 pos = octstr_search_char(packet->data, TAB, 0);
587 if (pos < 0)
588 return NULL; /* Bad packet, nothing we can do */
589
590 /* Parameters have a tab on each end. If we don't find the
591 * closing tab, we're at the checksum, so we stop. */
592 for ( ;
593 (next = octstr_search_char(packet->data, TAB, pos + 1)) >= 0;
594 pos = next) {
595 if (octstr_parse_long(&number, packet->data, pos + 1, 10) < 0)
596 continue;
597 if (number != parmno)
598 continue;
599 valuepos = octstr_search_char(packet->data, ':', pos + 1);
600 if (valuepos < 0)
601 continue; /* badly formatted parm */
602 valuepos++; /* skip the ':' */
603
604 /* Found the right parameter */
605 return octstr_copy(packet->data, valuepos, next - valuepos);
606 }
607
608 return NULL;
609 }
610
611
612 /* Look for an Integer parameter with id 'parmno' in the packet and
613 * return its value. Return INT_MIN if the parameter was not found.
614 * (Unfortunately, -1 is a valid parameter value for at least one
615 * parameter.) */
packet_get_int_parm(struct packet * packet,int parmno)616 static long packet_get_int_parm(struct packet *packet, int parmno)
617 {
618 Octstr *valuestr = NULL;
619 long value;
620
621 /* Our code should never even try a bad parameter access. */
622 gw_assert(parm_type(parmno) == P_INT);
623
624 valuestr = packet_get_parm(packet, parmno);
625 if (!valuestr)
626 goto error;
627
628 if (octstr_parse_long(&value, valuestr, 0, 10) < 0)
629 goto error;
630
631 octstr_destroy(valuestr);
632 return value;
633
634 error:
635 octstr_destroy(valuestr);
636 return INT_MIN;
637 }
638
639 /* Look for a String parameter with id 'parmno' in the packet and
640 * return its value. Return NULL if the parameter was not found.
641 * No translations are done on the value. */
packet_get_string_parm(struct packet * packet,int parmno)642 static Octstr *packet_get_string_parm(struct packet *packet, int parmno)
643 {
644 /* Our code should never even try a bad parameter access. */
645 gw_assert(parm_type(parmno) == P_STRING);
646
647 return packet_get_parm(packet, parmno);
648 }
649
650 /* Look for an Address parameter with id 'parmno' in the packet and
651 * return its value. Return NULL if the parameter was not found.
652 * No translations are done on the value. */
packet_get_address_parm(struct packet * packet,int parmno)653 static Octstr *packet_get_address_parm(struct packet *packet, int parmno)
654 {
655 /* Our code should never even try a bad parameter access. */
656 gw_assert(parm_type(parmno) == P_ADDRESS);
657
658 return packet_get_parm(packet, parmno);
659 }
660
661 /* Look for an SMS parameter with id 'parmno' in the packet and return its
662 * value. Return NULL if the parameter was not found. No translations
663 * are done on the value, so it will be in the ISO-Latin-1 character set
664 * with CIMD2-specific escapes. */
packet_get_sms_parm(struct packet * packet,int parmno)665 static Octstr *packet_get_sms_parm(struct packet *packet, int parmno)
666 {
667 /* Our code should never even try a bad parameter access. */
668 gw_assert(parm_type(parmno) == P_SMS);
669
670 return packet_get_parm(packet, parmno);
671 }
672
673 /* There is no packet_get_time_parm because the CIMD 2 timestamp
674 * format is useless. It's in the local time of the MC, with
675 * a 2-digit year and no DST information. We can do without.
676 */
677
678 /* Look for a Hex parameter with id 'parmno' in the packet and return
679 * its value. Return NULL if the parameter was not found. The value
680 * is de-hexed. */
packet_get_hex_parm(struct packet * packet,int parmno)681 static Octstr *packet_get_hex_parm(struct packet *packet, int parmno)
682 {
683 Octstr *value = NULL;
684
685 /* Our code should never even try a bad parameter access. */
686 gw_assert(parm_type(parmno) == P_HEX);
687
688 value = packet_get_parm(packet, parmno);
689 if (!value)
690 goto error;
691
692 if (octstr_hex_to_binary(value) < 0)
693 goto error;
694
695 return value;
696
697 error:
698 octstr_destroy(value);
699 return NULL;
700 }
701
702
703 /* Check if the header is according to CIMD 2 spec, generating log
704 * entries as necessary. Return -1 if anything was wrong, otherwise 0. */
packet_check_header(struct packet * packet,SMSCConn * conn)705 static int packet_check_header(struct packet *packet, SMSCConn *conn)
706 {
707 Octstr *data;
708
709 gw_assert(packet != NULL);
710 data = packet->data;
711
712 /* The header must have a two-digit operation code, a colon,
713 * and a three-digit sequence number, followed by a tab.
714 * (CIMD2, 3.1) */
715 if (octstr_len(data) < 8 ||
716 !octstr_check_range(data, 1, 2, gw_isdigit) ||
717 octstr_get_char(data, 3) != ':' ||
718 !octstr_check_range(data, 4, 3, gw_isdigit) ||
719 octstr_get_char(data, 7) != TAB) {
720 warning(0, "CIMD2[%s]: packet header in wrong format",
721 octstr_get_cstr(conn->id));
722 return -1;
723 }
724
725 return 0;
726 }
727
packet_check_parameter(struct packet * packet,long pos,long len,SMSCConn * conn)728 static int packet_check_parameter(struct packet *packet, long pos, long len, SMSCConn *conn)
729 {
730 Octstr *data;
731 long parm;
732 long dpos, dlen;
733 int negative;
734 long value;
735 int i;
736 int errors = 0;
737
738 gw_assert(packet != NULL);
739 data = packet->data;
740
741 /* The parameter header should be TAB, followed by a three-digit
742 * parameter number, a colon, and the data. We already know about
743 * the tab. */
744
745 if (len < 5 ||
746 !octstr_check_range(data, pos + 1, 3, gw_isdigit) ||
747 octstr_get_char(data, pos + 4) != ':') {
748 warning(0, "CIMD2[%s]: parameter at offset %ld in wrong format",
749 octstr_get_cstr(conn->id),
750 pos);
751 errors++;
752 }
753
754 /* If we can't parse a parameter number, there's nothing more
755 * that we can check. */
756 dpos = octstr_parse_long(&parm, data, pos + 1, 10);
757 if (dpos < 0)
758 return -1;
759 if (octstr_get_char(data, dpos) == ':')
760 dpos++;
761 dlen = len - (dpos - pos);
762 /* dlen can not go negative because octstr_parse_long must have
763 * been stopped by the TAB at the end of the parameter data. */
764 gw_assert(dlen >= 0);
765
766 i = parm_index(parm);
767
768 if (i < 0) {
769 warning(0, "CIMD2[%s]: packet contains unknown parameter %ld",
770 octstr_get_cstr(conn->id),
771 parm);
772 return -1;
773 }
774
775 if (dlen > parameters[i].maxlen) {
776 warning(0, "CIMD2[%s]: packet has '%s' parameter with length %ld, spec says max %d",
777 octstr_get_cstr(conn->id),
778 parameters[i].name, len, parameters[i].maxlen);
779 errors++;
780 }
781
782 switch (parameters[i].type) {
783 case P_INT:
784 /* Allow a leading - */
785 negative = (octstr_get_char(data, dpos) == '-');
786 if (!octstr_check_range(data, dpos + negative,
787 dlen - negative, gw_isdigit)) {
788 warning(0, "CIMD2[%s]: packet has '%s' parameter with non-integer contents",
789 octstr_get_cstr(conn->id),
790 parameters[i].name);
791 errors++;
792 }
793 if (octstr_parse_long(&value, data, dpos, 10) >= 0 &&
794 (value < parameters[i].minval || value > parameters[i].maxval)) {
795 warning(0, "CIMD2[%s]: packet has '%s' parameter out of range (value %ld, min %d, max %d)",
796 octstr_get_cstr(conn->id),
797 parameters[i].name, value,
798 parameters[i].minval, parameters[i].maxval);
799 errors++;
800 }
801 break;
802 case P_TIME:
803 if (!octstr_check_range(data, dpos, dlen, gw_isdigit)) {
804 warning(0, "CIMD2[%s]: packet has '%s' parameter with non-digit contents",
805 octstr_get_cstr(conn->id),
806 parameters[i].name);
807 errors++;
808 }
809 break;
810 case P_ADDRESS:
811 if (!octstr_check_range(data, dpos, dlen, isphonedigit)) {
812 warning(0, "CIMD2[%s]: packet has '%s' parameter with non phone number contents",
813 octstr_get_cstr(conn->id),
814 parameters[i].name);
815 errors++;
816 }
817 break;
818 case P_HEX:
819 if (!octstr_check_range(data, dpos, dlen, gw_isxdigit)) {
820 warning(0, "CIMD2[%s]: packet has '%s' parameter with non-hex contents",
821 octstr_get_cstr(conn->id),
822 parameters[i].name);
823 errors++;
824 }
825 if (dlen % 2 != 0) {
826 warning(0, "CIMD2[%s]: packet has odd-length '%s' parameter",
827 octstr_get_cstr(conn->id),
828 parameters[i].name);
829 errors++;
830 }
831 break;
832 case P_SMS:
833 case P_STRING: /* nothing to check */
834 break;
835 }
836
837 if (errors > 0)
838 return -1;
839 return 0;
840 }
841
842
843 /* Check the packet against the CIMD 2 spec, generating log entries as
844 * necessary. Return -1 if anything was wrong, otherwise 0. */
845 /* TODO: Check if parameters found actually belong in the packet type */
packet_check(struct packet * packet,SMSCConn * conn)846 static int packet_check(struct packet *packet, SMSCConn *conn)
847 {
848 int errors = 0;
849 long pos, next;
850 Octstr *data;
851
852 gw_assert(packet != NULL);
853 data = packet->data;
854
855 if (octstr_search_char(data, 0, 0) >= 0) {
856 /* CIMD2 spec does not allow NUL bytes in a packet */
857 warning(0, "CIMD2[%s]: packet contains NULs",
858 octstr_get_cstr(conn->id));
859 errors++;
860 }
861
862 /* Assume the packet starts with STX and ends with ETX,
863 * because we parsed it that way in the first place. */
864
865 errors += (packet_check_header(packet,conn) < 0);
866
867 /* Parameters are separated by tabs. After the last parameter
868 * there is a tab, an optional two-digit checksum, and the ETX.
869 * Check each parameter in turn, by skipping from tab to tab.
870 */
871 /* Start at the first tab, wherever it is, so that we can still
872 * check parameters if the header was weird. */
873 pos = octstr_search_char(data, TAB, 0);
874 for ( ; pos >= 0; pos = next) {
875 next = octstr_search_char(data, TAB, pos + 1);
876 if (next >= 0) {
877 errors += (packet_check_parameter(packet, pos, next - pos, conn) < 0);
878 } else {
879 /* Check if the checksum has the right format. Don't
880 * check the sum itself here, that will be done in a
881 * separate call later. */
882 /* There are two valid formats: TAB ETX (no checksum)
883 * and TAB digit digit ETX. We already know the TAB
884 * and the ETX are there. */
885 if (!(octstr_len(data) - pos == 2 ||
886 (octstr_len(data) - pos == 4 &&
887 octstr_check_range(data, pos + 1, 2, gw_isxdigit)))) {
888 warning(0, "CIMD2[%s]: packet checksum in wrong format",
889 octstr_get_cstr(conn->id));
890 errors++;
891 }
892 }
893 }
894
895
896 if (errors > 0) {
897 octstr_dump(packet->data, 0);
898 return -1;
899 }
900
901 return 0;
902 }
903
packet_check_can_receive(struct packet * packet,SMSCConn * conn)904 static void packet_check_can_receive(struct packet *packet, SMSCConn *conn)
905 {
906 gw_assert(packet != NULL);
907
908 if (!operation_can_receive(packet->operation)) {
909 Octstr *name = operation_name(packet->operation);
910 warning(0, "CIMD2[%s]: SMSC sent us %s request",
911 octstr_get_cstr(conn->id),
912 octstr_get_cstr(name));
913 octstr_destroy(name);
914 }
915 }
916
917 /* Table of known error codes */
918 static struct
919 {
920 int code;
921 char *text;
922 }
923 cimd2_errors[] = {
924 { 0, "No error" },
925 { 1, "Unexpected operation" },
926 { 2, "Syntax error" },
927 { 3, "Unsupported parameter error" },
928 { 4, "Connection to message center lost" },
929 { 5, "No response from message center" },
930 { 6, "General system error" },
931 { 7, "Cannot find information" },
932 { 8, "Parameter formatting error" },
933 { 9, "Requested operation failed" },
934 /* LOGIN error codes */
935 { 100, "Invalid login" },
936 { 101, "Incorrect access type" },
937 { 102, "Too many users with this login id" },
938 { 103, "Login refused by message center" },
939 /* SUBMIT MESSAGE error codes */
940 { 300, "Incorrect destination address" },
941 { 301, "Incorrect number of destination addresses" },
942 { 302, "Syntax error in user data parameter" },
943 { 303, "Incorrect bin/head/normal user data parameter combination" },
944 { 304, "Incorrect data coding scheme parameter usage" },
945 { 305, "Incorrect validity period parameters usage" },
946 { 306, "Incorrect originator address usage" },
947 { 307, "Incorrect pid paramterer usage" },
948 { 308, "Incorrect first delivery parameter usage" },
949 { 309, "Incorrect reply path usage" },
950 { 310, "Incorrect status report request parameter usage" },
951 { 311, "Incorrect cancel enabled parameter usage" },
952 { 312, "Incorrect priority parameter usage" },
953 { 313, "Incorrect tariff class parameter usage" },
954 { 314, "Incorrect service description parameter usage" },
955 { 315, "Incorrect transport type parameter usage" },
956 { 316, "Incorrect message type parameter usage" },
957 { 318, "Incorrect mms parameter usage" },
958 { 319, "Incorrect operation timer parameter usage" },
959 /* ENQUIRE MESSAGE STATUS error codes */
960 { 400, "Incorrect address parameter usage" },
961 { 401, "Incorrect scts parameter usage" },
962 /* DELIVERY REQUEST error codes */
963 { 500, "Incorrect scts parameter usage" },
964 { 501, "Incorrect mode parameter usage" },
965 { 502, "Incorrect parameter combination" },
966 /* CANCEL MESSAGE error codes */
967 { 600, "Incorrect scts parameter usage" },
968 { 601, "Incorrect address parameter usage" },
969 { 602, "Incorrect mode parameter usage" },
970 { 603, "Incorrect parameter combination" },
971 /* SET error codes */
972 { 800, "Changing password failed" },
973 { 801, "Changing password not allowed" },
974 /* GET error codes */
975 { 900, "Unsupported item requested" },
976 { -1, NULL }
977 };
978
packet_display_error(struct packet * packet,SMSCConn * conn)979 static int packet_display_error(struct packet *packet, SMSCConn *conn)
980 {
981 int code;
982 Octstr *text = NULL;
983 Octstr *opname = NULL;
984
985 code = packet_get_int_parm(packet, P_ERROR_CODE);
986 text = packet_get_string_parm(packet, P_ERROR_TEXT);
987
988 if (code <= 0) {
989 octstr_destroy(text);
990 return 0;
991 }
992
993 if (text == NULL) {
994 /* No error text. Try to find it in the table. */
995 int i;
996 for (i = 0; cimd2_errors[i].text != NULL; i++) {
997 if (cimd2_errors[i].code == code) {
998 text = octstr_create(cimd2_errors[i].text);
999 break;
1000 }
1001 }
1002 }
1003
1004 if (text == NULL) {
1005 /* Still no error text. Make one up. */
1006 text = octstr_create("Unknown error");
1007 }
1008
1009 opname = operation_name(packet->operation);
1010 error(0, "CIMD2[%s]: %s contained error message:",
1011 octstr_get_cstr(conn->id),
1012 octstr_get_cstr(opname));
1013 error(0, "code %03d: %s", code, octstr_get_cstr(text));
1014 octstr_destroy(opname);
1015 octstr_destroy(text);
1016 return code;
1017 }
1018
1019 /* Table of special combinations, for convert_gsm_to_latin1. */
1020 /* Each cimd1, cimd2 pair is mapped to a character in the GSM default
1021 * character set. */
1022 static const struct
1023 {
1024 unsigned char cimd1, cimd2;
1025 unsigned char gsm;
1026 }
1027 cimd_combinations[] = {
1028 { 'O', 'a', 0 }, /* @ */
1029 { 'L', '-', 1 }, /* Pounds sterling */
1030 { 'Y', '-', 3 }, /* Yen */
1031 { 'e', '`', 4 }, /* egrave */
1032 { 'e', '\'', 5 }, /* eacute */
1033 { 'u', '`', 6 }, /* ugrave */
1034 { 'i', '`', 7 }, /* igrave */
1035 { 'o', '`', 8 }, /* ograve */
1036 { 'C', ',', 9 }, /* C cedilla */
1037 { 'O', '/', 11 }, /* Oslash */
1038 { 'o', '/', 12 }, /* oslash */
1039 { 'A', '*', 14 }, /* Aring */
1040 { 'a', '*', 15 }, /* aring */
1041 { 'g', 'd', 16 }, /* greek delta */
1042 { '-', '-', 17 }, /* underscore */
1043 { 'g', 'f', 18 }, /* greek phi */
1044 { 'g', 'g', 19 }, /* greek gamma */
1045 { 'g', 'l', 20 }, /* greek lambda */
1046 { 'g', 'o', 21 }, /* greek omega */
1047 { 'g', 'p', 22 }, /* greek pi */
1048 { 'g', 'i', 23 }, /* greek psi */
1049 { 'g', 's', 24 }, /* greek sigma */
1050 { 'g', 't', 25 }, /* greek theta */
1051 { 'g', 'x', 26 }, /* greek xi */
1052 { 'X', 'X', 27 }, /* escape */
1053 { 'A', 'E', 28 }, /* AE ligature */
1054 { 'a', 'e', 29 }, /* ae ligature */
1055 { 's', 's', 30 }, /* german double s */
1056 { 'E', '\'', 31 }, /* Eacute */
1057 { 'q', 'q', '"' },
1058 { 'o', 'x', 36 }, /* international currency symbol */
1059 { '!', '!', 64 }, /* inverted ! */
1060 { 'A', '"', 91 }, /* Adieresis */
1061 { 'O', '"', 92 }, /* Odieresis */
1062 { 'N', '~', 93 }, /* N tilde */
1063 { 'U', '"', 94 }, /* Udieresis */
1064 { 's', 'o', 95 }, /* section mark */
1065 { '?', '?', 96 }, /* inverted ? */
1066 { 'a', '"', 123 }, /* adieresis */
1067 { 'o', '"', 124 }, /* odieresis */
1068 { 'n', '~', 125 }, /* n tilde */
1069 { 'u', '"', 126 }, /* udieresis */
1070 { 'a', '`', 127 }, /* agrave */
1071 { 0, 0, 0 }
1072 };
1073
1074
1075 /* Convert text in the CIMD2 User Data format to the GSM default
1076 * character set.
1077 * CIMD2 allows 8-bit characters in this format; they map directly
1078 * to the corresponding ISO-8859-1 characters. Since we are heading
1079 * toward that character set in the end, we don't bother converting
1080 * those to GSM. */
convert_cimd2_to_gsm(Octstr * text,SMSCConn * conn)1081 static void convert_cimd2_to_gsm(Octstr *text, SMSCConn *conn)
1082 {
1083 long pos, len;
1084 int cimd1, cimd2;
1085 int c;
1086 int i;
1087
1088 /* CIMD2 uses four single-character mappings that do not map
1089 * to themselves:
1090 * '@' from 64 to 0, '$' from 36 to 2, ']' from 93 to 14 (A-ring),
1091 * and '}' from 125 to 15 (a-ring).
1092 * Other than those, we only have to worry about the escape
1093 * sequences introduced by _ (underscore).
1094 */
1095
1096 len = octstr_len(text);
1097 for (pos = 0; pos < len; pos++) {
1098 c = octstr_get_char(text, pos);
1099 if (c == '@')
1100 octstr_set_char(text, pos, 0);
1101 else if (c == '$')
1102 octstr_set_char(text, pos, 2);
1103 else if (c == ']')
1104 octstr_set_char(text, pos, 14);
1105 else if (c == '}')
1106 octstr_set_char(text, pos, 15);
1107 else if (c == '_' && pos + 2 < len) {
1108 cimd1 = octstr_get_char(text, pos + 1);
1109 cimd2 = octstr_get_char(text, pos + 2);
1110 for (i = 0; cimd_combinations[i].cimd1 != 0; i++) {
1111 if (cimd_combinations[i].cimd1 == cimd1 &&
1112 cimd_combinations[i].cimd2 == cimd2)
1113 break;
1114 }
1115 if (cimd_combinations[i].cimd1 == 0)
1116 warning(0, "CIMD2[%s]: Encountered unknown "
1117 "escape code _%c%c, ignoring.",
1118 octstr_get_cstr(conn->id),
1119 cimd1, cimd2);
1120 else {
1121 octstr_delete(text, pos, 2);
1122 octstr_set_char(text, pos, cimd_combinations[i].gsm);
1123 len = octstr_len(text);
1124 }
1125 }
1126 }
1127 }
1128
1129
1130 /* Convert text in the GSM default character set to the CIMD2 User Data
1131 * format, which is a representation of the GSM default character set
1132 * in the lower 7 bits of ISO-8859-1. (8-bit characters are also
1133 * allowed, but it's just as easy not to use them.) */
convert_gsm_to_cimd2(Octstr * text)1134 static void convert_gsm_to_cimd2(Octstr *text)
1135 {
1136 long pos, len;
1137
1138 len = octstr_len(text);
1139 for (pos = 0; pos < len; pos++) {
1140 int c, i;
1141
1142 c = octstr_get_char(text, pos);
1143 /* If c is not in the GSM alphabet at this point,
1144 * the caller did something badly wrong. */
1145 gw_assert(c >= 0);
1146 gw_assert(c < 128);
1147
1148 for (i = 0; cimd_combinations[i].cimd1 != 0; i++) {
1149 if (cimd_combinations[i].gsm == c)
1150 break;
1151 }
1152
1153 if (cimd_combinations[i].gsm == c) {
1154 /* Escape sequence */
1155 octstr_insert_data(text, pos, "_ ", 2);
1156 pos += 2;
1157 len += 2;
1158 octstr_set_char(text, pos - 1, cimd_combinations[i].cimd1);
1159 octstr_set_char(text, pos, cimd_combinations[i].cimd2);
1160 } else if (c == 2) {
1161 /* The dollar sign is the only GSM character that
1162 * does not have a CIMD escape sequence and does not
1163 * map to itself. */
1164 octstr_set_char(text, pos, '$');
1165 }
1166 }
1167 }
1168
1169
1170 /***************************************************************************/
1171 /* Packet encoding functions. They do not allow the creation of invalid */
1172 /* CIMD 2 packets. */
1173 /***************************************************************************/
1174
1175 /* Build a new packet struct with this operation code and sequence number. */
packet_create(int operation,int seq)1176 static struct packet *packet_create(int operation, int seq)
1177 {
1178 struct packet *packet;
1179 char minpacket[sizeof("sOO:SSSte")];
1180
1181 packet = gw_malloc(sizeof(*packet));
1182 packet->operation = operation;
1183 packet->seq = seq;
1184 sprintf(minpacket, STX_str "%02d:%03d" TAB_str ETX_str, operation, seq);
1185 packet->data = octstr_create(minpacket);
1186
1187 return packet;
1188 }
1189
1190 /* Add a parameter to the end of packet */
packet_add_parm(struct packet * packet,int parmtype,int parmno,Octstr * value,SMSCConn * conn)1191 static void packet_add_parm(struct packet *packet, int parmtype,
1192 int parmno, Octstr *value, SMSCConn *conn)
1193 {
1194 char parmh[sizeof("tPPP:")];
1195 long position;
1196 long len;
1197 int copied = 0;
1198
1199 len = octstr_len(value);
1200
1201 gw_assert(packet != NULL);
1202 gw_assert(parm_type(parmno) == parmtype);
1203
1204 if (len > parm_maxlen(parmno)) {
1205 warning(0, "CIMD2[%s]: %s parameter too long, truncating from "
1206 "%ld to %ld characters",
1207 octstr_get_cstr(conn->id),
1208 parm_name(parmno),
1209 len,
1210 (long) parm_maxlen(parmno));
1211 value = octstr_copy(value, 0, parm_maxlen(parmno));
1212 copied = 1;
1213 }
1214
1215 /* There's a TAB and ETX at the end; insert it before those.
1216 * The new parameter will come with a new starting TAB. */
1217 position = octstr_len(packet->data) - 2;
1218
1219 sprintf(parmh, TAB_str "%03d:", parmno);
1220 octstr_insert_data(packet->data, position, parmh, strlen(parmh));
1221 octstr_insert(packet->data, value, position + strlen(parmh));
1222 if (copied)
1223 octstr_destroy(value);
1224 }
1225
1226 /* Add a String parameter to the packet */
packet_add_string_parm(struct packet * packet,int parmno,Octstr * value,SMSCConn * conn)1227 static void packet_add_string_parm(struct packet *packet, int parmno, Octstr *value, SMSCConn *conn)
1228 {
1229 packet_add_parm(packet, P_STRING, parmno, value, conn);
1230 }
1231
1232 /* Add an Address parameter to the packet */
packet_add_address_parm(struct packet * packet,int parmno,Octstr * value,SMSCConn * conn)1233 static void packet_add_address_parm(struct packet *packet, int parmno, Octstr *value, SMSCConn *conn)
1234 {
1235 gw_assert(octstr_check_range(value, 0, octstr_len(value), isphonedigit));
1236 packet_add_parm(packet, P_ADDRESS, parmno, value, conn);
1237 }
1238
1239 /* Add an SMS parameter to the packet. The caller is expected to have done
1240 * the translation to the GSM character set already. */
packet_add_sms_parm(struct packet * packet,int parmno,Octstr * value,SMSCConn * conn)1241 static void packet_add_sms_parm(struct packet *packet, int parmno, Octstr *value, SMSCConn *conn)
1242 {
1243 packet_add_parm(packet, P_SMS, parmno, value, conn);
1244 }
1245
1246 /* There is no function for adding a Time parameter to the packet, because
1247 * the format makes Time parameters useless for us. If you find that you
1248 * need to use them, then also add code for querying the SMS center timestamp
1249 * and using that for synchronization. And beware of DST changes. */
1250
1251 /* Add a Hexadecimal parameter to the packet */
packet_add_hex_parm(struct packet * packet,int parmno,Octstr * value,SMSCConn * conn)1252 static void packet_add_hex_parm(struct packet *packet, int parmno, Octstr *value, SMSCConn *conn)
1253 {
1254 value = octstr_duplicate(value);
1255 octstr_binary_to_hex(value, 1); /* 1 for uppercase hex, i.e. A .. F */
1256 packet_add_parm(packet, P_HEX, parmno, value, conn);
1257 octstr_destroy(value);
1258 }
1259
1260 /* Add an Integer parameter to the packet */
packet_add_int_parm(struct packet * packet,int parmno,long value,SMSCConn * conn)1261 static void packet_add_int_parm(struct packet *packet, int parmno, long value, SMSCConn *conn)
1262 {
1263 char buf[128];
1264 Octstr *valuestr;
1265
1266 gw_assert(parm_in_range(parmno, value));
1267
1268 sprintf(buf, "%ld", value);
1269 valuestr = octstr_create(buf);
1270 packet_add_parm(packet, P_INT, parmno, valuestr, conn);
1271 octstr_destroy(valuestr);
1272 }
1273
packet_set_checksum(struct packet * packet)1274 static void packet_set_checksum(struct packet *packet)
1275 {
1276 Octstr *data;
1277 int checksum;
1278 long pos, len;
1279 char buf[16];
1280
1281 gw_assert(packet != NULL);
1282
1283 data = packet->data;
1284 if (octstr_get_char(data, octstr_len(data) - 2) != TAB) {
1285 /* Packet already has checksum; kill it. */
1286 octstr_delete(data, octstr_len(data) - 3, 2);
1287 }
1288
1289 gw_assert(octstr_get_char(data, octstr_len(data) - 2) == TAB);
1290
1291 /* Sum all the way up to the last TAB */
1292 checksum = 0;
1293 for (pos = 0, len = octstr_len(data); pos < len - 1; pos++) {
1294 checksum += octstr_get_char(data, pos);
1295 checksum &= 0xff;
1296 }
1297
1298 sprintf(buf, "%02X", checksum);
1299 octstr_insert_data(data, len - 1, buf, 2);
1300 }
1301
packet_set_sequence(struct packet * packet,int seq)1302 static void packet_set_sequence(struct packet *packet, int seq)
1303 {
1304 char buf[16];
1305
1306 gw_assert(packet != NULL);
1307 gw_assert(seq >= 0);
1308 gw_assert(seq < 256);
1309
1310 sprintf(buf, "%03d", seq);
1311
1312 /* Start at 4 to skip the <STX> ZZ: part of the header. */
1313 octstr_set_char(packet->data, 4, buf[0]);
1314 octstr_set_char(packet->data, 5, buf[1]);
1315 octstr_set_char(packet->data, 6, buf[2]);
1316 packet->seq = seq;
1317 }
1318
packet_encode_message(Msg * msg,Octstr * sender_prefix,SMSCConn * conn)1319 static struct packet *packet_encode_message(Msg *msg, Octstr *sender_prefix, SMSCConn *conn)
1320 {
1321 struct packet *packet;
1322 PrivData *pdata = conn->data;
1323 Octstr *text;
1324 int spaceleft;
1325 long truncated;
1326 int dcs = 0;
1327 int setvalidity = 0;
1328
1329 gw_assert(msg != NULL);
1330 gw_assert(msg->type == sms);
1331 gw_assert(msg->sms.receiver != NULL);
1332
1333 dcs = fields_to_dcs(msg, (msg->sms.alt_dcs != -1 ?
1334 msg->sms.alt_dcs : conn->alt_dcs));
1335 if (msg->sms.sender == NULL)
1336 msg->sms.sender = octstr_create("");
1337
1338 if (!parm_valid_address(msg->sms.receiver)) {
1339 warning(0, "CIMD2[%s]: non-digits in destination phone number '%s', discarded",
1340 octstr_get_cstr(conn->id),
1341 octstr_get_cstr(msg->sms.receiver));
1342 return NULL;
1343 }
1344
1345 packet = packet_create(SUBMIT_MESSAGE, BOGUS_SEQUENCE);
1346
1347 packet_add_address_parm(packet, P_DESTINATION_ADDRESS, msg->sms.receiver, conn);
1348
1349 /* CIMD2 interprets the originating address as a sub-address to
1350 * our connection number (so if the connection is "400" and we
1351 * fill in "600" as the sender number, the user sees "400600").
1352 * Since we have no way to ask what this number is, it has to
1353 * be configured. */
1354
1355 /* Quick and dirty check to see if we are using alphanumeric sender */
1356 if (parm_valid_address(msg->sms.sender)) {
1357 /* We are not, so send in the usual way */
1358 /* Speed up the default case */
1359 if (octstr_len(sender_prefix) == 0) {
1360 packet_add_address_parm(packet, P_ORIGINATING_ADDRESS,msg->sms.sender, conn);
1361 }
1362 else if (octstr_compare(sender_prefix, octstr_imm("never")) != 0) {
1363 if (octstr_ncompare(sender_prefix, msg->sms.sender,
1364 octstr_len(sender_prefix)) == 0) {
1365 Octstr *sender;
1366 sender = octstr_copy(msg->sms.sender,
1367 octstr_len(sender_prefix), octstr_len(msg->sms.sender));
1368 packet_add_address_parm(packet, P_ORIGINATING_ADDRESS, sender, conn);
1369 octstr_destroy(sender);
1370 } else {
1371 warning(0, "CIMD2[%s]: Sending message with originating address <%s>, "
1372 "which does not start with the sender-prefix.",
1373 octstr_get_cstr(conn->id),
1374 octstr_get_cstr(msg->sms.sender));
1375 }
1376 }
1377 }
1378 else {
1379 /* The test above to check if sender was all digits failed, so assume we want alphanumeric sender */
1380 packet_add_string_parm(packet, P_ALPHANUMERIC_ORIGINATING_ADDRESS,msg->sms.sender, conn);
1381 }
1382
1383 /* Add the validity period if necessary. This sets the relative validity
1384 * period as this is the description of the "validity" parameter of the
1385 * sendsms interface.
1386 *
1387 * Convert from minutes to GSM 03.40 specification (section 9.2.3.12).
1388 * 0-143 = 0 to 12 hours in 5 minute increments.
1389 * 144-167 = 12hrs30min to 24hrs in 30 minute increments.
1390 * 168-196 = 2days to 30days in 1 day increments.
1391 * 197-255 = 5weeks to 63weeks in 1 week increments.
1392 *
1393 * This code was copied from smsc_at2.c.
1394 */
1395 if (msg->sms.validity != MSG_PARAM_UNDEFINED) {
1396 long val = (msg->sms.validity - time(NULL)) / 60;
1397 if (val > 635040)
1398 setvalidity = 255;
1399 if (val >= 50400 && val <= 635040)
1400 setvalidity = (val - 1) / 7 / 24 / 60 + 192 + 1;
1401 if (val > 43200 && val < 50400)
1402 setvalidity = 197;
1403 if (val >= 2880 && val <= 43200)
1404 setvalidity = (val - 1) / 24 / 60 + 166 + 1;
1405 if (val > 1440 && val < 2880)
1406 setvalidity = 168;
1407 if (val >= 750 && val <= 1440)
1408 setvalidity = (val - 720 - 1) / 30 + 143 + 1;
1409 if (val > 720 && val < 750)
1410 setvalidity = 144;
1411 if (val >= 5 && val <= 720)
1412 setvalidity = (val - 1) / 5 - 1 + 1;
1413 if (val < 5)
1414 setvalidity = 0;
1415
1416 packet_add_int_parm(packet, P_VALIDITY_PERIOD_RELATIVE, setvalidity, conn);
1417 }
1418
1419 /* Explicitly ask not to get status reports.
1420 * If we do not do this, the server's default might be to
1421 * send status reports in some cases, and we don't do anything
1422 * with those reports anyway. */
1423 /* ask for the delivery reports if needed*/
1424
1425 if (!pdata->no_dlr)
1426 if (DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
1427 packet_add_int_parm(packet, P_STATUS_REPORT_REQUEST, 14, conn);
1428 else
1429 packet_add_int_parm(packet, P_STATUS_REPORT_REQUEST, 0, conn);
1430 else if( pdata->no_dlr && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
1431 warning(0, "CIMD2[%s]: dlr request make no sense while no-dlr set to true",
1432 octstr_get_cstr(conn->id));
1433
1434 /* Turn off reply path as default.
1435 * This avoids phones automatically asking for a reply
1436 */
1437 if (msg->sms.rpi > 0)
1438 packet_add_int_parm(packet, P_REPLY_PATH, 1, conn);
1439 else
1440 packet_add_int_parm(packet, P_REPLY_PATH, 0, conn);
1441
1442 /* Use binfo to set the tariff class */
1443 if (octstr_len(msg->sms.binfo))
1444 packet_add_parm(packet, P_INT, P_TARIFF_CLASS, msg->sms.binfo, conn);
1445
1446 /* Set the protocol identifier if requested */
1447 if (msg->sms.pid > 0)
1448 packet_add_int_parm(packet, P_PROTOCOL_IDENTIFIER, msg->sms.pid, conn);
1449
1450 /* If there are more messages to the same destination, then set the
1451 * More Messages to Send flag. This allow faster delivery of many messages
1452 * to the same destination
1453 */
1454 if (msg->sms.msg_left > 0)
1455 packet_add_int_parm(packet, P_MORE_MESSAGES_TO_SEND, 1, conn);
1456 else
1457 packet_add_int_parm(packet, P_MORE_MESSAGES_TO_SEND, 0, conn);
1458
1459 truncated = 0;
1460
1461 spaceleft = 140;
1462 if (octstr_len(msg->sms.udhdata)) {
1463 /* udhdata will be truncated and warned about if
1464 * it does not fit. */
1465 packet_add_hex_parm(packet, P_USER_DATA_HEADER, msg->sms.udhdata, conn);
1466 }
1467 if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF)
1468 spaceleft = spaceleft * 8 / 7;
1469 if (spaceleft < 0)
1470 spaceleft = 0;
1471
1472 text = octstr_duplicate(msg->sms.msgdata);
1473
1474 if (octstr_len(text) > 0 && spaceleft == 0) {
1475 warning(0, "CIMD2[%s]: message filled up with UDH, no room for message text",
1476 octstr_get_cstr(conn->id));
1477 } else if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
1478 if (octstr_len(text) > spaceleft) {
1479 truncated = octstr_len(text) - spaceleft;
1480 octstr_truncate(text, spaceleft);
1481 }
1482 packet_add_hex_parm(packet, P_USER_DATA_BINARY, text, conn);
1483 } else {
1484 /* Going from latin1 to GSM to CIMD2 may seem like a
1485 * detour, but it's the only way to get all the escape
1486 * codes right. */
1487 charset_utf8_to_gsm(text);
1488 truncated = charset_gsm_truncate(text, spaceleft);
1489 convert_gsm_to_cimd2(text);
1490 packet_add_sms_parm(packet, P_USER_DATA, text, conn);
1491 }
1492
1493 if (dcs != 0)
1494 packet_add_int_parm(packet, P_DATA_CODING_SCHEME, dcs, conn);
1495
1496 if (truncated > 0) {
1497 warning(0, "CIMD2[%s]: truncating message text to fit in %d characters.",
1498 octstr_get_cstr(conn->id),
1499 spaceleft);
1500 }
1501
1502 octstr_destroy(text);
1503 return packet;
1504 }
1505
1506 /***************************************************************************/
1507 /* Protocol functions. These implement various transactions. */
1508 /***************************************************************************/
1509
1510 /* Give this packet a proper sequence number for sending. */
packet_set_send_sequence(struct packet * packet,PrivData * pdata)1511 static void packet_set_send_sequence(struct packet *packet, PrivData *pdata)
1512 {
1513 gw_assert(pdata != NULL);
1514 /* LOGIN packets always have sequence number 001 */
1515 if (packet->operation == LOGIN)
1516 pdata->send_seq = 1;
1517 /* Send sequence numbers are always odd, receiving are always even */
1518 gw_assert(pdata->send_seq % 2 == 1);
1519
1520 packet_set_sequence(packet, pdata->send_seq);
1521 pdata->send_seq += 2;
1522 if (pdata->send_seq > 256)
1523 pdata->send_seq = 1;
1524 }
1525
cimd2_get_packet(PrivData * pdata,Octstr ** ts)1526 static struct packet *cimd2_get_packet(PrivData *pdata, Octstr **ts)
1527 {
1528 struct packet *packet = NULL;
1529
1530 gw_assert(pdata != NULL);
1531
1532 /* If packet is already available, don't try to read anything */
1533 packet = packet_extract(pdata->inbuffer, pdata->conn);
1534
1535 while (packet == NULL) {
1536 if (read_available(pdata->socket, RESPONSE_TIMEOUT) != 1) {
1537 warning(0, "CIMD2[%s]: SMSC is not responding",
1538 octstr_get_cstr(pdata->conn->id));
1539 return NULL;
1540 }
1541
1542 if (octstr_append_from_socket(pdata->inbuffer, pdata->socket) <= 0) {
1543 error(0, "CIMD2[%s]: cimd2_get_packet: read failed",
1544 octstr_get_cstr(pdata->conn->id));
1545 return NULL;
1546 }
1547
1548 packet = packet_extract(pdata->inbuffer, pdata->conn);
1549 }
1550
1551 packet_check(packet,pdata->conn);
1552 packet_check_can_receive(packet,pdata->conn);
1553 debug("bb.sms.cimd2", 0, "CIMD2[%s]: received: <%s>",
1554 octstr_get_cstr(pdata->conn->id),
1555 octstr_get_cstr(packet->data));
1556 if (ts)
1557 *ts = packet_get_parm(packet,P_MC_TIMESTAMP);
1558
1559 if (pdata->keepalive > 0)
1560 pdata->next_ping = time(NULL) + pdata->keepalive;
1561
1562 return packet;
1563 }
1564
1565 /* Acknowledge a request. The CIMD 2 spec only defines positive responses
1566 * to the server, because the server is perfect. */
cimd2_send_response(struct packet * request,PrivData * pdata)1567 static void cimd2_send_response(struct packet *request, PrivData *pdata)
1568 {
1569 struct packet *response;
1570
1571 gw_assert(request != NULL);
1572 gw_assert(request->operation < RESPONSE);
1573
1574 response = packet_create(request->operation + RESPONSE, request->seq);
1575 packet_set_checksum(response);
1576
1577 debug("bb.sms.cimd2", 0, "CIMD2[%s]: sending <%s>",
1578 octstr_get_cstr(pdata->conn->id),
1579 octstr_get_cstr(response->data));
1580
1581 /* Don't check errors here because if there is something
1582 * wrong with the socket, the main loop will detect it. */
1583 octstr_write_to_socket(pdata->socket, response->data);
1584
1585 packet_destroy(response);
1586 }
1587
cimd2_accept_message(struct packet * request,SMSCConn * conn)1588 static Msg *cimd2_accept_message(struct packet *request, SMSCConn *conn)
1589 {
1590 Msg *message = NULL;
1591 Octstr *destination = NULL;
1592 Octstr *origin = NULL;
1593 Octstr *UDH = NULL;
1594 Octstr *text = NULL;
1595 int DCS;
1596
1597 /* See GSM 03.38. The bit patterns we can handle are:
1598 * 000xyyxx Uncompressed text, yy indicates alphabet.
1599 * yy = 00, default alphabet
1600 * yy = 01, 8-bit data
1601 * yy = 10, UCS-2
1602 * yy = 11, reserved
1603 * 1111xyxx Data, y indicates alphabet.
1604 * y = 0, default alphabet
1605 * y = 1, 8-bit data
1606 */
1607 DCS = packet_get_int_parm(request, P_DATA_CODING_SCHEME);
1608
1609 destination = packet_get_address_parm(request, P_DESTINATION_ADDRESS);
1610 origin = packet_get_address_parm(request, P_ORIGINATING_ADDRESS);
1611 UDH = packet_get_hex_parm(request, P_USER_DATA_HEADER);
1612 /* Text is either in User Data or User Data Binary field. */
1613 text = packet_get_sms_parm(request, P_USER_DATA);
1614 if (text != NULL) {
1615 convert_cimd2_to_gsm(text,conn);
1616 charset_gsm_to_utf8(text);
1617 } else {
1618 /*
1619 * FIXME: If DCS indicates GSM charset, and we get it in binary,
1620 * then it's probably bit-packed. We'll have to undo it because
1621 * our "charset_gsm" means one gsm character per octet. This is
1622 * not currently supported. -- RB
1623 */
1624 text = packet_get_hex_parm(request, P_USER_DATA_BINARY);
1625 }
1626
1627 /* Code elsewhere in the gateway always expects the sender and
1628 * receiver fields to be filled, so we discard messages that
1629 * lack them. If they should not be discarded, then the code
1630 * handling sms messages should be reviewed. -- RB */
1631 if (!destination || octstr_len(destination) == 0) {
1632 info(0, "CIMD2[%s]: Got SMS without receiver, discarding.",
1633 octstr_get_cstr(conn->id));
1634 goto error;
1635 }
1636 if (!origin || octstr_len(origin) == 0) {
1637 info(0, "CIMD2[%s]: Got SMS without sender, discarding.",
1638 octstr_get_cstr(conn->id));
1639 goto error;
1640 }
1641
1642 if (!text && (!UDH || octstr_len(UDH) == 0)) {
1643 info(0, "CIMD2[%s]: Got empty SMS, ignoring.",
1644 octstr_get_cstr(conn->id));
1645 goto error;
1646 }
1647
1648 message = msg_create(sms);
1649 if (! dcs_to_fields(&message, DCS)) {
1650 /* XXX Should reject this message ? */
1651 debug("bb.sms.cimd2", 0, "CIMD2[%s]: Invalid DCS",
1652 octstr_get_cstr(conn->id));
1653 dcs_to_fields(&message, 0);
1654 }
1655 time(&message->sms.time);
1656 message->sms.sender = origin;
1657 message->sms.receiver = destination;
1658 if (UDH) {
1659 message->sms.udhdata = UDH;
1660 }
1661 message->sms.msgdata = text;
1662 return message;
1663
1664 error:
1665 msg_destroy(message);
1666 octstr_destroy(destination);
1667 octstr_destroy(origin);
1668 octstr_destroy(UDH);
1669 octstr_destroy(text);
1670 return NULL;
1671 }
1672
1673 /* Deal with a request from the CIMD2 server, and acknowledge it. */
cimd2_handle_request(struct packet * request,SMSCConn * conn)1674 static void cimd2_handle_request(struct packet *request, SMSCConn *conn)
1675 {
1676 PrivData *pdata = conn->data;
1677 Msg *message = NULL;
1678
1679 if ((request->seq == 254 && pdata->receive_seq == 0) ||
1680 request->seq == pdata->receive_seq - 2) {
1681 warning(0, "CIMD2[%s]: request had same sequence number as previous.",
1682 octstr_get_cstr(conn->id));
1683 }
1684 else {
1685 pdata->receive_seq = request->seq + 2;
1686 if (pdata->receive_seq > 254)
1687 pdata->receive_seq = 0;
1688
1689 if (request->operation == DELIVER_STATUS_REPORT) {
1690 message = cimd2_accept_delivery_report_message(request, conn);
1691 if (message)
1692 gwlist_append(pdata->received, message);
1693 }
1694 else if (request->operation == DELIVER_MESSAGE) {
1695 message = cimd2_accept_message(request,conn);
1696 if (message)
1697 gwlist_append(pdata->received, message);
1698 }
1699 }
1700
1701 cimd2_send_response(request, pdata);
1702 }
1703
1704 /* Send a request and wait for the ack. If the other side responds with
1705 * an error code, attempt to correct and retry.
1706 * If other packets arrive while we wait for the ack, handle them.
1707 *
1708 * Return -1 if the SMSC refused the request. Return -2 for other
1709 * errors, such as being unable to send the request at all. If the
1710 * function returns -2, the caller would do well to try to reopen the
1711 * connection.
1712 *
1713 * The SMSCenter must be already open.
1714 *
1715 * TODO: This function has grown large and complex. Break it up
1716 * into smaller pieces.
1717 */
cimd2_request(struct packet * request,SMSCConn * conn,Octstr ** ts)1718 static int cimd2_request(struct packet *request, SMSCConn *conn, Octstr **ts)
1719 {
1720 PrivData *pdata = conn->data;
1721 int ret;
1722 struct packet *reply = NULL;
1723 int errorcode;
1724 int tries = 0;
1725
1726 gw_assert(pdata != NULL);
1727 gw_assert(request != NULL);
1728 gw_assert(operation_can_send(request->operation));
1729
1730 if (pdata->socket < 0) {
1731 warning(0, "CIMD2[%s]: cimd2_request: socket not open.",
1732 octstr_get_cstr(conn->id));
1733 return -2;
1734 }
1735
1736 retransmit:
1737 packet_set_send_sequence(request, pdata);
1738 packet_set_checksum(request);
1739
1740 debug("bb.sms.cimd2", 0, "CIMD2[%s]: sending <%s>",
1741 octstr_get_cstr(conn->id),
1742 octstr_get_cstr(request->data));
1743
1744 ret = octstr_write_to_socket(pdata->socket, request->data);
1745 if (ret < 0)
1746 goto io_error;
1747
1748 next_reply:
1749 packet_destroy(reply); /* destroy old, if any */
1750 reply = cimd2_get_packet(pdata, ts);
1751 if (!reply)
1752 goto io_error;
1753
1754 errorcode = packet_display_error(reply,conn);
1755
1756 if (reply->operation == NACK) {
1757 warning(0, "CIMD2[%s]: received NACK",
1758 octstr_get_cstr(conn->id));
1759 octstr_dump(reply->data, 0);
1760 /* Correct sequence number if server says it was wrong,
1761 * but only if server's number is sane. */
1762 if (reply->seq != request->seq && (reply->seq % 2) == 1) {
1763 warning(0, "CIMD2[%s]: correcting sequence number from %ld to %ld.",
1764 octstr_get_cstr(conn->id),
1765 (long) pdata->send_seq,
1766 (long) reply->seq);
1767 pdata->send_seq = reply->seq;
1768 }
1769 goto retry;
1770 }
1771
1772 if (reply->operation == GENERAL_ERROR_RESPONSE) {
1773 error(0, "CIMD2[%s]: received general error response",
1774 octstr_get_cstr(conn->id));
1775 goto io_error;
1776 }
1777
1778 /* The server sent us a request. Handle it, then wait for
1779 * a new reply. */
1780 if (reply->operation < RESPONSE) {
1781 cimd2_handle_request(reply, conn);
1782 goto next_reply;
1783 }
1784
1785 if (reply->seq != request->seq) {
1786 /* We got a response to a different request number than
1787 * what we send. Strange. */
1788 warning(0, "CIMD2[%s]: response had unexpected sequence number; ignoring.",
1789 octstr_get_cstr(conn->id));
1790 goto next_reply;
1791 }
1792
1793 if (reply->operation != request->operation + RESPONSE) {
1794 /* We got a response that didn't match our request */
1795 Octstr *request_name = operation_name(request->operation);
1796 Octstr *reply_name = operation_name(reply->operation);
1797 warning(0, "CIMD2[%s]: %s request got a %s",
1798 octstr_get_cstr(conn->id),
1799 octstr_get_cstr(request_name),
1800 octstr_get_cstr(reply_name));
1801
1802 octstr_destroy(request_name);
1803 octstr_destroy(reply_name);
1804 octstr_dump(reply->data, 0);
1805 goto retry;
1806 }
1807
1808 if (errorcode > 0)
1809 goto error;
1810
1811 /* The reply passed all the checks... looks like the SMSC accepted
1812 * our request! */
1813 packet_destroy(reply);
1814 return 0;
1815
1816 io_error:
1817 packet_destroy(reply);
1818 return -2;
1819
1820 error:
1821 packet_destroy(reply);
1822 return -1;
1823
1824 retry:
1825 if (++tries < 3) {
1826 warning(0, "CIMD2[%s]: Retransmitting (take %d)",
1827 octstr_get_cstr(conn->id),
1828 tries);
1829 goto retransmit;
1830 }
1831 warning(0, "CIMD2[%s]: Giving up.",
1832 octstr_get_cstr(conn->id));
1833 goto io_error;
1834 }
1835
1836 /* Close the SMSC socket without fanfare. */
cimd2_close_socket(PrivData * pdata)1837 static void cimd2_close_socket(PrivData *pdata)
1838 {
1839 gw_assert(pdata != NULL);
1840
1841 if (pdata->socket < 0)
1842 return;
1843
1844 if (close(pdata->socket) < 0)
1845 warning(errno, "CIMD2[%s]: error closing socket",
1846 octstr_get_cstr(pdata->conn->id));
1847 pdata->socket = -1;
1848 }
1849
1850 /* Open a socket to the SMSC, send a login packet, and wait for ack.
1851 * This may block. Return 0 for success, or -1 for failure. */
1852 /* Make sure the socket is closed before calling this function, otherwise
1853 * we will leak fd's. */
cimd2_login(SMSCConn * conn)1854 static int cimd2_login(SMSCConn *conn)
1855 {
1856 PrivData *pdata = conn->data;
1857 int ret;
1858 struct packet *packet = NULL;
1859
1860 gw_assert(pdata != NULL);
1861
1862 if (pdata->socket >= 0) {
1863 warning(0, "CIMD2[%s]: login: socket was already open; closing",
1864 octstr_get_cstr(conn->id));
1865 cimd2_close_socket(pdata);
1866 }
1867
1868 pdata->socket = tcpip_connect_to_server_with_port(
1869 octstr_get_cstr(pdata->host),
1870 pdata->port,
1871 pdata->our_port,
1872 (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL));
1873 if (pdata->socket != -1) {
1874
1875 packet = packet_create(LOGIN, BOGUS_SEQUENCE);
1876 packet_add_string_parm(packet, P_USER_IDENTITY, pdata->username, conn);
1877 packet_add_string_parm(packet, P_PASSWORD, pdata->password, conn);
1878
1879 ret = cimd2_request(packet, conn, NULL);
1880
1881 if (ret >= 0) {
1882 packet_destroy(packet);
1883 info(0, "CIMD2[%s] logged in.",
1884 octstr_get_cstr(conn->id));
1885 return 0;
1886 }
1887 }
1888 error(0, "CIMD2[%s] login failed.",
1889 octstr_get_cstr(conn->id));
1890 cimd2_close_socket(pdata);
1891 packet_destroy(packet);
1892 return -1;
1893 }
1894
cimd2_logout(SMSCConn * conn)1895 static void cimd2_logout(SMSCConn *conn)
1896 {
1897 struct packet *packet = NULL;
1898 int ret;
1899
1900 packet = packet_create(LOGOUT, BOGUS_SEQUENCE);
1901
1902 /* TODO: Don't wait very long for a response in this case. */
1903 ret = cimd2_request(packet, conn, NULL);
1904
1905 if (ret == 0) {
1906 info(0, "CIMD2[%s] logged out.",
1907 octstr_get_cstr(conn->id));
1908 }
1909 packet_destroy(packet);
1910 }
1911
cimd2_send_alive(SMSCConn * conn)1912 static int cimd2_send_alive(SMSCConn *conn)
1913 {
1914 struct packet *packet = NULL;
1915 int ret;
1916
1917 packet = packet_create(ALIVE, BOGUS_SEQUENCE);
1918 ret = cimd2_request(packet, conn, NULL);
1919 packet_destroy(packet);
1920
1921 if (ret < 0)
1922 warning(0, "CIMD2[%s]: SMSC not alive.",
1923 octstr_get_cstr(conn->id));
1924
1925 return ret;
1926 }
1927
1928
cimd2_destroy(PrivData * pdata)1929 static void cimd2_destroy(PrivData *pdata)
1930 {
1931 int discarded;
1932
1933 if (pdata == NULL)
1934 return;
1935
1936 octstr_destroy(pdata->host);
1937 octstr_destroy(pdata->username);
1938 octstr_destroy(pdata->password);
1939 octstr_destroy(pdata->inbuffer);
1940 octstr_destroy(pdata->my_number);
1941
1942 discarded = gwlist_len(pdata->received);
1943 if (discarded > 0)
1944 warning(0, "CIMD2[%s]: discarded %d received messages",
1945 octstr_get_cstr(pdata->conn->id),
1946 discarded);
1947
1948 gwlist_destroy(pdata->received, msg_destroy_item);
1949 gwlist_destroy(pdata->outgoing_queue, NULL);
1950 gwlist_destroy(pdata->stopped, NULL);
1951
1952 gw_free(pdata);
1953 }
1954
1955
cimd2_submit_msg(SMSCConn * conn,Msg * msg)1956 static int cimd2_submit_msg(SMSCConn *conn, Msg *msg)
1957 {
1958 PrivData *pdata = conn->data;
1959 struct packet *packet;
1960 Octstr *ts = NULL;
1961 int ret;
1962
1963 gw_assert(pdata != NULL);
1964 debug("bb.sms.cimd2", 0, "CIMD2[%s]: sending message",
1965 octstr_get_cstr(conn->id));
1966
1967 packet = packet_encode_message(msg, pdata->my_number,conn);
1968 if (!packet) {
1969 /* This is a protocol error. Does this help? I doubt..
1970 * But nevermind that.
1971 */
1972 bb_smscconn_send_failed(conn, msg,
1973 SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED"));
1974 return -1;
1975 }
1976
1977 ret = cimd2_request(packet, conn, &ts);
1978 if ((ret == 0) && (ts) && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask) && !pdata->no_dlr) {
1979 dlr_add(conn->name, ts, msg, 1);
1980 }
1981 octstr_destroy(ts);
1982 packet_destroy(packet);
1983
1984 if (ret == -1) {
1985 bb_smscconn_send_failed(conn, msg,
1986 SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED"));
1987 }
1988 else if (ret == -2) {
1989 cimd2_close_socket(pdata);
1990 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL);
1991 mutex_lock(conn->flow_mutex);
1992 conn->status = SMSCCONN_DISCONNECTED;
1993 mutex_unlock(conn->flow_mutex);
1994 }
1995 else {
1996 bb_smscconn_sent(conn,msg, NULL);
1997 }
1998
1999 return ret;
2000 }
2001
cimd2_receive_msg(SMSCConn * conn,Msg ** msg)2002 static int cimd2_receive_msg(SMSCConn *conn, Msg **msg)
2003 {
2004 PrivData *pdata = conn->data;
2005 long ret;
2006 struct packet *packet;
2007
2008 gw_assert(pdata != NULL);
2009
2010 if (gwlist_len(pdata->received) > 0) {
2011 *msg = gwlist_consume(pdata->received);
2012 return 1;
2013 }
2014
2015 if (pdata->socket < 0) {
2016 /* XXX We have to assume that smsc_send_message is
2017 * currently trying to reopen, so we have to make
2018 * this thread wait. It should be done in a nicer
2019 * way. */
2020 return 0;
2021 }
2022
2023 ret = read_available(pdata->socket, 0);
2024 if (ret == 0) {
2025 if (pdata->keepalive > 0 && pdata->next_ping < time(NULL)) {
2026 if (cimd2_send_alive(conn) < 0)
2027 return -1;
2028 }
2029 return 0;
2030 }
2031
2032 if (ret < 0) {
2033 warning(errno, "CIMD2[%s]: cimd2_receive_msg: read_available failed",
2034 octstr_get_cstr(conn->id));
2035 return -1;
2036 }
2037
2038 /* We have some data waiting... see if it is an sms delivery. */
2039 ret = octstr_append_from_socket(pdata->inbuffer, pdata->socket);
2040
2041 if (ret == 0) {
2042 warning(0, "CIMD2[%s]: cimd2_receive_msg: service center closed connection.",
2043 octstr_get_cstr(conn->id));
2044 return -1;
2045 }
2046 if (ret < 0) {
2047 warning(0, "CIMD2[%s]: cimd2_receive_msg: read failed",
2048 octstr_get_cstr(conn->id));
2049 return -1;
2050 }
2051
2052
2053 for (;;) {
2054 packet = packet_extract(pdata->inbuffer,conn);
2055 if (!packet)
2056 break;
2057
2058 packet_check(packet,conn);
2059 packet_check_can_receive(packet,conn);
2060 debug("bb.sms.cimd2", 0, "CIMD2[%s]: received: <%s>",
2061 octstr_get_cstr(pdata->conn->id),
2062 octstr_get_cstr(packet->data));
2063
2064 if (packet->operation < RESPONSE)
2065 cimd2_handle_request(packet, conn);
2066 else {
2067 error(0, "CIMD2[%s]: cimd2_receive_msg: unexpected response packet",
2068 octstr_get_cstr(conn->id));
2069 octstr_dump(packet->data, 0);
2070 }
2071
2072 packet_destroy(packet);
2073 }
2074
2075 if (gwlist_len(pdata->received) > 0) {
2076 *msg = gwlist_consume(pdata->received);
2077 return 1;
2078 }
2079 return 0;
2080 }
2081
2082
2083
cimd2_accept_delivery_report_message(struct packet * request,SMSCConn * conn)2084 static Msg *cimd2_accept_delivery_report_message(struct packet *request,
2085 SMSCConn *conn)
2086 {
2087 Msg *msg = NULL;
2088 Octstr *destination = NULL;
2089 Octstr *timestamp = NULL;
2090 Octstr *statuscode = NULL;
2091 int st_code;
2092 int code;
2093
2094 destination = packet_get_parm(request, P_DESTINATION_ADDRESS);
2095 timestamp = packet_get_parm(request, P_MC_TIMESTAMP);
2096 statuscode = packet_get_parm(request, P_STATUS_CODE);
2097
2098 st_code = atoi(octstr_get_cstr(statuscode));
2099
2100 switch(st_code)
2101 {
2102 case 2: /* validity period expired */
2103 case 3: /* delivery failed */
2104 case 6: /* last no response */
2105 case 7: /* message cancelled */
2106 case 8: /* message deleted */
2107 case 9: /* message deleted by cancel */
2108 code = DLR_FAIL;
2109 break;
2110 case 4: /* delivery successful */
2111 code = DLR_SUCCESS;
2112 break;
2113 default:
2114 code = 0;
2115 }
2116 if(code)
2117 msg = dlr_find(conn->name, timestamp, destination, code, 1);
2118 else
2119 msg = NULL;
2120
2121 /* recode the body into msgdata */
2122 if (msg) {
2123 msg->sms.msgdata = packet_get_parm(request, P_USER_DATA);
2124 if (!msg->sms.msgdata) {
2125 msg->sms.msgdata = statuscode;
2126 statuscode = NULL;
2127 }
2128 }
2129
2130 octstr_destroy(statuscode);
2131 octstr_destroy(destination);
2132 octstr_destroy(timestamp);
2133
2134 return msg;
2135 }
2136
sms_receive(SMSCConn * conn)2137 static Msg *sms_receive(SMSCConn *conn)
2138 {
2139 PrivData *pdata = conn->data;
2140 int ret;
2141 Msg *newmsg = NULL;
2142
2143 ret = cimd2_receive_msg(conn, &newmsg);
2144 if (ret == 1) {
2145 /* if any smsc_id available, use it */
2146 newmsg->sms.smsc_id = octstr_duplicate(conn->id);
2147 return newmsg;
2148 }
2149 else if (ret == 0) { /* no message, just retry... */
2150 return NULL;
2151 }
2152 /* error. reconnect. */
2153 msg_destroy(newmsg);
2154 mutex_lock(conn->flow_mutex);
2155 cimd2_close_socket(pdata);
2156 conn->status = SMSCCONN_DISCONNECTED;
2157 mutex_unlock(conn->flow_mutex);
2158 return NULL;
2159 }
2160
2161
io_thread(void * arg)2162 static void io_thread (void *arg)
2163 {
2164 Msg *msg;
2165 SMSCConn *conn = arg;
2166 PrivData *pdata = conn->data;
2167 double sleep = 0.0001;
2168
2169 /* Make sure we log into our own log-file if defined */
2170 log_thread_to(conn->log_idx);
2171
2172 /* remove messages from SMSC until we are killed */
2173 while (!pdata->quitting) {
2174
2175 gwlist_consume(pdata->stopped); /* block here if suspended/isolated */
2176
2177 /* check that connection is active */
2178 if (conn->status != SMSCCONN_ACTIVE) {
2179 if (cimd2_login(conn) != 0) {
2180 error(0, "CIMD2[%s]: Couldn't connect to SMSC (retrying in %ld seconds).",
2181 octstr_get_cstr(conn->id),
2182 conn->reconnect_delay);
2183 gwthread_sleep(conn->reconnect_delay);
2184 mutex_lock(conn->flow_mutex);
2185 conn->status = SMSCCONN_RECONNECTING;
2186 mutex_unlock(conn->flow_mutex);
2187 continue;
2188 }
2189 mutex_lock(conn->flow_mutex);
2190 conn->status = SMSCCONN_ACTIVE;
2191 conn->connect_time = time(NULL);
2192 bb_smscconn_connected(conn);
2193 mutex_unlock(conn->flow_mutex);
2194 }
2195
2196 /* receive messages */
2197 do {
2198 msg = sms_receive(conn);
2199 if (msg) {
2200 sleep = 0;
2201 debug("bb.sms.cimd2", 0, "CIMD2[%s]: new message received",
2202 octstr_get_cstr(conn->id));
2203 bb_smscconn_receive(conn, msg);
2204 }
2205 } while (msg);
2206
2207 /* send messages */
2208 do {
2209 msg = gwlist_extract_first(pdata->outgoing_queue);
2210 if (msg) {
2211 sleep = 0;
2212 if (cimd2_submit_msg(conn,msg) != 0) break;
2213 }
2214 } while (msg);
2215
2216 if (sleep > 0) {
2217
2218 /* note that this implementations means that we sleep even
2219 * when we fail connection.. but time is very short, anyway
2220 */
2221 gwthread_sleep(sleep);
2222 /* gradually sleep longer and longer times until something starts to
2223 * happen - this of course reduces response time, but that's better than
2224 * extensive CPU usage when it is not used
2225 */
2226 sleep *= 2;
2227 if (sleep >= 2.0)
2228 sleep = 1.999999;
2229 }
2230 else {
2231 sleep = 0.0001;
2232 }
2233 }
2234 }
2235
2236
cimd2_add_msg_cb(SMSCConn * conn,Msg * sms)2237 static int cimd2_add_msg_cb (SMSCConn *conn, Msg *sms)
2238 {
2239 PrivData *pdata = conn->data;
2240 Msg *copy;
2241
2242 copy = msg_duplicate(sms);
2243 gwlist_produce(pdata->outgoing_queue, copy);
2244 gwthread_wakeup(pdata->io_thread);
2245
2246 return 0;
2247 }
2248
2249
cimd2_shutdown_cb(SMSCConn * conn,int finish_sending)2250 static int cimd2_shutdown_cb (SMSCConn *conn, int finish_sending)
2251 {
2252 PrivData *pdata = conn->data;
2253
2254 debug("bb.sms", 0, "Shutting down SMSCConn CIMD2 %s (%s)",
2255 octstr_get_cstr(conn->id),
2256 finish_sending ? "slow" : "instant");
2257
2258 /* Documentation claims this would have been done by smscconn.c,
2259 but isn't when this code is being written. */
2260 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
2261 pdata->quitting = 1; /* Separate from why_killed to avoid locking, as
2262 * why_killed may be changed from outside? */
2263
2264 if (finish_sending == 0) {
2265 Msg *msg;
2266 while ((msg = gwlist_extract_first(pdata->outgoing_queue)) != NULL) {
2267 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
2268 }
2269 }
2270
2271 cimd2_logout(conn);
2272 if (conn->is_stopped) {
2273 gwlist_remove_producer(pdata->stopped);
2274 conn->is_stopped = 0;
2275 }
2276
2277 if (pdata->io_thread != -1) {
2278 gwthread_wakeup(pdata->io_thread);
2279 gwthread_join(pdata->io_thread);
2280 }
2281
2282 cimd2_close_socket(pdata);
2283 cimd2_destroy(pdata);
2284
2285 debug("bb.sms", 0, "SMSCConn CIMD2 %s shut down.",
2286 octstr_get_cstr(conn->id));
2287 conn->status = SMSCCONN_DEAD;
2288 bb_smscconn_killed();
2289 return 0;
2290 }
2291
cimd2_start_cb(SMSCConn * conn)2292 static void cimd2_start_cb (SMSCConn *conn)
2293 {
2294 PrivData *pdata = conn->data;
2295
2296 gwlist_remove_producer(pdata->stopped);
2297 /* in case there are messages in the buffer already */
2298 gwthread_wakeup(pdata->io_thread);
2299 debug("bb.sms", 0, "SMSCConn CIMD2 %s, start called",
2300 octstr_get_cstr(conn->id));
2301 }
2302
cimd2_stop_cb(SMSCConn * conn)2303 static void cimd2_stop_cb (SMSCConn *conn)
2304 {
2305 PrivData *pdata = conn->data;
2306 gwlist_add_producer(pdata->stopped);
2307 debug("bb.sms", 0, "SMSCConn CIMD2 %s, stop called",
2308 octstr_get_cstr(conn->id));
2309 }
2310
cimd2_queued_cb(SMSCConn * conn)2311 static long cimd2_queued_cb (SMSCConn *conn)
2312 {
2313 PrivData *pdata = conn->data;
2314 conn->load = (pdata ? (conn->status != SMSCCONN_DEAD ?
2315 gwlist_len(pdata->outgoing_queue) : 0) : 0);
2316 return conn->load;
2317 }
2318
smsc_cimd2_create(SMSCConn * conn,CfgGroup * grp)2319 int smsc_cimd2_create(SMSCConn *conn, CfgGroup *grp)
2320 {
2321 PrivData *pdata;
2322 int ok;
2323 int maxlen;
2324
2325 pdata = gw_malloc(sizeof(PrivData));
2326 conn->data = pdata;
2327 pdata->conn = conn;
2328
2329 pdata->no_dlr = 0;
2330 pdata->quitting = 0;
2331 pdata->socket = -1;
2332 pdata->received = gwlist_create();
2333 pdata->inbuffer = octstr_create("");
2334 pdata->send_seq = 1;
2335 pdata->receive_seq = 0;
2336 pdata->outgoing_queue = gwlist_create();
2337 pdata->stopped = gwlist_create();
2338 gwlist_add_producer(pdata->outgoing_queue);
2339
2340 if (conn->is_stopped)
2341 gwlist_add_producer(pdata->stopped);
2342
2343 pdata->host = cfg_get(grp, octstr_imm("host"));
2344 if (cfg_get_integer(&(pdata->port), grp, octstr_imm("port")) == -1)
2345 pdata->port = 0;
2346 if (cfg_get_integer(&(pdata->our_port), grp, octstr_imm("our-port")) == -1)
2347 pdata->our_port = 0;
2348 pdata->username = cfg_get(grp, octstr_imm("smsc-username"));
2349 pdata->password = cfg_get(grp, octstr_imm("smsc-password"));
2350 pdata->my_number = cfg_get(grp, octstr_imm("my-number"));
2351 if (cfg_get_integer(&(pdata->keepalive), grp,octstr_imm("keepalive")) == -1)
2352 pdata->keepalive = 0;
2353
2354 cfg_get_bool(&pdata->no_dlr, grp, octstr_imm("no-dlr"));
2355
2356 /* Check that config is OK */
2357 ok = 1;
2358 if (pdata->host == NULL) {
2359 error(0,"CIMD2[%s]: Configuration file doesn't specify host",
2360 octstr_get_cstr(conn->id));
2361 ok = 0;
2362 }
2363 if (pdata->port == 0) {
2364 error(0,"CIMD2[%s]: Configuration file doesn't specify port",
2365 octstr_get_cstr(conn->id));
2366 ok = 0;
2367 }
2368 if (pdata->username == NULL) {
2369 error(0, "CIMD2[%s]: Configuration file doesn't specify username.",
2370 octstr_get_cstr(conn->id));
2371 ok = 0;
2372 }
2373 if (pdata->password == NULL) {
2374 error(0, "CIMD2[%s]: Configuration file doesn't specify password.",
2375 octstr_get_cstr(conn->id));
2376 ok = 0;
2377 }
2378
2379 if (!ok) {
2380 cimd2_destroy(pdata);
2381 return -1;
2382 }
2383
2384 conn->name = octstr_format("CIMD2:%s:%d:%s",
2385 octstr_get_cstr(pdata->host),
2386 pdata->port,
2387 octstr_get_cstr(pdata->username));
2388
2389
2390 if (pdata->keepalive > 0) {
2391 debug("bb.sms.cimd2", 0, "CIMD2[%s]: Keepalive set to %ld seconds",
2392 octstr_get_cstr(conn->id),
2393 pdata->keepalive);
2394 pdata->next_ping = time(NULL) + pdata->keepalive;
2395 }
2396
2397 maxlen = parm_maxlen(P_USER_IDENTITY);
2398 if (octstr_len(pdata->username) > maxlen) {
2399 octstr_truncate(pdata->username, maxlen);
2400 warning(0, "CIMD2[%s]: Truncating username to %d chars",
2401 octstr_get_cstr(conn->id),
2402 maxlen);
2403 }
2404
2405 maxlen = parm_maxlen(P_PASSWORD);
2406 if (octstr_len(pdata->password) > maxlen) {
2407 octstr_truncate(pdata->password, maxlen);
2408 warning(0, "CIMD2[%s]: Truncating password to %d chars",
2409 octstr_get_cstr(conn->id),
2410 maxlen);
2411 }
2412
2413 pdata->io_thread = gwthread_create(io_thread, conn);
2414
2415 if (pdata->io_thread == -1) {
2416
2417 error(0,"CIMD2[%s]: Couldn't start I/O thread.",
2418 octstr_get_cstr(conn->id));
2419 pdata->quitting = 1;
2420 gwthread_wakeup(pdata->io_thread);
2421 gwthread_join(pdata->io_thread);
2422 cimd2_destroy(pdata);
2423 return -1;
2424 }
2425
2426 conn->send_msg = cimd2_add_msg_cb;
2427 conn->shutdown = cimd2_shutdown_cb;
2428 conn->queued = cimd2_queued_cb;
2429 conn->start_conn = cimd2_start_cb;
2430 conn->stop_conn = cimd2_stop_cb;
2431
2432 return 0;
2433 }
2434
2435