github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/nfqdatapath/autoport_nonwindows.go (about) 1 // +build !windows 2 3 package nfqdatapath 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "os" 9 "os/user" 10 "strconv" 11 "strings" 12 13 "go.aporeto.io/enforcerd/trireme-lib/utils/cgnetcls" 14 "go.uber.org/zap" 15 ) 16 17 const ( 18 procNetTCPFile = "/proc/net/tcp" 19 uidFieldOffset = 7 20 inodeFieldOffset = 9 21 procHeaderLineNum = 0 22 portOffset = 1 23 ipPortOffset = 1 24 sockStateOffset = 3 25 sockListeningState = "0A" 26 hexFormat = 16 27 integerSize = 64 28 minimumFields = 2 29 ) 30 31 func getUserName(uid string) (string, error) { 32 33 u, err := user.LookupId(uid) 34 if err != nil { 35 return "", err 36 } 37 return u.Username, nil 38 } 39 40 func (d *defaultRead) readProcNetTCP() (inodeMap map[string]string, userMap map[string]map[string]bool, err error) { 41 42 buffer, err := ioutil.ReadFile(procNetTCPFile) 43 if err != nil { 44 return nil, nil, fmt.Errorf("Failed to read /proc/net/tcp file %s", err) 45 } 46 47 inodeMap = map[string]string{} 48 userMap = map[string]map[string]bool{} 49 50 s := string(buffer) 51 52 for cnt, line := range strings.Split(s, "\n") { 53 54 line := strings.Fields(line) 55 // continue if not a valid line 56 if len(line) < uidFieldOffset { 57 continue 58 } 59 60 /* Look at socket which are in listening state only */ 61 if (cnt == procHeaderLineNum) || (line[sockStateOffset] != sockListeningState) { 62 continue 63 } 64 65 /* Get the UID */ 66 uid := line[uidFieldOffset] 67 inode := line[inodeFieldOffset] 68 69 portString := "" 70 { 71 ipPort := strings.Split(line[ipPortOffset], ":") 72 73 if len(ipPort) < minimumFields { 74 zap.L().Warn("Failed to extract port") 75 continue 76 } 77 78 portNum, err := strconv.ParseInt(ipPort[portOffset], hexFormat, integerSize) 79 if err != nil { 80 zap.L().Warn("failed to parse port", zap.String("port", ipPort[portOffset])) 81 continue 82 } 83 84 portString = strconv.Itoa(int(portNum)) 85 } 86 87 inodeMap[inode] = portString 88 89 // /proc/net/tcp file contains uid. Conversion to 90 // userName is required as they are keys to lookup tables. 91 userName, err := getUserName(uid) 92 if err != nil { 93 zap.L().Debug("Error converting to username", zap.Error(err)) 94 continue 95 } 96 97 portMap := userMap[userName] 98 if portMap == nil { 99 portMap = map[string]bool{} 100 } 101 portMap[portString] = true 102 userMap[userName] = portMap 103 } 104 105 return inodeMap, userMap, nil 106 } 107 108 func (d *defaultRead) readOpenSockFD(pid string) []string { 109 var inodes []string 110 fdPath := "/proc/" + pid + "/fd/" 111 112 buffer, err := ioutil.ReadDir(fdPath) 113 if err != nil { 114 zap.L().Warn("Failed to read", zap.String("file", fdPath), zap.Error(err)) 115 return nil 116 } 117 118 for _, f := range buffer { 119 link, err := os.Readlink(fdPath + f.Name()) 120 121 if err != nil { 122 zap.L().Warn("Failed to read", zap.String("file", fdPath+f.Name())) 123 continue 124 } 125 if strings.Contains(link, "socket:") { 126 socketInode := strings.Split(link, ":") 127 128 if len(socketInode) < minimumFields { 129 zap.L().Warn("Failed to parse socket inodes") 130 continue 131 } 132 133 inodeString := socketInode[1] 134 inodeString = strings.TrimSuffix(inodeString, "]") 135 inodeString = strings.TrimPrefix(inodeString, "[") 136 137 inodes = append(inodes, inodeString) 138 } 139 } 140 return inodes 141 } 142 143 func (d *defaultRead) getCgroupList() []string { 144 return cgnetcls.GetCgroupList() 145 } 146 147 func (d *defaultRead) listCgroupProcesses(cgroupname string) ([]string, error) { 148 return cgnetcls.ListCgroupProcesses(cgroupname) 149 }