FreeSWITCH API Documentation  1.7.0
Data Structures | Macros | Functions | Variables
switch_nat.c File Reference
#include <switch.h>
#include "../libs/miniupnpc/miniwget.h"
#include "../libs/miniupnpc/miniupnpc.h"
#include "../libs/miniupnpc/upnpcommands.h"
#include "../libs/miniupnpc/upnperrors.h"
#include "../libs/libnatpmp/natpmp.h"
+ Include dependency graph for switch_nat.c:

Go to the source code of this file.

Data Structures

struct  nat_globals_t
 
struct  nat_globals_perm_t
 

Macros

#define MULTICAST_BUFFSIZE   65536
 
#define IP_LEN   16
 
#define NAT_REFRESH_INTERVAL   900
 

Functions

static switch_status_t get_upnp_pubaddr (char *pub_addr)
 
static int init_upnp (void)
 
static int get_pmp_pubaddr (char *pub_addr)
 
static int init_pmp (void)
 
void switch_nat_set_mapping (switch_bool_t mapping)
 Update the setting if port mapping will be created. More...
 
void switch_nat_reinit (void)
 re-initializes NAT subsystem More...
 
switch_status_t init_nat_monitor (switch_memory_pool_t *pool)
 
static void *SWITCH_THREAD_FUNC switch_nat_multicast_runtime (switch_thread_t *thread, void *obj)
 
void switch_nat_thread_start (void)
 
void switch_nat_thread_stop (void)
 
void switch_nat_init (switch_memory_pool_t *pool, switch_bool_t mapping)
 Initilize the NAT Traversal System. More...
 
static switch_status_t switch_nat_add_mapping_pmp (switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t *external_port)
 
static switch_status_t switch_nat_add_mapping_upnp (switch_port_t port, switch_nat_ip_proto_t proto)
 
static switch_status_t switch_nat_del_mapping_pmp (switch_port_t port, switch_nat_ip_proto_t proto)
 
static switch_status_t switch_nat_del_mapping_upnp (switch_port_t port, switch_nat_ip_proto_t proto)
 
const char * switch_nat_get_type (void)
 
switch_status_t switch_nat_add_mapping_internal (switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t *external_port, switch_bool_t sticky, switch_bool_t publish)
 
switch_status_t switch_nat_add_mapping (switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t *external_port, switch_bool_t sticky)
 Maps a port through the NAT Traversal System. More...
 
switch_status_t switch_nat_del_mapping (switch_port_t port, switch_nat_ip_proto_t proto)
 Deletes a NAT mapping. More...
 
void switch_nat_republish (void)
 Republishes the nap mappings. More...
 
 SWITCH_STANDARD_SCHED_FUNC (switch_nat_republish_sched)
 
void switch_nat_late_init (void)
 Initilize the rest of the NAT Traversal System. More...
 
char * switch_nat_status (void)
 Returns a list of nat mappings and other status info. More...
 
switch_bool_t switch_nat_is_initialized (void)
 Has the NAT subsystem been initialized. More...
 
void switch_nat_shutdown (void)
 Shuts down the NAT Traversal System. More...
 

Variables

static nat_globals_t nat_globals
 
static nat_globals_perm_t nat_globals_perm
 
static switch_bool_t first_init = SWITCH_TRUE
 
static switch_bool_t initialized = SWITCH_FALSE
 
switch_thread_tnat_thread_p = NULL
 

Macro Definition Documentation

#define IP_LEN   16
#define MULTICAST_BUFFSIZE   65536

Definition at line 42 of file switch_nat.c.

Referenced by switch_nat_multicast_runtime().

#define NAT_REFRESH_INTERVAL   900

Definition at line 44 of file switch_nat.c.

Referenced by switch_nat_late_init(), and SWITCH_STANDARD_SCHED_FUNC().

Function Documentation

static int get_pmp_pubaddr ( char *  pub_addr)
static

Definition at line 147 of file switch_nat.c.

