github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/ns/init_linux.go (about)

     1  package ns
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os/exec"
     7  	"strings"
     8  	"sync"
     9  	"syscall"
    10  	"time"
    11  
    12  	"github.com/containerd/log"
    13  	"github.com/vishvananda/netlink"
    14  	"github.com/vishvananda/netns"
    15  )
    16  
    17  var (
    18  	initNs   netns.NsHandle
    19  	initNl   *netlink.Handle
    20  	initOnce sync.Once
    21  	// NetlinkSocketsTimeout represents the default timeout duration for the sockets
    22  	NetlinkSocketsTimeout = 3 * time.Second
    23  )
    24  
    25  // Init initializes a new network namespace
    26  func Init() {
    27  	var err error
    28  	initNs, err = netns.Get()
    29  	if err != nil {
    30  		log.G(context.TODO()).Errorf("could not get initial namespace: %v", err)
    31  	}
    32  	initNl, err = netlink.NewHandle(getSupportedNlFamilies()...)
    33  	if err != nil {
    34  		log.G(context.TODO()).Errorf("could not create netlink handle on initial namespace: %v", err)
    35  	}
    36  	err = initNl.SetSocketTimeout(NetlinkSocketsTimeout)
    37  	if err != nil {
    38  		log.G(context.TODO()).Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err)
    39  	}
    40  }
    41  
    42  // ParseHandlerInt transforms the namespace handler into an integer
    43  func ParseHandlerInt() int {
    44  	return int(getHandler())
    45  }
    46  
    47  // GetHandler returns the namespace handler
    48  func getHandler() netns.NsHandle {
    49  	initOnce.Do(Init)
    50  	return initNs
    51  }
    52  
    53  // NlHandle returns the netlink handler
    54  func NlHandle() *netlink.Handle {
    55  	initOnce.Do(Init)
    56  	return initNl
    57  }
    58  
    59  func getSupportedNlFamilies() []int {
    60  	fams := []int{syscall.NETLINK_ROUTE}
    61  	// NETLINK_XFRM test
    62  	if err := checkXfrmSocket(); err != nil {
    63  		log.G(context.TODO()).Warnf("Could not load necessary modules for IPSEC rules: %v", err)
    64  	} else {
    65  		fams = append(fams, syscall.NETLINK_XFRM)
    66  	}
    67  	// NETLINK_NETFILTER test
    68  	if err := loadNfConntrackModules(); err != nil {
    69  		if checkNfSocket() != nil {
    70  			log.G(context.TODO()).Warnf("Could not load necessary modules for Conntrack: %v", err)
    71  		} else {
    72  			fams = append(fams, syscall.NETLINK_NETFILTER)
    73  		}
    74  	} else {
    75  		fams = append(fams, syscall.NETLINK_NETFILTER)
    76  	}
    77  
    78  	return fams
    79  }
    80  
    81  // API check on required xfrm modules (xfrm_user, xfrm_algo)
    82  func checkXfrmSocket() error {
    83  	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_XFRM)
    84  	if err != nil {
    85  		return err
    86  	}
    87  	syscall.Close(fd)
    88  	return nil
    89  }
    90  
    91  func loadNfConntrackModules() error {
    92  	if out, err := exec.Command("modprobe", "-va", "nf_conntrack").CombinedOutput(); err != nil {
    93  		return fmt.Errorf("Running modprobe nf_conntrack failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
    94  	}
    95  	if out, err := exec.Command("modprobe", "-va", "nf_conntrack_netlink").CombinedOutput(); err != nil {
    96  		return fmt.Errorf("Running modprobe nf_conntrack_netlink failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
    97  	}
    98  	return nil
    99  }
   100  
   101  // API check on required nf_conntrack* modules (nf_conntrack, nf_conntrack_netlink)
   102  func checkNfSocket() error {
   103  	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_NETFILTER)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	syscall.Close(fd)
   108  	return nil
   109  }