M1: pf.c compiles into pf.ko

This commit is contained in:
lgcosta committed 2026-11-11 14:55:20 -03:00
1 parent 1fcd7b3046
commit 0119e70960
54 files changed
+14853 -96

No files matched your search

+152 -4
View File
@@ -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;
}