Commit 5e4e3d8e authored by Russ Cox's avatar Russ Cox

net: avoid Shutdown during Close

Once we've evicted all the blocked I/O, the ref count
should go to zero quickly, so it should be safe to
postpone the close(2) until then.

Fixes #1898.
Fixes #2116.
Fixes #2122.

R=golang-dev, mikioh.mikioh, bradfitz, fullung, iant
CC=golang-dev
https://golang.org/cl/5649076
parent b7360b9b
...@@ -114,6 +114,12 @@ func TestSelfConnect(t *testing.T) { ...@@ -114,6 +114,12 @@ func TestSelfConnect(t *testing.T) {
if testing.Short() { if testing.Short() {
n = 1000 n = 1000
} }
switch runtime.GOOS {
case "darwin", "freebsd", "openbsd", "windows":
// Non-Linux systems take a long time to figure
// out that there is nothing listening on localhost.
n = 100
}
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
c, err := Dial("tcp", addr) c, err := Dial("tcp", addr)
if err == nil { if err == nil {
......
This diff is collapsed.
...@@ -272,11 +272,27 @@ func (fd *netFD) connect(ra syscall.Sockaddr) error { ...@@ -272,11 +272,27 @@ func (fd *netFD) connect(ra syscall.Sockaddr) error {
return syscall.Connect(fd.sysfd, ra) return syscall.Connect(fd.sysfd, ra)
} }
var errClosing = errors.New("use of closed network connection")
// Add a reference to this fd. // Add a reference to this fd.
func (fd *netFD) incref() { // If closing==true, mark the fd as closing.
// Returns an error if the fd cannot be used.
func (fd *netFD) incref(closing bool) error {
if fd == nil {
return errClosing
}
fd.sysmu.Lock() fd.sysmu.Lock()
if fd.closing {
fd.sysmu.Unlock()
return errClosing
}
fd.sysref++ fd.sysref++
if closing {
fd.closing = true
}
closing = fd.closing
fd.sysmu.Unlock() fd.sysmu.Unlock()
return nil
} }
// Remove a reference to this FD and close if we've been asked to do so (and // Remove a reference to this FD and close if we've been asked to do so (and
...@@ -284,7 +300,17 @@ func (fd *netFD) incref() { ...@@ -284,7 +300,17 @@ func (fd *netFD) incref() {
func (fd *netFD) decref() { func (fd *netFD) decref() {
fd.sysmu.Lock() fd.sysmu.Lock()
fd.sysref-- fd.sysref--
if fd.closing && fd.sysref == 0 && fd.sysfd != syscall.InvalidHandle { // NOTE(rsc): On Unix we check fd.sysref == 0 here before closing,
// but on Windows we have no way to wake up the blocked I/O other
// than closing the socket (or calling Shutdown, which breaks other
// programs that might have a reference to the socket). So there is
// a small race here that we might close fd.sysfd and then some other
// goroutine might start a read of fd.sysfd (having read it before we
// write InvalidHandle to it), which might refer to some other file
// if the specific handle value gets reused. I think handle values on
// Windows are not reused as aggressively as file descriptors on Unix,
// so this might be tolerable.
if fd.closing && fd.sysfd != syscall.InvalidHandle {
// In case the user has set linger, switch to blocking mode so // In case the user has set linger, switch to blocking mode so
// the close blocks. As long as this doesn't happen often, we // the close blocks. As long as this doesn't happen often, we
// can handle the extra OS processes. Otherwise we'll need to // can handle the extra OS processes. Otherwise we'll need to
...@@ -299,13 +325,9 @@ func (fd *netFD) decref() { ...@@ -299,13 +325,9 @@ func (fd *netFD) decref() {
} }
func (fd *netFD) Close() error { func (fd *netFD) Close() error {
if fd == nil || fd.sysfd == syscall.InvalidHandle { if err := fd.incref(true); err != nil {
return os.EINVAL return err
} }
fd.incref()
syscall.Shutdown(fd.sysfd, syscall.SHUT_RDWR)
fd.closing = true
fd.decref() fd.decref()
return nil return nil
} }
...@@ -350,7 +372,9 @@ func (fd *netFD) Read(buf []byte) (int, error) { ...@@ -350,7 +372,9 @@ func (fd *netFD) Read(buf []byte) (int, error) {
} }
fd.rio.Lock() fd.rio.Lock()
defer fd.rio.Unlock() defer fd.rio.Unlock()
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
if fd.sysfd == syscall.InvalidHandle { if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL return 0, os.EINVAL
...@@ -390,11 +414,10 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { ...@@ -390,11 +414,10 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
} }
fd.rio.Lock() fd.rio.Lock()
defer fd.rio.Unlock() defer fd.rio.Unlock()
fd.incref() if err := fd.incref(false); err != nil {
defer fd.decref() return 0, nil, err
if fd.sysfd == syscall.InvalidHandle {
return 0, nil, os.EINVAL
} }
defer fd.decref()
var o readFromOp var o readFromOp
o.Init(fd, buf, 'r') o.Init(fd, buf, 'r')
o.rsan = int32(unsafe.Sizeof(o.rsa)) o.rsan = int32(unsafe.Sizeof(o.rsa))
...@@ -427,11 +450,10 @@ func (fd *netFD) Write(buf []byte) (int, error) { ...@@ -427,11 +450,10 @@ func (fd *netFD) Write(buf []byte) (int, error) {
} }
fd.wio.Lock() fd.wio.Lock()
defer fd.wio.Unlock() defer fd.wio.Unlock()
fd.incref() if err := fd.incref(false); err != nil {
defer fd.decref() return 0, err
if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL
} }
defer fd.decref()
var o writeOp var o writeOp
o.Init(fd, buf, 'w') o.Init(fd, buf, 'w')
return iosrv.ExecIO(&o, fd.wdeadline) return iosrv.ExecIO(&o, fd.wdeadline)
...@@ -462,7 +484,9 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { ...@@ -462,7 +484,9 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
} }
fd.wio.Lock() fd.wio.Lock()
defer fd.wio.Unlock() defer fd.wio.Unlock()
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
if fd.sysfd == syscall.InvalidHandle { if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL return 0, os.EINVAL
...@@ -493,10 +517,9 @@ func (o *acceptOp) Name() string { ...@@ -493,10 +517,9 @@ func (o *acceptOp) Name() string {
} }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
if fd == nil || fd.sysfd == syscall.InvalidHandle { if err := fd.incref(false); err != nil {
return nil, os.EINVAL return 0, err
} }
fd.incref()
defer fd.decref() defer fd.decref()
// Get new socket. // Get new socket.
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"regexp" "regexp"
"runtime" "runtime"
"testing" "testing"
"time"
) )
var runErrorTest = flag.Bool("run_error_test", false, "let TestDialError check for dns errors") var runErrorTest = flag.Bool("run_error_test", false, "let TestDialError check for dns errors")
...@@ -173,3 +174,58 @@ func TestShutdown(t *testing.T) { ...@@ -173,3 +174,58 @@ func TestShutdown(t *testing.T) {
t.Errorf("read = %q, want \"response\"", got) t.Errorf("read = %q, want \"response\"", got)
} }
} }
func TestTCPListenClose(t *testing.T) {
l, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
done := make(chan bool, 1)
go func() {
time.Sleep(100 * time.Millisecond)
l.Close()
}()
go func() {
_, err = l.Accept()
if err == nil {
t.Error("Accept succeeded")
} else {
t.Logf("Accept timeout error: %s (any error is fine)", err)
}
done <- true
}()
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("timeout waiting for TCP close")
}
}
func TestUDPListenClose(t *testing.T) {
l, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
buf := make([]byte, 1000)
done := make(chan bool, 1)
go func() {
time.Sleep(100 * time.Millisecond)
l.Close()
}()
go func() {
_, _, err = l.ReadFrom(buf)
if err == nil {
t.Error("ReadFrom succeeded")
} else {
t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
}
done <- true
}()
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("timeout waiting for UDP close")
}
}
...@@ -38,7 +38,9 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) { ...@@ -38,7 +38,9 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
c.wio.Lock() c.wio.Lock()
defer c.wio.Unlock() defer c.wio.Unlock()
c.incref() if err := c.incref(false); err != nil {
return 0, err, true
}
defer c.decref() defer c.decref()
dst := c.sysfd dst := c.sysfd
...@@ -57,9 +59,10 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) { ...@@ -57,9 +59,10 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
break break
} }
if err1 == syscall.EAGAIN && c.wdeadline >= 0 { if err1 == syscall.EAGAIN && c.wdeadline >= 0 {
pollserver.WaitWrite(c) if err1 = pollserver.WaitWrite(c); err1 == nil {
continue continue
} }
}
if err1 != nil { if err1 != nil {
// This includes syscall.ENOSYS (no kernel // This includes syscall.ENOSYS (no kernel
// support) and syscall.EINVAL (fd types which // support) and syscall.EINVAL (fd types which
......
...@@ -50,7 +50,9 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) { ...@@ -50,7 +50,9 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
c.wio.Lock() c.wio.Lock()
defer c.wio.Unlock() defer c.wio.Unlock()
c.incref() if err := c.incref(); err != nil {
return 0, err, true
}
defer c.decref() defer c.decref()
var o sendfileOp var o sendfileOp
......
...@@ -83,7 +83,7 @@ func connect(t *testing.T, network, addr string, isEmpty bool) { ...@@ -83,7 +83,7 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
} }
// Send explicit ending for unixpacket. // Send explicit ending for unixpacket.
// Older Linux kernels do stop reads on close. // Older Linux kernels do not stop reads on close.
if network == "unixpacket" { if network == "unixpacket" {
fd.Write([]byte("END")) fd.Write([]byte("END"))
} }
......
...@@ -105,13 +105,17 @@ done: ...@@ -105,13 +105,17 @@ done:
} }
func setReadBuffer(fd *netFD, bytes int) error { func setReadBuffer(fd *netFD, bytes int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)) return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
} }
func setWriteBuffer(fd *netFD, bytes int) error { func setWriteBuffer(fd *netFD, bytes int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)) return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
} }
...@@ -142,25 +146,33 @@ func setDeadline(fd *netFD, t time.Time) error { ...@@ -142,25 +146,33 @@ func setDeadline(fd *netFD, t time.Time) error {
} }
func setReuseAddr(fd *netFD, reuse bool) error { func setReuseAddr(fd *netFD, reuse bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))) return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse)))
} }
func setDontRoute(fd *netFD, dontroute bool) error { func setDontRoute(fd *netFD, dontroute bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))) return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute)))
} }
func setKeepAlive(fd *netFD, keepalive bool) error { func setKeepAlive(fd *netFD, keepalive bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))) return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
} }
func setNoDelay(fd *netFD, noDelay bool) error { func setNoDelay(fd *netFD, noDelay bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))) return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
} }
...@@ -174,7 +186,9 @@ func setLinger(fd *netFD, sec int) error { ...@@ -174,7 +186,9 @@ func setLinger(fd *netFD, sec int) error {
l.Onoff = 0 l.Onoff = 0
l.Linger = 0 l.Linger = 0
} }
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l)) return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
} }
...@@ -14,17 +14,21 @@ import ( ...@@ -14,17 +14,21 @@ import (
) )
func ipv4TOS(fd *netFD) (int, error) { func ipv4TOS(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS)
if err != nil { if err != nil {
return -1, os.NewSyscallError("getsockopt", err) return 0, os.NewSyscallError("getsockopt", err)
} }
return v, nil return v, nil
} }
func setIPv4TOS(fd *netFD, v int) error { func setIPv4TOS(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS, v)
if err != nil { if err != nil {
...@@ -34,17 +38,21 @@ func setIPv4TOS(fd *netFD, v int) error { ...@@ -34,17 +38,21 @@ func setIPv4TOS(fd *netFD, v int) error {
} }
func ipv4TTL(fd *netFD) (int, error) { func ipv4TTL(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL)
if err != nil { if err != nil {
return -1, os.NewSyscallError("getsockopt", err) return 0, os.NewSyscallError("getsockopt", err)
} }
return v, nil return v, nil
} }
func setIPv4TTL(fd *netFD, v int) error { func setIPv4TTL(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL, v)
if err != nil { if err != nil {
...@@ -58,7 +66,9 @@ func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error { ...@@ -58,7 +66,9 @@ func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
if err := setIPv4MreqToInterface(mreq, ifi); err != nil { if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
return err return err
} }
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)) return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
} }
...@@ -68,23 +78,29 @@ func leaveIPv4Group(fd *netFD, ifi *Interface, ip IP) error { ...@@ -68,23 +78,29 @@ func leaveIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
if err := setIPv4MreqToInterface(mreq, ifi); err != nil { if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
return err return err
} }
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)) return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
} }
func ipv6HopLimit(fd *netFD) (int, error) { func ipv6HopLimit(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS)
if err != nil { if err != nil {
return -1, os.NewSyscallError("getsockopt", err) return 0, os.NewSyscallError("getsockopt", err)
} }
return v, nil return v, nil
} }
func setIPv6HopLimit(fd *netFD, v int) error { func setIPv6HopLimit(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, v)
if err != nil { if err != nil {
...@@ -94,7 +110,9 @@ func setIPv6HopLimit(fd *netFD, v int) error { ...@@ -94,7 +110,9 @@ func setIPv6HopLimit(fd *netFD, v int) error {
} }
func ipv6MulticastInterface(fd *netFD) (*Interface, error) { func ipv6MulticastInterface(fd *netFD) (*Interface, error) {
fd.incref() if err := fd.incref(false); err != nil {
return nil, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF)
if err != nil { if err != nil {
...@@ -115,7 +133,9 @@ func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -115,7 +133,9 @@ func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
if ifi != nil { if ifi != nil {
v = ifi.Index v = ifi.Index
} }
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
if err != nil { if err != nil {
...@@ -125,17 +145,21 @@ func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -125,17 +145,21 @@ func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
} }
func ipv6MulticastHopLimit(fd *netFD) (int, error) { func ipv6MulticastHopLimit(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS)
if err != nil { if err != nil {
return -1, os.NewSyscallError("getsockopt", err) return 0, os.NewSyscallError("getsockopt", err)
} }
return v, nil return v, nil
} }
func setIPv6MulticastHopLimit(fd *netFD, v int) error { func setIPv6MulticastHopLimit(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, v)
if err != nil { if err != nil {
...@@ -145,7 +169,9 @@ func setIPv6MulticastHopLimit(fd *netFD, v int) error { ...@@ -145,7 +169,9 @@ func setIPv6MulticastHopLimit(fd *netFD, v int) error {
} }
func ipv6MulticastLoopback(fd *netFD) (bool, error) { func ipv6MulticastLoopback(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP)
if err != nil { if err != nil {
...@@ -155,7 +181,9 @@ func ipv6MulticastLoopback(fd *netFD) (bool, error) { ...@@ -155,7 +181,9 @@ func ipv6MulticastLoopback(fd *netFD) (bool, error) {
} }
func setIPv6MulticastLoopback(fd *netFD, v bool) error { func setIPv6MulticastLoopback(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
if err != nil { if err != nil {
...@@ -170,7 +198,9 @@ func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error { ...@@ -170,7 +198,9 @@ func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
if ifi != nil { if ifi != nil {
mreq.Interface = uint32(ifi.Index) mreq.Interface = uint32(ifi.Index)
} }
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)) return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
} }
...@@ -181,7 +211,9 @@ func leaveIPv6Group(fd *netFD, ifi *Interface, ip IP) error { ...@@ -181,7 +211,9 @@ func leaveIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
if ifi != nil { if ifi != nil {
mreq.Interface = uint32(ifi.Index) mreq.Interface = uint32(ifi.Index)
} }
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq)) return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq))
} }
...@@ -14,17 +14,21 @@ import ( ...@@ -14,17 +14,21 @@ import (
) )
func ipv4MulticastTTL(fd *netFD) (int, error) { func ipv4MulticastTTL(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL) v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
if err != nil { if err != nil {
return -1, os.NewSyscallError("getsockopt", err) return 0, os.NewSyscallError("getsockopt", err)
} }
return int(v), nil return int(v), nil
} }
func setIPv4MulticastTTL(fd *netFD, v int) error { func setIPv4MulticastTTL(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, byte(v)) err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, byte(v))
if err != nil { if err != nil {
...@@ -34,17 +38,21 @@ func setIPv4MulticastTTL(fd *netFD, v int) error { ...@@ -34,17 +38,21 @@ func setIPv4MulticastTTL(fd *netFD, v int) error {
} }
func ipv6TrafficClass(fd *netFD) (int, error) { func ipv6TrafficClass(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
if err != nil { if err != nil {
return -1, os.NewSyscallError("getsockopt", err) return 0, os.NewSyscallError("getsockopt", err)
} }
return v, nil return v, nil
} }
func setIPv6TrafficClass(fd *netFD, v int) error { func setIPv6TrafficClass(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
if err != nil { if err != nil {
......
...@@ -12,7 +12,9 @@ import ( ...@@ -12,7 +12,9 @@ import (
) )
func ipv4MulticastInterface(fd *netFD) (*Interface, error) { func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
fd.incref() if err := fd.incref(false); err != nil {
return nil, err
}
defer fd.decref() defer fd.decref()
a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF) a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil { if err != nil {
...@@ -28,7 +30,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -28,7 +30,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
} }
var x [4]byte var x [4]byte
copy(x[:], ip.To4()) copy(x[:], ip.To4())
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x) err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
if err != nil { if err != nil {
...@@ -38,7 +42,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -38,7 +42,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
} }
func ipv4MulticastLoopback(fd *netFD) (bool, error) { func ipv4MulticastLoopback(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil { if err != nil {
...@@ -48,7 +54,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) { ...@@ -48,7 +54,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) {
} }
func setIPv4MulticastLoopback(fd *netFD, v bool) error { func setIPv4MulticastLoopback(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil { if err != nil {
...@@ -58,7 +66,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error { ...@@ -58,7 +66,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error {
} }
func ipv4ReceiveInterface(fd *netFD) (bool, error) { func ipv4ReceiveInterface(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
if err != nil { if err != nil {
...@@ -68,7 +78,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) { ...@@ -68,7 +78,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) {
} }
func setIPv4ReceiveInterface(fd *netFD, v bool) error { func setIPv4ReceiveInterface(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
if err != nil { if err != nil {
......
...@@ -12,7 +12,9 @@ import ( ...@@ -12,7 +12,9 @@ import (
) )
func ipv4MulticastInterface(fd *netFD) (*Interface, error) { func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
fd.incref() if err := fd.incref(false); err != nil {
return nil, err
}
defer fd.decref() defer fd.decref()
mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF) mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil { if err != nil {
...@@ -30,7 +32,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -30,7 +32,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
v = int32(ifi.Index) v = int32(ifi.Index)
} }
mreq := &syscall.IPMreqn{Ifindex: v} mreq := &syscall.IPMreqn{Ifindex: v}
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq) err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
if err != nil { if err != nil {
...@@ -40,7 +44,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -40,7 +44,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
} }
func ipv4MulticastLoopback(fd *netFD) (bool, error) { func ipv4MulticastLoopback(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil { if err != nil {
...@@ -50,7 +56,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) { ...@@ -50,7 +56,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) {
} }
func setIPv4MulticastLoopback(fd *netFD, v bool) error { func setIPv4MulticastLoopback(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil { if err != nil {
...@@ -60,7 +68,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error { ...@@ -60,7 +68,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error {
} }
func ipv4ReceiveInterface(fd *netFD) (bool, error) { func ipv4ReceiveInterface(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
if err != nil { if err != nil {
...@@ -70,7 +80,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) { ...@@ -70,7 +80,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) {
} }
func setIPv4ReceiveInterface(fd *netFD, v bool) error { func setIPv4ReceiveInterface(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
if err != nil { if err != nil {
......
...@@ -12,7 +12,9 @@ import ( ...@@ -12,7 +12,9 @@ import (
) )
func ipv4MulticastInterface(fd *netFD) (*Interface, error) { func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
fd.incref() if err := fd.incref(false); err != nil {
return nil, err
}
defer fd.decref() defer fd.decref()
mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF) mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil { if err != nil {
...@@ -30,7 +32,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -30,7 +32,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
v = int32(ifi.Index) v = int32(ifi.Index)
} }
mreq := &syscall.IPMreqn{Ifindex: v} mreq := &syscall.IPMreqn{Ifindex: v}
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq) err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
if err != nil { if err != nil {
...@@ -40,7 +44,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -40,7 +44,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
} }
func ipv4MulticastTTL(fd *netFD) (int, error) { func ipv4MulticastTTL(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
if err != nil { if err != nil {
...@@ -50,7 +56,9 @@ func ipv4MulticastTTL(fd *netFD) (int, error) { ...@@ -50,7 +56,9 @@ func ipv4MulticastTTL(fd *netFD) (int, error) {
} }
func setIPv4MulticastTTL(fd *netFD, v int) error { func setIPv4MulticastTTL(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
if err != nil { if err != nil {
...@@ -60,7 +68,9 @@ func setIPv4MulticastTTL(fd *netFD, v int) error { ...@@ -60,7 +68,9 @@ func setIPv4MulticastTTL(fd *netFD, v int) error {
} }
func ipv4MulticastLoopback(fd *netFD) (bool, error) { func ipv4MulticastLoopback(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil { if err != nil {
...@@ -70,7 +80,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) { ...@@ -70,7 +80,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) {
} }
func setIPv4MulticastLoopback(fd *netFD, v bool) error { func setIPv4MulticastLoopback(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil { if err != nil {
...@@ -80,7 +92,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error { ...@@ -80,7 +92,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error {
} }
func ipv4ReceiveInterface(fd *netFD) (bool, error) { func ipv4ReceiveInterface(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO)
if err != nil { if err != nil {
...@@ -90,7 +104,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) { ...@@ -90,7 +104,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) {
} }
func setIPv4ReceiveInterface(fd *netFD, v bool) error { func setIPv4ReceiveInterface(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO, boolint(v))
if err != nil { if err != nil {
...@@ -100,17 +116,21 @@ func setIPv4ReceiveInterface(fd *netFD, v bool) error { ...@@ -100,17 +116,21 @@ func setIPv4ReceiveInterface(fd *netFD, v bool) error {
} }
func ipv6TrafficClass(fd *netFD) (int, error) { func ipv6TrafficClass(fd *netFD) (int, error) {
fd.incref() if err := fd.incref(false); err != nil {
return 0, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
if err != nil { if err != nil {
return -1, os.NewSyscallError("getsockopt", err) return 0, os.NewSyscallError("getsockopt", err)
} }
return v, nil return v, nil
} }
func setIPv6TrafficClass(fd *netFD, v int) error { func setIPv6TrafficClass(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
if err != nil { if err != nil {
......
...@@ -12,7 +12,9 @@ import ( ...@@ -12,7 +12,9 @@ import (
) )
func ipv4MulticastInterface(fd *netFD) (*Interface, error) { func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
fd.incref() if err := fd.incref(false); err != nil {
return nil, err
}
defer fd.decref() defer fd.decref()
a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF) a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil { if err != nil {
...@@ -28,7 +30,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -28,7 +30,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
} }
var x [4]byte var x [4]byte
copy(x[:], ip.To4()) copy(x[:], ip.To4())
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x) err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
if err != nil { if err != nil {
...@@ -38,7 +42,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -38,7 +42,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
} }
func ipv4MulticastLoopback(fd *netFD) (bool, error) { func ipv4MulticastLoopback(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP) v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil { if err != nil {
...@@ -48,7 +54,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) { ...@@ -48,7 +54,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) {
} }
func setIPv4MulticastLoopback(fd *netFD, v bool) error { func setIPv4MulticastLoopback(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v))) err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
if err != nil { if err != nil {
...@@ -58,7 +66,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error { ...@@ -58,7 +66,9 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error {
} }
func ipv4ReceiveInterface(fd *netFD) (bool, error) { func ipv4ReceiveInterface(fd *netFD) (bool, error) {
fd.incref() if err := fd.incref(false); err != nil {
return false, err
}
defer fd.decref() defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF) v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
if err != nil { if err != nil {
...@@ -68,7 +78,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) { ...@@ -68,7 +78,9 @@ func ipv4ReceiveInterface(fd *netFD) (bool, error) {
} }
func setIPv4ReceiveInterface(fd *netFD, v bool) error { func setIPv4ReceiveInterface(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
if err != nil { if err != nil {
......
...@@ -23,7 +23,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { ...@@ -23,7 +23,9 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
} }
var x [4]byte var x [4]byte
copy(x[:], ip.To4()) copy(x[:], ip.To4())
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x) err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
if err != nil { if err != nil {
...@@ -38,7 +40,9 @@ func ipv4MulticastTTL(fd *netFD) (int, error) { ...@@ -38,7 +40,9 @@ func ipv4MulticastTTL(fd *netFD) (int, error) {
} }
func setIPv4MulticastTTL(fd *netFD, v int) error { func setIPv4MulticastTTL(fd *netFD, v int) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
if err != nil { if err != nil {
...@@ -54,7 +58,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) { ...@@ -54,7 +58,9 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) {
} }
func setIPv4MulticastLoopback(fd *netFD, v bool) error { func setIPv4MulticastLoopback(fd *netFD, v bool) error {
fd.incref() if err := fd.incref(false); err != nil {
return err
}
defer fd.decref() defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)) err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil { if err != nil {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment