зеркало из https://github.com/mozilla/mig.git
vendor mozilla libaudit-go
This commit is contained in:
Родитель
00d70ad6c5
Коммит
31a6fbf5e1
|
@ -0,0 +1,10 @@
|
|||
language: go
|
||||
sudo: false
|
||||
|
||||
script: go test -v
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- tip
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2015 Ryan Hileman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,103 @@
|
|||
[![Build Status](https://travis-ci.org/lunixbochs/struc.svg?branch=master)](https://travis-ci.org/lunixbochs/struc)
|
||||
|
||||
struc
|
||||
====
|
||||
|
||||
Struc exists to pack and unpack C-style structures from bytes, which is useful for binary files and network protocols. It could be considered an alternative to `encoding/binary`, which requires massive boilerplate for some similar operations.
|
||||
|
||||
Take a look at an [example comparing `struc` and `encoding/binary`](https://bochs.info/p/cxvm9)
|
||||
|
||||
Struc considers usability first. That said, it does cache reflection data and aims to be competitive with `encoding/binary` struct packing in every way, including performance.
|
||||
|
||||
Example struct
|
||||
----
|
||||
|
||||
```Go
|
||||
type Example struct {
|
||||
Var int `struc:"int32,sizeof=Str"`
|
||||
Str string
|
||||
Weird []byte `struc:"[8]int64"`
|
||||
Var []int `struc:"[]int32,little"`
|
||||
}
|
||||
```
|
||||
|
||||
Struct tag format
|
||||
----
|
||||
|
||||
- ```Var []int `struc:"[]int32,little,sizeof=StringField"` ``` will pack Var as a slice of little-endian int32, and link it as the size of `StringField`.
|
||||
- `sizeof=`: Indicates this field is a number used to track the length of a another field. `sizeof` fields are automatically updated on `Pack()` based on the current length of the tracked field, and are used to size the target field during `Unpack()`.
|
||||
- Bare values will be parsed as type and endianness.
|
||||
|
||||
Endian formats
|
||||
----
|
||||
|
||||
- `big` (default)
|
||||
- `little`
|
||||
|
||||
Recognized types
|
||||
----
|
||||
|
||||
- `pad` - this type ignores field contents and is backed by a `[length]byte` containing nulls
|
||||
- `bool`
|
||||
- `byte`
|
||||
- `int8`, `uint8`
|
||||
- `int16`, `uint16`
|
||||
- `int32`, `uint32`
|
||||
- `int64`, `uint64`
|
||||
- `float32`
|
||||
- `float64`
|
||||
|
||||
Types can be indicated as arrays/slices using `[]` syntax. Example: `[]int64`, `[8]int32`.
|
||||
|
||||
Bare slice types (those with no `[size]`) must have a linked `Sizeof` field.
|
||||
|
||||
Private fields are ignored when packing and unpacking.
|
||||
|
||||
Example code
|
||||
----
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/lunixbochs/struc"
|
||||
)
|
||||
|
||||
type Example struct {
|
||||
A int `struc:"big"`
|
||||
|
||||
// B will be encoded/decoded as a 16-bit int (a "short")
|
||||
// but is stored as a native int in the struct
|
||||
B int `struc:"int16"`
|
||||
|
||||
// the sizeof key links a buffer's size to any int field
|
||||
Size int `struc:"int8,little,sizeof=Str"`
|
||||
Str string
|
||||
|
||||
// you can get freaky if you want
|
||||
Str2 string `struc:"[5]int64"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
var buf bytes.Buffer
|
||||
t := &Example{1, 2, 0, "test", "test2"}
|
||||
err := struc.Pack(&buf, t)
|
||||
o := &Example{}
|
||||
err = struc.Unpack(&buf, o)
|
||||
}
|
||||
```
|
||||
|
||||
Benchmark
|
||||
----
|
||||
|
||||
`BenchmarkEncode` uses struc. `Stdlib` benchmarks use equivalent `encoding/binary` code. `Manual` encodes without any reflection, and should be considered an upper bound on performance (which generated code based on struc definitions should be able to achieve).
|
||||
|
||||
```
|
||||
BenchmarkEncode 1000000 1265 ns/op
|
||||
BenchmarkStdlibEncode 1000000 1855 ns/op
|
||||
BenchmarkManualEncode 5000000 284 ns/op
|
||||
BenchmarkDecode 1000000 1259 ns/op
|
||||
BenchmarkStdlibDecode 1000000 1656 ns/op
|
||||
BenchmarkManualDecode 20000000 89.0 ns/op
|
||||
```
|
|
@ -0,0 +1,165 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type BenchExample struct {
|
||||
Test [5]byte
|
||||
A int32
|
||||
B, C, D int16
|
||||
Test2 [4]byte
|
||||
Length int32
|
||||
}
|
||||
|
||||
type BenchStrucExample struct {
|
||||
Test [5]byte `struc:"[5]byte"`
|
||||
A int `struc:"int32"`
|
||||
B, C, D int `struc:"int16"`
|
||||
Test2 [4]byte `struc:"[4]byte"`
|
||||
Length int `struc:"int32,sizeof=Data"`
|
||||
Data []byte
|
||||
}
|
||||
|
||||
var benchRef = &BenchExample{
|
||||
[5]byte{1, 2, 3, 4, 5},
|
||||
1, 2, 3, 4,
|
||||
[4]byte{1, 2, 3, 4},
|
||||
8,
|
||||
}
|
||||
|
||||
var eightBytes = []byte("8bytestr")
|
||||
|
||||
var benchStrucRef = &BenchStrucExample{
|
||||
[5]byte{1, 2, 3, 4, 5},
|
||||
1, 2, 3, 4,
|
||||
[4]byte{1, 2, 3, 4},
|
||||
8, eightBytes,
|
||||
}
|
||||
|
||||
func BenchmarkEncode(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
err := Pack(&buf, benchStrucRef)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStdlibEncode(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
err := binary.Write(&buf, binary.BigEndian, benchRef)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, err = buf.Write(eightBytes)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkManualEncode(b *testing.B) {
|
||||
order := binary.BigEndian
|
||||
s := benchStrucRef
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
tmp := make([]byte, 29)
|
||||
copy(tmp[0:5], s.Test[:])
|
||||
order.PutUint32(tmp[5:9], uint32(s.A))
|
||||
order.PutUint16(tmp[9:11], uint16(s.B))
|
||||
order.PutUint16(tmp[11:13], uint16(s.C))
|
||||
order.PutUint16(tmp[13:15], uint16(s.D))
|
||||
copy(tmp[15:19], s.Test2[:])
|
||||
order.PutUint32(tmp[19:23], uint32(s.Length))
|
||||
copy(tmp[23:], s.Data)
|
||||
_, err := buf.Write(tmp)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecode(b *testing.B) {
|
||||
var out BenchStrucExample
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, benchStrucRef); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
bufBytes := buf.Bytes()
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := bytes.NewReader(bufBytes)
|
||||
err := Unpack(buf, &out)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
out.Data = nil
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStdlibDecode(b *testing.B) {
|
||||
var out BenchExample
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.BigEndian, *benchRef)
|
||||
_, err := buf.Write(eightBytes)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
bufBytes := buf.Bytes()
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := bytes.NewReader(bufBytes)
|
||||
err := binary.Read(buf, binary.BigEndian, &out)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
tmp := make([]byte, out.Length)
|
||||
_, err = buf.Read(tmp)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkManualDecode(b *testing.B) {
|
||||
var o BenchStrucExample
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, benchStrucRef); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
tmp := buf.Bytes()
|
||||
order := binary.BigEndian
|
||||
for i := 0; i < b.N; i++ {
|
||||
copy(o.Test[:], tmp[0:5])
|
||||
o.A = int(order.Uint32(tmp[5:9]))
|
||||
o.B = int(order.Uint16(tmp[9:11]))
|
||||
o.C = int(order.Uint16(tmp[11:13]))
|
||||
o.D = int(order.Uint16(tmp[13:15]))
|
||||
copy(o.Test2[:], tmp[15:19])
|
||||
o.Length = int(order.Uint32(tmp[19:23]))
|
||||
o.Data = make([]byte, o.Length)
|
||||
copy(o.Data, tmp[23:])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFullEncode(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, reference); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFullDecode(b *testing.B) {
|
||||
var out Example
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := bytes.NewBuffer(referenceBytes)
|
||||
if err := Unpack(buf, &out); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type byteWriter struct {
|
||||
buf []byte
|
||||
pos int
|
||||
}
|
||||
|
||||
func (b byteWriter) Write(p []byte) (int, error) {
|
||||
capacity := len(b.buf) - b.pos
|
||||
if capacity < len(p) {
|
||||
p = p[:capacity]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
copy(b.buf[b.pos:], p)
|
||||
b.pos += len(p)
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
type binaryFallback reflect.Value
|
||||
|
||||
func (b binaryFallback) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (b binaryFallback) Sizeof(val reflect.Value, options *Options) int {
|
||||
return binary.Size(val.Interface())
|
||||
}
|
||||
|
||||
func (b binaryFallback) Pack(buf []byte, val reflect.Value, options *Options) (int, error) {
|
||||
tmp := byteWriter{buf: buf}
|
||||
var order binary.ByteOrder = binary.BigEndian
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
err := binary.Write(tmp, order, val.Interface())
|
||||
return tmp.pos, err
|
||||
}
|
||||
|
||||
func (b binaryFallback) Unpack(r io.Reader, val reflect.Value, options *Options) error {
|
||||
var order binary.ByteOrder = binary.BigEndian
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
return binary.Read(r, order, val.Interface())
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Custom interface {
|
||||
Pack(p []byte, opt *Options) (int, error)
|
||||
Unpack(r io.Reader, length int, opt *Options) error
|
||||
Size(opt *Options) int
|
||||
String() string
|
||||
}
|
||||
|
||||
type customFallback struct {
|
||||
custom Custom
|
||||
}
|
||||
|
||||
func (c customFallback) Pack(p []byte, val reflect.Value, opt *Options) (int, error) {
|
||||
return c.custom.Pack(p, opt)
|
||||
}
|
||||
|
||||
func (c customFallback) Unpack(r io.Reader, val reflect.Value, opt *Options) error {
|
||||
return c.custom.Unpack(r, 1, opt)
|
||||
}
|
||||
|
||||
func (c customFallback) Sizeof(val reflect.Value, opt *Options) int {
|
||||
return c.custom.Size(opt)
|
||||
}
|
||||
|
||||
func (c customFallback) String() string {
|
||||
return c.custom.String()
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Float16 float64
|
||||
|
||||
func (f *Float16) Pack(p []byte, opt *Options) (int, error) {
|
||||
order := opt.Order
|
||||
if order == nil {
|
||||
order = binary.BigEndian
|
||||
}
|
||||
sign := uint16(0)
|
||||
if *f < 0 {
|
||||
sign = 1
|
||||
}
|
||||
var frac, exp uint16
|
||||
if math.IsInf(float64(*f), 0) {
|
||||
exp = 0x1f
|
||||
frac = 0
|
||||
} else if math.IsNaN(float64(*f)) {
|
||||
exp = 0x1f
|
||||
frac = 1
|
||||
} else {
|
||||
bits := math.Float64bits(float64(*f))
|
||||
exp64 := (bits >> 52) & 0x7ff
|
||||
if exp64 != 0 {
|
||||
exp = uint16((exp64 - 1023 + 15) & 0x1f)
|
||||
}
|
||||
frac = uint16((bits >> 42) & 0x3ff)
|
||||
}
|
||||
var out uint16
|
||||
out |= sign << 15
|
||||
out |= exp << 10
|
||||
out |= frac & 0x3ff
|
||||
order.PutUint16(p, out)
|
||||
return 2, nil
|
||||
}
|
||||
func (f *Float16) Unpack(r io.Reader, length int, opt *Options) error {
|
||||
order := opt.Order
|
||||
if order == nil {
|
||||
order = binary.BigEndian
|
||||
}
|
||||
var tmp [2]byte
|
||||
if _, err := r.Read(tmp[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
val := order.Uint16(tmp[:2])
|
||||
sign := (val >> 15) & 1
|
||||
exp := int16((val >> 10) & 0x1f)
|
||||
frac := val & 0x3ff
|
||||
if exp == 0x1f {
|
||||
if frac != 0 {
|
||||
*f = Float16(math.NaN())
|
||||
} else {
|
||||
*f = Float16(math.Inf(int(sign)*-2 + 1))
|
||||
}
|
||||
} else {
|
||||
var bits uint64
|
||||
bits |= uint64(sign) << 63
|
||||
bits |= uint64(frac) << 42
|
||||
if exp > 0 {
|
||||
bits |= uint64(exp-15+1023) << 52
|
||||
}
|
||||
*f = Float16(math.Float64frombits(bits))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (f *Float16) Size(opt *Options) int {
|
||||
return 2
|
||||
}
|
||||
func (f *Float16) String() string {
|
||||
return strconv.FormatFloat(float64(*f), 'g', -1, 32)
|
||||
}
|
56
vendor/github.com/lunixbochs/struc/custom_float16_test.go
сгенерированный
поставляемый
Normal file
56
vendor/github.com/lunixbochs/struc/custom_float16_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,56 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFloat16(t *testing.T) {
|
||||
// test cases from https://en.wikipedia.org/wiki/Half-precision_floating-point_format#Half_precision_examples
|
||||
tests := []struct {
|
||||
B string
|
||||
F float64
|
||||
}{
|
||||
//s expnt significand
|
||||
{"0 01111 0000000000", 1},
|
||||
{"0 01111 0000000001", 1.0009765625},
|
||||
{"1 10000 0000000000", -2},
|
||||
{"0 11110 1111111111", 65504},
|
||||
// {"0 00001 0000000000", 0.0000610352},
|
||||
// {"0 00000 1111111111", 0.0000609756},
|
||||
// {"0 00000 0000000001", 0.0000000596046},
|
||||
{"0 00000 0000000000", 0},
|
||||
// {"1 00000 0000000000", -0},
|
||||
{"0 11111 0000000000", math.Inf(1)},
|
||||
{"1 11111 0000000000", math.Inf(-1)},
|
||||
{"0 01101 0101010101", 0.333251953125},
|
||||
}
|
||||
for _, test := range tests {
|
||||
var buf bytes.Buffer
|
||||
f := Float16(test.F)
|
||||
if err := Pack(&buf, &f); err != nil {
|
||||
t.Error("pack failed:", err)
|
||||
continue
|
||||
}
|
||||
bitval, _ := strconv.ParseUint(strings.Replace(test.B, " ", "", -1), 2, 16)
|
||||
tmp := binary.BigEndian.Uint16(buf.Bytes())
|
||||
if tmp != uint16(bitval) {
|
||||
t.Errorf("incorrect pack: %s != %016b (%f)", test.B, tmp, test.F)
|
||||
continue
|
||||
}
|
||||
var f2 Float16
|
||||
if err := Unpack(&buf, &f2); err != nil {
|
||||
t.Error("unpack failed:", err)
|
||||
continue
|
||||
}
|
||||
// let sprintf deal with (im)precision for me here
|
||||
if fmt.Sprintf("%f", f) != fmt.Sprintf("%f", f2) {
|
||||
t.Errorf("incorrect unpack: %016b %f != %f", bitval, f, f2)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Int3 uint32
|
||||
|
||||
func (i *Int3) Pack(p []byte, opt *Options) (int, error) {
|
||||
var tmp [4]byte
|
||||
binary.BigEndian.PutUint32(tmp[:], uint32(*i))
|
||||
copy(p, tmp[1:])
|
||||
return 3, nil
|
||||
}
|
||||
func (i *Int3) Unpack(r io.Reader, length int, opt *Options) error {
|
||||
var tmp [4]byte
|
||||
if _, err := r.Read(tmp[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*i = Int3(binary.BigEndian.Uint32(tmp[:]))
|
||||
return nil
|
||||
}
|
||||
func (i *Int3) Size(opt *Options) int {
|
||||
return 3
|
||||
}
|
||||
func (i *Int3) String() string {
|
||||
return strconv.FormatUint(uint64(*i), 10)
|
||||
}
|
||||
|
||||
func TestCustom(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
var i Int3 = 3
|
||||
if err := Pack(&buf, &i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), []byte{0, 0, 3}) {
|
||||
t.Fatal("error packing custom int")
|
||||
}
|
||||
var i2 Int3
|
||||
if err := Unpack(&buf, &i2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i2 != 3 {
|
||||
t.Fatal("error unpacking custom int")
|
||||
}
|
||||
}
|
||||
|
||||
type Int3Struct struct {
|
||||
I Int3
|
||||
}
|
||||
|
||||
func TestCustomStruct(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
i := Int3Struct{3}
|
||||
if err := Pack(&buf, &i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), []byte{0, 0, 3}) {
|
||||
t.Fatal("error packing custom int struct")
|
||||
}
|
||||
var i2 Int3Struct
|
||||
if err := Unpack(&buf, &i2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i2.I != 3 {
|
||||
t.Fatal("error unpacking custom int struct")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: slices of custom types don't work yet
|
||||
/*
|
||||
type Int3SliceStruct struct {
|
||||
I [2]Int3
|
||||
}
|
||||
|
||||
func TestCustomSliceStruct(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
i := Int3SliceStruct{[2]Int3{3, 4}}
|
||||
if err := Pack(&buf, &i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), []byte{0, 0, 3}) {
|
||||
t.Fatal("error packing custom int struct")
|
||||
}
|
||||
var i2 Int3SliceStruct
|
||||
if err := Unpack(&buf, &i2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i2.I[0] != 3 && i2.I[1] != 4 {
|
||||
t.Fatal("error unpacking custom int struct")
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,280 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
Name string
|
||||
Ptr bool
|
||||
Index int
|
||||
Type Type
|
||||
defType Type
|
||||
Array bool
|
||||
Slice bool
|
||||
Len int
|
||||
Order binary.ByteOrder
|
||||
Sizeof []int
|
||||
Sizefrom []int
|
||||
Fields Fields
|
||||
kind reflect.Kind
|
||||
}
|
||||
|
||||
func (f *Field) String() string {
|
||||
var out string
|
||||
if f.Type == Pad {
|
||||
return fmt.Sprintf("{type: Pad, len: %d}", f.Len)
|
||||
} else {
|
||||
out = fmt.Sprintf("type: %s, order: %v", f.Type.String(), f.Order)
|
||||
}
|
||||
if f.Sizefrom != nil {
|
||||
out += fmt.Sprintf(", sizefrom: %v", f.Sizefrom)
|
||||
} else if f.Len > 0 {
|
||||
out += fmt.Sprintf(", len: %d", f.Len)
|
||||
}
|
||||
if f.Sizeof != nil {
|
||||
out += fmt.Sprintf(", sizeof: %v", f.Sizeof)
|
||||
}
|
||||
return "{" + out + "}"
|
||||
}
|
||||
|
||||
func (f *Field) Size(val reflect.Value, options *Options) int {
|
||||
typ := f.Type.Resolve(options)
|
||||
size := 0
|
||||
if typ == Struct {
|
||||
vals := []reflect.Value{val}
|
||||
if f.Slice {
|
||||
vals = make([]reflect.Value, val.Len())
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
vals[i] = val.Index(i)
|
||||
}
|
||||
}
|
||||
for _, val := range vals {
|
||||
size += f.Fields.Sizeof(val, options)
|
||||
}
|
||||
} else if typ == Pad {
|
||||
size = f.Len
|
||||
} else if f.Slice || f.kind == reflect.String {
|
||||
length := val.Len()
|
||||
if f.Len > 1 {
|
||||
length = f.Len
|
||||
}
|
||||
size = length * typ.Size()
|
||||
} else if typ == CustomType {
|
||||
return val.Addr().Interface().(Custom).Size(options)
|
||||
} else {
|
||||
size = typ.Size()
|
||||
}
|
||||
align := options.ByteAlign
|
||||
if align > 0 && size < align {
|
||||
size = align
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) {
|
||||
order := f.Order
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
if f.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
typ := f.Type.Resolve(options)
|
||||
switch typ {
|
||||
case Struct:
|
||||
return f.Fields.Pack(buf, val, options)
|
||||
case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
|
||||
size = typ.Size()
|
||||
var n uint64
|
||||
switch f.kind {
|
||||
case reflect.Bool:
|
||||
if val.Bool() {
|
||||
n = 1
|
||||
} else {
|
||||
n = 0
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n = uint64(val.Int())
|
||||
default:
|
||||
n = val.Uint()
|
||||
}
|
||||
switch typ {
|
||||
case Bool:
|
||||
if n != 0 {
|
||||
buf[0] = 1
|
||||
} else {
|
||||
buf[0] = 0
|
||||
}
|
||||
case Int8, Uint8:
|
||||
buf[0] = byte(n)
|
||||
case Int16, Uint16:
|
||||
order.PutUint16(buf, uint16(n))
|
||||
case Int32, Uint32:
|
||||
order.PutUint32(buf, uint32(n))
|
||||
case Int64, Uint64:
|
||||
order.PutUint64(buf, uint64(n))
|
||||
}
|
||||
case Float32, Float64:
|
||||
size = typ.Size()
|
||||
n := val.Float()
|
||||
switch typ {
|
||||
case Float32:
|
||||
order.PutUint32(buf, math.Float32bits(float32(n)))
|
||||
case Float64:
|
||||
order.PutUint64(buf, math.Float64bits(n))
|
||||
}
|
||||
case String:
|
||||
switch f.kind {
|
||||
case reflect.String:
|
||||
size = val.Len()
|
||||
copy(buf, []byte(val.String()))
|
||||
default:
|
||||
// TODO: handle kind != bytes here
|
||||
size = val.Len()
|
||||
copy(buf, val.Bytes())
|
||||
}
|
||||
case CustomType:
|
||||
return val.Addr().Interface().(Custom).Pack(buf, options)
|
||||
default:
|
||||
panic(fmt.Sprintf("no pack handler for type: %s", typ))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) {
|
||||
typ := f.Type.Resolve(options)
|
||||
if typ == Pad {
|
||||
for i := 0; i < length; i++ {
|
||||
buf[i] = 0
|
||||
}
|
||||
return length, nil
|
||||
}
|
||||
if f.Slice {
|
||||
// special case strings and byte slices for performance
|
||||
end := val.Len()
|
||||
if !f.Array && typ == Uint8 && (f.defType == Uint8 || f.kind == reflect.String) {
|
||||
var tmp []byte
|
||||
if f.kind == reflect.String {
|
||||
tmp = []byte(val.String())
|
||||
} else {
|
||||
tmp = val.Bytes()
|
||||
}
|
||||
copy(buf, tmp)
|
||||
if end < length {
|
||||
// TODO: allow configuring pad byte?
|
||||
rep := bytes.Repeat([]byte{0}, length-end)
|
||||
copy(buf[end:], rep)
|
||||
return length, nil
|
||||
}
|
||||
return val.Len(), nil
|
||||
}
|
||||
pos := 0
|
||||
var zero reflect.Value
|
||||
if end < length {
|
||||
zero = reflect.Zero(val.Type().Elem())
|
||||
}
|
||||
for i := 0; i < length; i++ {
|
||||
cur := zero
|
||||
if i < end {
|
||||
cur = val.Index(i)
|
||||
}
|
||||
if n, err := f.packVal(buf[pos:], cur, 1, options); err != nil {
|
||||
return pos, err
|
||||
} else {
|
||||
pos += n
|
||||
}
|
||||
}
|
||||
return pos, nil
|
||||
} else {
|
||||
return f.packVal(buf, val, length, options)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Field) unpackVal(buf []byte, val reflect.Value, length int, options *Options) error {
|
||||
order := f.Order
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
if f.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
typ := f.Type.Resolve(options)
|
||||
switch typ {
|
||||
case Float32, Float64:
|
||||
var n float64
|
||||
switch typ {
|
||||
case Float32:
|
||||
n = float64(math.Float32frombits(order.Uint32(buf)))
|
||||
case Float64:
|
||||
n = math.Float64frombits(order.Uint64(buf))
|
||||
}
|
||||
switch f.kind {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
val.SetFloat(n)
|
||||
default:
|
||||
return fmt.Errorf("struc: refusing to unpack float into field %s of type %s", f.Name, f.kind.String())
|
||||
}
|
||||
case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
|
||||
var n uint64
|
||||
switch typ {
|
||||
case Bool, Int8, Uint8:
|
||||
n = uint64(buf[0])
|
||||
case Int16, Uint16:
|
||||
n = uint64(order.Uint16(buf))
|
||||
case Int32, Uint32:
|
||||
n = uint64(order.Uint32(buf))
|
||||
case Int64, Uint64:
|
||||
n = uint64(order.Uint64(buf))
|
||||
}
|
||||
switch f.kind {
|
||||
case reflect.Bool:
|
||||
val.SetBool(n != 0)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
val.SetInt(int64(n))
|
||||
default:
|
||||
val.SetUint(n)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("no unpack handler for type: %s", typ))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Field) Unpack(buf []byte, val reflect.Value, length int, options *Options) error {
|
||||
typ := f.Type.Resolve(options)
|
||||
if typ == Pad || f.kind == reflect.String {
|
||||
if typ == Pad {
|
||||
return nil
|
||||
} else {
|
||||
val.SetString(string(buf))
|
||||
return nil
|
||||
}
|
||||
} else if f.Slice {
|
||||
if val.Cap() < length {
|
||||
val.Set(reflect.MakeSlice(val.Type(), length, length))
|
||||
} else if val.Len() < length {
|
||||
val.Set(val.Slice(0, length))
|
||||
}
|
||||
// special case byte slices for performance
|
||||
if !f.Array && typ == Uint8 && f.defType == Uint8 {
|
||||
copy(val.Bytes(), buf[:length])
|
||||
return nil
|
||||
}
|
||||
pos := 0
|
||||
size := typ.Size()
|
||||
for i := 0; i < length; i++ {
|
||||
if err := f.unpackVal(buf[pos:pos+size], val.Index(i), 1, options); err != nil {
|
||||
return err
|
||||
}
|
||||
pos += size
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
return f.unpackVal(buf, val, length, options)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type badFloat struct {
|
||||
BadFloat int `struc:"float64"`
|
||||
}
|
||||
|
||||
func TestBadFloatField(t *testing.T) {
|
||||
buf := bytes.NewReader([]byte("00000000"))
|
||||
err := Unpack(buf, &badFloat{})
|
||||
if err == nil {
|
||||
t.Fatal("failed to error on bad float unpack")
|
||||
}
|
||||
}
|
||||
|
||||
type emptyLengthField struct {
|
||||
Strlen int `struc:"sizeof=Str"`
|
||||
Str []byte
|
||||
}
|
||||
|
||||
func TestEmptyLengthField(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
s := &emptyLengthField{0, []byte("test")}
|
||||
o := &emptyLengthField{}
|
||||
if err := Pack(&buf, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, o); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(s.Str, o.Str) {
|
||||
t.Fatal("empty length field encode failed")
|
||||
}
|
||||
}
|
||||
|
||||
type fixedSlicePad struct {
|
||||
Field []byte `struc:"[4]byte"`
|
||||
}
|
||||
|
||||
func TestFixedSlicePad(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
ref := []byte{0, 0, 0, 0}
|
||||
s := &fixedSlicePad{}
|
||||
if err := Pack(&buf, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), ref) {
|
||||
t.Fatal("implicit fixed slice pack failed")
|
||||
}
|
||||
if err := Unpack(&buf, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(s.Field, ref) {
|
||||
t.Fatal("implicit fixed slice unpack failed")
|
||||
}
|
||||
}
|
||||
|
||||
type sliceCap struct {
|
||||
Len int `struc:"sizeof=Field"`
|
||||
Field []byte
|
||||
}
|
||||
|
||||
func TestSliceCap(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
tmp := &sliceCap{0, []byte("1234")}
|
||||
if err := Pack(&buf, tmp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmp.Field = make([]byte, 0, 4)
|
||||
if err := Unpack(&buf, tmp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Fields []*Field
|
||||
|
||||
func (f Fields) SetByteOrder(order binary.ByteOrder) {
|
||||
for _, field := range f {
|
||||
if field != nil {
|
||||
field.Order = order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f Fields) String() string {
|
||||
fields := make([]string, len(f))
|
||||
for i, field := range f {
|
||||
if field != nil {
|
||||
fields[i] = field.String()
|
||||
}
|
||||
}
|
||||
return "{" + strings.Join(fields, ", ") + "}"
|
||||
}
|
||||
|
||||
func (f Fields) Sizeof(val reflect.Value, options *Options) int {
|
||||
for val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
size := 0
|
||||
for i, field := range f {
|
||||
if field != nil {
|
||||
size += field.Size(val.Field(i), options)
|
||||
}
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func (f Fields) sizefrom(val reflect.Value, index []int) int {
|
||||
field := val.FieldByIndex(index)
|
||||
switch field.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return int(field.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
n := int(field.Uint())
|
||||
// all the builtin array length types are native int
|
||||
// so this guards against weird truncation
|
||||
if n < 0 {
|
||||
return 0
|
||||
}
|
||||
return n
|
||||
default:
|
||||
name := val.Type().FieldByIndex(index).Name
|
||||
panic(fmt.Sprintf("sizeof field %T.%s not an integer type", val.Interface(), name))
|
||||
}
|
||||
}
|
||||
|
||||
func (f Fields) Pack(buf []byte, val reflect.Value, options *Options) (int, error) {
|
||||
for val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
pos := 0
|
||||
for i, field := range f {
|
||||
if field == nil {
|
||||
continue
|
||||
}
|
||||
v := val.Field(i)
|
||||
length := field.Len
|
||||
if field.Sizefrom != nil {
|
||||
length = f.sizefrom(val, field.Sizefrom)
|
||||
}
|
||||
if length <= 0 && field.Slice {
|
||||
length = v.Len()
|
||||
}
|
||||
if field.Sizeof != nil {
|
||||
length := val.FieldByIndex(field.Sizeof).Len()
|
||||
switch field.kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
// allocating a new int here has fewer side effects (doesn't update the original struct)
|
||||
// but it's a wasteful allocation
|
||||
// the old method might work if we just cast the temporary int/uint to the target type
|
||||
v = reflect.New(v.Type()).Elem()
|
||||
v.SetInt(int64(length))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
v = reflect.New(v.Type()).Elem()
|
||||
v.SetUint(uint64(length))
|
||||
default:
|
||||
panic(fmt.Sprintf("sizeof field is not int or uint type: %s, %s", field.Name, v.Type()))
|
||||
}
|
||||
}
|
||||
if n, err := field.Pack(buf[pos:], v, length, options); err != nil {
|
||||
return n, err
|
||||
} else {
|
||||
pos += n
|
||||
}
|
||||
}
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
func (f Fields) Unpack(r io.Reader, val reflect.Value, options *Options) error {
|
||||
for val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
var tmp [8]byte
|
||||
var buf []byte
|
||||
for i, field := range f {
|
||||
if field == nil {
|
||||
continue
|
||||
}
|
||||
v := val.Field(i)
|
||||
length := field.Len
|
||||
if field.Sizefrom != nil {
|
||||
length = f.sizefrom(val, field.Sizefrom)
|
||||
}
|
||||
if v.Kind() == reflect.Ptr && !v.Elem().IsValid() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
if field.Type == Struct {
|
||||
if field.Slice {
|
||||
vals := reflect.MakeSlice(v.Type(), length, length)
|
||||
for i := 0; i < length; i++ {
|
||||
v := vals.Index(i)
|
||||
fields, err := parseFields(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fields.Unpack(r, v, options); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Set(vals)
|
||||
} else {
|
||||
// TODO: DRY (we repeat the inner loop above)
|
||||
fields, err := parseFields(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fields.Unpack(r, v, options); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
typ := field.Type.Resolve(options)
|
||||
if typ == CustomType {
|
||||
if err := v.Addr().Interface().(Custom).Unpack(r, length, options); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
size := length * field.Type.Resolve(options).Size()
|
||||
if size < 8 {
|
||||
buf = tmp[:size]
|
||||
} else {
|
||||
buf = make([]byte, size)
|
||||
}
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
err := field.Unpack(buf[:size], v, length, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var refVal = reflect.ValueOf(reference)
|
||||
|
||||
func TestFieldsParse(t *testing.T) {
|
||||
if _, err := parseFields(refVal); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldsString(t *testing.T) {
|
||||
fields, _ := parseFields(refVal)
|
||||
fields.String()
|
||||
}
|
||||
|
||||
type sizefromStruct struct {
|
||||
Size1 uint `struc:"sizeof=Var1"`
|
||||
Var1 []byte
|
||||
Size2 int `struc:"sizeof=Var2"`
|
||||
Var2 []byte
|
||||
}
|
||||
|
||||
func TestFieldsSizefrom(t *testing.T) {
|
||||
var test = sizefromStruct{
|
||||
Var1: []byte{1, 2, 3},
|
||||
Var2: []byte{4, 5, 6},
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err := Pack(&buf, &test)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = Unpack(&buf, &test)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
type sizefromStructBad struct {
|
||||
Size1 string `struc:"sizeof=Var1"`
|
||||
Var1 []byte
|
||||
}
|
||||
|
||||
func TestFieldsSizefromBad(t *testing.T) {
|
||||
var test = &sizefromStructBad{Var1: []byte{1, 2, 3}}
|
||||
var buf bytes.Buffer
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Fatal("failed to panic on bad sizeof type")
|
||||
}
|
||||
}()
|
||||
Pack(&buf, &test)
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Deprecated. Use PackWithOptions.
|
||||
func PackWithOrder(w io.Writer, data interface{}, order binary.ByteOrder) error {
|
||||
return PackWithOptions(w, data, &Options{Order: order})
|
||||
}
|
||||
|
||||
// Deprecated. Use UnpackWithOptions.
|
||||
func UnpackWithOrder(r io.Reader, data interface{}, order binary.ByteOrder) error {
|
||||
return UnpackWithOptions(r, data, &Options{Order: order})
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var packableReference = []byte{
|
||||
1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16,
|
||||
0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24,
|
||||
}
|
||||
|
||||
func TestPackable(t *testing.T) {
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
|
||||
i8 int8 = 1
|
||||
i16 int16 = 2
|
||||
i32 int32 = 3
|
||||
i64 int64 = 4
|
||||
u8 uint8 = 5
|
||||
u16 uint16 = 6
|
||||
u32 uint32 = 7
|
||||
u64 uint64 = 8
|
||||
|
||||
u8a = [8]uint8{9, 10, 11, 12, 13, 14, 15, 16}
|
||||
u16a = [8]uint16{17, 18, 19, 20, 21, 22, 23, 24}
|
||||
)
|
||||
// pack tests
|
||||
if err := Pack(&buf, i8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, i16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, i32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, i64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u8a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u16a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), packableReference) {
|
||||
fmt.Println(buf.Bytes())
|
||||
fmt.Println(packableReference)
|
||||
t.Fatal("Packable Pack() did not match reference.")
|
||||
}
|
||||
// unpack tests
|
||||
i8 = 0
|
||||
i16 = 0
|
||||
i32 = 0
|
||||
i64 = 0
|
||||
u8 = 0
|
||||
u16 = 0
|
||||
u32 = 0
|
||||
u64 = 0
|
||||
if err := Unpack(&buf, &i8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &i16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &i32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &i64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, u8a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, u16a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// unpack checks
|
||||
if i8 != 1 || i16 != 2 || i32 != 3 || i64 != 4 {
|
||||
t.Fatal("Signed integer unpack failed.")
|
||||
}
|
||||
if u8 != 5 || u16 != 6 || u32 != 7 || u64 != 8 {
|
||||
t.Fatal("Unsigned integer unpack failed.")
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
if u8a[i] != uint8(i+9) {
|
||||
t.Fatal("uint8 array unpack failed.")
|
||||
}
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
if u16a[i] != uint16(i+17) {
|
||||
t.Fatal("uint16 array unpack failed.")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Packer interface {
|
||||
Pack(buf []byte, val reflect.Value, options *Options) (int, error)
|
||||
Unpack(r io.Reader, val reflect.Value, options *Options) error
|
||||
Sizeof(val reflect.Value, options *Options) int
|
||||
String() string
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// struc:"int32,big,sizeof=Data"
|
||||
|
||||
type strucTag struct {
|
||||
Type string
|
||||
Order binary.ByteOrder
|
||||
Sizeof string
|
||||
Skip bool
|
||||
}
|
||||
|
||||
func parseStrucTag(tag reflect.StructTag) *strucTag {
|
||||
t := &strucTag{
|
||||
Order: binary.BigEndian,
|
||||
}
|
||||
tagStr := tag.Get("struc")
|
||||
if tagStr == "" {
|
||||
// someone's going to typo this (I already did once)
|
||||
// sorry if you made a module actually using this tag
|
||||
// and you're mad at me now
|
||||
tagStr = tag.Get("struct")
|
||||
}
|
||||
for _, s := range strings.Split(tagStr, ",") {
|
||||
if strings.HasPrefix(s, "sizeof=") {
|
||||
tmp := strings.SplitN(s, "=", 2)
|
||||
t.Sizeof = tmp[1]
|
||||
} else if s == "big" {
|
||||
t.Order = binary.BigEndian
|
||||
} else if s == "little" {
|
||||
t.Order = binary.LittleEndian
|
||||
} else if s == "skip" {
|
||||
t.Skip = true
|
||||
} else {
|
||||
t.Type = s
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
var typeLenRe = regexp.MustCompile(`^\[(\d*)\]`)
|
||||
|
||||
func parseField(f reflect.StructField) (fd *Field, tag *strucTag, err error) {
|
||||
tag = parseStrucTag(f.Tag)
|
||||
var ok bool
|
||||
fd = &Field{
|
||||
Name: f.Name,
|
||||
Len: 1,
|
||||
Order: tag.Order,
|
||||
Slice: false,
|
||||
kind: f.Type.Kind(),
|
||||
}
|
||||
switch fd.kind {
|
||||
case reflect.Array:
|
||||
fd.Slice = true
|
||||
fd.Array = true
|
||||
fd.Len = f.Type.Len()
|
||||
fd.kind = f.Type.Elem().Kind()
|
||||
case reflect.Slice:
|
||||
fd.Slice = true
|
||||
fd.Len = -1
|
||||
fd.kind = f.Type.Elem().Kind()
|
||||
case reflect.Ptr:
|
||||
fd.Ptr = true
|
||||
fd.kind = f.Type.Elem().Kind()
|
||||
}
|
||||
// check for custom types
|
||||
tmp := reflect.New(f.Type)
|
||||
if _, ok := tmp.Interface().(Custom); ok {
|
||||
fd.Type = CustomType
|
||||
return
|
||||
}
|
||||
var defTypeOk bool
|
||||
fd.defType, defTypeOk = reflectTypeMap[fd.kind]
|
||||
// find a type in the struct tag
|
||||
pureType := typeLenRe.ReplaceAllLiteralString(tag.Type, "")
|
||||
if fd.Type, ok = typeLookup[pureType]; ok {
|
||||
fd.Len = 1
|
||||
match := typeLenRe.FindAllStringSubmatch(tag.Type, -1)
|
||||
if len(match) > 0 && len(match[0]) > 1 {
|
||||
fd.Slice = true
|
||||
first := match[0][1]
|
||||
// Field.Len = -1 indicates a []slice
|
||||
if first == "" {
|
||||
fd.Len = -1
|
||||
} else {
|
||||
fd.Len, err = strconv.Atoi(first)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// the user didn't specify a type
|
||||
switch f.Type {
|
||||
case reflect.TypeOf(Size_t(0)):
|
||||
fd.Type = SizeType
|
||||
case reflect.TypeOf(Off_t(0)):
|
||||
fd.Type = OffType
|
||||
default:
|
||||
if defTypeOk {
|
||||
fd.Type = fd.defType
|
||||
} else {
|
||||
err = errors.New("struc: Could not find field type.")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseFieldsLocked(v reflect.Value) (Fields, error) {
|
||||
// we need to repeat this logic because parseFields() below can't be recursively called due to locking
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
t := v.Type()
|
||||
if v.NumField() < 1 {
|
||||
return nil, errors.New("struc: Struct has no fields.")
|
||||
}
|
||||
sizeofMap := make(map[string][]int)
|
||||
fields := make(Fields, v.NumField())
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
f, tag, err := parseField(field)
|
||||
if tag.Skip {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !v.Field(i).CanSet() {
|
||||
continue
|
||||
}
|
||||
f.Index = i
|
||||
if tag.Sizeof != "" {
|
||||
target, ok := t.FieldByName(tag.Sizeof)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("struc: `sizeof=%s` field does not exist", tag.Sizeof)
|
||||
}
|
||||
f.Sizeof = target.Index
|
||||
sizeofMap[tag.Sizeof] = field.Index
|
||||
}
|
||||
if sizefrom, ok := sizeofMap[field.Name]; ok {
|
||||
f.Sizefrom = sizefrom
|
||||
}
|
||||
if f.Len == -1 && f.Sizefrom == nil {
|
||||
return nil, fmt.Errorf("struc: field `%s` is a slice with no length or sizeof field", field.Name)
|
||||
}
|
||||
// recurse into nested structs
|
||||
// TODO: handle loops (probably by indirecting the []Field and putting pointer in cache)
|
||||
if f.Type == Struct {
|
||||
typ := field.Type
|
||||
if f.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
if f.Slice {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
f.Fields, err = parseFieldsLocked(reflect.New(typ))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
fields[i] = f
|
||||
}
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
var fieldCache = make(map[reflect.Type]Fields)
|
||||
var fieldCacheLock sync.RWMutex
|
||||
var parseLock sync.Mutex
|
||||
|
||||
func fieldCacheLookup(t reflect.Type) Fields {
|
||||
fieldCacheLock.RLock()
|
||||
defer fieldCacheLock.RUnlock()
|
||||
if cached, ok := fieldCache[t]; ok {
|
||||
return cached
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseFields(v reflect.Value) (Fields, error) {
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
t := v.Type()
|
||||
|
||||
// fast path: hopefully the field parsing is already cached
|
||||
if cached := fieldCacheLookup(t); cached != nil {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
// hold a global lock so multiple goroutines can't parse (the same) fields at once
|
||||
parseLock.Lock()
|
||||
defer parseLock.Unlock()
|
||||
|
||||
// check cache a second time, in case parseLock was just released by
|
||||
// another thread who filled the cache for us
|
||||
if cached := fieldCacheLookup(t); cached != nil {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
// no luck, time to parse and fill the cache ourselves
|
||||
fields, err := parseFieldsLocked(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldCacheLock.Lock()
|
||||
fieldCache[t] = fields
|
||||
fieldCacheLock.Unlock()
|
||||
return fields, nil
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func parseTest(data interface{}) error {
|
||||
_, err := parseFields(reflect.ValueOf(data))
|
||||
return err
|
||||
}
|
||||
|
||||
type empty struct{}
|
||||
|
||||
func TestEmptyStruc(t *testing.T) {
|
||||
if err := parseTest(&empty{}); err == nil {
|
||||
t.Fatal("failed to error on empty struct")
|
||||
}
|
||||
}
|
||||
|
||||
type chanStruct struct {
|
||||
Test chan int
|
||||
}
|
||||
|
||||
func TestChanError(t *testing.T) {
|
||||
if err := parseTest(&chanStruct{}); err == nil {
|
||||
// TODO: should probably ignore channel fields
|
||||
t.Fatal("failed to error on struct containing channel")
|
||||
}
|
||||
}
|
||||
|
||||
type badSizeof struct {
|
||||
Size int `struc:"sizeof=Bad"`
|
||||
}
|
||||
|
||||
func TestBadSizeof(t *testing.T) {
|
||||
if err := parseTest(&badSizeof{}); err == nil {
|
||||
t.Fatal("failed to error on missing Sizeof target")
|
||||
}
|
||||
}
|
||||
|
||||
type missingSize struct {
|
||||
Test []byte
|
||||
}
|
||||
|
||||
func TestMissingSize(t *testing.T) {
|
||||
if err := parseTest(&missingSize{}); err == nil {
|
||||
t.Fatal("failed to error on missing field size")
|
||||
}
|
||||
}
|
||||
|
||||
type badNested struct {
|
||||
Empty empty
|
||||
}
|
||||
|
||||
func TestNestedParseError(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, &badNested{}); err == nil {
|
||||
t.Fatal("failed to error on bad nested struct")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ByteAlign int
|
||||
PtrSize int
|
||||
Order binary.ByteOrder
|
||||
}
|
||||
|
||||
func (o *Options) Validate() error {
|
||||
if o.PtrSize == 0 {
|
||||
o.PtrSize = 32
|
||||
} else {
|
||||
switch o.PtrSize {
|
||||
case 8, 16, 32, 64:
|
||||
default:
|
||||
return fmt.Errorf("Invalid Options.PtrSize: %d. Must be in (8, 16, 32, 64)", o.PtrSize)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var emptyOptions = &Options{}
|
||||
|
||||
func prep(data interface{}) (reflect.Value, Packer, error) {
|
||||
value := reflect.ValueOf(data)
|
||||
for value.Kind() == reflect.Ptr {
|
||||
next := value.Elem().Kind()
|
||||
if next == reflect.Struct || next == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
switch value.Kind() {
|
||||
case reflect.Struct:
|
||||
fields, err := parseFields(value)
|
||||
return value, fields, err
|
||||
default:
|
||||
if !value.IsValid() {
|
||||
return reflect.Value{}, nil, fmt.Errorf("Invalid reflect.Value for %+v", data)
|
||||
}
|
||||
if c, ok := data.(Custom); ok {
|
||||
return value, customFallback{c}, nil
|
||||
}
|
||||
return value, binaryFallback(value), nil
|
||||
}
|
||||
}
|
||||
|
||||
func Pack(w io.Writer, data interface{}) error {
|
||||
return PackWithOptions(w, data, nil)
|
||||
}
|
||||
|
||||
func PackWithOptions(w io.Writer, data interface{}, options *Options) error {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if val.Type().Kind() == reflect.String {
|
||||
val = val.Convert(reflect.TypeOf([]byte{}))
|
||||
}
|
||||
size := packer.Sizeof(val, options)
|
||||
buf := make([]byte, size)
|
||||
if _, err := packer.Pack(buf, val, options); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
func Unpack(r io.Reader, data interface{}) error {
|
||||
return UnpackWithOptions(r, data, nil)
|
||||
}
|
||||
|
||||
func UnpackWithOptions(r io.Reader, data interface{}, options *Options) error {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return packer.Unpack(r, val, options)
|
||||
}
|
||||
|
||||
func Sizeof(data interface{}) (int, error) {
|
||||
return SizeofWithOptions(data, nil)
|
||||
}
|
||||
|
||||
func SizeofWithOptions(data interface{}, options *Options) (int, error) {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return packer.Sizeof(val, options), nil
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Nested struct {
|
||||
Test2 int `struc:"int8"`
|
||||
}
|
||||
|
||||
type Example struct {
|
||||
Pad []byte `struc:"[5]pad"` // 00 00 00 00 00
|
||||
I8f int `struc:"int8"` // 01
|
||||
I16f int `struc:"int16"` // 00 02
|
||||
I32f int `struc:"int32"` // 00 00 00 03
|
||||
I64f int `struc:"int64"` // 00 00 00 00 00 00 00 04
|
||||
U8f int `struc:"uint8,little"` // 05
|
||||
U16f int `struc:"uint16,little"` // 06 00
|
||||
U32f int `struc:"uint32,little"` // 07 00 00 00
|
||||
U64f int `struc:"uint64,little"` // 08 00 00 00 00 00 00 00
|
||||
Boolf int `struc:"bool"` // 01
|
||||
Byte4f []byte `struc:"[4]byte"` // "abcd"
|
||||
|
||||
I8 int8 // 09
|
||||
I16 int16 // 00 0a
|
||||
I32 int32 // 00 00 00 0b
|
||||
I64 int64 // 00 00 00 00 00 00 00 0c
|
||||
U8 uint8 `struc:"little"` // 0d
|
||||
U16 uint16 `struc:"little"` // 0e 00
|
||||
U32 uint32 `struc:"little"` // 0f 00 00 00
|
||||
U64 uint64 `struc:"little"` // 10 00 00 00 00 00 00 00
|
||||
BoolT bool // 01
|
||||
BoolF bool // 00
|
||||
Byte4 [4]byte // "efgh"
|
||||
Float1 float32 // 41 a0 00 00
|
||||
Float2 float64 // 41 35 00 00 00 00 00 00
|
||||
|
||||
Size int `struc:"sizeof=Str,little"` // 0a 00 00 00
|
||||
Str string `struc:"[]byte"` // "ijklmnopqr"
|
||||
Strb string `struc:"[4]byte"` // "stuv"
|
||||
|
||||
Size2 int `struc:"uint8,sizeof=Str2"` // 04
|
||||
Str2 string // "1234"
|
||||
|
||||
Size3 int `struc:"uint8,sizeof=Bstr"` // 04
|
||||
Bstr []byte // "5678"
|
||||
|
||||
Nested Nested // 00 00 00 01
|
||||
NestedP *Nested // 00 00 00 02
|
||||
TestP64 *int `struc:"int64"` // 00 00 00 05
|
||||
|
||||
NestedSize int `struc:"sizeof=NestedA"` // 00 00 00 02
|
||||
NestedA []Nested // [00 00 00 03, 00 00 00 04]
|
||||
|
||||
Skip int `struc:"skip"`
|
||||
|
||||
CustomTypeSize Int3 `struc:"sizeof=CustomTypeSizeArr"` // 00 00 00 04
|
||||
CustomTypeSizeArr []byte // "ABCD"
|
||||
}
|
||||
|
||||
var five = 5
|
||||
|
||||
var reference = &Example{
|
||||
nil,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 0, []byte{'a', 'b', 'c', 'd'},
|
||||
9, 10, 11, 12, 13, 14, 15, 16, true, false, [4]byte{'e', 'f', 'g', 'h'},
|
||||
20, 21,
|
||||
10, "ijklmnopqr", "stuv",
|
||||
4, "1234",
|
||||
4, []byte("5678"),
|
||||
Nested{1}, &Nested{2}, &five,
|
||||
6, []Nested{{3}, {4}, {5}, {6}, {7}, {8}},
|
||||
0,
|
||||
Int3(4), []byte("ABCD"),
|
||||
}
|
||||
|
||||
var referenceBytes = []byte{
|
||||
0, 0, 0, 0, 0, // pad(5)
|
||||
1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, // fake int8-int64(1-4)
|
||||
5, 6, 0, 7, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, // fake little-endian uint8-uint64(5-8)
|
||||
0, // fake bool(0)
|
||||
'a', 'b', 'c', 'd', // fake [4]byte
|
||||
|
||||
9, 0, 10, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 12, // real int8-int64(9-12)
|
||||
13, 14, 0, 15, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, // real little-endian uint8-uint64(13-16)
|
||||
1, 0, // real bool(1), bool(0)
|
||||
'e', 'f', 'g', 'h', // real [4]byte
|
||||
65, 160, 0, 0, // real float32(20)
|
||||
64, 53, 0, 0, 0, 0, 0, 0, // real float64(21)
|
||||
|
||||
10, 0, 0, 0, // little-endian int32(10) sizeof=Str
|
||||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', // Str
|
||||
's', 't', 'u', 'v', // fake string([4]byte)
|
||||
04, '1', '2', '3', '4', // real string
|
||||
04, '5', '6', '7', '8', // fake []byte(string)
|
||||
|
||||
1, 2, // Nested{1}, Nested{2}
|
||||
0, 0, 0, 0, 0, 0, 0, 5, // &five
|
||||
|
||||
0, 0, 0, 6, // int32(6)
|
||||
3, 4, 5, 6, 7, 8, // [Nested{3}, ...Nested{8}]
|
||||
|
||||
0, 0, 4, 'A', 'B', 'C', 'D', // Int3(4), []byte("ABCD")
|
||||
}
|
||||
|
||||
func TestCodec(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, reference); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out := &Example{}
|
||||
if err := Unpack(&buf, out); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(reference, out) {
|
||||
t.Fatal("encode/decode failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, reference); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), referenceBytes) {
|
||||
t.Fatal("encode failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode(t *testing.T) {
|
||||
buf := bytes.NewReader(referenceBytes)
|
||||
out := &Example{}
|
||||
if err := Unpack(buf, out); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(reference, out) {
|
||||
t.Fatal("decode failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSizeof(t *testing.T) {
|
||||
size, err := Sizeof(reference)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if size != len(referenceBytes) {
|
||||
t.Fatal("sizeof failed")
|
||||
}
|
||||
}
|
||||
|
||||
type ExampleEndian struct {
|
||||
T int `struc:"int16,big"`
|
||||
}
|
||||
|
||||
func TestEndianSwap(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
big := &ExampleEndian{1}
|
||||
if err := PackWithOrder(&buf, big, binary.BigEndian); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
little := &ExampleEndian{}
|
||||
if err := UnpackWithOrder(&buf, little, binary.LittleEndian); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if little.T != 256 {
|
||||
t.Fatal("big -> little conversion failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilValue(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, nil); err == nil {
|
||||
t.Fatal("failed throw error for bad struct value")
|
||||
}
|
||||
if err := Unpack(&buf, nil); err == nil {
|
||||
t.Fatal("failed throw error for bad struct value")
|
||||
}
|
||||
if _, err := Sizeof(nil); err == nil {
|
||||
t.Fatal("failed to throw error for bad struct value")
|
||||
}
|
||||
}
|
||||
|
||||
type sliceUnderrun struct {
|
||||
Str string `struc:"[10]byte"`
|
||||
Arr []uint16 `struc:"[10]uint16"`
|
||||
}
|
||||
|
||||
func TestSliceUnderrun(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
v := sliceUnderrun{
|
||||
Str: "foo",
|
||||
Arr: []uint16{1, 2, 3},
|
||||
}
|
||||
if err := Pack(&buf, &v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Type int
|
||||
|
||||
const (
|
||||
Invalid Type = iota
|
||||
Pad
|
||||
Bool
|
||||
Int
|
||||
Int8
|
||||
Uint8
|
||||
Int16
|
||||
Uint16
|
||||
Int32
|
||||
Uint32
|
||||
Int64
|
||||
Uint64
|
||||
Float32
|
||||
Float64
|
||||
String
|
||||
Struct
|
||||
Ptr
|
||||
|
||||
SizeType
|
||||
OffType
|
||||
CustomType
|
||||
)
|
||||
|
||||
func (t Type) Resolve(options *Options) Type {
|
||||
switch t {
|
||||
case OffType:
|
||||
switch options.PtrSize {
|
||||
case 8:
|
||||
return Int8
|
||||
case 16:
|
||||
return Int16
|
||||
case 32:
|
||||
return Int32
|
||||
case 64:
|
||||
return Int64
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize))
|
||||
}
|
||||
case SizeType:
|
||||
switch options.PtrSize {
|
||||
case 8:
|
||||
return Uint8
|
||||
case 16:
|
||||
return Uint16
|
||||
case 32:
|
||||
return Uint32
|
||||
case 64:
|
||||
return Uint64
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize))
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t Type) String() string {
|
||||
return typeNames[t]
|
||||
}
|
||||
|
||||
func (t Type) Size() int {
|
||||
switch t {
|
||||
case SizeType, OffType:
|
||||
panic("Size_t/Off_t types must be converted to another type using options.PtrSize")
|
||||
case Pad, String, Int8, Uint8, Bool:
|
||||
return 1
|
||||
case Int16, Uint16:
|
||||
return 2
|
||||
case Int32, Uint32, Float32:
|
||||
return 4
|
||||
case Int64, Uint64, Float64:
|
||||
return 8
|
||||
default:
|
||||
panic("Cannot resolve size of type:" + t.String())
|
||||
}
|
||||
}
|
||||
|
||||
var typeLookup = map[string]Type{
|
||||
"pad": Pad,
|
||||
"bool": Bool,
|
||||
"byte": Uint8,
|
||||
"int8": Int8,
|
||||
"uint8": Uint8,
|
||||
"int16": Int16,
|
||||
"uint16": Uint16,
|
||||
"int32": Int32,
|
||||
"uint32": Uint32,
|
||||
"int64": Int64,
|
||||
"uint64": Uint64,
|
||||
"float32": Float32,
|
||||
"float64": Float64,
|
||||
|
||||
"size_t": SizeType,
|
||||
"off_t": OffType,
|
||||
}
|
||||
|
||||
var typeNames = map[Type]string{
|
||||
CustomType: "Custom",
|
||||
}
|
||||
|
||||
func init() {
|
||||
for name, enum := range typeLookup {
|
||||
typeNames[enum] = name
|
||||
}
|
||||
}
|
||||
|
||||
type Size_t uint64
|
||||
type Off_t int64
|
||||
|
||||
var reflectTypeMap = map[reflect.Kind]Type{
|
||||
reflect.Bool: Bool,
|
||||
reflect.Int8: Int8,
|
||||
reflect.Int16: Int16,
|
||||
reflect.Int: Int32,
|
||||
reflect.Int32: Int32,
|
||||
reflect.Int64: Int64,
|
||||
reflect.Uint8: Uint8,
|
||||
reflect.Uint16: Uint16,
|
||||
reflect.Uint: Uint32,
|
||||
reflect.Uint32: Uint32,
|
||||
reflect.Uint64: Uint64,
|
||||
reflect.Float32: Float32,
|
||||
reflect.Float64: Float64,
|
||||
reflect.String: String,
|
||||
reflect.Struct: Struct,
|
||||
reflect.Ptr: Ptr,
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBadType(t *testing.T) {
|
||||
defer func() { recover() }()
|
||||
Type(-1).Size()
|
||||
t.Fatal("failed to panic for invalid Type.Size()")
|
||||
}
|
||||
|
||||
func TestTypeString(t *testing.T) {
|
||||
if Pad.String() != "pad" {
|
||||
t.Fatal("type string representation failed")
|
||||
}
|
||||
}
|
||||
|
||||
type sizeOffTest struct {
|
||||
Size Size_t
|
||||
Off Off_t
|
||||
}
|
||||
|
||||
func TestSizeOffTypes(t *testing.T) {
|
||||
bits := []int{8, 16, 32, 64}
|
||||
var buf bytes.Buffer
|
||||
test := &sizeOffTest{1, 2}
|
||||
for _, b := range bits {
|
||||
if err := PackWithOptions(&buf, test, &Options{PtrSize: b}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
reference := []byte{
|
||||
1, 2,
|
||||
0, 1, 0, 2,
|
||||
0, 0, 0, 1, 0, 0, 0, 2,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
|
||||
}
|
||||
if !bytes.Equal(reference, buf.Bytes()) {
|
||||
t.Errorf("reference != bytes: %v", reference, buf.Bytes())
|
||||
}
|
||||
reader := bytes.NewReader(buf.Bytes())
|
||||
for _, b := range bits {
|
||||
out := &sizeOffTest{}
|
||||
if err := UnpackWithOptions(reader, out, &Options{PtrSize: b}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.Size != 1 || out.Off != 2 {
|
||||
t.Errorf("Size_t/Off_t mismatch: {%d, %d}\n%v", out.Size, out.Off, buf.Bytes())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
language: go
|
||||
dist: trusty
|
||||
sudo: required
|
||||
notifications:
|
||||
email: false
|
||||
go:
|
||||
- 1.8
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install -y auditd
|
||||
script:
|
||||
- sudo service auditd stop
|
||||
- make test
|
|
@ -0,0 +1,363 @@
|
|||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. "Contributor"
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the terms of
|
||||
a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
|
||||
means a work that combines Covered Software with other material, in a
|
||||
separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether
|
||||
at the time of the initial grant or subsequently, any and all of the
|
||||
rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the License,
|
||||
by the making, using, selling, offering for sale, having made, import,
|
||||
or transfer of either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, "control" means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights to
|
||||
grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter the
|
||||
recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
||||
limitations of liability) contained within the Source Code Form of the
|
||||
Covered Software, except that You may alter any license notices to the
|
||||
extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute,
|
||||
judicial order, or regulation then You must: (a) comply with the terms of
|
||||
this License to the maximum extent possible; and (b) describe the
|
||||
limitations and the code they affect. Such description must be placed in a
|
||||
text file included with all distributions of the Covered Software under
|
||||
this License. Except to the extent prohibited by statute or regulation,
|
||||
such description must be sufficiently detailed for a recipient of ordinary
|
||||
skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
||||
basis, if such Contributor fails to notify You of the non-compliance by
|
||||
some reasonable means prior to 60 days after You have come back into
|
||||
compliance. Moreover, Your grants from a particular Contributor are
|
||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
||||
non-compliance by some reasonable means, this is the first time You have
|
||||
received notice of non-compliance with this License from such
|
||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
||||
of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an "as is" basis,
|
||||
without warranty of any kind, either expressed, implied, or statutory,
|
||||
including, without limitation, warranties that the Covered Software is free
|
||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
||||
The entire risk as to the quality and performance of the Covered Software
|
||||
is with You. Should any Covered Software prove defective in any respect,
|
||||
You (not any Contributor) assume the cost of any necessary servicing,
|
||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
||||
part of this License. No use of any Covered Software is authorized under
|
||||
this License except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from
|
||||
such party's negligence to the extent applicable law prohibits such
|
||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
||||
incidental or consequential damages, so this exclusion and limitation may
|
||||
not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts
|
||||
of a jurisdiction where the defendant maintains its principal place of
|
||||
business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
||||
in this Section shall prevent a party's ability to bring cross-claims or
|
||||
counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides that
|
||||
the language of a contract shall be construed against the drafter shall not
|
||||
be used to construe this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses If You choose to distribute Source Code Form that is
|
||||
Incompatible With Secondary Licenses under the terms of this version of
|
||||
the License, the notice described in Exhibit B of this License must be
|
||||
attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file,
|
||||
then You may include the notice in a location (such as a LICENSE file in a
|
||||
relevant directory) where a recipient would be likely to look for such a
|
||||
notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
|
||||
This Source Code Form is "Incompatible
|
||||
With Secondary Licenses", as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
GOBIN := $(shell which go)
|
||||
GO := GO15VENDOREXPERIMENT=1 $(GOBIN)
|
||||
BUILDPRE := auditconstant_string.go
|
||||
|
||||
test: $(BUILDPRE)
|
||||
sudo $(GO) test -v -bench=. -covermode=count -coverprofile=coverage.out
|
||||
|
||||
profile: $(BUILDPRE)
|
||||
sudo $(GO) test -v -cpuprofile cpu.prof -memprofile mem.prof -bench=.
|
||||
|
||||
auditconstant_string.go: audit_constant.go
|
||||
$(GO) get golang.org/x/tools/cmd/stringer
|
||||
$(GO) generate
|
||||
|
||||
clean:
|
||||
rm -f $(BUILDPRE)
|
|
@ -0,0 +1,108 @@
|
|||
# libaudit in Go
|
||||
|
||||
libaudit-go is a go package for interfacing with Linux audit.
|
||||
|
||||
[![Build Status](https://travis-ci.org/mozilla/libaudit-go.svg?branch=master)](https://travis-ci.org/mozilla/libaudit-go)
|
||||
[![Go Report Card](https://goreportcard.com/badge/mozilla/libaudit-go "Go Report Card")](https://goreportcard.com/report/mozilla/libaudit-go)
|
||||
|
||||
libaudit-go is a pure Go client library for interfacing with the Linux auditing framework. It provides functions
|
||||
to interact with the auditing subsystems over Netlink, including controlling the rule set and obtaining/interpreting
|
||||
incoming audit events.
|
||||
|
||||
libaudit-go can be used to build go applications which perform tasks similar to the standard Linux auditing daemon
|
||||
`auditd`.
|
||||
|
||||
To get started see package documentation at [godoc](https://godoc.org/github.com/mozilla/libaudit-go).
|
||||
|
||||
For a simple example of usage, see the [auditprint](./auditprint/) tool included in this repository.
|
||||
|
||||
```bash
|
||||
sudo service stop auditd
|
||||
go get -u github.com/mozilla/libaudit-go
|
||||
cd $GOPATH/src/github.com/mozilla/libaudit-go
|
||||
go install github.com/mozilla/libaudit-go/auditprint
|
||||
sudo $GOPATH/bin/auditprint testdata/rules.json
|
||||
```
|
||||
|
||||
Some key functions are discussed in the overview section below.
|
||||
|
||||
## Overview
|
||||
|
||||
### General
|
||||
|
||||
##### NewNetlinkConnection
|
||||
|
||||
To use libaudit-go programs will need to initialize a new Netlink connection. `NewNetlinkConnection` can be used
|
||||
to allocate a new `NetlinkConnection` type which can then be passed to other functions in the library.
|
||||
|
||||
```go
|
||||
s, err := libaudit.NewNetlinkConnection()
|
||||
if err != nil {
|
||||
fmt.Printf("NewNetlinkConnection: %v\n", err)
|
||||
}
|
||||
defer s.Close()
|
||||
```
|
||||
|
||||
`NetlinkConnection` provides a `Send` and `Receive` method to send and receive Netlink messages to the kernel,
|
||||
however generally applications will use the various other functions included in libaudit-go and do not need to
|
||||
call these functions directly.
|
||||
|
||||
##### GetAuditEvents
|
||||
|
||||
GetAuditEvents starts an audit event monitor in a go-routine and returns. Programs can call this function and
|
||||
specify a callback function as an argument. When the audit event monitor receives a new event, this callback
|
||||
function will be called with the parsed `AuditEvent` as an argument.
|
||||
|
||||
```go
|
||||
|
||||
func myCallback(msg *libaudit.AuditEvent, err error) {
|
||||
if err != nil {
|
||||
// An error occurred getting or parsing the audit event
|
||||
return
|
||||
}
|
||||
// Print the fields
|
||||
fmt.Println(msg.Data)
|
||||
// Print the raw event
|
||||
fmt.Println(msg.Raw)
|
||||
}
|
||||
|
||||
libaudit.GetAuditEvents(s, myCallback)
|
||||
```
|
||||
|
||||
##### GetRawAuditEvents
|
||||
|
||||
`GetRawAuditEvents` behaves in a similar manner to `GetAuditEvents`, however programs can use this function
|
||||
to instead just retrieve raw audit events from the kernel as a string, instead of having libaudit-go parse
|
||||
these audit events into an `AuditEvent` type.
|
||||
|
||||
### Audit Rules
|
||||
|
||||
Audit rules can be loaded into the kernel using libaudit-go, however the format differs from the common rule
|
||||
set used by userspace tools such as auditctl/auditd.
|
||||
|
||||
libaudit-go rulesets are defined as a JSON document. See [rules.json](./testdata/rules.json) as an example.
|
||||
The libaudit-go type which stores the rule set is `AuditRules`.
|
||||
|
||||
##### SetRules
|
||||
|
||||
`SetRules` can be used to load an audit rule set into the kernel. The function takes a marshalled `AuditRules`
|
||||
type as an argument (slice of bytes), and converts the JSON based rule set into a set of audit rules suitable
|
||||
for submission to the kernel.
|
||||
|
||||
The function then makes the required Netlink calls to clear the existing rule set and load the new rules.
|
||||
|
||||
```go
|
||||
// Load all rules from a file
|
||||
content, err := ioutil.ReadFile("audit.rules.json")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Set audit rules
|
||||
err = libaudit.SetRules(s, content)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
```
|
474
vendor/github.com/mozilla/libaudit-go/audit_constant.go
сгенерированный
поставляемый
Normal file
474
vendor/github.com/mozilla/libaudit-go/audit_constant.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,474 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
// audit_constants.go contains constants used within libaudit, sourced from linux/audit.h
|
||||
// (from the Linux kernel) and from libaudit.h in the audit userspace source code.
|
||||
|
||||
// Code generated using various audit headers, DO NOT EDIT.
|
||||
|
||||
const (
|
||||
AUDIT_STATUS_SIZE = 40 // Size of auditStatus
|
||||
)
|
||||
|
||||
const (
|
||||
MAX_AUDIT_MESSAGE_LENGTH = 8970
|
||||
AUDIT_MAX_FIELDS = 64
|
||||
AUDIT_BITMASK_SIZE = 64
|
||||
//Rule Flags
|
||||
AUDIT_FILTER_USER = 0x00 /* Apply rule to user-generated messages */
|
||||
AUDIT_FILTER_TASK = 0x01 /* Apply rule at task creation (not syscall) */
|
||||
AUDIT_FILTER_ENTRY = 0x02 /* Apply rule at syscall entry */
|
||||
AUDIT_FILTER_WATCH = 0x03 /* Apply rule to file system watches */
|
||||
AUDIT_FILTER_EXIT = 0x04 /* Apply rule at syscall exit */
|
||||
AUDIT_FILTER_TYPE = 0x05 /* Apply rule at audit_log_start */
|
||||
/* These are used in filter control */
|
||||
AUDIT_FILTER_MASK = 0x07 /* Mask to get actual filter */
|
||||
AUDIT_FILTER_UNSET = 0x80 /* This value means filter is unset */
|
||||
|
||||
/* Rule actions */
|
||||
AUDIT_NEVER = 0 /* Do not build context if rule matches */
|
||||
AUDIT_POSSIBLE = 1 /* Build context if rule matches */
|
||||
AUDIT_ALWAYS = 2 /* Generate audit record if rule matches */
|
||||
|
||||
/* Rule fields */
|
||||
/* These are useful when checking the
|
||||
* task structure at task creation time
|
||||
* (AUDIT_PER_TASK). */
|
||||
AUDIT_PID = 0
|
||||
AUDIT_UID = 1
|
||||
AUDIT_EUID = 2
|
||||
AUDIT_SUID = 3
|
||||
AUDIT_FSUID = 4
|
||||
AUDIT_GID = 5
|
||||
AUDIT_EGID = 6
|
||||
AUDIT_SGID = 7
|
||||
AUDIT_FSGID = 8
|
||||
AUDIT_LOGINUID = 9
|
||||
AUDIT_OBJ_GID = 110
|
||||
AUDIT_OBJ_UID = 109
|
||||
AUDIT_EXIT = 103
|
||||
AUDIT_PERS = 10
|
||||
AUDIT_FILTER_EXCLUDE = 0x05
|
||||
AUDIT_ARCH = 11
|
||||
PATH_MAX = 4096
|
||||
AUDIT_MSGTYPE = 12
|
||||
AUDIT_MAX_KEY_LEN = 256
|
||||
AUDIT_PERM = 106
|
||||
AUDIT_FILTERKEY = 210
|
||||
AUDIT_SUBJ_USER = 13 /* security label user */
|
||||
AUDIT_SUBJ_ROLE = 14 /* security label role */
|
||||
AUDIT_SUBJ_TYPE = 15 /* security label type */
|
||||
AUDIT_SUBJ_SEN = 16 /* security label sensitivity label */
|
||||
AUDIT_SUBJ_CLR = 17 /* security label clearance label */
|
||||
AUDIT_PPID = 18
|
||||
AUDIT_OBJ_USER = 19
|
||||
AUDIT_OBJ_ROLE = 20
|
||||
AUDIT_OBJ_TYPE = 21
|
||||
AUDIT_WATCH = 105
|
||||
AUDIT_DIR = 107
|
||||
AUDIT_OBJ_LEV_LOW = 22
|
||||
AUDIT_OBJ_LEV_HIGH = 23
|
||||
AUDIT_LOGINUID_SET = 24
|
||||
AUDIT_DEVMAJOR = 100
|
||||
AUDIT_DEVMINOR = 101
|
||||
AUDIT_INODE = 102
|
||||
AUDIT_SUCCESS = 104
|
||||
AUDIT_FIELD_COMPARE = 111
|
||||
AUDIT_EXE = 112
|
||||
AUDIT_PERM_EXEC = 1
|
||||
AUDIT_PERM_WRITE = 2
|
||||
AUDIT_PERM_READ = 4
|
||||
AUDIT_PERM_ATTR = 8
|
||||
AUDIT_FILETYPE = 108
|
||||
AUDIT_ARG0 = 200
|
||||
AUDIT_ARG1 = (AUDIT_ARG0 + 1)
|
||||
AUDIT_ARG2 = (AUDIT_ARG0 + 2)
|
||||
AUDIT_ARG3 = (AUDIT_ARG0 + 3)
|
||||
AUDIT_BIT_MASK = 0x08000000
|
||||
AUDIT_LESS_THAN = 0x10000000
|
||||
AUDIT_GREATER_THAN = 0x20000000
|
||||
AUDIT_NOT_EQUAL = 0x30000000
|
||||
AUDIT_EQUAL = 0x40000000
|
||||
AUDIT_BIT_TEST = (AUDIT_BIT_MASK | AUDIT_EQUAL)
|
||||
AUDIT_LESS_THAN_OR_EQUAL = (AUDIT_LESS_THAN | AUDIT_EQUAL)
|
||||
AUDIT_GREATER_THAN_OR_EQUAL = (AUDIT_GREATER_THAN | AUDIT_EQUAL)
|
||||
AUDIT_OPERATORS = (AUDIT_EQUAL | AUDIT_NOT_EQUAL | AUDIT_BIT_MASK)
|
||||
/* Status symbols */
|
||||
/* Mask values */
|
||||
AUDIT_STATUS_ENABLED = 0x0001
|
||||
AUDIT_STATUS_FAILURE = 0x0002
|
||||
AUDIT_STATUS_PID = 0x0004
|
||||
AUDIT_STATUS_RATE_LIMIT = 0x0008
|
||||
AUDIT_STATUS_BACKLOG_LIMIT = 0x0010
|
||||
/* Failure-to-log actions */
|
||||
AUDIT_FAIL_SILENT = 0
|
||||
AUDIT_FAIL_PRINTK = 1
|
||||
AUDIT_FAIL_PANIC = 2
|
||||
|
||||
/* distinguish syscall tables */
|
||||
__AUDIT_ARCH_64BIT = 0x80000000
|
||||
__AUDIT_ARCH_LE = 0x40000000
|
||||
AUDIT_ARCH_ALPHA = (EM_ALPHA | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_ARM = (EM_ARM | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_ARMEB = (EM_ARM)
|
||||
AUDIT_ARCH_CRIS = (EM_CRIS | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_FRV = (EM_FRV)
|
||||
AUDIT_ARCH_I386 = (EM_386 | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_IA64 = (EM_IA_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_M32R = (EM_M32R)
|
||||
AUDIT_ARCH_M68K = (EM_68K)
|
||||
AUDIT_ARCH_MIPS = (EM_MIPS)
|
||||
AUDIT_ARCH_MIPSEL = (EM_MIPS | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_MIPS64 = (EM_MIPS | __AUDIT_ARCH_64BIT)
|
||||
AUDIT_ARCH_MIPSEL64 = (EM_MIPS | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
|
||||
// AUDIT_ARCH_OPENRISC = (EM_OPENRISC)
|
||||
// AUDIT_ARCH_PARISC = (EM_PARISC)
|
||||
// AUDIT_ARCH_PARISC64 = (EM_PARISC | __AUDIT_ARCH_64BIT)
|
||||
AUDIT_ARCH_PPC = (EM_PPC)
|
||||
AUDIT_ARCH_PPC64 = (EM_PPC64 | __AUDIT_ARCH_64BIT)
|
||||
AUDIT_ARCH_S390 = (EM_S390)
|
||||
AUDIT_ARCH_S390X = (EM_S390 | __AUDIT_ARCH_64BIT)
|
||||
AUDIT_ARCH_SH = (EM_SH)
|
||||
AUDIT_ARCH_SHEL = (EM_SH | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_SH64 = (EM_SH | __AUDIT_ARCH_64BIT)
|
||||
AUDIT_ARCH_SHEL64 = (EM_SH | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
|
||||
AUDIT_ARCH_SPARC = (EM_SPARC)
|
||||
AUDIT_ARCH_SPARC64 = (EM_SPARCV9 | __AUDIT_ARCH_64BIT)
|
||||
AUDIT_ARCH_X86_64 = (EM_X86_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
|
||||
///Temporary Solution need to add linux/elf-em.h
|
||||
EM_NONE = 0
|
||||
EM_M32 = 1
|
||||
EM_SPARC = 2
|
||||
EM_386 = 3
|
||||
EM_68K = 4
|
||||
EM_88K = 5
|
||||
EM_486 = 6 /* Perhaps disused */
|
||||
EM_860 = 7
|
||||
EM_MIPS = 8 /* MIPS R3000 (officially, big-endian only) */
|
||||
/* Next two are historical and binaries and
|
||||
modules of these types will be rejected by
|
||||
Linux. */
|
||||
EM_MIPS_RS3_LE = 10 /* MIPS R3000 little-endian */
|
||||
EM_MIPS_RS4_BE = 10 /* MIPS R4000 big-endian */
|
||||
|
||||
EM_PARISC = 15 /* HPPA */
|
||||
EM_SPARC32PLUS = 18 /* Sun's "v8plus" */
|
||||
EM_PPC = 20 /* PowerPC */
|
||||
EM_PPC64 = 21 /* PowerPC64 */
|
||||
EM_SPU = 23 /* Cell BE SPU */
|
||||
EM_ARM = 40 /* ARM 32 bit */
|
||||
EM_SH = 42 /* SuperH */
|
||||
EM_SPARCV9 = 43 /* SPARC v9 64-bit */
|
||||
EM_IA_64 = 50 /* HP/Intel IA-64 */
|
||||
EM_X86_64 = 62 /* AMD x86-64 */
|
||||
EM_S390 = 22 /* IBM S/390 */
|
||||
EM_CRIS = 76 /* Axis Communications 32-bit embedded processor */
|
||||
EM_V850 = 87 /* NEC v850 */
|
||||
EM_M32R = 88 /* Renesas M32R */
|
||||
EM_MN10300 = 89 /* Panasonic/MEI MN10300, AM33 */
|
||||
EM_BLACKFIN = 106 /* ADI Blackfin Processor */
|
||||
EM_TI_C6000 = 140 /* TI C6X DSPs */
|
||||
EM_AARCH64 = 183 /* ARM 64 bit */
|
||||
EM_FRV = 0x5441 /* Fujitsu FR-V */
|
||||
EM_AVR32 = 0x18ad /* Atmel AVR32 */
|
||||
|
||||
/*
|
||||
* This is an interim value that we will use until the committee comes
|
||||
* up with a final number.
|
||||
*/
|
||||
EM_ALPHA = 0x9026
|
||||
|
||||
/* Bogus old v850 magic number, used by old tools. */
|
||||
EM_CYGNUS_V850 = 0x9080
|
||||
/* Bogus old m32r magic number, used by old tools. */
|
||||
EM_CYGNUS_M32R = 0x9041
|
||||
/* This is the old interim value for S/390 architecture */
|
||||
EM_S390_OLD = 0xA390
|
||||
/* Also Panasonic/MEI MN10300, AM33 */
|
||||
EM_CYGNUS_MN10300 = 0xbeef
|
||||
//AUDIT_ARCH determination purpose
|
||||
_UTSNAME_LENGTH = 65
|
||||
_UTSNAME_DOMAIN_LENGTH = _UTSNAME_LENGTH
|
||||
_UTSNAME_NODENAME_LENGTH = _UTSNAME_DOMAIN_LENGTH
|
||||
)
|
||||
|
||||
/* Audit message types as of 2.6.29 kernel:
|
||||
* 1000 - 1099 are for commanding the audit system
|
||||
* 1100 - 1199 user space trusted application messages
|
||||
* 1200 - 1299 messages internal to the audit daemon
|
||||
* 1300 - 1399 audit event messages
|
||||
* 1400 - 1499 kernel SE Linux use
|
||||
* 1500 - 1599 AppArmor events
|
||||
* 1600 - 1699 kernel crypto events
|
||||
* 1700 - 1799 kernel anomaly records
|
||||
* 1800 - 1899 kernel integrity labels and related events
|
||||
* 1800 - 1999 future kernel use
|
||||
* 2001 - 2099 unused (kernel)
|
||||
* 2100 - 2199 user space anomaly records
|
||||
* 2200 - 2299 user space actions taken in response to anomalies
|
||||
* 2300 - 2399 user space generated LSPP events
|
||||
* 2400 - 2499 user space crypto events
|
||||
* 2500 - 2599 user space virtualization management events
|
||||
* 2600 - 2999 future user space (maybe integrity labels and related events)
|
||||
*/
|
||||
|
||||
//go:generate stringer -type=auditConstant audit_constant.go
|
||||
type auditConstant uint16
|
||||
|
||||
const (
|
||||
AUDIT_GET auditConstant = 1000 /* Get status */
|
||||
AUDIT_SET auditConstant = 1001 /* Set status (enable/disable/auditd) */
|
||||
AUDIT_LIST auditConstant = 1002 /* List syscall rules -- deprecated */
|
||||
AUDIT_ADD auditConstant = 1003 /* Add syscall rule -- deprecated */
|
||||
AUDIT_DEL auditConstant = 1004 /* Delete syscall rule -- deprecated */
|
||||
AUDIT_USER auditConstant = 1005 /* Message from userspace -- deprecated */
|
||||
AUDIT_LOGIN auditConstant = 1006 /* Define the login id and information */
|
||||
AUDIT_WATCH_INS auditConstant = 1007 /* Insert file/dir watch entry */
|
||||
AUDIT_WATCH_REM auditConstant = 1008 /* Remove file/dir watch entry */
|
||||
AUDIT_WATCH_LIST auditConstant = 1009 /* List all file/dir watches */
|
||||
AUDIT_SIGNAL_INFO auditConstant = 1010 /* Get info about sender of signal to auditd */
|
||||
AUDIT_ADD_RULE auditConstant = 1011 /* Add syscall filtering rule */
|
||||
AUDIT_DEL_RULE auditConstant = 1012 /* Delete syscall filtering rule */
|
||||
AUDIT_LIST_RULES auditConstant = 1013 /* List syscall filtering rules */
|
||||
AUDIT_TRIM auditConstant = 1014 /* Trim junk from watched tree */
|
||||
AUDIT_MAKE_EQUIV auditConstant = 1015 /* Append to watched tree */
|
||||
AUDIT_TTY_GET auditConstant = 1016 /* Get TTY auditing status */
|
||||
AUDIT_TTY_SET auditConstant = 1017 /* Set TTY auditing status */
|
||||
AUDIT_SET_FEATURE auditConstant = 1018 /* Turn an audit feature on or off */
|
||||
AUDIT_GET_FEATURE auditConstant = 1019 /* Get which features are enabled */
|
||||
|
||||
AUDIT_FIRST_USER_MSG auditConstant = 1100 /* First user space message */
|
||||
AUDIT_LAST_USER_MSG auditConstant = 1199 /* Last user space message */
|
||||
AUDIT_USER_AUTH auditConstant = 1100 /* User space authentication */
|
||||
AUDIT_USER_ACCT auditConstant = 1101 /* User space acct change */
|
||||
AUDIT_USER_MGMT auditConstant = 1102 /* User space acct management */
|
||||
AUDIT_CRED_ACQ auditConstant = 1103 /* User space credential acquired */
|
||||
AUDIT_CRED_DISP auditConstant = 1104 /* User space credential disposed */
|
||||
AUDIT_USER_START auditConstant = 1105 /* User space session start */
|
||||
AUDIT_USER_END auditConstant = 1106 /* User space session end */
|
||||
AUDIT_USER_AVC auditConstant = 1107 /* User space avc message */
|
||||
AUDIT_USER_CHAUTHTOK auditConstant = 1108 /* User space acct attr changed */
|
||||
AUDIT_USER_ERR auditConstant = 1109 /* User space acct state err */
|
||||
AUDIT_CRED_REFR auditConstant = 1110 /* User space credential refreshed */
|
||||
AUDIT_USYS_CONFIG auditConstant = 1111 /* User space system config change */
|
||||
AUDIT_USER_LOGIN auditConstant = 1112 /* User space user has logged in */
|
||||
AUDIT_USER_LOGOUT auditConstant = 1113 /* User space user has logged out */
|
||||
AUDIT_ADD_USER auditConstant = 1114 /* User space user account added */
|
||||
AUDIT_DEL_USER auditConstant = 1115 /* User space user account deleted */
|
||||
AUDIT_ADD_GROUP auditConstant = 1116 /* User space group added */
|
||||
AUDIT_DEL_GROUP auditConstant = 1117 /* User space group deleted */
|
||||
AUDIT_DAC_CHECK auditConstant = 1118 /* User space DAC check results */
|
||||
AUDIT_CHGRP_ID auditConstant = 1119 /* User space group ID changed */
|
||||
AUDIT_TEST auditConstant = 1120 /* Used for test success messages */
|
||||
AUDIT_TRUSTED_APP auditConstant = 1121 /* Trusted app msg - freestyle text */
|
||||
AUDIT_USER_SELINUX_ERR auditConstant = 1122 /* SE Linux user space error */
|
||||
AUDIT_USER_CMD auditConstant = 1123 /* User shell command and args */
|
||||
AUDIT_USER_TTY auditConstant = 1124 /* Non-ICANON TTY input meaning */
|
||||
AUDIT_CHUSER_ID auditConstant = 1125 /* Changed user ID supplemental data */
|
||||
AUDIT_GRP_AUTH auditConstant = 1126 /* Authentication for group password */
|
||||
AUDIT_SYSTEM_BOOT auditConstant = 1127 /* System boot */
|
||||
AUDIT_SYSTEM_SHUTDOWN auditConstant = 1128 /* System shutdown */
|
||||
AUDIT_SYSTEM_RUNLEVEL auditConstant = 1129 /* System runlevel change */
|
||||
AUDIT_SERVICE_START auditConstant = 1130 /* Service (daemon) start */
|
||||
AUDIT_SERVICE_STOP auditConstant = 1131 /* Service (daemon) stop */
|
||||
AUDIT_GRP_MGMT auditConstant = 1132 /* Group account attr was modified */
|
||||
AUDIT_GRP_CHAUTHTOK auditConstant = 1133 /* Group acct password or pin changed */
|
||||
AUDIT_MAC_CHECK auditConstant = 1134 /* User space MAC decision results */
|
||||
AUDIT_ACCT_LOCK auditConstant = 1135 /* User's account locked by admin */
|
||||
AUDIT_ACCT_UNLOCK auditConstant = 1136 /* User's account unlocked by admin */
|
||||
|
||||
AUDIT_FIRST_DAEMON auditConstant = 1200
|
||||
AUDIT_LAST_DAEMON auditConstant = 1299
|
||||
AUDIT_DAEMON_CONFIG auditConstant = 1203 /* Daemon config change */
|
||||
AUDIT_DAEMON_RECONFIG auditConstant = 1204 /* Auditd should reconfigure */
|
||||
AUDIT_DAEMON_ROTATE auditConstant = 1205 /* Auditd should rotate logs */
|
||||
AUDIT_DAEMON_RESUME auditConstant = 1206 /* Auditd should resume logging */
|
||||
AUDIT_DAEMON_ACCEPT auditConstant = 1207 /* Auditd accepted remote connection */
|
||||
AUDIT_DAEMON_CLOSE auditConstant = 1208 /* Auditd closed remote connection */
|
||||
|
||||
AUDIT_SYSCALL auditConstant = 1300 /* Syscall event */
|
||||
/* AUDIT_FS_WATCH auditConstant = 1301 * Deprecated */
|
||||
AUDIT_PATH auditConstant = 1302 /* Filename path information */
|
||||
AUDIT_IPC auditConstant = 1303 /* IPC record */
|
||||
AUDIT_SOCKETCALL auditConstant = 1304 /* sys_socketcall arguments */
|
||||
AUDIT_CONFIG_CHANGE auditConstant = 1305 /* Audit system configuration change */
|
||||
AUDIT_SOCKADDR auditConstant = 1306 /* sockaddr copied as syscall arg */
|
||||
AUDIT_CWD auditConstant = 1307 /* Current working directory */
|
||||
AUDIT_EXECVE auditConstant = 1309 /* execve arguments */
|
||||
AUDIT_IPC_SET_PERM auditConstant = 1311 /* IPC new permissions record type */
|
||||
AUDIT_MQ_OPEN auditConstant = 1312 /* POSIX MQ open record type */
|
||||
AUDIT_MQ_SENDRECV auditConstant = 1313 /* POSIX MQ send/receive record type */
|
||||
AUDIT_MQ_NOTIFY auditConstant = 1314 /* POSIX MQ notify record type */
|
||||
AUDIT_MQ_GETSETATTR auditConstant = 1315 /* POSIX MQ get/set attribute record type */
|
||||
AUDIT_KERNEL_OTHER auditConstant = 1316 /* For use by 3rd party modules */
|
||||
AUDIT_FD_PAIR auditConstant = 1317 /* audit record for pipe/socketpair */
|
||||
AUDIT_OBJ_PID auditConstant = 1318 /* ptrace target */
|
||||
AUDIT_TTY auditConstant = 1319 /* Input on an administrative TTY */
|
||||
AUDIT_EOE auditConstant = 1320 /* End of multi-record event */
|
||||
AUDIT_BPRM_FCAPS auditConstant = 1321 /* Information about fcaps increasing perms */
|
||||
AUDIT_CAPSET auditConstant = 1322 /* Record showing argument to sys_capset */
|
||||
AUDIT_MMAP auditConstant = 1323 /* Record showing descriptor and flags in mmap */
|
||||
AUDIT_NETFILTER_PKT auditConstant = 1324 /* Packets traversing netfilter chains */
|
||||
AUDIT_NETFILTER_CFG auditConstant = 1325 /* Netfilter chain modifications */
|
||||
AUDIT_SECCOMP auditConstant = 1326 /* Secure Computing event */
|
||||
AUDIT_PROCTITLE auditConstant = 1327 /* Proctitle emit event */
|
||||
AUDIT_FEATURE_CHANGE auditConstant = 1328 /* audit log listing feature changes */
|
||||
|
||||
/* AUDIT_FIRST_EVENT 1300 */ //TODO: libaudit define this as AUDIT_FIRST_EVENT but audit.h differently.
|
||||
AUDIT_LAST_EVENT auditConstant = 1399
|
||||
|
||||
/* AUDIT_FIRST_SELINUX 1400 */ // TODO: libaudit define this as AUDIT_FIRST_SELINUX but audit.h as AUDIT_AVC
|
||||
AUDIT_AVC auditConstant = 1400 /* SE Linux avc denial or grant */
|
||||
AUDIT_SELINUX_ERR auditConstant = 1401 /* internal SE Linux Errors */
|
||||
AUDIT_AVC_PATH auditConstant = 1402 /* dentry, vfsmount pair from avc */
|
||||
AUDIT_MAC_POLICY_LOAD auditConstant = 1403 /* Policy file load */
|
||||
AUDIT_MAC_STATUS auditConstant = 1404 /* Changed enforcing,permissive,off */
|
||||
AUDIT_MAC_CONFIG_CHANGE auditConstant = 1405 /* Changes to booleans */
|
||||
AUDIT_MAC_UNLBL_ALLOW auditConstant = 1406 /* NetLabel: allow unlabeled traffic */
|
||||
AUDIT_MAC_CIPSOV4_ADD auditConstant = 1407 /* NetLabel: add CIPSOv4 DOI entry */
|
||||
AUDIT_MAC_CIPSOV4_DEL auditConstant = 1408 /* NetLabel: del CIPSOv4 DOI entry */
|
||||
AUDIT_MAC_MAP_ADD auditConstant = 1409 /* NetLabel: add LSM domain mapping */
|
||||
AUDIT_MAC_MAP_DEL auditConstant = 1410 /* NetLabel: del LSM domain mapping */
|
||||
AUDIT_MAC_IPSEC_ADDSA auditConstant = 1411 /* Not used */
|
||||
AUDIT_MAC_IPSEC_DELSA auditConstant = 1412 /* Not used */
|
||||
AUDIT_MAC_IPSEC_ADDSPD auditConstant = 1413 /* Not used */
|
||||
AUDIT_MAC_IPSEC_DELSPD auditConstant = 1414 /* Not used */
|
||||
AUDIT_MAC_IPSEC_EVENT auditConstant = 1415 /* Audit an IPSec event */
|
||||
AUDIT_MAC_UNLBL_STCADD auditConstant = 1416 /* NetLabel: add a static label */
|
||||
AUDIT_MAC_UNLBL_STCDEL auditConstant = 1417 /* NetLabel: del a static label */
|
||||
AUDIT_LAST_SELINUX auditConstant = 1499
|
||||
|
||||
AUDIT_FIRST_APPARMOR auditConstant = 1500
|
||||
AUDIT_LAST_APPARMOR auditConstant = 1599
|
||||
|
||||
AUDIT_AA auditConstant = 1500 /* Not upstream yet*/
|
||||
AUDIT_APPARMOR_AUDIT auditConstant = 1501
|
||||
AUDIT_APPARMOR_ALLOWED auditConstant = 1502
|
||||
AUDIT_APPARMOR_DENIED auditConstant = 1503
|
||||
AUDIT_APPARMOR_HT auditConstant = 1504
|
||||
AUDIT_APPARMOR_STATUS auditConstant = 1505
|
||||
AUDIT_APPARMOR_ERROR auditConstant = 1506
|
||||
|
||||
AUDIT_FIRST_KERN_CRYPTO_MSG auditConstant = 1600
|
||||
AUDIT_LAST_KERN_CRYPTO_MSG auditConstant = 1699
|
||||
|
||||
// AUDIT_FIRST_KERN_ANOM_MSG auditConstant = 1700
|
||||
AUDIT_LAST_KERN_ANOM_MSG auditConstant = 1799
|
||||
AUDIT_ANOM_PROMISCUOUS auditConstant = 1700 /* Device changed promiscuous mode */
|
||||
AUDIT_ANOM_ABEND auditConstant = 1701 /* Process ended abnormally */
|
||||
AUDIT_ANOM_LINK auditConstant = 1702 /* Suspicious use of file links */
|
||||
|
||||
AUDIT_INTEGRITY_FIRST_MSG auditConstant = 1800
|
||||
AUDIT_TINTEGRITY_LAST_MSG auditConstant = 1899
|
||||
|
||||
AUDIT_INTEGRITY_DATA auditConstant = 1800 /* Data integrity verification */
|
||||
AUDIT_INTEGRITY_METADATA auditConstant = 1801 // Metadata integrity verification
|
||||
AUDIT_INTEGRITY_STATUS auditConstant = 1802 /* integrity enable status */
|
||||
AUDIT_INTEGRITY_HASH auditConstant = 1803 /* integrity HASH type */
|
||||
AUDIT_INTEGRITY_PCR auditConstant = 1804 /* PCR invalidation msgs */
|
||||
AUDIT_INTEGRITY_RULE auditConstant = 1805 /* Policy rule */
|
||||
AUDIT_KERNEL auditConstant = 2000 /* Asynchronous audit record. NOT A REQUEST. */
|
||||
|
||||
AUDIT_FIRST_ANOM_MSG auditConstant = 2100
|
||||
AUDIT_LAST_ANOM_MSG auditConstant = 2199
|
||||
AUDIT_ANOM_LOGIN_FAILURES auditConstant = 2100 // Failed login limit reached
|
||||
AUDIT_ANOM_LOGIN_TIME auditConstant = 2101 // Login attempted at bad time
|
||||
AUDIT_ANOM_LOGIN_SESSIONS auditConstant = 2102 // Max concurrent sessions reached
|
||||
AUDIT_ANOM_LOGIN_ACCT auditConstant = 2103 // Login attempted to watched acct
|
||||
AUDIT_ANOM_LOGIN_LOCATION auditConstant = 2104 // Login from forbidden location
|
||||
AUDIT_ANOM_MAX_DAC auditConstant = 2105 // Max DAC failures reached
|
||||
AUDIT_ANOM_MAX_MAC auditConstant = 2106 // Max MAC failures reached
|
||||
AUDIT_ANOM_AMTU_FAIL auditConstant = 2107 // AMTU failure
|
||||
AUDIT_ANOM_RBAC_FAIL auditConstant = 2108 // RBAC self test failure
|
||||
AUDIT_ANOM_RBAC_INTEGRITY_FAIL auditConstant = 2109 // RBAC file Tegrity failure
|
||||
AUDIT_ANOM_CRYPTO_FAIL auditConstant = 2110 // Crypto system test failure
|
||||
AUDIT_ANOM_ACCESS_FS auditConstant = 2111 // Access of file or dir
|
||||
AUDIT_ANOM_EXEC auditConstant = 2112 // Execution of file
|
||||
AUDIT_ANOM_MK_EXEC auditConstant = 2113 // Make an executable
|
||||
AUDIT_ANOM_ADD_ACCT auditConstant = 2114 // Adding an acct
|
||||
AUDIT_ANOM_DEL_ACCT auditConstant = 2115 // Deleting an acct
|
||||
AUDIT_ANOM_MOD_ACCT auditConstant = 2116 // Changing an acct
|
||||
AUDIT_ANOM_ROOT_TRANS auditConstant = 2117 // User became root
|
||||
|
||||
AUDIT_FIRST_ANOM_RESP auditConstant = 2200
|
||||
AUDIT_LAST_ANOM_RESP auditConstant = 2299
|
||||
AUDIT_RESP_ANOMALY auditConstant = 2200 /* Anomaly not reacted to */
|
||||
AUDIT_RESP_ALERT auditConstant = 2201 /* Alert email was sent */
|
||||
AUDIT_RESP_KILL_PROC auditConstant = 2202 /* Kill program */
|
||||
AUDIT_RESP_TERM_ACCESS auditConstant = 2203 /* Terminate session */
|
||||
AUDIT_RESP_ACCT_REMOTE auditConstant = 2204 /* Acct locked from remote access*/
|
||||
AUDIT_RESP_ACCT_LOCK_TIMED auditConstant = 2205 /* User acct locked for time */
|
||||
AUDIT_RESP_ACCT_UNLOCK_TIMED auditConstant = 2206 /* User acct unlocked from time */
|
||||
AUDIT_RESP_ACCT_LOCK auditConstant = 2207 /* User acct was locked */
|
||||
AUDIT_RESP_TERM_LOCK auditConstant = 2208 /* Terminal was locked */
|
||||
AUDIT_RESP_SEBOOL auditConstant = 2209 /* Set an SE Linux boolean */
|
||||
AUDIT_RESP_EXEC auditConstant = 2210 /* Execute a script */
|
||||
AUDIT_RESP_SINGLE auditConstant = 2211 /* Go to single user mode */
|
||||
AUDIT_RESP_HALT auditConstant = 2212 /* take the system down */
|
||||
|
||||
AUDIT_FIRST_USER_LSPP_MSG auditConstant = 2300
|
||||
AUDIT_LAST_USER_LSPP_MSG auditConstant = 2399
|
||||
AUDIT_USER_ROLE_CHANGE auditConstant = 2300 /* User changed to a new role */
|
||||
AUDIT_ROLE_ASSIGN auditConstant = 2301 /* Admin assigned user to role */
|
||||
AUDIT_ROLE_REMOVE auditConstant = 2302 /* Admin removed user from role */
|
||||
AUDIT_LABEL_OVERRIDE auditConstant = 2303 /* Admin is overriding a label */
|
||||
AUDIT_LABEL_LEVEL_CHANGE auditConstant = 2304 /* Object's level was changed */
|
||||
AUDIT_USER_LABELED_EXPORT auditConstant = 2305 /* Object exported with label */
|
||||
AUDIT_USER_UNLABELED_EXPORT auditConstant = 2306 /* Object exported without label */
|
||||
AUDIT_DEV_ALLOC auditConstant = 2307 /* Device was allocated */
|
||||
AUDIT_DEV_DEALLOC auditConstant = 2308 /* Device was deallocated */
|
||||
AUDIT_FS_RELABEL auditConstant = 2309 /* Filesystem relabeled */
|
||||
AUDIT_USER_MAC_POLICY_LOAD auditConstant = 2310 /* Userspc daemon loaded policy */
|
||||
AUDIT_ROLE_MODIFY auditConstant = 2311 /* Admin modified a role */
|
||||
AUDIT_USER_MAC_CONFIG_CHANGE auditConstant = 2312 /* Change made to MAC policy */
|
||||
|
||||
AUDIT_FIRST_CRYPTO_MSG auditConstant = 2400
|
||||
AUDIT_CRYPTO_TEST_USER auditConstant = 2400 /* Crypto test results */
|
||||
AUDIT_CRYPTO_PARAM_CHANGE_USER auditConstant = 2401 /* Crypto attribute change */
|
||||
AUDIT_CRYPTO_LOGIN auditConstant = 2402 /* Logged in as crypto officer */
|
||||
AUDIT_CRYPTO_LOGOUT auditConstant = 2403 /* Logged out from crypto */
|
||||
AUDIT_CRYPTO_KEY_USER auditConstant = 2404 /* Create,delete,negotiate */
|
||||
AUDIT_CRYPTO_FAILURE_USER auditConstant = 2405 /* Fail decrypt,encrypt,randomiz */
|
||||
AUDIT_CRYPTO_REPLAY_USER auditConstant = 2406 /* Crypto replay detected */
|
||||
AUDIT_CRYPTO_SESSION auditConstant = 2407 /* Record parameters set during TLS session establishment */
|
||||
AUDIT_CRYPTO_IKE_SA auditConstant = 2408 /* Record parameters related to IKE SA */
|
||||
AUDIT_CRYPTO_IPSEC_SA auditConstant = 2409 /* Record parameters related to IPSEC SA */
|
||||
|
||||
AUDIT_LAST_CRYPTO_MSG auditConstant = 2499
|
||||
|
||||
AUDIT_FIRST_VIRT_MSG auditConstant = 2500
|
||||
AUDIT_VIRT_CONTROL auditConstant = 2500 /* Start, Pause, Stop VM */
|
||||
AUDIT_VIRT_RESOURCE auditConstant = 2501 /* Resource assignment */
|
||||
AUDIT_VIRT_MACHINE_ID auditConstant = 2502 /* Binding of label to VM */
|
||||
AUDIT_LAST_VIRT_MSG auditConstant = 2599
|
||||
AUDIT_LAST_USER_MSG2 auditConstant = 2999
|
||||
// Field Comparing Constants
|
||||
AUDIT_COMPARE_UID_TO_OBJ_UID auditConstant = 1
|
||||
AUDIT_COMPARE_GID_TO_OBJ_GID auditConstant = 2
|
||||
AUDIT_COMPARE_EUID_TO_OBJ_UID auditConstant = 3
|
||||
AUDIT_COMPARE_EGID_TO_OBJ_GID auditConstant = 4
|
||||
AUDIT_COMPARE_AUID_TO_OBJ_UID auditConstant = 5
|
||||
AUDIT_COMPARE_SUID_TO_OBJ_UID auditConstant = 6
|
||||
AUDIT_COMPARE_SGID_TO_OBJ_GID auditConstant = 7
|
||||
AUDIT_COMPARE_FSUID_TO_OBJ_UID auditConstant = 8
|
||||
AUDIT_COMPARE_FSGID_TO_OBJ_GID auditConstant = 9
|
||||
AUDIT_COMPARE_UID_TO_AUID auditConstant = 10
|
||||
AUDIT_COMPARE_UID_TO_EUID auditConstant = 11
|
||||
AUDIT_COMPARE_UID_TO_FSUID auditConstant = 12
|
||||
AUDIT_COMPARE_UID_TO_SUID auditConstant = 13
|
||||
AUDIT_COMPARE_AUID_TO_FSUID auditConstant = 14
|
||||
AUDIT_COMPARE_AUID_TO_SUID auditConstant = 15
|
||||
AUDIT_COMPARE_AUID_TO_EUID auditConstant = 16
|
||||
AUDIT_COMPARE_EUID_TO_SUID auditConstant = 17
|
||||
AUDIT_COMPARE_EUID_TO_FSUID auditConstant = 18
|
||||
AUDIT_COMPARE_SUID_TO_FSUID auditConstant = 19
|
||||
AUDIT_COMPARE_GID_TO_EGID auditConstant = 20
|
||||
AUDIT_COMPARE_GID_TO_FSGID auditConstant = 21
|
||||
AUDIT_COMPARE_GID_TO_SGID auditConstant = 22
|
||||
AUDIT_COMPARE_EGID_TO_FSGID auditConstant = 23
|
||||
AUDIT_COMPARE_EGID_TO_SGID auditConstant = 24
|
||||
AUDIT_COMPARE_SGID_TO_FSGID auditConstant = 25
|
||||
)
|
|
@ -0,0 +1,164 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// EventCallback is the function definition for any function that wants to receive an AuditEvent as soon as
|
||||
// it is received from the kernel. Error will be set to indicate any error that occurs while receiving
|
||||
// messages.
|
||||
type EventCallback func(*AuditEvent, error)
|
||||
|
||||
// RawEventCallback is similar to EventCallback but the difference is that the function will receive only
|
||||
// the message string which contains the audit event and not the parsed AuditEvent struct.
|
||||
type RawEventCallback func(string, error)
|
||||
|
||||
// AuditEvent is a parsed audit message.
|
||||
type AuditEvent struct {
|
||||
Serial string // Message serial
|
||||
Timestamp string // Timestamp
|
||||
Type string // Audit event type
|
||||
Data map[string]string // Map of field values in the audit message
|
||||
Raw string // Raw audit message from kernel
|
||||
}
|
||||
|
||||
// NewAuditEvent takes a NetlinkMessage passed from the netlink connection and parses the data
|
||||
// from the message header to return an AuditEvent type.
|
||||
//
|
||||
// Note that it is possible here that we don't have a full event to return. In some cases, a
|
||||
// single audit event may be represented by multiple audit events from the kernel. This function
|
||||
// looks after buffering partial fragments of a full event, and may only return the complete event
|
||||
// once an AUDIT_EOE record has been recieved for the audit event.
|
||||
//
|
||||
// See https://www.redhat.com/archives/linux-audit/2016-January/msg00019.html for additional information
|
||||
// on the behavior of this function.
|
||||
func NewAuditEvent(msg NetlinkMessage) (*AuditEvent, error) {
|
||||
x, err := ParseAuditEvent(string(msg.Data[:]), auditConstant(msg.Header.Type), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if (*x).Type == "auditConstant("+strconv.Itoa(int(msg.Header.Type))+")" {
|
||||
return nil, fmt.Errorf("unknown message type %d", msg.Header.Type)
|
||||
}
|
||||
|
||||
// Determine if the event type is one which the kernel is expected to send only a single
|
||||
// packet for; in these cases we don't need to look into buffering it and can return the
|
||||
// event immediately.
|
||||
if auditConstant(msg.Header.Type) < AUDIT_SYSCALL ||
|
||||
auditConstant(msg.Header.Type) >= AUDIT_FIRST_ANOM_MSG {
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// If this is an EOE message, get the entire processed message and return it.
|
||||
if auditConstant(msg.Header.Type) == AUDIT_EOE {
|
||||
return bufferGet(x), nil
|
||||
}
|
||||
|
||||
// Otherwise we need to buffer this message.
|
||||
bufferEvent(x)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetAuditEvents receives audit messages from the kernel and parses them into an AuditEvent.
|
||||
// It passes them along the callback function and if any error occurs while receiving the message,
|
||||
// the same will be passed in the callback as well.
|
||||
//
|
||||
// This function executes a go-routine (which does not return) and the function itself returns
|
||||
// immediately.
|
||||
func GetAuditEvents(s Netlink, cb EventCallback) {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
default:
|
||||
msgs, _ := s.Receive(false)
|
||||
for _, msg := range msgs {
|
||||
if msg.Header.Type == syscall.NLMSG_ERROR {
|
||||
err := int32(hostEndian.Uint32(msg.Data[0:4]))
|
||||
if err != 0 {
|
||||
cb(nil, fmt.Errorf("audit error %d", err))
|
||||
}
|
||||
} else {
|
||||
nae, err := NewAuditEvent(msg)
|
||||
if nae == nil {
|
||||
continue
|
||||
}
|
||||
cb(nae, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// GetRawAuditEvents is similar to GetAuditEvents, however it returns raw messages and does not parse
|
||||
// incoming audit data.
|
||||
func GetRawAuditEvents(s Netlink, cb RawEventCallback) {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
default:
|
||||
msgs, _ := s.Receive(false)
|
||||
for _, msg := range msgs {
|
||||
var (
|
||||
m string
|
||||
err error
|
||||
)
|
||||
if msg.Header.Type == syscall.NLMSG_ERROR {
|
||||
v := int32(hostEndian.Uint32(msg.Data[0:4]))
|
||||
if v != 0 {
|
||||
cb(m, fmt.Errorf("audit error %d", v))
|
||||
}
|
||||
} else {
|
||||
Type := auditConstant(msg.Header.Type)
|
||||
if Type.String() == "auditConstant("+strconv.Itoa(int(msg.Header.Type))+")" {
|
||||
err = errors.New("Unknown Type: " + string(msg.Header.Type))
|
||||
} else {
|
||||
m = "type=" + Type.String()[6:] +
|
||||
" msg=" + string(msg.Data[:]) + "\n"
|
||||
}
|
||||
}
|
||||
cb(m, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// GetAuditMessages is a blocking function (runs in forever for loop) that receives audit messages
|
||||
// from the kernel and parses them to AuditEvent. It passes them along the callback function and if
|
||||
// any error occurs while receiving the message, the same will be passed in the callback as well.
|
||||
//
|
||||
// It will return when a signal is received on the done channel.
|
||||
func GetAuditMessages(s Netlink, cb EventCallback, done *chan bool) {
|
||||
for {
|
||||
select {
|
||||
case <-*done:
|
||||
return
|
||||
default:
|
||||
msgs, _ := s.Receive(false)
|
||||
for _, msg := range msgs {
|
||||
if msg.Header.Type == syscall.NLMSG_ERROR {
|
||||
v := int32(hostEndian.Uint32(msg.Data[0:4]))
|
||||
if v != 0 {
|
||||
cb(nil, fmt.Errorf("audit error %d", v))
|
||||
}
|
||||
} else {
|
||||
nae, err := NewAuditEvent(msg)
|
||||
if nae == nil {
|
||||
continue
|
||||
}
|
||||
cb(nae, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
239
vendor/github.com/mozilla/libaudit-go/auditconstant_string.go
сгенерированный
поставляемый
Normal file
239
vendor/github.com/mozilla/libaudit-go/auditconstant_string.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,239 @@
|
|||
// Code generated by "stringer -type=auditConstant audit_constant.go"; DO NOT EDIT.
|
||||
|
||||
package libaudit
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _auditConstant_name = "AUDIT_COMPARE_UID_TO_OBJ_UIDAUDIT_COMPARE_GID_TO_OBJ_GIDAUDIT_COMPARE_EUID_TO_OBJ_UIDAUDIT_COMPARE_EGID_TO_OBJ_GIDAUDIT_COMPARE_AUID_TO_OBJ_UIDAUDIT_COMPARE_SUID_TO_OBJ_UIDAUDIT_COMPARE_SGID_TO_OBJ_GIDAUDIT_COMPARE_FSUID_TO_OBJ_UIDAUDIT_COMPARE_FSGID_TO_OBJ_GIDAUDIT_COMPARE_UID_TO_AUIDAUDIT_COMPARE_UID_TO_EUIDAUDIT_COMPARE_UID_TO_FSUIDAUDIT_COMPARE_UID_TO_SUIDAUDIT_COMPARE_AUID_TO_FSUIDAUDIT_COMPARE_AUID_TO_SUIDAUDIT_COMPARE_AUID_TO_EUIDAUDIT_COMPARE_EUID_TO_SUIDAUDIT_COMPARE_EUID_TO_FSUIDAUDIT_COMPARE_SUID_TO_FSUIDAUDIT_COMPARE_GID_TO_EGIDAUDIT_COMPARE_GID_TO_FSGIDAUDIT_COMPARE_GID_TO_SGIDAUDIT_COMPARE_EGID_TO_FSGIDAUDIT_COMPARE_EGID_TO_SGIDAUDIT_COMPARE_SGID_TO_FSGIDAUDIT_GETAUDIT_SETAUDIT_LISTAUDIT_ADDAUDIT_DELAUDIT_USERAUDIT_LOGINAUDIT_WATCH_INSAUDIT_WATCH_REMAUDIT_WATCH_LISTAUDIT_SIGNAL_INFOAUDIT_ADD_RULEAUDIT_DEL_RULEAUDIT_LIST_RULESAUDIT_TRIMAUDIT_MAKE_EQUIVAUDIT_TTY_GETAUDIT_TTY_SETAUDIT_SET_FEATUREAUDIT_GET_FEATUREAUDIT_FIRST_USER_MSGAUDIT_USER_ACCTAUDIT_USER_MGMTAUDIT_CRED_ACQAUDIT_CRED_DISPAUDIT_USER_STARTAUDIT_USER_ENDAUDIT_USER_AVCAUDIT_USER_CHAUTHTOKAUDIT_USER_ERRAUDIT_CRED_REFRAUDIT_USYS_CONFIGAUDIT_USER_LOGINAUDIT_USER_LOGOUTAUDIT_ADD_USERAUDIT_DEL_USERAUDIT_ADD_GROUPAUDIT_DEL_GROUPAUDIT_DAC_CHECKAUDIT_CHGRP_IDAUDIT_TESTAUDIT_TRUSTED_APPAUDIT_USER_SELINUX_ERRAUDIT_USER_CMDAUDIT_USER_TTYAUDIT_CHUSER_IDAUDIT_GRP_AUTHAUDIT_SYSTEM_BOOTAUDIT_SYSTEM_SHUTDOWNAUDIT_SYSTEM_RUNLEVELAUDIT_SERVICE_STARTAUDIT_SERVICE_STOPAUDIT_GRP_MGMTAUDIT_GRP_CHAUTHTOKAUDIT_MAC_CHECKAUDIT_ACCT_LOCKAUDIT_ACCT_UNLOCKAUDIT_LAST_USER_MSGAUDIT_FIRST_DAEMONAUDIT_DAEMON_CONFIGAUDIT_DAEMON_RECONFIGAUDIT_DAEMON_ROTATEAUDIT_DAEMON_RESUMEAUDIT_DAEMON_ACCEPTAUDIT_DAEMON_CLOSEAUDIT_LAST_DAEMONAUDIT_SYSCALLAUDIT_PATHAUDIT_IPCAUDIT_SOCKETCALLAUDIT_CONFIG_CHANGEAUDIT_SOCKADDRAUDIT_CWDAUDIT_EXECVEAUDIT_IPC_SET_PERMAUDIT_MQ_OPENAUDIT_MQ_SENDRECVAUDIT_MQ_NOTIFYAUDIT_MQ_GETSETATTRAUDIT_KERNEL_OTHERAUDIT_FD_PAIRAUDIT_OBJ_PIDAUDIT_TTYAUDIT_EOEAUDIT_BPRM_FCAPSAUDIT_CAPSETAUDIT_MMAPAUDIT_NETFILTER_PKTAUDIT_NETFILTER_CFGAUDIT_SECCOMPAUDIT_PROCTITLEAUDIT_FEATURE_CHANGEAUDIT_LAST_EVENTAUDIT_AVCAUDIT_SELINUX_ERRAUDIT_AVC_PATHAUDIT_MAC_POLICY_LOADAUDIT_MAC_STATUSAUDIT_MAC_CONFIG_CHANGEAUDIT_MAC_UNLBL_ALLOWAUDIT_MAC_CIPSOV4_ADDAUDIT_MAC_CIPSOV4_DELAUDIT_MAC_MAP_ADDAUDIT_MAC_MAP_DELAUDIT_MAC_IPSEC_ADDSAAUDIT_MAC_IPSEC_DELSAAUDIT_MAC_IPSEC_ADDSPDAUDIT_MAC_IPSEC_DELSPDAUDIT_MAC_IPSEC_EVENTAUDIT_MAC_UNLBL_STCADDAUDIT_MAC_UNLBL_STCDELAUDIT_LAST_SELINUXAUDIT_FIRST_APPARMORAUDIT_APPARMOR_AUDITAUDIT_APPARMOR_ALLOWEDAUDIT_APPARMOR_DENIEDAUDIT_APPARMOR_HTAUDIT_APPARMOR_STATUSAUDIT_APPARMOR_ERRORAUDIT_LAST_APPARMORAUDIT_FIRST_KERN_CRYPTO_MSGAUDIT_LAST_KERN_CRYPTO_MSGAUDIT_ANOM_PROMISCUOUSAUDIT_ANOM_ABENDAUDIT_ANOM_LINKAUDIT_LAST_KERN_ANOM_MSGAUDIT_INTEGRITY_FIRST_MSGAUDIT_INTEGRITY_METADATAAUDIT_INTEGRITY_STATUSAUDIT_INTEGRITY_HASHAUDIT_INTEGRITY_PCRAUDIT_INTEGRITY_RULEAUDIT_TINTEGRITY_LAST_MSGAUDIT_KERNELAUDIT_FIRST_ANOM_MSGAUDIT_ANOM_LOGIN_TIMEAUDIT_ANOM_LOGIN_SESSIONSAUDIT_ANOM_LOGIN_ACCTAUDIT_ANOM_LOGIN_LOCATIONAUDIT_ANOM_MAX_DACAUDIT_ANOM_MAX_MACAUDIT_ANOM_AMTU_FAILAUDIT_ANOM_RBAC_FAILAUDIT_ANOM_RBAC_INTEGRITY_FAILAUDIT_ANOM_CRYPTO_FAILAUDIT_ANOM_ACCESS_FSAUDIT_ANOM_EXECAUDIT_ANOM_MK_EXECAUDIT_ANOM_ADD_ACCTAUDIT_ANOM_DEL_ACCTAUDIT_ANOM_MOD_ACCTAUDIT_ANOM_ROOT_TRANSAUDIT_LAST_ANOM_MSGAUDIT_FIRST_ANOM_RESPAUDIT_RESP_ALERTAUDIT_RESP_KILL_PROCAUDIT_RESP_TERM_ACCESSAUDIT_RESP_ACCT_REMOTEAUDIT_RESP_ACCT_LOCK_TIMEDAUDIT_RESP_ACCT_UNLOCK_TIMEDAUDIT_RESP_ACCT_LOCKAUDIT_RESP_TERM_LOCKAUDIT_RESP_SEBOOLAUDIT_RESP_EXECAUDIT_RESP_SINGLEAUDIT_RESP_HALTAUDIT_LAST_ANOM_RESPAUDIT_FIRST_USER_LSPP_MSGAUDIT_ROLE_ASSIGNAUDIT_ROLE_REMOVEAUDIT_LABEL_OVERRIDEAUDIT_LABEL_LEVEL_CHANGEAUDIT_USER_LABELED_EXPORTAUDIT_USER_UNLABELED_EXPORTAUDIT_DEV_ALLOCAUDIT_DEV_DEALLOCAUDIT_FS_RELABELAUDIT_USER_MAC_POLICY_LOADAUDIT_ROLE_MODIFYAUDIT_USER_MAC_CONFIG_CHANGEAUDIT_LAST_USER_LSPP_MSGAUDIT_FIRST_CRYPTO_MSGAUDIT_CRYPTO_PARAM_CHANGE_USERAUDIT_CRYPTO_LOGINAUDIT_CRYPTO_LOGOUTAUDIT_CRYPTO_KEY_USERAUDIT_CRYPTO_FAILURE_USERAUDIT_CRYPTO_REPLAY_USERAUDIT_CRYPTO_SESSIONAUDIT_CRYPTO_IKE_SAAUDIT_CRYPTO_IPSEC_SAAUDIT_LAST_CRYPTO_MSGAUDIT_FIRST_VIRT_MSGAUDIT_VIRT_RESOURCEAUDIT_VIRT_MACHINE_IDAUDIT_LAST_VIRT_MSGAUDIT_LAST_USER_MSG2"
|
||||
|
||||
var _auditConstant_map = map[auditConstant]string{
|
||||
1: _auditConstant_name[0:28],
|
||||
2: _auditConstant_name[28:56],
|
||||
3: _auditConstant_name[56:85],
|
||||
4: _auditConstant_name[85:114],
|
||||
5: _auditConstant_name[114:143],
|
||||
6: _auditConstant_name[143:172],
|
||||
7: _auditConstant_name[172:201],
|
||||
8: _auditConstant_name[201:231],
|
||||
9: _auditConstant_name[231:261],
|
||||
10: _auditConstant_name[261:286],
|
||||
11: _auditConstant_name[286:311],
|
||||
12: _auditConstant_name[311:337],
|
||||
13: _auditConstant_name[337:362],
|
||||
14: _auditConstant_name[362:389],
|
||||
15: _auditConstant_name[389:415],
|
||||
16: _auditConstant_name[415:441],
|
||||
17: _auditConstant_name[441:467],
|
||||
18: _auditConstant_name[467:494],
|
||||
19: _auditConstant_name[494:521],
|
||||
20: _auditConstant_name[521:546],
|
||||
21: _auditConstant_name[546:572],
|
||||
22: _auditConstant_name[572:597],
|
||||
23: _auditConstant_name[597:624],
|
||||
24: _auditConstant_name[624:650],
|
||||
25: _auditConstant_name[650:677],
|
||||
1000: _auditConstant_name[677:686],
|
||||
1001: _auditConstant_name[686:695],
|
||||
1002: _auditConstant_name[695:705],
|
||||
1003: _auditConstant_name[705:714],
|
||||
1004: _auditConstant_name[714:723],
|
||||
1005: _auditConstant_name[723:733],
|
||||
1006: _auditConstant_name[733:744],
|
||||
1007: _auditConstant_name[744:759],
|
||||
1008: _auditConstant_name[759:774],
|
||||
1009: _auditConstant_name[774:790],
|
||||
1010: _auditConstant_name[790:807],
|
||||
1011: _auditConstant_name[807:821],
|
||||
1012: _auditConstant_name[821:835],
|
||||
1013: _auditConstant_name[835:851],
|
||||
1014: _auditConstant_name[851:861],
|
||||
1015: _auditConstant_name[861:877],
|
||||
1016: _auditConstant_name[877:890],
|
||||
1017: _auditConstant_name[890:903],
|
||||
1018: _auditConstant_name[903:920],
|
||||
1019: _auditConstant_name[920:937],
|
||||
1100: _auditConstant_name[937:957],
|
||||
1101: _auditConstant_name[957:972],
|
||||
1102: _auditConstant_name[972:987],
|
||||
1103: _auditConstant_name[987:1001],
|
||||
1104: _auditConstant_name[1001:1016],
|
||||
1105: _auditConstant_name[1016:1032],
|
||||
1106: _auditConstant_name[1032:1046],
|
||||
1107: _auditConstant_name[1046:1060],
|
||||
1108: _auditConstant_name[1060:1080],
|
||||
1109: _auditConstant_name[1080:1094],
|
||||
1110: _auditConstant_name[1094:1109],
|
||||
1111: _auditConstant_name[1109:1126],
|
||||
1112: _auditConstant_name[1126:1142],
|
||||
1113: _auditConstant_name[1142:1159],
|
||||
1114: _auditConstant_name[1159:1173],
|
||||
1115: _auditConstant_name[1173:1187],
|
||||
1116: _auditConstant_name[1187:1202],
|
||||
1117: _auditConstant_name[1202:1217],
|
||||
1118: _auditConstant_name[1217:1232],
|
||||
1119: _auditConstant_name[1232:1246],
|
||||
1120: _auditConstant_name[1246:1256],
|
||||
1121: _auditConstant_name[1256:1273],
|
||||
1122: _auditConstant_name[1273:1295],
|
||||
1123: _auditConstant_name[1295:1309],
|
||||
1124: _auditConstant_name[1309:1323],
|
||||
1125: _auditConstant_name[1323:1338],
|
||||
1126: _auditConstant_name[1338:1352],
|
||||
1127: _auditConstant_name[1352:1369],
|
||||
1128: _auditConstant_name[1369:1390],
|
||||
1129: _auditConstant_name[1390:1411],
|
||||
1130: _auditConstant_name[1411:1430],
|
||||
1131: _auditConstant_name[1430:1448],
|
||||
1132: _auditConstant_name[1448:1462],
|
||||
1133: _auditConstant_name[1462:1481],
|
||||
1134: _auditConstant_name[1481:1496],
|
||||
1135: _auditConstant_name[1496:1511],
|
||||
1136: _auditConstant_name[1511:1528],
|
||||
1199: _auditConstant_name[1528:1547],
|
||||
1200: _auditConstant_name[1547:1565],
|
||||
1203: _auditConstant_name[1565:1584],
|
||||
1204: _auditConstant_name[1584:1605],
|
||||
1205: _auditConstant_name[1605:1624],
|
||||
1206: _auditConstant_name[1624:1643],
|
||||
1207: _auditConstant_name[1643:1662],
|
||||
1208: _auditConstant_name[1662:1680],
|
||||
1299: _auditConstant_name[1680:1697],
|
||||
1300: _auditConstant_name[1697:1710],
|
||||
1302: _auditConstant_name[1710:1720],
|
||||
1303: _auditConstant_name[1720:1729],
|
||||
1304: _auditConstant_name[1729:1745],
|
||||
1305: _auditConstant_name[1745:1764],
|
||||
1306: _auditConstant_name[1764:1778],
|
||||
1307: _auditConstant_name[1778:1787],
|
||||
1309: _auditConstant_name[1787:1799],
|
||||
1311: _auditConstant_name[1799:1817],
|
||||
1312: _auditConstant_name[1817:1830],
|
||||
1313: _auditConstant_name[1830:1847],
|
||||
1314: _auditConstant_name[1847:1862],
|
||||
1315: _auditConstant_name[1862:1881],
|
||||
1316: _auditConstant_name[1881:1899],
|
||||
1317: _auditConstant_name[1899:1912],
|
||||
1318: _auditConstant_name[1912:1925],
|
||||
1319: _auditConstant_name[1925:1934],
|
||||
1320: _auditConstant_name[1934:1943],
|
||||
1321: _auditConstant_name[1943:1959],
|
||||
1322: _auditConstant_name[1959:1971],
|
||||
1323: _auditConstant_name[1971:1981],
|
||||
1324: _auditConstant_name[1981:2000],
|
||||
1325: _auditConstant_name[2000:2019],
|
||||
1326: _auditConstant_name[2019:2032],
|
||||
1327: _auditConstant_name[2032:2047],
|
||||
1328: _auditConstant_name[2047:2067],
|
||||
1399: _auditConstant_name[2067:2083],
|
||||
1400: _auditConstant_name[2083:2092],
|
||||
1401: _auditConstant_name[2092:2109],
|
||||
1402: _auditConstant_name[2109:2123],
|
||||
1403: _auditConstant_name[2123:2144],
|
||||
1404: _auditConstant_name[2144:2160],
|
||||
1405: _auditConstant_name[2160:2183],
|
||||
1406: _auditConstant_name[2183:2204],
|
||||
1407: _auditConstant_name[2204:2225],
|
||||
1408: _auditConstant_name[2225:2246],
|
||||
1409: _auditConstant_name[2246:2263],
|
||||
1410: _auditConstant_name[2263:2280],
|
||||
1411: _auditConstant_name[2280:2301],
|
||||
1412: _auditConstant_name[2301:2322],
|
||||
1413: _auditConstant_name[2322:2344],
|
||||
1414: _auditConstant_name[2344:2366],
|
||||
1415: _auditConstant_name[2366:2387],
|
||||
1416: _auditConstant_name[2387:2409],
|
||||
1417: _auditConstant_name[2409:2431],
|
||||
1499: _auditConstant_name[2431:2449],
|
||||
1500: _auditConstant_name[2449:2469],
|
||||
1501: _auditConstant_name[2469:2489],
|
||||
1502: _auditConstant_name[2489:2511],
|
||||
1503: _auditConstant_name[2511:2532],
|
||||
1504: _auditConstant_name[2532:2549],
|
||||
1505: _auditConstant_name[2549:2570],
|
||||
1506: _auditConstant_name[2570:2590],
|
||||
1599: _auditConstant_name[2590:2609],
|
||||
1600: _auditConstant_name[2609:2636],
|
||||
1699: _auditConstant_name[2636:2662],
|
||||
1700: _auditConstant_name[2662:2684],
|
||||
1701: _auditConstant_name[2684:2700],
|
||||
1702: _auditConstant_name[2700:2715],
|
||||
1799: _auditConstant_name[2715:2739],
|
||||
1800: _auditConstant_name[2739:2764],
|
||||
1801: _auditConstant_name[2764:2788],
|
||||
1802: _auditConstant_name[2788:2810],
|
||||
1803: _auditConstant_name[2810:2830],
|
||||
1804: _auditConstant_name[2830:2849],
|
||||
1805: _auditConstant_name[2849:2869],
|
||||
1899: _auditConstant_name[2869:2894],
|
||||
2000: _auditConstant_name[2894:2906],
|
||||
2100: _auditConstant_name[2906:2926],
|
||||
2101: _auditConstant_name[2926:2947],
|
||||
2102: _auditConstant_name[2947:2972],
|
||||
2103: _auditConstant_name[2972:2993],
|
||||
2104: _auditConstant_name[2993:3018],
|
||||
2105: _auditConstant_name[3018:3036],
|
||||
2106: _auditConstant_name[3036:3054],
|
||||
2107: _auditConstant_name[3054:3074],
|
||||
2108: _auditConstant_name[3074:3094],
|
||||
2109: _auditConstant_name[3094:3124],
|
||||
2110: _auditConstant_name[3124:3146],
|
||||
2111: _auditConstant_name[3146:3166],
|
||||
2112: _auditConstant_name[3166:3181],
|
||||
2113: _auditConstant_name[3181:3199],
|
||||
2114: _auditConstant_name[3199:3218],
|
||||
2115: _auditConstant_name[3218:3237],
|
||||
2116: _auditConstant_name[3237:3256],
|
||||
2117: _auditConstant_name[3256:3277],
|
||||
2199: _auditConstant_name[3277:3296],
|
||||
2200: _auditConstant_name[3296:3317],
|
||||
2201: _auditConstant_name[3317:3333],
|
||||
2202: _auditConstant_name[3333:3353],
|
||||
2203: _auditConstant_name[3353:3375],
|
||||
2204: _auditConstant_name[3375:3397],
|
||||
2205: _auditConstant_name[3397:3423],
|
||||
2206: _auditConstant_name[3423:3451],
|
||||
2207: _auditConstant_name[3451:3471],
|
||||
2208: _auditConstant_name[3471:3491],
|
||||
2209: _auditConstant_name[3491:3508],
|
||||
2210: _auditConstant_name[3508:3523],
|
||||
2211: _auditConstant_name[3523:3540],
|
||||
2212: _auditConstant_name[3540:3555],
|
||||
2299: _auditConstant_name[3555:3575],
|
||||
2300: _auditConstant_name[3575:3600],
|
||||
2301: _auditConstant_name[3600:3617],
|
||||
2302: _auditConstant_name[3617:3634],
|
||||
2303: _auditConstant_name[3634:3654],
|
||||
2304: _auditConstant_name[3654:3678],
|
||||
2305: _auditConstant_name[3678:3703],
|
||||
2306: _auditConstant_name[3703:3730],
|
||||
2307: _auditConstant_name[3730:3745],
|
||||
2308: _auditConstant_name[3745:3762],
|
||||
2309: _auditConstant_name[3762:3778],
|
||||
2310: _auditConstant_name[3778:3804],
|
||||
2311: _auditConstant_name[3804:3821],
|
||||
2312: _auditConstant_name[3821:3849],
|
||||
2399: _auditConstant_name[3849:3873],
|
||||
2400: _auditConstant_name[3873:3895],
|
||||
2401: _auditConstant_name[3895:3925],
|
||||
2402: _auditConstant_name[3925:3943],
|
||||
2403: _auditConstant_name[3943:3962],
|
||||
2404: _auditConstant_name[3962:3983],
|
||||
2405: _auditConstant_name[3983:4008],
|
||||
2406: _auditConstant_name[4008:4032],
|
||||
2407: _auditConstant_name[4032:4052],
|
||||
2408: _auditConstant_name[4052:4071],
|
||||
2409: _auditConstant_name[4071:4092],
|
||||
2499: _auditConstant_name[4092:4113],
|
||||
2500: _auditConstant_name[4113:4133],
|
||||
2501: _auditConstant_name[4133:4152],
|
||||
2502: _auditConstant_name[4152:4173],
|
||||
2599: _auditConstant_name[4173:4192],
|
||||
2999: _auditConstant_name[4192:4212],
|
||||
}
|
||||
|
||||
func (i auditConstant) String() string {
|
||||
if str, ok := _auditConstant_map[i]; ok {
|
||||
return str
|
||||
}
|
||||
return fmt.Sprintf("auditConstant(%d)", i)
|
||||
}
|
105
vendor/github.com/mozilla/libaudit-go/auditprint/auditprint.go
сгенерированный
поставляемый
Normal file
105
vendor/github.com/mozilla/libaudit-go/auditprint/auditprint.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,105 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// auditprint is a simple command line tool that loads an audit rule set from a JSON file,
|
||||
// applies it to the current kernel and begins printing any audit event the kernel sends in
|
||||
// JSON format.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/mozilla/libaudit-go"
|
||||
)
|
||||
|
||||
func auditProc(e *libaudit.AuditEvent, err error) {
|
||||
if err != nil {
|
||||
// See if the error is libaudit.ErrorAuditParse, if so convert and also display
|
||||
// the audit record we could not parse
|
||||
if nerr, ok := err.(libaudit.ErrorAuditParse); ok {
|
||||
fmt.Printf("parser error: %v: %v\n", nerr, nerr.Raw)
|
||||
} else {
|
||||
fmt.Printf("callback received error: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// Marshal the event to JSON and print
|
||||
buf, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
fmt.Printf("callback was unable to marshal event: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%v\n", string(buf))
|
||||
}
|
||||
|
||||
func main() {
|
||||
s, err := libaudit.NewNetlinkConnection()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "NetNetlinkConnection: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Printf("usage: %v path_to_rules.json\n", os.Args[0])
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
err = libaudit.AuditSetEnabled(s, true)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "AuditSetEnabled: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = libaudit.AuditSetPID(s, os.Getpid())
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "AuditSetPid: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = libaudit.AuditSetRateLimit(s, 1000)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "AuditSetRateLimit: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = libaudit.AuditSetBacklogLimit(s, 250)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "AuditSetBacklogLimit: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var ar libaudit.AuditRules
|
||||
buf, err := ioutil.ReadFile(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ReadFile: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// Make sure we can unmarshal the rules JSON to validate it is the correct
|
||||
// format
|
||||
err = json.Unmarshal(buf, &ar)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unmarshaling rules JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Remove current rule set and send rules to the kernel
|
||||
err = libaudit.DeleteAllRules(s)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "DeleteAllRules: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
warnings, err := libaudit.SetRules(s, buf)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "SetRules: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// Print any warnings we got back but still continue
|
||||
for _, x := range warnings {
|
||||
fmt.Fprintf(os.Stderr, "ruleset warning: %v\n", x)
|
||||
}
|
||||
|
||||
doneCh := make(chan bool, 1)
|
||||
libaudit.GetAuditMessages(s, auditProc, &doneCh)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var bufferMap map[uint64][]*AuditEvent
|
||||
|
||||
// bufferEvent buffers an incoming audit event which contains partial record informatioa.
|
||||
func bufferEvent(a *AuditEvent) {
|
||||
if bufferMap == nil {
|
||||
bufferMap = make(map[uint64][]*AuditEvent)
|
||||
}
|
||||
|
||||
serial, err := strconv.ParseUint(a.Serial, 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, ok := bufferMap[serial]; !ok {
|
||||
bufferMap[serial] = make([]*AuditEvent, 5)
|
||||
}
|
||||
bufferMap[serial] = append(bufferMap[serial], a)
|
||||
}
|
||||
|
||||
// bufferGet returns the complete audit event from the buffer, given the AUDIT_EOE event a.
|
||||
func bufferGet(a *AuditEvent) *AuditEvent {
|
||||
serial, err := strconv.ParseUint(a.Serial, 10, 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
bm []*AuditEvent
|
||||
ok bool
|
||||
)
|
||||
if bm, ok = bufferMap[serial]; !ok {
|
||||
return nil
|
||||
}
|
||||
rlen := len(a.Raw)
|
||||
for i := range bm {
|
||||
if bm[i] == nil {
|
||||
continue
|
||||
}
|
||||
for k, v := range bm[i].Data {
|
||||
a.Data[k] = v
|
||||
}
|
||||
if len(bm[i].Raw) > rlen {
|
||||
a.Raw += " " + bm[i].Raw[rlen:]
|
||||
}
|
||||
}
|
||||
|
||||
delete(bufferMap, serial)
|
||||
return a
|
||||
}
|
7
vendor/github.com/mozilla/libaudit-go/headers/access_tab.go
сгенерированный
поставляемый
Normal file
7
vendor/github.com/mozilla/libaudit-go/headers/access_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,7 @@
|
|||
package headers
|
||||
|
||||
var AccessLookUp = map[int]string{
|
||||
1: "X_OK",
|
||||
2: "W_OK",
|
||||
4: "R_OK",
|
||||
}
|
333
vendor/github.com/mozilla/libaudit-go/headers/audit_x64.go
сгенерированный
поставляемый
Normal file
333
vendor/github.com/mozilla/libaudit-go/headers/audit_x64.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,333 @@
|
|||
package headers
|
||||
|
||||
// SysMapX64 is a mapping between x64 syscall names and their integer values
|
||||
// The list is taken from x86_64_table.h of auditd library
|
||||
var SysMapX64 = map[string]int{
|
||||
"read": 0,
|
||||
"write": 1,
|
||||
"open": 2,
|
||||
"close": 3,
|
||||
"stat": 4,
|
||||
"fstat": 5,
|
||||
"lstat": 6,
|
||||
"poll": 7,
|
||||
"lseek": 8,
|
||||
"mmap": 9,
|
||||
"mprotect": 10,
|
||||
"munmap": 11,
|
||||
"brk": 12,
|
||||
"rt_sigaction": 13,
|
||||
"rt_sigprocmask": 14,
|
||||
"rt_sigreturn": 15,
|
||||
"ioctl": 16,
|
||||
"pread64": 17,
|
||||
"pwrite64": 18,
|
||||
"readv": 19,
|
||||
"writev": 20,
|
||||
"access": 21,
|
||||
"pipe": 22,
|
||||
"select": 23,
|
||||
"sched_yield": 24,
|
||||
"mremap": 25,
|
||||
"msync": 26,
|
||||
"mincore": 27,
|
||||
"madvise": 28,
|
||||
"shmget": 29,
|
||||
"shmat": 30,
|
||||
"shmctl": 31,
|
||||
"dup": 32,
|
||||
"dup2": 33,
|
||||
"pause": 34,
|
||||
"nanosleep": 35,
|
||||
"getitimer": 36,
|
||||
"alarm": 37,
|
||||
"setitimer": 38,
|
||||
"getpid": 39,
|
||||
"sendfile": 40,
|
||||
"socket": 41,
|
||||
"connect": 42,
|
||||
"accept": 43,
|
||||
"sendto": 44,
|
||||
"recvfrom": 45,
|
||||
"sendmsg": 46,
|
||||
"recvmsg": 47,
|
||||
"shutdown": 48,
|
||||
"bind": 49,
|
||||
"listen": 50,
|
||||
"getsockname": 51,
|
||||
"getpeername": 52,
|
||||
"socketpair": 53,
|
||||
"setsockopt": 54,
|
||||
"getsockopt": 55,
|
||||
"clone": 56,
|
||||
"fork": 57,
|
||||
"vfork": 58,
|
||||
"execve": 59,
|
||||
"exit": 60,
|
||||
"wait4": 61,
|
||||
"kill": 62,
|
||||
"uname": 63,
|
||||
"semget": 64,
|
||||
"semop": 65,
|
||||
"semctl": 66,
|
||||
"shmdt": 67,
|
||||
"msgget": 68,
|
||||
"msgsnd": 69,
|
||||
"msgrcv": 70,
|
||||
"msgctl": 71,
|
||||
"fcntl": 72,
|
||||
"flock": 73,
|
||||
"fsync": 74,
|
||||
"fdatasync": 75,
|
||||
"truncate": 76,
|
||||
"ftruncate": 77,
|
||||
"getdents": 78,
|
||||
"getcwd": 79,
|
||||
"chdir": 80,
|
||||
"fchdir": 81,
|
||||
"rename": 82,
|
||||
"mkdir": 83,
|
||||
"rmdir": 84,
|
||||
"creat": 85,
|
||||
"link": 86,
|
||||
"unlink": 87,
|
||||
"symlink": 88,
|
||||
"readlink": 89,
|
||||
"chmod": 90,
|
||||
"fchmod": 91,
|
||||
"chown": 92,
|
||||
"fchown": 93,
|
||||
"lchown": 94,
|
||||
"umask": 95,
|
||||
"gettimeofday": 96,
|
||||
"getrlimit": 97,
|
||||
"getrusage": 98,
|
||||
"sysinfo": 99,
|
||||
"times": 100,
|
||||
"ptrace": 101,
|
||||
"getuid": 102,
|
||||
"syslog": 103,
|
||||
"getgid": 104,
|
||||
"setuid": 105,
|
||||
"setgid": 106,
|
||||
"geteuid": 107,
|
||||
"getegid": 108,
|
||||
"setpgid": 109,
|
||||
"getppid": 110,
|
||||
"getpgrp": 111,
|
||||
"setsid": 112,
|
||||
"setreuid": 113,
|
||||
"setregid": 114,
|
||||
"getgroups": 115,
|
||||
"setgroups": 116,
|
||||
"setresuid": 117,
|
||||
"getresuid": 118,
|
||||
"setresgid": 119,
|
||||
"getresgid": 120,
|
||||
"getpgid": 121,
|
||||
"setfsuid": 122,
|
||||
"setfsgid": 123,
|
||||
"getsid": 124,
|
||||
"capget": 125,
|
||||
"capset": 126,
|
||||
"rt_sigpending": 127,
|
||||
"rt_sigtimedwait": 128,
|
||||
"rt_sigqueueinfo": 129,
|
||||
"rt_sigsuspend": 130,
|
||||
"sigaltstack": 131,
|
||||
"utime": 132,
|
||||
"mknod": 133,
|
||||
"uselib": 134,
|
||||
"personality": 135,
|
||||
"ustat": 136,
|
||||
"statfs": 137,
|
||||
"fstatfs": 138,
|
||||
"sysfs": 139,
|
||||
"getpriority": 140,
|
||||
"setpriority": 141,
|
||||
"sched_setparam": 142,
|
||||
"sched_getparam": 143,
|
||||
"sched_setscheduler": 144,
|
||||
"sched_getscheduler": 145,
|
||||
"sched_get_priority_max": 146,
|
||||
"sched_get_priority_min": 147,
|
||||
"sched_rr_get_interval": 148,
|
||||
"mlock": 149,
|
||||
"munlock": 150,
|
||||
"mlockall": 151,
|
||||
"munlockall": 152,
|
||||
"vhangup": 153,
|
||||
"modify_ldt": 154,
|
||||
"pivot_root": 155,
|
||||
"_sysctl": 156,
|
||||
"prctl": 157,
|
||||
"arch_prctl": 158,
|
||||
"adjtimex": 159,
|
||||
"setrlimit": 160,
|
||||
"chroot": 161,
|
||||
"sync": 162,
|
||||
"acct": 163,
|
||||
"settimeofday": 164,
|
||||
"mount": 165,
|
||||
"umount2": 166,
|
||||
"swapon": 167,
|
||||
"swapoff": 168,
|
||||
"reboot": 169,
|
||||
"sethostname": 170,
|
||||
"setdomainname": 171,
|
||||
"iopl": 172,
|
||||
"ioperm": 173,
|
||||
"create_module": 174,
|
||||
"init_module": 175,
|
||||
"delete_module": 176,
|
||||
"get_kernel_syms": 177,
|
||||
"query_module": 178,
|
||||
"quotactl": 179,
|
||||
"nfsservctl": 180,
|
||||
"getpmsg": 181,
|
||||
"putpmsg": 182,
|
||||
"afs_": 183,
|
||||
"tuxcall": 184,
|
||||
"security": 185,
|
||||
"gettid": 186,
|
||||
"readahead": 187,
|
||||
"setxattr": 188,
|
||||
"lsetxattr": 189,
|
||||
"fsetxattr": 190,
|
||||
"getxattr": 191,
|
||||
"lgetxattr": 192,
|
||||
"fgetxattr": 193,
|
||||
"listxattr": 194,
|
||||
"llistxattr": 195,
|
||||
"flistxattr": 196,
|
||||
"removexattr": 197,
|
||||
"lremovexattr": 198,
|
||||
"fremovexattr": 199,
|
||||
"tkill": 200,
|
||||
"time": 201,
|
||||
"futex": 202,
|
||||
"sched_setaffinity": 203,
|
||||
"sched_getaffinity": 204,
|
||||
"set_thread_area": 205,
|
||||
"io_setup": 206,
|
||||
"io_destroy": 207,
|
||||
"io_getevents": 208,
|
||||
"io_submit": 209,
|
||||
"io_cancel": 210,
|
||||
"get_thread_area": 211,
|
||||
"lookup_dcookie": 212,
|
||||
"epoll_create": 213,
|
||||
"epoll_ctl_old": 214,
|
||||
"epoll_wait_old": 215,
|
||||
"remap_file_pages": 216,
|
||||
"getdents64": 217,
|
||||
"set_tid_address": 218,
|
||||
"restart_": 219,
|
||||
"semtimedop": 220,
|
||||
"fadvise64": 221,
|
||||
"timer_create": 222,
|
||||
"timer_settime": 223,
|
||||
"timer_gettime": 224,
|
||||
"timer_getoverrun": 225,
|
||||
"timer_delete": 226,
|
||||
"clock_settime": 227,
|
||||
"clock_gettime": 228,
|
||||
"clock_getres": 229,
|
||||
"clock_nanosleep": 230,
|
||||
"exit_group": 231,
|
||||
"epoll_wait": 232,
|
||||
"epoll_ctl": 233,
|
||||
"tgkill": 234,
|
||||
"utimes": 235,
|
||||
"vserver": 236,
|
||||
"mbind": 237,
|
||||
"set_mempolicy": 238,
|
||||
"get_mempolicy": 239,
|
||||
"mq_open": 240,
|
||||
"mq_unlink": 241,
|
||||
"mq_timedsend": 242,
|
||||
"mq_timedreceive": 243,
|
||||
"mq_notify": 244,
|
||||
"mq_getsetattr": 245,
|
||||
"kexec_load": 246,
|
||||
"waitid": 247,
|
||||
"add_key": 248,
|
||||
"request_key": 249,
|
||||
"keyctl": 250,
|
||||
"ioprio_set": 251,
|
||||
"ioprio_get": 252,
|
||||
"inotify_init": 253,
|
||||
"inotify_add_watch": 254,
|
||||
"inotify_rm_watch": 255,
|
||||
"migrate_pages": 256,
|
||||
"openat": 257,
|
||||
"mkdirat": 258,
|
||||
"mknodat": 259,
|
||||
"fchownat": 260,
|
||||
"futimesat": 261,
|
||||
"newfstatat": 262,
|
||||
"unlinkat": 263,
|
||||
"renameat": 264,
|
||||
"linkat": 265,
|
||||
"symlinkat": 266,
|
||||
"readlinkat": 267,
|
||||
"fchmodat": 268,
|
||||
"faccessat": 269,
|
||||
"pselect6": 270,
|
||||
"ppoll": 271,
|
||||
"unshare": 272,
|
||||
"set_robust_list": 273,
|
||||
"get_robust_list": 274,
|
||||
"splice": 275,
|
||||
"tee": 276,
|
||||
"sync_file_range": 277,
|
||||
"vmsplice": 278,
|
||||
"move_pages": 279,
|
||||
"utimensat": 280,
|
||||
"epoll_pwait": 281,
|
||||
"signalfd": 282,
|
||||
"timerfd_create": 283,
|
||||
"eventfd": 284,
|
||||
"fallocate": 285,
|
||||
"timerfd_settime": 286,
|
||||
"timerfd_gettime": 287,
|
||||
"accept4": 288,
|
||||
"signalfd4": 289,
|
||||
"eventfd2": 290,
|
||||
"epoll_create1": 291,
|
||||
"dup3": 292,
|
||||
"pipe2": 293,
|
||||
"inotify_init1": 294,
|
||||
"preadv": 295,
|
||||
"pwritev": 296,
|
||||
"rt_tgsigqueueinfo": 297,
|
||||
"perf_event_open": 298,
|
||||
"recvmmsg": 299,
|
||||
"fanotify_init": 300,
|
||||
"fanotify_mark": 301,
|
||||
"prlimit64": 302,
|
||||
"name_to_handle_at": 303,
|
||||
"open_by_handle_at": 304,
|
||||
"clock_adjtime": 305,
|
||||
"syncfs": 306,
|
||||
"sendmmsg": 307,
|
||||
"setns": 308,
|
||||
"getcpu": 309,
|
||||
"process_vm_readv": 310,
|
||||
"process_vm_writev": 311,
|
||||
"kcmp": 312,
|
||||
"finit_module": 313,
|
||||
"sched_setattr": 314,
|
||||
"sched_getattr": 315,
|
||||
"renameat2": 316,
|
||||
"seccomp": 317,
|
||||
"getrandom": 318,
|
||||
"memfd_create": 319,
|
||||
"kexec_file_load": 320,
|
||||
"bpf": 321,
|
||||
"execveat": 322,
|
||||
"userfaultfd": 323,
|
||||
"membarrier": 324,
|
||||
"mlock2": 325,
|
||||
"copy_file_range": 326,
|
||||
}
|
333
vendor/github.com/mozilla/libaudit-go/headers/audit_x64_i2s.go
сгенерированный
поставляемый
Normal file
333
vendor/github.com/mozilla/libaudit-go/headers/audit_x64_i2s.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,333 @@
|
|||
package headers
|
||||
|
||||
// ReverseSysMapX64 is a mapping between x64 syscall integer values and their names
|
||||
// The list is taken from x86_64_table.h of auditd library
|
||||
var ReverseSysMapX64 = map[string]string{
|
||||
"0": "read",
|
||||
"1": "write",
|
||||
"2": "open",
|
||||
"3": "close",
|
||||
"4": "stat",
|
||||
"5": "fstat",
|
||||
"6": "lstat",
|
||||
"7": "poll",
|
||||
"8": "lseek",
|
||||
"9": "mmap",
|
||||
"10": "mprotect",
|
||||
"11": "munmap",
|
||||
"12": "brk",
|
||||
"13": "rt_sigaction",
|
||||
"14": "rt_sigprocmask",
|
||||
"15": "rt_sigreturn",
|
||||
"16": "ioctl",
|
||||
"17": "pread64",
|
||||
"18": "pwrite64",
|
||||
"19": "readv",
|
||||
"20": "writev",
|
||||
"21": "access",
|
||||
"22": "pipe",
|
||||
"23": "select",
|
||||
"24": "sched_yield",
|
||||
"25": "mremap",
|
||||
"26": "msync",
|
||||
"27": "mincore",
|
||||
"28": "madvise",
|
||||
"29": "shmget",
|
||||
"30": "shmat",
|
||||
"31": "shmctl",
|
||||
"32": "dup",
|
||||
"33": "dup2",
|
||||
"34": "pause",
|
||||
"35": "nanosleep",
|
||||
"36": "getitimer",
|
||||
"37": "alarm",
|
||||
"38": "setitimer",
|
||||
"39": "getpid",
|
||||
"40": "sendfile",
|
||||
"41": "socket",
|
||||
"42": "connect",
|
||||
"43": "accept",
|
||||
"44": "sendto",
|
||||
"45": "recvfrom",
|
||||
"46": "sendmsg",
|
||||
"47": "recvmsg",
|
||||
"48": "shutdown",
|
||||
"49": "bind",
|
||||
"50": "listen",
|
||||
"51": "getsockname",
|
||||
"52": "getpeername",
|
||||
"53": "socketpair",
|
||||
"54": "setsockopt",
|
||||
"55": "getsockopt",
|
||||
"56": "clone",
|
||||
"57": "fork",
|
||||
"58": "vfork",
|
||||
"59": "execve",
|
||||
"60": "exit",
|
||||
"61": "wait4",
|
||||
"62": "kill",
|
||||
"63": "uname",
|
||||
"64": "semget",
|
||||
"65": "semop",
|
||||
"66": "semctl",
|
||||
"67": "shmdt",
|
||||
"68": "msgget",
|
||||
"69": "msgsnd",
|
||||
"70": "msgrcv",
|
||||
"71": "msgctl",
|
||||
"72": "fcntl",
|
||||
"73": "flock",
|
||||
"74": "fsync",
|
||||
"75": "fdatasync",
|
||||
"76": "truncate",
|
||||
"77": "ftruncate",
|
||||
"78": "getdents",
|
||||
"79": "getcwd",
|
||||
"80": "chdir",
|
||||
"81": "fchdir",
|
||||
"82": "rename",
|
||||
"83": "mkdir",
|
||||
"84": "rmdir",
|
||||
"85": "creat",
|
||||
"86": "link",
|
||||
"87": "unlink",
|
||||
"88": "symlink",
|
||||
"89": "readlink",
|
||||
"90": "chmod",
|
||||
"91": "fchmod",
|
||||
"92": "chown",
|
||||
"93": "fchown",
|
||||
"94": "lchown",
|
||||
"95": "umask",
|
||||
"96": "gettimeofday",
|
||||
"97": "getrlimit",
|
||||
"98": "getrusage",
|
||||
"99": "sysinfo",
|
||||
"100": "times",
|
||||
"101": "ptrace",
|
||||
"102": "getuid",
|
||||
"103": "syslog",
|
||||
"104": "getgid",
|
||||
"105": "setuid",
|
||||
"106": "setgid",
|
||||
"107": "geteuid",
|
||||
"108": "getegid",
|
||||
"109": "setpgid",
|
||||
"110": "getppid",
|
||||
"111": "getpgrp",
|
||||
"112": "setsid",
|
||||
"113": "setreuid",
|
||||
"114": "setregid",
|
||||
"115": "getgroups",
|
||||
"116": "setgroups",
|
||||
"117": "setresuid",
|
||||
"118": "getresuid",
|
||||
"119": "setresgid",
|
||||
"120": "getresgid",
|
||||
"121": "getpgid",
|
||||
"122": "setfsuid",
|
||||
"123": "setfsgid",
|
||||
"124": "getsid",
|
||||
"125": "capget",
|
||||
"126": "capset",
|
||||
"127": "rt_sigpending",
|
||||
"128": "rt_sigtimedwait",
|
||||
"129": "rt_sigqueueinfo",
|
||||
"130": "rt_sigsuspend",
|
||||
"131": "sigaltstack",
|
||||
"132": "utime",
|
||||
"133": "mknod",
|
||||
"134": "uselib",
|
||||
"135": "personality",
|
||||
"136": "ustat",
|
||||
"137": "statfs",
|
||||
"138": "fstatfs",
|
||||
"139": "sysfs",
|
||||
"140": "getpriority",
|
||||
"141": "setpriority",
|
||||
"142": "sched_setparam",
|
||||
"143": "sched_getparam",
|
||||
"144": "sched_setscheduler",
|
||||
"145": "sched_getscheduler",
|
||||
"146": "sched_get_priority_max",
|
||||
"147": "sched_get_priority_min",
|
||||
"148": "sched_rr_get_interval",
|
||||
"149": "mlock",
|
||||
"150": "munlock",
|
||||
"151": "mlockall",
|
||||
"152": "munlockall",
|
||||
"153": "vhangup",
|
||||
"154": "modify_ldt",
|
||||
"155": "pivot_root",
|
||||
"156": "_sysctl",
|
||||
"157": "prctl",
|
||||
"158": "arch_prctl",
|
||||
"159": "adjtimex",
|
||||
"160": "setrlimit",
|
||||
"161": "chroot",
|
||||
"162": "sync",
|
||||
"163": "acct",
|
||||
"164": "settimeofday",
|
||||
"165": "mount",
|
||||
"166": "umount2",
|
||||
"167": "swapon",
|
||||
"168": "swapoff",
|
||||
"169": "reboot",
|
||||
"170": "sethostname",
|
||||
"171": "setdomainname",
|
||||
"172": "iopl",
|
||||
"173": "ioperm",
|
||||
"174": "create_module",
|
||||
"175": "init_module",
|
||||
"176": "delete_module",
|
||||
"177": "get_kernel_syms",
|
||||
"178": "query_module",
|
||||
"179": "quotactl",
|
||||
"180": "nfsservctl",
|
||||
"181": "getpmsg",
|
||||
"182": "putpmsg",
|
||||
"183": "afs_",
|
||||
"184": "tuxcall",
|
||||
"185": "security",
|
||||
"186": "gettid",
|
||||
"187": "readahead",
|
||||
"188": "setxattr",
|
||||
"189": "lsetxattr",
|
||||
"190": "fsetxattr",
|
||||
"191": "getxattr",
|
||||
"192": "lgetxattr",
|
||||
"193": "fgetxattr",
|
||||
"194": "listxattr",
|
||||
"195": "llistxattr",
|
||||
"196": "flistxattr",
|
||||
"197": "removexattr",
|
||||
"198": "lremovexattr",
|
||||
"199": "fremovexattr",
|
||||
"200": "tkill",
|
||||
"201": "time",
|
||||
"202": "futex",
|
||||
"203": "sched_setaffinity",
|
||||
"204": "sched_getaffinity",
|
||||
"205": "set_thread_area",
|
||||
"206": "io_setup",
|
||||
"207": "io_destroy",
|
||||
"208": "io_getevents",
|
||||
"209": "io_submit",
|
||||
"210": "io_cancel",
|
||||
"211": "get_thread_area",
|
||||
"212": "lookup_dcookie",
|
||||
"213": "epoll_create",
|
||||
"214": "epoll_ctl_old",
|
||||
"215": "epoll_wait_old",
|
||||
"216": "remap_file_pages",
|
||||
"217": "getdents64",
|
||||
"218": "set_tid_address",
|
||||
"219": "restart_",
|
||||
"220": "semtimedop",
|
||||
"221": "fadvise64",
|
||||
"222": "timer_create",
|
||||
"223": "timer_settime",
|
||||
"224": "timer_gettime",
|
||||
"225": "timer_getoverrun",
|
||||
"226": "timer_delete",
|
||||
"227": "clock_settime",
|
||||
"228": "clock_gettime",
|
||||
"229": "clock_getres",
|
||||
"230": "clock_nanosleep",
|
||||
"231": "exit_group",
|
||||
"232": "epoll_wait",
|
||||
"233": "epoll_ctl",
|
||||
"234": "tgkill",
|
||||
"235": "utimes",
|
||||
"236": "vserver",
|
||||
"237": "mbind",
|
||||
"238": "set_mempolicy",
|
||||
"239": "get_mempolicy",
|
||||
"240": "mq_open",
|
||||
"241": "mq_unlink",
|
||||
"242": "mq_timedsend",
|
||||
"243": "mq_timedreceive",
|
||||
"244": "mq_notify",
|
||||
"245": "mq_getsetattr",
|
||||
"246": "kexec_load",
|
||||
"247": "waitid",
|
||||
"248": "add_key",
|
||||
"249": "request_key",
|
||||
"250": "keyctl",
|
||||
"251": "ioprio_set",
|
||||
"252": "ioprio_get",
|
||||
"253": "inotify_init",
|
||||
"254": "inotify_add_watch",
|
||||
"255": "inotify_rm_watch",
|
||||
"256": "migrate_pages",
|
||||
"257": "openat",
|
||||
"258": "mkdirat",
|
||||
"259": "mknodat",
|
||||
"260": "fchownat",
|
||||
"261": "futimesat",
|
||||
"262": "newfstatat",
|
||||
"263": "unlinkat",
|
||||
"264": "renameat",
|
||||
"265": "linkat",
|
||||
"266": "symlinkat",
|
||||
"267": "readlinkat",
|
||||
"268": "fchmodat",
|
||||
"269": "faccessat",
|
||||
"270": "pselect6",
|
||||
"271": "ppoll",
|
||||
"272": "unshare",
|
||||
"273": "set_robust_list",
|
||||
"274": "get_robust_list",
|
||||
"275": "splice",
|
||||
"276": "tee",
|
||||
"277": "sync_file_range",
|
||||
"278": "vmsplice",
|
||||
"279": "move_pages",
|
||||
"280": "utimensat",
|
||||
"281": "epoll_pwait",
|
||||
"282": "signalfd",
|
||||
"283": "timerfd_create",
|
||||
"284": "eventfd",
|
||||
"285": "fallocate",
|
||||
"286": "timerfd_settime",
|
||||
"287": "timerfd_gettime",
|
||||
"288": "accept4",
|
||||
"289": "signalfd4",
|
||||
"290": "eventfd2",
|
||||
"291": "epoll_create1",
|
||||
"292": "dup3",
|
||||
"293": "pipe2",
|
||||
"294": "inotify_init1",
|
||||
"295": "preadv",
|
||||
"296": "pwritev",
|
||||
"297": "rt_tgsigqueueinfo",
|
||||
"298": "perf_event_open",
|
||||
"299": "recvmmsg",
|
||||
"300": "fanotify_init",
|
||||
"301": "fanotify_mark",
|
||||
"302": "prlimit64",
|
||||
"303": "name_to_handle_at",
|
||||
"304": "open_by_handle_at",
|
||||
"305": "clock_adjtime",
|
||||
"306": "syncfs",
|
||||
"307": "sendmmsg",
|
||||
"308": "setns",
|
||||
"309": "getcpu",
|
||||
"310": "process_vm_readv",
|
||||
"311": "process_vm_writev",
|
||||
"312": "kcmp",
|
||||
"313": "finit_module",
|
||||
"314": "sched_setattr",
|
||||
"315": "sched_getattr",
|
||||
"316": "renameat2",
|
||||
"317": "seccomp",
|
||||
"318": "getrandom",
|
||||
"319": "memfd_create",
|
||||
"320": "kexec_file_load",
|
||||
"321": "bpf",
|
||||
"322": "execveat",
|
||||
"323": "userfaultfd",
|
||||
"324": "membarrier",
|
||||
"325": "mlock2",
|
||||
"326": "copy_file_range",
|
||||
}
|
43
vendor/github.com/mozilla/libaudit-go/headers/cap_tab.go
сгенерированный
поставляемый
Normal file
43
vendor/github.com/mozilla/libaudit-go/headers/cap_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,43 @@
|
|||
package headers
|
||||
|
||||
//Location: include/uapi/linux/capability.h
|
||||
var CapabLookup = map[int]string{
|
||||
0: "chown",
|
||||
1: "dac_override",
|
||||
2: "dac_read_search",
|
||||
3: "fowner",
|
||||
4: "fsetid",
|
||||
5: "kill",
|
||||
6: "setgid",
|
||||
7: "setuid",
|
||||
8: "setpcap",
|
||||
9: "linux_immutable",
|
||||
10: "net_bind_service",
|
||||
11: "net_broadcast",
|
||||
12: "net_admin",
|
||||
13: "net_raw",
|
||||
14: "ipc_lock",
|
||||
15: "ipc_owner",
|
||||
16: "sys_module",
|
||||
17: "sys_rawio",
|
||||
18: "sys_chroot",
|
||||
19: "sys_ptrace",
|
||||
20: "sys_pacct",
|
||||
21: "sys_admin",
|
||||
22: "sys_boot",
|
||||
23: "sys_nice",
|
||||
24: "sys_resource",
|
||||
25: "sys_time",
|
||||
26: "sys_tty_config",
|
||||
27: "mknod",
|
||||
28: "lease",
|
||||
29: "audit_write",
|
||||
30: "audit_control",
|
||||
31: "setfcap",
|
||||
32: "mac_override",
|
||||
33: "mac_admin",
|
||||
34: "syslog",
|
||||
35: "wake_alarm",
|
||||
36: "block_suspend",
|
||||
37: "audit_read",
|
||||
}
|
17
vendor/github.com/mozilla/libaudit-go/headers/clock_tab.go
сгенерированный
поставляемый
Normal file
17
vendor/github.com/mozilla/libaudit-go/headers/clock_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,17 @@
|
|||
package headers
|
||||
|
||||
//Location: include/uapi/linux/time.h
|
||||
var ClockLookup = map[int]string{
|
||||
0: "CLOCK_REALTIME",
|
||||
1: "CLOCK_MONOTONIC",
|
||||
2: "CLOCK_PROCESS_CPUTIME_ID",
|
||||
3: "CLOCK_THREAD_CPUTIME_ID",
|
||||
4: "CLOCK_MONOTONIC_RAW",
|
||||
5: "CLOCK_REALTIME_COARSE",
|
||||
6: "CLOCK_MONOTONIC_COARSE",
|
||||
7: "CLOCK_BOOTTIME",
|
||||
8: "CLOCK_REALTIME_ALARM",
|
||||
9: "CLOCK_BOOTTIME_ALARM",
|
||||
10: "CLOCK_SGI_CYCLE",
|
||||
11: "CLOCK_TAI",
|
||||
}
|
28
vendor/github.com/mozilla/libaudit-go/headers/cloneflag_tab.go
сгенерированный
поставляемый
Normal file
28
vendor/github.com/mozilla/libaudit-go/headers/cloneflag_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,28 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/sched.h
|
||||
var CloneLookUp = map[int]string{
|
||||
0x00000100: "CLONE_VM",
|
||||
0x00000200: "CLONE_FS",
|
||||
0x00000400: "CLONE_FILES",
|
||||
0x00000800: "CLONE_SIGHAND",
|
||||
0x00002000: "CLONE_PTRACE",
|
||||
0x00004000: "CLONE_VFORK",
|
||||
0x00008000: "CLONE_PARENT",
|
||||
0x00010000: "CLONE_THREAD",
|
||||
0x00020000: "CLONE_NEWNS",
|
||||
0x00040000: "CLONE_SYSVSEM",
|
||||
0x00080000: "CLONE_SETTLS",
|
||||
0x00100000: "CLONE_PARENT_SETTID",
|
||||
0x00200000: "CLONE_CHILD_CLEARTID",
|
||||
0x00400000: "CLONE_DETACHED",
|
||||
0x00800000: "CLONE_UNTRACED",
|
||||
0x01000000: "CLONE_CHILD_SETTID",
|
||||
0x02000000: "CLONE_STOPPED",
|
||||
0x04000000: "CLONE_NEWUTS",
|
||||
0x08000000: "CLONE_NEWIPC",
|
||||
0x10000000: "CLONE_NEWUSER",
|
||||
0x20000000: "CLONE_NEWPID",
|
||||
0x40000000: "CLONE_NEWNET",
|
||||
0x80000000: "CLONE_IO",
|
||||
}
|
8
vendor/github.com/mozilla/libaudit-go/headers/epollctl_tab.go
сгенерированный
поставляемый
Normal file
8
vendor/github.com/mozilla/libaudit-go/headers/epollctl_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,8 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/eventpoll.h
|
||||
var EpollLookup = map[int]string{
|
||||
1: "EPOLL_CTL_ADD",
|
||||
2: "EPOLL_CTL_DEL",
|
||||
3: "EPOLL_CTL_MOD",
|
||||
}
|
33
vendor/github.com/mozilla/libaudit-go/headers/fcntl_cmd_tab.go
сгенерированный
поставляемый
Normal file
33
vendor/github.com/mozilla/libaudit-go/headers/fcntl_cmd_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,33 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/asm-generic/fcntl.h <17
|
||||
// include/uapi/linux/fcntl.h >= 1024
|
||||
var FcntlLookup = map[int]string{
|
||||
0: "F_DUPFD",
|
||||
1: "F_GETFD",
|
||||
2: "F_SETFD",
|
||||
3: "F_GETFL",
|
||||
4: "F_SETFL",
|
||||
5: "F_GETLK",
|
||||
6: "F_SETLK",
|
||||
7: "F_SETLKW",
|
||||
8: "F_SETOWN",
|
||||
9: "F_GETOWN",
|
||||
10: "F_SETSIG",
|
||||
11: "F_GETSIG",
|
||||
12: "F_GETLK64",
|
||||
13: "F_SETLK64",
|
||||
14: "F_SETLKW64",
|
||||
15: "F_SETOWN_EX",
|
||||
16: "F_GETOWN_EX",
|
||||
17: "F_GETOWNER_UIDS",
|
||||
1024: "F_SETLEASE",
|
||||
1025: "F_GETLEASE",
|
||||
1026: "F_NOTIFY",
|
||||
1029: "F_CANCELLK",
|
||||
1030: "F_DUPFD_CLOEXEC",
|
||||
1031: "F_SETPIPE_SZ",
|
||||
1032: "F_GETPIPE_SZ",
|
||||
1033: "F_ADD_SEALS",
|
||||
1034: "F_GET_SEALS",
|
||||
}
|
46
vendor/github.com/mozilla/libaudit-go/headers/field_tab.go
сгенерированный
поставляемый
Normal file
46
vendor/github.com/mozilla/libaudit-go/headers/field_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,46 @@
|
|||
package headers
|
||||
|
||||
var FieldMap = map[string]int{
|
||||
"pid": 0,
|
||||
"uid": 1,
|
||||
"euid": 2,
|
||||
"suid": 3,
|
||||
"fsuid": 4,
|
||||
"gid": 5,
|
||||
"egid": 6,
|
||||
"sgid": 7,
|
||||
"fsgid": 8,
|
||||
"auid": 9,
|
||||
"loginuid": 9,
|
||||
"pers": 10,
|
||||
"arch": 11,
|
||||
"msgtype": 12,
|
||||
"subj_user": 13,
|
||||
"subj_role": 14,
|
||||
"subj_type": 15,
|
||||
"subj_sen": 16,
|
||||
"subj_clr": 17,
|
||||
"ppid": 18,
|
||||
"obj_user": 19,
|
||||
"obj_role": 20,
|
||||
"obj_type": 21,
|
||||
"obj_lev_low": 22,
|
||||
"obj_lev_high": 23,
|
||||
"devmajor": 100,
|
||||
"devminor": 101,
|
||||
"inode": 102,
|
||||
"exit": 103,
|
||||
"success": 104,
|
||||
"path": 105,
|
||||
"perm": 106,
|
||||
"dir": 107,
|
||||
"filetype": 108,
|
||||
"obj_uid": 109,
|
||||
"obj_gid": 110,
|
||||
"field_compare": 111,
|
||||
"a0": 200,
|
||||
"a1": 201,
|
||||
"a2": 202,
|
||||
"a3": 203,
|
||||
"key": 210,
|
||||
}
|
11
vendor/github.com/mozilla/libaudit-go/headers/ftype_tab.go
сгенерированный
поставляемый
Normal file
11
vendor/github.com/mozilla/libaudit-go/headers/ftype_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,11 @@
|
|||
package headers
|
||||
|
||||
var FtypeTab = map[string]int{
|
||||
"block": 24576,
|
||||
"character": 8192,
|
||||
"dir": 16384,
|
||||
"fifo": 4096,
|
||||
"file": 32768,
|
||||
"link": 40960,
|
||||
"socket": 49152,
|
||||
}
|
18
vendor/github.com/mozilla/libaudit-go/headers/icmptype_tab.go
сгенерированный
поставляемый
Normal file
18
vendor/github.com/mozilla/libaudit-go/headers/icmptype_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,18 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/icmp.h
|
||||
var IcmpLookup = map[int]string{
|
||||
0: "echo-reply",
|
||||
3: "destination-unreachable",
|
||||
4: "source-quench",
|
||||
5: "redirect",
|
||||
8: "echo",
|
||||
11: "time-exceeded",
|
||||
12: "parameter-problem",
|
||||
13: "timestamp-request",
|
||||
14: "timestamp-reply",
|
||||
15: "info-request",
|
||||
16: "info-reply",
|
||||
17: "address-mask-request",
|
||||
18: "address-mask-reply",
|
||||
}
|
39
vendor/github.com/mozilla/libaudit-go/headers/ioctlreq_tab.go
сгенерированный
поставляемый
Normal file
39
vendor/github.com/mozilla/libaudit-go/headers/ioctlreq_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,39 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/kd.h
|
||||
// include/uapi/linux/cdrom.h
|
||||
// include/uapi/asm-generic/ioctls.h
|
||||
// include/uapi/drm/drm.h
|
||||
|
||||
var IoctlLookup = map[int]string{
|
||||
0x4B3A: "KDSETMODE",
|
||||
0x4B3B: "KDGETMODE",
|
||||
0x5309: "CDROMEJECT",
|
||||
0x530F: "CDROMEJECT_SW",
|
||||
0x5311: "CDROM_GET_UPC",
|
||||
0x5316: "CDROMSEEK",
|
||||
0x5401: "TCGETS",
|
||||
0x5402: "TCSETS",
|
||||
0x5403: "TCSETSW",
|
||||
0x5404: "TCSETSF",
|
||||
0x5409: "TCSBRK",
|
||||
0x540B: "TCFLSH",
|
||||
0x540E: "TIOCSCTTY",
|
||||
0x540F: "TIOCGPGRP",
|
||||
0x5410: "TIOCSPGRP",
|
||||
0x5413: "TIOCGWINSZ",
|
||||
0x5414: "TIOCSWINSZ",
|
||||
0x541B: "TIOCINQ",
|
||||
0x5421: "FIONBIO",
|
||||
0x8901: "FIOSETOWN",
|
||||
0x8903: "FIOGETOWN",
|
||||
0x8910: "SIOCGIFNAME",
|
||||
0x8927: "SIOCGIFHWADDR",
|
||||
0x8933: "SIOCGIFINDEX",
|
||||
0x89a2: "SIOCBRADDIF",
|
||||
0x40045431: "TIOCSPTLCK",
|
||||
0x80045430: "TIOCGPTN",
|
||||
0x80045431: "TIOCSPTLCK",
|
||||
0xC01C64A3: "DRM_IOCTL_MODE_CURSOR",
|
||||
0xC01864B0: "DRM_IOCTL_MODE_PAGE_FLIP",
|
||||
0xC01864B1: "DRM_IOCTL_MODE_DIRTYFB"}
|
70
vendor/github.com/mozilla/libaudit-go/headers/ip6optname_tab.go
сгенерированный
поставляемый
Normal file
70
vendor/github.com/mozilla/libaudit-go/headers/ip6optname_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,70 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/in6.h
|
||||
// include/uapi/linux/netfilter_ipv6/ip6_tables.h
|
||||
// include/uapi/linux/mroute6.h
|
||||
|
||||
var Ip6OptLookup = map[int]string{
|
||||
1: "IPV6_ADDRFORM",
|
||||
2: "IPV6_2292PKTINFO",
|
||||
3: "IPV6_2292HOPOPTS",
|
||||
4: "IPV6_2292DSTOPTS",
|
||||
5: "IPV6_2292RTHDR",
|
||||
6: "IPV6_2292PKTOPTIONS",
|
||||
7: "IPV6_CHECKSUM",
|
||||
8: "IPV6_2292HOPLIMIT",
|
||||
9: "IPV6_NEXTHOP",
|
||||
10: "IPV6_AUTHHDR",
|
||||
11: "IPV6_FLOWINFO",
|
||||
16: "IPV6_UNICAST_HOPS",
|
||||
17: "IPV6_MULTICAST_IF",
|
||||
18: "IPV6_MULTICAST_HOPS",
|
||||
19: "IPV6_MULTICAST_LOOP",
|
||||
20: "IPV6_ADD_MEMBERSHIP",
|
||||
21: "IPV6_DROP_MEMBERSHIP",
|
||||
22: "IPV6_ROUTER_ALERT",
|
||||
23: "IPV6_MTU_DISCOVER",
|
||||
24: "IPV6_MTU",
|
||||
25: "IPV6_RECVERR",
|
||||
26: "IPV6_V6ONLY",
|
||||
27: "IPV6_JOIN_ANYCAST",
|
||||
28: "IPV6_LEAVE_ANYCAST",
|
||||
32: "IPV6_FLOWLABEL_MGR",
|
||||
33: "IPV6_FLOWINFO_SEND",
|
||||
34: "IPV6_IPSEC_POLICY",
|
||||
35: "IPV6_XFRM_POLICY",
|
||||
42: "MCAST_JOIN_GROUP",
|
||||
43: "MCAST_BLOCK_SOURCE",
|
||||
44: "MCAST_UNBLOCK_SOURCE",
|
||||
45: "MCAST_LEAVE_GROUP",
|
||||
46: "MCAST_JOIN_SOURCE_GROUP",
|
||||
47: "MCAST_LEAVE_SOURCE_GROUP",
|
||||
48: "MCAST_MSFILTER",
|
||||
49: "IPV6_RECVPKTINFO",
|
||||
50: "IPV6_PKTINFO",
|
||||
51: "IPV6_RECVHOPLIMIT",
|
||||
52: "IPV6_HOPLIMIT",
|
||||
53: "IPV6_RECVHOPOPTS",
|
||||
54: "IPV6_HOPOPTS",
|
||||
55: "IPV6_RTHDRDSTOPTS",
|
||||
56: "IPV6_RECVRTHDR",
|
||||
57: "IPV6_RTHDR",
|
||||
58: "IPV6_RECVDSTOPTS",
|
||||
59: "IPV6_DSTOPTS",
|
||||
60: "IPV6_RECVPATHMTU",
|
||||
61: "IPV6_PATHMTU",
|
||||
62: "IPV6_DONTFRAG",
|
||||
63: "IPV6_USE_MIN_MTU",
|
||||
64: "IP6T_SO_SET_REPLACE",
|
||||
65: "IP6T_SO_SET_ADD_COUNTERS",
|
||||
66: "IPV6_RECVTCLASS",
|
||||
67: "IPV6_TCLASS",
|
||||
68: "IP6T_SO_GET_REVISION_MATCH",
|
||||
69: "IP6T_SO_GET_REVISION_TARGET",
|
||||
72: "IPV6_ADDR_PREFERENCES",
|
||||
73: "IPV6_MINHOPCOUNT",
|
||||
74: "IPV6_ORIGDSTADDR",
|
||||
75: "IPV6_TRANSPARENT",
|
||||
76: "IPV6_UNICAST_IF",
|
||||
80: "IP6T_SO_ORIGINAL_DST",
|
||||
}
|
19
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go
сгенерированный
поставляемый
Normal file
19
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,19 @@
|
|||
package headers
|
||||
|
||||
import "syscall"
|
||||
|
||||
// Location: include/uapi/linux/ipc.h
|
||||
var IpccallLookup = map[int]string{
|
||||
syscall.SYS_SEMOP: "semop",
|
||||
syscall.SYS_SEMGET: "semget",
|
||||
syscall.SYS_SEMCTL: "semctl",
|
||||
4: "semtimedop",
|
||||
syscall.SYS_MSGSND: "msgsnd",
|
||||
syscall.SYS_MSGRCV: "msgrcv",
|
||||
syscall.SYS_MSGGET: "msgget",
|
||||
syscall.SYS_MSGCTL: "msgctl",
|
||||
syscall.SYS_SHMAT: "shmat",
|
||||
syscall.SYS_SHMDT: "shmdt",
|
||||
syscall.SYS_SHMGET: "shmget",
|
||||
syscall.SYS_SHMCTL: "shmctl",
|
||||
}
|
50
vendor/github.com/mozilla/libaudit-go/headers/ipoptname_tab.go
сгенерированный
поставляемый
Normal file
50
vendor/github.com/mozilla/libaudit-go/headers/ipoptname_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,50 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/in.h
|
||||
// include/uapi/linux/netfilter_ipv4/ip_tables.h
|
||||
var IpOptLookup = map[int]string{
|
||||
1: "IP_TOS",
|
||||
2: "IP_TTL",
|
||||
3: "IP_HDRINCL",
|
||||
4: "IP_OPTIONS",
|
||||
5: "IP_ROUTER_ALERT",
|
||||
6: "IP_RECVOPTS",
|
||||
7: "IP_RETOPTS",
|
||||
8: "IP_PKTINFO",
|
||||
9: "IP_PKTOPTIONS",
|
||||
10: "IP_MTU_DISCOVER",
|
||||
11: "IP_RECVERR",
|
||||
12: "IP_RECVTTL",
|
||||
14: "IP_MTU",
|
||||
15: "IP_FREEBIND",
|
||||
16: "IP_IPSEC_POLICY",
|
||||
17: "IP_XFRM_POLICY",
|
||||
18: "IP_PASSSEC",
|
||||
19: "IP_TRANSPARENT",
|
||||
20: "IP_ORIGDSTADDR",
|
||||
21: "IP_MINTTL",
|
||||
22: "IP_NODEFRAG",
|
||||
23: "IP_CHECKSUM",
|
||||
32: "IP_MULTICAST_IF",
|
||||
33: "IP_MULTICAST_TTL",
|
||||
34: "IP_MULTICAST_LOOP",
|
||||
35: "IP_ADD_MEMBERSHIP",
|
||||
36: "IP_DROP_MEMBERSHIP",
|
||||
37: "IP_UNBLOCK_SOURCE",
|
||||
38: "IP_BLOCK_SOURCE",
|
||||
39: "IP_ADD_SOURCE_MEMBERSHIP",
|
||||
40: "IP_DROP_SOURCE_MEMBERSHIP",
|
||||
41: "IP_MSFILTER",
|
||||
42: "MCAST_JOIN_GROUP",
|
||||
43: "MCAST_BLOCK_SOURCE",
|
||||
44: "MCAST_UNBLOCK_SOURCE",
|
||||
45: "MCAST_LEAVE_GROUP",
|
||||
46: "MCAST_JOIN_SOURCE_GROUP",
|
||||
47: "MCAST_LEAVE_SOURCE_GROUP",
|
||||
48: "MCAST_MSFILTER",
|
||||
49: "IP_MULTICAST_ALL",
|
||||
50: "IP_UNICAST_IF",
|
||||
64: "IPT_SO_SET_REPLACE",
|
||||
65: "IPT_SO_SET_ADD_COUNTERS",
|
||||
66: "IPT_SO_GET_REVISION_TARGET",
|
||||
}
|
20
vendor/github.com/mozilla/libaudit-go/headers/mmap_tab.go
сгенерированный
поставляемый
Normal file
20
vendor/github.com/mozilla/libaudit-go/headers/mmap_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,20 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/asm-generic/mman.h >0x100
|
||||
// include/uapi/asm-generic/mman-common.h < 0x100
|
||||
var MmapLookUp = map[int]string{
|
||||
0x00001: "MAP_SHARED",
|
||||
0x00002: "MAP_PRIVATE",
|
||||
0x00010: "MAP_FIXED",
|
||||
0x00020: "MAP_ANONYMOUS",
|
||||
0x00040: "MAP_32BIT",
|
||||
0x00100: "MAP_GROWSDOWN",
|
||||
0x00800: "MAP_DENYWRITE",
|
||||
0x01000: "MAP_EXECUTABLE",
|
||||
0x02000: "MAP_LOCKED",
|
||||
0x04000: "MAP_NORESERVE",
|
||||
0x08000: "MAP_POPULATE",
|
||||
0x10000: "MAP_NONBLOCK",
|
||||
0x20000: "MAP_STACK",
|
||||
0x40000: "MAP_HUGETLB",
|
||||
}
|
36
vendor/github.com/mozilla/libaudit-go/headers/mount_tab.go
сгенерированный
поставляемый
Normal file
36
vendor/github.com/mozilla/libaudit-go/headers/mount_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,36 @@
|
|||
package headers
|
||||
|
||||
import "syscall"
|
||||
|
||||
// Location: include/uapi/linux/fs.h
|
||||
// when updating look at printMount
|
||||
var MountLookUp = map[int]string{
|
||||
syscall.MS_RDONLY: "MS_RDONLY",
|
||||
syscall.MS_NOSUID: "MS_NOSUID",
|
||||
syscall.MS_NODEV: "MS_NODEV",
|
||||
syscall.MS_NOEXEC: "MS_NOEXEC",
|
||||
syscall.MS_SYNCHRONOUS: "MS_SYNCHRONOUS",
|
||||
syscall.MS_REMOUNT: "MS_REMOUNT",
|
||||
syscall.MS_MANDLOCK: "MS_MANDLOCK",
|
||||
syscall.MS_DIRSYNC: "MS_DIRSYNC",
|
||||
syscall.MS_NOATIME: "MS_NOATIME",
|
||||
syscall.MS_NODIRATIME: "MS_NODIRATIME",
|
||||
syscall.MS_BIND: "MS_BIND",
|
||||
syscall.MS_MOVE: "MS_MOVE",
|
||||
syscall.MS_REC: "MS_REC",
|
||||
syscall.MS_SILENT: "MS_SILENT",
|
||||
syscall.MS_POSIXACL: "MS_POSIXACL",
|
||||
syscall.MS_UNBINDABLE: "MS_UNBINDABLE",
|
||||
syscall.MS_PRIVATE: "MS_PRIVATE",
|
||||
syscall.MS_SLAVE: "MS_SLAVE",
|
||||
syscall.MS_SHARED: "MS_SHARED",
|
||||
syscall.MS_RELATIME: "MS_RELATIME",
|
||||
syscall.MS_KERNMOUNT: "MS_KERNMOUNT",
|
||||
syscall.MS_I_VERSION: "MS_I_VERSION",
|
||||
1 << 24: "MS_STRICTATIME",
|
||||
1 << 27: "MS_SNAP_STABLE",
|
||||
1 << 28: "MS_NOSEC",
|
||||
1 << 29: "MS_BORN",
|
||||
syscall.MS_ACTIVE: "MS_ACTIVE",
|
||||
syscall.MS_NOUSER: "MS_NOUSER",
|
||||
}
|
12
vendor/github.com/mozilla/libaudit-go/headers/nfproto_tab.go
сгенерированный
поставляемый
Normal file
12
vendor/github.com/mozilla/libaudit-go/headers/nfproto_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,12 @@
|
|||
package headers
|
||||
|
||||
//Location: include/uapi/linux/netfilter.h
|
||||
var NfProtoLookup = map[int]string{
|
||||
0: "unspecified",
|
||||
1: "inet",
|
||||
2: "ipv4",
|
||||
3: "arp",
|
||||
7: "bridge",
|
||||
10: "ipv6",
|
||||
12: "decnet",
|
||||
}
|
24
vendor/github.com/mozilla/libaudit-go/headers/pktoptname_tab.go
сгенерированный
поставляемый
Normal file
24
vendor/github.com/mozilla/libaudit-go/headers/pktoptname_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,24 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/if_packet.h
|
||||
var PktOptLookup = map[int]string{
|
||||
1: "PACKET_ADD_MEMBERSHIP",
|
||||
2: "PACKET_DROP_MEMBERSHIP",
|
||||
3: "PACKET_RECV_OUTPUT",
|
||||
5: "PACKET_RX_RING",
|
||||
6: "PACKET_STATISTICS",
|
||||
7: "PACKET_COPY_THRESH",
|
||||
8: "PACKET_AUXDATA",
|
||||
9: "PACKET_ORIGDEV",
|
||||
10: "PACKET_VERSION",
|
||||
11: "PACKET_HDRLEN",
|
||||
12: "PACKET_RESERVE",
|
||||
13: "PACKET_TX_RING",
|
||||
14: "PACKET_LOSS",
|
||||
15: "PACKET_VNET_HDR",
|
||||
16: "PACKET_TX_TIMESTAMP",
|
||||
17: "PACKET_TIMESTAMP",
|
||||
18: "PACKET_FANOUT",
|
||||
19: "PACKET_TX_HAS_OFF",
|
||||
20: "PACKET_QDISC_BYPASS",
|
||||
}
|
51
vendor/github.com/mozilla/libaudit-go/headers/prctl_opt_tab.go
сгенерированный
поставляемый
Normal file
51
vendor/github.com/mozilla/libaudit-go/headers/prctl_opt_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,51 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/prctl.h
|
||||
|
||||
var PrctlLookup = map[int]string{
|
||||
1: "PR_SET_PDEATHSIG",
|
||||
2: "PR_GET_PDEATHSIG",
|
||||
3: "PR_GET_DUMPABLE",
|
||||
4: "PR_SET_DUMPABLE",
|
||||
5: "PR_GET_UNALIGN",
|
||||
6: "PR_SET_UNALIGN",
|
||||
7: "PR_GET_KEEPCAPS",
|
||||
8: "PR_SET_KEEPCAPS",
|
||||
9: "PR_GET_FPEMU",
|
||||
10: "PR_SET_FPEMU",
|
||||
11: "PR_GET_FPEXC",
|
||||
12: "PR_SET_FPEXC",
|
||||
13: "PR_GET_TIMING",
|
||||
14: "PR_SET_TIMING",
|
||||
15: "PR_SET_NAME",
|
||||
16: "PR_GET_NAME",
|
||||
19: "PR_GET_ENDIAN",
|
||||
20: "PR_SET_ENDIAN",
|
||||
21: "PR_GET_SECCOMP",
|
||||
22: "PR_SET_SECCOMP",
|
||||
23: "PR_CAPBSET_READ",
|
||||
24: "PR_CAPBSET_DROP",
|
||||
25: "PR_GET_TSC",
|
||||
26: "PR_SET_TSC",
|
||||
27: "PR_GET_SECUREBITS",
|
||||
28: "PR_SET_SECUREBITS",
|
||||
29: "PR_SET_TIMERSLACK",
|
||||
30: "PR_GET_TIMERSLACK",
|
||||
31: "PR_TASK_PERF_EVENTS_DISABLE",
|
||||
32: "PR_TASK_PERF_EVENTS_ENABLE",
|
||||
33: "PR_MCE_KILL",
|
||||
34: "PR_MCE_KILL_GET",
|
||||
35: "PR_SET_MM",
|
||||
36: "PR_SET_CHILD_SUBREAPER",
|
||||
37: "PR_GET_CHILD_SUBREAPER",
|
||||
38: "PR_SET_NO_NEW_PRIVS",
|
||||
39: "PR_GET_NO_NEW_PRIVS",
|
||||
40: "PR_GET_TID_ADDRESS",
|
||||
41: "PR_SET_THP_DISABLE",
|
||||
42: "PR_GET_THP_DISABLE",
|
||||
43: "PR_MPX_ENABLE_MANAGEMENT",
|
||||
44: "PR_MPX_DISABLE_MANAGEMENT",
|
||||
45: "PR_SET_FP_MODE",
|
||||
46: "PR_GET_FP_MODE",
|
||||
47: "PR_CAP_AMBIENT",
|
||||
}
|
10
vendor/github.com/mozilla/libaudit-go/headers/protocol_tab.go
сгенерированный
поставляемый
Normal file
10
vendor/github.com/mozilla/libaudit-go/headers/protocol_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Location: include/uapi/asm-generic/mman-common.h
|
||||
|
||||
package headers
|
||||
|
||||
var ProtLookUp = map[int]string{
|
||||
1: "PROT_READ",
|
||||
2: "PROT_WRITE",
|
||||
4: "PROT_EXEC",
|
||||
8: "PROT_SEM",
|
||||
}
|
37
vendor/github.com/mozilla/libaudit-go/headers/ptrace_tab.go
сгенерированный
поставляемый
Normal file
37
vendor/github.com/mozilla/libaudit-go/headers/ptrace_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Location: include/uapi/linux/ptrace.h
|
||||
|
||||
package headers
|
||||
|
||||
var PtraceLookup = map[int]string{
|
||||
0: "PTRACE_TRACEME",
|
||||
1: "PTRACE_PEEKTEXT",
|
||||
2: "PTRACE_PEEKDATA",
|
||||
3: "PTRACE_PEEKUSER",
|
||||
4: "PTRACE_POKETEXT",
|
||||
5: "PTRACE_POKEDATA",
|
||||
6: "PTRACE_POKEUSER",
|
||||
7: "PTRACE_CONT",
|
||||
8: "PTRACE_KILL",
|
||||
9: "PTRACE_SINGLESTEP",
|
||||
12: "PTRACE_GETREGS",
|
||||
13: "PTRACE_SETREGS",
|
||||
14: "PTRACE_GETFPREGS",
|
||||
15: "PTRACE_SETFPREGS",
|
||||
16: "PTRACE_ATTACH",
|
||||
17: "PTRACE_DETACH",
|
||||
18: "PTRACE_GETFPXREGS",
|
||||
19: "PTRACE_SETFPXREGS",
|
||||
24: "PTRACE_SYSCALL",
|
||||
0x4200: "PTRACE_SETOPTIONS",
|
||||
0x4201: "PTRACE_GETEVENTMSG",
|
||||
0x4202: "PTRACE_GETSIGINFO",
|
||||
0x4203: "PTRACE_SETSIGINFO",
|
||||
0x4204: "PTRACE_GETREGSET",
|
||||
0x4205: "PTRACE_SETREGSET",
|
||||
0x4206: "PTRACE_SEIZE",
|
||||
0x4207: "PTRACE_INTERRUPT",
|
||||
0x4208: "PTRACE_LISTEN",
|
||||
0x4209: "PTRACE_PEEKSIGINFO",
|
||||
0x420a: "PTRACE_GETSIGMASK",
|
||||
0x420b: "PTRACE_SETSIGMASK",
|
||||
}
|
26
vendor/github.com/mozilla/libaudit-go/headers/recv_tab.go
сгенерированный
поставляемый
Normal file
26
vendor/github.com/mozilla/libaudit-go/headers/recv_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,26 @@
|
|||
package headers
|
||||
|
||||
// Location: include/linux/socket.h
|
||||
var RecvLookUp = map[int]string{
|
||||
0x00000001: "MSG_OOB",
|
||||
0x00000002: "MSG_PEEK",
|
||||
0x00000004: "MSG_DONTROUTE",
|
||||
0x00000008: "MSG_CTRUNC",
|
||||
0x00000010: "MSG_PROXY",
|
||||
0x00000020: "MSG_TRUNC",
|
||||
0x00000040: "MSG_DONTWAIT",
|
||||
0x00000080: "MSG_EOR",
|
||||
0x00000100: "MSG_WAITALL",
|
||||
0x00000200: "MSG_FIN",
|
||||
0x00000400: "MSG_SYN",
|
||||
0x00000800: "MSG_CONFIRM",
|
||||
0x00001000: "MSG_RST",
|
||||
0x00002000: "MSG_ERRQUEUE",
|
||||
0x00004000: "MSG_NOSIGNAL",
|
||||
0x00008000: "MSG_MORE",
|
||||
0x00010000: "MSG_WAITFORONE",
|
||||
0x00020000: "MSG_SENDPAGE_NOTLAST",
|
||||
0x20000000: "MSG_FASTOPEN",
|
||||
0x40000000: "MSG_CMSG_CLOEXEC",
|
||||
0x80000000: "MSG_CMSG_COMPAT",
|
||||
}
|
21
vendor/github.com/mozilla/libaudit-go/headers/rlimit_tab.go
сгенерированный
поставляемый
Normal file
21
vendor/github.com/mozilla/libaudit-go/headers/rlimit_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,21 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/asm-generic/resource.h
|
||||
var RlimitLookup = map[int]string{
|
||||
0: "RLIMIT_CPU",
|
||||
1: "RLIMIT_FSIZE",
|
||||
2: "RLIMIT_DATA",
|
||||
3: "RLIMIT_STACK",
|
||||
4: "RLIMIT_CORE",
|
||||
5: "RLIMIT_RSS",
|
||||
6: "RLIMIT_NPROC",
|
||||
7: "RLIMIT_NOFILE",
|
||||
8: "RLIMIT_MEMLOCK",
|
||||
9: "RLIMIT_AS",
|
||||
10: "RLIMIT_LOCKS",
|
||||
11: "RLIMIT_SIGPENDING",
|
||||
12: "RLIMIT_MSGQUEUE",
|
||||
13: "RLIMIT_NICE",
|
||||
14: "RLIMIT_RTPRIO",
|
||||
15: "RLIMIT_RTTIME",
|
||||
}
|
12
vendor/github.com/mozilla/libaudit-go/headers/sched_tab.go
сгенерированный
поставляемый
Normal file
12
vendor/github.com/mozilla/libaudit-go/headers/sched_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,12 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/sched.h
|
||||
|
||||
var SchedLookup = map[int]string{
|
||||
0: "SCHED_OTHER",
|
||||
1: "SCHED_FIFO",
|
||||
2: "SCHED_RR",
|
||||
3: "SCHED_BATCH",
|
||||
5: "SCHED_IDLE",
|
||||
6: "SCHED_DEADLINE",
|
||||
}
|
10
vendor/github.com/mozilla/libaudit-go/headers/seccomp_tab.go
сгенерированный
поставляемый
Normal file
10
vendor/github.com/mozilla/libaudit-go/headers/seccomp_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/seccomp.h
|
||||
var SeccompCodeLookUp = map[int]string{
|
||||
0x00000000: "kill",
|
||||
0x00030000: "trap",
|
||||
0x00050000: "errno",
|
||||
0x7ff00000: "trace",
|
||||
0x7fff0000: "allow",
|
||||
}
|
10
vendor/github.com/mozilla/libaudit-go/headers/seek_tab.go
сгенерированный
поставляемый
Normal file
10
vendor/github.com/mozilla/libaudit-go/headers/seek_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/fs.h
|
||||
var SeekLookup = map[int]string{
|
||||
0: "SEEK_SET",
|
||||
1: "SEEK_CUR",
|
||||
2: "SEEK_END",
|
||||
3: "SEEK_DATA",
|
||||
4: "SEEK_HOLE",
|
||||
}
|
37
vendor/github.com/mozilla/libaudit-go/headers/signal_tab.go
сгенерированный
поставляемый
Normal file
37
vendor/github.com/mozilla/libaudit-go/headers/signal_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,37 @@
|
|||
package headers
|
||||
|
||||
//Location: include/uapi/asm-generic/signal.h
|
||||
var SignalLookup = map[int]string{
|
||||
0: "SIG0",
|
||||
1: "SIGHUP",
|
||||
2: "SIGINT",
|
||||
3: "SIGQUIT",
|
||||
4: "SIGILL",
|
||||
5: "SIGTRAP",
|
||||
6: "SIGABRT",
|
||||
7: "SIGBUS",
|
||||
8: "SIGFPE",
|
||||
9: "SIGKILL",
|
||||
10: "SIGUSR1",
|
||||
11: "SIGSEGV",
|
||||
12: "SIGUSR2",
|
||||
13: "SIGPIPE",
|
||||
14: "SIGALRM",
|
||||
15: "SIGTERM",
|
||||
16: "SIGSTKFLT",
|
||||
17: "SIGCHLD",
|
||||
18: "SIGCONT",
|
||||
19: "SIGSTOP",
|
||||
20: "SIGTSTP",
|
||||
21: "SIGTTIN",
|
||||
22: "SIGTTOU",
|
||||
23: "SIGURG",
|
||||
24: "SIGXCPU",
|
||||
25: "SIGXFSZ",
|
||||
26: "SIGVTALRM",
|
||||
27: "SIGPROF",
|
||||
28: "SIGWINCH",
|
||||
29: "SIGIO",
|
||||
30: "IGPWR",
|
||||
31: "SIGSYS",
|
||||
}
|
27
vendor/github.com/mozilla/libaudit-go/headers/sock_tab.go
сгенерированный
поставляемый
Normal file
27
vendor/github.com/mozilla/libaudit-go/headers/sock_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,27 @@
|
|||
package headers
|
||||
|
||||
import "syscall"
|
||||
|
||||
// Location: include/uapi/linux/net.h
|
||||
var SockLookup = map[int]string{
|
||||
syscall.SYS_SOCKET: "socket",
|
||||
syscall.SYS_BIND: "bind",
|
||||
syscall.SYS_CONNECT: "connect",
|
||||
syscall.SYS_LISTEN: "listen",
|
||||
syscall.SYS_ACCEPT: "accept",
|
||||
syscall.SYS_GETSOCKNAME: "getsockname",
|
||||
syscall.SYS_GETPEERNAME: "getpeername",
|
||||
syscall.SYS_SOCKETPAIR: "socketpair",
|
||||
9: "send",
|
||||
10: "recv",
|
||||
syscall.SYS_SENDTO: "sendto",
|
||||
syscall.SYS_RECVFROM: "recvfrom",
|
||||
syscall.SYS_SHUTDOWN: "shutdown",
|
||||
syscall.SYS_SETSOCKOPT: "setsockopt",
|
||||
syscall.SYS_GETSOCKOPT: "getsockopt",
|
||||
syscall.SYS_SENDMSG: "sendmsg",
|
||||
syscall.SYS_RECVMSG: "recvmsg",
|
||||
syscall.SYS_ACCEPT4: "accept4",
|
||||
19: "recvmmsg",
|
||||
20: "sendmmsg",
|
||||
}
|
45
vendor/github.com/mozilla/libaudit-go/headers/sockfam_tab.go
сгенерированный
поставляемый
Normal file
45
vendor/github.com/mozilla/libaudit-go/headers/sockfam_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,45 @@
|
|||
package headers
|
||||
|
||||
import "syscall"
|
||||
|
||||
//Location: include/linux/socket.h
|
||||
var SocketFamLookup = map[int]string{
|
||||
syscall.AF_LOCAL: "local",
|
||||
syscall.AF_INET: "inet",
|
||||
syscall.AF_AX25: "ax25",
|
||||
syscall.AF_IPX: "ipx",
|
||||
syscall.AF_APPLETALK: "appletalk",
|
||||
syscall.AF_NETROM: "netrom",
|
||||
syscall.AF_BRIDGE: "bridge",
|
||||
syscall.AF_ATMPVC: "atmpvc",
|
||||
syscall.AF_X25: "x25",
|
||||
syscall.AF_INET6: "inet6",
|
||||
syscall.AF_ROSE: "rose",
|
||||
syscall.AF_DECnet: "decnet",
|
||||
syscall.AF_NETBEUI: "netbeui",
|
||||
syscall.AF_SECURITY: "security",
|
||||
syscall.AF_KEY: "key",
|
||||
syscall.AF_NETLINK: "netlink",
|
||||
syscall.AF_PACKET: "packet",
|
||||
syscall.AF_ASH: "ash",
|
||||
syscall.AF_ECONET: "econet",
|
||||
syscall.AF_ATMSVC: "atmsvc",
|
||||
syscall.AF_RDS: "rds",
|
||||
syscall.AF_SNA: "sna",
|
||||
syscall.AF_IRDA: "irda",
|
||||
syscall.AF_PPPOX: "pppox",
|
||||
syscall.AF_WANPIPE: "wanpipe",
|
||||
syscall.AF_LLC: "llc",
|
||||
syscall.AF_CAN: "can",
|
||||
syscall.AF_TIPC: "tipc",
|
||||
syscall.AF_BLUETOOTH: "bluetooth",
|
||||
syscall.AF_IUCV: "iucv",
|
||||
syscall.AF_RXRPC: "rxrpc",
|
||||
syscall.AF_ISDN: "isdn",
|
||||
syscall.AF_PHONET: "phonet",
|
||||
syscall.AF_IEEE802154: "ieee802154",
|
||||
37: "caif",
|
||||
38: "alg",
|
||||
39: "nfc",
|
||||
40: "vsock",
|
||||
}
|
37
vendor/github.com/mozilla/libaudit-go/headers/socklevel_tab.go
сгенерированный
поставляемый
Normal file
37
vendor/github.com/mozilla/libaudit-go/headers/socklevel_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,37 @@
|
|||
package headers
|
||||
|
||||
// Location: include/linux/socket.h
|
||||
var SockOptLookup = map[int]string{
|
||||
0: "SOL_IP",
|
||||
6: "SOL_TCP",
|
||||
17: "SOL_UDP",
|
||||
41: "SOL_IPV6",
|
||||
58: "SOL_ICMPV6",
|
||||
132: "SOL_SCTP",
|
||||
136: "SOL_UDPLITE",
|
||||
255: "SOL_RAW",
|
||||
256: "SOL_IPX",
|
||||
257: "SOL_AX25",
|
||||
258: "SOL_ATALK",
|
||||
259: "SOL_NETROM",
|
||||
260: "SOL_ROSE",
|
||||
261: "SOL_DECNET",
|
||||
263: "SOL_PACKET",
|
||||
264: "SOL_ATM",
|
||||
265: "SOL_AAL",
|
||||
266: "SOL_IRDA",
|
||||
267: "SOL_NETBEUI",
|
||||
268: "SOL_LLC",
|
||||
269: "SOL_DCCP",
|
||||
270: "SOL_NETLINK",
|
||||
271: "SOL_TIPC",
|
||||
272: "SOL_RXRPC",
|
||||
273: "SOL_PPPOL2TP",
|
||||
274: "SOL_BLUETOOTH",
|
||||
275: "SOL_PNPIPE",
|
||||
276: "SOL_RDS",
|
||||
277: "SOL_IUCV",
|
||||
278: "SOL_CAIF",
|
||||
279: "SOL_ALG",
|
||||
280: "SOL_NFC",
|
||||
}
|
63
vendor/github.com/mozilla/libaudit-go/headers/sockoptname_tab.go
сгенерированный
поставляемый
Normal file
63
vendor/github.com/mozilla/libaudit-go/headers/sockoptname_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,63 @@
|
|||
package headers
|
||||
|
||||
// File: include/uapi/asm-generic/socket.h
|
||||
var SockOptNameLookup = map[int]string{
|
||||
1: "SO_DEBUG",
|
||||
2: "SO_REUSEADDR",
|
||||
3: "SO_TYPE",
|
||||
4: "SO_ERROR",
|
||||
5: "SO_DONTROUTE",
|
||||
6: "SO_BROADCAST",
|
||||
7: "SO_SNDBUF",
|
||||
8: "SO_RCVBUF",
|
||||
9: "SO_KEEPALIVE",
|
||||
10: "SO_OOBINLINE",
|
||||
11: "SO_NO_CHECK",
|
||||
12: "SO_PRIORITY",
|
||||
13: "SO_LINGER",
|
||||
14: "SO_BSDCOMPAT",
|
||||
15: "SO_REUSEPORT",
|
||||
16: "SO_PASSCRED",
|
||||
17: "SO_PEERCRED",
|
||||
18: "SO_RCVLOWAT",
|
||||
19: "SO_SNDLOWAT",
|
||||
20: "SO_RCVTIMEO",
|
||||
21: "SO_SNDTIMEO",
|
||||
22: "SO_SECURITY_AUTHENTICATION",
|
||||
23: "SO_SECURITY_ENCRYPTION_TRANSPORT",
|
||||
24: "SO_SECURITY_ENCRYPTION_NETWORK",
|
||||
25: "SO_BINDTODEVICE",
|
||||
26: "SO_ATTACH_FILTER",
|
||||
27: "SO_DETACH_FILTER",
|
||||
28: "SO_PEERNAME",
|
||||
29: "SO_TIMESTAMP",
|
||||
30: "SO_ACCEPTCONN",
|
||||
31: "SO_PEERSEC",
|
||||
32: "SO_SNDBUFFORCE",
|
||||
33: "SO_RCVBUFFORCE",
|
||||
34: "SO_PASSSEC",
|
||||
35: "SO_TIMESTAMPNS",
|
||||
36: "SO_MARK",
|
||||
37: "SO_TIMESTAMPING",
|
||||
38: "SO_PROTOCOL",
|
||||
39: "SO_DOMAIN",
|
||||
40: "SO_RXQ_OVFL",
|
||||
41: "SO_WIFI_STATUS",
|
||||
42: "SO_PEEK_OFF",
|
||||
43: "SO_NOFCS",
|
||||
44: "SO_LOCK_FILTER",
|
||||
45: "SO_SELECT_ERR_QUEUE",
|
||||
46: "SO_BUSY_POLL",
|
||||
47: "SO_MAX_PACING_RATE",
|
||||
48: "SO_BPF_EXTENSIONS",
|
||||
49: "SO_INCOMING_CPU",
|
||||
50: "SO_ATTACH_BPF",
|
||||
|
||||
// PPC has these different
|
||||
116: "SO_RCVLOWAT",
|
||||
117: "SO_SNDLOWAT",
|
||||
118: "SO_RCVTIMEO",
|
||||
119: "SO_SNDTIMEO",
|
||||
120: "SO_PASSCRED",
|
||||
121: "SO_PEERCRED",
|
||||
}
|
12
vendor/github.com/mozilla/libaudit-go/headers/socktype_tab.go
сгенерированный
поставляемый
Normal file
12
vendor/github.com/mozilla/libaudit-go/headers/socktype_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,12 @@
|
|||
package headers
|
||||
|
||||
// Location: include/linux/net.h
|
||||
var SockTypeLookup = map[int]string{
|
||||
1: "SOCK_STREAM",
|
||||
2: "SOCK_DGRAM",
|
||||
3: "SOCK_RAW",
|
||||
4: "SOCK_RDM",
|
||||
5: "SOCK_SEQPACKET",
|
||||
6: "SOCK_DCCP",
|
||||
10: "SOCK_PACKET",
|
||||
}
|
30
vendor/github.com/mozilla/libaudit-go/headers/tcpoptname_tab.go
сгенерированный
поставляемый
Normal file
30
vendor/github.com/mozilla/libaudit-go/headers/tcpoptname_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,30 @@
|
|||
package headers
|
||||
|
||||
// Location: include/uapi/linux/tcp.h
|
||||
var TcpOptLookup = map[int]string{
|
||||
1: "TCP_NODELAY",
|
||||
2: "TCP_MAXSEG",
|
||||
3: "TCP_CORK",
|
||||
4: "TCP_KEEPIDLE",
|
||||
5: "TCP_KEEPINTVL",
|
||||
6: "TCP_KEEPCNT",
|
||||
7: "TCP_SYNCNT",
|
||||
8: "TCP_LINGER2",
|
||||
9: "TCP_DEFER_ACCEPT",
|
||||
10: "TCP_WINDOW_CLAMP",
|
||||
11: "TCP_INFO",
|
||||
12: "TCP_QUICKACK",
|
||||
13: "TCP_CONGESTION",
|
||||
14: "TCP_MD5SIG",
|
||||
15: "TCP_COOKIE_TRANSACTIONS",
|
||||
16: "TCP_THIN_LINEAR_TIMEOUTS",
|
||||
17: "TCP_THIN_DUPACK",
|
||||
18: "TCP_USER_TIMEOUT",
|
||||
19: "TCP_REPAIR",
|
||||
20: "TCP_REPAIR_QUEUE",
|
||||
21: "TCP_QUEUE_SEQ",
|
||||
22: "TCP_REPAIR_OPTIONS",
|
||||
23: "TCP_FASTOPEN",
|
||||
24: "TCP_TIMESTAMP",
|
||||
25: "TCP_NOTSENT_LOWAT",
|
||||
}
|
10
vendor/github.com/mozilla/libaudit-go/headers/umount_tab.go
сгенерированный
поставляемый
Normal file
10
vendor/github.com/mozilla/libaudit-go/headers/umount_tab.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
package headers
|
||||
|
||||
// Location: include/linux/fs.h
|
||||
var UmountLookUp = map[int]string{
|
||||
0x00000001: "MNT_FORCE",
|
||||
0x00000002: "MNT_DETACH",
|
||||
0x00000004: "MNT_EXPIRE",
|
||||
0x00000008: "UMOUNT_NOFOLLOW",
|
||||
0x80000001: "UMOUNT_UNUSED",
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,444 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package libaudit is a client library used for interfacing with the Linux kernel auditing framework. It
|
||||
// provides an API for executing audit related tasks such as setting audit rules, changing the auditing
|
||||
// configuration, and processing incoming audit events.
|
||||
//
|
||||
// The intent for this package is to provide a means for an application to take the role of auditd, for
|
||||
// consumption and analysis of audit events in your go program.
|
||||
package libaudit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// The sequence number used for requests from us to the kernel in netlink messages,
|
||||
// just increments.
|
||||
var sequenceNumber uint32
|
||||
|
||||
// hostEndian is initialized to the byte order of the system
|
||||
var hostEndian binary.ByteOrder
|
||||
|
||||
func init() {
|
||||
hostEndian = nativeEndian()
|
||||
}
|
||||
|
||||
func nextSequence() uint32 {
|
||||
return atomic.AddUint32(&sequenceNumber, 1)
|
||||
}
|
||||
|
||||
// NetlinkMessage is the struct type that is used for communicating on netlink sockets.
|
||||
type NetlinkMessage syscall.NetlinkMessage
|
||||
|
||||
// auditStatus represents the c struct audit_status (libaudit.h). It is used for passing
|
||||
// information related to the status of the auditing services between the kernel and
|
||||
// userspace.
|
||||
type auditStatus struct {
|
||||
Mask uint32 /* Bit mask for valid entries */
|
||||
Enabled uint32 /* 1 = enabled, 0 = disabled */
|
||||
Failure uint32 /* Failure-to-log action */
|
||||
Pid uint32 /* pid of auditd process */
|
||||
RateLimit uint32 /* messages rate limit (per second) */
|
||||
BacklogLimit uint32 /* waiting messages limit */
|
||||
Lost uint32 /* messages lost */
|
||||
Backlog uint32 /* messages waiting in queue */
|
||||
Version uint32 /* audit api version number */
|
||||
BacklogWaitTime uint32 /* message queue wait timeout */
|
||||
}
|
||||
|
||||
// Netlink is an abstracting netlink IO functions; generally used with NetlinkConnection
|
||||
type Netlink interface {
|
||||
Send(request *NetlinkMessage) error // Send a NetlinkMessage
|
||||
Receive(nonblocking bool) ([]NetlinkMessage, error) // Receive netlink message(s) from the kernel
|
||||
GetPID() (int, error) // Get netlink peer PID
|
||||
}
|
||||
|
||||
// NetlinkConnection describes a netlink interface with the kernel.
|
||||
//
|
||||
// Programs should call NewNetlinkConnection() to create a new instance.
|
||||
type NetlinkConnection struct {
|
||||
fd int // File descriptor used for communication
|
||||
address syscall.SockaddrNetlink // Netlink sockaddr
|
||||
}
|
||||
|
||||
// Close closes the Netlink connection.
|
||||
func (s *NetlinkConnection) Close() {
|
||||
syscall.Close(s.fd)
|
||||
}
|
||||
|
||||
// Send sends NetlinkMessage request using an allocated NetlinkConnection.
|
||||
func (s *NetlinkConnection) Send(request *NetlinkMessage) error {
|
||||
return syscall.Sendto(s.fd, request.ToWireFormat(), 0, &s.address)
|
||||
}
|
||||
|
||||
// Receive returns any available netlink messages being sent to us by the kernel.
|
||||
func (s *NetlinkConnection) Receive(nonblocking bool) ([]NetlinkMessage, error) {
|
||||
var (
|
||||
flags = 0
|
||||
)
|
||||
if nonblocking {
|
||||
flags |= syscall.MSG_DONTWAIT
|
||||
}
|
||||
buf := make([]byte, MAX_AUDIT_MESSAGE_LENGTH+syscall.NLMSG_HDRLEN)
|
||||
nr, _, err := syscall.Recvfrom(s.fd, buf, flags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseAuditNetlinkMessage(buf[:nr])
|
||||
}
|
||||
|
||||
// GetPID returns the netlink port ID of the netlink socket peer.
|
||||
func (s *NetlinkConnection) GetPID() (int, error) {
|
||||
var (
|
||||
address syscall.Sockaddr
|
||||
v *syscall.SockaddrNetlink
|
||||
err error
|
||||
)
|
||||
address, err = syscall.Getsockname(s.fd)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v = address.(*syscall.SockaddrNetlink)
|
||||
return int(v.Pid), nil
|
||||
}
|
||||
|
||||
// nativeEndian determines the byte order for the system
|
||||
func nativeEndian() binary.ByteOrder {
|
||||
var x uint32 = 0x01020304
|
||||
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
|
||||
return binary.BigEndian
|
||||
}
|
||||
return binary.LittleEndian
|
||||
}
|
||||
|
||||
// ToWireFormat converts a given NetlinkMessage to a byte stream suitable to be sent to
|
||||
// the kernel.
|
||||
func (rr *NetlinkMessage) ToWireFormat() []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
pbytes := nlmAlignOf(int(rr.Header.Len)) - int(rr.Header.Len)
|
||||
err := binary.Write(buf, hostEndian, rr.Header.Len)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
err = binary.Write(buf, hostEndian, rr.Header.Type)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
err = binary.Write(buf, hostEndian, rr.Header.Flags)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
err = binary.Write(buf, hostEndian, rr.Header.Seq)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
err = binary.Write(buf, hostEndian, rr.Header.Pid)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
err = binary.Write(buf, hostEndian, rr.Data)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if pbytes > 0 {
|
||||
pbuf := make([]byte, pbytes)
|
||||
_, err = buf.Write(pbuf)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// nlmAlignOf rounds the length of a netlink message up to align it properly.
|
||||
func nlmAlignOf(msglen int) int {
|
||||
return (msglen + syscall.NLMSG_ALIGNTO - 1) & ^(syscall.NLMSG_ALIGNTO - 1)
|
||||
}
|
||||
|
||||
// parseAuditNetlinkMessage processes an incoming netlink message from the socket,
|
||||
// and returns a slice of NetlinkMessage types, or an error if an error is encountered.
|
||||
//
|
||||
// This function handles incoming messages with NLM_F_MULTI; in the case of
|
||||
// a multipart message, ret will contain all netlink messages which are part
|
||||
// of the kernel message. If it is not a multipart message, ret will simply
|
||||
// contain a single message.
|
||||
func parseAuditNetlinkMessage(b []byte) (ret []NetlinkMessage, err error) {
|
||||
for len(b) != 0 {
|
||||
multi := false
|
||||
var (
|
||||
m NetlinkMessage
|
||||
)
|
||||
|
||||
m.Header.Len, b, err = netlinkPopuint32(b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Determine our alignment size given the reported header length
|
||||
alignbounds := nlmAlignOf(int(m.Header.Len))
|
||||
padding := alignbounds - int(m.Header.Len)
|
||||
|
||||
// Subtract 4 from alignbounds here to account for already having popped 4 bytes
|
||||
// off the input buffer
|
||||
if len(b) < alignbounds-4 {
|
||||
return ret, fmt.Errorf("short read on audit message, expected %v bytes had %v",
|
||||
alignbounds, len(b)+4)
|
||||
}
|
||||
// If we get here, we have enough data for the entire message
|
||||
m.Header.Type, b, err = netlinkPopuint16(b)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
m.Header.Flags, b, err = netlinkPopuint16(b)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
if (m.Header.Flags & syscall.NLM_F_MULTI) != 0 {
|
||||
multi = true
|
||||
}
|
||||
m.Header.Seq, b, err = netlinkPopuint32(b)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
m.Header.Pid, b, err = netlinkPopuint32(b)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
// Determine how much data we want to read here; if this isn't NLM_F_MULTI, we'd
|
||||
// typically want to read m.Header.Len bytes (the length of the payload indicated in
|
||||
// the netlink header.
|
||||
//
|
||||
// However, this isn't always the case. Depending on what is generating the audit
|
||||
// message (e.g., via audit_log_end) the kernel does not include the netlink header
|
||||
// size in the submitted audit message. So, we just read whatever is left in the buffer
|
||||
// we have if this isn't multipart.
|
||||
//
|
||||
// Additionally, it seems like there are also a few messages types where the netlink paylaod
|
||||
// value is inaccurate and can't be relied upon.
|
||||
//
|
||||
// XXX Just consuming the rest of the buffer based on the event type might be a better
|
||||
// approach here.
|
||||
if !multi {
|
||||
m.Data = b
|
||||
} else {
|
||||
datalen := m.Header.Len - syscall.NLMSG_HDRLEN
|
||||
m.Data = b[:datalen]
|
||||
b = b[int(datalen)+padding:]
|
||||
}
|
||||
ret = append(ret, m)
|
||||
if !multi {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// netlinkPopuint16 pops a uint16 off the front of b, returning the value and the new buffer
|
||||
func netlinkPopuint16(b []byte) (uint16, []byte, error) {
|
||||
if len(b) < 2 {
|
||||
return 0, b, fmt.Errorf("not enough bytes for uint16")
|
||||
}
|
||||
return hostEndian.Uint16(b[:2]), b[2:], nil
|
||||
}
|
||||
|
||||
// netlinkPopuint32 pops a uint32 off the front of b, returning the value and the new buffer
|
||||
func netlinkPopuint32(b []byte) (uint32, []byte, error) {
|
||||
if len(b) < 4 {
|
||||
return 0, b, fmt.Errorf("not enough bytes for uint32")
|
||||
}
|
||||
return hostEndian.Uint32(b[:4]), b[4:], nil
|
||||
}
|
||||
|
||||
// newNetlinkAuditRequest initializes the header section as preparation for sending a new
|
||||
// netlink message.
|
||||
func newNetlinkAuditRequest(proto uint16, family, sizeofData int) *NetlinkMessage {
|
||||
rr := &NetlinkMessage{}
|
||||
rr.Header.Len = uint32(syscall.NLMSG_HDRLEN + sizeofData)
|
||||
rr.Header.Type = proto
|
||||
rr.Header.Flags = syscall.NLM_F_REQUEST | syscall.NLM_F_ACK
|
||||
rr.Header.Seq = nextSequence()
|
||||
return rr
|
||||
}
|
||||
|
||||
// NewNetlinkConnection creates a new netlink connection with the kernel audit subsystem
|
||||
// and returns a NetlinkConnection describing it. The process should ensure it has the
|
||||
// required privileges before calling. An error is returned if any error is encountered
|
||||
// creating the netlink connection.
|
||||
func NewNetlinkConnection() (ret *NetlinkConnection, err error) {
|
||||
ret = &NetlinkConnection{}
|
||||
ret.fd, err = syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_AUDIT)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ret.address.Family = syscall.AF_NETLINK
|
||||
ret.address.Groups = 0
|
||||
ret.address.Pid = 0 // 0 for kernel space
|
||||
if err = syscall.Bind(ret.fd, &ret.address); err != nil {
|
||||
syscall.Close(ret.fd)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// auditGetReply gets a reply to a message from the kernel. The message(s) we are looking for are
|
||||
// indicated by passing sequence number seq.
|
||||
//
|
||||
// Once we recieve the full response any matching messages are returned. Note this function
|
||||
// would generally be used to retrieve a response from various AUDIT_SET functions or similar
|
||||
// configuration routines, and we do not use this for draining the audit event queue.
|
||||
//
|
||||
// chkAck should be set to true if the response we are expecting is just an ACK packet back
|
||||
// from netlink. If chkAck is false, the function will also retrieve other types of messages
|
||||
// related to the specified sequence number (like the response messages related to a query).
|
||||
//
|
||||
// XXX Right now we just discard any unrelated messages, which is not neccesarily
|
||||
// ideal. This could be adapted to handle this better.
|
||||
//
|
||||
// XXX This function also waits until it gets the correct message, so if for some reason
|
||||
// the message does not come through it will not return. This should also be improved.
|
||||
func auditGetReply(s Netlink, seq uint32, chkAck bool) (ret []NetlinkMessage, err error) {
|
||||
done:
|
||||
for {
|
||||
dbrk := false
|
||||
msgs, err := s.Receive(false)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
for _, m := range msgs {
|
||||
socketPID, err := s.GetPID()
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
if m.Header.Seq != seq {
|
||||
// Wasn't the sequence number we are looking for, just discard it
|
||||
continue
|
||||
}
|
||||
if int(m.Header.Pid) != socketPID {
|
||||
// PID didn't match, just discard it
|
||||
continue
|
||||
}
|
||||
if m.Header.Type == syscall.NLMSG_DONE {
|
||||
break done
|
||||
}
|
||||
if m.Header.Type == syscall.NLMSG_ERROR {
|
||||
e := int32(hostEndian.Uint32(m.Data[0:4]))
|
||||
if e == 0 {
|
||||
// ACK response from the kernel; if chkAck is true
|
||||
// we just return as there is nothing left to do
|
||||
if chkAck {
|
||||
break done
|
||||
}
|
||||
// Otherwise, keep going so we can get the response
|
||||
// we want
|
||||
continue
|
||||
} else {
|
||||
return ret, fmt.Errorf("error while recieving reply %v", e)
|
||||
}
|
||||
}
|
||||
ret = append(ret, m)
|
||||
if (m.Header.Flags & syscall.NLM_F_MULTI) == 0 {
|
||||
// If it's not a multipart message, once we get one valid
|
||||
// message just return
|
||||
dbrk = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if dbrk {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// auditSendStatus sends AUDIT_SET with the associated auditStatus configuration
|
||||
func auditSendStatus(s Netlink, status auditStatus) (err error) {
|
||||
buf := new(bytes.Buffer)
|
||||
err = binary.Write(buf, hostEndian, status)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
wb := newNetlinkAuditRequest(uint16(AUDIT_SET), syscall.AF_NETLINK, AUDIT_STATUS_SIZE)
|
||||
wb.Data = buf.Bytes()
|
||||
if err = s.Send(wb); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = auditGetReply(s, wb.Header.Seq, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuditSetEnabled enables or disables auditing in the kernel.
|
||||
func AuditSetEnabled(s Netlink, enabled bool) (err error) {
|
||||
var status auditStatus
|
||||
if enabled {
|
||||
status.Enabled = 1
|
||||
} else {
|
||||
status.Enabled = 0
|
||||
}
|
||||
status.Mask = AUDIT_STATUS_ENABLED
|
||||
return auditSendStatus(s, status)
|
||||
}
|
||||
|
||||
// AuditIsEnabled returns true if auditing is enabled in the kernel.
|
||||
func AuditIsEnabled(s Netlink) (bool, error) {
|
||||
var status auditStatus
|
||||
|
||||
wb := newNetlinkAuditRequest(uint16(AUDIT_GET), syscall.AF_NETLINK, 0)
|
||||
if err := s.Send(wb); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
msgs, err := auditGetReply(s, wb.Header.Seq, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(msgs) != 1 {
|
||||
return false, fmt.Errorf("unexpected number of responses from kernel for status request")
|
||||
}
|
||||
m := msgs[0]
|
||||
if m.Header.Type != uint16(AUDIT_GET) {
|
||||
return false, fmt.Errorf("status request response type was invalid")
|
||||
}
|
||||
// Convert the response to auditStatus
|
||||
buf := bytes.NewBuffer(m.Data)
|
||||
err = binary.Read(buf, hostEndian, &status)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if status.Enabled == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// AuditSetPID sets the PID for the audit daemon in the kernel (audit_set_pid(3))
|
||||
func AuditSetPID(s Netlink, pid int) error {
|
||||
var status auditStatus
|
||||
status.Mask = AUDIT_STATUS_PID
|
||||
status.Pid = uint32(pid)
|
||||
return auditSendStatus(s, status)
|
||||
}
|
||||
|
||||
// AuditSetRateLimit sets the rate limit for audit messages from the kernel
|
||||
func AuditSetRateLimit(s Netlink, limit int) error {
|
||||
var status auditStatus
|
||||
status.Mask = AUDIT_STATUS_RATE_LIMIT
|
||||
status.RateLimit = uint32(limit)
|
||||
return auditSendStatus(s, status)
|
||||
}
|
||||
|
||||
// AuditSetBacklogLimit sets the backlog limit for audit messages in the kernel
|
||||
func AuditSetBacklogLimit(s Netlink, limit int) error {
|
||||
var status auditStatus
|
||||
status.Mask = AUDIT_STATUS_BACKLOG_LIMIT
|
||||
status.BacklogLimit = uint32(limit)
|
||||
return auditSendStatus(s, status)
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestWireFormat(t *testing.T) {
|
||||
rr := NetlinkMessage{}
|
||||
rr.Header.Len = uint32(syscall.NLMSG_HDRLEN + 4)
|
||||
rr.Header.Type = syscall.AF_NETLINK
|
||||
rr.Header.Flags = syscall.NLM_F_REQUEST | syscall.NLM_F_ACK
|
||||
rr.Header.Seq = 2
|
||||
|
||||
data := make([]byte, 4)
|
||||
hostEndian.PutUint32(data, 12)
|
||||
rr.Data = append(rr.Data[:], data[:]...)
|
||||
|
||||
expected := []byte{20, 0, 0, 0, 16, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0}
|
||||
result := rr.ToWireFormat()
|
||||
if bytes.Compare(expected, result) != 0 {
|
||||
t.Fatalf("ToWireFormat: resulting bytes unexpected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetlinkConnection(t *testing.T) {
|
||||
if os.Getuid() != 0 {
|
||||
t.Skipf("skipping test, not root user")
|
||||
}
|
||||
s, err := NewNetlinkConnection()
|
||||
if err != nil {
|
||||
t.Fatalf("NewNetlinkConnection: %v", err)
|
||||
}
|
||||
defer s.Close()
|
||||
wb := newNetlinkAuditRequest(uint16(AUDIT_GET), syscall.AF_NETLINK, 0)
|
||||
if err = s.Send(wb); err != nil {
|
||||
t.Errorf("Send: %v", err)
|
||||
}
|
||||
_, err = auditGetReply(s, wb.Header.Seq, true)
|
||||
if err != nil {
|
||||
t.Errorf("TestNetlinkConnection: test failed %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetters(t *testing.T) {
|
||||
rand.Seed(time.Now().Unix())
|
||||
var (
|
||||
s *NetlinkConnection
|
||||
pid = os.Getpid()
|
||||
ratelimit = 20 + rand.Intn(480)
|
||||
backlog = 20 + rand.Intn(480)
|
||||
)
|
||||
if os.Getuid() != 0 {
|
||||
t.Skipf("skipping test, not root user")
|
||||
}
|
||||
s, err := NewNetlinkConnection()
|
||||
if err != nil {
|
||||
t.Fatalf("NewNetlinkConnection: %v", err)
|
||||
}
|
||||
defer s.Close()
|
||||
err = AuditSetEnabled(s, true)
|
||||
if err != nil {
|
||||
t.Fatalf("AuditSetEnabled: %v", err)
|
||||
}
|
||||
auditstatus, err := AuditIsEnabled(s)
|
||||
if err != nil {
|
||||
t.Fatalf("AuditIsEnabled: %v", err)
|
||||
}
|
||||
if !auditstatus {
|
||||
t.Fatalf("AuditIsEnabled returned false")
|
||||
}
|
||||
err = AuditSetRateLimit(s, ratelimit)
|
||||
if err != nil {
|
||||
t.Fatalf("AuditSetRateLimit: %v", err)
|
||||
}
|
||||
err = AuditSetBacklogLimit(s, backlog)
|
||||
if err != nil {
|
||||
t.Fatalf("AuditSetBacklogLimit: %v", err)
|
||||
}
|
||||
err = AuditSetPID(s, pid)
|
||||
if err != nil {
|
||||
t.Fatalf("AuditSetPID: %v", err)
|
||||
}
|
||||
|
||||
// Use the external auditctl program to obtain the set values, and compare to what we
|
||||
// expect
|
||||
cmd := exec.Command("auditctl", "-s")
|
||||
cmdOutput := &bytes.Buffer{}
|
||||
cmd.Stdout = cmdOutput
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Fatalf("exec auditctl: %v", err)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(cmdOutput)
|
||||
for scanner.Scan() {
|
||||
args := strings.Split(scanner.Text(), " ")
|
||||
if len(args) < 2 {
|
||||
t.Fatalf("auditctl: malformed output %q", scanner.Text())
|
||||
}
|
||||
switch args[0] {
|
||||
case "enabled":
|
||||
if args[1] != "1" {
|
||||
t.Fatalf("enabled should have been 1")
|
||||
}
|
||||
case "pid":
|
||||
v, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
t.Fatalf("pid argument was not an integer")
|
||||
}
|
||||
if v != pid {
|
||||
t.Fatalf("pid should have been %v, was %v", pid, v)
|
||||
}
|
||||
case "rate_limit":
|
||||
v, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
t.Fatalf("rate_limit argument was not an integer")
|
||||
}
|
||||
if v != ratelimit {
|
||||
t.Fatalf("ratelimit should have been %v, was %v", ratelimit, v)
|
||||
}
|
||||
case "backlog_limit":
|
||||
v, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
t.Fatalf("backlog_limit argument was not an integer")
|
||||
}
|
||||
if v != backlog {
|
||||
t.Fatalf("backlog_limit should have been %v, was %v", backlog, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,358 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
// fieldLookupMap is for interpreting field names in audit messages for their integer values
|
||||
var fieldLookupMap = map[string]fieldType{
|
||||
"auid": typeUID,
|
||||
"uid": typeUID,
|
||||
"euid": typeUID,
|
||||
"suid": typeUID,
|
||||
"fsuid": typeUID,
|
||||
"ouid": typeUID,
|
||||
"oauid": typeUID,
|
||||
"iuid": typeUID,
|
||||
"id": typeUID,
|
||||
"inode_uid": typeUID,
|
||||
"sauid": typeUID,
|
||||
"obj_uid": typeUID,
|
||||
"obj_gid": typeGID,
|
||||
"gid": typeGID,
|
||||
"egid": typeGID,
|
||||
"sgid": typeGID,
|
||||
"fsgid": typeGID,
|
||||
"ogid": typeGID,
|
||||
"igid": typeGID,
|
||||
"inode_gid": typeGID,
|
||||
"new_gid": typeGID,
|
||||
"syscall": typeSyscall,
|
||||
"arch": typeArch,
|
||||
"exit": typeExit,
|
||||
"path": typeEscaped,
|
||||
"comm": typeEscaped,
|
||||
"exe": typeEscaped,
|
||||
"file": typeEscaped,
|
||||
"name": typeEscaped,
|
||||
"watch": typeEscaped,
|
||||
"cwd": typeEscaped,
|
||||
"cmd": typeEscaped,
|
||||
"acct": typeEscaped,
|
||||
"dir": typeEscaped,
|
||||
"key": typeEscaped,
|
||||
"vm": typeEscaped,
|
||||
"old-disk": typeEscaped,
|
||||
"new-disk": typeEscaped,
|
||||
"old-fs": typeEscaped,
|
||||
"new-fs": typeEscaped,
|
||||
"device": typeEscaped,
|
||||
"cgroup": typeEscaped,
|
||||
"perm": typePerm,
|
||||
"perm_mask": typePerm,
|
||||
"mode": typeMode,
|
||||
"saddr": typeSockaddr,
|
||||
"prom": typePromisc,
|
||||
"old_prom": typePromisc,
|
||||
"capability": typeCapability,
|
||||
"res": typeSuccess,
|
||||
"result": typeSuccess,
|
||||
"a0": typeA0,
|
||||
"a1": typeA1,
|
||||
"a2": typeA2,
|
||||
"a3": typeA3,
|
||||
"sig": typeSignal,
|
||||
"list": typeList,
|
||||
"data": typeTTYData,
|
||||
"ses": typeSession,
|
||||
"cap_pi": typeCapBitmap,
|
||||
"cap_pe": typeCapBitmap,
|
||||
"cap_pp": typeCapBitmap,
|
||||
"cap_fi": typeCapBitmap,
|
||||
"cap_fp": typeCapBitmap,
|
||||
"fp": typeCapBitmap,
|
||||
"fi": typeCapBitmap,
|
||||
"fe": typeCapBitmap,
|
||||
"old_pp": typeCapBitmap,
|
||||
"old_pi": typeCapBitmap,
|
||||
"old_pe": typeCapBitmap,
|
||||
"new_pp": typeCapBitmap,
|
||||
"new_pi": typeCapBitmap,
|
||||
"new_pe": typeCapBitmap,
|
||||
"family": typeNFProto,
|
||||
"icmptype": typeICMP,
|
||||
"proto": typeProtocol,
|
||||
"addr": typeAddr,
|
||||
"apparmor": typeEscaped,
|
||||
"operation": typeEscaped,
|
||||
"denied_mask": typeEscaped,
|
||||
"info": typeEscaped,
|
||||
"profile": typeEscaped,
|
||||
"requested_mask": typeEscaped,
|
||||
"per": typePersonality,
|
||||
"code": typeSeccomp,
|
||||
"old-rng": typeEscaped,
|
||||
"new-rng": typeEscaped,
|
||||
"oflag": typeOFlag,
|
||||
"ocomm": typeEscaped,
|
||||
"flags": typeMmap,
|
||||
"sigev_signo": typeEscaped,
|
||||
"subj": typeMacLabel,
|
||||
"obj": typeMacLabel,
|
||||
"scontext": typeMacLabel,
|
||||
"tcontext": typeMacLabel,
|
||||
"vm-ctx": typeMacLabel,
|
||||
"img-ctx": typeMacLabel,
|
||||
"proctitle": typeProctile,
|
||||
"grp": typeEscaped,
|
||||
"new_group": typeEscaped,
|
||||
}
|
||||
|
||||
// actionLookup is for mapping audit actions applied on auditRuleData
|
||||
var actionLookup = map[int]string{
|
||||
AUDIT_NEVER: "never",
|
||||
AUDIT_POSSIBLE: "possible",
|
||||
AUDIT_ALWAYS: "always",
|
||||
}
|
||||
|
||||
// flagLookup is for mapping flags applied on auditRuleData
|
||||
var flagLookup = map[int]string{
|
||||
AUDIT_FILTER_TASK: "task",
|
||||
AUDIT_FILTER_ENTRY: "entry",
|
||||
AUDIT_FILTER_EXIT: "exit",
|
||||
AUDIT_FILTER_USER: "user",
|
||||
AUDIT_FILTER_EXCLUDE: "exclude",
|
||||
}
|
||||
|
||||
// opLookup is for mapping operators applied on auditRuleData
|
||||
var opLookup = map[int]string{
|
||||
AUDIT_EQUAL: "=",
|
||||
AUDIT_NOT_EQUAL: "!=",
|
||||
AUDIT_GREATER_THAN: ">",
|
||||
AUDIT_GREATER_THAN_OR_EQUAL: ">=",
|
||||
AUDIT_LESS_THAN: "<",
|
||||
AUDIT_LESS_THAN_OR_EQUAL: "<=",
|
||||
AUDIT_BIT_MASK: "&",
|
||||
AUDIT_BIT_TEST: "&=",
|
||||
}
|
||||
|
||||
// fieldLookup is for mapping fields applied on auditRuleData and also used for interpreting
|
||||
// fields set in auditRuleData struct
|
||||
var fieldLookup = map[int]string{
|
||||
AUDIT_PID: "pid",
|
||||
AUDIT_UID: "uid",
|
||||
AUDIT_EUID: "euid",
|
||||
AUDIT_SUID: "suid",
|
||||
AUDIT_FSUID: "fsuid",
|
||||
AUDIT_GID: "gid",
|
||||
AUDIT_EGID: "egid",
|
||||
AUDIT_SGID: "sgid",
|
||||
AUDIT_FSGID: "fsgid",
|
||||
AUDIT_LOGINUID: "auid",
|
||||
// AUDIT_LOGINUID: "loginuid",
|
||||
AUDIT_PERS: "pers",
|
||||
AUDIT_ARCH: "arch",
|
||||
AUDIT_MSGTYPE: "msgtype",
|
||||
AUDIT_SUBJ_USER: "subj_user",
|
||||
AUDIT_SUBJ_ROLE: "subj_role",
|
||||
AUDIT_SUBJ_TYPE: "subj_type",
|
||||
AUDIT_SUBJ_SEN: "subj_sen",
|
||||
AUDIT_SUBJ_CLR: "subj_clr",
|
||||
AUDIT_PPID: "ppid",
|
||||
AUDIT_OBJ_USER: "obj_user",
|
||||
AUDIT_OBJ_ROLE: "obj_role",
|
||||
AUDIT_OBJ_TYPE: "obj_type",
|
||||
AUDIT_OBJ_LEV_LOW: "obj_lev_low",
|
||||
AUDIT_OBJ_LEV_HIGH: "obj_lev_high",
|
||||
AUDIT_DEVMAJOR: "devmajor",
|
||||
AUDIT_DEVMINOR: "devminor",
|
||||
AUDIT_INODE: "inode",
|
||||
AUDIT_EXIT: "exit",
|
||||
AUDIT_SUCCESS: "success",
|
||||
AUDIT_WATCH: "path",
|
||||
AUDIT_PERM: "perm",
|
||||
AUDIT_DIR: "dir",
|
||||
AUDIT_FILETYPE: "filetype",
|
||||
AUDIT_OBJ_UID: "obj_uid",
|
||||
AUDIT_OBJ_GID: "obj_gid",
|
||||
AUDIT_FIELD_COMPARE: "field_compare",
|
||||
AUDIT_ARG0: "a0",
|
||||
AUDIT_ARG1: "a1",
|
||||
AUDIT_ARG2: "a2",
|
||||
AUDIT_ARG3: "a3",
|
||||
AUDIT_FILTERKEY: "key",
|
||||
AUDIT_EXE: "exe",
|
||||
}
|
||||
|
||||
// msgTypeTab is to look up audit header type based on string prefixes attached to audit messages
|
||||
var msgTypeTab = map[string]auditConstant{
|
||||
"USER": AUDIT_USER,
|
||||
"LOGIN": AUDIT_LOGIN,
|
||||
"USER_AUTH": AUDIT_USER_AUTH,
|
||||
"USER_ACCT": AUDIT_USER_ACCT,
|
||||
"USER_MGMT": AUDIT_USER_MGMT,
|
||||
"CRED_ACQ": AUDIT_CRED_ACQ,
|
||||
"CRED_DISP": AUDIT_CRED_DISP,
|
||||
"USER_START": AUDIT_USER_START,
|
||||
"USER_END": AUDIT_USER_END,
|
||||
"USER_AVC": AUDIT_USER_AVC,
|
||||
"USER_CHAUTHTOK": AUDIT_USER_CHAUTHTOK,
|
||||
"USER_ERR": AUDIT_USER_ERR,
|
||||
"CRED_REFR": AUDIT_CRED_REFR,
|
||||
"USYS_CONFIG": AUDIT_USYS_CONFIG,
|
||||
"USER_LOGIN": AUDIT_USER_LOGIN,
|
||||
"USER_LOGOUT": AUDIT_USER_LOGOUT,
|
||||
"ADD_USER": AUDIT_ADD_USER,
|
||||
"DEL_USER": AUDIT_DEL_USER,
|
||||
"ADD_GROUP": AUDIT_ADD_GROUP,
|
||||
"DEL_GROUP": AUDIT_DEL_GROUP,
|
||||
"DAC_CHECK": AUDIT_DAC_CHECK,
|
||||
"CHGRP_ID": AUDIT_CHGRP_ID,
|
||||
"TEST": AUDIT_TEST,
|
||||
"TRUSTED_APP": AUDIT_TRUSTED_APP,
|
||||
"USER_SELINUX_ERR": AUDIT_USER_SELINUX_ERR,
|
||||
"USER_CMD": AUDIT_USER_CMD,
|
||||
"USER_TTY": AUDIT_USER_TTY,
|
||||
"CHUSER_ID": AUDIT_CHUSER_ID,
|
||||
"GRP_AUTH": AUDIT_GRP_AUTH,
|
||||
"MAC_CHECK": AUDIT_MAC_CHECK,
|
||||
"ACCT_LOCK": AUDIT_ACCT_LOCK,
|
||||
"ACCT_UNLOCK": AUDIT_ACCT_UNLOCK,
|
||||
"SYSTEM_BOOT": AUDIT_SYSTEM_BOOT,
|
||||
"SYSTEM_SHUTDOWN": AUDIT_SYSTEM_SHUTDOWN,
|
||||
"SYSTEM_RUNLEVEL": AUDIT_SYSTEM_RUNLEVEL,
|
||||
"SERVICE_START": AUDIT_SERVICE_START,
|
||||
"SERVICE_STOP": AUDIT_SERVICE_STOP,
|
||||
"GRP_MGMT": AUDIT_GRP_MGMT,
|
||||
"GRP_CHAUTHTOK": AUDIT_GRP_CHAUTHTOK,
|
||||
// "DAEMON_START": AUDIT_DAEMON_START,
|
||||
// "DAEMON_END": AUDIT_DAEMON_END,
|
||||
// "DAEMON_ABORT": AUDIT_DAEMON_ABORT,
|
||||
"DAEMON_CONFIG": AUDIT_DAEMON_CONFIG,
|
||||
"DAEMON_RECONFIG": AUDIT_DAEMON_RECONFIG,
|
||||
"DAEMON_ROTATE": AUDIT_DAEMON_ROTATE,
|
||||
"DAEMON_RESUME": AUDIT_DAEMON_RESUME,
|
||||
"DAEMON_ACCEPT": AUDIT_DAEMON_ACCEPT,
|
||||
"DAEMON_CLOSE": AUDIT_DAEMON_CLOSE,
|
||||
// "DAEMON_ERR": AUDIT_DAEMON_ERR,
|
||||
"SYSCALL": AUDIT_SYSCALL,
|
||||
// "FS_WATCH": AUDIT_FS_WATCH,
|
||||
"PATH": AUDIT_PATH,
|
||||
"IPC": AUDIT_IPC,
|
||||
"SOCKETCALL": AUDIT_SOCKETCALL,
|
||||
"CONFIG_CHANGE": AUDIT_CONFIG_CHANGE,
|
||||
"SOCKADDR": AUDIT_SOCKADDR,
|
||||
"CWD": AUDIT_CWD,
|
||||
// "FS_INODE": AUDIT_FS_INODE,
|
||||
"EXECVE": AUDIT_EXECVE,
|
||||
"IPC_SET_PERM": AUDIT_IPC_SET_PERM,
|
||||
"MQ_OPEN": AUDIT_MQ_OPEN,
|
||||
"MQ_SENDRECV": AUDIT_MQ_SENDRECV,
|
||||
"MQ_NOTIFY": AUDIT_MQ_NOTIFY,
|
||||
"MQ_GETSETATTR": AUDIT_MQ_GETSETATTR,
|
||||
"KERNEL_OTHER": AUDIT_KERNEL_OTHER,
|
||||
"FD_PAIR": AUDIT_FD_PAIR,
|
||||
"OBJ_PID": AUDIT_OBJ_PID,
|
||||
"TTY": AUDIT_TTY,
|
||||
"EOE": AUDIT_EOE,
|
||||
"BPRM_FCAPS": AUDIT_BPRM_FCAPS,
|
||||
"CAPSET": AUDIT_CAPSET,
|
||||
"MMAP": AUDIT_MMAP,
|
||||
"NETFILTER_PKT": AUDIT_NETFILTER_PKT,
|
||||
"NETFILTER_CFG": AUDIT_NETFILTER_CFG,
|
||||
"SECCOMP": AUDIT_SECCOMP,
|
||||
"PROCTITLE": AUDIT_PROCTITLE,
|
||||
"FEATURE_CHANGE": AUDIT_FEATURE_CHANGE,
|
||||
"AVC": AUDIT_AVC,
|
||||
"SELINUX_ERR": AUDIT_SELINUX_ERR,
|
||||
"AVC_PATH": AUDIT_AVC_PATH,
|
||||
"MAC_POLICY_LOAD": AUDIT_MAC_POLICY_LOAD,
|
||||
"MAC_STATUS": AUDIT_MAC_STATUS,
|
||||
"MAC_CONFIG_CHANGE": AUDIT_MAC_CONFIG_CHANGE,
|
||||
"MAC_UNLBL_ALLOW": AUDIT_MAC_UNLBL_ALLOW,
|
||||
"MAC_CIPSOV4_ADD": AUDIT_MAC_CIPSOV4_ADD,
|
||||
"MAC_CIPSOV4_DEL": AUDIT_MAC_CIPSOV4_DEL,
|
||||
"MAC_MAP_ADD": AUDIT_MAC_MAP_ADD,
|
||||
"MAC_MAP_DEL": AUDIT_MAC_MAP_DEL,
|
||||
"MAC_IPSEC_ADDSA": AUDIT_MAC_IPSEC_ADDSA,
|
||||
"MAC_IPSEC_DELSA": AUDIT_MAC_IPSEC_DELSA,
|
||||
"MAC_IPSEC_ADDSPD": AUDIT_MAC_IPSEC_ADDSPD,
|
||||
"MAC_IPSEC_DELSPD": AUDIT_MAC_IPSEC_DELSPD,
|
||||
"MAC_IPSEC_EVENT": AUDIT_MAC_IPSEC_EVENT,
|
||||
"MAC_UNLBL_STCADD": AUDIT_MAC_UNLBL_STCADD,
|
||||
"MAC_UNLBL_STCDEL": AUDIT_MAC_UNLBL_STCDEL,
|
||||
"ANOM_PROMISCUOUS": AUDIT_ANOM_PROMISCUOUS,
|
||||
"ANOM_ABEND": AUDIT_ANOM_ABEND,
|
||||
"ANOM_LINK": AUDIT_ANOM_LINK,
|
||||
"INTEGRITY_DATA": AUDIT_INTEGRITY_DATA,
|
||||
"INTEGRITY_METADATA": AUDIT_INTEGRITY_METADATA,
|
||||
"INTEGRITY_STATUS": AUDIT_INTEGRITY_STATUS,
|
||||
"INTEGRITY_HASH": AUDIT_INTEGRITY_HASH,
|
||||
"INTEGRITY_PCR": AUDIT_INTEGRITY_PCR,
|
||||
"INTEGRITY_RULE": AUDIT_INTEGRITY_RULE,
|
||||
"APPARMOR": AUDIT_AA,
|
||||
"APPARMOR_AUDIT": AUDIT_APPARMOR_AUDIT,
|
||||
"APPARMOR_ALLOWED": AUDIT_APPARMOR_ALLOWED,
|
||||
"APPARMOR_DENIED": AUDIT_APPARMOR_DENIED,
|
||||
// "APPARMOR_HINT": AUDIT_APPARMOR_HINT,
|
||||
"APPARMOR_STATUS": AUDIT_APPARMOR_STATUS,
|
||||
"APPARMOR_ERROR": AUDIT_APPARMOR_ERROR,
|
||||
"KERNEL": AUDIT_KERNEL,
|
||||
"ANOM_LOGIN_FAILURES": AUDIT_ANOM_LOGIN_FAILURES,
|
||||
"ANOM_LOGIN_TIME": AUDIT_ANOM_LOGIN_TIME,
|
||||
"ANOM_LOGIN_SESSIONS": AUDIT_ANOM_LOGIN_SESSIONS,
|
||||
"ANOM_LOGIN_ACCT": AUDIT_ANOM_LOGIN_ACCT,
|
||||
"ANOM_LOGIN_LOCATION": AUDIT_ANOM_LOGIN_LOCATION,
|
||||
"ANOM_MAX_DAC": AUDIT_ANOM_MAX_DAC,
|
||||
"ANOM_MAX_MAC": AUDIT_ANOM_MAX_MAC,
|
||||
"ANOM_AMTU_FAIL": AUDIT_ANOM_AMTU_FAIL,
|
||||
"ANOM_RBAC_FAIL": AUDIT_ANOM_RBAC_FAIL,
|
||||
"ANOM_RBAC_INTEGRITY_FAIL": AUDIT_ANOM_RBAC_INTEGRITY_FAIL,
|
||||
"ANOM_CRYPTO_FAIL": AUDIT_ANOM_CRYPTO_FAIL,
|
||||
"ANOM_ACCESS_FS": AUDIT_ANOM_ACCESS_FS,
|
||||
"ANOM_EXEC": AUDIT_ANOM_EXEC,
|
||||
"ANOM_MK_EXEC": AUDIT_ANOM_MK_EXEC,
|
||||
"ANOM_ADD_ACCT": AUDIT_ANOM_ADD_ACCT,
|
||||
"ANOM_DEL_ACCT": AUDIT_ANOM_DEL_ACCT,
|
||||
"ANOM_MOD_ACCT": AUDIT_ANOM_MOD_ACCT,
|
||||
"ANOM_ROOT_TRANS": AUDIT_ANOM_ROOT_TRANS,
|
||||
"RESP_ANOMALY": AUDIT_RESP_ANOMALY,
|
||||
"RESP_ALERT": AUDIT_RESP_ALERT,
|
||||
"RESP_KILL_PROC": AUDIT_RESP_KILL_PROC,
|
||||
"RESP_TERM_ACCESS": AUDIT_RESP_TERM_ACCESS,
|
||||
"RESP_ACCT_REMOTE": AUDIT_RESP_ACCT_REMOTE,
|
||||
"RESP_ACCT_LOCK_TIMED": AUDIT_RESP_ACCT_LOCK_TIMED,
|
||||
"RESP_ACCT_UNLOCK_TIMED": AUDIT_RESP_ACCT_UNLOCK_TIMED,
|
||||
"RESP_ACCT_LOCK": AUDIT_RESP_ACCT_LOCK,
|
||||
"RESP_TERM_LOCK": AUDIT_RESP_TERM_LOCK,
|
||||
"RESP_SEBOOL": AUDIT_RESP_SEBOOL,
|
||||
"RESP_EXEC": AUDIT_RESP_EXEC,
|
||||
"RESP_SINGLE": AUDIT_RESP_SINGLE,
|
||||
"RESP_HALT": AUDIT_RESP_HALT,
|
||||
"USER_ROLE_CHANGE": AUDIT_USER_ROLE_CHANGE,
|
||||
"ROLE_ASSIGN": AUDIT_ROLE_ASSIGN,
|
||||
"ROLE_REMOVE": AUDIT_ROLE_REMOVE,
|
||||
"LABEL_OVERRIDE": AUDIT_LABEL_OVERRIDE,
|
||||
"LABEL_LEVEL_CHANGE": AUDIT_LABEL_LEVEL_CHANGE,
|
||||
"USER_LABELED_EXPORT": AUDIT_USER_LABELED_EXPORT,
|
||||
"USER_UNLABELED_EXPORT": AUDIT_USER_UNLABELED_EXPORT,
|
||||
"DEV_ALLOC": AUDIT_DEV_ALLOC,
|
||||
"DEV_DEALLOC": AUDIT_DEV_DEALLOC,
|
||||
"FS_RELABEL": AUDIT_FS_RELABEL,
|
||||
"USER_MAC_POLICY_LOAD": AUDIT_USER_MAC_POLICY_LOAD,
|
||||
"ROLE_MODIFY": AUDIT_ROLE_MODIFY,
|
||||
"USER_MAC_CONFIG_CHANGE": AUDIT_USER_MAC_CONFIG_CHANGE,
|
||||
"CRYPTO_TEST_USER": AUDIT_CRYPTO_TEST_USER,
|
||||
"CRYPTO_PARAM_CHANGE_USER": AUDIT_CRYPTO_PARAM_CHANGE_USER,
|
||||
"CRYPTO_LOGIN": AUDIT_CRYPTO_LOGIN,
|
||||
"CRYPTO_LOGOUT": AUDIT_CRYPTO_LOGOUT,
|
||||
"CRYPTO_KEY_USER": AUDIT_CRYPTO_KEY_USER,
|
||||
"CRYPTO_FAILURE_USER": AUDIT_CRYPTO_FAILURE_USER,
|
||||
"CRYPTO_REPLAY_USER": AUDIT_CRYPTO_REPLAY_USER,
|
||||
"CRYPTO_SESSION": AUDIT_CRYPTO_SESSION,
|
||||
"CRYPTO_IKE_SA": AUDIT_CRYPTO_IKE_SA,
|
||||
"CRYPTO_IPSEC_SA": AUDIT_CRYPTO_IPSEC_SA,
|
||||
"VIRT_CONTROL": AUDIT_VIRT_CONTROL,
|
||||
"VIRT_RESOURCE": AUDIT_VIRT_RESOURCE,
|
||||
"VIRT_MACHINE_ID": AUDIT_VIRT_MACHINE_ID,
|
||||
}
|
|
@ -0,0 +1,292 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type record struct {
|
||||
syscallNum string
|
||||
arch string
|
||||
a0 int
|
||||
a1 int
|
||||
}
|
||||
|
||||
// ErrorAuditParse is an implementation of the error interface that is returned by
|
||||
// ParseAuditEvent. msg will contain a description of the error, and the raw audit event
|
||||
// which failed parsing is returned in raw for inspection by the calling program.
|
||||
type ErrorAuditParse struct {
|
||||
Msg string
|
||||
Raw string
|
||||
}
|
||||
|
||||
// Error returns a string representation of ErrorAuditParse e
|
||||
func (e ErrorAuditParse) Error() string {
|
||||
return e.Msg
|
||||
}
|
||||
|
||||
// newErrorAuditParse returns a new ErrorAuditParse type with the fields populated
|
||||
func newErrorAuditParse(raw string, f string, v ...interface{}) ErrorAuditParse {
|
||||
ret := ErrorAuditParse{
|
||||
Raw: raw,
|
||||
Msg: fmt.Sprintf(f, v...),
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ParseAuditEvent parses an incoming audit message from kernel and returns an AuditEvent.
|
||||
//
|
||||
// msgType is supposed to come from the calling function which holds the msg header indicating header
|
||||
// type of the messages. It uses simple string parsing techniques and provider better performance than
|
||||
// the regex parser, idea taken from parse_up_record(rnode* r) in ellist.c (libauparse).
|
||||
func ParseAuditEvent(str string, msgType auditConstant, interpret bool) (*AuditEvent, error) {
|
||||
var r record
|
||||
var event = AuditEvent{
|
||||
Raw: str,
|
||||
}
|
||||
|
||||
// Create the map which will store the audit record fields for this event, note we
|
||||
// provide an allocation hint here based on the average number of fields we would come
|
||||
// across in an audit event
|
||||
m := make(map[string]string, 24)
|
||||
|
||||
if strings.HasPrefix(str, "audit(") {
|
||||
str = str[6:]
|
||||
} else {
|
||||
return nil, newErrorAuditParse(event.Raw, "malformed, missing audit prefix")
|
||||
}
|
||||
index := strings.Index(str, ":")
|
||||
if index == -1 {
|
||||
return nil, newErrorAuditParse(event.Raw, "malformed, can't locate start of fields")
|
||||
}
|
||||
|
||||
// determine timestamp
|
||||
timestamp := str[:index]
|
||||
// move further on string, skipping ':'
|
||||
str = str[index+1:]
|
||||
index = strings.Index(str, ")")
|
||||
if index == -1 {
|
||||
return nil, newErrorAuditParse(event.Raw, "malformed, can't locate end of prefix")
|
||||
}
|
||||
serial := str[:index]
|
||||
if strings.HasPrefix(str, serial+"): ") {
|
||||
str = str[index+3:]
|
||||
} else {
|
||||
return nil, newErrorAuditParse(event.Raw, "malformed, prefix termination unexpected")
|
||||
}
|
||||
|
||||
var (
|
||||
nBytes string
|
||||
orig = len(str)
|
||||
n int
|
||||
key string
|
||||
value string
|
||||
av bool
|
||||
)
|
||||
|
||||
for n < orig {
|
||||
getSpaceSlice(&str, &nBytes, &n)
|
||||
var newIndex int
|
||||
newIndex = strings.Index(nBytes, "=")
|
||||
if newIndex == -1 {
|
||||
// check type for special cases of AVC and USER_AVC
|
||||
if msgType == AUDIT_AVC || msgType == AUDIT_USER_AVC {
|
||||
if nBytes == "avc:" && strings.HasPrefix(str, "avc:") {
|
||||
// skip over 'avc:'
|
||||
str = str[len(nBytes)+1:]
|
||||
av = true
|
||||
continue
|
||||
}
|
||||
if av {
|
||||
key = "seresult"
|
||||
value = nBytes
|
||||
if interpret {
|
||||
var err error
|
||||
value, err = interpretField(key, value, msgType, r)
|
||||
if err != nil {
|
||||
return nil, newErrorAuditParse(event.Raw, "interpretField: %v", err)
|
||||
}
|
||||
}
|
||||
m[key] = value
|
||||
av = false
|
||||
if len(str) == len(nBytes) {
|
||||
break
|
||||
} else {
|
||||
str = str[len(nBytes)+1:]
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(nBytes, "{") {
|
||||
key = "seperms"
|
||||
str = str[len(nBytes)+1:]
|
||||
var v string
|
||||
getSpaceSlice(&str, &nBytes, &n)
|
||||
for nBytes != "}" {
|
||||
if len(v) != 0 {
|
||||
v += ","
|
||||
}
|
||||
v += nBytes
|
||||
str = str[len(nBytes)+1:]
|
||||
getSpaceSlice(&str, &nBytes, &n)
|
||||
}
|
||||
value = v
|
||||
if interpret {
|
||||
var err error
|
||||
value, err = interpretField(key, value, msgType, r)
|
||||
if err != nil {
|
||||
return nil, newErrorAuditParse(event.Raw, "interpretField: %v", err)
|
||||
}
|
||||
}
|
||||
m[key] = value
|
||||
fixPunctuations(&value)
|
||||
if len(str) == len(nBytes) {
|
||||
//reached the end of message
|
||||
break
|
||||
} else {
|
||||
str = str[len(nBytes)+1:]
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
// We might get values with space, add it to prev key
|
||||
// skip 'for' in avc message (special case)
|
||||
if nBytes == "for" {
|
||||
str = str[len(nBytes)+1:]
|
||||
continue
|
||||
}
|
||||
value += " " + nBytes
|
||||
fixPunctuations(&value)
|
||||
if interpret {
|
||||
var err error
|
||||
value, err = interpretField(key, value, msgType, r)
|
||||
if err != nil {
|
||||
return nil, newErrorAuditParse(event.Raw, "interpretField: %v", err)
|
||||
}
|
||||
}
|
||||
m[key] = value
|
||||
}
|
||||
} else {
|
||||
// We might get values with space, add it to prev key
|
||||
value += " " + nBytes
|
||||
fixPunctuations(&value)
|
||||
if interpret {
|
||||
var err error
|
||||
value, err = interpretField(key, value, msgType, r)
|
||||
if err != nil {
|
||||
return nil, newErrorAuditParse(event.Raw, "interpretField: %v", err)
|
||||
}
|
||||
}
|
||||
m[key] = value
|
||||
}
|
||||
|
||||
} else {
|
||||
key = nBytes[:newIndex]
|
||||
value = nBytes[newIndex+1:]
|
||||
// for cases like msg='
|
||||
// we look again for key value pairs
|
||||
if strings.HasPrefix(value, "'") && key == "msg" {
|
||||
newIndex = strings.Index(value, "=")
|
||||
if newIndex == -1 {
|
||||
// special case USER_AVC messages, start of: msg='avc:
|
||||
if strings.HasPrefix(str, "msg='avc") {
|
||||
str = str[5:]
|
||||
}
|
||||
continue
|
||||
}
|
||||
key = value[1:newIndex]
|
||||
value = value[newIndex+1:]
|
||||
}
|
||||
|
||||
fixPunctuations(&value)
|
||||
if key == "arch" {
|
||||
// determine machine type
|
||||
}
|
||||
if key == "a0" {
|
||||
val, err := strconv.ParseInt(value, 16, 64)
|
||||
if err != nil {
|
||||
r.a0 = -1
|
||||
} else {
|
||||
r.a0 = int(val)
|
||||
}
|
||||
}
|
||||
if key == "a1" {
|
||||
val, err := strconv.ParseInt(value, 16, 64)
|
||||
if err != nil {
|
||||
r.a1 = -1
|
||||
} else {
|
||||
r.a1 = int(val)
|
||||
}
|
||||
}
|
||||
if key == "syscall" {
|
||||
r.syscallNum = value
|
||||
}
|
||||
if interpret {
|
||||
var err error
|
||||
value, err = interpretField(key, value, msgType, r)
|
||||
if err != nil {
|
||||
return nil, newErrorAuditParse(event.Raw, "interpretField: %v", err)
|
||||
}
|
||||
}
|
||||
m[key] = value
|
||||
}
|
||||
if len(str) == len(nBytes) {
|
||||
// Reached the end of message
|
||||
break
|
||||
} else {
|
||||
str = str[len(nBytes)+1:]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
event.Timestamp = timestamp
|
||||
event.Serial = serial
|
||||
event.Data = m
|
||||
event.Type = msgType.String()[6:]
|
||||
return &event, nil
|
||||
|
||||
}
|
||||
|
||||
// getSpaceSlice checks the index of the next space and put the string up to that space into
|
||||
// the second string, total number of characters processed is updated with each call to the function
|
||||
func getSpaceSlice(str *string, b *string, v *int) {
|
||||
index := strings.Index(*str, " ")
|
||||
if index != -1 {
|
||||
if index == 0 {
|
||||
// Found space on the first location only, just forward on the orig
|
||||
// string and try again
|
||||
*str = (*str)[1:]
|
||||
getSpaceSlice(str, b, v)
|
||||
} else {
|
||||
*b = (*str)[:index]
|
||||
// Keep updating total characters processed
|
||||
*v += len(*b)
|
||||
}
|
||||
} else {
|
||||
*b = (*str)
|
||||
// Keep updating total characters processed
|
||||
*v += len(*b)
|
||||
}
|
||||
}
|
||||
|
||||
func fixPunctuations(value *string) {
|
||||
// Remove trailing punctuation
|
||||
l := len(*value)
|
||||
if l > 0 && strings.HasSuffix(*value, "'") {
|
||||
*value = (*value)[:l-1]
|
||||
l--
|
||||
}
|
||||
if l > 0 && strings.HasSuffix(*value, ",") {
|
||||
*value = (*value)[:l-1]
|
||||
l--
|
||||
}
|
||||
if l > 0 && strings.HasSuffix(*value, ")") {
|
||||
if *value != "(none)" && *value != "(null)" {
|
||||
*value = (*value)[:l-1]
|
||||
l--
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,340 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var auditTests = []struct {
|
||||
msg string
|
||||
msgType auditConstant
|
||||
expected error
|
||||
match bool
|
||||
event AuditEvent
|
||||
}{
|
||||
{
|
||||
`audit(1226874073.147:96): avc: denied { getattr } for pid=2465 comm="httpd" path="/var/www/html/file1 space" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "96",
|
||||
Timestamp: "1226874073.147",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"path": `"/var/www/html/file1 space"`, "dev": "dm-0", "ino": "284133", "scontext": "unconfined_u:system_r:httpd_t:s0", "tcontext": "unconfined_u:object_r:samba_share_t:s0", "pid": "2465", "seperms": "getattr", "comm": `"httpd"`, "tclass": "file", "seresult": "denied"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464176620.068:1445): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=23975 comm="chrome" exe="/opt/google/chrome/chrome" sig=0 arch=c000003e syscall=273 compat=0 ip=0x7f1da6d8b694 code=0x50000`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "1445",
|
||||
Timestamp: "1464176620.068",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"comm": `"chrome"`, "exe": `"/opt/google/chrome/chrome"`, "arch": "c000003e", "compat": "0", "code": "0x50000", "ses": "4294967295", "uid": "1000", "gid": "1000", "pid": "23975", "sig": "0", "syscall": "273", "ip": "0x7f1da6d8b694", "auid": "4294967295"},
|
||||
},
|
||||
},
|
||||
{`audit(1464163771.720:20): arch=c000003e syscall=1 success=yes exit=658651 a0=6 a1=7f26862ea010 a2=a0cdb a3=0 items=0 ppid=712 pid=716 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="apparmor_parser" exe="/sbin/apparmor_parser" key=(null)`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "20",
|
||||
Timestamp: "1464163771.720",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"success": "yes", "a2": "a0cdb", "uid": "0", "sgid": "0", "fsgid": "0", "ses": "4294967295", "exit": "658651", "a0": "6", "ppid": "712", "suid": "0", "key": "(null)", "tty": "(none)", "comm": `"apparmor_parser"`, "arch": "c000003e", "syscall": "1", "a1": "7f26862ea010", "items": "0", "pid": "716", "fsuid": "0", "exe": `"/sbin/apparmor_parser"`, "a3": "0", "auid": "4294967295", "gid": "0", "euid": "0", "egid": "0"},
|
||||
},
|
||||
},
|
||||
{`audit(1464093935.845:993): pid=4148 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:setcred acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/18 res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "993",
|
||||
Timestamp: "1464093935.845",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"op": "PAM:setcred", "acct": `"root"`, "hostname": "?", "addr": "?", "res": "success", "uid": "0", "auid": "4294967295", "exe": `"/usr/bin/sudo"`, "terminal": "/dev/pts/18", "pid": "4148", "ses": "4294967295"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1267534395.930:19): user pid=1169 uid=0 auid=4294967295 ses=4294967295 subj=system_u:unconfined_r:unconfined_t msg='avc: denied { read } for request=SELinux:SELinuxGetClientContext comm=X-setest resid=3c00001 restype=<unknown> scontext=unconfined_u:unconfined_r:x_select_paste_t tcontext=unconfined_u:unconfined_r:unconfined_t tclass=x_resource : exe="/usr/bin/Xorg " sauid=0 hostname=? addr=? terminal=?'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "19",
|
||||
Timestamp: "1267534395.930",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"": " user", "uid": "0", "subj": "system_u:unconfined_r:unconfined_t", "scontext": "unconfined_u:unconfined_r:x_select_paste_t", "ses": "4294967295", "comm": "X-setest", "sauid": "0", "addr": "?", "pid": "1169", "auid": "4294967295", "request": "SELinux:SELinuxGetClientContext", "resid": "3c00001", "restype": "<unknown>", "hostname": "?", "terminal": "?", "seresult": "denied", "seperms": "read", "tcontext": "unconfined_u:unconfined_r:unconfined_t", "tclass": "x_resource :", "exe": `"/usr/bin/Xorg "`},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464617439.911:1421): pid=30576 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:setcred acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/18 res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "1421",
|
||||
Timestamp: "1464617439.911",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"pid": "30576", "auid": "4294967295", "exe": `"/usr/bin/sudo"`, "addr": "?", "terminal": "/dev/pts/18", "uid": "0", "ses": "4294967295", "op": "PAM:setcred", "acct": `"root"`, "hostname": "?", "res": "success"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464617439.911:1422): pid=30576 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:session_open acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/18 res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "1422",
|
||||
Timestamp: "1464617439.911",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"uid": "0", "auid": "4294967295", "ses": "4294967295", "op": "PAM:session_open", "exe": `"/usr/bin/sudo"`, "addr": "?", "terminal": "/dev/pts/18", "pid": "30576", "res": "success", "hostname": "?", "acct": `"root"`},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464617444.219:1425): pid=30579 uid=1000 auid=4294967295 ses=4294967295 msg='cwd="/home/arun/Work/go-ground/src/github.com/arunk-s/parser" cmd=636174202F7661722F6C6F672F61756469742F61756469742E6C6F67 terminal=pts/18 res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "1425",
|
||||
Timestamp: "1464617444.219",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"auid": "4294967295", "ses": "4294967295", "cwd": `"/home/arun/Work/go-ground/src/github.com/arunk-s/parser"`, "cmd": "636174202F7661722F6C6F672F61756469742F61756469742E6C6F67", "terminal": "pts/18", "res": "success", "pid": "30579", "uid": "1000"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464617461.107:1431): pid=30586 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:setcred acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/18 res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "1431",
|
||||
Timestamp: "1464617461.107",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"exe": `"/usr/bin/sudo"`, "hostname": "?", "addr": "?", "terminal": "/dev/pts/18", "res": "success", "pid": "30586", "uid": "0", "auid": "4294967295", "ses": "4294967295", "op": "PAM:setcred", "acct": `"root"`},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464614823.239:1290): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=NetworkManager-dispatcher comm="systemd" exe="/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "1290",
|
||||
Timestamp: "1464614823.239",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"hostname": "?", "addr": "?", "res": "success", "auid": "4294967295", "ses": "4294967295", "unit": "NetworkManager-dispatcher", "comm": `"systemd"`, "exe": `"/lib/systemd/systemd"`, "pid": "1", "uid": "0", "terminal": "?"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464614843.495:1292): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-rfkill comm="systemd" exe="/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "1292",
|
||||
Timestamp: "1464614843.495",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"pid": "1", "auid": "4294967295", "ses": "4294967295", "unit": "systemd-rfkill", "comm": `"systemd"`, "exe": `"/lib/systemd/systemd"`, "hostname": "?", "res": "success", "uid": "0", "addr": "?", "terminal": "?"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464590772.564:302): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=5803 comm="chrome" exe="/opt/google/chrome/chrome" sig=0 arch=c000003e syscall=273 compat=0 ip=0x7f3deee65694 code=0x50000`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "302",
|
||||
Timestamp: "1464590772.564",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"pid": "5803", "comm": `"chrome"`, "syscall": "273", "ip": "0x7f3deee65694", "gid": "1000", "uid": "1000", "ses": "4294967295", "exe": `"/opt/google/chrome/chrome"`, "sig": "0", "arch": "c000003e", "compat": "0", "code": "0x50000", "auid": "4294967295"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464505771.166:388): pid=1 uid=0 auid=4294967295 ses=4294967295'unit=NetworkManager-dispatcher comm="systemd" exe="/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "388",
|
||||
Timestamp: "1464505771.166",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"pid": "1", "hostname": "?", "res": "success", "terminal": "?", "uid": "0", "auid": "4294967295", "ses": "4294967295'unit=NetworkManager-dispatcher", "comm": `"systemd"`, "exe": `"/lib/systemd/systemd"`, "addr": "?"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464505794.710:389): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=4075 comm="Chrome_libJingl" exe="/opt/google/chrome/chrome" sig=0 arch=c000003e syscall=273 compat=0 ip=0x7fb359e4d694 code=0x50000`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "389",
|
||||
Timestamp: "1464505794.710",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"auid": "4294967295", "comm": `"Chrome_libJingl"`, "sig": "0", "arch": "c000003e", "ip": "0x7fb359e4d694", "code": "0x50000", "uid": "1000", "gid": "1000", "ses": "4294967295", "pid": "4075", "exe": `"/opt/google/chrome/chrome"`, "syscall": "273", "compat": "0"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464505808.342:401): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=4076 comm="Chrome_libJingl" exe="/opt/google/chrome/chrome" sig=0 arch=c000003e syscall=273 compat=0 ip=0x7fb359e4d694 code=0x50000`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "401",
|
||||
Timestamp: "1464505808.342",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"pid": "4076", "comm": `"Chrome_libJingl"`, "exe": `"/opt/google/chrome/chrome"`, "sig": "0", "syscall": "273", "compat": "0", "code": "0x50000", "ses": "4294967295", "uid": "1000", "gid": "1000", "arch": "c000003e", "ip": "0x7fb359e4d694", "auid": "4294967295"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464505810.566:403): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=4078 comm="chrome" exe="/opt/google/chrome/chrome" sig=0 arch=c000003e syscall=273 compat=0 ip=0x7fb359e4d694 code=0x50000`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "403",
|
||||
Timestamp: "1464505810.566",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"auid": "4294967295", "exe": `"/opt/google/chrome/chrome"`, "sig": "0", "arch": "c000003e", "syscall": "273", "compat": "0", "code": "0x50000", "uid": "1000", "gid": "1000", "ses": "4294967295", "pid": "4078", "comm": `"chrome"`, "ip": "0x7fb359e4d694"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464505927.046:474): pid=1 uid=0 auid=4294967295 ses=4294967295 unit=lm-sensors comm="systemd" exe="/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "474",
|
||||
Timestamp: "1464505927.046",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"uid": "0", "exe": `"/lib/systemd/systemd"`, "hostname": "?", "addr": "?", "terminal": "?", "res": "success", "pid": "1", "auid": "4294967295", "ses": "4294967295", "unit": "lm-sensors", "comm": `"systemd"`},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464505927.314:508): pid=1 uid=0 auid=4294967295 ses=4294967295 unit=rc-local comm="systemd" exe="/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "508",
|
||||
Timestamp: "1464505927.314",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"pid": "1", "hostname": "?", "addr": "?", "unit": "rc-local", "comm": `"systemd"`, "exe": `"/lib/systemd/systemd"`, "terminal": "?", "res": "success", "uid": "0", "auid": "4294967295", "ses": "4294967295"},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1464550921.784:3509): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=14869 comm="chrome" exe="/opt/google/chrome/chrome" sig=0 arch=c000003e syscall=273 compat=0 ip=0x7f26b8828694 code=0x50000`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "3509",
|
||||
Timestamp: "1464550921.784",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"syscall": "273", "compat": "0", "ip": "0x7f26b8828694", "code": "0x50000", "auid": "4294967295", "uid": "1000", "gid": "1000", "sig": "0", "arch": "c000003e", "ses": "4294967295", "pid": "14869", "comm": `"chrome"`, "exe": `"/opt/google/chrome/chrome"`},
|
||||
},
|
||||
},
|
||||
{
|
||||
`audit(1170021493.977:293): avc: denied { read write } for pid=13010 comm="pickup" name="maildrop" dev=hda7 ino=14911367 scontext=system_u:system_r:postfix_pickup_t:s0 tcontext=system_u:object_r:postfix_spool_maildrop_t:s0 tclass=dir`,
|
||||
AUDIT_AVC,
|
||||
nil,
|
||||
true,
|
||||
AuditEvent{
|
||||
Serial: "293",
|
||||
Timestamp: "1170021493.977",
|
||||
Type: "AVC",
|
||||
Data: map[string]string{
|
||||
"scontext": "system_u:system_r:postfix_pickup_t:s0", "seresult": "denied", "comm": `"pickup"`, "name": `"maildrop"`, "dev": "hda7", "ino": "14911367", "tcontext": "system_u:object_r:postfix_spool_maildrop_t:s0", "tclass": "dir", "seperms": "read,write", "pid": "13010"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestMalformedPrefix(t *testing.T) {
|
||||
tmsg := []struct {
|
||||
msg string
|
||||
msgType auditConstant
|
||||
err string
|
||||
}{
|
||||
{"xyzabc", AUDIT_AVC, "malformed, missing audit prefix"},
|
||||
{`audit(1464163771`, AUDIT_AVC, "malformed, can't locate start of fields"},
|
||||
{`audit(1464176620.068:1445`, AUDIT_AVC, "malformed, can't locate end of prefix"},
|
||||
}
|
||||
for _, m := range tmsg {
|
||||
_, err := ParseAuditEvent(m.msg, m.msgType, false)
|
||||
if err == nil {
|
||||
t.Fatalf("ParseAuditEvent should have failed on %q", m.msg)
|
||||
}
|
||||
if err.Error() != m.err {
|
||||
t.Fatalf("ParseAuditEvent failed, but error %q was unexpected", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNativeParser(t *testing.T) {
|
||||
for i, tt := range auditTests {
|
||||
x, err := ParseAuditEvent(tt.msg, tt.msgType, false)
|
||||
if err != tt.expected {
|
||||
t.Fatalf("ParseAuditEvent: event %v had unexpected error value", i)
|
||||
}
|
||||
if tt.match {
|
||||
checkEvent(i, &tt.event, x, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNativeParser(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
ParseAuditEvent(`audit(1226874073.147:96): avc: denied { getattr } for pid=2465 comm="httpd" path="/var/www/html/file1 space" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file`, AUDIT_AVC, true)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNativeParserTable(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
for _, x := range auditTests {
|
||||
ParseAuditEvent(x.msg, AUDIT_AVC, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkEvent compares auditEvent a to b, ensuring they are identical.
|
||||
func checkEvent(eventid int, a *AuditEvent, b *AuditEvent, t *testing.T) {
|
||||
if a.Serial != b.Serial {
|
||||
t.Fatalf("audit event %v serial did not match", eventid)
|
||||
}
|
||||
if a.Timestamp != b.Timestamp {
|
||||
t.Fatalf("audit event %v timestamp did not match", eventid)
|
||||
}
|
||||
if a.Type != b.Type {
|
||||
t.Fatalf("audit event %v type did not match", eventid)
|
||||
}
|
||||
if !reflect.DeepEqual(a.Data, b.Data) {
|
||||
t.Fatalf("audit event %v data was not equal", eventid)
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,148 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package libaudit
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var expectedRules = []string{
|
||||
"-w /etc/libaudit.conf -p wa -k audit",
|
||||
"-w /etc/rsyslog.conf -p wa -k syslog",
|
||||
"-a always,exit-F arch=b64 -S personality -F key=bypass",
|
||||
"-a never,exit -F path=/bin/ls -F perm=x",
|
||||
"-a always,exit-F arch=b64 -S execve -F key=exec",
|
||||
"-a always,exit -S clone,fork,vfork",
|
||||
"-a always,exit -S adjtimex,settimeofday -F key=time-change",
|
||||
"-a always,exit-F arch=b64 -S rename,renameat -F auid>=1000 -F key=rename",
|
||||
}
|
||||
|
||||
func TestSetRules(t *testing.T) {
|
||||
if os.Getuid() != 0 {
|
||||
t.Skipf("skipping test, not root user")
|
||||
}
|
||||
|
||||
jsonRules, err := ioutil.ReadFile("./testdata/rules.json")
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
|
||||
s, err := NewNetlinkConnection()
|
||||
if err != nil {
|
||||
t.Fatalf("NewNetlinkConnection: %v", err)
|
||||
}
|
||||
err = DeleteAllRules(s)
|
||||
if err != nil {
|
||||
t.Fatalf("DeleteAllRules: %v", err)
|
||||
}
|
||||
|
||||
_, err = SetRules(s, jsonRules)
|
||||
if err != nil {
|
||||
t.Fatalf("SetRules: %v", err)
|
||||
}
|
||||
s.Close()
|
||||
|
||||
// Open up a new connection before we list the rules
|
||||
x, err := NewNetlinkConnection()
|
||||
if err != nil {
|
||||
t.Fatalf("NewNetlinkConnection: %v", err)
|
||||
}
|
||||
|
||||
setRules, err := ListAllRules(x)
|
||||
if err != nil {
|
||||
t.Fatalf("ListAllRules: %v", err)
|
||||
}
|
||||
if len(setRules) != len(expectedRules) {
|
||||
t.Fatalf("number of set rules unexpected, wanted %v got %v", len(expectedRules),
|
||||
len(setRules))
|
||||
}
|
||||
for i := range setRules {
|
||||
if setRules[i] != expectedRules[i] {
|
||||
t.Fatalf("expected rule %q, got rule %q", expectedRules[i], setRules[i])
|
||||
}
|
||||
}
|
||||
x.Close()
|
||||
}
|
||||
|
||||
// Try to load a rule set with strict path checking enabled, where the path in a watch rule is
|
||||
// nonexistent; should fail.
|
||||
func TestSetRulesStrictPathFail(t *testing.T) {
|
||||
if os.Getuid() != 0 {
|
||||
t.Skipf("skipping test, not root user")
|
||||
}
|
||||
|
||||
jsonRules, err := ioutil.ReadFile("./testdata/strictpathfail.json")
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
|
||||
s, err := NewNetlinkConnection()
|
||||
if err != nil {
|
||||
t.Fatalf("NewNetlinkConnection: %v", err)
|
||||
}
|
||||
err = DeleteAllRules(s)
|
||||
if err != nil {
|
||||
t.Fatalf("DeleteAllRules: %v", err)
|
||||
}
|
||||
|
||||
_, err = SetRules(s, jsonRules)
|
||||
if err == nil {
|
||||
t.Fatalf("SetRules should have failed on nonexistent path")
|
||||
}
|
||||
s.Close()
|
||||
}
|
||||
|
||||
// Try to load a rule set with strict path checking disabled, where the path in a watch rule is
|
||||
// nonexistent; should succeed but ignore the invalid rule.
|
||||
func TestSetRulesNoStrictPath(t *testing.T) {
|
||||
if os.Getuid() != 0 {
|
||||
t.Skipf("skipping test, not root user")
|
||||
}
|
||||
|
||||
jsonRules, err := ioutil.ReadFile("./testdata/badpathnostrictpath.json")
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
|
||||
s, err := NewNetlinkConnection()
|
||||
if err != nil {
|
||||
t.Fatalf("NewNetlinkConnection: %v", err)
|
||||
}
|
||||
err = DeleteAllRules(s)
|
||||
if err != nil {
|
||||
t.Fatalf("DeleteAllRules: %v", err)
|
||||
}
|
||||
|
||||
warnings, err := SetRules(s, jsonRules)
|
||||
if err != nil {
|
||||
t.Fatalf("SetRules: %v", err)
|
||||
}
|
||||
|
||||
// We should have gotten one warning back
|
||||
if len(warnings) != 1 {
|
||||
t.Fatalf("SetRules: should have returned 1 warning")
|
||||
}
|
||||
|
||||
// Open up a new connection before we list the rules
|
||||
x, err := NewNetlinkConnection()
|
||||
if err != nil {
|
||||
t.Fatalf("NewNetlinkConnection: %v", err)
|
||||
}
|
||||
|
||||
setRules, err := ListAllRules(x)
|
||||
if err != nil {
|
||||
t.Fatalf("ListAllRules: %v", err)
|
||||
}
|
||||
// We should have 1 rule here, since the test data set contains 2 rules, one of which
|
||||
// should have been ignored.
|
||||
expectedRules := 1
|
||||
if len(setRules) != expectedRules {
|
||||
t.Fatalf("number of set rules unexpected, wanted %v got %v", expectedRules,
|
||||
len(setRules))
|
||||
}
|
||||
s.Close()
|
||||
}
|
244
vendor/github.com/mozilla/libaudit-go/s2i_type_conversion.json
сгенерированный
поставляемый
Normal file
244
vendor/github.com/mozilla/libaudit-go/s2i_type_conversion.json
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,244 @@
|
|||
{
|
||||
"machine" : [
|
||||
{
|
||||
"string": "armeb",
|
||||
"s2iS" : 0,
|
||||
"s2iI" : 8
|
||||
},
|
||||
{
|
||||
"name": "armv5tejl",
|
||||
"s2iS" : 6,
|
||||
"s2iI" : 8
|
||||
},
|
||||
{
|
||||
"name": "armv7l",
|
||||
"s2iS" : 16,
|
||||
"s2iI" : 8
|
||||
},
|
||||
{
|
||||
"name": "i386",
|
||||
"s2iS" : 23,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "i486",
|
||||
"s2iS" : 28,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "i586",
|
||||
"s2iS" : 33,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "i686",
|
||||
"s2iS" : 38,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ia64",
|
||||
"s2iS" : 43,
|
||||
"s2iI" : 2
|
||||
},
|
||||
{
|
||||
"name": "ppc",
|
||||
"s2iS" : 48,
|
||||
"s2iI" : 4
|
||||
},
|
||||
{
|
||||
"name": "ppc64",
|
||||
"s2iS" : 52,
|
||||
"s2iI" : 3
|
||||
},
|
||||
{
|
||||
"name": "s390",
|
||||
"s2iS" : 58,
|
||||
"s2iI" : 6
|
||||
},
|
||||
{
|
||||
"name": "s390x",
|
||||
"s2iS" : 63,
|
||||
"s2iI" : 5
|
||||
},
|
||||
{
|
||||
"name": "x86_64",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 1
|
||||
}
|
||||
],
|
||||
|
||||
"errStrings" : [
|
||||
{
|
||||
"string": "E2BIG",,
|
||||
"s2iS" : 0,
|
||||
"s2iI" : 8
|
||||
},
|
||||
{
|
||||
"name": "EACCES",
|
||||
"s2iS" : 6,
|
||||
"s2iI" : 8
|
||||
},
|
||||
{
|
||||
"name": "EADDRINUSE",
|
||||
"s2iS" : 16,
|
||||
"s2iI" : 8
|
||||
},
|
||||
{
|
||||
"name": ,"EADDRNOTAVAIL",
|
||||
"s2iS" : 23,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EADV",
|
||||
"s2iS" : 28,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EAFNOSUPPORT",
|
||||
"s2iS" : 33,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EAGAIN",
|
||||
"s2iS" : 38,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EALREADY",
|
||||
"s2iS" : 43,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EBADE",
|
||||
"s2iS" : 48,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EBADF",
|
||||
"s2iS" : 52,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EBADFD",
|
||||
"s2iS" : 58,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EBADMSG",
|
||||
"s2iS" : 63,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EBADR",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EBADRQC",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EBADSLT",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": ,"EBFONT",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EBUSY",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ECANCELED",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ECHILD",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ECHRNG",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ECOMM",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ECONNABORTED",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ECONNREFUSED",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "ECONNRESET",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EDEADLK",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EDEADLOCK",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EDESTADDRREQ",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EDOM",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EDOTDOT",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EDQUOT",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EEXIST",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EFAULT",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EFBIG",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
},
|
||||
{
|
||||
"name": "EHOSTDOWN",
|
||||
"s2iS" : 69,
|
||||
"s2iI" : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
////////// Need to make message type follow http://www.filewatcher.com/p/audit-debuginfo-1.7.7-6.el5.ia64.rpm.955920/usr/src/debug/audit-1.7.7/lib/msg_typetabs.h.html to make it
|
27
vendor/github.com/mozilla/libaudit-go/testdata/badpathnostrictpath.json
сгенерированный
поставляемый
Normal file
27
vendor/github.com/mozilla/libaudit-go/testdata/badpathnostrictpath.json
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"audit_rules": [
|
||||
{
|
||||
"key": "nonexist",
|
||||
"path": "/non/existent/path",
|
||||
"permission": "wa",
|
||||
"strict_path_check": false
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
"always",
|
||||
"exit"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "arch",
|
||||
"op": "eq",
|
||||
"value": 64
|
||||
}
|
||||
],
|
||||
"key": "bypass",
|
||||
"syscalls": [
|
||||
"personality"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
111
vendor/github.com/mozilla/libaudit-go/testdata/rules.json
сгенерированный
поставляемый
Normal file
111
vendor/github.com/mozilla/libaudit-go/testdata/rules.json
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,111 @@
|
|||
{
|
||||
"audit_rules": [
|
||||
{
|
||||
"key": "audit",
|
||||
"path": "/etc/libaudit.conf",
|
||||
"permission": "wa"
|
||||
},
|
||||
{
|
||||
"key": "syslog",
|
||||
"path": "/etc/rsyslog.conf",
|
||||
"permission": "wa"
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
"always",
|
||||
"exit"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "arch",
|
||||
"op": "eq",
|
||||
"value": 64
|
||||
}
|
||||
],
|
||||
"key": "bypass",
|
||||
"syscalls": [
|
||||
"personality"
|
||||
]
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
"exit",
|
||||
"never"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "path",
|
||||
"op": "eq",
|
||||
"value": "/bin/ls"
|
||||
},
|
||||
{
|
||||
"name": "perm",
|
||||
"op": "eq",
|
||||
"value": "x"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
"exit",
|
||||
"always"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "arch",
|
||||
"op": "eq",
|
||||
"value": 64
|
||||
}
|
||||
],
|
||||
"key": "exec",
|
||||
"syscalls": [
|
||||
"execve"
|
||||
]
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
"entry",
|
||||
"always"
|
||||
],
|
||||
"syscalls": [
|
||||
"clone",
|
||||
"fork",
|
||||
"vfork"
|
||||
]
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
"always",
|
||||
"exit"
|
||||
],
|
||||
"syscalls": [
|
||||
"settimeofday",
|
||||
"adjtimex"
|
||||
],
|
||||
"key": "time-change"
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
"always",
|
||||
"exit"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "arch",
|
||||
"op": "eq",
|
||||
"value": 64
|
||||
},
|
||||
{
|
||||
"name": "auid",
|
||||
"op": "gt_or_eq",
|
||||
"value": 1000
|
||||
}
|
||||
],
|
||||
"key": "rename",
|
||||
"syscalls": [
|
||||
"rename",
|
||||
"renameat"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
10
vendor/github.com/mozilla/libaudit-go/testdata/strictpathfail.json
сгенерированный
поставляемый
Normal file
10
vendor/github.com/mozilla/libaudit-go/testdata/strictpathfail.json
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"audit_rules": [
|
||||
{
|
||||
"key": "nonexist",
|
||||
"path": "/non/existent/path",
|
||||
"permission": "wa",
|
||||
"strict_path_check": true
|
||||
}
|
||||
]
|
||||
}
|
10
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/.travis.yml
сгенерированный
поставляемый
Normal file
10
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/.travis.yml
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
language: go
|
||||
sudo: false
|
||||
|
||||
script: go test -v
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- tip
|
19
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/LICENSE
сгенерированный
поставляемый
Normal file
19
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/LICENSE
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2015 Ryan Hileman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
103
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/README.md
сгенерированный
поставляемый
Normal file
103
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/README.md
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,103 @@
|
|||
[![Build Status](https://travis-ci.org/lunixbochs/struc.svg?branch=master)](https://travis-ci.org/lunixbochs/struc)
|
||||
|
||||
struc
|
||||
====
|
||||
|
||||
Struc exists to pack and unpack C-style structures from bytes, which is useful for binary files and network protocols. It could be considered an alternative to `encoding/binary`, which requires massive boilerplate for some similar operations.
|
||||
|
||||
Take a look at an [example comparing `struc` and `encoding/binary`](https://bochs.info/p/cxvm9)
|
||||
|
||||
Struc considers usability first. That said, it does cache reflection data and aims to be competitive with `encoding/binary` struct packing in every way, including performance.
|
||||
|
||||
Example struct
|
||||
----
|
||||
|
||||
```Go
|
||||
type Example struct {
|
||||
Var int `struc:"int32,sizeof=Str"`
|
||||
Str string
|
||||
Weird []byte `struc:"[8]int64"`
|
||||
Var []int `struc:"[]int32,little"`
|
||||
}
|
||||
```
|
||||
|
||||
Struct tag format
|
||||
----
|
||||
|
||||
- ```Var []int `struc:"[]int32,little,sizeof=StringField"` ``` will pack Var as a slice of little-endian int32, and link it as the size of `StringField`.
|
||||
- `sizeof=`: Indicates this field is a number used to track the length of a another field. `sizeof` fields are automatically updated on `Pack()` based on the current length of the tracked field, and are used to size the target field during `Unpack()`.
|
||||
- Bare values will be parsed as type and endianness.
|
||||
|
||||
Endian formats
|
||||
----
|
||||
|
||||
- `big` (default)
|
||||
- `little`
|
||||
|
||||
Recognized types
|
||||
----
|
||||
|
||||
- `pad` - this type ignores field contents and is backed by a `[length]byte` containing nulls
|
||||
- `bool`
|
||||
- `byte`
|
||||
- `int8`, `uint8`
|
||||
- `int16`, `uint16`
|
||||
- `int32`, `uint32`
|
||||
- `int64`, `uint64`
|
||||
- `float32`
|
||||
- `float64`
|
||||
|
||||
Types can be indicated as arrays/slices using `[]` syntax. Example: `[]int64`, `[8]int32`.
|
||||
|
||||
Bare slice types (those with no `[size]`) must have a linked `Sizeof` field.
|
||||
|
||||
Private fields are ignored when packing and unpacking.
|
||||
|
||||
Example code
|
||||
----
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/lunixbochs/struc"
|
||||
)
|
||||
|
||||
type Example struct {
|
||||
A int `struc:"big"`
|
||||
|
||||
// B will be encoded/decoded as a 16-bit int (a "short")
|
||||
// but is stored as a native int in the struct
|
||||
B int `struc:"int16"`
|
||||
|
||||
// the sizeof key links a buffer's size to any int field
|
||||
Size int `struc:"int8,little,sizeof=Str"`
|
||||
Str string
|
||||
|
||||
// you can get freaky if you want
|
||||
Str2 string `struc:"[5]int64"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
var buf bytes.Buffer
|
||||
t := &Example{1, 2, 0, "test", "test2"}
|
||||
err := struc.Pack(&buf, t)
|
||||
o := &Example{}
|
||||
err = struc.Unpack(&buf, o)
|
||||
}
|
||||
```
|
||||
|
||||
Benchmark
|
||||
----
|
||||
|
||||
`BenchmarkEncode` uses struc. `Stdlib` benchmarks use equivalent `encoding/binary` code. `Manual` encodes without any reflection, and should be considered an upper bound on performance (which generated code based on struc definitions should be able to achieve).
|
||||
|
||||
```
|
||||
BenchmarkEncode 1000000 1265 ns/op
|
||||
BenchmarkStdlibEncode 1000000 1855 ns/op
|
||||
BenchmarkManualEncode 5000000 284 ns/op
|
||||
BenchmarkDecode 1000000 1259 ns/op
|
||||
BenchmarkStdlibDecode 1000000 1656 ns/op
|
||||
BenchmarkManualDecode 20000000 89.0 ns/op
|
||||
```
|
165
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/bench_test.go
сгенерированный
поставляемый
Normal file
165
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/bench_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,165 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type BenchExample struct {
|
||||
Test [5]byte
|
||||
A int32
|
||||
B, C, D int16
|
||||
Test2 [4]byte
|
||||
Length int32
|
||||
}
|
||||
|
||||
type BenchStrucExample struct {
|
||||
Test [5]byte `struc:"[5]byte"`
|
||||
A int `struc:"int32"`
|
||||
B, C, D int `struc:"int16"`
|
||||
Test2 [4]byte `struc:"[4]byte"`
|
||||
Length int `struc:"int32,sizeof=Data"`
|
||||
Data []byte
|
||||
}
|
||||
|
||||
var benchRef = &BenchExample{
|
||||
[5]byte{1, 2, 3, 4, 5},
|
||||
1, 2, 3, 4,
|
||||
[4]byte{1, 2, 3, 4},
|
||||
8,
|
||||
}
|
||||
|
||||
var eightBytes = []byte("8bytestr")
|
||||
|
||||
var benchStrucRef = &BenchStrucExample{
|
||||
[5]byte{1, 2, 3, 4, 5},
|
||||
1, 2, 3, 4,
|
||||
[4]byte{1, 2, 3, 4},
|
||||
8, eightBytes,
|
||||
}
|
||||
|
||||
func BenchmarkEncode(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
err := Pack(&buf, benchStrucRef)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStdlibEncode(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
err := binary.Write(&buf, binary.BigEndian, benchRef)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, err = buf.Write(eightBytes)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkManualEncode(b *testing.B) {
|
||||
order := binary.BigEndian
|
||||
s := benchStrucRef
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
tmp := make([]byte, 29)
|
||||
copy(tmp[0:5], s.Test[:])
|
||||
order.PutUint32(tmp[5:9], uint32(s.A))
|
||||
order.PutUint16(tmp[9:11], uint16(s.B))
|
||||
order.PutUint16(tmp[11:13], uint16(s.C))
|
||||
order.PutUint16(tmp[13:15], uint16(s.D))
|
||||
copy(tmp[15:19], s.Test2[:])
|
||||
order.PutUint32(tmp[19:23], uint32(s.Length))
|
||||
copy(tmp[23:], s.Data)
|
||||
_, err := buf.Write(tmp)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecode(b *testing.B) {
|
||||
var out BenchStrucExample
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, benchStrucRef); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
bufBytes := buf.Bytes()
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := bytes.NewReader(bufBytes)
|
||||
err := Unpack(buf, &out)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
out.Data = nil
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStdlibDecode(b *testing.B) {
|
||||
var out BenchExample
|
||||
var buf bytes.Buffer
|
||||
binary.Write(&buf, binary.BigEndian, *benchRef)
|
||||
_, err := buf.Write(eightBytes)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
bufBytes := buf.Bytes()
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := bytes.NewReader(bufBytes)
|
||||
err := binary.Read(buf, binary.BigEndian, &out)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
tmp := make([]byte, out.Length)
|
||||
_, err = buf.Read(tmp)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkManualDecode(b *testing.B) {
|
||||
var o BenchStrucExample
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, benchStrucRef); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
tmp := buf.Bytes()
|
||||
order := binary.BigEndian
|
||||
for i := 0; i < b.N; i++ {
|
||||
copy(o.Test[:], tmp[0:5])
|
||||
o.A = int(order.Uint32(tmp[5:9]))
|
||||
o.B = int(order.Uint16(tmp[9:11]))
|
||||
o.C = int(order.Uint16(tmp[11:13]))
|
||||
o.D = int(order.Uint16(tmp[13:15]))
|
||||
copy(o.Test2[:], tmp[15:19])
|
||||
o.Length = int(order.Uint32(tmp[19:23]))
|
||||
o.Data = make([]byte, o.Length)
|
||||
copy(o.Data, tmp[23:])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFullEncode(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, reference); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFullDecode(b *testing.B) {
|
||||
var out Example
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := bytes.NewBuffer(referenceBytes)
|
||||
if err := Unpack(buf, &out); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
52
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/binary.go
сгенерированный
поставляемый
Normal file
52
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/binary.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,52 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type byteWriter struct {
|
||||
buf []byte
|
||||
pos int
|
||||
}
|
||||
|
||||
func (b byteWriter) Write(p []byte) (int, error) {
|
||||
capacity := len(b.buf) - b.pos
|
||||
if capacity < len(p) {
|
||||
p = p[:capacity]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
copy(b.buf[b.pos:], p)
|
||||
b.pos += len(p)
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
type binaryFallback reflect.Value
|
||||
|
||||
func (b binaryFallback) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (b binaryFallback) Sizeof(val reflect.Value, options *Options) int {
|
||||
return binary.Size(val.Interface())
|
||||
}
|
||||
|
||||
func (b binaryFallback) Pack(buf []byte, val reflect.Value, options *Options) (int, error) {
|
||||
tmp := byteWriter{buf: buf}
|
||||
var order binary.ByteOrder = binary.BigEndian
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
err := binary.Write(tmp, order, val.Interface())
|
||||
return tmp.pos, err
|
||||
}
|
||||
|
||||
func (b binaryFallback) Unpack(r io.Reader, val reflect.Value, options *Options) error {
|
||||
var order binary.ByteOrder = binary.BigEndian
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
return binary.Read(r, order, val.Interface())
|
||||
}
|
33
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom.go
сгенерированный
поставляемый
Normal file
33
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,33 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Custom interface {
|
||||
Pack(p []byte, opt *Options) (int, error)
|
||||
Unpack(r io.Reader, length int, opt *Options) error
|
||||
Size(opt *Options) int
|
||||
String() string
|
||||
}
|
||||
|
||||
type customFallback struct {
|
||||
custom Custom
|
||||
}
|
||||
|
||||
func (c customFallback) Pack(p []byte, val reflect.Value, opt *Options) (int, error) {
|
||||
return c.custom.Pack(p, opt)
|
||||
}
|
||||
|
||||
func (c customFallback) Unpack(r io.Reader, val reflect.Value, opt *Options) error {
|
||||
return c.custom.Unpack(r, 1, opt)
|
||||
}
|
||||
|
||||
func (c customFallback) Sizeof(val reflect.Value, opt *Options) int {
|
||||
return c.custom.Size(opt)
|
||||
}
|
||||
|
||||
func (c customFallback) String() string {
|
||||
return c.custom.String()
|
||||
}
|
78
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom_float16.go
сгенерированный
поставляемый
Normal file
78
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom_float16.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,78 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Float16 float64
|
||||
|
||||
func (f *Float16) Pack(p []byte, opt *Options) (int, error) {
|
||||
order := opt.Order
|
||||
if order == nil {
|
||||
order = binary.BigEndian
|
||||
}
|
||||
sign := uint16(0)
|
||||
if *f < 0 {
|
||||
sign = 1
|
||||
}
|
||||
var frac, exp uint16
|
||||
if math.IsInf(float64(*f), 0) {
|
||||
exp = 0x1f
|
||||
frac = 0
|
||||
} else if math.IsNaN(float64(*f)) {
|
||||
exp = 0x1f
|
||||
frac = 1
|
||||
} else {
|
||||
bits := math.Float64bits(float64(*f))
|
||||
exp64 := (bits >> 52) & 0x7ff
|
||||
if exp64 != 0 {
|
||||
exp = uint16((exp64 - 1023 + 15) & 0x1f)
|
||||
}
|
||||
frac = uint16((bits >> 42) & 0x3ff)
|
||||
}
|
||||
var out uint16
|
||||
out |= sign << 15
|
||||
out |= exp << 10
|
||||
out |= frac & 0x3ff
|
||||
order.PutUint16(p, out)
|
||||
return 2, nil
|
||||
}
|
||||
func (f *Float16) Unpack(r io.Reader, length int, opt *Options) error {
|
||||
order := opt.Order
|
||||
if order == nil {
|
||||
order = binary.BigEndian
|
||||
}
|
||||
var tmp [2]byte
|
||||
if _, err := r.Read(tmp[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
val := order.Uint16(tmp[:2])
|
||||
sign := (val >> 15) & 1
|
||||
exp := int16((val >> 10) & 0x1f)
|
||||
frac := val & 0x3ff
|
||||
if exp == 0x1f {
|
||||
if frac != 0 {
|
||||
*f = Float16(math.NaN())
|
||||
} else {
|
||||
*f = Float16(math.Inf(int(sign)*-2 + 1))
|
||||
}
|
||||
} else {
|
||||
var bits uint64
|
||||
bits |= uint64(sign) << 63
|
||||
bits |= uint64(frac) << 42
|
||||
if exp > 0 {
|
||||
bits |= uint64(exp-15+1023) << 52
|
||||
}
|
||||
*f = Float16(math.Float64frombits(bits))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (f *Float16) Size(opt *Options) int {
|
||||
return 2
|
||||
}
|
||||
func (f *Float16) String() string {
|
||||
return strconv.FormatFloat(float64(*f), 'g', -1, 32)
|
||||
}
|
56
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom_float16_test.go
сгенерированный
поставляемый
Normal file
56
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom_float16_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,56 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFloat16(t *testing.T) {
|
||||
// test cases from https://en.wikipedia.org/wiki/Half-precision_floating-point_format#Half_precision_examples
|
||||
tests := []struct {
|
||||
B string
|
||||
F float64
|
||||
}{
|
||||
//s expnt significand
|
||||
{"0 01111 0000000000", 1},
|
||||
{"0 01111 0000000001", 1.0009765625},
|
||||
{"1 10000 0000000000", -2},
|
||||
{"0 11110 1111111111", 65504},
|
||||
// {"0 00001 0000000000", 0.0000610352},
|
||||
// {"0 00000 1111111111", 0.0000609756},
|
||||
// {"0 00000 0000000001", 0.0000000596046},
|
||||
{"0 00000 0000000000", 0},
|
||||
// {"1 00000 0000000000", -0},
|
||||
{"0 11111 0000000000", math.Inf(1)},
|
||||
{"1 11111 0000000000", math.Inf(-1)},
|
||||
{"0 01101 0101010101", 0.333251953125},
|
||||
}
|
||||
for _, test := range tests {
|
||||
var buf bytes.Buffer
|
||||
f := Float16(test.F)
|
||||
if err := Pack(&buf, &f); err != nil {
|
||||
t.Error("pack failed:", err)
|
||||
continue
|
||||
}
|
||||
bitval, _ := strconv.ParseUint(strings.Replace(test.B, " ", "", -1), 2, 16)
|
||||
tmp := binary.BigEndian.Uint16(buf.Bytes())
|
||||
if tmp != uint16(bitval) {
|
||||
t.Errorf("incorrect pack: %s != %016b (%f)", test.B, tmp, test.F)
|
||||
continue
|
||||
}
|
||||
var f2 Float16
|
||||
if err := Unpack(&buf, &f2); err != nil {
|
||||
t.Error("unpack failed:", err)
|
||||
continue
|
||||
}
|
||||
// let sprintf deal with (im)precision for me here
|
||||
if fmt.Sprintf("%f", f) != fmt.Sprintf("%f", f2) {
|
||||
t.Errorf("incorrect unpack: %016b %f != %f", bitval, f, f2)
|
||||
}
|
||||
}
|
||||
}
|
97
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom_test.go
сгенерированный
поставляемый
Normal file
97
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/custom_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,97 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Int3 uint32
|
||||
|
||||
func (i *Int3) Pack(p []byte, opt *Options) (int, error) {
|
||||
var tmp [4]byte
|
||||
binary.BigEndian.PutUint32(tmp[:], uint32(*i))
|
||||
copy(p, tmp[1:])
|
||||
return 3, nil
|
||||
}
|
||||
func (i *Int3) Unpack(r io.Reader, length int, opt *Options) error {
|
||||
var tmp [4]byte
|
||||
if _, err := r.Read(tmp[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*i = Int3(binary.BigEndian.Uint32(tmp[:]))
|
||||
return nil
|
||||
}
|
||||
func (i *Int3) Size(opt *Options) int {
|
||||
return 3
|
||||
}
|
||||
func (i *Int3) String() string {
|
||||
return strconv.FormatUint(uint64(*i), 10)
|
||||
}
|
||||
|
||||
func TestCustom(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
var i Int3 = 3
|
||||
if err := Pack(&buf, &i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), []byte{0, 0, 3}) {
|
||||
t.Fatal("error packing custom int")
|
||||
}
|
||||
var i2 Int3
|
||||
if err := Unpack(&buf, &i2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i2 != 3 {
|
||||
t.Fatal("error unpacking custom int")
|
||||
}
|
||||
}
|
||||
|
||||
type Int3Struct struct {
|
||||
I Int3
|
||||
}
|
||||
|
||||
func TestCustomStruct(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
i := Int3Struct{3}
|
||||
if err := Pack(&buf, &i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), []byte{0, 0, 3}) {
|
||||
t.Fatal("error packing custom int struct")
|
||||
}
|
||||
var i2 Int3Struct
|
||||
if err := Unpack(&buf, &i2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i2.I != 3 {
|
||||
t.Fatal("error unpacking custom int struct")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: slices of custom types don't work yet
|
||||
/*
|
||||
type Int3SliceStruct struct {
|
||||
I [2]Int3
|
||||
}
|
||||
|
||||
func TestCustomSliceStruct(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
i := Int3SliceStruct{[2]Int3{3, 4}}
|
||||
if err := Pack(&buf, &i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), []byte{0, 0, 3}) {
|
||||
t.Fatal("error packing custom int struct")
|
||||
}
|
||||
var i2 Int3SliceStruct
|
||||
if err := Unpack(&buf, &i2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i2.I[0] != 3 && i2.I[1] != 4 {
|
||||
t.Fatal("error unpacking custom int struct")
|
||||
}
|
||||
}
|
||||
*/
|
281
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/field.go
сгенерированный
поставляемый
Normal file
281
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/field.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,281 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
Name string
|
||||
CanSet bool
|
||||
Ptr bool
|
||||
Index int
|
||||
Type Type
|
||||
defType Type
|
||||
Array bool
|
||||
Slice bool
|
||||
Len int
|
||||
Order binary.ByteOrder
|
||||
Sizeof []int
|
||||
Sizefrom []int
|
||||
Fields Fields
|
||||
kind reflect.Kind
|
||||
}
|
||||
|
||||
func (f *Field) String() string {
|
||||
var out string
|
||||
if f.Type == Pad {
|
||||
return fmt.Sprintf("{type: Pad, len: %d}", f.Len)
|
||||
} else {
|
||||
out = fmt.Sprintf("type: %s, order: %v", f.Type.String(), f.Order)
|
||||
}
|
||||
if f.Sizefrom != nil {
|
||||
out += fmt.Sprintf(", sizefrom: %v", f.Sizefrom)
|
||||
} else if f.Len > 0 {
|
||||
out += fmt.Sprintf(", len: %d", f.Len)
|
||||
}
|
||||
if f.Sizeof != nil {
|
||||
out += fmt.Sprintf(", sizeof: %v", f.Sizeof)
|
||||
}
|
||||
return "{" + out + "}"
|
||||
}
|
||||
|
||||
func (f *Field) Size(val reflect.Value, options *Options) int {
|
||||
typ := f.Type.Resolve(options)
|
||||
size := 0
|
||||
if typ == Struct {
|
||||
vals := []reflect.Value{val}
|
||||
if f.Slice {
|
||||
vals = make([]reflect.Value, val.Len())
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
vals[i] = val.Index(i)
|
||||
}
|
||||
}
|
||||
for _, val := range vals {
|
||||
size += f.Fields.Sizeof(val, options)
|
||||
}
|
||||
} else if typ == Pad {
|
||||
size = f.Len
|
||||
} else if f.Slice || f.kind == reflect.String {
|
||||
length := val.Len()
|
||||
if f.Len > 1 {
|
||||
length = f.Len
|
||||
}
|
||||
size = length * typ.Size()
|
||||
} else if typ == CustomType {
|
||||
return val.Addr().Interface().(Custom).Size(options)
|
||||
} else {
|
||||
size = typ.Size()
|
||||
}
|
||||
align := options.ByteAlign
|
||||
if align > 0 && size < align {
|
||||
size = align
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) {
|
||||
order := f.Order
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
if f.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
typ := f.Type.Resolve(options)
|
||||
switch typ {
|
||||
case Struct:
|
||||
return f.Fields.Pack(buf, val, options)
|
||||
case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
|
||||
size = typ.Size()
|
||||
var n uint64
|
||||
switch f.kind {
|
||||
case reflect.Bool:
|
||||
if val.Bool() {
|
||||
n = 1
|
||||
} else {
|
||||
n = 0
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n = uint64(val.Int())
|
||||
default:
|
||||
n = val.Uint()
|
||||
}
|
||||
switch typ {
|
||||
case Bool:
|
||||
if n != 0 {
|
||||
buf[0] = 1
|
||||
} else {
|
||||
buf[0] = 0
|
||||
}
|
||||
case Int8, Uint8:
|
||||
buf[0] = byte(n)
|
||||
case Int16, Uint16:
|
||||
order.PutUint16(buf, uint16(n))
|
||||
case Int32, Uint32:
|
||||
order.PutUint32(buf, uint32(n))
|
||||
case Int64, Uint64:
|
||||
order.PutUint64(buf, uint64(n))
|
||||
}
|
||||
case Float32, Float64:
|
||||
size = typ.Size()
|
||||
n := val.Float()
|
||||
switch typ {
|
||||
case Float32:
|
||||
order.PutUint32(buf, math.Float32bits(float32(n)))
|
||||
case Float64:
|
||||
order.PutUint64(buf, math.Float64bits(n))
|
||||
}
|
||||
case String:
|
||||
switch f.kind {
|
||||
case reflect.String:
|
||||
size = val.Len()
|
||||
copy(buf, []byte(val.String()))
|
||||
default:
|
||||
// TODO: handle kind != bytes here
|
||||
size = val.Len()
|
||||
copy(buf, val.Bytes())
|
||||
}
|
||||
case CustomType:
|
||||
return val.Addr().Interface().(Custom).Pack(buf, options)
|
||||
default:
|
||||
panic(fmt.Sprintf("no pack handler for type: %s", typ))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) {
|
||||
typ := f.Type.Resolve(options)
|
||||
if typ == Pad {
|
||||
for i := 0; i < length; i++ {
|
||||
buf[i] = 0
|
||||
}
|
||||
return length, nil
|
||||
}
|
||||
if f.Slice {
|
||||
// special case strings and byte slices for performance
|
||||
end := val.Len()
|
||||
if !f.Array && typ == Uint8 && (f.defType == Uint8 || f.kind == reflect.String) {
|
||||
var tmp []byte
|
||||
if f.kind == reflect.String {
|
||||
tmp = []byte(val.String())
|
||||
} else {
|
||||
tmp = val.Bytes()
|
||||
}
|
||||
copy(buf, tmp)
|
||||
if end < length {
|
||||
// TODO: allow configuring pad byte?
|
||||
rep := bytes.Repeat([]byte{0}, length-end)
|
||||
copy(buf[end:], rep)
|
||||
return length, nil
|
||||
}
|
||||
return val.Len(), nil
|
||||
}
|
||||
pos := 0
|
||||
var zero reflect.Value
|
||||
if end < length {
|
||||
zero = reflect.Zero(val.Type().Elem())
|
||||
}
|
||||
for i := 0; i < length; i++ {
|
||||
cur := zero
|
||||
if i < end {
|
||||
cur = val.Index(i)
|
||||
}
|
||||
if n, err := f.packVal(buf[pos:], cur, 1, options); err != nil {
|
||||
return pos, err
|
||||
} else {
|
||||
pos += n
|
||||
}
|
||||
}
|
||||
return pos, nil
|
||||
} else {
|
||||
return f.packVal(buf, val, length, options)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Field) unpackVal(buf []byte, val reflect.Value, length int, options *Options) error {
|
||||
order := f.Order
|
||||
if options.Order != nil {
|
||||
order = options.Order
|
||||
}
|
||||
if f.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
typ := f.Type.Resolve(options)
|
||||
switch typ {
|
||||
case Float32, Float64:
|
||||
var n float64
|
||||
switch typ {
|
||||
case Float32:
|
||||
n = float64(math.Float32frombits(order.Uint32(buf)))
|
||||
case Float64:
|
||||
n = math.Float64frombits(order.Uint64(buf))
|
||||
}
|
||||
switch f.kind {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
val.SetFloat(n)
|
||||
default:
|
||||
return fmt.Errorf("struc: refusing to unpack float into field %s of type %s", f.Name, f.kind.String())
|
||||
}
|
||||
case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
|
||||
var n uint64
|
||||
switch typ {
|
||||
case Bool, Int8, Uint8:
|
||||
n = uint64(buf[0])
|
||||
case Int16, Uint16:
|
||||
n = uint64(order.Uint16(buf))
|
||||
case Int32, Uint32:
|
||||
n = uint64(order.Uint32(buf))
|
||||
case Int64, Uint64:
|
||||
n = uint64(order.Uint64(buf))
|
||||
}
|
||||
switch f.kind {
|
||||
case reflect.Bool:
|
||||
val.SetBool(n != 0)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
val.SetInt(int64(n))
|
||||
default:
|
||||
val.SetUint(n)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("no unpack handler for type: %s", typ))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Field) Unpack(buf []byte, val reflect.Value, length int, options *Options) error {
|
||||
typ := f.Type.Resolve(options)
|
||||
if typ == Pad || f.kind == reflect.String {
|
||||
if typ == Pad {
|
||||
return nil
|
||||
} else {
|
||||
val.SetString(string(buf))
|
||||
return nil
|
||||
}
|
||||
} else if f.Slice {
|
||||
if val.Cap() < length {
|
||||
val.Set(reflect.MakeSlice(val.Type(), length, length))
|
||||
} else if val.Len() < length {
|
||||
val.Set(val.Slice(0, length))
|
||||
}
|
||||
// special case byte slices for performance
|
||||
if !f.Array && typ == Uint8 && f.defType == Uint8 {
|
||||
copy(val.Bytes(), buf[:length])
|
||||
return nil
|
||||
}
|
||||
pos := 0
|
||||
size := typ.Size()
|
||||
for i := 0; i < length; i++ {
|
||||
if err := f.unpackVal(buf[pos:pos+size], val.Index(i), 1, options); err != nil {
|
||||
return err
|
||||
}
|
||||
pos += size
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
return f.unpackVal(buf, val, length, options)
|
||||
}
|
||||
}
|
77
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/field_test.go
сгенерированный
поставляемый
Normal file
77
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/field_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,77 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type badFloat struct {
|
||||
BadFloat int `struc:"float64"`
|
||||
}
|
||||
|
||||
func TestBadFloatField(t *testing.T) {
|
||||
buf := bytes.NewReader([]byte("00000000"))
|
||||
err := Unpack(buf, &badFloat{})
|
||||
if err == nil {
|
||||
t.Fatal("failed to error on bad float unpack")
|
||||
}
|
||||
}
|
||||
|
||||
type emptyLengthField struct {
|
||||
Strlen int `struc:"sizeof=Str"`
|
||||
Str []byte
|
||||
}
|
||||
|
||||
func TestEmptyLengthField(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
s := &emptyLengthField{0, []byte("test")}
|
||||
o := &emptyLengthField{}
|
||||
if err := Pack(&buf, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, o); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(s.Str, o.Str) {
|
||||
t.Fatal("empty length field encode failed")
|
||||
}
|
||||
}
|
||||
|
||||
type fixedSlicePad struct {
|
||||
Field []byte `struc:"[4]byte"`
|
||||
}
|
||||
|
||||
func TestFixedSlicePad(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
ref := []byte{0, 0, 0, 0}
|
||||
s := &fixedSlicePad{}
|
||||
if err := Pack(&buf, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), ref) {
|
||||
t.Fatal("implicit fixed slice pack failed")
|
||||
}
|
||||
if err := Unpack(&buf, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(s.Field, ref) {
|
||||
t.Fatal("implicit fixed slice unpack failed")
|
||||
}
|
||||
}
|
||||
|
||||
type sliceCap struct {
|
||||
Len int `struc:"sizeof=Field"`
|
||||
Field []byte
|
||||
}
|
||||
|
||||
func TestSliceCap(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
tmp := &sliceCap{0, []byte("1234")}
|
||||
if err := Pack(&buf, tmp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmp.Field = make([]byte, 0, 4)
|
||||
if err := Unpack(&buf, tmp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
169
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/fields.go
сгенерированный
поставляемый
Normal file
169
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/fields.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,169 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Fields []*Field
|
||||
|
||||
func (f Fields) SetByteOrder(order binary.ByteOrder) {
|
||||
for _, field := range f {
|
||||
field.Order = order
|
||||
}
|
||||
}
|
||||
|
||||
func (f Fields) String() string {
|
||||
fields := make([]string, len(f))
|
||||
for i, field := range f {
|
||||
fields[i] = field.String()
|
||||
}
|
||||
return "{" + strings.Join(fields, ", ") + "}"
|
||||
}
|
||||
|
||||
func (f Fields) Sizeof(val reflect.Value, options *Options) int {
|
||||
for val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
size := 0
|
||||
for i, field := range f {
|
||||
v := val.Field(i)
|
||||
if v.CanSet() {
|
||||
size += field.Size(v, options)
|
||||
}
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func (f Fields) sizefrom(val reflect.Value, index []int) int {
|
||||
field := val.FieldByIndex(index)
|
||||
switch field.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return int(field.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
n := int(field.Uint())
|
||||
// all the builtin array length types are native int
|
||||
// so this guards against weird truncation
|
||||
if n < 0 {
|
||||
return 0
|
||||
}
|
||||
return n
|
||||
default:
|
||||
name := val.Type().FieldByIndex(index).Name
|
||||
panic(fmt.Sprintf("sizeof field %T.%s not an integer type", val.Interface(), name))
|
||||
}
|
||||
}
|
||||
|
||||
func (f Fields) Pack(buf []byte, val reflect.Value, options *Options) (int, error) {
|
||||
for val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
pos := 0
|
||||
for i, field := range f {
|
||||
if !field.CanSet {
|
||||
continue
|
||||
}
|
||||
v := val.Field(i)
|
||||
length := field.Len
|
||||
if field.Sizefrom != nil {
|
||||
length = f.sizefrom(val, field.Sizefrom)
|
||||
}
|
||||
if length <= 0 && field.Slice {
|
||||
length = v.Len()
|
||||
}
|
||||
if field.Sizeof != nil {
|
||||
length := val.FieldByIndex(field.Sizeof).Len()
|
||||
switch field.kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
// allocating a new int here has fewer side effects (doesn't update the original struct)
|
||||
// but it's a wasteful allocation
|
||||
// the old method might work if we just cast the temporary int/uint to the target type
|
||||
v = reflect.New(v.Type()).Elem()
|
||||
v.SetInt(int64(length))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
v = reflect.New(v.Type()).Elem()
|
||||
v.SetUint(uint64(length))
|
||||
default:
|
||||
panic(fmt.Sprintf("sizeof field is not int or uint type: %s, %s", field.Name, v.Type()))
|
||||
}
|
||||
}
|
||||
if n, err := field.Pack(buf[pos:], v, length, options); err != nil {
|
||||
return n, err
|
||||
} else {
|
||||
pos += n
|
||||
}
|
||||
}
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
func (f Fields) Unpack(r io.Reader, val reflect.Value, options *Options) error {
|
||||
for val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
var tmp [8]byte
|
||||
var buf []byte
|
||||
for i, field := range f {
|
||||
if !field.CanSet {
|
||||
continue
|
||||
}
|
||||
v := val.Field(i)
|
||||
length := field.Len
|
||||
if field.Sizefrom != nil {
|
||||
length = f.sizefrom(val, field.Sizefrom)
|
||||
}
|
||||
if v.Kind() == reflect.Ptr && !v.Elem().IsValid() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
if field.Type == Struct {
|
||||
if field.Slice {
|
||||
vals := reflect.MakeSlice(v.Type(), length, length)
|
||||
for i := 0; i < length; i++ {
|
||||
v := vals.Index(i)
|
||||
fields, err := parseFields(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fields.Unpack(r, v, options); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Set(vals)
|
||||
} else {
|
||||
// TODO: DRY (we repeat the inner loop above)
|
||||
fields, err := parseFields(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fields.Unpack(r, v, options); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
typ := field.Type.Resolve(options)
|
||||
if typ == CustomType {
|
||||
if err := v.Addr().Interface().(Custom).Unpack(r, length, options); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
size := length * field.Type.Resolve(options).Size()
|
||||
if size < 8 {
|
||||
buf = tmp[:size]
|
||||
} else {
|
||||
buf = make([]byte, size)
|
||||
}
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
err := field.Unpack(buf[:size], v, length, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
59
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/fields_test.go
сгенерированный
поставляемый
Normal file
59
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/fields_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,59 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var refVal = reflect.ValueOf(reference)
|
||||
|
||||
func TestFieldsParse(t *testing.T) {
|
||||
if _, err := parseFields(refVal); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldsString(t *testing.T) {
|
||||
fields, _ := parseFields(refVal)
|
||||
fields.String()
|
||||
}
|
||||
|
||||
type sizefromStruct struct {
|
||||
Size1 uint `struc:"sizeof=Var1"`
|
||||
Var1 []byte
|
||||
Size2 int `struc:"sizeof=Var2"`
|
||||
Var2 []byte
|
||||
}
|
||||
|
||||
func TestFieldsSizefrom(t *testing.T) {
|
||||
var test = sizefromStruct{
|
||||
Var1: []byte{1, 2, 3},
|
||||
Var2: []byte{4, 5, 6},
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err := Pack(&buf, &test)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = Unpack(&buf, &test)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
type sizefromStructBad struct {
|
||||
Size1 string `struc:"sizeof=Var1"`
|
||||
Var1 []byte
|
||||
}
|
||||
|
||||
func TestFieldsSizefromBad(t *testing.T) {
|
||||
var test = &sizefromStructBad{Var1: []byte{1, 2, 3}}
|
||||
var buf bytes.Buffer
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Fatal("failed to panic on bad sizeof type")
|
||||
}
|
||||
}()
|
||||
Pack(&buf, &test)
|
||||
}
|
16
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/legacy.go
сгенерированный
поставляемый
Normal file
16
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/legacy.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,16 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Deprecated. Use PackWithOptions.
|
||||
func PackWithOrder(w io.Writer, data interface{}, order binary.ByteOrder) error {
|
||||
return PackWithOptions(w, data, &Options{Order: order})
|
||||
}
|
||||
|
||||
// Deprecated. Use UnpackWithOptions.
|
||||
func UnpackWithOrder(r io.Reader, data interface{}, order binary.ByteOrder) error {
|
||||
return UnpackWithOptions(r, data, &Options{Order: order})
|
||||
}
|
123
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/packable_test.go
сгенерированный
поставляемый
Normal file
123
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/packable_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,123 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var packableReference = []byte{
|
||||
1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16,
|
||||
0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24,
|
||||
}
|
||||
|
||||
func TestPackable(t *testing.T) {
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
|
||||
i8 int8 = 1
|
||||
i16 int16 = 2
|
||||
i32 int32 = 3
|
||||
i64 int64 = 4
|
||||
u8 uint8 = 5
|
||||
u16 uint16 = 6
|
||||
u32 uint32 = 7
|
||||
u64 uint64 = 8
|
||||
|
||||
u8a = [8]uint8{9, 10, 11, 12, 13, 14, 15, 16}
|
||||
u16a = [8]uint16{17, 18, 19, 20, 21, 22, 23, 24}
|
||||
)
|
||||
// pack tests
|
||||
if err := Pack(&buf, i8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, i16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, i32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, i64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u8a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Pack(&buf, u16a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), packableReference) {
|
||||
fmt.Println(buf.Bytes())
|
||||
fmt.Println(packableReference)
|
||||
t.Fatal("Packable Pack() did not match reference.")
|
||||
}
|
||||
// unpack tests
|
||||
i8 = 0
|
||||
i16 = 0
|
||||
i32 = 0
|
||||
i64 = 0
|
||||
u8 = 0
|
||||
u16 = 0
|
||||
u32 = 0
|
||||
u64 = 0
|
||||
if err := Unpack(&buf, &i8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &i16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &i32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &i64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u8); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u16); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, &u64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, u8a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Unpack(&buf, u16a[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// unpack checks
|
||||
if i8 != 1 || i16 != 2 || i32 != 3 || i64 != 4 {
|
||||
t.Fatal("Signed integer unpack failed.")
|
||||
}
|
||||
if u8 != 5 || u16 != 6 || u32 != 7 || u64 != 8 {
|
||||
t.Fatal("Unsigned integer unpack failed.")
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
if u8a[i] != uint8(i+9) {
|
||||
t.Fatal("uint8 array unpack failed.")
|
||||
}
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
if u16a[i] != uint16(i+17) {
|
||||
t.Fatal("uint16 array unpack failed.")
|
||||
}
|
||||
}
|
||||
}
|
13
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/packer.go
сгенерированный
поставляемый
Normal file
13
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/packer.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,13 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Packer interface {
|
||||
Pack(buf []byte, val reflect.Value, options *Options) (int, error)
|
||||
Unpack(r io.Reader, val reflect.Value, options *Options) error
|
||||
Sizeof(val reflect.Value, options *Options) int
|
||||
String() string
|
||||
}
|
217
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/parse.go
сгенерированный
поставляемый
Normal file
217
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/parse.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,217 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// struc:"int32,big,sizeof=Data"
|
||||
|
||||
var tagWordsRe = regexp.MustCompile(`(\[|\b)[^"]+\b+$`)
|
||||
|
||||
type strucTag struct {
|
||||
Type string
|
||||
Order binary.ByteOrder
|
||||
Sizeof string
|
||||
}
|
||||
|
||||
func parseStrucTag(tag reflect.StructTag) *strucTag {
|
||||
t := &strucTag{
|
||||
Order: binary.BigEndian,
|
||||
}
|
||||
tagStr := tag.Get("struc")
|
||||
if tagStr == "" {
|
||||
// someone's going to typo this (I already did once)
|
||||
// sorry if you made a module actually using this tag
|
||||
// and you're mad at me now
|
||||
tagStr = tag.Get("struct")
|
||||
}
|
||||
for _, s := range strings.Split(tagStr, ",") {
|
||||
if strings.HasPrefix(s, "sizeof=") {
|
||||
tmp := strings.SplitN(s, "=", 2)
|
||||
t.Sizeof = tmp[1]
|
||||
} else if s == "big" {
|
||||
t.Order = binary.BigEndian
|
||||
} else if s == "little" {
|
||||
t.Order = binary.LittleEndian
|
||||
} else {
|
||||
t.Type = s
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
var typeLenRe = regexp.MustCompile(`^\[(\d*)\]`)
|
||||
|
||||
func parseField(f reflect.StructField) (fd *Field, err error) {
|
||||
tag := parseStrucTag(f.Tag)
|
||||
var ok bool
|
||||
fd = &Field{
|
||||
Name: f.Name,
|
||||
Len: 1,
|
||||
Order: tag.Order,
|
||||
Slice: false,
|
||||
kind: f.Type.Kind(),
|
||||
}
|
||||
switch fd.kind {
|
||||
case reflect.Array:
|
||||
fd.Slice = true
|
||||
fd.Array = true
|
||||
fd.Len = f.Type.Len()
|
||||
fd.kind = f.Type.Elem().Kind()
|
||||
case reflect.Slice:
|
||||
fd.Slice = true
|
||||
fd.Len = -1
|
||||
fd.kind = f.Type.Elem().Kind()
|
||||
case reflect.Ptr:
|
||||
fd.Ptr = true
|
||||
fd.kind = f.Type.Elem().Kind()
|
||||
}
|
||||
// check for custom types
|
||||
tmp := reflect.New(f.Type)
|
||||
if _, ok := tmp.Interface().(Custom); ok {
|
||||
fd.Type = CustomType
|
||||
return
|
||||
}
|
||||
var defTypeOk bool
|
||||
fd.defType, defTypeOk = reflectTypeMap[fd.kind]
|
||||
// find a type in the struct tag
|
||||
pureType := typeLenRe.ReplaceAllLiteralString(tag.Type, "")
|
||||
if fd.Type, ok = typeLookup[pureType]; ok {
|
||||
fd.Len = 1
|
||||
match := typeLenRe.FindAllStringSubmatch(tag.Type, -1)
|
||||
if len(match) > 0 && len(match[0]) > 1 {
|
||||
fd.Slice = true
|
||||
first := match[0][1]
|
||||
// Field.Len = -1 indicates a []slice
|
||||
if first == "" {
|
||||
fd.Len = -1
|
||||
} else {
|
||||
fd.Len, err = strconv.Atoi(first)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// the user didn't specify a type
|
||||
switch f.Type {
|
||||
case reflect.TypeOf(Size_t(0)):
|
||||
fd.Type = SizeType
|
||||
case reflect.TypeOf(Off_t(0)):
|
||||
fd.Type = OffType
|
||||
default:
|
||||
if defTypeOk {
|
||||
fd.Type = fd.defType
|
||||
} else {
|
||||
err = errors.New("struc: Could not find field type.")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseFieldsLocked(v reflect.Value) (Fields, error) {
|
||||
// we need to repeat this logic because parseFields() below can't be recursively called due to locking
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
t := v.Type()
|
||||
if v.NumField() < 1 {
|
||||
return nil, errors.New("struc: Struct has no fields.")
|
||||
}
|
||||
sizeofMap := make(map[string][]int)
|
||||
fields := make(Fields, 0, v.NumField())
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
f, err := parseField(field)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.CanSet = v.Field(i).CanSet()
|
||||
if !f.CanSet {
|
||||
continue
|
||||
}
|
||||
f.Index = i
|
||||
tag := parseStrucTag(field.Tag)
|
||||
if tag.Sizeof != "" {
|
||||
target, ok := t.FieldByName(tag.Sizeof)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("struc: `sizeof=%s` field does not exist", tag.Sizeof)
|
||||
}
|
||||
f.Sizeof = target.Index
|
||||
sizeofMap[tag.Sizeof] = field.Index
|
||||
}
|
||||
if sizefrom, ok := sizeofMap[field.Name]; ok {
|
||||
f.Sizefrom = sizefrom
|
||||
}
|
||||
if f.Len == -1 && f.Sizefrom == nil {
|
||||
return nil, fmt.Errorf("struc: field `%s` is a slice with no length or sizeof field", field.Name)
|
||||
}
|
||||
// recurse into nested structs
|
||||
// TODO: handle loops (probably by indirecting the []Field and putting pointer in cache)
|
||||
if f.Type == Struct {
|
||||
typ := field.Type
|
||||
if f.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
if f.Slice {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
f.Fields, err = parseFieldsLocked(reflect.New(typ))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
fields = append(fields, f)
|
||||
}
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
var fieldCache = make(map[reflect.Type]Fields)
|
||||
var fieldCacheLock sync.RWMutex
|
||||
var parseLock sync.Mutex
|
||||
|
||||
func fieldCacheLookup(t reflect.Type) Fields {
|
||||
fieldCacheLock.RLock()
|
||||
defer fieldCacheLock.RUnlock()
|
||||
if cached, ok := fieldCache[t]; ok {
|
||||
return cached
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseFields(v reflect.Value) (Fields, error) {
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
t := v.Type()
|
||||
|
||||
// fast path: hopefully the field parsing is already cached
|
||||
if cached := fieldCacheLookup(t); cached != nil {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
// hold a global lock so multiple goroutines can't parse (the same) fields at once
|
||||
parseLock.Lock()
|
||||
defer parseLock.Unlock()
|
||||
|
||||
// check cache a second time, in case parseLock was just released by
|
||||
// another thread who filled the cache for us
|
||||
if cached := fieldCacheLookup(t); cached != nil {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
// no luck, time to parse and fill the cache ourselves
|
||||
fields, err := parseFieldsLocked(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldCacheLock.Lock()
|
||||
fieldCache[t] = fields
|
||||
fieldCacheLock.Unlock()
|
||||
return fields, nil
|
||||
}
|
62
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/parse_test.go
сгенерированный
поставляемый
Normal file
62
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/parse_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,62 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func parseTest(data interface{}) error {
|
||||
_, err := parseFields(reflect.ValueOf(data))
|
||||
return err
|
||||
}
|
||||
|
||||
type empty struct{}
|
||||
|
||||
func TestEmptyStruc(t *testing.T) {
|
||||
if err := parseTest(&empty{}); err == nil {
|
||||
t.Fatal("failed to error on empty struct")
|
||||
}
|
||||
}
|
||||
|
||||
type chanStruct struct {
|
||||
Test chan int
|
||||
}
|
||||
|
||||
func TestChanError(t *testing.T) {
|
||||
if err := parseTest(&chanStruct{}); err == nil {
|
||||
// TODO: should probably ignore channel fields
|
||||
t.Fatal("failed to error on struct containing channel")
|
||||
}
|
||||
}
|
||||
|
||||
type badSizeof struct {
|
||||
Size int `struc:"sizeof=Bad"`
|
||||
}
|
||||
|
||||
func TestBadSizeof(t *testing.T) {
|
||||
if err := parseTest(&badSizeof{}); err == nil {
|
||||
t.Fatal("failed to error on missing Sizeof target")
|
||||
}
|
||||
}
|
||||
|
||||
type missingSize struct {
|
||||
Test []byte
|
||||
}
|
||||
|
||||
func TestMissingSize(t *testing.T) {
|
||||
if err := parseTest(&missingSize{}); err == nil {
|
||||
t.Fatal("failed to error on missing field size")
|
||||
}
|
||||
}
|
||||
|
||||
type badNested struct {
|
||||
Empty empty
|
||||
}
|
||||
|
||||
func TestNestedParseError(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, &badNested{}); err == nil {
|
||||
t.Fatal("failed to error on bad nested struct")
|
||||
}
|
||||
}
|
117
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/struc.go
сгенерированный
поставляемый
Normal file
117
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/struc.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,117 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ByteAlign int
|
||||
PtrSize int
|
||||
Order binary.ByteOrder
|
||||
}
|
||||
|
||||
func (o *Options) Validate() error {
|
||||
if o.PtrSize == 0 {
|
||||
o.PtrSize = 32
|
||||
} else {
|
||||
switch o.PtrSize {
|
||||
case 8, 16, 32, 64:
|
||||
default:
|
||||
return fmt.Errorf("Invalid Options.PtrSize: %d. Must be in (8, 16, 32, 64)", o.PtrSize)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var emptyOptions = &Options{}
|
||||
|
||||
func prep(data interface{}) (reflect.Value, Packer, error) {
|
||||
value := reflect.ValueOf(data)
|
||||
for value.Kind() == reflect.Ptr {
|
||||
next := value.Elem().Kind()
|
||||
if next == reflect.Struct || next == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
switch value.Kind() {
|
||||
case reflect.Struct:
|
||||
fields, err := parseFields(value)
|
||||
return value, fields, err
|
||||
default:
|
||||
if !value.IsValid() {
|
||||
return reflect.Value{}, nil, fmt.Errorf("Invalid reflect.Value for %+v", data)
|
||||
}
|
||||
if c, ok := data.(Custom); ok {
|
||||
return value, customFallback{c}, nil
|
||||
}
|
||||
return value, binaryFallback(value), nil
|
||||
}
|
||||
}
|
||||
|
||||
func Pack(w io.Writer, data interface{}) error {
|
||||
return PackWithOptions(w, data, nil)
|
||||
}
|
||||
|
||||
func PackWithOptions(w io.Writer, data interface{}, options *Options) error {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if val.Type().Kind() == reflect.String {
|
||||
val = val.Convert(reflect.TypeOf([]byte{}))
|
||||
}
|
||||
size := packer.Sizeof(val, options)
|
||||
buf := make([]byte, size)
|
||||
if _, err := packer.Pack(buf, val, options); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
func Unpack(r io.Reader, data interface{}) error {
|
||||
return UnpackWithOptions(r, data, nil)
|
||||
}
|
||||
|
||||
func UnpackWithOptions(r io.Reader, data interface{}, options *Options) error {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return packer.Unpack(r, val, options)
|
||||
}
|
||||
|
||||
func Sizeof(data interface{}) (int, error) {
|
||||
return SizeofWithOptions(data, nil)
|
||||
}
|
||||
|
||||
func SizeofWithOptions(data interface{}, options *Options) (int, error) {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return packer.Sizeof(val, options), nil
|
||||
}
|
197
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/struc_test.go
сгенерированный
поставляемый
Normal file
197
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/struc_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,197 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Nested struct {
|
||||
Test2 int `struc:"int8"`
|
||||
}
|
||||
|
||||
type Example struct {
|
||||
Pad []byte `struc:"[5]pad"` // 00 00 00 00 00
|
||||
I8f int `struc:"int8"` // 01
|
||||
I16f int `struc:"int16"` // 00 02
|
||||
I32f int `struc:"int32"` // 00 00 00 03
|
||||
I64f int `struc:"int64"` // 00 00 00 00 00 00 00 04
|
||||
U8f int `struc:"uint8,little"` // 05
|
||||
U16f int `struc:"uint16,little"` // 06 00
|
||||
U32f int `struc:"uint32,little"` // 07 00 00 00
|
||||
U64f int `struc:"uint64,little"` // 08 00 00 00 00 00 00 00
|
||||
Boolf int `struc:"bool"` // 01
|
||||
Byte4f []byte `struc:"[4]byte"` // "abcd"
|
||||
|
||||
I8 int8 // 09
|
||||
I16 int16 // 00 0a
|
||||
I32 int32 // 00 00 00 0b
|
||||
I64 int64 // 00 00 00 00 00 00 00 0c
|
||||
U8 uint8 `struc:"little"` // 0d
|
||||
U16 uint16 `struc:"little"` // 0e 00
|
||||
U32 uint32 `struc:"little"` // 0f 00 00 00
|
||||
U64 uint64 `struc:"little"` // 10 00 00 00 00 00 00 00
|
||||
BoolT bool // 01
|
||||
BoolF bool // 00
|
||||
Byte4 [4]byte // "efgh"
|
||||
Float1 float32 // 41 a0 00 00
|
||||
Float2 float64 // 41 35 00 00 00 00 00 00
|
||||
|
||||
Size int `struc:"sizeof=Str,little"` // 0a 00 00 00
|
||||
Str string `struc:"[]byte"` // "ijklmnopqr"
|
||||
Strb string `struc:"[4]byte"` // "stuv"
|
||||
|
||||
Size2 int `struc:"uint8,sizeof=Str2"` // 04
|
||||
Str2 string // "1234"
|
||||
|
||||
Size3 int `struc:"uint8,sizeof=Bstr"` // 04
|
||||
Bstr []byte // "5678"
|
||||
|
||||
Nested Nested // 00 00 00 01
|
||||
NestedP *Nested // 00 00 00 02
|
||||
TestP64 *int `struc:"int64"` // 00 00 00 05
|
||||
|
||||
NestedSize int `struc:"sizeof=NestedA"` // 00 00 00 02
|
||||
NestedA []Nested // [00 00 00 03, 00 00 00 04]
|
||||
|
||||
CustomTypeSize Int3 `struc:"sizeof=CustomTypeSizeArr"` // 00 00 00 04
|
||||
CustomTypeSizeArr []byte // "ABCD"
|
||||
}
|
||||
|
||||
var five = 5
|
||||
|
||||
var reference = &Example{
|
||||
nil,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 0, []byte{'a', 'b', 'c', 'd'},
|
||||
9, 10, 11, 12, 13, 14, 15, 16, true, false, [4]byte{'e', 'f', 'g', 'h'},
|
||||
20, 21,
|
||||
10, "ijklmnopqr", "stuv",
|
||||
4, "1234",
|
||||
4, []byte("5678"),
|
||||
Nested{1}, &Nested{2}, &five,
|
||||
6, []Nested{{3}, {4}, {5}, {6}, {7}, {8}},
|
||||
Int3(4), []byte("ABCD"),
|
||||
}
|
||||
|
||||
var referenceBytes = []byte{
|
||||
0, 0, 0, 0, 0, // pad(5)
|
||||
1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, // fake int8-int64(1-4)
|
||||
5, 6, 0, 7, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, // fake little-endian uint8-uint64(5-8)
|
||||
0, // fake bool(0)
|
||||
'a', 'b', 'c', 'd', // fake [4]byte
|
||||
|
||||
9, 0, 10, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 12, // real int8-int64(9-12)
|
||||
13, 14, 0, 15, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, // real little-endian uint8-uint64(13-16)
|
||||
1, 0, // real bool(1), bool(0)
|
||||
'e', 'f', 'g', 'h', // real [4]byte
|
||||
65, 160, 0, 0, // real float32(20)
|
||||
64, 53, 0, 0, 0, 0, 0, 0, // real float64(21)
|
||||
|
||||
10, 0, 0, 0, // little-endian int32(10) sizeof=Str
|
||||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', // Str
|
||||
's', 't', 'u', 'v', // fake string([4]byte)
|
||||
04, '1', '2', '3', '4', // real string
|
||||
04, '5', '6', '7', '8', // fake []byte(string)
|
||||
|
||||
1, 2, // Nested{1}, Nested{2}
|
||||
0, 0, 0, 0, 0, 0, 0, 5, // &five
|
||||
|
||||
0, 0, 0, 6, // int32(6)
|
||||
3, 4, 5, 6, 7, 8, // [Nested{3}, ...Nested{8}]
|
||||
|
||||
0, 0, 4, 'A', 'B', 'C', 'D', // Int3(4), []byte("ABCD")
|
||||
}
|
||||
|
||||
func TestCodec(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, reference); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out := &Example{}
|
||||
if err := Unpack(&buf, out); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(reference, out) {
|
||||
t.Fatal("encode/decode failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, reference); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), referenceBytes) {
|
||||
t.Fatal("encode failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode(t *testing.T) {
|
||||
buf := bytes.NewReader(referenceBytes)
|
||||
out := &Example{}
|
||||
if err := Unpack(buf, out); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(reference, out) {
|
||||
t.Fatal("decode failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSizeof(t *testing.T) {
|
||||
size, err := Sizeof(reference)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if size != len(referenceBytes) {
|
||||
t.Fatal("sizeof failed")
|
||||
}
|
||||
}
|
||||
|
||||
type ExampleEndian struct {
|
||||
T int `struc:"int16,big"`
|
||||
}
|
||||
|
||||
func TestEndianSwap(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
big := &ExampleEndian{1}
|
||||
if err := PackWithOrder(&buf, big, binary.BigEndian); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
little := &ExampleEndian{}
|
||||
if err := UnpackWithOrder(&buf, little, binary.LittleEndian); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if little.T != 256 {
|
||||
t.Fatal("big -> little conversion failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilValue(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := Pack(&buf, nil); err == nil {
|
||||
t.Fatal("failed throw error for bad struct value")
|
||||
}
|
||||
if err := Unpack(&buf, nil); err == nil {
|
||||
t.Fatal("failed throw error for bad struct value")
|
||||
}
|
||||
if _, err := Sizeof(nil); err == nil {
|
||||
t.Fatal("failed to throw error for bad struct value")
|
||||
}
|
||||
}
|
||||
|
||||
type sliceUnderrun struct {
|
||||
Str string `struc:"[10]byte"`
|
||||
Arr []uint16 `struc:"[10]uint16"`
|
||||
}
|
||||
|
||||
func TestSliceUnderrun(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
v := sliceUnderrun{
|
||||
Str: "foo",
|
||||
Arr: []uint16{1, 2, 3},
|
||||
}
|
||||
if err := Pack(&buf, &v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
136
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/types.go
сгенерированный
поставляемый
Normal file
136
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/types.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,136 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Type int
|
||||
|
||||
const (
|
||||
Invalid Type = iota
|
||||
Pad
|
||||
Bool
|
||||
Int
|
||||
Int8
|
||||
Uint8
|
||||
Int16
|
||||
Uint16
|
||||
Int32
|
||||
Uint32
|
||||
Int64
|
||||
Uint64
|
||||
Float32
|
||||
Float64
|
||||
String
|
||||
Struct
|
||||
Ptr
|
||||
|
||||
SizeType
|
||||
OffType
|
||||
CustomType
|
||||
)
|
||||
|
||||
func (t Type) Resolve(options *Options) Type {
|
||||
switch t {
|
||||
case OffType:
|
||||
switch options.PtrSize {
|
||||
case 8:
|
||||
return Int8
|
||||
case 16:
|
||||
return Int16
|
||||
case 32:
|
||||
return Int32
|
||||
case 64:
|
||||
return Int64
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize))
|
||||
}
|
||||
case SizeType:
|
||||
switch options.PtrSize {
|
||||
case 8:
|
||||
return Uint8
|
||||
case 16:
|
||||
return Uint16
|
||||
case 32:
|
||||
return Uint32
|
||||
case 64:
|
||||
return Uint64
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize))
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t Type) String() string {
|
||||
return typeNames[t]
|
||||
}
|
||||
|
||||
func (t Type) Size() int {
|
||||
switch t {
|
||||
case SizeType, OffType:
|
||||
panic("Size_t/Off_t types must be converted to another type using options.PtrSize")
|
||||
case Pad, String, Int8, Uint8, Bool:
|
||||
return 1
|
||||
case Int16, Uint16:
|
||||
return 2
|
||||
case Int32, Uint32, Float32:
|
||||
return 4
|
||||
case Int64, Uint64, Float64:
|
||||
return 8
|
||||
default:
|
||||
panic("Cannot resolve size of type:" + t.String())
|
||||
}
|
||||
}
|
||||
|
||||
var typeLookup = map[string]Type{
|
||||
"pad": Pad,
|
||||
"bool": Bool,
|
||||
"byte": Uint8,
|
||||
"int8": Int8,
|
||||
"uint8": Uint8,
|
||||
"int16": Int16,
|
||||
"uint16": Uint16,
|
||||
"int32": Int32,
|
||||
"uint32": Uint32,
|
||||
"int64": Int64,
|
||||
"uint64": Uint64,
|
||||
"float32": Float32,
|
||||
"float64": Float64,
|
||||
|
||||
"size_t": SizeType,
|
||||
"off_t": OffType,
|
||||
}
|
||||
|
||||
var typeNames = map[Type]string{
|
||||
CustomType: "Custom",
|
||||
}
|
||||
|
||||
func init() {
|
||||
for name, enum := range typeLookup {
|
||||
typeNames[enum] = name
|
||||
}
|
||||
}
|
||||
|
||||
type Size_t uint64
|
||||
type Off_t int64
|
||||
|
||||
var reflectTypeMap = map[reflect.Kind]Type{
|
||||
reflect.Bool: Bool,
|
||||
reflect.Int8: Int8,
|
||||
reflect.Int16: Int16,
|
||||
reflect.Int: Int32,
|
||||
reflect.Int32: Int32,
|
||||
reflect.Int64: Int64,
|
||||
reflect.Uint8: Uint8,
|
||||
reflect.Uint16: Uint16,
|
||||
reflect.Uint: Uint32,
|
||||
reflect.Uint32: Uint32,
|
||||
reflect.Uint64: Uint64,
|
||||
reflect.Float32: Float32,
|
||||
reflect.Float64: Float64,
|
||||
reflect.String: String,
|
||||
reflect.Struct: Struct,
|
||||
reflect.Ptr: Ptr,
|
||||
}
|
53
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/types_test.go
сгенерированный
поставляемый
Normal file
53
vendor/github.com/mozilla/libaudit-go/vendor/github.com/lunixbochs/struc/types_test.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,53 @@
|
|||
package struc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBadType(t *testing.T) {
|
||||
defer func() { recover() }()
|
||||
Type(-1).Size()
|
||||
t.Fatal("failed to panic for invalid Type.Size()")
|
||||
}
|
||||
|
||||
func TestTypeString(t *testing.T) {
|
||||
if Pad.String() != "pad" {
|
||||
t.Fatal("type string representation failed")
|
||||
}
|
||||
}
|
||||
|
||||
type sizeOffTest struct {
|
||||
Size Size_t
|
||||
Off Off_t
|
||||
}
|
||||
|
||||
func TestSizeOffTypes(t *testing.T) {
|
||||
bits := []int{8, 16, 32, 64}
|
||||
var buf bytes.Buffer
|
||||
test := &sizeOffTest{1, 2}
|
||||
for _, b := range bits {
|
||||
if err := PackWithOptions(&buf, test, &Options{PtrSize: b}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
reference := []byte{
|
||||
1, 2,
|
||||
0, 1, 0, 2,
|
||||
0, 0, 0, 1, 0, 0, 0, 2,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
|
||||
}
|
||||
if !bytes.Equal(reference, buf.Bytes()) {
|
||||
t.Errorf("reference != bytes: %v", reference, buf.Bytes())
|
||||
}
|
||||
reader := bytes.NewReader(buf.Bytes())
|
||||
for _, b := range bits {
|
||||
out := &sizeOffTest{}
|
||||
if err := UnpackWithOptions(reader, out, &Options{PtrSize: b}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.Size != 1 || out.Off != 2 {
|
||||
t.Errorf("Size_t/Off_t mismatch: {%d, %d}\n%v", out.Size, out.Off, buf.Bytes())
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче