| 
									
										
										
										
											2014-02-02 19:22:39 +01:00
										 |  |  | package eth | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2014-08-23 19:01:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	natpmp "github.com/jackpal/go-nat-pmp" | 
					
						
							| 
									
										
										
										
											2014-02-02 19:22:39 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Adapt the NAT-PMP protocol to the NAT interface | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TODO: | 
					
						
							|  |  |  | //  + Register for changes to the external address. | 
					
						
							|  |  |  | //  + Re-register port mapping when router reboots. | 
					
						
							|  |  |  | //  + A mechanism for keeping a port mapping registered. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type natPMPClient struct { | 
					
						
							|  |  |  | 	client *natpmp.Client | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewNatPMP(gateway net.IP) (nat NAT) { | 
					
						
							|  |  |  | 	return &natPMPClient{natpmp.NewClient(gateway)} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *natPMPClient) GetExternalAddress() (addr net.IP, err error) { | 
					
						
							|  |  |  | 	response, err := n.client.GetExternalAddress() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ip := response.ExternalIPAddress | 
					
						
							|  |  |  | 	addr = net.IPv4(ip[0], ip[1], ip[2], ip[3]) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *natPMPClient) AddPortMapping(protocol string, externalPort, internalPort int, | 
					
						
							|  |  |  | 	description string, timeout int) (mappedExternalPort int, err error) { | 
					
						
							|  |  |  | 	if timeout <= 0 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("timeout must not be <= 0") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Note order of port arguments is switched between our AddPortMapping and the client's AddPortMapping. | 
					
						
							|  |  |  | 	response, err := n.client.AddPortMapping(protocol, internalPort, externalPort, timeout) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mappedExternalPort = int(response.MappedExternalPort) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *natPMPClient) DeletePortMapping(protocol string, externalPort, internalPort int) (err error) { | 
					
						
							|  |  |  | 	// To destroy a mapping, send an add-port with | 
					
						
							|  |  |  | 	// an internalPort of the internal port to destroy, an external port of zero and a time of zero. | 
					
						
							|  |  |  | 	_, err = n.client.AddPortMapping(protocol, internalPort, 0, 0) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } |