netlink_linux.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. // +build amd64
  2. package netlink
  3. import (
  4. "encoding/binary"
  5. "fmt"
  6. "net"
  7. "syscall"
  8. "unsafe"
  9. )
  10. var nextSeqNr int
  11. func nativeEndian() binary.ByteOrder {
  12. var x uint32 = 0x01020304
  13. if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
  14. return binary.BigEndian
  15. }
  16. return binary.LittleEndian
  17. }
  18. func getSeq() int {
  19. nextSeqNr = nextSeqNr + 1
  20. return nextSeqNr
  21. }
  22. func getIpFamily(ip net.IP) int {
  23. if len(ip) <= net.IPv4len {
  24. return syscall.AF_INET
  25. }
  26. if ip.To4() != nil {
  27. return syscall.AF_INET
  28. }
  29. return syscall.AF_INET6
  30. }
  31. type NetlinkRequestData interface {
  32. ToWireFormat() []byte
  33. }
  34. type IfInfomsg struct {
  35. syscall.IfInfomsg
  36. }
  37. func newIfInfomsg(family int) *IfInfomsg {
  38. msg := &IfInfomsg{}
  39. msg.Family = uint8(family)
  40. msg.Type = uint16(0)
  41. msg.Index = int32(0)
  42. msg.Flags = uint32(0)
  43. msg.Change = uint32(0)
  44. return msg
  45. }
  46. func (msg *IfInfomsg) ToWireFormat() []byte {
  47. native := nativeEndian()
  48. len := syscall.SizeofIfInfomsg
  49. b := make([]byte, len)
  50. b[0] = msg.Family
  51. b[1] = 0
  52. native.PutUint16(b[2:4], msg.Type)
  53. native.PutUint32(b[4:8], uint32(msg.Index))
  54. native.PutUint32(b[8:12], msg.Flags)
  55. native.PutUint32(b[12:16], msg.Change)
  56. return b
  57. }
  58. type IfAddrmsg struct {
  59. syscall.IfAddrmsg
  60. }
  61. func newIfAddrmsg(family int) *IfAddrmsg {
  62. msg := &IfAddrmsg{}
  63. msg.Family = uint8(family)
  64. msg.Prefixlen = uint8(0)
  65. msg.Flags = uint8(0)
  66. msg.Scope = uint8(0)
  67. msg.Index = uint32(0)
  68. return msg
  69. }
  70. func (msg *IfAddrmsg) ToWireFormat() []byte {
  71. native := nativeEndian()
  72. len := syscall.SizeofIfAddrmsg
  73. b := make([]byte, len)
  74. b[0] = msg.Family
  75. b[1] = msg.Prefixlen
  76. b[2] = msg.Flags
  77. b[3] = msg.Scope
  78. native.PutUint32(b[4:8], msg.Index)
  79. return b
  80. }
  81. type RtMsg struct {
  82. syscall.RtMsg
  83. }
  84. func newRtMsg(family int) *RtMsg {
  85. msg := &RtMsg{}
  86. msg.Family = uint8(family)
  87. msg.Table = syscall.RT_TABLE_MAIN
  88. msg.Scope = syscall.RT_SCOPE_UNIVERSE
  89. msg.Protocol = syscall.RTPROT_BOOT
  90. msg.Type = syscall.RTN_UNICAST
  91. return msg
  92. }
  93. func (msg *RtMsg) ToWireFormat() []byte {
  94. native := nativeEndian()
  95. len := syscall.SizeofRtMsg
  96. b := make([]byte, len)
  97. b[0] = msg.Family
  98. b[1] = msg.Dst_len
  99. b[2] = msg.Src_len
  100. b[3] = msg.Tos
  101. b[4] = msg.Table
  102. b[5] = msg.Protocol
  103. b[6] = msg.Scope
  104. b[7] = msg.Type
  105. native.PutUint32(b[8:12], msg.Flags)
  106. return b
  107. }
  108. func rtaAlignOf(attrlen int) int {
  109. return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
  110. }
  111. type RtAttr struct {
  112. syscall.RtAttr
  113. Data []byte
  114. }
  115. func newRtAttr(attrType int, data []byte) *RtAttr {
  116. attr := &RtAttr{}
  117. attr.Type = uint16(attrType)
  118. attr.Data = data
  119. return attr
  120. }
  121. func (attr *RtAttr) ToWireFormat() []byte {
  122. native := nativeEndian()
  123. len := syscall.SizeofRtAttr + len(attr.Data)
  124. b := make([]byte, rtaAlignOf(len))
  125. native.PutUint16(b[0:2], uint16(len))
  126. native.PutUint16(b[2:4], attr.Type)
  127. for i, d := range attr.Data {
  128. b[4+i] = d
  129. }
  130. return b
  131. }
  132. type NetlinkRequest struct {
  133. syscall.NlMsghdr
  134. Data []NetlinkRequestData
  135. }
  136. func (rr *NetlinkRequest) ToWireFormat() []byte {
  137. native := nativeEndian()
  138. length := rr.Len
  139. dataBytes := make([][]byte, len(rr.Data))
  140. for i, data := range rr.Data {
  141. dataBytes[i] = data.ToWireFormat()
  142. length = length + uint32(len(dataBytes[i]))
  143. }
  144. b := make([]byte, length)
  145. native.PutUint32(b[0:4], length)
  146. native.PutUint16(b[4:6], rr.Type)
  147. native.PutUint16(b[6:8], rr.Flags)
  148. native.PutUint32(b[8:12], rr.Seq)
  149. native.PutUint32(b[12:16], rr.Pid)
  150. i := 16
  151. for _, data := range dataBytes {
  152. for _, dataByte := range data {
  153. b[i] = dataByte
  154. i = i + 1
  155. }
  156. }
  157. return b
  158. }
  159. func (rr *NetlinkRequest) AddData(data NetlinkRequestData) {
  160. rr.Data = append(rr.Data, data)
  161. }
  162. func newNetlinkRequest(proto, flags int) *NetlinkRequest {
  163. rr := &NetlinkRequest{}
  164. rr.Len = uint32(syscall.NLMSG_HDRLEN)
  165. rr.Type = uint16(proto)
  166. rr.Flags = syscall.NLM_F_REQUEST | uint16(flags)
  167. rr.Seq = uint32(getSeq())
  168. return rr
  169. }
  170. type NetlinkSocket struct {
  171. fd int
  172. lsa syscall.SockaddrNetlink
  173. }
  174. func getNetlinkSocket() (*NetlinkSocket, error) {
  175. fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_ROUTE)
  176. if err != nil {
  177. return nil, err
  178. }
  179. s := &NetlinkSocket{
  180. fd: fd,
  181. }
  182. s.lsa.Family = syscall.AF_NETLINK
  183. if err := syscall.Bind(fd, &s.lsa); err != nil {
  184. syscall.Close(fd)
  185. return nil, err
  186. }
  187. return s, nil
  188. }
  189. func (s *NetlinkSocket) Close() {
  190. syscall.Close(s.fd)
  191. }
  192. func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
  193. if err := syscall.Sendto(s.fd, request.ToWireFormat(), 0, &s.lsa); err != nil {
  194. return err
  195. }
  196. return nil
  197. }
  198. func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
  199. rb := make([]byte, syscall.Getpagesize())
  200. nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
  201. if err != nil {
  202. return nil, err
  203. }
  204. if nr < syscall.NLMSG_HDRLEN {
  205. return nil, fmt.Errorf("Got short response from netlink")
  206. }
  207. rb = rb[:nr]
  208. return syscall.ParseNetlinkMessage(rb)
  209. }
  210. func (s *NetlinkSocket) GetPid() (uint32, error) {
  211. lsa, err := syscall.Getsockname(s.fd)
  212. if err != nil {
  213. return 0, err
  214. }
  215. switch v := lsa.(type) {
  216. case *syscall.SockaddrNetlink:
  217. return v.Pid, nil
  218. }
  219. return 0, fmt.Errorf("Wrong socket type")
  220. }
  221. func (s *NetlinkSocket) HandleAck(seq uint32) error {
  222. native := nativeEndian()
  223. pid, err := s.GetPid()
  224. if err != nil {
  225. return err
  226. }
  227. done:
  228. for {
  229. msgs, err := s.Receive()
  230. if err != nil {
  231. return err
  232. }
  233. for _, m := range msgs {
  234. if m.Header.Seq != seq {
  235. return fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, seq)
  236. }
  237. if m.Header.Pid != pid {
  238. return fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
  239. }
  240. if m.Header.Type == syscall.NLMSG_DONE {
  241. break done
  242. }
  243. if m.Header.Type == syscall.NLMSG_ERROR {
  244. error := int32(native.Uint32(m.Data[0:4]))
  245. if error == 0 {
  246. break done
  247. }
  248. return syscall.Errno(-error)
  249. }
  250. }
  251. }
  252. return nil
  253. }
  254. // Add a new default gateway. Identical to:
  255. // ip route add default via $ip
  256. func AddDefaultGw(ip net.IP) error {
  257. s, err := getNetlinkSocket()
  258. if err != nil {
  259. return err
  260. }
  261. defer s.Close()
  262. family := getIpFamily(ip)
  263. wb := newNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
  264. msg := newRtMsg(family)
  265. wb.AddData(msg)
  266. var ipData []byte
  267. if family == syscall.AF_INET {
  268. ipData = ip.To4()
  269. } else {
  270. ipData = ip.To16()
  271. }
  272. gateway := newRtAttr(syscall.RTA_GATEWAY, ipData)
  273. wb.AddData(gateway)
  274. if err := s.Send(wb); err != nil {
  275. return err
  276. }
  277. return s.HandleAck(wb.Seq)
  278. }
  279. // Bring up a particular network interface
  280. func NetworkLinkUp(iface *net.Interface) error {
  281. s, err := getNetlinkSocket()
  282. if err != nil {
  283. return err
  284. }
  285. defer s.Close()
  286. wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
  287. msg := newIfInfomsg(syscall.AF_UNSPEC)
  288. msg.Change = syscall.IFF_UP
  289. msg.Flags = syscall.IFF_UP
  290. msg.Index = int32(iface.Index)
  291. wb.AddData(msg)
  292. if err := s.Send(wb); err != nil {
  293. return err
  294. }
  295. return s.HandleAck(wb.Seq)
  296. }
  297. func NetworkSetMTU(iface *net.Interface, mtu int) error {
  298. s, err := getNetlinkSocket()
  299. if err != nil {
  300. return err
  301. }
  302. defer s.Close()
  303. wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
  304. msg := newIfInfomsg(syscall.AF_UNSPEC)
  305. msg.Type = syscall.RTM_SETLINK
  306. msg.Flags = syscall.NLM_F_REQUEST
  307. msg.Index = int32(iface.Index)
  308. msg.Change = 0xFFFFFFFF
  309. wb.AddData(msg)
  310. var (
  311. b = make([]byte, 4)
  312. native = nativeEndian()
  313. )
  314. native.PutUint32(b, uint32(mtu))
  315. data := newRtAttr(syscall.IFLA_MTU, b)
  316. wb.AddData(data)
  317. if err := s.Send(wb); err != nil {
  318. return err
  319. }
  320. return s.HandleAck(wb.Seq)
  321. }
  322. // same as ip link set $name master $master
  323. func NetworkSetMaster(iface, master *net.Interface) error {
  324. s, err := getNetlinkSocket()
  325. if err != nil {
  326. return err
  327. }
  328. defer s.Close()
  329. wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
  330. msg := newIfInfomsg(syscall.AF_UNSPEC)
  331. msg.Type = syscall.RTM_SETLINK
  332. msg.Flags = syscall.NLM_F_REQUEST
  333. msg.Index = int32(iface.Index)
  334. msg.Change = 0xFFFFFFFF
  335. wb.AddData(msg)
  336. var (
  337. b = make([]byte, 4)
  338. native = nativeEndian()
  339. )
  340. native.PutUint32(b, uint32(master.Index))
  341. data := newRtAttr(syscall.IFLA_MASTER, b)
  342. wb.AddData(data)
  343. if err := s.Send(wb); err != nil {
  344. return err
  345. }
  346. return s.HandleAck(wb.Seq)
  347. }
  348. // Add an Ip address to an interface. This is identical to:
  349. // ip addr add $ip/$ipNet dev $iface
  350. func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
  351. s, err := getNetlinkSocket()
  352. if err != nil {
  353. return err
  354. }
  355. defer s.Close()
  356. family := getIpFamily(ip)
  357. wb := newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
  358. msg := newIfAddrmsg(family)
  359. msg.Index = uint32(iface.Index)
  360. prefixLen, _ := ipNet.Mask.Size()
  361. msg.Prefixlen = uint8(prefixLen)
  362. wb.AddData(msg)
  363. var ipData []byte
  364. if family == syscall.AF_INET {
  365. ipData = ip.To4()
  366. } else {
  367. ipData = ip.To16()
  368. }
  369. localData := newRtAttr(syscall.IFA_LOCAL, ipData)
  370. wb.AddData(localData)
  371. addrData := newRtAttr(syscall.IFA_ADDRESS, ipData)
  372. wb.AddData(addrData)
  373. if err := s.Send(wb); err != nil {
  374. return err
  375. }
  376. return s.HandleAck(wb.Seq)
  377. }
  378. func zeroTerminated(s string) []byte {
  379. bytes := make([]byte, len(s)+1)
  380. for i := 0; i < len(s); i++ {
  381. bytes[i] = s[i]
  382. }
  383. bytes[len(s)] = 0
  384. return bytes
  385. }
  386. func nonZeroTerminated(s string) []byte {
  387. bytes := make([]byte, len(s))
  388. for i := 0; i < len(s); i++ {
  389. bytes[i] = s[i]
  390. }
  391. return bytes
  392. }
  393. // Add a new network link of a specified type. This is identical to
  394. // running: ip add link $name type $linkType
  395. func NetworkLinkAdd(name string, linkType string) error {
  396. s, err := getNetlinkSocket()
  397. if err != nil {
  398. return err
  399. }
  400. defer s.Close()
  401. wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
  402. msg := newIfInfomsg(syscall.AF_UNSPEC)
  403. wb.AddData(msg)
  404. nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name))
  405. wb.AddData(nameData)
  406. IFLA_INFO_KIND := 1
  407. kindData := newRtAttr(IFLA_INFO_KIND, nonZeroTerminated(linkType))
  408. infoData := newRtAttr(syscall.IFLA_LINKINFO, kindData.ToWireFormat())
  409. wb.AddData(infoData)
  410. if err := s.Send(wb); err != nil {
  411. return err
  412. }
  413. return s.HandleAck(wb.Seq)
  414. }
  415. // Returns an array of IPNet for all the currently routed subnets on ipv4
  416. // This is similar to the first column of "ip route" output
  417. func NetworkGetRoutes() ([]Route, error) {
  418. native := nativeEndian()
  419. s, err := getNetlinkSocket()
  420. if err != nil {
  421. return nil, err
  422. }
  423. defer s.Close()
  424. wb := newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
  425. msg := newIfInfomsg(syscall.AF_UNSPEC)
  426. wb.AddData(msg)
  427. if err := s.Send(wb); err != nil {
  428. return nil, err
  429. }
  430. pid, err := s.GetPid()
  431. if err != nil {
  432. return nil, err
  433. }
  434. res := make([]Route, 0)
  435. done:
  436. for {
  437. msgs, err := s.Receive()
  438. if err != nil {
  439. return nil, err
  440. }
  441. for _, m := range msgs {
  442. if m.Header.Seq != wb.Seq {
  443. return nil, fmt.Errorf("Wrong Seq nr %d, expected 1", m.Header.Seq)
  444. }
  445. if m.Header.Pid != pid {
  446. return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
  447. }
  448. if m.Header.Type == syscall.NLMSG_DONE {
  449. break done
  450. }
  451. if m.Header.Type == syscall.NLMSG_ERROR {
  452. error := int32(native.Uint32(m.Data[0:4]))
  453. if error == 0 {
  454. break done
  455. }
  456. return nil, syscall.Errno(-error)
  457. }
  458. if m.Header.Type != syscall.RTM_NEWROUTE {
  459. continue
  460. }
  461. var r Route
  462. msg := (*RtMsg)(unsafe.Pointer(&m.Data[0:syscall.SizeofRtMsg][0]))
  463. if msg.Flags&syscall.RTM_F_CLONED != 0 {
  464. // Ignore cloned routes
  465. continue
  466. }
  467. if msg.Table != syscall.RT_TABLE_MAIN {
  468. // Ignore non-main tables
  469. continue
  470. }
  471. if msg.Family != syscall.AF_INET {
  472. // Ignore non-ipv4 routes
  473. continue
  474. }
  475. if msg.Dst_len == 0 {
  476. // Default routes
  477. r.Default = true
  478. }
  479. attrs, err := syscall.ParseNetlinkRouteAttr(&m)
  480. if err != nil {
  481. return nil, err
  482. }
  483. for _, attr := range attrs {
  484. switch attr.Attr.Type {
  485. case syscall.RTA_DST:
  486. ip := attr.Value
  487. r.IPNet = &net.IPNet{
  488. IP: ip,
  489. Mask: net.CIDRMask(int(msg.Dst_len), 8*len(ip)),
  490. }
  491. case syscall.RTA_OIF:
  492. index := int(native.Uint32(attr.Value[0:4]))
  493. r.Iface, _ = net.InterfaceByIndex(index)
  494. }
  495. }
  496. if r.Default || r.IPNet != nil {
  497. res = append(res, r)
  498. }
  499. }
  500. }
  501. return res, nil
  502. }