o Log the (payload/size) of all packet types, not just TCP packets

o  If the new ``filter-decapsulation'' is enabled, delve into UDP packets
   that contain 0xff 0x03 as the first two bytes, and if we recognise it
   as PROTO_IP, decapsulate it for the purpose of filter checking.

   If we recognise it as PROTO_<anything else> mention this for logging
   purposes only.

This change is aimed at people running PPPoUDP where the UDP traffic is
being sent over another PPP link.  It's desireable to have the top level
link connected all the time, but to have the bottom level link capable
of decapsulating the traffic and comparing the payload against the filters,
thus allowing ``set filter dial ...'' to work in tunnelled environments.

The caveat here is that the top ppp cannot employ any compression layers
without making the data unreadable for the bottom ppp.  ``disable deflate
pred1 vj'' and ``deny deflate pred1 vj'' is suggested.
This commit is contained in:
Brian Somers 2000-07-07 14:22:08 +00:00
parent 3660ebc2c0
commit 9825166754
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=62778
8 changed files with 157 additions and 33 deletions

View File

@ -570,7 +570,7 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
bundle->ncp.ipcp.my_ip.s_addr) {
/* we've been asked to send something addressed *to* us :( */
if (Enabled(bundle, OPT_LOOPBACK)) {
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.in);
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.in, NULL);
if (pri >= 0) {
n += sz - sizeof tun.data;
write(bundle->dev.fd, data, n);
@ -591,7 +591,8 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
* Note, we must be in AUTO mode :-/ otherwise our interface should
* *not* be UP and we can't receive data
*/
if ((pri = PacketCheck(bundle, tun.data, n, &bundle->filter.dial)) >= 0)
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.dial, NULL);
if (pri > 0)
bundle_Open(bundle, NULL, PHYS_AUTO, 0);
else
/*
@ -604,7 +605,7 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
return;
}
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.out);
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.out, NULL);
if (pri >= 0)
ip_Enqueue(&bundle->ncp.ipcp, pri, tun.data, n);
}
@ -1206,21 +1207,23 @@ bundle_ShowStatus(struct cmdargs const *arg)
prompt_Printf(arg->prompt, " Sticky Routes: %-20.20s",
optval(arg->bundle, OPT_SROUTES));
prompt_Printf(arg->prompt, " ID check: %s\n",
prompt_Printf(arg->prompt, " Filter Decap: %s\n",
optval(arg->bundle, OPT_FILTERDECAP));
prompt_Printf(arg->prompt, " ID check: %-20.20s",
optval(arg->bundle, OPT_IDCHECK));
prompt_Printf(arg->prompt, " Keep-Session: %-20.20s",
prompt_Printf(arg->prompt, " Keep-Session: %s\n",
optval(arg->bundle, OPT_KEEPSESSION));
prompt_Printf(arg->prompt, " Loopback: %s\n",
prompt_Printf(arg->prompt, " Loopback: %-20.20s",
optval(arg->bundle, OPT_LOOPBACK));
prompt_Printf(arg->prompt, " PasswdAuth: %-20.20s",
prompt_Printf(arg->prompt, " PasswdAuth: %s\n",
optval(arg->bundle, OPT_PASSWDAUTH));
prompt_Printf(arg->prompt, " Proxy: %s\n",
prompt_Printf(arg->prompt, " Proxy: %-20.20s",
optval(arg->bundle, OPT_PROXY));
prompt_Printf(arg->prompt, " Proxyall: %-20.20s",
prompt_Printf(arg->prompt, " Proxyall: %s\n",
optval(arg->bundle, OPT_PROXYALL));
prompt_Printf(arg->prompt, " Throughput: %s\n",
prompt_Printf(arg->prompt, " Throughput: %-20.20s",
optval(arg->bundle, OPT_THROUGHPUT));
prompt_Printf(arg->prompt, " Utmp Logging: %-20.20s",
prompt_Printf(arg->prompt, " Utmp Logging: %s\n",
optval(arg->bundle, OPT_UTMP));
prompt_Printf(arg->prompt, " Iface-Alias: %s\n",
optval(arg->bundle, OPT_IFACEALIAS));

View File

@ -33,16 +33,17 @@
#define PHASE_TERMINATE 4 /* Terminating link */
/* cfg.opt bit settings */
#define OPT_IDCHECK 0x0001
#define OPT_IFACEALIAS 0x0002
#define OPT_KEEPSESSION 0x0004
#define OPT_LOOPBACK 0x0008
#define OPT_PASSWDAUTH 0x0010
#define OPT_PROXY 0x0020
#define OPT_PROXYALL 0x0040
#define OPT_SROUTES 0x0080
#define OPT_THROUGHPUT 0x0100
#define OPT_UTMP 0x0200
#define OPT_FILTERDECAP 0x0001
#define OPT_IDCHECK 0x0002
#define OPT_IFACEALIAS 0x0004
#define OPT_KEEPSESSION 0x0008
#define OPT_LOOPBACK 0x0010
#define OPT_PASSWDAUTH 0x0020
#define OPT_PROXY 0x0040
#define OPT_PROXYALL 0x0080
#define OPT_SROUTES 0x0100
#define OPT_THROUGHPUT 0x0200
#define OPT_UTMP 0x0400
#define MAX_ENDDISC_CLASS 5

