1
0

netstat.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package netstat
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "net/http"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "runtime"
  10. "strconv"
  11. "strings"
  12. "imuslab.com/zoraxy/mod/utils"
  13. )
  14. func HandleGetNetworkInterfaceStats(w http.ResponseWriter, r *http.Request) {
  15. rx, tx, err := GetNetworkInterfaceStats()
  16. if err != nil {
  17. utils.SendErrorResponse(w, err.Error())
  18. return
  19. }
  20. currnetNetSpec := struct {
  21. RX int64
  22. TX int64
  23. }{
  24. rx,
  25. tx,
  26. }
  27. js, _ := json.Marshal(currnetNetSpec)
  28. utils.SendJSONResponse(w, string(js))
  29. }
  30. // Get network interface stats, return accumulated rx bits, tx bits and error if any
  31. func GetNetworkInterfaceStats() (int64, int64, error) {
  32. if runtime.GOOS == "windows" {
  33. cmd := exec.Command("wmic", "path", "Win32_PerfRawData_Tcpip_NetworkInterface", "Get", "BytesReceivedPersec,BytesSentPersec,BytesTotalPersec")
  34. out, err := cmd.Output()
  35. if err != nil {
  36. return 0, 0, err
  37. }
  38. //Filter out the first line
  39. lines := strings.Split(strings.ReplaceAll(string(out), "\r\n", "\n"), "\n")
  40. if len(lines) >= 2 && len(lines[1]) >= 0 {
  41. dataLine := lines[1]
  42. for strings.Contains(dataLine, " ") {
  43. dataLine = strings.ReplaceAll(dataLine, " ", " ")
  44. }
  45. dataLine = strings.TrimSpace(dataLine)
  46. info := strings.Split(dataLine, " ")
  47. if len(info) < 3 {
  48. return 0, 0, errors.New("Invalid wmic results")
  49. }
  50. rxString := info[0]
  51. txString := info[1]
  52. rx := int64(0)
  53. tx := int64(0)
  54. if s, err := strconv.ParseInt(rxString, 10, 64); err == nil {
  55. rx = s
  56. }
  57. if s, err := strconv.ParseInt(txString, 10, 64); err == nil {
  58. tx = s
  59. }
  60. //log.Println(rx, tx)
  61. return rx * 4, tx * 4, nil
  62. } else {
  63. //Invalid data
  64. return 0, 0, errors.New("Invalid wmic results")
  65. }
  66. } else if runtime.GOOS == "linux" {
  67. allIfaceRxByteFiles, err := filepath.Glob("/sys/class/net/*/statistics/rx_bytes")
  68. if err != nil {
  69. //Permission denied
  70. return 0, 0, errors.New("Access denied")
  71. }
  72. if len(allIfaceRxByteFiles) == 0 {
  73. return 0, 0, errors.New("No valid iface found")
  74. }
  75. rxSum := int64(0)
  76. txSum := int64(0)
  77. for _, rxByteFile := range allIfaceRxByteFiles {
  78. rxBytes, err := os.ReadFile(rxByteFile)
  79. if err == nil {
  80. rxBytesInt, err := strconv.Atoi(strings.TrimSpace(string(rxBytes)))
  81. if err == nil {
  82. rxSum += int64(rxBytesInt)
  83. }
  84. }
  85. //Usually the tx_bytes file is nearby it. Read it as well
  86. txByteFile := filepath.Join(filepath.Dir(rxByteFile), "tx_bytes")
  87. txBytes, err := os.ReadFile(txByteFile)
  88. if err == nil {
  89. txBytesInt, err := strconv.Atoi(strings.TrimSpace(string(txBytes)))
  90. if err == nil {
  91. txSum += int64(txBytesInt)
  92. }
  93. }
  94. }
  95. //Return value as bits
  96. return rxSum * 8, txSum * 8, nil
  97. } else if runtime.GOOS == "darwin" {
  98. cmd := exec.Command("netstat", "-ib") //get data from netstat -ib
  99. out, err := cmd.Output()
  100. if err != nil {
  101. return 0, 0, err
  102. }
  103. outStrs := string(out) //byte array to multi-line string
  104. for _, outStr := range strings.Split(strings.TrimSuffix(outStrs, "\n"), "\n") { //foreach multi-line string
  105. if strings.HasPrefix(outStr, "en") { //search for ethernet interface
  106. if strings.Contains(outStr, "<Link#") { //search for the link with <Link#?>
  107. outStrSplit := strings.Fields(outStr) //split by white-space
  108. rxSum, errRX := strconv.Atoi(outStrSplit[6]) //received bytes sum
  109. if errRX != nil {
  110. return 0, 0, errRX
  111. }
  112. txSum, errTX := strconv.Atoi(outStrSplit[9]) //transmitted bytes sum
  113. if errTX != nil {
  114. return 0, 0, errTX
  115. }
  116. return int64(rxSum) * 8, int64(txSum) * 8, nil
  117. }
  118. }
  119. }
  120. return 0, 0, nil //no ethernet adapters with en*/<Link#*>
  121. }
  122. return 0, 0, errors.New("Platform not supported")
  123. }