Index: contrib/tcpdump/print-ip.c
===================================================================
RCS file: /home/ncvs/src/contrib/tcpdump/print-ip.c,v
retrieving revision 1.7.2.3
diff -u -u -r1.7.2.3 print-ip.c
--- contrib/tcpdump/print-ip.c	3 Mar 2003 05:11:02 -0000	1.7.2.3
+++ contrib/tcpdump/print-ip.c	1 Apr 2003 08:55:47 -0000
@@ -510,6 +510,12 @@
 	} else if (off & IP_DF)
 		(void)printf(" (DF)");
 
+#ifndef	IP_EF
+#define	IP_EF	0x8000
+#endif /* IP_EF */
+	if (off & IP_EF)
+		(void)printf(" (EF)");
+
 	if (ip->ip_tos) {
 		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
 		/* ECN bits */
Index: sbin/ping/ping.8
===================================================================
RCS file: /home/ncvs/src/sbin/ping/ping.8,v
retrieving revision 1.25.2.11
diff -u -u -r1.25.2.11 ping.8
--- sbin/ping/ping.8	23 Feb 2003 21:03:24 -0000	1.25.2.11
+++ sbin/ping/ping.8	1 Apr 2003 08:55:50 -0000
@@ -42,7 +42,7 @@
 packets to network hosts
 .Sh SYNOPSIS
 .Nm
-.Op Fl AQRadfnqrv
+.Op Fl AQRadEfnqrv
 .Op Fl c Ar count
 .Op Fl i Ar wait
 .Op Fl l Ar preload
@@ -107,6 +107,8 @@
 If this option is not specified,
 .Nm
 will operate until interrupted.
+.It Fl E
+Set the EVIL bit.
 .It Fl d
 Set the
 .Dv SO_DEBUG
Index: sbin/ping/ping.c
===================================================================
RCS file: /home/ncvs/src/sbin/ping/ping.c,v
retrieving revision 1.52.2.13
diff -u -u -r1.52.2.13 ping.c
--- sbin/ping/ping.c	29 Oct 2002 10:23:21 -0000	1.52.2.13
+++ sbin/ping/ping.c	1 Apr 2003 08:55:52 -0000
@@ -137,6 +137,7 @@
 #endif /*IPSEC*/
 #define	F_TTL		0x8000
 #define	F_MISSED	0x10000
+#define	F_SO_EVIL	0x200000
 
 /*
  * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -242,7 +243,7 @@
 
 	datap = &outpack[MINICMPLEN + PHDR_LEN];
 	while ((ch = getopt(argc, argv,
-		"AI:LQRS:T:c:adfi:l:m:np:qrs:t:v"
+		"AI:LQRS:T:c:adEfi:l:m:np:qrs:t:v"
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
 		"P:"
@@ -268,6 +269,9 @@
 		case 'd':
 			options |= F_SO_DEBUG;
 			break;
+		case 'E':
+			options |= F_SO_EVIL;
+			break;
 		case 'f':
 			if (uid) {
 				errno = EPERM;
@@ -476,6 +480,10 @@
 	if (options & F_SO_DONTROUTE)
 		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
 		    sizeof(hold));
+	if (options & F_SO_EVIL)
+		if (setsockopt(s, IPPROTO_IP, IP_EVIL_INTENT, (char *)&hold,
+		    sizeof(hold)) != 0)
+		err(EX_OSERR, "setsockopt(s, IPPROTO_IP, IP_EVIL_INTENT, ...)");
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
 	if (options & F_POLICY) {
@@ -877,6 +885,8 @@
 			(void)printf(" ttl=%d", ip->ip_ttl);
 			if (timing)
 				(void)printf(" time=%.3f ms", triptime);
+			if (ip->ip_off & IP_EF)
+				(void)printf(" (EVIL)");
 			if (dupflag)
 				(void)printf(" (DUP!)");
 			if (options & F_AUDIBLE)
Index: share/man/man4/inet.4
===================================================================
RCS file: /home/ncvs/src/share/man/man4/inet.4,v
retrieving revision 1.11.2.6
diff -u -u -r1.11.2.6 inet.4
--- share/man/man4/inet.4	17 Dec 2001 11:30:12 -0000	1.11.2.6
+++ share/man/man4/inet.4	1 Apr 2003 08:55:52 -0000
@@ -258,6 +258,17 @@
 .Pq ip.rtmaxcache
 Integer: trigger level of cached, unreferenced, protocol-cloned routes
 which initiates dynamic adaptation (default 128).
+.It Dv IPCTL_RFC3514
+.Pq ip.rfc3514
+Boolean: Enable support for RFC3514.  Defaults to off.
+.It Dv IPCTL_SPEAK_NO_EVIL
+.Pq ip.speak_no_evil
+Boolean: Prevent the transmission of RFC3514 (EVIL) packets.
+Defaults to off.
+.It Dv IPCTL_HEAR_NO_EVIL
+.Pq ip.hear_no_evil
+Boolean: Prevent the reception of RFC3514 (EVIL) packets.
+Defaults to off.
 .El
 .Sh SEE ALSO
 .Xr ioctl 2 ,
Index: share/man/man4/ip.4
===================================================================
RCS file: /home/ncvs/src/share/man/man4/ip.4,v
retrieving revision 1.13.2.9
diff -u -u -r1.13.2.9 ip.4
--- share/man/man4/ip.4	2 May 2002 02:40:26 -0000	1.13.2.9
+++ share/man/man4/ip.4	1 Apr 2003 08:55:53 -0000
@@ -136,6 +136,15 @@
 cmsg_type = IP_RECVDSTADDR
 .Ed
 .Pp
+.Dv IP_EVIL_INTENT can be used to specify that IP packets should have their
+EVIL option set as per RFC3514.
+The cmsghdr fields should have the following values:
+.Bd -literal
+cmsg_len = sizeof(struct in_addr)
+cmsg_level = IPPROTO_IP
+cmsg_type = IP_EVIL_INTENT
+.Ed
+.Pp
 .Dv IP_PORTRANGE
 may be used to set the port range used for selecting a local port number
 on a socket with an unspecified (zero) port number.
Index: sys/netinet/in.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in.h,v
retrieving revision 1.48.2.9
diff -u -u -r1.48.2.9 in.h
--- sys/netinet/in.h	1 Dec 2002 14:03:10 -0000	1.48.2.9
+++ sys/netinet/in.h	1 Apr 2003 08:55:55 -0000
@@ -333,6 +333,8 @@
 #define	IP_DUMMYNET_FLUSH	62   /* flush dummynet */
 #define	IP_DUMMYNET_GET		64   /* get entire dummynet pipes */
 
+#define	IP_EVIL_INTENT		65   /* RFC3514 */
+
 /*
  * Defaults and limits for options
  */
Index: sys/netinet/in_pcb.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_pcb.h,v
retrieving revision 1.32.2.7
diff -u -u -r1.32.2.7 in_pcb.h
--- sys/netinet/in_pcb.h	24 Jan 2003 05:11:34 -0000	1.32.2.7
+++ sys/netinet/in_pcb.h	1 Apr 2003 08:55:57 -0000
@@ -262,6 +262,7 @@
 #define	INP_RECVIF		0x80	/* receive incoming interface */
 #define	INP_MTUDISC		0x100	/* user can do MTU discovery */
 #define	INP_FAITH		0x200	/* accept FAITH'ed connections */
+#define	INP_EVIL		0x400	/* Packet has evil intentions */
 
 #define IN6P_IPV6_V6ONLY	0x008000 /* restrict AF_INET6 socket for v6 */
 
Index: sys/netinet/ip.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip.h,v
retrieving revision 1.17
diff -u -u -r1.17 ip.h
--- sys/netinet/ip.h	22 Dec 1999 19:13:20 -0000	1.17
+++ sys/netinet/ip.h	1 Apr 2003 08:55:57 -0000
@@ -64,6 +64,7 @@
 	u_short	ip_id;			/* identification */
 	u_short	ip_off;			/* fragment offset field */
 #define	IP_RF 0x8000			/* reserved fragment flag */
+#define	IP_EF 0x8000			/* packet is evil */
 #define	IP_DF 0x4000			/* dont fragment flag */
 #define	IP_MF 0x2000			/* more fragments flag */
 #define	IP_OFFMASK 0x1fff		/* mask for fragmenting bits */
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.130.2.52
diff -u -u -r1.130.2.52 ip_input.c
--- sys/netinet/ip_input.c	7 Mar 2003 07:01:28 -0000	1.130.2.52
+++ sys/netinet/ip_input.c	1 Apr 2003 08:56:00 -0000
@@ -137,6 +137,11 @@
 	&ip_sendsourcequench, 0,
 	"Enable the transmission of source quench packets");
 