References IP_LEN, nat_globals_t::nat_type, SWITCH_CHANNEL_LOG, switch_copy_string(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_NAT_TYPE_PMP, SWITCH_POLL_ERROR, SWITCH_POLL_HUP, SWITCH_POLL_READ, and switch_wait_sock().

Referenced by init_pmp(), and switch_nat_multicast_runtime().

148 {
149  int r = 0, i = 0, max = 5;
150  natpmpresp_t response;
151  char *pubaddr = NULL;
152  natpmp_t natpmp;
153  const char *err = NULL;
154  int pflags;
155 
156  if ((r = initnatpmp(&natpmp)) < 0) {
157  err = "init failed";
158  goto end;
159  }
160 
161  if ((r = sendpublicaddressrequest(&natpmp)) < 0) {
162  err = "pub addr req failed";
163  goto end;
164  }
165 
166  do {
167  struct timeval timeout = { 1, 0 };
168 
169  i++;
170  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for PMP %d/%d\n", i, max);
171  if ((r = getnatpmprequesttimeout(&natpmp, &timeout)) < 0) {
172  err = "get timeout failed";
173  goto end;
174  }
175 
177 
178  if ((pflags & SWITCH_POLL_ERROR) || (pflags & SWITCH_POLL_HUP)) {
179  err = "wait sock failed";
180  goto end;
181  }
182  r = readnatpmpresponseorretry(&natpmp, &response);
183  } while (r == NATPMP_TRYAGAIN && i < max);
184 
185  if (r < 0) {
186  err = "general error";
187  goto end;
188  }
189 
190  pubaddr = inet_ntoa(response.pnu.publicaddress.addr);
191  switch_copy_string(pub_addr, pubaddr, IP_LEN);
193 
194  closenatpmp(&natpmp);
195 
196  end:
197 
198  if (err) {
199  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error checking for PMP [%s]\n", err);
200  }
201 
202  return r;
203 }
#define SWITCH_CHANNEL_LOG
#define IP_LEN
Definition: switch_nat.c:43
int switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags)
switch_nat_type_t nat_type
Definition: switch_nat.c:47
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static nat_globals_t nat_globals
Definition: switch_nat.c:57
static switch_status_t get_upnp_pubaddr ( char *  pub_addr)
static

Definition at line 71 of file switch_nat.c.

References nat_globals_t::data, SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, nat_globals_t::urls, and zstr_buf.

Referenced by init_upnp(), and switch_nat_multicast_runtime().

72 {
73  if (UPNP_GetExternalIPAddress(nat_globals.urls.controlURL, nat_globals.data.servicetype, pub_addr) == UPNPCOMMAND_SUCCESS) {
74  if (!strcmp(pub_addr, "0.0.0.0") || zstr_buf(pub_addr)) {
76  "uPNP Device (url: %s) returned an invalid external address of '%s'. Disabling uPNP\n", nat_globals.urls.controlURL,
77  pub_addr);
78  return SWITCH_STATUS_GENERR;
79  }
80  } else {
81  return SWITCH_STATUS_GENERR;
82  }
83  return SWITCH_STATUS_SUCCESS;
84 }
#define SWITCH_CHANNEL_LOG
struct UPNPUrls urls
Definition: switch_nat.c:49
struct IGDdatas data
Definition: switch_nat.c:50
#define zstr_buf(s)
Definition: switch_utils.h:285
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static nat_globals_t nat_globals
Definition: switch_nat.c:57
switch_status_t init_nat_monitor ( switch_memory_pool_t pool)

Definition at line 220 of file switch_nat.c.

References nat_globals_perm_t::maddress, nat_globals_perm_t::msocket, nat_globals_t::nat_type, SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_mcast_join(), SWITCH_NAT_TYPE_PMP, SWITCH_NAT_TYPE_UPNP, SWITCH_SO_NONBLOCK, SWITCH_SO_REUSEADDR, switch_sockaddr_info_get(), switch_socket_bind(), switch_socket_close(), switch_socket_create(), switch_socket_opt_set(), SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TERM, SWITCH_UNSPEC, and TRUE.

Referenced by switch_nat_thread_start().

