ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c

175
packages/mesh-init/abi.go Normal file
View file

@ -0,0 +1,175 @@
package main
import (
"encoding/binary"
"math"
"runtime"
)
const (
xtHeader = 32
ruleHead = 112
)
type tableInfo struct {
Name [32]byte
Valid uint32
Hooks [5]uint32
Underflow [5]uint32
Count uint32
Size uint32
}
type replaceHead struct {
Name [32]byte
Valid uint32
Count uint32
Size uint32
Hooks [5]uint32
Underflow [5]uint32
OldCount uint32
Address uint64
}
type ipMatch struct {
Addresses [4]uint32
In [16]byte
Out [16]byte
InMask [16]byte
OutMask [16]byte
Protocol uint16
Flags uint8
Inverse uint8
}
type counter struct {
Packets uint64
Bytes uint64
}
type ruleHeader struct {
IP ipMatch
Cache uint32
Target uint16
Next uint16
From uint32
Counters counter
}
type replacement struct {
data []byte
counters []counter
pins runtime.Pinner
}
func encode(value any) []byte {
data, err := binary.Append(nil, binary.NativeEndian, value)
if err != nil {
panic(err)
}
return data
}
func size16(size int) uint16 {
if size < 0 || size > math.MaxUint16 {
panic("iptables size exceeds uint16")
}
return uint16(size)
}
func size32(size int) uint32 {
if size < 0 || uint64(size) > math.MaxUint32 {
panic("iptables size exceeds uint32")
}
return uint32(size)
}
func extension(name string, revision uint8, data []byte) []byte {
size := (xtHeader + len(data) + 7) &^ 7
header := struct {
Size uint16
Name [29]byte
Revision uint8
}{Size: size16(size), Revision: revision}
copy(header.Name[:], name)
result := append(encode(header), data...)
return append(result, make([]byte, size-len(result))...)
}
func accept() []byte {
return extension("", 0, encode(int32(-2)))
}
func redirect(port uint16) []byte {
rangeInfo := struct {
Count uint32
Flags uint32
IPs [2]uint32
Ports [4]byte
}{Count: 1, Flags: 2}
binary.BigEndian.PutUint16(rangeInfo.Ports[:2], port)
binary.BigEndian.PutUint16(rangeInfo.Ports[2:], port)
return extension("REDIRECT", 0, encode(rangeInfo))
}
func tcp(port uint16) []byte {
return extension("tcp", 0, encode(struct {
Source [2]uint16
Dest [2]uint16
Flags [4]uint8
}{Source: [2]uint16{0, math.MaxUint16}, Dest: [2]uint16{port, port}}))
}
func owner(uid uint32) []byte {
return extension("owner", 1, encode(struct {
UID [2]uint32
GID [2]uint32
Match uint8
Invert uint8
Pad [2]byte
}{UID: [2]uint32{uid, uid}, Match: 1}))
}
func rule(protocol uint16, match, target []byte, loopback bool) []byte {
header := ruleHeader{
IP: ipMatch{Protocol: protocol},
Target: size16(ruleHead + len(match)),
Next: size16(ruleHead + len(match) + len(target)),
}
if loopback {
copy(header.IP.Out[:], "lo")
header.IP.OutMask[0], header.IP.OutMask[1], header.IP.OutMask[2] = 255, 255, 255
}
return append(append(encode(header), match...), target...)
}
func table(value config, count uint32, address uint64) []byte {
header := replaceHead{Valid: 27, OldCount: count, Address: address}
copy(header.Name[:], "nat")
var body []byte
add := func(data []byte) {
body = append(body, data...)
header.Count++
}
for _, hook := range []int{0, 1, 3, 4} {
header.Hooks[hook] = size32(len(body))
switch hook {
case 0:
for _, port := range value.exclude {
add(rule(6, tcp(port), accept(), false))
}
add(rule(6, nil, redirect(value.inbound), false))
case 3:
add(rule(0, owner(value.proxyUID), accept(), false))
add(rule(0, nil, accept(), true))
add(rule(6, nil, redirect(value.outbound), false))
}
header.Underflow[hook] = size32(len(body))
add(rule(0, nil, accept(), false))
}
var label [30]byte
copy(label[:], "ERROR")
add(rule(0, nil, extension("ERROR", 0, label[:]), false))
header.Size = size32(len(body))
return append(encode(header), body...)
}