github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/trace/sni/tracer/tracer.go (about)

     1  // Copyright 2019-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  //go:build !withoutebpf
    16  
    17  package tracer
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"unsafe"
    24  
    25  	gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context"
    26  	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets"
    27  	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/sni/types"
    28  	"github.com/inspektor-gadget/inspektor-gadget/pkg/networktracer"
    29  	eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
    30  )
    31  
    32  //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags ${CFLAGS} -type event_t snisnoop ./bpf/snisnoop.c -- $CLANG_OS_FLAGS -I./bpf/
    33  
    34  const (
    35  	TLSMaxServerNameLen = len(snisnoopEventT{}.Name)
    36  )
    37  
    38  type Tracer struct {
    39  	*networktracer.Tracer[types.Event]
    40  
    41  	ctx    context.Context
    42  	cancel context.CancelFunc
    43  }
    44  
    45  func NewTracer() (*Tracer, error) {
    46  	t := &Tracer{}
    47  
    48  	if err := t.install(); err != nil {
    49  		t.Close()
    50  		return nil, fmt.Errorf("installing tracer: %w", err)
    51  	}
    52  
    53  	return t, nil
    54  }
    55  
    56  // RunWorkaround is used by pkg/gadget-collection/gadgets/trace/sni/gadget.go to run the gadget
    57  // after calling NewTracer()
    58  func (t *Tracer) RunWorkaround() error {
    59  	if err := t.run(); err != nil {
    60  		t.Close()
    61  
    62  		return fmt.Errorf("running tracer: %w", err)
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func parseSNIEvent(sample []byte, netns uint64) (*types.Event, error) {
    69  	bpfEvent := (*snisnoopEventT)(unsafe.Pointer(&sample[0]))
    70  	if len(sample) < int(unsafe.Sizeof(*bpfEvent)) {
    71  		return nil, errors.New("invalid sample size")
    72  	}
    73  
    74  	timestamp := gadgets.WallTimeFromBootTime(bpfEvent.Timestamp)
    75  
    76  	name := gadgets.FromCString(bpfEvent.Name[:])
    77  	if len(name) == 0 {
    78  		return nil, nil
    79  	}
    80  
    81  	event := types.Event{
    82  		Event: eventtypes.Event{
    83  			Type:      eventtypes.NORMAL,
    84  			Timestamp: timestamp,
    85  		},
    86  		Pid:           bpfEvent.Pid,
    87  		Tid:           bpfEvent.Tid,
    88  		Uid:           bpfEvent.Uid,
    89  		Gid:           bpfEvent.Gid,
    90  		WithMountNsID: eventtypes.WithMountNsID{MountNsID: bpfEvent.MountNsId},
    91  		WithNetNsID:   eventtypes.WithNetNsID{NetNsID: netns},
    92  		Comm:          gadgets.FromCString(bpfEvent.Task[:]),
    93  
    94  		Name: name,
    95  	}
    96  
    97  	return &event, nil
    98  }
    99  
   100  // --- Registry changes
   101  
   102  func (g *GadgetDesc) NewInstance() (gadgets.Gadget, error) {
   103  	return &Tracer{}, nil
   104  }
   105  
   106  func (t *Tracer) Init(gadgetCtx gadgets.GadgetContext) error {
   107  	if err := t.install(); err != nil {
   108  		t.Close()
   109  		return fmt.Errorf("installing tracer: %w", err)
   110  	}
   111  
   112  	t.ctx, t.cancel = gadgetcontext.WithTimeoutOrCancel(gadgetCtx.Context(), gadgetCtx.Timeout())
   113  	return nil
   114  }
   115  
   116  func (t *Tracer) install() error {
   117  	networkTracer, err := networktracer.NewTracer[types.Event]()
   118  	if err != nil {
   119  		return fmt.Errorf("creating network tracer: %w", err)
   120  	}
   121  	t.Tracer = networkTracer
   122  	return nil
   123  }
   124  
   125  func (t *Tracer) run() error {
   126  	spec, err := loadSnisnoop()
   127  	if err != nil {
   128  		return fmt.Errorf("loading asset: %w", err)
   129  	}
   130  
   131  	err = t.Tracer.Run(spec, types.Base, parseSNIEvent)
   132  	if err != nil {
   133  		return fmt.Errorf("setting network tracer spec: %w", err)
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  func (t *Tracer) Run(gadgetCtx gadgets.GadgetContext) error {
   140  	if err := t.run(); err != nil {
   141  		return nil
   142  	}
   143  
   144  	<-t.ctx.Done()
   145  	return nil
   146  }
   147  
   148  func (t *Tracer) Close() {
   149  	if t.cancel != nil {
   150  		t.cancel()
   151  	}
   152  
   153  	if t.Tracer != nil {
   154  		t.Tracer.Close()
   155  	}
   156  }