Пример #1
0
// Saves stats from the socket to the TPacket instance
func (h *TPacket) SocketStats() (SocketStats, SocketStatsV3, error) {
	h.mu.Lock()
	defer h.mu.Unlock()
	// We need to save the counters since asking for the stats will clear them
	if h.tpVersion == TPacketVersion3 {
		prevStats := h.socketStatsV3
		socklen := unsafe.Sizeof(h.socketStatsV3)
		var slt C.socklen_t = C.socklen_t(socklen)
		_, err := C.getsockopt(h.fd, C.SOL_PACKET, C.PACKET_STATISTICS, unsafe.Pointer(&h.socketStatsV3), &slt)
		if err != nil {
			return SocketStats{}, SocketStatsV3{}, err
		}

		h.socketStatsV3.tp_packets += prevStats.tp_packets
		h.socketStatsV3.tp_drops += prevStats.tp_drops
		h.socketStatsV3.tp_freeze_q_cnt += prevStats.tp_freeze_q_cnt

		return h.socketStats, h.socketStatsV3, nil
	} else {
		prevStats := h.socketStats
		socklen := unsafe.Sizeof(h.socketStats)
		var slt C.socklen_t = C.socklen_t(socklen)
		_, err := C.getsockopt(h.fd, C.SOL_PACKET, C.PACKET_STATISTICS, unsafe.Pointer(&h.socketStats), &slt)
		if err != nil {
			return SocketStats{}, SocketStatsV3{}, err
		}

		h.socketStats.tp_packets += prevStats.tp_packets
		h.socketStats.tp_drops += prevStats.tp_drops

		return h.socketStats, h.socketStatsV3, nil

	}
}
Пример #2
0
func cgoSockaddr(ip IP, zone string) (*C.struct_sockaddr, C.socklen_t) {
	if ip4 := ip.To4(); ip4 != nil {
		return cgoSockaddrInet4(ip4), C.socklen_t(syscall.SizeofSockaddrInet4)
	}
	if ip6 := ip.To16(); ip6 != nil {
		return cgoSockaddrInet6(ip6, zoneToInt(zone)), C.socklen_t(syscall.SizeofSockaddrInet6)
	}
	return nil, 0
}
Пример #3
0
func (sock fd) accept() (nfd fd, addr ax25Addr, err error) {
	addrLen := C.socklen_t(unsafe.Sizeof(addr))

	n, err := C.accept(
		C.int(sock),
		(*C.struct_sockaddr)(unsafe.Pointer(&addr)),
		&addrLen)

	if addrLen != C.socklen_t(unsafe.Sizeof(addr)) {
		panic("unexpected socklet_t")
	}

	return fd(n), addr, err
}
Пример #4
0
func newAfalg() (a *afalg, err error) {
	a = &afalg{tfm_fd: -1, op_fd: -1}
	runtime.SetFinalizer(a, func(a *afalg) {
		a.Close()
	})
	a.tfm_fd, err = syscall.Socket(syscall.AF_ALG, syscall.SOCK_SEQPACKET, 0)
	if err != nil || a.tfm_fd == -1 {
		a.Close()
		return nil, fmt.Errorf("failed creating af_alg socket: %v", err)
	}

	// rats, we can't call Bind with a sockaddr_alg. There's no sockaddr_alg
	// in the go stdlib, nor can i make up my own byte array that matches
	// the required sockaddr interface in the bind call. have to use cgo.
	if C.bind(C.int(a.tfm_fd), (*C.struct_sockaddr)(unsafe.Pointer(&C.sha1_sa)),
		C.socklen_t(unsafe.Sizeof(C.sha1_sa))) != 0 {
		a.Close()
		return nil, fmt.Errorf("failed binding af_alg connection")
	}

	// can't call Accept with go's stdlib, cause it's going to make up and
	// pass a sockaddr to fill in. not only do we not care about the sockaddr,
	// the sockaddr type is sockaddr_alg, and go doesn't understand that.
	nfd, _, e := syscall.Syscall(syscall.SYS_ACCEPT, uintptr(a.tfm_fd), 0, 0)
	a.op_fd = int(nfd)
	if e != 0 || a.op_fd == -1 {
		a.Close()
		return nil, fmt.Errorf("failed accepting af_alg connection: %v", e)
	}
	return a, nil
}
Пример #5
0
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
}
Пример #6
0
func (sock fd) bind(addr ax25Addr) (err error) {
	_, err = C.bind(
		C.int(sock),
		(*C.struct_sockaddr)(unsafe.Pointer(&addr)),
		C.socklen_t(unsafe.Sizeof(addr)))

	return
}
Пример #7
0
// setTPacketVersion asks the kernel to set TPacket to a particular version, and returns an error on failure.
func (h *TPacket) setTPacketVersion(version OptTPacketVersion) error {
	val := C.int(version)
	_, err := C.setsockopt(h.fd, C.SOL_PACKET, C.PACKET_VERSION, unsafe.Pointer(&val), C.socklen_t(unsafe.Sizeof(val)))
	if err != nil {
		return fmt.Errorf("setsockopt packet_version: %v", err)
	}
	return nil
}
Пример #8
0
// Processes a UDP packet. For when you're handling UDP yourself.
func (c *UTPContext) ProcessUDP(buf []byte, len int,
	to *syscall.RawSockaddr, tolen int) int {

	bufptr := (*C.byte)(unsafe.Pointer(&buf[0]))
	adrptr := (*C.struct_sockaddr)(unsafe.Pointer(to))
	return int(C.utp_process_udp(c.raw, bufptr, C.size_t(len),
		adrptr, C.socklen_t(tolen)))
}
Пример #9
0
// SetFanout activates TPacket's fanout ability.
// Use of Fanout requires creating multiple TPacket objects and the same id/type to
// a SetFanout call on each.  Note that this can be done cross-process, so if two
// different processes both call SetFanout with the same type/id, they'll share
// packets between them.  The same should work for multiple TPacket objects within
// the same process.
func (h *TPacket) SetFanout(t FanoutType, id uint16) error {
	h.mu.Lock()
	defer h.mu.Unlock()
	arg := C.int(t) << 16
	arg |= C.int(id)
	_, err := C.setsockopt(h.fd, C.SOL_PACKET, C.PACKET_FANOUT, unsafe.Pointer(&arg), C.socklen_t(unsafe.Sizeof(arg)))
	return err
}
Пример #10
0
// Clear socket counters and return empty stats
func (h *TPacket) InitSocketStats() error {
	if h.tpVersion == TPacketVersion3 {
		socklen := unsafe.Sizeof(h.socketStatsV3)
		var slt C.socklen_t = C.socklen_t(socklen)
		_, err := C.getsockopt(h.fd, C.SOL_PACKET, C.PACKET_STATISTICS, unsafe.Pointer(&h.socketStatsV3), &slt)
		if err != nil {
			return err
		}
		h.socketStatsV3 = SocketStatsV3{}
	} else {
		socklen := unsafe.Sizeof(h.socketStats)
		var slt C.socklen_t = C.socklen_t(socklen)
		_, err := C.getsockopt(h.fd, C.SOL_PACKET, C.PACKET_STATISTICS, unsafe.Pointer(&h.socketStats), &slt)
		if err != nil {
			return err
		}
		h.socketStats = SocketStats{}
	}
	return nil
}
func NewInterfaces() ([]InterfaceTotal, string) {
	var ifaces *C.struct_ifaddrs
	if getrc, _ := C.getifaddrs(&ifaces); getrc != 0 {
		return []InterfaceTotal{}, ""
	}
	defer C.freeifaddrs(ifaces)

	ifs := []InterfaceTotal{}
	IP := ""

	for fi := ifaces; fi != nil; fi = fi.ifa_next {
		if fi.ifa_addr == nil {
			continue
		}

		ifa_name := C.GoString(fi.ifa_name)
		if IP == "" &&
			fi.ifa_addr.sa_family == C.AF_INET &&
			ifa_name != "lo" &&
			!rx_lo.Match([]byte(ifa_name)) &&
			realInterfaceName(ifa_name) {

			sa_in := (*C.struct_sockaddr_in)(unsafe.Pointer(fi.ifa_addr))
			if C.inet_ntop(
				C.int(fi.ifa_addr.sa_family), // C.AF_INET,
				unsafe.Pointer(&sa_in.sin_addr),
				&C.ADDR[0],
				C.socklen_t(unsafe.Sizeof(C.ADDR))) != nil {

				IP = C.GoString((*C.char)(unsafe.Pointer(&C.ADDR)))
			}
		}

		if fi.ifa_addr.sa_family != C.AF_LINK {
			continue
		}

		data := fi.ifa_data
		if C.Ibytes(data) == 0 &&
			C.Obytes(data) == 0 {
			continue
		}
		ifs = append(ifs, InterfaceTotal{
			Name: ifa_name,
			In:   uint(C.Ibytes(data)),
			Out:  uint(C.Obytes(data)),
		})
	}
	return ifs, IP
}
Пример #12
0
// bindToInterface binds the TPacket socket to a particular named interface.
func (h *TPacket) bindToInterface(ifaceName string) error {
	iface, err := net.InterfaceByName(ifaceName)
	if err != nil {
		return fmt.Errorf("InterfaceByName: %v", err)
	}
	var ll C.struct_sockaddr_ll
	ll.sll_family = C.AF_PACKET
	ll.sll_protocol = C.__be16(C.htons(C.ETH_P_ALL))
	ll.sll_ifindex = C.int(iface.Index)
	if _, err := C.bind(h.fd, (*C.struct_sockaddr)(unsafe.Pointer(&ll)), C.socklen_t(unsafe.Sizeof(ll))); err != nil {
		return fmt.Errorf("bindToInterface: %v", err)
	}
	return nil
}
Пример #13
0
func ntop(fi *C.struct_ifaddrs) (string, bool) {
	if fi.ifa_addr == nil {
		return "", false
	}
	if fi.ifa_addr.sa_family != C.AF_INET {
		return "", false
	}
	saIn := (*C.struct_sockaddr_in)(unsafe.Pointer(fi.ifa_addr))
	if nil == C.inet_ntop(
		C.int(fi.ifa_addr.sa_family), // C.AF_INET,
		unsafe.Pointer(&saIn.sin_addr),
		&C.ADDR[0],
		C.socklen_t(unsafe.Sizeof(C.ADDR))) {
		return "", false
	}
	return C.GoString((*C.char)(unsafe.Pointer(&C.ADDR))), true
}
Пример #14
0
func (s *UTPSocket) Connect(addr *UTPAddr) (int, error) {
	// func (s *UTPSocket) Connect(to *syscall.RawSockaddr, tolen int) int {

	if addr == nil {
		return 0, net.InvalidAddrError("No address given.")
	}

	sa, err := addr.Sockaddr()
	if err != nil {
		return 0, err
	}

	rsa, err := sockaddr.NewRawSockaddr(&sa)
	if err != nil {
		return 0, err
	}

	ptr := (*C.struct_sockaddr)(unsafe.Pointer(&rsa.Raw))
	ret := int(C.utp_connect(s.raw, ptr, C.socklen_t(rsa.Len)))
	return ret, nil
}
Пример #15
0
// SetBPFFilter compiles and sets a BPF filter for the TPacket handle.
func (h *TPacket) SetBPFFilter(expr string) (err error) {
	// Open a dummy pcap handle
	p, err := pcap.OpenDead(layers.LinkTypeEthernet, int32(h.opts.frameSize))
	if err != nil {
		return fmt.Errorf("OpenDead: %s", err)
	}

	bpf, err := p.NewBPF(expr)
	if err != nil {
		return fmt.Errorf("NewBPF: %s", err)
	}

	program := bpf.BPF()

	_, err = C.setsockopt(h.fd, C.SOL_SOCKET, C.SO_ATTACH_FILTER,
		unsafe.Pointer(&program), C.socklen_t(unsafe.Sizeof(program)))
	if err != nil {
		return fmt.Errorf("setsockopt: %s", err)
	}
	return nil
}
func NewInterfaces(CH chan InterfacesInfo) {
	var ifaces *C.struct_ifaddrs
	if getrc, _ := C.getifaddrs(&ifaces); getrc != 0 {
		CH <- InterfacesInfo{}
		return
	}
	defer C.freeifaddrs(ifaces)

	ifs := []InterfaceInfo{}
	IP := ""

	for fi := ifaces; fi != nil; fi = fi.ifa_next {
		if fi.ifa_addr == nil {
			continue
		}

		ifa_name := C.GoString(fi.ifa_name)
		if IP == "" &&
			fi.ifa_addr.sa_family == C.AF_INET &&
			!rx_lo.Match([]byte(ifa_name)) &&
			realInterfaceName(ifa_name) {

			sa_in := (*C.struct_sockaddr_in)(unsafe.Pointer(fi.ifa_addr))
			if C.inet_ntop(
				C.int(fi.ifa_addr.sa_family), // C.AF_INET,
				unsafe.Pointer(&sa_in.sin_addr),
				&C.ADDR[0],
				C.socklen_t(unsafe.Sizeof(C.ADDR))) != nil {

				IP = C.GoString((*C.char)(unsafe.Pointer(&C.ADDR)))
			}
		}

		if fi.ifa_addr.sa_family != C.AF_LINK {
			continue
		}

		data := fi.ifa_data
		it := InterfaceInfo{
			Name:       ifa_name,
			InBytes:    uint(C.Ibytes(data)),
			OutBytes:   uint(C.Obytes(data)),
			InPackets:  uint(C.Ipackets(data)),
			OutPackets: uint(C.Opackets(data)),
			InErrors:   uint(C.Ierrors(data)),
			OutErrors:  uint(C.Oerrors(data)),
		}
		if it.InBytes == 0 &&
			it.OutBytes == 0 &&
			it.InPackets == 0 &&
			it.OutPackets == 0 &&
			it.InErrors == 0 &&
			it.OutErrors == 0 {
			continue
		}
		ifs = append(ifs, it)
	}
	CH <- InterfacesInfo{
		List: ifs,
		IP:   IP,
	}
}
Пример #17
0
// setUpRing sets up the shared-memory ring buffer between the user process and the kernel.
func (h *TPacket) setUpRing() (err error) {
	totalSize := C.uint(h.opts.framesPerBlock * h.opts.numBlocks * h.opts.frameSize)
	switch h.tpVersion {
	case TPacketVersion1, TPacketVersion2:
		var tp C.struct_tpacket_req
		tp.tp_block_size = C.uint(h.opts.blockSize)
		tp.tp_block_nr = C.uint(h.opts.numBlocks)
		tp.tp_frame_size = C.uint(h.opts.frameSize)
		tp.tp_frame_nr = C.uint(h.opts.framesPerBlock * h.opts.numBlocks)
		if _, err := C.setsockopt(h.fd, C.SOL_PACKET, C.PACKET_RX_RING, unsafe.Pointer(&tp), C.socklen_t(unsafe.Sizeof(tp))); err != nil {
			return fmt.Errorf("setsockopt packet_rx_ring: %v", err)
		}
	case TPacketVersion3:
		var tp C.struct_tpacket_req3
		tp.tp_block_size = C.uint(h.opts.blockSize)
		tp.tp_block_nr = C.uint(h.opts.numBlocks)
		tp.tp_frame_size = C.uint(h.opts.frameSize)
		tp.tp_frame_nr = C.uint(h.opts.framesPerBlock * h.opts.numBlocks)
		tp.tp_retire_blk_tov = C.uint(h.opts.blockTimeout / time.Millisecond)
		if _, err := C.setsockopt(h.fd, C.SOL_PACKET, C.PACKET_RX_RING, unsafe.Pointer(&tp), C.socklen_t(unsafe.Sizeof(tp))); err != nil {
			return fmt.Errorf("setsockopt packet_rx_ring v3: %v", err)
		}
	default:
		return errors.New("invalid tpVersion")
	}
	if h.ring, err = C.mmap(nil, C.size_t(totalSize), C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, C.int(h.fd), 0); err != nil {
		return
	}
	if h.ring == nil {
		return errors.New("no ring")
	}
	return nil
}
Пример #18
0
func cgoNameinfoPTR(b []byte, sa *C.struct_sockaddr, salen C.socklen_t) (int, error) {
	gerrno, err := C.getnameinfo(sa, salen, (*C.char)(unsafe.Pointer(&b[0])), C.socklen_t(len(b)), nil, 0, C.NI_NAMEREQD)
	return int(gerrno), err
}