// createPortMapping creates a NAT port mapping, or nil if none requested or found. func CreatePortMapping(flags *TorrentFlags) (nat NAT, err error) { if flags.UseUPnP && flags.UseNATPMP { err = fmt.Errorf("Cannot specify both -useUPnP and -useNATPMP") return } if flags.UseUPnP { log.Println("Using UPnP to open port.") nat, err = Discover() } if flags.UseNATPMP { var gatewayIP net.IP if flags.Gateway == "" { log.Printf("useNATPMP but gateway not provided, trying discovery") gatewayIP, err = gateway.DiscoverGateway() if err != nil { return } log.Printf("...discovered gateway IP: %s", gatewayIP) } else { gatewayIP = net.ParseIP(flags.Gateway) } log.Println("Using NAT-PMP to open port.") if gatewayIP == nil { err = fmt.Errorf("Could not parse gateway %q", flags.Gateway) } nat = NewNatPMP(gatewayIP) } return }
// TODO: improve this. We currently assume that (on most networks) // the router is X.X.X.1 in a local LAN range. func potentialGateways() (gws []net.IP) { ifaces, err := net.Interfaces() if err != nil { return nil } for _, iface := range ifaces { if iface.Flags == net.FlagLoopback { continue } ifaddrs, err := iface.Addrs() if err != nil { return gws } for _, addr := range ifaddrs { switch x := addr.(type) { case *net.IPNet: if lan10.Contains(x.IP) || lan176.Contains(x.IP) || lan192.Contains(x.IP) { ip := x.IP.Mask(x.Mask).To4() if ip != nil { ip[3] = ip[3] | 0x01 gws = append(gws, ip) } } } } } wip, err := gateway.DiscoverGateway() if err == nil { gws = append(gws, wip) } return gws }
// Create a NAT-PMP client for the NAT-PMP server at the default gateway. func NewClientForDefaultGateway(timeout time.Duration) (nat *Client, err error) { var g net.IP g, err = gateway.DiscoverGateway() if err != nil { return } nat = NewClient(g, timeout) return }
// Create a NAT-PMP client for the NAT-PMP server at the default gateway. func NewClientForDefaultGateway() (nat *Client, err error) { var g net.IP g, err = gateway.DiscoverGateway() if err != nil { return } nat = NewClient(g) return }
func discoverNATPMP() <-chan NAT { res := make(chan NAT, 1) ip, err := gateway.DiscoverGateway() if err == nil { go discoverNATPMPWithAddr(res, ip) } return res }
func Discover(renewal, timeout time.Duration) []nat.Device { ip, err := gateway.DiscoverGateway() if err != nil { l.Debugln("Failed to discover gateway", err) return nil } if ip == nil || ip.IsUnspecified() { return nil } l.Debugln("Discovered gateway at", ip) c := natpmp.NewClient(ip, timeout) // Try contacting the gateway, if it does not respond, assume it does not // speak NAT-PMP. _, err = c.GetExternalAddress() if err != nil && strings.Contains(err.Error(), "Timed out") { l.Debugln("Timeout trying to get external address, assume no NAT-PMP available") return nil } var localIP net.IP // Port comes from the natpmp package conn, err := net.DialTimeout("udp", net.JoinHostPort(ip.String(), "5351"), timeout) if err == nil { conn.Close() localIPAddress, _, err := net.SplitHostPort(conn.LocalAddr().String()) if err == nil { localIP = net.ParseIP(localIPAddress) } else { l.Debugln("Failed to lookup local IP", err) } } return []nat.Device{&wrapper{ renewal: renewal, localIP: localIP, gatewayIP: ip, client: c, }} }