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  * smpp_pdu.c - parse and generate SMPP PDUs
59  *
60  * Lars Wirzenius
61  * Alexander Malysh <amalysh@kannel.org>:
62  *     Extended optional parameters implementation.
63  */
64 
65 
66 #include <string.h>
67 #include "smpp_pdu.h"
68 
69 #define MIN_SMPP_PDU_LEN    (4*4)
70 /* old value was (1024). We need more because message_payload can be up to 64K octets*/
71 #define MAX_SMPP_PDU_LEN    (7424)
72 /* we use ; in the middle because ; is split char in smsc-id and can't be in the smsc-id */
73 #define DEFAULT_SMSC_ID "def;ault"
74 
75 struct smpp_tlv {
76     Octstr *name;
77     long tag;
78     long length;
79     enum { SMPP_TLV_OCTETS = 0, SMPP_TLV_NULTERMINATED = 1, SMPP_TLV_INTEGER = 2 } type;
80 };
81 
82 /* Dict(smsc_id, Dict(tag, tlv)) */
83 static Dict *tlvs_by_tag;
84 /* Dict(smsc_id, Dict(tag_name, tlv)) */
85 static Dict *tlvs_by_name;
86 static List *tlvs;
87 static int initialized;
88 
89 
smpp_tlv_destroy(struct smpp_tlv * tlv)90 static void smpp_tlv_destroy(struct smpp_tlv *tlv)
91 {
92     if (tlv == NULL)
93         return;
94     octstr_destroy(tlv->name);
95     gw_free(tlv);
96 }
97 
smpp_tlv_get_by_name(Octstr * smsc_id,Octstr * name)98 static struct smpp_tlv *smpp_tlv_get_by_name(Octstr *smsc_id, Octstr *name)
99 {
100     struct smpp_tlv *res = NULL;
101     Dict *tmp_dict;
102 
103     if (tlvs_by_name == NULL || name == NULL)
104         return NULL;
105 
106     if (smsc_id != NULL) {
107         tmp_dict = dict_get(tlvs_by_name, smsc_id);
108         if (tmp_dict != NULL)
109             res = dict_get(tmp_dict, name);
110     }
111     if (res == NULL) {
112         /* try default smsc_id */
113         smsc_id = octstr_imm(DEFAULT_SMSC_ID);
114         tmp_dict = dict_get(tlvs_by_name, smsc_id);
115         if (tmp_dict != NULL)
116             res = dict_get(tmp_dict, name);
117     }
118     return res;
119 }
120 
smpp_tlv_get_by_tag(Octstr * smsc_id,long tag)121 static struct smpp_tlv *smpp_tlv_get_by_tag(Octstr *smsc_id, long tag)
122 {
123     struct smpp_tlv *res = NULL;
124     Dict *tmp_dict;
125     Octstr *tmp;
126 
127     if (tlvs_by_tag == NULL)
128         return NULL;
129 
130     tmp = octstr_format("%ld", tag);
131 
132     if (smsc_id != NULL) {
133         tmp_dict = dict_get(tlvs_by_tag, smsc_id);
134         if (tmp_dict != NULL)
135             res = dict_get(tmp_dict, tmp);
136     }
137     if (res == NULL) {
138         /* try default smsc_id */
139         smsc_id = octstr_imm(DEFAULT_SMSC_ID);
140         tmp_dict = dict_get(tlvs_by_tag, smsc_id);
141         if (tmp_dict != NULL)
142             res = dict_get(tmp_dict, tmp);
143     }
144 
145     octstr_destroy(tmp);
146 
147     return res;
148 }
149 
smpp_pdu_init(Cfg * cfg)150 int smpp_pdu_init(Cfg *cfg)
151 {
152     CfgGroup *grp;
153     List *l;
154 
155     if (initialized)
156         return 0;
157 
158     l = cfg_get_multi_group(cfg, octstr_imm("smpp-tlv"));
159     tlvs = gwlist_create();
160     tlvs_by_tag = dict_create(1024, (void(*)(void*))dict_destroy);
161     tlvs_by_name = dict_create(1024, (void(*)(void*))dict_destroy);
162     while (l != NULL && (grp = gwlist_extract_first(l)) != NULL) {
163         struct smpp_tlv *tlv;
164         Octstr *tmp, *smsc_id;
165         List *l2;
166 
167         tlv = gw_malloc(sizeof(*tlv));
168         if ((tlv->name = cfg_get(grp, octstr_imm("name"))) == NULL) {
169             error(0, "SMPP: Unable to get name for smpp-tlv.");
170             smpp_tlv_destroy(tlv);
171             goto failed;
172         }
173         if (cfg_get_integer(&tlv->tag, grp, octstr_imm("tag")) == -1) {
174             error(0, "SMPP: Unable to get tag for smpp-tlv.");
175             smpp_tlv_destroy(tlv);
176             goto failed;
177         }
178         if (cfg_get_integer(&tlv->length, grp, octstr_imm("length")) == -1) {
179             error(0, "SMPP: Unable to get length for smpp-tlv.");
180             smpp_tlv_destroy(tlv);
181             goto failed;
182         }
183         if ((tmp = cfg_get(grp, octstr_imm("type"))) == NULL) {
184             error(0, "SMPP: Unable to get type for smpp-tlv.");
185             smpp_tlv_destroy(tlv);
186             goto failed;
187         }
188         if (octstr_str_case_compare(tmp, "octetstring") == 0)
189             tlv->type = SMPP_TLV_OCTETS;
190         else if (octstr_str_case_compare(tmp, "nulterminated") == 0)
191             tlv->type = SMPP_TLV_NULTERMINATED;
192         else if (octstr_str_case_compare(tmp, "integer") == 0)
193             tlv->type = SMPP_TLV_INTEGER;
194         else {
195             error(0, "SMPP: Unknown type for smpp-tlv: `%s'", octstr_get_cstr(tmp));
196             octstr_destroy(tmp);
197             smpp_tlv_destroy(tlv);
198             goto failed;
199         }
200         octstr_destroy(tmp);
201 
202         /* put to all TLVs */
203         gwlist_produce(tlvs, tlv);
204 
205         smsc_id = cfg_get(grp, octstr_imm("smsc-id"));
206         if (smsc_id != NULL) {
207             l2 = octstr_split(smsc_id, octstr_imm(";"));
208             octstr_destroy(smsc_id);
209         } else {
210             l2 = gwlist_create();
211             gwlist_produce(l2, octstr_create(DEFAULT_SMSC_ID));
212         }
213         while(l2 != NULL && (smsc_id = gwlist_extract_first(l2)) != NULL) {
214             Dict *tmp_dict;
215 
216             debug("sms.smpp", 0, "adding smpp-tlv for smsc-id=%s", octstr_get_cstr(smsc_id));
217 
218             tmp_dict = dict_get(tlvs_by_name, smsc_id);
219             if (tmp_dict == NULL) {
220                 tmp_dict = dict_create(1024, NULL);
221                 dict_put(tlvs_by_name, smsc_id, tmp_dict);
222             }
223             /* put into dict */
224             if (!dict_put_once(tmp_dict, tlv->name, tlv)) {
225                 error(0, "SMPP: Double TLV name %s found.", octstr_get_cstr(tlv->name));
226                 octstr_destroy(smsc_id);
227                 goto failed;
228             }
229 
230             tmp_dict = dict_get(tlvs_by_tag, smsc_id);
231             if (tmp_dict == NULL) {
232                 tmp_dict = dict_create(1024, NULL);
233                 dict_put(tlvs_by_tag, smsc_id, tmp_dict);
234             }
235             tmp = octstr_format("%ld", tlv->tag);
236             if (!dict_put_once(tmp_dict, tmp, tlv)) {
237                 error(0, "SMPP: Double TLV tag %s found.", octstr_get_cstr(tmp));
238                 gwlist_destroy(l2, octstr_destroy_item);
239                 octstr_destroy(tmp);
240                 octstr_destroy(smsc_id);
241                 goto failed;
242             }
243             octstr_destroy(tmp);
244             octstr_destroy(smsc_id);
245         }
246         gwlist_destroy(l2, octstr_destroy_item);
247     }
248     gwlist_destroy(l, NULL);
249 
250     initialized = 1;
251     return 0;
252 
253 failed:
254     gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy);
255     dict_destroy(tlvs_by_tag);
256     dict_destroy(tlvs_by_name);
257     return -1;
258 }
259 
260 
smpp_pdu_shutdown(void)261 int smpp_pdu_shutdown(void)
262 {
263     if (initialized == 0)
264         return 0;
265 
266     initialized = 0;
267     gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy);
268     tlvs = NULL;
269     dict_destroy(tlvs_by_tag);
270     dict_destroy(tlvs_by_name);
271     tlvs_by_tag = tlvs_by_name = NULL;
272 
273     return 0;
274 }
275 
276 
decode_integer(Octstr * os,long pos,int octets)277 static long decode_integer(Octstr *os, long pos, int octets)
278 {
279     unsigned long u;
280     int i;
281 
282     if (octstr_len(os) < pos + octets)
283         return -1;
284 
285     u = 0;
286     for (i = 0; i < octets; ++i)
287     	u = (u << 8) | octstr_get_char(os, pos + i);
288 
289     return u;
290 }
291 
292 
append_encoded_integer(Octstr * os,unsigned long u,long octets)293 static void append_encoded_integer(Octstr *os, unsigned long u, long octets)
294 {
295     long i;
296 
297     for (i = 0; i < octets; ++i)
298     	octstr_append_char(os, (u >> ((octets - i - 1) * 8)) & 0xFF);
299 }
300 
301 
copy_until_nul(const char * field_name,Octstr * os,long * pos,long max_octets,Octstr ** data)302 static int copy_until_nul(const char *field_name, Octstr *os, long *pos, long max_octets, Octstr **data)
303 {
304     long nul;
305 
306     *data = NULL;
307 
308     nul = octstr_search_char(os, '\0', *pos);
309     if (nul == -1) {
310         warning(0, "SMPP: PDU NULL terminated string (%s) has no NULL.", field_name);
311         return -1;
312     }
313     if (*pos + max_octets < nul) {
314         error(0, "SMPP: PDU NULL terminated string (%s) longer than allowed.", field_name);
315         return -1;
316     }
317     *data = (nul - *pos > 0) ? octstr_copy(os, *pos, nul - *pos) : NULL;
318     *pos = nul + 1;
319     return 0;
320 }
321 
322 
smpp_pdu_create(unsigned long type,unsigned long seq_no)323 SMPP_PDU *smpp_pdu_create(unsigned long type, unsigned long seq_no)
324 {
325     SMPP_PDU *pdu;
326 
327     pdu = gw_malloc(sizeof(*pdu));
328     pdu->type = type;
329 
330     switch (type) {
331     #define OPTIONAL_BEGIN
332     #define TLV_INTEGER(name, octets) p->name = -1;
333     #define TLV_NULTERMINATED(name, max_len) p->name = NULL;
334     #define TLV_OCTETS(name, min_len, max_len) p->name = NULL;
335     #define OPTIONAL_END p->tlv = dict_create(1024, octstr_destroy_item);
336     #define INTEGER(name, octets) p->name = 0;
337     #define NULTERMINATED(name, max_octets) p->name = NULL;
338     #define OCTETS(name, field_giving_octetst) p->name = NULL;
339     #define PDU(name, id, fields) \
340         case id: { \
341             struct name *p = &pdu->u.name; \
342             pdu->type_name = #name; \
343             fields \
344             p->command_id = type; \
345             p->sequence_number = seq_no; \
346         } break;
347     #include "smpp_pdu.def"
348     default:
349         error(0, "Unknown SMPP_PDU type, internal error.");
350         gw_free(pdu);
351         return NULL;
352     }
353 
354     return pdu;
355 }
356 
smpp_pdu_destroy(SMPP_PDU * pdu)357 void smpp_pdu_destroy(SMPP_PDU *pdu)
358 {
359     if (pdu == NULL)
360         return;
361 
362     switch (pdu->type) {
363     #define OPTIONAL_BEGIN
364     #define TLV_INTEGER(name, octets) p->name = -1;
365     #define TLV_NULTERMINATED(name, max_octets) octstr_destroy(p->name);
366     #define TLV_OCTETS(name, min_len, max_len) octstr_destroy(p->name);
367     #define OPTIONAL_END dict_destroy(p->tlv);
368     #define INTEGER(name, octets) p->name = 0; /* Make sure "p" is used */
369     #define NULTERMINATED(name, max_octets) octstr_destroy(p->name);
370     #define OCTETS(name, field_giving_octets) octstr_destroy(p->name);
371     #define PDU(name, id, fields) \
372         case id: { struct name *p = &pdu->u.name; fields } break;
373     #include "smpp_pdu.def"
374     default:
375         error(0, "Unknown SMPP_PDU type, internal error while destroying.");
376     }
377     gw_free(pdu);
378 }
379 
380 
smpp_pdu_pack(Octstr * smsc_id,SMPP_PDU * pdu)381 Octstr *smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu)
382 {
383     Octstr *os;
384     Octstr *temp;
385 
386     os = octstr_create("");
387 
388     gw_assert(pdu != NULL);
389 
390     /*
391      * Fix lengths of octet string fields.
392      */
393     switch (pdu->type) {
394     #define OPTIONAL_BEGIN
395     #define TLV_INTEGER(name, octets)
396     #define TLV_NULTERMINATED(name, max_len)
397     #define TLV_OCTETS(name, min_len, max_len)
398     #define OPTIONAL_END
399     #define INTEGER(name, octets) p = *(&p);
400     #define NULTERMINATED(name, max_octets) p = *(&p);
401     #define OCTETS(name, field_giving_octets) \
402     	p->field_giving_octets = octstr_len(p->name);
403     #define PDU(name, id, fields) \
404     	case id: { struct name *p = &pdu->u.name; fields } break;
405     #include "smpp_pdu.def"
406     default:
407     	error(0, "Unknown SMPP_PDU type, internal error while packing.");
408     }
409 
410     switch (pdu->type) {
411     #define TL(name, octets) \
412         append_encoded_integer(os, SMPP_##name, 2); \
413         append_encoded_integer(os, octets, 2);
414     #define OPTIONAL_BEGIN
415     #define TLV_INTEGER(name, octets) \
416         if (p->name >= 0) { \
417             TL(name, octets); \
418             INTEGER(name, octets) \
419         }
420     #define TLV_NULTERMINATED(name, max_len) \
421         if (p->name != NULL) { \
422             TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name) + 1)); \
423             NULTERMINATED(name, max_len) \
424         }
425     #define TLV_OCTETS(name, min_len, max_len) \
426         if (p->name != NULL) { \
427             unsigned long len = octstr_len(p->name); \
428             if (len > max_len || len < min_len) { \
429                 error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
430                     #name, len, min_len, max_len);\
431             } else { \
432                 TL(name, len); \
433                 octstr_append(os, p->name); \
434             } \
435         }
436     #define OPTIONAL_END \
437         if (p->tlv != NULL) { \
438             Octstr *key; \
439             List *keys; \
440             struct smpp_tlv *tlv; \
441             keys = dict_keys(p->tlv); \
442             while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
443                 tlv = smpp_tlv_get_by_name(smsc_id, key); \
444                 if (tlv == NULL) { \
445                     error(0, "SMPP: Unknown TLV `%s', don't send.", octstr_get_cstr(key)); \
446                     octstr_destroy(key); \
447                     continue; \
448                 } \
449                 switch(tlv->type) { \
450                 case SMPP_TLV_INTEGER: { \
451                     long val = atol(octstr_get_cstr(dict_get(p->tlv, key))); \
452                     append_encoded_integer(os, tlv->tag, 2); \
453                     append_encoded_integer(os, tlv->length, 2); \
454                     append_encoded_integer(os, val, tlv->length); \
455                     break; \
456                 } \
457                 case SMPP_TLV_OCTETS: \
458                 case SMPP_TLV_NULTERMINATED: { \
459                     Octstr *val = dict_get(p->tlv, key); \
460                     unsigned long len = octstr_len(val); \
461                     if (len > tlv->length) { \
462                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \
463                               octstr_get_cstr(key), len, tlv->length);\
464                         octstr_destroy(key); \
465                         continue; \
466                     } \
467                     append_encoded_integer(os, tlv->tag, 2); \
468                     if (tlv->type == SMPP_TLV_NULTERMINATED) \
469                         append_encoded_integer(os, len + 1, 2); \
470                     else \
471                         append_encoded_integer(os, len, 2); \
472                     octstr_append(os, val); \
473                     if (tlv->type == SMPP_TLV_NULTERMINATED) \
474                         octstr_append_char(os, '\0'); \
475                     break; \
476                 } \
477                 default: \
478                     panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \
479                     break; \
480                 } \
481                 octstr_destroy(key); \
482             } \
483             gwlist_destroy(keys, octstr_destroy_item); \
484         }
485     #define INTEGER(name, octets) \
486         append_encoded_integer(os, p->name, octets);
487     #define NULTERMINATED(name, max_octets) \
488         if (p->name != NULL) { \
489             if (octstr_len(p->name) >= max_octets) { \
490                 warning(0, "SMPP: PDU element <%s> too long " \
491                         "(length is %ld, should be %d)", \
492                         #name, octstr_len(p->name), max_octets-1); \
493                 temp = octstr_copy(p->name, 0, max_octets-1); \
494             } else \
495                 temp = octstr_duplicate(p->name); \
496             octstr_append(os, temp); \
497             octstr_destroy(temp); \
498         } \
499         octstr_append_char(os, '\0');
500     #define OCTETS(name, field_giving_octets) \
501         if (p->name) octstr_append(os, p->name);
502     #define PDU(name, id, fields) \
503         case id: { struct name *p = &pdu->u.name; fields } break;
504     #include "smpp_pdu.def"
505     default:
506         error(0, "Unknown SMPP_PDU type 0x%08lx, internal error while packing.", pdu->type);
507         break;
508     }
509 
510     temp = octstr_create("");
511     append_encoded_integer(temp, octstr_len(os) + 4, 4);
512     octstr_insert(os, temp, 0);
513     octstr_destroy(temp);
514 
515     return os;
516 }
517 
518 
smpp_pdu_unpack(Octstr * smsc_id,Octstr * data_without_len)519 SMPP_PDU *smpp_pdu_unpack(Octstr *smsc_id, Octstr *data_without_len)
520 {
521     SMPP_PDU *pdu;
522     unsigned long type;
523     long len, pos;
524 
525     len = octstr_len(data_without_len);
526 
527     if (len < 4) {
528         error(0, "SMPP: PDU was too short (%ld bytes).",
529               octstr_len(data_without_len));
530         return NULL;
531     }
532 
533     /* get the PDU type */
534     if ((type = decode_integer(data_without_len, 0, 4)) == -1)
535         return NULL;
536 
537     /* create a coresponding representation structure */
538     pdu = smpp_pdu_create(type, 0);
539     if (pdu == NULL)
540         return NULL;
541 
542     pos = 0;
543 
544     switch (type) {
545     #define OPTIONAL_BEGIN  \
546         {   /* Read optional parameters */  \
547             while (pos + 4 <= len) { \
548                 struct smpp_tlv *tlv; \
549                 unsigned long opt_tag, opt_len; \
550                 opt_tag = decode_integer(data_without_len, pos, 2); pos += 2; \
551                 debug("sms.smpp", 0, "Optional parameter tag (0x%04lx)", opt_tag);  \
552                 opt_len = decode_integer(data_without_len, pos, 2); pos += 2;  \
553                 debug("sms.smpp", 0, "Optional parameter length read as %ld", opt_len); \
554                 /* check configured TLVs */ \
555                 tlv = smpp_tlv_get_by_tag(smsc_id, opt_tag); \
556                 if (tlv != NULL) debug("sms.smpp", 0, "Found configured optional parameter `%s'", octstr_get_cstr(tlv->name));
557     #define TLV_INTEGER(mname, octets) \
558                 if (SMPP_##mname == opt_tag) { \
559                     /* check length */ \
560                     if (opt_len > octets) { \
561                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len); \
562                         pos += opt_len; \
563                         continue; \
564                     } \
565                     INTEGER(mname, opt_len); \
566                     if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_format("%ld", p->mname)); \
567                 } else
568     #define TLV_NULTERMINATED(mname, max_len) \
569                 if (SMPP_##mname == opt_tag) { \
570                     /* check length */ \
571                     if (opt_len > max_len || pos+opt_len > len) { \
572                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len);  \
573                         pos += opt_len; \
574                         continue; \
575                     } \
576                     copy_until_nul(#mname, data_without_len, &pos, opt_len, &p->mname); \
577                     if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \
578                 } else
579     #define TLV_OCTETS(mname, min_len, max_len) \
580                 if (SMPP_##mname == opt_tag) { \
581                     /* check length */ \
582                     if (opt_len < min_len || opt_len > max_len || pos + opt_len > len) { \
583                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
584                             #mname, opt_len, min_len, max_len);  \
585                         pos += opt_len; \
586                         continue; \
587                     } \
588                     p->mname = octstr_copy(data_without_len, pos, opt_len); \
589                     pos += opt_len; \
590                     if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \
591                 } else
592     #define OPTIONAL_END \
593                 { \
594                     Octstr *val = NULL; \
595                     if (tlv != NULL) { \
596                         /* found configured tlv */ \
597                         /* check length */ \
598                         if (opt_len > tlv->length) { \
599                             error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \
600                                   octstr_get_cstr(tlv->name), opt_len, tlv->length); \
601                             pos += opt_len; \
602                             continue; \
603                         } \
604                         switch (tlv->type) { \
605                         case SMPP_TLV_INTEGER: { \
606                             long val_i; \
607                             if ((val_i = decode_integer(data_without_len, pos, opt_len)) == -1) \
608                                 goto err; \
609                             val = octstr_format("%ld", val_i); \
610                             dict_put(p->tlv, tlv->name, val); \
611                             pos += opt_len; \
612                             break; \
613                         } \
614                         case SMPP_TLV_OCTETS: { \
615                             val = octstr_copy(data_without_len, pos, opt_len); \
616                             dict_put(p->tlv, tlv->name, val); \
617                             pos += opt_len; \
618                             break; \
619                         } \
620                         case SMPP_TLV_NULTERMINATED: { \
621                             if (copy_until_nul(octstr_get_cstr(tlv->name), data_without_len, &pos, opt_len, &val) == 0) \
622                                 dict_put(p->tlv, tlv->name, val); \
623                             break; \
624                         } \
625                         default: \
626                             panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \
627                             break; \
628                         } \
629                     }  else { \
630                         val = octstr_copy(data_without_len, pos, opt_len); \
631                         if (val) \
632                             octstr_binary_to_hex(val, 0); \
633                         else \
634                             val = octstr_create(""); \
635                         warning(0, "SMPP: Unknown TLV(0x%04lx,0x%04lx,%s) for PDU type (%s) received!", \
636                             opt_tag, opt_len, octstr_get_cstr(val), pdu->type_name); \
637                         octstr_destroy(val); \
638                         pos += opt_len; \
639                     } \
640                 } \
641             } \
642         }
643     #define INTEGER(name, octets) \
644         if ((p->name = decode_integer(data_without_len, pos, octets)) == -1) \
645             goto err; \
646         pos += octets;
647     #define NULTERMINATED(name, max_octets) \
648         /* just warn about errors but not fail */ \
649         copy_until_nul(#name, data_without_len, &pos, max_octets, &p->name);
650     #define OCTETS(name, field_giving_octets) \
651     	p->name = octstr_copy(data_without_len, pos, \
652 	    	    	      p->field_giving_octets); \
653         if (p->field_giving_octets != (unsigned long) octstr_len(p->name)) { \
654             error(0, "smpp_pdu: error while unpacking '" #name "', " \
655                      "len is %ld but should have been %ld, dropping.", \
656                      octstr_len(p->name), p->field_giving_octets); \
657             goto err; \
658         } else { \
659             pos += p->field_giving_octets; \
660         }
661     #define PDU(name, id, fields) \
662     	case id: { struct name *p = &pdu->u.name; fields } break;
663     #include "smpp_pdu.def"
664     default:
665     	error(0, "Unknown SMPP_PDU type 0x%08lx, internal error while unpacking.", type);
666     	break;
667     }
668 
669     return pdu;
670 
671 err:
672     smpp_pdu_destroy(pdu);
673     octstr_dump(data_without_len, 0);
674     return NULL;
675 }
676 
677 
smpp_pdu_dump(Octstr * smsc_id,SMPP_PDU * pdu)678 void smpp_pdu_dump(Octstr *smsc_id, SMPP_PDU *pdu)
679 {
680     debug("sms.smpp", 0, "SMPP PDU %p dump:", (void *) pdu);
681     debug("sms.smpp", 0, "  type_name: %s", pdu->type_name);
682     switch (pdu->type) {
683     #define OPTIONAL_BEGIN
684     #define TLV_INTEGER(name, max_len) \
685         if (p->name != -1)  { \
686             INTEGER(name, max_len) \
687         }
688     #define TLV_NULTERMINATED(name, max_len) \
689         if (p->name != NULL) { \
690             NULTERMINATED(name, max_len) \
691         }
692     #define TLV_OCTETS(name, min_len, max_len) \
693         if (p->name != NULL) { \
694             OCTETS(name, max_len) \
695         }
696     #define OPTIONAL_END \
697         if (p->tlv != NULL) { \
698             List *keys; \
699             Octstr *key; \
700             struct smpp_tlv *tlv; \
701             keys = dict_keys(p->tlv); \
702             while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
703                 tlv = smpp_tlv_get_by_name(smsc_id, key); \
704                 if (tlv != NULL) { \
705                     octstr_dump_short(dict_get(p->tlv, key), 2, octstr_get_cstr(key)); \
706                 } \
707                 octstr_destroy(key); \
708             } \
709             gwlist_destroy(keys, octstr_destroy_item); \
710         }
711     #define INTEGER(name, octets) \
712         debug("sms.smpp", 0, "  %s: %lu = 0x%08lx", #name, p->name, p->name);
713     #define NULTERMINATED(name, max_octets) \
714         octstr_dump_short(p->name, 2, #name);
715     #define OCTETS(name, field_giving_octets) \
716         octstr_dump_short(p->name, 2, #name);
717     #define PDU(name, id, fields) \
718         case id: { struct name *p = &pdu->u.name; fields } break;
719     #include "smpp_pdu.def"
720     default:
721         error(0, "Unknown SMPP_PDU type, internal error.");
722         break;
723     }
724     debug("sms.smpp", 0, "SMPP PDU dump ends.");
725 }
726 
727 
smpp_pdu_read_len(Connection * conn)728 long smpp_pdu_read_len(Connection *conn)
729 {
730     Octstr *os;
731     unsigned char buf[4];    /* The length is 4 octets. */
732     long len;
733 
734     os = conn_read_fixed(conn, sizeof(buf));
735     if (os == NULL)
736     	return 0;
737     octstr_get_many_chars((char*) buf, os, 0, sizeof(buf));
738     octstr_destroy(os);
739     len = decode_network_long(buf);
740     if (len < MIN_SMPP_PDU_LEN) {
741 	error(0, "SMPP: PDU length was too small (%ld, minimum is %ld).",
742 	      len, (long) MIN_SMPP_PDU_LEN);
743     	return -1;
744     }
745     if (len > MAX_SMPP_PDU_LEN) {
746 	error(0, "SMPP: PDU length was too large (%ld, maximum is %ld).",
747 	      len, (long) MAX_SMPP_PDU_LEN);
748     	return -1;
749     }
750     return len;
751 }
752 
753 
smpp_pdu_read_data(Connection * conn,long len)754 Octstr *smpp_pdu_read_data(Connection *conn, long len)
755 {
756     Octstr *os;
757 
758     os = conn_read_fixed(conn, len - 4);    /* `len' includes itself. */
759     return os;
760 }
761 
762 
763 /*
764  * Return error string for given error code
765  * NOTE: If you add new error strings here please use
766  *       error strings from SMPP spec. and please keep
767  *       error codes in switch statement sorted by error
768  *       code ID.
769  */
smpp_error_to_string(enum SMPP_ERROR_MESSAGES error)770 const char *smpp_error_to_string(enum SMPP_ERROR_MESSAGES error)
771 {
772     switch (error) {
773         case SMPP_ESME_ROK:
774             return "OK";
775         case SMPP_ESME_RINVMSGLEN:
776             return "Message Length is invalid";
777         case SMPP_ESME_RINVCMDLEN:
778             return "Command Length is invalid";
779         case SMPP_ESME_RINVCMDID:
780             return "Invalid Command ID";
781         case SMPP_ESME_RINVBNDSTS:
782             return "Incorrect BIND Status for given command";
783         case SMPP_ESME_RALYNBD:
784             return "ESME Already in Bound State";
785         case SMPP_ESME_RINVPRTFLG:
786             return "Invalid Priority Flag";
787         case SMPP_ESME_RINVREGDLVFLG:
788             return "Invalid Registered Delivery Flag";
789         case SMPP_ESME_RSYSERR:
790             return "System Error";
791         case SMPP_ESME_RINVSRCADR:
792             return "Invalid Source Address";
793         case SMPP_ESME_RINVDSTADR:
794             return "Invalid Destination Address";
795         case SMPP_ESME_RBINDFAIL:
796             return "Bind Failed";
797         case SMPP_ESME_RINVPASWD:
798             return "Invalid Password";
799         case SMPP_ESME_RINVSYSID:
800             return "Invalid System ID";
801         case SMPP_ESME_RCANCELFAIL:
802             return "Cancel SM Failed";
803         case SMPP_ESME_RREPLACEFAIL:
804             return "Replace SM Failed";
805         case SMPP_ESME_RMSGQFUL:
806             return "Message Queue Full";
807         case SMPP_ESME_RINVSERTYP:
808             return "Invalid Service Type";
809         case SMPP_ESME_RINVNUMDESTS:
810             return "Invalid number of destinations";
811         case SMPP_ESME_RINVDLNAME:
812             return "Invalid Distribution List Name";
813         case SMPP_ESME_RINVDESTFLAG:
814             return "Destination flag is invalid";
815         case SMPP_ESME_RINVSUBREP:
816             return "Submit w/replace not supported/allowed";
817         case SMPP_ESME_RINVESMCLASS:
818             return "Invalid esm_class field data";
819         case SMPP_ESME_RCNTSUBDL:
820             return "Cannot Submit to Distribution List";
821         case SMPP_ESME_RSUBMITFAIL:
822             return "Submit failed";
823         case SMPP_ESME_RINVSRCTON:
824             return "Invalid Source address TON";
825         case SMPP_ESME_RINVSRCNPI:
826             return "Invalid Source address NPI";
827         case SMPP_ESME_RINVDSTTON:
828             return "Invalid Destination address TON";
829         case SMPP_ESME_RINVDSTNPI:
830             return "Invalid Destination address NPI";
831         case SMPP_ESME_RINVSYSTYP:
832             return "Invalid system_type field";
833         case SMPP_ESME_RINVREPFLAG:
834             return "Invalid replace_if_present flag";
835         case SMPP_ESME_RINVNUMMSGS:
836             return "Invalid number of messages";
837         case SMPP_ESME_RTHROTTLED:
838             return "Throttling error";
839         case SMPP_ESME_RINVSCHED:
840             return "Invalid Scheduled Delivery Time";
841         case SMPP_ESME_RINVEXPIRY:
842             return "Invalid message validity period";
843         case SMPP_ESME_RINVDFTMSGID:
844             return "Predefined Message ID is Invalid or specific predefined message was not found";
845         case SMPP_ESME_RX_T_APPN:
846             return "ESME Receiver Temporary App Error Code";
847         case SMPP_ESME_RX_P_APPN:
848             return "ESME Receiver Permanent App Error Code";
849         case SMPP_ESME_RX_R_APPN:
850             return "ESME Receiver Reject Message Error Code";
851         case SMPP_ESME_RQUERYFAIL:
852             return "query_sm request failed";
853         case SMPP_ESME_RINVTLVSTREAM:
854             return "Error in optional part of the PDU Body";
855         case SMPP_ESME_RTLVNOTALLWD:
856             return "TLV not allowed";
857         case SMPP_ESME_RINVTLVLEN:
858             return "Invalid Parameter Length";
859         case SMPP_ESME_RMISSINGTLV:
860             return "Expected TLV missing";
861         case SMPP_ESME_RINVTLVVAL:
862             return "Invalid TLV value";
863         case SMPP_ESME_RDELIVERYFAILURE:
864             return "Transaction Delivery Failure";
865         case SMPP_ESME_RUNKNOWNERR:
866             return "Unknown Error";
867         case SMPP_ESME_RSERTYPUNAUTH:
868             return "ESME Not authorized to use specified service_type";
869         case SMPP_ESME_RPROHIBITED:
870             return "ESME Prohibited from using specified operation";
871         case SMPP_ESME_RSERTYPUNAVAIL:
872             return "Specified service_type is unavailable";
873         case SMPP_ESME_RSERTYPDENIED:
874             return "Specified service_type is denied";
875         case SMPP_ESME_RINVDCS:
876             return "Invalid Data Coding Scheme";
877         case SMPP_ESME_RINVSRCADDRSUBUNIT:
878             return "Source Address Sub unit is invalid";
879         case SMPP_ESME_RINVDSTADDRSUBUNIT:
880             return "Destination Address Sub unit is invalid";
881         case SMPP_ESME_RINVBCASTFREQINT:
882             return "Broadcast Frequency Interval is invalid";
883         case SMPP_ESME_RINVBCASTALIAS_NAME:
884             return "Broadcast Alias Name is invalid";
885         case SMPP_ESME_RINVBCASTAREAFMT:
886             return "Broadcast Area Format is invalid";
887         case SMPP_ESME_RINVNUMBCAST_AREAS:
888             return "Number of Broadcast Areas is invalid";
889         case SMPP_ESME_RINVBCASTCNTTYPE:
890             return "Broadcast Content Type is invalid";
891         case SMPP_ESME_RINVBCASTMSGCLASS:
892             return "Broadcast Message Class is invalid";
893         case SMPP_ESME_RBCASTFAIL:
894             return "broadcast_sm operation failed";
895         case SMPP_ESME_RBCASTQUERYFAIL:
896             return "broadcast_query_sm operation failed";
897         case SMPP_ESME_RBCASTCANCELFAIL:
898             return "broadcast_cancel_sm operation failed";
899         case SMPP_ESME_RINVBCAST_REP:
900             return "Number of Repeated Broadcasts is invalid";
901         case SMPP_ESME_RINVBCASTSRVGRP:
902             return "Broadcast Service Group is invalid";
903         case SMPP_ESME_RINVBCASTCHANIND:
904             return "Broadcast Channel Indicator is invalid";
905 
906         default:
907             /* tell the user that we have a vendor-specific beast here */
908             if (error >= 0x0400 && error <= 0x04FF)
909                 return "Vendor-specific error, please refer to your SMPP provider";
910             else
911                 return "Unknown/Reserved";
912     }
913 }
914