/
netlinkmessage.go
133 lines (122 loc) · 3.63 KB
/
netlinkmessage.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
133
// @@
// @ Author : Eacher
// @ Date : 2023-06-26 08:01:05
// @ LastEditTime : 2023-07-08 15:39:34
// @ LastEditors : Eacher
// @ --------------------------------------------------------------------------------<
// @ Description :
// @ --------------------------------------------------------------------------------<
// @ FilePath : /networkmanager/netlinkmessage.go
// @@
package networkmanager
import (
"fmt"
"net"
"sync"
"unsafe"
"syscall"
"encoding/binary"
"github.com/20yyq/packet"
"github.com/20yyq/networkmanager/socket/rtnetlink"
)
func DeserializeNlMsgerr(nlm *syscall.NetlinkMessage) error {
if len(nlm.Data) < packet.SizeofNlMsgerr {
return syscall.Errno(34)
}
msg := packet.NewNlMsgerr(([packet.SizeofNlMsgerr]byte)(nlm.Data[:packet.SizeofNlMsgerr]))
if msg.Error < 0 {
msg.Error *= -1
}
if msg.Error > 0 {
return syscall.Errno(msg.Error)
}
return nil
}
type NetlinkMessage struct {
req uint32
pid uint32
wait bool
mutex sync.Mutex
cond *sync.Cond
Message []*syscall.NetlinkMessage
}
func (ifi *Interface) deserializeIfAddrmsgMessages(nlm *rtnetlink.NetlinkMessage) ([]*Addrs, error) {
var res []*Addrs
name := ifi.iface.Name + string([]byte{0})
for _, m := range nlm.Message {
if l, err := syscall.ParseNetlinkRouteAttr(m); err == nil {
single := Addrs{IfAddrmsg: packet.NewIfAddrmsg(([packet.SizeofIfAddrmsg]byte)(m.Data[:packet.SizeofIfAddrmsg])), label: ""}
for _, v := range l {
switch v.Attr.Type {
case IFA_ADDRESS:
single.address = net.IPv4(v.Value[0], v.Value[1], v.Value[2], v.Value[3])
case IFA_LOCAL:
single.Local = net.IPv4(v.Value[0], v.Value[1], v.Value[2], v.Value[3])
case IFA_BROADCAST:
single.Broadcast = net.IPv4(v.Value[0], v.Value[1], v.Value[2], v.Value[3])
case IFA_ANYCAST:
single.Anycast = net.IPv4(v.Value[0], v.Value[1], v.Value[2], v.Value[3])
case IFA_LABEL:
single.label = string(v.Value)
case IFA_CACHEINFO:
single.Cache = (*cacheInfo)(unsafe.Pointer(&v.Value[:16][0]))
default:
fmt.Println("IFLA_COST", v.Attr.Type, v.Value, single)
}
}
if single.label == name {
res = append(res, &single)
}
continue
}
if 1 > len(res) {
return nil, DeserializeNlMsgerr(m)
}
}
return res, nil
}
func (ifi *Interface) deserializeRtMsgMessages(nlm *rtnetlink.NetlinkMessage) ([]*Routes, error) {
var res []*Routes
for _, m := range nlm.Message {
if l, err := syscall.ParseNetlinkRouteAttr(m); err == nil {
single := Routes{
RtMsg: packet.NewRtMsg(([packet.SizeofRtMsg]byte)(m.Data[:packet.SizeofRtMsg])),
oifIdx: -9999, iifIdx: -9999,
}
for _, v := range l {
switch v.Attr.Type {
case RTA_DST: // 目标地址
single.Dst = net.IP(v.Value)
case RTA_SRC: // 源地址
case RTA_PREFSRC:
single.Src = net.IP(v.Value)
case RTA_IIF: // 输入接口iifIdx
single.iifIdx = int(binary.LittleEndian.Uint32(v.Value))
case RTA_OIF: // 输出接口oifIdx
single.oifIdx = int(binary.LittleEndian.Uint32(v.Value))
case RTA_GATEWAY:
single.Gw = net.IP(v.Value)
case RTA_PRIORITY:
single.Priority = binary.LittleEndian.Uint32(v.Value)
case RTA_METRICS:
case RTA_FLOW: // 所属领域
case RTA_TABLE:
case RTA_CACHEINFO:
fmt.Println("syscall.RTA_CACHEINFO", v.Value)
case RTNLGRP_ND_USEROPT:
fmt.Println("syscall.RTNLGRP_ND_USEROPT", v.Value)
default:
fmt.Println("RTA_MULTIPATH", v.Attr.Type, v.Value, single)
}
}
if single.oifIdx == ifi.iface.Index {
res = append(res, &single)
}
continue
}
if 1 > len(res) {
return nil, DeserializeNlMsgerr(m)
}
}
return res, nil
}