2019-01-02 01:55:51 +01:00
|
|
|
/* SPDX-License-Identifier: MIT
|
2018-05-03 15:04:00 +02:00
|
|
|
*
|
2019-01-02 01:55:51 +01:00
|
|
|
* Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
|
2018-05-03 15:04:00 +02:00
|
|
|
*/
|
|
|
|
|
2017-08-11 16:18:20 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2017-09-24 21:35:25 +02:00
|
|
|
"errors"
|
2017-11-14 16:27:53 +01:00
|
|
|
"golang.org/x/net/ipv4"
|
|
|
|
"golang.org/x/net/ipv6"
|
2017-08-11 16:18:20 +02:00
|
|
|
"net"
|
|
|
|
)
|
|
|
|
|
2018-05-16 22:20:15 +02:00
|
|
|
const (
|
|
|
|
ConnRoutineNumber = 2
|
|
|
|
)
|
|
|
|
|
2017-11-18 23:34:02 +01:00
|
|
|
/* A Bind handles listening on a port for both IPv6 and IPv4 UDP traffic
|
|
|
|
*/
|
|
|
|
type Bind interface {
|
2017-10-08 22:03:32 +02:00
|
|
|
SetMark(value uint32) error
|
2017-11-18 23:34:02 +01:00
|
|
|
ReceiveIPv6(buff []byte) (int, Endpoint, error)
|
|
|
|
ReceiveIPv4(buff []byte) (int, Endpoint, error)
|
2019-02-23 14:14:09 +01:00
|
|
|
Send(buff []byte, end Endpoint, tos byte) error
|
2017-10-08 22:03:32 +02:00
|
|
|
Close() error
|
|
|
|
}
|
|
|
|
|
2017-11-17 17:25:45 +01:00
|
|
|
/* An Endpoint maintains the source/destination caching for a peer
|
|
|
|
*
|
2017-11-18 23:34:02 +01:00
|
|
|
* dst : the remote address of a peer ("endpoint" in uapi terminology)
|
2017-11-17 17:25:45 +01:00
|
|
|
* src : the local address from which datagrams originate going to the peer
|
|
|
|
*/
|
2017-11-18 23:34:02 +01:00
|
|
|
type Endpoint interface {
|
2017-11-17 17:25:45 +01:00
|
|
|
ClearSrc() // clears the source address
|
|
|
|
SrcToString() string // returns the local source address (ip:port)
|
|
|
|
DstToString() string // returns the destination address (ip:port)
|
|
|
|
DstToBytes() []byte // used for mac2 cookie calculations
|
|
|
|
DstIP() net.IP
|
|
|
|
SrcIP() net.IP
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
}
|
2018-05-18 05:02:35 +02:00
|
|
|
ip4 := addr.IP.To4()
|
|
|
|
if ip4 != nil {
|
|
|
|
addr.IP = ip4
|
|
|
|
}
|
2017-09-24 21:35:25 +02:00
|
|
|
return addr, err
|
|
|
|
}
|
|
|
|
|
2017-11-19 13:35:17 +01:00
|
|
|
func unsafeCloseBind(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
|
|
|
|
}
|
2018-05-20 06:19:29 +02:00
|
|
|
netc.stopping.Wait()
|
2017-11-11 23:26:44 +01:00
|
|
|
return err
|
2017-11-11 15:43:55 +01:00
|
|
|
}
|
|
|
|
|
2018-02-18 20:49:03 +01:00
|
|
|
func (device *Device) BindSetMark(mark uint32) error {
|
|
|
|
|
2019-01-03 19:04:00 +01:00
|
|
|
device.net.Lock()
|
|
|
|
defer device.net.Unlock()
|
2018-02-18 20:49:03 +01:00
|
|
|
|
|
|
|
// check if modified
|
|
|
|
|
|
|
|
if device.net.fwmark == mark {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// update fwmark on existing bind
|
|
|
|
|
|
|
|
device.net.fwmark = mark
|
|
|
|
if device.isUp.Get() && device.net.bind != nil {
|
|
|
|
if err := device.net.bind.SetMark(mark); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-13 23:14:43 +02:00
|
|
|
// clear cached source addresses
|
|
|
|
|
2019-01-03 19:04:00 +01:00
|
|
|
device.peers.RLock()
|
2018-05-13 23:14:43 +02:00
|
|
|
for _, peer := range device.peers.keyMap {
|
2019-01-03 19:04:00 +01:00
|
|
|
peer.Lock()
|
|
|
|
defer peer.Unlock()
|
2018-05-13 23:14:43 +02:00
|
|
|
if peer.endpoint != nil {
|
|
|
|
peer.endpoint.ClearSrc()
|
|
|
|
}
|
|
|
|
}
|
2019-01-03 19:04:00 +01:00
|
|
|
device.peers.RUnlock()
|
2018-05-13 23:14:43 +02:00
|
|
|
|
2018-02-18 20:49:03 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-01-26 22:52:32 +01:00
|
|
|
func (device *Device) BindUpdate() error {
|
|
|
|
|
2019-01-03 19:04:00 +01:00
|
|
|
device.net.Lock()
|
|
|
|
defer device.net.Unlock()
|
2018-02-02 16:40:14 +01:00
|
|
|
|
2017-10-07 22:35:23 +02:00
|
|
|
// close existing sockets
|
2017-08-11 16:18:20 +02:00
|
|
|
|
2017-11-19 13:35:17 +01:00
|
|
|
if err := unsafeCloseBind(device); err != nil {
|
2017-11-11 15:43:55 +01:00
|
|
|
return err
|
2017-08-11 16:18:20 +02:00
|
|
|
}
|
|
|
|
|
2017-10-07 22:35:23 +02:00
|
|
|
// open new sockets
|
2017-08-11 16:18:20 +02:00
|
|
|
|
2017-12-29 17:42:09 +01:00
|
|
|
if device.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
|
2018-02-02 16:40:14 +01:00
|
|
|
netc := &device.net
|
2018-05-14 03:00:40 +02:00
|
|
|
netc.bind, netc.port, err = CreateBind(netc.port, device)
|
2017-10-08 22:03:32 +02:00
|
|
|
if err != nil {
|
2017-11-11 15:43:55 +01:00
|
|
|
netc.bind = nil
|
2018-02-18 20:49:03 +01:00
|
|
|
netc.port = 0
|
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
|
|
|
|
2018-02-18 20:49:03 +01:00
|
|
|
// set fwmark
|
2017-10-08 22:03:32 +02:00
|
|
|
|
2018-02-18 20:49:03 +01:00
|
|
|
if netc.fwmark != 0 {
|
|
|
|
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
|
|
|
|
|
2019-01-03 19:04:00 +01:00
|
|
|
device.peers.RLock()
|
2018-02-02 16:40:14 +01:00
|
|
|
for _, peer := range device.peers.keyMap {
|
2019-01-03 19:04:00 +01:00
|
|
|
peer.Lock()
|
|
|
|
defer peer.Unlock()
|
2017-11-18 23:34:02 +01:00
|
|
|
if peer.endpoint != nil {
|
|
|
|
peer.endpoint.ClearSrc()
|
|
|
|
}
|
2017-10-16 21:33:47 +02:00
|
|
|
}
|
2019-01-03 19:04:00 +01:00
|
|
|
device.peers.RUnlock()
|
2017-11-11 15:43:55 +01:00
|
|
|
|
2018-01-26 22:52:32 +01:00
|
|
|
// start receiving routines
|
2017-11-11 15:43:55 +01:00
|
|
|
|
2018-05-20 06:19:29 +02:00
|
|
|
device.net.starting.Add(ConnRoutineNumber)
|
|
|
|
device.net.stopping.Add(ConnRoutineNumber)
|
2017-11-29 18:46:31 +01:00
|
|
|
go device.RoutineReceiveIncoming(ipv4.Version, netc.bind)
|
|
|
|
go device.RoutineReceiveIncoming(ipv6.Version, netc.bind)
|
2018-05-20 06:19:29 +02:00
|
|
|
device.net.starting.Wait()
|
2017-11-14 16:27:53 +01:00
|
|
|
|
2017-11-11 23:26:44 +01:00
|
|
|
device.log.Debug.Println("UDP bind has been updated")
|
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
|
|
|
}
|
|
|
|
|
2018-01-26 22:52:32 +01:00
|
|
|
func (device *Device) BindClose() error {
|
2019-01-03 19:04:00 +01:00
|
|
|
device.net.Lock()
|
2017-11-19 13:35:17 +01:00
|
|
|
err := unsafeCloseBind(device)
|
2019-01-03 19:04:00 +01:00
|
|
|
device.net.Unlock()
|
2017-11-11 15:43:55 +01:00
|
|
|
return err
|
2017-08-11 16:18:20 +02:00
|
|
|
}
|