Example #1
0
func (m *mapping) tryNATPMPGW(gw net.IP, destroy bool) bool {
	var externalPort uint16
	var actualLifetime time.Duration
	var err error

	var preferredLifetime time.Duration
	if destroy && !m.lIsActive() {
		// no point destroying if we're not active
		return true
	} else if !destroy {
		// lifetime is zero if we're destroying
		preferredLifetime = m.cfg.Lifetime
	}

	// attempt mapping
	externalPort, actualLifetime, err = natpmp.Map(gw,
		natpmp.Protocol(m.cfg.Protocol), m.cfg.InternalPort, m.cfg.ExternalPort, preferredLifetime)
	if err != nil {
		log.Infof("NAT-PMP failed: %v", err)
		return false
	}

	m.mutex.Lock()
	m.cfg.ExternalPort = externalPort
	m.cfg.Lifetime = actualLifetime
	m.mutex.Unlock()
	if preferredLifetime == 0 {
		// we have finished tearing down the mapping by mapping it with a
		// lifetime of zero, so return
		return true
	}

	expireTime := time.Now().Add(actualLifetime)

	// Now attempt to get the external IP.
	extIP, err := natpmp.GetExternalAddr(gw)

	m.mutex.Lock()
	defer m.mutex.Unlock()

	// update external address
	if err == nil {
		m.externalAddr = extIP.String()
	}

	m.expireTime = expireTime
	return true
}
Example #2
0
// Attempt to obtain the external IP address from the default gateway.
//
// If the host has a globally routable IP, returns that IP.
//
// Currently this only tries NAT-PMP and does not attempt to learn the external
// IP address via UPnP.
//
// This function is not very useful because the IP address returned may still
// be an RFC1918 address, due to the possibility of a double NAT setup. There
// are better solutions for obtaining one's public IP address, such as STUN.
func ExternalAddr() (net.IP, error) {
	if gr, ip := isGloballyRoutable(); gr {
		return ip, nil
	}

	gwa, err := gateway.GetIPs()
	if err != nil {
		return nil, err
	}

	var extaddr net.IP
	for _, gw := range gwa {
		extaddr, err = natpmp.GetExternalAddr(gw)
		if err == nil {
			return extaddr, nil
		}
	}

	return nil, err
}