1 Index: linux-2.6.27.y/include/linux/sysctl.h
2 ===================================================================
3 --- linux-2.6.27.y.orig/include/linux/sysctl.h
4 +++ linux-2.6.27.y/include/linux/sysctl.h
5 @@ -437,6 +437,13 @@ enum
6 NET_TCP_ALLOWED_CONG_CONTROL=123,
7 NET_TCP_MAX_SSTHRESH=124,
8 NET_TCP_FRTO_RESPONSE=125,
9 +#ifdef CONFIG_ICMP_IPOD
10 + NET_IPV4_ICMP_IPOD_VERSION,
11 + NET_IPV4_ICMP_IPOD_ENABLED,
12 + NET_IPV4_ICMP_IPOD_HOST,
13 + NET_IPV4_ICMP_IPOD_MASK,
14 + NET_IPV4_ICMP_IPOD_KEY
19 Index: linux-2.6.27.y/include/net/icmp.h
20 ===================================================================
21 --- linux-2.6.27.y.orig/include/net/icmp.h
22 +++ linux-2.6.27.y/include/net/icmp.h
23 @@ -59,4 +59,12 @@ static inline struct raw_sock *raw_sk(co
24 return (struct raw_sock *)sk;
27 +#ifdef CONFIG_ICMP_IPOD
28 +extern int sysctl_icmp_ipod_version;
29 +extern int sysctl_icmp_ipod_enabled;
30 +extern u32 sysctl_icmp_ipod_host;
31 +extern u32 sysctl_icmp_ipod_mask;
32 +extern char sysctl_icmp_ipod_key[32+1];
36 Index: linux-2.6.27.y/net/ipv4/icmp.c
37 ===================================================================
38 --- linux-2.6.27.y.orig/net/ipv4/icmp.c
39 +++ linux-2.6.27.y/net/ipv4/icmp.c
40 @@ -962,6 +962,67 @@ static void icmp_address_reply(struct sk
44 +#ifdef CONFIG_ICMP_IPOD
45 +#include <linux/reboot.h>
47 +int sysctl_icmp_ipod_version = 2;
48 +int sysctl_icmp_ipod_enabled = 0;
49 +u32 sysctl_icmp_ipod_host = 0xffffffff;
50 +u32 sysctl_icmp_ipod_mask = 0xffffffff;
51 +char sysctl_icmp_ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
52 +#define IPOD_CHECK_KEY \
53 + (sysctl_icmp_ipod_key[0] != 0)
54 +#define IPOD_VALID_KEY(d) \
55 + (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
57 +static void icmp_ping_of_death(struct sk_buff *skb)
59 + struct icmphdr *icmph = (struct icmphdr *)skb_transport_header(skb);
60 + struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
64 + printk(KERN_INFO "IPOD: got type=6, code=%d, host=%u.%u.%u.%u\n", icmph->code, ntohs(iph->tot_len), NIPQUAD(iph->saddr));
68 + * If IPOD not enabled or wrong ICMP code, ignore.
70 + if (!sysctl_icmp_ipod_enabled || icmph->code != 6)
74 + * First check the source address info.
75 + * If host not set, ignore.
77 + if (sysctl_icmp_ipod_host != 0xffffffff &&
78 + (ntohl(iph->saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_ipod_host) {
80 + * Now check the key if enabled.
81 + * If packet doesn't contain enough data or key
82 + * is otherwise invalid, ignore.
84 + if (IPOD_CHECK_KEY) {
85 + if (pskb_may_pull(skb, sizeof(sysctl_icmp_ipod_key)-1) &&
86 + IPOD_VALID_KEY(skb->data))
94 + sysctl_icmp_ipod_enabled = 0;
95 + printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
96 + NIPQUAD(iph->saddr));
97 + machine_restart(NULL);
99 + printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
100 + NIPQUAD(iph->saddr));
105 static void icmp_discard(struct sk_buff *skb)
108 @@ -1084,10 +1145,17 @@ static const struct icmp_control icmp_po
109 .handler = icmp_redirect,
112 +#ifdef CONFIG_ICMP_IPOD
114 + .handler = icmp_ping_of_death,
119 .handler = icmp_discard,
124 .handler = icmp_discard,
126 Index: linux-2.6.27.y/net/ipv4/Kconfig
127 ===================================================================
128 --- linux-2.6.27.y.orig/net/ipv4/Kconfig
129 +++ linux-2.6.27.y/net/ipv4/Kconfig
130 @@ -632,3 +632,14 @@ config TCP_MD5SIG
132 source "net/ipv4/ipvs/Kconfig"
139 + bool "ICMP: ICMP Ping-of-Death (Emulab)"
140 + depends on INET && SYSCTL
142 + Support immediately rebooting upon receiving a specially
143 + formed ICMP type 6 packet whose payload matches a string
144 + configured by the administrator.
145 Index: linux-2.6.27.y/net/ipv4/sysctl_net_ipv4.c
146 ===================================================================
147 --- linux-2.6.27.y.orig/net/ipv4/sysctl_net_ipv4.c
148 +++ linux-2.6.27.y/net/ipv4/sysctl_net_ipv4.c
149 @@ -773,6 +773,49 @@ static struct ctl_table ipv4_net_table[]
151 .proc_handler = &proc_dointvec
153 +#ifdef CONFIG_ICMP_IPOD
155 + .ctl_name = NET_IPV4_ICMP_IPOD_VERSION,
156 + .procname = "icmp_ipod_version",
157 + .data = &sysctl_icmp_ipod_version,
158 + .maxlen = sizeof(sysctl_icmp_ipod_version),
160 + .proc_handler = &proc_dointvec
163 + .ctl_name = NET_IPV4_ICMP_IPOD_ENABLED,
164 + .procname = "icmp_ipod_enabled",
165 + .data = &sysctl_icmp_ipod_enabled,
166 + .maxlen = sizeof(sysctl_icmp_ipod_enabled),
168 + .proc_handler = &proc_dointvec
171 + .ctl_name = NET_IPV4_ICMP_IPOD_HOST,
172 + .procname = "icmp_ipod_host",
173 + .data = &sysctl_icmp_ipod_host,
174 + .maxlen = sizeof(sysctl_icmp_ipod_host),
176 + .proc_handler = &proc_dointvec
179 + .ctl_name = NET_IPV4_ICMP_IPOD_MASK,
180 + .procname = "icmp_ipod_mask",
181 + .data = &sysctl_icmp_ipod_mask,
182 + .maxlen = sizeof(sysctl_icmp_ipod_mask),
184 + .proc_handler = &proc_dointvec
187 + .ctl_name = NET_IPV4_ICMP_IPOD_KEY,
188 + .procname = "icmp_ipod_key",
189 + .data = &sysctl_icmp_ipod_key,
190 + .maxlen = sizeof(sysctl_icmp_ipod_key),
192 + .proc_handler = &proc_dostring,
193 + .strategy = &sysctl_string
197 .ctl_name = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
198 .procname = "icmp_errors_use_inbound_ifaddr",
199 Index: linux-2.6.27.y/net/ipv4/udp.c
200 ===================================================================
201 --- linux-2.6.27.y.orig/net/ipv4/udp.c
202 +++ linux-2.6.27.y/net/ipv4/udp.c
203 @@ -1173,6 +1173,75 @@ static inline int udp4_csum_init(struct
207 +/* XXX (mef) need to generalize the IPOD stuff. Right now I am borrowing
208 + from the ICMP infrastructure. */
209 +#ifdef CONFIG_ICMP_IPOD
210 +#include <linux/reboot.h>
212 +extern int sysctl_icmp_ipod_version;
213 +extern int sysctl_icmp_ipod_enabled;
214 +extern u32 sysctl_icmp_ipod_host;
215 +extern u32 sysctl_icmp_ipod_mask;
216 +extern char sysctl_icmp_ipod_key[32+1];
217 +#define IPOD_CHECK_KEY \
218 + (sysctl_icmp_ipod_key[0] != 0)
219 +#define IPOD_VALID_KEY(d) \
220 + (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
222 +static void udp_ping_of_death(struct sk_buff *skb, struct udphdr *uh, u32 saddr)
227 + * If IPOD not enabled or wrong UDP IPOD port, ignore.
229 + if (!sysctl_icmp_ipod_enabled || (ntohs(uh->dest) != 664))
233 + printk(KERN_INFO "IPOD: got udp pod request, host=%u.%u.%u.%u\n", NIPQUAD(saddr));
238 + * First check the source address info.
239 + * If host not set, ignore.
241 + if (sysctl_icmp_ipod_host != 0xffffffff &&
242 + (ntohl(saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_ipod_host) {
244 + * Now check the key if enabled.
245 + * If packet doesn't contain enough data or key
246 + * is otherwise invalid, ignore.
248 + if (IPOD_CHECK_KEY) {
249 + if (pskb_may_pull(skb, sizeof(sysctl_icmp_ipod_key)+sizeof(struct udphdr)-1)){
252 + for (i=0;i<32+1;i++){
253 + printk("%c",((char*)skb->data)[i+sizeof(struct udphdr)]);
257 + if (IPOD_VALID_KEY(skb->data+sizeof(struct udphdr)))
265 + sysctl_icmp_ipod_enabled = 0;
266 + printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
268 + machine_restart(NULL);
270 + printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
277 * All we need to do is get the socket, and then do a checksum.
279 @@ -1213,6 +1282,9 @@ int __udp4_lib_rcv(struct sk_buff *skb,
280 return __udp4_lib_mcast_deliver(net, skb, uh,
281 saddr, daddr, udptable);
283 +#ifdef CONFIG_ICMP_IPOD
284 + udp_ping_of_death(skb, uh, saddr);
286 sk = __udp4_lib_lookup(net, saddr, uh->source, daddr,
287 uh->dest, inet_iif(skb), udptable);