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  }