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

     1  package portmapper
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  
     8  	"github.com/ishidawataru/sctp"
     9  )
    10  
    11  type userlandProxy interface {
    12  	Start() error
    13  	Stop() error
    14  }
    15  
    16  // ipVersion refers to IP version - v4 or v6
    17  type ipVersion string
    18  
    19  const (
    20  	// IPv4 is version 4
    21  	ipv4 ipVersion = "4"
    22  	// IPv4 is version 6
    23  	ipv6 ipVersion = "6"
    24  )
    25  
    26  // dummyProxy just listen on some port, it is needed to prevent accidental
    27  // port allocations on bound port, because without userland proxy we using
    28  // iptables rules and not net.Listen
    29  type dummyProxy struct {
    30  	listener  io.Closer
    31  	addr      net.Addr
    32  	ipVersion ipVersion
    33  }
    34  
    35  func newDummyProxy(proto string, hostIP net.IP, hostPort int) (userlandProxy, error) {
    36  	// detect version of hostIP to bind only to correct version
    37  	version := ipv4
    38  	if hostIP.To4() == nil {
    39  		version = ipv6
    40  	}
    41  	switch proto {
    42  	case "tcp":
    43  		addr := &net.TCPAddr{IP: hostIP, Port: hostPort}
    44  		return &dummyProxy{addr: addr, ipVersion: version}, nil
    45  	case "udp":
    46  		addr := &net.UDPAddr{IP: hostIP, Port: hostPort}
    47  		return &dummyProxy{addr: addr, ipVersion: version}, nil
    48  	case "sctp":
    49  		addr := &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: hostIP}}, Port: hostPort}
    50  		return &dummyProxy{addr: addr, ipVersion: version}, nil
    51  	default:
    52  		return nil, fmt.Errorf("Unknown addr type: %s", proto)
    53  	}
    54  }
    55  
    56  func (p *dummyProxy) Start() error {
    57  	switch addr := p.addr.(type) {
    58  	case *net.TCPAddr:
    59  		l, err := net.ListenTCP("tcp"+string(p.ipVersion), addr)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		p.listener = l
    64  	case *net.UDPAddr:
    65  		l, err := net.ListenUDP("udp"+string(p.ipVersion), addr)
    66  		if err != nil {
    67  			return err
    68  		}
    69  		p.listener = l
    70  	case *sctp.SCTPAddr:
    71  		l, err := sctp.ListenSCTP("sctp"+string(p.ipVersion), addr)
    72  		if err != nil {
    73  			return err
    74  		}
    75  		p.listener = l
    76  	default:
    77  		return fmt.Errorf("Unknown addr type: %T", p.addr)
    78  	}
    79  	return nil
    80  }
    81  
    82  func (p *dummyProxy) Stop() error {
    83  	if p.listener != nil {
    84  		return p.listener.Close()
    85  	}
    86  	return nil
    87  }