Update
This commit is contained in:
9
vendor/github.com/tailscale/wireguard-go/conn/bind_std.go
generated
vendored
9
vendor/github.com/tailscale/wireguard-go/conn/bind_std.go
generated
vendored
@@ -341,7 +341,7 @@ func (e ErrUDPGSODisabled) Unwrap() error {
|
||||
return e.RetryErr
|
||||
}
|
||||
|
||||
func (s *StdNetBind) Send(bufs [][]byte, endpoint Endpoint) error {
|
||||
func (s *StdNetBind) Send(bufs [][]byte, endpoint Endpoint, offset int) error {
|
||||
s.mu.Lock()
|
||||
blackhole := s.blackhole4
|
||||
conn := s.ipv4
|
||||
@@ -384,7 +384,7 @@ func (s *StdNetBind) Send(bufs [][]byte, endpoint Endpoint) error {
|
||||
)
|
||||
retry:
|
||||
if offload {
|
||||
n := coalesceMessages(ua, endpoint.(*StdNetEndpoint), bufs, *msgs, setGSOSize)
|
||||
n := coalesceMessages(ua, endpoint.(*StdNetEndpoint), bufs, offset, *msgs, setGSOSize)
|
||||
err = s.send(conn, br, (*msgs)[:n])
|
||||
if err != nil && offload && errShouldDisableUDPGSO(err) {
|
||||
offload = false
|
||||
@@ -401,7 +401,7 @@ retry:
|
||||
} else {
|
||||
for i := range bufs {
|
||||
(*msgs)[i].Addr = ua
|
||||
(*msgs)[i].Buffers[0] = bufs[i]
|
||||
(*msgs)[i].Buffers[0] = bufs[i][offset:]
|
||||
setSrcControl(&(*msgs)[i].OOB, endpoint.(*StdNetEndpoint))
|
||||
}
|
||||
err = s.send(conn, br, (*msgs)[:len(bufs)])
|
||||
@@ -450,7 +450,7 @@ const (
|
||||
|
||||
type setGSOFunc func(control *[]byte, gsoSize uint16)
|
||||
|
||||
func coalesceMessages(addr *net.UDPAddr, ep *StdNetEndpoint, bufs [][]byte, msgs []ipv6.Message, setGSO setGSOFunc) int {
|
||||
func coalesceMessages(addr *net.UDPAddr, ep *StdNetEndpoint, bufs [][]byte, offset int, msgs []ipv6.Message, setGSO setGSOFunc) int {
|
||||
var (
|
||||
base = -1 // index of msg we are currently coalescing into
|
||||
gsoSize int // segmentation size of msgs[base]
|
||||
@@ -462,6 +462,7 @@ func coalesceMessages(addr *net.UDPAddr, ep *StdNetEndpoint, bufs [][]byte, msgs
|
||||
maxPayloadLen = maxIPv6PayloadLen
|
||||
}
|
||||
for i, buf := range bufs {
|
||||
buf = buf[offset:]
|
||||
if i > 0 {
|
||||
msgLen := len(buf)
|
||||
baseLenBefore := len(msgs[base].Buffers[0])
|
||||
|
||||
3
vendor/github.com/tailscale/wireguard-go/conn/bind_windows.go
generated
vendored
3
vendor/github.com/tailscale/wireguard-go/conn/bind_windows.go
generated
vendored
@@ -486,7 +486,7 @@ func (bind *afWinRingBind) Send(buf []byte, nend *WinRingEndpoint, isOpen *atomi
|
||||
return winrio.SendEx(bind.rq, dataBuffer, 1, nil, addressBuffer, nil, nil, 0, 0)
|
||||
}
|
||||
|
||||
func (bind *WinRingBind) Send(bufs [][]byte, endpoint Endpoint) error {
|
||||
func (bind *WinRingBind) Send(bufs [][]byte, endpoint Endpoint, offset int) error {
|
||||
nend, ok := endpoint.(*WinRingEndpoint)
|
||||
if !ok {
|
||||
return ErrWrongEndpointType
|
||||
@@ -494,6 +494,7 @@ func (bind *WinRingBind) Send(bufs [][]byte, endpoint Endpoint) error {
|
||||
bind.mu.RLock()
|
||||
defer bind.mu.RUnlock()
|
||||
for _, buf := range bufs {
|
||||
buf = buf[offset:]
|
||||
switch nend.family {
|
||||
case windows.AF_INET:
|
||||
if bind.v4.blackhole {
|
||||
|
||||
36
vendor/github.com/tailscale/wireguard-go/conn/conn.go
generated
vendored
36
vendor/github.com/tailscale/wireguard-go/conn/conn.go
generated
vendored
@@ -45,9 +45,11 @@ type Bind interface {
|
||||
// This mark is passed to the kernel as the socket option SO_MARK.
|
||||
SetMark(mark uint32) error
|
||||
|
||||
// Send writes one or more packets in bufs to address ep. The length of
|
||||
// bufs must not exceed BatchSize().
|
||||
Send(bufs [][]byte, ep Endpoint) error
|
||||
// Send writes one or more packets in bufs to address ep. A nonzero offset
|
||||
// can be used to instruct the Bind on where packet data begins in each
|
||||
// element of the bufs slice. Space preceding offset is free to use for
|
||||
// additional encapsulation. The length of bufs must not exceed BatchSize().
|
||||
Send(bufs [][]byte, ep Endpoint, offset int) error
|
||||
|
||||
// ParseEndpoint creates a new endpoint from a string.
|
||||
ParseEndpoint(s string) (Endpoint, error)
|
||||
@@ -84,18 +86,38 @@ type Endpoint interface {
|
||||
SrcIP() netip.Addr
|
||||
}
|
||||
|
||||
// InitiationAwareEndpoint is an optional [Endpoint] specialization for
|
||||
// integrations that want to know when a WireGuard handshake initiation
|
||||
// message has been received, enabling just-in-time peer configuration before
|
||||
// attempted decryption.
|
||||
//
|
||||
// It's most useful when used in combination with [PeerAwareEndpoint], enabling
|
||||
// JIT peer configuration and post-decryption peer verification from a single
|
||||
// implementer.
|
||||
type InitiationAwareEndpoint interface {
|
||||
// InitiationMessagePublicKey is called when a handshake initiation message
|
||||
// has been received, and the sender's public key has been identified, but
|
||||
// BEFORE an attempt has been made to verify it.
|
||||
InitiationMessagePublicKey(peerPublicKey [32]byte)
|
||||
}
|
||||
|
||||
// PeerAwareEndpoint is an optional Endpoint specialization for
|
||||
// integrations that want to know about the outcome of cryptorouting
|
||||
// integrations that want to know about the outcome of Cryptokey Routing
|
||||
// identification.
|
||||
//
|
||||
// If they receive a packet from a source they had not pre-identified,
|
||||
// to learn the identification WireGuard can derive from the session
|
||||
// or handshake.
|
||||
//
|
||||
// If GetPeerEndpoint returns nil, WireGuard will be unable to respond
|
||||
// to the peer until a new endpoint is written by a later packet.
|
||||
// A [PeerAwareEndpoint] may be installed as the [conn.Endpoint] following
|
||||
// successful decryption unless endpoint roaming has been disabled for
|
||||
// the peer.
|
||||
type PeerAwareEndpoint interface {
|
||||
GetPeerEndpoint(peerPublicKey [32]byte) Endpoint
|
||||
// FromPeer is called at least once per successfully Cryptokey Routing ID'd
|
||||
// [ReceiveFunc] packets batch for a given node key. wireguard-go will
|
||||
// always call it for the latest/tail packet in the batch, only ever
|
||||
// suppressing calls for older packets.
|
||||
FromPeer(peerPublicKey [32]byte)
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
6
vendor/github.com/tailscale/wireguard-go/device/constants.go
generated
vendored
6
vendor/github.com/tailscale/wireguard-go/device/constants.go
generated
vendored
@@ -27,9 +27,9 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
MinMessageSize = MessageKeepaliveSize // minimum size of transport message (keepalive)
|
||||
MaxMessageSize = MaxSegmentSize // maximum size of transport message
|
||||
MaxContentSize = MaxSegmentSize - MessageTransportSize // maximum size of transport message content
|
||||
MinMessageSize = MessageKeepaliveSize // minimum size of transport message (keepalive)
|
||||
MaxMessageSize = MaxSegmentSize // maximum size of transport message
|
||||
MaxContentSize = MaxSegmentSize - MessageTransportSize - MessageEncapsulatingTransportSize // maximum size of transport message content
|
||||
)
|
||||
|
||||
/* Implementation constants */
|
||||
|
||||
4
vendor/github.com/tailscale/wireguard-go/device/device.go
generated
vendored
4
vendor/github.com/tailscale/wireguard-go/device/device.go
generated
vendored
@@ -368,10 +368,10 @@ func (device *Device) RemoveAllPeers() {
|
||||
}
|
||||
|
||||
func (device *Device) Close() {
|
||||
device.ipcMutex.Lock()
|
||||
defer device.ipcMutex.Unlock()
|
||||
device.state.Lock()
|
||||
defer device.state.Unlock()
|
||||
device.ipcMutex.Lock()
|
||||
defer device.ipcMutex.Unlock()
|
||||
if device.isClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
116
vendor/github.com/tailscale/wireguard-go/device/noise-protocol.go
generated
vendored
116
vendor/github.com/tailscale/wireguard-go/device/noise-protocol.go
generated
vendored
@@ -6,6 +6,7 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/poly1305"
|
||||
|
||||
"github.com/tailscale/wireguard-go/conn"
|
||||
"github.com/tailscale/wireguard-go/tai64n"
|
||||
)
|
||||
|
||||
@@ -60,13 +62,14 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
MessageInitiationSize = 148 // size of handshake initiation message
|
||||
MessageResponseSize = 92 // size of response message
|
||||
MessageCookieReplySize = 64 // size of cookie reply message
|
||||
MessageTransportHeaderSize = 16 // size of data preceding content in transport message
|
||||
MessageTransportSize = MessageTransportHeaderSize + poly1305.TagSize // size of empty transport
|
||||
MessageKeepaliveSize = MessageTransportSize // size of keepalive
|
||||
MessageHandshakeSize = MessageInitiationSize // size of largest handshake related message
|
||||
MessageInitiationSize = 148 // size of handshake initiation message
|
||||
MessageResponseSize = 92 // size of response message
|
||||
MessageCookieReplySize = 64 // size of cookie reply message
|
||||
MessageTransportHeaderSize = 16 // size of data preceding content in transport message
|
||||
MessageEncapsulatingTransportSize = 8 // size of optional, free (for use by conn.Bind.Send()) space preceding the transport header
|
||||
MessageTransportSize = MessageTransportHeaderSize + poly1305.TagSize // size of empty transport
|
||||
MessageKeepaliveSize = MessageTransportSize // size of keepalive
|
||||
MessageHandshakeSize = MessageInitiationSize // size of largest handshake related message
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -115,6 +118,98 @@ type MessageCookieReply struct {
|
||||
Cookie [blake2s.Size128 + poly1305.TagSize]byte
|
||||
}
|
||||
|
||||
var errMessageLengthMismatch = errors.New("message length mismatch")
|
||||
|
||||
func (msg *MessageInitiation) unmarshal(b []byte) error {
|
||||
if len(b) != MessageInitiationSize {
|
||||
return errMessageLengthMismatch
|
||||
}
|
||||
|
||||
msg.Type = binary.LittleEndian.Uint32(b)
|
||||
msg.Sender = binary.LittleEndian.Uint32(b[4:])
|
||||
copy(msg.Ephemeral[:], b[8:])
|
||||
copy(msg.Static[:], b[8+len(msg.Ephemeral):])
|
||||
copy(msg.Timestamp[:], b[8+len(msg.Ephemeral)+len(msg.Static):])
|
||||
copy(msg.MAC1[:], b[8+len(msg.Ephemeral)+len(msg.Static)+len(msg.Timestamp):])
|
||||
copy(msg.MAC2[:], b[8+len(msg.Ephemeral)+len(msg.Static)+len(msg.Timestamp)+len(msg.MAC1):])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *MessageInitiation) marshal(b []byte) error {
|
||||
if len(b) != MessageInitiationSize {
|
||||
return errMessageLengthMismatch
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(b, msg.Type)
|
||||
binary.LittleEndian.PutUint32(b[4:], msg.Sender)
|
||||
copy(b[8:], msg.Ephemeral[:])
|
||||
copy(b[8+len(msg.Ephemeral):], msg.Static[:])
|
||||
copy(b[8+len(msg.Ephemeral)+len(msg.Static):], msg.Timestamp[:])
|
||||
copy(b[8+len(msg.Ephemeral)+len(msg.Static)+len(msg.Timestamp):], msg.MAC1[:])
|
||||
copy(b[8+len(msg.Ephemeral)+len(msg.Static)+len(msg.Timestamp)+len(msg.MAC1):], msg.MAC2[:])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *MessageResponse) unmarshal(b []byte) error {
|
||||
if len(b) != MessageResponseSize {
|
||||
return errMessageLengthMismatch
|
||||
}
|
||||
|
||||
msg.Type = binary.LittleEndian.Uint32(b)
|
||||
msg.Sender = binary.LittleEndian.Uint32(b[4:])
|
||||
msg.Receiver = binary.LittleEndian.Uint32(b[8:])
|
||||
copy(msg.Ephemeral[:], b[12:])
|
||||
copy(msg.Empty[:], b[12+len(msg.Ephemeral):])
|
||||
copy(msg.MAC1[:], b[12+len(msg.Ephemeral)+len(msg.Empty):])
|
||||
copy(msg.MAC2[:], b[12+len(msg.Ephemeral)+len(msg.Empty)+len(msg.MAC1):])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *MessageResponse) marshal(b []byte) error {
|
||||
if len(b) != MessageResponseSize {
|
||||
return errMessageLengthMismatch
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(b, msg.Type)
|
||||
binary.LittleEndian.PutUint32(b[4:], msg.Sender)
|
||||
binary.LittleEndian.PutUint32(b[8:], msg.Receiver)
|
||||
copy(b[12:], msg.Ephemeral[:])
|
||||
copy(b[12+len(msg.Ephemeral):], msg.Empty[:])
|
||||
copy(b[12+len(msg.Ephemeral)+len(msg.Empty):], msg.MAC1[:])
|
||||
copy(b[12+len(msg.Ephemeral)+len(msg.Empty)+len(msg.MAC1):], msg.MAC2[:])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *MessageCookieReply) unmarshal(b []byte) error {
|
||||
if len(b) != MessageCookieReplySize {
|
||||
return errMessageLengthMismatch
|
||||
}
|
||||
|
||||
msg.Type = binary.LittleEndian.Uint32(b)
|
||||
msg.Receiver = binary.LittleEndian.Uint32(b[4:])
|
||||
copy(msg.Nonce[:], b[8:])
|
||||
copy(msg.Cookie[:], b[8+len(msg.Nonce):])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *MessageCookieReply) marshal(b []byte) error {
|
||||
if len(b) != MessageCookieReplySize {
|
||||
return errMessageLengthMismatch
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(b, msg.Type)
|
||||
binary.LittleEndian.PutUint32(b[4:], msg.Receiver)
|
||||
copy(b[8:], msg.Nonce[:])
|
||||
copy(b[8+len(msg.Nonce):], msg.Cookie[:])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Handshake struct {
|
||||
state handshakeState
|
||||
mutex sync.RWMutex
|
||||
@@ -244,7 +339,7 @@ func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, e
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation) *Peer {
|
||||
func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation, endpoint conn.Endpoint) *Peer {
|
||||
var (
|
||||
hash [blake2s.Size]byte
|
||||
chainKey [blake2s.Size]byte
|
||||
@@ -278,6 +373,11 @@ func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation) *Peer {
|
||||
|
||||
// lookup peer
|
||||
|
||||
initEP, ok := endpoint.(conn.InitiationAwareEndpoint)
|
||||
if ok {
|
||||
initEP.InitiationMessagePublicKey(peerPK)
|
||||
}
|
||||
|
||||
peer := device.LookupPeer(peerPK)
|
||||
if peer == nil || !peer.isRunning.Load() {
|
||||
return nil
|
||||
|
||||
8
vendor/github.com/tailscale/wireguard-go/device/peer.go
generated
vendored
8
vendor/github.com/tailscale/wireguard-go/device/peer.go
generated
vendored
@@ -113,6 +113,9 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
|
||||
return peer, nil
|
||||
}
|
||||
|
||||
// SendBuffers sends buffers to peer. WireGuard packet data in each element of
|
||||
// buffers must be preceded by MessageEncapsulatingTransportSize number of
|
||||
// bytes.
|
||||
func (peer *Peer) SendBuffers(buffers [][]byte) error {
|
||||
peer.device.net.RLock()
|
||||
defer peer.device.net.RUnlock()
|
||||
@@ -133,7 +136,7 @@ func (peer *Peer) SendBuffers(buffers [][]byte) error {
|
||||
}
|
||||
peer.endpoint.Unlock()
|
||||
|
||||
err := peer.device.net.bind.Send(buffers, endpoint)
|
||||
err := peer.device.net.bind.Send(buffers, endpoint, MessageEncapsulatingTransportSize)
|
||||
if err == nil {
|
||||
var totalLen uint64
|
||||
for _, b := range buffers {
|
||||
@@ -283,9 +286,6 @@ func (peer *Peer) SetEndpointFromPacket(endpoint conn.Endpoint) {
|
||||
return
|
||||
}
|
||||
peer.endpoint.clearSrcOnTx = false
|
||||
if ep, ok := endpoint.(conn.PeerAwareEndpoint); ok {
|
||||
endpoint = ep.GetPeerEndpoint(peer.handshake.remoteStatic)
|
||||
}
|
||||
peer.endpoint.val = endpoint
|
||||
}
|
||||
|
||||
|
||||
20
vendor/github.com/tailscale/wireguard-go/device/receive.go
generated
vendored
20
vendor/github.com/tailscale/wireguard-go/device/receive.go
generated
vendored
@@ -6,7 +6,6 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -287,8 +286,7 @@ func (device *Device) RoutineHandshake(id int) {
|
||||
// unmarshal packet
|
||||
|
||||
var reply MessageCookieReply
|
||||
reader := bytes.NewReader(elem.packet)
|
||||
err := binary.Read(reader, binary.LittleEndian, &reply)
|
||||
err := reply.unmarshal(elem.packet)
|
||||
if err != nil {
|
||||
device.log.Verbosef("Failed to decode cookie reply")
|
||||
goto skip
|
||||
@@ -353,8 +351,7 @@ func (device *Device) RoutineHandshake(id int) {
|
||||
// unmarshal
|
||||
|
||||
var msg MessageInitiation
|
||||
reader := bytes.NewReader(elem.packet)
|
||||
err := binary.Read(reader, binary.LittleEndian, &msg)
|
||||
err := msg.unmarshal(elem.packet)
|
||||
if err != nil {
|
||||
device.log.Errorf("Failed to decode initiation message")
|
||||
goto skip
|
||||
@@ -362,7 +359,7 @@ func (device *Device) RoutineHandshake(id int) {
|
||||
|
||||
// consume initiation
|
||||
|
||||
peer := device.ConsumeMessageInitiation(&msg)
|
||||
peer := device.ConsumeMessageInitiation(&msg, elem.endpoint)
|
||||
if peer == nil {
|
||||
device.log.Verbosef("Received invalid initiation message from %s", elem.endpoint.DstToString())
|
||||
goto skip
|
||||
@@ -386,8 +383,7 @@ func (device *Device) RoutineHandshake(id int) {
|
||||
// unmarshal
|
||||
|
||||
var msg MessageResponse
|
||||
reader := bytes.NewReader(elem.packet)
|
||||
err := binary.Read(reader, binary.LittleEndian, &msg)
|
||||
err := msg.unmarshal(elem.packet)
|
||||
if err != nil {
|
||||
device.log.Errorf("Failed to decode response message")
|
||||
goto skip
|
||||
@@ -447,6 +443,7 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
|
||||
elemsContainer.Lock()
|
||||
validTailPacket := -1
|
||||
dataPacketReceived := false
|
||||
rxBytesLen := uint64(0)
|
||||
for i, elem := range elemsContainer.elems {
|
||||
if elem.packet == nil {
|
||||
// decryption failed
|
||||
@@ -463,7 +460,10 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
|
||||
peer.timersHandshakeComplete()
|
||||
peer.SendStagedPackets()
|
||||
}
|
||||
peer.rxBytes.Add(uint64(len(elem.packet) + MinMessageSize))
|
||||
if ep, ok := elem.endpoint.(conn.PeerAwareEndpoint); ok {
|
||||
ep.FromPeer(peer.handshake.remoteStatic)
|
||||
}
|
||||
rxBytesLen += uint64(len(elem.packet) + MinMessageSize)
|
||||
|
||||
if len(elem.packet) == 0 {
|
||||
device.log.Verbosef("%v - Receiving keepalive packet", peer)
|
||||
@@ -512,6 +512,8 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
|
||||
|
||||
bufs = append(bufs, elem.buffer[:MessageTransportOffsetContent+len(elem.packet)])
|
||||
}
|
||||
|
||||
peer.rxBytes.Add(rxBytesLen)
|
||||
if validTailPacket >= 0 {
|
||||
peer.SetEndpointFromPacket(elemsContainer.elems[validTailPacket].endpoint)
|
||||
peer.keepKeyFreshReceiving()
|
||||
|
||||
51
vendor/github.com/tailscale/wireguard-go/device/send.go
generated
vendored
51
vendor/github.com/tailscale/wireguard-go/device/send.go
generated
vendored
@@ -6,7 +6,6 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -46,11 +45,15 @@ import (
|
||||
*/
|
||||
|
||||
type QueueOutboundElement struct {
|
||||
buffer *[MaxMessageSize]byte // slice holding the packet data
|
||||
packet []byte // slice of "buffer" (always!)
|
||||
nonce uint64 // nonce for encryption
|
||||
keypair *Keypair // keypair for encryption
|
||||
peer *Peer // related peer
|
||||
buffer *[MaxMessageSize]byte // slice holding the packet data
|
||||
// packet is always a slice of "buffer". The starting offset in buffer
|
||||
// is either:
|
||||
// a) MessageEncapsulatingTransportSize+MessageTransportHeaderSize (plaintext)
|
||||
// b) 0 (post-encryption)
|
||||
packet []byte
|
||||
nonce uint64 // nonce for encryption
|
||||
keypair *Keypair // keypair for encryption
|
||||
peer *Peer // related peer
|
||||
}
|
||||
|
||||
type QueueOutboundElementsContainer struct {
|
||||
@@ -124,16 +127,15 @@ func (peer *Peer) SendHandshakeInitiation(isRetry bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var buf [MessageInitiationSize]byte
|
||||
writer := bytes.NewBuffer(buf[:0])
|
||||
binary.Write(writer, binary.LittleEndian, msg)
|
||||
packet := writer.Bytes()
|
||||
buf := make([]byte, MessageEncapsulatingTransportSize+MessageInitiationSize)
|
||||
packet := buf[MessageEncapsulatingTransportSize:]
|
||||
_ = msg.marshal(packet)
|
||||
peer.cookieGenerator.AddMacs(packet)
|
||||
|
||||
peer.timersAnyAuthenticatedPacketTraversal()
|
||||
peer.timersAnyAuthenticatedPacketSent()
|
||||
|
||||
err = peer.SendBuffers([][]byte{packet})
|
||||
err = peer.SendBuffers([][]byte{buf})
|
||||
if err != nil {
|
||||
peer.device.log.Errorf("%v - Failed to send handshake initiation: %v", peer, err)
|
||||
}
|
||||
@@ -155,10 +157,9 @@ func (peer *Peer) SendHandshakeResponse() error {
|
||||
return err
|
||||
}
|
||||
|
||||
var buf [MessageResponseSize]byte
|
||||
writer := bytes.NewBuffer(buf[:0])
|
||||
binary.Write(writer, binary.LittleEndian, response)
|
||||
packet := writer.Bytes()
|
||||
buf := make([]byte, MessageEncapsulatingTransportSize+MessageResponseSize)
|
||||
packet := buf[MessageEncapsulatingTransportSize:]
|
||||
_ = response.marshal(packet)
|
||||
peer.cookieGenerator.AddMacs(packet)
|
||||
|
||||
err = peer.BeginSymmetricSession()
|
||||
@@ -172,7 +173,7 @@ func (peer *Peer) SendHandshakeResponse() error {
|
||||
peer.timersAnyAuthenticatedPacketSent()
|
||||
|
||||
// TODO: allocation could be avoided
|
||||
err = peer.SendBuffers([][]byte{packet})
|
||||
err = peer.SendBuffers([][]byte{buf})
|
||||
if err != nil {
|
||||
peer.device.log.Errorf("%v - Failed to send handshake response: %v", peer, err)
|
||||
}
|
||||
@@ -189,11 +190,12 @@ func (device *Device) SendHandshakeCookie(initiatingElem *QueueHandshakeElement)
|
||||
return err
|
||||
}
|
||||
|
||||
var buf [MessageCookieReplySize]byte
|
||||
writer := bytes.NewBuffer(buf[:0])
|
||||
binary.Write(writer, binary.LittleEndian, reply)
|
||||
buf := make([]byte, MessageEncapsulatingTransportSize+MessageCookieReplySize)
|
||||
packet := buf[MessageEncapsulatingTransportSize:]
|
||||
_ = reply.marshal(packet)
|
||||
// TODO: allocation could be avoided
|
||||
device.net.bind.Send([][]byte{writer.Bytes()}, initiatingElem.endpoint)
|
||||
device.net.bind.Send([][]byte{buf}, initiatingElem.endpoint, MessageEncapsulatingTransportSize)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -225,7 +227,7 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
elemsByPeer = make(map[*Peer]*QueueOutboundElementsContainer, batchSize)
|
||||
count = 0
|
||||
sizes = make([]int, batchSize)
|
||||
offset = MessageTransportHeaderSize
|
||||
offset = MessageEncapsulatingTransportSize + MessageTransportHeaderSize
|
||||
)
|
||||
|
||||
for i := range elems {
|
||||
@@ -451,7 +453,7 @@ func (device *Device) RoutineEncryption(id int) {
|
||||
for elemsContainer := range device.queue.encryption.c {
|
||||
for _, elem := range elemsContainer.elems {
|
||||
// populate header fields
|
||||
header := elem.buffer[:MessageTransportHeaderSize]
|
||||
header := elem.buffer[MessageEncapsulatingTransportSize : MessageEncapsulatingTransportSize+MessageTransportHeaderSize]
|
||||
|
||||
fieldType := header[0:4]
|
||||
fieldReceiver := header[4:8]
|
||||
@@ -474,6 +476,9 @@ func (device *Device) RoutineEncryption(id int) {
|
||||
elem.packet,
|
||||
nil,
|
||||
)
|
||||
|
||||
// re-slice packet to include encapsulating transport space
|
||||
elem.packet = elem.buffer[:MessageEncapsulatingTransportSize+len(elem.packet)]
|
||||
}
|
||||
elemsContainer.Unlock()
|
||||
}
|
||||
@@ -512,7 +517,7 @@ func (peer *Peer) RoutineSequentialSender(maxBatchSize int) {
|
||||
dataSent := false
|
||||
elemsContainer.Lock()
|
||||
for _, elem := range elemsContainer.elems {
|
||||
if len(elem.packet) != MessageKeepaliveSize {
|
||||
if len(elem.packet[MessageEncapsulatingTransportSize:]) != MessageKeepaliveSize {
|
||||
dataSent = true
|
||||
}
|
||||
bufs = append(bufs, elem.packet)
|
||||
|
||||
147
vendor/github.com/tailscale/wireguard-go/tun/tun_plan9.go
generated
vendored
Normal file
147
vendor/github.com/tailscale/wireguard-go/tun/tun_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type NativeTun struct {
|
||||
name string // "/net/ipifc/2"
|
||||
ctlFile *os.File
|
||||
dataFile *os.File
|
||||
events chan Event
|
||||
errors chan error
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func CreateTUN(_ string, mtu int) (Device, error) {
|
||||
ctl, err := os.OpenFile("/net/ipifc/clone", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nbuf := make([]byte, 5)
|
||||
n, err := ctl.Read(nbuf)
|
||||
if err != nil {
|
||||
ctl.Close()
|
||||
return nil, fmt.Errorf("error reading from clone file: %w", err)
|
||||
}
|
||||
ifn, err := strconv.Atoi(strings.TrimSpace(string(nbuf[:n])))
|
||||
if err != nil {
|
||||
ctl.Close()
|
||||
return nil, fmt.Errorf("error converting clone result %q to int: %w", nbuf[:n], err)
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(ctl, "bind pkt\n"); err != nil {
|
||||
ctl.Close()
|
||||
return nil, fmt.Errorf("error binding to pkt: %w", err)
|
||||
}
|
||||
if mtu > 0 {
|
||||
if _, err := fmt.Fprintf(ctl, "mtu %d\n", mtu); err != nil {
|
||||
ctl.Close()
|
||||
return nil, fmt.Errorf("error setting MTU: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
dataFile, err := os.OpenFile(fmt.Sprintf("/net/ipifc/%d/data", ifn), os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
ctl.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tun := &NativeTun{
|
||||
ctlFile: ctl,
|
||||
dataFile: dataFile,
|
||||
name: fmt.Sprintf("/net/ipifc/%d", ifn),
|
||||
events: make(chan Event, 10),
|
||||
errors: make(chan error, 5),
|
||||
}
|
||||
tun.events <- EventUp
|
||||
|
||||
return tun, nil
|
||||
}
|
||||
|
||||
func (tun *NativeTun) Name() (string, error) {
|
||||
return tun.name, nil
|
||||
}
|
||||
|
||||
func (tun *NativeTun) File() *os.File {
|
||||
return tun.ctlFile
|
||||
}
|
||||
|
||||
func (tun *NativeTun) Events() <-chan Event {
|
||||
return tun.events
|
||||
}
|
||||
|
||||
func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) {
|
||||
select {
|
||||
case err := <-tun.errors:
|
||||
return 0, err
|
||||
default:
|
||||
n, err := tun.dataFile.Read(bufs[0][offset:])
|
||||
if n == 1 && bufs[0][offset] == 0 {
|
||||
// EOF
|
||||
err = io.EOF
|
||||
n = 0
|
||||
}
|
||||
sizes[0] = n
|
||||
return 1, err
|
||||
}
|
||||
}
|
||||
|
||||
func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) {
|
||||
for i, buf := range bufs {
|
||||
if _, err := tun.dataFile.Write(buf[offset:]); err != nil {
|
||||
return i, err
|
||||
}
|
||||
}
|
||||
return len(bufs), nil
|
||||
}
|
||||
|
||||
func (tun *NativeTun) Close() error {
|
||||
var err1, err2 error
|
||||
tun.closeOnce.Do(func() {
|
||||
_, err1 := fmt.Fprintf(tun.ctlFile, "unbind\n")
|
||||
if err := tun.ctlFile.Close(); err != nil && err1 == nil {
|
||||
err1 = err
|
||||
}
|
||||
err2 = tun.dataFile.Close()
|
||||
})
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return err2
|
||||
}
|
||||
|
||||
func (tun *NativeTun) MTU() (int, error) {
|
||||
var buf [100]byte
|
||||
f, err := os.Open(tun.name + "/status")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
n, err := f.Read(buf[:])
|
||||
_, res, ok := strings.Cut(string(buf[:n]), " maxtu ")
|
||||
if ok {
|
||||
if mtus, _, ok := strings.Cut(res, " "); ok {
|
||||
mtu, err := strconv.Atoi(mtus)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error converting mtu %q to int: %w", mtus, err)
|
||||
}
|
||||
return mtu, nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("no 'maxtu' field found in %s/status", tun.name)
|
||||
}
|
||||
|
||||
func (tun *NativeTun) BatchSize() int {
|
||||
return 1
|
||||
}
|
||||
Reference in New Issue
Block a user