View File

@ -2437,11 +2437,14 @@ NegotiateSet(struct cmdargs const *arg)
}
static struct cmdtab const NegotiateCommands[] = {
{"filter-decapsulation", NULL, OptSet, LOCAL_AUTH,
"filter on PPPoUDP payloads", "disable|enable",
(const void *)OPT_FILTERDECAP},
{"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids",
"disable|enable", (const void *)OPT_IDCHECK},
{"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH,
"retain interface addresses", "disable|enable",
(const void *)OPT_IFACEALIAS},
"retain interface addresses", "disable|enable",
(const void *)OPT_IFACEALIAS},
{"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader",
"disable|enable", (const void *)OPT_KEEPSESSION},
{"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface",

View File

@ -430,7 +430,8 @@ ip_LogDNS(const struct udphdr *uh, const char *direction)
* For debugging aid.
*/
int
PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
struct filter *filter, const char *prefix)
{
static const char *const TcpFlags[] = {
"FIN", "SYN", "RST", "PSH", "ACK", "URG"
@ -439,7 +440,7 @@ PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
struct tcphdr *th;
struct udphdr *uh;
struct icmp *icmph;
char *ptop;
unsigned char *ptop;
int mask, len, n, pri, logit, loglen, result;
char logbuf[200];
@ -452,7 +453,9 @@ PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
uh = NULL;
if (logit && loglen < sizeof logbuf) {
if (filter)
if (prefix)
snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s", prefix);
else if (filter)
snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
else
snprintf(logbuf + loglen, sizeof logbuf - loglen, " ");
@ -463,12 +466,14 @@ PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
switch (pip->ip_p) {
case IPPROTO_ICMP:
if (logit && loglen < sizeof logbuf) {
len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *icmph;
icmph = (struct icmp *) ptop;
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
"%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), icmph->icmp_type,
len, nb);
loglen += strlen(logbuf + loglen);
}
break;
@ -484,23 +489,65 @@ PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
pri++;
if (logit && loglen < sizeof logbuf) {
len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *uh;
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
"%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport),
len, nb);
loglen += strlen(logbuf + loglen);
}
if (Enabled(bundle, OPT_FILTERDECAP) &&
ptop[sizeof *uh] == HDLC_ADDR && ptop[sizeof *uh + 1] == HDLC_UI) {
u_short proto;
const char *type;
memcpy(&proto, ptop + sizeof *uh + 2, sizeof proto);
type = NULL;
switch (ntohs(proto)) {
case PROTO_IP:
snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
result = PacketCheck(bundle, ptop + sizeof *uh + 4,
nb - (ptop - cp) - sizeof *uh - 4, filter,
logbuf);
if (result != -2)
return result;
type = "IP";
break;
case PROTO_VJUNCOMP: type = "compressed VJ"; break;
case PROTO_VJCOMP: type = "uncompressed VJ"; break;
case PROTO_MP: type = "Multi-link"; break;
case PROTO_ICOMPD: type = "Individual link CCP"; break;
case PROTO_COMPD: type = "CCP"; break;
case PROTO_IPCP: type = "IPCP"; break;
case PROTO_LCP: type = "LCP"; break;
case PROTO_PAP: type = "PAP"; break;
case PROTO_CBCP: type = "CBCP"; break;
case PROTO_LQR: type = "LQR"; break;
case PROTO_CHAP: type = "CHAP"; break;
}
if (type) {
snprintf(logbuf + loglen, sizeof logbuf - loglen,
" - %s data", type);
loglen += strlen(logbuf + loglen);
}
}
break;
#ifdef IPPROTO_GRE
case IPPROTO_GRE:
if (logit && loglen < sizeof logbuf) {
len = ntohs(pip->ip_len) - (pip->ip_hl << 2);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"GRE: %s ---> ", inet_ntoa(pip->ip_src));
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s", inet_ntoa(pip->ip_dst));
"%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
loglen += strlen(logbuf + loglen);
}
break;
@ -509,11 +556,12 @@ PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
#ifdef IPPROTO_OSPFIGP
case IPPROTO_OSPFIGP:
if (logit && loglen < sizeof logbuf) {
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", inet_ntoa(pip->ip_dst));
"%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
loglen += strlen(logbuf + loglen);
}
break;
@ -586,6 +634,10 @@ PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
}
}
break;
default:
if (prefix)
return -2;
}
if (filter && FilterCheck(pip, filter)) {
@ -637,7 +689,7 @@ ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
}
mbuf_Read(bp, tun.data, nb);
if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in, NULL) < 0)
return NULL;
pip = (struct ip *)tun.data;

