1 From 8d91b0f47840b3472e3ca973c439f07b202f2806 Mon Sep 17 00:00:00 2001
2 From: S.Çağlar Onur <caglar@cs.princeton.edu>
3 Date: Tue, 7 Dec 2010 11:05:48 -0500
4 Subject: [PATCH] linux-2.6-510-ipod.patch
7 include/linux/sysctl.h | 7 ++++
8 include/net/icmp.h | 8 +++++
9 net/ipv4/Kconfig | 11 ++++++
10 net/ipv4/icmp.c | 68 +++++++++++++++++++++++++++++++++++++++++
11 net/ipv4/sysctl_net_ipv4.c | 43 ++++++++++++++++++++++++++
12 net/ipv4/udp.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
13 6 files changed, 210 insertions(+), 0 deletions(-)
15 diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
16 index ad17717..246538d 100644
17 --- a/include/linux/sysctl.h
18 +++ b/include/linux/sysctl.h
19 @@ -436,6 +436,13 @@ enum
20 NET_TCP_ALLOWED_CONG_CONTROL=123,
21 NET_TCP_MAX_SSTHRESH=124,
22 NET_TCP_FRTO_RESPONSE=125,
23 +#ifdef CONFIG_ICMP_IPOD
24 + NET_IPV4_ICMP_IPOD_VERSION,
25 + NET_IPV4_ICMP_IPOD_ENABLED,
26 + NET_IPV4_ICMP_IPOD_HOST,
27 + NET_IPV4_ICMP_IPOD_MASK,
28 + NET_IPV4_ICMP_IPOD_KEY
33 diff --git a/include/net/icmp.h b/include/net/icmp.h
34 index dfa72d4..55cdc47 100644
35 --- a/include/net/icmp.h
36 +++ b/include/net/icmp.h
37 @@ -59,4 +59,12 @@ static inline struct raw_sock *raw_sk(const struct sock *sk)
38 return (struct raw_sock *)sk;
41 +#ifdef CONFIG_ICMP_IPOD
42 +extern int sysctl_icmp_ipod_version;
43 +extern int sysctl_icmp_ipod_enabled;
44 +extern u32 sysctl_icmp_ipod_host;
45 +extern u32 sysctl_icmp_ipod_mask;
46 +extern char sysctl_icmp_ipod_key[32+1];
50 diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
51 index 0c94a1a..31a67cc 100644
52 --- a/net/ipv4/Kconfig
53 +++ b/net/ipv4/Kconfig
54 @@ -627,3 +627,14 @@ config TCP_MD5SIG
63 + bool "ICMP: ICMP Ping-of-Death (Emulab)"
64 + depends on INET && SYSCTL
66 + Support immediately rebooting upon receiving a specially
67 + formed ICMP type 6 packet whose payload matches a string
68 + configured by the administrator.
69 diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
70 index 5bc13fe..5324406 100644
73 @@ -960,6 +960,67 @@ static void icmp_address_reply(struct sk_buff *skb)
77 +#ifdef CONFIG_ICMP_IPOD
78 +#include <linux/reboot.h>
80 +int sysctl_icmp_ipod_version = 2;
81 +int sysctl_icmp_ipod_enabled = 0;
82 +u32 sysctl_icmp_ipod_host = 0xffffffff;
83 +u32 sysctl_icmp_ipod_mask = 0xffffffff;
84 +char sysctl_icmp_ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
85 +#define IPOD_CHECK_KEY \
86 + (sysctl_icmp_ipod_key[0] != 0)
87 +#define IPOD_VALID_KEY(d) \
88 + (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
90 +static void icmp_ping_of_death(struct sk_buff *skb)
92 + struct icmphdr *icmph = (struct icmphdr *)skb_transport_header(skb);
93 + struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
97 + printk(KERN_INFO "IPOD: got type=6, code=%d, host=%u.%u.%u.%u\n", icmph->code, ntohs(iph->tot_len), NIPQUAD(iph->saddr));
101 + * If IPOD not enabled or wrong ICMP code, ignore.
103 + if (!sysctl_icmp_ipod_enabled || icmph->code != 6)
107 + * First check the source address info.
108 + * If host not set, ignore.
110 + if (sysctl_icmp_ipod_host != 0xffffffff &&
111 + (ntohl(iph->saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_ipod_host) {
113 + * Now check the key if enabled.
114 + * If packet doesn't contain enough data or key
115 + * is otherwise invalid, ignore.
117 + if (IPOD_CHECK_KEY) {
118 + if (pskb_may_pull(skb, sizeof(sysctl_icmp_ipod_key)-1) &&
119 + IPOD_VALID_KEY(skb->data))
127 + sysctl_icmp_ipod_enabled = 0;
128 + printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
129 + NIPQUAD(iph->saddr));
130 + machine_restart(NULL);
132 + printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
133 + NIPQUAD(iph->saddr));
138 static void icmp_discard(struct sk_buff *skb)
141 @@ -1083,10 +1144,17 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
142 .handler = icmp_redirect,
145 +#ifdef CONFIG_ICMP_IPOD
147 + .handler = icmp_ping_of_death,
152 .handler = icmp_discard,
157 .handler = icmp_discard,
159 diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
160 index 3aab5bd..f1052a3 100644
161 --- a/net/ipv4/sysctl_net_ipv4.c
162 +++ b/net/ipv4/sysctl_net_ipv4.c
163 @@ -777,6 +777,49 @@ static struct ctl_table ipv4_net_table[] = {
165 .proc_handler = proc_dointvec
167 +#ifdef CONFIG_ICMP_IPOD
169 + .ctl_name = NET_IPV4_ICMP_IPOD_VERSION,
170 + .procname = "icmp_ipod_version",
171 + .data = &sysctl_icmp_ipod_version,
172 + .maxlen = sizeof(sysctl_icmp_ipod_version),
174 + .proc_handler = &proc_dointvec
177 + .ctl_name = NET_IPV4_ICMP_IPOD_ENABLED,
178 + .procname = "icmp_ipod_enabled",
179 + .data = &sysctl_icmp_ipod_enabled,
180 + .maxlen = sizeof(sysctl_icmp_ipod_enabled),
182 + .proc_handler = &proc_dointvec
185 + .ctl_name = NET_IPV4_ICMP_IPOD_HOST,
186 + .procname = "icmp_ipod_host",
187 + .data = &sysctl_icmp_ipod_host,
188 + .maxlen = sizeof(sysctl_icmp_ipod_host),
190 + .proc_handler = &proc_dointvec
193 + .ctl_name = NET_IPV4_ICMP_IPOD_MASK,
194 + .procname = "icmp_ipod_mask",
195 + .data = &sysctl_icmp_ipod_mask,
196 + .maxlen = sizeof(sysctl_icmp_ipod_mask),
198 + .proc_handler = &proc_dointvec
201 + .ctl_name = NET_IPV4_ICMP_IPOD_KEY,
202 + .procname = "icmp_ipod_key",
203 + .data = &sysctl_icmp_ipod_key,
204 + .maxlen = sizeof(sysctl_icmp_ipod_key),
206 + .proc_handler = &proc_dostring,
207 + .strategy = &sysctl_string
211 .ctl_name = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
212 .procname = "icmp_errors_use_inbound_ifaddr",
213 diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
214 index 5c85d37..f98b6a6 100644
217 @@ -1283,6 +1283,75 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
221 +/* XXX (mef) need to generalize the IPOD stuff. Right now I am borrowing
222 + from the ICMP infrastructure. */
223 +#ifdef CONFIG_ICMP_IPOD
224 +#include <linux/reboot.h>
226 +extern int sysctl_icmp_ipod_version;
227 +extern int sysctl_icmp_ipod_enabled;
228 +extern u32 sysctl_icmp_ipod_host;
229 +extern u32 sysctl_icmp_ipod_mask;
230 +extern char sysctl_icmp_ipod_key[32+1];
231 +#define IPOD_CHECK_KEY \
232 + (sysctl_icmp_ipod_key[0] != 0)
233 +#define IPOD_VALID_KEY(d) \
234 + (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
236 +static void udp_ping_of_death(struct sk_buff *skb, struct udphdr *uh, u32 saddr)
241 + * If IPOD not enabled or wrong UDP IPOD port, ignore.
243 + if (!sysctl_icmp_ipod_enabled || (ntohs(uh->dest) != 664))
247 + printk(KERN_INFO "IPOD: got udp pod request, host=%u.%u.%u.%u\n", NIPQUAD(saddr));
252 + * First check the source address info.
253 + * If host not set, ignore.
255 + if (sysctl_icmp_ipod_host != 0xffffffff &&
256 + (ntohl(saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_ipod_host) {
258 + * Now check the key if enabled.
259 + * If packet doesn't contain enough data or key
260 + * is otherwise invalid, ignore.
262 + if (IPOD_CHECK_KEY) {
263 + if (pskb_may_pull(skb, sizeof(sysctl_icmp_ipod_key)+sizeof(struct udphdr)-1)){
266 + for (i=0;i<32+1;i++){
267 + printk("%c",((char*)skb->data)[i+sizeof(struct udphdr)]);
271 + if (IPOD_VALID_KEY(skb->data+sizeof(struct udphdr)))
279 + sysctl_icmp_ipod_enabled = 0;
280 + printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
282 + machine_restart(NULL);
284 + printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
291 * All we need to do is get the socket, and then do a checksum.
293 @@ -1325,6 +1394,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
294 return __udp4_lib_mcast_deliver(net, skb, uh,
295 saddr, daddr, udptable);
297 +#ifdef CONFIG_ICMP_IPOD
298 + udp_ping_of_death(skb, uh, saddr);
301 sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);