github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/ns/init_linux.go (about)

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