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