221 {
222  char *addr = NULL;
223  switch_port_t port = 0;
224 
226  addr = "239.255.255.250";
227  port = 1900;
228  } else if (nat_globals.nat_type == SWITCH_NAT_TYPE_PMP) {
229  addr = "224.0.0.1";
230  port = 5350;
231  }
232 
234  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find address\n");
235  return SWITCH_STATUS_TERM;
236  }
237 
238  if (switch_socket_create(&nat_globals_perm.msocket, AF_INET, SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) {
240  return SWITCH_STATUS_TERM;
241  }
242 
244  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Option Error\n");
246  return SWITCH_STATUS_TERM;
247  }
248 
252  return SWITCH_STATUS_TERM;
253  }
254 
258  return SWITCH_STATUS_TERM;
259  }
260 
262  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread configured\n");
263  return SWITCH_STATUS_SUCCESS;
264 }
#define SWITCH_CHANNEL_LOG
switch_status_t switch_socket_bind(switch_socket_t *sock, switch_sockaddr_t *sa)
Definition: switch_apr.c:719
switch_memory_pool_t * pool
switch_socket_t * msocket
Definition: switch_nat.c:63
switch_status_t switch_socket_opt_set(switch_socket_t *sock, int32_t opt, int32_t on)
Definition: switch_apr.c:823
uint16_t switch_port_t
switch_nat_type_t nat_type
Definition: switch_nat.c:47
switch_sockaddr_t * maddress
Definition: switch_nat.c:62
switch_status_t switch_socket_create(switch_socket_t **new_sock, int family, int type, int protocol, switch_memory_pool_t *pool)
Definition: switch_apr.c:704
#define SWITCH_SO_NONBLOCK
Definition: switch_apr.h:994
switch_status_t switch_socket_close(switch_socket_t *sock)
Definition: switch_apr.c:714
#define SWITCH_UNSPEC
Definition: switch_apr.h:1022
static nat_globals_perm_t nat_globals_perm
Definition: switch_nat.c:66
#define SWITCH_SO_REUSEADDR
Definition: switch_apr.h:995
switch_status_t switch_mcast_join(switch_socket_t *sock, switch_sockaddr_t *join, switch_sockaddr_t *iface, switch_sockaddr_t *source)
Definition: switch_apr.c:871
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define TRUE
switch_status_t switch_sockaddr_info_get(switch_sockaddr_t **sa, const char *hostname, int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:817
static nat_globals_t nat_globals
Definition: switch_nat.c:57
static int init_pmp ( void  )
static

Definition at line 205 of file switch_nat.c.

References get_pmp_pubaddr(), and nat_globals_t::pub_addr.

Referenced by switch_nat_init().

206 {
208 }
static int get_pmp_pubaddr(char *pub_addr)
Definition: switch_nat.c:147
char pub_addr[IP_LEN]
Definition: switch_nat.c:52
static nat_globals_t nat_globals
Definition: switch_nat.c:57
static int init_upnp ( void  )
static

Definition at line 86 of file switch_nat.c.

References nat_globals_t::data, nat_globals_t::descURL, get_upnp_pubaddr(), memset(), nat_globals_t::nat_type, nat_globals_t::pub_addr, SWITCH_CHANNEL_LOG, switch_core_get_variable(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_NAT_TYPE_UPNP, SWITCH_STATUS_SUCCESS, switch_stristr(), and nat_globals_t::urls.

Referenced by switch_nat_init().

87 {
88  struct UPNPDev *devlist;
89  struct UPNPDev *dev = NULL;
90  struct UPNPDev *trydev = NULL;
91  char *descXML;
92  int descXMLsize = 0;
93  const char *minissdpdpath = switch_core_get_variable("local_ip_v4");
94 
95  memset(&nat_globals.urls, 0, sizeof(struct UPNPUrls));
96  memset(&nat_globals.data, 0, sizeof(struct IGDdatas));
97 
98  devlist = upnpDiscover(3000, minissdpdpath, minissdpdpath, 0);
99 
100  if (devlist) {
101  dev = devlist;
102  while (dev) {
103  if (strstr(dev->st, "InternetGatewayDevice")) {
104  break;
105  }
106  if (!trydev && !switch_stristr("printer", dev->descURL)) {
107  trydev = dev;
108  }
109 
110  dev = dev->pNext;
111  }
112 
113  }
114 
115  if (!dev && trydev) {
116  dev = trydev; /* defaulting to first device */
117  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No InternetGatewayDevice, using first entry as default (%s).\n", dev->descURL);
118  } else if (devlist && !dev && !trydev) {
119  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No InternetGatewayDevice found and I am NOT going to try your printer because printers should not route to the internet, that would be DAFT\n");
120  }
121 
122  if (dev) {
123  descXML = miniwget(dev->descURL, &descXMLsize);
124 
125  nat_globals.descURL = strdup(dev->descURL);
126 
127  if (descXML) {
128  parserootdesc(descXML, descXMLsize, &nat_globals.data);
129  free(descXML);
130  descXML = 0;
131  GetUPNPUrls(&nat_globals.urls, &nat_globals.data, dev->descURL);
132  } else {
133  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unable to retrieve device description XML (%s).\n", dev->descURL);
134  }
135 
136  freeUPNPDevlist(devlist);
137  }
138 
141  return 0;
142  }
143 
144  return -2;
145 }
#define SWITCH_CHANNEL_LOG
struct UPNPUrls urls
Definition: switch_nat.c:49
struct IGDdatas data
Definition: switch_nat.c:50
char * descURL
Definition: switch_nat.c:51
switch_nat_type_t nat_type
Definition: switch_nat.c:47
char * switch_core_get_variable(_In_z_ const char *varname)
Retrieve a global variable from the core.
char pub_addr[IP_LEN]
Definition: switch_nat.c:52
static switch_status_t get_upnp_pubaddr(char *pub_addr)
Definition: switch_nat.c:71
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
const char * switch_stristr(const char *instr, const char *str)
static nat_globals_t nat_globals
Definition: switch_nat.c:57
memset(buf, 0, buflen)
switch_status_t switch_nat_add_mapping_internal ( switch_port_t  port,
switch_nat_ip_proto_t  proto,
switch_port_t external_port,
switch_bool_t  sticky,
switch_bool_t  publish 
)

Definition at line 580 of file switch_nat.c.

References initialized, nat_globals_t::mapping, nat_globals_t::nat_type, SWITCH_CHANNEL_LOG, switch_event_add_header(), switch_event_add_header_string(), switch_event_create, switch_event_fire, SWITCH_EVENT_NAT, SWITCH_LOG_INFO, switch_log_printf(), switch_nat_add_mapping_pmp(), switch_nat_add_mapping_upnp(), SWITCH_NAT_TYPE_PMP, SWITCH_NAT_TYPE_UPNP, SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_nat_add_mapping(), and switch_nat_republish().

582 {
584  switch_event_t *event = NULL;
585 
586  if (!initialized || !nat_globals.nat_type) return status;
587  if (!nat_globals.mapping) {
588  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "NAT port mapping disabled\n");
589  return status;
590  }
591 
592  switch (nat_globals.nat_type) {
593  case SWITCH_NAT_TYPE_PMP:
594  status = switch_nat_add_mapping_pmp(port, proto, external_port);
595  break;
597  if ((status = switch_nat_add_mapping_upnp(port, proto)) == SWITCH_STATUS_SUCCESS) {
598  if (external_port) {
599  *external_port = port;
600  }
601  }
602  break;
603  default:
604  break;
605  }
606 
607  if (publish && status == SWITCH_STATUS_SUCCESS) {
610  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "port", "%d", port);
611  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "%d", proto);
612  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sticky", (sticky ? "true" : "false"));
613  switch_event_fire(&event);
614  }
615 
616  return status;
617 }
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define SWITCH_CHANNEL_LOG
switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt,...) PRINTF_FUNCTION(4
Add a header to an event.
Representation of an event.
Definition: switch_event.h:80
static switch_status_t switch_nat_add_mapping_upnp(switch_port_t port, switch_nat_ip_proto_t proto)
Definition: switch_nat.c:491
switch_bool_t mapping
Definition: switch_nat.c:54
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
switch_nat_type_t nat_type
Definition: switch_nat.c:47
switch_status_t
Common return values.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static switch_bool_t initialized
Definition: switch_nat.c:69
static nat_globals_t nat_globals
Definition: switch_nat.c:57
static switch_status_t switch_nat_add_mapping_pmp(switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t *external_port)
Definition: switch_nat.c:444
static switch_status_t switch_nat_add_mapping_pmp ( switch_port_t  port,
switch_nat_ip_proto_t  proto,
switch_port_t external_port 
)
static

Definition at line 444 of file switch_nat.c.

References SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, switch_log_printf(), SWITCH_NAT_TCP, SWITCH_NAT_UDP, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_nat_add_mapping_internal().

445 {
447  natpmpresp_t response;
448  int r;
449  natpmp_t natpmp;
450 
451  initnatpmp(&natpmp);
452 
453  if (proto == SWITCH_NAT_TCP) {
454  sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, port, port, 31104000);
455  } else if (proto == SWITCH_NAT_UDP) {
456  sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 31104000);
457  }
458 
459  do {
460  fd_set fds;
461  struct timeval timeout = { 1, 0 };
462  FD_ZERO(&fds);
463  FD_SET(natpmp.s, &fds);
464  getnatpmprequesttimeout(&natpmp, &timeout);
465  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
466  r = readnatpmpresponseorretry(&natpmp, &response);
467  } while (r == NATPMP_TRYAGAIN);
468 
469  if (r == 0) {
470  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "mapped public port %hu protocol %s to localport %hu\n",
471  response.pnu.newportmapping.mappedpublicport,
472  response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" :
473  (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : "UNKNOWN"), response.pnu.newportmapping.privateport);
474  if (external_port) {
475  *external_port = response.pnu.newportmapping.mappedpublicport;
476  } else if (response.pnu.newportmapping.mappedpublicport != response.pnu.newportmapping.privateport) {
477  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "External port %hu protocol %s was not available, it was instead mapped to %hu\n",
478  response.pnu.newportmapping.privateport,
479  response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" :
480  (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : "UNKNOWN"), response.pnu.newportmapping.mappedpublicport);
481  }
482 
483  status = SWITCH_STATUS_SUCCESS;
484  }
485 
486  closenatpmp(&natpmp);
487 
488  return status;
489 }
#define SWITCH_CHANNEL_LOG
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static switch_status_t switch_nat_add_mapping_upnp ( switch_port_t  port,
switch_nat_ip_proto_t  proto 
)
static

