Beispiel #1
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
}
Beispiel #2
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
}
Beispiel #3
0
func (a *OpenAnchor) Insert(r *Rule) error {
	rule := C.struct_pfioc_rule{}

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

	nr := &rule.rule

	// defaults
	nr.af = syscall.AF_INET
	nr.rtableid = C.int(-1)
	nr.onrdomain = C.int(-1)
	nr.keep_state = PF_STATE_NORMAL
	nr.flags = 0x2
	nr.flagset = 0x12
	nr.src.addr._type = PF_ADDR_ADDRMASK
	nr.dst.addr._type = PF_ADDR_ADDRMASK
	nr.nat.addr._type = PF_ADDR_NONE
	nr.rdr.addr._type = PF_ADDR_ADDRMASK

	switch r.Action {
	case Block:
		nr.action = PF_BLOCK
	case Pass:
		nr.action = PF_PASS
	case Match:
		nr.action = PF_MATCH
	}

	switch r.Direction {
	case InOut:
		nr.direction = PF_INOUT
	case In:
		nr.direction = PF_IN
	case Out:
		nr.direction = PF_OUT
	}

	if r.Log {
		nr.log = C.u_int8_t(1)
	}

	if r.Quick {
		nr.quick = C.u_int8_t(1)
	}

	ifname := C.CString(r.Interface)
	defer C.free(unsafe.Pointer(ifname))

	C.strlcpy(&nr.ifname[0], ifname, C.size_t(unsafe.Sizeof(nr.ifname)))

	tagname := C.CString(r.Tag)
	defer C.free(unsafe.Pointer(tagname))

	C.strlcpy(&nr.tagname[0], tagname, C.size_t(unsafe.Sizeof(nr.tagname)))

	if r.Src.Addr != nil {
		goaddrtopfaddr(r.Src.Addr, &nr.src.addr)
	}
	if r.Src.Port != 0 {
		nr.src.port_op = PF_OP_EQ
		nr.src.port[0] = C.u_int16_t(C.chtons(C.uint16_t(r.Src.Port)))
	}

	if r.Dst.Addr != nil {
		goaddrtopfaddr(r.Dst.Addr, &nr.dst.addr)
	}
	if r.Dst.Port != 0 {
		nr.dst.port_op = PF_OP_EQ
		nr.dst.port[0] = C.u_int16_t(C.chtons(C.uint16_t(r.Dst.Port)))
	}

	if r.Rdr != nil {
		if r.Rdr.Addr != nil {
			goaddrtopfaddr(r.Rdr.Addr, &nr.rdr.addr)
		}
		if r.Rdr.Port != 0 {
			//nr.rdr.port_op = PF_OP_EQ
			nr.rdr.proxy_port[0] = C.u_int16_t(r.Rdr.Port)
			nr.rdr.proxy_port[1] = C.u_int16_t(r.Rdr.Port)
		}
	}

	rule.action = PF_CHANGE_GET_TICKET

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

	rule.action = PF_CHANGE_ADD_TAIL

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

	return nil
}