Files
kubeshark/tap/tlstapper/sockfd_info.go
David Levanon 6979441422 tls missing addresses (#825)
* stream seen file descriptors from ebpf

* re-generate bpf object files

* fixing pr comments
2022-03-14 15:40:27 +02:00

103 lines
2.4 KiB
Go

package tlstapper
import (
"fmt"
"io/ioutil"
"net"
"os"
"regexp"
"strconv"
"strings"
"github.com/go-errors/errors"
)
var socketInodeRegex = regexp.MustCompile(`socket:\[(\d+)\]`)
const (
SRC_ADDRESS_FILED_INDEX = 1
DST_ADDRESS_FILED_INDEX = 2
INODE_FILED_INDEX = 9
)
// This file helps to extract Ip and Port out of a Socket file descriptor.
//
// The equivalent bash commands are:
//
// > ls -l /proc/<pid>/fd/<fd>
// Output something like "socket:[1234]" for sockets - 1234 is the inode of the socket
// > cat /proc/<pid>/net/tcp | grep <inode>
// Output a line per ipv4 socket, the 9th field is the inode of the socket
// The 1st and 2nd fields are the source and dest ip and ports in a Hex format
// 0100007F:50 is 127.0.0.1:80
func getAddressBySockfd(procfs string, pid uint32, fd uint32, src bool) (net.IP, uint16, error) {
inode, err := getSocketInode(procfs, pid, fd)
if err != nil {
return nil, 0, err
}
tcppath := fmt.Sprintf("%s/%d/net/tcp", procfs, pid)
tcp, err := ioutil.ReadFile(tcppath)
if err != nil {
return nil, 0, errors.Wrap(err, 0)
}
for _, line := range strings.Split(string(tcp), "\n") {
parts := strings.Fields(line)
if len(parts) < 10 {
continue
}
if inode == parts[INODE_FILED_INDEX] {
if src {
return parseHexAddress(parts[SRC_ADDRESS_FILED_INDEX])
} else {
return parseHexAddress(parts[DST_ADDRESS_FILED_INDEX])
}
}
}
return nil, 0, errors.Errorf("address not found [pid: %d] [sockfd: %d] [inode: %s]", pid, fd, inode)
}
func getSocketInode(procfs string, pid uint32, fd uint32) (string, error) {
fdlinkPath := fmt.Sprintf("%s/%d/fd/%d", procfs, pid, fd)
fdlink, err := os.Readlink(fdlinkPath)
if err != nil {
return "", errors.Wrap(err, 0)
}
tokens := socketInodeRegex.FindStringSubmatch(fdlink)
if tokens == nil || len(tokens) < 1 {
return "", errors.Errorf("socket inode not found [pid: %d] [sockfd: %d] [link: %s]", pid, fd, fdlink)
}
return tokens[1], nil
}
// Format looks like 0100007F:50 for 127.0.0.1:80
//
func parseHexAddress(addr string) (net.IP, uint16, error) {
addrParts := strings.Split(addr, ":")
port, err := strconv.ParseUint(addrParts[1], 16, 16)
if err != nil {
return nil, 0, errors.Wrap(err, 0)
}
ip, err := strconv.ParseUint(addrParts[0], 16, 32)
if err != nil {
return nil, 0, errors.Wrap(err, 0)
}
return net.IP{uint8(ip), uint8(ip >> 8), uint8(ip >> 16), uint8(ip >> 24)}, uint16(port), nil
}