Definition at line 491 of file switch_nat.c.

References nat_globals_t::data, IP_LEN, nat_globals_t::pvt_addr, SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_NAT_TCP, SWITCH_NAT_UDP, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and nat_globals_t::urls.

Referenced by switch_nat_add_mapping_internal().

492 {
494  char port_str[IP_LEN];
495  int r = UPNPCOMMAND_UNKNOWN_ERROR;
496 
497  sprintf(port_str, "%d", port);
498 
499  if (proto == SWITCH_NAT_TCP) {
500  r = UPNP_AddPortMapping(nat_globals.urls.controlURL, nat_globals.data.servicetype, port_str, port_str,
501  nat_globals.pvt_addr, "FreeSWITCH", "TCP", 0);
502  } else if (proto == SWITCH_NAT_UDP) {
503  r = UPNP_AddPortMapping(nat_globals.urls.controlURL, nat_globals.data.servicetype, port_str, port_str,
504  nat_globals.pvt_addr, "FreeSWITCH", "UDP", 0);
505  }
506 
507  if (r == UPNPCOMMAND_SUCCESS) {
508  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mapped public port %s protocol %s to localport %s\n", port_str,
509  (proto == SWITCH_NAT_TCP) ? "TCP" : (proto == SWITCH_NAT_UDP ? "UDP" : "UNKNOWN"), port_str);
510  status = SWITCH_STATUS_SUCCESS;
511  }
512 
513  return status;
514 }
#define SWITCH_CHANNEL_LOG
#define IP_LEN
Definition: switch_nat.c:43
struct UPNPUrls urls
Definition: switch_nat.c:49
struct IGDdatas data
Definition: switch_nat.c:50
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static nat_globals_t nat_globals
Definition: switch_nat.c:57
char pvt_addr[IP_LEN]
Definition: switch_nat.c:53
static switch_status_t switch_nat_del_mapping_pmp ( switch_port_t  port,
switch_nat_ip_proto_t  proto 
)
static

