From owner-p4-projects@FreeBSD.ORG Thu Sep 16 07:52:59 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D979A16A4D1; Thu, 16 Sep 2004 07:52:58 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id AD13A16A4CE for ; Thu, 16 Sep 2004 07:52:58 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8B61A43D4C for ; Thu, 16 Sep 2004 07:52:58 +0000 (GMT) (envelope-from brooks@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.11/8.12.11) with ESMTP id i8G7qwnx023486 for ; Thu, 16 Sep 2004 07:52:58 GMT (envelope-from brooks@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.11/8.12.11/Submit) id i8G7qwOS023483 for perforce@freebsd.org; Thu, 16 Sep 2004 07:52:58 GMT (envelope-from brooks@freebsd.org) Date: Thu, 16 Sep 2004 07:52:58 GMT Message-Id: <200409160752.i8G7qwOS023483@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to brooks@freebsd.org using -f From: Brooks Davis To: Perforce Change Reviews Subject: PERFORCE change 61600 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 16 Sep 2004 07:52:59 -0000 http://perforce.freebsd.org/chv.cgi?CH=61600 Change 61600 by brooks@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 +#include + +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