route_linux.go 22 KB

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