route_linux.go 28 KB

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