net_windows.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. //go:build windows
  2. // +build windows
  3. package net
  4. import (
  5. "context"
  6. "fmt"
  7. "net"
  8. "os"
  9. "syscall"
  10. "unsafe"
  11. "github.com/shirou/gopsutil/v3/internal/common"
  12. "golang.org/x/sys/windows"
  13. )
  14. var (
  15. modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
  16. procGetExtendedTCPTable = modiphlpapi.NewProc("GetExtendedTcpTable")
  17. procGetExtendedUDPTable = modiphlpapi.NewProc("GetExtendedUdpTable")
  18. procGetIfEntry2 = modiphlpapi.NewProc("GetIfEntry2")
  19. )
  20. const (
  21. TCPTableBasicListener = iota
  22. TCPTableBasicConnections
  23. TCPTableBasicAll
  24. TCPTableOwnerPIDListener
  25. TCPTableOwnerPIDConnections
  26. TCPTableOwnerPIDAll
  27. TCPTableOwnerModuleListener
  28. TCPTableOwnerModuleConnections
  29. TCPTableOwnerModuleAll
  30. )
  31. type netConnectionKindType struct {
  32. family uint32
  33. sockType uint32
  34. filename string
  35. }
  36. var kindTCP4 = netConnectionKindType{
  37. family: syscall.AF_INET,
  38. sockType: syscall.SOCK_STREAM,
  39. filename: "tcp",
  40. }
  41. var kindTCP6 = netConnectionKindType{
  42. family: syscall.AF_INET6,
  43. sockType: syscall.SOCK_STREAM,
  44. filename: "tcp6",
  45. }
  46. var kindUDP4 = netConnectionKindType{
  47. family: syscall.AF_INET,
  48. sockType: syscall.SOCK_DGRAM,
  49. filename: "udp",
  50. }
  51. var kindUDP6 = netConnectionKindType{
  52. family: syscall.AF_INET6,
  53. sockType: syscall.SOCK_DGRAM,
  54. filename: "udp6",
  55. }
  56. var netConnectionKindMap = map[string][]netConnectionKindType{
  57. "all": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
  58. "tcp": {kindTCP4, kindTCP6},
  59. "tcp4": {kindTCP4},
  60. "tcp6": {kindTCP6},
  61. "udp": {kindUDP4, kindUDP6},
  62. "udp4": {kindUDP4},
  63. "udp6": {kindUDP6},
  64. "inet": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
  65. "inet4": {kindTCP4, kindUDP4},
  66. "inet6": {kindTCP6, kindUDP6},
  67. }
  68. // https://github.com/microsoft/ethr/blob/aecdaf923970e5a9b4c461b4e2e3963d781ad2cc/plt_windows.go#L114-L170
  69. type guid struct {
  70. Data1 uint32
  71. Data2 uint16
  72. Data3 uint16
  73. Data4 [8]byte
  74. }
  75. const (
  76. maxStringSize = 256
  77. maxPhysAddressLength = 32
  78. pad0for64_4for32 = 0
  79. )
  80. type mibIfRow2 struct {
  81. InterfaceLuid uint64
  82. InterfaceIndex uint32
  83. InterfaceGuid guid
  84. Alias [maxStringSize + 1]uint16
  85. Description [maxStringSize + 1]uint16
  86. PhysicalAddressLength uint32
  87. PhysicalAddress [maxPhysAddressLength]uint8
  88. PermanentPhysicalAddress [maxPhysAddressLength]uint8
  89. Mtu uint32
  90. Type uint32
  91. TunnelType uint32
  92. MediaType uint32
  93. PhysicalMediumType uint32
  94. AccessType uint32
  95. DirectionType uint32
  96. InterfaceAndOperStatusFlags uint32
  97. OperStatus uint32
  98. AdminStatus uint32
  99. MediaConnectState uint32
  100. NetworkGuid guid
  101. ConnectionType uint32
  102. padding1 [pad0for64_4for32]byte
  103. TransmitLinkSpeed uint64
  104. ReceiveLinkSpeed uint64
  105. InOctets uint64
  106. InUcastPkts uint64
  107. InNUcastPkts uint64
  108. InDiscards uint64
  109. InErrors uint64
  110. InUnknownProtos uint64
  111. InUcastOctets uint64
  112. InMulticastOctets uint64
  113. InBroadcastOctets uint64
  114. OutOctets uint64
  115. OutUcastPkts uint64
  116. OutNUcastPkts uint64
  117. OutDiscards uint64
  118. OutErrors uint64
  119. OutUcastOctets uint64
  120. OutMulticastOctets uint64
  121. OutBroadcastOctets uint64
  122. OutQLen uint64
  123. }
  124. func IOCounters(pernic bool) ([]IOCountersStat, error) {
  125. return IOCountersWithContext(context.Background(), pernic)
  126. }
  127. func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
  128. ifs, err := net.Interfaces()
  129. if err != nil {
  130. return nil, err
  131. }
  132. var counters []IOCountersStat
  133. err = procGetIfEntry2.Find()
  134. if err == nil { // Vista+, uint64 values (issue#693)
  135. for _, ifi := range ifs {
  136. c := IOCountersStat{
  137. Name: ifi.Name,
  138. }
  139. row := mibIfRow2{InterfaceIndex: uint32(ifi.Index)}
  140. ret, _, err := procGetIfEntry2.Call(uintptr(unsafe.Pointer(&row)))
  141. if ret != 0 {
  142. return nil, os.NewSyscallError("GetIfEntry2", err)
  143. }
  144. c.BytesSent = uint64(row.OutOctets)
  145. c.BytesRecv = uint64(row.InOctets)
  146. c.PacketsSent = uint64(row.OutUcastPkts)
  147. c.PacketsRecv = uint64(row.InUcastPkts)
  148. c.Errin = uint64(row.InErrors)
  149. c.Errout = uint64(row.OutErrors)
  150. c.Dropin = uint64(row.InDiscards)
  151. c.Dropout = uint64(row.OutDiscards)
  152. counters = append(counters, c)
  153. }
  154. } else { // WinXP fallback, uint32 values
  155. for _, ifi := range ifs {
  156. c := IOCountersStat{
  157. Name: ifi.Name,
  158. }
  159. row := windows.MibIfRow{Index: uint32(ifi.Index)}
  160. err = windows.GetIfEntry(&row)
  161. if err != nil {
  162. return nil, os.NewSyscallError("GetIfEntry", err)
  163. }
  164. c.BytesSent = uint64(row.OutOctets)
  165. c.BytesRecv = uint64(row.InOctets)
  166. c.PacketsSent = uint64(row.OutUcastPkts)
  167. c.PacketsRecv = uint64(row.InUcastPkts)
  168. c.Errin = uint64(row.InErrors)
  169. c.Errout = uint64(row.OutErrors)
  170. c.Dropin = uint64(row.InDiscards)
  171. c.Dropout = uint64(row.OutDiscards)
  172. counters = append(counters, c)
  173. }
  174. }
  175. if !pernic {
  176. return getIOCountersAll(counters)
  177. }
  178. return counters, nil
  179. }
  180. // IOCountersByFile exists just for compatibility with Linux.
  181. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
  182. return IOCountersByFileWithContext(context.Background(), pernic, filename)
  183. }
  184. func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
  185. return IOCounters(pernic)
  186. }
  187. // Return a list of network connections
  188. // Available kind:
  189. // reference to netConnectionKindMap
  190. func Connections(kind string) ([]ConnectionStat, error) {
  191. return ConnectionsWithContext(context.Background(), kind)
  192. }
  193. func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
  194. return ConnectionsPidWithContext(ctx, kind, 0)
  195. }
  196. // ConnectionsPid Return a list of network connections opened by a process
  197. func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
  198. return ConnectionsPidWithContext(context.Background(), kind, pid)
  199. }
  200. func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
  201. tmap, ok := netConnectionKindMap[kind]
  202. if !ok {
  203. return nil, fmt.Errorf("invalid kind, %s", kind)
  204. }
  205. return getProcInet(tmap, pid)
  206. }
  207. func getProcInet(kinds []netConnectionKindType, pid int32) ([]ConnectionStat, error) {
  208. stats := make([]ConnectionStat, 0)
  209. for _, kind := range kinds {
  210. s, err := getNetStatWithKind(kind)
  211. if err != nil {
  212. continue
  213. }
  214. if pid == 0 {
  215. stats = append(stats, s...)
  216. } else {
  217. for _, ns := range s {
  218. if ns.Pid != pid {
  219. continue
  220. }
  221. stats = append(stats, ns)
  222. }
  223. }
  224. }
  225. return stats, nil
  226. }
  227. func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error) {
  228. if kindType.filename == "" {
  229. return nil, fmt.Errorf("kind filename must be required")
  230. }
  231. switch kindType.filename {
  232. case kindTCP4.filename:
  233. return getTCPConnections(kindTCP4.family)
  234. case kindTCP6.filename:
  235. return getTCPConnections(kindTCP6.family)
  236. case kindUDP4.filename:
  237. return getUDPConnections(kindUDP4.family)
  238. case kindUDP6.filename:
  239. return getUDPConnections(kindUDP6.family)
  240. }
  241. return nil, fmt.Errorf("invalid kind filename, %s", kindType.filename)
  242. }
  243. // Return a list of network connections opened returning at most `max`
  244. // connections for each running process.
  245. func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) {
  246. return ConnectionsMaxWithContext(context.Background(), kind, max)
  247. }
  248. func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
  249. return []ConnectionStat{}, common.ErrNotImplementedError
  250. }
  251. // Return a list of network connections opened, omitting `Uids`.
  252. // WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
  253. // removed from the API in the future.
  254. func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
  255. return ConnectionsWithoutUidsWithContext(context.Background(), kind)
  256. }
  257. func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
  258. return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
  259. }
  260. func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
  261. return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
  262. }
  263. func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
  264. return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
  265. }
  266. func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
  267. return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
  268. }
  269. func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
  270. return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
  271. }
  272. func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
  273. return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
  274. }
  275. func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
  276. return []ConnectionStat{}, common.ErrNotImplementedError
  277. }
  278. func FilterCounters() ([]FilterStat, error) {
  279. return FilterCountersWithContext(context.Background())
  280. }
  281. func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
  282. return nil, common.ErrNotImplementedError
  283. }
  284. func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
  285. return ConntrackStatsWithContext(context.Background(), percpu)
  286. }
  287. func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
  288. return nil, common.ErrNotImplementedError
  289. }
  290. // NetProtoCounters returns network statistics for the entire system
  291. // If protocols is empty then all protocols are returned, otherwise
  292. // just the protocols in the list are returned.
  293. // Not Implemented for Windows
  294. func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
  295. return ProtoCountersWithContext(context.Background(), protocols)
  296. }
  297. func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
  298. return nil, common.ErrNotImplementedError
  299. }
  300. func getTableUintptr(family uint32, buf []byte) uintptr {
  301. var (
  302. pmibTCPTable pmibTCPTableOwnerPidAll
  303. pmibTCP6Table pmibTCP6TableOwnerPidAll
  304. p uintptr
  305. )
  306. switch family {
  307. case kindTCP4.family:
  308. if len(buf) > 0 {
  309. pmibTCPTable = (*mibTCPTableOwnerPid)(unsafe.Pointer(&buf[0]))
  310. p = uintptr(unsafe.Pointer(pmibTCPTable))
  311. } else {
  312. p = uintptr(unsafe.Pointer(pmibTCPTable))
  313. }
  314. case kindTCP6.family:
  315. if len(buf) > 0 {
  316. pmibTCP6Table = (*mibTCP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
  317. p = uintptr(unsafe.Pointer(pmibTCP6Table))
  318. } else {
  319. p = uintptr(unsafe.Pointer(pmibTCP6Table))
  320. }
  321. }
  322. return p
  323. }
  324. func getTableInfo(filename string, table interface{}) (index, step, length int) {
  325. switch filename {
  326. case kindTCP4.filename:
  327. index = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).DwNumEntries))
  328. step = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).Table))
  329. length = int(table.(pmibTCPTableOwnerPidAll).DwNumEntries)
  330. case kindTCP6.filename:
  331. index = int(unsafe.Sizeof(table.(pmibTCP6TableOwnerPidAll).DwNumEntries))
  332. step = int(unsafe.Sizeof(table.(pmibTCP6TableOwnerPidAll).Table))
  333. length = int(table.(pmibTCP6TableOwnerPidAll).DwNumEntries)
  334. case kindUDP4.filename:
  335. index = int(unsafe.Sizeof(table.(pmibUDPTableOwnerPid).DwNumEntries))
  336. step = int(unsafe.Sizeof(table.(pmibUDPTableOwnerPid).Table))
  337. length = int(table.(pmibUDPTableOwnerPid).DwNumEntries)
  338. case kindUDP6.filename:
  339. index = int(unsafe.Sizeof(table.(pmibUDP6TableOwnerPid).DwNumEntries))
  340. step = int(unsafe.Sizeof(table.(pmibUDP6TableOwnerPid).Table))
  341. length = int(table.(pmibUDP6TableOwnerPid).DwNumEntries)
  342. }
  343. return
  344. }
  345. func getTCPConnections(family uint32) ([]ConnectionStat, error) {
  346. var (
  347. p uintptr
  348. buf []byte
  349. size uint32
  350. pmibTCPTable pmibTCPTableOwnerPidAll
  351. pmibTCP6Table pmibTCP6TableOwnerPidAll
  352. )
  353. if family == 0 {
  354. return nil, fmt.Errorf("faimly must be required")
  355. }
  356. for {
  357. switch family {
  358. case kindTCP4.family:
  359. if len(buf) > 0 {
  360. pmibTCPTable = (*mibTCPTableOwnerPid)(unsafe.Pointer(&buf[0]))
  361. p = uintptr(unsafe.Pointer(pmibTCPTable))
  362. } else {
  363. p = uintptr(unsafe.Pointer(pmibTCPTable))
  364. }
  365. case kindTCP6.family:
  366. if len(buf) > 0 {
  367. pmibTCP6Table = (*mibTCP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
  368. p = uintptr(unsafe.Pointer(pmibTCP6Table))
  369. } else {
  370. p = uintptr(unsafe.Pointer(pmibTCP6Table))
  371. }
  372. }
  373. err := getExtendedTcpTable(p,
  374. &size,
  375. true,
  376. family,
  377. tcpTableOwnerPidAll,
  378. 0)
  379. if err == nil {
  380. break
  381. }
  382. if err != windows.ERROR_INSUFFICIENT_BUFFER {
  383. return nil, err
  384. }
  385. buf = make([]byte, size)
  386. }
  387. var (
  388. index, step int
  389. length int
  390. )
  391. stats := make([]ConnectionStat, 0)
  392. switch family {
  393. case kindTCP4.family:
  394. index, step, length = getTableInfo(kindTCP4.filename, pmibTCPTable)
  395. case kindTCP6.family:
  396. index, step, length = getTableInfo(kindTCP6.filename, pmibTCP6Table)
  397. }
  398. if length == 0 {
  399. return nil, nil
  400. }
  401. for i := 0; i < length; i++ {
  402. switch family {
  403. case kindTCP4.family:
  404. mibs := (*mibTCPRowOwnerPid)(unsafe.Pointer(&buf[index]))
  405. ns := mibs.convertToConnectionStat()
  406. stats = append(stats, ns)
  407. case kindTCP6.family:
  408. mibs := (*mibTCP6RowOwnerPid)(unsafe.Pointer(&buf[index]))
  409. ns := mibs.convertToConnectionStat()
  410. stats = append(stats, ns)
  411. }
  412. index += step
  413. }
  414. return stats, nil
  415. }
  416. func getUDPConnections(family uint32) ([]ConnectionStat, error) {
  417. var (
  418. p uintptr
  419. buf []byte
  420. size uint32
  421. pmibUDPTable pmibUDPTableOwnerPid
  422. pmibUDP6Table pmibUDP6TableOwnerPid
  423. )
  424. if family == 0 {
  425. return nil, fmt.Errorf("faimly must be required")
  426. }
  427. for {
  428. switch family {
  429. case kindUDP4.family:
  430. if len(buf) > 0 {
  431. pmibUDPTable = (*mibUDPTableOwnerPid)(unsafe.Pointer(&buf[0]))
  432. p = uintptr(unsafe.Pointer(pmibUDPTable))
  433. } else {
  434. p = uintptr(unsafe.Pointer(pmibUDPTable))
  435. }
  436. case kindUDP6.family:
  437. if len(buf) > 0 {
  438. pmibUDP6Table = (*mibUDP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
  439. p = uintptr(unsafe.Pointer(pmibUDP6Table))
  440. } else {
  441. p = uintptr(unsafe.Pointer(pmibUDP6Table))
  442. }
  443. }
  444. err := getExtendedUdpTable(
  445. p,
  446. &size,
  447. true,
  448. family,
  449. udpTableOwnerPid,
  450. 0,
  451. )
  452. if err == nil {
  453. break
  454. }
  455. if err != windows.ERROR_INSUFFICIENT_BUFFER {
  456. return nil, err
  457. }
  458. buf = make([]byte, size)
  459. }
  460. var index, step, length int
  461. stats := make([]ConnectionStat, 0)
  462. switch family {
  463. case kindUDP4.family:
  464. index, step, length = getTableInfo(kindUDP4.filename, pmibUDPTable)
  465. case kindUDP6.family:
  466. index, step, length = getTableInfo(kindUDP6.filename, pmibUDP6Table)
  467. }
  468. if length == 0 {
  469. return nil, nil
  470. }
  471. for i := 0; i < length; i++ {
  472. switch family {
  473. case kindUDP4.family:
  474. mibs := (*mibUDPRowOwnerPid)(unsafe.Pointer(&buf[index]))
  475. ns := mibs.convertToConnectionStat()
  476. stats = append(stats, ns)
  477. case kindUDP6.family:
  478. mibs := (*mibUDP6RowOwnerPid)(unsafe.Pointer(&buf[index]))
  479. ns := mibs.convertToConnectionStat()
  480. stats = append(stats, ns)
  481. }
  482. index += step
  483. }
  484. return stats, nil
  485. }
  486. // tcpStatuses https://msdn.microsoft.com/en-us/library/windows/desktop/bb485761(v=vs.85).aspx
  487. var tcpStatuses = map[mibTCPState]string{
  488. 1: "CLOSED",
  489. 2: "LISTEN",
  490. 3: "SYN_SENT",
  491. 4: "SYN_RECEIVED",
  492. 5: "ESTABLISHED",
  493. 6: "FIN_WAIT_1",
  494. 7: "FIN_WAIT_2",
  495. 8: "CLOSE_WAIT",
  496. 9: "CLOSING",
  497. 10: "LAST_ACK",
  498. 11: "TIME_WAIT",
  499. 12: "DELETE",
  500. }
  501. func getExtendedTcpTable(pTcpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass tcpTableClass, reserved uint32) (errcode error) {
  502. r1, _, _ := syscall.Syscall6(procGetExtendedTCPTable.Addr(), 6, pTcpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
  503. if r1 != 0 {
  504. errcode = syscall.Errno(r1)
  505. }
  506. return
  507. }
  508. func getExtendedUdpTable(pUdpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass udpTableClass, reserved uint32) (errcode error) {
  509. r1, _, _ := syscall.Syscall6(procGetExtendedUDPTable.Addr(), 6, pUdpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
  510. if r1 != 0 {
  511. errcode = syscall.Errno(r1)
  512. }
  513. return
  514. }
  515. func getUintptrFromBool(b bool) uintptr {
  516. if b {
  517. return 1
  518. }
  519. return 0
  520. }
  521. const anySize = 1
  522. // type MIB_TCP_STATE int32
  523. type mibTCPState int32
  524. type tcpTableClass int32
  525. const (
  526. tcpTableBasicListener tcpTableClass = iota
  527. tcpTableBasicConnections
  528. tcpTableBasicAll
  529. tcpTableOwnerPidListener
  530. tcpTableOwnerPidConnections
  531. tcpTableOwnerPidAll
  532. tcpTableOwnerModuleListener
  533. tcpTableOwnerModuleConnections
  534. tcpTableOwnerModuleAll
  535. )
  536. type udpTableClass int32
  537. const (
  538. udpTableBasic udpTableClass = iota
  539. udpTableOwnerPid
  540. udpTableOwnerModule
  541. )
  542. // TCP
  543. type mibTCPRowOwnerPid struct {
  544. DwState uint32
  545. DwLocalAddr uint32
  546. DwLocalPort uint32
  547. DwRemoteAddr uint32
  548. DwRemotePort uint32
  549. DwOwningPid uint32
  550. }
  551. func (m *mibTCPRowOwnerPid) convertToConnectionStat() ConnectionStat {
  552. ns := ConnectionStat{
  553. Family: kindTCP4.family,
  554. Type: kindTCP4.sockType,
  555. Laddr: Addr{
  556. IP: parseIPv4HexString(m.DwLocalAddr),
  557. Port: uint32(decodePort(m.DwLocalPort)),
  558. },
  559. Raddr: Addr{
  560. IP: parseIPv4HexString(m.DwRemoteAddr),
  561. Port: uint32(decodePort(m.DwRemotePort)),
  562. },
  563. Pid: int32(m.DwOwningPid),
  564. Status: tcpStatuses[mibTCPState(m.DwState)],
  565. }
  566. return ns
  567. }
  568. type mibTCPTableOwnerPid struct {
  569. DwNumEntries uint32
  570. Table [anySize]mibTCPRowOwnerPid
  571. }
  572. type mibTCP6RowOwnerPid struct {
  573. UcLocalAddr [16]byte
  574. DwLocalScopeId uint32
  575. DwLocalPort uint32
  576. UcRemoteAddr [16]byte
  577. DwRemoteScopeId uint32
  578. DwRemotePort uint32
  579. DwState uint32
  580. DwOwningPid uint32
  581. }
  582. func (m *mibTCP6RowOwnerPid) convertToConnectionStat() ConnectionStat {
  583. ns := ConnectionStat{
  584. Family: kindTCP6.family,
  585. Type: kindTCP6.sockType,
  586. Laddr: Addr{
  587. IP: parseIPv6HexString(m.UcLocalAddr),
  588. Port: uint32(decodePort(m.DwLocalPort)),
  589. },
  590. Raddr: Addr{
  591. IP: parseIPv6HexString(m.UcRemoteAddr),
  592. Port: uint32(decodePort(m.DwRemotePort)),
  593. },
  594. Pid: int32(m.DwOwningPid),
  595. Status: tcpStatuses[mibTCPState(m.DwState)],
  596. }
  597. return ns
  598. }
  599. type mibTCP6TableOwnerPid struct {
  600. DwNumEntries uint32
  601. Table [anySize]mibTCP6RowOwnerPid
  602. }
  603. type (
  604. pmibTCPTableOwnerPidAll *mibTCPTableOwnerPid
  605. pmibTCP6TableOwnerPidAll *mibTCP6TableOwnerPid
  606. )
  607. // UDP
  608. type mibUDPRowOwnerPid struct {
  609. DwLocalAddr uint32
  610. DwLocalPort uint32
  611. DwOwningPid uint32
  612. }
  613. func (m *mibUDPRowOwnerPid) convertToConnectionStat() ConnectionStat {
  614. ns := ConnectionStat{
  615. Family: kindUDP4.family,
  616. Type: kindUDP4.sockType,
  617. Laddr: Addr{
  618. IP: parseIPv4HexString(m.DwLocalAddr),
  619. Port: uint32(decodePort(m.DwLocalPort)),
  620. },
  621. Pid: int32(m.DwOwningPid),
  622. }
  623. return ns
  624. }
  625. type mibUDPTableOwnerPid struct {
  626. DwNumEntries uint32
  627. Table [anySize]mibUDPRowOwnerPid
  628. }
  629. type mibUDP6RowOwnerPid struct {
  630. UcLocalAddr [16]byte
  631. DwLocalScopeId uint32
  632. DwLocalPort uint32
  633. DwOwningPid uint32
  634. }
  635. func (m *mibUDP6RowOwnerPid) convertToConnectionStat() ConnectionStat {
  636. ns := ConnectionStat{
  637. Family: kindUDP6.family,
  638. Type: kindUDP6.sockType,
  639. Laddr: Addr{
  640. IP: parseIPv6HexString(m.UcLocalAddr),
  641. Port: uint32(decodePort(m.DwLocalPort)),
  642. },
  643. Pid: int32(m.DwOwningPid),
  644. }
  645. return ns
  646. }
  647. type mibUDP6TableOwnerPid struct {
  648. DwNumEntries uint32
  649. Table [anySize]mibUDP6RowOwnerPid
  650. }
  651. type (
  652. pmibUDPTableOwnerPid *mibUDPTableOwnerPid
  653. pmibUDP6TableOwnerPid *mibUDP6TableOwnerPid
  654. )
  655. func decodePort(port uint32) uint16 {
  656. return syscall.Ntohs(uint16(port))
  657. }
  658. func parseIPv4HexString(addr uint32) string {
  659. return fmt.Sprintf("%d.%d.%d.%d", addr&255, addr>>8&255, addr>>16&255, addr>>24&255)
  660. }
  661. func parseIPv6HexString(addr [16]byte) string {
  662. var ret [16]byte
  663. for i := 0; i < 16; i++ {
  664. ret[i] = uint8(addr[i])
  665. }
  666. // convert []byte to net.IP
  667. ip := net.IP(ret[:])
  668. return ip.String()
  669. }