summaryrefslogtreecommitdiff
path: root/vendor/github.com/ishidawataru/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/ishidawataru/sctp')
-rw-r--r--vendor/github.com/ishidawataru/sctp/.gitignore2
-rw-r--r--vendor/github.com/ishidawataru/sctp/.travis.yml1
-rw-r--r--vendor/github.com/ishidawataru/sctp/GO_LICENSE27
-rw-r--r--vendor/github.com/ishidawataru/sctp/ipsock_linux.go218
-rw-r--r--vendor/github.com/ishidawataru/sctp/sctp.go88
-rw-r--r--vendor/github.com/ishidawataru/sctp/sctp_linux.go111
-rw-r--r--vendor/github.com/ishidawataru/sctp/sctp_unsupported.go12
7 files changed, 376 insertions, 83 deletions
diff --git a/vendor/github.com/ishidawataru/sctp/.gitignore b/vendor/github.com/ishidawataru/sctp/.gitignore
index a1338d685..cf2d826c1 100644
--- a/vendor/github.com/ishidawataru/sctp/.gitignore
+++ b/vendor/github.com/ishidawataru/sctp/.gitignore
@@ -12,3 +12,5 @@
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
+
+example/example
diff --git a/vendor/github.com/ishidawataru/sctp/.travis.yml b/vendor/github.com/ishidawataru/sctp/.travis.yml
index 64f85ef28..e72c57864 100644
--- a/vendor/github.com/ishidawataru/sctp/.travis.yml
+++ b/vendor/github.com/ishidawataru/sctp/.travis.yml
@@ -4,6 +4,7 @@ go:
- 1.7
- 1.8
- 1.9
+ - "1.10"
script:
- go test -v -race ./...
diff --git a/vendor/github.com/ishidawataru/sctp/GO_LICENSE b/vendor/github.com/ishidawataru/sctp/GO_LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/github.com/ishidawataru/sctp/GO_LICENSE
@@ -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.
diff --git a/vendor/github.com/ishidawataru/sctp/ipsock_linux.go b/vendor/github.com/ishidawataru/sctp/ipsock_linux.go
new file mode 100644
index 000000000..f5632b72d
--- /dev/null
+++ b/vendor/github.com/ishidawataru/sctp/ipsock_linux.go
@@ -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))
+}
diff --git a/vendor/github.com/ishidawataru/sctp/sctp.go b/vendor/github.com/ishidawataru/sctp/sctp.go
index cac1a889c..30d619640 100644
--- a/vendor/github.com/ishidawataru/sctp/sctp.go
+++ b/vendor/github.com/ishidawataru/sctp/sctp.go
@@ -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(&param)), 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 {
+ var scopeid uint32
+ ifi, err := net.InterfaceByName(ip.Zone)
+ if err == nil {
+ scopeid = uint32(ifi.Index)
+ }
s := syscall.RawSockaddrInet6{
- Family: syscall.AF_INET6,
- Port: p,
+ Family: syscall.AF_INET6,
+ Port: p,
+ Scope_id: scopeid,
}
- copy(s.Addr[:], ip)
+ 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(&param)), 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)
diff --git a/vendor/github.com/ishidawataru/sctp/sctp_linux.go b/vendor/github.com/ishidawataru/sctp/sctp_linux.go
index f93ab8622..5a6ad9378 100644
--- a/vendor/github.com/ishidawataru/sctp/sctp_linux.go
+++ b/vendor/github.com/ishidawataru/sctp/sctp_linux.go
@@ -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
diff --git a/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go b/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
index adcbf78b4..e5415843d 100644
--- a/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
+++ b/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
@@ -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
+}