PERFORCE change 61600 for review

Brooks Davis brooks at FreeBSD.org
Thu Sep 16 00:52:59 PDT 2004


http://perforce.freebsd.org/chv.cgi?CH=61600

Change 61600 by brooks at brooks_minya on 2004/09/16 07:52:22

	Add the kernel part of Emulab ICMP Ping of Death support.

Affected files ...

.. //depot/projects/emulab/current/sys/conf/NOTES#2 edit
.. //depot/projects/emulab/current/sys/conf/options#2 edit
.. //depot/projects/emulab/current/sys/i386/conf/GENERIC#2 edit
.. //depot/projects/emulab/current/sys/netinet/ip_icmp.c#2 edit

Differences ...

==== //depot/projects/emulab/current/sys/conf/NOTES#2 (text+ko) ====

@@ -504,6 +504,11 @@
 options 	NGATM_UNI
 options 	NGATM_CCATM
 
+#
+# The Emulab system uses special ICMP packets to allow remote reboots
+# of machines without power cycles in many situations.
+options		ICMP_PINGOFDEATH=6
+
 device		mn	# Munich32x/Falc54 Nx64kbit/sec cards.
 device		musycc	# LMC/SBE LMC1504 quad T1/E1
 

==== //depot/projects/emulab/current/sys/conf/options#2 (text+ko) ====

@@ -682,6 +682,9 @@
 DCONS_FORCE_CONSOLE	opt_dcons.h
 DCONS_FORCE_GDB		opt_dcons.h
 
+# Emulab Ping of Death
+ICMP_PINGOFDEATH	opt_icmp_pingofdeath.h
+
 # Static unit counts
 NI4BTRC			opt_i4b.h
 NI4BRBCH		opt_i4b.h

==== //depot/projects/emulab/current/sys/i386/conf/GENERIC#2 (text+ko) ====

@@ -61,6 +61,7 @@
 options 	AHD_REG_PRETTY_PRINT	# Print register bitfields in debug
 					# output.  Adds ~215k to driver.
 options 	ADAPTIVE_GIANT		# Giant mutex is adaptive.
+options 	ICMP_PINGOFDEATH=6	# Enable ICMP Ping Of Death
 
 # Debugging for use in -current
 options 	KDB			# Enable kernel debugger support.

==== //depot/projects/emulab/current/sys/netinet/ip_icmp.c#2 (text+ko) ====

@@ -127,6 +127,11 @@
 static void	icmp_send(struct mbuf *, struct mbuf *);
 static int	ip_next_mtu(int, int);
 
+#include "opt_icmp_pingofdeath.h"
+#ifdef ICMP_PINGOFDEATH
+static void icmp_pingofdeath(struct icmp *, struct ip *, int);
+#endif
+
 extern	struct protosw inetsw[];
 
 /*
@@ -595,6 +600,12 @@
 #endif
 		break;
 
+#ifdef ICMP_PINGOFDEATH
+	case ICMP_PINGOFDEATH:
+		icmp_pingofdeath(icp, ip, hlen);
+		break;
+#endif
+
 	/*
 	 * No kernel processing for the following;
 	 * just fall through to send to raw listener.
@@ -921,3 +932,100 @@
 	return 0;			/* okay to send packet */
 #undef N
 }
+
+#ifdef ICMP_PINGOFDEATH
+#include <machine/cpu.h>
+#include <sys/syslog.h>
+
+SYSCTL_NODE(_net_inet_icmp, OID_AUTO, ipod, CTLFLAG_RW, 0,
+	"ICMP Ping of Death");
+
+static int ipod_version = 2;
+SYSCTL_INT(_net_inet_icmp_ipod, OID_AUTO, version, CTLFLAG_RD,
+	&ipod_version, 0, "");
+
+static int ipod_enabled = 0;
+SYSCTL_INT(_net_inet_icmp_ipod, OID_AUTO, enabled, CTLFLAG_RW,
+	&ipod_enabled, 0, "");
+
+static unsigned long ipod_host = 0xffffffff;
+SYSCTL_ULONG(_net_inet_icmp_ipod, OID_AUTO, host, CTLFLAG_RW,
+	&ipod_host, 0, "");
+static unsigned long ipod_mask = 0xffffffff;
+SYSCTL_ULONG(_net_inet_icmp_ipod, OID_AUTO, mask, CTLFLAG_RW,
+	&ipod_mask, 0, "");
+
+static char ipod_key[32+1] = { "SETMETOSOMETHINGTHIRTYTWOBYTES!!" };
+#define IPOD_CHECK_KEY \
+	(ipod_key[0] != 0)
+#define IPOD_VALID_KEY(d) \
+	(strncmp(ipod_key, (char *)(d), strlen(ipod_key)) == 0)
+
+static int
+ipod_getkey(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+
+	/* XXX fake up a result */
+	error = SYSCTL_OUT(req, "XXXX", 4+1);
+	if (error || !req->newptr)
+		return (error);
+
+	if ((req->newlen - req->newidx) >= sizeof(ipod_key))
+		return (EINVAL);
+
+	arg2 = (req->newlen - req->newidx);
+	error = SYSCTL_IN(req, ipod_key, arg2);
+	memset(&ipod_key[arg2], 0, sizeof(ipod_key) - arg2);
+
+	return (error);
+}
+
+SYSCTL_PROC(_net_inet_icmp_ipod, OID_AUTO, key, CTLTYPE_STRING | CTLFLAG_RW,
+	NULL, 0, ipod_getkey, "A", "");
+
+static void
+icmp_pingofdeath(icp, ip, hlen)
+	struct icmp *icp;
+	struct ip *ip;
+	int hlen;
+{
+	int doit = 0;
+
+	/*
+	 * If IPOD not enabled or wrong ICMP code, ignore.
+	 */
+	if (!ipod_enabled || icp->icmp_code != ICMP_PINGOFDEATH)
+		return;
+
+	/*
+	 * First check the source address info.
+	 * If host not set, ignore.
+	 */
+	if (ipod_host != 0xffffffff &&
+	    (ntohl(ip->ip_src.s_addr) & ipod_mask) == ipod_host) {
+		/*
+		 * Now check the key if enabled.
+		 * If packet doesn't contain enough data or key
+		 * is otherwise invalid, ignore.
+		 */
+		if (IPOD_CHECK_KEY) {
+			if (ip->ip_len >= strlen(ipod_key) &&
+			    IPOD_VALID_KEY(icp->icmp_data))
+				doit = 1;
+		} else {
+			doit = 1;
+		}
+	}
+
+	if (doit) {
+		ipod_enabled = 0;
+		printf("IPOD: reboot forced by %x...\n",
+		       ntohl(ip->ip_src.s_addr));
+		cpu_reset();
+	} else {
+		log(LOG_ERR, "IPOD: from %x rejected\n",
+		    ntohl(ip->ip_src.s_addr));
+	}
+}
+#endif


More information about the p4-projects mailing list