nl_linux.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. // Package nl has low level primitives for making Netlink calls.
  2. package nl
  3. import (
  4. "bytes"
  5. "encoding/binary"
  6. "fmt"
  7. "net"
  8. "runtime"
  9. "sync"
  10. "sync/atomic"
  11. "syscall"
  12. "unsafe"
  13. "github.com/vishvananda/netns"
  14. "golang.org/x/sys/unix"
  15. )
  16. const (
  17. // Family type definitions
  18. FAMILY_ALL = unix.AF_UNSPEC
  19. FAMILY_V4 = unix.AF_INET
  20. FAMILY_V6 = unix.AF_INET6
  21. FAMILY_MPLS = AF_MPLS
  22. )
  23. // SupportedNlFamilies contains the list of netlink families this netlink package supports
  24. var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETLINK_NETFILTER}
  25. var nextSeqNr uint32
  26. // GetIPFamily returns the family type of a net.IP.
  27. func GetIPFamily(ip net.IP) int {
  28. if len(ip) <= net.IPv4len {
  29. return FAMILY_V4
  30. }
  31. if ip.To4() != nil {
  32. return FAMILY_V4
  33. }
  34. return FAMILY_V6
  35. }
  36. var nativeEndian binary.ByteOrder
  37. // Get native endianness for the system
  38. func NativeEndian() binary.ByteOrder {
  39. if nativeEndian == nil {
  40. var x uint32 = 0x01020304
  41. if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
  42. nativeEndian = binary.BigEndian
  43. } else {
  44. nativeEndian = binary.LittleEndian
  45. }
  46. }
  47. return nativeEndian
  48. }
  49. // Byte swap a 16 bit value if we aren't big endian
  50. func Swap16(i uint16) uint16 {
  51. if NativeEndian() == binary.BigEndian {
  52. return i
  53. }
  54. return (i&0xff00)>>8 | (i&0xff)<<8
  55. }
  56. // Byte swap a 32 bit value if aren't big endian
  57. func Swap32(i uint32) uint32 {
  58. if NativeEndian() == binary.BigEndian {
  59. return i
  60. }
  61. return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24
  62. }
  63. type NetlinkRequestData interface {
  64. Len() int
  65. Serialize() []byte
  66. }
  67. // IfInfomsg is related to links, but it is used for list requests as well
  68. type IfInfomsg struct {
  69. unix.IfInfomsg
  70. }
  71. // Create an IfInfomsg with family specified
  72. func NewIfInfomsg(family int) *IfInfomsg {
  73. return &IfInfomsg{
  74. IfInfomsg: unix.IfInfomsg{
  75. Family: uint8(family),
  76. },
  77. }
  78. }
  79. func DeserializeIfInfomsg(b []byte) *IfInfomsg {
  80. return (*IfInfomsg)(unsafe.Pointer(&b[0:unix.SizeofIfInfomsg][0]))
  81. }
  82. func (msg *IfInfomsg) Serialize() []byte {
  83. return (*(*[unix.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
  84. }
  85. func (msg *IfInfomsg) Len() int {
  86. return unix.SizeofIfInfomsg
  87. }
  88. func (msg *IfInfomsg) EncapType() string {
  89. switch msg.Type {
  90. case 0:
  91. return "generic"
  92. case unix.ARPHRD_ETHER:
  93. return "ether"
  94. case unix.ARPHRD_EETHER:
  95. return "eether"
  96. case unix.ARPHRD_AX25:
  97. return "ax25"
  98. case unix.ARPHRD_PRONET:
  99. return "pronet"
  100. case unix.ARPHRD_CHAOS:
  101. return "chaos"
  102. case unix.ARPHRD_IEEE802:
  103. return "ieee802"
  104. case unix.ARPHRD_ARCNET:
  105. return "arcnet"
  106. case unix.ARPHRD_APPLETLK:
  107. return "atalk"
  108. case unix.ARPHRD_DLCI:
  109. return "dlci"
  110. case unix.ARPHRD_ATM:
  111. return "atm"
  112. case unix.ARPHRD_METRICOM:
  113. return "metricom"
  114. case unix.ARPHRD_IEEE1394:
  115. return "ieee1394"
  116. case unix.ARPHRD_INFINIBAND:
  117. return "infiniband"
  118. case unix.ARPHRD_SLIP:
  119. return "slip"
  120. case unix.ARPHRD_CSLIP:
  121. return "cslip"
  122. case unix.ARPHRD_SLIP6:
  123. return "slip6"
  124. case unix.ARPHRD_CSLIP6:
  125. return "cslip6"
  126. case unix.ARPHRD_RSRVD:
  127. return "rsrvd"
  128. case unix.ARPHRD_ADAPT:
  129. return "adapt"
  130. case unix.ARPHRD_ROSE:
  131. return "rose"
  132. case unix.ARPHRD_X25:
  133. return "x25"
  134. case unix.ARPHRD_HWX25:
  135. return "hwx25"
  136. case unix.ARPHRD_PPP:
  137. return "ppp"
  138. case unix.ARPHRD_HDLC:
  139. return "hdlc"
  140. case unix.ARPHRD_LAPB:
  141. return "lapb"
  142. case unix.ARPHRD_DDCMP:
  143. return "ddcmp"
  144. case unix.ARPHRD_RAWHDLC:
  145. return "rawhdlc"
  146. case unix.ARPHRD_TUNNEL:
  147. return "ipip"
  148. case unix.ARPHRD_TUNNEL6:
  149. return "tunnel6"
  150. case unix.ARPHRD_FRAD:
  151. return "frad"
  152. case unix.ARPHRD_SKIP:
  153. return "skip"
  154. case unix.ARPHRD_LOOPBACK:
  155. return "loopback"
  156. case unix.ARPHRD_LOCALTLK:
  157. return "ltalk"
  158. case unix.ARPHRD_FDDI:
  159. return "fddi"
  160. case unix.ARPHRD_BIF:
  161. return "bif"
  162. case unix.ARPHRD_SIT:
  163. return "sit"
  164. case unix.ARPHRD_IPDDP:
  165. return "ip/ddp"
  166. case unix.ARPHRD_IPGRE:
  167. return "gre"
  168. case unix.ARPHRD_PIMREG:
  169. return "pimreg"
  170. case unix.ARPHRD_HIPPI:
  171. return "hippi"
  172. case unix.ARPHRD_ASH:
  173. return "ash"
  174. case unix.ARPHRD_ECONET:
  175. return "econet"
  176. case unix.ARPHRD_IRDA:
  177. return "irda"
  178. case unix.ARPHRD_FCPP:
  179. return "fcpp"
  180. case unix.ARPHRD_FCAL:
  181. return "fcal"
  182. case unix.ARPHRD_FCPL:
  183. return "fcpl"
  184. case unix.ARPHRD_FCFABRIC:
  185. return "fcfb0"
  186. case unix.ARPHRD_FCFABRIC + 1:
  187. return "fcfb1"
  188. case unix.ARPHRD_FCFABRIC + 2:
  189. return "fcfb2"
  190. case unix.ARPHRD_FCFABRIC + 3:
  191. return "fcfb3"
  192. case unix.ARPHRD_FCFABRIC + 4:
  193. return "fcfb4"
  194. case unix.ARPHRD_FCFABRIC + 5:
  195. return "fcfb5"
  196. case unix.ARPHRD_FCFABRIC + 6:
  197. return "fcfb6"
  198. case unix.ARPHRD_FCFABRIC + 7:
  199. return "fcfb7"
  200. case unix.ARPHRD_FCFABRIC + 8:
  201. return "fcfb8"
  202. case unix.ARPHRD_FCFABRIC + 9:
  203. return "fcfb9"
  204. case unix.ARPHRD_FCFABRIC + 10:
  205. return "fcfb10"
  206. case unix.ARPHRD_FCFABRIC + 11:
  207. return "fcfb11"
  208. case unix.ARPHRD_FCFABRIC + 12:
  209. return "fcfb12"
  210. case unix.ARPHRD_IEEE802_TR:
  211. return "tr"
  212. case unix.ARPHRD_IEEE80211:
  213. return "ieee802.11"
  214. case unix.ARPHRD_IEEE80211_PRISM:
  215. return "ieee802.11/prism"
  216. case unix.ARPHRD_IEEE80211_RADIOTAP:
  217. return "ieee802.11/radiotap"
  218. case unix.ARPHRD_IEEE802154:
  219. return "ieee802.15.4"
  220. case 65534:
  221. return "none"
  222. case 65535:
  223. return "void"
  224. }
  225. return fmt.Sprintf("unknown%d", msg.Type)
  226. }
  227. func rtaAlignOf(attrlen int) int {
  228. return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1)
  229. }
  230. func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
  231. msg := NewIfInfomsg(family)
  232. parent.children = append(parent.children, msg)
  233. return msg
  234. }
  235. // Extend RtAttr to handle data and children
  236. type RtAttr struct {
  237. unix.RtAttr
  238. Data []byte
  239. children []NetlinkRequestData
  240. }
  241. // Create a new Extended RtAttr object
  242. func NewRtAttr(attrType int, data []byte) *RtAttr {
  243. return &RtAttr{
  244. RtAttr: unix.RtAttr{
  245. Type: uint16(attrType),
  246. },
  247. children: []NetlinkRequestData{},
  248. Data: data,
  249. }
  250. }
  251. // Create a new RtAttr obj anc add it as a child of an existing object
  252. func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
  253. attr := NewRtAttr(attrType, data)
  254. parent.children = append(parent.children, attr)
  255. return attr
  256. }
  257. // AddChild adds an existing RtAttr as a child.
  258. func (a *RtAttr) AddChild(attr *RtAttr) {
  259. a.children = append(a.children, attr)
  260. }
  261. func (a *RtAttr) Len() int {
  262. if len(a.children) == 0 {
  263. return (unix.SizeofRtAttr + len(a.Data))
  264. }
  265. l := 0
  266. for _, child := range a.children {
  267. l += rtaAlignOf(child.Len())
  268. }
  269. l += unix.SizeofRtAttr
  270. return rtaAlignOf(l + len(a.Data))
  271. }
  272. // Serialize the RtAttr into a byte array
  273. // This can't just unsafe.cast because it must iterate through children.
  274. func (a *RtAttr) Serialize() []byte {
  275. native := NativeEndian()
  276. length := a.Len()
  277. buf := make([]byte, rtaAlignOf(length))
  278. next := 4
  279. if a.Data != nil {
  280. copy(buf[next:], a.Data)
  281. next += rtaAlignOf(len(a.Data))
  282. }
  283. if len(a.children) > 0 {
  284. for _, child := range a.children {
  285. childBuf := child.Serialize()
  286. copy(buf[next:], childBuf)
  287. next += rtaAlignOf(len(childBuf))
  288. }
  289. }
  290. if l := uint16(length); l != 0 {
  291. native.PutUint16(buf[0:2], l)
  292. }
  293. native.PutUint16(buf[2:4], a.Type)
  294. return buf
  295. }
  296. type NetlinkRequest struct {
  297. unix.NlMsghdr
  298. Data []NetlinkRequestData
  299. RawData []byte
  300. Sockets map[int]*SocketHandle
  301. }
  302. // Serialize the Netlink Request into a byte array
  303. func (req *NetlinkRequest) Serialize() []byte {
  304. length := unix.SizeofNlMsghdr
  305. dataBytes := make([][]byte, len(req.Data))
  306. for i, data := range req.Data {
  307. dataBytes[i] = data.Serialize()
  308. length = length + len(dataBytes[i])
  309. }
  310. length += len(req.RawData)
  311. req.Len = uint32(length)
  312. b := make([]byte, length)
  313. hdr := (*(*[unix.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:]
  314. next := unix.SizeofNlMsghdr
  315. copy(b[0:next], hdr)
  316. for _, data := range dataBytes {
  317. for _, dataByte := range data {
  318. b[next] = dataByte
  319. next = next + 1
  320. }
  321. }
  322. // Add the raw data if any
  323. if len(req.RawData) > 0 {
  324. copy(b[next:length], req.RawData)
  325. }
  326. return b
  327. }
  328. func (req *NetlinkRequest) AddData(data NetlinkRequestData) {
  329. if data != nil {
  330. req.Data = append(req.Data, data)
  331. }
  332. }
  333. // AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization
  334. func (req *NetlinkRequest) AddRawData(data []byte) {
  335. if data != nil {
  336. req.RawData = append(req.RawData, data...)
  337. }
  338. }
  339. // Execute the request against a the given sockType.
  340. // Returns a list of netlink messages in serialized format, optionally filtered
  341. // by resType.
  342. func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) {
  343. var (
  344. s *NetlinkSocket
  345. err error
  346. )
  347. if req.Sockets != nil {
  348. if sh, ok := req.Sockets[sockType]; ok {
  349. s = sh.Socket
  350. req.Seq = atomic.AddUint32(&sh.Seq, 1)
  351. }
  352. }
  353. sharedSocket := s != nil
  354. if s == nil {
  355. s, err = getNetlinkSocket(sockType)
  356. if err != nil {
  357. return nil, err
  358. }
  359. defer s.Close()
  360. } else {
  361. s.Lock()
  362. defer s.Unlock()
  363. }
  364. if err := s.Send(req); err != nil {
  365. return nil, err
  366. }
  367. pid, err := s.GetPid()
  368. if err != nil {
  369. return nil, err
  370. }
  371. var res [][]byte
  372. done:
  373. for {
  374. msgs, err := s.Receive()
  375. if err != nil {
  376. return nil, err
  377. }
  378. for _, m := range msgs {
  379. if m.Header.Seq != req.Seq {
  380. if sharedSocket {
  381. continue
  382. }
  383. return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
  384. }
  385. if m.Header.Pid != pid {
  386. return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
  387. }
  388. if m.Header.Type == unix.NLMSG_DONE {
  389. break done
  390. }
  391. if m.Header.Type == unix.NLMSG_ERROR {
  392. native := NativeEndian()
  393. error := int32(native.Uint32(m.Data[0:4]))
  394. if error == 0 {
  395. break done
  396. }
  397. return nil, syscall.Errno(-error)
  398. }
  399. if resType != 0 && m.Header.Type != resType {
  400. continue
  401. }
  402. res = append(res, m.Data)
  403. if m.Header.Flags&unix.NLM_F_MULTI == 0 {
  404. break done
  405. }
  406. }
  407. }
  408. return res, nil
  409. }
  410. // Create a new netlink request from proto and flags
  411. // Note the Len value will be inaccurate once data is added until
  412. // the message is serialized
  413. func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
  414. return &NetlinkRequest{
  415. NlMsghdr: unix.NlMsghdr{
  416. Len: uint32(unix.SizeofNlMsghdr),
  417. Type: uint16(proto),
  418. Flags: unix.NLM_F_REQUEST | uint16(flags),
  419. Seq: atomic.AddUint32(&nextSeqNr, 1),
  420. },
  421. }
  422. }
  423. type NetlinkSocket struct {
  424. fd int32
  425. lsa unix.SockaddrNetlink
  426. sync.Mutex
  427. }
  428. func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
  429. fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC, protocol)
  430. if err != nil {
  431. return nil, err
  432. }
  433. s := &NetlinkSocket{
  434. fd: int32(fd),
  435. }
  436. s.lsa.Family = unix.AF_NETLINK
  437. if err := unix.Bind(fd, &s.lsa); err != nil {
  438. unix.Close(fd)
  439. return nil, err
  440. }
  441. return s, nil
  442. }
  443. // GetNetlinkSocketAt opens a netlink socket in the network namespace newNs
  444. // and positions the thread back into the network namespace specified by curNs,
  445. // when done. If curNs is close, the function derives the current namespace and
  446. // moves back into it when done. If newNs is close, the socket will be opened
  447. // in the current network namespace.
  448. func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSocket, error) {
  449. c, err := executeInNetns(newNs, curNs)
  450. if err != nil {
  451. return nil, err
  452. }
  453. defer c()
  454. return getNetlinkSocket(protocol)
  455. }
  456. // executeInNetns sets execution of the code following this call to the
  457. // network namespace newNs, then moves the thread back to curNs if open,
  458. // otherwise to the current netns at the time the function was invoked
  459. // In case of success, the caller is expected to execute the returned function
  460. // at the end of the code that needs to be executed in the network namespace.
  461. // Example:
  462. // func jobAt(...) error {
  463. // d, err := executeInNetns(...)
  464. // if err != nil { return err}
  465. // defer d()
  466. // < code which needs to be executed in specific netns>
  467. // }
  468. // TODO: his function probably belongs to netns pkg.
  469. func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
  470. var (
  471. err error
  472. moveBack func(netns.NsHandle) error
  473. closeNs func() error
  474. unlockThd func()
  475. )
  476. restore := func() {
  477. // order matters
  478. if moveBack != nil {
  479. moveBack(curNs)
  480. }
  481. if closeNs != nil {
  482. closeNs()
  483. }
  484. if unlockThd != nil {
  485. unlockThd()
  486. }
  487. }
  488. if newNs.IsOpen() {
  489. runtime.LockOSThread()
  490. unlockThd = runtime.UnlockOSThread
  491. if !curNs.IsOpen() {
  492. if curNs, err = netns.Get(); err != nil {
  493. restore()
  494. return nil, fmt.Errorf("could not get current namespace while creating netlink socket: %v", err)
  495. }
  496. closeNs = curNs.Close
  497. }
  498. if err := netns.Set(newNs); err != nil {
  499. restore()
  500. return nil, fmt.Errorf("failed to set into network namespace %d while creating netlink socket: %v", newNs, err)
  501. }
  502. moveBack = netns.Set
  503. }
  504. return restore, nil
  505. }
  506. // Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE)
  507. // and subscribe it to multicast groups passed in variable argument list.
  508. // Returns the netlink socket on which Receive() method can be called
  509. // to retrieve the messages from the kernel.
  510. func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
  511. fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, protocol)
  512. if err != nil {
  513. return nil, err
  514. }
  515. s := &NetlinkSocket{
  516. fd: int32(fd),
  517. }
  518. s.lsa.Family = unix.AF_NETLINK
  519. for _, g := range groups {
  520. s.lsa.Groups |= (1 << (g - 1))
  521. }
  522. if err := unix.Bind(fd, &s.lsa); err != nil {
  523. unix.Close(fd)
  524. return nil, err
  525. }
  526. return s, nil
  527. }
  528. // SubscribeAt works like Subscribe plus let's the caller choose the network
  529. // namespace in which the socket would be opened (newNs). Then control goes back
  530. // to curNs if open, otherwise to the netns at the time this function was called.
  531. func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*NetlinkSocket, error) {
  532. c, err := executeInNetns(newNs, curNs)
  533. if err != nil {
  534. return nil, err
  535. }
  536. defer c()
  537. return Subscribe(protocol, groups...)
  538. }
  539. func (s *NetlinkSocket) Close() {
  540. fd := int(atomic.SwapInt32(&s.fd, -1))
  541. unix.Close(fd)
  542. }
  543. func (s *NetlinkSocket) GetFd() int {
  544. return int(atomic.LoadInt32(&s.fd))
  545. }
  546. func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
  547. fd := int(atomic.LoadInt32(&s.fd))
  548. if fd < 0 {
  549. return fmt.Errorf("Send called on a closed socket")
  550. }
  551. if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
  552. return err
  553. }
  554. return nil
  555. }
  556. func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
  557. fd := int(atomic.LoadInt32(&s.fd))
  558. if fd < 0 {
  559. return nil, fmt.Errorf("Receive called on a closed socket")
  560. }
  561. rb := make([]byte, unix.Getpagesize())
  562. nr, _, err := unix.Recvfrom(fd, rb, 0)
  563. if err != nil {
  564. return nil, err
  565. }
  566. if nr < unix.NLMSG_HDRLEN {
  567. return nil, fmt.Errorf("Got short response from netlink")
  568. }
  569. rb = rb[:nr]
  570. return syscall.ParseNetlinkMessage(rb)
  571. }
  572. // SetSendTimeout allows to set a send timeout on the socket
  573. func (s *NetlinkSocket) SetSendTimeout(timeout *unix.Timeval) error {
  574. // Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine
  575. // remains stuck on a send on a closed fd
  576. return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, timeout)
  577. }
  578. // SetReceiveTimeout allows to set a receive timeout on the socket
  579. func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error {
  580. // Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine
  581. // remains stuck on a recvmsg on a closed fd
  582. return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout)
  583. }
  584. func (s *NetlinkSocket) GetPid() (uint32, error) {
  585. fd := int(atomic.LoadInt32(&s.fd))
  586. lsa, err := unix.Getsockname(fd)
  587. if err != nil {
  588. return 0, err
  589. }
  590. switch v := lsa.(type) {
  591. case *unix.SockaddrNetlink:
  592. return v.Pid, nil
  593. }
  594. return 0, fmt.Errorf("Wrong socket type")
  595. }
  596. func ZeroTerminated(s string) []byte {
  597. bytes := make([]byte, len(s)+1)
  598. for i := 0; i < len(s); i++ {
  599. bytes[i] = s[i]
  600. }
  601. bytes[len(s)] = 0
  602. return bytes
  603. }
  604. func NonZeroTerminated(s string) []byte {
  605. bytes := make([]byte, len(s))
  606. for i := 0; i < len(s); i++ {
  607. bytes[i] = s[i]
  608. }
  609. return bytes
  610. }
  611. func BytesToString(b []byte) string {
  612. n := bytes.Index(b, []byte{0})
  613. return string(b[:n])
  614. }
  615. func Uint8Attr(v uint8) []byte {
  616. return []byte{byte(v)}
  617. }
  618. func Uint16Attr(v uint16) []byte {
  619. native := NativeEndian()
  620. bytes := make([]byte, 2)
  621. native.PutUint16(bytes, v)
  622. return bytes
  623. }
  624. func Uint32Attr(v uint32) []byte {
  625. native := NativeEndian()
  626. bytes := make([]byte, 4)
  627. native.PutUint32(bytes, v)
  628. return bytes
  629. }
  630. func Uint64Attr(v uint64) []byte {
  631. native := NativeEndian()
  632. bytes := make([]byte, 8)
  633. native.PutUint64(bytes, v)
  634. return bytes
  635. }
  636. func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
  637. var attrs []syscall.NetlinkRouteAttr
  638. for len(b) >= unix.SizeofRtAttr {
  639. a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
  640. if err != nil {
  641. return nil, err
  642. }
  643. ra := syscall.NetlinkRouteAttr{Attr: syscall.RtAttr(*a), Value: vbuf[:int(a.Len)-unix.SizeofRtAttr]}
  644. attrs = append(attrs, ra)
  645. b = b[alen:]
  646. }
  647. return attrs, nil
  648. }
  649. func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) {
  650. a := (*unix.RtAttr)(unsafe.Pointer(&b[0]))
  651. if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) {
  652. return nil, nil, 0, unix.EINVAL
  653. }
  654. return a, b[unix.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
  655. }
  656. // SocketHandle contains the netlink socket and the associated
  657. // sequence counter for a specific netlink family
  658. type SocketHandle struct {
  659. Seq uint32
  660. Socket *NetlinkSocket
  661. }
  662. // Close closes the netlink socket
  663. func (sh *SocketHandle) Close() {
  664. if sh.Socket != nil {
  665. sh.Socket.Close()
  666. }
  667. }