2017-08-11 16:18:20 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2017-09-24 21:35:25 +02:00
|
|
|
"errors"
|
2017-08-11 16:18:20 +02:00
|
|
|
"net"
|
|
|
|
)
|
|
|
|
|
2017-10-08 22:03:32 +02:00
|
|
|
type UDPBind interface {
|
|
|
|
SetMark(value uint32) error
|
|
|
|
ReceiveIPv6(buff []byte, end *Endpoint) (int, error)
|
|
|
|
ReceiveIPv4(buff []byte, end *Endpoint) (int, error)
|
|
|
|
Send(buff []byte, end *Endpoint) error
|
|
|
|
Close() error
|
|
|
|
}
|
|
|
|
|
2017-09-24 21:35:25 +02:00
|
|
|
func parseEndpoint(s string) (*net.UDPAddr, error) {
|
|
|
|
|
|
|
|
// ensure that the host is an IP address
|
|
|
|
|
|
|
|
host, _, err := net.SplitHostPort(s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if ip := net.ParseIP(host); ip == nil {
|
|
|
|
return nil, errors.New("Failed to parse IP address: " + host)
|
|
|
|
}
|
|
|
|
|
|
|
|
// parse address and port
|
|
|
|
|
|
|
|
addr, err := net.ResolveUDPAddr("udp", s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return addr, err
|
|
|
|
}
|
|
|
|
|
2017-11-11 15:43:55 +01:00
|
|
|
/* Must hold device and net lock
|
|
|
|
*/
|
|
|
|
func unsafeCloseUDPListener(device *Device) error {
|
2017-11-11 23:26:44 +01:00
|
|
|
var err error
|
2017-11-11 15:43:55 +01:00
|
|
|
netc := &device.net
|
|
|
|
if netc.bind != nil {
|
2017-11-11 23:26:44 +01:00
|
|
|
err = netc.bind.Close()
|
2017-11-11 15:43:55 +01:00
|
|
|
netc.bind = nil
|
2017-11-11 23:26:44 +01:00
|
|
|
netc.update.Add(1)
|
2017-11-11 15:43:55 +01:00
|
|
|
}
|
2017-11-11 23:26:44 +01:00
|
|
|
return err
|
2017-11-11 15:43:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// must inform all listeners
|
2017-10-16 21:33:47 +02:00
|
|
|
func UpdateUDPListener(device *Device) error {
|
|
|
|
device.mutex.Lock()
|
|
|
|
defer device.mutex.Unlock()
|
|
|
|
|
2017-08-11 16:18:20 +02:00
|
|
|
netc := &device.net
|
|
|
|
netc.mutex.Lock()
|
2017-08-17 12:58:18 +02:00
|
|
|
defer netc.mutex.Unlock()
|
2017-08-11 16:18:20 +02:00
|
|
|
|
2017-10-07 22:35:23 +02:00
|
|
|
// close existing sockets
|
2017-08-11 16:18:20 +02:00
|
|
|
|
2017-11-11 15:43:55 +01:00
|
|
|
if err := unsafeCloseUDPListener(device); err != nil {
|
|
|
|
return err
|
2017-08-11 16:18:20 +02:00
|
|
|
}
|
|
|
|
|
2017-11-11 23:26:44 +01:00
|
|
|
// assumption: netc.update WaitGroup should be exactly 1
|
2017-11-11 15:43:55 +01:00
|
|
|
|
2017-10-07 22:35:23 +02:00
|
|
|
// open new sockets
|
2017-08-11 16:18:20 +02:00
|
|
|
|
|
|
|
if device.tun.isUp.Get() {
|
2017-08-17 12:58:18 +02:00
|
|
|
|
2017-10-08 22:03:32 +02:00
|
|
|
// bind to new port
|
|
|
|
|
|
|
|
var err error
|
|
|
|
netc.bind, netc.port, err = CreateUDPBind(netc.port)
|
|
|
|
if err != nil {
|
2017-11-11 15:43:55 +01:00
|
|
|
netc.bind = nil
|
2017-10-08 22:03:32 +02:00
|
|
|
return err
|
2017-08-11 16:18:20 +02:00
|
|
|
}
|
2017-08-17 12:58:18 +02:00
|
|
|
|
2017-10-08 22:03:32 +02:00
|
|
|
// set mark
|
|
|
|
|
|
|
|
err = netc.bind.SetMark(netc.fwmark)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2017-08-22 17:22:45 +02:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:33:47 +02:00
|
|
|
// clear cached source addresses
|
|
|
|
|
|
|
|
for _, peer := range device.peers {
|
|
|
|
peer.mutex.Lock()
|
|
|
|
peer.endpoint.value.ClearSrc()
|
|
|
|
peer.mutex.Unlock()
|
|
|
|
}
|
2017-11-11 15:43:55 +01:00
|
|
|
|
2017-11-11 23:26:44 +01:00
|
|
|
// decrease waitgroup to 0
|
2017-11-11 15:43:55 +01:00
|
|
|
|
2017-11-11 23:26:44 +01:00
|
|
|
device.log.Debug.Println("UDP bind has been updated")
|
|
|
|
netc.update.Done()
|
2017-08-11 16:18:20 +02:00
|
|
|
}
|
|
|
|
|
2017-08-17 12:58:18 +02:00
|
|
|
return nil
|
2017-08-11 16:18:20 +02:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:33:47 +02:00
|
|
|
func CloseUDPListener(device *Device) error {
|
2017-11-11 15:43:55 +01:00
|
|
|
device.mutex.Lock()
|
|
|
|
device.net.mutex.Lock()
|
|
|
|
err := unsafeCloseUDPListener(device)
|
|
|
|
device.net.mutex.Unlock()
|
|
|
|
device.mutex.Unlock()
|
|
|
|
return err
|
2017-08-11 16:18:20 +02:00
|
|
|
}
|