// Close all poller file descriptors, but not the one passed to it.
func (poller *fdPoller) close() {
	if poller.pipe[1] != -1 {
		unix.Close(poller.pipe[1])
	}
	if poller.pipe[0] != -1 {
		unix.Close(poller.pipe[0])
	}
	if poller.epfd != -1 {
		unix.Close(poller.epfd)
	}
}
示例#2
0
func (c conn) Close() (err error) {
	err = unix.Close(c.fd)
	if err != nil {
		err = Err{err}
	}
	return
}
示例#3
0
// TcpListen is listening for incoming IP packets which are being intercepted.
// In conflict to regular Listen mehtod the socket destination and source addresses
// are of the intercepted connection.
// Else then that it works exactly like net package net.Listen.
func TcpListen(listenAddr string) (listener net.Listener, err error) {
	s, err := unix.Socket(unix.AF_INET6, unix.SOCK_STREAM, 0)
	if err != nil {
		return nil, err
	}
	defer unix.Close(s)
	err = unix.SetsockoptInt(s, unix.SOL_IP, unix.IP_TRANSPARENT, 1)
	if err != nil {
		return nil, err
	}

	sa, err := IPv6TcpAddrToUnixSocksAddr(listenAddr)
	if err != nil {
		return nil, err
	}
	err = unix.Bind(s, sa)
	if err != nil {
		return nil, err
	}
	err = unix.Listen(s, unix.SOMAXCONN)
	if err != nil {
		return nil, err
	}
	f := os.NewFile(uintptr(s), "TProxy")
	defer f.Close()
	return net.FileListener(f)
}
示例#4
0
// dial tcp with tcp fastopen
// 第一个包体积不要太大,需要小于一定数量,否则会被吃掉(正确性问题),
// 如果过大,此处会在连接时发送前一部分,连接后又发送一部分
func TfoDial(nextAddr string, data []byte) (conn net.Conn, err error) {
	s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0)
	if err != nil {
		return nil, err
	}
	defer unix.Close(s)
	sa, err := kmgUnix.IPv4TcpAddrToUnixSocksAddr(nextAddr)
	if err != nil {
		return nil, err
	}
	if len(data) <= tfoFirstSize {
		err = unix.Sendto(s, data, unix.MSG_FASTOPEN, sa)
		if err != nil {
			return
		}
	} else {
		err = unix.Sendto(s, data[:tfoFirstSize], unix.MSG_FASTOPEN, sa)
		if err != nil {
			return
		}
	}
	f := os.NewFile(uintptr(s), "TFODial")
	defer f.Close()
	conn, err = net.FileConn(f)
	if err != nil {
		return
	}
	if len(data) > tfoFirstSize {
		_, err = conn.Write(data[tfoFirstSize:])
		if err != nil {
			return nil, err
		}
	}
	return conn, nil
}
示例#5
0
//network is useless ,it will always use tcp4
func TfoListen(network string, listenAddr string) (listener net.Listener, err error) {
	s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0)
	if err != nil {
		return nil, err
	}
	defer unix.Close(s)
	err = unix.SetsockoptInt(s, unix.SOL_TCP, 23, 10)
	if err != nil {
		return nil, err
	}
	err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
	if err != nil {
		return nil, err
	}
	sa, err := kmgUnix.IPv4TcpAddrToUnixSocksAddr(listenAddr)
	if err != nil {
		return nil, err
	}
	err = unix.Bind(s, sa)
	if err != nil {
		return nil, err
	}
	err = unix.Listen(s, 10)
	if err != nil {
		return nil, err
	}
	f := os.NewFile(uintptr(s), "TFOListen")
	defer f.Close()
	return net.FileListener(f)
}
示例#6
0
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events.
func NewWatcher() (*Watcher, error) {
	// Create inotify fd
	fd, errno := unix.InotifyInit()
	if fd == -1 {
		return nil, errno
	}
	// Create epoll
	poller, err := newFdPoller(fd)
	if err != nil {
		unix.Close(fd)
		return nil, err
	}
	w := &Watcher{
		fd:       fd,
		poller:   poller,
		watches:  make(map[string]*watch),
		paths:    make(map[int]string),
		Events:   make(chan Event),
		Errors:   make(chan error),
		done:     make(chan struct{}),
		doneResp: make(chan struct{}),
	}
	w.cv = sync.NewCond(&w.mu)

	go w.readEvents()
	return w, nil
}
示例#7
0
// TfoListen announces on the local network address laddr using tcp protocol and fast open option.
// laddr must be in the form of "host:port".
// It returns a tfo-enabled listener and an error if any.
func tfoListen(laddr string) (lst net.Listener, err error) {
	s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0)
	if err != nil {
		return
	}
	defer unix.Close(s)

	sa, err := tcpAddrToSockaddr(laddr)
	if err != nil {
		return
	}

	err = unix.Bind(s, sa)
	if err != nil {
		return
	}

	// set the socket to fast open mode
	err = unix.SetsockoptInt(s, unix.SOL_TCP, 23, TCP_FASTOPEN_VAL)
	if err != nil {
		return
	}

	err = unix.Listen(s, 10)
	if err != nil {
		return
	}

	f := os.NewFile(uintptr(s), "TFOListen")
	defer f.Close()

	return net.FileListener(f)
}
示例#8
0
func stop() {
	if cxt != nil {
		// notify HandleRequest() that we're done
		if _, err := unix.Write(pipeFds[1], []byte{0}); err != nil {
			log.Errorln("Fail to notify poll for finishing: ", err)
		}
		close(done)
		C.tcmulib_close(cxt)
		if err := unix.Close(pipeFds[0]); err != nil {
			log.Errorln("Fail to close pipeFds[0]: ", err)
		}
		if err := unix.Close(pipeFds[1]); err != nil {
			log.Errorln("Fail to close pipeFds[1]: ", err)
		}
		cxt = nil
	}
}
示例#9
0
文件: hack.go 项目: decomp/decomp
// hackDump returns the value dump as a string.
func hackDump(v llvm.Value) (string, error) {
	// Open temp file.
	// TODO: Use an in-memory file instead of /tmp/x.
	fd, err := unix.Open("/tmp/x", unix.O_WRONLY|unix.O_TRUNC|unix.O_CREAT, 0644)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Store original stderr.
	stderr, err := unix.Dup(2)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Capture stderr and redirect its output to the temp file.
	err = unix.Dup2(fd, 2)
	if err != nil {
		return "", errutil.Err(err)
	}
	err = unix.Close(fd)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Dump value.
	v.Dump()
	C.fflush_stderr()

	// Restore stderr.
	err = unix.Dup2(stderr, 2)
	if err != nil {
		return "", errutil.Err(err)
	}
	err = unix.Close(stderr)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Return content of temp file.
	buf, err := ioutil.ReadFile("/tmp/x")
	if err != nil {
		return "", errutil.Err(err)
	}
	return string(buf), nil
}
示例#10
0
func UdpTProxyConn(listenAddr string) (udp *net.UDPConn, err error) {
	var c net.Conn
	s, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0)
	if err != nil {
		return nil, err
	}
	//Why close here ???
	defer unix.Close(s)

	err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
	if err != nil {
		return nil, err
	}

	err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_BROADCAST, 1)
	if err != nil {
		return nil, err
	}

	err = unix.SetsockoptInt(s, unix.SOL_IP, unix.IP_TRANSPARENT, 1)
	if err != nil {
		return nil, err
	}

	err = unix.SetsockoptInt(s, unix.IPPROTO_IP, unix.IP_RECVORIGDSTADDR, 1)
	if err != nil {
		return nil, err
	}

	sa, err := IPv6TcpAddrToUnixSocksAddr(listenAddr)
	if err != nil {
		return nil, err
	}
	err = unix.Bind(s, sa)
	if err != nil {
		return nil, err
	}

	f := os.NewFile(uintptr(s), "TProxy")
	defer f.Close()
	c, err = net.FileConn(f)
	if err != nil {
		return nil, err
	}

	var ok bool
	if udp, ok = c.(*net.UDPConn); ok {
		return
	} else {
		c.Close()
		return nil, errors.New("type error")
	}
}
示例#11
0
文件: testhelpers.go 项目: aanm/cni
func MakeNetworkNS(containerID string) string {
	namespace := "/var/run/netns/" + containerID

	err := os.MkdirAll("/var/run/netns", 0600)
	Expect(err).NotTo(HaveOccurred())

	// create an empty file at the mount point
	mountPointFd, err := os.Create(namespace)
	Expect(err).NotTo(HaveOccurred())
	mountPointFd.Close()

	var wg sync.WaitGroup
	wg.Add(1)

	// do namespace work in a dedicated goroutine, so that we can safely
	// Lock/Unlock OSThread without upsetting the lock/unlock state of
	// the caller of this function.  See block comment above.
	go (func() {
		defer wg.Done()

		runtime.LockOSThread()
		defer runtime.UnlockOSThread()

		defer GinkgoRecover()

		// capture current thread's original netns
		currentThreadNetNSPath := getCurrentThreadNetNSPath()
		originalNetNS, err := unix.Open(currentThreadNetNSPath, unix.O_RDONLY, 0)
		Expect(err).NotTo(HaveOccurred())
		defer unix.Close(originalNetNS)

		// create a new netns on the current thread
		err = unix.Unshare(unix.CLONE_NEWNET)
		Expect(err).NotTo(HaveOccurred())

		// bind mount the new netns from the current thread onto the mount point
		err = unix.Mount(currentThreadNetNSPath, namespace, "none", unix.MS_BIND, "")
		Expect(err).NotTo(HaveOccurred())

		// reset current thread's netns to the original
		_, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(originalNetNS), uintptr(unix.CLONE_NEWNET), 0)
		Expect(e1).To(BeZero())
	})()

	wg.Wait()

	return namespace
}
示例#12
0
// TestFcntlFlock tests whether the file locking structure matches
// the calling convention of each kernel.
func TestFcntlFlock(t *testing.T) {
	name := filepath.Join(os.TempDir(), "TestFcntlFlock")
	fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0)
	if err != nil {
		t.Fatalf("Open failed: %v", err)
	}
	defer unix.Unlink(name)
	defer unix.Close(fd)
	flock := unix.Flock_t{
		Type:  unix.F_RDLCK,
		Start: 0, Len: 0, Whence: 1,
	}
	if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil {
		t.Fatalf("FcntlFlock failed: %v", err)
	}
}
示例#13
0
文件: kqueue.go 项目: nak3/nomad
// Remove stops watching the named file or directory (non-recursively).
func (w *Watcher) Remove(name string) error {
	name = filepath.Clean(name)
	w.mu.Lock()
	watchfd, ok := w.watches[name]
	w.mu.Unlock()
	if !ok {
		return fmt.Errorf("can't remove non-existent kevent watch for: %s", name)
	}

	const registerRemove = unix.EV_DELETE
	if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil {
		return err
	}

	unix.Close(watchfd)

	w.mu.Lock()
	isDir := w.paths[watchfd].isDir
	delete(w.watches, name)
	delete(w.paths, watchfd)
	delete(w.dirFlags, name)
	w.mu.Unlock()

	// Find all watched paths that are in this directory that are not external.
	if isDir {
		var pathsToRemove []string
		w.mu.Lock()
		for _, path := range w.paths {
			wdir, _ := filepath.Split(path.name)
			if filepath.Clean(wdir) == name {
				if !w.externalWatches[path.name] {
					pathsToRemove = append(pathsToRemove, path.name)
				}
			}
		}
		w.mu.Unlock()
		for _, name := range pathsToRemove {
			// Since these are internal, not much sense in propagating error
			// to the user, as that will just confuse them with an error about
			// a path they did not explicitly watch themselves.
			w.Remove(name)
		}
	}

	return nil
}
示例#14
0
// TfoDial dials to addr using tcp protocol with fast open option set,
// addr should be in the form of "addr:port",
// the data is sent along with the first syn packet of tcp handshake.
// It returns a established connection and an error if any.
func tfoDial(addr string, data []byte) (conn net.Conn, err error) {
	fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0)
	if err != nil {
		return
	}
	defer unix.Close(fd)

	sa, err := tcpAddrToSockaddr(addr)
	if err != nil {
		return
	}

	err = unix.Sendto(fd, data, unix.MSG_FASTOPEN, sa)
	if err != nil {
		return
	}

	f := os.NewFile(uintptr(fd), "TFODial")
	defer f.Close()

	return net.FileConn(f)
}
示例#15
0
func makeNetworkNS(containerID string) string {
	namespace := "/var/run/netns/" + containerID
	pid := unix.Getpid()
	tid := unix.Gettid()

	err := os.MkdirAll("/var/run/netns", 0600)
	Expect(err).NotTo(HaveOccurred())

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()
	go (func() {
		defer GinkgoRecover()

		err = unix.Unshare(unix.CLONE_NEWNET)
		Expect(err).NotTo(HaveOccurred())

		fd, err := os.Create(namespace)
		Expect(err).NotTo(HaveOccurred())
		defer fd.Close()

		err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "")
		Expect(err).NotTo(HaveOccurred())
	})()

	Eventually(namespace).Should(BeAnExistingFile())

	fd, err := unix.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid), unix.O_RDONLY, 0)
	Expect(err).NotTo(HaveOccurred())

	defer unix.Close(fd)

	_, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(fd), uintptr(unix.CLONE_NEWNET), 0)
	Expect(e1).To(BeZero())

	return namespace
}
示例#16
0
文件: socket.go 项目: currantlabs/ble
func (s *Socket) Close() error {
	return errors.Wrap(unix.Close(s.fd), "can't close hci socket")
}
示例#17
0
文件: creds_test.go 项目: apcera/cni
// TestSCMCredentials tests the sending and receiving of credentials
// (PID, UID, GID) in an ancillary message between two UNIX
// sockets. The SO_PASSCRED socket option is enabled on the sending
// socket for this to work.
func TestSCMCredentials(t *testing.T) {
	fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
	if err != nil {
		t.Fatalf("Socketpair: %v", err)
	}
	defer unix.Close(fds[0])
	defer unix.Close(fds[1])

	err = unix.SetsockoptInt(fds[0], unix.SOL_SOCKET, unix.SO_PASSCRED, 1)
	if err != nil {
		t.Fatalf("SetsockoptInt: %v", err)
	}

	srvFile := os.NewFile(uintptr(fds[0]), "server")
	defer srvFile.Close()
	srv, err := net.FileConn(srvFile)
	if err != nil {
		t.Errorf("FileConn: %v", err)
		return
	}
	defer srv.Close()

	cliFile := os.NewFile(uintptr(fds[1]), "client")
	defer cliFile.Close()
	cli, err := net.FileConn(cliFile)
	if err != nil {
		t.Errorf("FileConn: %v", err)
		return
	}
	defer cli.Close()

	var ucred unix.Ucred
	if os.Getuid() != 0 {
		ucred.Pid = int32(os.Getpid())
		ucred.Uid = 0
		ucred.Gid = 0
		oob := unix.UnixCredentials(&ucred)
		_, _, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
		if err.(*net.OpError).Err != syscall.EPERM {
			t.Fatalf("WriteMsgUnix failed with %v, want EPERM", err)
		}
	}

	ucred.Pid = int32(os.Getpid())
	ucred.Uid = uint32(os.Getuid())
	ucred.Gid = uint32(os.Getgid())
	oob := unix.UnixCredentials(&ucred)

	// this is going to send a dummy byte
	n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
	if err != nil {
		t.Fatalf("WriteMsgUnix: %v", err)
	}
	if n != 0 {
		t.Fatalf("WriteMsgUnix n = %d, want 0", n)
	}
	if oobn != len(oob) {
		t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
	}

	oob2 := make([]byte, 10*len(oob))
	n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
	if err != nil {
		t.Fatalf("ReadMsgUnix: %v", err)
	}
	if flags != 0 {
		t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
	}
	if n != 1 {
		t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
	}
	if oobn2 != oobn {
		// without SO_PASSCRED set on the socket, ReadMsgUnix will
		// return zero oob bytes
		t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
	}
	oob2 = oob2[:oobn2]
	if !bytes.Equal(oob, oob2) {
		t.Fatal("ReadMsgUnix oob bytes don't match")
	}

	scm, err := unix.ParseSocketControlMessage(oob2)
	if err != nil {
		t.Fatalf("ParseSocketControlMessage: %v", err)
	}
	newUcred, err := unix.ParseUnixCredentials(&scm[0])
	if err != nil {
		t.Fatalf("ParseUnixCredentials: %v", err)
	}
	if *newUcred != ucred {
		t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
	}
}
示例#18
0
func cl(fd int) (err error) {
	return unix.Close(fd)
}
示例#19
0
func xserverInit(display *C.struct_wl_display) {
	// Fetch a valid lock file and DISPLAY number
	displayNum, _ := TryLock()
	numStr := strconv.Itoa(displayNum)
	// Set DISPLAY number
	displayName := ":" + numStr
	os.Setenv("DISPLAY", displayName)
	println(displayName)

	// Open a socket for the Wayland connection from Xwayland.
	wls, _ := syscall.Socketpair(syscall.AF_UNIX,
		syscall.SOCK_STREAM, 0)

	wms, _ := syscall.Socketpair(syscall.AF_UNIX,
		syscall.SOCK_STREAM, 0)

	initXwm((uintptr)(wms[0]))

	client := C.wl_client_create(display, (C.int)(wls[0]))

	println(client)
	unixFd := listen2(SOCKET_FMT + numStr)
	abstructFd := listen2("@" + SOCKET_FMT + numStr)

	unsetCloseOnExec(unixFd)
	unsetCloseOnExec(abstructFd)

	pid := forkXWayland()
	if pid == 0 { // child

		unix.Close(wls[0])
		unix.Close(wms[0])

		// init DISPLAY unix socket
		// do not close the listener(Close them will remove the file in filesystem).
		// unixListener, _ := listen(SOCKET_FMT + numStr)
		// abstructListener, _ := listen("@" + SOCKET_FMT + numStr)

		// unixFile, _ := unixListener.File()
		// abstructFile, _ := abstructListener.File()

		// unixFd := unixFile.Fd()
		// abstructFd := abstructFile.Fd()

		C.signal_ignore((C.int)(syscall.SIGUSR1))
		os.Setenv("WAYLAND_SOCKET", strconv.Itoa(wls[1]))
		args := []string{
			"Xwayland",
			displayName,
			"-rootless",
			"-terminate",
			"-listen", strconv.Itoa((int)(unixFd)),
			"-listen", strconv.Itoa((int)(abstructFd)),
			"-wm", strconv.Itoa(wms[1]),
		}

		binary, lookErr := exec.LookPath("Xwayland")
		// binary, lookErr := exec.LookPath("strace")
		if lookErr != nil {
			panic(lookErr)
		}

		env := os.Environ()
		execErr := syscall.Exec(binary, args, env)
		if execErr != nil {
			panic(lookErr)
		}

	} else { // parent
		unix.Close(wls[1])
		unix.Close(wms[1])
	}
}
示例#20
0
func main() {
	fmt.Println("Listening on port :", port)
	counter := new(connCounter)

	// create socket
	fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0)
	if err != nil {
		log.Fatal("socket-error: ", err)
	}

	// sa struct
	sa := new(unix.SockaddrInet4)
	sa.Port = 9090

	// bind
	err = unix.Bind(fd, sa)
	if err != nil {
		log.Fatal("bind: ", err)
	}

	// listen
	err = unix.Listen(fd, 3)
	if err != nil {
		log.Fatal("listen: ", err)
	}

	for {
		connInfo := new(connection)
		// accept connection, discard SA struct
		newFd, _, err := unix.Accept(fd)
		connInfo.fd = newFd
		if err != nil {
			log.Fatal("accept: ", err)
		}

		// client reads until closes, adding
		// a gorutine allows dealing with more
		// requests.
		counter.mu.Lock()
		counter.num += 1
		counter.mu.Unlock()
		fmt.Println("Number of connections: ", counter.num)
		go func(c *connection, counter *connCounter) {
			fmt.Printf("Conn.fd=%d\n", c.fd)
			for {
				// read
				c.buf = make([]byte, 50)
				n, err := unix.Read(c.fd, c.buf)
				if err != nil {
					log.Fatal("read: ", err)
				}

				fmt.Printf("Read: %d Value: %s\n", n, string(c.buf[0:n]))

				// close
				if string(c.buf[0:5]) == "close" {
					_, err = unix.Write(c.fd, []byte(`Bye bye buddy`))
					if err != nil {
						log.Fatal("close: ", err)
					}

					err = unix.Close(c.fd)
					if err != nil {
						log.Fatal("close: ", err)
					}
					counter.mu.Lock()
					counter.num = counter.num - 1
					counter.mu.Unlock()
					return
				}
			}
		}(connInfo, counter)
	}
}
示例#21
0
// readEvents reads from the inotify file descriptor, converts the
// received events into Event objects and sends them via the Events channel
func (w *Watcher) readEvents() {
	var (
		buf   [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
		n     int                                  // Number of bytes read with read()
		errno error                                // Syscall errno
		ok    bool                                 // For poller.wait
	)

	defer close(w.doneResp)
	defer close(w.Errors)
	defer close(w.Events)
	defer unix.Close(w.fd)
	defer w.poller.close()

	for {
		// See if we have been closed.
		if w.isClosed() {
			return
		}

		ok, errno = w.poller.wait()
		if errno != nil {
			select {
			case w.Errors <- errno:
			case <-w.done:
				return
			}
			continue
		}

		if !ok {
			continue
		}

		n, errno = unix.Read(w.fd, buf[:])
		// If a signal interrupted execution, see if we've been asked to close, and try again.
		// http://man7.org/linux/man-pages/man7/signal.7.html :
		// "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable"
		if errno == unix.EINTR {
			continue
		}

		// unix.Read might have been woken up by Close. If so, we're done.
		if w.isClosed() {
			return
		}

		if n < unix.SizeofInotifyEvent {
			var err error
			if n == 0 {
				// If EOF is received. This should really never happen.
				err = io.EOF
			} else if n < 0 {
				// If an error occurred while reading.
				err = errno
			} else {
				// Read was too short.
				err = errors.New("notify: short read in readEvents()")
			}
			select {
			case w.Errors <- err:
			case <-w.done:
				return
			}
			continue
		}

		var offset uint32
		// We don't know how many events we just read into the buffer
		// While the offset points to at least one whole event...
		for offset <= uint32(n-unix.SizeofInotifyEvent) {
			// Point "raw" to the event in the buffer
			raw := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))

			mask := uint32(raw.Mask)
			nameLen := uint32(raw.Len)
			// If the event happened to the watched directory or the watched file, the kernel
			// doesn't append the filename to the event, but we would like to always fill the
			// the "Name" field with a valid filename. We retrieve the path of the watch from
			// the "paths" map.
			w.mu.Lock()
			name := w.paths[int(raw.Wd)]
			w.mu.Unlock()
			if nameLen > 0 {
				// Point "bytes" at the first byte of the filename
				bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))
				// The filename is padded with NULL bytes. TrimRight() gets rid of those.
				name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
			}

			event := newEvent(name, mask)

			// Send the events that are not ignored on the events channel
			if !event.ignoreLinux(w, raw.Wd, mask) {
				select {
				case w.Events <- event:
				case <-w.done:
					return
				}
			}

			// Move to the next event in the buffer
			offset += unix.SizeofInotifyEvent + nameLen
		}
	}
}
示例#22
0
// TcpDial is a special tcp connection which binds a non local address as the source.
// Except then the option to bind to a specific local address which the machine doesn't posses
// it is exactly like any other net.Conn connection.
// It is advised to use port numbered 0 in the localAddr and leave the kernel to choose which
// Local port to use in order to avoid errors and binding conflicts.
func TcpDial(localAddr, remoteAddr string) (conn net.Conn, err error) {
	fmt.Println(localAddr)
	fmt.Println(remoteAddr)
	s, err := unix.Socket(unix.AF_INET6, unix.SOCK_STREAM, 0)

	//In a case there was a need for a non-blocking socket an example
	//s, err := unix.Socket(unix.AF_INET6, unix.SOCK_STREAM |unix.SOCK_NONBLOCK, 0)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	defer unix.Close(s)
	err = unix.SetsockoptInt(s, unix.SOL_IP, unix.IP_TRANSPARENT, 1)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	rhost, rport, err := net.SplitHostPort(localAddr)
	_ = rport
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}

	sa, err := IPv6TcpAddrToUnixSocksAddr(rhost + ":0")
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	remoteSocket, err := IPv6TcpAddrToUnixSocksAddr(remoteAddr)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	err = unix.Bind(s, sa)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	err = unix.Connect(s, remoteSocket)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	f := os.NewFile(uintptr(s), "TProxyTcpClient")
	client, err := net.FileConn(f)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	fmt.Println(client.LocalAddr())
	fmt.Println(client.RemoteAddr())
	return client, err
}
示例#23
0
func (pc *packetSock) Close() error {
	return unix.Close(pc.fd)
}
示例#24
0
文件: kqueue.go 项目: nak3/nomad
// addWatch adds name to the watched file set.
// The flags are interpreted as described in kevent(2).
// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks.
func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
	var isDir bool
	// Make ./name and name equivalent
	name = filepath.Clean(name)

	w.mu.Lock()
	if w.isClosed {
		w.mu.Unlock()
		return "", errors.New("kevent instance already closed")
	}
	watchfd, alreadyWatching := w.watches[name]
	// We already have a watch, but we can still override flags.
	if alreadyWatching {
		isDir = w.paths[watchfd].isDir
	}
	w.mu.Unlock()

	if !alreadyWatching {
		fi, err := os.Lstat(name)
		if err != nil {
			return "", err
		}

		// Don't watch sockets.
		if fi.Mode()&os.ModeSocket == os.ModeSocket {
			return "", nil
		}

		// Don't watch named pipes.
		if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
			return "", nil
		}

		// Follow Symlinks
		// Unfortunately, Linux can add bogus symlinks to watch list without
		// issue, and Windows can't do symlinks period (AFAIK). To  maintain
		// consistency, we will act like everything is fine. There will simply
		// be no file events for broken symlinks.
		// Hence the returns of nil on errors.
		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
			name, err = filepath.EvalSymlinks(name)
			if err != nil {
				return "", nil
			}

			w.mu.Lock()
			_, alreadyWatching = w.watches[name]
			w.mu.Unlock()

			if alreadyWatching {
				return name, nil
			}

			fi, err = os.Lstat(name)
			if err != nil {
				return "", nil
			}
		}

		watchfd, err = unix.Open(name, openMode, 0700)
		if watchfd == -1 {
			return "", err
		}

		isDir = fi.IsDir()
	}

	const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE
	if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil {
		unix.Close(watchfd)
		return "", err
	}

	if !alreadyWatching {
		w.mu.Lock()
		w.watches[name] = watchfd
		w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
		w.mu.Unlock()
	}

	if isDir {
		// Watch the directory if it has not been watched before,
		// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
		w.mu.Lock()

		watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
			(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
		// Store flags so this watch can be updated later
		w.dirFlags[name] = flags
		w.mu.Unlock()

		if watchDir {
			if err := w.watchDirectoryFiles(name); err != nil {
				return "", err
			}
		}
	}
	return name, nil
}
示例#25
0
// DeviceChan binds the udev_monitor socket to the event source and spawns a
// goroutine. The goroutine efficiently waits on the monitor socket using epoll.
// Data is received from the udev monitor socket and a new Device is created
// with the data received. Pointers to the device are sent on the returned channel.
// The function takes a done signalling channel as a parameter, which when
// triggered will stop the goroutine and close the device channel.
// Only socket connections with uid=0 are accepted.
func (m *Monitor) DeviceChan(done <-chan struct{}) (<-chan *Device, error) {

	var event unix.EpollEvent
	var events [maxEpollEvents]unix.EpollEvent

	// Lock the context
	m.lock()
	defer m.unlock()

	// Enable receiving
	if C.udev_monitor_enable_receiving(m.ptr) != 0 {
		return nil, errors.New("udev: udev_monitor_enable_receiving failed")
	}

	// Set the fd to non-blocking
	fd := C.udev_monitor_get_fd(m.ptr)
	if e := unix.SetNonblock(int(fd), true); e != nil {
		return nil, errors.New("udev: unix.SetNonblock failed")
	}

	// Create an epoll fd
	epfd, e := unix.EpollCreate1(0)
	if e != nil {
		return nil, errors.New("udev: unix.EpollCreate1 failed")
	}

	// Add the fd to the epoll fd
	event.Events = unix.EPOLLIN | unix.EPOLLET
	event.Fd = int32(fd)
	if e = unix.EpollCtl(epfd, unix.EPOLL_CTL_ADD, int(fd), &event); e != nil {
		return nil, errors.New("udev: unix.EpollCtl failed")
	}

	// Create the channel
	ch := make(chan *Device)

	// Create goroutine to epoll the fd
	go func(done <-chan struct{}, fd int32) {
		// Close the epoll fd when goroutine exits
		defer unix.Close(epfd)
		// Close the channel when goroutine exits
		defer close(ch)
		// Loop forever
		for {
			// Poll the file descriptor
			nevents, e := unix.EpollWait(epfd, events[:], epollTimeout)
			if e != nil {
				return
			}
			// Process events
			for ev := 0; ev < nevents; ev++ {
				if events[ev].Fd == fd {
					if (events[ev].Events & unix.EPOLLIN) != 0 {
						for d := m.receiveDevice(); d != nil; d = m.receiveDevice() {
							ch <- d
						}
					}
				}
			}
			// Check for done signal
			select {
			case <-done:
				return
			default:
			}
		}
	}(done, int32(fd))

	return ch, nil
}
func (tfd testFd) close() {
	unix.Close(tfd[1])
	unix.Close(tfd[0])
}
func (tfd testFd) closeWrite(t *testing.T) {
	errno := unix.Close(tfd[1])
	if errno != nil {
		t.Fatalf("Failed to close write end of pipe: %v", errno)
	}
}
示例#28
0
文件: kqueue.go 项目: nak3/nomad
// readEvents reads from kqueue and converts the received kevents into
// Event values that it sends down the Events channel.
func (w *Watcher) readEvents() {
	eventBuffer := make([]unix.Kevent_t, 10)

	for {
		// See if there is a message on the "done" channel
		select {
		case <-w.done:
			err := unix.Close(w.kq)
			if err != nil {
				w.Errors <- err
			}
			close(w.Events)
			close(w.Errors)
			return
		default:
		}

		// Get new events
		kevents, err := read(w.kq, eventBuffer, &keventWaitTime)
		// EINTR is okay, the syscall was interrupted before timeout expired.
		if err != nil && err != unix.EINTR {
			w.Errors <- err
			continue
		}

		// Flush the events we received to the Events channel
		for len(kevents) > 0 {
			kevent := &kevents[0]
			watchfd := int(kevent.Ident)
			mask := uint32(kevent.Fflags)
			w.mu.Lock()
			path := w.paths[watchfd]
			w.mu.Unlock()
			event := newEvent(path.name, mask)

			if path.isDir && !(event.Op&Remove == Remove) {
				// Double check to make sure the directory exists. This can happen when
				// we do a rm -fr on a recursively watched folders and we receive a
				// modification event first but the folder has been deleted and later
				// receive the delete event
				if _, err := os.Lstat(event.Name); os.IsNotExist(err) {
					// mark is as delete event
					event.Op |= Remove
				}
			}

			if event.Op&Rename == Rename || event.Op&Remove == Remove {
				w.Remove(event.Name)
				w.mu.Lock()
				delete(w.fileExists, event.Name)
				w.mu.Unlock()
			}

			if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) {
				w.sendDirectoryChangeEvents(event.Name)
			} else {
				// Send the event on the Events channel
				w.Events <- event
			}

			if event.Op&Remove == Remove {
				// Look for a file that may have overwritten this.
				// For example, mv f1 f2 will delete f2, then create f2.
				if path.isDir {
					fileDir := filepath.Clean(event.Name)
					w.mu.Lock()
					_, found := w.watches[fileDir]
					w.mu.Unlock()
					if found {
						// make sure the directory exists before we watch for changes. When we
						// do a recursive watch and perform rm -fr, the parent directory might
						// have gone missing, ignore the missing directory and let the
						// upcoming delete event remove the watch from the parent directory.
						if _, err := os.Lstat(fileDir); err == nil {
							w.sendDirectoryChangeEvents(fileDir)
						}
					}
				} else {
					filePath := filepath.Clean(event.Name)
					if fileInfo, err := os.Lstat(filePath); err == nil {
						w.sendFileCreatedEventIfNew(filePath, fileInfo)
					}
				}
			}

			// Move to next event
			kevents = kevents[1:]
		}
	}
}
示例#29
0
// TestPassFD tests passing a file descriptor over a Unix socket.
//
// This test involved both a parent and child process. The parent
// process is invoked as a normal test, with "go test", which then
// runs the child process by running the current test binary with args
// "-test.run=^TestPassFD$" and an environment variable used to signal
// that the test should become the child process instead.
func TestPassFD(t *testing.T) {
	switch runtime.GOOS {
	case "dragonfly":
		// TODO(jsing): Figure out why sendmsg is returning EINVAL.
		t.Skip("skipping test on dragonfly")
	case "solaris":
		// TODO(aram): Figure out why ReadMsgUnix is returning empty message.
		t.Skip("skipping test on solaris, see issue 7402")
	}
	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
		passFDChild()
		return
	}

	tempDir, err := ioutil.TempDir("", "TestPassFD")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
	if err != nil {
		t.Fatalf("Socketpair: %v", err)
	}
	defer unix.Close(fds[0])
	defer unix.Close(fds[1])
	writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
	readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
	defer writeFile.Close()
	defer readFile.Close()

	cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
	if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" {
		cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp)
	}
	cmd.ExtraFiles = []*os.File{writeFile}

	out, err := cmd.CombinedOutput()
	if len(out) > 0 || err != nil {
		t.Fatalf("child process: %q, %v", out, err)
	}

	c, err := net.FileConn(readFile)
	if err != nil {
		t.Fatalf("FileConn: %v", err)
	}
	defer c.Close()

	uc, ok := c.(*net.UnixConn)
	if !ok {
		t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
	}

	buf := make([]byte, 32) // expect 1 byte
	oob := make([]byte, 32) // expect 24 bytes
	closeUnix := time.AfterFunc(5*time.Second, func() {
		t.Logf("timeout reading from unix socket")
		uc.Close()
	})
	_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
	closeUnix.Stop()

	scms, err := unix.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		t.Fatalf("ParseSocketControlMessage: %v", err)
	}
	if len(scms) != 1 {
		t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
	}
	scm := scms[0]
	gotFds, err := unix.ParseUnixRights(&scm)
	if err != nil {
		t.Fatalf("unix.ParseUnixRights: %v", err)
	}
	if len(gotFds) != 1 {
		t.Fatalf("wanted 1 fd; got %#v", gotFds)
	}

	f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
	defer f.Close()

	got, err := ioutil.ReadAll(f)
	want := "Hello from child process!\n"
	if string(got) != want {
		t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
	}
}
示例#30
0
// close closes the file descriptor mapped to a network namespace
func (h nsHandle) close() error {
	return unix.Close(int(h))
}