36 #include "../libs/miniupnpc/miniwget.h"
37 #include "../libs/miniupnpc/miniupnpc.h"
38 #include "../libs/miniupnpc/upnpcommands.h"
39 #include "../libs/miniupnpc/upnperrors.h"
40 #include "../libs/libnatpmp/natpmp.h"
42 #define MULTICAST_BUFFSIZE 65536
44 #define NAT_REFRESH_INTERVAL 900
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,
88 struct UPNPDev *devlist;
89 struct UPNPDev *dev = NULL;
90 struct UPNPDev *trydev = NULL;
95 memset(&nat_globals.
urls, 0,
sizeof(
struct UPNPUrls));
96 memset(&nat_globals.
data, 0,
sizeof(
struct IGDdatas));
98 devlist = upnpDiscover(3000, minissdpdpath, minissdpdpath, 0);
103 if (strstr(dev->st,
"InternetGatewayDevice")) {
115 if (!dev && trydev) {
118 }
else if (devlist && !dev && !trydev) {
123 descXML = miniwget(dev->descURL, &descXMLsize);
125 nat_globals.
descURL = strdup(dev->descURL);
128 parserootdesc(descXML, descXMLsize, &nat_globals.
data);
131 GetUPNPUrls(&nat_globals.
urls, &nat_globals.
data, dev->descURL);
136 freeUPNPDevlist(devlist);
149 int r = 0, i = 0, max = 5;
150 natpmpresp_t response;
151 char *pubaddr = NULL;
153 const char *err = NULL;
156 if ((r = initnatpmp(&natpmp)) < 0) {
161 if ((r = sendpublicaddressrequest(&natpmp)) < 0) {
162 err =
"pub addr req failed";
167 struct timeval timeout = { 1, 0 };
171 if ((r = getnatpmprequesttimeout(&natpmp, &timeout)) < 0) {
172 err =
"get timeout failed";
179 err =
"wait sock failed";
182 r = readnatpmpresponseorretry(&natpmp, &response);
183 }
while (r == NATPMP_TRYAGAIN && i < max);
186 err =
"general error";
190 pubaddr = inet_ntoa(response.pnu.publicaddress.addr);
194 closenatpmp(&natpmp);
226 addr =
"239.255.255.250";
279 while (nat_globals_perm.
running == 1) {
298 if (strstr(buf, nat_globals.
descURL) && (buf == NULL || strstr(buf, nat_globals.
data.servicetype))) {
299 if ((pos = strstr(buf,
"NTS:"))) {
301 while (*pos && *pos ==
' ') {
304 if (!strncmp(pos,
"ssdp:alive", 10)) {
310 "Unable to get current pubaddr after receiving UPnP keep alive packet.\n");
312 }
else if (!strncmp(pos,
"ssdp:byebye", 11)) {
314 "got UPnP signoff packet. Your NAT gateway is probably going offline.\n");
328 if ((strlen(newip) > 0) && strcmp(newip,
"0.0.0.0") && strcmp(newip, nat_globals.
pub_addr)) {
378 if (nat_globals_perm.
running == 1) {
386 while (nat_globals_perm.
running) {
402 FreeUPNPUrls(&nat_globals.
urls);
405 memset(&nat_globals, 0,
sizeof(nat_globals));
408 memset(&nat_globals_perm, 0,
sizeof(nat_globals_perm));
447 natpmpresp_t response;
454 sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, port, port, 31104000);
456 sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 31104000);
461 struct timeval timeout = { 1, 0 };
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);
471 response.pnu.newportmapping.mappedpublicport,
472 response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ?
"UDP" :
473 (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ?
"TCP" :
"UNKNOWN"), response.pnu.newportmapping.privateport);
475 *external_port = response.pnu.newportmapping.mappedpublicport;
476 }
else if (response.pnu.newportmapping.mappedpublicport != response.pnu.newportmapping.privateport) {
478 response.pnu.newportmapping.privateport,
479 response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ?
"UDP" :
480 (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ?
"TCP" :
"UNKNOWN"), response.pnu.newportmapping.mappedpublicport);
486 closenatpmp(&natpmp);
495 int r = UPNPCOMMAND_UNKNOWN_ERROR;
497 sprintf(port_str,
"%d", port);
500 r = UPNP_AddPortMapping(nat_globals.
urls.controlURL, nat_globals.
data.servicetype, port_str, port_str,
501 nat_globals.
pvt_addr,
"FreeSWITCH",
"TCP", 0);
503 r = UPNP_AddPortMapping(nat_globals.
urls.controlURL, nat_globals.
data.servicetype, port_str, port_str,
504 nat_globals.
pvt_addr,
"FreeSWITCH",
"UDP", 0);
507 if (r == UPNPCOMMAND_SUCCESS) {
519 natpmpresp_t response;
526 sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, port, port, 0);
528 sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 0);
533 struct timeval timeout;
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);
543 response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ?
"UDP" :
544 (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ?
"TCP" :
"UNKNOWN"), response.pnu.newportmapping.privateport);
548 closenatpmp(&natpmp);
557 int r = UPNPCOMMAND_UNKNOWN_ERROR;
559 sprintf(port_str,
"%d", port);
562 r = UPNP_DeletePortMapping(nat_globals.
urls.controlURL, nat_globals.
data.servicetype, port_str,
"TCP", 0);
564 r = UPNP_DeletePortMapping(nat_globals.
urls.controlURL, nat_globals.
data.servicetype, port_str,
"UDP", 0);
567 if (r == UPNPCOMMAND_SUCCESS) {
599 *external_port = port;
672 while (row != NULL) {
685 if (sport && sproto) {
703 if (nat_globals_perm.
running == 1) {
710 if (nat_globals_perm.
running == 1) {
744 FreeUPNPUrls(&nat_globals.
urls);
static int get_pmp_pubaddr(char *pub_addr)
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
void switch_nat_shutdown(void)
Shuts down the NAT Traversal System.
#define SWITCH_CHANNEL_LOG
switch_xml_t switch_xml_find_child(_In_ switch_xml_t node, _In_z_ const char *childname, _In_opt_z_ const char *attrname, _In_opt_z_ const char *value)
find a child tag in a node called 'childname' with an attribute 'attrname' which equals 'value' ...
switch_status_t switch_socket_bind(switch_socket_t *sock, switch_sockaddr_t *sa)
#define SWITCH_STATUS_IS_BREAK(x)
int switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags)
#define switch_xml_next(xml)
returns the next tag of the same name in the same section and depth or NULL \ if not found ...
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)
void switch_nat_reinit(void)
re-initializes NAT subsystem
switch_status_t switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
Execute a registered API command.
switch_memory_pool_t * pool
static switch_bool_t first_init
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.
void switch_core_set_variable(_In_z_ const char *varname, _In_opt_z_ const char *value)
Add a global variable to the core.
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.
A representation of an XML tree.
switch_socket_t * msocket
static switch_status_t switch_nat_add_mapping_upnp(switch_port_t port, switch_nat_ip_proto_t proto)
static switch_thread_t * thread
switch_status_t switch_socket_recvfrom(switch_sockaddr_t *from, switch_socket_t *sock, int32_t flags, char *buf, size_t *len)
uint32_t switch_scheduler_add_task(time_t task_runtime, switch_scheduler_func_t func, const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags)
Schedule a task in the future.
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
void switch_nat_set_mapping(switch_bool_t mapping)
Update the setting if port mapping will be created.
const char * switch_nat_get_type(void)
char * switch_nat_status(void)
Returns a list of nat mappings and other status info.
static void *SWITCH_THREAD_FUNC switch_nat_multicast_runtime(switch_thread_t *thread, void *obj)
void switch_nat_thread_start(void)
void switch_nat_init(switch_memory_pool_t *pool, switch_bool_t mapping)
Initilize the NAT Traversal System.
void switch_nat_thread_stop(void)
switch_byte_t switch_byte_t * buf
switch_bool_t switch_nat_is_initialized(void)
Has the NAT subsystem been initialized.
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
struct apr_sockaddr_t switch_sockaddr_t
switch_memory_pool_t * pool
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.
static switch_status_t switch_nat_del_mapping_upnp(switch_port_t port, switch_nat_ip_proto_t proto)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
#define NAT_REFRESH_INTERVAL
switch_status_t switch_socket_opt_set(switch_socket_t *sock, int32_t opt, int32_t on)
#define MULTICAST_BUFFSIZE
#define SWITCH_STANDARD_STREAM(s)
char * switch_core_get_variable(_In_z_ const char *varname)
Retrieve a global variable from the core.
switch_nat_type_t nat_type
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
switch_status_t switch_nat_del_mapping(switch_port_t port, switch_nat_ip_proto_t proto)
Deletes a NAT mapping.
#define switch_xml_parse_str_dup(x)
Parses a string into a switch_xml_t.
void switch_nat_late_init(void)
Initilize the rest of the NAT Traversal System.
static switch_status_t switch_nat_del_mapping_pmp(switch_port_t port, switch_nat_ip_proto_t proto)
static switch_status_t get_upnp_pubaddr(char *pub_addr)
switch_sockaddr_t * maddress
switch_status_t switch_socket_create(switch_socket_t **new_sock, int family, int type, int protocol, switch_memory_pool_t *pool)
switch_stream_handle_write_function_t write_function
switch_status_t
Common return values.
#define SWITCH_SO_NONBLOCK
switch_status_t switch_socket_close(switch_socket_t *sock)
struct apr_thread_t switch_thread_t
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
switch_status_t init_nat_monitor(switch_memory_pool_t *pool)
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
static nat_globals_perm_t nat_globals_perm
#define switch_set_string(_dst, _src)
static int init_pmp(void)
#define SWITCH_SO_REUSEADDR
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
switch_status_t switch_mcast_join(switch_socket_t *sock, switch_sockaddr_t *join, switch_sockaddr_t *iface, switch_sockaddr_t *source)
switch_thread_t * nat_thread_p
struct apr_pool_t switch_memory_pool_t
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)
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
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)
switch_status_t switch_find_local_ip(_Out_opt_bytecapcount_(len) char *buf, _In_ int len, _In_opt_ int *mask, _In_ int family)
find local ip of the box
static switch_bool_t initialized
SWITCH_STANDARD_SCHED_FUNC(switch_nat_republish_sched)
void switch_nat_republish(void)
Republishes the nap mappings.
struct apr_socket_t switch_socket_t
static int init_upnp(void)
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)
static nat_globals_t nat_globals
static switch_status_t switch_nat_add_mapping_pmp(switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t *external_port)