6a696e03e7
* migrate to golang.zx2c4.com/wireguard/wgctrl This commit introduces the usage of wgctrl. It avoids the usage of exec calls of the wg command and parsing the output of `wg show`. Signed-off-by: leonnicolas <leonloechner@gmx.de> * vendor wgctrl Signed-off-by: leonnicolas <leonloechner@gmx.de> * apply suggestions from code review Remove wireguard.Enpoint struct and use net.UDPAddr for the resolved endpoint and addr string (dnsanme:port) if a DN was supplied. Signed-off-by: leonnicolas <leonloechner@gmx.de> * pkg/*: use wireguard.Enpoint This commit introduces the wireguard.Enpoint struct. It encapsulates a DN name with port and a net.UPDAddr. The fields are private and only accessible over exported Methods to avoid accidental modification. Also iptables.GetProtocol is improved to avoid ipv4 rules being applied by `ip6tables`. Signed-off-by: leonnicolas <leonloechner@gmx.de> * pkg/wireguard/conf_test.go: add tests for Endpoint Signed-off-by: leonnicolas <leonloechner@gmx.de> * cmd/kg/main.go: validate port range Signed-off-by: leonnicolas <leonloechner@gmx.de> * add suggestions from review Signed-off-by: leonnicolas <leonloechner@gmx.de> * pkg/mesh/mesh.go: use Equal func Implement an Equal func for Enpoint and use it instead of comparing strings. Signed-off-by: leonnicolas <leonloechner@gmx.de> * cmd/kgctl/main.go: check port range Signed-off-by: leonnicolas <leonloechner@gmx.de> * vendor Signed-off-by: leonnicolas <leonloechner@gmx.de>
151 lines
4.0 KiB
Go
151 lines
4.0 KiB
Go
// Copyright 2016 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package bpf
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// A VM is an emulated BPF virtual machine.
|
|
type VM struct {
|
|
filter []Instruction
|
|
}
|
|
|
|
// NewVM returns a new VM using the input BPF program.
|
|
func NewVM(filter []Instruction) (*VM, error) {
|
|
if len(filter) == 0 {
|
|
return nil, errors.New("one or more Instructions must be specified")
|
|
}
|
|
|
|
for i, ins := range filter {
|
|
check := len(filter) - (i + 1)
|
|
switch ins := ins.(type) {
|
|
// Check for out-of-bounds jumps in instructions
|
|
case Jump:
|
|
if check <= int(ins.Skip) {
|
|
return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip)
|
|
}
|
|
case JumpIf:
|
|
if check <= int(ins.SkipTrue) {
|
|
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
|
|
}
|
|
if check <= int(ins.SkipFalse) {
|
|
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
|
}
|
|
case JumpIfX:
|
|
if check <= int(ins.SkipTrue) {
|
|
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
|
|
}
|
|
if check <= int(ins.SkipFalse) {
|
|
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
|
}
|
|
// Check for division or modulus by zero
|
|
case ALUOpConstant:
|
|
if ins.Val != 0 {
|
|
break
|
|
}
|
|
|
|
switch ins.Op {
|
|
case ALUOpDiv, ALUOpMod:
|
|
return nil, errors.New("cannot divide by zero using ALUOpConstant")
|
|
}
|
|
// Check for unknown extensions
|
|
case LoadExtension:
|
|
switch ins.Num {
|
|
case ExtLen:
|
|
default:
|
|
return nil, fmt.Errorf("extension %d not implemented", ins.Num)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make sure last instruction is a return instruction
|
|
switch filter[len(filter)-1].(type) {
|
|
case RetA, RetConstant:
|
|
default:
|
|
return nil, errors.New("BPF program must end with RetA or RetConstant")
|
|
}
|
|
|
|
// Though our VM works using disassembled instructions, we
|
|
// attempt to assemble the input filter anyway to ensure it is compatible
|
|
// with an operating system VM.
|
|
_, err := Assemble(filter)
|
|
|
|
return &VM{
|
|
filter: filter,
|
|
}, err
|
|
}
|
|
|
|
// Run runs the VM's BPF program against the input bytes.
|
|
// Run returns the number of bytes accepted by the BPF program, and any errors
|
|
// which occurred while processing the program.
|
|
func (v *VM) Run(in []byte) (int, error) {
|
|
var (
|
|
// Registers of the virtual machine
|
|
regA uint32
|
|
regX uint32
|
|
regScratch [16]uint32
|
|
|
|
// OK is true if the program should continue processing the next
|
|
// instruction, or false if not, causing the loop to break
|
|
ok = true
|
|
)
|
|
|
|
// TODO(mdlayher): implement:
|
|
// - NegateA:
|
|
// - would require a change from uint32 registers to int32
|
|
// registers
|
|
|
|
// TODO(mdlayher): add interop tests that check signedness of ALU
|
|
// operations against kernel implementation, and make sure Go
|
|
// implementation matches behavior
|
|
|
|
for i := 0; i < len(v.filter) && ok; i++ {
|
|
ins := v.filter[i]
|
|
|
|
switch ins := ins.(type) {
|
|
case ALUOpConstant:
|
|
regA = aluOpConstant(ins, regA)
|
|
case ALUOpX:
|
|
regA, ok = aluOpX(ins, regA, regX)
|
|
case Jump:
|
|
i += int(ins.Skip)
|
|
case JumpIf:
|
|
jump := jumpIf(ins, regA)
|
|
i += jump
|
|
case JumpIfX:
|
|
jump := jumpIfX(ins, regA, regX)
|
|
i += jump
|
|
case LoadAbsolute:
|
|
regA, ok = loadAbsolute(ins, in)
|
|
case LoadConstant:
|
|
regA, regX = loadConstant(ins, regA, regX)
|
|
case LoadExtension:
|
|
regA = loadExtension(ins, in)
|
|
case LoadIndirect:
|
|
regA, ok = loadIndirect(ins, in, regX)
|
|
case LoadMemShift:
|
|
regX, ok = loadMemShift(ins, in)
|
|
case LoadScratch:
|
|
regA, regX = loadScratch(ins, regScratch, regA, regX)
|
|
case RetA:
|
|
return int(regA), nil
|
|
case RetConstant:
|
|
return int(ins.Val), nil
|
|
case StoreScratch:
|
|
regScratch = storeScratch(ins, regScratch, regA, regX)
|
|
case TAX:
|
|
regX = regA
|
|
case TXA:
|
|
regA = regX
|
|
default:
|
|
return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins)
|
|
}
|
|
}
|
|
|
|
return 0, nil
|
|
}
|