Merge pull request #2403 from thaJeztah/carry_2370_sctp_update
[carry 2370] Update sctp package
This commit is contained in:
commit
c3d402cef3
11 changed files with 391 additions and 101 deletions
|
@ -51,8 +51,8 @@ func parseHostContainerAddrs() (host net.Addr, container net.Addr) {
|
|||
host = &net.UDPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort}
|
||||
container = &net.UDPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort}
|
||||
case "sctp":
|
||||
host = &sctp.SCTPAddr{IP: []net.IP{net.ParseIP(*hostIP)}, Port: *hostPort}
|
||||
container = &sctp.SCTPAddr{IP: []net.IP{net.ParseIP(*containerIP)}, Port: *containerPort}
|
||||
host = &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: net.ParseIP(*hostIP)}}, Port: *hostPort}
|
||||
container = &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: net.ParseIP(*containerIP)}}, Port: *containerPort}
|
||||
default:
|
||||
log.Fatalf("unsupported protocol %s", *proto)
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ func TestSCTP4Proxy(t *testing.T) {
|
|||
backend := NewEchoServer(t, "sctp", "127.0.0.1:0", EchoServerOptions{})
|
||||
defer backend.Close()
|
||||
backend.Run()
|
||||
frontendAddr := &sctp.SCTPAddr{IP: []net.IP{net.IPv4(127, 0, 0, 1)}, Port: 0}
|
||||
frontendAddr := &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: net.IPv4(127, 0, 0, 1)}}, Port: 0}
|
||||
proxy, err := NewProxy(frontendAddr, backend.LocalAddr())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -298,7 +298,7 @@ func TestSCTP6Proxy(t *testing.T) {
|
|||
backend := NewEchoServer(t, "sctp", "[::1]:0", EchoServerOptions{})
|
||||
defer backend.Close()
|
||||
backend.Run()
|
||||
frontendAddr := &sctp.SCTPAddr{IP: []net.IP{net.IPv6loopback}, Port: 0}
|
||||
frontendAddr := &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: net.IPv6loopback}}, Port: 0}
|
||||
proxy, err := NewProxy(frontendAddr, backend.LocalAddr())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -115,16 +115,16 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart,
|
|||
|
||||
m = &mapping{
|
||||
proto: proto,
|
||||
host: &sctp.SCTPAddr{IP: []net.IP{hostIP}, Port: allocatedHostPort},
|
||||
host: &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: hostIP}}, Port: allocatedHostPort},
|
||||
container: container,
|
||||
}
|
||||
|
||||
if useProxy {
|
||||
sctpAddr := container.(*sctp.SCTPAddr)
|
||||
if len(sctpAddr.IP) == 0 {
|
||||
if len(sctpAddr.IPAddrs) == 0 {
|
||||
return nil, ErrSCTPAddrNoIP
|
||||
}
|
||||
m.userlandProxy, err = newProxy(proto, hostIP, allocatedHostPort, sctpAddr.IP[0], sctpAddr.Port, pm.proxyPath)
|
||||
m.userlandProxy, err = newProxy(proto, hostIP, allocatedHostPort, sctpAddr.IPAddrs[0].IP, sctpAddr.Port, pm.proxyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -210,10 +210,10 @@ func (pm *PortMapper) Unmap(host net.Addr) error {
|
|||
case *net.UDPAddr:
|
||||
return pm.Allocator.ReleasePort(a.IP, "udp", a.Port)
|
||||
case *sctp.SCTPAddr:
|
||||
if len(a.IP) == 0 {
|
||||
if len(a.IPAddrs) == 0 {
|
||||
return ErrSCTPAddrNoIP
|
||||
}
|
||||
return pm.Allocator.ReleasePort(a.IP[0], "sctp", a.Port)
|
||||
return pm.Allocator.ReleasePort(a.IPAddrs[0].IP, "sctp", a.Port)
|
||||
}
|
||||
return ErrUnknownBackendAddressType
|
||||
}
|
||||
|
@ -239,11 +239,11 @@ func getKey(a net.Addr) string {
|
|||
case *net.UDPAddr:
|
||||
return fmt.Sprintf("%s:%d/%s", t.IP.String(), t.Port, "udp")
|
||||
case *sctp.SCTPAddr:
|
||||
if len(t.IP) == 0 {
|
||||
if len(t.IPAddrs) == 0 {
|
||||
logrus.Error(ErrSCTPAddrNoIP)
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s:%d/%s", t.IP[0].String(), t.Port, "sctp")
|
||||
return fmt.Sprintf("%s:%d/%s", t.IPAddrs[0].IP.String(), t.Port, "sctp")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -255,11 +255,11 @@ func getIPAndPort(a net.Addr) (net.IP, int) {
|
|||
case *net.UDPAddr:
|
||||
return t.IP, t.Port
|
||||
case *sctp.SCTPAddr:
|
||||
if len(t.IP) == 0 {
|
||||
if len(t.IPAddrs) == 0 {
|
||||
logrus.Error(ErrSCTPAddrNoIP)
|
||||
return nil, 0
|
||||
}
|
||||
return t.IP[0], t.Port
|
||||
return t.IPAddrs[0].IP, t.Port
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ func newDummyProxy(proto string, hostIP net.IP, hostPort int) (userlandProxy, er
|
|||
addr := &net.UDPAddr{IP: hostIP, Port: hostPort}
|
||||
return &dummyProxy{addr: addr}, nil
|
||||
case "sctp":
|
||||
addr := &sctp.SCTPAddr{IP: []net.IP{hostIP}, Port: hostPort}
|
||||
addr := &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: hostIP}}, Port: hostPort}
|
||||
return &dummyProxy{addr: addr}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("Unknown addr type: %s", proto)
|
||||
|
|
|
@ -99,7 +99,7 @@ func (p PortBinding) HostAddr() (net.Addr, error) {
|
|||
case TCP:
|
||||
return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
|
||||
case SCTP:
|
||||
return &sctp.SCTPAddr{IP: []net.IP{p.HostIP}, Port: int(p.HostPort)}, nil
|
||||
return &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: p.HostIP}}, Port: int(p.HostPort)}, nil
|
||||
default:
|
||||
return nil, ErrInvalidProtocolBinding(p.Proto.String())
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ func (p PortBinding) ContainerAddr() (net.Addr, error) {
|
|||
case TCP:
|
||||
return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil
|
||||
case SCTP:
|
||||
return &sctp.SCTPAddr{IP: []net.IP{p.IP}, Port: int(p.Port)}, nil
|
||||
return &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: p.IP}}, Port: int(p.Port)}, nil
|
||||
default:
|
||||
return nil, ErrInvalidProtocolBinding(p.Proto.String())
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ golang.org/x/net a680a1efc54dd51c040b3b5ce4939ea3cf2ea0d1
|
|||
golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba
|
||||
golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
|
||||
github.com/pkg/errors ba968bfe8b2f7e042a574c888954fccecfa385b4 # v0.8.1
|
||||
github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb
|
||||
github.com/ishidawataru/sctp 6e2cb1366111dcf547c13531e3a263a067715847
|
||||
|
||||
gotest.tools b6e20af1ed078cd01a6413b734051a292450b4cb # v2.1.0
|
||||
github.com/google/go-cmp 3af367b6b30c263d47e8895973edcca9a49cf029 # v0.2.0
|
||||
|
|
27
libnetwork/vendor/github.com/ishidawataru/sctp/GO_LICENSE
generated
vendored
Normal file
27
libnetwork/vendor/github.com/ishidawataru/sctp/GO_LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
218
libnetwork/vendor/github.com/ishidawataru/sctp/ipsock_linux.go
generated
vendored
Normal file
218
libnetwork/vendor/github.com/ishidawataru/sctp/ipsock_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,218 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
//from https://github.com/golang/go
|
||||
// Boolean to int.
|
||||
func boolint(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
func ipToSockaddr(family int, ip net.IP, port int, zone string) (syscall.Sockaddr, error) {
|
||||
switch family {
|
||||
case syscall.AF_INET:
|
||||
if len(ip) == 0 {
|
||||
ip = net.IPv4zero
|
||||
}
|
||||
ip4 := ip.To4()
|
||||
if ip4 == nil {
|
||||
return nil, &net.AddrError{Err: "non-IPv4 address", Addr: ip.String()}
|
||||
}
|
||||
sa := &syscall.SockaddrInet4{Port: port}
|
||||
copy(sa.Addr[:], ip4)
|
||||
return sa, nil
|
||||
case syscall.AF_INET6:
|
||||
// In general, an IP wildcard address, which is either
|
||||
// "0.0.0.0" or "::", means the entire IP addressing
|
||||
// space. For some historical reason, it is used to
|
||||
// specify "any available address" on some operations
|
||||
// of IP node.
|
||||
//
|
||||
// When the IP node supports IPv4-mapped IPv6 address,
|
||||
// we allow an listener to listen to the wildcard
|
||||
// address of both IP addressing spaces by specifying
|
||||
// IPv6 wildcard address.
|
||||
if len(ip) == 0 || ip.Equal(net.IPv4zero) {
|
||||
ip = net.IPv6zero
|
||||
}
|
||||
// We accept any IPv6 address including IPv4-mapped
|
||||
// IPv6 address.
|
||||
ip6 := ip.To16()
|
||||
if ip6 == nil {
|
||||
return nil, &net.AddrError{Err: "non-IPv6 address", Addr: ip.String()}
|
||||
}
|
||||
//we set ZoneId to 0, as currently we use this functon only to probe the IP capabilities of the host
|
||||
//if real Zone handling is required, the zone cache implementation in golang/net should be pulled here
|
||||
sa := &syscall.SockaddrInet6{Port: port, ZoneId: 0}
|
||||
copy(sa.Addr[:], ip6)
|
||||
return sa, nil
|
||||
}
|
||||
return nil, &net.AddrError{Err: "invalid address family", Addr: ip.String()}
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
func sockaddr(a *net.TCPAddr, family int) (syscall.Sockaddr, error) {
|
||||
if a == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
type ipStackCapabilities struct {
|
||||
sync.Once // guards following
|
||||
ipv4Enabled bool
|
||||
ipv6Enabled bool
|
||||
ipv4MappedIPv6Enabled bool
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
var ipStackCaps ipStackCapabilities
|
||||
|
||||
//from https://github.com/golang/go
|
||||
// supportsIPv4 reports whether the platform supports IPv4 networking
|
||||
// functionality.
|
||||
func supportsIPv4() bool {
|
||||
ipStackCaps.Once.Do(ipStackCaps.probe)
|
||||
return ipStackCaps.ipv4Enabled
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
// supportsIPv6 reports whether the platform supports IPv6 networking
|
||||
// functionality.
|
||||
func supportsIPv6() bool {
|
||||
ipStackCaps.Once.Do(ipStackCaps.probe)
|
||||
return ipStackCaps.ipv6Enabled
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
// supportsIPv4map reports whether the platform supports mapping an
|
||||
// IPv4 address inside an IPv6 address at transport layer
|
||||
// protocols. See RFC 4291, RFC 4038 and RFC 3493.
|
||||
func supportsIPv4map() bool {
|
||||
ipStackCaps.Once.Do(ipStackCaps.probe)
|
||||
return ipStackCaps.ipv4MappedIPv6Enabled
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
// Probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication
|
||||
// capabilities which are controlled by the IPV6_V6ONLY socket option
|
||||
// and kernel configuration.
|
||||
//
|
||||
// Should we try to use the IPv4 socket interface if we're only
|
||||
// dealing with IPv4 sockets? As long as the host system understands
|
||||
// IPv4-mapped IPv6, it's okay to pass IPv4-mapeed IPv6 addresses to
|
||||
// the IPv6 interface. That simplifies our code and is most
|
||||
// general. Unfortunately, we need to run on kernels built without
|
||||
// IPv6 support too. So probe the kernel to figure it out.
|
||||
func (p *ipStackCapabilities) probe() {
|
||||
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
|
||||
switch err {
|
||||
case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
|
||||
case nil:
|
||||
syscall.Close(s)
|
||||
p.ipv4Enabled = true
|
||||
}
|
||||
var probes = []struct {
|
||||
laddr net.TCPAddr
|
||||
value int
|
||||
}{
|
||||
// IPv6 communication capability
|
||||
{laddr: net.TCPAddr{IP: net.IPv6loopback}, value: 1},
|
||||
// IPv4-mapped IPv6 address communication capability
|
||||
{laddr: net.TCPAddr{IP: net.IPv4(127, 0, 0, 1)}, value: 0},
|
||||
}
|
||||
|
||||
for i := range probes {
|
||||
s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
|
||||
sa, err := sockaddr(&(probes[i].laddr), syscall.AF_INET6)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if err := syscall.Bind(s, sa); err != nil {
|
||||
continue
|
||||
}
|
||||
if i == 0 {
|
||||
p.ipv6Enabled = true
|
||||
} else {
|
||||
p.ipv4MappedIPv6Enabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
//Change: we check the first IP address in the list of candidate SCTP IP addresses
|
||||
func (a *SCTPAddr) isWildcard() bool {
|
||||
if a == nil {
|
||||
return true
|
||||
}
|
||||
if 0 == len(a.IPAddrs) {
|
||||
return true
|
||||
}
|
||||
|
||||
return a.IPAddrs[0].IP.IsUnspecified()
|
||||
}
|
||||
|
||||
func (a *SCTPAddr) family() int {
|
||||
if a != nil {
|
||||
for _, ip := range a.IPAddrs {
|
||||
if ip.IP.To4() == nil {
|
||||
return syscall.AF_INET6
|
||||
}
|
||||
}
|
||||
}
|
||||
return syscall.AF_INET
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
func favoriteAddrFamily(network string, laddr *SCTPAddr, raddr *SCTPAddr, mode string) (family int, ipv6only bool) {
|
||||
switch network[len(network)-1] {
|
||||
case '4':
|
||||
return syscall.AF_INET, false
|
||||
case '6':
|
||||
return syscall.AF_INET6, true
|
||||
}
|
||||
|
||||
if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
|
||||
if supportsIPv4map() || !supportsIPv4() {
|
||||
return syscall.AF_INET6, false
|
||||
}
|
||||
if laddr == nil {
|
||||
return syscall.AF_INET, false
|
||||
}
|
||||
return laddr.family(), false
|
||||
}
|
||||
|
||||
if (laddr == nil || laddr.family() == syscall.AF_INET) &&
|
||||
(raddr == nil || raddr.family() == syscall.AF_INET) {
|
||||
return syscall.AF_INET, false
|
||||
}
|
||||
return syscall.AF_INET6, false
|
||||
}
|
||||
|
||||
//from https://github.com/golang/go
|
||||
//Changes: it is for SCTP only
|
||||
func setDefaultSockopts(s int, family int, ipv6only bool) error {
|
||||
if family == syscall.AF_INET6 {
|
||||
// Allow both IP versions even if the OS default
|
||||
// is otherwise. Note that some operating systems
|
||||
// never admit this option.
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
|
||||
}
|
||||
// Allow broadcast.
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
|
||||
}
|
90
libnetwork/vendor/github.com/ishidawataru/sctp/sctp.go
generated
vendored
90
libnetwork/vendor/github.com/ishidawataru/sctp/sctp.go
generated
vendored
|
@ -197,37 +197,58 @@ func htons(h uint16) uint16 {
|
|||
|
||||
var ntohs = htons
|
||||
|
||||
func setNumOstreams(fd, num int) error {
|
||||
param := InitMsg{
|
||||
NumOstreams: uint16(num),
|
||||
}
|
||||
optlen := unsafe.Sizeof(param)
|
||||
_, _, err := setsockopt(fd, SCTP_INITMSG, uintptr(unsafe.Pointer(¶m)), uintptr(optlen))
|
||||
// setInitOpts sets options for an SCTP association initialization
|
||||
// see https://tools.ietf.org/html/rfc4960#page-25
|
||||
func setInitOpts(fd int, options InitMsg) error {
|
||||
optlen := unsafe.Sizeof(options)
|
||||
_, _, err := setsockopt(fd, SCTP_INITMSG, uintptr(unsafe.Pointer(&options)), uintptr(optlen))
|
||||
return err
|
||||
}
|
||||
|
||||
func setNumOstreams(fd, num int) error {
|
||||
return setInitOpts(fd, InitMsg{NumOstreams: uint16(num)})
|
||||
}
|
||||
|
||||
type SCTPAddr struct {
|
||||
IP []net.IP
|
||||
Port int
|
||||
IPAddrs []net.IPAddr
|
||||
Port int
|
||||
}
|
||||
|
||||
func (a *SCTPAddr) ToRawSockAddrBuf() []byte {
|
||||
buf := []byte{}
|
||||
p := htons(uint16(a.Port))
|
||||
for _, ip := range a.IP {
|
||||
if ip.To4() != nil {
|
||||
if len(a.IPAddrs) == 0 { // if a.IPAddrs list is empty - fall back to IPv4 zero addr
|
||||
s := syscall.RawSockaddrInet4{
|
||||
Family: syscall.AF_INET,
|
||||
Port: p,
|
||||
}
|
||||
copy(s.Addr[:], net.IPv4zero)
|
||||
return toBuf(s)
|
||||
}
|
||||
buf := []byte{}
|
||||
for _, ip := range a.IPAddrs {
|
||||
ipBytes := ip.IP
|
||||
if len(ipBytes) == 0 {
|
||||
ipBytes = net.IPv4zero
|
||||
}
|
||||
if ip4 := ipBytes.To4(); ip4 != nil {
|
||||
s := syscall.RawSockaddrInet4{
|
||||
Family: syscall.AF_INET,
|
||||
Port: p,
|
||||
}
|
||||
copy(s.Addr[:], ip.To4())
|
||||
copy(s.Addr[:], ip4)
|
||||
buf = append(buf, toBuf(s)...)
|
||||
} else {
|
||||
s := syscall.RawSockaddrInet6{
|
||||
Family: syscall.AF_INET6,
|
||||
Port: p,
|
||||
var scopeid uint32
|
||||
ifi, err := net.InterfaceByName(ip.Zone)
|
||||
if err == nil {
|
||||
scopeid = uint32(ifi.Index)
|
||||
}
|
||||
copy(s.Addr[:], ip)
|
||||
s := syscall.RawSockaddrInet6{
|
||||
Family: syscall.AF_INET6,
|
||||
Port: p,
|
||||
Scope_id: scopeid,
|
||||
}
|
||||
copy(s.Addr[:], ipBytes)
|
||||
buf = append(buf, toBuf(s)...)
|
||||
}
|
||||
}
|
||||
|
@ -237,15 +258,15 @@ func (a *SCTPAddr) ToRawSockAddrBuf() []byte {
|
|||
func (a *SCTPAddr) String() string {
|
||||
var b bytes.Buffer
|
||||
|
||||
for n, i := range a.IP {
|
||||
if a.IP[n].To4() != nil {
|
||||
for n, i := range a.IPAddrs {
|
||||
if i.IP.To4() != nil {
|
||||
b.WriteString(i.String())
|
||||
} else if a.IP[n].To16() != nil {
|
||||
} else if i.IP.To16() != nil {
|
||||
b.WriteRune('[')
|
||||
b.WriteString(i.String())
|
||||
b.WriteRune(']')
|
||||
}
|
||||
if n < len(a.IP)-1 {
|
||||
if n < len(a.IPAddrs)-1 {
|
||||
b.WriteRune('/')
|
||||
}
|
||||
}
|
||||
|
@ -260,6 +281,7 @@ func ResolveSCTPAddr(network, addrs string) (*SCTPAddr, error) {
|
|||
tcpnet := ""
|
||||
switch network {
|
||||
case "", "sctp":
|
||||
tcpnet = "tcp"
|
||||
case "sctp4":
|
||||
tcpnet = "tcp4"
|
||||
case "sctp6":
|
||||
|
@ -271,26 +293,26 @@ func ResolveSCTPAddr(network, addrs string) (*SCTPAddr, error) {
|
|||
if len(elems) == 0 {
|
||||
return nil, fmt.Errorf("invalid input: %s", addrs)
|
||||
}
|
||||
ipaddrs := make([]net.IP, 0, len(elems))
|
||||
ipaddrs := make([]net.IPAddr, 0, len(elems))
|
||||
for _, e := range elems[:len(elems)-1] {
|
||||
tcpa, err := net.ResolveTCPAddr(tcpnet, e+":")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipaddrs = append(ipaddrs, tcpa.IP)
|
||||
ipaddrs = append(ipaddrs, net.IPAddr{IP: tcpa.IP, Zone: tcpa.Zone})
|
||||
}
|
||||
tcpa, err := net.ResolveTCPAddr(tcpnet, elems[len(elems)-1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tcpa.IP != nil {
|
||||
ipaddrs = append(ipaddrs, tcpa.IP)
|
||||
ipaddrs = append(ipaddrs, net.IPAddr{IP: tcpa.IP, Zone: tcpa.Zone})
|
||||
} else {
|
||||
ipaddrs = nil
|
||||
}
|
||||
return &SCTPAddr{
|
||||
IP: ipaddrs,
|
||||
Port: tcpa.Port,
|
||||
IPAddrs: ipaddrs,
|
||||
Port: tcpa.Port,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -357,15 +379,12 @@ func (c *SCTPConn) Read(b []byte) (int, error) {
|
|||
}
|
||||
|
||||
func (c *SCTPConn) SetInitMsg(numOstreams, maxInstreams, maxAttempts, maxInitTimeout int) error {
|
||||
param := InitMsg{
|
||||
return setInitOpts(c.fd(), InitMsg{
|
||||
NumOstreams: uint16(numOstreams),
|
||||
MaxInstreams: uint16(maxInstreams),
|
||||
MaxAttempts: uint16(maxAttempts),
|
||||
MaxInitTimeout: uint16(maxInitTimeout),
|
||||
}
|
||||
optlen := unsafe.Sizeof(param)
|
||||
_, _, err := setsockopt(c.fd(), SCTP_INITMSG, uintptr(unsafe.Pointer(¶m)), uintptr(optlen))
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (c *SCTPConn) SubscribeEvents(flags int) error {
|
||||
|
@ -473,7 +492,7 @@ func (c *SCTPConn) GetDefaultSentParam() (*SndRcvInfo, error) {
|
|||
|
||||
func resolveFromRawAddr(ptr unsafe.Pointer, n int) (*SCTPAddr, error) {
|
||||
addr := &SCTPAddr{
|
||||
IP: make([]net.IP, n),
|
||||
IPAddrs: make([]net.IPAddr, n),
|
||||
}
|
||||
|
||||
switch family := (*(*syscall.RawSockaddrAny)(ptr)).Addr.Family; family {
|
||||
|
@ -484,7 +503,7 @@ func resolveFromRawAddr(ptr unsafe.Pointer, n int) (*SCTPAddr, error) {
|
|||
for i := 0; i < n; i++ {
|
||||
a := *(*syscall.RawSockaddrInet4)(unsafe.Pointer(
|
||||
uintptr(ptr) + size*uintptr(i)))
|
||||
addr.IP[i] = a.Addr[:]
|
||||
addr.IPAddrs[i] = net.IPAddr{IP: a.Addr[:]}
|
||||
}
|
||||
case syscall.AF_INET6:
|
||||
addr.Port = int(ntohs(uint16((*(*syscall.RawSockaddrInet4)(ptr)).Port)))
|
||||
|
@ -493,7 +512,12 @@ func resolveFromRawAddr(ptr unsafe.Pointer, n int) (*SCTPAddr, error) {
|
|||
for i := 0; i < n; i++ {
|
||||
a := *(*syscall.RawSockaddrInet6)(unsafe.Pointer(
|
||||
uintptr(ptr) + size*uintptr(i)))
|
||||
addr.IP[i] = a.Addr[:]
|
||||
var zone string
|
||||
ifi, err := net.InterfaceByIndex(int(a.Scope_id))
|
||||
if err == nil {
|
||||
zone = ifi.Name
|
||||
}
|
||||
addr.IPAddrs[i] = net.IPAddr{IP: a.Addr[:], Zone: zone}
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown address family: %d", family)
|
||||
|
|
111
libnetwork/vendor/github.com/ishidawataru/sctp/sctp_linux.go
generated
vendored
111
libnetwork/vendor/github.com/ishidawataru/sctp/sctp_linux.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
|
@ -115,31 +114,14 @@ func (c *SCTPConn) Close() error {
|
|||
return syscall.EBADF
|
||||
}
|
||||
|
||||
// ListenSCTP - start listener on specified address/port
|
||||
func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
||||
af := syscall.AF_INET
|
||||
switch net {
|
||||
case "sctp":
|
||||
hasv6 := func(addr *SCTPAddr) bool {
|
||||
if addr == nil {
|
||||
return false
|
||||
}
|
||||
for _, ip := range addr.IP {
|
||||
if ip.To4() == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if hasv6(laddr) {
|
||||
af = syscall.AF_INET6
|
||||
}
|
||||
case "sctp4":
|
||||
case "sctp6":
|
||||
af = syscall.AF_INET6
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid net: %s", net)
|
||||
}
|
||||
return ListenSCTPExt(net, laddr, InitMsg{NumOstreams: SCTP_MAX_STREAM})
|
||||
}
|
||||
|
||||
// ListenSCTPExt - start listener on specified address/port with given SCTP options
|
||||
func ListenSCTPExt(network string, laddr *SCTPAddr, options InitMsg) (*SCTPListener, error) {
|
||||
af, ipv6only := favoriteAddrFamily(network, laddr, nil, "listen")
|
||||
sock, err := syscall.Socket(
|
||||
af,
|
||||
syscall.SOCK_STREAM,
|
||||
|
@ -148,11 +130,30 @@ func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setNumOstreams(sock, SCTP_MAX_STREAM)
|
||||
|
||||
// close socket on error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
syscall.Close(sock)
|
||||
}
|
||||
}()
|
||||
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setInitOpts(sock, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if laddr != nil && len(laddr.IP) != 0 {
|
||||
|
||||
if laddr != nil {
|
||||
// If IP address and/or port was not provided so far, let's use the unspecified IPv4 or IPv6 address
|
||||
if len(laddr.IPAddrs) == 0 {
|
||||
if af == syscall.AF_INET {
|
||||
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv4zero})
|
||||
} else if af == syscall.AF_INET6 {
|
||||
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv6zero})
|
||||
}
|
||||
}
|
||||
err := SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -167,40 +168,30 @@ func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (ln *SCTPListener) Accept() (net.Conn, error) {
|
||||
// AcceptSCTP waits for and returns the next SCTP connection to the listener.
|
||||
func (ln *SCTPListener) AcceptSCTP() (*SCTPConn, error) {
|
||||
fd, _, err := syscall.Accept4(ln.fd, 0)
|
||||
return NewSCTPConn(fd, nil), err
|
||||
}
|
||||
|
||||
// Accept waits for and returns the next connection connection to the listener.
|
||||
func (ln *SCTPListener) Accept() (net.Conn, error) {
|
||||
return ln.AcceptSCTP()
|
||||
}
|
||||
|
||||
func (ln *SCTPListener) Close() error {
|
||||
syscall.Shutdown(ln.fd, syscall.SHUT_RDWR)
|
||||
return syscall.Close(ln.fd)
|
||||
}
|
||||
|
||||
// DialSCTP - bind socket to laddr (if given) and connect to raddr
|
||||
func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
||||
af := syscall.AF_INET
|
||||
switch net {
|
||||
case "sctp":
|
||||
hasv6 := func(addr *SCTPAddr) bool {
|
||||
if addr == nil {
|
||||
return false
|
||||
}
|
||||
for _, ip := range addr.IP {
|
||||
if ip.To4() == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if hasv6(laddr) || hasv6(raddr) {
|
||||
af = syscall.AF_INET6
|
||||
}
|
||||
case "sctp4":
|
||||
case "sctp6":
|
||||
af = syscall.AF_INET6
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid net: %s", net)
|
||||
}
|
||||
return DialSCTPExt(net, laddr, raddr, InitMsg{NumOstreams: SCTP_MAX_STREAM})
|
||||
}
|
||||
|
||||
// DialSCTPExt - same as DialSCTP but with given SCTP options
|
||||
func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTPConn, error) {
|
||||
af, ipv6only := favoriteAddrFamily(network, laddr, raddr, "dial")
|
||||
sock, err := syscall.Socket(
|
||||
af,
|
||||
syscall.SOCK_STREAM,
|
||||
|
@ -209,11 +200,29 @@ func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setNumOstreams(sock, SCTP_MAX_STREAM)
|
||||
|
||||
// close socket on error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
syscall.Close(sock)
|
||||
}
|
||||
}()
|
||||
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setInitOpts(sock, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if laddr != nil {
|
||||
// If IP address and/or port was not provided so far, let's use the unspecified IPv4 or IPv6 address
|
||||
if len(laddr.IPAddrs) == 0 {
|
||||
if af == syscall.AF_INET {
|
||||
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv4zero})
|
||||
} else if af == syscall.AF_INET6 {
|
||||
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv6zero})
|
||||
}
|
||||
}
|
||||
err := SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
12
libnetwork/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
generated
vendored
12
libnetwork/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
generated
vendored
|
@ -34,10 +34,18 @@ func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
|||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func ListenSCTPExt(net string, laddr *SCTPAddr, options InitMsg) (*SCTPListener, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func (ln *SCTPListener) Accept() (net.Conn, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func (ln *SCTPListener) AcceptSCTP() (*SCTPConn, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func (ln *SCTPListener) Close() error {
|
||||
return ErrUnsupported
|
||||
}
|
||||
|
@ -45,3 +53,7 @@ func (ln *SCTPListener) Close() error {
|
|||
func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTPConn, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue