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