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 /*
58 * smsc.c - implement interface to SMS centers as defined by smsc.h
59 *
60 * Lars Wirzenius and Kalle Marjola for WapIT Ltd.
61 */
62
63 /* NOTE: private functions (only for smsc_* use) are named smscenter_*,
64 * public functions (used by gateway) are named smsc_*
65 */
66
67 #include <errno.h>
68 #include <signal.h>
69 #include <stdarg.h>
70 #include <stdlib.h>
71 #include <string.h>
72 #include <time.h>
73 #include <unistd.h>
74 #include <sys/time.h>
75
76 #include "gwlib/gwlib.h"
77 #include "smsc.h"
78 #include "smsc_p.h"
79 #include "msg.h"
80
81 /*
82 * Maximum number of characters for read_into_buffer to read at a time.
83 */
84 #define MAX_READ_INTO_BUFFER (1024)
85
86
87 static void smscenter_lock(SMSCenter *smsc);
88 static void smscenter_unlock(SMSCenter *smsc);
89
90 /*--------------------------------------------------------------------
91 * TODO: WAP WDP functions!
92 */
93
94
95 /*--------------------------------------------------------------------
96 * smscenter functions
97 */
98
99
100
smscenter_construct(void)101 SMSCenter *smscenter_construct(void)
102 {
103 SMSCenter *smsc;
104 static int next_id = 1;
105
106 smsc = gw_malloc(sizeof(SMSCenter));
107
108 smsc->killed = 0;
109 smsc->type = SMSC_TYPE_DELETED;
110 smsc->preferred_prefix = NULL;
111 smsc->allowed_prefix = NULL;
112 smsc->denied_prefix = NULL;
113 smsc->alt_charset = 0;
114 smsc->keepalive = 0;
115
116 smsc->mutex = mutex_create();
117
118 sprintf(smsc->name, "Unknown SMSC");
119 smsc->id = next_id++;
120
121 /* FAKE */
122 smsc->hostname = NULL;
123 smsc->port = -1;
124 smsc->socket = -1;
125
126 /* CIMD */
127 smsc->cimd_hostname = NULL;
128 smsc->cimd_port = -1;
129 smsc->cimd_username = NULL;
130 smsc->cimd_password = NULL;
131
132 /* EMI_X25 */
133 smsc->emi_phonenum = NULL;
134 smsc->emi_serialdevice = NULL;
135 smsc->emi_username = NULL;
136 smsc->emi_password = NULL;
137
138 /* SEMA SMS2000 */
139 smsc->sema_smscnua = NULL;
140 smsc->sema_homenua = NULL;
141 smsc->sema_serialdevice = NULL;
142 smsc->sema_fd = -1;
143
144 /* SEMA SMS2000 OIS X.25 */
145 smsc->ois_alive = 0;
146 smsc->ois_alive2 = 0;
147 smsc->ois_received_mo = NULL;
148 smsc->ois_ack_debt = 0;
149 smsc->ois_flags = 0;
150 smsc->ois_listening_socket = -1;
151 smsc->ois_socket = -1;
152 smsc->ois_buflen = 0;
153 smsc->ois_bufsize = 0;
154 smsc->ois_buffer = 0;
155
156 /* add new SMSCes here */
157
158 /* Memory */
159 smsc->buflen = 0;
160 smsc->bufsize = 10*1024;
161 smsc->buffer = gw_malloc(smsc->bufsize);
162 memset(smsc->buffer, 0, smsc->bufsize);
163
164 return smsc;
165 }
166
167
smscenter_destruct(SMSCenter * smsc)168 void smscenter_destruct(SMSCenter *smsc)
169 {
170 if (smsc == NULL)
171 return;
172
173 /* FAKE */
174 gw_free(smsc->hostname);
175
176 /* CIMD */
177 gw_free(smsc->cimd_hostname);
178 gw_free(smsc->cimd_username);
179 gw_free(smsc->cimd_password);
180
181 /* EMI_X25 */
182 gw_free(smsc->emi_phonenum);
183 gw_free(smsc->emi_serialdevice);
184 gw_free(smsc->emi_username);
185 gw_free(smsc->emi_password);
186
187 /* SEMA */
188 gw_free(smsc->sema_smscnua);
189 gw_free(smsc->sema_homenua);
190 gw_free(smsc->sema_serialdevice);
191
192 /* OIS */
193 ois_delete_queue(smsc);
194 gw_free(smsc->ois_buffer);
195
196 /* add new SMSCes here */
197
198 /* Other fields */
199 mutex_destroy(smsc->mutex);
200
201 /* Memory */
202 gw_free(smsc->buffer);
203 gw_free(smsc);
204 }
205
206
207
208
smscenter_submit_msg(SMSCenter * smsc,Msg * msg)209 int smscenter_submit_msg(SMSCenter *smsc, Msg *msg)
210 {
211 smscenter_lock(smsc);
212
213 switch (smsc->type) {
214
215 case SMSC_TYPE_CIMD:
216 if (cimd_submit_msg(smsc, msg) == -1)
217 goto error;
218 break;
219
220 case SMSC_TYPE_EMI_X25:
221 if (emi_submit_msg(smsc, msg) == -1)
222 goto error;
223 break;
224
225 case SMSC_TYPE_SEMA_X28:
226 if (sema_submit_msg(smsc, msg) == -1)
227 goto error;
228 break;
229
230 case SMSC_TYPE_OIS:
231 if (ois_submit_msg(smsc, msg) == -1)
232 goto error;
233 break;
234
235 /* add new SMSCes here */
236
237 default:
238 goto error;
239 }
240
241 smscenter_unlock(smsc);
242 return 0;
243
244 error:
245 smscenter_unlock(smsc);
246 return -1;
247 }
248
249
250
smscenter_receive_msg(SMSCenter * smsc,Msg ** msg)251 int smscenter_receive_msg(SMSCenter *smsc, Msg **msg)
252 {
253 int ret;
254
255 smscenter_lock(smsc);
256
257 switch (smsc->type) {
258
259 case SMSC_TYPE_CIMD:
260 ret = cimd_receive_msg(smsc, msg);
261 if (ret == -1)
262 goto error;
263 break;
264
265 case SMSC_TYPE_EMI_X25:
266 ret = emi_receive_msg(smsc, msg);
267 if (ret == -1)
268 goto error;
269 break;
270
271 case SMSC_TYPE_OIS:
272 ret = ois_receive_msg(smsc, msg);
273 if (ret == -1)
274 goto error;
275 break;
276
277
278 case SMSC_TYPE_SEMA_X28:
279 ret = sema_receive_msg(smsc, msg);
280 if (ret == -1)
281 goto error;
282 break;
283
284 default:
285 goto error;
286
287 }
288 smscenter_unlock(smsc);
289
290 /* If the SMSC didn't set the timestamp, set it here. */
291 if (ret == 1 && msg_type(*msg) == sms && (*msg)->sms.time == 0)
292 time(&(*msg)->sms.time);
293
294 return ret;
295
296 error:
297 smscenter_unlock(smsc);
298 return -1;
299 }
300
301
smscenter_pending_smsmessage(SMSCenter * smsc)302 int smscenter_pending_smsmessage(SMSCenter *smsc)
303 {
304 int ret;
305
306 smscenter_lock(smsc);
307
308 switch (smsc->type) {
309
310 case SMSC_TYPE_CIMD:
311 ret = cimd_pending_smsmessage(smsc);
312 if (ret == -1)
313 goto error;
314 break;
315
316 case SMSC_TYPE_EMI_X25:
317 ret = emi_pending_smsmessage(smsc);
318 if (ret == -1)
319 goto error;
320 break;
321
322 case SMSC_TYPE_SEMA_X28:
323 ret = sema_pending_smsmessage(smsc);
324 if (ret == -1)
325 goto error;
326 break;
327
328 case SMSC_TYPE_OIS:
329 ret = ois_pending_smsmessage(smsc);
330 if (ret == -1)
331 goto error;
332 break;
333
334 default:
335 goto error;
336 }
337
338 smscenter_unlock(smsc);
339 return ret;
340
341 error:
342 error(0, "smscenter_pending_smsmessage is failing");
343 smscenter_unlock(smsc);
344 return -1;
345 }
346
347
smscenter_read_into_buffer(SMSCenter * smsc)348 int smscenter_read_into_buffer(SMSCenter *smsc)
349 {
350 char *p;
351 int ret;
352 fd_set read_fd;
353 struct timeval tv, tvinit;
354 size_t bytes_read;
355
356 tvinit.tv_sec = 0;
357 tvinit.tv_usec = 1000;
358
359 bytes_read = 0;
360 for (;;) {
361 FD_ZERO(&read_fd);
362 FD_SET(smsc->socket, &read_fd);
363 tv = tvinit;
364 ret = select(smsc->socket + 1, &read_fd, NULL, NULL, &tv);
365 if (ret == -1) {
366 if (errno == EINTR) goto got_data;
367 if (errno == EAGAIN) goto got_data;
368 error(errno, "Error doing select for socket");
369 goto error;
370 } else if (ret == 0)
371 goto got_data;
372
373 if (smsc->buflen == smsc->bufsize) {
374 p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
375 smsc->buffer = p;
376 smsc->bufsize *= 2;
377 }
378
379 ret = read(smsc->socket,
380 smsc->buffer + smsc->buflen,
381 1);
382 if (ret == -1) {
383 error(errno, "Reading from `%s' port `%d' failed.",
384 smsc->hostname, smsc->port);
385 goto error;
386 }
387 if (ret == 0)
388 goto eof;
389 smsc->buflen += ret;
390 bytes_read += ret;
391 if (bytes_read >= MAX_READ_INTO_BUFFER)
392 break;
393 }
394
395 eof:
396 ret = 0;
397 goto unblock;
398
399 got_data:
400 ret = 1;
401 goto unblock;
402
403 error:
404 ret = -1;
405 goto unblock;
406
407 unblock:
408 return ret;
409 }
410
411
smscenter_remove_from_buffer(SMSCenter * smsc,size_t n)412 void smscenter_remove_from_buffer(SMSCenter *smsc, size_t n)
413 {
414 memmove(smsc->buffer, smsc->buffer + n, smsc->buflen - n);
415 smsc->buflen -= n;
416 }
417
418
419 /*
420 * Lock an SMSCenter. Return -1 for error, 0 for OK.
421 */
smscenter_lock(SMSCenter * smsc)422 static void smscenter_lock(SMSCenter *smsc)
423 {
424 if (smsc->type == SMSC_TYPE_DELETED)
425 error(0, "smscenter_lock called on DELETED SMSC.");
426 mutex_lock(smsc->mutex);
427 }
428
429
430 /*
431 * Unlock an SMSCenter. Return -1 for error, 0 for OK.
432 */
smscenter_unlock(SMSCenter * smsc)433 static void smscenter_unlock(SMSCenter *smsc)
434 {
435 mutex_unlock(smsc->mutex);
436 }
437
438
439 /*------------------------------------------------------------------------
440 * Public SMSC functions
441 */
442
443
smsc_open(CfgGroup * grp)444 SMSCenter *smsc_open(CfgGroup *grp)
445 {
446 SMSCenter *smsc;
447 Octstr *type, *host, *username, *password, *phone, *device;
448 Octstr *preferred_prefix, *allowed_prefix, *denied_prefix;
449 Octstr *alt_chars, *allow_ip;
450 Octstr *sema_smscnua, *sema_homenua, *sema_report;
451 Octstr *sender_prefix;
452
453 long iwaitreport;
454 long port, receive_port, our_port;
455 long keepalive;
456 long ois_debug;
457 long alt_dcs;
458 int typeno;
459
460
461 type = cfg_get(grp, octstr_imm("smsc"));
462 if (type == NULL) {
463 error(0, "Required field 'smsc' missing for smsc group.");
464 return NULL;
465 }
466 if (octstr_compare(type, octstr_imm("cimd")) == 0)
467 typeno = SMSC_TYPE_CIMD;
468 else if (octstr_compare(type, octstr_imm("emi_x25")) == 0)
469 typeno = SMSC_TYPE_EMI_X25;
470 else if (octstr_compare(type, octstr_imm("sema")) == 0)
471 typeno = SMSC_TYPE_SEMA_X28;
472 else if (octstr_compare(type, octstr_imm("ois")) == 0)
473 typeno = SMSC_TYPE_OIS;
474 else {
475 error(0, "Unknown SMSC type '%s'", octstr_get_cstr(type));
476 octstr_destroy(type);
477 return NULL;
478 }
479
480 host = cfg_get(grp, octstr_imm("host"));
481 if (cfg_get_integer(&port, grp, octstr_imm("port")) == -1)
482 port = 0;
483 if (cfg_get_integer(&receive_port, grp, octstr_imm("receive-port")) == -1)
484 receive_port = 0;
485 if (cfg_get_integer(&our_port, grp, octstr_imm("our-port")) == -1)
486 our_port = 0;
487 username = cfg_get(grp, octstr_imm("smsc-username"));
488 password = cfg_get(grp, octstr_imm("smsc-password"));
489 phone = cfg_get(grp, octstr_imm("phone"));
490 device = cfg_get(grp, octstr_imm("device"));
491 preferred_prefix = cfg_get(grp, octstr_imm("preferred-prefix"));
492 allowed_prefix = cfg_get(grp, octstr_imm("allowed-prefix"));
493 denied_prefix = cfg_get(grp, octstr_imm("denied-prefix"));
494 alt_chars = cfg_get(grp, octstr_imm("alt-charset"));
495
496 allow_ip = cfg_get(grp, octstr_imm("connect-allow-ip"));
497
498 sema_smscnua = cfg_get(grp, octstr_imm("smsc_nua"));
499 sema_homenua = cfg_get(grp, octstr_imm("home_nua"));
500 sema_report = cfg_get(grp, octstr_imm("wait_report"));
501 if (sema_report == NULL)
502 iwaitreport = 1;
503 else
504 octstr_parse_long(&iwaitreport, sema_report, 0, 0);
505
506 if (cfg_get_integer(&keepalive, grp, octstr_imm("keepalive")) == -1)
507 keepalive = 0;
508
509 if (cfg_get_integer(&alt_dcs, grp, octstr_imm("alt-dcs")) == -1)
510 alt_dcs = 0;
511 if (alt_dcs > 1)
512 alt_dcs = 1;
513
514 if (cfg_get_integer(&ois_debug, grp, octstr_imm("ois-debug-level")) == -1)
515 ois_debug = 0;
516
517 sender_prefix = cfg_get(grp, octstr_imm("sender-prefix"));
518 if (sender_prefix == NULL)
519 sender_prefix = octstr_create("never");
520
521 smsc = NULL;
522
523 switch (typeno) {
524 case SMSC_TYPE_CIMD:
525 if (host == NULL || port == 0 || username == NULL || password == NULL)
526 error(0, "Required field missing for CIMD center.");
527 else
528 smsc = cimd_open(octstr_get_cstr(host),
529 port,
530 octstr_get_cstr(username),
531 octstr_get_cstr(password));
532 break;
533
534 case SMSC_TYPE_EMI_X25:
535 if (phone == NULL || device == NULL || username == NULL ||
536 password == NULL)
537 error(0, "Required field missing for EMI_X25 center.");
538 else
539 smsc = emi_open(octstr_get_cstr(phone),
540 octstr_get_cstr(device),
541 octstr_get_cstr(username),
542 octstr_get_cstr(password));
543 break;
544
545 case SMSC_TYPE_SEMA_X28:
546 if (device == NULL || sema_smscnua == NULL || sema_homenua == NULL)
547 error(0, "Required field missing for SEMA center.");
548 else
549 smsc = sema_open(octstr_get_cstr(sema_smscnua),
550 octstr_get_cstr(sema_homenua),
551 octstr_get_cstr(device),
552 iwaitreport);
553 break;
554
555 case SMSC_TYPE_OIS:
556 if (host == NULL || port == 0 || receive_port == 0)
557 error(0, "Required field missing for OIS center.");
558 else
559 smsc = ois_open(receive_port,
560 octstr_get_cstr(host),
561 port,
562 ois_debug);
563 break;
564
565 /* add new SMSCes here */
566
567 default: /* Unknown SMSC type */
568 break;
569 }
570
571 if (smsc != NULL) {
572 if (cfg_get_integer(&smsc->alt_charset, grp,
573 octstr_imm("alt-charset")) == -1)
574 smsc->alt_charset = 0;
575 if (preferred_prefix == NULL)
576 smsc->preferred_prefix = NULL;
577 else
578 smsc->preferred_prefix =
579 gw_strdup(octstr_get_cstr(preferred_prefix));
580 if (allowed_prefix == NULL)
581 smsc->allowed_prefix = NULL;
582 else
583 smsc->allowed_prefix = gw_strdup(octstr_get_cstr(allowed_prefix));
584 if (denied_prefix == NULL)
585 smsc->denied_prefix = NULL;
586 else
587 smsc->denied_prefix = gw_strdup(octstr_get_cstr(denied_prefix));
588 }
589
590 octstr_destroy(type);
591 octstr_destroy(host);
592 octstr_destroy(username);
593 octstr_destroy(password);
594 octstr_destroy(phone);
595 octstr_destroy(device);
596 octstr_destroy(preferred_prefix);
597 octstr_destroy(denied_prefix);
598 octstr_destroy(allowed_prefix);
599 octstr_destroy(alt_chars);
600 octstr_destroy(allow_ip);
601 octstr_destroy(sema_smscnua);
602 octstr_destroy(sema_homenua);
603 octstr_destroy(sema_report);
604 octstr_destroy(sender_prefix);
605 return smsc;
606 }
607
608
609
smsc_reopen(SMSCenter * smsc)610 int smsc_reopen(SMSCenter *smsc)
611 {
612 int ret;
613
614 if (smsc->killed)
615 return -2;
616
617 smscenter_lock(smsc);
618
619 switch (smsc->type) {
620 case SMSC_TYPE_CIMD:
621 ret = cimd_reopen(smsc);
622 break;
623 case SMSC_TYPE_EMI_X25:
624 ret = emi_reopen(smsc);
625 break;
626 case SMSC_TYPE_SEMA_X28:
627 ret = sema_reopen(smsc);
628 break;
629 case SMSC_TYPE_OIS:
630 ret = ois_reopen(smsc);
631 break;
632 /* add new SMSCes here */
633 default: /* Unknown SMSC type */
634 ret = -2; /* no use */
635 }
636
637 smscenter_unlock(smsc);
638 return ret;
639 }
640
641
642
smsc_name(SMSCenter * smsc)643 char *smsc_name(SMSCenter *smsc)
644 {
645 return smsc->name;
646 }
647
smsc_close(SMSCenter * smsc)648 int smsc_close(SMSCenter *smsc)
649 {
650 int errors = 0;
651
652 if (smsc == NULL)
653 return 0;
654
655 smscenter_lock(smsc);
656
657 switch (smsc->type) {
658 case SMSC_TYPE_CIMD:
659 if (cimd_close(smsc) == -1)
660 errors = 1;
661 break;
662
663 case SMSC_TYPE_EMI_X25:
664 if (emi_close(smsc) == -1)
665 errors = 1;
666 break;
667
668 case SMSC_TYPE_SEMA_X28:
669 if (sema_close(smsc) == -1)
670 errors = 1;
671 break;
672
673 case SMSC_TYPE_OIS:
674 if (ois_close(smsc) == -1)
675 errors = 1;
676 break;
677
678 /* add new SMSCes here */
679
680 default: /* Unknown SMSC type */
681 break;
682 }
683 /*
684 smsc->type = SMSC_TYPE_DELETED;
685 smscenter_unlock(smsc);
686 */
687 if (errors)
688 return -1;
689
690 return 0;
691 }
692
693