Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
bb_udp.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 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  * bb_udpc.c : bearerbox UDP sender/receiver module
59  *
60  * handles start/restart/shutdown/suspend/die operations of the UDP
61  * WDP interface
62  *
63  * Kalle Marjola <rpr@wapit.com> 2000 for project Kannel
64  */
65 
66 #include <errno.h>
67 #include <stdlib.h>
68 #include <stdio.h>
69 #include <time.h>
70 #include <string.h>
71 #include <sys/time.h>
72 #include <sys/types.h>
73 #include <unistd.h>
74 #include <signal.h>
75 #include <fcntl.h>
76 #include <assert.h>
77 
78 #include "gwlib/gwlib.h"
79 #include "msg.h"
80 #include "bearerbox.h"
81 
82 /* passed from bearerbox core */
83 
84 extern volatile sig_atomic_t bb_status;
85 extern List *incoming_wdp;
86 
89 
90 extern List *flow_threads;
91 extern List *suspended;
92 extern List *isolated;
93 
94 /* our own thingies */
95 
96 static volatile sig_atomic_t udp_running;
97 static List *udpc_list;
98 
99 
100 typedef struct _udpc {
101  int fd;
104  long receiver;
105 } Udpc;
106 
107 
108 /*
109  * IP numbers which are allowed or denied us of the bearerbox via UDP.
110  */
111 static Octstr *allow_ip;
112 static Octstr *deny_ip;
113 
114 
115 /* forward declarations */
116 
117 static void udpc_destroy(Udpc *udpc);
118 
119 /*-------------------------------------------------
120  * receiver thingies
121  */
122 
123 static void udp_receiver(void *arg)
124 {
125  Octstr *datagram, *cliaddr;
126  int ret;
127  Msg *msg;
128  Udpc *conn = arg;
129  Octstr *ip;
130 
131  gwlist_add_producer(incoming_wdp);
132  gwlist_add_producer(flow_threads);
134 
135  /* remove messages from socket until it is closed */
136  while (bb_status != BB_DEAD && bb_status != BB_SHUTDOWN) {
137 
138  gwlist_consume(isolated); /* block here if suspended/isolated */
139 
140  if (read_available(conn->fd, 100000) < 1)
141  continue;
142 
143  ret = udp_recvfrom(conn->fd, &datagram, &cliaddr);
144  if (ret == -1) {
145  if (errno == EAGAIN)
146  /* No datagram available, don't block. */
147  continue;
148 
149  error(errno, "Failed to receive an UDP");
150  /*
151  * just continue, or is there ANY error that would result
152  * in situation where it would be better to break; or even
153  * die off? - Kalle 28.2
154  */
155  continue;
156  }
157 
158  /* discard the message if the client is not allowed */
159  ip = udp_get_ip(cliaddr);
160  if (!is_allowed_ip(allow_ip, deny_ip, ip)) {
161  warning(0, "UDP: Discarding packet from %s, IP is denied.",
162  octstr_get_cstr(ip));
163  octstr_destroy(datagram);
164  } else {
165  debug("bb.udp", 0, "datagram received");
166  msg = msg_create(wdp_datagram);
167 
168  msg->wdp_datagram.source_address = udp_get_ip(cliaddr);
169  msg->wdp_datagram.source_port = udp_get_port(cliaddr);
170  msg->wdp_datagram.destination_address = udp_get_ip(conn->addr);
171  msg->wdp_datagram.destination_port = udp_get_port(conn->addr);
172  msg->wdp_datagram.user_data = datagram;
173 
174  gwlist_produce(incoming_wdp, msg);
175  counter_increase(incoming_wdp_counter);
176  }
177 
178  octstr_destroy(cliaddr);
179  octstr_destroy(ip);
180  }
181  gwlist_remove_producer(incoming_wdp);
182  gwlist_remove_producer(flow_threads);
183 }
184 
185 
186 /*---------------------------------------------
187  * sender thingies
188  */
189 
190 static int send_udp(int fd, Msg *msg)
191 {
192  Octstr *cliaddr;
193  int ret;
194 
195  cliaddr = udp_create_address(msg->wdp_datagram.destination_address,
196  msg->wdp_datagram.destination_port);
197  ret = udp_sendto(fd, msg->wdp_datagram.user_data, cliaddr);
198  if (ret == -1)
199  error(0, "WDP/UDP: could not send UDP datagram");
200  octstr_destroy(cliaddr);
201  return ret;
202 }
203 
204 
205 static void udp_sender(void *arg)
206 {
207  Msg *msg;
208  Udpc *conn = arg;
209 
210  gwlist_add_producer(flow_threads);
211  while(bb_status != BB_DEAD) {
212 
213  gwlist_consume(suspended); /* block here if suspended */
214 
215  if ((msg = gwlist_consume(conn->outgoing_list)) == NULL)
216  break;
217 
218  debug("bb.udp", 0, "udp: sending message");
219 
220  if (send_udp(conn->fd, msg) == -1)
221  /* ok, we failed... tough
222  * XXX log the message or something like that... but this
223  * is not as fatal as it is with SMS-messages...
224  */ {
225  msg_destroy(msg);
226  continue;
227  }
228  counter_increase(outgoing_wdp_counter);
229  msg_destroy(msg);
230  }
231  gwthread_join(conn->receiver);
232 
233  udpc_destroy(conn);
234  gwlist_remove_producer(flow_threads);
235 }
236 
237 /*---------------------------------------------------------------
238  * accept/create thingies
239  */
240 
241 
242 static Udpc *udpc_create(int port, char *interface_name)
243 {
244  Udpc *udpc;
245  Octstr *os;
246  int fl;
247 
248  udpc = gw_malloc(sizeof(Udpc));
249  udpc->fd = udp_bind(port, interface_name);
250 
251  os = octstr_create(interface_name);
252  udpc->addr = udp_create_address(os, port);
253  octstr_destroy(os);
254  if (udpc->addr == NULL) {
255  error(0, "updc_create: could not resolve interface <%s>",
256  interface_name);
257  close(udpc->fd);
258  gw_free(udpc);
259  return NULL;
260  }
261 
262  fl = fcntl(udpc->fd, F_GETFL);
263  fcntl(udpc->fd, F_SETFL, fl | O_NONBLOCK);
264 
265  os = udp_get_ip(udpc->addr);
266  debug("bb.udp", 0, "udpc_create: Bound to UDP <%s:%d>",
267  octstr_get_cstr(os), udp_get_port(udpc->addr));
268 
269  octstr_destroy(os);
270 
271  udpc->outgoing_list = gwlist_create();
272 
273  return udpc;
274 }
275 
276 
277 static void udpc_destroy(Udpc *udpc)
278 {
279  if (udpc == NULL)
280  return;
281 
282  if (udpc->fd >= 0)
283  close(udpc->fd);
284  octstr_destroy(udpc->addr);
285  gw_assert(gwlist_len(udpc->outgoing_list) == 0);
286  gwlist_destroy(udpc->outgoing_list, NULL);
287 
288  gw_free(udpc);
289 }
290 
291 
292 static int add_service(int port, char *interface_name)
293 {
294  Udpc *udpc;
295 
296  if ((udpc = udpc_create(port, interface_name)) == NULL)
297  goto error;
299 
300  udpc->receiver = gwthread_create(udp_receiver, udpc);
301  if (udpc->receiver == -1)
302  goto error;
303 
304  if (gwthread_create(udp_sender, udpc) == -1)
305  goto error;
306 
307  gwlist_append(udpc_list, udpc);
308  return 0;
309 
310 error:
311  error(0, "Failed to start UDP receiver/sender thread");
312  udpc_destroy(udpc);
313  return -1;
314 }
315 
316 
317 
318 /*-------------------------------------------------------------
319  * public functions
320  *
321  */
322 
324 {
325  CfgGroup *grp;
326  Octstr *iface;
327  List *ifs;
328  int allow_wtls;
329 
330  if (udp_running) return -1;
331 
332  debug("bb.udp", 0, "starting UDP sender/receiver module");
333 
334  grp = cfg_get_single_group(cfg, octstr_imm("core"));
335  iface = cfg_get(grp, octstr_imm("wdp-interface-name"));
336  if (iface == NULL) {
337  error(0, "Missing wdp-interface-name variable, cannot start UDP");
338  return -1;
339  }
340 
341  allow_ip = cfg_get(grp, octstr_imm("udp-allow-ip"));
342  deny_ip = cfg_get(grp, octstr_imm("udp-deny-ip"));
343 
344  /* we'll activate WTLS as soon as we have a 'wtls' config group */
345  grp = cfg_get_single_group(cfg, octstr_imm("wtls"));
346  allow_wtls = grp != NULL ? 1 : 0;
347 
348  udpc_list = gwlist_create(); /* have a list of running systems */
349 
350  ifs = octstr_split(iface, octstr_imm(";"));
351  octstr_destroy(iface);
352  while (gwlist_len(ifs) > 0) {
353  iface = gwlist_extract_first(ifs);
354  info(0, "Adding interface %s", octstr_get_cstr(iface));
355  add_service(9200, octstr_get_cstr(iface)); /* wsp */
356  add_service(9201, octstr_get_cstr(iface)); /* wsp/wtp */
357 
358 #ifdef HAVE_WTLS_OPENSSL
359  if (allow_wtls) {
360  add_service(9202, octstr_get_cstr(iface)); /* wsp/wtls */
361  add_service(9203, octstr_get_cstr(iface)); /* wsp/wtp/wtls */
362  }
363 #else
364  if (allow_wtls)
365  error(0, "These is a 'wtls' group in configuration, but no WTLS support compiled in!");
366 #endif
367  /* add_service(9204, octstr_get_cstr(interface_name)); * vcard */
368  /* add_service(9205, octstr_get_cstr(interface_name)); * vcal */
369  /* add_service(9206, octstr_get_cstr(interface_name)); * vcard/wtls */
370  /* add_service(9207, octstr_get_cstr(interface_name)); * vcal/wtls */
371  octstr_destroy(iface);
372  }
373  gwlist_destroy(ifs, NULL);
374 
375  gwlist_add_producer(incoming_wdp);
376  udp_running = 1;
377  return 0;
378 }
379 
380 
381 /*
382  * this function receives an WDP message and adds it to
383  * corresponding outgoing_list.
384  */
386 {
387  int i;
388  Udpc *udpc, *def_udpc;
389  Octstr *ip;
390 
391  def_udpc = NULL;
392  if (!udp_running) return -1;
393  assert(msg != NULL);
394  assert(msg_type(msg) == wdp_datagram);
395 
396  gwlist_lock(udpc_list);
397  /* select in which list to add this */
398  for (i=0; i < gwlist_len(udpc_list); i++) {
399  udpc = gwlist_get(udpc_list, i);
400 
401  if (msg->wdp_datagram.source_port == udp_get_port(udpc->addr)) {
402  def_udpc = udpc;
403  ip = udp_get_ip(udpc->addr);
404  if (octstr_compare(msg->wdp_datagram.source_address, ip) == 0) {
405  octstr_destroy(ip);
406  gwlist_produce(udpc->outgoing_list, msg);
407  gwlist_unlock(udpc_list);
408  return 0;
409  }
410  octstr_destroy(ip);
411  }
412  }
413 
414  if (NULL != def_udpc) {
415  gwlist_produce(def_udpc->outgoing_list, msg);
416  gwlist_unlock(udpc_list);
417  return 0;
418  }
419 
420  gwlist_unlock(udpc_list);
421  return -1;
422 }
423 
424 int udp_shutdown(void)
425 {
426  if (!udp_running) return -1;
427 
428  debug("bb.thread", 0, "udp_shutdown: Starting avalanche");
429  gwlist_remove_producer(incoming_wdp);
430  return 0;
431 }
432 
433 
434 int udp_die(void)
435 {
436  Udpc *udpc;
437 
438  if (!udp_running) return -1;
439 
440  /*
441  * remove producers from all outgoing lists.
442  */
443  debug("bb.udp", 0, "udp_die: removing producers from udp-lists");
444 
445  while((udpc = gwlist_consume(udpc_list)) != NULL) {
447  }
448  gwlist_destroy(udpc_list, NULL);
449  udp_running = 0;
450 
451  octstr_destroy(allow_ip);
452  octstr_destroy(deny_ip);
453  allow_ip = NULL;
454  deny_ip = NULL;
455 
456  return 0;
457 }
458 
459 
461 {
462  int i, q = 0;
463  Udpc *udpc;
464 
465  if (!udp_running || udpc_list == NULL)
466  return 0;
467 
468  gwlist_lock(udpc_list);
469  for (i=0; i < gwlist_len(udpc_list); i++) {
470  udpc = gwlist_get(udpc_list, i);
471  q += gwlist_len(udpc->outgoing_list);
472  }
473  gwlist_unlock(udpc_list);
474  return q;
475 }
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
Definition: http.c:1998
struct _udpc Udpc
static int send_udp(int fd, Msg *msg)
Definition: bb_udp.c:190
Counter * incoming_wdp_counter
Definition: bearerbox.c:94
void gwlist_append(List *list, void *item)
Definition: list.c:179
int udp_addwdp(Msg *msg)
Definition: bb_udp.c:385
void gwlist_produce(List *list, void *item)
Definition: list.c:411
void gwthread_join(long thread)
long gwlist_len(List *list)
Definition: list.c:166
int udp_get_port(Octstr *addr)
Definition: socket.c:547
void * gwlist_get(List *list, long pos)
Definition: list.c:292
List * incoming_wdp
Definition: bearerbox.c:87
msg_type
Definition: msg.h:73
#define cfg_get(grp, varname)
Definition: cfg.h:86
#define msg_create(type)
Definition: msg.h:136
static List * udpc_list
Definition: bb_udp.c:97
int udp_outgoing_queue(void)
Definition: bb_udp.c:460
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static void udpc_destroy(Udpc *udpc)
Definition: bb_udp.c:277
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
int is_allowed_ip(Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
Definition: utils.c:815
Counter * outgoing_wdp_counter
Definition: bearerbox.c:95
void gwlist_unlock(List *list)
Definition: list.c:354
Definition: bb_udp.c:100
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
int udp_die(void)
Definition: bb_udp.c:434
Definition: msg.h:79
Definition: cfg.c:164
int udp_bind(int port, const char *source_addr)
Definition: socket.c:478
void * gwlist_extract_first(List *list)
Definition: list.c:305
void gwlist_remove_producer(List *list)
Definition: list.c:401
static void udp_receiver(void *arg)
Definition: bb_udp.c:123
List * outgoing_list
Definition: bb_udp.c:103
static Octstr * deny_ip
Definition: bb_udp.c:112
void msg_destroy(Msg *msg)
Definition: msg.c:132
void warning(int err, const char *fmt,...)
Definition: log.c:624
int udp_start(Cfg *cfg)
Definition: bb_udp.c:323
int udp_shutdown(void)
Definition: bb_udp.c:424
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
Octstr * addr
Definition: bb_udp.c:102
gw_assert(wtls_machine->packet_to_send!=NULL)
List * flow_threads
Definition: bearerbox.c:116
static int add_service(int port, char *interface_name)
Definition: bb_udp.c:292
static Octstr * allow_ip
Definition: bb_udp.c:111
void gwlist_lock(List *list)
Definition: list.c:347
static Cfg * cfg
Definition: smsbox.c:115
long receiver
Definition: bb_udp.c:104
static Udpc * udpc_create(int port, char *interface_name)
Definition: bb_udp.c:242
Definition: octstr.c:118
void * gwlist_consume(List *list)
Definition: list.c:427
int read_available(int fd, long wait_usec)
Definition: socket.c:406
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
volatile sig_atomic_t bb_status
Definition: bearerbox.c:132
void gwthread_wakeup(long thread)
Definition: cfg.c:73
static volatile sig_atomic_t udp_running
Definition: bb_udp.c:96
#define gwlist_create()
Definition: list.h:136
List * suspended
Definition: bearerbox.c:122
List * isolated
Definition: bearerbox.c:127
int udp_sendto(int s, Octstr *datagram, Octstr *addr)
Definition: socket.c:567
#define MAIN_THREAD_ID
Definition: gwthread.h:77
static Octstr * interface_name
Definition: wapproxy.c:111
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:636
void gwlist_add_producer(List *list)
Definition: list.c:383
List * octstr_split(const Octstr *os, const Octstr *sep)
Definition: octstr.c:1638
Definition: list.c:102
int fd
Definition: bb_udp.c:101
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static void udp_sender(void *arg)
Definition: bb_udp.c:205
int udp_recvfrom(int s, Octstr **datagram, Octstr **addr)
Definition: socket.c:582
Octstr * udp_create_address(Octstr *host_or_ip, int port)
Definition: socket.c:517
Octstr * udp_get_ip(Octstr *addr)
Definition: socket.c:557
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.