Skip to content

Instantly share code, notes, and snippets.

@ti-mo
Created March 14, 2017 16:42
Show Gist options
  • Save ti-mo/513aadd02922062e0a265b64876294bc to your computer and use it in GitHub Desktop.
Save ti-mo/513aadd02922062e0a265b64876294bc to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"errors"
"encoding/binary"
"syscall"
)
func main() {
dump1 := []byte{52, 0, 1, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 17, 0, 2, 8, 0, 2, 0, 192, 168, 65, 1, 28, 0, 2, 128, 5, 0, 1, 0, 17, 0, 0, 0, 6, 0, 2, 0, 215, 32, 0, 0, 6, 0, 3, 0, 0, 53, 0, 0, 52, 0, 2, 128, 20, 0, 1, 128, 8, 0, 1, 0, 192, 168, 65, 1, 8, 0, 2, 0, 172, 17, 0, 2, 28, 0, 2, 128, 5, 0, 1, 0, 17, 0, 0, 0, 6, 0, 2, 0, 0, 53, 0, 0, 6, 0, 3, 0, 215, 32, 0, 0, 8, 0, 12, 0, 239, 175, 148, 0, 8, 0, 3, 0, 0, 0, 0, 8, 8, 0, 7, 0, 0, 0, 0, 30}
dump2 := []byte{52, 0, 1, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 17, 0, 2, 8, 0, 2, 0, 192, 168, 65, 1, 28, 0, 2, 128, 5, 0, 1, 0, 17, 0, 0, 0, 6, 0, 2, 0, 183, 16, 0, 0, 6, 0, 3, 0, 0, 53, 0, 0, 52, 0, 2, 128, 20, 0, 1, 128, 8, 0, 1, 0, 192, 168, 65, 1, 8, 0, 2, 0, 172, 17, 0, 2, 28, 0, 2, 128, 5, 0, 1, 0, 17, 0, 0, 0, 6, 0, 2, 0, 0, 53, 0, 0, 6, 0, 3, 0, 183, 16, 0, 0, 8, 0, 12, 0, 239, 177, 130, 0, 8, 0, 3, 0, 0, 0, 0, 10, 8, 0, 7, 0, 0, 0, 0, 30}
dump3 := []byte{60, 0, 1, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 17, 0, 2, 8, 0, 2, 0, 172, 217, 0, 14, 36, 0, 2, 128, 5, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 12, 155, 0, 0, 5, 0, 5, 0, 8, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 60, 0, 2, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 217, 0, 14, 8, 0, 2, 0, 172, 17, 0, 2, 36, 0, 2, 128, 5, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 12, 155, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 8, 0, 12, 0, 239, 177, 139, 0, 8, 0, 3, 0, 0, 0, 0, 8, 8, 0, 7, 0, 0, 0, 0, 30}
dump4 := []byte{60, 0, 1, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 17, 0, 2, 8, 0, 2, 0, 172, 217, 0, 14, 36, 0, 2, 128, 5, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 12, 155, 0, 0, 5, 0, 5, 0, 8, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 60, 0, 2, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 217, 0, 14, 8, 0, 2, 0, 172, 17, 0, 2, 36, 0, 2, 128, 5, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 12, 155, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 8, 0, 12, 0, 239, 177, 139, 0, 8, 0, 3, 0, 0, 0, 0, 10, 8, 0, 7, 0, 0, 0, 0, 30}
dump5 := []byte{60, 0, 1, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 17, 0, 2, 8, 0, 2, 0, 172, 217, 0, 14, 36, 0, 2, 128, 5, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 12, 155, 0, 0, 5, 0, 5, 0, 8, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 60, 0, 2, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 217, 0, 14, 8, 0, 2, 0, 172, 17, 0, 2, 36, 0, 2, 128, 5, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 12, 155, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 8, 0, 12, 0, 239, 177, 139, 0, 8, 0, 3, 0, 0, 0, 2, 10}
dump6 := []byte{52, 0, 1, 128, 20, 0, 1, 128, 8, 0, 1, 0, 172, 17, 0, 2, 8, 0, 2, 0, 192, 168, 65, 1, 28, 0, 2, 128, 5, 0, 1, 0, 17, 0, 0, 0, 6, 0, 2, 0, 183, 16, 0, 0, 6, 0, 3, 0, 0, 53, 0, 0, 52, 0, 2, 128, 20, 0, 1, 128, 8, 0, 1, 0, 192, 168, 65, 1, 8, 0, 2, 0, 172, 17, 0, 2, 28, 0, 2, 128, 5, 0, 1, 0, 17, 0, 0, 0, 6, 0, 2, 0, 0, 53, 0, 0, 6, 0, 3, 0, 183, 16, 0, 0, 8, 0, 12, 0, 239, 177, 130, 0, 8, 0, 3, 0, 0, 0, 2, 10}
parse1, _ := parseAttrs(dump1)
fmt.Printf("%v\n", parse1)
parse2, _ := parseAttrs(dump2)
fmt.Printf("%v\n", parse2)
parse3, _ := parseAttrs(dump3)
fmt.Printf("%v\n", parse3)
parse4, _ := parseAttrs(dump4)
fmt.Printf("%v\n", parse4)
parse5, _ := parseAttrs(dump5)
fmt.Printf("%v\n", parse5)
parse6, _ := parseAttrs(dump6)
fmt.Printf("%v\n", parse6)
}
const (
// #defined in libnfnetlink/include/libnfnetlink/libnfnetlink.h
NLA_F_NESTED = uint16(1 << 15)
NLA_F_NET_BYTEORDER = uint16(1 << 14)
NLA_TYPE_MASK = ^(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
NLM_F_EXCL = 0x200
NLM_F_CREATE = 0x400
)
const attrHdrLength = 4
type Attr struct {
Msg []byte
Typ int
IsNested bool
IsNetByteorder bool
Attrs []Attr
}
func parseAttrs(b []byte) ([]Attr, error) {
var attrs []Attr
for len(b) >= attrHdrLength {
var attr Attr
attr, b = parseAttr(b)
attrs = append(attrs, attr)
}
if len(b) != 0 {
return nil, errors.New("leftover attr bytes")
}
return attrs, nil
}
func parseAttr(b []byte) (Attr, []byte) {
attrLen := binary.LittleEndian.Uint16(b[0:2])
// length is header + payload
attrLen -= uint16(attrHdrLength)
typ := binary.LittleEndian.Uint16(b[2:4])
attr := Attr{
Msg: b[attrHdrLength : attrHdrLength+int(attrLen)],
Typ: int(typ & NLA_TYPE_MASK),
IsNested: typ&NLA_F_NESTED > 0,
IsNetByteorder: typ&NLA_F_NET_BYTEORDER > 0,
}
if attr.IsNested {
attr.Attrs, _ = parseAttrs(attr.Msg)
}
return attr, b[rtaAlignOf(attrHdrLength+int(attrLen)):]
}
// Round the length of a netlink route attribute up to align it
// properly.
func rtaAlignOf(attrlen int) int {
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment