netlink_linux.go 14 KB

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