Definition at line 516 of file switch_nat.c.

References SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_NAT_TCP, SWITCH_NAT_UDP, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_nat_del_mapping().

517 {
519  natpmpresp_t response;
520  int r;
521  natpmp_t natpmp;
522 
523  initnatpmp(&natpmp);
524 
525  if (proto == SWITCH_NAT_TCP) {
526  sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, port, port, 0);
527  } else if (proto == SWITCH_NAT_UDP) {
528  sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 0);
529  }
530 
531  do {
532  fd_set fds;
533  struct timeval timeout;
534  FD_ZERO(&fds);
535  FD_SET(natpmp.s, &fds);
536  getnatpmprequesttimeout(&natpmp, &timeout);
537  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
538  r = readnatpmpresponseorretry(&natpmp, &response);
539  } while (r == NATPMP_TRYAGAIN);
540 
541  if (r == 0) {
542  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unmapped public port %hu protocol %s to localport %hu\n", response.pnu.newportmapping.privateport, /* This might be wrong but its so 0 isn't displayed */
543  response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" :
544  (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : "UNKNOWN"), response.pnu.newportmapping.privateport);
545  status = SWITCH_STATUS_SUCCESS;
546  }
547 
548  closenatpmp(&natpmp);
549 
550  return status;
551 }
#define SWITCH_CHANNEL_LOG
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static switch_status_t switch_nat_del_mapping_upnp ( switch_port_t  port,
switch_nat_ip_proto_t  proto 
)
static

