M1: compat layer + pf.ko skeleton builds against Linux 7.3.4

- pfk.h: BSD types/ioctl encoding (OpenBSD bit layout), locks (NET_LOCK=rwsem),
  pools, timeouts, mbuf shim over sk_buff, ifnet registry, toeplitz/siphash
- pfk_mod/pfk_hooks: misc /dev/pf (0600), IPv4 netfilter hook skeleton,
  DIOCGETSTATUS answered (M1 skeleton; engine ioctls land with pf_ioctl.c)
- vendorize/stage-port scripts: deterministic upstream staging with seds
  (struct renames, IFF_*->PFIFF_*, sa_len drops) logged to docs/porting-notes
- fixes: modules_prepare+Module.symvers for out-of-tree builds
This commit is contained in:
lgcosta committed 2026-11-11 12:09:34 -03:00
1 parent ba81284bd3
commit da2e9b679a
87 files changed
+47256 -3

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
/* $OpenBSD: if_pflog.h,v 1.29 2021/01/13 09:13:30 mvs Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NET_IF_PFLOG_H_
#define _NET_IF_PFLOG_H_
#include <sys/queue.h>
#include <net/pfvar.h>
#define PFLOG_RULESET_NAME_SIZE 16
struct pfloghdr {
u_int8_t length;
sa_family_t af;
u_int8_t action;
u_int8_t reason;
char ifname[IFNAMSIZ];
char ruleset[PFLOG_RULESET_NAME_SIZE];
u_int32_t rulenr;
u_int32_t subrulenr;
uid_t uid;
pid_t pid;
uid_t rule_uid;
pid_t rule_pid;
u_int8_t dir;
u_int8_t rewritten;
sa_family_t naf;
u_int8_t pad[1];
struct pf_addr saddr;
struct pf_addr daddr;
u_int16_t sport;
u_int16_t dport;
};
#define PFLOG_HDRLEN sizeof(struct pfloghdr)
/* used to be minus pad, also used as a signature */
#define PFLOG_REAL_HDRLEN PFLOG_HDRLEN
#define PFLOG_OLD_HDRLEN offsetof(struct pfloghdr, pad)
#ifdef _KERNEL
struct pflog_softc {
LIST_ENTRY(pflog_softc) sc_entry;
struct ifnet sc_if; /* the interface */
int sc_unit;
};
#endif /* _KERNEL */
#endif /* _NET_IF_PFLOG_H_ */
+16
View File
@@ -0,0 +1,16 @@
/* PFLINUX compat: <net/if_types.h> — OpenBSD IFT_* constants
* (values must match OpenBSD: they travel in pf_rule/pfk_if ioctls). */
#ifndef _PFK_IF_TYPES_H
#define _PFK_IF_TYPES_H
#define IFT_OTHER 0x1
#define IFT_ETHER 0x6
#define IFT_TOKENRING 0xf
#define IFT_FDDI 0x12
#define IFT_LOOP 0x18
#define IFT_SLIP 0x1f
#define IFT_PPPOINT 0x1e
#define IFT_GIF 0xe6
#define IFT_PFLOG 0xf0
#define IFT_PFSYNC 0xf1
#define IFT_CARP 0xf8
#endif
+5
View File
@@ -0,0 +1,5 @@
/* PFLINUX compat: <net/if_var.h> — ifnet view comes from pfk_if.h */
#ifndef _PFK_IF_VAR_H
#define _PFK_IF_VAR_H
/* intentionally minimal; struct pfk_ifnet is the ifnet */
#endif
+507
View File
@@ -0,0 +1,507 @@
/* $OpenBSD: ifq.h,v 1.44 2025/03/04 01:13:37 dlg Exp $ */
/*
* Copyright (c) 2015 David Gwynne <dlg@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _NET_IFQ_H_
#define _NET_IFQ_H_
struct ifnet;
struct kstat;
struct ifq_ops;
struct ifqueue {
struct ifnet *ifq_if;
struct taskq *ifq_softnet;
union {
void *_ifq_softc;
/*
* a rings sndq is found by looking up an array of pointers.
* by default we only have one sndq and the default drivers
* dont use ifq_softc, so we can borrow it for the map until
* we need to allocate a proper map.
*/
struct ifqueue *_ifq_ifqs[1];
} _ifq_ptr;
#define ifq_softc _ifq_ptr._ifq_softc
#define ifq_ifqs _ifq_ptr._ifq_ifqs
/* mbuf handling */
struct mutex ifq_mtx;
const struct ifq_ops *ifq_ops;
void *ifq_q;
struct mbuf_list ifq_free;
unsigned int ifq_len;
unsigned int ifq_oactive;
/* statistics */
uint64_t ifq_packets;
uint64_t ifq_bytes;
uint64_t ifq_qdrops;
uint64_t ifq_errors;
uint64_t ifq_mcasts;
uint32_t ifq_oactives;
struct kstat *ifq_kstat;
/* work serialisation */
struct mutex ifq_task_mtx;
struct task_list ifq_task_list;
void *ifq_serializer;
struct task ifq_bundle;
/* work to be serialised */
struct task ifq_start;
struct task ifq_restart;
/* properties */
unsigned int ifq_maxlen;
unsigned int ifq_idx;
};
struct ifiqueue {
struct ifnet *ifiq_if;
caddr_t *ifiq_bpfp;
struct taskq *ifiq_softnet;
union {
void *_ifiq_softc;
struct ifiqueue *_ifiq_ifiqs[1];
} _ifiq_ptr;
#define ifiq_softc _ifiq_ptr._ifiq_softc
#define ifiq_ifiqs _ifiq_ptr._ifiq_ifiqs
struct mutex ifiq_mtx;
struct mbuf_list ifiq_ml;
struct task ifiq_task;
unsigned int ifiq_pressure;
/* counters */
uint64_t ifiq_packets;
uint64_t ifiq_bytes;
uint64_t ifiq_fdrops;
uint64_t ifiq_qdrops;
uint64_t ifiq_errors;
uint64_t ifiq_mcasts;
uint64_t ifiq_noproto;
/* number of times a list of packets were put on ifiq_ml */
uint64_t ifiq_enqueues;
/* number of times a list of packets were pulled off ifiq_ml */
uint64_t ifiq_dequeues;
struct kstat *ifiq_kstat;
/* properties */
unsigned int ifiq_idx;
};
#ifdef _KERNEL
#define IFQ_MAXLEN 256
/*
*
* Interface Send Queues
*
* struct ifqueue sits between the network stack and a drivers
* transmission of packets. The high level view is that when the stack
* has finished generating a packet it hands it to a driver for
* transmission. It does this by queueing the packet on an ifqueue and
* notifying the driver to start transmission of the queued packets.
*
* A network device may have multiple contexts for the transmission
* of packets, ie, independent transmit rings. Such a network device,
* represented by a struct ifnet, would then have multiple ifqueue
* structures, each of which maps to an independent transmit ring.
*
* struct ifqueue also provides the point where conditioning of
* traffic (ie, priq and hfsc) is implemented, and provides some
* infrastructure to assist in the implementation of network drivers.
*
* = ifq API
*
* The ifq API provides functions for three distinct consumers:
*
* 1. The network stack
* 2. Traffic QoS/conditioning implementations
* 3. Network drivers
*
* == Network Stack API
*
* The network stack is responsible for initialising and destroying
* the ifqueue structures, changing the traffic conditioner on an
* interface, enqueuing packets for transmission, and notifying
* the driver to start transmission of a particular ifqueue.
*
* === ifq_init()
*
* During if_attach(), the network stack calls ifq_init to initialise
* the ifqueue structure. By default it configures the priq traffic
* conditioner.
*
* === ifq_destroy()
*
* The network stack calls ifq_destroy() during if_detach to tear down
* the ifqueue structure. It frees the traffic conditioner state, and
* frees any mbufs that were left queued.
*
* === ifq_attach()
*
* ifq_attach() is used to replace the current traffic conditioner on
* the ifqueue. All the pending mbufs are removed from the previous
* conditioner and requeued on the new.
*
* === ifq_idx()
*
* ifq_idx() selects a specific ifqueue from the current ifnet
* structure for use in the transmission of the mbuf.
*
* === ifq_enqueue()
*
* ifq_enqueue() attempts to fit an mbuf onto the ifqueue. The
* current traffic conditioner may drop a packet to make space on the
* queue.
*
* === ifq_start()
*
* Once a packet has been successfully queued with ifq_enqueue(),
* the network card is notified with a call to ifq_start().
* Calls to ifq_start() run in the ifqueue serialisation context,
* guaranteeing that only one instance of ifp->if_qstart() will be
* running on behalf of a specific ifqueue in the system at any point
* in time.
*
* == Traffic conditioners API
*
* The majority of interaction between struct ifqueue and a traffic
* conditioner occurs via the callbacks a traffic conditioner provides
* in an instance of struct ifq_ops.
*
* XXX document ifqop_*
*
* The ifqueue API implements the locking on behalf of the conditioning
* implementations so conditioners only have to reject or keep mbufs.
* If something needs to inspect a conditioners internals, the queue lock
* needs to be taken to allow for a consistent or safe view. The queue
* lock may be taken and released with ifq_q_enter() and ifq_q_leave().
*
* === ifq_q_enter()
*
* Code wishing to access a conditioners internals may take the queue
* lock with ifq_q_enter(). The caller must pass a reference to the
* conditioners ifq_ops structure so the infrastructure can ensure the
* caller is able to understand the internals. ifq_q_enter() returns
* a pointer to the conditioners internal structures, or NULL if the
* ifq_ops did not match the current conditioner.
*
* === ifq_q_leave()
*
* The queue lock acquired with ifq_q_enter() is released with
* ifq_q_leave().
*
* === ifq_mfreem() and ifq_mfreeml()
*
* A goal of the API is to avoid freeing an mbuf while mutexes are
* held. Because the ifq API manages the lock on behalf of the backend
* ifqops, the backend should not directly free mbufs. If a conditioner
* backend needs to drop a packet during the handling of ifqop_deq_begin,
* it may free it by calling ifq_mfreem(). This accounts for the drop,
* and schedules the free of the mbuf outside the hold of ifq_mtx.
* ifq_mfreeml() takes an mbuf list as an argument instead.
*
*
* == Network Driver API
*
* The API used by network drivers is mostly documented in the
* ifq_dequeue(9) manpage except for ifq_serialize().
*
* === ifq_serialize()
*
* A driver may run arbitrary work in the ifqueue serialiser context
* via ifq_serialize(). The work to be done is represented by a task
* that has been prepared with task_set.
*
* The work will be run in series with any other work dispatched by
* ifq_start(), ifq_restart(), or other ifq_serialize() calls.
*
* Because the work may be run on another CPU, the lifetime of the
* task and the work it represents can extend beyond the end of the
* call to ifq_serialize() that dispatched it.
*
*
* = ifqueue work serialisation
*
* ifqueues provide a mechanism to dispatch work to be run in a single
* context. Work in this mechanism is represented by task structures.
*
* The tasks are run in a context similar to a taskq serviced by a
* single kernel thread, except the work is run immediately by the
* first CPU that dispatches work. If a second CPU attempts to dispatch
* additional tasks while the first is still running, it will be queued
* to be run by the first CPU. The second CPU will return immediately.
*
* = MP Safe Network Drivers
*
* An MP safe network driver is one in which its start routine can be
* called by the network stack without holding the big kernel lock.
*
* == Attach
*
* A driver advertises its ability to run its start routine without
* the kernel lock by setting the IFXF_MPSAFE flag in ifp->if_xflags
* before calling if_attach(). Advertising an MPSAFE start routine
* also implies that the driver understands that a network card can
* have multiple rings or transmit queues, and therefore provides
* if_qstart function (which takes an ifqueue pointer) instead of an
* if_start function (which takes an ifnet pointer).
*
* If the hardware supports multiple transmit rings, it advertises
* support for multiple rings to the network stack with if_attach_queues()
* after the call to if_attach(). if_attach_queues allocates a struct
* ifqueue for each hardware ring, which can then be initialised by
* the driver with data for each ring.
*
* void drv_start(struct ifqueue *);
*
* void
* drv_attach()
* {
* ...
* ifp->if_xflags = IFXF_MPSAFE;
* ifp->if_qstart = drv_start;
* if_attach(ifp);
*
* if_attach_queues(ifp, DRV_NUM_TX_RINGS);
* for (i = 0; i < DRV_NUM_TX_RINGS; i++) {
* struct ifqueue *ifq = ifp->if_ifqs[i];
* struct drv_tx_ring *ring = &sc->sc_tx_rings[i];
*
* ifq->ifq_softc = ring;
* ring->ifq = ifq;
* }
* }
*
* The network stack will then call ifp->if_qstart via ifq_start()
* to guarantee there is only one instance of that function running
* for each ifq in the system, and to serialise it with other work
* the driver may provide.
*
* == Initialise
*
* When the stack requests an interface be brought up (ie, drv_ioctl()
* is called to handle SIOCSIFFLAGS with IFF_UP set in ifp->if_flags)
* drivers should set IFF_RUNNING in ifp->if_flags, and then call
* ifq_clr_oactive() against each ifq.
*
* == if_start
*
* ifq_start() checks that IFF_RUNNING is set in ifp->if_flags, that
* ifq_is_oactive() does not return true, and that there are pending
* packets to transmit via a call to ifq_len(). Therefore, drivers are
* no longer responsible for doing this themselves.
*
* If a driver should not transmit packets while its link is down, use
* ifq_purge() to flush pending packets from the transmit queue.
*
* Drivers for hardware should use the following pattern to transmit
* packets:
*
* void
* drv_start(struct ifqueue *ifq)
* {
* struct drv_tx_ring *ring = ifq->ifq_softc;
* struct ifnet *ifp = ifq->ifq_if;
* struct drv_softc *sc = ifp->if_softc;
* struct mbuf *m;
* int kick = 0;
*
* if (NO_LINK) {
* ifq_purge(ifq);
* return;
* }
*
* for (;;) {
* if (NO_SPACE(ring)) {
* ifq_set_oactive(ifq);
* break;
* }
*
* m = ifq_dequeue(ifq);
* if (m == NULL)
* break;
*
* if (drv_encap(sc, ring, m) != 0) { // map and fill ring
* m_freem(m);
* continue;
* }
*
* bpf_mtap();
* }
*
* drv_kick(ring); // notify hw of new descriptors on the ring
* }
*
* == Transmission completion
*
* The following pattern should be used for transmit queue interrupt
* processing:
*
* void
* drv_txeof(struct drv_tx_ring *ring)
* {
* struct ifqueue *ifq = ring->ifq;
*
* while (COMPLETED_PKTS(ring)) {
* // unmap packets, m_freem() the mbufs.
* }
*
* if (ifq_is_oactive(ifq))
* ifq_restart(ifq);
* }
*
* == Stop
*
* Bringing an interface down (ie, IFF_UP was cleared in ifp->if_flags)
* should clear IFF_RUNNING in ifp->if_flags, and guarantee the start
* routine is not running before freeing any resources it uses:
*
* void
* drv_down(struct drv_softc *sc)
* {
* struct ifnet *ifp = &sc->sc_if;
* struct ifqueue *ifq;
* int i;
*
* CLR(ifp->if_flags, IFF_RUNNING);
* DISABLE_INTERRUPTS();
*
* for (i = 0; i < sc->sc_num_queues; i++) {
* ifq = ifp->if_ifqs[i];
* ifq_barrier(ifq);
* }
*
* intr_barrier(sc->sc_ih);
*
* FREE_RESOURCES();
*
* for (i = 0; i < sc->sc_num_queues; i++) {
* ifq = ifp->if_ifqs[i];
* ifq_clr_oactive(ifq);
* }
* }
*
*/
struct ifq_ops {
unsigned int (*ifqop_idx)(unsigned int,
const struct mbuf *);
struct mbuf *(*ifqop_enq)(struct ifqueue *, struct mbuf *);
struct mbuf *(*ifqop_deq_begin)(struct ifqueue *, void **);
void (*ifqop_deq_commit)(struct ifqueue *,
struct mbuf *, void *);
void (*ifqop_purge)(struct ifqueue *,
struct mbuf_list *);
void *(*ifqop_alloc)(unsigned int, void *);
void (*ifqop_free)(unsigned int, void *);
};
extern const struct ifq_ops * const ifq_priq_ops;
/*
* Interface send queues.
*/
void ifq_init(struct ifqueue *, struct ifnet *, unsigned int);
void ifq_attach(struct ifqueue *, const struct ifq_ops *, void *);
void ifq_destroy(struct ifqueue *);
void ifq_add_data(struct ifqueue *, struct if_data *);
int ifq_enqueue(struct ifqueue *, struct mbuf *);
void ifq_start(struct ifqueue *);
struct mbuf *ifq_deq_begin(struct ifqueue *);
void ifq_deq_commit(struct ifqueue *, struct mbuf *);
void ifq_deq_rollback(struct ifqueue *, struct mbuf *);
struct mbuf *ifq_dequeue(struct ifqueue *);
int ifq_hdatalen(struct ifqueue *);
void ifq_init_maxlen(struct ifqueue *, unsigned int);
void ifq_mfreem(struct ifqueue *, struct mbuf *);
void ifq_mfreeml(struct ifqueue *, struct mbuf_list *);
unsigned int ifq_purge(struct ifqueue *);
void *ifq_q_enter(struct ifqueue *, const struct ifq_ops *);
void ifq_q_leave(struct ifqueue *, void *);
void ifq_serialize(struct ifqueue *, struct task *);
void ifq_barrier(struct ifqueue *);
void ifq_set_oactive(struct ifqueue *);
void ifq_deq_set_oactive(struct ifqueue *);
int ifq_deq_sleep(struct ifqueue *, struct mbuf **, int, int,
const char *, volatile unsigned int *,
volatile unsigned int *);
#define ifq_len(_ifq) READ_ONCE((_ifq)->ifq_len)
#define ifq_empty(_ifq) (ifq_len(_ifq) == 0)
static inline int
ifq_is_priq(struct ifqueue *ifq)
{
return (ifq->ifq_ops == ifq_priq_ops);
}
static inline void
ifq_clr_oactive(struct ifqueue *ifq)
{
ifq->ifq_oactive = 0;
}
static inline unsigned int
ifq_is_oactive(struct ifqueue *ifq)
{
return (ifq->ifq_oactive);
}
static inline void
ifq_restart(struct ifqueue *ifq)
{
ifq_serialize(ifq, &ifq->ifq_restart);
}
static inline unsigned int
ifq_idx(struct ifqueue *ifq, unsigned int nifqs, const struct mbuf *m)
{
return ((*ifq->ifq_ops->ifqop_idx)(nifqs, m));
}
/* ifiq */
void ifiq_init(struct ifiqueue *, struct ifnet *, unsigned int);
void ifiq_destroy(struct ifiqueue *);
int ifiq_input(struct ifiqueue *, struct mbuf_list *);
int ifiq_enqueue_qlim(struct ifiqueue *, struct mbuf *,
unsigned int);
void ifiq_add_data(struct ifiqueue *, struct if_data *);
#define ifiq_len(_ifiq) READ_ONCE(ml_len(&(_ifiq)->ifiq_ml))
#define ifiq_empty(_ifiq) (ifiq_len(_ifiq) == 0)
static inline int
ifiq_enqueue(struct ifiqueue *ifiq, struct mbuf *m)
{
return ifiq_enqueue_qlim(ifiq, m, 0);
}
#endif /* _KERNEL */
#endif /* _NET_IFQ_H_ */
+75
View File
@@ -0,0 +1,75 @@
/* PFLINUX compat: <net/radix.h> — OpenBSD 8.0 radix structures/API
* (rn_*), cleaned of BSD-only syntax. Implementation: compat/radix.c
* (ported from OpenBSD 8.0 sys/net/radix.c, task T10). */
#ifndef _PFK_RADIX_H
#define _PFK_RADIX_H
#include <linux/types.h>
struct radix_mask;
struct radix_node {
struct radix_mask *rn_mklist;
struct radix_node *rn_p;
short rn_b;
char rn_bmask;
u_char rn_flags;
#define RNF_NORMAL 1
#define RNF_ROOT 2
#define RNF_ACTIVE 4
union {
struct {
caddr_t rn_Key;
caddr_t rn_Mask;
struct radix_node *rn_Dupedkey;
} rn_leaf;
struct {
int rn_Off;
struct radix_node *rn_L;
struct radix_node *rn_R;
} rn_node;
} rn_u;
};
#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
#define rn_key rn_u.rn_leaf.rn_Key
#define rn_mask rn_u.rn_leaf.rn_Mask
#define rn_off rn_u.rn_node.rn_Off
#define rn_l rn_u.rn_node.rn_L
#define rn_r rn_u.rn_node.rn_R
struct radix_mask {
short rm_b;
char rm_unused;
u_char rm_flags;
struct radix_mask *rm_mklist;
union {
caddr_t rmu_mask;
struct radix_node *rmu_leaf;
} rm_rmu;
int rm_refs;
};
#define rm_mask rm_rmu.rmu_mask
#define rm_leaf rm_rmu.rmu_leaf
struct radix_node_head {
struct radix_node *rnh_treetop;
int rnh_addrsize;
int rnh_pktsize;
struct radix_node rnh_nodes[3];
u_int rnh_rtableid;
};
void rn_init(unsigned int);
int rn_inithead(void **, int);
int rn_walktree(struct radix_node_head *,
int (*)(struct radix_node *, void *, u_int), void *);
struct radix_node *rn_addroute(void *, void *, struct radix_node_head *,
struct radix_node [2], u_int8_t);
struct radix_node *rn_delete(void *, void *, struct radix_node_head *,
struct radix_node *);
struct radix_node *rn_lookup(void *, void *, struct radix_node_head *);
struct radix_node *rn_match(void *, struct radix_node_head *);
#endif /* _PFK_RADIX_H_ */
+82
View File
@@ -0,0 +1,82 @@
/* $OpenBSD: rtable.h,v 1.36 2025/07/15 09:55:49 dlg Exp $ */
/*
* Copyright (c) 2014-2016 Martin Pieuchot
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _NET_RTABLE_H_
#define _NET_RTABLE_H_
#include <sys/rwlock.h>
struct art;
/*
* Locks used to protect struct members in this file:
* I immutable after creation
* N net lock
*/
struct rtable {
struct rwlock r_lock;
struct art *r_art; /* [I] */
unsigned int r_off; /* [I] Offset of key in bytes */
struct sockaddr *r_source; /* [N] use optional src addr */
};
/*
* Newer routing table implementation based on ART (Allotment Routing
* Table).
*/
#define rt_key(rt) ((rt)->rt_dest)
#define rt_plen(rt) ((rt)->rt_plen)
#define RT_ROOT(rt) (0)
int rtable_satoplen(sa_family_t, const struct sockaddr *);
void rtable_init(void);
int rtable_exists(unsigned int);
int rtable_empty(unsigned int);
int rtable_add(unsigned int);
unsigned int rtable_l2(unsigned int);
unsigned int rtable_loindex(unsigned int);
void rtable_l2set(unsigned int, unsigned int, unsigned int);
int rtable_setsource(unsigned int, int, struct sockaddr *);
struct sockaddr *rtable_getsource(unsigned int, int);
void rtable_clearsource(unsigned int, struct sockaddr *);
struct rtentry *rtable_lookup(unsigned int, const struct sockaddr *,
const struct sockaddr *, const struct sockaddr *, uint8_t);
struct rtentry *rtable_match(unsigned int, const struct sockaddr *,
uint32_t *);
struct rtentry *rtable_iterate(struct rtentry *);
int rtable_insert(unsigned int, struct sockaddr *,
const struct sockaddr *, const struct sockaddr *, uint8_t,
struct rtentry *);
int rtable_delete(unsigned int, const struct sockaddr *,
const struct sockaddr *, struct rtentry *);
int rtable_walk(unsigned int, sa_family_t, struct rtentry **,
int (*)(struct rtentry *, void *, unsigned int), void *);
int rtable_read(unsigned int, sa_family_t,
int (*)(const struct rtentry *, void *, unsigned int),
void *);
int rtable_mpath_capable(unsigned int, sa_family_t);
int rtable_mpath_reprio(unsigned int, struct sockaddr *, int,
uint8_t, struct rtentry *);
#endif /* _NET_RTABLE_H_ */
+53
View File
@@ -0,0 +1,53 @@
/* PFLINUX compat: <net/toeplitz.h> — software Toeplitz hash (RFC 3305)
* with the OpenBSD API shape used by PF (global cache + stoeplitz_* macros).
* Implementation: compat/toeplitz.c (uses kernel crypto_shash "sha256"). */
#ifndef _PFK_TOEPLITZ_H
#define _PFK_TOEPLITZ_H
#include <linux/types.h>
#define TOEPLITZ_KEY_LEN 40
struct stoeplitz_cache {
u8 key[TOEPLITZ_KEY_LEN];
u8 keyhash[32]; /* SHA256(key) */
int initialized;
};
extern struct stoeplitz_cache *stoeplitz_cache;
void stoeplitz_init(void);
void stoeplitz_cache_init(struct stoeplitz_cache *, const u8 *key);
uint16_t stoeplitz_hash_ip4(const struct stoeplitz_cache *,
const struct in_addr *, const struct in_addr *);
uint16_t stoeplitz_hash_ip4port(const struct stoeplitz_cache *,
const struct in_addr *, const struct in_addr *,
u16, u16);
uint16_t stoeplitz_hash_ip6(const struct stoeplitz_cache *,
const struct in6_addr *, const struct in6_addr *);
uint16_t stoeplitz_hash_ip6port(const struct stoeplitz_cache *,
const struct in6_addr *, const struct in6_addr *,
u16, u16);
uint16_t stoeplitz_hash_eaddr(const struct stoeplitz_cache *,
const u8 *);
uint16_t stoeplitz_hash_n16(const struct stoeplitz_cache *, u16);
uint16_t stoeplitz_hash_n32(const struct stoeplitz_cache *, u32);
uint16_t stoeplitz_hash_h16(const struct stoeplitz_cache *, u16);
uint16_t stoeplitz_hash_h32(const struct stoeplitz_cache *, u32);
uint16_t stoeplitz_hash_h64(const struct stoeplitz_cache *, u64);
#define stoeplitz_n32(_n32) stoeplitz_hash_n32(stoeplitz_cache, (_n32))
#define stoeplitz_h16(_h16) stoeplitz_hash_h16(stoeplitz_cache, (_h16))
#define stoeplitz_h32(_h32) stoeplitz_hash_h32(stoeplitz_cache, (_h32))
#define stoeplitz_h64(_h64) stoeplitz_hash_h64(stoeplitz_cache, (_h64))
#define stoeplitz_ip4(_sa4, _da4) \
stoeplitz_hash_ip4(stoeplitz_cache, (_sa4), (_da4))
#define stoeplitz_ip4port(_sa4, _da4, _sp, _dp) \
stoeplitz_hash_ip4port(stoeplitz_cache, (_sa4), (_da4), (_sp), (_dp))
#define stoeplitz_ip6(_sa6, _da6) \
stoeplitz_hash_ip6(stoeplitz_cache, (_sa6), (_da6))
#define stoeplitz_ip6port(_sa6, _da6, _sp, _dp) \
stoeplitz_hash_ip6port(stoeplitz_cache, (_sa6), (_da6), (_sp), (_dp))
#define stoeplitz_eaddr(_ea) \
stoeplitz_hash_eaddr(stoeplitz_cache, (_ea))
#endif