github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/operators/socketenricher/socketenricher.go (about)

     1  // Copyright 2023-2024 The Inspektor Gadget authors
     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 socketenricher creates an eBPF map exposing processes owning each socket.
    16  //
    17  // This makes it possible for network gadgets to access that information and display it directly
    18  // from the BPF code. Example of such code in the dns and sni gadgets.
    19  package socketenricher
    20  
    21  import (
    22  	"fmt"
    23  	"sync"
    24  
    25  	"github.com/cilium/ebpf"
    26  	log "github.com/sirupsen/logrus"
    27  
    28  	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-service/api"
    29  	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets"
    30  	"github.com/inspektor-gadget/inspektor-gadget/pkg/operators"
    31  	"github.com/inspektor-gadget/inspektor-gadget/pkg/params"
    32  	tracer "github.com/inspektor-gadget/inspektor-gadget/pkg/socketenricher"
    33  )
    34  
    35  const (
    36  	OperatorName = "SocketEnricher"
    37  )
    38  
    39  type SocketEnricherInterface interface {
    40  	SetSocketEnricherMap(*ebpf.Map)
    41  }
    42  
    43  type SocketEnricher struct {
    44  	mu             sync.Mutex
    45  	socketEnricher *tracer.SocketEnricher
    46  	refCount       int
    47  }
    48  
    49  func (s *SocketEnricher) Name() string {
    50  	return OperatorName
    51  }
    52  
    53  func (s *SocketEnricher) Description() string {
    54  	return "Socket enricher provides process information for sockets"
    55  }
    56  
    57  func (s *SocketEnricher) GlobalParamDescs() params.ParamDescs {
    58  	return nil
    59  }
    60  
    61  func (s *SocketEnricher) ParamDescs() params.ParamDescs {
    62  	return nil
    63  }
    64  
    65  func (s *SocketEnricher) Dependencies() []string {
    66  	return nil
    67  }
    68  
    69  func (s *SocketEnricher) CanOperateOn(gadget gadgets.GadgetDesc) bool {
    70  	gi, ok := gadget.(gadgets.GadgetInstantiate)
    71  	if !ok {
    72  		return false
    73  	}
    74  
    75  	instance, err := gi.NewInstance()
    76  	if err != nil {
    77  		log.Warnf("failed to create dummy %s instance: %s", OperatorName, err)
    78  		return false
    79  	}
    80  
    81  	_, hasSocketEnricherInterface := instance.(SocketEnricherInterface)
    82  	return hasSocketEnricherInterface
    83  }
    84  
    85  func (s *SocketEnricher) Init(params *params.Params) error {
    86  	return nil
    87  }
    88  
    89  func (s *SocketEnricher) Close() error {
    90  	s.mu.Lock()
    91  	defer s.mu.Unlock()
    92  
    93  	if s.socketEnricher != nil {
    94  		s.socketEnricher.Close()
    95  		s.socketEnricher = nil
    96  	}
    97  	return nil
    98  }
    99  
   100  func (s *SocketEnricher) Instantiate(gadgetCtx operators.GadgetContext, gadgetInstance any, params *params.Params) (operators.OperatorInstance, error) {
   101  	return &SocketEnricherInstance{
   102  		gadgetCtx:      gadgetCtx,
   103  		manager:        s,
   104  		gadgetInstance: gadgetInstance,
   105  	}, nil
   106  }
   107  
   108  type SocketEnricherInstance struct {
   109  	gadgetCtx      operators.GadgetContext
   110  	manager        *SocketEnricher
   111  	gadgetInstance any
   112  }
   113  
   114  func (i *SocketEnricherInstance) Name() string {
   115  	return "SocketEnricherInstance"
   116  }
   117  
   118  func (i *SocketEnricherInstance) PreGadgetRun() error {
   119  	setter, ok := i.gadgetInstance.(SocketEnricherInterface)
   120  	if !ok {
   121  		return fmt.Errorf("gadget doesn't implement socket enricher interface")
   122  	}
   123  
   124  	i.manager.mu.Lock()
   125  	defer i.manager.mu.Unlock()
   126  
   127  	if i.manager.refCount == 0 {
   128  		t, err := tracer.NewSocketEnricher()
   129  		if err != nil {
   130  			return err
   131  		}
   132  		i.manager.socketEnricher = t
   133  	}
   134  
   135  	i.manager.refCount++
   136  
   137  	setter.SetSocketEnricherMap(i.manager.socketEnricher.SocketsMap())
   138  
   139  	return nil
   140  }
   141  
   142  func (i *SocketEnricherInstance) PostGadgetRun() error {
   143  	i.manager.mu.Lock()
   144  	defer i.manager.mu.Unlock()
   145  
   146  	i.manager.refCount--
   147  	if i.manager.refCount == 0 {
   148  		i.manager.socketEnricher.Close()
   149  		i.manager.socketEnricher = nil
   150  	}
   151  
   152  	return nil
   153  }
   154  
   155  func (i *SocketEnricherInstance) EnrichEvent(ev any) error {
   156  	return nil
   157  }
   158  
   159  func (s *SocketEnricher) GlobalParams() api.Params {
   160  	return nil
   161  }
   162  
   163  func (s *SocketEnricher) InstanceParams() api.Params {
   164  	return nil
   165  }
   166  
   167  func (s *SocketEnricher) InstantiateDataOperator(gadgetCtx operators.GadgetContext, instanceParamValues api.ParamValues) (operators.DataOperatorInstance, error) {
   168  	if _, ok := gadgetCtx.GetVar(tracer.SocketsMapName); !ok {
   169  		return nil, nil
   170  	}
   171  
   172  	instance := &SocketEnricherInstance{
   173  		gadgetCtx: gadgetCtx,
   174  		manager:   s,
   175  	}
   176  	instance.gadgetInstance = instance
   177  	return instance, nil
   178  }
   179  
   180  func (s *SocketEnricher) Priority() int {
   181  	return 10
   182  }
   183  
   184  func (i *SocketEnricherInstance) PreStart(gadgetCtx operators.GadgetContext) error {
   185  	return i.PreGadgetRun()
   186  }
   187  
   188  func (i *SocketEnricherInstance) Start(gadgetCtx operators.GadgetContext) error {
   189  	return nil
   190  }
   191  
   192  func (i *SocketEnricherInstance) Stop(gadgetCtx operators.GadgetContext) error {
   193  	return i.PostGadgetRun()
   194  }
   195  
   196  func (i *SocketEnricherInstance) SetSocketEnricherMap(m *ebpf.Map) {
   197  	i.gadgetCtx.Logger().Debugf("setting sockets map")
   198  	i.gadgetCtx.SetVar(tracer.SocketsMapName, m)
   199  }
   200  
   201  func init() {
   202  	op := &SocketEnricher{}
   203  	operators.Register(op)
   204  	operators.RegisterDataOperator(op)
   205  }