func TestHubSocksOption(t *testing.T) { assert := assert.On(t) if os.Geteuid() != 0 { // This test case requires root permission. return } hub, err := ListenUDP(v2net.LocalHostIP, v2net.Port(0), ListenOption{ Callback: func(*buf.Buffer, *proxy.SessionInfo) {}, ReceiveOriginalDest: true, }) assert.Error(err).IsNil() conn := hub.Connection() fd, err := internal.GetSysFd(conn) assert.Error(err).IsNil() val, err := syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT) assert.Error(err).IsNil() assert.Int(val).Equals(1) val, err = syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR) assert.Error(err).IsNil() assert.Int(val).Equals(1) }
// GetsockoptInt wraps syscall.GetsockoptInt. func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) { so := sw.sockso(s) if so == nil { return syscall.GetsockoptInt(s, level, opt) } sw.fmu.RLock() f, _ := sw.fltab[FilterGetsockoptInt] sw.fmu.RUnlock() af, err := f.apply(so) if err != nil { return -1, err } so.SocketErr, so.Err = syscall.GetsockoptInt(s, level, opt) if err = af.apply(so); err != nil { return -1, err } if so.Err != nil { return -1, so.Err } if opt == syscall.SO_ERROR && (so.SocketErr == 0 || syscall.Errno(so.SocketErr) == syscall.EISCONN) { sw.smu.Lock() sw.stats.getLocked(so.Cookie).Connected++ sw.smu.Unlock() } return so.SocketErr, nil }
func ipv6MulticastLoopback(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_LOOP) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv6MulticastHopLimit(fd int) (int, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_MULTICAST_HOPS) if err != nil { return 0, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv6TrafficClass(fd int) (int, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_TCLASS) if err != nil { return 0, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv4MulticastTTL(fd int) (int, error) { v, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL) if err != nil { return 0, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv4SendSourceAddress(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_SENDSRCADDR) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv4MulticastTTL(fd int) (int, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptMulticastTTL) if err != nil { return 0, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv4MulticastLoopback(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptMulticastLoopback) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv6ReceivePacketInfo(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_2292PKTINFO) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv4ReceiveTOS(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveTOS) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv4PacketInfo(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_PKTINFO) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv4MulticastLoopback(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv6ReceivePathMTU(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall_IPV6_RECVPATHMTU) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv6ReceiveTrafficClass(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_RECVTCLASS) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv4ReceiveDestinationAddress(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_RECVDSTADDR) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func (sender *RawUDPSender) Send(msg []byte) error { payload := gopacket.Payload(msg) sender.udpHeader.DstPort = layers.UDPPort(sender.conn.RemoteUDPAddr().Port) err := gopacket.SerializeLayers(sender.ipBuf, sender.opts, sender.udpHeader, &payload) if err != nil { return err } packet := sender.ipBuf.Bytes() _, err = sender.socket.Write(packet) if err == nil || PosixError(err) != syscall.EMSGSIZE { return err } f, err := sender.socket.File() if err != nil { return err } defer f.Close() fd := int(f.Fd()) log.Println("EMSGSIZE on send, expecting PMTU update (IP packet was", len(packet), "bytes, payload was", len(msg), "bytes)") pmtu, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MTU) if err != nil { return err } return MsgTooBigError{PMTU: pmtu} }
func ipv4HeaderPrepend(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_HDRINCL) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv4TOS(fd int) (int, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_TOS) if err != nil { return 0, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv4ReceiveInterface(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_RECVIF) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv6ReceiveHopLimit(fd int) (bool, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, syscall.IPV6_2292HOPLIMIT) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv6HopLimit(fd int) (int, error) { v, err := syscall.GetsockoptInt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit) if err != nil { return 0, os.NewSyscallError("getsockopt", err) } return v, nil }
func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. switch err := syscall.Connect(fd.sysfd, ra); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case nil, syscall.EISCONN: if !deadline.IsZero() && deadline.Before(time.Now()) { return errTimeout } if err := fd.init(); err != nil { return err } return nil case syscall.EINVAL: // On Solaris we can see EINVAL if the socket has // already been accepted and closed by the server. // Treat this as a successful connection--writes to // the socket will see EOF. For details and a test // case in C see http://golang.org/issue/6828. if runtime.GOOS == "solaris" { return nil } fallthrough default: return err } if err := fd.init(); err != nil { return err } if !deadline.IsZero() { fd.setWriteDeadline(deadline) defer fd.setWriteDeadline(noDeadline) } for { // Performing multiple connect system calls on a // non-blocking socket under Unix variants does not // necessarily result in earlier errors being // returned. Instead, once runtime-integrated network // poller tells us that the socket is ready, get the // SO_ERROR socket option to see if the connection // succeeded or failed. See issue 7474 for further // details. if err := fd.pd.WaitWrite(); err != nil { return err } nerr, err := syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return err } switch err := syscall.Errno(nerr); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case syscall.Errno(0), syscall.EISCONN: return nil default: return err } } }
func newFileFD(f *os.File) (*netFD, error) { syscall.ForkLock.RLock() fd, err := syscall.Dup(int(f.Fd())) if err != nil { syscall.ForkLock.RUnlock() return nil, os.NewSyscallError("dup", err) } syscall.CloseOnExec(fd) syscall.ForkLock.RUnlock() sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) if err != nil { closesocket(fd) return nil, os.NewSyscallError("getsockopt", err) } family := syscall.AF_UNSPEC toAddr := sockaddrToTCP sa, _ := syscall.Getsockname(fd) switch sa.(type) { default: closesocket(fd) return nil, syscall.EINVAL case *syscall.SockaddrInet4: family = syscall.AF_INET if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrInet6: family = syscall.AF_INET6 if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrUnix: family = syscall.AF_UNIX toAddr = sockaddrToUnix if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUnixgram } else if sotype == syscall.SOCK_SEQPACKET { toAddr = sockaddrToUnixpacket } } laddr := toAddr(sa) sa, _ = syscall.Getpeername(fd) raddr := toAddr(sa) netfd, err := newFD(fd, family, sotype, laddr.Network()) if err != nil { closesocket(fd) return nil, err } netfd.setAddr(laddr, raddr) return netfd, nil }
func ipv6HopLimit(fd *netFD) (int, error) { fd.incref() defer fd.decref() v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS) if err != nil { return -1, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv4MulticastTTL(fd *netFD) (int, error) { fd.incref() defer fd.decref() v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL) if err != nil { return -1, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv4TOS(fd *netFD) (int, error) { fd.incref() defer fd.decref() v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS) if err != nil { return -1, os.NewSyscallError("getsockopt", err) } return v, nil }
func ipv4ReceiveInterface(fd *netFD) (bool, error) { fd.incref() defer fd.decref() v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv4MulticastLoopback(fd *netFD) (bool, error) { fd.incref() defer fd.decref() v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP) if err != nil { return false, os.NewSyscallError("getsockopt", err) } return v == 1, nil }
func ipv6TrafficClass(fd *netFD) (int, error) { fd.incref() defer fd.decref() v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS) if err != nil { return -1, os.NewSyscallError("getsockopt", err) } return v, nil }