From owner-FreeBSD-net-jp@jp.freebsd.org  Sat Jul 14 16:01:40 2001
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id QAA99518;
	Sat, 14 Jul 2001 16:01:40 +0900 (JST)
	(envelope-from owner-FreeBSD-net-jp@jp.FreeBSD.org)
Received: from ns.matatabi.or.jp (ns.matatabi.or.jp [210.163.106.162])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id QAA99513
	for <net-jp@jp.FreeBSD.org>; Sat, 14 Jul 2001 16:01:38 +0900 (JST)
	(envelope-from matusita@matatabi.or.jp)
Received: from localhost (localhost [127.0.0.1]) by ns.matatabi.or.jp (8.11.3/3.7W/MATATABI-1.0v9-NS1.2) with ESMTP id f6E71av87064 for <net-jp@jp.FreeBSD.org>; Sat, 14 Jul 2001 16:01:36 +0900 (JST)
	(envelope-from matusita@matatabi.or.jp)
In-Reply-To: <20010703005158X.matusita@matatabi.or.jp>
References: <20010703005158X.matusita@matatabi.or.jp>
X-Face: '*aj"d@ijeQ:/X}]oM5c5Uz{ZZZk90WPt>a^y4$cGQp8:!H\W=hSM;PuNiidkc]/%,;6VGu
 e+`&APmz|P;F~OL/QK%;P2vU>\j4X.8@i%j6[%DTs_3J,Fff0)*oHg$A.cDm&jc#pD24WK@{,"Ef!0
 P\):.2}8jo-BiZ?X&t$V
X-User-Agent: Mew/1.94.2 XEmacs/21.5 (alfalfa)
X-FaceAnim: (-O_O-)(O_O- )(_O-  )(O-   )(-   -)(   -O)(  -O_)( -O_O)(-O_O-)
Mime-Version: 1.0
Content-Type: Text/Plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
X-Dispatcher: imput version 20000228(IM140)
Lines: 525
From: Makoto MATSUSHITA <matusita@matatabi.or.jp>
To: net-jp@jp.FreeBSD.org
Date: Sat, 14 Jul 2001 16:01:28 +0900
Message-Id: <20010714160128B.matusita@matatabi.or.jp>
Reply-To: FreeBSD-net-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+010328
X-Sequence: FreeBSD-net-jp 3229
Subject: [FreeBSD-net-jp 3229] Re: [patch] Add 'ipv6' (protocol 41) support for ppp(8)
Errors-To: owner-FreeBSD-net-jp@jp.freebsd.org
Sender: owner-FreeBSD-net-jp@jp.freebsd.org
X-Originator: matusita@matatabi.or.jp


matusita> filter $B$r;H$o$J$1$l$PBg>fIW!$$G$O$"$j$^$9$,!$$;$C$+$/(B ppp $B$K(B 
matusita> filter $B$"$k$s$@$+$i$=$l$r;H$$$?$$!$$H;W$C$?$N$G!$(Bfilter $B$r;H$C(B
matusita> $B$?;~$G$b$A$c$s$H(Btunnel packet $B$rDL$;$k$h$&$K!$(Bpatch $B$r=q$$$F(B
matusita> $B$_$^$7$?!%(B

$B$H$$$&$N$r0JA0=P$7$?$N$G$9$,!$$d$C$Q$j!V$"$i$f$k(B protocol $B$r;XDj$G$-$J(B
$B$-$c$@$a$@$h$M!W$H$$$&5$$,$7$?$N$G!$=q$-$+$($F$_$^$7$?!%(B

***

filter $B$N%k!<%kCf!$(Bprotocol $B$r;XDj$9$k=j$G(B protoN (N $B$O?t;z(B)$B$H=q$/$H!$(B
protocol number $B$,(B N $B$G$"$k(B protocol $B$r;XDj$7$?$N$HEy2A$K$J$k$h$&$K$7(B
$B$F$_$^$7$?!%Nc$($P!$(B

	set filter out 0 permit proto115

$B$H=q$/$H!$(BL2TP $B$N(B packet $B$r5v2D$9$k!$$H$$$&$3$H$K$J$j$^$9!%EvA3$H$$$((B
$B$PEvA3$G$9$,!$(Bproto6 $B$H=q$/$H!$(Btcp $B$H=q$$$?$N$HEy2A$K$J$j$^$9!%(B

$B0l1~<j85$N4D6-$GF0$+$7$F$&$^$/$$$C$F$$$k$D$b$j$G$9$,!$$b$7$*;~4V$"$j$^(B
$B$7$?$i(B review $B$7$F$b$i$($k$H4r$7$$$G$9!%(Bbrian $B;a$K$O$9$G$KO"Mm$7$F$"$j(B
$B$^$9$N$G!$$&$^$/$$$C$F$$$?$i(B merge $B$7$F$b$i$&$N$,L\I8$G$9(B:)

-- -
Makoto `MAR' MATSUSHITA

