From ab27472eb44b0690f74d542ddb9a972460eceb9a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 11 Aug 2008 22:07:41 -0400 Subject: [PATCH] src: move to a pskb-based API It occurred that skb reallocation does happen on older kernels, and those kernels should really be supported, since the patch is really minimal. --- extensions/compat_xtables.c | 63 +++++++++++++------------------------ extensions/compat_xtables.h | 18 +++++------ extensions/compat_xtnu.h | 6 ++-- extensions/xt_CHAOS.c | 15 ++++----- extensions/xt_DELUDE.c | 12 ++++--- extensions/xt_ECHO.c | 3 +- extensions/xt_IPMARK.c | 6 ++-- extensions/xt_LOGMARK.c | 3 +- extensions/xt_SYSRQ.c | 14 +++++---- extensions/xt_TARPIT.c | 11 ++++--- extensions/xt_TEE.c | 6 ++-- 11 files changed, 75 insertions(+), 82 deletions(-) diff --git a/extensions/compat_xtables.c b/extensions/compat_xtables.c index 8e05b87..3c40863 100644 --- a/extensions/compat_xtables.c +++ b/extensions/compat_xtables.c @@ -20,15 +20,6 @@ #include "compat_skbuff.h" #include "compat_xtnu.h" -static inline int unable(const char *cause, unsigned int c) -{ - if (net_ratelimit()) - printk(KERN_ERR KBUILD_MODNAME - ": compat layer limits reached (%s) - " - "dropping packets (%u so far)\n", cause, c); - return -1; -} - #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22) static int xtnu_match_run(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, @@ -161,15 +152,21 @@ static unsigned int xtnu_target_run(struct sk_buff **pskb, static unsigned int xtnu_target_run(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *ct, const void *targinfo) +#else +static unsigned int xtnu_target_run(struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const struct xt_target *ct, const void *targinfo) #endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) { struct xtnu_target *nt = xtcompat_nutarget(ct); if (nt != NULL && nt->target != NULL) - return nt->target(*pskb, in, out, hooknum, nt, targinfo); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) + return nt->target(pskb, in, out, hooknum, nt, targinfo); +#else + return nt->target(&skb, in, out, hooknum, nt, targinfo); +#endif return XT_CONTINUE; } -#endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) static int xtnu_target_check(const char *table, const void *entry, @@ -178,11 +175,10 @@ static int xtnu_target_check(const char *table, const void *entry, #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22) static int xtnu_target_check(const char *table, const void *entry, const struct xt_target *ct, void *targinfo, unsigned int hook_mask) -#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) +#else static bool xtnu_target_check(const char *table, const void *entry, const struct xt_target *ct, void *targinfo, unsigned int hook_mask) #endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) { struct xtnu_target *nt = xtcompat_nutarget(ct); if (nt == NULL) @@ -192,23 +188,19 @@ static bool xtnu_target_check(const char *table, const void *entry, return true; return nt->checkentry(table, entry, nt, targinfo, hook_mask); } -#endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo, unsigned int targinfosize) -#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) +#else static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo) #endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) { struct xtnu_target *nt = xtcompat_nutarget(ct); if (nt != NULL && nt->destroy != NULL) nt->destroy(nt, targinfo); } -#endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) int xtnu_register_target(struct xtnu_target *nt) { struct xt_target *ct; @@ -276,7 +268,6 @@ void xtnu_unregister_targets(struct xtnu_target *nt, unsigned int num) xtnu_unregister_target(&nt[i]); } EXPORT_SYMBOL_GPL(xtnu_unregister_targets); -#endif struct xt_match *xtnu_request_find_match(unsigned int af, const char *name, uint8_t revision) @@ -302,38 +293,28 @@ struct xt_match *xtnu_request_find_match(unsigned int af, const char *name, } EXPORT_SYMBOL_GPL(xtnu_request_find_match); -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) -int xtnu_ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type) +int xtnu_ip_route_me_harder(struct sk_buff **pskb, unsigned int addr_type) { - static unsigned int rmh_counter; - struct sk_buff *nskb = skb; - int ret; - #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17) /* Actually this one is valid up to 2.6.18.4, but changed in 2.6.18.5 */ - ret = ip_route_me_harder(&skb); + return ip_route_me_harder(pskb); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) - ret = ip_route_me_harder(&nskb, addr_type); + return ip_route_me_harder(pskb, addr_type); +#else + return ip_route_me_harder(*pskb, addr_type); #endif - if (nskb != skb) - return unable(__func__, ++rmh_counter); - return ret; } EXPORT_SYMBOL_GPL(xtnu_ip_route_me_harder); -int xtnu_skb_make_writable(struct sk_buff *skb, unsigned int len) +int xtnu_skb_make_writable(struct sk_buff **pskb, unsigned int len) { - static unsigned int mkw_counter; - struct sk_buff *nskb = skb; - int ret; - - ret = skb_make_writable(&skb, len); - if (nskb != skb) - return unable(__func__, ++mkw_counter) <= 0 ? false : true; - return ret; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) + return skb_make_writable(pskb, len); +#else + return skb_make_writable(*pskb, len); +#endif } EXPORT_SYMBOL_GPL(xtnu_skb_make_writable); -#endif #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 24) static int __xtnu_ip_local_out(struct sk_buff *skb) diff --git a/extensions/compat_xtables.h b/extensions/compat_xtables.h index 617314c..9d2d2d2 100644 --- a/extensions/compat_xtables.h +++ b/extensions/compat_xtables.h @@ -6,7 +6,7 @@ #include "compat_xtnu.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -# warning Kernels below 2.6.18 not supported. +# warning Kernels below 2.6.18.5 not supported. #endif #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) @@ -59,15 +59,13 @@ # define xt_unregister_matches xtnu_unregister_matches #endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) -# define xt_target xtnu_target -# define ip_route_me_harder xtnu_ip_route_me_harder -# define skb_make_writable xtnu_skb_make_writable -# define xt_register_target xtnu_register_target -# define xt_unregister_target xtnu_unregister_target -# define xt_register_targets xtnu_register_targets -# define xt_unregister_targets xtnu_unregister_targets -#endif +#define ip_route_me_harder xtnu_ip_route_me_harder +#define skb_make_writable xtnu_skb_make_writable +#define xt_target xtnu_target +#define xt_register_target xtnu_register_target +#define xt_unregister_target xtnu_unregister_target +#define xt_register_targets xtnu_register_targets +#define xt_unregister_targets xtnu_unregister_targets #define xt_request_find_match xtnu_request_find_match diff --git a/extensions/compat_xtnu.h b/extensions/compat_xtnu.h index 5fe8e2f..3c9334f 100644 --- a/extensions/compat_xtnu.h +++ b/extensions/compat_xtnu.h @@ -38,7 +38,7 @@ struct xtnu_match { struct xtnu_target { struct list_head list; char name[XT_FUNCTION_MAXNAMELEN - 1 - sizeof(void *)]; - unsigned int (*target)(struct sk_buff *, const struct net_device *, + unsigned int (*target)(struct sk_buff **, const struct net_device *, const struct net_device *, unsigned int, const struct xtnu_target *, const void *); bool (*checkentry)(const char *, const void *, @@ -68,8 +68,8 @@ static inline struct xtnu_target *xtcompat_nutarget(const struct xt_target *t) } extern int xtnu_ip_local_out(struct sk_buff *); -extern int xtnu_ip_route_me_harder(struct sk_buff *, unsigned int); -extern int xtnu_skb_make_writable(struct sk_buff *, unsigned int); +extern int xtnu_ip_route_me_harder(struct sk_buff **, unsigned int); +extern int xtnu_skb_make_writable(struct sk_buff **, unsigned int); extern int xtnu_register_match(struct xtnu_match *); extern int xtnu_ip_route_output_key(void *, struct rtable **, struct flowi *); extern void xtnu_unregister_match(struct xtnu_match *); diff --git a/extensions/xt_CHAOS.c b/extensions/xt_CHAOS.c index d4c2be2..72d2872 100644 --- a/extensions/xt_CHAOS.c +++ b/extensions/xt_CHAOS.c @@ -75,9 +75,9 @@ static void xt_chaos_total(const struct xt_chaos_tginfo *info, return; } -static unsigned int chaos_tg(struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, unsigned int hooknum, - const struct xt_target *target, const void *targinfo) +static unsigned int chaos_tg(struct sk_buff **pskb, + const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const struct xt_target *target, const void *targinfo) { /* * Equivalent to: @@ -88,18 +88,19 @@ static unsigned int chaos_tg(struct sk_buff *skb, const struct net_device *in, * -A chaos -j DROP; */ const struct xt_chaos_tginfo *info = targinfo; + struct sk_buff *skb = *pskb; const struct iphdr *iph = ip_hdr(skb); if ((unsigned int)net_random() <= reject_percentage) #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) - return xt_reject->target(&skb, in, out, hooknum, + return xt_reject->target(pskb, in, out, hooknum, target->__compat_target, &reject_params, NULL); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) - return xt_reject->target(&skb, in, out, hooknum, + return xt_reject->target(pskb, in, out, hooknum, target->__compat_target, &reject_params); #else - return xt_reject->target(skb, in, out, hooknum, target, - &reject_params); + return xt_reject->target(skb, in, out, hooknum, + target->__compat_target, &reject_params); #endif /* TARPIT/DELUDE may not be called from the OUTPUT chain */ diff --git a/extensions/xt_DELUDE.c b/extensions/xt_DELUDE.c index 4fd150d..2e2829c 100644 --- a/extensions/xt_DELUDE.c +++ b/extensions/xt_DELUDE.c @@ -122,8 +122,10 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook) dst_hold(oldskb->dst); nskb->dst = oldskb->dst; - if (ip_route_me_harder(nskb, addr_type)) + if (ip_route_me_harder(&nskb, addr_type)) goto free_nskb; + else + niph = ip_hdr(nskb); niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); nskb->ip_summed = CHECKSUM_NONE; @@ -141,14 +143,14 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook) kfree_skb(nskb); } -static unsigned int delude_tg(struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, unsigned int hooknum, - const struct xt_target *target, const void *targinfo) +static unsigned int delude_tg(struct sk_buff **pskb, + const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const struct xt_target *target, const void *targinfo) { /* WARNING: This code causes reentry within iptables. This means that the iptables jump stack is now crap. We must return an absolute verdict. --RR */ - delude_send_reset(skb, hooknum); + delude_send_reset(*pskb, hooknum); return NF_DROP; } diff --git a/extensions/xt_ECHO.c b/extensions/xt_ECHO.c index 32b017b..38d8e90 100644 --- a/extensions/xt_ECHO.c +++ b/extensions/xt_ECHO.c @@ -20,10 +20,11 @@ #include #include "compat_xtables.h" -static unsigned int echo_tg4(struct sk_buff *oldskb, +static unsigned int echo_tg4(struct sk_buff **poldskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { + const struct sk_buff *oldskb = *poldskb; const struct udphdr *oldudp; const struct iphdr *oldip; struct udphdr *newudp, oldudp_buf; diff --git a/extensions/xt_IPMARK.c b/extensions/xt_IPMARK.c index 7af0dc3..89756ef 100644 --- a/extensions/xt_IPMARK.c +++ b/extensions/xt_IPMARK.c @@ -25,11 +25,12 @@ MODULE_ALIAS("ipt_IPMARK"); MODULE_ALIAS("ip6t_IPMARK"); static unsigned int -ipmark_tg4(struct sk_buff *skb, const struct net_device *in, +ipmark_tg4(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { const struct xt_ipmark_tginfo *ipmarkinfo = targinfo; + const struct sk_buff *skb = *pskb; const struct iphdr *iph = ip_hdr(skb); __u32 mark; @@ -62,11 +63,12 @@ static __u32 ipmark_from_ip6(const struct in6_addr *a, unsigned int s) } static unsigned int -ipmark_tg6(struct sk_buff *skb, const struct net_device *in, +ipmark_tg6(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { const struct xt_ipmark_tginfo *info = targinfo; + const struct sk_buff *skb = *pskb; const struct ipv6hdr *iph = ipv6_hdr(skb); __u32 mark; diff --git a/extensions/xt_LOGMARK.c b/extensions/xt_LOGMARK.c index dca76ae..754d26b 100644 --- a/extensions/xt_LOGMARK.c +++ b/extensions/xt_LOGMARK.c @@ -30,10 +30,11 @@ static const char *const dir_names[] = { }; static unsigned int -logmark_tg(struct sk_buff *skb, const struct net_device *in, +logmark_tg(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { + const struct sk_buff *skb = *pskb; const struct xt_logmark_tginfo *info = targinfo; const struct nf_conn *ct; enum ip_conntrack_info ctinfo; diff --git a/extensions/xt_SYSRQ.c b/extensions/xt_SYSRQ.c index 86d2e34..976393b 100644 --- a/extensions/xt_SYSRQ.c +++ b/extensions/xt_SYSRQ.c @@ -58,10 +58,11 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len) return NF_ACCEPT; } -static unsigned int sysrq_tg4(struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, unsigned int hooknum, - const struct xt_target *target, const void *targinfo) +static unsigned int sysrq_tg4(struct sk_buff **pskb, + const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const struct xt_target *target, const void *targinfo) { + struct sk_buff *skb = *pskb; const struct iphdr *iph; const struct udphdr *udph; uint16_t len; @@ -79,10 +80,11 @@ static unsigned int sysrq_tg4(struct sk_buff *skb, const struct net_device *in, return sysrq_tg((void *)udph + sizeof(struct udphdr), len); } -static unsigned int sysrq_tg6(struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, unsigned int hooknum, - const struct xt_target *target, const void *targinfo) +static unsigned int sysrq_tg6(struct sk_buff **pskb, + const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const struct xt_target *target, const void *targinfo) { + struct sk_buff *skb = *pskb; const struct ipv6hdr *iph; const struct udphdr *udph; uint16_t len; diff --git a/extensions/xt_TARPIT.c b/extensions/xt_TARPIT.c index 4ede95e..90e6574 100644 --- a/extensions/xt_TARPIT.c +++ b/extensions/xt_TARPIT.c @@ -49,7 +49,7 @@ #include #include "compat_xtables.h" -static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook) +static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook) { struct tcphdr _otcph, *oth, *tcph; unsigned int addr_type; @@ -157,8 +157,10 @@ static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook) #endif addr_type = RTN_LOCAL; - if (ip_route_me_harder(nskb, addr_type)) + if (ip_route_me_harder(&nskb, addr_type)) goto free_nskb; + else + niph = ip_hdr(nskb); nskb->ip_summed = CHECKSUM_NONE; @@ -184,10 +186,11 @@ static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook) } static unsigned int -tarpit_tg(struct sk_buff *skb, const struct net_device *in, +tarpit_tg(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { + const struct sk_buff *skb = *pskb; const struct iphdr *iph = ip_hdr(skb); const struct rtable *rt = (const void *)skb->dst; @@ -215,7 +218,7 @@ tarpit_tg(struct sk_buff *skb, const struct net_device *in, if (iph->frag_off & htons(IP_OFFSET)) return NF_DROP; - tarpit_tcp(skb, hooknum); + tarpit_tcp(*pskb, hooknum); return NF_DROP; } diff --git a/extensions/xt_TEE.c b/extensions/xt_TEE.c index b160df2..f07ef8b 100644 --- a/extensions/xt_TEE.c +++ b/extensions/xt_TEE.c @@ -142,11 +142,12 @@ static void tee_ip_direct_send(struct sk_buff *skb) * packets when we see they already have that ->nfct. */ static unsigned int -tee_tg(struct sk_buff *skb, const struct net_device *in, +tee_tg(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { const struct xt_tee_tginfo *info = targinfo; + struct sk_buff *skb = *pskb; #ifdef WITH_CONNTRACK if (skb->nfct == &tee_track.ct_general) { @@ -160,8 +161,9 @@ tee_tg(struct sk_buff *skb, const struct net_device *in, } #endif - if (!skb_make_writable(skb, sizeof(struct iphdr))) + if (!skb_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; + skb = *pskb; /* * If we are in INPUT, the checksum must be recalculated since -- 2.47.3