M1: pf.c compiles into pf.ko
This commit is contained in:
1 parent
1fcd7b3046
commit
0119e70960
54 files changed
+14853
-96
No files matched your search
+152
-4
@@ -1,8 +1,14 @@
|
||||
/*
|
||||
* PFLINUX rtable compatibility (ISC 2026).
|
||||
* PFLINUX rtable/route compatibility (ISC 2026).
|
||||
* Linux has no per-rtableid FIBs: rtable_exists() accepts every id and
|
||||
* rtable_iterate() is a terminal stub — the route-to implementation uses
|
||||
* the Linux FIB through pfk_xmit.c (pf_route/pf_route6, plan task T14).
|
||||
* rtable_iterate() stops after the first route (multipath iteration is
|
||||
* not modelled; recorded deviation). The PF route-to/mb-path checks get
|
||||
* their answers from the Linux FIB here; forwarding itself happens in
|
||||
* pfk_ip4.c/pfk_xmit.c.
|
||||
*
|
||||
* struct pf_rtentry instances are small heap snapshots of the Linux
|
||||
* route: egress ifindex + a BSD-shaped interface address view (needed by
|
||||
* ifatoia/ifatoia6 in pf.c) + label id (always 0, labels not modelled).
|
||||
*/
|
||||
#include <pfk.h>
|
||||
#include "compat/net/rtable.h"
|
||||
@@ -17,6 +23,148 @@ rtable_exists(unsigned int rtableid)
|
||||
struct pf_rtentry *
|
||||
rtable_iterate(struct pf_rtentry *rt)
|
||||
{
|
||||
/* PFLINUX: replaced by Linux FIB walk in pfk_route_next() (T14). */
|
||||
/* PFLINUX: multipath route iteration is not modelled; PF falls
|
||||
* back to the single Linux FIB answer (checked once). */
|
||||
(void)rt;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* attach a BSD interface-address view for the egress device */
|
||||
static void
|
||||
pfk_rt_fill_ifa(struct pf_rtentry *rt, struct pfk_ifnet *ifp, int family)
|
||||
{
|
||||
struct pfk_in_ifaddr *ia4;
|
||||
struct pfk_in6_ifaddr *ia6;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
if (!ifp)
|
||||
return;
|
||||
if (family == AF_INET) {
|
||||
ia4 = pfk_malloc(sizeof(*ia4), M_NOWAIT | M_ZERO);
|
||||
if (!ia4)
|
||||
return;
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
|
||||
ia4->ia_addr = *sintosa(ifa->ifa_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rt->rt_ifa = ia4;
|
||||
} else {
|
||||
ia6 = pfk_malloc(sizeof(*ia6), M_NOWAIT | M_ZERO);
|
||||
if (!ia6)
|
||||
return;
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
ia6->ia_addr = *sin6tosa(ifa->ifa_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rt->rt_ifa = ia6;
|
||||
}
|
||||
}
|
||||
|
||||
static struct pf_rtentry *
|
||||
pfk_rtentry_from_dst(struct dst_entry *d, const struct sockaddr *dst)
|
||||
{
|
||||
struct pf_rtentry *rt;
|
||||
struct pfk_ifnet *ifp;
|
||||
|
||||
rt = pfk_malloc(sizeof(*rt), M_NOWAIT | M_ZERO);
|
||||
if (!rt)
|
||||
return NULL;
|
||||
rt->rt_addr = (void *)dst; /* borrowed; not freed */
|
||||
rt->rt_ifidx = d->dev ? d->dev->ifindex : 0;
|
||||
rt->rt_flags = RTF_UP;
|
||||
ifp = d->dev ? pfk_ifp_byindex(d->dev->ifindex) : NULL;
|
||||
pfk_rt_fill_ifa(rt, ifp, dst->sa_family);
|
||||
return rt;
|
||||
}
|
||||
|
||||
struct pf_rtentry *
|
||||
rtalloc(const void *sap, int flags, unsigned int rtableid)
|
||||
{
|
||||
const struct sockaddr *sa = (const struct sockaddr *)sap;
|
||||
struct pf_rtentry *rt = NULL;
|
||||
|
||||
(void)flags; (void)rtableid; /* PFLINUX: one FIB, resolve implied */
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET: {
|
||||
struct flowi4 fl4 = { };
|
||||
struct rtable *r4;
|
||||
|
||||
fl4.daddr = sintosa(sa)->sin_addr.s_addr;
|
||||
r4 = ip_route_output_key(&init_net, &fl4);
|
||||
if (!IS_ERR(r4)) {
|
||||
rt = pfk_rtentry_from_dst(&r4->dst, sa);
|
||||
dst_release(&r4->dst);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
struct flowi6 fl6 = { };
|
||||
struct dst_entry *d;
|
||||
|
||||
fl6.daddr = sin6tosa(sa)->sin6_addr;
|
||||
d = ip6_route_output(&init_net, NULL, &fl6);
|
||||
if (d && !d->error) {
|
||||
rt = pfk_rtentry_from_dst(d, sa);
|
||||
dst_release(d);
|
||||
} else if (d)
|
||||
dst_release(d);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
struct pf_rtentry *
|
||||
rtalloc_mpath(const void *sa, uint32_t *hash, unsigned int rtableid)
|
||||
{
|
||||
/* PFLINUX: no multipath selection; hash hint unused. */
|
||||
(void)hash;
|
||||
return rtalloc(sa, RT_RESOLVE, rtableid);
|
||||
}
|
||||
|
||||
int
|
||||
rtisvalid(struct pf_rtentry *rt)
|
||||
{
|
||||
return rt != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rtfree(struct pf_rtentry *rt)
|
||||
{
|
||||
if (!rt)
|
||||
return;
|
||||
if (rt->rt_ifa)
|
||||
pfk_free(rt->rt_ifa);
|
||||
pfk_free(rt);
|
||||
}
|
||||
|
||||
/* ---------------- route labels ---------------- */
|
||||
/* Routing domains/labels are a non-goal of the port; these satisfy the
|
||||
* ioctl layer and report "unavailable" instead of pretending (pfk.h). */
|
||||
int
|
||||
rtlabel_name2id(const char *name)
|
||||
{
|
||||
(void)name;
|
||||
return (0); /* 0 == no label, pf_ioctl treats as failure */
|
||||
}
|
||||
|
||||
char *
|
||||
rtlabel_id2name(unsigned int id, char *buf, size_t len)
|
||||
{
|
||||
(void)id; (void)buf; (void)len;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
rtlabel_unref(unsigned int id)
|
||||
{
|
||||
(void)id;
|
||||
}
|
||||
Reference in new issue
Block a user