github.com/containerd/nerdctl@v1.7.7/pkg/bypass4netnsutil/bypass.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package bypass4netnsutil
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net"
    23  	"path/filepath"
    24  
    25  	"github.com/containerd/errdefs"
    26  	gocni "github.com/containerd/go-cni"
    27  	b4nnapi "github.com/rootless-containers/bypass4netns/pkg/api"
    28  	"github.com/rootless-containers/bypass4netns/pkg/api/daemon/client"
    29  	rlkclient "github.com/rootless-containers/rootlesskit/pkg/api/client"
    30  )
    31  
    32  func NewBypass4netnsCNIBypassManager(client client.Client, rlkClient rlkclient.Client) (*Bypass4netnsCNIBypassManager, error) {
    33  	if client == nil || rlkClient == nil {
    34  		return nil, errdefs.ErrInvalidArgument
    35  	}
    36  	pm := &Bypass4netnsCNIBypassManager{
    37  		Client:    client,
    38  		rlkClient: rlkClient,
    39  	}
    40  	return pm, nil
    41  }
    42  
    43  type Bypass4netnsCNIBypassManager struct {
    44  	client.Client
    45  	rlkClient rlkclient.Client
    46  }
    47  
    48  func (b4nnm *Bypass4netnsCNIBypassManager) StartBypass(ctx context.Context, ports []gocni.PortMapping, id, stateDir string) error {
    49  	socketPath, err := GetSocketPathByID(id)
    50  	if err != nil {
    51  		return err
    52  	}
    53  	pidFilePath, err := GetPidFilePathByID(id)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	logFilePath := filepath.Join(stateDir, "bypass4netns.log")
    58  
    59  	rlkInfo, err := b4nnm.rlkClient.Info(ctx)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	if rlkInfo.NetworkDriver == nil {
    64  		return fmt.Errorf("no network driver is set in RootlessKit info: %+v", rlkInfo)
    65  	}
    66  	rlkIP := rlkInfo.NetworkDriver.ChildIP
    67  	const mask = 24 // currently hard-coded
    68  	rlkCIDR := fmt.Sprintf("%s/%d", rlkIP.Mask(net.CIDRMask(mask, 32)), mask)
    69  
    70  	spec := b4nnapi.BypassSpec{
    71  		ID:          id,
    72  		SocketPath:  socketPath,
    73  		PidFilePath: pidFilePath,
    74  		LogFilePath: logFilePath,
    75  		// "auto" can detect CNI CIDRs automatically
    76  		IgnoreSubnets: []string{"127.0.0.0/8", rlkCIDR, "auto"},
    77  	}
    78  	portMap := []b4nnapi.PortSpec{}
    79  	for _, p := range ports {
    80  		portMap = append(portMap, b4nnapi.PortSpec{
    81  			ParentIP:   p.HostIP,
    82  			ParentPort: int(p.HostPort),
    83  			ChildPort:  int(p.ContainerPort),
    84  			Protos:     []string{p.Protocol},
    85  		})
    86  	}
    87  	spec.PortMapping = portMap
    88  	_, err = b4nnm.BypassManager().StartBypass(ctx, spec)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	return nil
    94  }
    95  
    96  func (b4nnm *Bypass4netnsCNIBypassManager) StopBypass(ctx context.Context, id string) error {
    97  	err := b4nnm.BypassManager().StopBypass(ctx, id)
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	return nil
   103  }