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_at.c
59 *
60 * New driver for serial connected AT based
61 * devices.
62 * 4.9.2001
63 * Andreas Fink <andreas@fink.org>
64
65 * 23.6.2008, Andreas Fink,
66 * added support for telnet connections
67 * (for example Multi-Tech MTCBA-G-EN-F4)
68 *
69 */
70
71 #include <errno.h>
72 #include <stdarg.h>
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <unistd.h>
77 #include <fcntl.h>
78 #include <ctype.h>
79 #include <termios.h>
80 #include <sys/time.h>
81 #include <sys/types.h>
82 #include <sys/socket.h>
83 #include <netinet/in.h>
84 #include <netdb.h>
85 #include <sys/ioctl.h>
86 #include <time.h>
87 #include <math.h>
88
89 #include "gwlib/gwlib.h"
90 #include "gwlib/charset.h"
91 #include "smscconn.h"
92 #include "smscconn_p.h"
93 #include "bb_smscconn_cb.h"
94 #include "msg.h"
95 #include "sms.h"
96 #include "dlr.h"
97 #include "smsc_at.h"
98 #include "load.h"
99
100 static Octstr *gsm2number(Octstr *pdu);
101 static unsigned char nibble2hex(unsigned char b);
102
at2_scan_for_telnet_escapes(PrivAT2data * privdata)103 static void at2_scan_for_telnet_escapes(PrivAT2data *privdata)
104 {
105 int len;
106 int pos;
107 int start;
108 int a;
109 int b;
110 Octstr *hex;
111
112 char answer[5];
113
114
115 if(!privdata->ilb)
116 return;
117 start = 0;
118 len = octstr_len(privdata->ilb);
119 hex = octstr_duplicate(privdata->ilb);
120 octstr_binary_to_hex(hex,1);
121
122 octstr_destroy(hex);
123
124 while(start < len)
125 {
126 pos = octstr_search_char(privdata->ilb, 0xFF, start);
127 if(pos < 0)
128 return;
129 if((len - pos )<3)
130 return;
131 a = octstr_get_char(privdata->ilb,pos+1);
132 b = octstr_get_char(privdata->ilb,pos+2);
133 switch(a)
134 {
135 case 0xFD: /* do! */
136 answer[0] = 0xFF; /* escape */
137 answer[1] = 0xFC; /* wont do any option*/
138 answer[2] = b;
139 write(privdata->fd,&answer,3);
140 octstr_delete(privdata->ilb,pos,3);
141 len -=3;
142 break;
143 break;
144 case 0xFA: /* do you support option b ? */
145 octstr_delete(privdata->ilb,pos,3);
146 len -=3;
147 break;
148 break;
149 case 0xFB: /* will */
150 octstr_delete(privdata->ilb,pos,3);
151 len -=3;
152 break;
153 case 0xFC: /* wont */
154 octstr_delete(privdata->ilb,pos,3);
155 len -=3;
156 break;
157 }
158 start = pos;
159 }
160
161 }
162
at2_open_device1(PrivAT2data * privdata)163 static int at2_open_device1(PrivAT2data *privdata)
164 {
165 info(0, "AT2[%s]: opening device", octstr_get_cstr(privdata->name));
166 if (privdata->fd > 0) {
167 warning(0, "AT2[%s]: trying to open device with not closed device!!! Please report!!!",
168 octstr_get_cstr(privdata->name));
169 at2_close_device(privdata);
170 }
171 if (privdata->is_serial) {
172 privdata->fd = open(octstr_get_cstr(privdata->device),
173 O_RDWR | O_NONBLOCK | O_NOCTTY);
174 privdata->use_telnet = 0;
175 } else {
176 if (octstr_str_compare(privdata->device, "rawtcp") == 0) {
177 privdata->use_telnet = 0;
178 privdata->fd = tcpip_connect_to_server(octstr_get_cstr(privdata->rawtcp_host),
179 privdata->rawtcp_port, NULL);
180 }
181 else if (octstr_str_compare(privdata->device, "telnet") == 0) {
182 privdata->use_telnet = 1;
183 privdata->fd = tcpip_connect_to_server(octstr_get_cstr(privdata->rawtcp_host),
184 privdata->rawtcp_port, NULL);
185
186 } else {
187 gw_assert(0);
188 }
189 }
190 if (privdata->fd == -1) {
191 error(errno, "AT2[%s]: open failed! ERRNO=%d", octstr_get_cstr(privdata->name), errno);
192 privdata->fd = -1;
193 return -1;
194 }
195 debug("bb.smsc.at2", 0, "AT2[%s]: device opened. Telnet mode = %d", octstr_get_cstr(privdata->name),privdata->use_telnet);
196
197 return 0;
198 }
199
200
at2_login_device(PrivAT2data * privdata)201 static int at2_login_device(PrivAT2data *privdata)
202 {
203 info(0, "AT2[%s]: Logging in", octstr_get_cstr(privdata->name));
204
205 at2_read_buffer(privdata, 0);
206 gwthread_sleep(0.5);
207 at2_read_buffer(privdata, 0);
208
209 if((octstr_len(privdata->username) == 0 ) && (octstr_len(privdata->password)> 0)) {
210 at2_wait_modem_command(privdata, 10, 3, NULL); /* wait for Password: prompt */
211 at2_send_modem_command(privdata, octstr_get_cstr(privdata->password), 2,0); /* wait for OK: */
212 at2_send_modem_command(privdata, "AT", 2,0); /* wait for OK: */
213 }
214 else if((octstr_len(privdata->username) > 0 ) && (octstr_len(privdata->password)> 0)) {
215 at2_wait_modem_command(privdata, 10, 2, NULL); /* wait for Login: prompt */
216 at2_send_modem_command(privdata, octstr_get_cstr(privdata->username), 10,3); /* wait fo Password: */
217 at2_send_modem_command(privdata, octstr_get_cstr(privdata->password), 2,0); /* wait for OK: */
218 at2_send_modem_command(privdata, "AT", 2,0); /* wait for OK: */
219 }
220
221 return 0;
222 }
223
224
at2_open_device(PrivAT2data * privdata)225 static int at2_open_device(PrivAT2data *privdata)
226 {
227 struct termios tios;
228 int ret;
229
230 if ((ret = at2_open_device1(privdata)) != 0)
231 return ret;
232
233 if (!privdata->is_serial)
234 return 0;
235
236 tcgetattr(privdata->fd, &tios);
237
238 kannel_cfmakeraw(&tios);
239
240 tios.c_iflag |= IGNBRK; /* ignore break & parity errors */
241 tios.c_iflag &= ~INPCK; /* INPCK: disable parity check */
242 tios.c_cflag |= HUPCL; /* hangup on close */
243 tios.c_cflag |= CREAD; /* enable receiver */
244 tios.c_cflag |= CLOCAL; /* Ignore modem control lines */
245 tios.c_cflag &= ~CSIZE; /* set to 8 bit */
246 tios.c_cflag |= CS8;
247 tios.c_oflag &= ~ONLCR; /* no NL to CR-NL mapping outgoing */
248 tios.c_iflag |= IGNPAR; /* ignore parity */
249 tios.c_iflag &= ~INPCK;
250 #if defined(CRTSCTS)
251 if(privdata->modem) {
252 if(privdata->modem->hardware_flow_control) {
253 tios.c_cflag |= CRTSCTS; /* enable hardware flow control */
254 }
255 else {
256 tios.c_cflag &= ~CRTSCTS; /* disable hardware flow control */
257 }
258 }
259 else {
260 tios.c_cflag &= ~CRTSCTS; /* disable hardware flow control */
261 }
262 #endif
263 tios.c_cc[VSUSP] = 0; /* otherwhise we can not send CTRL Z */
264
265 /*
266 if ( ModemTypes[privdata->modemid].enable_parity )
267 tios.c_cflag ^= PARODD;
268 */
269
270 ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */
271 if (ret == -1) {
272 error(errno, "AT2[%s]: at_data_link: fail to set termios attribute",
273 octstr_get_cstr(privdata->name));
274 }
275 tcflush(privdata->fd, TCIOFLUSH);
276
277 /*
278 * Nokia 7110 and 6210 need some time between opening
279 * the connection and sending the first AT commands
280 */
281 if (privdata->modem == NULL || privdata->modem->need_sleep)
282 sleep(1);
283 debug("bb.smsc.at2", 0, "AT2[%s]: device opened", octstr_get_cstr(privdata->name));
284 return 0;
285 }
286
287
at2_close_device(PrivAT2data * privdata)288 static void at2_close_device(PrivAT2data *privdata)
289 {
290 info(0, "AT2[%s]: Closing device", octstr_get_cstr(privdata->name));
291 if (privdata->fd != -1)
292 close(privdata->fd);
293 privdata->fd = -1;
294 privdata->pin_ready = 0;
295 privdata->phase2plus = 0;
296 if (privdata->ilb != NULL)
297 octstr_destroy(privdata->ilb);
298 privdata->ilb = octstr_create("");
299 }
300
301
at2_read_buffer(PrivAT2data * privdata,double timeout)302 static void at2_read_buffer(PrivAT2data *privdata, double timeout)
303 {
304 char buf[MAX_READ + 1];
305 int ret;
306 size_t count;
307 signed int s;
308 fd_set read_fd;
309 struct timeval tv;
310
311 if (privdata->fd == -1) {
312 error(errno, "AT2[%s]: at2_read_buffer: fd = -1. Can not read",
313 octstr_get_cstr(privdata->name));
314 return;
315 }
316 count = MAX_READ;
317
318 #ifdef SSIZE_MAX
319 if (count > SSIZE_MAX)
320 count = SSIZE_MAX;
321 #endif
322
323 if (timeout <= 0) {
324 tv.tv_sec = 0;
325 tv.tv_usec = 1000;
326 } else {
327 int usecs = timeout * 1000000;
328 tv.tv_sec = usecs / 1000000;
329 tv.tv_usec = usecs % 1000000;
330 }
331
332 FD_ZERO(&read_fd);
333 FD_SET(privdata->fd, &read_fd);
334 ret = select(privdata->fd + 1, &read_fd, NULL, NULL, &tv);
335 if (ret == -1) {
336 if (!(errno == EINTR || errno == EAGAIN))
337 error(errno, "AT2[%s]: error on select", octstr_get_cstr(privdata->name));
338 return;
339 }
340
341 if (ret == 0)
342 return;
343
344 s = read(privdata->fd, buf, count);
345 if (s < 0) {
346 error(errno, "AT2[%s]: at2_read_buffer: Error during read",
347 octstr_get_cstr(privdata->name));
348 at2_close_device(privdata);
349 } else {
350 octstr_append_data(privdata->ilb, buf, s);
351 if(privdata->use_telnet)
352 at2_scan_for_telnet_escapes(privdata);
353 }
354 }
355
356
at2_wait_line(PrivAT2data * privdata,time_t timeout,int gt_flag)357 static Octstr *at2_wait_line(PrivAT2data *privdata, time_t timeout, int gt_flag)
358 {
359 Octstr *line;
360 time_t end_time;
361 time_t cur_time;
362
363 if (timeout == 0)
364 timeout = 3;
365 end_time = time(NULL) + timeout;
366
367 if (privdata->lines != NULL)
368 octstr_destroy(privdata->lines);
369 privdata->lines = octstr_create("");
370 while (time(&cur_time) <= end_time) {
371 line = at2_read_line(privdata, gt_flag, timeout);
372 if (line)
373 return line;
374 }
375 return NULL;
376 }
377
378
at2_extract_line(PrivAT2data * privdata,int gt_flag)379 static Octstr *at2_extract_line(PrivAT2data *privdata, int gt_flag)
380 {
381 int eol;
382 int gtloc;
383 int len;
384 Octstr *line;
385 Octstr *buf2;
386 int i;
387
388 len = octstr_len(privdata->ilb);
389 if (len == 0)
390 return NULL;
391
392 if (gt_flag==1) {
393 /* looking for > if needed */
394 gtloc = octstr_search_char(privdata->ilb, '>', 0);
395 } else if((gt_flag == 2) && (privdata->username)) { /* looking for "Login" */
396 gtloc = -1;
397 if(privdata->login_prompt) {
398 gtloc = octstr_search(privdata->ilb,privdata->login_prompt,0);
399 }
400 if(gtloc == -1) {
401 gtloc = octstr_search(privdata->ilb,octstr_imm("Login:"),0);
402 }
403 if(gtloc == -1) {
404 gtloc = octstr_search(privdata->ilb,octstr_imm("Username:"),0);
405 }
406 } else if ((gt_flag == 3) && (privdata->password)) {/* looking for Password */
407 gtloc = -1;
408 if(privdata->password_prompt) {
409 gtloc = octstr_search(privdata->ilb,privdata->password_prompt,0);
410 }
411 if(gtloc == -1) {
412 gtloc = octstr_search(privdata->ilb,octstr_imm("Password:"),0);
413 }
414 } else
415 gtloc = -1;
416
417 /*
418 if (gt_flag && (gtloc != -1))
419 debug("bb.smsc.at2", 0, "in at2_read_line with gt_flag=1, gtloc=%d, ilb=%s",
420 gtloc, octstr_get_cstr(privdata->ilb));
421 */
422
423 eol = octstr_search_char(privdata->ilb, '\r', 0); /* looking for CR */
424
425 if ((gtloc != -1) && ((eol == -1) || (eol > gtloc)))
426 eol = gtloc;
427
428 if (eol == -1)
429 return NULL;
430
431 line = octstr_copy(privdata->ilb, 0, eol);
432 buf2 = octstr_copy(privdata->ilb, eol + 1, len);
433 octstr_destroy(privdata->ilb);
434 privdata->ilb = buf2;
435
436 /* remove any non printable chars (including linefeed for example) */
437 for (i = 0; i < octstr_len(line); i++) {
438 if (octstr_get_char(line, i) < 32)
439 octstr_set_char(line, i, ' ');
440 }
441 octstr_strip_blanks(line);
442
443 /* empty line, skipping */
444 if (octstr_len(line) == 0 && (gt_flag == 0)) {
445 return line;
446 }
447 if ((gt_flag) && (gtloc != -1)) {
448 /* got to re-add it again as the parser needs to see it */
449 octstr_append_cstr(line, ">");
450 }
451 debug("bb.smsc.at2", 0, "AT2[%s]: <-- %s", octstr_get_cstr(privdata->name),
452 octstr_get_cstr(line));
453 return line;
454 }
455
456
at2_read_line(PrivAT2data * privdata,int gt_flag,double timeout)457 static Octstr *at2_read_line(PrivAT2data *privdata, int gt_flag, double timeout)
458 {
459 Octstr *line;
460
461 line = at2_extract_line(privdata, gt_flag);
462 if (!line) {
463 at2_read_buffer(privdata, timeout);
464 line = at2_extract_line(privdata, gt_flag);
465 }
466 return line;
467 }
468
469
at2_write_line(PrivAT2data * privdata,char * line)470 static int at2_write_line(PrivAT2data *privdata, char *line)
471 {
472 int count;
473 int s = 0;
474 int write_count = 0, data_written = 0;
475 Octstr *linestr = NULL;
476
477 linestr = octstr_format("%s\r", line);
478
479 debug("bb.smsc.at2", 0, "AT2[%s]: --> %s^M", octstr_get_cstr(privdata->name), line);
480
481 count = octstr_len(linestr);
482 while (count > data_written) {
483 errno = 0;
484 s = write(privdata->fd, octstr_get_cstr(linestr) + data_written,
485 count - data_written);
486 if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
487 gwthread_sleep(1);
488 ++write_count;
489 } else if (s > 0) {
490 data_written += s;
491 write_count = 0;
492 } else
493 break;
494 }
495 O_DESTROY(linestr);
496 if (s < 0) {
497 error(errno, "AT2[%s]: Couldnot write to device.",
498 octstr_get_cstr(privdata->name));
499 tcflush(privdata->fd, TCOFLUSH);
500 return s;
501 }
502 tcdrain(privdata->fd);
503 gwthread_sleep((double) (privdata->modem == NULL ?
504 100 : privdata->modem->sendline_sleep) / 1000);
505 return s;
506 }
507
508
at2_write_ctrlz(PrivAT2data * privdata)509 static int at2_write_ctrlz(PrivAT2data *privdata)
510 {
511 int s;
512 char *ctrlz = "\032" ;
513 int write_count = 0;
514
515 debug("bb.smsc.at2", 0, "AT2[%s]: --> ^Z", octstr_get_cstr(privdata->name));
516 while (1) {
517 errno = 0;
518 s = write(privdata->fd, ctrlz, 1);
519 if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
520 gwthread_sleep(1);
521 ++write_count;
522 } else
523 break;
524 }
525 if (s < 0) {
526 error(errno, "AT2[%s]: Couldnot write to device.",
527 octstr_get_cstr(privdata->name));
528 tcflush(privdata->fd, TCOFLUSH);
529 return s;
530 }
531 tcdrain(privdata->fd);
532 gwthread_sleep((double) (privdata->modem == NULL ?
533 100 : privdata->modem->sendline_sleep) / 1000);
534 return s;
535 }
536
537
at2_write(PrivAT2data * privdata,char * line)538 static int at2_write(PrivAT2data *privdata, char *line)
539 {
540 int count, data_written = 0, write_count = 0;
541 int s = 0;
542
543 debug("bb.smsc.at2", 0, "AT2[%s]: --> %s", octstr_get_cstr(privdata->name), line);
544
545 count = strlen(line);
546 while(count > data_written) {
547 s = write(privdata->fd, line + data_written, count - data_written);
548 if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
549 gwthread_sleep(1);
550 ++write_count;
551 } else if (s > 0) {
552 data_written += s;
553 write_count = 0;
554 } else
555 break;
556 }
557
558 if (s < 0) {
559 error(errno, "AT2[%s]: Couldnot write to device.",
560 octstr_get_cstr(privdata->name));
561 tcflush(privdata->fd, TCOFLUSH);
562 return s;
563 }
564 tcdrain(privdata->fd);
565 gwthread_sleep((double) (privdata->modem == NULL ?
566 100 : privdata->modem->sendline_sleep) / 1000);
567 return s;
568 }
569
570
at2_flush_buffer(PrivAT2data * privdata)571 static void at2_flush_buffer(PrivAT2data *privdata)
572 {
573 at2_read_buffer(privdata, 0);
574 octstr_destroy(privdata->ilb);
575 privdata->ilb = octstr_create("");
576 }
577
578
at2_init_device(PrivAT2data * privdata)579 static int at2_init_device(PrivAT2data *privdata)
580 {
581 int ret;
582 Octstr *setpin;
583
584 info(0, "AT2[%s]: init device", octstr_get_cstr(privdata->name));
585
586 at2_set_speed(privdata, privdata->speed);
587 /* sleep 10 ms in order to get device some time to accept speed */
588 gwthread_sleep(0.1);
589
590 /* reset the modem */
591 if (at2_send_modem_command(privdata, "ATZ", 0, 0) == -1) {
592 error(0, "AT2[%s]: Wrong or no answer to ATZ, ignoring",
593 octstr_get_cstr(privdata->name));
594 return -1;
595 }
596
597 /* check if the modem responded */
598 if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
599 error(0, "AT2[%s]: Wrong or no answer to AT. Trying again",
600 octstr_get_cstr(privdata->name));
601 if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
602 error(0, "AT2[%s]: Second attempt to send AT failed",
603 octstr_get_cstr(privdata->name));
604 return -1;
605 }
606 }
607
608 at2_flush_buffer(privdata);
609
610 if (at2_send_modem_command(privdata, "AT&F", 7, 0) == -1) {
611 error(0, "AT2[%s]: No answer to AT&F. Trying again",
612 octstr_get_cstr(privdata->name));
613 if (at2_send_modem_command(privdata, "AT&F", 7, 0) == -1) {
614 return -1;
615 }
616 }
617
618 at2_flush_buffer(privdata);
619
620 /* check if the modem responded */
621 if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
622 error(0, "AT2[%s]: Wrong or no answer to ATE0. Trying again",
623 octstr_get_cstr(privdata->name));
624 if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
625 error(0, "AT2[%s]: Second attempt to send ATE0 failed",
626 octstr_get_cstr(privdata->name));
627 return -1;
628 }
629 }
630
631 at2_flush_buffer(privdata);
632
633
634 /* enable hardware handshake */
635 if (octstr_len(privdata->modem->enable_hwhs)) {
636 if (at2_send_modem_command(privdata,
637 octstr_get_cstr(privdata->modem->enable_hwhs), 0, 0) == -1)
638 info(0, "AT2[%s]: cannot enable hardware handshake",
639 octstr_get_cstr(privdata->name));
640 }
641
642 /*
643 * Check does the modem require a PIN and, if so, send it.
644 * This is not supported by the Nokia Premicell
645 */
646 if (!privdata->modem->no_pin) {
647 ret = at2_send_modem_command(privdata, "AT+CPIN?", 10, 0);
648
649 if (!privdata->pin_ready) {
650 if (ret == 2) {
651 if (privdata->pin == NULL)
652 return -1;
653 setpin = octstr_format("AT+CPIN=\"%s\"", octstr_get_cstr(privdata->pin));
654 ret = at2_send_modem_command(privdata, octstr_get_cstr(setpin), 0, 0);
655 octstr_destroy(setpin);
656 if (ret != 0 )
657 return -1;
658 } else if (ret == -1)
659 return -1;
660 }
661
662 /*
663 * we have to wait until +CPIN: READY appears before issuing
664 * the next command. 10 sec should be suficient
665 */
666 if (!privdata->pin_ready) {
667 at2_wait_modem_command(privdata, 10, 0, NULL);
668 if (!privdata->pin_ready) {
669 at2_send_modem_command(privdata, "AT+CPIN?", 10, 0);
670 if (!privdata->pin_ready) {
671 return -1; /* give up */
672 }
673 }
674 }
675 }
676 /*
677 * Set the GSM SMS message center address if supplied
678 */
679 if (octstr_len(privdata->sms_center)) {
680 Octstr *temp;
681 temp = octstr_create("AT+CSCA=");
682 octstr_append_char(temp, 34);
683 octstr_append(temp, privdata->sms_center);
684 octstr_append_char(temp, 34);
685 /*
686 * XXX If some modem don't process the +, remove it and add ",145"
687 * and ",129" to national numbers
688 */
689 ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
690 octstr_destroy(temp);
691 if (ret == -1)
692 return -1;
693 if (ret > 0) {
694 info(0, "AT2[%s]: Cannot set SMS message center, continuing",
695 octstr_get_cstr(privdata->name));
696 }
697 }
698
699 /* Set the modem to PDU mode and autodisplay of new messages */
700 ret = at2_send_modem_command(privdata, "AT+CMGF=0", 0, 0);
701 if (ret != 0 )
702 return -1;
703
704 /* lets see if it supports GSM SMS 2+ mode */
705 ret = at2_send_modem_command(privdata, "AT+CSMS=?", 0, 0);
706 if (ret != 0) {
707 /* if it doesnt even understand the command, I'm sure it wont support it */
708 privdata->phase2plus = 0;
709 } else {
710 /* we have to take a part a string like +CSMS: (0,1,128) */
711 Octstr *ts;
712 int i;
713 List *vals;
714
715 ts = privdata->lines;
716 privdata->lines = NULL;
717
718 i = octstr_search_char(ts, '(', 0);
719 if (i > 0) {
720 octstr_delete(ts, 0, i + 1);
721 }
722 i = octstr_search_char(ts, ')', 0);
723 if (i > 0) {
724 octstr_truncate(ts, i);
725 }
726 vals = octstr_split(ts, octstr_imm(","));
727 octstr_destroy(ts);
728 ts = gwlist_search(vals, octstr_imm("1"), (void*) octstr_item_match);
729 if (ts)
730 privdata->phase2plus = 1;
731 gwlist_destroy(vals, octstr_destroy_item);
732 }
733 if (privdata->phase2plus) {
734 info(0, "AT2[%s]: Phase 2+ is supported", octstr_get_cstr(privdata->name));
735 ret = at2_send_modem_command(privdata, "AT+CSMS=1", 0, 0);
736 if (ret != 0)
737 return -1;
738 }
739
740 /* send init string */
741 ret = at2_send_modem_command(privdata, octstr_get_cstr(privdata->modem->init_string), 0, 0);
742 if (ret != 0)
743 return -1;
744
745 if (privdata->sms_memory_poll_interval && privdata->modem->message_storage) {
746 /* set message storage location for "SIM buffering" using the CPMS command */
747 if (at2_set_message_storage(privdata, privdata->modem->message_storage) != 0)
748 return -1;
749 }
750
751 info(0, "AT2[%s]: AT SMSC successfully opened.", octstr_get_cstr(privdata->name));
752 return 0;
753 }
754
755
at2_send_modem_command(PrivAT2data * privdata,char * cmd,time_t timeout,int gt_flag)756 static int at2_send_modem_command(PrivAT2data *privdata, char *cmd, time_t timeout, int gt_flag)
757 {
758 if (at2_write_line(privdata, cmd) == -1)
759 return -1;
760 return at2_wait_modem_command(privdata, timeout, gt_flag, NULL);
761 }
762
763
at2_wait_modem_command(PrivAT2data * privdata,time_t timeout,int gt_flag,int * output)764 static int at2_wait_modem_command(PrivAT2data *privdata, time_t timeout, int gt_flag, int *output)
765 {
766 Octstr *line = NULL;
767 Octstr *line2 = NULL;
768 Octstr *pdu = NULL;
769 Octstr *smsc_number = NULL;
770 int ret;
771 time_t end_time;
772 time_t cur_time;
773 Msg *msg;
774 int cmgr_flag = 0;
775
776 if (!timeout)
777 timeout = 3;
778 end_time = time(NULL) + timeout;
779
780 if (privdata->lines != NULL)
781 octstr_destroy(privdata->lines);
782 privdata->lines = octstr_create("");
783
784 smsc_number = octstr_create("");
785 while (privdata->fd != -1 && time(&cur_time) <= end_time) {
786 O_DESTROY(line);
787 if ((line = at2_read_line(privdata, gt_flag, timeout))) {
788 octstr_append(privdata->lines, line);
789 octstr_append_cstr(privdata->lines, "\n");
790
791 if (octstr_search(line, octstr_imm("SIM PIN"), 0) != -1) {
792 ret = 2;
793 goto end;
794 }
795 if (octstr_search(line, octstr_imm("OK"), 0) != -1) {
796 ret = 0;
797 goto end;
798 }
799 if ((gt_flag ) && (octstr_search(line, octstr_imm(">"), 0) != -1)) {
800 ret = 1;
801 goto end;
802 }
803 if (octstr_search(line, octstr_imm("RING"), 0) != -1) {
804 at2_write_line(privdata, "ATH0");
805 continue;
806 }
807 if (octstr_search(line, octstr_imm("+CPIN: READY"), 0) != -1) {
808 privdata->pin_ready = 1;
809 ret = 3;
810 goto end;
811 }
812 if (octstr_search(line, octstr_imm("+CMS ERROR"), 0) != -1) {
813 int errcode;
814 error(0, "AT2[%s]: +CMS ERROR: %s", octstr_get_cstr(privdata->name),
815 octstr_get_cstr(line));
816 if (sscanf(octstr_get_cstr(line), "+CMS ERROR: %d", &errcode) == 1)
817 error(0, "AT2[%s]: +CMS ERROR: %s (%d)", octstr_get_cstr(privdata->name),
818 at2_error_string(errcode), errcode);
819 ret = 1;
820 goto end;
821 } else if (octstr_search(line, octstr_imm("+CME ERROR"), 0) != -1) {
822 int errcode;
823 error(0, "AT2[%s]: +CME ERROR: %s", octstr_get_cstr(privdata->name),
824 octstr_get_cstr(line));
825 if (sscanf(octstr_get_cstr(line), "+CME ERROR: %d", &errcode) == 1)
826 error(0, "AT2[%s]: +CME ERROR: %s (%d)", octstr_get_cstr(privdata->name),
827 at2_error_string(errcode), errcode);
828 ret = 1;
829 goto end;
830 }
831 if (octstr_search(line, octstr_imm("+CMTI:"), 0) != -1 ||
832 octstr_search(line, octstr_imm("+CDSI:"), 0) != -1) {
833 /*
834 * we received an incoming message indication
835 * put it in the pending_incoming_messages queue for later retrieval
836 */
837 debug("bb.smsc.at2", 0, "AT2[%s]: +CMTI incoming SMS indication: %s",
838 octstr_get_cstr(privdata->name), octstr_get_cstr(line));
839 gwlist_append(privdata->pending_incoming_messages, line);
840 line = NULL;
841 continue;
842 }
843 if (octstr_search(line, octstr_imm("+CMT:"), 0) != -1 ||
844 octstr_search(line, octstr_imm("+CDS:"), 0) != -1 ||
845 ((octstr_search(line, octstr_imm("+CMGR:"), 0) != -1) && (cmgr_flag = 1)) ) {
846 line2 = at2_wait_line(privdata, 1, 0);
847
848 if (line2 == NULL) {
849 error(0, "AT2[%s]: got +CMT but waiting for next line timed out",
850 octstr_get_cstr(privdata->name));
851 } else {
852 octstr_append_cstr(line, "\n");
853 octstr_append(line, line2);
854 O_DESTROY(line2);
855 at2_pdu_extract(privdata, &pdu, line, smsc_number);
856 if (pdu == NULL) {
857 error(0, "AT2[%s]: got +CMT but pdu_extract failed",
858 octstr_get_cstr(privdata->name));
859 } else {
860 /* count message even if I can't decode it */
861 if (output)
862 ++(*output);
863 msg = at2_pdu_decode(pdu, privdata);
864 if (msg != NULL) {
865 octstr_destroy(msg->sms.smsc_id);
866 octstr_destroy(msg->sms.smsc_number);
867 msg->sms.smsc_id = octstr_duplicate(privdata->conn->id);
868 msg->sms.smsc_number = octstr_duplicate(smsc_number);
869 bb_smscconn_receive(privdata->conn, msg);
870 } else {
871 error(0, "AT2[%s]: could not decode PDU to a message.",
872 octstr_get_cstr(privdata->name));
873 }
874
875 if (!cmgr_flag) {
876 if (privdata->phase2plus) {
877 at2_send_modem_command(privdata, "AT+CNMA", 3, 0);
878 }
879 }
880
881 O_DESTROY(pdu);
882 }
883 }
884 continue;
885 }
886 if ((octstr_search(line, octstr_imm("+CMGS:"),0) != -1) && (output)) {
887 /*
888 * found response to a +CMGS command, read the message id
889 * and return it in output
890 */
891 long temp;
892 if (octstr_parse_long(&temp, line, octstr_search(line, octstr_imm("+CMGS:"), 0) + 6, 10) == -1)
893 error(0, "AT2[%s]: Got +CMGS but failed to read message id",
894 octstr_get_cstr(privdata->name));
895 else
896 *output = temp;
897 }
898 /* finally check if we received a generic error */
899 if (octstr_search(line, octstr_imm("ERROR"), 0) != -1) {
900 int errcode;
901 error(0, "AT2[%s]: Generic error: %s", octstr_get_cstr(privdata->name),
902 octstr_get_cstr(line));
903 if (sscanf(octstr_get_cstr(line), "ERROR: %d", &errcode) == 1)
904 error(0, "AT2[%s]: Generic error: %s (%d)", octstr_get_cstr(privdata->name),
905 at2_error_string(errcode), errcode);
906 ret = -1;
907 goto end;
908 }
909 }
910 }
911
912 /*
913 error(0,"AT2[%s]: timeout. received <%s> until now, buffer size is %d, buf=%s",
914 octstr_get_cstr(privdata->name),
915 privdata->lines ? octstr_get_cstr(privdata->lines) : "<nothing>", len,
916 privdata->ilb ? octstr_get_cstr(privdata->ilb) : "<nothing>");
917 */
918 O_DESTROY(line);
919 O_DESTROY(line2);
920 O_DESTROY(pdu);
921 O_DESTROY(smsc_number);
922 return -1; /* timeout */
923
924 end:
925 O_DESTROY(smsc_number);
926 octstr_append(privdata->lines, line);
927 octstr_append_cstr(privdata->lines, "\n");
928 O_DESTROY(line);
929 O_DESTROY(line2);
930 O_DESTROY(pdu);
931 return ret;
932 }
933
934
at2_read_delete_message(PrivAT2data * privdata,int message_number)935 static int at2_read_delete_message(PrivAT2data* privdata, int message_number)
936 {
937 char cmd[20];
938 int message_count = 0;
939
940 sprintf(cmd, "AT+CMGR=%d", message_number);
941 /* read one message from memory */
942 at2_write_line(privdata, cmd);
943 if (at2_wait_modem_command(privdata, 0, 0, &message_count) != 0) {
944 debug("bb.smsc.at2", 0, "AT2[%s]: failed to get message %d.",
945 octstr_get_cstr(privdata->name), message_number);
946 return 0; /* failed to read the message - skip to next message */
947 }
948
949 /* no need to delete if no message collected */
950 if (!message_count) {
951 debug("bb.smsc.at2", 0, "AT2[%s]: not deleted.",
952 octstr_get_cstr(privdata->name));
953 return 0;
954 }
955
956 sprintf(cmd, "AT+CMGD=%d", message_number); /* delete the message we just read */
957 /*
958 * 3 seconds (default timeout of send_modem_command()) is not enough with some
959 * modems if the message is large, so we'll give it 7 seconds
960 */
961 if (at2_send_modem_command(privdata, cmd, 7, 0) != 0) {
962 /*
963 * failed to delete the message, we'll just ignore it for now,
964 * this is bad, since if the message really didn't get deleted
965 * we'll see it next time around.
966 */
967 error(2, "AT2[%s]: failed to delete message %d.",
968 octstr_get_cstr(privdata->name), message_number);
969 }
970
971 return 1;
972 }
973
974
975 /*
976 * This function loops through the pending_incoming_messages queue for CMTI
977 * notifications.
978 * Every notification is parsed and the messages are read (and deleted)
979 * accordingly.
980 */
at2_read_pending_incoming_messages(PrivAT2data * privdata)981 static void at2_read_pending_incoming_messages(PrivAT2data *privdata)
982 {
983 Octstr *current_storage = NULL;
984
985 if (privdata->modem->message_storage) {
986 current_storage = octstr_duplicate(privdata->modem->message_storage);
987 }
988 while (gwlist_len(privdata->pending_incoming_messages) > 0) {
989 int pos;
990 long location;
991 Octstr *cmti_storage = NULL, *line = NULL;
992
993 line = gwlist_extract_first(privdata->pending_incoming_messages);
994 /* message memory starts after the first quote in the string */
995 if ((pos = octstr_search_char(line, '"', 0)) != -1) {
996 /* grab memory storage name */
997 int next_quote = octstr_search_char(line, '"', ++pos);
998 if (next_quote == -1) { /* no second qoute - this line must be broken somehow */
999 O_DESTROY(line);
1000 continue;
1001 }
1002
1003 /* store notification storage location for reference */
1004 cmti_storage = octstr_copy(line, pos, next_quote - pos);
1005 } else
1006 /* reset pos for the next lookup which would start from the beginning if no memory
1007 * location was found */
1008 pos = 0;
1009
1010 /* if no message storage is set in configuration - set now */
1011 if (!privdata->modem->message_storage && cmti_storage) {
1012 info(2, "AT2[%s]: CMTI received, but no message-storage is set in confiuration."
1013 "setting now to <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(cmti_storage));
1014 privdata->modem->message_storage = octstr_duplicate(cmti_storage);
1015 current_storage = octstr_duplicate(cmti_storage);
1016 at2_set_message_storage(privdata, cmti_storage);
1017 }
1018
1019 /* find the message id from the line, which should appear after the first comma */
1020 if ((pos = octstr_search_char(line, ',', pos)) == -1) { /* this CMTI notification is probably broken */
1021 error(2, "AT2[%s]: failed to find memory location in CMTI notification",
1022 octstr_get_cstr(privdata->name));
1023 O_DESTROY(line);
1024 octstr_destroy(cmti_storage);
1025 continue;
1026 }
1027
1028 if ((pos = octstr_parse_long(&location, line, ++pos, 10)) == -1) {
1029 /* there was an error parsing the message id. next! */
1030 error(2, "AT2[%s]: error parsing memory location in CMTI notification",
1031 octstr_get_cstr(privdata->name));
1032 O_DESTROY(line);
1033 octstr_destroy(cmti_storage);
1034 continue;
1035 }
1036
1037 /* check if we need to change storage location before issuing the read command */
1038 if (!current_storage || (octstr_compare(current_storage, cmti_storage) != 0)) {
1039 octstr_destroy(current_storage);
1040 current_storage = octstr_duplicate(cmti_storage);
1041 at2_set_message_storage(privdata, cmti_storage);
1042 }
1043
1044 if (!at2_read_delete_message(privdata, location)) {
1045 error(1, "AT2[%s]: CMTI notification received, but no message found in memory!",
1046 octstr_get_cstr(privdata->name));
1047 }
1048
1049 octstr_destroy(line);
1050 octstr_destroy(cmti_storage);
1051 }
1052
1053 /* set prefered message storage back to what configured */
1054 if (current_storage && privdata->modem->message_storage
1055 && (octstr_compare(privdata->modem->message_storage, current_storage) != 0))
1056 at2_set_message_storage(privdata, privdata->modem->message_storage);
1057
1058 octstr_destroy(current_storage);
1059 }
1060
1061
at2_read_sms_memory(PrivAT2data * privdata)1062 static int at2_read_sms_memory(PrivAT2data* privdata)
1063 {
1064 /* get memory status */
1065 if (at2_check_sms_memory(privdata) == -1) {
1066 debug("bb.smsc.at2", 0, "AT2[%s]: memory check error", octstr_get_cstr(privdata->name));
1067 return -1;
1068 }
1069
1070 if (privdata->sms_memory_usage) {
1071 /*
1072 * that is - greater then 0, meaning there are some messages to fetch
1073 * now - I used to just loop over the first input_mem_sms_used locations,
1074 * but it doesn't hold, since under load, messages may be received while
1075 * we're in the loop, and get stored in locations towards the end of the list,
1076 * thus creating 'holes' in the memory.
1077 *
1078 * There are two ways we can fix this :
1079 * (a) Just read the last message location, delete it and return.
1080 * It's not a complete solution since holes can still be created if messages
1081 * are received between the memory check and the delete command,
1082 * and anyway - it will slow us down and won't hold well under pressure
1083 * (b) Just scan the entire memory each call, bottom to top.
1084 * This will be slow too, but it'll be reliable.
1085 *
1086 * We can massivly improve performance by stopping after input_mem_sms_used messages
1087 * have been read, but send_modem_command returns 0 for no message as well as for a
1088 * message read, and the only other way to implement it is by doing memory_check
1089 * after each read and stoping when input_mem_sms_used get to 0. This is slow
1090 * (modem commands take time) so we improve speed only if there are less then 10
1091 * messages in memory.
1092 *
1093 * I implemented the alternative - changed at2_wait_modem_command to return the
1094 * number of messages it collected.
1095 */
1096 int i;
1097 int message_count = 0; /* cound number of messages collected */
1098 ModemDef *modem = privdata->modem;
1099
1100 debug("bb.smsc.at2", 0, "AT2[%s]: %d messages waiting in memory",
1101 octstr_get_cstr(privdata->name), privdata->sms_memory_usage);
1102
1103 /*
1104 * loop till end of memory or collected enouch messages
1105 */
1106 for (i = modem->message_start; i < (privdata->sms_memory_capacity + modem->message_start) && message_count < privdata->sms_memory_usage; ++i) {
1107
1108 /* if (meanwhile) there are pending CMTI notifications, process these first
1109 * to not let CMTI and sim buffering sit in each others way */
1110 while (gwlist_len(privdata->pending_incoming_messages) > 0) {
1111 at2_read_pending_incoming_messages(privdata);
1112 }
1113 /* read the message and delete it */
1114 message_count += at2_read_delete_message(privdata, i);
1115 }
1116 }
1117
1118 /*
1119 at2_send_modem_command(privdata, ModemTypes[privdata->modemid].init1, 0, 0);
1120 */
1121 return 0;
1122 }
1123
1124
at2_check_sms_memory(PrivAT2data * privdata)1125 static int at2_check_sms_memory(PrivAT2data *privdata)
1126 {
1127 long values[4]; /* array to put response data in */
1128 int pos; /* position of parser in data stream */
1129 int ret;
1130 Octstr *search_cpms = NULL;
1131
1132 /* select memory type and get report */
1133 if ((ret = at2_send_modem_command(privdata, "AT+CPMS?", 0, 0)) != 0) {
1134 debug("bb.smsc.at2.memory_check", 0, "failed to send mem select command to modem %d", ret);
1135 return -1;
1136 }
1137
1138 search_cpms = octstr_create("+CPMS:");
1139
1140 if ((pos = octstr_search(privdata->lines, search_cpms, 0)) != -1) {
1141 /* got back a +CPMS response */
1142 int index = 0; /* index in values array */
1143 pos += 6; /* position of parser in the stream - start after header */
1144
1145 /* skip memory indication */
1146 pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;
1147
1148 /* find all the values */
1149 while (index < 4 && pos < octstr_len(privdata->lines) &&
1150 (pos = octstr_parse_long(&values[index], privdata->lines, pos, 10)) != -1) {
1151 ++pos; /* skip number seperator */
1152 ++index; /* increment array index */
1153 if (index == 2)
1154 /* skip second memory indication */
1155 pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;
1156 }
1157
1158 if (index < 4) {
1159 /* didn't get all memory data - I don't why, so I'll bail */
1160 debug("bb.smsc.at2", 0, "AT2[%s]: couldn't parse all memory locations : %d:'%s'.",
1161 octstr_get_cstr(privdata->name), index,
1162 &(octstr_get_cstr(privdata->lines)[pos]));
1163 O_DESTROY(search_cpms);
1164 return -1;
1165 }
1166
1167 privdata->sms_memory_usage = values[0];
1168 privdata->sms_memory_capacity = values[1];
1169 /*
1170 privdata->output_mem_sms_used = values[2];
1171 privdata->output_mem_sms_capacity = values[3];
1172 */
1173
1174 /* everything's cool */
1175 ret = 0;
1176
1177 /* clear the buffer */
1178 O_DESTROY(privdata->lines);
1179
1180 } else {
1181 debug("bb.smsc.at2", 0, "AT2[%s]: no correct header for CPMS response.",
1182 octstr_get_cstr(privdata->name));
1183
1184 /* didn't get a +CPMS response - this is clearly an error */
1185 ret = -1;
1186 }
1187
1188 O_DESTROY(search_cpms);
1189 return ret;
1190 }
1191
1192
at2_set_speed(PrivAT2data * privdata,int bps)1193 static void at2_set_speed(PrivAT2data *privdata, int bps)
1194 {
1195 struct termios tios;
1196 int ret;
1197 int speed;
1198
1199 if (!privdata->is_serial)
1200 return;
1201
1202 tcgetattr(privdata->fd, &tios);
1203
1204 switch (bps) {
1205 case 300:
1206 speed = B300;
1207 break;
1208 case 1200:
1209 speed = B1200;
1210 break;
1211 case 2400:
1212 speed = B2400;
1213 break;
1214 case 4800:
1215 speed = B4800;
1216 break;
1217 case 9600:
1218 speed = B9600;
1219 break;
1220 case 19200:
1221 speed = B19200;
1222 break;
1223 case 38400:
1224 speed = B38400;
1225 break;
1226 #ifdef B57600
1227 case 57600:
1228 speed = B57600;
1229 break;
1230 #endif
1231 #ifdef B115200
1232 case 115200:
1233 speed = B115200;
1234 break;
1235 #endif
1236 #ifdef B230400
1237 case 230400:
1238 speed = B230400;
1239 break;
1240 #endif
1241 #ifdef B460800
1242 case 460800:
1243 speed = B460800;
1244 break;
1245 #endif
1246 #ifdef B500000
1247 case 500000:
1248 speed = B500000;
1249 break;
1250 #endif
1251 #ifdef B576000
1252 case 576000:
1253 speed = B576000;
1254 break;
1255 #endif
1256 #ifdef B921600
1257 case 921600:
1258 speed = B921600;
1259 break;
1260 #endif
1261 default:
1262 #if B9600 == 9600
1263 speed = bps;
1264 #else
1265 speed = B9600;
1266 #endif
1267 }
1268
1269 cfsetospeed(&tios, speed);
1270 cfsetispeed(&tios, speed);
1271 ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */
1272 if (ret == -1) {
1273 error(errno, "AT2[%s]: at_data_link: fail to set termios attribute",
1274 octstr_get_cstr(privdata->name));
1275 }
1276 tcflush(privdata->fd, TCIOFLUSH);
1277
1278 info(0, "AT2[%s]: speed set to %d", octstr_get_cstr(privdata->name), bps);
1279 }
1280
1281
at2_device_thread(void * arg)1282 static void at2_device_thread(void *arg)
1283 {
1284 SMSCConn *conn = arg;
1285 PrivAT2data *privdata = conn->data;
1286 int reconnecting = 0, error_count = 0;
1287 long idle_timeout, memory_poll_timeout = 0;
1288
1289 conn->status = SMSCCONN_CONNECTING;
1290
1291 /* Make sure we log into our own log-file if defined */
1292 log_thread_to(conn->log_idx);
1293
1294 reconnect:
1295
1296 do {
1297 if (reconnecting) {
1298 if (conn->status == SMSCCONN_ACTIVE) {
1299 mutex_lock(conn->flow_mutex);
1300 conn->status = SMSCCONN_RECONNECTING;
1301 mutex_unlock(conn->flow_mutex);
1302 }
1303 error(0, "AT2[%s]: Couldn't connect (retrying in %ld seconds).",
1304 octstr_get_cstr(privdata->name), conn->reconnect_delay);
1305 gwthread_sleep(conn->reconnect_delay);
1306 reconnecting = 0;
1307 }
1308
1309 /* If modems->speed is defined, try to use it, else autodetect */
1310 if (privdata->speed == 0 && privdata->modem != NULL && privdata->modem->speed != 0) {
1311
1312 info(0, "AT2[%s]: trying to use speed <%ld> from modem definition",
1313 octstr_get_cstr(privdata->name), privdata->modem->speed);
1314 if (at2_test_speed(privdata, privdata->modem->speed) == 0) {
1315 privdata->speed = privdata->modem->speed;
1316 info(0, "AT2[%s]: speed is %ld",
1317 octstr_get_cstr(privdata->name), privdata->speed);
1318 } else {
1319 info(0, "AT2[%s]: speed in modem definition don't work, will autodetect",
1320 octstr_get_cstr(privdata->name));
1321 }
1322 }
1323
1324 if (privdata->speed == 0 && at2_detect_speed(privdata) == -1) {
1325 reconnecting = 1;
1326 continue;
1327 }
1328
1329 if (privdata->modem == NULL && at2_detect_modem_type(privdata) == -1) {
1330 reconnecting = 1;
1331 continue;
1332 }
1333
1334 if (at2_open_device(privdata)) {
1335 error(errno, "AT2[%s]: at2_device_thread: open_at2_device failed.",
1336 octstr_get_cstr(privdata->name));
1337 reconnecting = 1;
1338 continue;
1339 }
1340
1341 if (at2_login_device(privdata)) {
1342 error(errno, "AT2[%s]: at2_device_thread: at2_login_device failed.",
1343 octstr_get_cstr(privdata->name));
1344 reconnecting = 1;
1345 continue;
1346 }
1347
1348 if (privdata->max_error_count > 0 && error_count > privdata->max_error_count
1349 && privdata->modem != NULL && privdata->modem->reset_string != NULL) {
1350 error_count = 0;
1351 if (at2_send_modem_command(privdata,
1352 octstr_get_cstr(privdata->modem->reset_string), 0, 0) != 0) {
1353 error(0, "AT2[%s]: Reset of modem failed.", octstr_get_cstr(privdata->name));
1354 at2_close_device(privdata);
1355 reconnecting = 1;
1356 continue;
1357 } else {
1358 info(0, "AT2[%s]: Modem reseted.", octstr_get_cstr(privdata->name));
1359 }
1360 }
1361
1362 if (at2_init_device(privdata) != 0) {
1363 error(0, "AT2[%s]: Initialization of device failed. Attempt #%d on %ld max.", octstr_get_cstr(privdata->name),
1364 error_count, privdata->max_error_count);
1365 at2_close_device(privdata);
1366 error_count++;
1367 reconnecting = 1;
1368 continue;
1369 } else
1370 error_count = 0;
1371
1372 /* If we got here, then the device is opened */
1373 break;
1374 } while (!privdata->shutdown);
1375
1376 mutex_lock(conn->flow_mutex);
1377 conn->status = SMSCCONN_ACTIVE;
1378 conn->connect_time = time(NULL);
1379 mutex_unlock(conn->flow_mutex);
1380 bb_smscconn_connected(conn);
1381
1382 idle_timeout = 0;
1383 while (!privdata->shutdown) {
1384 at2_wait_modem_command(privdata, 1, 0, NULL);
1385
1386 /* read error, so re-connect */
1387 if (privdata->fd == -1) {
1388 at2_close_device(privdata);
1389 reconnecting = 1;
1390 goto reconnect;
1391 }
1392
1393 while (gwlist_len(privdata->pending_incoming_messages) > 0) {
1394 at2_read_pending_incoming_messages(privdata);
1395 }
1396
1397 if (privdata->keepalive &&
1398 idle_timeout + privdata->keepalive < time(NULL)) {
1399 if (at2_send_modem_command(privdata,
1400 octstr_get_cstr(privdata->modem->keepalive_cmd), 5, 0) < 0) {
1401 at2_close_device(privdata);
1402 reconnecting = 1;
1403 goto reconnect;
1404 }
1405 idle_timeout = time(NULL);
1406 }
1407
1408 if (privdata->sms_memory_poll_interval &&
1409 memory_poll_timeout + privdata->sms_memory_poll_interval < time(NULL)) {
1410 if (at2_read_sms_memory(privdata) == -1) {
1411 at2_close_device(privdata);
1412 reconnecting = 1;
1413 goto reconnect;
1414 }
1415 memory_poll_timeout = time(NULL);
1416 }
1417
1418 if (gw_prioqueue_len(privdata->outgoing_queue) > 0) {
1419 at2_send_messages(privdata);
1420 idle_timeout = time(NULL);
1421 }
1422 }
1423 at2_close_device(privdata);
1424 mutex_lock(conn->flow_mutex);
1425 conn->status = SMSCCONN_DISCONNECTED;
1426 mutex_unlock(conn->flow_mutex);
1427 /* maybe some cleanup here? */
1428 at2_destroy_modem(privdata->modem);
1429 octstr_destroy(privdata->device);
1430 octstr_destroy(privdata->ilb);
1431 octstr_destroy(privdata->lines);
1432 octstr_destroy(privdata->pin);
1433 octstr_destroy(privdata->validityperiod);
1434 octstr_destroy(privdata->my_number);
1435 octstr_destroy(privdata->sms_center);
1436 octstr_destroy(privdata->name);
1437 octstr_destroy(privdata->configfile);
1438 octstr_destroy(privdata->username);
1439 octstr_destroy(privdata->password);
1440 octstr_destroy(privdata->rawtcp_host);
1441 gw_prioqueue_destroy(privdata->outgoing_queue, NULL);
1442 gwlist_destroy(privdata->pending_incoming_messages, octstr_destroy_item);
1443 load_destroy(privdata->load);
1444 gw_free(conn->data);
1445 conn->data = NULL;
1446 mutex_lock(conn->flow_mutex);
1447 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
1448 conn->status = SMSCCONN_DEAD;
1449 mutex_unlock(conn->flow_mutex);
1450 bb_smscconn_killed();
1451 }
1452
1453
at2_shutdown_cb(SMSCConn * conn,int finish_sending)1454 static int at2_shutdown_cb(SMSCConn *conn, int finish_sending)
1455 {
1456 PrivAT2data *privdata = conn->data;
1457
1458 debug("bb.sms", 0, "AT2[%s]: Shutting down SMSCConn, %s",
1459 octstr_get_cstr(privdata->name),
1460 finish_sending ? "slow" : "instant");
1461
1462 /*
1463 * Documentation claims this would have been done by smscconn.c,
1464 * but isn't when this code is being written.
1465 */
1466 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
1467 privdata->shutdown = 1;
1468 /*
1469 * Separate from why_killed to avoid locking, as
1470 * why_killed may be changed from outside?
1471 */
1472 if (finish_sending == 0) {
1473 Msg *msg;
1474 while ((msg = gw_prioqueue_remove(privdata->outgoing_queue)) != NULL) {
1475 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
1476 }
1477 }
1478 gwthread_wakeup(privdata->device_thread);
1479 return 0;
1480
1481 }
1482
1483
at2_queued_cb(SMSCConn * conn)1484 static long at2_queued_cb(SMSCConn *conn)
1485 {
1486 PrivAT2data *privdata;
1487
1488 privdata = conn->data;
1489 conn->load = (privdata ? (conn->status != SMSCCONN_DEAD ?
1490 gw_prioqueue_len(privdata->outgoing_queue) : 0) : 0);
1491 return conn->load;
1492 }
1493
1494
at2_start_cb(SMSCConn * conn)1495 static void at2_start_cb(SMSCConn *conn)
1496 {
1497 PrivAT2data *privdata;
1498
1499 privdata = conn->data;
1500 if (conn->status == SMSCCONN_DISCONNECTED)
1501 conn->status = SMSCCONN_ACTIVE;
1502
1503 /* in case there are messages in the buffer already */
1504 gwthread_wakeup(privdata->device_thread);
1505 debug("smsc.at2", 0, "AT2[%s]: start called", octstr_get_cstr(privdata->name));
1506 }
1507
at2_add_msg_cb(SMSCConn * conn,Msg * sms)1508 static int at2_add_msg_cb(SMSCConn *conn, Msg *sms)
1509 {
1510 PrivAT2data *privdata;
1511
1512 privdata = conn->data;
1513 gw_prioqueue_produce(privdata->outgoing_queue, msg_duplicate(sms));
1514 gwthread_wakeup(privdata->device_thread);
1515 return 0;
1516 }
1517
1518
smsc_at2_create(SMSCConn * conn,CfgGroup * cfg)1519 int smsc_at2_create(SMSCConn *conn, CfgGroup *cfg)
1520 {
1521 PrivAT2data *privdata;
1522 Octstr *modem_type_string;
1523 long portno; /* has to be long because of cfg_get_integer */
1524
1525 privdata = gw_malloc(sizeof(PrivAT2data));
1526 memset(privdata, 0, sizeof(PrivAT2data));
1527 privdata->outgoing_queue = gw_prioqueue_create(sms_priority_compare);
1528 privdata->pending_incoming_messages = gwlist_create();
1529
1530 privdata->configfile = cfg_get_configfile(cfg);
1531
1532 privdata->device = cfg_get(cfg, octstr_imm("device"));
1533 if (privdata->device == NULL) {
1534 error(0, "AT2[-]: 'device' missing in at2 configuration.");
1535 goto error;
1536 }
1537
1538 if (octstr_str_compare(privdata->device, "rawtcp") == 0) {
1539 privdata->rawtcp_host = cfg_get(cfg, octstr_imm("host"));
1540 if (privdata->rawtcp_host == NULL) {
1541 error(0, "AT2[-]: 'host' missing in at2 rawtcp configuration.");
1542 goto error;
1543 }
1544 if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) {
1545 error(0, "AT2[-]: 'port' missing in at2 rawtcp configuration.");
1546 goto error;
1547 }
1548 privdata->rawtcp_port = portno;
1549 privdata->is_serial = 0;
1550 privdata->use_telnet = 0;
1551 } else if (octstr_str_compare(privdata->device, "telnet") == 0) {
1552 privdata->rawtcp_host = cfg_get(cfg, octstr_imm("host"));
1553 if (privdata->rawtcp_host == NULL) {
1554 error(0, "AT2[-]: 'host' missing in at2 telnet configuration.");
1555 goto error;
1556 }
1557 if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) {
1558 error(0, "AT2[-]: 'port' missing in at2 telnet configuration.");
1559 goto error;
1560 }
1561 privdata->rawtcp_port = portno;
1562 privdata->is_serial = 0;
1563 privdata->use_telnet = 1;
1564 } else {
1565 privdata->is_serial = 1;
1566 privdata->use_telnet = 0;
1567 }
1568
1569 privdata->name = cfg_get(cfg, octstr_imm("smsc-id"));
1570 if (privdata->name == NULL) {
1571 privdata->name = octstr_duplicate(privdata->device);
1572 }
1573
1574 privdata->speed = 0;
1575 cfg_get_integer(&privdata->speed, cfg, octstr_imm("speed"));
1576
1577 privdata->keepalive = 0;
1578 cfg_get_integer(&privdata->keepalive, cfg, octstr_imm("keepalive"));
1579
1580 cfg_get_bool(&privdata->sms_memory_poll_interval, cfg, octstr_imm("sim-buffering"));
1581 if (privdata->sms_memory_poll_interval) {
1582 if (privdata->keepalive)
1583 privdata->sms_memory_poll_interval = privdata->keepalive;
1584 else
1585 privdata->sms_memory_poll_interval = AT2_DEFAULT_SMS_POLL_INTERVAL;
1586 }
1587
1588 privdata->my_number = cfg_get(cfg, octstr_imm("my-number"));
1589 privdata->sms_center = cfg_get(cfg, octstr_imm("sms-center"));
1590 privdata->username = cfg_get(cfg, octstr_imm("smsc-username"));
1591 privdata->password = cfg_get(cfg, octstr_imm("smsc-password"));
1592 privdata->login_prompt = cfg_get(cfg, octstr_imm("login-prompt"));
1593 privdata->password_prompt = cfg_get(cfg, octstr_imm("password-prompt"));
1594 modem_type_string = cfg_get(cfg, octstr_imm("modemtype"));
1595
1596 privdata->modem = NULL;
1597
1598 if (modem_type_string != NULL) {
1599 if (octstr_compare(modem_type_string, octstr_imm("auto")) == 0 ||
1600 octstr_compare(modem_type_string, octstr_imm("autodetect")) == 0)
1601 O_DESTROY(modem_type_string);
1602 }
1603
1604 if (octstr_len(modem_type_string) == 0) {
1605 info(0, "AT2[%s]: configuration doesn't show modemtype. will autodetect",
1606 octstr_get_cstr(privdata->name));
1607 } else {
1608 info(0, "AT2[%s]: configuration shows modemtype <%s>",
1609 octstr_get_cstr(privdata->name),
1610 octstr_get_cstr(modem_type_string));
1611 privdata->modem = at2_read_modems(privdata, privdata->configfile,
1612 modem_type_string, 0);
1613 if (privdata->modem == NULL) {
1614 info(0, "AT2[%s]: modemtype not found, revert to autodetect",
1615 octstr_get_cstr(privdata->name));
1616 } else {
1617 info(0, "AT2[%s]: read modem definition for <%s>",
1618 octstr_get_cstr(privdata->name),
1619 octstr_get_cstr(privdata->modem->name));
1620 }
1621 O_DESTROY(modem_type_string);
1622 }
1623
1624 privdata->ilb = octstr_create("");
1625 privdata->fd = -1;
1626 privdata->lines = NULL;
1627 privdata->pin = cfg_get(cfg, octstr_imm("pin"));
1628 privdata->pin_ready = 0;
1629 privdata->conn = conn;
1630 privdata->phase2plus = 0;
1631 privdata->validityperiod = cfg_get(cfg, octstr_imm("validityperiod"));
1632 if (cfg_get_integer((long *) &privdata->max_error_count, cfg, octstr_imm("max-error-count")) == -1)
1633 privdata->max_error_count = -1;
1634
1635 privdata->load = load_create_real(0);
1636 load_add_interval(privdata->load, 1);
1637
1638 conn->data = privdata;
1639 conn->name = octstr_format("AT2[%s]", octstr_get_cstr(privdata->name));
1640 conn->status = SMSCCONN_CONNECTING;
1641 conn->connect_time = time(NULL);
1642
1643 privdata->shutdown = 0;
1644
1645 if ((privdata->device_thread = gwthread_create(at2_device_thread, conn)) == -1) {
1646 privdata->shutdown = 1;
1647 goto error;
1648 }
1649
1650 conn->shutdown = at2_shutdown_cb;
1651 conn->queued = at2_queued_cb;
1652 conn->start_conn = at2_start_cb;
1653 conn->send_msg = at2_add_msg_cb;
1654 return 0;
1655
1656 error:
1657 error(0, "AT2[%s]: Failed to create at2 smsc connection",
1658 octstr_len(privdata->name) ? octstr_get_cstr(privdata->name) : "");
1659 if (privdata != NULL) {
1660 gw_prioqueue_destroy(privdata->outgoing_queue, NULL);
1661 }
1662 gw_free(privdata);
1663 conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
1664 conn->status = SMSCCONN_DEAD;
1665 info(0, "AT2[%s]: exiting", octstr_get_cstr(privdata->name));
1666 return -1;
1667 }
1668
1669
at2_pdu_extract(PrivAT2data * privdata,Octstr ** pdu,Octstr * line,Octstr * smsc_number)1670 static int at2_pdu_extract(PrivAT2data *privdata, Octstr **pdu, Octstr *line, Octstr *smsc_number)
1671 {
1672 Octstr *buffer;
1673 long len = 0;
1674 int pos = 0;
1675 int tmp;
1676 Octstr *numtmp;
1677 Octstr *tmp2;
1678
1679 buffer = octstr_duplicate(line);
1680 /* find the beginning of a message from the modem*/
1681
1682 if ((pos = octstr_search(buffer, octstr_imm("+CDS:"), 0)) != -1)
1683 pos += 5;
1684 else {
1685 if ((pos = octstr_search(buffer, octstr_imm("+CMT:"), 0)) != -1)
1686 pos += 5;
1687 else if ((pos = octstr_search(buffer, octstr_imm("+CMGR:"), 0)) != -1) {
1688 /* skip status field in +CMGR response */
1689 if ((pos = octstr_search(buffer, octstr_imm(","), pos + 6)) != -1)
1690 pos++;
1691 else
1692 goto nomsg;
1693 } else
1694 goto nomsg;
1695
1696 /* skip the next comma in CMGR and CMT responses */
1697 tmp = octstr_search(buffer, octstr_imm(","), pos);
1698 if (!privdata->modem->broken && tmp == -1)
1699 goto nomsg;
1700 if (tmp != -1)
1701 pos = tmp + 1;
1702 }
1703
1704 /* read the message length */
1705 pos = octstr_parse_long(&len, buffer, pos, 10);
1706 if (pos == -1 || len == 0)
1707 goto nomsg;
1708
1709 /* skip the spaces and line return */
1710 while (isspace(octstr_get_char(buffer, pos)))
1711 pos++;
1712
1713 octstr_truncate(smsc_number,0);
1714
1715 /* skip the SMSC address on some modem types */
1716 if (!privdata->modem->no_smsc) {
1717 tmp = at2_hexchar(octstr_get_char(buffer, pos)) * 16
1718 + at2_hexchar(octstr_get_char(buffer, pos + 1));
1719 if (tmp < 0)
1720 goto nomsg;
1721
1722 numtmp = octstr_create_from_data(octstr_get_cstr(buffer)+pos+2,tmp * 2); /* we now have the hexchars of the SMSC in GSM encoding */
1723 octstr_hex_to_binary(numtmp);
1724 tmp2 = gsm2number(numtmp);
1725 debug("bb.smsc.at2", 0, "AT2[%s]: received message from SMSC: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(tmp2));
1726 octstr_destroy(numtmp);
1727 octstr_append(smsc_number,tmp2);
1728 octstr_destroy(tmp2);
1729 pos += 2 + tmp * 2;
1730 }
1731
1732 /* check if the buffer is long enough to contain the full message */
1733 if (!privdata->modem->broken && octstr_len(buffer) < len * 2 + pos)
1734 goto nomsg;
1735
1736 if (privdata->modem->broken && octstr_len(buffer) < len * 2)
1737 goto nomsg;
1738
1739 /* copy the PDU then remove it from the input buffer*/
1740 *pdu = octstr_copy(buffer, pos, len * 2);
1741
1742 octstr_destroy(buffer);
1743 return 1;
1744
1745 nomsg:
1746 octstr_destroy(buffer);
1747 return 0;
1748 }
1749
nibble2hex(unsigned char b)1750 static unsigned char nibble2hex(unsigned char b)
1751 {
1752 if(b < 0x0A)
1753 return '0'+ b;
1754 else
1755 return 'A'+ b - 0x0A;
1756 }
1757
gsm2number(Octstr * pdu)1758 static Octstr *gsm2number(Octstr *pdu)
1759 {
1760 Octstr *tmp = NULL;
1761 unsigned char c;
1762 unsigned char a;
1763 unsigned char b;
1764 int ton;
1765 int len;
1766 int pos;
1767
1768 pos=0;
1769 len = octstr_len(pdu);
1770 if(len<= 0)
1771 return octstr_create("");
1772
1773 ton = octstr_get_char(pdu,pos++);
1774 ton = (ton >> 4) & 0x07;
1775
1776 switch(ton)
1777 {
1778 case 0: /* unknown */
1779 tmp = octstr_create("");
1780 break;
1781 case 1: /* international */
1782 tmp = octstr_create("+");
1783 break;
1784 case 2: /* national */
1785 tmp = octstr_create("0");
1786 break;
1787 case 3: /* network-specific */
1788 default:
1789 tmp = octstr_create("");
1790 break;
1791 }
1792 while(--len > 0)
1793 {
1794 c = octstr_get_char(pdu,pos++);
1795 a = c & 0x0F;
1796 b = ((c & 0xF0) >> 4);
1797
1798 if((b == 0x0F) && (len < 2))
1799 {
1800 octstr_append_char(tmp, nibble2hex(a));
1801 }
1802 else
1803 {
1804 octstr_append_char(tmp, nibble2hex(a));
1805 octstr_append_char(tmp, nibble2hex(b));
1806 }
1807 }
1808 return tmp;
1809 }
1810
at2_hexchar(int hexc)1811 static int at2_hexchar(int hexc)
1812 {
1813 hexc = toupper(hexc) - 48;
1814 return (hexc > 9) ? hexc - 7 : hexc;
1815 }
1816
1817
at2_pdu_decode(Octstr * data,PrivAT2data * privdata)1818 static Msg *at2_pdu_decode(Octstr *data, PrivAT2data *privdata)
1819 {
1820 int type;
1821 Msg *msg = NULL;
1822
1823 /* Get the PDU type */
1824 type = octstr_get_char(data, 1) & 3;
1825
1826 switch (type) {
1827
1828 case AT_DELIVER_SM:
1829 msg = at2_pdu_decode_deliver_sm(data, privdata);
1830 break;
1831 case AT_STATUS_REPORT_SM:
1832 msg = at2_pdu_decode_report_sm(data, privdata);
1833 break;
1834
1835 /* Add other message types here: */
1836 }
1837
1838 return msg;
1839 }
1840
1841
at2_pdu_decode_deliver_sm(Octstr * data,PrivAT2data * privdata)1842 static Msg *at2_pdu_decode_deliver_sm(Octstr *data, PrivAT2data *privdata)
1843 {
1844 int len, pos, i, ntype;
1845 int udhi, dcs, udhlen, pid;
1846 Octstr *origin = NULL;
1847 Octstr *udh = NULL;
1848 Octstr *text = NULL, *tmpstr;
1849 Octstr *pdu = NULL;
1850 Msg *message = NULL;
1851 struct universaltime mtime; /* time structure */
1852 long stime; /* time in seconds */
1853 int timezone; /* timezone in 15 minutes jumps from GMT */
1854
1855 /*
1856 * Note: some parts of the PDU are not decoded because they are
1857 * not needed for the Msg type.
1858 */
1859
1860 /* convert the pdu to binary format for ease of processing */
1861 pdu = at2_convertpdu(data);
1862
1863 /* UDH Indicator */
1864 udhi = (octstr_get_char(pdu, 0) & 64) >> 6;
1865
1866 /* originating address */
1867 len = octstr_get_char(pdu, 1);
1868 if (len > 20) /* maximum valid number of semi-octets in Address-Value field */
1869 goto msg_error;
1870 ntype = octstr_get_char(pdu, 2);
1871
1872 pos = 3;
1873 if ((ntype & 0xD0) == 0xD0) {
1874 /* Alphanumeric sender */
1875 origin = octstr_create("");
1876 tmpstr = octstr_copy(pdu, 3, len);
1877 at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, origin, 0);
1878 octstr_destroy(tmpstr);
1879 debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric sender <%s>",
1880 octstr_get_cstr(privdata->name), octstr_get_cstr(origin));
1881 pos += (len + 1) / 2;
1882 } else {
1883 origin = octstr_create("");
1884 if ((ntype & 0x90) == 0x90) {
1885 /* International number */
1886 octstr_append_char(origin, '+');
1887 }
1888 for (i = 0; i < len; i += 2, pos++) {
1889 octstr_append_char(origin, (octstr_get_char(pdu, pos) & 15) + 48);
1890 if (i + 1 < len)
1891 octstr_append_char(origin, (octstr_get_char(pdu, pos) >> 4) + 48);
1892 }
1893 debug("bb.smsc.at2", 0, "AT2[%s]: Numeric sender %s <%s>",
1894 octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),
1895 octstr_get_cstr(origin));
1896 }
1897
1898 if (pos > octstr_len(pdu))
1899 goto msg_error;
1900
1901 /* PID */
1902 pid = octstr_get_char(pdu, pos);
1903 pos++;
1904
1905 /* DCS */
1906 dcs = octstr_get_char(pdu, pos);
1907 pos++;
1908
1909 /* get the timestamp */
1910 mtime.year = swap_nibbles(octstr_get_char(pdu, pos));
1911 pos++;
1912 mtime.year += (mtime.year < 70 ? 2000 : 1900);
1913 mtime.month = swap_nibbles(octstr_get_char(pdu, pos));
1914 mtime.month--;
1915 pos++;
1916 mtime.day = swap_nibbles(octstr_get_char(pdu, pos));
1917 pos++;
1918 mtime.hour = swap_nibbles(octstr_get_char(pdu, pos));
1919 pos++;
1920 mtime.minute = swap_nibbles(octstr_get_char(pdu, pos));
1921 pos++;
1922 mtime.second = swap_nibbles(octstr_get_char(pdu, pos));
1923 pos++;
1924
1925 /*
1926 * time zone:
1927 *
1928 * time zone is "swapped nibble", with the MSB as the sign (1 is negative).
1929 */
1930 timezone = swap_nibbles(octstr_get_char(pdu, pos));
1931 pos++;
1932 timezone = ((timezone >> 7) ? -1 : 1) * (timezone & 127);
1933 /*
1934 * Ok, that was the time zone as read from the PDU. Now how to interpert it?
1935 * All the handsets I tested send the timestamp of their local time and the
1936 * timezone as GMT+0. I assume that the timestamp is the handset's local time,
1937 * so we need to apply the timezone in reverse to get GM time:
1938 */
1939
1940 /*
1941 * time in PDU is handset's local time and timezone is handset's time zone
1942 * difference from GMT
1943 */
1944 mtime.hour -= timezone / 4;
1945 mtime.minute -= 15 * (timezone % 4);
1946
1947 stime = date_convert_universal(&mtime);
1948
1949 /* get data length
1950 * TODO: Is it allowed to have length = 0 ??? (alex)
1951 */
1952 len = octstr_get_char(pdu, pos);
1953 pos++;
1954
1955 debug("bb.smsc.at2", 0, "AT2[%s]: User data length read as (%d)",
1956 octstr_get_cstr(privdata->name), len);
1957
1958 /* if there is a UDH */
1959 udhlen = 0;
1960 if (udhi && len > 0) {
1961 udhlen = octstr_get_char(pdu, pos);
1962 pos++;
1963 if (udhlen + 1 > len)
1964 goto msg_error;
1965 udh = octstr_copy(pdu, pos-1, udhlen+1);
1966 pos += udhlen;
1967 len -= udhlen + 1;
1968 } else if (len <= 0) /* len < 0 is impossible, but sure is sure */
1969 udhi = 0;
1970
1971 debug("bb.smsc.at2", 0, "AT2[%s]: Udh decoding done len=%d udhi=%d udhlen=%d udh='%s'",
1972 octstr_get_cstr(privdata->name), len, udhi, udhlen, (udh ? octstr_get_cstr(udh) : ""));
1973
1974 if (pos > octstr_len(pdu) || len < 0)
1975 goto msg_error;
1976
1977 /* build the message */
1978 message = msg_create(sms);
1979 if (!dcs_to_fields(&message, dcs)) {
1980 /* TODO Should we reject this message? */
1981 error(0, "AT2[%s]: Invalid DCS (0x%02x)", octstr_get_cstr(privdata->name), dcs);
1982 dcs_to_fields(&message, 0);
1983 }
1984
1985 message->sms.pid = pid;
1986
1987 /* deal with the user data -- 7 or 8 bit encoded */
1988 tmpstr = octstr_copy(pdu, pos, len);
1989 if (message->sms.coding == DC_8BIT || message->sms.coding == DC_UCS2) {
1990 text = octstr_duplicate(tmpstr);
1991 } else {
1992 int offset = 0;
1993 text = octstr_create("");
1994 if (udhi && message->sms.coding == DC_7BIT) {
1995 int nbits;
1996 nbits = (udhlen + 1) * 8;
1997 /* fill bits for UDH to septet boundary */
1998 offset = (((nbits / 7) + 1) * 7 - nbits) % 7;
1999 /*
2000 * Fix length because UDH data length is determined
2001 * in septets if we are in GSM coding, otherwise it's in octets. Adding 6
2002 * will ensure that for an octet length of 0, we get septet length 0,
2003 * and for octet length 1 we get septet length 2.
2004 */
2005 len = len + udhlen + 1 - (8 * (udhlen + 1) + 6) / 7;
2006 }
2007 at2_decode7bituncompressed(tmpstr, len, text, offset);
2008 }
2009
2010 message->sms.sender = origin;
2011 if (octstr_len(privdata->my_number)) {
2012 message->sms.receiver = octstr_duplicate(privdata->my_number);
2013 } else {
2014 /* Put a dummy address in the receiver for now (SMSC requires one) */
2015 message->sms.receiver = octstr_create_from_data("1234", 4);
2016 }
2017 if (udhi) {
2018 message->sms.udhdata = udh;
2019 }
2020 message->sms.msgdata = text;
2021 message->sms.time = stime;
2022
2023 /* cleanup */
2024 octstr_destroy(pdu);
2025 octstr_destroy(tmpstr);
2026
2027 return message;
2028
2029 msg_error:
2030 error(1, "AT2[%s]: Invalid DELIVER-SMS pdu!", octstr_get_cstr(privdata->name));
2031 O_DESTROY(udh);
2032 O_DESTROY(origin);
2033 O_DESTROY(text);
2034 O_DESTROY(pdu);
2035 return NULL;
2036 }
2037
2038
at2_pdu_decode_report_sm(Octstr * data,PrivAT2data * privdata)2039 static Msg *at2_pdu_decode_report_sm(Octstr *data, PrivAT2data *privdata)
2040 {
2041 Msg *dlrmsg = NULL;
2042 Octstr *pdu, *msg_id, *tmpstr = NULL, *receiver = NULL;
2043 int type, tp_mr, len, ntype, pos;
2044
2045 /*
2046 * parse the PDU.
2047 */
2048
2049 /* convert the pdu to binary format for ease of processing */
2050 pdu = at2_convertpdu(data);
2051
2052 /* Message reference */
2053 tp_mr = octstr_get_char(pdu, 1);
2054 msg_id = octstr_format("%d", tp_mr);
2055 debug("bb.smsc.at2", 0, "AT2[%s]: got STATUS-REPORT for message <%d>:",
2056 octstr_get_cstr(privdata->name), tp_mr);
2057
2058 /* reciver address */
2059 len = octstr_get_char(pdu, 2);
2060 ntype = octstr_get_char(pdu, 3);
2061
2062 pos = 4;
2063 if ((ntype & 0xD0) == 0xD0) {
2064 /* Alphanumeric sender */
2065 receiver = octstr_create("");
2066 tmpstr = octstr_copy(pdu, pos, (len + 1) / 2);
2067 at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, receiver, 0);
2068 octstr_destroy(tmpstr);
2069 debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric receiver <%s>",
2070 octstr_get_cstr(privdata->name), octstr_get_cstr(receiver));
2071 pos += (len + 1) / 2;
2072 } else {
2073 int i;
2074 receiver = octstr_create("");
2075 if ((ntype & 0x90) == 0x90) {
2076 /* International number */
2077 octstr_append_char(receiver, '+');
2078 }
2079 for (i = 0; i < len; i += 2, pos++) {
2080 octstr_append_char(receiver, (octstr_get_char(pdu, pos) & 15) + 48);
2081 if (i + 1 < len)
2082 octstr_append_char(receiver, (octstr_get_char(pdu, pos) >> 4) + 48);
2083 }
2084 debug("bb.smsc.at2", 0, "AT2[%s]: Numeric receiver %s <%s>",
2085 octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),
2086 octstr_get_cstr(receiver));
2087 }
2088
2089 pos += 14; /* skip time stamps for now */
2090
2091 if ((type = octstr_get_char(pdu, pos)) == -1 ) {
2092 error(1, "AT2[%s]: STATUS-REPORT pdu too short to have TP-Status field !",
2093 octstr_get_cstr(privdata->name));
2094 goto error;
2095 }
2096
2097 /* Check DLR type:
2098 * 3GPP TS 23.040 defines this a bit mapped field with lots of options
2099 * most of which are not really intersting to us, as we are only interested
2100 * in one of three conditions : failed, held in SC for delivery later, or delivered successfuly
2101 * and here's how I suggest to test it (read the 3GPP reference for further detailes) -
2102 * we'll test the 6th and 5th bits (7th bit when set making all other values 'reseved' so I want to test it).
2103 */
2104 type = type & 0xE0; /* filter out everything but the 7th, 6th and 5th bits */
2105 switch (type) {
2106 case 0x00:
2107 /* 0 0 : success class */
2108 type = DLR_SUCCESS;
2109 tmpstr = octstr_create("Success");
2110 break;
2111 case 0x20:
2112 /* 0 1 : buffered class (temporary error) */
2113 type = DLR_BUFFERED;
2114 tmpstr = octstr_create("Buffered");
2115 break;
2116 case 0x40:
2117 case 0x60:
2118 default:
2119 /* 1 0 : failed class */
2120 /* 1 1 : failed class (actually, temporary error but timed out) */
2121 /* and any other value (can't think of any) is considered failure */
2122 type = DLR_FAIL;
2123 tmpstr = octstr_create("Failed");
2124 break;
2125 }
2126 /* Actually, the above implementation is not correct, as the reference
2127 * says that implementations should consider any "reserved" values to be
2128 * "failure", but most reserved values fall into one of the three
2129 * categories. It will catch "reserved" values where the first 3 MSBits
2130 * are not set as "Success" which may not be correct. */
2131
2132 if ((dlrmsg = dlr_find(privdata->conn->id, msg_id, receiver, type, 0)) == NULL) {
2133 debug("bb.smsc.at2", 1, "AT2[%s]: Received delivery notification but can't find that ID in the DLR storage",
2134 octstr_get_cstr(privdata->name));
2135 goto error;
2136 }
2137
2138 /* Beware DLR URL is now in msg->sms.dlr_url given by dlr_find() */
2139 dlrmsg->sms.msgdata = octstr_duplicate(tmpstr);
2140
2141 error:
2142 O_DESTROY(tmpstr);
2143 O_DESTROY(pdu);
2144 O_DESTROY(receiver);
2145 O_DESTROY(msg_id);
2146 return dlrmsg;
2147 }
2148
at2_convertpdu(Octstr * pdutext)2149 static Octstr *at2_convertpdu(Octstr *pdutext)
2150 {
2151 Octstr *pdu;
2152 int i;
2153 int len = octstr_len(pdutext);
2154
2155 pdu = octstr_create("");
2156 for (i = 0; i < len; i += 2) {
2157 octstr_append_char(pdu, at2_hexchar(octstr_get_char(pdutext, i)) * 16
2158 + at2_hexchar(octstr_get_char(pdutext, i + 1)));
2159 }
2160 return pdu;
2161 }
2162
2163
2164 static int at2_rmask[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };
2165 static int at2_lmask[8] = { 0, 128, 192, 224, 240, 248, 252, 254 };
2166
at2_decode7bituncompressed(Octstr * input,int len,Octstr * decoded,int offset)2167 static void at2_decode7bituncompressed(Octstr *input, int len, Octstr *decoded, int offset)
2168 {
2169 unsigned char septet, octet, prevoctet;
2170 int i;
2171 int r = 1;
2172 int c = 7;
2173 int pos = 0;
2174
2175 /* Shift the buffer offset bits to the left */
2176 if (offset > 0) {
2177 unsigned char *ip;
2178 for (i = 0, ip = (unsigned char *)octstr_get_cstr(input); i < octstr_len(input); i++) {
2179 if (i == octstr_len(input) - 1)
2180 *ip = *ip >> offset;
2181 else
2182 *ip = (*ip >> offset) | (*(ip + 1) << (8 - offset));
2183 ip++;
2184 }
2185 }
2186 octet = octstr_get_char(input, pos);
2187 prevoctet = 0;
2188 for (i = 0; i < len; i++) {
2189 septet = ((octet & at2_rmask[c]) << (r - 1)) + prevoctet;
2190 octstr_append_char(decoded, septet);
2191
2192 prevoctet = (octet & at2_lmask[r]) >> c;
2193
2194 /* When r=7 we have a full character in prevoctet */
2195 if ((r == 7) && (i < len - 1)) {
2196 i++;
2197 octstr_append_char(decoded, prevoctet);
2198 prevoctet = 0;
2199 }
2200
2201 r = (r > 6) ? 1 : r + 1;
2202 c = (c < 2) ? 7 : c - 1;
2203
2204 pos++;
2205 octet = octstr_get_char(input, pos);
2206 }
2207 charset_gsm_to_utf8(decoded);
2208 }
2209
2210
at2_send_messages(PrivAT2data * privdata)2211 static void at2_send_messages(PrivAT2data *privdata)
2212 {
2213 Msg *msg;
2214
2215 if (privdata->modem->enable_mms && gw_prioqueue_len(privdata->outgoing_queue) > 1)
2216 at2_send_modem_command(privdata, "AT+CMMS=2", 0, 0);
2217
2218 if (privdata->conn->throughput > 0 && load_get(privdata->load, 0) >= privdata->conn->throughput) {
2219 debug("bb.sms.at2", 0, "AT2[%s]: throughput limit exceeded (load: %.02f, throughput: %.02f)",
2220 octstr_get_cstr(privdata->conn->id), load_get(privdata->load, 0), privdata->conn->throughput);
2221 } else {
2222 if ((msg = gw_prioqueue_remove(privdata->outgoing_queue))) {
2223 load_increase(privdata->load);
2224 at2_send_one_message(privdata, msg);
2225 }
2226 }
2227 }
2228
2229
at2_send_one_message(PrivAT2data * privdata,Msg * msg)2230 static void at2_send_one_message(PrivAT2data *privdata, Msg *msg)
2231 {
2232 char command[500];
2233 int ret = -1;
2234 char sc[3];
2235
2236 if (octstr_len(privdata->my_number)) {
2237 octstr_destroy(msg->sms.sender);
2238 msg->sms.sender = octstr_duplicate(privdata->my_number);
2239 }
2240
2241 /*
2242 * The standard says you should be prepending the PDU with 00 to indicate
2243 * to use the default SC. Some older modems dont expect this so it can be
2244 * disabled
2245 * NB: This extra padding is not counted in the CMGS byte count
2246 */
2247 sc[0] = '\0';
2248
2249 if (!privdata->modem->no_smsc)
2250 strcpy(sc, "00");
2251
2252 if (msg_type(msg) == sms) {
2253 Octstr *pdu;
2254 int msg_id = -1;
2255
2256 if ((pdu = at2_pdu_encode(msg, privdata)) == NULL) {
2257 error(2, "AT2[%s]: Error encoding PDU!",octstr_get_cstr(privdata->name));
2258 return;
2259 }
2260
2261 /*
2262 * send the initial command and then wait for >
2263 */
2264 sprintf(command, "AT+CMGS=%ld", octstr_len(pdu) / 2);
2265
2266 ret = at2_send_modem_command(privdata, command, 5, 1);
2267 debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
2268 octstr_get_cstr(privdata->name), ret);
2269
2270 if (ret == 1) {/* > only! */
2271
2272 /*
2273 * Ok the > has been see now so we can send the PDU now and a
2274 * control Z but no CR or LF
2275 *
2276 * We will handle the 'nokiaphone' types a bit differently, since
2277 * they have a generic error in accepting PDUs that are "too big".
2278 * Which means, PDU that are longer then 18 bytes get truncated by
2279 * the phone modems. We'll buffer the PDU output in a loop.
2280 * All other types will get handled as used to be.
2281 */
2282
2283 if (octstr_compare(privdata->modem->id, octstr_imm("nokiaphone")) != 0) {
2284 sprintf(command, "%s%s", sc, octstr_get_cstr(pdu));
2285 at2_write(privdata, command);
2286 at2_write_ctrlz(privdata);
2287 } else {
2288 /* include the CTRL-Z in the PDU string */
2289 sprintf(command, "%s%s%c", sc, octstr_get_cstr(pdu), 0x1A);
2290
2291 /* chop PDU into 18-byte-at-a-time pieces to prevent choking
2292 * of certain GSM Phones (e.g. Nokia 6310, 6230 etc.) */
2293 if (strlen(command) > 18) {
2294 char chop[20];
2295 int len = strlen(command);
2296 int pos = 0;
2297 int ret = 18;
2298
2299 while (pos < len) {
2300 if (pos + ret > len)
2301 ret = len - pos;
2302 memcpy(chop, command + pos, ret);
2303 pos += ret;
2304 chop[ret] = '\0';
2305 at2_write(privdata, chop);
2306 gwthread_sleep((double) 10/1000);
2307 }
2308 } else {
2309 at2_write(privdata, command);
2310 }
2311 }
2312
2313 /* wait 20 secs for modem command */
2314 ret = at2_wait_modem_command(privdata, 20, 0, &msg_id);
2315 debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
2316 octstr_get_cstr(privdata->name), ret);
2317
2318 if (ret != 0) {
2319 bb_smscconn_send_failed(privdata->conn, msg,
2320 SMSCCONN_FAILED_TEMPORARILY, octstr_create("ERROR"));
2321 } else {
2322 /* store DLR message if needed for SMSC generated delivery reports */
2323 if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
2324 if (msg_id == -1)
2325 error(0,"AT2[%s]: delivery notification requested, but I have no message ID!",
2326 octstr_get_cstr(privdata->name));
2327 else {
2328 Octstr *dlrmsgid = octstr_format("%d", msg_id);
2329
2330 dlr_add(privdata->conn->id, dlrmsgid, msg, 0);
2331
2332 O_DESTROY(dlrmsgid);
2333
2334 }
2335 }
2336
2337 bb_smscconn_sent(privdata->conn, msg, NULL);
2338 }
2339 } else {
2340 error(0,"AT2[%s]: Error received, notifying failure, "
2341 "sender: %s receiver: %s msgdata: %s udhdata: %s",
2342 octstr_get_cstr(privdata->name),
2343 octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver),
2344 octstr_get_cstr(msg->sms.msgdata), octstr_get_cstr(msg->sms.udhdata));
2345 bb_smscconn_send_failed(privdata->conn, msg,
2346 SMSCCONN_FAILED_TEMPORARILY, octstr_create("ERROR"));
2347 }
2348 O_DESTROY(pdu);
2349 }
2350 }
2351
2352
at2_pdu_encode(Msg * msg,PrivAT2data * privdata)2353 static Octstr *at2_pdu_encode(Msg *msg, PrivAT2data *privdata)
2354 {
2355 /*
2356 * Message coding is done as a binary octet string,
2357 * as per 3GPP TS 23.040 specification (GSM 03.40),
2358 */
2359 Octstr *pdu = NULL, *temp = NULL, *buffer = octstr_create("");
2360 int len, setvalidity = 0;
2361
2362 /*
2363 * message type SUBMIT , bit mapped :
2364 * bit7 .. bit0
2365 * TP-RP , TP-UDHI, TP-SRR, TP-VPF(4), TP-VPF(3), TP-RD, TP-MTI(1), TP-MTI(0)
2366 */
2367 octstr_append_char(buffer,
2368 ((msg->sms.rpi > 0 ? 1 : 0) << 7) /* TP-RP */
2369 | ((octstr_len(msg->sms.udhdata) ? 1 : 0) << 6) /* TP-UDHI */
2370 | ((DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask) ? 1 : 0) << 5) /* TP-SRR */
2371 | 16 /* TP-VP(Rel)*/
2372 | 1 /* TP-MTI: SUBMIT_SM */
2373 );
2374
2375 /* message reference (0 for now) */
2376 octstr_append_char(buffer, 0);
2377
2378 /* destination address */
2379 if ((temp = at2_format_address_field(msg->sms.receiver)) == NULL)
2380 goto error;
2381 octstr_append(buffer, temp);
2382 O_DESTROY(temp);
2383
2384 octstr_append_char(buffer, (msg->sms.pid == SMS_PARAM_UNDEFINED ? 0 : msg->sms.pid) ); /* protocol identifier */
2385 octstr_append_char(buffer, fields_to_dcs(msg, /* data coding scheme */
2386 (msg->sms.alt_dcs != SMS_PARAM_UNDEFINED ? msg->sms.alt_dcs : privdata->conn->alt_dcs)));
2387
2388 /*
2389 * Validity-Period (TP-VP)
2390 * see GSM 03.40 section 9.2.3.12
2391 * defaults to 24 hours = 167 if not set
2392 */
2393 if (msg->sms.validity != MSG_PARAM_UNDEFINED) {
2394 long val = (msg->sms.validity - time(NULL)) / 60;
2395 if (val > 635040)
2396 setvalidity = 255;
2397 if (val >= 50400 && val <= 635040)
2398 setvalidity = (val - 1) / 7 / 24 / 60 + 192 + 1;
2399 if (val > 43200 && val < 50400)
2400 setvalidity = 197;
2401 if (val >= 2880 && val <= 43200)
2402 setvalidity = (val - 1) / 24 / 60 + 166 + 1;
2403 if (val > 1440 && val < 2880)
2404 setvalidity = 168;
2405 if (val >= 750 && val <= 1440)
2406 setvalidity = (val - 720 - 1) / 30 + 143 + 1;
2407 if (val > 720 && val < 750)
2408 setvalidity = 144;
2409 if (val >= 5 && val <= 720)
2410 setvalidity = (val - 1) / 5 - 1 + 1;
2411 if (val < 5)
2412 setvalidity = 0;
2413 } else
2414 setvalidity = (privdata->validityperiod != NULL ?
2415 atoi(octstr_get_cstr(privdata->validityperiod)) : 167);
2416
2417 if (setvalidity >= 0 && setvalidity <= 143)
2418 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d minutes",
2419 octstr_get_cstr(privdata->name), (setvalidity + 1)*5);
2420 else if (setvalidity >= 144 && setvalidity <= 167)
2421 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %3.1f hours",
2422 octstr_get_cstr(privdata->name), ((float)(setvalidity - 143) / 2) + 12);
2423 else if (setvalidity >= 168 && setvalidity <= 196)
2424 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d days",
2425 octstr_get_cstr(privdata->name), (setvalidity - 166));
2426 else
2427 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d weeks",
2428 octstr_get_cstr(privdata->name), (setvalidity - 192));
2429 octstr_append_char(buffer, setvalidity);
2430
2431 /* user data length - include length of UDH if it exists */
2432 len = sms_msgdata_len(msg);
2433
2434 if (octstr_len(msg->sms.udhdata)) {
2435 if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
2436 len += octstr_len(msg->sms.udhdata);
2437 if (len > SMS_8BIT_MAX_LEN) { /* truncate user data to allow UDH to fit */
2438 octstr_delete(msg->sms.msgdata, SMS_8BIT_MAX_LEN - octstr_len(msg->sms.udhdata), 9999);
2439 len = SMS_8BIT_MAX_LEN;
2440 }
2441 } else {
2442 /*
2443 * The reason we branch here is because UDH data length is determined
2444 * in septets if we are in GSM coding, otherwise it's in octets. Adding 6
2445 * will ensure that for an octet length of 0, we get septet length 0,
2446 * and for octet length 1 we get septet length 2.
2447 */
2448 int temp_len;
2449 len += (temp_len = (((8 * octstr_len(msg->sms.udhdata)) + 6) / 7));
2450 if (len > SMS_7BIT_MAX_LEN) { /* truncate user data to allow UDH to fit */
2451 octstr_delete(msg->sms.msgdata, SMS_7BIT_MAX_LEN - temp_len, 9999);
2452 len = SMS_7BIT_MAX_LEN;
2453 }
2454 }
2455 }
2456
2457 octstr_append_char(buffer,len);
2458
2459 if (octstr_len(msg->sms.udhdata)) /* udh */
2460 octstr_append(buffer, msg->sms.udhdata);
2461
2462 /* user data */
2463 if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
2464 octstr_append(buffer, msg->sms.msgdata);
2465 } else {
2466 int offset = 0;
2467 Octstr *msgdata;
2468
2469 /*
2470 * calculate the number of fill bits needed to align
2471 * the 7bit encoded user data on septet boundry
2472 */
2473 if (octstr_len(msg->sms.udhdata)) { /* Have UDH */
2474 int nbits = octstr_len(msg->sms.udhdata) * 8; /* Includes UDH length byte */
2475 offset = (((nbits / 7) + 1) * 7 - nbits) % 7; /* Fill bits */
2476 }
2477
2478 msgdata = octstr_duplicate(msg->sms.msgdata);
2479 charset_utf8_to_gsm(msgdata);
2480
2481 if ((temp = at2_encode7bituncompressed(msgdata, offset)) != NULL)
2482 octstr_append(buffer, temp);
2483 O_DESTROY(temp);
2484 octstr_destroy(msgdata);
2485 }
2486
2487 /* convert PDU to HEX representation suitable for the AT2 command set */
2488 pdu = at2_encode8bituncompressed(buffer);
2489 O_DESTROY(buffer);
2490
2491 return pdu;
2492
2493 error:
2494 O_DESTROY(temp);
2495 O_DESTROY(buffer);
2496 O_DESTROY(pdu);
2497 return NULL;
2498 }
2499
2500
at2_encode7bituncompressed(Octstr * source,int offset)2501 static Octstr *at2_encode7bituncompressed(Octstr *source, int offset)
2502 {
2503 int LSBmask[8] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
2504 int MSBmask[8] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7C, 0x7E, 0x7F };
2505 int destRemain = (int)ceil((octstr_len(source) * 7.0 + offset) / 8.0);
2506 int i = (offset?8-offset:7), iStore = offset;
2507 int posS;
2508 Octstr *target = octstr_create("");
2509 int target_chr = 0, source_chr;
2510
2511 /* start packing the septet stream into an octet stream */
2512 for (posS = 0; (source_chr = octstr_get_char(source, posS++)) != -1;) {
2513 /* grab least significant bits from current septet and
2514 * store them packed to the right */
2515 target_chr |= (source_chr & LSBmask[i]) << iStore;
2516 /* store current byte if last command filled it */
2517 if (iStore != 0) {
2518 destRemain--;
2519 octstr_append_char(target, target_chr);
2520 target_chr = 0;
2521 }
2522 /* grab most significant bits from current septet and
2523 * store them packed to the left */
2524 target_chr |= (source_chr & MSBmask[7 - i]) >> (8 - iStore) % 8;
2525 /* advance target bit index by 7 (modulo 8 addition ) */
2526 iStore = (--iStore < 0 ? 7 : iStore);
2527 /* if just finished packing 8 septets (into 7 octets) don't advance mask index */
2528 if (iStore != 0)
2529 i = (++i > 7 ? 1 : i);
2530 }
2531
2532 /* don't forget to pack the leftovers ;-) */
2533 if (destRemain > 0)
2534 octstr_append_char(target, target_chr);
2535
2536 return target;
2537 }
2538
2539
at2_encode8bituncompressed(Octstr * input)2540 static Octstr *at2_encode8bituncompressed(Octstr *input)
2541 {
2542 int len, i;
2543 Octstr *out = octstr_create("");
2544
2545 len = octstr_len(input);
2546
2547 for (i = 0; i < len; i++) {
2548 /* each character is encoded in its hex representation (2 chars) */
2549 octstr_append_char(out, at2_numtext( (octstr_get_char(input, i) & 0xF0) >> 4));
2550 octstr_append_char(out, at2_numtext( (octstr_get_char(input, i) & 0x0F)));
2551 }
2552 return out;
2553 }
2554
2555
at2_numtext(int num)2556 static int at2_numtext(int num)
2557 {
2558 return (num > 9) ? (num + 55) : (num + 48);
2559 }
2560
2561
at2_detect_speed(PrivAT2data * privdata)2562 static int at2_detect_speed(PrivAT2data *privdata)
2563 {
2564 int i;
2565 int autospeeds[] = {
2566 #ifdef B115200
2567 115200,
2568 #endif
2569 #ifdef B57600
2570 57600,
2571 #endif
2572 38400, 19200, 9600 };
2573
2574 debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem speed. ",
2575 octstr_get_cstr(privdata->name));
2576
2577 for (i = 0; i < (sizeof(autospeeds) / sizeof(int)) && !privdata->shutdown; i++) {
2578 if(at2_test_speed(privdata, autospeeds[i]) == 0) {
2579 privdata->speed = autospeeds[i];
2580 break;
2581 }
2582 }
2583 if (privdata->speed == 0) {
2584 info(0, "AT2[%s]: cannot detect speed", octstr_get_cstr(privdata->name));
2585 return -1;
2586 }
2587 info(0, "AT2[%s]: detect speed is %ld", octstr_get_cstr(privdata->name), privdata->speed);
2588 return 0;
2589 }
2590
2591
at2_test_speed(PrivAT2data * privdata,long speed)2592 static int at2_test_speed(PrivAT2data *privdata, long speed)
2593 {
2594 int res;
2595
2596 if (at2_open_device(privdata) == -1)
2597 return -1;
2598
2599 at2_read_buffer(privdata, 0); /* give telnet escape sequences a chance */
2600 at2_set_speed(privdata, speed);
2601 /* send a return so the modem can detect the speed */
2602 res = at2_send_modem_command(privdata, "", 1, 0);
2603 res = at2_send_modem_command(privdata, "AT", 0, 0);
2604
2605 if (res != 0)
2606 res = at2_send_modem_command(privdata, "AT", 0, 0);
2607 if (res != 0)
2608 res = at2_send_modem_command(privdata, "AT", 0, 0);
2609
2610 at2_close_device(privdata);
2611
2612 return res;
2613 }
2614
2615
at2_detect_modem_type(PrivAT2data * privdata)2616 static int at2_detect_modem_type(PrivAT2data *privdata)
2617 {
2618 int res;
2619 ModemDef *modem;
2620 int i;
2621
2622 debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem type", octstr_get_cstr(privdata->name));
2623
2624 if (at2_open_device(privdata) == -1)
2625 return -1;
2626
2627 at2_set_speed(privdata, privdata->speed);
2628 /* sleep 10 ms in order to get device some time to accept speed */
2629 gwthread_sleep(0.1);
2630
2631 /* reset the modem */
2632 if (at2_send_modem_command(privdata, "ATZ", 0, 0) == -1) {
2633 error(0, "AT2[%s]: Wrong or no answer to ATZ", octstr_get_cstr(privdata->name));
2634 at2_close_device(privdata);
2635 return -1;
2636 }
2637
2638 /* check if the modem responded */
2639 if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
2640 error(0, "AT2[%s]: Wrong or no answer to AT. Trying again", octstr_get_cstr(privdata->name));
2641 if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
2642 error(0, "AT2[%s]: Second attempt to send AT failed", octstr_get_cstr(privdata->name));
2643 at2_close_device(privdata);
2644 return -1;
2645 }
2646 }
2647
2648 at2_flush_buffer(privdata);
2649
2650 /* send a return so the modem can detect the speed */
2651 res = at2_send_modem_command(privdata, "", 1, 0);
2652 res = at2_send_modem_command(privdata, "AT", 0, 0);
2653
2654 if (at2_send_modem_command(privdata, "AT&F", 0, 0) == -1) {
2655 at2_close_device(privdata);
2656 return -1;
2657 }
2658
2659 at2_flush_buffer(privdata);
2660
2661 if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
2662 at2_close_device(privdata);
2663 return -1;
2664 }
2665
2666 at2_flush_buffer(privdata);
2667
2668 if (at2_send_modem_command(privdata, "ATI", 0, 0) == -1) {
2669 at2_close_device(privdata);
2670 return -1;
2671 }
2672
2673 /* we try to detect the modem automatically */
2674 i = 1;
2675 while ((modem = at2_read_modems(privdata, privdata->configfile, NULL, i++)) != NULL) {
2676
2677 if (octstr_len(modem->detect_string) == 0) {
2678 at2_destroy_modem(modem);
2679 continue;
2680 }
2681
2682 /*
2683 debug("bb.smsc.at2",0,"AT2[%s]: searching for %s", octstr_get_cstr(privdata->name),
2684 octstr_get_cstr(modem->name));
2685 */
2686
2687 if (octstr_search(privdata->lines, modem->detect_string, 0) != -1) {
2688 if (octstr_len(modem->detect_string2) == 0) {
2689 debug("bb.smsc.at2", 0, "AT2[%s]: found string <%s>, using modem definition <%s>",
2690 octstr_get_cstr(privdata->name), octstr_get_cstr(modem->detect_string),
2691 octstr_get_cstr(modem->name));
2692 privdata->modem = modem;
2693 break;
2694 } else {
2695 if (octstr_search(privdata->lines, modem->detect_string2, 0) != -1) {
2696 debug("bb.smsc.at2", 0, "AT2[%s]: found string <%s> plus <%s>, using modem "
2697 "definition <%s>", octstr_get_cstr(privdata->name),
2698 octstr_get_cstr(modem->detect_string),
2699 octstr_get_cstr(modem->detect_string2),
2700 octstr_get_cstr(modem->name));
2701 privdata->modem = modem;
2702 break;
2703 }
2704 }
2705 } else {
2706 /* Destroy modem */
2707 at2_destroy_modem(modem);
2708 }
2709 }
2710
2711 if (privdata->modem == NULL) {
2712 debug("bb.smsc.at2", 0, "AT2[%s]: Cannot detect modem, using generic",
2713 octstr_get_cstr(privdata->name));
2714 if ((modem = at2_read_modems(privdata, privdata->configfile, octstr_imm("generic"), 0)) == NULL) {
2715 panic(0, "AT2[%s]: Cannot detect modem and generic not found",
2716 octstr_get_cstr(privdata->name));
2717 } else {
2718 privdata->modem = modem;
2719 }
2720 }
2721
2722 /* lets see if it supports GSM SMS 2+ mode */
2723 res = at2_send_modem_command(privdata, "AT+CSMS=?", 0, 0);
2724 if (res != 0)
2725 /* if it doesnt even understand the command, I'm sure it won't support it */
2726 privdata->phase2plus = 0;
2727 else {
2728 /* we have to take a part a string like +CSMS: (0,1,128) */
2729 Octstr *ts;
2730 int i;
2731 List *vals;
2732
2733 ts = privdata->lines;
2734 privdata->lines = NULL;
2735
2736 i = octstr_search_char(ts, '(', 0);
2737 if (i > 0) {
2738 octstr_delete(ts, 0, i + 1);
2739 }
2740 i = octstr_search_char(ts, ')', 0);
2741 if (i > 0) {
2742 octstr_truncate(ts, i);
2743 }
2744 vals = octstr_split(ts, octstr_imm(","));
2745 octstr_destroy(ts);
2746 ts = gwlist_search(vals, octstr_imm("1"), (void*) octstr_item_match);
2747 if (ts)
2748 privdata->phase2plus = 1;
2749 gwlist_destroy(vals, octstr_destroy_item);
2750 }
2751 if (privdata->phase2plus)
2752 info(0, "AT2[%s]: Phase 2+ is supported", octstr_get_cstr(privdata->name));
2753 at2_close_device(privdata);
2754 return 0;
2755 }
2756
2757
at2_read_modems(PrivAT2data * privdata,Octstr * file,Octstr * id,int idnumber)2758 static ModemDef *at2_read_modems(PrivAT2data *privdata, Octstr *file, Octstr *id, int idnumber)
2759 {
2760 Cfg *cfg;
2761 List *grplist;
2762 CfgGroup *grp;
2763 Octstr *p;
2764 ModemDef *modem;
2765 int i = 1;
2766
2767 /*
2768 * Use id and idnumber=0 or id=NULL and idnumber > 0
2769 */
2770 if (octstr_len(id) == 0 && idnumber == 0)
2771 return NULL;
2772
2773 if (idnumber == 0)
2774 debug("bb.smsc.at2", 0, "AT2[%s]: Reading modem definitions from <%s>",
2775 octstr_get_cstr(privdata->name), octstr_get_cstr(file));
2776 cfg = cfg_create(file);
2777
2778 if (cfg_read(cfg) == -1)
2779 panic(0, "Cannot read modem definition file");
2780
2781 grplist = cfg_get_multi_group(cfg, octstr_imm("modems"));
2782 if (idnumber == 0)
2783 debug("bb.smsc.at2", 0, "AT2[%s]: Found <%ld> modems in config",
2784 octstr_get_cstr(privdata->name), gwlist_len(grplist));
2785
2786 if (grplist == NULL)
2787 panic(0, "Where are the modem definitions ?!?!");
2788
2789 grp = NULL;
2790 while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
2791 p = cfg_get(grp, octstr_imm("id"));
2792 if (p == NULL) {
2793 info(0, "Modems group without id, bad");
2794 continue;
2795 }
2796 /* Check by id */
2797 if (octstr_len(id) != 0 && octstr_compare(p, id) == 0) {
2798 O_DESTROY(p);
2799 break;
2800 }
2801 /* Check by idnumber */
2802 if (octstr_len(id) == 0 && idnumber == i) {
2803 O_DESTROY(p);
2804 break;
2805 }
2806 O_DESTROY(p);
2807 i++;
2808 grp = NULL;
2809 }
2810 if (grplist != NULL)
2811 gwlist_destroy(grplist, NULL);
2812
2813 if (grp != NULL) {
2814 modem = gw_malloc(sizeof(ModemDef));
2815
2816 modem->id = cfg_get(grp, octstr_imm("id"));
2817
2818 modem->name = cfg_get(grp, octstr_imm("name"));
2819 if (modem->name == NULL)
2820 modem->name = octstr_duplicate(modem->id);
2821
2822 modem->detect_string = cfg_get(grp, octstr_imm("detect-string"));
2823 modem->detect_string2 = cfg_get(grp, octstr_imm("detect-string2"));
2824
2825 modem->init_string = cfg_get(grp, octstr_imm("init-string"));
2826 if (modem->init_string == NULL)
2827 modem->init_string = octstr_create("AT+CNMI=1,2,0,1,0");
2828
2829 modem->reset_string = cfg_get(grp, octstr_imm("reset-string"));
2830
2831 modem->speed = 9600;
2832 cfg_get_integer(&modem->speed, grp, octstr_imm("speed"));
2833
2834 cfg_get_bool(&modem->need_sleep, grp, octstr_imm("need-sleep"));
2835
2836 modem->enable_hwhs = cfg_get(grp, octstr_imm("enable-hwhs"));
2837 if (modem->enable_hwhs == NULL)
2838 modem->enable_hwhs = octstr_create("AT+IFC=2,2");
2839
2840 cfg_get_bool(&modem->no_pin, grp, octstr_imm("no-pin"));
2841
2842 cfg_get_bool(&modem->no_smsc, grp, octstr_imm("no-smsc"));
2843
2844 modem->sendline_sleep = 100;
2845 cfg_get_integer(&modem->sendline_sleep, grp, octstr_imm("sendline-sleep"));
2846
2847 modem->keepalive_cmd = cfg_get(grp, octstr_imm("keepalive-cmd"));
2848 if (modem->keepalive_cmd == NULL)
2849 modem->keepalive_cmd = octstr_create("AT");
2850
2851 modem->message_storage = cfg_get(grp, octstr_imm("message-storage"));
2852 if (cfg_get_integer(&modem->message_start, grp, octstr_imm("message-start")))
2853 modem->message_start = 1;
2854
2855 cfg_get_bool(&modem->enable_mms, grp, octstr_imm("enable-mms"));
2856 modem->hardware_flow_control = 1;
2857 cfg_get_bool(&modem->hardware_flow_control, grp, octstr_imm("hardware-flow-control"));
2858
2859 /*
2860 if (modem->message_storage == NULL)
2861 modem->message_storage = octstr_create("SM");
2862 */
2863
2864 cfg_get_bool(&modem->broken, grp, octstr_imm("broken"));
2865
2866 cfg_destroy(cfg);
2867 return modem;
2868
2869 } else {
2870 cfg_destroy(cfg);
2871 return NULL;
2872 }
2873 }
2874
2875
at2_destroy_modem(ModemDef * modem)2876 static void at2_destroy_modem(ModemDef *modem)
2877 {
2878 if (modem != NULL) {
2879 O_DESTROY(modem->id);
2880 O_DESTROY(modem->name);
2881 O_DESTROY(modem->detect_string);
2882 O_DESTROY(modem->detect_string2);
2883 O_DESTROY(modem->init_string);
2884 O_DESTROY(modem->enable_hwhs);
2885 O_DESTROY(modem->keepalive_cmd);
2886 O_DESTROY(modem->message_storage);
2887 O_DESTROY(modem->reset_string);
2888 gw_free(modem);
2889 }
2890 }
2891
2892
swap_nibbles(unsigned char byte)2893 static int swap_nibbles(unsigned char byte)
2894 {
2895 return ( ( byte & 15 ) * 10 ) + ( byte >> 4 );
2896 }
2897
2898
at2_format_address_field(Octstr * msisdn)2899 static Octstr *at2_format_address_field(Octstr *msisdn)
2900 {
2901 int ntype = PNT_UNKNOWN;
2902 Octstr *out = octstr_create("");
2903 Octstr *temp = octstr_duplicate(msisdn);
2904
2905 octstr_strip_blanks(temp);
2906 /*
2907 * Check for international numbers
2908 * number starting with '+' or '00' are international,
2909 * others are national.
2910 */
2911 if (strncmp(octstr_get_cstr(msisdn), "+", 1) == 0) {
2912 octstr_delete(temp, 0, 1);
2913 ntype = PNT_INTER; /* international */
2914 } else if (strncmp(octstr_get_cstr(msisdn), "00", 2) == 0) {
2915 octstr_delete(temp, 0, 2);
2916 ntype = PNT_INTER; /* international */
2917 }
2918
2919 /* address length */
2920 octstr_append_char(out, octstr_len(temp));
2921
2922 /* Type of address : bit mapped values */
2923 octstr_append_char(out, 0x80 /* Type-of-address prefix */ |
2924 0x01 /* Numbering-plan: MSISDN */ |
2925 (ntype == PNT_INTER ? 0x10 : 0x00) /* Type-of-number: International or National */
2926 );
2927
2928 /* grab the digits from the MSISDN and encode as swapped semi-octets */
2929 while (out != NULL && octstr_len(temp) > 0) {
2930 int digit1, digit2;
2931 /* get the first two digit */
2932 digit1 = octstr_get_char(temp,0) - 48;
2933 digit2 = octstr_get_char(temp,1) - '0';
2934 if (digit2 < 0)
2935 digit2 = 0x0F;
2936 if(digit1 >= 0 && digit1 < 16 && digit2 < 16) {
2937 octstr_append_char(out, (digit2 << 4) | digit1);
2938 }
2939 else {
2940 O_DESTROY(out);
2941 out = NULL;
2942 }
2943 octstr_delete(temp, 0, 2);
2944 }
2945
2946 O_DESTROY(temp);
2947 return out;
2948 }
2949
2950
at2_set_message_storage(PrivAT2data * privdata,Octstr * memory_name)2951 static int at2_set_message_storage(PrivAT2data *privdata, Octstr *memory_name)
2952 {
2953 Octstr *temp;
2954 int ret;
2955
2956 if (!memory_name || !privdata)
2957 return -1;
2958
2959 temp = octstr_format("AT+CPMS=\"%S\"", memory_name);
2960 ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
2961 octstr_destroy(temp);
2962
2963 return !ret ? 0 : -1;
2964 }
2965
2966
at2_error_string(int errcode)2967 static const char *at2_error_string(int errcode)
2968 {
2969 /*
2970 * +CMS ERRORS
2971 * 0...127 from GSM 04.11 Annex E-2 values
2972 * 128...255 from GSM 03.40 subclause 9.2.3.22
2973 * 300...511 from GSM 07.05 subclause 3.2.5
2974 * 512+ are manufacturer specific according to GSM 07.05 subclause 3.2.5
2975 *
2976 * +CME ERRORS
2977 * CME Error codes from GSM 07.07 section 9.2
2978 * GPP TS 27.007 /2/
2979 * GPRS-related errors - (GSM 04.08 cause codes)
2980 *
2981 */
2982 switch (errcode) {
2983 case 0:
2984 /*
2985 * Default the code to 0 then when you extract the value from the
2986 * modem response message and no code is found, 0 will result.
2987 */
2988 return "Modem returned ERROR but no error code - possibly unsupported or invalid command?";
2989 case 1:
2990 /*
2991 * This cause indicates that the destination requested by the Mobile
2992 * Station cannot be reached because, although the number is in a
2993 * valid format, it is not currently assigned (allocated).
2994 */
2995 return "Unassigned (unallocated) number (+CMS) or No connection to phone (+CME)";
2996 case 2:
2997 return "Phone-adaptor link reserved";
2998 case 3:
2999 /*
3000 * This can be a lot of things, depending upon the command, but in general
3001 * it relates to trying to do a command when no connection exists.
3002 */
3003 return "Operation not allowed at this time (connection may be required)";
3004 case 4:
3005 /*
3006 * This can be a lot of things, depending upon the command, but in general
3007 * it relates to invaid parameters being passed.
3008 */
3009 return "Operation / Parameter(s) not supported";
3010 case 5:
3011 return "PH-SIM PIN required";
3012 case 8:
3013 /*
3014 * This cause indicates that the MS has tried to send a mobile originating
3015 * short message when the MS's network operator or service provider has
3016 * forbidden such transactions.
3017 */
3018 return "Operator determined barring";
3019 case 10:
3020 /*
3021 * This cause indicates that the outgoing call barred service applies to
3022 * the short message service for the called destination.
3023 */
3024 return "Call barred (+CMS) or SIM not inserted or Card inserted is not a SIM (+CME)";
3025 case 11:
3026 return "SIM PIN required";
3027 case 12:
3028 return "SIM PUK required";
3029 case 13:
3030 return "SIM failure";
3031 case 14:
3032 return "SIM busy";
3033 case 15:
3034 return "SIM wrong";
3035 case 16:
3036 return "Incorrect password";
3037 case 17:
3038 /*
3039 * This cause is sent to the MS if the MSC cannot service an MS generated
3040 * request because of PLMN failures, e.g. problems in MAP.
3041 */
3042 return "Network failure (+CMS) or SIM PIN2 required (+CME)";
3043 case 18:
3044 return "SIM PUK2 required";
3045 case 20:
3046 return "Memory full";
3047 case 21:
3048 /*
3049 * This cause indicates that the equipment sending this cause does not
3050 * wish to accept this short message, although it could have accepted
3051 * the short message since the equipment sending this cause is neither
3052 * busy nor incompatible.
3053 */
3054 return "Short message transfer rejected (+CMS) or Invalid Index (+CME)";
3055 case 22:
3056 /*
3057 * This cause is sent if the service request cannot be actioned because
3058 * of congestion (e.g. no channel, facility busy/congested etc.). Or
3059 * this cause indicates that the mobile station cannot store the
3060 * incoming short message due to lack of storage capacity.
3061 */
3062 return "Congestion (+CMS) or Memory capacity exceeded (+CME)";
3063 case 23:
3064 return "Memory failure";
3065 case 24:
3066 return "Text string too long"; /* +CPBW, +CPIN, +CPIN2, +CLCK, +CPWD */
3067 case 25:
3068 return "Invalid characters in text string";
3069 case 26:
3070 return "Dial string too long"; /* +CPBW, ATD, +CCFC */
3071 case 27:
3072 /*
3073 * This cause indicates that the destination indicated by the Mobile
3074 * Station cannot be reached because the interface to the destination
3075 * is not functioning correctly. The term "not functioning correctly"
3076 * indicates that a signalling message was unable to be delivered to
3077 * the remote user; e.g., a physical layer or data link layer failure
3078 * at the remote user, user equipment off-line, etc.
3079 * Also means "Invalid characters in dial string" for +CPBW.
3080 */
3081 return "Destination out of service";
3082 case 28:
3083 /*
3084 * This cause indicates that the subscriber is not registered in the PLMN
3085 * (i.e. IMSI not known).
3086 */
3087 return "Unidentified subscriber";
3088 case 29:
3089 /*
3090 * This cause indicates that the facility requested by the Mobile Station
3091 * is not supported by the PLMN.
3092 */
3093 return "Facility rejected";
3094 case 30:
3095 /*
3096 * This cause indicates that the subscriber is not registered in the HLR
3097 * (i.e. IMSI or directory number is not allocated to a subscriber).
3098 * Also means "No network service" for +VTS, +COPS=?, +CLCK, +CCFC, +CCWA, +CUSD
3099 */
3100 return "Unknown subscriber (+CMS) or No network service (+CME)";
3101 case 31:
3102 return "Network timeout";
3103 case 32:
3104 return "Network not allowed - emergency calls only"; /* +COPS */
3105 case 38:
3106 /*
3107 * This cause indicates that the network is not functioning correctly and
3108 * that the condition is likely to last a relatively long period of time;
3109 * e.g., immediately reattempting the short message transfer is not
3110 * likely to be successful.
3111 */
3112 return "Network out of order";
3113 case 40:
3114 return "Network personal PIN required (Network lock)";
3115 case 41:
3116 /*
3117 * This cause indicates that the network is not functioning correctly and
3118 * that the condition is not likely to last a long period of time; e.g.,
3119 * the Mobile Station may wish to try another short message transfer
3120 * attempt almost immediately.
3121 */
3122 return "Temporary failure (+CMS) or Network personalization PUK required (+CME)";
3123 case 42:
3124 /*
3125 * This cause indicates that the short message service cannot be serviced
3126 * because of high traffic.
3127 */
3128 return "Congestion (+CMS) or Network subset personalization PIN required (+CME)";
3129 case 43:
3130 return "Network subset personalization PUK required";
3131 case 44:
3132 return "Service provider personalization PIN required";
3133 case 45:
3134 return "Service provider personalization PUK required";
3135 case 46:
3136 return "Corporate personalization PIN required";
3137 case 47:
3138 /*
3139 * This cause is used to report a resource unavailable event only when no
3140 * other cause applies.
3141 */
3142 return "Resources unavailable, unspecified (+CMS) or Corporate personalization PUK required (+CME)";
3143 case 50:
3144 /*
3145 * This cause indicates that the requested short message service could not
3146 * be provided by the network because the user has not completed the
3147 * necessary administrative arrangements with its supporting networks.
3148 */
3149 return "Requested facility not subscribed";
3150 case 69:
3151 /*
3152 * This cause indicates that the network is unable to provide the
3153 * requested short message service.
3154 */
3155 return "Requested facility not implemented";
3156 case 81:
3157 /*
3158 * This cause indicates that the equipment sending this cause has received
3159 * a message with a short message reference which is not currently in use
3160 * on the MS-network interface.
3161 */
3162 return "Invalid short message transfer reference value";
3163 case 95:
3164 /*
3165 * This cause is used to report an invalid message event only when no
3166 * other cause in the invalid message class applies.
3167 */
3168 return "Invalid message, unspecified";
3169 case 96:
3170 /*
3171 * This cause indicates that the equipment sending this cause has received
3172 * a message where a mandatory information element is missing and/or has
3173 * a content error (the two cases are indistinguishable).
3174 */
3175 return "Invalid mandatory information";
3176 case 97:
3177 /*
3178 * This cause indicates that the equipment sending this cause has received
3179 * a message with a message type it does not recognize either because this
3180 * is a message not defined or defined but not implemented by the
3181 * equipment sending this cause.
3182 */
3183 return "Message type non-existent or not implemented";
3184 case 98:
3185 /*
3186 * This cause indicates that the equipment sending this cause has received
3187 * a message such that the procedures do not indicate that this is a
3188 * permissible message to receive while in the short message transfer
3189 * state.
3190 */
3191 return "Message not compatible with short message protocol state";
3192 case 99:
3193 /*
3194 * This cause indicates that the equipment sending this cause has received
3195 * a message which includes information elements not recognized because
3196 * the information element identifier is not defined or it is defined
3197 * but not implemented by the equipment sending the cause. However, the
3198 * information element is not required to be present in the message in
3199 * order for the equipment sending the cause to process the message.
3200 */
3201 return "Information element non-existent or not implemented";
3202 case 100:
3203 return "Unknown";
3204 case 103:
3205 return "Illegal MS (#3)"; /* +CGATT */
3206 case 106:
3207 return "Illegal ME (#6)"; /* +CGATT */
3208 case 107:
3209 return "GPRS services not allowed (#7)"; /* +CGATT */
3210 case 111:
3211 /*
3212 * This cause is used to report a protocol error event only when no other
3213 * cause applies.
3214 * Also means "PLMN not allowed (#11)" for +CGATT
3215 */
3216 return "Protocol error, unspecified (+CMS) or PLMN not allowed (#11) (+CME)";
3217 case 112:
3218 return "Location area not allowed (#12)"; /* +CGATT */
3219 case 113:
3220 return "Roaming not allowed in this area (#13)"; /* +CGATT */
3221 case 127:
3222 /*
3223 * This cause indicates that there has been interworking with a network
3224 * which does not provide causes for actions it takes; thus, the precise
3225 * cause for a message which is being send cannot be ascertained.
3226 */
3227 return "Interworking, unspecified";
3228 case 128:
3229 return "Telematic interworking not supported";
3230 case 129:
3231 return "Short message Type 0 not supported";
3232 case 130:
3233 return "Cannot replace short message";
3234 case 132:
3235 return "Service option not supported (#32)"; /* +CGACT +CGDATA ATD*99 */
3236 case 133:
3237 return "Requested service option not subscribed (#33)"; /* +CGACT +CGDATA ATD*99 */
3238 case 134:
3239 return "Service option temporarily out of order (#34)"; /* +CGACT +CGDATA ATD*99 */
3240 case 143:
3241 return "Unspecified TP-PID error";
3242 case 144:
3243 return "Data coding scheme (alphabet) not supported";
3244 case 145:
3245 return "Message class not supported";
3246 case 148:
3247 return "Unspecified GPRS error";
3248 case 149:
3249 return "PDP authentication failure"; /* +CGACT +CGDATA ATD*99 */
3250 case 150:
3251 return "Invalid mobile class";
3252 case 159:
3253 return "Unspecified TP-DCS error";
3254 case 160:
3255 return "Command cannot be actioned";
3256 case 161:
3257 return "Unsupported command";
3258 case 175:
3259 return "Unspecified TP-Command error";
3260 case 176:
3261 return "TPDU not supported";
3262 case 192:
3263 return "SC busy";
3264 case 193:
3265 return "No SC subscription";
3266 case 194:
3267 return "SC system failure";
3268 case 195:
3269 return "Invalid SME address";
3270 case 196:
3271 return "Destination SME barred";
3272 case 197:
3273 return "SM Rejected-Duplicate SM";
3274 case 198:
3275 return "TP-VPF not supported";
3276 case 199:
3277 return "TP-VP not supported";
3278 case 208:
3279 return "DO SIM SMS storage full";
3280 case 209:
3281 return "No SMS storage capability in SIM";
3282 case 210:
3283 return "Error in MS";
3284 case 211:
3285 return "SIM Memory Capacity Exceeded";
3286 case 212:
3287 return "SIM Application Toolkit Busy";
3288 case 213:
3289 return "SIM data download error";
3290 case 255:
3291 return "Unspecified error cause";
3292 case 300:
3293 /*
3294 * Mobile equipment refers to the mobile device that communicates with
3295 * the wireless network. Usually it is a mobile phone or GSM/GPRS modem.
3296 * The SIM card is defined as a separate entity and is not part of mobile equipment.
3297 */
3298 return "Mobile equipment (ME) failure";
3299 case 301:
3300 /*
3301 * See +CMS error code 300 for the meaning of mobile equipment.
3302 */
3303 return "SMS service of mobile equipment (ME) is reserved";
3304 case 302:
3305 return "The operation to be done by the AT command is not allowed";
3306 case 303:
3307 return "The operation to be done by the AT command is not supported";
3308 case 304:
3309 return "One or more parameter values assigned to the AT command are invalid";
3310 case 305:
3311 return "One or more parameter values assigned to the AT command are invalid";
3312 case 310:
3313 return "There is no SIM card";
3314 case 311:
3315 /*
3316 * The AT command +CPIN (command name in text: Enter PIN)
3317 * can be used to send the PIN to the SIM card.
3318 */
3319 return "The SIM card requires a PIN to operate";
3320 case 312:
3321 /*
3322 * The AT command +CPIN (command name in text: Enter PIN)
3323 * can be used to send the PH-SIM PIN to the SIM card.
3324 */
3325 return "The SIM card requires a PH-SIM PIN to operate";
3326 case 313:
3327 return "SIM card failure";
3328 case 314:
3329 return "The SIM card is busy";
3330 case 315:
3331 return "The SIM card is wrong";
3332 case 316:
3333 /*
3334 * The AT command +CPIN (command name in text: Enter PIN)
3335 * can be used to send the PUK to the SIM card.
3336 */
3337 return "The SIM card requires a PUK to operate";
3338 case 317:
3339 return "The SIM card requires a PIN2 to operate";
3340 case 318:
3341 return "The SIM card requires a PUK2 to operate";
3342 case 320:
3343 return "Memory/message storage failure";
3344 case 321:
3345 return "The memory/message storage index assigned to the AT command is invalid";
3346 case 322:
3347 return "The memory/message storage is out of space";
3348 case 330:
3349 return "The SMS center (SMSC) address is unknown";
3350 case 331:
3351 return "No network service is available";
3352 case 332:
3353 return "Network timeout occurred";
3354 case 340:
3355 return "There is no need to send message ack by the AT command +CNMA";
3356 case 500:
3357 return "An unknown error occurred";
3358 case 512:
3359 /*
3360 * Resulting from +CMGS, +CMSS
3361 */
3362 return "User abort or MM establishment failure (SMS)";
3363 case 513:
3364 /*
3365 * Resulting from +CMGS, +CMSS
3366 */
3367 return "Lower layer falure (SMS)";
3368 case 514:
3369 /*
3370 * Resulting from +CMGS, +CMSS
3371 */
3372 return "CP error (SMS)";
3373 case 515:
3374 return "Please wait, service not available, init or command in progress";
3375 case 517:
3376 /*
3377 * Resulting from +STGI
3378 */
3379 return "SIM ToolKit facility not supported";
3380 case 518:
3381 /*
3382 * Resulting from +STGI
3383 */
3384 return "SIM ToolKit indication not received";
3385 case 519:
3386 /*
3387 * Resulting from +ECHO, +VIP
3388 */
3389 return "Reset the product to activate or change a new echo cancellation algorithm";
3390 case 520:
3391 /*
3392 * Resulting from +COPS=?
3393 */
3394 return "Automatic abort about get plmn list for an incoming call";
3395 case 526:
3396 /*
3397 * Resulting from +CLCK
3398 */
3399 return "PIN deactivation forbidden with this SIM card";
3400 case 527:
3401 /*
3402 * Resulting from +COPS
3403 */
3404 return "Please wait, RR or MM is busy. Retry your selection later";
3405 case 528:
3406 /*
3407 * Resulting from +COPS
3408 */
3409 return "Location update failure. Emergency calls only";
3410 case 529:
3411 /*
3412 * Resulting from +COPS
3413 */
3414 return "PLMN selection failure. Emergency calls only";
3415 case 531:
3416 /*
3417 * Resulting from +CMGS, +CMSS
3418 */
3419 return "SMS not sent: the <da> is not in FDN phonebook, and FDN lock is enabled";
3420 case 532:
3421 /*
3422 * Resulting from +WOPEN
3423 */
3424 return "The embedded application is activated so the objects flash are not erased";
3425 case 533:
3426 /*
3427 * Resulting from +ATD*99,+GACT,+CGDATA
3428 */
3429 return "Missing or unknown APN";
3430 default:
3431 return "Error number unknown. Ask google and add it";
3432 }
3433 }
3434
3435