k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/proxy/util/nfacct/handler.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  /*
     5  Copyright 2024 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package nfacct
    21  
    22  import (
    23  	"github.com/vishvananda/netlink/nl"
    24  	"github.com/vishvananda/netns"
    25  	"golang.org/x/sys/unix"
    26  )
    27  
    28  // handler is an injectable interface for creating netlink request.
    29  type handler interface {
    30  	newRequest(cmd int, flags uint16) request
    31  }
    32  
    33  // request is an injectable interface representing a netlink request.
    34  type request interface {
    35  	Serialize() []byte
    36  	AddData(data nl.NetlinkRequestData)
    37  	AddRawData(data []byte)
    38  	Execute(sockType int, resType uint16) ([][]byte, error)
    39  }
    40  
    41  // netlinkHandler is an implementation of the handler interface. It maintains a netlink socket
    42  // for communication with the NFAcct subsystem.
    43  type netlinkHandler struct {
    44  	socket *nl.NetlinkSocket
    45  }
    46  
    47  // newNetlinkHandler initializes a netlink socket in the current network namespace and returns
    48  // an instance of netlinkHandler with the initialized socket.
    49  func newNetlinkHandler() (handler, error) {
    50  	socket, err := nl.GetNetlinkSocketAt(netns.None(), netns.None(), unix.NETLINK_NETFILTER)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	return &netlinkHandler{socket: socket}, nil
    55  }
    56  
    57  // newRequest creates a netlink request tailored for the NFAcct subsystem encapsulating the
    58  // specified cmd and flags. It incorporates the netlink header and netfilter generic header
    59  // into the resulting request.
    60  func (n *netlinkHandler) newRequest(cmd int, flags uint16) request {
    61  	req := &nl.NetlinkRequest{
    62  		// netlink message header
    63  		// (definition: https://github.com/torvalds/linux/blob/v6.7/include/uapi/linux/netlink.h#L44-L58)
    64  		NlMsghdr: unix.NlMsghdr{
    65  			Len:   uint32(unix.SizeofNlMsghdr),
    66  			Type:  uint16(cmd | (unix.NFNL_SUBSYS_ACCT << 8)),
    67  			Flags: flags,
    68  		},
    69  		Sockets: map[int]*nl.SocketHandle{
    70  			unix.NETLINK_NETFILTER: {Socket: n.socket},
    71  		},
    72  		Data: []nl.NetlinkRequestData{
    73  			// netfilter generic message
    74  			// (definition: https://github.com/torvalds/linux/blob/v6.7/include/uapi/linux/netfilter/nfnetlink.h#L32-L38)
    75  			&nl.Nfgenmsg{
    76  				NfgenFamily: uint8(unix.AF_NETLINK),
    77  				Version:     nl.NFNETLINK_V0,
    78  				ResId:       0,
    79  			},
    80  		},
    81  	}
    82  	return req
    83  }