Index: command.c
===================================================================
RCS file: /home/cvs/FreeBSD/usr.sbin/ppp/command.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- command.c	2001/07/10 10:17:07	1.1.1.1
+++ command.c	2001/07/14 06:25:24	1.3
@@ -2169,7 +2169,7 @@
   "escape characters", "set escape hex-digit ..."},
   {"filter", NULL, filter_Set, LOCAL_AUTH,
   "packet filters", "set filter alive|dial|in|out rule-no permit|deny "
-  "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp "
+  "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp|ipv6|protoN "
   "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"},
   {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
   "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP},
Index: filter.c
===================================================================
RCS file: /home/cvs/FreeBSD/usr.sbin/ppp/filter.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- filter.c	2001/07/10 10:17:06	1.1.1.1
+++ filter.c	2001/07/14 06:25:25	1.3
@@ -159,13 +159,13 @@
   int port;
 
   switch (proto) {
-  case P_IPIP:
+  case IPPROTO_IPIP:
     protocol_name = "ipip";
     break;
-  case P_UDP:
+  case IPPROTO_UDP:
     protocol_name = "udp";
     break;
-  case P_TCP:
+  case IPPROTO_TCP:
     protocol_name = "tcp";
     break;
   default:
@@ -197,7 +197,7 @@
   switch (argc) {
   case 0:
     /* permit/deny all ICMP types */
-    tgt->f_srcop = OP_NONE;
+    tgt->f_srcop = tgt->f_dstop = OP_NONE;
     break;
 
   case 3:
@@ -209,6 +209,7 @@
       }
       tgt->f_srcop = OP_EQ;
       tgt->f_srcport = type;
+      tgt->f_dstop = OP_NONE;
     }
     break;
 
@@ -255,7 +256,7 @@
     argv += 3;
   }
 
-  if (proto == P_TCP) {
+  if (proto == IPPROTO_TCP) {
     for (; argc > 0; argc--, argv++)
       if (!strcmp(*argv, "estab"))
         tgt->f_estab = 1;
@@ -286,13 +287,45 @@
     log_Printf(LogWARN, "ParseIgmp: Too many parameters\n");
     return 0;
   } else
-    tgt->f_srcop = OP_NONE;
+    tgt->f_srcop = tgt->f_dstop = OP_NONE;
 
   return 1;
 }
 
-#ifdef P_GRE
 static int
