route_linux.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. package netlink
  2. import (
  3. "fmt"
  4. "net"
  5. "strings"
  6. "syscall"
  7. "github.com/vishvananda/netlink/nl"
  8. "github.com/vishvananda/netns"
  9. )
  10. // RtAttr is shared so it is in netlink_linux.go
  11. const (
  12. SCOPE_UNIVERSE Scope = syscall.RT_SCOPE_UNIVERSE
  13. SCOPE_SITE Scope = syscall.RT_SCOPE_SITE
  14. SCOPE_LINK Scope = syscall.RT_SCOPE_LINK
  15. SCOPE_HOST Scope = syscall.RT_SCOPE_HOST
  16. SCOPE_NOWHERE Scope = syscall.RT_SCOPE_NOWHERE
  17. )
  18. const (
  19. RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota)
  20. RT_FILTER_SCOPE
  21. RT_FILTER_TYPE
  22. RT_FILTER_TOS
  23. RT_FILTER_IIF
  24. RT_FILTER_OIF
  25. RT_FILTER_DST
  26. RT_FILTER_SRC
  27. RT_FILTER_GW
  28. RT_FILTER_TABLE
  29. )
  30. const (
  31. FLAG_ONLINK NextHopFlag = syscall.RTNH_F_ONLINK
  32. FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE
  33. )
  34. var testFlags = []flagString{
  35. {f: FLAG_ONLINK, s: "onlink"},
  36. {f: FLAG_PERVASIVE, s: "pervasive"},
  37. }
  38. func listFlags(flag int) []string {
  39. var flags []string
  40. for _, tf := range testFlags {
  41. if flag&int(tf.f) != 0 {
  42. flags = append(flags, tf.s)
  43. }
  44. }
  45. return flags
  46. }
  47. func (r *Route) ListFlags() []string {
  48. return listFlags(r.Flags)
  49. }
  50. func (n *NexthopInfo) ListFlags() []string {
  51. return listFlags(n.Flags)
  52. }
  53. type MPLSDestination struct {
  54. Labels []int
  55. }
  56. func (d *MPLSDestination) Family() int {
  57. return nl.FAMILY_MPLS
  58. }
  59. func (d *MPLSDestination) Decode(buf []byte) error {
  60. d.Labels = nl.DecodeMPLSStack(buf)
  61. return nil
  62. }
  63. func (d *MPLSDestination) Encode() ([]byte, error) {
  64. return nl.EncodeMPLSStack(d.Labels...), nil
  65. }
  66. func (d *MPLSDestination) String() string {
  67. s := make([]string, 0, len(d.Labels))
  68. for _, l := range d.Labels {
  69. s = append(s, fmt.Sprintf("%d", l))
  70. }
  71. return strings.Join(s, "/")
  72. }
  73. func (d *MPLSDestination) Equal(x Destination) bool {
  74. o, ok := x.(*MPLSDestination)
  75. if !ok {
  76. return false
  77. }
  78. if d == nil && o == nil {
  79. return true
  80. }
  81. if d == nil || o == nil {
  82. return false
  83. }
  84. if d.Labels == nil && o.Labels == nil {
  85. return true
  86. }
  87. if d.Labels == nil || o.Labels == nil {
  88. return false
  89. }
  90. if len(d.Labels) != len(o.Labels) {
  91. return false
  92. }
  93. for i := range d.Labels {
  94. if d.Labels[i] != o.Labels[i] {
  95. return false
  96. }
  97. }
  98. return true
  99. }
  100. type MPLSEncap struct {
  101. Labels []int
  102. }
  103. func (e *MPLSEncap) Type() int {
  104. return nl.LWTUNNEL_ENCAP_MPLS
  105. }
  106. func (e *MPLSEncap) Decode(buf []byte) error {
  107. if len(buf) < 4 {
  108. return fmt.Errorf("Lack of bytes")
  109. }
  110. native := nl.NativeEndian()
  111. l := native.Uint16(buf)
  112. if len(buf) < int(l) {
  113. return fmt.Errorf("Lack of bytes")
  114. }
  115. buf = buf[:l]
  116. typ := native.Uint16(buf[2:])
  117. if typ != nl.MPLS_IPTUNNEL_DST {
  118. return fmt.Errorf("Unknown MPLS Encap Type: %d", typ)
  119. }
  120. e.Labels = nl.DecodeMPLSStack(buf[4:])
  121. return nil
  122. }
  123. func (e *MPLSEncap) Encode() ([]byte, error) {
  124. s := nl.EncodeMPLSStack(e.Labels...)
  125. native := nl.NativeEndian()
  126. hdr := make([]byte, 4)
  127. native.PutUint16(hdr, uint16(len(s)+4))
  128. native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST)
  129. return append(hdr, s...), nil
  130. }
  131. func (e *MPLSEncap) String() string {
  132. s := make([]string, 0, len(e.Labels))
  133. for _, l := range e.Labels {
  134. s = append(s, fmt.Sprintf("%d", l))
  135. }
  136. return strings.Join(s, "/")
  137. }
  138. func (e *MPLSEncap) Equal(x Encap) bool {
  139. o, ok := x.(*MPLSEncap)
  140. if !ok {
  141. return false
  142. }
  143. if e == nil && o == nil {
  144. return true
  145. }
  146. if e == nil || o == nil {
  147. return false
  148. }
  149. if e.Labels == nil && o.Labels == nil {
  150. return true
  151. }
  152. if e.Labels == nil || o.Labels == nil {
  153. return false
  154. }
  155. if len(e.Labels) != len(o.Labels) {
  156. return false
  157. }
  158. for i := range e.Labels {
  159. if e.Labels[i] != o.Labels[i] {
  160. return false
  161. }
  162. }
  163. return true
  164. }
  165. // RouteAdd will add a route to the system.
  166. // Equivalent to: `ip route add $route`
  167. func RouteAdd(route *Route) error {
  168. return pkgHandle.RouteAdd(route)
  169. }
  170. // RouteAdd will add a route to the system.
  171. // Equivalent to: `ip route add $route`
  172. func (h *Handle) RouteAdd(route *Route) error {
  173. flags := syscall.NLM_F_CREATE | syscall.NLM_F_EXCL | syscall.NLM_F_ACK
  174. req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags)
  175. return h.routeHandle(route, req, nl.NewRtMsg())
  176. }
  177. // RouteReplace will add a route to the system.
  178. // Equivalent to: `ip route replace $route`
  179. func RouteReplace(route *Route) error {
  180. return pkgHandle.RouteReplace(route)
  181. }
  182. // RouteReplace will add a route to the system.
  183. // Equivalent to: `ip route replace $route`
  184. func (h *Handle) RouteReplace(route *Route) error {
  185. flags := syscall.NLM_F_CREATE | syscall.NLM_F_REPLACE | syscall.NLM_F_ACK
  186. req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags)
  187. return h.routeHandle(route, req, nl.NewRtMsg())
  188. }
  189. // RouteDel will delete a route from the system.
  190. // Equivalent to: `ip route del $route`
  191. func RouteDel(route *Route) error {
  192. return pkgHandle.RouteDel(route)
  193. }
  194. // RouteDel will delete a route from the system.
  195. // Equivalent to: `ip route del $route`
  196. func (h *Handle) RouteDel(route *Route) error {
  197. req := h.newNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK)
  198. return h.routeHandle(route, req, nl.NewRtDelMsg())
  199. }
  200. func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
  201. if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
  202. return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
  203. }
  204. family := -1
  205. var rtAttrs []*nl.RtAttr
  206. if route.Dst != nil && route.Dst.IP != nil {
  207. dstLen, _ := route.Dst.Mask.Size()
  208. msg.Dst_len = uint8(dstLen)
  209. dstFamily := nl.GetIPFamily(route.Dst.IP)
  210. family = dstFamily
  211. var dstData []byte
  212. if dstFamily == FAMILY_V4 {
  213. dstData = route.Dst.IP.To4()
  214. } else {
  215. dstData = route.Dst.IP.To16()
  216. }
  217. rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
  218. } else if route.MPLSDst != nil {
  219. family = nl.FAMILY_MPLS
  220. msg.Dst_len = uint8(20)
  221. msg.Type = syscall.RTN_UNICAST
  222. rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst)))
  223. }
  224. if route.NewDst != nil {
  225. if family != -1 && family != route.NewDst.Family() {
  226. return fmt.Errorf("new destination and destination are not the same address family")
  227. }
  228. buf, err := route.NewDst.Encode()
  229. if err != nil {
  230. return err
  231. }
  232. rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_NEWDST, buf))
  233. }
  234. if route.Encap != nil {
  235. buf := make([]byte, 2)
  236. native.PutUint16(buf, uint16(route.Encap.Type()))
  237. rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf))
  238. buf, err := route.Encap.Encode()
  239. if err != nil {
  240. return err
  241. }
  242. rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP, buf))
  243. }
  244. if route.Src != nil {
  245. srcFamily := nl.GetIPFamily(route.Src)
  246. if family != -1 && family != srcFamily {
  247. return fmt.Errorf("source and destination ip are not the same IP family")
  248. }
  249. family = srcFamily
  250. var srcData []byte
  251. if srcFamily == FAMILY_V4 {
  252. srcData = route.Src.To4()
  253. } else {
  254. srcData = route.Src.To16()
  255. }
  256. // The commonly used src ip for routes is actually PREFSRC
  257. rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PREFSRC, srcData))
  258. }
  259. if route.Gw != nil {
  260. gwFamily := nl.GetIPFamily(route.Gw)
  261. if family != -1 && family != gwFamily {
  262. return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
  263. }
  264. family = gwFamily
  265. var gwData []byte
  266. if gwFamily == FAMILY_V4 {
  267. gwData = route.Gw.To4()
  268. } else {
  269. gwData = route.Gw.To16()
  270. }
  271. rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
  272. }
  273. if len(route.MultiPath) > 0 {
  274. buf := []byte{}
  275. for _, nh := range route.MultiPath {
  276. rtnh := &nl.RtNexthop{
  277. RtNexthop: syscall.RtNexthop{
  278. Hops: uint8(nh.Hops),
  279. Ifindex: int32(nh.LinkIndex),
  280. Flags: uint8(nh.Flags),
  281. },
  282. }
  283. children := []nl.NetlinkRequestData{}
  284. if nh.Gw != nil {
  285. gwFamily := nl.GetIPFamily(nh.Gw)
  286. if family != -1 && family != gwFamily {
  287. return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
  288. }
  289. if gwFamily == FAMILY_V4 {
  290. children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To4())))
  291. } else {
  292. children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16())))
  293. }
  294. }
  295. if nh.NewDst != nil {
  296. if family != -1 && family != nh.NewDst.Family() {
  297. return fmt.Errorf("new destination and destination are not the same address family")
  298. }
  299. buf, err := nh.NewDst.Encode()
  300. if err != nil {
  301. return err
  302. }
  303. children = append(children, nl.NewRtAttr(nl.RTA_NEWDST, buf))
  304. }
  305. if nh.Encap != nil {
  306. buf := make([]byte, 2)
  307. native.PutUint16(buf, uint16(nh.Encap.Type()))
  308. rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf))
  309. buf, err := nh.Encap.Encode()
  310. if err != nil {
  311. return err
  312. }
  313. children = append(children, nl.NewRtAttr(nl.RTA_ENCAP, buf))
  314. }
  315. rtnh.Children = children
  316. buf = append(buf, rtnh.Serialize()...)
  317. }
  318. rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_MULTIPATH, buf))
  319. }
  320. if route.Table > 0 {
  321. if route.Table >= 256 {
  322. msg.Table = syscall.RT_TABLE_UNSPEC
  323. b := make([]byte, 4)
  324. native.PutUint32(b, uint32(route.Table))
  325. rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_TABLE, b))
  326. } else {
  327. msg.Table = uint8(route.Table)
  328. }
  329. }
  330. if route.Priority > 0 {
  331. b := make([]byte, 4)
  332. native.PutUint32(b, uint32(route.Priority))
  333. rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PRIORITY, b))
  334. }
  335. if route.Tos > 0 {
  336. msg.Tos = uint8(route.Tos)
  337. }
  338. if route.Protocol > 0 {
  339. msg.Protocol = uint8(route.Protocol)
  340. }
  341. if route.Type > 0 {
  342. msg.Type = uint8(route.Type)
  343. }
  344. msg.Flags = uint32(route.Flags)
  345. msg.Scope = uint8(route.Scope)
  346. msg.Family = uint8(family)
  347. req.AddData(msg)
  348. for _, attr := range rtAttrs {
  349. req.AddData(attr)
  350. }
  351. var (
  352. b = make([]byte, 4)
  353. native = nl.NativeEndian()
  354. )
  355. native.PutUint32(b, uint32(route.LinkIndex))
  356. req.AddData(nl.NewRtAttr(syscall.RTA_OIF, b))
  357. _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
  358. return err
  359. }
  360. // RouteList gets a list of routes in the system.
  361. // Equivalent to: `ip route show`.
  362. // The list can be filtered by link and ip family.
  363. func RouteList(link Link, family int) ([]Route, error) {
  364. return pkgHandle.RouteList(link, family)
  365. }
  366. // RouteList gets a list of routes in the system.
  367. // Equivalent to: `ip route show`.
  368. // The list can be filtered by link and ip family.
  369. func (h *Handle) RouteList(link Link, family int) ([]Route, error) {
  370. var routeFilter *Route
  371. if link != nil {
  372. routeFilter = &Route{
  373. LinkIndex: link.Attrs().Index,
  374. }
  375. }
  376. return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
  377. }
  378. // RouteListFiltered gets a list of routes in the system filtered with specified rules.
  379. // All rules must be defined in RouteFilter struct
  380. func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
  381. return pkgHandle.RouteListFiltered(family, filter, filterMask)
  382. }
  383. // RouteListFiltered gets a list of routes in the system filtered with specified rules.
  384. // All rules must be defined in RouteFilter struct
  385. func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
  386. req := h.newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
  387. infmsg := nl.NewIfInfomsg(family)
  388. req.AddData(infmsg)
  389. msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
  390. if err != nil {
  391. return nil, err
  392. }
  393. var res []Route
  394. for _, m := range msgs {
  395. msg := nl.DeserializeRtMsg(m)
  396. if msg.Flags&syscall.RTM_F_CLONED != 0 {
  397. // Ignore cloned routes
  398. continue
  399. }
  400. if msg.Table != syscall.RT_TABLE_MAIN {
  401. if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
  402. // Ignore non-main tables
  403. continue
  404. }
  405. }
  406. route, err := deserializeRoute(m)
  407. if err != nil {
  408. return nil, err
  409. }
  410. if filter != nil {
  411. switch {
  412. case filterMask&RT_FILTER_TABLE != 0 && filter.Table != syscall.RT_TABLE_UNSPEC && route.Table != filter.Table:
  413. continue
  414. case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
  415. continue
  416. case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
  417. continue
  418. case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
  419. continue
  420. case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
  421. continue
  422. case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
  423. continue
  424. case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
  425. continue
  426. case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
  427. continue
  428. case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
  429. continue
  430. case filterMask&RT_FILTER_DST != 0:
  431. if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
  432. if !ipNetEqual(route.Dst, filter.Dst) {
  433. continue
  434. }
  435. }
  436. }
  437. }
  438. res = append(res, route)
  439. }
  440. return res, nil
  441. }
  442. // deserializeRoute decodes a binary netlink message into a Route struct
  443. func deserializeRoute(m []byte) (Route, error) {
  444. msg := nl.DeserializeRtMsg(m)
  445. attrs, err := nl.ParseRouteAttr(m[msg.Len():])
  446. if err != nil {
  447. return Route{}, err
  448. }
  449. route := Route{
  450. Scope: Scope(msg.Scope),
  451. Protocol: int(msg.Protocol),
  452. Table: int(msg.Table),
  453. Type: int(msg.Type),
  454. Tos: int(msg.Tos),
  455. Flags: int(msg.Flags),
  456. }
  457. native := nl.NativeEndian()
  458. var encap, encapType syscall.NetlinkRouteAttr
  459. for _, attr := range attrs {
  460. switch attr.Attr.Type {
  461. case syscall.RTA_GATEWAY:
  462. route.Gw = net.IP(attr.Value)
  463. case syscall.RTA_PREFSRC:
  464. route.Src = net.IP(attr.Value)
  465. case syscall.RTA_DST:
  466. if msg.Family == nl.FAMILY_MPLS {
  467. stack := nl.DecodeMPLSStack(attr.Value)
  468. if len(stack) == 0 || len(stack) > 1 {
  469. return route, fmt.Errorf("invalid MPLS RTA_DST")
  470. }
  471. route.MPLSDst = &stack[0]
  472. } else {
  473. route.Dst = &net.IPNet{
  474. IP: attr.Value,
  475. Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
  476. }
  477. }
  478. case syscall.RTA_OIF:
  479. route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
  480. case syscall.RTA_IIF:
  481. route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
  482. case syscall.RTA_PRIORITY:
  483. route.Priority = int(native.Uint32(attr.Value[0:4]))
  484. case syscall.RTA_TABLE:
  485. route.Table = int(native.Uint32(attr.Value[0:4]))
  486. case syscall.RTA_MULTIPATH:
  487. parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) {
  488. if len(value) < syscall.SizeofRtNexthop {
  489. return nil, nil, fmt.Errorf("Lack of bytes")
  490. }
  491. nh := nl.DeserializeRtNexthop(value)
  492. if len(value) < int(nh.RtNexthop.Len) {
  493. return nil, nil, fmt.Errorf("Lack of bytes")
  494. }
  495. info := &NexthopInfo{
  496. LinkIndex: int(nh.RtNexthop.Ifindex),
  497. Hops: int(nh.RtNexthop.Hops),
  498. Flags: int(nh.RtNexthop.Flags),
  499. }
  500. attrs, err := nl.ParseRouteAttr(value[syscall.SizeofRtNexthop:int(nh.RtNexthop.Len)])
  501. if err != nil {
  502. return nil, nil, err
  503. }
  504. var encap, encapType syscall.NetlinkRouteAttr
  505. for _, attr := range attrs {
  506. switch attr.Attr.Type {
  507. case syscall.RTA_GATEWAY:
  508. info.Gw = net.IP(attr.Value)
  509. case nl.RTA_NEWDST:
  510. var d Destination
  511. switch msg.Family {
  512. case nl.FAMILY_MPLS:
  513. d = &MPLSDestination{}
  514. }
  515. if err := d.Decode(attr.Value); err != nil {
  516. return nil, nil, err
  517. }
  518. info.NewDst = d
  519. case nl.RTA_ENCAP_TYPE:
  520. encapType = attr
  521. case nl.RTA_ENCAP:
  522. encap = attr
  523. }
  524. }
  525. if len(encap.Value) != 0 && len(encapType.Value) != 0 {
  526. typ := int(native.Uint16(encapType.Value[0:2]))
  527. var e Encap
  528. switch typ {
  529. case nl.LWTUNNEL_ENCAP_MPLS:
  530. e = &MPLSEncap{}
  531. if err := e.Decode(encap.Value); err != nil {
  532. return nil, nil, err
  533. }
  534. }
  535. info.Encap = e
  536. }
  537. return info, value[int(nh.RtNexthop.Len):], nil
  538. }
  539. rest := attr.Value
  540. for len(rest) > 0 {
  541. info, buf, err := parseRtNexthop(rest)
  542. if err != nil {
  543. return route, err
  544. }
  545. route.MultiPath = append(route.MultiPath, info)
  546. rest = buf
  547. }
  548. case nl.RTA_NEWDST:
  549. var d Destination
  550. switch msg.Family {
  551. case nl.FAMILY_MPLS:
  552. d = &MPLSDestination{}
  553. }
  554. if err := d.Decode(attr.Value); err != nil {
  555. return route, err
  556. }
  557. route.NewDst = d
  558. case nl.RTA_ENCAP_TYPE:
  559. encapType = attr
  560. case nl.RTA_ENCAP:
  561. encap = attr
  562. }
  563. }
  564. if len(encap.Value) != 0 && len(encapType.Value) != 0 {
  565. typ := int(native.Uint16(encapType.Value[0:2]))
  566. var e Encap
  567. switch typ {
  568. case nl.LWTUNNEL_ENCAP_MPLS:
  569. e = &MPLSEncap{}
  570. if err := e.Decode(encap.Value); err != nil {
  571. return route, err
  572. }
  573. }
  574. route.Encap = e
  575. }
  576. return route, nil
  577. }
  578. // RouteGet gets a route to a specific destination from the host system.
  579. // Equivalent to: 'ip route get'.
  580. func RouteGet(destination net.IP) ([]Route, error) {
  581. return pkgHandle.RouteGet(destination)
  582. }
  583. // RouteGet gets a route to a specific destination from the host system.
  584. // Equivalent to: 'ip route get'.
  585. func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
  586. req := h.newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_REQUEST)
  587. family := nl.GetIPFamily(destination)
  588. var destinationData []byte
  589. var bitlen uint8
  590. if family == FAMILY_V4 {
  591. destinationData = destination.To4()
  592. bitlen = 32
  593. } else {
  594. destinationData = destination.To16()
  595. bitlen = 128
  596. }
  597. msg := &nl.RtMsg{}
  598. msg.Family = uint8(family)
  599. msg.Dst_len = bitlen
  600. req.AddData(msg)
  601. rtaDst := nl.NewRtAttr(syscall.RTA_DST, destinationData)
  602. req.AddData(rtaDst)
  603. msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
  604. if err != nil {
  605. return nil, err
  606. }
  607. var res []Route
  608. for _, m := range msgs {
  609. route, err := deserializeRoute(m)
  610. if err != nil {
  611. return nil, err
  612. }
  613. res = append(res, route)
  614. }
  615. return res, nil
  616. }
  617. // RouteSubscribe takes a chan down which notifications will be sent
  618. // when routes are added or deleted. Close the 'done' chan to stop subscription.
  619. func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
  620. return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil)
  621. }
  622. // RouteSubscribeAt works like RouteSubscribe plus it allows the caller
  623. // to choose the network namespace in which to subscribe (ns).
  624. func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
  625. return routeSubscribeAt(ns, netns.None(), ch, done, nil)
  626. }
  627. // RouteSubscribeOptions contains a set of options to use with
  628. // RouteSubscribeWithOptions.
  629. type RouteSubscribeOptions struct {
  630. Namespace *netns.NsHandle
  631. ErrorCallback func(error)
  632. }
  633. // RouteSubscribeWithOptions work like RouteSubscribe but enable to
  634. // provide additional options to modify the behavior. Currently, the
  635. // namespace can be provided as well as an error callback.
  636. func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, options RouteSubscribeOptions) error {
  637. if options.Namespace == nil {
  638. none := netns.None()
  639. options.Namespace = &none
  640. }
  641. return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback)
  642. }
  643. func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error)) error {
  644. s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
  645. if err != nil {
  646. return err
  647. }
  648. if done != nil {
  649. go func() {
  650. <-done
  651. s.Close()
  652. }()
  653. }
  654. go func() {
  655. defer close(ch)
  656. for {
  657. msgs, err := s.Receive()
  658. if err != nil {
  659. if cberr != nil {
  660. cberr(err)
  661. }
  662. return
  663. }
  664. for _, m := range msgs {
  665. route, err := deserializeRoute(m.Data)
  666. if err != nil {
  667. if cberr != nil {
  668. cberr(err)
  669. }
  670. return
  671. }
  672. ch <- RouteUpdate{Type: m.Header.Type, Route: route}
  673. }
  674. }
  675. }()
  676. return nil
  677. }