Commit f214a3ec authored by David Johnson's avatar David Johnson

Update the Linux ipod module to compat with at least kernel 4.4.x .

There were changes to the netfilter hook API in 4.1 and 4.4 to account
for, but those were simple.  No hook params we rely on changed.

There was a minor change to the proc handler table conventions back in
2.6.33, but that wasn't a deal-breaker.  Anyway, "fixed".

Much more bizarre was an apparent proc_dointvec change.  Since some
kernel between Ubuntu 3.13 and Ubuntu 4.2, proc_dointvec's behavior
changed (well, *something* changed!).  Some of our ipod sysctls
("icmp_ipod_host" and "icmp_ipod_mask") are uint32ts, but we have been
using proc_dointvec to parse the values sent in from sysctl, probably
forever.  So of course we regularly have to send in large negative
values (i.e. 155.98.32.70, aka 0x9b622046, aka -1688068026).  At 3.13,
proc_dointvec was happy to parse the hex version of that.  At 4.2, it is
not happy to parse the hex, but it will parse decimal.  Well, we don't
supply decimal in rc.ipod, just hex, and I don't want to fix it there.
So I switched those two sysctl's proc handlers to proc_dointvec_minmax,
specify INT_MIN and INT_MAX as my min/max values, and that works like a
charm.  Very odd that this would change.  Of course these should just
use an unsigned proc handler, like proc_doulongvec, but I don't want to
break the fact that you used to be able to send in negative decimal
integers and have things work (an oft-used feature, no doubt, in some
parallel universe!).

This is tested and working back to UBUNTU12-64-STD.  It should be fine
going further back, as far back as 2.4.x, but I can't easily test there.
parent 79085c5f
/*
* Copyright (c) 2000-2015 University of Utah and the Flux Group.
* Copyright (c) 2000-2016 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
......@@ -37,6 +37,7 @@
#include <net/ip.h>
#include <net/net_namespace.h>
#include <linux/version.h>
#include <linux/limits.h>
#define IPOD_ICMP_TYPE 6
#define IPOD_ICMP_CODE 6
......@@ -52,6 +53,15 @@ char sysctl_ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
#define IPOD_VALID_KEY(d) \
(strncmp(sysctl_ipod_key,(char *)(d),sizeof(sysctl_ipod_key) - 1) == 0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
#define __PHP &
#else
#define __PHP
#endif
static u32 __ipod_min = INT_MIN;
static u32 __ipod_max = INT_MAX;
/*
* Register the simple icmp table in /proc/sys/net/ipv4 . This way, if
* somebody else ever adds a net.ipv4.icmp table, like net.ipv6.icmp, we
......@@ -64,31 +74,35 @@ static struct ctl_table ipod_table[] = {
.data = &sysctl_ipod_version,
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = &proc_dointvec,
.proc_handler = __PHP proc_dointvec,
},
{ .procname = "icmp_ipod_enabled",
.data = &sysctl_ipod_enabled,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
.proc_handler = __PHP proc_dointvec,
},
{ .procname = "icmp_ipod_host",
.data = &sysctl_ipod_host,
.maxlen = sizeof(u32),
.mode = 0644,
.proc_handler = &proc_dointvec,
.proc_handler = __PHP proc_dointvec_minmax,
.extra1 = &__ipod_min,
.extra2 = &__ipod_max,
},
{ .procname = "icmp_ipod_mask",
.data = &sysctl_ipod_mask,
.maxlen = sizeof(u32),
.mode = 0644,
.proc_handler = &proc_dointvec,
.proc_handler = __PHP proc_dointvec_minmax,
.extra1 = &__ipod_min,
.extra2 = &__ipod_max,
},
{ .procname = "icmp_ipod_key",
.data = &sysctl_ipod_key,
.maxlen = sizeof(sysctl_ipod_key),
.mode = 0600,
.proc_handler = &proc_dostring,
.proc_handler = __PHP proc_dostring,
},
{ 0 },
};
......@@ -113,32 +127,52 @@ static struct ctl_path ipod_path[] = {
static struct ctl_table_header *ipod_table_header;
static unsigned int ipod_hook_fn(
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
static unsigned int ipod_hook_fn(unsigned int hooknum,
unsigned int hooknum,
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
const struct nf_hook_ops *ops,
#else
static unsigned int ipod_hook_fn(const struct nf_hook_ops *ops,
void *priv,
#endif
struct sk_buff *skb,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *));
int (*okfn)(struct sk_buff *)
#else
const struct nf_hook_state *state
#endif
);
static struct nf_hook_ops ipod_hook_ops = {
.hook = ipod_hook_fn,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
.owner = THIS_MODULE,
#endif
.hooknum = NF_INET_LOCAL_IN,
.pf = PF_INET,
.priority = NF_IP_PRI_FIRST,
};
static unsigned int ipod_hook_fn(
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
static unsigned int ipod_hook_fn(unsigned int hooknum,
unsigned int hooknum,
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
const struct nf_hook_ops *ops,
#else
static unsigned int ipod_hook_fn(const struct nf_hook_ops *ops,
void *priv,
#endif
struct sk_buff *skb,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *)) {
int (*okfn)(struct sk_buff *)
#else
const struct nf_hook_state *state
#endif
) {
struct iphdr *iph;
struct icmphdr *icmph;
int doit = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment