Пример #1
0
// NewRing creates a new PFRing.  Note that when the ring is initially created,
// it is disabled.  The caller must call Enable to start receiving packets.
// The caller should call Close on the given ring when finished with it.
func NewRing(device string, snaplen uint32, flags Flag) (ring *Ring, _ error) {
	dev := C.CString(device)
	defer C.free(unsafe.Pointer(dev))

	cptr, err := C.pfring_open(dev, C.u_int32_t(snaplen), C.u_int32_t(flags))
	if cptr == nil || err != nil {
		return nil, fmt.Errorf("pfring NewRing error: %v", err)
	}
	ring = &Ring{cptr: cptr, snaplen: int(snaplen)}
	ring.SetApplicationName(os.Args[0])
	return
}
Пример #2
0
func OpenBDB(env Environment, txn Transaction, file string, database *string, dbtype DbType, flags DbFlag, mode int) (*BerkeleyDB, error) {
	cFile := C.CString(file)
	defer C.free(unsafe.Pointer(cFile))

	var cDatabase *C.char
	if database != nil {
		cDatabase = C.CString(*database)
		defer C.free(unsafe.Pointer(cDatabase))
	}

	var db *BerkeleyDB = new(BerkeleyDB)

	//The flags parameter is currently unused, and must be set to 0.
	// https://docs.oracle.com/cd/E17276_01/html/api_reference/C/dbcreate.html
	err := Err(C.db_create(&db.ptr, env.ptr, 0))
	if err != nil {
		return nil, err
	}

	err = Err(C.db_open(db.ptr, txn.ptr, cFile, cDatabase, C.DBTYPE(dbtype), C.u_int32_t(flags), C.int(mode)))
	if err != nil {
		db.Close(0)
		return nil, err
	}
	return db, ok
}
Пример #3
0
func (db BerkeleyDB) Put(txn Transaction, key, val []byte, flags DbFlag) error {
	cKey := AllocDBT(key)
	defer cKey.Free()
	cVal := AllocDBT(val)
	defer cVal.Free()

	return Err(C.db_put(db.ptr, txn.ptr, cKey, cVal, C.u_int32_t(flags)))
}
Пример #4
0
func (db BerkeleyDB) NewCursor(txn Transaction, flags DbFlag) (*Cursor, error) {
	ret := new(Cursor)
	err := Err(C.db_cursor(db.ptr, txn.ptr, &ret.ptr, C.u_int32_t(flags)))
	if err != nil {
		return nil, err
	}
	return ret, ok
}
Пример #5
0
func AllocDBT(val []byte) *C.DBT {
	return &C.DBT{
		// someday we will be able to use C.CBytes() for this purpose
		// https://github.com/golang/go/issues/14838
		data:  unsafe.Pointer(C.CString(string(val))),
		size:  C.u_int32_t(len(val)),
		flags: C.DB_DBT_USERMEM,
	}
}
Пример #6
0
// NewRing creates a new PFRing.  Note that when the ring is initially created,
// it is disabled.  The caller must call Enable to start receiving packets.
// The caller should call Close on the given ring when finished with it.
func NewRing(device string, snaplen uint32, flags Flag) (ring *Ring, _ error) {
	dev := C.CString(device)
	defer C.free(unsafe.Pointer(dev))

	cptr, err := C.pfring_open(dev, C.u_int32_t(snaplen), C.u_int32_t(flags))
	if cptr == nil || err != nil {
		return nil, fmt.Errorf("pfring NewRing error: %v", err)
	}
	ring = &Ring{cptr: cptr, snaplen: int(snaplen)}

	if flags&FlagLongHeader == FlagLongHeader {
		ring.useExtendedPacketHeader = true
	} else {
		ifc, err := net.InterfaceByName(device)
		if err == nil {
			ring.interfaceIndex = ifc.Index
		}
	}
	ring.SetApplicationName(os.Args[0])
	return
}
Пример #7
0
func (cursor Cursor) CursorGetRaw(flags DbFlag) ([]byte, []byte, error) {
	key := C.DBT{flags: C.DB_DBT_REALLOC}
	defer C.free(key.data)
	val := C.DBT{flags: C.DB_DBT_REALLOC}
	defer C.free(val.data)

	err := Err(C.db_cursor_get(cursor.ptr, &key, &val, C.u_int32_t(flags)))
	if err != nil {
		return nil, nil, err
	}
	return cloneToBytes(&key), cloneToBytes(&val), ok
}
Пример #8
0
func (env Environment) Close(flags DbFlag) error {
	if env.ptr == nil {
		return ok
	}

	err := Err(C.db_env_close(env.ptr, C.u_int32_t(flags)))
	if err != nil {
		return err
	}

	env.ptr = nil
	return ok
}
Пример #9
0
func (db BerkeleyDB) Close(flags DbFlag) error {
	if db.ptr == nil {
		return ok
	}

	err := Err(C.db_close(db.ptr, C.u_int32_t(flags)))
	if err != nil {
		return err
	}

	db.ptr = nil
	return ok
}
Пример #10
0
func (db BerkeleyDB) Get(txn Transaction, key []byte, flags DbFlag) ([]byte, error) {
	data := &C.DBT{flags: C.DB_DBT_REALLOC}
	defer data.Free()

	cKey := AllocDBT(key)
	defer cKey.Free()

	err := Err(C.db_get(db.ptr, txn.ptr, cKey, data, C.u_int32_t(flags)))
	if err != nil {
		return nil, err
	}

	return cloneToBytes(data), ok
}
Пример #11
0
// Queues returns all queues in pf.
func (p *OpenPf) Queues() ([]Queue, error) {
	pq := &C.struct_pfioc_queue{}
	pqs := &C.struct_pfioc_qstats{}
	hfscstats := &C.struct_hfsc_class_stats{}

	err := ioctl(p.fd.Fd(), DIOCGETQUEUES, uintptr(unsafe.Pointer(pq)))
	if err != nil {
		return nil, err
	}

	queues := make([]Queue, 0)

	n := int(pq.nr)

	for i := 0; i < n; i++ {
		pqs.nr = C.u_int32_t(i)
		pqs.ticket = pq.ticket
		pqs.buf = unsafe.Pointer(hfscstats)
		pqs.nbytes = C.int(unsafe.Sizeof(C.struct_hfsc_class_stats{}))

		err := ioctl(p.fd.Fd(), DIOCGETQSTATS, uintptr(unsafe.Pointer(pqs)))
		if err != nil {
			return nil, err
		}

		qname := C.GoString(&pqs.queue.qname[0])
		if qname[0] == '_' {
			continue
		}

		qparent := C.GoString(&pqs.queue.parent[0])
		qifname := C.GoString(&pqs.queue.ifname[0])

		queue := Queue{
			Name:   qname,
			Parent: qparent,
			IfName: qifname,
			Stats: QueueStats{
				TransmitPackets: uint64(hfscstats.xmit_cnt.packets),
				TransmitBytes:   uint64(hfscstats.xmit_cnt.bytes),
				DroppedPackets:  uint64(hfscstats.drop_cnt.packets),
				DroppedBytes:    uint64(hfscstats.drop_cnt.bytes),
			},
		}

		queues = append(queues, queue)
	}

	return queues, nil
}
Пример #12
0
// Perform an operation within a transaction. The transaction is
// automatically committed if the action doesn't return an error. If
// an error occurs, the transaction is automatically aborted. Any
// error is passed through to the caller.
func (env Environment) WithTransaction(config *TransactionConfig, action func(Transaction) error) (err error) {
	var parent *C.DB_TXN
	var flags C.u_int32_t = C.DB_READ_COMMITTED

	if config != nil {
		if config.Parent != NoTransaction {
			parent = config.Parent.ptr
		}
		if config.Isolation != 0 {
			flags = C.u_int32_t(config.Isolation)
		}
		if config.Bulk {
			flags |= C.DB_TXN_BULK
		}
		if config.NoWait {
			flags |= C.DB_TXN_NOWAIT
		}
		if config.NoSync {
			flags |= C.DB_TXN_NOSYNC
		}
		if config.WriteNoSync {
			flags |= C.DB_TXN_WRITE_NOSYNC
		}
	}

	var txn Transaction
	err = check(C.db_env_txn_begin(env.ptr, parent, &txn.ptr, flags))
	if err == nil {
		defer func() {
			if err != nil && txn.ptr != nil {
				C.db_txn_abort(txn.ptr)
				txn.ptr = nil
			}
		}()
	} else {
		return
	}

	err = action(txn)
	if err == nil {
		err = check(C.db_txn_commit(txn.ptr, 0))
		txn.ptr = nil
	} else {
		return
	}

	return
}
Пример #13
0
// Marshal a protobuf struct into a database thang.
func marshalDBT(dbt *C.DBT, val proto.Message) (err error) {
	buf, err := proto.Marshal(val)
	if err != nil {
		return
	}

	if len(buf) > 0 {
		dbt.data = unsafe.Pointer(&buf[0])
		dbt.size = C.u_int32_t(len(buf))
	} else {
		dbt.data = nil
		dbt.size = 0
	}

	return
}
Пример #14
0
//Create and bind to queue specified by queueId
func NewNFQueue(queueId uint16, maxPacketsInQueue uint32, packetSize uint32) (*NFQueue, error) {
	var nfq = NFQueue{}
	var err error
	var ret C.int

	if nfq.h, err = C.nfq_open(); err != nil {
		return nil, fmt.Errorf("Error opening NFQueue handle: %v\n", err)
	}

	if ret, err = C.nfq_unbind_pf(nfq.h, AF_INET); err != nil || ret < 0 {
		return nil, fmt.Errorf("Error unbinding existing NFQ handler from AF_INET protocol family: %v\n", err)
	}

	if ret, err := C.nfq_bind_pf(nfq.h, AF_INET); err != nil || ret < 0 {
		return nil, fmt.Errorf("Error binding to AF_INET protocol family: %v\n", err)
	}

	nfq.packets = make(chan NFPacket)
	if nfq.qh, err = C.CreateQueue(nfq.h, C.u_int16_t(queueId), unsafe.Pointer(&nfq.packets)); err != nil || nfq.qh == nil {
		C.nfq_close(nfq.h)
		return nil, fmt.Errorf("Error binding to queue: %v\n", err)
	}

	if ret, err = C.nfq_set_queue_maxlen(nfq.qh, C.u_int32_t(maxPacketsInQueue)); err != nil || ret < 0 {
		C.nfq_destroy_queue(nfq.qh)
		C.nfq_close(nfq.h)
		return nil, fmt.Errorf("Unable to set max packets in queue: %v\n", err)
	}

	if C.nfq_set_mode(nfq.qh, C.u_int8_t(2), C.uint(packetSize)) < 0 {
		C.nfq_destroy_queue(nfq.qh)
		C.nfq_close(nfq.h)
		return nil, fmt.Errorf("Unable to set packets copy mode: %v\n", err)
	}

	if nfq.fd, err = C.nfq_fd(nfq.h); err != nil {
		C.nfq_destroy_queue(nfq.qh)
		C.nfq_close(nfq.h)
		return nil, fmt.Errorf("Unable to get queue file-descriptor. %v", err)
	}

	go nfq.run()

	return &nfq, nil
}
Пример #15
0
func NewEnvironment(home string, flags DbFlag, mode int) (*Environment, error) {
	ret := new(Environment)

	err := Err(C.db_env_create(&ret.ptr, 0))
	if err != nil {
		return nil, err
	}

	cHome := C.CString(home)
	defer C.free(unsafe.Pointer(cHome))

	err = Err(C.db_env_open(ret.ptr, cHome, C.u_int32_t(flags), C.int(mode)))
	if err != nil {
		ret.Close(0)
		return nil, err
	}

	return ret, ok
}
Пример #16
0
func (p *OpenPf) Anchors() ([]string, error) {
	pr := &C.struct_pfioc_ruleset{}

	err := ioctl(p.fd.Fd(), DIOCGETRULESETS, uintptr(unsafe.Pointer(pr)))
	if err != nil {
		return nil, err
	}

	anchors := make([]string, 0)

	n := int(pr.nr)

	for i := 0; i < n; i++ {
		pr.nr = C.u_int32_t(i)

		err := ioctl(p.fd.Fd(), DIOCGETRULESET, uintptr(unsafe.Pointer(pr)))
		if err != nil {
			return nil, err
		}

		anchor := ""

		if pr.path[0] != '\x00' {
			anchor += C.GoString(&pr.path[0]) + "/"
		}

		name := C.GoString(&pr.name[0])

		if name == PF_RESERVED_ANCHOR {
			continue
		}

		anchor += name

		anchors = append(anchors, anchor)
	}

	return anchors, nil
}
Пример #17
0
func (a *OpenAnchor) DeleteIndex(nr int) error {
	rule := C.struct_pfioc_rule{
		action: PF_CHANGE_GET_TICKET,
		nr:     C.u_int32_t(nr),
	}

	aname := C.CString(a.name)
	C.strlcpy(&rule.anchor[0], aname, C.size_t(unsafe.Sizeof(rule.anchor)))
	C.free(unsafe.Pointer(aname))

	err := ioctl(a.pf.fd.Fd(), DIOCCHANGERULE, uintptr(unsafe.Pointer(&rule)))
	if err != nil {
		return err
	}

	rule.action = PF_CHANGE_REMOVE

	err = ioctl(a.pf.fd.Fd(), DIOCCHANGERULE, uintptr(unsafe.Pointer(&rule)))
	if err != nil {
		return err
	}

	return nil
}
Пример #18
0
func (a *OpenAnchor) Rules() ([]Rule, error) {
	pr := &C.struct_pfioc_rule{}

	aname := C.CString(a.name)
	defer C.free(unsafe.Pointer(aname))

	C.strlcpy(&pr.anchor[0], aname, C.size_t(unsafe.Sizeof(pr.anchor)))

	err := ioctl(a.pf.fd.Fd(), DIOCGETRULES, uintptr(unsafe.Pointer(pr)))
	if err != nil {
		return nil, err
	}

	count := int(pr.nr)

	rules := make([]Rule, 0)

	for i := 0; i < count; i++ {
		pr.nr = C.u_int32_t(i)
		err := ioctl(a.pf.fd.Fd(), DIOCGETRULE, uintptr(unsafe.Pointer(pr)))
		if err != nil {
			return nil, err
		}

		if pr.anchor_call[0] != 0 {
			continue
		}

		r := Rule{Nr: uint32(pr.nr)}

		switch pr.rule.action {
		case PF_PASS:
			r.Action = Pass
		case PF_BLOCK:
			r.Action = Block
		case PF_MATCH:
			r.Action = Match
		default:
			panic("bad action")
		}

		switch pr.rule.direction {
		case PF_INOUT:
			r.Direction = InOut
		case PF_IN:
			r.Direction = In
		case PF_OUT:
			r.Direction = Out
		default:
			panic("bad direction")
		}

		if pr.rule.log != 0 {
			r.Log = true
		}

		if pr.rule.quick != 0 {
			r.Quick = true
		}

		r.Interface = C.GoString(&pr.rule.ifname[0])
		r.Tag = C.GoString(&pr.rule.tagname[0])

		r.Src = Target{Port: ntohs((uint16(pr.rule.src.port[0])))}

		switch pr.rule.src.addr._type {
		case PF_ADDR_ADDRMASK:
			_, net, err := net.ParseCIDR(addrwrapstr(&pr.rule.src.addr, int(pr.rule.af)))
			if err != nil {
				panic(err)
			}
			r.Src.Addr = AddrIPMask{*net}
		case PF_ADDR_DYNIFTL:
			r.Src.Addr = AddrDynIf{addrwrapstr(&pr.rule.src.addr, int(pr.rule.af))}
		default:
			panic("bad src")
		}

		r.Dst = Target{Port: ntohs((uint16(pr.rule.dst.port[0])))}

		switch pr.rule.dst.addr._type {
		case PF_ADDR_ADDRMASK:
			_, net, err := net.ParseCIDR(addrwrapstr(&pr.rule.dst.addr, int(pr.rule.af)))
			if err != nil {
				panic(err)
			}
			r.Dst.Addr = AddrIPMask{*net}
		case PF_ADDR_DYNIFTL:
			r.Dst.Addr = AddrDynIf{addrwrapstr(&pr.rule.dst.addr, int(pr.rule.af))}
		default:
			panic("bad dst")
		}

		if pr.rule.rdr.addr._type != PF_ADDR_NONE {
			r.Rdr = &Target{Port: uint16(pr.rule.rdr.proxy_port[0])}

			switch pr.rule.rdr.addr._type {
			case PF_ADDR_ADDRMASK:
				_, net, err := net.ParseCIDR(addrwrapstr(&pr.rule.rdr.addr, int(pr.rule.af)))
				if err != nil {
					panic(err)
				}
				r.Rdr.Addr = AddrIPMask{*net}
			case PF_ADDR_DYNIFTL:
				r.Rdr.Addr = AddrDynIf{addrwrapstr(&pr.rule.rdr.addr, int(pr.rule.af))}
			}
		}

		rules = append(rules, r)
	}

	return rules, nil
}
Пример #19
0
func (db BerkeleyDB) Del(txn Transaction, key []byte, flags DbFlag) error {
	cKey := AllocDBT(key)
	defer cKey.Free()
	return Err(C.db_del(db.ptr, txn.ptr, cKey, C.u_int32_t(flags)))
}
Пример #20
0
// Close the environment.
func (env Environment) Close() (err error) {
	err = check(C.db_env_close(env.ptr, C.u_int32_t(C.DB_FORCESYNC)))
	return
}
Пример #21
0
// SetSamplingRate sets the sampling rate to 1/<rate>.
func (r *Ring) SetSamplingRate(rate int) error {
	if rv := C.pfring_set_sampling_rate(r.cptr, C.u_int32_t(rate)); rv != 0 {
		return fmt.Errorf("Unable to set sampling rate, got error code %d", rv)
	}
	return nil
}