net_windows.go 20 KB

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