+static int	hear_no_evil = 0;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, hear_no_evil, CTLFLAG_RW,
+	&hear_no_evil, 0,
+	"Drop all received EVIL packets.");
+
 /*
  * XXX - Setting ip_checkinterface mostly implements the receive side of
  * the Strong ES model described in RFC 1122, but since the routing table
@@ -405,6 +410,15 @@
 		goto bad;
 	}
 	ip->ip_off = ntohs(ip->ip_off);
+
+	/*
+	 * Check for RFC3514 (EVIL) packets.
+	 */
+	if (ip->ip_off & IP_EF) {
+		ipstat.ips_evil++;
+		if (hear_no_evil)
+			goto bad;
+	}
 
 	/*
 	 * Check that the amount of data in the buffers
Index: sys/netinet/ip_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.99.2.36
diff -u -u -r1.99.2.36 ip_output.c
--- sys/netinet/ip_output.c	30 Jan 2003 05:53:28 -0000	1.99.2.36
+++ sys/netinet/ip_output.c	1 Apr 2003 08:56:05 -0000
@@ -51,6 +51,7 @@
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
+#include <sys/sysctl.h>
 #include <sys/proc.h>
 
 #include <net/if.h>
@@ -94,6 +95,14 @@
 
 u_short ip_id;
 
+static int ip_do_rfc3514 = 0;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, rfc3514, CTLFLAG_RW,
+	&ip_do_rfc3514, 0, "IPv4 Header Security Flag Support");
+
+static int speak_no_evil = 0;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, speak_no_evil, CTLFLAG_RW,
+	&speak_no_evil, 0, "Drop all EVIL packets before output.");
+
 static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *);
 static struct ifnet *ip_multicast_if(struct in_addr *, int *);
 static void	ip_mloopback
@@ -216,7 +225,7 @@
 	 */
 	if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
 		ip->ip_vhl = IP_MAKE_VHL(IPVERSION, hlen >> 2);
