Kannel: Open Source WAP and SMS gateway  svn-r5335
smasi_pdu.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 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_smasi.c - parse and generate SMASI PDUs
59  *
60  * Stipe Tolj <stolj@wapme.de>
61  */
62 
63 
64 #include <string.h>
65 #include "smasi_pdu.h"
66 
67 
69 {
70  long p1, p2;
71  Octstr *temp;
72 
73  if ((p2 = octstr_search_char(os, ':', 0)) == -1)
74  return NULL;
75 
76  if ((p1 = octstr_search_char(os, '!', 0)) != -1 && p1 < p2) {
77  p1++;
78  } else {
79  p1 = 0;
80  }
81 
82  temp = octstr_copy(os, p1, p2 - p1);
83 
84  return temp;
85 }
86 
87 
88 static Octstr *copy_until_coma(Octstr *os, long *pos)
89 {
90  long nul;
91  Octstr *data;
92 
93  nul = octstr_search_char(os, ',', *pos);
94  if (nul == -1) {
95  warning(0, "SMASI: Parameter without value or value not properly terminated: %s", octstr_get_cstr(os));
96  return NULL;
97  }
98  data = octstr_copy(os, *pos, nul - *pos);
99  *pos = nul + 1;
100  return data;
101 }
102 
103 
104 static Octstr *copy_until_assign(Octstr *os, long *pos)
105 {
106  long nul;
107  Octstr *data;
108 
109  nul = octstr_search_char(os, '=', *pos);
110  if (nul == -1 && (octstr_len(os) - *pos) > 1) {
111  warning(0, "SMASI: Garbage at end of parameter list: %s", octstr_get_cstr(os));
112  *pos = octstr_len(os);
113  return NULL;
114  }
115  data = octstr_copy(os, *pos, nul - *pos);
116  *pos = nul + 1;
117  return data;
118 }
119 
120 
121 static void skip_until_after_colon(Octstr *os, long *pos)
122 {
123  long colon = octstr_search_char(os, ':', *pos);
124 
125  if (colon == -1) warning(0, "SMASI: No colon after SMASI PDU name: %s", octstr_get_cstr(os));
126 
127  *pos = colon + 1;
128 
129 }
130 
131 
133 {
134  SMASI_PDU *pdu;
135 
136  pdu = gw_malloc(sizeof(*pdu));
137  pdu->type = type;
138 
139  switch (type) {
140  #define NONTERMINATED(name) p->name = NULL;
141  #define COMATERMINATED(name) p->name = NULL;
142  #define PDU(name, id, fields) \
143  case id: { \
144  struct name *p = &pdu->u.name; \
145  pdu->type_name = #name; \
146  pdu->needs_hyphen = (id < SMASI_HYPHEN_ID ? 1 : 0); \
147  fields \
148  } break;
149  #include "smasi_pdu.def"
150  default:
151  warning(0, "Unknown SMASI_PDU type, internal error.");
152  gw_free(pdu);
153  return NULL;
154  }
155 
156  return pdu;
157 }
158 
159 
161 {
162  if (pdu == NULL)
163  return;
164 
165  switch (pdu->type) {
166  #define NONTERMINATED(name) octstr_destroy(p->name);
167  #define COMATERMINATED(name) octstr_destroy(p->name);
168  #define PDU(name, id, fields) \
169  case id: { struct name *p = &pdu->u.name; fields } break;
170  #include "smasi_pdu.def"
171  default:
172  error(0, "Unknown SMASI_PDU type, internal error while destroying.");
173  }
174  gw_free(pdu);
175 }
176 
177 
179 {
180  Octstr *os;
181  Octstr *temp;
182 
183  os = octstr_create("");
184 
185  /*
186  * Fix lengths of octet string fields.
187  */
188  switch (pdu->type) {
189  #define NONTERMINATED(name) p = *(&p);
190  #define COMATERMINATED(name) p = *(&p);
191  #define PDU(name, id, fields) \
192  case id: { struct name *p = &pdu->u.name; fields } break;
193  #include "smasi_pdu.def"
194  default:
195  error(0, "Unknown SMASI_PDU type, internal error while packing.");
196  }
197 
198  switch (pdu->type) {
199  #define NONTERMINATED(name) p = *(&p);
200  #define COMATERMINATED(name) \
201  if (p->name != NULL) { octstr_append_cstr(os, #name); \
202  octstr_append_char(os, '='); \
203  octstr_append(os, p->name); \
204  octstr_append_char(os, ','); }
205  #define PDU(name, id, fields) \
206  case id: { struct name *p = &pdu->u.name; fields } break;
207  #include "smasi_pdu.def"
208  default:
209  error(0, "Unknown SMASI_PDU type, internal error while packing.");
210  }
211 
212  octstr_append_char(os, '\n');
213  temp = pdu->needs_hyphen ? octstr_create("!") : octstr_create("");
214  octstr_append_cstr(temp, pdu->type_name);
215  octstr_append_char(temp, ':');
216  octstr_insert(os, temp, 0);
217  octstr_destroy(temp);
218 
219  return os;
220 }
221 
222 
223 SMASI_PDU *smasi_pdu_unpack(Octstr *data_without_len)
224 {
225  SMASI_PDU *pdu;
226  char *type_name;
227  Octstr *temp;
228  long pos;
229  unsigned long type = 0;
230 
231  /* extract the PDU type identifier */
232  temp = decode_type(data_without_len);
233  type_name = (temp ? octstr_get_cstr(temp) : "");
234 
235  if (strcmp(type_name, "dummy") == 0) type = 0;
236  #define NONTERMINATED(name) p = *(&p);
237  #define COMATERMINATED(name) p = *(&p);
238  #define PDU(name, id, fields) \
239  else if (strcmp(type_name, #name) == 0) type = id;
240  #include "smasi_pdu.def"
241  else warning(0, "unknown SMASI PDU type");
242 
243  pdu = smasi_pdu_create(type);
244  if (pdu == NULL) return NULL;
245 
246  pos = 0;
247  skip_until_after_colon(data_without_len, &pos);
248 
249  switch (type) {
250  #define NONTERMINATED(name) p = *(&p);
251  #define COMATERMINATED(name) \
252  if (octstr_str_compare(field_name, #name) == 0 && field_value != NULL) \
253  p->name = octstr_duplicate(field_value);
254  #define PDU(name, id, fields) \
255  case id: { \
256  Octstr * field_name = NULL; \
257  Octstr * field_value = NULL; \
258  struct name *p = &pdu->u.name; \
259  while (pos < octstr_len(data_without_len)) { \
260  field_name = copy_until_assign(data_without_len, &pos); \
261  if (field_name == NULL) break; \
262  field_value = copy_until_coma(data_without_len, &pos); \
263  if (field_value == NULL) continue; \
264  fields \
265  octstr_destroy(field_name); \
266  octstr_destroy(field_value); \
267  } \
268  } break;
269  #include "smasi_pdu.def"
270  default:
271  warning(0, "Unknown SMASI_PDU type, internal error while unpacking.");
272  }
273 
274  octstr_destroy(temp);
275 
276  return pdu;
277 }
278 
279 
281 {
282  debug("sms.smasi", 0, "SMASI PDU %p dump:", (void *) pdu);
283  debug("sms.smasi", 0, " type_name: %s", pdu->type_name);
284  switch (pdu->type) {
285  #define NONTERMINATED(name) p = *(&p);
286  #define COMATERMINATED(name) \
287  octstr_dump_short(p->name, 2, #name);
288  #define PDU(name, id, fields) \
289  case id: { struct name *p = &pdu->u.name; fields } break;
290  #include "smasi_pdu.def"
291  default:
292  warning(0, "Unknown SMASI_PDU type, internal error.");
293  break;
294  }
295  debug("sms.smasi", 0, "SMASI PDU dump ends.");
296 }
297 
298 
300 {
301  Octstr *line;
302 
303  line = conn_read_line(conn); /* read one line */
304  return line;
305 }
void smasi_pdu_dump(SMASI_PDU *pdu)
Definition: smasi_pdu.c:280
Octstr * conn_read_line(Connection *conn)
Definition: conn.c:1134
void error(int err, const char *fmt,...)
Definition: log.c:648
unsigned int needs_hyphen
Definition: smasi_pdu.h:87
const char * type_name
Definition: smasi_pdu.h:86
static Octstr * decode_type(Octstr *os)
Definition: smasi_pdu.c:68
static Octstr * copy_until_coma(Octstr *os, long *pos)
Definition: smasi_pdu.c:88
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
unsigned long type
Definition: smasi_pdu.h:85
int type
Definition: smsc_cimd2.c:215
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1511
SMASI_PDU * smasi_pdu_create(unsigned long type)
Definition: smasi_pdu.c:132
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1012
Octstr * smasi_pdu_pack(SMASI_PDU *pdu)
Definition: smasi_pdu.c:178
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1303
SMASI_PDU * smasi_pdu_unpack(Octstr *data_without_len)
Definition: smasi_pdu.c:223
static void skip_until_after_colon(Octstr *os, long *pos)
Definition: smasi_pdu.c:121
Octstr * smasi_pdu_read(Connection *conn)
Definition: smasi_pdu.c:299
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
static Octstr * colon
Definition: smsc_smasi.c:218
static Octstr * copy_until_assign(Octstr *os, long *pos)
Definition: smasi_pdu.c:104
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void smasi_pdu_destroy(SMASI_PDU *pdu)
Definition: smasi_pdu.c:160
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.