+ParseIPv6(int argc, char const * const *argv, struct filterent *tgt)
+{
+  /*
+   * Filter currently is a catch-all. Requests are either permitted or
+   * dropped.
+   */
+  if (argc != 0) {
+    log_Printf(LogWARN, "ParseIPv6: Too many parameters\n");
+    return 0;
+  } else
+    tgt->f_srcop = tgt->f_dstop = OP_NONE;
+
+  return 1;
+}
+
+static int
+ParseGenericProtocol(int argc, char const * const *argv, struct filterent *tgt)
+{
+  /*
+   * Filter currently is a catch-all. Requests are either permitted or
+   * dropped.
+   */
+  if (argc != 0) {
+    log_Printf(LogWARN, "ParseGenericProtocol: Too many parameters\n");
+    return 0;
+  } else
+    tgt->f_srcop = tgt->f_dstop = OP_NONE;
+
+  return 1;
+}
+
+#ifdef IPPROTO_GRE
+static int
 ParseGRE(int argc, char const * const *argv, struct filterent *tgt)
 {
   /*
@@ -303,13 +336,13 @@
     log_Printf(LogWARN, "ParseGRE: Too many parameters\n");
     return 0;
   } else
-    tgt->f_srcop = OP_NONE;
+    tgt->f_srcop = tgt->f_dstop = OP_NONE;
 
   return 1;
 }
 #endif
 
-#ifdef P_OSPF
+#ifdef IPPROTO_OSPF
 static int
 ParseOspf(int argc, char const * const *argv, struct filterent *tgt)
 {
@@ -321,7 +354,7 @@
     log_Printf(LogWARN, "ParseOspf: Too many parameters\n");
     return 0;
   } else
-    tgt->f_srcop = OP_NONE;
+    tgt->f_srcop = tgt->f_dstop = OP_NONE;
 
   return 1;
 }
@@ -401,7 +434,7 @@
   }
   argv++;
 
-  proto = P_NONE;
+  proto = 0;
   memset(&filterdata, '\0', sizeof filterdata);
 
   val = strtol(*argv, &wp, 0);
@@ -435,7 +468,7 @@
   }
 
   proto = filter_Nam2Proto(argc, argv);
-  if (proto == P_NONE) {
+  if (proto == 0) {
     if (!argc)
       log_Printf(LogWARN, "Parse: address/mask is expected.\n");
     else if (ParseAddr(ipcp, *argv, &filterdata.f_src.ipaddr,
@@ -446,7 +479,7 @@
       proto = filter_Nam2Proto(argc, argv);
       if (!argc)
         log_Printf(LogWARN, "Parse: address/mask is expected.\n");
-      else if (proto == P_NONE) {
+      else if (proto == 0) {
 	if (ParseAddr(ipcp, *argv, &filterdata.f_dst.ipaddr,
 		      &filterdata.f_dst.mask, &filterdata.f_dst.width)) {
           filterdata.f_dsttype = addrtype(*argv);
@@ -456,7 +489,7 @@
           filterdata.f_dsttype = T_ADDR;
         if (argc) {
 	  proto = filter_Nam2Proto(argc, argv);
-	  if (proto == P_NONE) {
+	  if (proto == 0) {
             log_Printf(LogWARN, "Parse: %s: Invalid protocol\n", *argv);
             return 0;
           } else {
@@ -486,31 +519,37 @@
   filterdata.f_proto = proto;
 
   switch (proto) {
-  case P_TCP:
-    val = ParseUdpOrTcp(argc, argv, P_TCP, &filterdata);
+  case IPPROTO_TCP:
+    val = ParseUdpOrTcp(argc, argv, IPPROTO_TCP, &filterdata);
+    break;
+  case IPPROTO_UDP:
+    val = ParseUdpOrTcp(argc, argv, IPPROTO_UDP, &filterdata);
     break;
-  case P_UDP:
-    val = ParseUdpOrTcp(argc, argv, P_UDP, &filterdata);
+  case IPPROTO_IPIP:
+    val = ParseUdpOrTcp(argc, argv, IPPROTO_IPIP, &filterdata);
     break;
-  case P_IPIP:
-    val = ParseUdpOrTcp(argc, argv, P_IPIP, &filterdata);
+  case IPPROTO_IPV6:
+    val = ParseIPv6(argc, argv, &filterdata);
     break;
-  case P_ICMP:
+  case IPPROTO_ICMP:
     val = ParseIcmp(argc, argv, &filterdata);
     break;
-  case P_IGMP:
+  case IPPROTO_IGMP:
     val = ParseIgmp(argc, argv, &filterdata);
     break;
-#ifdef P_OSPF
-  case P_OSPF:
+#ifdef IPPROTO_OSPF
+  case IPPROTO_OSPF:
     val = ParseOspf(argc, argv, &filterdata);
     break;
 #endif
-#ifdef P_GRE
-  case P_GRE:
+#ifdef IPPROTO_GRE
+  case IPPROTO_GRE:
     val = ParseGRE(argc, argv, &filterdata);
     break;
 #endif
+  default:
+    val = ParseGenericProtocol(argc, argv, &filterdata);
+    break;
   }
 
   log_Printf(LogDEBUG, "Parse: Src: %s\n", inet_ntoa(filterdata.f_src.ipaddr));
@@ -652,31 +691,61 @@
   return 0;
 }
 
-static const char * const protoname[] = {
-  "none", "tcp", "udp", "icmp", "ospf", "igmp", "gre", "ipip"
+struct  protoname_table {
+	char	*name;			/* protocol name */
+	int	proto;			/* protocol number */
+};
+static const struct protoname_table protoname[] = {
+	{"icmp", IPPROTO_ICMP},
+	{"igmp", IPPROTO_IGMP},
+	{"ipip", IPPROTO_IPIP},
+	{"tcp", IPPROTO_TCP},
+	{"udp", IPPROTO_UDP},
+	{"ipv6", IPPROTO_IPV6},
+	{"gre", IPPROTO_GRE},
+	{"esp", IPPROTO_ESP},
+	{"ah", IPPROTO_AH},
+	{"ospf", IPPROTO_OSPFIGP},
+	{NULL, 0},			/* end marker */
 };
 
 const char *
 filter_Proto2Nam(int proto)
 {
-  if (proto >= sizeof protoname / sizeof protoname[0])
-    return "unknown";
-  return protoname[proto];
+  int idx = 0;
+  static char buf[BUFSIZ+1];
+
+  while (protoname[idx].name != NULL) {
+    if (protoname[idx].proto == proto) {
+      return protoname[idx].name;
+    }
+    idx++;
+  }
+  snprintf(buf, BUFSIZ, "proto%d", proto);
+  return buf;
 }
 
 static int
 filter_Nam2Proto(int argc, char const *const *argv)
 {
+  int idx = 0;
   int proto;
 
   if (argc == 0)
-    proto = 0;
-  else
-    for (proto = sizeof protoname / sizeof protoname[0] - 1; proto; proto--)
-      if (!strcasecmp(*argv, protoname[proto]))
-        break;
+    return 0;
 
-  return proto;
+  while (protoname[idx].name != NULL) {
+    if (!strcasecmp(*argv, protoname[idx].name)) {
+      return protoname[idx].proto;
+    }
+    idx++;
+  }
+  if (strncmp(*argv, "proto", 5) == 0) {
+    proto = atoi(*argv + 5);
+    if (proto > 0 && proto < IPPROTO_MAX)
+      return proto;
+  }
+  return 0;
 }
 
 static const char * const opname[] = {"none", "eq", "gt", "lt"};
