xfrm_policy_linux.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package netlink
  2. import (
  3. "syscall"
  4. "github.com/vishvananda/netlink/nl"
  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. }
  29. // XfrmPolicyAdd will add an xfrm policy to the system.
  30. // Equivalent to: `ip xfrm policy add $policy`
  31. func XfrmPolicyAdd(policy *XfrmPolicy) error {
  32. return pkgHandle.XfrmPolicyAdd(policy)
  33. }
  34. // XfrmPolicyAdd will add an xfrm policy to the system.
  35. // Equivalent to: `ip xfrm policy add $policy`
  36. func (h *Handle) XfrmPolicyAdd(policy *XfrmPolicy) error {
  37. return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_NEWPOLICY)
  38. }
  39. // XfrmPolicyUpdate will update an xfrm policy to the system.
  40. // Equivalent to: `ip xfrm policy update $policy`
  41. func XfrmPolicyUpdate(policy *XfrmPolicy) error {
  42. return pkgHandle.XfrmPolicyUpdate(policy)
  43. }
  44. // XfrmPolicyUpdate will update an xfrm policy to the system.
  45. // Equivalent to: `ip xfrm policy update $policy`
  46. func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error {
  47. return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_UPDPOLICY)
  48. }
  49. func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
  50. req := h.newNetlinkRequest(nlProto, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
  51. msg := &nl.XfrmUserpolicyInfo{}
  52. selFromPolicy(&msg.Sel, policy)
  53. msg.Priority = uint32(policy.Priority)
  54. msg.Index = uint32(policy.Index)
  55. msg.Dir = uint8(policy.Dir)
  56. msg.Lft.SoftByteLimit = nl.XFRM_INF
  57. msg.Lft.HardByteLimit = nl.XFRM_INF
  58. msg.Lft.SoftPacketLimit = nl.XFRM_INF
  59. msg.Lft.HardPacketLimit = nl.XFRM_INF
  60. req.AddData(msg)
  61. tmplData := make([]byte, nl.SizeofXfrmUserTmpl*len(policy.Tmpls))
  62. for i, tmpl := range policy.Tmpls {
  63. start := i * nl.SizeofXfrmUserTmpl
  64. userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl])
  65. userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst)
  66. userTmpl.Saddr.FromIP(tmpl.Src)
  67. userTmpl.XfrmId.Proto = uint8(tmpl.Proto)
  68. userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
  69. userTmpl.Mode = uint8(tmpl.Mode)
  70. userTmpl.Reqid = uint32(tmpl.Reqid)
  71. userTmpl.Aalgos = ^uint32(0)
  72. userTmpl.Ealgos = ^uint32(0)
  73. userTmpl.Calgos = ^uint32(0)
  74. }
  75. if len(tmplData) > 0 {
  76. tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData)
  77. req.AddData(tmpls)
  78. }
  79. if policy.Mark != nil {
  80. out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
  81. req.AddData(out)
  82. }
  83. _, err := req.Execute(syscall.NETLINK_XFRM, 0)
  84. return err
  85. }
  86. // XfrmPolicyDel will delete an xfrm policy from the system. Note that
  87. // the Tmpls are ignored when matching the policy to delete.
  88. // Equivalent to: `ip xfrm policy del $policy`
  89. func XfrmPolicyDel(policy *XfrmPolicy) error {
  90. return pkgHandle.XfrmPolicyDel(policy)
  91. }
  92. // XfrmPolicyDel will delete an xfrm policy from the system. Note that
  93. // the Tmpls are ignored when matching the policy to delete.
  94. // Equivalent to: `ip xfrm policy del $policy`
  95. func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error {
  96. _, err := h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_DELPOLICY)
  97. return err
  98. }
  99. // XfrmPolicyList gets a list of xfrm policies in the system.
  100. // Equivalent to: `ip xfrm policy show`.
  101. // The list can be filtered by ip family.
  102. func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
  103. return pkgHandle.XfrmPolicyList(family)
  104. }
  105. // XfrmPolicyList gets a list of xfrm policies in the system.
  106. // Equivalent to: `ip xfrm policy show`.
  107. // The list can be filtered by ip family.
  108. func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
  109. req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, syscall.NLM_F_DUMP)
  110. msg := nl.NewIfInfomsg(family)
  111. req.AddData(msg)
  112. msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
  113. if err != nil {
  114. return nil, err
  115. }
  116. var res []XfrmPolicy
  117. for _, m := range msgs {
  118. if policy, err := parseXfrmPolicy(m, family); err == nil {
  119. res = append(res, *policy)
  120. } else if err == familyError {
  121. continue
  122. } else {
  123. return nil, err
  124. }
  125. }
  126. return res, nil
  127. }
  128. // XfrmPolicyGet gets a the policy described by the index or selector, if found.
  129. // Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`.
  130. func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
  131. return pkgHandle.XfrmPolicyGet(policy)
  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 (h *Handle) XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
  136. return h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_GETPOLICY)
  137. }
  138. // XfrmPolicyFlush will flush the policies on the system.
  139. // Equivalent to: `ip xfrm policy flush`
  140. func XfrmPolicyFlush() error {
  141. return pkgHandle.XfrmPolicyFlush()
  142. }
  143. // XfrmPolicyFlush will flush the policies on the system.
  144. // Equivalent to: `ip xfrm policy flush`
  145. func (h *Handle) XfrmPolicyFlush() error {
  146. req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, syscall.NLM_F_ACK)
  147. _, err := req.Execute(syscall.NETLINK_XFRM, 0)
  148. return err
  149. }
  150. func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
  151. req := h.newNetlinkRequest(nlProto, syscall.NLM_F_ACK)
  152. msg := &nl.XfrmUserpolicyId{}
  153. selFromPolicy(&msg.Sel, policy)
  154. msg.Index = uint32(policy.Index)
  155. msg.Dir = uint8(policy.Dir)
  156. req.AddData(msg)
  157. if policy.Mark != nil {
  158. out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark))
  159. req.AddData(out)
  160. }
  161. resType := nl.XFRM_MSG_NEWPOLICY
  162. if nlProto == nl.XFRM_MSG_DELPOLICY {
  163. resType = 0
  164. }
  165. msgs, err := req.Execute(syscall.NETLINK_XFRM, uint16(resType))
  166. if err != nil {
  167. return nil, err
  168. }
  169. if nlProto == nl.XFRM_MSG_DELPOLICY {
  170. return nil, err
  171. }
  172. p, err := parseXfrmPolicy(msgs[0], FAMILY_ALL)
  173. if err != nil {
  174. return nil, err
  175. }
  176. return p, nil
  177. }
  178. func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
  179. msg := nl.DeserializeXfrmUserpolicyInfo(m)
  180. // This is mainly for the policy dump
  181. if family != FAMILY_ALL && family != int(msg.Sel.Family) {
  182. return nil, familyError
  183. }
  184. var policy XfrmPolicy
  185. policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD)
  186. policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS)
  187. policy.Proto = Proto(msg.Sel.Proto)
  188. policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
  189. policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
  190. policy.Priority = int(msg.Priority)
  191. policy.Index = int(msg.Index)
  192. policy.Dir = Dir(msg.Dir)
  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. }