View File

@ -27,7 +27,8 @@ struct link;
struct bundle;
extern int ip_PushPacket(struct link *, struct bundle *);
extern int PacketCheck(struct bundle *, char *, int, struct filter *);
extern int PacketCheck(struct bundle *, unsigned char *, int, struct filter *,
const char *);
extern void ip_Enqueue(struct ipcp *, int, char *, int);
extern struct mbuf *ip_Input(struct bundle *, struct link *, struct mbuf *);
extern void ip_DeleteQueue(struct ipcp *);

View File

@ -423,7 +423,7 @@ nat_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
case PKT_ALIAS_IGNORED:
if (log_IsKept(LogTCPIP)) {
log_Printf(LogTCPIP, "NAT engine ignored data:\n");
PacketCheck(bundle, MBUF_CTOP(bp), bp->m_len, NULL);
PacketCheck(bundle, MBUF_CTOP(bp), bp->m_len, NULL, NULL);
}
break;

View File

@ -1654,6 +1654,14 @@ i.e., the default is to allow everything through.
If no rule is matched to a packet, that packet will be discarded
(blocked).
.It
It's possible to filter based on the payload of UDP frames where those
frames contain a
.Em PROTO_IP
.Em PPP
frame header. See the
.Ar filter-decapsulation
option below for further details.
.It
Use
.Dq set filter Ar name No -1
to flush all rules.
@ -2722,6 +2730,30 @@ This option determines if Van Jacobson header compression will be used.
The following options are not actually negotiated with the peer.
Therefore, accepting or denying them makes no sense.
.Bl -tag -width XX
.It filter-decapsulation
Default: Disabled.
When this option is enabled,
.Nm
will examine UDP frames to see if they actually contain a
.Em PPP
frame as their payload. If this is the case, all filters will operate
on the payload rather than the actual packet.
.Pp
This is useful if you want to send PPPoUDP traffic over a
.Em PPP
link, but want that link to do smart things with the real data rather than
the UDP wrapper.
.Pp
The UDP frame payload must not be compressed in any way, otherwise
.Nm
will not be able to interpret it. It's therefore recommended that
you
.Ic disable vj pred1 deflate
and
.Ic deny vj pred1 deflate
in the configuration for the
.Nm
invocation with the udp link.
.It idcheck
Default: Enabled.
When

View File

@ -1654,6 +1654,14 @@ i.e., the default is to allow everything through.
If no rule is matched to a packet, that packet will be discarded
(blocked).
.It
It's possible to filter based on the payload of UDP frames where those
frames contain a
.Em PROTO_IP
.Em PPP
frame header. See the
.Ar filter-decapsulation
option below for further details.
.It
Use
.Dq set filter Ar name No -1
to flush all rules.
@ -2722,6 +2730,30 @@ This option determines if Van Jacobson header compression will be used.
The following options are not actually negotiated with the peer.
Therefore, accepting or denying them makes no sense.
.Bl -tag -width XX
.It filter-decapsulation
Default: Disabled.
When this option is enabled,
.Nm
will examine UDP frames to see if they actually contain a
.Em PPP
frame as their payload. If this is the case, all filters will operate
on the payload rather than the actual packet.
.Pp
This is useful if you want to send PPPoUDP traffic over a
.Em PPP
link, but want that link to do smart things with the real data rather than
the UDP wrapper.
.Pp
The UDP frame payload must not be compressed in any way, otherwise
.Nm
will not be able to interpret it. It's therefore recommended that
you
.Ic disable vj pred1 deflate
and
.Ic deny vj pred1 deflate
in the configuration for the
.Nm
invocation with the udp link.
.It idcheck
Default: Enabled.
When