Definition at line 553 of file switch_nat.c.

References nat_globals_t::data, IP_LEN, SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_NAT_TCP, SWITCH_NAT_UDP, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and nat_globals_t::urls.

Referenced by switch_nat_del_mapping().

554 {
556  char port_str[IP_LEN];
557  int r = UPNPCOMMAND_UNKNOWN_ERROR;
558 
559  sprintf(port_str, "%d", port);
560 
561  if (proto == SWITCH_NAT_TCP) {
562  r = UPNP_DeletePortMapping(nat_globals.urls.controlURL, nat_globals.data.servicetype, port_str, "TCP", 0);
563  } else if (proto == SWITCH_NAT_UDP) {
564  r = UPNP_DeletePortMapping(nat_globals.urls.controlURL, nat_globals.data.servicetype, port_str, "UDP", 0);
565  }
566 
567  if (r == UPNPCOMMAND_SUCCESS) {
568  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unmapped public port %s protocol %s to localport %s\n", port_str,
569  (proto == SWITCH_NAT_TCP) ? "TCP" : (proto == SWITCH_NAT_UDP ? "UDP" : "UNKNOWN"), port_str);
570  status = SWITCH_STATUS_SUCCESS;
571  }
572  return status;
573 }
#define SWITCH_CHANNEL_LOG
#define IP_LEN
Definition: switch_nat.c:43
struct UPNPUrls urls
Definition: switch_nat.c:49
struct IGDdatas data
Definition: switch_nat.c:50
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static nat_globals_t nat_globals
Definition: switch_nat.c:57
static void* SWITCH_THREAD_FUNC switch_nat_multicast_runtime ( switch_thread_t thread,
void *  obj 
)
static

Definition at line 266 of file switch_nat.c.

References buf, nat_globals_t::data, nat_globals_t::descURL, get_pmp_pubaddr(), get_upnp_pubaddr(), nat_globals_perm_t::maddress, memset(), nat_globals_perm_t::msocket, MULTICAST_BUFFSIZE, nat_globals_t::nat_type, nat_globals_t::pub_addr, nat_globals_perm_t::running, switch_assert, SWITCH_CHANNEL_LOG, switch_event_add_header_string(), switch_event_create, switch_event_fire, SWITCH_EVENT_TRAP, SWITCH_FALSE, SWITCH_LOG_DEBUG, SWITCH_LOG_INFO, switch_log_printf(), SWITCH_LOG_WARNING, switch_nat_reinit(), switch_nat_republish(), SWITCH_NAT_TYPE_UPNP, switch_safe_free, switch_set_string, switch_socket_recvfrom(), SWITCH_STACK_BOTTOM, SWITCH_STATUS_IS_BREAK, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_yield.

