nl_linux.go 19 KB

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