github.com/20yyq/packet@v0.1.4-0.20231013092308-386a004a3baa/netlink.go (about) 1 // @@ 2 // @ Author : Eacher 3 // @ Date : 2023-07-01 15:20:41 4 // @ LastEditTime : 2023-09-20 09:44:57 5 // @ LastEditors : Eacher 6 // @ --------------------------------------------------------------------------------< 7 // @ Description : 8 // @ --------------------------------------------------------------------------------< 9 // @ FilePath : /20yyq/packet/netlink.go 10 // @@ 11 package packet 12 13 import ( 14 "unsafe" 15 "syscall" 16 ) 17 18 const ( 19 SizeofNlMsghdr = syscall.SizeofNlMsghdr 20 SizeofNlAttr = syscall.SizeofNlAttr 21 SizeofRtAttr = syscall.SizeofRtAttr 22 SizeofNlMsgerr = syscall.SizeofNlMsgerr 23 SizeofIfAddrmsg = syscall.SizeofIfAddrmsg 24 SizeofRtMsg = syscall.SizeofRtMsg 25 SizeofIfInfomsg = syscall.SizeofIfInfomsg 26 ) 27 28 type IfInfomsg syscall.IfInfomsg 29 type IfAddrmsg syscall.IfAddrmsg 30 type RtMsg syscall.RtMsg 31 type NlMsghdr syscall.NlMsghdr 32 type NlMsgerr struct { 33 Error int32 34 Msg NlMsghdr 35 } 36 type NetlinkMessage struct { 37 Header *NlMsghdr 38 Data []byte 39 } 40 type RtAttr struct { 41 *syscall.RtAttr 42 Data []byte 43 } 44 type NlAttr struct { 45 *syscall.NlAttr 46 Data []byte 47 } 48 49 //go:linkname nlmAlignOf syscall.nlmAlignOf 50 func nlmAlignOf(msglen int) int 51 52 //go:linkname rtaAlignOf syscall.rtaAlignOf 53 func rtaAlignOf(attrlen int) int 54 55 func NewIfInfomsg(b [SizeofIfInfomsg]byte) (info *IfInfomsg) { 56 info = (*IfInfomsg)(unsafe.Pointer(&b[0])) 57 return 58 } 59 60 func (info IfInfomsg) WireFormat() []byte { 61 var b [SizeofIfInfomsg]byte 62 b[0], b[1] = info.Family, info.X__ifi_pad 63 *(*uint16)(unsafe.Pointer(&b[2])) = info.Type 64 *(*int32)(unsafe.Pointer(&b[4])) = info.Index 65 *(*uint32)(unsafe.Pointer(&b[8])) = info.Flags 66 *(*uint32)(unsafe.Pointer(&b[12])) = info.Change 67 return b[:] 68 } 69 70 func NewIfAddrmsg(b [SizeofIfAddrmsg]byte) (addr *IfAddrmsg) { 71 addr = (*IfAddrmsg)(unsafe.Pointer(&b[0])) 72 return 73 } 74 75 func (addr IfAddrmsg) WireFormat() []byte { 76 var b [SizeofIfAddrmsg]byte 77 b[0], b[1], b[2], b[3] = addr.Family, addr.Prefixlen, addr.Flags, addr.Scope 78 *(*uint32)(unsafe.Pointer(&b[4])) = addr.Index 79 return b[:] 80 } 81 82 func NewRtMsg(b [SizeofRtMsg]byte) (rtmsg *RtMsg) { 83 rtmsg = (*RtMsg)(unsafe.Pointer(&b[0])) 84 return 85 } 86 87 func (rtmsg RtMsg) WireFormat() []byte { 88 var b [SizeofRtMsg]byte 89 b[0], b[1], b[2], b[3] = rtmsg.Family, rtmsg.Dst_len, rtmsg.Src_len, rtmsg.Tos 90 b[4], b[5], b[6], b[7] = rtmsg.Table, rtmsg.Protocol, rtmsg.Scope, rtmsg.Type 91 *(*uint32)(unsafe.Pointer(&b[8])) = rtmsg.Flags 92 return b[:] 93 } 94 95 func NewNlMsghdr(b [SizeofNlMsghdr]byte) (hdr *NlMsghdr) { 96 hdr = (*NlMsghdr)(unsafe.Pointer(&b[0])) 97 return 98 } 99 100 func (hdr NlMsghdr) WireFormat() []byte { 101 var b [SizeofNlMsghdr]byte 102 hdr.WireFormatToByte(&b) 103 return b[:] 104 } 105 106 func (hdr NlMsghdr) WireFormatToByte(b *[SizeofNlMsghdr]byte) { 107 *(*uint32)(unsafe.Pointer(&b[0])) = hdr.Len 108 *(*uint16)(unsafe.Pointer(&b[4])) = hdr.Type 109 *(*uint16)(unsafe.Pointer(&b[6])) = hdr.Flags 110 *(*uint32)(unsafe.Pointer(&b[8])) = hdr.Seq 111 *(*uint32)(unsafe.Pointer(&b[12])) = hdr.Pid 112 } 113 114 func NewNlMsgerr(b [SizeofNlMsgerr]byte) (nlmsge *NlMsgerr) { 115 nlmsge = (*NlMsgerr)(unsafe.Pointer(&b[0])) 116 return 117 } 118 119 func (nlmsge NlMsgerr) WireFormat() []byte { 120 var b [SizeofNlMsgerr]byte 121 *(*int32)(unsafe.Pointer(&b[0])) = nlmsge.Error 122 nlmsge.Msg.WireFormatToByte((*[SizeofNlMsghdr]byte)(b[4:])) 123 return b[:] 124 } 125 126 func NewNetlinkMessage(b []byte) (nlmsg []*NetlinkMessage) { 127 for len(b) >= SizeofNlMsghdr { 128 m := &NetlinkMessage{Header: NewNlMsghdr(([SizeofNlMsghdr]byte)(b))} 129 l := nlmAlignOf(int(m.Header.Len)) 130 if m.Header.Len < SizeofNlMsghdr || l > len(b) { 131 break 132 } 133 if int(m.Header.Len - SizeofNlMsghdr) < len(b) { 134 m.Data = b[SizeofNlMsghdr:m.Header.Len] 135 } else { 136 m.Data = b[SizeofNlMsghdr:] 137 } 138 b = b[l:] 139 nlmsg = append(nlmsg, m) 140 } 141 return 142 } 143 144 func (nlmsg NetlinkMessage) WireFormat() []byte { 145 b := make([]byte, SizeofNlMsghdr + len(nlmsg.Data)) 146 copy(b, nlmsg.Header.WireFormat()) 147 copy(b[SizeofNlMsghdr:], nlmsg.Data) 148 return b 149 } 150 151 // ParseNetlinkRouteAttr parses m's payload as an array of netlink 152 // route attributes and returns the slice containing the 153 // NetlinkRouteAttr structures. 154 func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]*RtAttr, error) { 155 var b []byte 156 switch m.Header.Type { 157 case syscall.RTM_NEWLINK, syscall.RTM_DELLINK: 158 b = m.Data[SizeofIfInfomsg:] 159 case syscall.RTM_NEWADDR, syscall.RTM_DELADDR: 160 b = m.Data[SizeofIfAddrmsg:] 161 case syscall.RTM_NEWROUTE, syscall.RTM_DELROUTE: 162 b = m.Data[SizeofRtMsg:] 163 default: 164 return nil, syscall.EINVAL 165 } 166 return NewRtAttrs(b), nil 167 } 168 169 func NewRtAttrs(b []byte) []*RtAttr { 170 var attrs []*RtAttr 171 for len(b) >= SizeofRtAttr { 172 r := (*syscall.RtAttr)(unsafe.Pointer(&b[0])) 173 if int(r.Len) < SizeofRtAttr || int(r.Len) > len(b) { 174 break 175 } 176 attrs = append(attrs, &RtAttr{RtAttr: r, Data: b[SizeofRtAttr:r.Len]}) 177 b = b[rtaAlignOf(int(r.Len)):] 178 } 179 return attrs 180 } 181 182 func (rta RtAttr) WireFormat() []byte { 183 b := make([]byte, SizeofRtAttr + len(rta.Data)) 184 *(*uint16)(unsafe.Pointer(&b[0])) = rta.Len 185 *(*uint16)(unsafe.Pointer(&b[2])) = rta.Type 186 copy(b[SizeofRtAttr:], rta.Data) 187 return b 188 } 189 190 func NewNlAttrs(b []byte) []*NlAttr { 191 var attrs []*NlAttr 192 for len(b) >= SizeofNlAttr { 193 nl := (*syscall.NlAttr)(unsafe.Pointer(&b[0])) 194 if int(nl.Len) < SizeofNlAttr || int(nl.Len) > len(b) { 195 break 196 } 197 attrs = append(attrs, &NlAttr{NlAttr: nl, Data: b[SizeofNlAttr:nl.Len]}) 198 b = b[rtaAlignOf(int(nl.Len)):] 199 } 200 return attrs 201 } 202 203 func (nla NlAttr) WireFormat() []byte { 204 b := make([]byte, SizeofNlAttr + len(nla.Data)) 205 *(*uint16)(unsafe.Pointer(&b[0])) = nla.Len 206 *(*uint16)(unsafe.Pointer(&b[2])) = nla.Type 207 copy(b[SizeofNlAttr:], nla.Data) 208 return b 209 }