github.com/vishvananda/netlink@v1.3.0/proc_event_linux.go (about)

     1  package netlink
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"os"
     8  	"syscall"
     9  
    10  	"github.com/vishvananda/netlink/nl"
    11  	"github.com/vishvananda/netns"
    12  	"golang.org/x/sys/unix"
    13  )
    14  
    15  const CN_IDX_PROC = 0x1
    16  
    17  const (
    18  	PROC_EVENT_NONE     = 0x00000000
    19  	PROC_EVENT_FORK     = 0x00000001
    20  	PROC_EVENT_EXEC     = 0x00000002
    21  	PROC_EVENT_UID      = 0x00000004
    22  	PROC_EVENT_GID      = 0x00000040
    23  	PROC_EVENT_SID      = 0x00000080
    24  	PROC_EVENT_PTRACE   = 0x00000100
    25  	PROC_EVENT_COMM     = 0x00000200
    26  	PROC_EVENT_COREDUMP = 0x40000000
    27  	PROC_EVENT_EXIT     = 0x80000000
    28  )
    29  
    30  const (
    31  	CN_VAL_PROC          = 0x1
    32  	PROC_CN_MCAST_LISTEN = 0x1
    33  )
    34  
    35  type ProcEventMsg interface {
    36  	Pid() uint32
    37  	Tgid() uint32
    38  }
    39  
    40  type ProcEventHeader struct {
    41  	What      uint32
    42  	CPU       uint32
    43  	Timestamp uint64
    44  }
    45  
    46  type ProcEvent struct {
    47  	ProcEventHeader
    48  	Msg ProcEventMsg
    49  }
    50  
    51  func (pe *ProcEvent) setHeader(h ProcEventHeader) {
    52  	pe.What = h.What
    53  	pe.CPU = h.CPU
    54  	pe.Timestamp = h.Timestamp
    55  }
    56  
    57  type ExitProcEvent struct {
    58  	ProcessPid  uint32
    59  	ProcessTgid uint32
    60  	ExitCode    uint32
    61  	ExitSignal  uint32
    62  	ParentPid   uint32
    63  	ParentTgid  uint32
    64  }
    65  
    66  func (e *ExitProcEvent) Pid() uint32 {
    67  	return e.ProcessPid
    68  }
    69  
    70  func (e *ExitProcEvent) Tgid() uint32 {
    71  	return e.ProcessTgid
    72  }
    73  
    74  type ExecProcEvent struct {
    75  	ProcessPid  uint32
    76  	ProcessTgid uint32
    77  }
    78  
    79  func (e *ExecProcEvent) Pid() uint32 {
    80  	return e.ProcessPid
    81  }
    82  
    83  func (e *ExecProcEvent) Tgid() uint32 {
    84  	return e.ProcessTgid
    85  }
    86  
    87  type ForkProcEvent struct {
    88  	ParentPid  uint32
    89  	ParentTgid uint32
    90  	ChildPid   uint32
    91  	ChildTgid  uint32
    92  }
    93  
    94  func (e *ForkProcEvent) Pid() uint32 {
    95  	return e.ParentPid
    96  }
    97  
    98  func (e *ForkProcEvent) Tgid() uint32 {
    99  	return e.ParentTgid
   100  }
   101  
   102  type CommProcEvent struct {
   103  	ProcessPid  uint32
   104  	ProcessTgid uint32
   105  	Comm        [16]byte
   106  }
   107  
   108  func (e *CommProcEvent) Pid() uint32 {
   109  	return e.ProcessPid
   110  }
   111  
   112  func (e *CommProcEvent) Tgid() uint32 {
   113  	return e.ProcessTgid
   114  }
   115  
   116  func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error {
   117  	h, err := NewHandle()
   118  	if err != nil {
   119  		return err
   120  	}
   121  	defer h.Delete()
   122  
   123  	s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC)
   124  	if err != nil {
   125  		return err
   126  	}
   127  
   128  	var nlmsg nl.NetlinkRequest
   129  
   130  	nlmsg.Pid = uint32(os.Getpid())
   131  	nlmsg.Type = unix.NLMSG_DONE
   132  	nlmsg.Len = uint32(unix.SizeofNlMsghdr)
   133  
   134  	cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN)
   135  	nlmsg.AddData(cm)
   136  
   137  	s.Send(&nlmsg)
   138  
   139  	if done != nil {
   140  		go func() {
   141  			<-done
   142  			s.Close()
   143  		}()
   144  	}
   145  
   146  	go func() {
   147  		defer close(ch)
   148  		for {
   149  			msgs, from, err := s.Receive()
   150  			if err != nil {
   151  				errorChan <- err
   152  				return
   153  			}
   154  			if from.Pid != nl.PidKernel {
   155  				errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
   156  				return
   157  			}
   158  
   159  			for _, m := range msgs {
   160  				e := parseNetlinkMessage(m)
   161  				if e != nil {
   162  					ch <- *e
   163  				}
   164  			}
   165  
   166  		}
   167  	}()
   168  
   169  	return nil
   170  }
   171  
   172  func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent {
   173  	if m.Header.Type == unix.NLMSG_DONE {
   174  		buf := bytes.NewBuffer(m.Data)
   175  		msg := &nl.CnMsg{}
   176  		hdr := &ProcEventHeader{}
   177  		binary.Read(buf, nl.NativeEndian(), msg)
   178  		binary.Read(buf, nl.NativeEndian(), hdr)
   179  
   180  		pe := &ProcEvent{}
   181  		pe.setHeader(*hdr)
   182  		switch hdr.What {
   183  		case PROC_EVENT_EXIT:
   184  			event := &ExitProcEvent{}
   185  			binary.Read(buf, nl.NativeEndian(), event)
   186  			pe.Msg = event
   187  			return pe
   188  		case PROC_EVENT_FORK:
   189  			event := &ForkProcEvent{}
   190  			binary.Read(buf, nl.NativeEndian(), event)
   191  			pe.Msg = event
   192  			return pe
   193  		case PROC_EVENT_EXEC:
   194  			event := &ExecProcEvent{}
   195  			binary.Read(buf, nl.NativeEndian(), event)
   196  			pe.Msg = event
   197  			return pe
   198  		case PROC_EVENT_COMM:
   199  			event := &CommProcEvent{}
   200  			binary.Read(buf, nl.NativeEndian(), event)
   201  			pe.Msg = event
   202  			return pe
   203  		}
   204  		return nil
   205  	}
   206  
   207  	return nil
   208  }