static int get_pmp_pubaddr(char *pub_addr) { int r = 0, i = 0, max = 5; natpmpresp_t response; char *pubaddr = NULL; fd_set fds; natpmp_t natpmp; const char *err = NULL; if ((r = initnatpmp(&natpmp)) < 0) { err = "init failed"; goto end; } if ((r = sendpublicaddressrequest(&natpmp)) < 0) { err = "pub addr req failed"; goto end; } do { struct timeval timeout = { 1, 0 }; i++; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for PMP %d/%d\n", i, max); FD_ZERO(&fds); FD_SET(natpmp.s, &fds); if ((r = getnatpmprequesttimeout(&natpmp, &timeout)) < 0) { err = "get timeout failed"; goto end; } if ((r = select(FD_SETSIZE, &fds, NULL, NULL, &timeout)) < 0) { err = "select failed"; goto end; } r = readnatpmpresponseorretry(&natpmp, &response); } while (r == NATPMP_TRYAGAIN && i < max); if (r < 0) { err = "general error"; goto end; } pubaddr = inet_ntoa(response.pnu.publicaddress.addr); switch_copy_string(pub_addr, pubaddr, IP_LEN); nat_globals.nat_type = SWITCH_NAT_TYPE_PMP; closenatpmp(&natpmp); end: if (err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error checking for PMP [%s]\n", err); } return r; }
void tr_natpmpClose (tr_natpmp * nat) { if (nat) { closenatpmp (&nat->natpmp); tr_free (nat); } }
void natpmp_uninit(struct natpmp_handle_t **handle) { // Remove all port mapping associated with this host struct natpmp_handle_t *m = *handle; sendnewportmappingrequest(&m->natpmp, NATPMP_PROTOCOL_TCP, 0, 0, 0); sendnewportmappingrequest(&m->natpmp, NATPMP_PROTOCOL_UDP, 0, 0, 0); closenatpmp(&m->natpmp); free(*handle); *handle = NULL; }
/** Tear down the NAT-PMP connection stored in <b>backend_state</b>.*/ int tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state) { natpmp_state_t *state = (natpmp_state_t *) backend_state; int r = 0; if (tor_fw_options->verbose) fprintf(stdout, "V: natpmp cleanup...\n"); r = closenatpmp(&(state->natpmp)); if (tor_fw_options->verbose) fprintf(stdout, "V: closing natpmp socket: %d\n", r); return r; }
static switch_status_t switch_nat_add_mapping_pmp(switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t * external_port) { switch_status_t status = SWITCH_STATUS_FALSE; natpmpresp_t response; int r; natpmp_t natpmp; initnatpmp(&natpmp); if (proto == SWITCH_NAT_TCP) { sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, port, port, 31104000); } else if (proto == SWITCH_NAT_UDP) { sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 31104000); } do { fd_set fds; struct timeval timeout = { 1, 0 }; FD_ZERO(&fds); FD_SET(natpmp.s, &fds); getnatpmprequesttimeout(&natpmp, &timeout); select(FD_SETSIZE, &fds, NULL, NULL, &timeout); r = readnatpmpresponseorretry(&natpmp, &response); } while (r == NATPMP_TRYAGAIN); if (r == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "mapped public port %hu protocol %s to localport %hu\n", response.pnu.newportmapping.mappedpublicport, response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" : (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : "UNKNOWN"), response.pnu.newportmapping.privateport); if (external_port) { *external_port = response.pnu.newportmapping.mappedpublicport; } else if (response.pnu.newportmapping.mappedpublicport != response.pnu.newportmapping.privateport) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "External port %hu protocol %s was not available, it was instead mapped to %hu\n", response.pnu.newportmapping.privateport, response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" : (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : "UNKNOWN"), response.pnu.newportmapping.mappedpublicport); } status = SWITCH_STATUS_SUCCESS; } closenatpmp(&natpmp); return status; }
static switch_status_t switch_nat_del_mapping_pmp(switch_port_t port, switch_nat_ip_proto_t proto) { switch_status_t status = SWITCH_STATUS_FALSE; natpmpresp_t response; int r; natpmp_t natpmp; initnatpmp(&natpmp); if (proto == SWITCH_NAT_TCP) { sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, port, port, 0); } else if (proto == SWITCH_NAT_UDP) { sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 0); } do { fd_set fds; struct timeval timeout; FD_ZERO(&fds); FD_SET(natpmp.s, &fds); getnatpmprequesttimeout(&natpmp, &timeout); select(FD_SETSIZE, &fds, NULL, NULL, &timeout); r = readnatpmpresponseorretry(&natpmp, &response); } while (r == NATPMP_TRYAGAIN); if (r == 0) { 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 */ response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" : (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : "UNKNOWN"), response.pnu.newportmapping.privateport); status = SWITCH_STATUS_SUCCESS; } closenatpmp(&natpmp); return status; }
/* sample code for using libnatpmp */ int main(int argc, char * * argv) { natpmp_t natpmp; natpmpresp_t response; int r; int sav_errno; struct timeval timeout; fd_set fds; int i; int protocol = 0; uint16_t privateport = 0; uint16_t publicport = 0; uint32_t lifetime = 3600; int command = 0; int forcegw = 0; in_addr_t gateway = 0; struct in_addr gateway_in_use; #ifdef WIN32 WSADATA wsaData; int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); if(nResult != NO_ERROR) { fprintf(stderr, "WSAStartup() failed.\n"); return -1; } #endif /* argument parsing */ for(i=1; i<argc; i++) { if(argv[i][0] == '-') { switch(argv[i][1]) { case 'h': usage(stdout, argv[0]); return 0; case 'g': forcegw = 1; if(argc < i + 1) { fprintf(stderr, "Not enough arguments for option -%c\n", argv[i][1]); return 1; } gateway = inet_addr(argv[++i]); break; case 'a': command = 'a'; if(argc < i + 4) { fprintf(stderr, "Not enough arguments for option -%c\n", argv[i][1]); return 1; } i++; if(1 != sscanf(argv[i], "%hu", &publicport)) { fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]); return 1; } i++; if(1 != sscanf(argv[i], "%hu", &privateport)) { fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]); return 1; } i++; if(0 == strcasecmp(argv[i], "tcp")) protocol = NATPMP_PROTOCOL_TCP; else if(0 == strcasecmp(argv[i], "udp")) protocol = NATPMP_PROTOCOL_UDP; else { fprintf(stderr, "%s is not a valid protocol\n", argv[i]); return 1; } if(argc > i + 1) { if(1 != sscanf(argv[i+1], "%u", &lifetime)) { fprintf(stderr, "%s is not a correct 32bits unsigned integer\n", argv[i]); } else { i++; } } break; default: fprintf(stderr, "Unknown option %s\n", argv[i]); usage(stderr, argv[0]); return 1; } } else { fprintf(stderr, "Unknown option %s\n", argv[i]); usage(stderr, argv[0]); return 1; } } /* initnatpmp() */ r = initnatpmp(&natpmp, forcegw, gateway); printf("initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS"); if(r<0) return 1; gateway_in_use.s_addr = natpmp.gateway; printf("using gateway : %s\n", inet_ntoa(gateway_in_use)); /* sendpublicaddressrequest() */ r = sendpublicaddressrequest(&natpmp); printf("sendpublicaddressrequest returned %d (%s)\n", r, r==2?"SUCCESS":"FAILED"); if(r<0) return 1; do { FD_ZERO(&fds); FD_SET(natpmp.s, &fds); getnatpmprequesttimeout(&natpmp, &timeout); r = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); if(r<0) { fprintf(stderr, "select()"); return 1; } r = readnatpmpresponseorretry(&natpmp, &response); sav_errno = errno; printf("readnatpmpresponseorretry returned %d (%s)\n", r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); if(r<0 && r!=NATPMP_TRYAGAIN) { #ifdef ENABLE_STRNATPMPERR fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n", strnatpmperr(r)); #endif fprintf(stderr, " errno=%d '%s'\n", sav_errno, strerror(sav_errno)); } } while(r==NATPMP_TRYAGAIN); if(r<0) return 1; /* TODO : check that response.type == 0 */ printf("Public IP address : %s\n", inet_ntoa(response.pnu.publicaddress.addr)); printf("epoch = %u\n", response.epoch); if(command == 'a') { /* sendnewportmappingrequest() */ r = sendnewportmappingrequest(&natpmp, protocol, privateport, publicport, lifetime); printf("sendnewportmappingrequest returned %d (%s)\n", r, r==12?"SUCCESS":"FAILED"); if(r < 0) return 1; do { FD_ZERO(&fds); FD_SET(natpmp.s, &fds); getnatpmprequesttimeout(&natpmp, &timeout); select(FD_SETSIZE, &fds, NULL, NULL, &timeout); r = readnatpmpresponseorretry(&natpmp, &response); printf("readnatpmpresponseorretry returned %d (%s)\n", r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); } while(r==NATPMP_TRYAGAIN); if(r<0) { #ifdef ENABLE_STRNATPMPERR fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n", strnatpmperr(r)); #endif return 1; } printf("Mapped public port %hu protocol %s to local port %hu " "liftime %u\n", response.pnu.newportmapping.mappedpublicport, response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" : (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : "UNKNOWN"), response.pnu.newportmapping.privateport, response.pnu.newportmapping.lifetime); printf("epoch = %u\n", response.epoch); } r = closenatpmp(&natpmp); printf("closenatpmp() returned %d (%s)\n", r, r==0?"SUCCESS":"FAILED"); if(r<0) return 1; return 0; }
NATPMPInterface::~NATPMPInterface() { closenatpmp(&p->natpmp); }