Referenced by switch_nat_thread_start().

267 {
268  char *buf = NULL;
269  char newip[16] = "";
270  char *pos;
271  switch_event_t *event = NULL;
272 
273  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread started\n");
274 
275  buf = (char *) malloc(MULTICAST_BUFFSIZE);
276  switch_assert(buf);
278 
279  while (nat_globals_perm.running == 1) {
280  size_t len = MULTICAST_BUFFSIZE;
281  switch_status_t status;
282  switch_bool_t do_repub = SWITCH_FALSE;
283  memset(buf, 0, len);
284 
286 
287  if (!len) {
288  if (SWITCH_STATUS_IS_BREAK(status)) {
289  switch_yield(5000000);
290  continue;
291  }
292 
293  break;
294  }
295 
297  /* look for our desc URL and servicetype in the packet */
298  if (strstr(buf, nat_globals.descURL) && (buf == NULL || strstr(buf, nat_globals.data.servicetype))) {
299  if ((pos = strstr(buf, "NTS:"))) {
300  pos = pos + 4;
301  while (*pos && *pos == ' ') {
302  pos++;
303  }
304  if (!strncmp(pos, "ssdp:alive", 10)) {
305  /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP keep alive packet: \n%s\n", buf); */
306  /* did pub ip change */
307  newip[0] = '\0';
308  if (get_upnp_pubaddr(newip) != SWITCH_STATUS_SUCCESS) {
310  "Unable to get current pubaddr after receiving UPnP keep alive packet.\n");
311  }
312  } else if (!strncmp(pos, "ssdp:byebye", 11)) {
314  "got UPnP signoff packet. Your NAT gateway is probably going offline.\n");
315  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP signoff packet: \n%s\n", buf);
316  } else {
317  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UNKNOWN UPnP keep alive packet: \n%s\n", buf);
318  }
319  }
320  }
321  } else {
322  /* got some data in NAT-PMP mode, treat any data as a republish event */
323  if (get_pmp_pubaddr(newip) < 0) {
324  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to get current pubaddr after receiving UPnP keep alive packet.\n");
325  }
326  }
327 
328  if ((strlen(newip) > 0) && strcmp(newip, "0.0.0.0") && strcmp(newip, nat_globals.pub_addr)) {
329  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Public IP changed from '%s' to '%s'.\n", nat_globals.pub_addr, newip);
330  do_repub = SWITCH_TRUE;
331 
333  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "network-external-address-change");
334  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-external-address-previous-v4", nat_globals.pub_addr);
335  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-external-address-change-v4", newip);
336  switch_event_fire(&event);
337 
340  }
341 
342  if (do_repub) {
344  }
345  }
346 
347  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread ending\n");
349 
350  switch_safe_free(buf);
351 
352  return NULL;
353 }
static int get_pmp_pubaddr(char *pub_addr)
Definition: switch_nat.c:147
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define SWITCH_CHANNEL_LOG
#define SWITCH_STATUS_IS_BREAK(x)
Definition: switch_utils.h:564
void switch_nat_reinit(void)
re-initializes NAT subsystem
Definition: switch_nat.c:215
switch_bool_t
Definition: switch_types.h:405
Representation of an event.
Definition: switch_event.h:80
struct IGDdatas data
Definition: switch_nat.c:50
switch_socket_t * msocket
Definition: switch_nat.c:63
switch_status_t switch_socket_recvfrom(switch_sockaddr_t *from, switch_socket_t *sock, int32_t flags, char *buf, size_t *len)
Definition: switch_apr.c:936
switch_byte_t switch_byte_t * buf
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
#define MULTICAST_BUFFSIZE
Definition: switch_nat.c:42
char * descURL
Definition: switch_nat.c:51
switch_nat_type_t nat_type
Definition: switch_nat.c:47
char pub_addr[IP_LEN]
Definition: switch_nat.c:52
static switch_status_t get_upnp_pubaddr(char *pub_addr)
Definition: switch_nat.c:71
switch_sockaddr_t * maddress
Definition: switch_nat.c:62
switch_status_t
Common return values.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
static nat_globals_perm_t nat_globals_perm
Definition: switch_nat.c:66
#define switch_set_string(_dst, _src)
Definition: switch_utils.h:665
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
void switch_nat_republish(void)
Republishes the nap mappings.
Definition: switch_nat.c:652
#define switch_assert(expr)
static nat_globals_t nat_globals
Definition: switch_nat.c:57
memset(buf, 0, buflen)
void switch_nat_thread_start ( void  )

