forked from vishvananda/netlink
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnl_linux_test.go
132 lines (116 loc) · 3.23 KB
/
nl_linux_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package nl
import (
"bytes"
"crypto/rand"
"encoding/binary"
"reflect"
"testing"
"time"
"golang.org/x/sys/unix"
)
type testSerializer interface {
serializeSafe() []byte
Serialize() []byte
}
func testDeserializeSerialize(t *testing.T, orig []byte, safemsg testSerializer, msg testSerializer) {
if !reflect.DeepEqual(safemsg, msg) {
t.Fatal("Deserialization failed.\n", safemsg, "\n", msg)
}
safe := msg.serializeSafe()
if !bytes.Equal(safe, orig) {
t.Fatal("Safe serialization failed.\n", safe, "\n", orig)
}
b := msg.Serialize()
if !bytes.Equal(b, safe) {
t.Fatal("Serialization failed.\n", b, "\n", safe)
}
}
func (msg *IfInfomsg) write(b []byte) {
native := NativeEndian()
b[0] = msg.Family
// pad byte is skipped because it is not exported on linux/s390x
native.PutUint16(b[2:4], msg.Type)
native.PutUint32(b[4:8], uint32(msg.Index))
native.PutUint32(b[8:12], msg.Flags)
native.PutUint32(b[12:16], msg.Change)
}
func (msg *IfInfomsg) serializeSafe() []byte {
length := unix.SizeofIfInfomsg
b := make([]byte, length)
msg.write(b)
return b
}
func deserializeIfInfomsgSafe(b []byte) *IfInfomsg {
var msg = IfInfomsg{}
binary.Read(bytes.NewReader(b[0:unix.SizeofIfInfomsg]), NativeEndian(), &msg)
return &msg
}
func TestIfInfomsgDeserializeSerialize(t *testing.T) {
var orig = make([]byte, unix.SizeofIfInfomsg)
rand.Read(orig)
// zero out the pad byte
orig[1] = 0
safemsg := deserializeIfInfomsgSafe(orig)
msg := DeserializeIfInfomsg(orig)
testDeserializeSerialize(t, orig, safemsg, msg)
}
func TestIfSocketCloses(t *testing.T) {
nlSock, err := Subscribe(unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH)
if err != nil {
t.Fatalf("Error on creating the socket: %v", err)
}
nlSock.SetReceiveTimeout(&unix.Timeval{Sec: 2, Usec: 0})
endCh := make(chan error)
go func(sk *NetlinkSocket, endCh chan error) {
endCh <- nil
for {
_, _, err := sk.Receive()
// Receive returned because of a timeout and the FD == -1 means that the socket got closed
if err == unix.EAGAIN && nlSock.GetFd() == -1 {
endCh <- err
return
}
}
}(nlSock, endCh)
// first receive nil
if msg := <-endCh; msg != nil {
t.Fatalf("Expected nil instead got: %v", msg)
}
// this to guarantee that the receive is invoked before the close
time.Sleep(4 * time.Second)
// Close the socket
nlSock.Close()
// Expect to have an error
msg := <-endCh
if msg == nil {
t.Fatalf("Expected error instead received nil")
}
}
func (msg *CnMsgOp) write(b []byte) {
native := NativeEndian()
native.PutUint32(b[0:4], msg.ID.Idx)
native.PutUint32(b[4:8], msg.ID.Val)
native.PutUint32(b[8:12], msg.Seq)
native.PutUint32(b[12:16], msg.Ack)
native.PutUint16(b[16:18], msg.Length)
native.PutUint16(b[18:20], msg.Flags)
native.PutUint32(b[20:24], msg.Op)
}
func (msg *CnMsgOp) serializeSafe() []byte {
length := msg.Len()
b := make([]byte, length)
msg.write(b)
return b
}
func deserializeCnMsgOpSafe(b []byte) *CnMsgOp {
var msg = CnMsgOp{}
binary.Read(bytes.NewReader(b[0:SizeofCnMsgOp]), NativeEndian(), &msg)
return &msg
}
func TestCnMsgOpDeserializeSerialize(t *testing.T) {
var orig = make([]byte, SizeofCnMsgOp)
rand.Read(orig)
safemsg := deserializeCnMsgOpSafe(orig)
msg := DeserializeCnMsgOp(orig)
testDeserializeSerialize(t, orig, safemsg, msg)
}