xfrm_policy_linux.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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.Aalgos = ^uint32(0)
  74. userTmpl.Ealgos = ^uint32(0)
  75. userTmpl.Calgos = ^uint32(0)
  76. }
  77. if len(tmplData) > 0 {
  78. tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData)
  79. req.AddData(tmpls)
  80. }
  81. if policy.Mark != nil {
  82. out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
  83. req.AddData(out)
  84. }
  85. _, err := req.Execute(unix.NETLINK_XFRM, 0)
  86. return err
  87. }
  88. // XfrmPolicyDel will delete an xfrm policy from the system. Note that
  89. // the Tmpls are ignored when matching the policy to delete.
  90. // Equivalent to: `ip xfrm policy del $policy`
  91. func XfrmPolicyDel(policy *XfrmPolicy) error {
  92. return pkgHandle.XfrmPolicyDel(policy)
  93. }
  94. // XfrmPolicyDel will delete an xfrm policy from the system. Note that
  95. // the Tmpls are ignored when matching the policy to delete.
  96. // Equivalent to: `ip xfrm policy del $policy`
  97. func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error {
  98. _, err := h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_DELPOLICY)
  99. return err
  100. }
  101. // XfrmPolicyList gets a list of xfrm policies in the system.
  102. // Equivalent to: `ip xfrm policy show`.
  103. // The list can be filtered by ip family.
  104. func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
  105. return pkgHandle.XfrmPolicyList(family)
  106. }
  107. // XfrmPolicyList gets a list of xfrm policies in the system.
  108. // Equivalent to: `ip xfrm policy show`.
  109. // The list can be filtered by ip family.
  110. func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
  111. req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP)
  112. msg := nl.NewIfInfomsg(family)
  113. req.AddData(msg)
  114. msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
  115. if err != nil {
  116. return nil, err
  117. }
  118. var res []XfrmPolicy
  119. for _, m := range msgs {
  120. if policy, err := parseXfrmPolicy(m, family); err == nil {
  121. res = append(res, *policy)
  122. } else if err == familyError {
  123. continue
  124. } else {
  125. return nil, err
  126. }
  127. }
  128. return res, nil
  129. }
  130. // XfrmPolicyGet gets a the policy described by the index or selector, if found.
  131. // Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`.
  132. func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
  133. return pkgHandle.XfrmPolicyGet(policy)
  134. }
  135. // XfrmPolicyGet gets a the policy described by the index or selector, if found.
  136. // Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`.
  137. func (h *Handle) XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
  138. return h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_GETPOLICY)
  139. }
  140. // XfrmPolicyFlush will flush the policies on the system.
  141. // Equivalent to: `ip xfrm policy flush`
  142. func XfrmPolicyFlush() error {
  143. return pkgHandle.XfrmPolicyFlush()
  144. }
  145. // XfrmPolicyFlush will flush the policies on the system.
  146. // Equivalent to: `ip xfrm policy flush`
  147. func (h *Handle) XfrmPolicyFlush() error {
  148. req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK)
  149. _, err := req.Execute(unix.NETLINK_XFRM, 0)
  150. return err
  151. }
  152. func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
  153. req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK)
  154. msg := &nl.XfrmUserpolicyId{}
  155. selFromPolicy(&msg.Sel, policy)
  156. msg.Index = uint32(policy.Index)
  157. msg.Dir = uint8(policy.Dir)
  158. req.AddData(msg)
  159. if policy.Mark != nil {
  160. out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
  161. req.AddData(out)
  162. }
  163. resType := nl.XFRM_MSG_NEWPOLICY
  164. if nlProto == nl.XFRM_MSG_DELPOLICY {
  165. resType = 0
  166. }
  167. msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType))
  168. if err != nil {
  169. return nil, err
  170. }
  171. if nlProto == nl.XFRM_MSG_DELPOLICY {
  172. return nil, err
  173. }
  174. return parseXfrmPolicy(msgs[0], FAMILY_ALL)
  175. }
  176. func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
  177. msg := nl.DeserializeXfrmUserpolicyInfo(m)
  178. // This is mainly for the policy dump
  179. if family != FAMILY_ALL && family != int(msg.Sel.Family) {
  180. return nil, familyError
  181. }
  182. var policy XfrmPolicy
  183. policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD)
  184. policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS)
  185. policy.Proto = Proto(msg.Sel.Proto)
  186. policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
  187. policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
  188. policy.Ifindex = int(msg.Sel.Ifindex)
  189. policy.Priority = int(msg.Priority)
  190. policy.Index = int(msg.Index)
  191. policy.Dir = Dir(msg.Dir)
  192. policy.Action = PolicyAction(msg.Action)
  193. attrs, err := nl.ParseRouteAttr(m[msg.Len():])
  194. if err != nil {
  195. return nil, err
  196. }
  197. for _, attr := range attrs {
  198. switch attr.Attr.Type {
  199. case nl.XFRMA_TMPL:
  200. max := len(attr.Value)
  201. for i := 0; i < max; i += nl.SizeofXfrmUserTmpl {
  202. var resTmpl XfrmPolicyTmpl
  203. tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl])
  204. resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP()
  205. resTmpl.Src = tmpl.Saddr.ToIP()
  206. resTmpl.Proto = Proto(tmpl.XfrmId.Proto)
  207. resTmpl.Mode = Mode(tmpl.Mode)
  208. resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi))
  209. resTmpl.Reqid = int(tmpl.Reqid)
  210. policy.Tmpls = append(policy.Tmpls, resTmpl)
  211. }
  212. case nl.XFRMA_MARK:
  213. mark := nl.DeserializeXfrmMark(attr.Value[:])
  214. policy.Mark = new(XfrmMark)
  215. policy.Mark.Value = mark.Value
  216. policy.Mark.Mask = mark.Mask
  217. }
  218. }
  219. return &policy, nil
  220. }