Definition at line 357 of file switch_nat.c.

References init_nat_monitor(), nat_thread_p, nat_globals_perm_t::pool, SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, switch_log_printf(), switch_nat_multicast_runtime(), SWITCH_STATUS_SUCCESS, switch_thread_create(), and switch_threadattr_create().

Referenced by switch_nat_init().

358 {
359 
360  switch_threadattr_t *thd_attr;
361 
363  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to initialize NAT thread\n");
364  return;
365  }
366 
369 }
#define SWITCH_CHANNEL_LOG
static void *SWITCH_THREAD_FUNC switch_nat_multicast_runtime(switch_thread_t *thread, void *obj)
Definition: switch_nat.c:266
switch_memory_pool_t * pool
Definition: switch_nat.c:60
switch_status_t init_nat_monitor(switch_memory_pool_t *pool)
Definition: switch_nat.c:220
static nat_globals_perm_t nat_globals_perm
Definition: switch_nat.c:66
switch_thread_t * nat_thread_p
Definition: switch_nat.c:355
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:642
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:675
void switch_nat_thread_stop ( void  )

Definition at line 371 of file switch_nat.c.

References nat_thread_p, nat_globals_perm_t::running, SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, switch_log_printf(), SWITCH_LOG_WARNING, switch_thread_join(), and switch_yield.

Referenced by switch_nat_shutdown().

372 {
373  /* don't do anything if no thread ptr */
374  if (!nat_thread_p) {
375  return;
376  }
377  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping NAT Task Thread\n");
378  if (nat_globals_perm.running == 1) {
379  int sanity = 0;
380  switch_status_t st;
381 
383 
385 
386  while (nat_globals_perm.running) {
387  switch_yield(1000000); /* can take up to 5s for the thread to terminate, so wait for 10 */
388  if (++sanity > 10) {
389  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Timed out waiting for NAT Task Thread to stop\n");
390  break;
391  }
392  }
393  }
394 
395  nat_thread_p = NULL;
396 }
#define SWITCH_CHANNEL_LOG
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1255
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
switch_status_t
Common return values.
static nat_globals_perm_t nat_globals_perm
Definition: switch_nat.c:66
switch_thread_t * nat_thread_p
Definition: switch_nat.c:355
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
SWITCH_STANDARD_SCHED_FUNC ( switch_nat_republish_sched  )

Definition at line 700 of file switch_nat.c.

References NAT_REFRESH_INTERVAL, nat_globals_perm_t::running, switch_epoch_time_now(), and switch_nat_republish().

701 {
703  if (nat_globals_perm.running == 1) {
704  task->runtime = switch_epoch_time_now(NULL) + NAT_REFRESH_INTERVAL;
705  }
706 }
#define NAT_REFRESH_INTERVAL
Definition: switch_nat.c:44
static nat_globals_perm_t nat_globals_perm
Definition: switch_nat.c:66
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
void switch_nat_republish(void)
Republishes the nap mappings.
Definition: switch_nat.c:652

Variable Documentation

switch_bool_t first_init = SWITCH_TRUE
static

Definition at line 68 of file switch_nat.c.

Referenced by switch_nat_init().

switch_bool_t initialized = SWITCH_FALSE
static
nat_globals_t nat_globals
static

Definition at line 57 of file switch_nat.c.

nat_globals_perm_t nat_globals_perm
static

Definition at line 66 of file switch_nat.c.

switch_thread_t* nat_thread_p = NULL

Definition at line 355 of file switch_nat.c.

Referenced by switch_nat_init(), switch_nat_thread_start(), and switch_nat_thread_stop().