Setting tag linux-2.6-22-50
[linux-2.6.git] / linux-2.6-510-ipod.patch
1 diff -Nurp linux-2.6.22.10-vs2.3.0.29-pl01/include/linux/sysctl.h linux-2.6.22.10-vs2.3.0.29-pl02/include/linux/sysctl.h
2 --- linux-2.6.22.10-vs2.3.0.29-pl01/include/linux/sysctl.h      2007-10-29 21:23:59.000000000 -0400
3 +++ linux-2.6.22.10-vs2.3.0.29-pl02/include/linux/sysctl.h      2007-11-14 13:58:15.000000000 -0500
4 @@ -442,6 +442,13 @@ enum
5         NET_TCP_ALLOWED_CONG_CONTROL=123,
6         NET_TCP_MAX_SSTHRESH=124,
7         NET_TCP_FRTO_RESPONSE=125,
8 +#ifdef CONFIG_ICMP_IPOD
9 +       NET_IPV4_ICMP_IPOD_VERSION,
10 +       NET_IPV4_ICMP_IPOD_ENABLED,
11 +       NET_IPV4_ICMP_IPOD_HOST,
12 +       NET_IPV4_ICMP_IPOD_MASK,
13 +       NET_IPV4_ICMP_IPOD_KEY
14 +#endif
15  };
16  
17  enum {
18 diff -Nurp linux-2.6.22.10-vs2.3.0.29-pl01/include/net/icmp.h linux-2.6.22.10-vs2.3.0.29-pl02/include/net/icmp.h
19 --- linux-2.6.22.10-vs2.3.0.29-pl01/include/net/icmp.h  2007-05-04 09:57:44.000000000 -0400
20 +++ linux-2.6.22.10-vs2.3.0.29-pl02/include/net/icmp.h  2007-11-14 13:57:27.000000000 -0500
21 @@ -64,4 +64,12 @@ extern int sysctl_icmp_errors_use_inboun
22  extern int sysctl_icmp_ratelimit;
23  extern int sysctl_icmp_ratemask;
24  
25 +#ifdef CONFIG_ICMP_IPOD
26 +extern int sysctl_icmp_ipod_version;
27 +extern int sysctl_icmp_ipod_enabled;
28 +extern u32 sysctl_icmp_ipod_host;
29 +extern u32 sysctl_icmp_ipod_mask;
30 +extern char sysctl_icmp_ipod_key[32+1];
31 +#endif
32 +
33  #endif /* _ICMP_H */
34 diff -Nurp linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/icmp.c linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/icmp.c
35 --- linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/icmp.c     2007-07-21 18:00:25.000000000 -0400
36 +++ linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/icmp.c     2007-11-14 14:00:56.000000000 -0500
37 @@ -922,6 +922,67 @@ static void icmp_address_reply(struct sk
38  out:;
39  }
40  
41 +#ifdef CONFIG_ICMP_IPOD
42 +#include <linux/reboot.h>
43 +
44 +int sysctl_icmp_ipod_version = 2;
45 +int sysctl_icmp_ipod_enabled = 0;
46 +u32 sysctl_icmp_ipod_host = 0xffffffff;
47 +u32 sysctl_icmp_ipod_mask = 0xffffffff;
48 +char sysctl_icmp_ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
49 +#define IPOD_CHECK_KEY \
50 +       (sysctl_icmp_ipod_key[0] != 0)
51 +#define IPOD_VALID_KEY(d) \
52 +       (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
53 +
54 +static void icmp_ping_of_death(struct sk_buff *skb)
55 +{
56 +       struct icmphdr *icmph = skb_transport_header(skb);
57 +       struct iphdr *iph = skb_network_header(skb);
58 +       int doit = 0;
59 +
60 +#if 0
61 +       printk(KERN_INFO "IPOD: got type=6, code=%d, host=%u.%u.%u.%u\n", icmph->code, ntohs(iph->tot_len), NIPQUAD(iph->saddr));
62 +#endif
63 +
64 +       /*
65 +        * If IPOD not enabled or wrong ICMP code, ignore.
66 +        */
67 +       if (!sysctl_icmp_ipod_enabled || icmph->code != 6)
68 +               return;
69 +
70 +       /*
71 +        * First check the source address info.
72 +        * If host not set, ignore.
73 +        */
74 +       if (sysctl_icmp_ipod_host != 0xffffffff &&
75 +           (ntohl(iph->saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_ipod_host) {
76 +               /*
77 +                * Now check the key if enabled.
78 +                * If packet doesn't contain enough data or key
79 +                * is otherwise invalid, ignore.
80 +                */
81 +               if (IPOD_CHECK_KEY) {
82 +                       if (pskb_may_pull(skb, sizeof(sysctl_icmp_ipod_key)-1) &&
83 +                           IPOD_VALID_KEY(skb->data))
84 +                               doit = 1;
85 +               } else {
86 +                       doit = 1;
87 +               }
88 +       }
89 +
90 +       if (doit) {
91 +               sysctl_icmp_ipod_enabled = 0;
92 +               printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
93 +                      NIPQUAD(iph->saddr));
94 +               machine_restart(NULL);
95 +       } else {
96 +               printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
97 +                      NIPQUAD(iph->saddr));
98 +       }
99 +}
100 +#endif
101 +
102  static void icmp_discard(struct sk_buff *skb)
103  {
104  }
105 @@ -1036,12 +1097,21 @@ static const struct icmp_control icmp_po
106                 .handler = icmp_redirect,
107                 .error = 1,
108         },
109 +#ifdef CONFIG_ICMP_IPOD
110 +       [6] = {
111 +               .output_entry = ICMP_MIB_DUMMY,
112 +               .input_entry = ICMP_MIB_DUMMY,
113 +               .handler = icmp_ping_of_death,
114 +               .error = 1,
115 +       },
116 +#else
117         [6] = {
118                 .output_entry = ICMP_MIB_DUMMY,
119                 .input_entry = ICMP_MIB_INERRORS,
120                 .handler = icmp_discard,
121                 .error = 1,
122         },
123 +#endif
124         [7] = {
125                 .output_entry = ICMP_MIB_DUMMY,
126                 .input_entry = ICMP_MIB_INERRORS,
127 diff -Nurp linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/Kconfig linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/Kconfig
128 --- linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/Kconfig    2007-07-21 18:00:25.000000000 -0400
129 +++ linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/Kconfig    2007-11-14 14:00:36.000000000 -0500
130 @@ -660,3 +660,14 @@ config TCP_MD5SIG
131  
132  source "net/ipv4/ipvs/Kconfig"
133  
134 +#
135 +# Emulab special
136 +#
137 +
138 +config ICMP_IPOD
139 +       bool "ICMP: ICMP Ping-of-Death (Emulab)"
140 +       depends on INET && SYSCTL
141 +       ---help---
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 diff -Nurp linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/sysctl_net_ipv4.c linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/sysctl_net_ipv4.c
146 --- linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/sysctl_net_ipv4.c  2007-07-21 18:00:27.000000000 -0400
147 +++ linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/sysctl_net_ipv4.c  2007-11-14 14:00:36.000000000 -0500
148 @@ -456,6 +456,49 @@ ctl_table ipv4_table[] = {
149                 .mode           = 0644,
150                 .proc_handler   = &proc_dointvec
151         },
152 +#ifdef CONFIG_ICMP_IPOD
153 +       {
154 +               .ctl_name       = NET_IPV4_ICMP_IPOD_VERSION,
155 +               .procname       = "icmp_ipod_version",
156 +               .data           = &sysctl_icmp_ipod_version,
157 +               .maxlen         = sizeof(sysctl_icmp_ipod_version),
158 +               .mode           = 0444,
159 +               .proc_handler   = &proc_dointvec
160 +       },
161 +       {
162 +               .ctl_name       = NET_IPV4_ICMP_IPOD_ENABLED,
163 +               .procname       = "icmp_ipod_enabled",
164 +               .data           = &sysctl_icmp_ipod_enabled,
165 +               .maxlen         = sizeof(sysctl_icmp_ipod_enabled),
166 +               .mode           = 0644,
167 +               .proc_handler   = &proc_dointvec
168 +       },
169 +       {
170 +               .ctl_name       = NET_IPV4_ICMP_IPOD_HOST,
171 +               .procname       = "icmp_ipod_host",
172 +               .data           = &sysctl_icmp_ipod_host,
173 +               .maxlen         = sizeof(sysctl_icmp_ipod_host),
174 +               .mode           = 0644,
175 +               .proc_handler   = &proc_dointvec
176 +       },
177 +       {
178 +               .ctl_name       = NET_IPV4_ICMP_IPOD_MASK,
179 +               .procname       = "icmp_ipod_mask",
180 +               .data           = &sysctl_icmp_ipod_mask,
181 +               .maxlen         = sizeof(sysctl_icmp_ipod_mask),
182 +               .mode           = 0644,
183 +               .proc_handler   = &proc_dointvec
184 +       },
185 +       {
186 +               .ctl_name       = NET_IPV4_ICMP_IPOD_KEY,
187 +               .procname       = "icmp_ipod_key",
188 +               .data           = &sysctl_icmp_ipod_key,
189 +               .maxlen         = sizeof(sysctl_icmp_ipod_key),
190 +               .mode           = 0600,
191 +               .proc_handler   = &proc_dostring,
192 +               .strategy       = &sysctl_string
193 +       },
194 +#endif
195         {
196                 .ctl_name       = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
197                 .procname       = "icmp_errors_use_inbound_ifaddr",
198 diff -Nurp linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/udp.c linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/udp.c
199 --- linux-2.6.22.10-vs2.3.0.29-pl01/net/ipv4/udp.c      2007-10-29 21:23:59.000000000 -0400
200 +++ linux-2.6.22.10-vs2.3.0.29-pl02/net/ipv4/udp.c      2007-11-14 14:00:36.000000000 -0500
201 @@ -1212,6 +1212,75 @@ static inline int udp4_csum_init(struct 
202         return 0;
203  }
204  
205 +/* XXX (mef) need to generalize the IPOD stuff.  Right now I am borrowing 
206 +   from the ICMP infrastructure. */
207 +#ifdef CONFIG_ICMP_IPOD
208 +#include <linux/reboot.h>
209 +
210 +extern int sysctl_icmp_ipod_version;
211 +extern int sysctl_icmp_ipod_enabled;
212 +extern u32 sysctl_icmp_ipod_host;
213 +extern u32 sysctl_icmp_ipod_mask;
214 +extern char sysctl_icmp_ipod_key[32+1];
215 +#define IPOD_CHECK_KEY \
216 +       (sysctl_icmp_ipod_key[0] != 0)
217 +#define IPOD_VALID_KEY(d) \
218 +       (strncmp(sysctl_icmp_ipod_key, (char *)(d), strlen(sysctl_icmp_ipod_key)) == 0)
219 +
220 +static void udp_ping_of_death(struct sk_buff *skb, struct udphdr *uh, u32 saddr)
221 +{
222 +       int doit = 0;
223 +
224 +       /*
225 +        * If IPOD not enabled or wrong UDP IPOD port, ignore.
226 +        */
227 +       if (!sysctl_icmp_ipod_enabled || (ntohs(uh->dest) != 664))
228 +               return;
229 +
230 +#if 0
231 +       printk(KERN_INFO "IPOD: got udp pod request, host=%u.%u.%u.%u\n", NIPQUAD(saddr));
232 +#endif
233 +
234 +
235 +       /*
236 +        * First check the source address info.
237 +        * If host not set, ignore.
238 +        */
239 +       if (sysctl_icmp_ipod_host != 0xffffffff &&
240 +           (ntohl(saddr) & sysctl_icmp_ipod_mask) == sysctl_icmp_ipod_host) {
241 +               /*
242 +                * Now check the key if enabled.
243 +                * If packet doesn't contain enough data or key
244 +                * is otherwise invalid, ignore.
245 +                */
246 +               if (IPOD_CHECK_KEY) {
247 +                       if (pskb_may_pull(skb, sizeof(sysctl_icmp_ipod_key)+sizeof(struct udphdr)-1)){
248 +#if 0
249 +                           int i;
250 +                           for (i=0;i<32+1;i++){
251 +                               printk("%c",((char*)skb->data)[i+sizeof(struct udphdr)]);
252 +                           }   
253 +                           printk("\n");
254 +#endif
255 +                           if (IPOD_VALID_KEY(skb->data+sizeof(struct udphdr)))
256 +                               doit = 1;
257 +                       }
258 +               } else {
259 +                       doit = 1;
260 +               }
261 +       }
262 +       if (doit) {
263 +               sysctl_icmp_ipod_enabled = 0;
264 +               printk(KERN_CRIT "IPOD: reboot forced by %u.%u.%u.%u...\n",
265 +                      NIPQUAD(saddr));
266 +               machine_restart(NULL);
267 +       } else {
268 +               printk(KERN_WARNING "IPOD: from %u.%u.%u.%u rejected\n",
269 +                      NIPQUAD(saddr));
270 +       }
271 +}
272 +#endif
273 +
274  /*
275   *     All we need to do is get the socket, and then do a checksum.
276   */
277 @@ -1249,6 +1318,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, 
278         if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
279                 return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
280  
281 +#ifdef CONFIG_ICMP_IPOD
282 +       udp_ping_of_death(skb, uh, saddr);
283 +#endif
284 +
285         sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
286                                skb->dev->ifindex, udptable        );
287