mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 08:34:40 +01:00

We'll try to dump the AF_PACKET sockets from the kernel. If it's not possible, we'll fallback to read /proc/net/packet.
172 lines
5.3 KiB
Go
172 lines
5.3 KiB
Go
package netlink
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/log"
|
|
"github.com/vishvananda/netlink/nl"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// request:
|
|
// {nlmsg_len=36, nlmsg_type=SOCK_DIAG_BY_FAMILY, nlmsg_flags=NLM_F_REQUEST|NLM_F_DUMP, nlmsg_seq=123456, nlmsg_pid=0},
|
|
// {sdiag_family=AF_PACKET, sdiag_protocol=0, pdiag_ino=0, pdiag_show=PACKET_SHOW_INFO, pdiag_cookie=[0, 0]}
|
|
|
|
// responses (depends on what filters are passed in the request):
|
|
// {pdiag_family=AF_PACKET, pdiag_type=SOCK_RAW, pdiag_num=ETH_P_ALL, pdiag_ino=257944535, pdiag_cookie=[1291434, 0]},
|
|
// {nla_len=28, nla_type=PACKET_DIAG_INFO},
|
|
// {pdi_index=if_nametoindex("wifi0"), pdi_version=TPACKET_V3, pdi_reserve=4, pdi_copy_thresh=0, pdi_tstamp=0, pdi_flags=PDI_RUNNING|PDI_AUXDATA}
|
|
// {nla_len=8, nla_type=PACKET_DIAG_UID}, 0}
|
|
// {nla_len=32, nla_type=PACKET_DIAG_RX_RING},
|
|
// {pdr_block_size=262144, pdr_block_nr=8, pdr_frame_size=262144, pdr_frame_nr=8, pdr_retire_tmo=10, pdr_sizeof_priv=0, pdr_features=0}
|
|
// {nla_len=40, nla_type=PACKET_DIAG_MEMINFO},
|
|
// [[SK_MEMINFO_RMEM_ALLOC]=0, [SK_MEMINFO_RCVBUF]=212992, [SK_MEMINFO_WMEM_ALLOC]=0, [SK_MEMINFO_SNDBUF]=212992, [SK_MEMINFO_FWD_ALLOC]=0, [SK_MEMINFO_WMEM_QUEUED]=0, [SK_MEMINFO_OPTMEM]=128, [SK_MEMINFO_BACKLOG]=0, [SK_MEMINFO_DROPS]=0]],
|
|
// {nla_len=12, nla_type=PACKET_DIAG_FILTER}, 0x512e76dfc140}
|
|
|
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/packet_diag.h#L16
|
|
// list of possible information to request
|
|
const (
|
|
PACKET_SHOW_INFO = 0x00000001 /* Basic packet_sk information */
|
|
PACKET_SHOW_MCLIST = 0x00000002 /* A set of packet_diag_mclist-s */
|
|
PACKET_SHOW_RING_CFG = 0x00000004 /* Rings configuration parameters */
|
|
PACKET_SHOW_FANOUT = 0x00000008
|
|
PACKET_SHOW_MEMINFO = 0x00000010
|
|
PACKET_SHOW_FILTER = 0x00000020
|
|
)
|
|
|
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/packet_diag.h#L32
|
|
// types of messages retrieved from kernel
|
|
const (
|
|
PACKET_DIAG_INFO = iota
|
|
PACKET_DIAG_MCLIST
|
|
PACKET_DIAG_RX_RING
|
|
PACKET_DIAG_TX_RING
|
|
PACKET_DIAG_FANOUT
|
|
PACKET_DIAG_UID
|
|
PACKET_DIAG_MEMINFO
|
|
PACKET_DIAG_FILTER
|
|
)
|
|
|
|
const (
|
|
sizePktDiagReq = 20
|
|
sizePktDiagMclist = 28
|
|
)
|
|
|
|
// PacketDiagMsg holds the message(s) sent by the kernel
|
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/packet_diag.h#L23
|
|
type PacketDiagMsg struct {
|
|
Mclist PacketDiagMclist
|
|
Cookie [2]uint32
|
|
Inode uint32
|
|
UID uint32
|
|
Num uint16 // ETH_P_ALL, etc
|
|
Family uint8
|
|
Type uint8
|
|
}
|
|
|
|
// PacketDiagMclist struct
|
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/packet_diag.h#L63
|
|
type PacketDiagMclist struct {
|
|
Index uint32
|
|
Count uint32
|
|
Type uint16
|
|
Alen uint16
|
|
Addr [32]uint8 /* MAX_ADDR_LEN */
|
|
}
|
|
|
|
func (pm *PacketDiagMsg) deserialize(b []byte) error {
|
|
rb := readBuffer{Bytes: b}
|
|
|
|
// 1st message: PacketDiagMsg
|
|
pm.Family = rb.Read()
|
|
pm.Type = rb.Read()
|
|
pm.Num = native.Uint16(rb.Next(2))
|
|
pm.Inode = native.Uint32(rb.Next(4))
|
|
pm.Cookie[0] = native.Uint32(rb.Next(4))
|
|
pm.Cookie[1] = native.Uint32(rb.Next(4))
|
|
|
|
nextMsg := rb.Read() // next msg size
|
|
if nextMsg == sizePktDiagMclist {
|
|
pm.Mclist = PacketDiagMclist{
|
|
// XXX: wrong values with native.Uint32()
|
|
Index: binary.BigEndian.Uint32(rb.Next(4)),
|
|
Count: binary.BigEndian.Uint32(rb.Next(4)),
|
|
Type: binary.BigEndian.Uint16(rb.Next(2)),
|
|
Alen: binary.BigEndian.Uint16(rb.Next(2)),
|
|
}
|
|
copy(pm.Mclist.Addr[:], rb.Next(16))
|
|
}
|
|
|
|
// {nla_len=8, nla_type=PACKET_DIAG_UID}, 1000}
|
|
nextMsg = rb.Read() // 8, size of next msg
|
|
nextMsg = rb.Read() // pad?
|
|
if nextMsg == PACKET_DIAG_UID {
|
|
rb.Read() // pad?
|
|
pm.UID = native.Uint32(rb.Next(4))
|
|
}
|
|
log.Trace("PktDiagMsg.deserialize (size: %d, sizeOf(PacketDiagMsg): %d): %+v", len(b), unsafe.Sizeof(b), pm)
|
|
|
|
return nil
|
|
}
|
|
|
|
// PacketDiagReq struct to request data from the kernel
|
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/packet_diag.h#L7
|
|
type PacketDiagReq struct {
|
|
Family uint8
|
|
Protocol uint8
|
|
Pad uint16
|
|
Inode uint32
|
|
Show uint32
|
|
Cookie [2]uint32
|
|
}
|
|
|
|
// Serialize ...
|
|
func (p *PacketDiagReq) Serialize() []byte {
|
|
b := writeBuffer{Bytes: make([]byte, sizePktDiagReq)}
|
|
b.Write(p.Family)
|
|
b.Write(p.Protocol)
|
|
native.PutUint16(b.Next(2), p.Pad)
|
|
native.PutUint32(b.Next(4), p.Inode)
|
|
native.PutUint32(b.Next(4), p.Show)
|
|
native.PutUint32(b.Next(4), p.Cookie[0])
|
|
native.PutUint32(b.Next(4), p.Cookie[1])
|
|
|
|
return b.Bytes
|
|
}
|
|
|
|
// Len ...
|
|
func (p *PacketDiagReq) Len() int { return sizePktDiagReq }
|
|
|
|
// SocketDiagPacket dumps AF_PACKET sockets from kernel
|
|
func SocketDiagPacket(proto uint8) ([]*PacketDiagMsg, error) {
|
|
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, syscall.NLM_F_DUMP)
|
|
req.AddData(&PacketDiagReq{
|
|
Family: unix.AF_PACKET,
|
|
Protocol: proto,
|
|
// TODO: dump bpf filters | PACKET_SHOW_FILTER
|
|
Show: PACKET_SHOW_INFO | PACKET_SHOW_MCLIST,
|
|
})
|
|
msgs, err := req.Execute(syscall.NETLINK_INET_DIAG, 0)
|
|
if err != nil {
|
|
log.Debug("[netlink] socket.packetRequest: %s", err)
|
|
return nil, err
|
|
}
|
|
if len(msgs) == 0 {
|
|
log.Debug("[netlink] socket.packetRequest: 0 msgs")
|
|
return []*PacketDiagMsg{}, nil
|
|
}
|
|
|
|
pkts := make([]*PacketDiagMsg, len(msgs))
|
|
for n, m := range msgs {
|
|
log.Trace("[netlink] AF_PACKET, size: %d, %+v", len(m), m)
|
|
p := &PacketDiagMsg{}
|
|
if err = p.deserialize(m); err != nil {
|
|
log.Trace("[%d] netlink socket.packet error: %s", n, err)
|
|
continue
|
|
}
|
|
pkts[n] = p
|
|
}
|
|
return pkts, nil
|
|
}
|