1 package netlink
2
3 import (
4 "fmt"
5 "net"
6
7 "github.com/vishvananda/netlink/nl"
8 "golang.org/x/sys/unix"
9 )
10
11
12 type Dir uint8
13
14 const (
15 XFRM_DIR_IN Dir = iota
16 XFRM_DIR_OUT
17 XFRM_DIR_FWD
18 XFRM_SOCKET_IN
19 XFRM_SOCKET_OUT
20 XFRM_SOCKET_FWD
21 )
22
23 func (d Dir) String() string {
24 switch d {
25 case XFRM_DIR_IN:
26 return "dir in"
27 case XFRM_DIR_OUT:
28 return "dir out"
29 case XFRM_DIR_FWD:
30 return "dir fwd"
31 case XFRM_SOCKET_IN:
32 return "socket in"
33 case XFRM_SOCKET_OUT:
34 return "socket out"
35 case XFRM_SOCKET_FWD:
36 return "socket fwd"
37 }
38 return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN)
39 }
40
41
42 type PolicyAction uint8
43
44 const (
45 XFRM_POLICY_ALLOW PolicyAction = 0
46 XFRM_POLICY_BLOCK PolicyAction = 1
47 )
48
49 func (a PolicyAction) String() string {
50 switch a {
51 case XFRM_POLICY_ALLOW:
52 return "allow"
53 case XFRM_POLICY_BLOCK:
54 return "block"
55 default:
56 return fmt.Sprintf("action %d", a)
57 }
58 }
59
60
61
62
63 type XfrmPolicyTmpl struct {
64 Dst net.IP
65 Src net.IP
66 Proto Proto
67 Mode Mode
68 Spi int
69 Reqid int
70 Optional int
71 }
72
73 func (t XfrmPolicyTmpl) String() string {
74 return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}",
75 t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid)
76 }
77
78
79
80
81 type XfrmPolicy struct {
82 Dst *net.IPNet
83 Src *net.IPNet
84 Proto Proto
85 DstPort int
86 SrcPort int
87 Dir Dir
88 Priority int
89 Index int
90 Action PolicyAction
91 Ifindex int
92 Ifid int
93 Mark *XfrmMark
94 Tmpls []XfrmPolicyTmpl
95 }
96
97 func (p XfrmPolicy) String() string {
98 return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}",
99 p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls)
100 }
101
102 func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
103 sel.Family = uint16(nl.FAMILY_V4)
104 if policy.Dst != nil {
105 sel.Family = uint16(nl.GetIPFamily(policy.Dst.IP))
106 sel.Daddr.FromIP(policy.Dst.IP)
107 prefixlenD, _ := policy.Dst.Mask.Size()
108 sel.PrefixlenD = uint8(prefixlenD)
109 }
110 if policy.Src != nil {
111 sel.Saddr.FromIP(policy.Src.IP)
112 prefixlenS, _ := policy.Src.Mask.Size()
113 sel.PrefixlenS = uint8(prefixlenS)
114 }
115 sel.Proto = uint8(policy.Proto)
116 sel.Dport = nl.Swap16(uint16(policy.DstPort))
117 sel.Sport = nl.Swap16(uint16(policy.SrcPort))
118 if sel.Dport != 0 {
119 sel.DportMask = ^uint16(0)
120 }
121 if sel.Sport != 0 {
122 sel.SportMask = ^uint16(0)
123 }
124 sel.Ifindex = int32(policy.Ifindex)
125 }
126
127
128
129 func XfrmPolicyAdd(policy *XfrmPolicy) error {
130 return pkgHandle.XfrmPolicyAdd(policy)
131 }
132
133
134
135 func (h *Handle) XfrmPolicyAdd(policy *XfrmPolicy) error {
136 return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_NEWPOLICY)
137 }
138
139
140
141 func XfrmPolicyUpdate(policy *XfrmPolicy) error {
142 return pkgHandle.XfrmPolicyUpdate(policy)
143 }
144
145
146
147 func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error {
148 return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_UPDPOLICY)
149 }
150
151 func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
152 req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
153
154 msg := &nl.XfrmUserpolicyInfo{}
155 selFromPolicy(&msg.Sel, policy)
156 msg.Priority = uint32(policy.Priority)
157 msg.Index = uint32(policy.Index)
158 msg.Dir = uint8(policy.Dir)
159 msg.Action = uint8(policy.Action)
160 msg.Lft.SoftByteLimit = nl.XFRM_INF
161 msg.Lft.HardByteLimit = nl.XFRM_INF
162 msg.Lft.SoftPacketLimit = nl.XFRM_INF
163 msg.Lft.HardPacketLimit = nl.XFRM_INF
164 req.AddData(msg)
165
166 tmplData := make([]byte, nl.SizeofXfrmUserTmpl*len(policy.Tmpls))
167 for i, tmpl := range policy.Tmpls {
168 start := i * nl.SizeofXfrmUserTmpl
169 userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl])
170 userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst)
171 userTmpl.Saddr.FromIP(tmpl.Src)
172 userTmpl.Family = uint16(nl.GetIPFamily(tmpl.Dst))
173 userTmpl.XfrmId.Proto = uint8(tmpl.Proto)
174 userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
175 userTmpl.Mode = uint8(tmpl.Mode)
176 userTmpl.Reqid = uint32(tmpl.Reqid)
177 userTmpl.Optional = uint8(tmpl.Optional)
178 userTmpl.Aalgos = ^uint32(0)
179 userTmpl.Ealgos = ^uint32(0)
180 userTmpl.Calgos = ^uint32(0)
181 }
182 if len(tmplData) > 0 {
183 tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData)
184 req.AddData(tmpls)
185 }
186 if policy.Mark != nil {
187 out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
188 req.AddData(out)
189 }
190
191 if policy.Ifid != 0 {
192 ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
193 req.AddData(ifId)
194 }
195
196 _, err := req.Execute(unix.NETLINK_XFRM, 0)
197 return err
198 }
199
200
201
202
203 func XfrmPolicyDel(policy *XfrmPolicy) error {
204 return pkgHandle.XfrmPolicyDel(policy)
205 }
206
207
208
209
210 func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error {
211 _, err := h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_DELPOLICY)
212 return err
213 }
214
215
216
217
218 func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
219 return pkgHandle.XfrmPolicyList(family)
220 }
221
222
223
224
225 func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
226 req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP)
227
228 msg := nl.NewIfInfomsg(family)
229 req.AddData(msg)
230
231 msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
232 if err != nil {
233 return nil, err
234 }
235
236 var res []XfrmPolicy
237 for _, m := range msgs {
238 if policy, err := parseXfrmPolicy(m, family); err == nil {
239 res = append(res, *policy)
240 } else if err == familyError {
241 continue
242 } else {
243 return nil, err
244 }
245 }
246 return res, nil
247 }
248
249
250
251 func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
252 return pkgHandle.XfrmPolicyGet(policy)
253 }
254
255
256
257 func (h *Handle) XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
258 return h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_GETPOLICY)
259 }
260
261
262
263 func XfrmPolicyFlush() error {
264 return pkgHandle.XfrmPolicyFlush()
265 }
266
267
268
269 func (h *Handle) XfrmPolicyFlush() error {
270 req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK)
271 _, err := req.Execute(unix.NETLINK_XFRM, 0)
272 return err
273 }
274
275 func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
276 req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK)
277
278 msg := &nl.XfrmUserpolicyId{}
279 selFromPolicy(&msg.Sel, policy)
280 msg.Index = uint32(policy.Index)
281 msg.Dir = uint8(policy.Dir)
282 req.AddData(msg)
283
284 if policy.Mark != nil {
285 out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
286 req.AddData(out)
287 }
288
289 if policy.Ifid != 0 {
290 ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
291 req.AddData(ifId)
292 }
293
294 resType := nl.XFRM_MSG_NEWPOLICY
295 if nlProto == nl.XFRM_MSG_DELPOLICY {
296 resType = 0
297 }
298
299 msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType))
300 if err != nil {
301 return nil, err
302 }
303
304 if nlProto == nl.XFRM_MSG_DELPOLICY {
305 return nil, err
306 }
307
308 return parseXfrmPolicy(msgs[0], FAMILY_ALL)
309 }
310
311 func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
312 msg := nl.DeserializeXfrmUserpolicyInfo(m)
313
314
315 if family != FAMILY_ALL && family != int(msg.Sel.Family) {
316 return nil, familyError
317 }
318
319 var policy XfrmPolicy
320
321 policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, uint16(family))
322 policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, uint16(family))
323 policy.Proto = Proto(msg.Sel.Proto)
324 policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
325 policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
326 policy.Ifindex = int(msg.Sel.Ifindex)
327 policy.Priority = int(msg.Priority)
328 policy.Index = int(msg.Index)
329 policy.Dir = Dir(msg.Dir)
330 policy.Action = PolicyAction(msg.Action)
331
332 attrs, err := nl.ParseRouteAttr(m[msg.Len():])
333 if err != nil {
334 return nil, err
335 }
336
337 for _, attr := range attrs {
338 switch attr.Attr.Type {
339 case nl.XFRMA_TMPL:
340 max := len(attr.Value)
341 for i := 0; i < max; i += nl.SizeofXfrmUserTmpl {
342 var resTmpl XfrmPolicyTmpl
343 tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl])
344 resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP()
345 resTmpl.Src = tmpl.Saddr.ToIP()
346 resTmpl.Proto = Proto(tmpl.XfrmId.Proto)
347 resTmpl.Mode = Mode(tmpl.Mode)
348 resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi))
349 resTmpl.Reqid = int(tmpl.Reqid)
350 resTmpl.Optional = int(tmpl.Optional)
351 policy.Tmpls = append(policy.Tmpls, resTmpl)
352 }
353 case nl.XFRMA_MARK:
354 mark := nl.DeserializeXfrmMark(attr.Value[:])
355 policy.Mark = new(XfrmMark)
356 policy.Mark.Value = mark.Value
357 policy.Mark.Mask = mark.Mask
358 case nl.XFRMA_IF_ID:
359 policy.Ifid = int(native.Uint32(attr.Value))
360 }
361 }
362
363 return &policy, nil
364 }
365
View as plain text