socket_linux.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. package netlink
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "syscall"
  7. "github.com/vishvananda/netlink/nl"
  8. "golang.org/x/sys/unix"
  9. )
  10. const (
  11. sizeofSocketID = 0x30
  12. sizeofSocketRequest = sizeofSocketID + 0x8
  13. sizeofSocket = sizeofSocketID + 0x18
  14. sizeofUnixSocketRequest = 0x18 // 24 byte
  15. sizeofUnixSocket = 0x10 // 16 byte
  16. )
  17. type socketRequest struct {
  18. Family uint8
  19. Protocol uint8
  20. Ext uint8
  21. pad uint8
  22. States uint32
  23. ID SocketID
  24. }
  25. type writeBuffer struct {
  26. Bytes []byte
  27. pos int
  28. }
  29. func (b *writeBuffer) Write(c byte) {
  30. b.Bytes[b.pos] = c
  31. b.pos++
  32. }
  33. func (b *writeBuffer) Next(n int) []byte {
  34. s := b.Bytes[b.pos : b.pos+n]
  35. b.pos += n
  36. return s
  37. }
  38. func (r *socketRequest) Serialize() []byte {
  39. b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)}
  40. b.Write(r.Family)
  41. b.Write(r.Protocol)
  42. b.Write(r.Ext)
  43. b.Write(r.pad)
  44. native.PutUint32(b.Next(4), r.States)
  45. networkOrder.PutUint16(b.Next(2), r.ID.SourcePort)
  46. networkOrder.PutUint16(b.Next(2), r.ID.DestinationPort)
  47. if r.Family == unix.AF_INET6 {
  48. copy(b.Next(16), r.ID.Source)
  49. copy(b.Next(16), r.ID.Destination)
  50. } else {
  51. copy(b.Next(16), r.ID.Source.To4())
  52. copy(b.Next(16), r.ID.Destination.To4())
  53. }
  54. native.PutUint32(b.Next(4), r.ID.Interface)
  55. native.PutUint32(b.Next(4), r.ID.Cookie[0])
  56. native.PutUint32(b.Next(4), r.ID.Cookie[1])
  57. return b.Bytes
  58. }
  59. func (r *socketRequest) Len() int { return sizeofSocketRequest }
  60. // According to linux/include/uapi/linux/unix_diag.h
  61. type unixSocketRequest struct {
  62. Family uint8
  63. Protocol uint8
  64. pad uint16
  65. States uint32
  66. INode uint32
  67. Show uint32
  68. Cookie [2]uint32
  69. }
  70. func (r *unixSocketRequest) Serialize() []byte {
  71. b := writeBuffer{Bytes: make([]byte, sizeofUnixSocketRequest)}
  72. b.Write(r.Family)
  73. b.Write(r.Protocol)
  74. native.PutUint16(b.Next(2), r.pad)
  75. native.PutUint32(b.Next(4), r.States)
  76. native.PutUint32(b.Next(4), r.INode)
  77. native.PutUint32(b.Next(4), r.Show)
  78. native.PutUint32(b.Next(4), r.Cookie[0])
  79. native.PutUint32(b.Next(4), r.Cookie[1])
  80. return b.Bytes
  81. }
  82. func (r *unixSocketRequest) Len() int { return sizeofUnixSocketRequest }
  83. type readBuffer struct {
  84. Bytes []byte
  85. pos int
  86. }
  87. func (b *readBuffer) Read() byte {
  88. c := b.Bytes[b.pos]
  89. b.pos++
  90. return c
  91. }
  92. func (b *readBuffer) Next(n int) []byte {
  93. s := b.Bytes[b.pos : b.pos+n]
  94. b.pos += n
  95. return s
  96. }
  97. func (s *Socket) deserialize(b []byte) error {
  98. if len(b) < sizeofSocket {
  99. return fmt.Errorf("socket data short read (%d); want %d", len(b), sizeofSocket)
  100. }
  101. rb := readBuffer{Bytes: b}
  102. s.Family = rb.Read()
  103. s.State = rb.Read()
  104. s.Timer = rb.Read()
  105. s.Retrans = rb.Read()
  106. s.ID.SourcePort = networkOrder.Uint16(rb.Next(2))
  107. s.ID.DestinationPort = networkOrder.Uint16(rb.Next(2))
  108. if s.Family == unix.AF_INET6 {
  109. s.ID.Source = net.IP(rb.Next(16))
  110. s.ID.Destination = net.IP(rb.Next(16))
  111. } else {
  112. s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read())
  113. rb.Next(12)
  114. s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read())
  115. rb.Next(12)
  116. }
  117. s.ID.Interface = native.Uint32(rb.Next(4))
  118. s.ID.Cookie[0] = native.Uint32(rb.Next(4))
  119. s.ID.Cookie[1] = native.Uint32(rb.Next(4))
  120. s.Expires = native.Uint32(rb.Next(4))
  121. s.RQueue = native.Uint32(rb.Next(4))
  122. s.WQueue = native.Uint32(rb.Next(4))
  123. s.UID = native.Uint32(rb.Next(4))
  124. s.INode = native.Uint32(rb.Next(4))
  125. return nil
  126. }
  127. func (u *UnixSocket) deserialize(b []byte) error {
  128. if len(b) < sizeofUnixSocket {
  129. return fmt.Errorf("unix diag data short read (%d); want %d", len(b), sizeofUnixSocket)
  130. }
  131. rb := readBuffer{Bytes: b}
  132. u.Type = rb.Read()
  133. u.Family = rb.Read()
  134. u.State = rb.Read()
  135. u.pad = rb.Read()
  136. u.INode = native.Uint32(rb.Next(4))
  137. u.Cookie[0] = native.Uint32(rb.Next(4))
  138. u.Cookie[1] = native.Uint32(rb.Next(4))
  139. return nil
  140. }
  141. // SocketGet returns the Socket identified by its local and remote addresses.
  142. //
  143. // If the returned error is [ErrDumpInterrupted], the search for a result may
  144. // be incomplete and the caller should retry.
  145. func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) {
  146. var protocol uint8
  147. var localIP, remoteIP net.IP
  148. var localPort, remotePort uint16
  149. switch l := local.(type) {
  150. case *net.TCPAddr:
  151. r, ok := remote.(*net.TCPAddr)
  152. if !ok {
  153. return nil, ErrNotImplemented
  154. }
  155. localIP = l.IP
  156. localPort = uint16(l.Port)
  157. remoteIP = r.IP
  158. remotePort = uint16(r.Port)
  159. protocol = unix.IPPROTO_TCP
  160. case *net.UDPAddr:
  161. r, ok := remote.(*net.UDPAddr)
  162. if !ok {
  163. return nil, ErrNotImplemented
  164. }
  165. localIP = l.IP
  166. localPort = uint16(l.Port)
  167. remoteIP = r.IP
  168. remotePort = uint16(r.Port)
  169. protocol = unix.IPPROTO_UDP
  170. default:
  171. return nil, ErrNotImplemented
  172. }
  173. var family uint8
  174. if localIP.To4() != nil && remoteIP.To4() != nil {
  175. family = unix.AF_INET
  176. }
  177. if family == 0 && localIP.To16() != nil && remoteIP.To16() != nil {
  178. family = unix.AF_INET6
  179. }
  180. if family == 0 {
  181. return nil, ErrNotImplemented
  182. }
  183. req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
  184. req.AddData(&socketRequest{
  185. Family: family,
  186. Protocol: protocol,
  187. States: 0xffffffff,
  188. ID: SocketID{
  189. SourcePort: localPort,
  190. DestinationPort: remotePort,
  191. Source: localIP,
  192. Destination: remoteIP,
  193. Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE},
  194. },
  195. })
  196. msgs, err := req.Execute(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY)
  197. if err != nil {
  198. return nil, err
  199. }
  200. if len(msgs) == 0 {
  201. return nil, errors.New("no message nor error from netlink")
  202. }
  203. if len(msgs) > 2 {
  204. return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs))
  205. }
  206. sock := &Socket{}
  207. if err := sock.deserialize(msgs[0]); err != nil {
  208. return nil, err
  209. }
  210. return sock, nil
  211. }
  212. // SocketGet returns the Socket identified by its local and remote addresses.
  213. //
  214. // If the returned error is [ErrDumpInterrupted], the search for a result may
  215. // be incomplete and the caller should retry.
  216. func SocketGet(local, remote net.Addr) (*Socket, error) {
  217. return pkgHandle.SocketGet(local, remote)
  218. }
  219. // SocketDestroy kills the Socket identified by its local and remote addresses.
  220. func (h *Handle) SocketDestroy(local, remote net.Addr) error {
  221. localTCP, ok := local.(*net.TCPAddr)
  222. if !ok {
  223. return ErrNotImplemented
  224. }
  225. remoteTCP, ok := remote.(*net.TCPAddr)
  226. if !ok {
  227. return ErrNotImplemented
  228. }
  229. localIP := localTCP.IP.To4()
  230. if localIP == nil {
  231. return ErrNotImplemented
  232. }
  233. remoteIP := remoteTCP.IP.To4()
  234. if remoteIP == nil {
  235. return ErrNotImplemented
  236. }
  237. s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
  238. if err != nil {
  239. return err
  240. }
  241. defer s.Close()
  242. req := h.newNetlinkRequest(nl.SOCK_DESTROY, unix.NLM_F_ACK)
  243. req.AddData(&socketRequest{
  244. Family: unix.AF_INET,
  245. Protocol: unix.IPPROTO_TCP,
  246. ID: SocketID{
  247. SourcePort: uint16(localTCP.Port),
  248. DestinationPort: uint16(remoteTCP.Port),
  249. Source: localIP,
  250. Destination: remoteIP,
  251. Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE},
  252. },
  253. })
  254. _, err = req.Execute(unix.NETLINK_INET_DIAG, 0)
  255. return err
  256. }
  257. // SocketDestroy kills the Socket identified by its local and remote addresses.
  258. func SocketDestroy(local, remote net.Addr) error {
  259. return pkgHandle.SocketDestroy(local, remote)
  260. }
  261. // SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
  262. //
  263. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  264. // or incomplete.
  265. func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
  266. // Construct the request
  267. req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
  268. req.AddData(&socketRequest{
  269. Family: family,
  270. Protocol: unix.IPPROTO_TCP,
  271. Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
  272. States: uint32(0xfff), // all states
  273. })
  274. // Do the query and parse the result
  275. var result []*InetDiagTCPInfoResp
  276. executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
  277. sockInfo := &Socket{}
  278. var err error
  279. if err = sockInfo.deserialize(msg); err != nil {
  280. return false
  281. }
  282. var attrs []syscall.NetlinkRouteAttr
  283. if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
  284. return false
  285. }
  286. var res *InetDiagTCPInfoResp
  287. if res, err = attrsToInetDiagTCPInfoResp(attrs, sockInfo); err != nil {
  288. return false
  289. }
  290. result = append(result, res)
  291. return true
  292. })
  293. if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
  294. return nil, executeErr
  295. }
  296. return result, executeErr
  297. }
  298. // SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
  299. //
  300. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  301. // or incomplete.
  302. func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
  303. return pkgHandle.SocketDiagTCPInfo(family)
  304. }
  305. // SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
  306. //
  307. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  308. // or incomplete.
  309. func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) {
  310. // Construct the request
  311. req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
  312. req.AddData(&socketRequest{
  313. Family: family,
  314. Protocol: unix.IPPROTO_TCP,
  315. Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
  316. States: uint32(0xfff), // all states
  317. })
  318. // Do the query and parse the result
  319. var result []*Socket
  320. executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
  321. sockInfo := &Socket{}
  322. if err := sockInfo.deserialize(msg); err != nil {
  323. return false
  324. }
  325. result = append(result, sockInfo)
  326. return true
  327. })
  328. if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
  329. return nil, executeErr
  330. }
  331. return result, executeErr
  332. }
  333. // SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
  334. //
  335. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  336. // or incomplete.
  337. func SocketDiagTCP(family uint8) ([]*Socket, error) {
  338. return pkgHandle.SocketDiagTCP(family)
  339. }
  340. // SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
  341. //
  342. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  343. // or incomplete.
  344. func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
  345. // Construct the request
  346. var extensions uint8
  347. extensions = 1 << (INET_DIAG_VEGASINFO - 1)
  348. extensions |= 1 << (INET_DIAG_INFO - 1)
  349. extensions |= 1 << (INET_DIAG_MEMINFO - 1)
  350. req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
  351. req.AddData(&socketRequest{
  352. Family: family,
  353. Protocol: unix.IPPROTO_UDP,
  354. Ext: extensions,
  355. States: uint32(0xfff), // all states
  356. })
  357. // Do the query and parse the result
  358. var result []*InetDiagUDPInfoResp
  359. executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
  360. sockInfo := &Socket{}
  361. if err := sockInfo.deserialize(msg); err != nil {
  362. return false
  363. }
  364. var attrs []syscall.NetlinkRouteAttr
  365. var err error
  366. if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
  367. return false
  368. }
  369. var res *InetDiagUDPInfoResp
  370. if res, err = attrsToInetDiagUDPInfoResp(attrs, sockInfo); err != nil {
  371. return false
  372. }
  373. result = append(result, res)
  374. return true
  375. })
  376. if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
  377. return nil, executeErr
  378. }
  379. return result, executeErr
  380. }
  381. // SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
  382. //
  383. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  384. // or incomplete.
  385. func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
  386. return pkgHandle.SocketDiagUDPInfo(family)
  387. }
  388. // SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
  389. //
  390. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  391. // or incomplete.
  392. func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) {
  393. // Construct the request
  394. req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
  395. req.AddData(&socketRequest{
  396. Family: family,
  397. Protocol: unix.IPPROTO_UDP,
  398. Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
  399. States: uint32(0xfff), // all states
  400. })
  401. // Do the query and parse the result
  402. var result []*Socket
  403. executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
  404. sockInfo := &Socket{}
  405. if err := sockInfo.deserialize(msg); err != nil {
  406. return false
  407. }
  408. result = append(result, sockInfo)
  409. return true
  410. })
  411. if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
  412. return nil, executeErr
  413. }
  414. return result, executeErr
  415. }
  416. // SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
  417. //
  418. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  419. // or incomplete.
  420. func SocketDiagUDP(family uint8) ([]*Socket, error) {
  421. return pkgHandle.SocketDiagUDP(family)
  422. }
  423. // UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
  424. //
  425. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  426. // or incomplete.
  427. func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
  428. // Construct the request
  429. var extensions uint8
  430. extensions = 1 << UNIX_DIAG_NAME
  431. extensions |= 1 << UNIX_DIAG_PEER
  432. extensions |= 1 << UNIX_DIAG_RQLEN
  433. req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
  434. req.AddData(&unixSocketRequest{
  435. Family: unix.AF_UNIX,
  436. States: ^uint32(0), // all states
  437. Show: uint32(extensions),
  438. })
  439. var result []*UnixDiagInfoResp
  440. executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
  441. sockInfo := &UnixSocket{}
  442. if err := sockInfo.deserialize(msg); err != nil {
  443. return false
  444. }
  445. // Diagnosis also delivers sockets with AF_INET family, filter those
  446. if sockInfo.Family != unix.AF_UNIX {
  447. return false
  448. }
  449. var attrs []syscall.NetlinkRouteAttr
  450. var err error
  451. if attrs, err = nl.ParseRouteAttr(msg[sizeofUnixSocket:]); err != nil {
  452. return false
  453. }
  454. var res *UnixDiagInfoResp
  455. if res, err = attrsToUnixDiagInfoResp(attrs, sockInfo); err != nil {
  456. return false
  457. }
  458. result = append(result, res)
  459. return true
  460. })
  461. if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
  462. return nil, executeErr
  463. }
  464. return result, executeErr
  465. }
  466. // UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
  467. //
  468. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  469. // or incomplete.
  470. func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
  471. return pkgHandle.UnixSocketDiagInfo()
  472. }
  473. // UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
  474. //
  475. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  476. // or incomplete.
  477. func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) {
  478. // Construct the request
  479. req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
  480. req.AddData(&unixSocketRequest{
  481. Family: unix.AF_UNIX,
  482. States: ^uint32(0), // all states
  483. })
  484. var result []*UnixSocket
  485. executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
  486. sockInfo := &UnixSocket{}
  487. if err := sockInfo.deserialize(msg); err != nil {
  488. return false
  489. }
  490. // Diagnosis also delivers sockets with AF_INET family, filter those
  491. if sockInfo.Family == unix.AF_UNIX {
  492. result = append(result, sockInfo)
  493. }
  494. return true
  495. })
  496. if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
  497. return nil, executeErr
  498. }
  499. return result, executeErr
  500. }
  501. // UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
  502. //
  503. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  504. // or incomplete.
  505. func UnixSocketDiag() ([]*UnixSocket, error) {
  506. return pkgHandle.UnixSocketDiag()
  507. }
  508. func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
  509. info := &InetDiagTCPInfoResp{
  510. InetDiagMsg: sockInfo,
  511. }
  512. for _, a := range attrs {
  513. switch a.Attr.Type {
  514. case INET_DIAG_INFO:
  515. info.TCPInfo = &TCPInfo{}
  516. if err := info.TCPInfo.deserialize(a.Value); err != nil {
  517. return nil, err
  518. }
  519. case INET_DIAG_BBRINFO:
  520. info.TCPBBRInfo = &TCPBBRInfo{}
  521. if err := info.TCPBBRInfo.deserialize(a.Value); err != nil {
  522. return nil, err
  523. }
  524. }
  525. }
  526. return info, nil
  527. }
  528. func attrsToInetDiagUDPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagUDPInfoResp, error) {
  529. info := &InetDiagUDPInfoResp{
  530. InetDiagMsg: sockInfo,
  531. }
  532. for _, a := range attrs {
  533. switch a.Attr.Type {
  534. case INET_DIAG_MEMINFO:
  535. info.Memory = &MemInfo{}
  536. if err := info.Memory.deserialize(a.Value); err != nil {
  537. return nil, err
  538. }
  539. }
  540. }
  541. return info, nil
  542. }
  543. func attrsToUnixDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *UnixSocket) (*UnixDiagInfoResp, error) {
  544. info := &UnixDiagInfoResp{
  545. DiagMsg: sockInfo,
  546. }
  547. for _, a := range attrs {
  548. switch a.Attr.Type {
  549. case UNIX_DIAG_NAME:
  550. name := string(a.Value[:a.Attr.Len])
  551. info.Name = &name
  552. case UNIX_DIAG_PEER:
  553. peer := native.Uint32(a.Value)
  554. info.Peer = &peer
  555. case UNIX_DIAG_RQLEN:
  556. info.Queue = &QueueInfo{
  557. RQueue: native.Uint32(a.Value[:4]),
  558. WQueue: native.Uint32(a.Value[4:]),
  559. }
  560. // default:
  561. // fmt.Println("unknown unix attribute type", a.Attr.Type, "with data", a.Value)
  562. }
  563. }
  564. return info, nil
  565. }