session.go raw

   1  //go:build windows
   2  
   3  /* SPDX-License-Identifier: MIT
   4   *
   5   * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
   6   */
   7  
   8  package wintun
   9  
  10  import (
  11  	"syscall"
  12  	"unsafe"
  13  
  14  	"golang.org/x/sys/windows"
  15  )
  16  
  17  type Session struct {
  18  	handle uintptr
  19  }
  20  
  21  const (
  22  	PacketSizeMax   = 0xffff    // Maximum packet size
  23  	RingCapacityMin = 0x20000   // Minimum ring capacity (128 kiB)
  24  	RingCapacityMax = 0x4000000 // Maximum ring capacity (64 MiB)
  25  )
  26  
  27  // Packet with data
  28  type Packet struct {
  29  	Next *Packet              // Pointer to next packet in queue
  30  	Size uint32               // Size of packet (max WINTUN_MAX_IP_PACKET_SIZE)
  31  	Data *[PacketSizeMax]byte // Pointer to layer 3 IPv4 or IPv6 packet
  32  }
  33  
  34  var (
  35  	procWintunAllocateSendPacket   = modwintun.NewProc("WintunAllocateSendPacket")
  36  	procWintunEndSession           = modwintun.NewProc("WintunEndSession")
  37  	procWintunGetReadWaitEvent     = modwintun.NewProc("WintunGetReadWaitEvent")
  38  	procWintunReceivePacket        = modwintun.NewProc("WintunReceivePacket")
  39  	procWintunReleaseReceivePacket = modwintun.NewProc("WintunReleaseReceivePacket")
  40  	procWintunSendPacket           = modwintun.NewProc("WintunSendPacket")
  41  	procWintunStartSession         = modwintun.NewProc("WintunStartSession")
  42  )
  43  
  44  func (wintun *Adapter) StartSession(capacity uint32) (session Session, err error) {
  45  	r0, _, e1 := syscall.Syscall(procWintunStartSession.Addr(), 2, uintptr(wintun.handle), uintptr(capacity), 0)
  46  	if r0 == 0 {
  47  		err = e1
  48  	} else {
  49  		session = Session{r0}
  50  	}
  51  	return
  52  }
  53  
  54  func (session Session) End() {
  55  	syscall.Syscall(procWintunEndSession.Addr(), 1, session.handle, 0, 0)
  56  	session.handle = 0
  57  }
  58  
  59  func (session Session) ReadWaitEvent() (handle windows.Handle) {
  60  	r0, _, _ := syscall.Syscall(procWintunGetReadWaitEvent.Addr(), 1, session.handle, 0, 0)
  61  	handle = windows.Handle(r0)
  62  	return
  63  }
  64  
  65  func (session Session) ReceivePacket() (packet []byte, err error) {
  66  	var packetSize uint32
  67  	r0, _, e1 := syscall.Syscall(procWintunReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packetSize)), 0)
  68  	if r0 == 0 {
  69  		err = e1
  70  		return
  71  	}
  72  	packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize)
  73  	return
  74  }
  75  
  76  func (session Session) ReleaseReceivePacket(packet []byte) {
  77  	syscall.Syscall(procWintunReleaseReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0)
  78  }
  79  
  80  func (session Session) AllocateSendPacket(packetSize int) (packet []byte, err error) {
  81  	r0, _, e1 := syscall.Syscall(procWintunAllocateSendPacket.Addr(), 2, session.handle, uintptr(packetSize), 0)
  82  	if r0 == 0 {
  83  		err = e1
  84  		return
  85  	}
  86  	packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize)
  87  	return
  88  }
  89  
  90  func (session Session) SendPacket(packet []byte) {
  91  	syscall.Syscall(procWintunSendPacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0)
  92  }
  93