xfrm_policy_linux.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. package netlink
  2. import (
  3. "github.com/vishvananda/netlink/nl"
  4. "golang.org/x/sys/unix"
  5. )
  6. func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
  7. sel.Family = uint16(nl.FAMILY_V4)
  8. if policy.Dst != nil {
  9. sel.Family = uint16(nl.GetIPFamily(policy.Dst.IP))
  10. sel.Daddr.FromIP(policy.Dst.IP)
  11. prefixlenD, _ := policy.Dst.Mask.Size()
  12. sel.PrefixlenD = uint8(prefixlenD)
  13. }
  14. if policy.Src != nil {
  15. sel.Saddr.FromIP(policy.Src.IP)
  16. prefixlenS, _ := policy.Src.Mask.Size()
  17. sel.PrefixlenS = uint8(prefixlenS)
  18. }
  19. sel.Proto = uint8(policy.Proto)
  20. sel.Dport = nl.Swap16(uint16(policy.DstPort))
  21. sel.Sport = nl.Swap16(uint16(policy.SrcPort))
  22. if sel.Dport != 0 {
  23. sel.DportMask = ^uint16(0)
  24. }
  25. if sel.Sport != 0 {
  26. sel.SportMask = ^uint16(0)
  27. }
  28. sel.Ifindex = int32(policy.Ifindex)
  29. }
  30. // XfrmPolicyAdd will add an xfrm policy to the system.
  31. // Equivalent to: `ip xfrm policy add $policy`
  32. func XfrmPolicyAdd(policy *XfrmPolicy) error {
  33. return pkgHandle.XfrmPolicyAdd(policy)
  34. }
  35. // XfrmPolicyAdd will add an xfrm policy to the system.
  36. // Equivalent to: `ip xfrm policy add $policy`
  37. func (h *Handle) XfrmPolicyAdd(policy *XfrmPolicy) error {
  38. return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_NEWPOLICY)
  39. }
  40. // XfrmPolicyUpdate will update an xfrm policy to the system.
  41. // Equivalent to: `ip xfrm policy update $policy`
  42. func XfrmPolicyUpdate(policy *XfrmPolicy) error {
  43. return pkgHandle.XfrmPolicyUpdate(policy)
  44. }
  45. // XfrmPolicyUpdate will update an xfrm policy to the system.
  46. // Equivalent to: `ip xfrm policy update $policy`
  47. func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error {
  48. return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_UPDPOLICY)
  49. }
  50. func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
  51. req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
  52. msg := &nl.XfrmUserpolicyInfo{}
  53. selFromPolicy(&msg.Sel, policy)
  54. msg.Priority = uint32(policy.Priority)
  55. msg.Index = uint32(policy.Index)
  56. msg.Dir = uint8(policy.Dir)
  57. msg.Action = uint8(policy.Action)
  58. msg.Lft.SoftByteLimit = nl.XFRM_INF
  59. msg.Lft.HardByteLimit = nl.XFRM_INF
  60. msg.Lft.SoftPacketLimit = nl.XFRM_INF
  61. msg.Lft.HardPacketLimit = nl.XFRM_INF
  62. req.AddData(msg)
  63. tmplData := make([]byte, nl.SizeofXfrmUserTmpl*len(policy.Tmpls))
  64. for i, tmpl := range policy.Tmpls {
  65. start := i * nl.SizeofXfrmUserTmpl
  66. userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl])
  67. userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst)
  68. userTmpl.Saddr.FromIP(tmpl.Src)
  69. userTmpl.XfrmId.Proto = uint8(tmpl.Proto)
  70. userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
  71. userTmpl.Mode = uint8(tmpl.Mode)
  72. userTmpl.Reqid = uint32(tmpl.Reqid)
  73. userTmpl.Optional = uint8(tmpl.Optional)
  74. userTmpl.Aalgos = ^uint32(0)
  75. userTmpl.Ealgos = ^uint32(0)
  76. userTmpl.Calgos = ^uint32(0)
  77. }
  78. if len(tmplData) > 0 {
  79. tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData)
  80. req.AddData(tmpls)
  81. }
  82. if policy.Mark != nil {
  83. out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
  84. req.AddData(out)
  85. }
  86. ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
  87. req.AddData(ifId)
  88. _, err := req.Execute(unix.NETLINK_XFRM, 0)
  89. return err
  90. }
  91. // XfrmPolicyDel will delete an xfrm policy from the system. Note that
  92. // the Tmpls are ignored when matching the policy to delete.
  93. // Equivalent to: `ip xfrm policy del $policy`
  94. func XfrmPolicyDel(policy *XfrmPolicy) error {
  95. return pkgHandle.XfrmPolicyDel(policy)
  96. }
  97. // XfrmPolicyDel will delete an xfrm policy from the system. Note that
  98. // the Tmpls are ignored when matching the policy to delete.
  99. // Equivalent to: `ip xfrm policy del $policy`
  100. func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error {
  101. _, err := h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_DELPOLICY)
  102. return err
  103. }
  104. // XfrmPolicyList gets a list of xfrm policies in the system.
  105. // Equivalent to: `ip xfrm policy show`.
  106. // The list can be filtered by ip family.
  107. func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
  108. return pkgHandle.XfrmPolicyList(family)
  109. }
  110. // XfrmPolicyList gets a list of xfrm policies in the system.
  111. // Equivalent to: `ip xfrm policy show`.
  112. // The list can be filtered by ip family.
  113. func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
  114. req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP)
  115. msg := nl.NewIfInfomsg(family)
  116. req.AddData(msg)
  117. msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
  118. if err != nil {
  119. return nil, err
  120. }
  121. var res []XfrmPolicy
  122. for _, m := range msgs {
  123. if policy, err := parseXfrmPolicy(m, family); err == nil {
  124. res = append(res, *policy)
  125. } else if err == familyError {
  126. continue
  127. } else {
  128. return nil, err
  129. }
  130. }
  131. return res, nil
  132. }
  133. // XfrmPolicyGet gets a the policy described by the index or selector, if found.
  134. // Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`.
  135. func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
  136. return pkgHandle.XfrmPolicyGet(policy)
  137. }
  138. // XfrmPolicyGet gets a the policy described by the index or selector, if found.
  139. // Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`.
  140. func (h *Handle) XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
  141. return h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_GETPOLICY)
  142. }
  143. // XfrmPolicyFlush will flush the policies on the system.
  144. // Equivalent to: `ip xfrm policy flush`
  145. func XfrmPolicyFlush() error {
  146. return pkgHandle.XfrmPolicyFlush()
  147. }
  148. // XfrmPolicyFlush will flush the policies on the system.
  149. // Equivalent to: `ip xfrm policy flush`
  150. func (h *Handle) XfrmPolicyFlush() error {
  151. req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK)
  152. _, err := req.Execute(unix.NETLINK_XFRM, 0)
  153. return err
  154. }
  155. func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
  156. req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK)
  157. msg := &nl.XfrmUserpolicyId{}
  158. selFromPolicy(&msg.Sel, policy)
  159. msg.Index = uint32(policy.Index)
  160. msg.Dir = uint8(policy.Dir)
  161. req.AddData(msg)
  162. if policy.Mark != nil {
  163. out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
  164. req.AddData(out)
  165. }
  166. ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
  167. req.AddData(ifId)
  168. resType := nl.XFRM_MSG_NEWPOLICY
  169. if nlProto == nl.XFRM_MSG_DELPOLICY {
  170. resType = 0
  171. }
  172. msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType))
  173. if err != nil {
  174. return nil, err
  175. }
  176. if nlProto == nl.XFRM_MSG_DELPOLICY {
  177. return nil, err
  178. }
  179. return parseXfrmPolicy(msgs[0], FAMILY_ALL)
  180. }
  181. func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
  182. msg := nl.DeserializeXfrmUserpolicyInfo(m)
  183. // This is mainly for the policy dump
  184. if family != FAMILY_ALL && family != int(msg.Sel.Family) {
  185. return nil, familyError
  186. }
  187. var policy XfrmPolicy
  188. policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD)
  189. policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS)
  190. policy.Proto = Proto(msg.Sel.Proto)
  191. policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
  192. policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
  193. policy.Ifindex = int(msg.Sel.Ifindex)
  194. policy.Priority = int(msg.Priority)
  195. policy.Index = int(msg.Index)
  196. policy.Dir = Dir(msg.Dir)
  197. policy.Action = PolicyAction(msg.Action)
  198. attrs, err := nl.ParseRouteAttr(m[msg.Len():])
  199. if err != nil {
  200. return nil, err
  201. }
  202. for _, attr := range attrs {
  203. switch attr.Attr.Type {
  204. case nl.XFRMA_TMPL:
  205. max := len(attr.Value)
  206. for i := 0; i < max; i += nl.SizeofXfrmUserTmpl {
  207. var resTmpl XfrmPolicyTmpl
  208. tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl])
  209. resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP()
  210. resTmpl.Src = tmpl.Saddr.ToIP()
  211. resTmpl.Proto = Proto(tmpl.XfrmId.Proto)
  212. resTmpl.Mode = Mode(tmpl.Mode)
  213. resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi))
  214. resTmpl.Reqid = int(tmpl.Reqid)
  215. resTmpl.Optional = int(tmpl.Optional)
  216. policy.Tmpls = append(policy.Tmpls, resTmpl)
  217. }
  218. case nl.XFRMA_MARK:
  219. mark := nl.DeserializeXfrmMark(attr.Value[:])
  220. policy.Mark = new(XfrmMark)
  221. policy.Mark.Value = mark.Value
  222. policy.Mark.Mask = mark.Mask
  223. case nl.XFRMA_IF_ID:
  224. policy.Ifid = int(native.Uint32(attr.Value))
  225. }
  226. }
  227. return &policy, nil
  228. }