-		ip->ip_off &= IP_DF;
+		ip->ip_off &= IP_DF|IP_EF;
 #ifdef RANDOM_IP_ID
 		ip->ip_id = ip_randomid();
 #else
@@ -227,6 +236,17 @@
 		hlen = IP_VHL_HL(ip->ip_vhl) << 2;
 	}
 
+	/* RFC3514 */
+	if ((inp != NULL) &&				/* Originated	*/
+	    ip_do_rfc3514 &&				/* Supported	*/
+	    ((inp->inp_flags & INP_EVIL) == INP_EVIL))	/* Optioned	*/
+		ip->ip_off |= IP_EF;
+
+	if (speak_no_evil && (ip->ip_off & IP_EF)) {
+		error = EACCES;
+		goto bad;
+	}
+
 #ifdef FAST_IPSEC
 	if (ro == NULL) {
 		ro = &iproute;
@@ -1338,6 +1358,7 @@
 		case IP_RECVDSTADDR:
 		case IP_RECVIF:
 		case IP_FAITH:
+		case IP_EVIL_INTENT:
 			error = sooptcopyin(sopt, &optval, sizeof optval,
 					    sizeof optval);
 			if (error)
@@ -1376,6 +1397,12 @@
 			case IP_FAITH:
 				OPTSET(INP_FAITH);
 				break;
+			case IP_EVIL_INTENT:
+				if (ip_do_rfc3514) {
+					OPTSET(INP_EVIL);
+				} else
+					error = EINVAL;
+				break;
 			}
 			break;
 #undef OPTSET
@@ -1508,6 +1535,8 @@
 			case IP_FAITH:
 				optval = OPTBIT(INP_FAITH);
 				break;
+			case IP_EVIL_INTENT:
+				optval = OPTBIT(INP_EVIL);
 			}
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
Index: sys/netinet/ip_var.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.50.2.12
diff -u -u -r1.50.2.12 ip_var.h
--- sys/netinet/ip_var.h	27 Feb 2003 04:50:02 -0000	1.50.2.12
+++ sys/netinet/ip_var.h	1 Apr 2003 08:56:05 -0000
@@ -127,6 +127,7 @@
 	u_long	ips_notmember;		/* multicasts for unregistered grps */
 	u_long	ips_nogif;		/* no match gif found */
 	u_long	ips_badaddr;		/* invalid address on header */
+	u_long	ips_evil;		/* EVIL packets received */
 };
 
 #ifdef _KERNEL
Index: usr.bin/netstat/inet.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/netstat/inet.c,v
retrieving revision 1.37.2.9
diff -u -u -r1.37.2.9 inet.c
--- usr.bin/netstat/inet.c	17 Dec 2001 20:03:59 -0000	1.37.2.9
+++ usr.bin/netstat/inet.c	1 Apr 2003 08:56:06 -0000
@@ -567,6 +567,7 @@
 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
 	p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
 	p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
+	p(ips_evil, "\t%lu EVIL datagram%s received.\n");
 #undef p
 #undef p1a
 }
