Beispiel #1
0
func leaveIPv4Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
	mreq := syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
	if err := setSyscallIPMreq(&mreq, ifi); err != nil {
		return err
	}
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_DROP_MEMBERSHIP, (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
}
Beispiel #2
0
func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
	// Do not need to call fd.writeLock here,
	// because fd is not yet accessible to user,
	// so no concurrent operations are possible.
	if !canUseConnectEx(fd.net) {
		return syscall.Connect(fd.sysfd, ra)
	}
	// ConnectEx windows API requires an unconnected, previously bound socket.
	if la == nil {
		switch ra.(type) {
		case *syscall.SockaddrInet4:
			la = &syscall.SockaddrInet4{}
		case *syscall.SockaddrInet6:
			la = &syscall.SockaddrInet6{}
		default:
			panic("unexpected type in connect")
		}
		if err := syscall.Bind(fd.sysfd, la); err != nil {
			return err
		}
	}
	// Call ConnectEx API.
	o := &fd.wop
	o.sa = ra
	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
		return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
	})
	if err != nil {
		return err
	}
	// Refresh socket properties.
	return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
}
Beispiel #3
0
func setsockoptIPMreq(fd syscall.Handle, name int, ifi *net.Interface, grp net.IP) error {
	mreq := sysIPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
	if err := setIPMreqInterface(&mreq, ifi); err != nil {
		return err
	}
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, iana.ProtocolIP, int32(name), (*byte)(unsafe.Pointer(&mreq)), int32(sysSizeofIPMreq)))
}
Beispiel #4
0
func (fd *netFD) connect(ra syscall.Sockaddr) error {
	if !canUseConnectEx(fd.net) {
		return syscall.Connect(fd.sysfd, ra)
	}
	// ConnectEx windows API requires an unconnected, previously bound socket.
	var la syscall.Sockaddr
	switch ra.(type) {
	case *syscall.SockaddrInet4:
		la = &syscall.SockaddrInet4{}
	case *syscall.SockaddrInet6:
		la = &syscall.SockaddrInet6{}
	default:
		panic("unexpected type in connect")
	}
	if err := syscall.Bind(fd.sysfd, la); err != nil {
		return err
	}
	// Call ConnectEx API.
	var o connectOp
	o.Init(fd, 'w')
	o.ra = ra
	_, err := iosrv.ExecIO(&o, fd.wdeadline.value())
	if err != nil {
		return err
	}
	// Refresh socket properties.
	return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
}
func setIPv6MulticastInterface(fd syscall.Handle, ifi *net.Interface) error {
	var v int32
	if ifi != nil {
		v = int32(ifi.Index)
	}
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(ianaProtocolIPv6), int32(syscall.IPV6_MULTICAST_IF), (*byte)(unsafe.Pointer(&v)), 4))
}
Beispiel #6
0
func setInt(fd syscall.Handle, opt *sockOpt, v int) error {
	if opt.name < 1 || opt.typ != ssoTypeInt {
		return errOpNoSupport
	}
	i := int32(v)
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, iana.ProtocolIP, int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
}
Beispiel #7
0
func setsockoptIPMreq(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
	var mreq sysIPv6Mreq
	copy(mreq.Multiaddr[:], grp)
	if ifi != nil {
		mreq.setIfindex(ifi.Index)
	}
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&mreq)), sysSizeofIPv6Mreq))
}
func joinIPv6Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
	mreq := sysMulticastReq{}
	copy(mreq.IP[:], grp)
	if ifi != nil {
		mreq.IfIndex = uint32(ifi.Index)
	}
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptJoinGroup, (*byte)(unsafe.Pointer(&mreq)), int32(sysSizeofMulticastReq)))
}
func setIPv4MulticastTTL(fd syscall.Handle, v int) error {
	vv := int32(v)
	err := syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_TTL, (*byte)(unsafe.Pointer(&vv)), 4)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	return nil
}
Beispiel #10
0
func setIPv4MulticastLoopback(fd syscall.Handle, v bool) error {
	vv := int32(boolint(v))
	err := syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_LOOP, (*byte)(unsafe.Pointer(&vv)), 4)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	return nil
}
Beispiel #11
0
func setIPv4TTL(fd syscall.Handle, v int) error {
	vv := int32(v)
	err := syscall.Setsockopt(fd, int32(syscall.IPPROTO_IP), int32(syscall.IP_TTL), (*byte)(unsafe.Pointer(&vv)), 4)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	return nil
}
func joinIPv6Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
	mreq := syscall.IPv6Mreq{}
	copy(mreq.Multiaddr[:], grp)
	if ifi != nil {
		mreq.Interface = uint32(ifi.Index)
	}
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(ianaProtocolIPv6), int32(syscall.IPV6_JOIN_GROUP), (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
}
Beispiel #13
0
func setIPv4MulticastInterface(fd syscall.Handle, ifi *net.Interface) error {
	ip, err := netInterfaceToIP4(ifi)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	var v [4]byte
	copy(v[:], ip.To4())
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&v[0])), 4))
}
Beispiel #14
0
func setsockoptInterface(fd syscall.Handle, name int, ifi *net.Interface) error {
	ip, err := netInterfaceToIP4(ifi)
	if err != nil {
		return err
	}
	var b [4]byte
	copy(b[:], ip)
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, iana.ProtocolIP, int32(name), (*byte)(unsafe.Pointer(&b[0])), 4))
}
func setInterface(fd syscall.Handle, opt *sockOpt, ifi *net.Interface) error {
	if opt.name < 1 || opt.typ != ssoTypeInterface {
		return errOpNoSupport
	}
	var i int32
	if ifi != nil {
		i = int32(ifi.Index)
	}
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(opt.level), int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
}
Beispiel #16
0
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
	if err := fd.readLock(); err != nil {
		return nil, err
	}
	defer fd.readUnlock()

	// Get new socket.
	s, err := sysSocket(fd.family, fd.sotype, 0)
	if err != nil {
		return nil, &OpError{"socket", fd.net, fd.laddr, err}
	}

	// Associate our new socket with IOCP.
	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
	if err != nil {
		closesocket(s)
		return nil, &OpError{"accept", fd.net, fd.laddr, err}
	}
	if err := netfd.init(); err != nil {
		fd.Close()
		return nil, err
	}

	// Submit accept request.
	o := &fd.rop
	o.handle = s
	var rawsa [2]syscall.RawSockaddrAny
	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
	_, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
		return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
	})
	if err != nil {
		netfd.Close()
		return nil, err
	}

	// Inherit properties of the listening socket.
	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
	if err != nil {
		netfd.Close()
		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
	}

	// Get local and peer addr out of AcceptEx buffer.
	var lrsa, rrsa *syscall.RawSockaddrAny
	var llen, rlen int32
	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
		0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen)
	lsa, _ := lrsa.Sockaddr()
	rsa, _ := rrsa.Sockaddr()

	netfd.setAddr(toAddr(lsa), toAddr(rsa))
	return netfd, nil
}
Beispiel #17
0
func joinIPv4Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
	mreq := &syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
	if err := setSyscallIPMreq(mreq, ifi); err != nil {
		return err
	}
	err := syscall.Setsockopt(fd, int32(syscall.IPPROTO_IP), int32(syscall.IP_ADD_MEMBERSHIP), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	return nil
}
Beispiel #18
0
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
	if fd == nil || fd.sysfd == syscall.InvalidHandle {
		return nil, os.EINVAL
	}
	fd.incref()
	defer fd.decref()

	// Get new socket.
	// See ../syscall/exec.go for description of ForkLock.
	syscall.ForkLock.RLock()
	s, e := syscall.Socket(fd.family, fd.proto, 0)
	if e != 0 {
		syscall.ForkLock.RUnlock()
		return nil, os.Errno(e)
	}
	syscall.CloseOnExec(s)
	syscall.ForkLock.RUnlock()

	// Associate our new socket with IOCP.
	onceStartServer.Do(startServer)
	if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != 0 {
		return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)}
	}

	// Submit accept request.
	var o acceptOp
	o.Init(fd, 'r')
	o.newsock = s
	_, err = iosrv.ExecIO(&o, 0)
	if err != nil {
		closesocket(s)
		return nil, err
	}

	// Inherit properties of the listening socket.
	e = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
	if e != 0 {
		closesocket(s)
		return nil, err
	}

	// Get local and peer addr out of AcceptEx buffer.
	var lrsa, rrsa *syscall.RawSockaddrAny
	var llen, rlen int32
	l := uint32(unsafe.Sizeof(*lrsa))
	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])),
		0, l, l, &lrsa, &llen, &rrsa, &rlen)
	lsa, _ := lrsa.Sockaddr()
	rsa, _ := rrsa.Sockaddr()

	nfd = allocFD(s, fd.family, fd.proto, fd.net)
	nfd.setAddr(toAddr(lsa), toAddr(rsa))
	return nfd, nil
}
Beispiel #19
0
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
	if err := fd.incref(false); err != nil {
		return err
	}
	defer fd.decref()
	vv := int32(boolint(v))
	err := syscall.Setsockopt(fd.sysfd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_LOOP), (*byte)(unsafe.Pointer(&vv)), 4)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	return nil
}
Beispiel #20
0
func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
	ip, err := interfaceToIPv4Addr(ifi)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	var a [4]byte
	copy(a[:], ip.To4())
	if err := fd.incref(); err != nil {
		return err
	}
	defer fd.decref()
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&a[0])), 4))
}
Beispiel #21
0
func setIPv4MulticastInterface(fd syscall.Handle, ifi *net.Interface) error {
	ip, err := netInterfaceToIP4(ifi)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	var a [4]byte
	copy(a[:], ip.To4())
	err = syscall.Setsockopt(fd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_IF), (*byte)(unsafe.Pointer(&a[0])), 4)
	if err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	return nil
}
Beispiel #22
0
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
	if err := fd.incref(false); err != nil {
		return nil, err
	}
	defer fd.decref()

	// Get new socket.
	s, err := sysSocket(fd.family, fd.sotype, 0)
	if err != nil {
		return nil, &OpError{"socket", fd.net, fd.laddr, err}
	}

	// Associate our new socket with IOCP.
	onceStartServer.Do(startServer)
	if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); err != nil {
		closesocket(s)
		return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err}
	}

	// Submit accept request.
	var o acceptOp
	o.Init(fd, 'r')
	o.newsock = s
	_, err = iosrv.ExecIO(&o, fd.rdeadline.value())
	if err != nil {
		closesocket(s)
		return nil, err
	}

	// Inherit properties of the listening socket.
	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
	if err != nil {
		closesocket(s)
		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
	}

	// Get local and peer addr out of AcceptEx buffer.
	var lrsa, rrsa *syscall.RawSockaddrAny
	var llen, rlen int32
	l := uint32(unsafe.Sizeof(*lrsa))
	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])),
		0, l, l, &lrsa, &llen, &rrsa, &rlen)
	lsa, _ := lrsa.Sockaddr()
	rsa, _ := rrsa.Sockaddr()

	netfd := allocFD(s, fd.family, fd.sotype, fd.net)
	netfd.setAddr(toAddr(lsa), toAddr(rsa))
	return netfd, nil
}
Beispiel #23
0
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.
	if err := fd.init(); err != nil {
		return err
	}
	if !deadline.IsZero() {
		fd.setWriteDeadline(deadline)
		defer fd.setWriteDeadline(noDeadline)
	}
	if !canUseConnectEx(fd.net) {
		return os.NewSyscallError("connect", connectFunc(fd.sysfd, ra))
	}
	// ConnectEx windows API requires an unconnected, previously bound socket.
	if la == nil {
		switch ra.(type) {
		case *syscall.SockaddrInet4:
			la = &syscall.SockaddrInet4{}
		case *syscall.SockaddrInet6:
			la = &syscall.SockaddrInet6{}
		default:
			panic("unexpected type in connect")
		}
		if err := syscall.Bind(fd.sysfd, la); err != nil {
			return os.NewSyscallError("bind", err)
		}
	}
	// Call ConnectEx API.
	o := &fd.wop
	o.sa = ra
	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
		return connectExFunc(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
	})
	if err != nil {
		if _, ok := err.(syscall.Errno); ok {
			err = os.NewSyscallError("connectex", err)
		}
		return err
	}
	// Refresh socket properties.
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))))
}
Beispiel #24
0
func (fd *netFD) acceptOne(rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
	// Get new socket.
	s, err := sysSocket(fd.family, fd.sotype, 0)
	if err != nil {
		return nil, err
	}

	// Associate our new socket with IOCP.
	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
	if err != nil {
		closeFunc(s)
		return nil, err
	}
	if err := netfd.init(); err != nil {
		fd.Close()
		return nil, err
	}

	// Submit accept request.
	o.handle = s
	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
	_, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
		return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
	})
	if err != nil {
		netfd.Close()
		if _, ok := err.(syscall.Errno); ok {
			err = os.NewSyscallError("acceptex", err)
		}
		return nil, err
	}

	// Inherit properties of the listening socket.
	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
	if err != nil {
		netfd.Close()
		return nil, os.NewSyscallError("setsockopt", err)
	}

	return netfd, nil
}
Beispiel #25
0
func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) error {
	// Do not need to call fd.writeLock here,
	// because fd is not yet accessible to user,
	// so no concurrent operations are possible.
	if err := fd.init(); err != nil {
		return err
	}
	if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
		fd.setWriteDeadline(deadline)
		defer fd.setWriteDeadline(noDeadline)
	}
	if !canUseConnectEx(fd.net) {
		err := connectFunc(fd.sysfd, ra)
		return os.NewSyscallError("connect", err)
	}
	// ConnectEx windows API requires an unconnected, previously bound socket.
	if la == nil {
		switch ra.(type) {
		case *syscall.SockaddrInet4:
			la = &syscall.SockaddrInet4{}
		case *syscall.SockaddrInet6:
			la = &syscall.SockaddrInet6{}
		default:
			panic("unexpected type in connect")
		}
		if err := syscall.Bind(fd.sysfd, la); err != nil {
			return os.NewSyscallError("bind", err)
		}
	}
	// Call ConnectEx API.
	o := &fd.wop
	o.sa = ra

	// Wait for the goroutine converting context.Done into a write timeout
	// to exist, otherwise our caller might cancel the context and
	// cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
	done := make(chan bool) // must be unbuffered
	defer func() { done <- true }()
	go func() {
		select {
		case <-ctx.Done():
			// Force the runtime's poller to immediately give
			// up waiting for writability.
			fd.setWriteDeadline(aLongTimeAgo)
			<-done
		case <-done:
		}
	}()

	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
		return connectExFunc(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
	})
	if err != nil {
		select {
		case <-ctx.Done():
			return mapErr(ctx.Err())
		default:
			if _, ok := err.(syscall.Errno); ok {
				err = os.NewSyscallError("connectex", err)
			}
			return err
		}
	}
	// Refresh socket properties.
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))))
}
func setIPv6MulticastLoopback(fd syscall.Handle, v bool) error {
	vv := int32(boolint(v))
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(ianaProtocolIPv6), int32(syscall.IPV6_MULTICAST_LOOP), (*byte)(unsafe.Pointer(&vv)), 4))
}
func setIPv6MulticastHopLimit(fd syscall.Handle, v int) error {
	vv := int32(v)
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, int32(ianaProtocolIPv6), int32(syscall.IPV6_MULTICAST_HOPS), (*byte)(unsafe.Pointer(&vv)), 4))
}
func setIPv6MulticastHopLimit(fd syscall.Handle, v int) error {
	vv := int32(v)
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, (*byte)(unsafe.Pointer(&vv)), 4))
}
Beispiel #29
0
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
	return syscall.Setsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(v), int32(l))
}
func setIPv6MulticastLoopback(fd syscall.Handle, v bool) error {
	vv := int32(boolint(v))
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&vv)), 4))
}