Skip to content

Commit

Permalink
print sockaddr common families in go (#52)
Browse files Browse the repository at this point in the history
print sockaddr common families in go
  • Loading branch information
itaysk committed Mar 4, 2020
1 parent 6b2ce47 commit 1ae06bc
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 6 deletions.
16 changes: 16 additions & 0 deletions tracee/argprinters.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package tracee

import (
"encoding/binary"
"net"
"strconv"
"strings"
)
Expand Down Expand Up @@ -290,6 +292,20 @@ func PrintSocketDomain(sd uint32) string {
return res
}

// PrintUint32IP prints the IP address encoded as a uint32
func PrintUint32IP(in uint32) string {
ip := make(net.IP, net.IPv4len)
binary.BigEndian.PutUint32(ip, in)
return ip.String()
}

// Print16BytesSliceIP prints the IP address encoded as 16 bytes long PrintBytesSliceIP
// It would be more correct to accept a [16]byte instead of variable lenth slice, but that would case unnecessary memory copying and type conversions
func Print16BytesSliceIP(in []byte) string {
ip := net.IP(in)
return ip.String()
}

// PrintCapability prints the `capability` bitmask argument of the `cap_capable` function
// include/uapi/linux/capability.h
func PrintCapability(cap int32) string {
Expand Down
134 changes: 128 additions & 6 deletions tracee/tracee.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io/ioutil"
"os"
"os/signal"
"strconv"

bpf "github.com/iovisor/gobpf/bcc"
)
Expand Down Expand Up @@ -326,17 +327,45 @@ func readStringFromBuff(buff io.Reader) (string, error) {
if err != nil {
return "", fmt.Errorf("error reading string size: %v", err)
}
res := make([]byte, size-1) //last byte is string terminated null
res, err := readByteSliceFromBuff(buff, int(size-1)) //last byte is string terminating null
defer func() {
_, _ = readInt8FromBuff(buff) //discard last byte which is string terminated null
_, _ = readInt8FromBuff(buff) //discard last byte which is string terminating null
}()
err = binary.Read(buff, binary.LittleEndian, &res)
if err != nil {
return "", fmt.Errorf("error reading string arg: %v", err)
}
return string(res), nil
}

// readStringVarFromBuff reads a null-terminated string from `buff`
// max length can be passed as `max` to optimize memory allocation, otherwise pass 0
func readStringVarFromBuff(buff io.Reader, max int) (string, error) {
var err error
res := make([]byte, max)
char, err := readInt8FromBuff(buff)
if err != nil {
return "", fmt.Errorf("error reading null terminated string: %v", err)
}
for char != 0 {
res = append(res, byte(char))
char, err = readInt8FromBuff(buff)
if err != nil {
return "", fmt.Errorf("error reading null terminated string: %v", err)
}
}
return string(res), nil
}

func readByteSliceFromBuff(buff io.Reader, len int) ([]byte, error) {
var err error
res := make([]byte, len)
err = binary.Read(buff, binary.LittleEndian, &res)
if err != nil {
return nil, fmt.Errorf("error reading byte array: %v", err)
}
return res, nil
}

func readInt8FromBuff(buff io.Reader) (int8, error) {
var res int8
err := binary.Read(buff, binary.LittleEndian, &res)
Expand All @@ -361,6 +390,12 @@ func readUInt16FromBuff(buff io.Reader) (uint16, error) {
return res, err
}

func readUInt16BigendFromBuff(buff io.Reader) (uint16, error) {
var res uint16
err := binary.Read(buff, binary.BigEndian, &res)
return res, err
}

func readInt32FromBuff(buff io.Reader) (int32, error) {
var res int32
err := binary.Read(buff, binary.LittleEndian, &res)
Expand All @@ -373,6 +408,12 @@ func readUInt32FromBuff(buff io.Reader) (uint32, error) {
return res, err
}

func readUInt32BigendFromBuff(buff io.Reader) (uint32, error) {
var res uint32
err := binary.Read(buff, binary.BigEndian, &res)
return res, err
}

func readInt64FromBuff(buff io.Reader) (int64, error) {
var res int64
err := binary.Read(buff, binary.LittleEndian, &res)
Expand All @@ -385,6 +426,88 @@ func readUInt64FromBuff(buff io.Reader) (uint64, error) {
return res, err
}

func readSockaddrFromBuff(buff io.Reader) (map[string]string, error) {
res := make(map[string]string, 3)
family, err := readInt16FromBuff(buff)
if err != nil {
return nil, err
}
res["sa_family"] = PrintSocketDomain(uint32(family))
switch family {
case 1: // AF_UNIX
/*
http://man7.org/linux/man-pages/man7/unix.7.html
struct sockaddr_un {
sa_family_t sun_family; // AF_UNIX
char sun_path[108]; // Pathname
};
*/
sunPath, err := readStringVarFromBuff(buff, 108)
if err != nil {
return nil, fmt.Errorf("error parsing sockaddr_un: %v", err)
}
res["sun_path"] = sunPath
case 2: // AF_INET
/*
http://man7.org/linux/man-pages/man7/ip.7.html
struct sockaddr_in {
sa_family_t sin_family; // address family: AF_INET
in_port_t sin_port; // port in network byte order
struct in_addr sin_addr; // internet address
};
struct in_addr {
uint32_t s_addr; // address in network byte order
};
*/
port, err := readUInt16BigendFromBuff(buff)
if err != nil {
return nil, fmt.Errorf("error parsing sockaddr_in: %v", err)
}
res["sin_port"] = strconv.Itoa(int(port))
addr, err := readUInt32BigendFromBuff(buff)
if err != nil {
return nil, fmt.Errorf("error parsing sockaddr_in: %v", err)
}
res["sin_addr"] = PrintUint32IP(addr)
case 10: // AF_INET6
/*
struct sockaddr_in6 {
sa_family_t sin6_family; // AF_INET6
in_port_t sin6_port; // port number
uint32_t sin6_flowinfo; // IPv6 flow information
struct in6_addr sin6_addr; // IPv6 address
uint32_t sin6_scope_id; // Scope ID (new in 2.4)
};
struct in6_addr {
unsigned char s6_addr[16]; // IPv6 address
};
*/
port, err := readUInt16BigendFromBuff(buff)
if err != nil {
return nil, fmt.Errorf("error parsing sockaddr_in6: %v", err)
}
res["sin6_port"] = strconv.Itoa(int(port))

flowinfo, err := readUInt32BigendFromBuff(buff)
if err != nil {
return nil, fmt.Errorf("error parsing sockaddr_in6: %v", err)
}
res["sin6_flowinfo"] = strconv.Itoa(int(flowinfo))
addr, err := readByteSliceFromBuff(buff, 16)
if err != nil {
return nil, fmt.Errorf("error parsing sockaddr_in6: %v", err)
}
res["sin6_addr"] = Print16BytesSliceIP(addr)
scopeid, err := readUInt32BigendFromBuff(buff)
if err != nil {
return nil, fmt.Errorf("error parsing sockaddr_in6: %v", err)
}
res["sin6_scopeid"] = strconv.Itoa(int(scopeid))
}
return res, nil
}

func readArgFromBuff(dataBuff io.Reader) (interface{}, error) {
var err error
var res interface{}
Expand Down Expand Up @@ -469,12 +592,11 @@ func readArgFromBuff(dataBuff io.Reader) (interface{}, error) {
}
res = fmt.Sprintf("%X", ptr)
case SOCKADDR_T:
// this is not really the sockaddr struct, but just the `sockaddr.sa_family`
family, err := readInt16FromBuff(dataBuff)
sockaddr, err := readSockaddrFromBuff(dataBuff)
if err != nil {
return nil, err
}
res = PrintSocketDomain(uint32(family))
res = fmt.Sprintf("%v", sockaddr)[3:] // remove the leading "map" string
case OPEN_FLAGS_T:
flags, err := readUInt32FromBuff(dataBuff)
if err != nil {
Expand Down

0 comments on commit 1ae06bc

Please sign in to comment.