Index: filter.h
===================================================================
RCS file: /home/cvs/FreeBSD/usr.sbin/ppp/filter.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- filter.h	2001/07/10 10:17:05	1.1.1.1
+++ filter.h	2001/07/14 06:25:25	1.3
@@ -28,22 +28,6 @@
  * $FreeBSD: src/usr.sbin/ppp/filter.h,v 1.27 2001/06/13 21:52:16 brian Exp $
  */
 
-/* Known protocols - f_proto */
-#define	P_NONE	0
-#define	P_TCP	1
-#define	P_UDP	2
-#define	P_ICMP	3
-#ifdef IPPROTO_OSPFIGP
-#define	P_OSPF	4
-#endif
-#define	P_IGMP	5
-#ifdef IPPROTO_GRE
-#define P_GRE	6
-#endif
-#define P_ESP	7
-#define P_AH	8
-#define P_IPIP	9
-
 /* Operations - f_srcop, f_dstop */
 #define	OP_NONE	0
 #define	OP_EQ	1
@@ -73,7 +57,7 @@
  */
 struct filterent {
   unsigned f_action : 8;		/* Filtering action: goto or A_... */
-  unsigned f_proto : 8;		/* Protocol: P_... */
+  unsigned f_proto : 8;		/* Protocol: IPPROTO_... */
   unsigned f_srcop : 2;		/* Source port operation: OP_... */
   unsigned f_dstop : 2;		/* Destination port operation: OP_... */
   unsigned f_srctype : 3;	/* T_ value of src */
Index: ip.c
===================================================================
RCS file: /home/cvs/FreeBSD/usr.sbin/ppp/ip.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- ip.c	2001/07/10 10:17:04	1.1.1.1
+++ ip.c	2001/07/14 06:25:25	1.3
@@ -166,7 +166,7 @@
 FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
 {
   int gotinfo;			/* true if IP payload decoded */
-  int cproto;			/* P_* protocol type if (gotinfo) */
+  int cproto;			/* IPPROTO_* protocol type if (gotinfo) */
   int estab, syn, finrst;	/* TCP state flags if (gotinfo) */
   u_short sport, dport;		/* src, dest port from packet if (gotinfo) */
   int n;			/* filter rule to process */
@@ -220,7 +220,7 @@
           fp->f_src.mask.s_addr) &&
         !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
           fp->f_dst.mask.s_addr)) {
-      if (fp->f_proto != P_NONE) {
+      if (fp->f_proto != 0) {
         if (!gotinfo) {
           const char *ptop = (const char *) pip + (pip->ip_hl << 2);
           const struct tcphdr *th;
@@ -229,9 +229,9 @@
           int datalen;	/* IP datagram length */
 
           datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+	  cproto = pip->ip_p;
           switch (pip->ip_p) {
           case IPPROTO_ICMP:
-            cproto = P_ICMP;
             if (datalen < 8) {	/* ICMP must be at least 8 octets */
               log_Printf(LogFILTER, " error: ICMP must be at least 8 octets\n");
               return 1;
@@ -244,7 +244,6 @@
               snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
             break;
           case IPPROTO_IGMP:
-            cproto = P_IGMP;
             if (datalen < 8) {	/* IGMP uses 8-octet messages */
               log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n");
               return 1;
@@ -254,7 +253,6 @@
             break;
 #ifdef IPPROTO_GRE
           case IPPROTO_GRE:
-            cproto = P_GRE;
             if (datalen < 2) {    /* GRE uses 2-octet+ messages */
               log_Printf(LogFILTER, " error: GRE must be at least 2 octets\n");
               return 1;
@@ -265,7 +263,6 @@
 #endif
 #ifdef IPPROTO_OSPFIGP
           case IPPROTO_OSPFIGP:
-            cproto = P_OSPF;
             if (datalen < 8) {	/* IGMP uses 8-octet messages */
               log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n");
               return 1;
@@ -275,22 +272,26 @@
             break;
 #endif
           case IPPROTO_ESP:
-            cproto = P_ESP;
             estab = syn = finrst = -1;
             sport = ntohs(0);
             break;
           case IPPROTO_AH:
-            cproto = P_AH;
             estab = syn = finrst = -1;
             sport = ntohs(0);
             break;
           case IPPROTO_IPIP:
-            cproto = P_IPIP;
             sport = dport = 0;
             estab = syn = finrst = -1;
             break;
+          case IPPROTO_IPV6:
+            if (datalen < 20) {	/* RFC2893 Section 3.5: 5 * 32bit words */
+              log_Printf(LogFILTER, " error: IPV6 header incorrect\n");
+              return 1;
+            }
+            sport = dport = 0;
+            estab = syn = finrst = -1;
+            break;
           case IPPROTO_UDP:
-            cproto = P_UDP;
             if (datalen < 8) {	/* UDP header is 8 octets */
               log_Printf(LogFILTER, " error: UDP/IPIP"
                          " must be at least 8 octets\n");
@@ -306,7 +307,6 @@
                        sport, dport);
             break;
           case IPPROTO_TCP:
-            cproto = P_TCP;
             th = (const struct tcphdr *) ptop;
             /* TCP headers are variable length.  The following code
              * ensures that the TCP header length isn't de-referenced if
@@ -331,8 +331,10 @@
             }
             break;
           default:
-            log_Printf(LogFILTER, " error: unknown protocol\n");
-            return 1;		/* We'll block unknown type of packet */
+            /* unknown protocol, no port checking and flags */
+            sport = dport = 0;
+            estab = syn = finrst = -1;
+            break;
           }
 
           if (log_IsKept(LogDEBUG)) {
@@ -640,6 +642,20 @@
       len = ntohs(pip->ip_len) - (pip->ip_hl << 2);
       snprintf(logbuf + loglen, sizeof logbuf - loglen,
                "OSPF: %s ---> ", inet_ntoa(pip->ip_src));
+      loglen += strlen(logbuf + loglen);
+      snprintf(logbuf + loglen, sizeof logbuf - loglen,
+               "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
+      loglen += strlen(logbuf + loglen);
+    }
+    break;
+#endif
+
+#ifdef IPPROTO_IPV6
+  case IPPROTO_IPV6:
+    if (logit && loglen < sizeof logbuf) {
+      len = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+      snprintf(logbuf + loglen, sizeof logbuf - loglen,
+               "IPv6: %s ---> ", inet_ntoa(pip->ip_src));
       loglen += strlen(logbuf + loglen);
       snprintf(logbuf + loglen, sizeof logbuf - loglen,
                "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
Index: ppp.8
===================================================================
RCS file: /home/cvs/FreeBSD/usr.sbin/ppp/ppp.8,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- ppp.8	2001/07/10 10:17:02	1.1.1.1
+++ ppp.8	2001/07/14 06:25:25	1.3
@@ -1746,10 +1746,13 @@
 .Sq icmp ,
 .Sq igmp ,
 .Sq ipip ,
+.Sq ipv6 ,
 .Sq ospf ,
-.Sq udp
+.Sq udp ,
+.Sq tcp
 or
-.Sq tcp .
+.Sq protoN
+where N is a protocol number.
 .It
 .Ar Cmp
 is one of
