1
0
mirror of https://git.zx2c4.com/wireguard-go synced 2024-11-15 09:15:14 +01:00
wireguard-go/device/conn.go

188 lines
3.8 KiB
Go
Raw Normal View History

2019-01-02 01:55:51 +01:00
/* SPDX-License-Identifier: MIT
*
2019-01-02 01:55:51 +01:00
* Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
*/
2019-03-03 04:04:41 +01:00
package device
import (
"errors"
"net"
"strings"
2019-05-14 09:09:52 +02:00
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
const (
ConnRoutineNumber = 2
)
/* 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
ReceiveIPv6(buff []byte) (int, Endpoint, error)
ReceiveIPv4(buff []byte) (int, Endpoint, error)
Send(buff []byte, end Endpoint) error
2017-10-08 22:03:32 +02:00
Close() error
}
/* An Endpoint maintains the source/destination caching for a peer
*
* dst : the remote address of a peer ("endpoint" in uapi terminology)
* src : the local address from which datagrams originate going to the peer
*/
type Endpoint interface {
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
}
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 i := strings.LastIndexByte(host, '%'); i > 0 && strings.IndexByte(host, ':') >= 0 {
// Remove the scope, if any. ResolveUDPAddr below will use it, but here we're just
// trying to make sure with a small sanity test that this is a real IP address and
// not something that's likely to incur DNS lookups.
host = host[:i]
}
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
}
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
}
netc.stopping.Wait()
2017-11-11 23:26:44 +01:00
return err
2017-11-11 15:43:55 +01:00
}
func (device *Device) BindSetMark(mark uint32) error {
device.net.Lock()
defer device.net.Unlock()
// 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
device.peers.RLock()
2018-05-13 23:14:43 +02:00
for _, peer := range device.peers.keyMap {
peer.Lock()
defer peer.Unlock()
2018-05-13 23:14:43 +02:00
if peer.endpoint != nil {
peer.endpoint.ClearSrc()
}
}
device.peers.RUnlock()
2018-05-13 23:14:43 +02:00
return nil
}
func (device *Device) BindUpdate() error {
device.net.Lock()
defer device.net.Unlock()
// close existing sockets
2017-11-19 13:35:17 +01:00
if err := unsafeCloseBind(device); err != nil {
2017-11-11 15:43:55 +01:00
return err
}
// open new sockets
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
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
netc.port = 0
2017-10-08 22:03:32 +02:00
return err
}
2017-08-17 12:58:18 +02:00
// set fwmark
2017-10-08 22:03:32 +02:00
if netc.fwmark != 0 {
err = netc.bind.SetMark(netc.fwmark)
if err != nil {
return err
}
2017-08-22 17:22:45 +02:00
}
// clear cached source addresses
device.peers.RLock()
for _, peer := range device.peers.keyMap {
peer.Lock()
defer peer.Unlock()
if peer.endpoint != nil {
peer.endpoint.ClearSrc()
}
}
device.peers.RUnlock()
2017-11-11 15:43:55 +01:00
// start receiving routines
2017-11-11 15:43:55 +01:00
device.net.starting.Add(ConnRoutineNumber)
device.net.stopping.Add(ConnRoutineNumber)
go device.RoutineReceiveIncoming(ipv4.Version, netc.bind)
go device.RoutineReceiveIncoming(ipv6.Version, netc.bind)
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-17 12:58:18 +02:00
return nil
}
func (device *Device) BindClose() error {
device.net.Lock()
2017-11-19 13:35:17 +01:00
err := unsafeCloseBind(device)
device.net.Unlock()
2017-11-11 15:43:55 +01:00
return err
2019-03-21 21:43:04 +01:00
}