I've sent following patch;
matusita> This patch does teach ppp(8) about 'ipv6' protocol (protocol
matusita> number 41) to filter. This patch also fixes
matusita> not-initializing 'f_dstop' variable for other protocols.
but some other guys says that "why not you make ppp to specify
protocol number directly, just like 'set filter out 0 permit 41' or whatever?"
It's good suggestion to me, so I've update my patch to support this.
***
This patch allows to users to specify any IP protocol number in their
filter ruleset. For example, if you want to pass incoming L2TP
(protocol number 115) packet,
set filter in 0 permit proto115
where 'proto115' means 'protocol number 115'. Since ppp(8) doesn't
know L2TP or any ppp(8) unsupported protocol, you can only specify
src/dst addresses to a filter rule of these unknown protocols
(specifying 'port' or whatever will not work).
I hope this patch works as expected (I've tested with my ADSL line and
it seems working) and doesn't hurt any existing features, but if you
have a time, please review this patch.
-- -
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
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-net" in the body of the message