From: Thomas Walker Lynch Date: Tue, 21 Oct 2025 02:59:27 +0000 (+0000) Subject: . X-Git-Url: https://git.reasoningtechnology.com/style/static/git-favicon.png?a=commitdiff_plain;h=afe8f8e6aa0528c4f708b1912f985ee4d63deb85;p=Rabbit%2F.git . --- diff --git a/developer/.gitignore b/developer/.gitignore deleted file mode 100644 index 120f485..0000000 --- a/developer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!/.gitignore diff --git a/developer/cc/Rabbit_2017_count.kmod.c b/developer/cc/Rabbit_2017_count.kmod.c new file mode 100644 index 0000000..ff4801b --- /dev/null +++ b/developer/cc/Rabbit_2017_count.kmod.c @@ -0,0 +1,81 @@ +// rabbit_uid2017.c — Count v4/v6 LOCAL_OUT & POST_ROUTING packets from UID 2017 only. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Hardcoded target UID */ +#define RABBIT_UID 2017 + +/* Counters: only increment when packet is from UID 2017 */ +static atomic64_t cnt_v4_local_out = ATOMIC64_INIT(0); +static atomic64_t cnt_v4_postroute = ATOMIC64_INIT(0); +static atomic64_t cnt_v6_local_out = ATOMIC64_INIT(0); +static atomic64_t cnt_v6_postroute = ATOMIC64_INIT(0); + +static inline bool from_uid_2017(const struct nf_hook_state *st, struct sk_buff *skb) { + struct sock *sk = st->sk ? st->sk : skb_to_full_sk(skb); + if (!sk) return false; /* no socket context */ + return __kuid_val(sock_i_uid(sk)) == RABBIT_UID; +} + +static unsigned int rabbit_v4_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *st) { + if (!from_uid_2017(st, skb)) return NF_ACCEPT; + + if (st->hook == NF_INET_LOCAL_OUT) atomic64_inc(&cnt_v4_local_out); + else if (st->hook == NF_INET_POST_ROUTING) atomic64_inc(&cnt_v4_postroute); + return NF_ACCEPT; +} + +static unsigned int rabbit_v6_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *st) { + if (!from_uid_2017(st, skb)) return NF_ACCEPT; + + if (st->hook == NF_INET_LOCAL_OUT) atomic64_inc(&cnt_v6_local_out); + else if (st->hook == NF_INET_POST_ROUTING) atomic64_inc(&cnt_v6_postroute); + return NF_ACCEPT; +} + +static struct nf_hook_ops rabbit_ops[] = { + { .hook = rabbit_v4_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_FIRST }, + { .hook = rabbit_v4_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_FIRST }, + { .hook = rabbit_v6_hook, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_FIRST }, + { .hook = rabbit_v6_hook, .pf = NFPROTO_IPV6, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP6_PRI_FIRST }, +}; + +static int __init rabbit_init(void) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + int ret = nf_register_net_hooks(&init_net, rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#else + int ret = nf_register_hooks(rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#endif + if (ret) pr_err("rabbit_uid2017: nf_register_* failed: %d\n", ret); + else pr_info("rabbit_uid2017: loaded; counting UID %d only (no-op)\n", RABBIT_UID); + return ret; +} + +static void __exit rabbit_exit(void) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + nf_unregister_net_hooks(&init_net, rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#else + nf_unregister_hooks(rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#endif + pr_info("rabbit_uid2017: unload stats v4(lo=%lld,po=%lld) v6(lo=%lld,po=%lld) [UID=%d]\n", + (long long)atomic64_read(&cnt_v4_local_out), + (long long)atomic64_read(&cnt_v4_postroute), + (long long)atomic64_read(&cnt_v6_local_out), + (long long)atomic64_read(&cnt_v6_postroute), + RABBIT_UID); +} + +module_init(rabbit_init); +module_exit(rabbit_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rabbit"); +MODULE_DESCRIPTION("Count LOCAL_OUT/POST_ROUTING packets from UID 2017"); diff --git a/developer/cc/Rabbit_2017_to_WG.kmod.c b/developer/cc/Rabbit_2017_to_WG.kmod.c new file mode 100644 index 0000000..cb2ed99 --- /dev/null +++ b/developer/cc/Rabbit_2017_to_WG.kmod.c @@ -0,0 +1,106 @@ +// rabbit_2017_to_WG.c — forward UID 2017 traffic to WG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RABBIT_UID 2017 +#define DEV_NAME "US" /* WireGuard iface to force */ + +static atomic64_t cnt_v4_local_out = ATOMIC64_INIT(0); +static atomic64_t cnt_v4_postroute = ATOMIC64_INIT(0); + +struct v4_cidr { __be32 net, mask; }; +#define V4(x) (__force __be32)cpu_to_be32(x) +static struct v4_cidr v4_excepts[] = { + { V4(0x7f000000), V4(0xff000000) }, /* 127.0.0.0/8 */ + { V4(0xa9fe0000), V4(0xffff0000) }, /* 169.254.0.0/16 */ + { V4(0xc0a80000), V4(0xffff0000) }, /* 192.168.0.0/16 (adjust) */ + { V4(0x0a000002), V4(0xffffffff) }, /* 10.0.0.2/32 US local */ + { V4(0x0a080004), V4(0xffffffff) }, /* 10.8.0.4/32 x6 local */ +}; +static inline bool v4_in_cidr(__be32 a, struct v4_cidr c){ return (a & c.mask) == (c.net & c.mask); } +static bool v4_is_except(__be32 d){ int i; for (i=0;isk ? st->sk : skb_to_full_sk(skb); + if (!sk) return false; + return __kuid_val(sock_i_uid(sk)) == RABBIT_UID; +} + +/* Bind the socket to DEV_NAME once we see its first packet */ +static inline void maybe_bind_socket_to_us(struct sk_buff *skb, const struct iphdr *iph, const struct nf_hook_state *st){ + struct sock *sk = st->sk ? st->sk : skb_to_full_sk(skb); + if (!sk || !us_ifindex) return; + if (v4_is_except(iph->daddr)) return; + if (READ_ONCE(sk->sk_bound_dev_if) == us_ifindex) return; + WRITE_ONCE(sk->sk_bound_dev_if, us_ifindex); +} + +static unsigned int rabbit_v4_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *st){ + if (st->pf != NFPROTO_IPV4) return NF_ACCEPT; + + if (st->hook == NF_INET_LOCAL_OUT) { + if (from_uid_2017(st, skb)) { + const struct iphdr *iph = ip_hdr(skb); + if (iph) maybe_bind_socket_to_us(skb, iph, st); + atomic64_inc(&cnt_v4_local_out); + } + } else if (st->hook == NF_INET_POST_ROUTING) { + if (from_uid_2017(st, skb)) atomic64_inc(&cnt_v4_postroute); + } + return NF_ACCEPT; +} + +static struct nf_hook_ops rabbit_ops[] = { + { .hook = rabbit_v4_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_FIRST }, + { .hook = rabbit_v4_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_FIRST }, +}; + +static int __init rabbit_init(void){ + struct net_device *dev; + rcu_read_lock(); + dev = dev_get_by_name_rcu(&init_net, DEV_NAME); + us_ifindex = dev ? dev->ifindex : 0; + rcu_read_unlock(); + if (!us_ifindex) { + pr_err("rabbit_uid2017_bind: device \"%s\" not found\n", DEV_NAME); + return -ENODEV; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + { + int ret = nf_register_net_hooks(&init_net, rabbit_ops, ARRAY_SIZE(rabbit_ops)); + if (ret) return ret; + } +#else + { int ret = nf_register_hooks(rabbit_ops, ARRAY_SIZE(rabbit_ops)); if (ret) return ret; } +#endif + pr_info("rabbit_uid2017_bind: loaded; UID=%d bound to dev %s(ifindex=%d)\n", RABBIT_UID, DEV_NAME, us_ifindex); + return 0; +} + +static void __exit rabbit_exit(void){ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + nf_unregister_net_hooks(&init_net, rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#else + nf_unregister_hooks(rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#endif + pr_info("rabbit_uid2017_bind: unload v4(lo=%lld,po=%lld)\n", + (long long)atomic64_read(&cnt_v4_local_out), + (long long)atomic64_read(&cnt_v4_postroute)); +} + +module_init(rabbit_init); +module_exit(rabbit_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rabbit"); +MODULE_DESCRIPTION("Force UID 2017 traffic onto dev \"US\" at LOCAL_OUT with IPv4 exceptions"); diff --git a/developer/cc/Rabbit_no-op.kmod.c b/developer/cc/Rabbit_no-op.kmod.c new file mode 100644 index 0000000..619f86a --- /dev/null +++ b/developer/cc/Rabbit_no-op.kmod.c @@ -0,0 +1,69 @@ +// rabbit_noop.c — Rabbit no-op netfilter interposer (Debian 12/Bookworm) +// Build: out-of-tree module. Load/unload to verify hook coverage. +// Behavior: increments counters, returns NF_ACCEPT. No packet mutation. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static atomic64_t cnt_v4_local_out = ATOMIC_LONG_INIT(0); +static atomic64_t cnt_v4_postroute = ATOMIC_LONG_INIT(0); +static atomic64_t cnt_v6_local_out = ATOMIC_LONG_INIT(0); +static atomic64_t cnt_v6_postroute = ATOMIC_LONG_INIT(0); + +static unsigned int rabbit_v4_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *st) { + if (st->hook == NF_INET_LOCAL_OUT) atomic64_inc(&cnt_v4_local_out); + else if (st->hook == NF_INET_POST_ROUTING) atomic64_inc(&cnt_v4_postroute); + return NF_ACCEPT; +} + +static unsigned int rabbit_v6_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *st) { + if (st->hook == NF_INET_LOCAL_OUT) atomic64_inc(&cnt_v6_local_out); + else if (st->hook == NF_INET_POST_ROUTING) atomic64_inc(&cnt_v6_postroute); + return NF_ACCEPT; +} + +static struct nf_hook_ops rabbit_ops[] = { + { .hook = rabbit_v4_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_FIRST }, + { .hook = rabbit_v4_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING,.priority = NF_IP_PRI_FIRST }, + { .hook = rabbit_v6_hook, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_FIRST }, + { .hook = rabbit_v6_hook, .pf = NFPROTO_IPV6, .hooknum = NF_INET_POST_ROUTING,.priority = NF_IP6_PRI_FIRST }, +}; + +static int __init rabbit_init(void) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + int ret = nf_register_net_hooks(&init_net, rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#else + int ret = nf_register_hooks(rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#endif + if (ret) + pr_err("rabbit_noop: nf_register_* failed: %d\n", ret); + else + pr_info("rabbit_noop: loaded (no-op)\n"); + return ret; +} + +static void __exit rabbit_exit(void) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) + nf_unregister_net_hooks(&init_net, rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#else + nf_unregister_hooks(rabbit_ops, ARRAY_SIZE(rabbit_ops)); +#endif + pr_info("rabbit_noop: unload stats v4(lo=%lld,po=%lld) v6(lo=%lld,po=%lld)\n", + (long long)atomic64_read(&cnt_v4_local_out), + (long long)atomic64_read(&cnt_v4_postroute), + (long long)atomic64_read(&cnt_v6_local_out), + (long long)atomic64_read(&cnt_v6_postroute)); +} + +module_init(rabbit_init); +module_exit(rabbit_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rabbit"); +MODULE_DESCRIPTION("Rabbit no-op netfilter interposer"); diff --git a/developer/scratchpad/.gitignore b/developer/scratchpad/.gitignore new file mode 100644 index 0000000..120f485 --- /dev/null +++ b/developer/scratchpad/.gitignore @@ -0,0 +1,2 @@ +* +!/.gitignore diff --git a/developer/tool/makefile b/developer/tool/makefile index 9677018..dacde58 100644 --- a/developer/tool/makefile +++ b/developer/tool/makefile @@ -6,7 +6,7 @@ include $(RT_INCOMMON)/make/environment_RT_1.mk .PHONY: usage usage: - @printf "Usage: make [usage|information|all|lib|cli|kmod|clean]\n"; exit 2 + @printf "Usage: make [usage|information|all|lib|cli|kmod|clean]\n" .PHONY: version version: @@ -29,13 +29,13 @@ information: .PHONY: all all: lib cli kmod -.PHONY: lib -lib: - @$(MAKE) -f $(RT_INCOMMON)/make/target_lib_cli.mk lib +.PHONY: library lib +library lib: + @$(MAKE) -f $(RT_INCOMMON)/make/target_library_cli.mk library .PHONY: cli cli: - @$(MAKE) -f $(RT_INCOMMON)/make/target_lib_cli.mk cli + @$(MAKE) -f $(RT_INCOMMON)/make/target_library_cli.mk cli .PHONY: kmod kmod: @@ -43,7 +43,7 @@ kmod: .PHONY: clean clean: - @$(MAKE) -f $(RT_INCOMMON)/make/target_lib_cli.mk clean + @$(MAKE) -f $(RT_INCOMMON)/make/target_library_cli.mk clean @$(MAKE) -f $(RT_INCOMMON)/make/target_kmod.mk clean diff --git a/document/conventions/release_howto.org b/document/conventions/release_howto.org deleted file mode 100644 index c4ebedc..0000000 --- a/document/conventions/release_howto.org +++ /dev/null @@ -1 +0,0 @@ -See 'workflow.org' diff --git a/document/quick_start_developer.sh b/document/quick_start_developer.sh new file mode 100644 index 0000000..3f31a98 --- /dev/null +++ b/document/quick_start_developer.sh @@ -0,0 +1,26 @@ +# This is a document, not a script +# There are more docs on IDEs, directory structure, etc. +# Note especially the workflow document. + +#1. In a login shell + + # enter the project environment as a developer + > cd Rabbit + > . env_developer + + # run your IDE + > emacs + +# 2. inside of an emacs shell, or IDE build scrit + + # do you edits + # run local test experiments + + > make all + > make release + + + # 3. In env_tester run more thorough test suite. When satisfied make a release branch and tag it. + # Release branches have consecutive major release numbers. + + diff --git a/release/kmod/Rabbit_2017_count.ko b/release/kmod/Rabbit_2017_count.ko new file mode 100644 index 0000000..6edb934 Binary files /dev/null and b/release/kmod/Rabbit_2017_count.ko differ