Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wapproxy.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  * wapproxy.c - an WDP, WSP, WTP layer proxy
59  *
60  * This module contains the main program for the WAP proxy box.
61  * It's intention is to sit between a WTP initiator and WTP repsonder
62  * and log all the UDP traffic that is send in a session.
63  *
64  * The architecture looks like this:
65  *
66  * ---------- UDP -------- UDP ------
67  * wap device ---> wapproxy ---> wap gw
68  * ---------- <--- -------- <--- ------
69  * port 51000 p 9201 p 51000 port 9201
70  * (a) (b)
71  *
72  * This means wapproxy gets the UDP/WDP packets that are actually to
73  * be transmitted to the real wap gw. It changes the source addr within
74  * that packet to reflect wapproxy has send it and binds to the port the
75  * wap device was sending the packet. Then the packet is send to the real
76  * wap gw and wapproxy listens on the client source port (i.e. 51000) for
77  * packets from the wap gw. When those are received the communication is
78  * inverted, which means wapproxy changes again the source addr from the
79  * value of wap gw to it's own and forwards the packet to the client source
80  * addr port.
81  *
82  * Hence the wap device uses wapproxy transparently without knowing that
83  * it is only a proxy and the packets are forwarded to other boxes.
84  *
85  * Stipe Tolj <stolj@wapme.de>
86  */
87 
88 #include <errno.h>
89 #include <stdlib.h>
90 #include <stdio.h>
91 #include <time.h>
92 #include <string.h>
93 #include <sys/time.h>
94 #include <sys/types.h>
95 #include <unistd.h>
96 #include <signal.h>
97 #include <fcntl.h>
98 #include <assert.h>
99 
100 #include "gwlib/gwlib.h"
101 #include "msg.h"
102 //#include "bearerbox.h"
103 #include "shared.h"
104 #include "wap/wap.h"
105 #include "wap/wtp.h"
106 #include "wap/wtp_pdu.h"
107 
108 /* globals */
109 static volatile sig_atomic_t udp_running;
110 static List *udpc_list;
111 static Octstr *interface_name = NULL;
112 static Octstr *wapgw;
113 static int verbose = 0;
114 static int server_port = 0;
115 
119 
122 
123 enum {
128 };
129 
130 /* structure for a UDP connection */
131 typedef struct _udpc {
132  int fd;
133  Octstr *addr;
136  long receiver;
137 } Udpc;
138 
139 /* forward declarations */
140 static void udpc_destroy(Udpc *udpc);
141 
142 
143 /*-------------------------------------------------------------
144  * analyze and dump functions
145  *
146  */
147 
149 {
150  WAPEvent *dgram = NULL;
151 
152  gw_assert(msg_type(msg) == wdp_datagram);
153 
154  if (msg->wdp_datagram.destination_port == server_port ||
155  msg->wdp_datagram.source_port == server_port ||
156  msg->wdp_datagram.destination_port == CONNECTION_ORIENTED_PORT ||
157  msg->wdp_datagram.source_port == CONNECTION_ORIENTED_PORT) {
158 
159  dgram = wap_event_create(T_DUnitdata_Ind);
160  dgram->u.T_DUnitdata_Ind.addr_tuple = wap_addr_tuple_create(
161  msg->wdp_datagram.source_address,
162  msg->wdp_datagram.source_port,
163  msg->wdp_datagram.destination_address,
164  msg->wdp_datagram.destination_port);
165  dgram->u.T_DUnitdata_Ind.user_data =
166  octstr_duplicate(msg->wdp_datagram.user_data);
167  }
168  return dgram;
169 }
170 
171 
172 static void wdp_event_dump(Msg *msg)
173 {
174  WAPEvent *dgram;
175 
176  if ((dgram = wdp_msg2event(msg)) != NULL)
177  /* wap_dispatch_datagram(dgram); */
178  wap_event_dump(dgram);
179 
180  wap_event_destroy(dgram);
181 }
182 
183 
184 static void wtp_event_dump(Msg *msg)
185 {
186  WAPEvent *dgram;
187  List *events;
188  long i, n;
189 
190  dgram = wdp_msg2event(msg);
191  if (dgram == NULL)
192  error(0, "dgram is null");
193 
194  /*
195  pdu = wtp_pdu_unpack(dgram->u.T_DUnitdata_Ind.user_data);
196  if (pdu == NULL) {
197  error(0, "WTP PDU unpacking failed, WAP event is:");
198  wap_event_dump(dgram);
199  } else {
200  wtp_pdu_dump(pdu, 0);
201  wtp_pdu_destroy(pdu);
202  }
203  */
204 
205  events = wtp_unpack_wdp_datagram(dgram);
206  n = gwlist_len(events);
207  debug("wap.proxy",0,"datagram contains %ld events", n);
208 
209  i = 1;
210  while (gwlist_len(events) > 0) {
211  WAPEvent *event;
212 
213  event = gwlist_extract_first(events);
214 
215  info(0, "WTP: %ld/%ld event %s.", i, n, wap_event_name(event->type));
216 
217  if (wtp_event_is_for_responder(event))
218  /* wtp_resp_dispatch_event(event); */
219  debug("",0,"datagram is for WTP responder");
220  else
221  /* wtp_initiator_dispatch_event(event); */
222  debug("",0,"datagram is for WTP initiator");
223 
224  wap_event_dump(event);
225  /*
226  switch (event->type) {
227  RcvInvoke:
228  debug("",0,"XXX invoke");
229  break;
230  RcvResult:
231  debug("",0,"XXX result");
232  break;
233  default:
234  error(0,"unkown WTP event type while unpacking");
235  break;
236  }
237  */
238  i++;
239  }
240 
241  wap_event_destroy(dgram);
242  gwlist_destroy(events, NULL);
243 }
244 
245 
246 static void dump(Msg *msg)
247 {
248  switch (verbose) {
249  case 0:
250  break;
251  case 1:
252  msg_dump(msg, 0);
253  break;
254  case 2:
255  wdp_event_dump(msg);
256  break;
257  case 3:
258  msg_dump(msg, 0);
259  wdp_event_dump(msg);
260  break;
261  case 4:
262  wtp_event_dump(msg);
263  break;
264  case 5:
265  msg_dump(msg, 0);
266  wtp_event_dump(msg);
267  break;
268  case 6:
269  wdp_event_dump(msg);
270  wtp_event_dump(msg);
271  break;
272  case 7:
273  msg_dump(msg, 0);
274  wdp_event_dump(msg);
275  wtp_event_dump(msg);
276  break;
277  }
278 }
279 
280 
281 /*-------------------------------------------------
282  * receiver thread
283  */
284 
285 static void udp_receiver(void *arg)
286 {
287  Octstr *datagram, *cliaddr;
288  int ret;
289  Msg *msg;
290  Udpc *conn = arg;
291  Octstr *ip;
292 
293  gwlist_add_producer(incoming_wdp);
294  gwlist_add_producer(flow_threads);
296 
297  /* remove messages from socket until it is closed */
298  while (1) {
299 
300  if (read_available(conn->fd, 100000) < 1)
301  continue;
302 
303  ret = udp_recvfrom(conn->fd, &datagram, &cliaddr);
304  if (ret == -1) {
305  if (errno == EAGAIN)
306  /* No datagram available, don't block. */
307  continue;
308 
309  error(errno, "Failed to receive an UDP");
310  continue;
311  }
312 
313  ip = udp_get_ip(cliaddr);
314  msg = msg_create(wdp_datagram);
315 
316  msg->wdp_datagram.source_address = udp_get_ip(cliaddr);
317  msg->wdp_datagram.source_port = udp_get_port(cliaddr);
318  msg->wdp_datagram.destination_address = udp_get_ip(conn->addr);
319  msg->wdp_datagram.destination_port = udp_get_port(conn->addr);
320  msg->wdp_datagram.user_data = datagram;
321 
322  info(0, "datagram received <%s:%d> -> <%s:%d>",
323  octstr_get_cstr(udp_get_ip(cliaddr)), udp_get_port(cliaddr),
325 
326  dump(msg);
327 
328  /*
329  * Descide if this is (a) or (b) UDP packet and add them to the
330  * corresponding queues
331  */
332  if (octstr_compare(conn->addr, conn->map_addr) == 0) {
333  gwlist_produce(incoming_wdp, msg);
334  counter_increase(incoming_wdp_counter);
335  } else {
336  gwlist_produce(outgoing_wdp, msg);
337  counter_increase(outgoing_wdp_counter);
338  }
339 
340  octstr_destroy(cliaddr);
341  octstr_destroy(ip);
342  }
343  gwlist_remove_producer(incoming_wdp);
344  gwlist_remove_producer(flow_threads);
345 }
346 
347 
348 /*---------------------------------------------
349  * sender thread
350  */
351 
352 static int send_udp(int fd, Msg *msg)
353 {
354  Octstr *cliaddr;
355  int ret;
356 
357  cliaddr = udp_create_address(msg->wdp_datagram.destination_address,
358  msg->wdp_datagram.destination_port);
359  ret = udp_sendto(fd, msg->wdp_datagram.user_data, cliaddr);
360  if (ret == -1)
361  error(0, "could not send UDP datagram");
362  octstr_destroy(cliaddr);
363  return ret;
364 }
365 
366 
367 static void udp_sender(void *arg)
368 {
369  Msg *msg;
370  Udpc *conn = arg;
371 
372  gwlist_add_producer(flow_threads);
373  while (1) {
374 
375  if ((msg = gwlist_consume(conn->outgoing_list)) == NULL)
376  break;
377 
378  info(0, "sending datagram <%s:%ld> -> <%s:%ld>",
379  octstr_get_cstr(msg->wdp_datagram.source_address),
380  msg->wdp_datagram.source_port,
381  octstr_get_cstr(msg->wdp_datagram.destination_address),
382  msg->wdp_datagram.destination_port);
383 
384  dump(msg);
385 
386  if (send_udp(conn->fd, msg) == -1) {
387  msg_destroy(msg);
388  continue;
389  }
390  counter_increase(outgoing_wdp_counter);
391  msg_destroy(msg);
392  }
393  gwthread_join(conn->receiver);
394 
395  udpc_destroy(conn);
396  gwlist_remove_producer(flow_threads);
397 }
398 
399 
400 /*---------------------------------------------------------------
401  * create UDP connection
402  */
403 
404 static Udpc *udpc_create(int port, char *interface_name, Octstr *map_addr)
405 {
406  Udpc *udpc;
407  Octstr *os;
408  int fl;
409 
410  udpc = gw_malloc(sizeof(Udpc));
411  udpc->fd = udp_bind(port, interface_name);
412 
413  os = octstr_create(interface_name);
414  udpc->addr = udp_create_address(os, port);
415  udpc->map_addr = map_addr ? map_addr : udpc->addr;
416 
417  octstr_destroy(os);
418  if (udpc->addr == NULL) {
419  error(0, "updc_create: could not resolve interface <%s>", interface_name);
420  close(udpc->fd);
421  gw_free(udpc);
422  return NULL;
423  }
424 
425  fl = fcntl(udpc->fd, F_GETFL);
426  fcntl(udpc->fd, F_SETFL, fl | O_NONBLOCK);
427 
428  os = udp_get_ip(udpc->addr);
429  debug("wap.proxy",0, "bound to UDP <%s:%d>",
430  octstr_get_cstr(os), udp_get_port(udpc->addr));
431 
432  octstr_destroy(os);
433 
434  udpc->outgoing_list = gwlist_create();
435 
436  return udpc;
437 }
438 
439 
440 static void udpc_destroy(Udpc *udpc)
441 {
442  if (udpc == NULL)
443  return;
444 
445  if (udpc->fd >= 0)
446  close(udpc->fd);
447  octstr_destroy(udpc->addr);
448  gw_assert(gwlist_len(udpc->outgoing_list) == 0);
449  gwlist_destroy(udpc->outgoing_list, NULL);
450 
451  gw_free(udpc);
452 }
453 
454 
455 static int add_service(int port, char *interface_name, Octstr *map_addr)
456 {
457  Udpc *udpc;
458 
459  if ((udpc = udpc_create(port, interface_name, map_addr)) == NULL)
460  goto error;
462 
463  udpc->receiver = gwthread_create(udp_receiver, udpc);
464  if (udpc->receiver == -1)
465  goto error;
466 
467  if (gwthread_create(udp_sender, udpc) == -1)
468  goto error;
469 
470  gwlist_append(udpc_list, udpc);
471  return 0;
472 
473 error:
474  error(0, "Failed to start UDP receiver/sender thread");
475  udpc_destroy(udpc);
476  return -1;
477 }
478 
479 
480 /*-------------------------------------------------------------
481  * main calling functions
482  *
483  */
484 
485 static int udp_start(Cfg *cfg)
486 {
487 
488  if (udp_running) return -1;
489 
490  debug("wap.proxy", 0, "starting UDP sender/receiver module");
491 
492  udpc_list = gwlist_create(); /* have a list of running systems */
493 
494  add_service(server_port, octstr_get_cstr(interface_name), NULL); /* wsp/wtp */
495 
496  gwlist_add_producer(incoming_wdp);
497  udp_running = 1;
498  return 0;
499 }
500 
501 
502 static Udpc *udpc_find_mapping(Msg *msg, int inbound)
503 {
504  int i;
505  Udpc *udpc;
506  Octstr *addr;
507 
508  /* check if there is allready a bound UDP port */
509  gwlist_lock(udpc_list);
510  for (i=0; i < gwlist_len(udpc_list); i++) {
511  udpc = gwlist_get(udpc_list, i);
512 
513  /* decide if we compare against inbound or outbound traffic mapping */
514  addr = inbound ? udpc->map_addr : udpc->addr;
515 
516  if (msg->wdp_datagram.source_port == udp_get_port(addr) &&
517  octstr_compare(msg->wdp_datagram.source_address,
518  udp_get_ip(addr)) == 0) {
519  gwlist_unlock(udpc_list);
520  return udpc;
521  }
522  }
523  gwlist_unlock(udpc_list);
524  return NULL;
525 }
526 
527 
528 /*
529  * this function receives an WDP message and adds it to
530  * corresponding outgoing_list.
531  */
533 {
534  Udpc *udpc;
535  Octstr *os;
536  Octstr *source;
537 
538  if (!udp_running) return -1;
539  assert(msg != NULL);
540  assert(msg_type(msg) == wdp_datagram);
541 
542  octstr_destroy(msg->wdp_datagram.source_address);
543  msg->wdp_datagram.source_address =
544  octstr_create(octstr_get_cstr(msg->wdp_datagram.destination_address));
545  msg->wdp_datagram.source_port = msg->wdp_datagram.destination_port;
546 
547  if ((udpc = udpc_find_mapping(msg, 0)) == NULL)
548  /* there should have been one */
549  panic(0,"Could not find UDP mapping, internal error");
550 
551  /* insert the found mapped destination */
552  octstr_destroy(msg->wdp_datagram.source_address);
553  octstr_destroy(msg->wdp_datagram.destination_address);
554 
555  msg->wdp_datagram.destination_address = udp_get_ip(udpc->map_addr);
556  msg->wdp_datagram.destination_port = udp_get_port(udpc->map_addr);
557 
558  /* now search for our inbound UDP socket */
559  os = octstr_duplicate(interface_name);
560  source = udp_create_address(os, server_port);
561 
562  msg->wdp_datagram.source_address = udp_get_ip(source);
563  msg->wdp_datagram.source_port = udp_get_port(source);
564  if ((udpc = udpc_find_mapping(msg, 0)) == NULL)
565  panic(0,"Could not find main inbound UDP socket, internal error");
566 
567  /*
568  * ok, got the destination, got the socket,
569  * now put it on the outbound queue
570  */
571  gwlist_produce(udpc->outgoing_list, msg);
572 
573  octstr_destroy(os);
574 
575  return 0;
576 }
577 
578 
579 /*
580  * this function receives an WDP message and checks if a UDP
581  * service for this client has to be created
582  */
584 {
585  Udpc *udpc;
586  Octstr *map_addr;
587  Octstr *os;
588  Octstr *source;
589 
590  if (!udp_running) return -1;
591  assert(msg != NULL);
592  assert(msg_type(msg) == wdp_datagram);
593 
594  /*
595  * Check if there is allready a bound UDP port for this mapping.
596  * If not create a mapping and bind the mapped UDP port
597  * The mapped port is simply 2x of the client port.
598  */
599  if ((udpc = udpc_find_mapping(msg, 1)) == NULL) {
600  info(0, "Creating UDP mapping <%s:%ld> <-> <%s:%ld>",
601  octstr_get_cstr(msg->wdp_datagram.source_address),
602  msg->wdp_datagram.source_port,
603  octstr_get_cstr(msg->wdp_datagram.destination_address),
604  msg->wdp_datagram.source_port*2);
605 
606  map_addr = udp_create_address(msg->wdp_datagram.source_address,
607  msg->wdp_datagram.source_port);
608  add_service(msg->wdp_datagram.source_port * 2,
609  octstr_get_cstr(interface_name), map_addr);
610  /* now we should find it in the udpc_list */
611  if ((udpc = udpc_find_mapping(msg, 1)) == NULL)
612  panic(0,"Could not find UDP mapping, internal error");
613  }
614 
615  /* now swap the message addressing */
616  octstr_destroy(msg->wdp_datagram.source_address);
617  octstr_destroy(msg->wdp_datagram.destination_address);
618 
619  os = octstr_duplicate(interface_name);
620  source = udp_create_address(os, msg->wdp_datagram.source_port * 2);
621  msg->wdp_datagram.source_address = udp_get_ip(source);
622  msg->wdp_datagram.source_port = udp_get_port(source);
623  msg->wdp_datagram.destination_address = octstr_duplicate(wapgw);
624  msg->wdp_datagram.destination_port = CONNECTION_ORIENTED_PORT;
625 
626  octstr_destroy(os);
627 
628  gwlist_produce(udpc->outgoing_list, msg);
629 
630  return -1;
631 }
632 
633 
634 static int udp_shutdown(void)
635 {
636  if (!udp_running) return -1;
637 
638  debug("bb.thread", 0, "udp_shutdown: Starting avalanche");
639  gwlist_remove_producer(incoming_wdp);
640  return 0;
641 }
642 
643 
644 static int udp_die(void)
645 {
646  Udpc *udpc;
647 
648  if (!udp_running) return -1;
649 
650  /*
651  * remove producers from all outgoing lists.
652  */
653  debug("bb.udp", 0, "udp_die: removing producers from udp-lists");
654 
655  while ((udpc = gwlist_consume(udpc_list)) != NULL) {
657  }
658  gwlist_destroy(udpc_list, NULL);
659  udp_running = 0;
660 
661  return 0;
662 }
663 
664 
665 /*-------------------------------------------------------------
666  * main consumer threads
667  *
668  */
669 
670 static void wdp_router(void *arg)
671 {
672  Msg *msg;
673 
674  gwlist_add_producer(flow_threads);
675 
676  while (1) {
677 
678  if ((msg = gwlist_consume(outgoing_wdp)) == NULL)
679  break;
680 
681  gw_assert(msg_type(msg) == wdp_datagram);
682 
684  }
685  udp_die();
686 
687  gwlist_remove_producer(flow_threads);
688 }
689 
690 
691 static void service_router(void *arg)
692 {
693  Msg *msg;
694 
695  gwlist_add_producer(flow_threads);
696 
697  while (1) {
698 
699  if ((msg = gwlist_consume(incoming_wdp)) == NULL)
700  break;
701 
702  gw_assert(msg_type(msg) == wdp_datagram);
703 
705  }
706  udp_die();
707 
708  gwlist_remove_producer(flow_threads);
709 }
710 
711 
712 /*-------------------------------------------------------------
713  * main functions
714  *
715  */
716 
717 static void help(void)
718 {
719  info(0, "Usage: wapproxy [options] host ...");
720  info(0, "where host is the real wap gw to forward to and options are:");
721  info(0, "-v number");
722  info(0, " set log level for stderr logging");
723  info(0, "-i interface");
724  info(0, " bind to the given interface for UDP server port (default: 0.0.0.0)");
725  info(0, "-p port");
726  info(0, " bind to the given port for UDP server port (default: 9201)");
727  info(0, "-m");
728  info(0, " dump WDP/UDP packets, msg_dump()");
729  info(0, "-e");
730  info(0, " dump WAP event packets, wap_event_dump()");
731  info(0, "-t");
732  info(0, " dump WTP PDUs, wtp_pdu_dump()");
733 }
734 
735 
736 int main(int argc, char **argv)
737 {
738  int opt;
739  Cfg *cfg = NULL;
740 
741  gwlib_init();
742 
744 
745  while ((opt = getopt(argc, argv, "v:meti:p:")) != EOF) {
746 
747  switch (opt) {
748  case 'v':
750  break;
751 
752  case 'm':
753  verbose += 1;
754  break;
755 
756  case 'e':
757  verbose += 2;
758  break;
759 
760  case 't':
761  verbose += 4;
762  break;
763 
764  case 'h':
765  help();
766  exit(0);
767 
768  case 'i':
769  interface_name = octstr_create(optarg);
770  break;
771 
772  case 'p':
773  server_port = atoi(optarg);
774  break;
775 
776  case '?':
777  default:
778  error(0, "Invalid option %c", opt);
779  help();
780  panic(0, "Stopping.");
781  }
782  }
783 
784  if (optind == argc) {
785  help();
786  exit(0);
787  }
788 
789  /* get the host or IP of the real wap gw to forward the WDP packets */
790  wapgw = octstr_create(argv[optind]);
791 
792  /* if no interface was given use 0.0.0.0 */
793  if (!interface_name)
794  interface_name = octstr_create("*");
795 
796  report_versions("wapproxy");
797 
798  /* initialize main inbound and outbound queues */
799  outgoing_wdp = gwlist_create();
800  incoming_wdp = gwlist_create();
801  flow_threads = gwlist_create();
802 
803  outgoing_wdp_counter = counter_create();
804  incoming_wdp_counter = counter_create();
805 
806  /* start the main UDP listening threads */
807  udp_start(cfg);
808 
809  gwlist_add_producer(outgoing_wdp);
810 
811  debug("bb", 0, "starting WDP routers");
812  if (gwthread_create(service_router, NULL) == -1)
813  panic(0, "Failed to start a new thread for inbound WDP routing");
814  if (gwthread_create(wdp_router, NULL) == -1)
815  panic(0, "Failed to start a new thread for outbound WDP routing");
816 
817  gwthread_sleep(5.0); /* give time to threads to register themselves */
818 
819  while (gwlist_consume(flow_threads) != NULL)
820  ;
821 
822  udp_shutdown();
823 
824  gwlist_remove_producer(outgoing_wdp);
825 
826  gwlist_destroy(flow_threads, NULL);
827  gwlist_destroy(incoming_wdp, NULL);
828  gwlist_destroy(outgoing_wdp, NULL);
829 
830  counter_destroy(incoming_wdp_counter);
831  counter_destroy(outgoing_wdp_counter);
832  octstr_destroy(interface_name);
833  octstr_destroy(wapgw);
834 
835  gwlib_shutdown();
836 
837  return 0;
838 }
void msg_dump(Msg *msg, int level)
Definition: msg.c:152
void error(int err, const char *fmt,...)
Definition: log.c:612
List * wtp_unpack_wdp_datagram(WAPEvent *datagram)
Definition: wtp.c:98
void info(int err, const char *fmt,...)
Definition: log.c:636
static int server_port
Definition: wapproxy.c:114
static Udpc * udpc_find_mapping(Msg *msg, int inbound)
Definition: wapproxy.c:502
Definition: http.c:1998
static int udp_start(Cfg *cfg)
Definition: wapproxy.c:485
static void wtp_event_dump(Msg *msg)
Definition: wapproxy.c:184
void counter_destroy(Counter *counter)
Definition: counter.c:110
void gwlist_append(List *list, void *item)
Definition: list.c:179
static void wdp_event_dump(Msg *msg)
Definition: wapproxy.c:172
static void dump(Msg *msg)
Definition: wapproxy.c:246
void gwlist_produce(List *list, void *item)
Definition: list.c:411
static Octstr * wapgw
Definition: wapproxy.c:112
void gwthread_join(long thread)
static int udp_addwdp_from_server(Msg *msg)
Definition: wapproxy.c:532
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
msg_type
Definition: msg.h:73
int main(int argc, char **argv)
Definition: wapproxy.c:736
int optind
Definition: attgetopt.c:80
#define msg_create(type)
Definition: msg.h:136
List * incoming_wdp
Definition: wapproxy.c:116
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void wap_event_dump(WAPEvent *event)
Definition: wap_events.c:181
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
List * outgoing_wdp
Definition: wapproxy.c:117
void gwlist_unlock(List *list)
Definition: list.c:354
int getopt(int argc, char **argv, char *opts)
Definition: attgetopt.c:84
Definition: bb_udp.c:100
static void udpc_destroy(Udpc *udpc)
Definition: wapproxy.c:440
static int udp_shutdown(void)
Definition: wapproxy.c:634
Definition: msg.h:79
Definition: cfg.c:164
static List * udpc_list
Definition: wapproxy.c:110
int udp_bind(int port, const char *source_addr)
Definition: socket.c:478
Counter * counter_create(void)
Definition: counter.c:94
static int udp_addwdp_from_client(Msg *msg)
Definition: wapproxy.c:583
void * gwlist_extract_first(List *list)
Definition: list.c:305
void log_set_output_level(enum output_level level)
Definition: log.c:217
static void help(void)
Definition: wapproxy.c:717
List * flow_threads
Definition: wapproxy.c:118
void gwlist_remove_producer(List *list)
Definition: list.c:401
List * outgoing_list
Definition: bb_udp.c:103
int wtp_event_is_for_responder(WAPEvent *event)
Definition: wtp.c:156
static volatile sig_atomic_t udp_running
Definition: wapproxy.c:109
#define octstr_duplicate(ostr)
Definition: octstr.h:187
const char * wap_event_name(WAPEventName type)
Definition: wap_events.c:169
void msg_destroy(Msg *msg)
Definition: msg.c:132
struct _udpc Udpc
#define wap_event_create(type)
Definition: wap_events.h:107
static void udp_receiver(void *arg)
Definition: wapproxy.c:285
static int udp_die(void)
Definition: wapproxy.c:644
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)
void gwthread_sleep(double seconds)
static WAPEvent * wdp_msg2event(Msg *msg)
Definition: wapproxy.c:148
void gwlist_lock(List *list)
Definition: list.c:347
Octstr * map_addr
Definition: wapproxy.c:134
void report_versions(const char *boxname)
Definition: utils.c:539
static Cfg * cfg
Definition: smsbox.c:115
long receiver
Definition: bb_udp.c:104
Definition: octstr.c:118
static int verbose
Definition: wapproxy.c:113
void * gwlist_consume(List *list)
Definition: list.c:427
int read_available(int fd, long wait_usec)
Definition: socket.c:406
Counter * outgoing_wdp_counter
Definition: wapproxy.c:121
static int send_udp(int fd, Msg *msg)
Definition: wapproxy.c:352
static void wdp_router(void *arg)
Definition: wapproxy.c:670
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
char * optarg
Definition: attgetopt.c:82
#define panic
Definition: log.h:87
void gwthread_wakeup(long thread)
WAPAddrTuple * wap_addr_tuple_create(Octstr *rmt_addr, long rmt_port, Octstr *lcl_addr, long lcl_port)
Definition: wap_addr.c:96
WAPEventName type
Definition: wap_events.h:88
void gwlib_shutdown(void)
Definition: gwlib.c:94
#define gwlist_create()
Definition: list.h:136
static void udp_sender(void *arg)
Definition: wapproxy.c:367
int udp_sendto(int s, Octstr *datagram, Octstr *addr)
Definition: socket.c:567
void gwlib_init(void)
Definition: gwlib.c:78
Counter * incoming_wdp_counter
Definition: wapproxy.c:120
#define MAIN_THREAD_ID
Definition: gwthread.h:77
static Octstr * interface_name
Definition: wapproxy.c:111
static void service_router(void *arg)
Definition: wapproxy.c:691
void gwlist_add_producer(List *list)
Definition: list.c:383
union WAPEvent::@87 u
static Udpc * udpc_create(int port, char *interface_name, Octstr *map_addr)
Definition: wapproxy.c:404
Definition: list.c:102
int fd
Definition: bb_udp.c:101
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static int add_service(int port, char *interface_name, Octstr *map_addr)
Definition: wapproxy.c:455
int udp_recvfrom(int s, Octstr **datagram, Octstr **addr)
Definition: socket.c:582
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102
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.