LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Netlink sockets and messages | 5 // Netlink sockets and messages |
6 | 6 |
7 package syscall | 7 package syscall |
8 | 8 |
9 import ( | 9 import ( |
10 "unsafe" | 10 "unsafe" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 rr.Header.Type = uint16(proto) | 56 rr.Header.Type = uint16(proto) |
57 rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST | 57 rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST |
58 rr.Header.Seq = uint32(seq) | 58 rr.Header.Seq = uint32(seq) |
59 rr.Data.Family = uint8(family) | 59 rr.Data.Family = uint8(family) |
60 return rr.toWireFormat() | 60 return rr.toWireFormat() |
61 } | 61 } |
62 | 62 |
63 // NetlinkRIB returns routing information base, as known as RIB, | 63 // NetlinkRIB returns routing information base, as known as RIB, |
64 // which consists of network facility information, states and | 64 // which consists of network facility information, states and |
65 // parameters. | 65 // parameters. |
66 func NetlinkRIB(proto, family int) ([]byte, int) { | 66 func NetlinkRIB(proto, family int) ([]byte, error) { |
67 var ( | 67 var ( |
68 s int | |
69 e int | |
70 lsanl SockaddrNetlink | 68 lsanl SockaddrNetlink |
71 seq int | |
72 tab []byte | 69 tab []byte |
73 ) | 70 ) |
74 | 71 |
75 » s, e = Socket(AF_NETLINK, SOCK_RAW, 0) | 72 » s, e := Socket(AF_NETLINK, SOCK_RAW, 0) |
76 » if e != 0 { | 73 » if e != nil { |
77 return nil, e | 74 return nil, e |
78 } | 75 } |
79 defer Close(s) | 76 defer Close(s) |
80 | 77 |
81 lsanl.Family = AF_NETLINK | 78 lsanl.Family = AF_NETLINK |
82 e = Bind(s, &lsanl) | 79 e = Bind(s, &lsanl) |
83 » if e != 0 { | 80 » if e != nil { |
84 return nil, e | 81 return nil, e |
85 } | 82 } |
86 | 83 |
87 » seq++ | 84 » seq := 1 |
88 wb := newNetlinkRouteRequest(proto, seq, family) | 85 wb := newNetlinkRouteRequest(proto, seq, family) |
89 e = Sendto(s, wb, 0, &lsanl) | 86 e = Sendto(s, wb, 0, &lsanl) |
90 » if e != 0 { | 87 » if e != nil { |
91 return nil, e | 88 return nil, e |
92 } | 89 } |
93 | 90 |
94 for { | 91 for { |
95 var ( | 92 var ( |
96 rb []byte | 93 rb []byte |
97 nr int | 94 nr int |
98 lsa Sockaddr | 95 lsa Sockaddr |
99 ) | 96 ) |
100 | 97 |
101 rb = make([]byte, Getpagesize()) | 98 rb = make([]byte, Getpagesize()) |
102 nr, _, e = Recvfrom(s, rb, 0) | 99 nr, _, e = Recvfrom(s, rb, 0) |
103 » » if e != 0 { | 100 » » if e != nil { |
104 return nil, e | 101 return nil, e |
105 } | 102 } |
106 if nr < NLMSG_HDRLEN { | 103 if nr < NLMSG_HDRLEN { |
107 return nil, EINVAL | 104 return nil, EINVAL |
108 } | 105 } |
109 rb = rb[:nr] | 106 rb = rb[:nr] |
110 tab = append(tab, rb...) | 107 tab = append(tab, rb...) |
111 | 108 |
112 msgs, _ := ParseNetlinkMessage(rb) | 109 msgs, _ := ParseNetlinkMessage(rb) |
113 for _, m := range msgs { | 110 for _, m := range msgs { |
114 » » » if lsa, e = Getsockname(s); e != 0 { | 111 » » » if lsa, e = Getsockname(s); e != nil { |
115 return nil, e | 112 return nil, e |
116 } | 113 } |
117 switch v := lsa.(type) { | 114 switch v := lsa.(type) { |
118 case *SockaddrNetlink: | 115 case *SockaddrNetlink: |
119 if m.Header.Seq != uint32(seq) || m.Header.Pid !
= v.Pid { | 116 if m.Header.Seq != uint32(seq) || m.Header.Pid !
= v.Pid { |
120 return nil, EINVAL | 117 return nil, EINVAL |
121 } | 118 } |
122 default: | 119 default: |
123 return nil, EINVAL | 120 return nil, EINVAL |
124 } | 121 } |
125 if m.Header.Type == NLMSG_DONE { | 122 if m.Header.Type == NLMSG_DONE { |
126 goto done | 123 goto done |
127 } | 124 } |
128 if m.Header.Type == NLMSG_ERROR { | 125 if m.Header.Type == NLMSG_ERROR { |
129 return nil, EINVAL | 126 return nil, EINVAL |
130 } | 127 } |
131 } | 128 } |
132 } | 129 } |
133 | 130 |
134 done: | 131 done: |
135 » return tab, 0 | 132 » return tab, nil |
136 } | 133 } |
137 | 134 |
138 // NetlinkMessage represents the netlink message. | 135 // NetlinkMessage represents the netlink message. |
139 type NetlinkMessage struct { | 136 type NetlinkMessage struct { |
140 Header NlMsghdr | 137 Header NlMsghdr |
141 Data []byte | 138 Data []byte |
142 } | 139 } |
143 | 140 |
144 // ParseNetlinkMessage parses buf as netlink messages and returns | 141 // ParseNetlinkMessage parses buf as netlink messages and returns |
145 // the slice containing the NetlinkMessage structs. | 142 // the slice containing the NetlinkMessage structs. |
146 func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) { | 143 func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, error) { |
147 var ( | 144 var ( |
148 h *NlMsghdr | 145 h *NlMsghdr |
149 dbuf []byte | 146 dbuf []byte |
150 dlen int | 147 dlen int |
151 » » e int | 148 » » e error |
152 msgs []NetlinkMessage | 149 msgs []NetlinkMessage |
153 ) | 150 ) |
154 | 151 |
155 for len(buf) >= NLMSG_HDRLEN { | 152 for len(buf) >= NLMSG_HDRLEN { |
156 h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf) | 153 h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf) |
157 » » if e != 0 { | 154 » » if e != nil { |
158 break | 155 break |
159 } | 156 } |
160 m := NetlinkMessage{} | 157 m := NetlinkMessage{} |
161 m.Header = *h | 158 m.Header = *h |
162 m.Data = dbuf[:h.Len-NLMSG_HDRLEN] | 159 m.Data = dbuf[:h.Len-NLMSG_HDRLEN] |
163 msgs = append(msgs, m) | 160 msgs = append(msgs, m) |
164 buf = buf[dlen:] | 161 buf = buf[dlen:] |
165 } | 162 } |
166 | 163 |
167 return msgs, e | 164 return msgs, e |
168 } | 165 } |
169 | 166 |
170 func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, int) { | 167 func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, error) { |
171 h := (*NlMsghdr)(unsafe.Pointer(&buf[0])) | 168 h := (*NlMsghdr)(unsafe.Pointer(&buf[0])) |
172 if h.Len < NLMSG_HDRLEN || int(h.Len) > len(buf) { | 169 if h.Len < NLMSG_HDRLEN || int(h.Len) > len(buf) { |
173 return nil, nil, 0, EINVAL | 170 return nil, nil, 0, EINVAL |
174 } | 171 } |
175 » return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), 0 | 172 » return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil |
176 } | 173 } |
177 | 174 |
178 // NetlinkRouteAttr represents the netlink route attribute. | 175 // NetlinkRouteAttr represents the netlink route attribute. |
179 type NetlinkRouteAttr struct { | 176 type NetlinkRouteAttr struct { |
180 Attr RtAttr | 177 Attr RtAttr |
181 Value []byte | 178 Value []byte |
182 } | 179 } |
183 | 180 |
184 // ParseNetlinkRouteAttr parses msg's payload as netlink route | 181 // ParseNetlinkRouteAttr parses msg's payload as netlink route |
185 // attributes and returns the slice containing the NetlinkRouteAttr | 182 // attributes and returns the slice containing the NetlinkRouteAttr |
186 // structs. | 183 // structs. |
187 func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) { | 184 func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, error) { |
188 var ( | 185 var ( |
189 buf []byte | 186 buf []byte |
190 a *RtAttr | 187 a *RtAttr |
191 alen int | 188 alen int |
192 vbuf []byte | 189 vbuf []byte |
193 » » e int | 190 » » e error |
194 attrs []NetlinkRouteAttr | 191 attrs []NetlinkRouteAttr |
195 ) | 192 ) |
196 | 193 |
197 switch msg.Header.Type { | 194 switch msg.Header.Type { |
198 case RTM_NEWLINK, RTM_DELLINK: | 195 case RTM_NEWLINK, RTM_DELLINK: |
199 buf = msg.Data[SizeofIfInfomsg:] | 196 buf = msg.Data[SizeofIfInfomsg:] |
200 case RTM_NEWADDR, RTM_DELADDR: | 197 case RTM_NEWADDR, RTM_DELADDR: |
201 buf = msg.Data[SizeofIfAddrmsg:] | 198 buf = msg.Data[SizeofIfAddrmsg:] |
202 case RTM_NEWROUTE, RTM_DELROUTE: | 199 case RTM_NEWROUTE, RTM_DELROUTE: |
203 buf = msg.Data[SizeofRtMsg:] | 200 buf = msg.Data[SizeofRtMsg:] |
204 default: | 201 default: |
205 return nil, EINVAL | 202 return nil, EINVAL |
206 } | 203 } |
207 | 204 |
208 for len(buf) >= SizeofRtAttr { | 205 for len(buf) >= SizeofRtAttr { |
209 a, vbuf, alen, e = netlinkRouteAttrAndValue(buf) | 206 a, vbuf, alen, e = netlinkRouteAttrAndValue(buf) |
210 » » if e != 0 { | 207 » » if e != nil { |
211 break | 208 break |
212 } | 209 } |
213 ra := NetlinkRouteAttr{} | 210 ra := NetlinkRouteAttr{} |
214 ra.Attr = *a | 211 ra.Attr = *a |
215 ra.Value = vbuf[:a.Len-SizeofRtAttr] | 212 ra.Value = vbuf[:a.Len-SizeofRtAttr] |
216 attrs = append(attrs, ra) | 213 attrs = append(attrs, ra) |
217 buf = buf[alen:] | 214 buf = buf[alen:] |
218 } | 215 } |
219 | 216 |
220 » return attrs, 0 | 217 » return attrs, nil |
221 } | 218 } |
222 | 219 |
223 func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, int) { | 220 func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, error) { |
224 h := (*RtAttr)(unsafe.Pointer(&buf[0])) | 221 h := (*RtAttr)(unsafe.Pointer(&buf[0])) |
225 if h.Len < SizeofRtAttr || int(h.Len) > len(buf) { | 222 if h.Len < SizeofRtAttr || int(h.Len) > len(buf) { |
226 return nil, nil, 0, EINVAL | 223 return nil, nil, 0, EINVAL |
227 } | 224 } |
228 » return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), 0 | 225 » return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), nil |
229 } | 226 } |
LEFT | RIGHT |