1 /*
2  * Copyright (C) 2006 Raul Tremsal
3  * File  : smpp34_unpack.c
4  * Author: Raul Tremsal <ultraismo@yahoo.com>
5  *
6  * This file is part of libsmpp34 (c-open-smpp3.4 library).
7  *
8  * The libsmpp34 library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2.1 of the
11  * License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  */
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 
29 #ifdef __linux__
30 #include <stdint.h>
31 #endif
32 
33 #include "smpp34.h"
34 #include "smpp34_structs.h"
35 #include "smpp34_params.h"
36 
37 /* GLOBALS ********************************************************************/
38 /* EXTERN *********************************************************************/
39 extern int smpp34_errno;
40 extern char smpp34_strerror[2048];
41 extern char *ptrerror;
42 
43 /* FUNCTIONS ******************************************************************/
44 int
smpp34_unpack(uint32_t type,void * tt,uint8_t * ptrBuf,int ptrLen)45 smpp34_unpack(uint32_t type, void* tt, uint8_t *ptrBuf, int ptrLen)
46 {
47 
48     char dummy_b[SMALL_BUFF];
49     uint8_t *ini      = ptrBuf;
50     uint8_t *aux      = ptrBuf;
51     int lenval = 0;
52     int left = ptrLen;
53     int lefterror = 0;
54 
55     memset(smpp34_strerror, 0, sizeof(smpp34_strerror));
56     ptrerror = smpp34_strerror;
57     lefterror = sizeof(smpp34_strerror);
58 
59 #define instancia t1->
60 
61 #define U32( inst, par, _str ){\
62     lenval = sizeof( uint32_t );\
63     if( lenval > left ){\
64         PUTLOG("[%s:%08X(%s)]", par, inst par,\
65                                       "Value lenght exceed buffer lenght");\
66         return( -1 );\
67     };\
68     memcpy(&inst par, aux, lenval);\
69     left -= lenval; aux += lenval;\
70     inst par = ntohl( inst par );\
71     _str(inst par, dummy_b);\
72     if( strcmp("", dummy_b) == 0 ){\
73         PUTLOG( "[%s:%08X(%s)]", par, inst par, "Invalid value");\
74         return( -1 );\
75     };\
76     PUTLOG("[%s:%08X(%s)]", par, inst par, "OK");\
77 };
78 
79 #define U16( inst, par, _str ){\
80     lenval = sizeof( uint16_t );\
81     if( lenval > left ){\
82         PUTLOG("[%s:%04X(%s)]", par, inst par,\
83                                       "Value lenght exceed buffer lenght");\
84         return( -1 );\
85     }\
86     memcpy(&inst par, aux, lenval);\
87     left -= lenval; aux += lenval;\
88     inst par = ntohs( inst par );\
89     _str(inst par, dummy_b);\
90     if( strcmp("", dummy_b) == 0 ){\
91         PUTLOG("[%s:%04X(%s)]", par, inst par, "Invalid value");\
92         return( -1 );\
93     };\
94     PUTLOG("[%s:%04X(%s)]", par, inst par, "OK");\
95 };
96 
97 #define U08( inst, par, _str ){\
98     lenval = sizeof( uint8_t );\
99     if( lenval > left ){\
100         PUTLOG("[%s:%02X(%s)]", par, inst par,\
101                                       "Value lenght exceed buffer lenght");\
102         return( -1 );\
103     };\
104     memcpy(&inst par, aux, lenval);\
105     left -= lenval; aux += lenval;\
106     _str(inst par, dummy_b);\
107     if( strcmp("", dummy_b) == 0 ){\
108         PUTLOG( "[%s:%02X(%s)]", par, inst par, "Invalid value");\
109         return( -1 );\
110     };\
111     PUTLOG("[%s:%02X(%s)]", par, inst par, "OK");\
112 };
113 
114 /* NOTA: Importante, Los WARNINGs de los octetos, advierten de una
115  *       inconsistencia de largo en los octets/c_octets recibidos, segun se
116  *       decida el grado de restriccion estos pueden ser errores graves.
117  *       La accion a tomar es truncar estos datos a los largos permitidos en la
118  *       especicacion, pero seguir parseando (saltando segun los largos
119  *       invalidos) los datos recibidos.
120  */
121 #define O_C_OCTET( inst, par, sizeval ){\
122     if( !(inst command_status) ){\
123         C_OCTET( inst, par, sizeval );\
124     } else {\
125         PUTLOG("[%s:%s(%s)]", par, inst par, "OK");\
126     };\
127 }
128 
129 
130 #define C_OCTET( inst, par, size ){\
131     lenval = strlen( (char*) aux ) + 1;\
132     if( lenval > left ){\
133         PUTLOG("[len(%s):%d(%s)]", par, lenval, \
134                                       "Value lenght exceed buffer lenght");\
135         return( -1 );\
136     };\
137     if( lenval > size ){\
138         PUTLOG("[%s:%s(%s)]", par, inst par, "Data length is invalid");\
139         return( -1 );\
140     } else {\
141         /*snprintf(inst par, (lenval>size)?size:lenval, "%s", aux); */ \
142         memcpy(inst par, aux, lenval);\
143         left -= lenval; aux += lenval;\
144         PUTLOG("[%s:%s(%s)]", par, inst par, "OK");\
145     };\
146 }
147 
148 #define OCTET8( inst, par, size ){\
149     lenval = *((inst par) - 1);\
150     if( lenval > left ){\
151         PUTLOG("[leng %s:%d(%s)]", par, lenval,\
152                                       "Value lenght exceed buffer lenght");\
153         return( -1 );\
154     };\
155     if( lenval > size ){\
156         PUTLOG("[%s:%s(%s)]", par, "<bin>",\
157                                       "Data length is invalid (truncate)");\
158         return( -1 );\
159     };\
160     memcpy(&inst par, aux, (lenval>size)?size:lenval);\
161     left -= lenval; aux += lenval;\
162     PUTLOG("[%s:%s(%s)]", par, "<bin>", "OK");\
163 }
164 
165 #define OCTET16( inst, par, size ){\
166     uint16_t l_lenval = 0; /* VERIFICAR ESTO */\
167     memcpy(&l_lenval, (inst par - sizeof(uint16_t)), sizeof(uint16_t));\
168     if( l_lenval > left ){\
169         PUTLOG("[leng %s:%d(%s)]", par, l_lenval,\
170                                       "Value lenght exceed buffer lenght");\
171         return( -1 );\
172     };\
173     if( l_lenval > size ){\
174         PUTLOG("[%s:%s(%s)]", par, "<bin>", "Data length is invalid");\
175         return( -1 );\
176     };\
177     PUTLOG("[%s:%s(%s)]", par, "<bin>", "OK");\
178     memcpy(&(inst par), aux, (l_lenval>size)?size:l_lenval);\
179     left -= l_lenval; aux += l_lenval;\
180 }
181 
182 #define TLV( inst, tlv3, do_tlv ){\
183     tlv_t *aux_tlv = NULL;\
184     while( (aux - ini) < t1->command_length ){\
185         aux_tlv = (tlv_t *) malloc(sizeof( tlv_t ));\
186         memset(aux_tlv, 0, sizeof(tlv_t));\
187         do_tlv( aux_tlv );\
188         aux_tlv->next = inst tlv3;\
189         inst tlv3 = aux_tlv;\
190     };\
191 };
192 
193 #define UDAD( inst, udad3, do_udad ){\
194     udad_t *aux_udad = NULL;\
195     int c = 0;\
196     while( c < t1->no_unsuccess ){\
197         aux_udad = (udad_t *) malloc(sizeof( udad_t ));\
198         memset(aux_udad, 0, sizeof(udad_t));\
199         do_udad( aux_udad );\
200         aux_udad->next = inst udad3;\
201         inst udad3 = aux_udad;\
202         c++;\
203     };\
204 };
205 
206 #define DAD( inst, dad3, do_dad ){\
207     dad_t *aux_dad = NULL;\
208     int c = 0;\
209     while( c < t1->number_of_dests ){\
210         aux_dad = (dad_t *) malloc(sizeof( dad_t ));\
211         memset(aux_dad, 0, sizeof(dad_t));\
212         do_dad( aux_dad );\
213         aux_dad->next = inst dad3;\
214         inst dad3 = aux_dad;\
215         c++;\
216     };\
217 };
218 
219 #include "def_frame/alert_notification.tlv"
220 #include "def_frame/bind_receiver_resp.tlv"
221 #include "def_frame/bind_transceiver_resp.tlv"
222 #include "def_frame/bind_transmitter_resp.tlv"
223 #include "def_frame/data_sm.tlv"
224 #include "def_frame/data_sm_resp.tlv"
225 #include "def_frame/deliver_sm.tlv"
226 #include "def_frame/submit_multi_resp.udad"
227 #include "def_frame/submit_multi.dad"
228 #include "def_frame/submit_multi.tlv"
229 #include "def_frame/submit_sm.tlv"
230 #include "def_list/smpp34_protocol.def"
231 
232     { /* Hace algunas Verificaciones **************************************/
233         uint32_t len_orig;
234         uint32_t l;
235         memcpy(&len_orig, tt, sizeof(uint32_t));
236         l = ntohl( len_orig );
237         if( len_orig != (aux - ini) ){
238             PUTLOG("[%s:(Error in PDU length %d!=%d)]",PDU,len_orig,(uint32_t)(aux-ini));
239             return( -1 );
240         };
241     };
242 
243 #include "def_frame/clean.frame"
244     return( 0 );
245 };
246 
247 int
smpp34_unpack2(void * tt,uint8_t * ptrBuf,int ptrLen)248 smpp34_unpack2(void* tt, uint8_t *ptrBuf, int ptrLen)
249 {
250     uint32_t cmdid;
251     uint32_t tempo;
252     memcpy(&tempo, ptrBuf + 4, sizeof(uint32_t)); /* get command_id PDU */
253     cmdid = ntohl( tempo );
254     return( smpp34_unpack(cmdid, tt, ptrBuf, ptrLen) );
255 };
256