-
Notifications
You must be signed in to change notification settings - Fork 0
/
nat.go
59 lines (48 loc) · 1.7 KB
/
nat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Package nat implements NAT handling facilities
package nat
import (
"errors"
"math"
"math/rand"
"net"
"time"
)
var ErrNoExternalAddress = errors.New("no external address")
var ErrNoInternalAddress = errors.New("no internal address")
var ErrNoNATFound = errors.New("no NAT found")
// protocol is either "udp" or "tcp"
type NAT interface {
// Type returns the kind of NAT port mapping service that is used
Type() string
// GetDeviceAddress returns the internal address of the gateway device.
GetDeviceAddress() (addr net.IP, err error)
// GetExternalAddress returns the external address of the gateway device.
GetExternalAddress() (addr net.IP, err error)
// GetInternalAddress returns the address of the local host.
GetInternalAddress() (addr net.IP, err error)
// AddPortMapping maps a port on the local host to an external port.
AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (mappedExternalPort int, err error)
// DeletePortMapping removes a port mapping.
DeletePortMapping(protocol string, internalPort int) (err error)
// DeleteExternalPortMapping removes an external port mapping.
DeleteExternalPortMapping(protocol string, externalPort int) (err error)
}
// DiscoverGateway attempts to find a gateway device.
func DiscoverGateway() (NAT, error) {
select {
case nat := <-discoverUPNP_IG1():
return nat, nil
case nat := <-discoverUPNP_IG2():
return nat, nil
case nat := <-discoverUPNP_GenIGDev():
return nat, nil
case nat := <-discoverNATPMP():
return nat, nil
case <-time.After(10 * time.Second):
return nil, ErrNoNATFound
}
}
func randomPort() int {
rand.Seed(time.Now().UnixNano())
return rand.Intn(math.MaxUint16-10000) + 10000
}