Index: sbin/ipfw/ipfw2.c
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw2.c,v
retrieving revision 1.46
diff -u -p -r1.46 ipfw2.c
--- sbin/ipfw/ipfw2.c	9 Apr 2004 17:26:01 -0000	1.46
+++ sbin/ipfw/ipfw2.c	23 Apr 2004 12:33:24 -0000
@@ -226,6 +226,7 @@ enum tokens {
 	TOK_MAC,
 	TOK_MACTYPE,
 	TOK_VERREVPATH,
+	TOK_VERSRCREACH,
 	TOK_IPSEC,
 	TOK_COMMENT,
 
@@ -338,6 +339,7 @@ struct _s_x rule_options[] = {
 	{ "mac",		TOK_MAC },
 	{ "mac-type",		TOK_MACTYPE },
 	{ "verrevpath",		TOK_VERREVPATH },
+	{ "versrcreach",	TOK_VERSRCREACH },
 	{ "ipsec",		TOK_IPSEC },
 	{ "//",			TOK_COMMENT },
 
@@ -1268,6 +1270,10 @@ show_ipfw(struct ip_fw *rule, int pcwidt
 				printf(" verrevpath");
 				break;
 
+			case O_VERSRCREACH:
+				printf(" versrcreach");
+				break;
+
 			case O_IPSEC:
 				printf(" ipsec");
 				break;
@@ -1874,7 +1880,7 @@ help(void)
 "	ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
 "	mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
 "	setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
-"	verrevpath\n"
+"	verrevpath | versrcreach\n"
 );
 exit(0);
 }
@@ -3398,6 +3404,10 @@ read_options:
 
 		case TOK_VERREVPATH:
 			fill_cmd(cmd, O_VERREVPATH, 0, 0);
+			break;
+
+		case TOK_VERSRCREACH:
+			fill_cmd(cmd, O_VERSRCREACH, 0, 0);
 			break;
 
 		case TOK_IPSEC:
Index: sbin/ipfw/ipfw.8
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw.8,v
retrieving revision 1.142
diff -u -p -r1.142 ipfw.8
--- sbin/ipfw/ipfw.8	27 Mar 2004 14:13:53 -0000	1.142
+++ sbin/ipfw/ipfw.8	23 Apr 2004 12:33:28 -0000
@@ -1230,7 +1230,23 @@ the Cisco IOS command:
 .Pp
 .Dl ip verify unicast reverse-path
 .Pp
-This option can be used to make anti-spoofing rules.
+This option can be used to make anti-spoofing rules to reject all
+packets with source addresses not from this interface.
+.It Cm versrcreach
+For incoming packets,
+a routing table lookup is done on the packet's source address.
+If a route to the source address exists, but not the default route,
+the packet matches.
+Otherwise the packet does not match.
+All outgoing packets match.
+.Pp
+The name and functionality of the option is intentionally similar to
+the Cisco IOS command:
+.Pp
+.Dl ip verify unicast source reachable-via any
+.Pp
+This option can be used to make anti-spoofing rules to reject all
+packets whose source address is unreachable.
 .El
 .Sh SETS OF RULES
 Each rule belongs to one of 32 different
Index: netinet/ip_fw.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw.h,v
retrieving revision 1.83
diff -u -p -r1.83 ip_fw.h
--- netinet/ip_fw.h	25 Feb 2004 19:55:28 -0000	1.83
+++ netinet/ip_fw.h	23 Apr 2004 12:33:45 -0000
@@ -95,6 +95,7 @@ enum ipfw_opcodes {		/* arguments (4 byt
 	O_TCPOPTS,		/* arg1 = 2*u8 bitmap		*/
 
 	O_VERREVPATH,		/* none				*/
+	O_VERSRCREACH,		/* none				*/
 
 	O_PROBE_STATE,		/* none				*/
 	O_KEEP_STATE,		/* none				*/
Index: netinet/ip_fw2.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.56
diff -u -p -r1.56 ip_fw2.c
--- netinet/ip_fw2.c	25 Feb 2004 19:55:28 -0000	1.56
+++ netinet/ip_fw2.c	23 Apr 2004 12:33:50 -0000
@@ -439,21 +439,27 @@ iface_match(struct ifnet *ifp, ipfw_insn
 }
 
 /*
+ * The verify_path function checks if a route to the src exists and
+ * if it is reachable via ifp (when provided).
+ * 
  * The 'verrevpath' option checks that the interface that an IP packet
  * arrives on is the same interface that traffic destined for the
- * packet's source address would be routed out of. This is a measure
- * to block forged packets. This is also commonly known as "anti-spoofing"
- * or Unicast Reverse Path Forwarding (Unicast RFP) in Cisco-ese. The
- * name of the knob is purposely reminisent of the Cisco IOS command,
+ * packet's source address would be routed out of.  The 'versrcreach'
+ * option just checks that the source address is reachable via any route
+ * (except default) in the routing table.  These two are a measure to block
+ * forged packets.  This is also commonly known as "anti-spoofing" or Unicast
+ * Reverse Path Forwarding (Unicast RFP) in Cisco-ese. The name of the knobs
+ * is purposely reminiscent of the Cisco IOS command,
  *
  *   ip verify unicast reverse-path
+ *   ip verify unicast source reachable-via any
  *
  * which implements the same functionality. But note that syntax is
  * misleading. The check may be performed on all IP packets whether unicast,
  * multicast, or broadcast.
  */
 static int
-verify_rev_path(struct in_addr src, struct ifnet *ifp)
+verify_path(struct in_addr src, struct ifnet *ifp)
 {
 	struct route ro;
 	struct sockaddr_in *dst;
@@ -468,10 +474,21 @@ verify_rev_path(struct in_addr src, stru
 
 	if (ro.ro_rt == NULL)
 		return 0;
-	if ((ifp == NULL) || (ro.ro_rt->rt_ifp->if_index != ifp->if_index)) {
+
+	/* if ifp is provided, check for equality with rtentry */
+	if (ifp != NULL && ro.ro_rt->rt_ifp != ifp) {
+		RTFREE(ro.ro_rt);
+		return 0;
+	}
+
+	/* if no ifp provided, check if rtentry is not default route */
+	if (ifp == NULL &&
+	     satosin(rt_key(ro.ro_rt))->sin_addr.s_addr == INADDR_ANY) {
 		RTFREE(ro.ro_rt);
 		return 0;
 	}
+
+	/* found valid route */
 	RTFREE(ro.ro_rt);
 	return 1;
 }
@@ -1911,7 +1928,13 @@ check_body:
 				/* Outgoing packets automatically pass/match */
 				match = ((oif != NULL) ||
 				    (m->m_pkthdr.rcvif == NULL) ||
-				    verify_rev_path(src_ip, m->m_pkthdr.rcvif));
+				    verify_path(src_ip, m->m_pkthdr.rcvif));
+				break;
+
+			case O_VERSRCREACH:
+				/* Outgoing packets automatically pass/match */
+				match = ((oif != NULL) ||
+				     verify_path(src_ip, NULL));
 				break;
 
 			case O_IPSEC:
@@ -2546,6 +2569,7 @@ check_ipfw_struct(struct ip_fw *rule, in
 		case O_TCPOPTS:
 		case O_ESTAB:
 		case O_VERREVPATH:
+		case O_VERSRCREACH:
 		case O_IPSEC:
 			if (cmdlen != F_INSN_SIZE(ipfw_insn))
 				goto bad_size;
