github.com/elfadel/cilium@v1.6.12/pkg/proxy/netstat.go (about)

     1  // Copyright 2018 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package proxy
    16  
    17  import (
    18  	"bytes"
    19  	"io/ioutil"
    20  	"regexp"
    21  	"strconv"
    22  
    23  	"github.com/cilium/cilium/pkg/logging/logfields"
    24  )
    25  
    26  var (
    27  	// procNetTCPFiles is the constant list of /proc/net files to read to get
    28  	// the same information about open TCP connections as output by netstat.
    29  	procNetTCPFiles = []string{
    30  		"/proc/net/tcp",
    31  		"/proc/net/tcp6",
    32  	}
    33  
    34  	// procNetUDPFiles is the constant list of /proc/net files to read to get
    35  	// the same information about open UDP connections as output by netstat.
    36  	procNetUDPFiles = []string{
    37  		"/proc/net/udp",
    38  		"/proc/net/udp6",
    39  	}
    40  
    41  	// procNetFileRegexp matches the first two columns of /proc/net/{tcp,udp}*
    42  	// files and submatches on the local port number.
    43  	procNetFileRegexp = regexp.MustCompile("^ *[[:digit:]]*: *[[:xdigit:]]*:([[:xdigit:]]*) ")
    44  )
    45  
    46  // readOpenLocalPorts returns the set of L4 ports currently open locally.
    47  // procNetFiles should be procNetTCPFiles or procNetUDPFiles (or both).
    48  func readOpenLocalPorts(procNetFiles []string) map[uint16]struct{} {
    49  	openLocalPorts := make(map[uint16]struct{}, 128)
    50  
    51  	for _, file := range procNetFiles {
    52  		b, err := ioutil.ReadFile(file)
    53  		if err != nil {
    54  			log.WithError(err).WithField(logfields.Path, file).Errorf("cannot read proc file")
    55  			continue
    56  		}
    57  
    58  		lines := bytes.Split(b, []byte("\n"))
    59  
    60  		// Extract the local port number from the "local_address" column.
    61  		// The header line won't match and will be ignored.
    62  		for _, line := range lines {
    63  			groups := procNetFileRegexp.FindSubmatch(line)
    64  			if len(groups) != 2 { // no match
    65  				continue
    66  			}
    67  			// The port number is in hexadecimal.
    68  			localPort, err := strconv.ParseUint(string(groups[1]), 16, 16)
    69  			if err != nil {
    70  				log.WithError(err).WithField(logfields.Path, file).Errorf("cannot read proc file")
    71  				continue
    72  			}
    73  			openLocalPorts[uint16(localPort)] = struct{}{}
    74  		}
    75  	}
    76  
    77  	return openLocalPorts
    78  }