Add support for fwmark on linux

This commit is contained in:
Mathias Hall-Andersen 2017-08-22 17:22:45 +02:00
parent c6d03ef17f
commit 4986cfe78b
4 changed files with 44 additions and 12 deletions

View File

@ -145,10 +145,10 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
return &IPCError{Code: ipcErrorInvalid} return &IPCError{Code: ipcErrorInvalid}
} }
netc := &device.net device.net.mutex.Lock()
netc.mutex.Lock() device.net.addr = addr
netc.addr = addr device.net.mutex.Unlock()
netc.mutex.Unlock()
err = updateUDPConn(device) err = updateUDPConn(device)
if err != nil { if err != nil {
logError.Println("Failed to set listen_port:", err) logError.Println("Failed to set listen_port:", err)
@ -158,7 +158,24 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
// TODO: Clear source address of all peers // TODO: Clear source address of all peers
case "fwmark": case "fwmark":
logError.Println("FWMark not handled yet") fwmark, err := strconv.ParseInt(value, 10, 32)
if err != nil {
logError.Println("Invalid fwmark", err)
return &IPCError{Code: ipcErrorInvalid}
}
device.net.mutex.Lock()
device.net.fwmark = int(fwmark)
err = setMark(
device.net.conn,
device.net.fwmark,
)
device.net.mutex.Unlock()
if err != nil {
logError.Println("Failed to set fwmark:", err)
return &IPCError{Code: ipcErrorIO}
}
// TODO: Clear source address of all peers // TODO: Clear source address of all peers
case "public_key": case "public_key":

View File

@ -13,6 +13,7 @@ func updateUDPConn(device *Device) error {
if netc.conn != nil { if netc.conn != nil {
netc.conn.Close() netc.conn.Close()
netc.conn = nil
} }
// open new connection // open new connection
@ -26,11 +27,24 @@ func updateUDPConn(device *Device) error {
return err return err
} }
// set fwmark
err = setMark(netc.conn, netc.fwmark)
if err != nil {
return err
}
// retrieve port (may have been chosen by kernel) // retrieve port (may have been chosen by kernel)
addr := conn.LocalAddr() addr := conn.LocalAddr()
netc.conn = conn netc.conn = conn
netc.addr, _ = net.ResolveUDPAddr(addr.Network(), addr.String()) netc.addr, _ = net.ResolveUDPAddr(
addr.Network(),
addr.String(),
)
// notify goroutines
signalSend(device.signal.newUDPConn) signalSend(device.signal.newUDPConn)
} }

View File

@ -21,9 +21,10 @@ type Device struct {
messageBuffers sync.Pool messageBuffers sync.Pool
} }
net struct { net struct {
mutex sync.RWMutex mutex sync.RWMutex
addr *net.UDPAddr // UDP source address addr *net.UDPAddr // UDP source address
conn *net.UDPConn // UDP "connection" conn *net.UDPConn // UDP "connection"
fwmark int
} }
mutex sync.RWMutex mutex sync.RWMutex
privateKey NoisePrivateKey privateKey NoisePrivateKey

View File

@ -34,28 +34,28 @@ func (device *Device) RoutineTUNEventReader() {
if err != nil { if err != nil {
logError.Println("Failed to load updated MTU of device:", err) logError.Println("Failed to load updated MTU of device:", err)
} else if int(old) != mtu { } else if int(old) != mtu {
atomic.StoreInt32(&device.tun.mtu, int32(mtu))
if mtu+MessageTransportSize > MaxMessageSize { if mtu+MessageTransportSize > MaxMessageSize {
logInfo.Println("MTU updated:", mtu, "(too large)") logInfo.Println("MTU updated:", mtu, "(too large)")
} else { } else {
logInfo.Println("MTU updated:", mtu) logInfo.Println("MTU updated:", mtu)
} }
atomic.StoreInt32(&device.tun.mtu, int32(mtu))
} }
} }
if event&TUNEventUp != 0 { if event&TUNEventUp != 0 {
if !device.tun.isUp.Get() { if !device.tun.isUp.Get() {
logInfo.Println("Interface set up")
device.tun.isUp.Set(true) device.tun.isUp.Set(true)
updateUDPConn(device) updateUDPConn(device)
logInfo.Println("Interface set up")
} }
} }
if event&TUNEventDown != 0 { if event&TUNEventDown != 0 {
if device.tun.isUp.Get() { if device.tun.isUp.Get() {
logInfo.Println("Interface set down")
device.tun.isUp.Set(false) device.tun.isUp.Set(false)
closeUDPConn(device) closeUDPConn(device)
logInfo.Println("Interface set down")
} }
} }
} }