Пример #1
0
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;
}
bool NATPMPInterface::removePortForward(const NATPortMapping& mapping) {
	if (sendnewportmappingrequest(&p->natpmp, mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, 0, 0, mapping.getLocalPort()) < 0) {
		SWIFT_LOG(debug) << "Failed to send NAT-PMP remove forwarding request!" << std::endl;
		return false;
	}

	int r = 0;
	natpmpresp_t response;
	do {
	  fd_set fds;
	  struct timeval timeout;
	  FD_ZERO(&fds);
	  FD_SET(p->natpmp.s, &fds);
	  getnatpmprequesttimeout(&p->natpmp, &timeout);
	  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
	  r = readnatpmpresponseorretry(&p->natpmp, &response);
	} while(r == NATPMP_TRYAGAIN);

	if (r == 0) {
		return true;
	}
	else {
		SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl;
		return false;
	}
}
boost::optional<NATPortMapping> NATPMPInterface::addPortForward(int localPort, int publicPort) {
	NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP);
	if (sendnewportmappingrequest(&p->natpmp, mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, mapping.getLeaseInSeconds(), mapping.getPublicPort(), mapping.getLocalPort()) < 0) {
			SWIFT_LOG(debug) << "Failed to send NAT-PMP port forwarding request!" << std::endl;
			return boost::optional<NATPortMapping>();
	}

	int r = 0;
	natpmpresp_t response;
	do {
		fd_set fds;
		struct timeval timeout;
		FD_ZERO(&fds);
		FD_SET(p->natpmp.s, &fds);
		getnatpmprequesttimeout(&p->natpmp, &timeout);
		select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
		r = readnatpmpresponseorretry(&p->natpmp, &response);
	} while(r == NATPMP_TRYAGAIN);

	if (r == 0) {
		NATPortMapping result(response.pnu.newportmapping.privateport, response.pnu.newportmapping.mappedpublicport, NATPortMapping::TCP, response.pnu.newportmapping.lifetime);
		return result;
	}
	else {
		SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl;
		return boost::optional<NATPortMapping>();
	}
}
Пример #4
0
int
tor_natpmp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port,
                           int is_verbose, void *backend_state)
{
  int r = 0;
  int x = 0;
  int sav_errno;
  natpmp_state_t *state = (natpmp_state_t *) backend_state;

  struct timeval timeout;

  if (is_verbose)
    fprintf(stderr, "V: sending natpmp portmapping request...\n");
  r = sendnewportmappingrequest(&(state->natpmp), state->protocol,
                                internal_port,
                                external_port,
                                state->lease);
  if (is_verbose)
    fprintf(stderr, "tor-fw-helper: NAT-PMP sendnewportmappingrequest "
            "returned %d (%s)\n", r, r==12?"SUCCESS":"FAILED");

  do {
    getnatpmprequesttimeout(&(state->natpmp), &timeout);
    x = wait_until_fd_readable(state->natpmp.s, &timeout);
    if (x == -1)
      return -1;

    if (is_verbose)
      fprintf(stderr, "V: attempting to readnatpmpreponseorretry...\n");
    r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
    sav_errno = tor_socket_errno(state->natpmp.s);

    if (r<0 && r!=NATPMP_TRYAGAIN) {
      fprintf(stderr, "E: readnatpmpresponseorretry failed %d\n", r);
      fprintf(stderr, "E: errno=%d '%s'\n", sav_errno,
              tor_socket_strerror(sav_errno));
    }

  } while (r == NATPMP_TRYAGAIN);

  if (r != 0) {
    /* XXX TODO: NATPMP_* should be formatted into useful error strings */
    fprintf(stderr, "E: NAT-PMP It appears that something went wrong:"
            " %d\n", r);
    if (r == -51)
      fprintf(stderr, "E: NAT-PMP It appears that the request was "
              "unauthorized\n");
    return r;
  }

  if (r == NATPMP_SUCCESS) {
    fprintf(stderr, "tor-fw-helper: NAT-PMP mapped public port %hu to"
            " localport %hu liftime %u\n",
            (state->response).pnu.newportmapping.mappedpublicport,
            (state->response).pnu.newportmapping.privateport,
            (state->response).pnu.newportmapping.lifetime);
  }

  return (r == NATPMP_SUCCESS) ? 0 : -1;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
/* 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;
}
int
tr_natpmpPulse( struct tr_natpmp * nat, tr_port private_port, bool is_enabled, tr_port * public_port )
{
    int ret;

    if( is_enabled && ( nat->state == TR_NATPMP_DISCOVER ) )
    {
        int val = initnatpmp( &nat->natpmp );
        logVal( "initnatpmp", val );
        val = sendpublicaddressrequest( &nat->natpmp );
        logVal( "sendpublicaddressrequest", val );
        nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_PUB;
        nat->has_discovered = true;
        setCommandTime( nat );
    }

    if( ( nat->state == TR_NATPMP_RECV_PUB ) && canSendCommand( nat ) )
    {
        natpmpresp_t response;
        const int val = readnatpmpresponseorretry( &nat->natpmp, &response );
        logVal( "readnatpmpresponseorretry", val );
        if( val >= 0 )
        {
            char str[128];
            evutil_inet_ntop( AF_INET, &response.pnu.publicaddress.addr, str, sizeof( str ) );
            tr_ninf( getKey( ), _( "Found public address \"%s\"" ), str );
            nat->state = TR_NATPMP_IDLE;
        }
        else if( val != NATPMP_TRYAGAIN )
        {
            nat->state = TR_NATPMP_ERR;
        }
    }

    if( ( nat->state == TR_NATPMP_IDLE ) || ( nat->state == TR_NATPMP_ERR ) )
    {
        if( nat->is_mapped && ( !is_enabled || ( nat->private_port != private_port ) ) )
            nat->state = TR_NATPMP_SEND_UNMAP;
    }

    if( ( nat->state == TR_NATPMP_SEND_UNMAP ) && canSendCommand( nat ) )
    {
        const int val = sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP,
                                                   nat->private_port,
                                                   nat->public_port,
                                                   0 );
        logVal( "sendnewportmappingrequest", val );
        nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_UNMAP;
        setCommandTime( nat );
    }

    if( nat->state == TR_NATPMP_RECV_UNMAP )
    {
        natpmpresp_t resp;
        const int val = readnatpmpresponseorretry( &nat->natpmp, &resp );
        logVal( "readnatpmpresponseorretry", val );
        if( val >= 0 )
        {
            const int private_port = resp.pnu.newportmapping.privateport;

            tr_ninf( getKey( ), _( "no longer forwarding port %d" ), private_port );

            if( nat->private_port == private_port )
            {
                nat->private_port = 0;
                nat->public_port = 0;
                nat->state = TR_NATPMP_IDLE;
                nat->is_mapped = false;
            }
        }
        else if( val != NATPMP_TRYAGAIN )
        {
            nat->state = TR_NATPMP_ERR;
        }
    }

    if( nat->state == TR_NATPMP_IDLE )
    {
        if( is_enabled && !nat->is_mapped && nat->has_discovered )
            nat->state = TR_NATPMP_SEND_MAP;

        else if( nat->is_mapped && tr_time( ) >= nat->renew_time )
            nat->state = TR_NATPMP_SEND_MAP;
    }

    if( ( nat->state == TR_NATPMP_SEND_MAP ) && canSendCommand( nat ) )
    {
        const int val = sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP, private_port, private_port, LIFETIME_SECS );
        logVal( "sendnewportmappingrequest", val );
        nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_MAP;
        setCommandTime( nat );
    }

    if( nat->state == TR_NATPMP_RECV_MAP )
    {
        natpmpresp_t resp;
        const int    val = readnatpmpresponseorretry( &nat->natpmp, &resp );
        logVal( "readnatpmpresponseorretry", val );
        if( val >= 0 )
        {
            nat->state = TR_NATPMP_IDLE;
            nat->is_mapped = true;
            nat->renew_time = tr_time( ) + ( resp.pnu.newportmapping.lifetime / 2 );
            nat->private_port = resp.pnu.newportmapping.privateport;
            nat->public_port = resp.pnu.newportmapping.mappedpublicport;
            tr_ninf( getKey( ), _( "Port %d forwarded successfully" ), nat->private_port );
        }
        else if( val != NATPMP_TRYAGAIN )
        {
            nat->state = TR_NATPMP_ERR;
        }
    }

    switch( nat->state )
    {
        case TR_NATPMP_IDLE:
            *public_port = nat->public_port;
            return nat->is_mapped ? TR_PORT_MAPPED : TR_PORT_UNMAPPED;
            break;

        case TR_NATPMP_DISCOVER:
            ret = TR_PORT_UNMAPPED; break;

        case TR_NATPMP_RECV_PUB:
        case TR_NATPMP_SEND_MAP:
        case TR_NATPMP_RECV_MAP:
            ret = TR_PORT_MAPPING; break;

        case TR_NATPMP_SEND_UNMAP:
        case TR_NATPMP_RECV_UNMAP:
            ret = TR_PORT_UNMAPPING; break;

        default:
            ret = TR_PORT_ERROR; break;
    }
    return ret;
}
Пример #9
0
int natpmp_handler(struct natpmp_handle_t *handle, uint16_t port, time_t lifespan, time_t now)
{
	natpmpresp_t response;

	// Retry later if we want to wait longer
	if (handle->retry > now) {
		return PF_RETRY;
	}

#ifdef DEBUG
	log_debug("NAT-PMP: Handle port: %hu, lifespan: %ld, state: %s", port, lifespan, natpmp_statestr(handle->state));
#endif

	// Initialize data structure / socket
	if (handle->state == NATPMP_STATE_INIT) {
		int rc = initnatpmp(&handle->natpmp, 0, 0);
		if (rc >= 0) {
			handle->state = NATPMP_STATE_REQUEST_GATEWAY;
			return PF_RETRY;
		} else {
			log_debug("NAT-PMP: Method initnatpmp returned %d.", rc);
			goto error;
		}
	}

	// Request gateway address
	if (handle->state == NATPMP_STATE_REQUEST_GATEWAY) {
		int rc = sendpublicaddressrequest(&handle->natpmp);
		if (rc >= 0) {
			handle->retry = now + 8;
			handle->state = NATPMP_STATE_RECEIVE_GATEWAY;
			return PF_RETRY;
		} else {
			log_debug("NAT-PMP: Method sendpublicaddressrequest returned %d.", rc);
			goto error;
		}
	}

	// Read public gateway address
	if (handle->state == NATPMP_STATE_RECEIVE_GATEWAY) {
		int rc = readnatpmpresponseorretry(&handle->natpmp, &response);
		
		if (rc >= 0) {
			char str[INET_ADDRSTRLEN];
			inet_ntop(AF_INET, &response.pnu.publicaddress.addr, str, sizeof (str));
			log_info("NAT-PMP: Found public address \"%s\".", str);
			handle->state = NATPMP_STATE_REQUEST_PORTMAPPING;
			return PF_RETRY;
		} else if (rc == NATPMP_TRYAGAIN) {
			handle->retry = now + (10 * 60);
			handle->state = NATPMP_STATE_REQUEST_GATEWAY;
			return PF_RETRY;
		} else {
			log_debug("NAT-PMP: Method readnatpmpresponseorretry returned %d.", rc);
			goto error;
		}
	}

	// Add/Remove port mappings
	if (handle->state == NATPMP_STATE_REQUEST_PORTMAPPING) {
		int rc_udp = sendnewportmappingrequest(&handle->natpmp, NATPMP_PROTOCOL_UDP, port, port, lifespan);
		int rc_tcp = sendnewportmappingrequest(&handle->natpmp, NATPMP_PROTOCOL_TCP, port, port, lifespan);

		if (rc_udp >= 0 && rc_tcp >= 0) {
			handle->retry = now + 2;
			handle->state = NATPMP_STATE_RECEIVE_PORTMAPPING;
			return PF_RETRY;
		} else {

			log_debug("NAT-PMP: Method sendnewportmappingrequest returned an error: %s",
				strnatpmperr((rc_udp >= 0) ? rc_tcp : rc_udp));
			goto error;
		}
	}

	// Check port mapping
	if (handle->state == NATPMP_STATE_RECEIVE_PORTMAPPING) {
		int rc = readnatpmpresponseorretry(&handle->natpmp, &response);
		if (rc >= 0) {
			int private_port = response.pnu.newportmapping.privateport;
			int public_port = response.pnu.newportmapping.mappedpublicport;
			time_t lifetime = response.pnu.newportmapping.lifetime;

			if (lifetime > 0) {
				log_info("NAT-PMP: Port forwarding added for port %d (to private port %d) for %ld seconds.", public_port, private_port, lifetime);
				handle->state = NATPMP_STATE_REQUEST_PORTMAPPING;
				return PF_DONE;
			} else {
				log_debug("NAT-PMP: Port forwarding removed for public port %d (to private port %d) for %ld seconds.", public_port, private_port, lifetime);
				handle->state = NATPMP_STATE_REQUEST_PORTMAPPING;
				return PF_DONE;
			}
		} else if (rc == NATPMP_TRYAGAIN) {
			handle->state = NATPMP_STATE_RECEIVE_PORTMAPPING;
			return PF_RETRY;
		} else {
			log_debug("NAT-PMP: Port forwarding failed for port %d.", port);
			goto error;
		}
	}
	
	error:;
	handle->retry = now + 60;
	handle->state = NATPMP_STATE_ERROR;
	return PF_ERROR;
}
Пример #10
0
static int
natpmpPulse( ml_upnpmp_t * map )
{
    int ret;

    if( map->enabled && ( map->natpmpState == ML_NATPMP_DISCOVER ) )
    {
        int val = initnatpmp( &map->natpmp, 0, 0 );
        dbg_printf( "initnatpmp = %d\n", val );
        val = sendpublicaddressrequest( &map->natpmp );
        dbg_printf( "sendpublicaddressrequest = %d\n", val );
        map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_PUB;
        map->natpmpDiscovered = 1;
        setCommandTime( map );
    }

    if( ( map->natpmpState == ML_NATPMP_RECV_PUB ) && canSendCommand( map ) )
    {
        natpmpresp_t response;
        const int    val = readnatpmpresponseorretry( &map->natpmp,
                                                      &response );
        dbg_printf( "readnatpmpresponseorretry = %d\n", val );
        if( val >= 0 )
        {
            dbg_printf( "Found public address \"%s\"\n", inet_ntoa( response.pnu.publicaddress.addr ) );
            map->natpmpState = ML_NATPMP_IDLE;
        }
        else if( val != NATPMP_TRYAGAIN )
        {
        	 map->natpmpState = ML_NATPMP_ERR;
        }
    }

    if( (  map->natpmpState == ML_NATPMP_IDLE ) || (  map->natpmpState == ML_NATPMP_ERR ) )
    {
        if(  map->natpmpMapped && ( ! map->enabled ) )
            map->natpmpState = ML_NATPMP_SEND_UNMAP;
    }

    if( ( map->natpmpState == ML_NATPMP_SEND_UNMAP ) && canSendCommand( map ) )
    {
        const int val =
            sendnewportmappingrequest( &map->natpmp, NATPMP_PROTOCOL_TCP,
                                       map->intPort, map->extPort,
                                       0 );
        dbg_printf( "sendnewportmappingrequest = %d\n", val );
        map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_UNMAP;
        setCommandTime( map );
    }

    if( map->natpmpState == ML_NATPMP_RECV_UNMAP )
    {
        natpmpresp_t resp;
        const int    val = readnatpmpresponseorretry( &map->natpmp, &resp );
        dbg_printf( "readnatpmpresponseorretry = %d\n", val );
        if( val >= 0 )
        {
            const int p = resp.pnu.newportmapping.privateport;
            dbg_printf( "no longer forwarding port %d\n", p );
            if( map->extPort == p )
            {
            	map->extPort = 0;
            	map->natpmpState = ML_NATPMP_IDLE;
                map->natpmpMapped = 0;
            }
        }
        else if( val != NATPMP_TRYAGAIN )
        {
        	map->natpmpState = ML_NATPMP_ERR;
        }
    }

    if( map->natpmpState == ML_NATPMP_IDLE )
    {
        if( map->enabled && !map->natpmpMapped && map->natpmpDiscovered )
        	map->natpmpState = ML_NATPMP_SEND_MAP;

        else if( map->natpmpMapped && time(NULL) >= map->renewTime )
            map->natpmpState = ML_NATPMP_SEND_MAP;
    }

    if( ( map->natpmpState == ML_NATPMP_SEND_MAP ) && canSendCommand( map ) )
    {
        const int val =
            sendnewportmappingrequest( &map->natpmp, NATPMP_PROTOCOL_TCP,
                                       map->intPort,
                                       map->extPort,
                                       LIFETIME_SECS );
        dbg_printf( "sendnewportmappingrequest = %d\n", val );
        map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_MAP;
        setCommandTime( map );
    }

    if( map->natpmpState == ML_NATPMP_RECV_MAP )
    {
        natpmpresp_t resp;
        const int    val = readnatpmpresponseorretry( &map->natpmp, &resp );
        dbg_printf( "readnatpmpresponseorretry = %d\n", val );
        if( val >= 0 )
        {
        	map->natpmpState = ML_NATPMP_IDLE;
            map->natpmpMapped = 1;
            map->renewTime = time(NULL) + LIFETIME_SECS;
            map->extPort = resp.pnu.newportmapping.privateport;
            dbg_printf( "Port %d forwarded successfully\n", map->extPort );
        }
        else if( val != NATPMP_TRYAGAIN )
        {
            map->natpmpState = ML_NATPMP_ERR;
        }
    }

    switch( map->natpmpState )
    {
        case ML_NATPMP_IDLE:
            ret = map->natpmpMapped ? ML_PORT_MAPPED : ML_PORT_UNMAPPED; break;

        case ML_NATPMP_DISCOVER:
            ret = ML_PORT_UNMAPPED; break;

        case ML_NATPMP_RECV_PUB:
        case ML_NATPMP_SEND_MAP:
        case ML_NATPMP_RECV_MAP:
            ret = ML_PORT_MAPPING; break;

        case ML_NATPMP_SEND_UNMAP:
        case ML_NATPMP_RECV_UNMAP:
            ret = ML_PORT_UNMAPPING; break;

        default:
            ret = ML_PORT_ERROR; break;
    }
    return ret;
}
Пример #11
0
int
tr_natpmpPulse( struct tr_natpmp * nat,
                int                port,
                int                isEnabled )
{
    int ret;

    if( isEnabled && ( nat->state == TR_NATPMP_DISCOVER ) )
    {
        int val = initnatpmp( &nat->natpmp );
        logVal( "initnatpmp", val );
        val = sendpublicaddressrequest( &nat->natpmp );
        logVal( "sendpublicaddressrequest", val );
        nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_PUB;
        nat->hasDiscovered = 1;
        setCommandTime( nat );
    }

    if( ( nat->state == TR_NATPMP_RECV_PUB ) && canSendCommand( nat ) )
    {
        natpmpresp_t response;
        const int    val = readnatpmpresponseorretry( &nat->natpmp,
                                                      &response );
        logVal( "readnatpmpresponseorretry", val );
        if( val >= 0 )
        {
            tr_ninf( getKey( ), _(
                        "Found public address \"%s\"" ),
                    inet_ntoa( response.pnu.publicaddress.addr ) );
            nat->state = TR_NATPMP_IDLE;
        }
        else if( val != NATPMP_TRYAGAIN )
        {
            nat->state = TR_NATPMP_ERR;
        }
    }

    if( ( nat->state == TR_NATPMP_IDLE ) || ( nat->state == TR_NATPMP_ERR ) )
    {
        if( nat->isMapped && ( !isEnabled || ( nat->port != port ) ) )
            nat->state = TR_NATPMP_SEND_UNMAP;
    }

    if( ( nat->state == TR_NATPMP_SEND_UNMAP ) && canSendCommand( nat ) )
    {
        const int val =
            sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP,
                                       nat->port, nat->port,
                                       0 );
        logVal( "sendnewportmappingrequest", val );
        nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_UNMAP;
        setCommandTime( nat );
    }

    if( nat->state == TR_NATPMP_RECV_UNMAP )
    {
        natpmpresp_t resp;
        const int    val = readnatpmpresponseorretry( &nat->natpmp, &resp );
        logVal( "readnatpmpresponseorretry", val );
        if( val >= 0 )
        {
            const int p = resp.pnu.newportmapping.privateport;
            tr_ninf( getKey( ), _( "no longer forwarding port %d" ), p );
            if( nat->port == p )
            {
                nat->port = -1;
                nat->state = TR_NATPMP_IDLE;
                nat->isMapped = 0;
            }
        }
        else if( val != NATPMP_TRYAGAIN )
        {
            nat->state = TR_NATPMP_ERR;
        }
    }

    if( nat->state == TR_NATPMP_IDLE )
    {
        if( isEnabled && !nat->isMapped && nat->hasDiscovered )
            nat->state = TR_NATPMP_SEND_MAP;

        else if( nat->isMapped && tr_time( ) >= nat->renewTime )
            nat->state = TR_NATPMP_SEND_MAP;
    }

    if( ( nat->state == TR_NATPMP_SEND_MAP ) && canSendCommand( nat ) )
    {
        const int val =
            sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP,
                                       port,
                                       port,
                                       LIFETIME_SECS );
        logVal( "sendnewportmappingrequest", val );
        nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_MAP;
        setCommandTime( nat );
    }

    if( nat->state == TR_NATPMP_RECV_MAP )
    {
        natpmpresp_t resp;
        const int    val = readnatpmpresponseorretry( &nat->natpmp, &resp );
        logVal( "readnatpmpresponseorretry", val );
        if( val >= 0 )
        {
            nat->state = TR_NATPMP_IDLE;
            nat->isMapped = 1;
            nat->renewTime = tr_time( ) + LIFETIME_SECS;
            nat->port = resp.pnu.newportmapping.privateport;
            tr_ninf( getKey( ), _(
                         "Port %d forwarded successfully" ), nat->port );
        }
        else if( val != NATPMP_TRYAGAIN )
        {
            nat->state = TR_NATPMP_ERR;
        }
    }

    switch( nat->state )
    {
        case TR_NATPMP_IDLE:
            ret = nat->isMapped ? TR_PORT_MAPPED : TR_PORT_UNMAPPED; break;

        case TR_NATPMP_DISCOVER:
            ret = TR_PORT_UNMAPPED; break;

        case TR_NATPMP_RECV_PUB:
        case TR_NATPMP_SEND_MAP:
        case TR_NATPMP_RECV_MAP:
            ret = TR_PORT_MAPPING; break;

        case TR_NATPMP_SEND_UNMAP:
        case TR_NATPMP_RECV_UNMAP:
            ret = TR_PORT_UNMAPPING; break;

        default:
            ret = TR_PORT_ERROR; break;
    }
    return ret;
}