Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wgcfg: new package #11

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
19 changes: 7 additions & 12 deletions device/boundif_windows.go → conn/boundif_windows.go
Expand Up @@ -3,11 +3,10 @@
* Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
*/

package device
package conn

import (
"encoding/binary"
"errors"
"unsafe"

"golang.org/x/sys/windows"
Expand All @@ -18,17 +17,13 @@ const (
sockoptIPV6_UNICAST_IF = 31
)

func (device *Device) BindSocketToInterface4(interfaceIndex uint32, blackhole bool) error {
func (bind *nativeBind) BindSocketToInterface4(interfaceIndex uint32, blackhole bool) error {
/* MSDN says for IPv4 this needs to be in net byte order, so that it's like an IP address with leading zeros. */
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, interfaceIndex)
interfaceIndex = *(*uint32)(unsafe.Pointer(&bytes[0]))

if device.net.bind == nil {
return errors.New("Bind is not yet initialized")
}

sysconn, err := device.net.bind.(*nativeBind).ipv4.SyscallConn()
sysconn, err := bind.ipv4.SyscallConn()
if err != nil {
return err
}
Expand All @@ -41,12 +36,12 @@ func (device *Device) BindSocketToInterface4(interfaceIndex uint32, blackhole bo
if err != nil {
return err
}
device.net.bind.(*nativeBind).blackhole4 = blackhole
bind.blackhole4 = blackhole
return nil
}

func (device *Device) BindSocketToInterface6(interfaceIndex uint32, blackhole bool) error {
sysconn, err := device.net.bind.(*nativeBind).ipv6.SyscallConn()
func (bind *nativeBind) BindSocketToInterface6(interfaceIndex uint32, blackhole bool) error {
sysconn, err := bind.ipv6.SyscallConn()
if err != nil {
return err
}
Expand All @@ -59,6 +54,6 @@ func (device *Device) BindSocketToInterface6(interfaceIndex uint32, blackhole bo
if err != nil {
return err
}
device.net.bind.(*nativeBind).blackhole6 = blackhole
bind.blackhole6 = blackhole
return nil
}
101 changes: 101 additions & 0 deletions conn/conn.go
@@ -0,0 +1,101 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
*/

// Package conn implements WireGuard's network connections.
package conn

import (
"errors"
"net"
"strings"
)

// A Bind listens on a port for both IPv6 and IPv4 UDP traffic.
type Bind interface {
// LastMark reports the last mark set for this Bind.
LastMark() uint32

// SetMark sets the mark for each packet sent through this Bind.
// This mark is passed to the kernel as the socket option SO_MARK.
SetMark(mark uint32) error

// ReceiveIPv6 reads an IPv6 UDP packet into b.
//
// It reports the number of bytes read, n,
// the packet source address ep,
// and any error.
ReceiveIPv6(buff []byte) (n int, ep Endpoint, err error)

// ReceiveIPv4 reads an IPv4 UDP packet into b.
//
// It reports the number of bytes read, n,
// the packet source address ep,
// and any error.
ReceiveIPv4(b []byte) (n int, ep Endpoint, err error)

// Send writes a packet b to address ep.
Send(b []byte, ep Endpoint) error

// Close closes the Bind connection.
Close() error
}

// CreateBind creates a Bind bound to a port.
//
// The value actualPort reports the actual port number the Bind
// object gets bound to.
func CreateBind(port uint16) (b Bind, actualPort uint16, err error) {
return createBind(port)
}

// BindToInterface is implemented by Bind objects that support being
// tied to a single network interface.
type BindToInterface interface {
BindToInterface4(interfaceIndex uint32, blackhole bool) error
BindToInterface6(interfaceIndex uint32, blackhole bool) 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
}
ip4 := addr.IP.To4()
if ip4 != nil {
addr.IP = ip4
}
return addr, err
}
13 changes: 6 additions & 7 deletions device/conn_default.go → conn/conn_default.go
Expand Up @@ -5,7 +5,7 @@
* Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
*/

package device
package conn

import (
"net"
Expand Down Expand Up @@ -67,16 +67,13 @@ func (e *NativeEndpoint) SrcToString() string {
}

func listenNet(network string, port int) (*net.UDPConn, int, error) {

// listen

conn, err := net.ListenUDP(network, &net.UDPAddr{Port: port})
if err != nil {
return nil, 0, err
}

// retrieve port

// Retrieve port.
// TODO(crawshaw): under what circumstances is this necessary?
laddr := conn.LocalAddr()
uaddr, err := net.ResolveUDPAddr(
laddr.Network(),
Expand All @@ -100,7 +97,7 @@ func extractErrno(err error) error {
return syscallErr.Err
}

func CreateBind(uport uint16, device *Device) (Bind, uint16, error) {
func createBind(uport uint16) (Bind, uint16, error) {
var err error
var bind nativeBind

Expand Down Expand Up @@ -135,6 +132,8 @@ func (bind *nativeBind) Close() error {
return err2
}

func (bind *nativeBind) LastMark() uint32 { return 0 }

func (bind *nativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
if bind.ipv4 == nil {
return 0, nil, syscall.EAFNOSUPPORT
Expand Down