netlink_linux.go 16 KB

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