Allow a ``timeout secs'' filter option to let specific packet types

effect the idle timer in different ways.

Submitted by: Stefan Esser <se@freebsd.org>

With adjustments by me to document the option in the man page and to
give the same semantics for outgoing traffic as incoming.

I made the style more consistent in ip.c - this should really have
been done as a separate commit.
This commit is contained in:
Brian Somers 2000-07-11 22:11:36 +00:00
parent f2a2857bb3
commit 0a4b6c5c5c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=62977
10 changed files with 290 additions and 207 deletions

View File

@ -222,7 +222,7 @@ bundle_LinkAdded(struct bundle *bundle, struct datalink *dl)
if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL))
!= bundle->phys_type.open && bundle->idle.timer.state == TIMER_STOPPED)
/* We may need to start our idle timer */
bundle_StartIdleTimer(bundle);
bundle_StartIdleTimer(bundle, 0);
}
void
@ -265,7 +265,7 @@ bundle_LayerUp(void *v, struct fsm *fp)
} else if (fp->proto == PROTO_IPCP) {
bundle_CalculateBandwidth(fp->bundle);
time(&bundle->upat);
bundle_StartIdleTimer(bundle);
bundle_StartIdleTimer(bundle, 0);
bundle_Notify(bundle, EX_NORMAL);
mp_CheckAutoloadTimer(&fp->bundle->ncp.mp);
}
@ -519,6 +519,7 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
const fd_set *fdset)
{
struct datalink *dl;
unsigned secs;
if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
descriptor_Read(&bundle->ncp.mp.server.desc, bundle, fdset);
@ -561,7 +562,7 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
bundle->dev.Name, n);
return;
}
if (ntohl(tun.family) != AF_INET)
if (ntohl(tun.header.family) != AF_INET)
/* XXX: Should be maintaining drop/family counts ! */
return;
}
@ -570,7 +571,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, NULL);
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.in, NULL, NULL);
if (pri >= 0) {
n += sz - sizeof tun.data;
write(bundle->dev.fd, data, n);
@ -591,7 +592,7 @@ 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
*/
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.dial, NULL);
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.dial, NULL, NULL);
if (pri >= 0)
bundle_Open(bundle, NULL, PHYS_AUTO, 0);
else
@ -605,9 +606,13 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
return;
}
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.out, NULL);
if (pri >= 0)
ip_Enqueue(&bundle->ncp.ipcp, pri, tun.data, n);
secs = 0;
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.out, NULL, &secs);
if (pri >= 0) {
/* Prepend the number of seconds timeout given in the filter */
tun.header.timeout = secs;
ip_Enqueue(&bundle->ncp.ipcp, pri, (char *)&tun, n + sizeof tun.header);
}
}
}
@ -1246,18 +1251,22 @@ bundle_IdleTimeout(void *v)
* close LCP and link.
*/
void
bundle_StartIdleTimer(struct bundle *bundle)
bundle_StartIdleTimer(struct bundle *bundle, unsigned secs)
{
timer_Stop(&bundle->idle.timer);
if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL)) !=
bundle->phys_type.open && bundle->cfg.idle.timeout) {
int secs;
time_t now = time(NULL);
secs = bundle->cfg.idle.timeout;
if (secs == 0)
secs = bundle->cfg.idle.timeout;
/* We want at least `secs' */
if (bundle->cfg.idle.min_timeout > secs && bundle->upat) {
int up = time(NULL) - bundle->upat;
int up = now - bundle->upat;
if ((long long)bundle->cfg.idle.min_timeout - up > (long long)secs)
/* Only increase from the current `remaining' value */
secs = bundle->cfg.idle.min_timeout - up;
}
bundle->idle.timer.func = bundle_IdleTimeout;
@ -1265,7 +1274,7 @@ bundle_StartIdleTimer(struct bundle *bundle)
bundle->idle.timer.load = secs * SECTICKS;
bundle->idle.timer.arg = bundle;
timer_Start(&bundle->idle.timer);
bundle->idle.done = time(NULL) + secs;
bundle->idle.done = now + secs;
}
}
@ -1276,7 +1285,7 @@ bundle_SetIdleTimer(struct bundle *bundle, int timeout, int min_timeout)
if (min_timeout >= 0)
bundle->cfg.idle.min_timeout = min_timeout;
if (bundle_LinkIsUp(bundle))
bundle_StartIdleTimer(bundle);
bundle_StartIdleTimer(bundle, 0);
}
void

View File

@ -158,7 +158,7 @@ extern void bundle_LinkClosed(struct bundle *, struct datalink *);
extern int bundle_ShowLinks(struct cmdargs const *);
extern int bundle_ShowStatus(struct cmdargs const *);
extern void bundle_StartIdleTimer(struct bundle *);
extern void bundle_StartIdleTimer(struct bundle *, unsigned secs);
extern void bundle_SetIdleTimer(struct bundle *, int, int);
extern void bundle_StopIdleTimer(struct bundle *);
extern int bundle_IsDead(struct bundle *);

View File

@ -468,6 +468,11 @@ Parse(struct ipcp *ipcp, int argc, char const *const *argv,
argv++;
}
if (argc >= 2 && strcmp(argv[argc - 2], "timeout") == 0) {
filterdata.timeout = strtoul(argv[argc - 1], NULL, 10);
argc -= 2;
}
val = 1;
filterdata.f_proto = proto;
@ -587,6 +592,8 @@ doShowFilter(struct filterent *fp, struct prompt *prompt)
if (fp->f_finrst)
prompt_Printf(prompt, " finrst");
}
if (fp->timeout != 0)
prompt_Printf(prompt, " timeout %u", fp->timeout);
prompt_Printf(prompt, "\n");
}
}

View File

@ -75,6 +75,7 @@ struct filterent {
struct in_range f_dst; /* Destination address and mask */
u_short f_srcport; /* Source port, compared with f_srcop */
u_short f_dstport; /* Destination port, compared with f_dstop */
unsigned timeout; /* Keep alive value for passed packet */
};
#define MAXFILTERS 40 /* in each filter set */

View File

@ -139,13 +139,13 @@ PortMatch(int op, u_short pport, u_short rport)
{
switch (op) {
case OP_EQ:
return (pport == rport);
return pport == rport;
case OP_GT:
return (pport > rport);
return pport > rport;
case OP_LT:
return (pport < rport);
return pport < rport;
default:
return (0);
return 0;
}
}
@ -158,7 +158,7 @@ PortMatch(int op, u_short pport, u_short rport)
* must not attempt to over-write it.
*/
static int
FilterCheck(const struct ip *pip, const struct filter *filter)
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) */
@ -172,20 +172,22 @@ FilterCheck(const struct ip *pip, const struct filter *filter)
char dbuff[100];
if (fp->f_action == A_NONE)
return (0); /* No rule is given. Permit this packet */
return 0; /* No rule is given. Permit this packet */
/* Deny any packet fragment that tries to over-write the header.
/*
* Deny any packet fragment that tries to over-write the header.
* Since we no longer have the real header available, punt on the
* largest normal header - 20 bytes for TCP without options, rounded
* up to the next possible fragment boundary. Since the smallest
* `legal' MTU is 576, and the smallest recommended MTU is 296, any
* fragmentation within this range is dubious at best */
* fragmentation within this range is dubious at best
*/
len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
if (len > 0) { /* Not first fragment within datagram */
if (len < (24 >> 3)) /* don't allow fragment to over-write header */
return (1);
return 1;
/* permit fragments on in and out filter */
return (!filter->fragok);
return !filter->fragok;
}
cproto = gotinfo = estab = syn = finrst = didname = 0;
@ -204,142 +206,142 @@ FilterCheck(const struct ip *pip, const struct filter *filter)
match = 0;
if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
fp->f_src.mask.s_addr) &&
!((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
fp->f_dst.mask.s_addr)) {
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 (!gotinfo) {
const char *ptop = (const char *) pip + (pip->ip_hl << 2);
const struct tcphdr *th;
const struct udphdr *uh;
const struct icmp *ih;
int datalen; /* IP datagram length */
if (!gotinfo) {
const char *ptop = (const char *) pip + (pip->ip_hl << 2);
const struct tcphdr *th;
const struct udphdr *uh;
const struct icmp *ih;
int datalen; /* IP datagram length */
datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
switch (pip->ip_p) {
case IPPROTO_ICMP:
cproto = P_ICMP;
if (datalen < 8) /* ICMP must be at least 8 octets */
return (1);
ih = (const struct icmp *) ptop;
sport = ih->icmp_type;
estab = syn = finrst = -1;
if (log_IsKept(LogDEBUG))
snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
break;
case IPPROTO_IGMP:
cproto = P_IGMP;
if (datalen < 8) /* IGMP uses 8-octet messages */
return (1);
estab = syn = finrst = -1;
sport = ntohs(0);
break;
datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
switch (pip->ip_p) {
case IPPROTO_ICMP:
cproto = P_ICMP;
if (datalen < 8) /* ICMP must be at least 8 octets */
return 1;
ih = (const struct icmp *) ptop;
sport = ih->icmp_type;
estab = syn = finrst = -1;
if (log_IsKept(LogDEBUG))
snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
break;
case IPPROTO_IGMP:
cproto = P_IGMP;
if (datalen < 8) /* IGMP uses 8-octet messages */
return 1;
estab = syn = finrst = -1;
sport = ntohs(0);
break;
#ifdef IPPROTO_GRE
case IPPROTO_GRE:
cproto = P_GRE;
if (datalen < 2) /* GRE uses 2-octet+ messages */
return (1);
return 1;
estab = syn = finrst = -1;
sport = ntohs(0);
break;
#endif
#ifdef IPPROTO_OSPFIGP
case IPPROTO_OSPFIGP:
cproto = P_OSPF;
if (datalen < 8) /* IGMP uses 8-octet messages */
return (1);
estab = syn = finrst = -1;
sport = ntohs(0);
break;
case IPPROTO_OSPFIGP:
cproto = P_OSPF;
if (datalen < 8) /* IGMP uses 8-octet messages */
return 1;
estab = syn = finrst = -1;
sport = ntohs(0);
break;
#endif
case IPPROTO_UDP:
case IPPROTO_IPIP:
cproto = P_UDP;
if (datalen < 8) /* UDP header is 8 octets */
return (1);
uh = (const struct udphdr *) ptop;
sport = ntohs(uh->uh_sport);
dport = ntohs(uh->uh_dport);
estab = syn = finrst = -1;
if (log_IsKept(LogDEBUG))
snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
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
* the datagram is too short
*/
if (datalen < 20 || datalen < (th->th_off << 2))
return (1);
sport = ntohs(th->th_sport);
dport = ntohs(th->th_dport);
estab = (th->th_flags & TH_ACK);
syn = (th->th_flags & TH_SYN);
finrst = (th->th_flags & (TH_FIN|TH_RST));
if (log_IsKept(LogDEBUG)) {
if (!estab)
snprintf(dbuff, sizeof dbuff,
"flags = %02x, sport = %d, dport = %d",
th->th_flags, sport, dport);
else
*dbuff = '\0';
}
break;
default:
return (1); /* We'll block unknown type of packet */
}
case IPPROTO_UDP:
case IPPROTO_IPIP:
cproto = P_UDP;
if (datalen < 8) /* UDP header is 8 octets */
return 1;
uh = (const struct udphdr *) ptop;
sport = ntohs(uh->uh_sport);
dport = ntohs(uh->uh_dport);
estab = syn = finrst = -1;
if (log_IsKept(LogDEBUG))
snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
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
* the datagram is too short
*/
if (datalen < 20 || datalen < (th->th_off << 2))
return 1;
sport = ntohs(th->th_sport);
dport = ntohs(th->th_dport);
estab = (th->th_flags & TH_ACK);
syn = (th->th_flags & TH_SYN);
finrst = (th->th_flags & (TH_FIN|TH_RST));
if (log_IsKept(LogDEBUG)) {
if (!estab)
snprintf(dbuff, sizeof dbuff,
"flags = %02x, sport = %d, dport = %d",
th->th_flags, sport, dport);
else
*dbuff = '\0';
}
break;
default:
return 1; /* We'll block unknown type of packet */
}
if (log_IsKept(LogDEBUG)) {
if (estab != -1) {
len = strlen(dbuff);
snprintf(dbuff + len, sizeof dbuff - len,
", estab = %d, syn = %d, finrst = %d",
estab, syn, finrst);
}
log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
filter_Proto2Nam(cproto), dbuff);
}
gotinfo = 1;
}
if (log_IsKept(LogDEBUG)) {
if (fp->f_srcop != OP_NONE) {
snprintf(dbuff, sizeof dbuff, ", src %s %d",
filter_Op2Nam(fp->f_srcop), fp->f_srcport);
len = strlen(dbuff);
} else
len = 0;
if (fp->f_dstop != OP_NONE) {
snprintf(dbuff + len, sizeof dbuff - len,
", dst %s %d", filter_Op2Nam(fp->f_dstop),
fp->f_dstport);
} else if (!len)
*dbuff = '\0';
if (log_IsKept(LogDEBUG)) {
if (estab != -1) {
len = strlen(dbuff);
snprintf(dbuff + len, sizeof dbuff - len,
", estab = %d, syn = %d, finrst = %d",
estab, syn, finrst);
}
log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
filter_Proto2Nam(cproto), dbuff);
}
gotinfo = 1;
}
if (log_IsKept(LogDEBUG)) {
if (fp->f_srcop != OP_NONE) {
snprintf(dbuff, sizeof dbuff, ", src %s %d",
filter_Op2Nam(fp->f_srcop), fp->f_srcport);
len = strlen(dbuff);
} else
len = 0;
if (fp->f_dstop != OP_NONE) {
snprintf(dbuff + len, sizeof dbuff - len,
", dst %s %d", filter_Op2Nam(fp->f_dstop),
fp->f_dstport);
} else if (!len)
*dbuff = '\0';
log_Printf(LogDEBUG, " rule = %d: Address match, "
"check against proto %s%s, action = %s\n",
n, filter_Proto2Nam(fp->f_proto),
dbuff, filter_Action2Nam(fp->f_action));
}
log_Printf(LogDEBUG, " rule = %d: Address match, "
"check against proto %s%s, action = %s\n",
n, filter_Proto2Nam(fp->f_proto),
dbuff, filter_Action2Nam(fp->f_action));
}
if (cproto == fp->f_proto) {
if ((fp->f_srcop == OP_NONE ||
PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
(fp->f_dstop == OP_NONE ||
PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
(fp->f_estab == 0 || estab) &&
(fp->f_syn == 0 || syn) &&
(fp->f_finrst == 0 || finrst)) {
match = 1;
}
}
if (cproto == fp->f_proto) {
if ((fp->f_srcop == OP_NONE ||
PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
(fp->f_dstop == OP_NONE ||
PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
(fp->f_estab == 0 || estab) &&
(fp->f_syn == 0 || syn) &&
(fp->f_finrst == 0 || finrst)) {
match = 1;
}
}
} else {
/* Address is matched and no protocol specified. Make a decision. */
log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
filter_Action2Nam(fp->f_action));
match = 1;
/* Address is matched and no protocol specified. Make a decision. */
log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
filter_Action2Nam(fp->f_action));
match = 1;
}
} else
log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
@ -347,15 +349,20 @@ FilterCheck(const struct ip *pip, const struct filter *filter)
if (match != fp->f_invert) {
/* Take specified action */
if (fp->f_action < A_NONE)
fp = &filter->rule[n = fp->f_action];
fp = &filter->rule[n = fp->f_action];
else
return (fp->f_action != A_PERMIT);
if (fp->f_action == A_PERMIT) {
if (psecs != NULL)
*psecs = fp->timeout;
return 0;
} else
return 1;
} else {
n++;
fp++;
}
}
return (1); /* No rule is mached. Deny this packet */
return 1; /* No rule is mached. Deny this packet */
}
#ifdef notdef
@ -393,7 +400,7 @@ ip_LogDNS(const struct udphdr *uh, const char *direction)
len -= sizeof header;
while (pktptr < (const u_short *)ptr) {
*hptr++ = ntohs(*pktptr); /* Careful of macro side-effects ! */
*hptr++ = ntohs(*pktptr); /* Careful of macro side-effects ! */
pktptr++;
}
@ -431,7 +438,7 @@ ip_LogDNS(const struct udphdr *uh, const char *direction)
*/
int
PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
struct filter *filter, const char *prefix)
struct filter *filter, const char *prefix, unsigned *psecs)
{
static const char *const TcpFlags[] = {
"FIN", "SYN", "RST", "PSH", "ACK", "URG"
@ -469,10 +476,10 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
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);
"ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d (%d/%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);
}
@ -491,11 +498,11 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
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));
"UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport),
len, nb);
"%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport),
len, nb);
loglen += strlen(logbuf + loglen);
}
@ -512,7 +519,7 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
result = PacketCheck(bundle, ptop + sizeof *uh + 4,
nb - (ptop - cp) - sizeof *uh - 4, filter,
logbuf);
logbuf, psecs);
if (result != -2)
return result;
type = "IP";
@ -558,10 +565,10 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
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));
"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);
"%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
loglen += strlen(logbuf + loglen);
}
break;
@ -571,10 +578,11 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
if (logit && loglen < sizeof logbuf) {
uh = (struct udphdr *) ptop;
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
"IPIP: %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", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
loglen += strlen(logbuf + loglen);
}
break;
@ -583,10 +591,11 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
if (logit && loglen < sizeof logbuf) {
uh = (struct udphdr *) ptop;
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
"IGMP: %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", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
loglen += strlen(logbuf + loglen);
}
break;
@ -604,33 +613,33 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
if (logit && loglen < sizeof logbuf) {
len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
"TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
"%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
loglen += strlen(logbuf + loglen);
n = 0;
for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
if (th->th_flags & mask) {
snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
loglen += strlen(logbuf + loglen);
}
n++;
if (th->th_flags & mask) {
snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
loglen += strlen(logbuf + loglen);
}
n++;
}
snprintf(logbuf + loglen, sizeof logbuf - loglen,
" seq:%lx ack:%lx (%d/%d)",
(u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
" seq:%lx ack:%lx (%d/%d)",
(u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
loglen += strlen(logbuf + loglen);
if ((th->th_flags & TH_SYN) && nb > 40) {
u_short *sp;
u_short *sp;
ptop += 20;
sp = (u_short *) ptop;
if (ntohs(sp[0]) == 0x0204) {
snprintf(logbuf + loglen, sizeof logbuf - loglen,
" MSS = %d", ntohs(sp[1]));
loglen += strlen(logbuf + loglen);
}
ptop += 20;
sp = (u_short *) ptop;
if (ntohs(sp[0]) == 0x0204) {
snprintf(logbuf + loglen, sizeof logbuf - loglen,
" MSS = %d", ntohs(sp[1]));
loglen += strlen(logbuf + loglen);
}
}
}
break;
@ -640,7 +649,7 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
return -2;
}
if (filter && FilterCheck(pip, filter)) {
if (filter && FilterCheck(pip, filter, psecs)) {
if (logit)
log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
#ifdef notdef
@ -651,10 +660,23 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
} else {
/* Check Keep Alive filter */
if (logit && log_IsKept(LogTCPIP)) {
if (filter && FilterCheck(pip, &bundle->filter.alive))
unsigned alivesecs;
alivesecs = 0;
if (filter && FilterCheck(pip, &bundle->filter.alive, &alivesecs))
log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
else
log_Printf(LogTCPIP, "%s\n", logbuf);
else if (psecs != NULL) {
if(*psecs == 0)
*psecs = alivesecs;
if (*psecs) {
if (*psecs != alivesecs)
log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n",
logbuf, *psecs, alivesecs);
else
log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs);
} else
log_Printf(LogTCPIP, "%s\n", logbuf);
}
}
result = pri;
}
@ -672,6 +694,7 @@ ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
struct tun_data tun;
struct ip *pip;
char *data;
unsigned secs, alivesecs;
if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
@ -689,17 +712,22 @@ 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, NULL) < 0)
secs = 0;
if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in, NULL, &secs) < 0)
return NULL;
pip = (struct ip *)tun.data;
if (!FilterCheck(pip, &bundle->filter.alive))
bundle_StartIdleTimer(bundle);
alivesecs = 0;
if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) {
if (secs == 0)
secs = alivesecs;
bundle_StartIdleTimer(bundle, secs);
}
ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
if (bundle->dev.header) {
tun.family = htonl(AF_INET);
tun.header.family = htonl(AF_INET);
nb += sizeof tun - sizeof tun.data;
data = (char *)&tun;
} else
@ -770,6 +798,8 @@ ip_PushPacket(struct link *l, struct bundle *bundle)
struct mbuf *bp;
struct ip *pip;
int m_len;
u_int32_t secs = 0;
unsigned alivesecs = 0;
if (ipcp->fsm.state != ST_OPENED)
return 0;
@ -777,11 +807,16 @@ ip_PushPacket(struct link *l, struct bundle *bundle)
queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
do {
if (queue->top) {
bp = m_pullup(m_dequeue(queue));
bp = m_dequeue(queue);
bp = mbuf_Read(bp, &secs, sizeof secs);
bp = m_pullup(bp);
m_len = m_length(bp);
pip = (struct ip *)MBUF_CTOP(bp);
if (!FilterCheck(pip, &bundle->filter.alive))
bundle_StartIdleTimer(bundle);
if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) {
if (secs == 0)
secs = alivesecs;
bundle_StartIdleTimer(bundle, secs);
}
link_PushPacket(l, bp, bundle, 0, PROTO_IP);
ipcp_AddOutOctets(ipcp, m_len);
return 1;

View File

@ -28,7 +28,7 @@ struct bundle;
extern int ip_PushPacket(struct link *, struct bundle *);
extern int PacketCheck(struct bundle *, unsigned char *, int, struct filter *,
const char *);
const char *, unsigned *secs);
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, NULL);
PacketCheck(bundle, MBUF_CTOP(bp), bp->m_len, NULL, NULL, NULL);
}
break;

View File

@ -1541,7 +1541,7 @@ set filter
.Op estab
.Op syn
.Op finrst
.Oc
.Oc Op timeout Ar secs
.Bl -enum
.It
.Ar Name
@ -1644,6 +1644,15 @@ flags are only allowed when
is set to
.Sq tcp ,
and represent the TH_ACK, TH_SYN and TH_FIN or TH_RST TCP flags respectively.
.It
The timeout value adjusts the current idle timeout to at least
.Ar secs
seconds.
If a timeout is given in the alive filter as well as in the in/out
filter, the in/out value is used. If no timeout is given, the default
timeout (set using
.Ic set timeout
and defaulting to 180 seconds) is used.
.El
.Pp
.It
@ -1651,8 +1660,9 @@ Each filter can hold up to 40 rules, starting from rule 0.
The entire rule set is not effective until rule 0 is defined,
i.e., the default is to allow everything through.
.It
If no rule is matched to a packet, that packet will be discarded
(blocked).
If no rule in a defined set of rules matches a packet, that packet will
be discarded (blocked).
If there are no rules in a given filter, the packet will be permitted.
.It
It's possible to filter based on the payload of UDP frames where those
frames contain a
@ -4385,7 +4395,7 @@ as they travel across the link.
.Op estab
.Op syn
.Op finrst
.Oc
.Oc Op timeout Ar secs
.Xc
.Nm
supports four filter sets.
@ -4410,7 +4420,7 @@ filter specifies packets that are allowed out of the machine.
Filtering is done prior to any IP alterations that might be done by the
NAT engine on outgoing packets and after any IP alterations that might
be done by the NAT engine on incoming packets.
By default all filter sets allow all packets to pass.
By default all empty filter sets allow all packets to pass.
Rules are processed in order according to
.Ar rule-no
(unless skipped by specifying a rule number as the
@ -4425,8 +4435,12 @@ and
filters, this means that the packet is dropped.
In the case of
.Em alive
filters it means that the packet will not reset the idle timer and in
the case of
filters it means that the packet will not reset the idle timer (even if
the
.Ar in Ns No / Ns Ar out
filter has a
.Dq timeout
value) and in the case of
.Em dial
filters it means that the packet will not trigger a dial.
A packet failing to trigger a dial will be dropped rather than queued.

View File

@ -1541,7 +1541,7 @@ set filter
.Op estab
.Op syn
.Op finrst
.Oc
.Oc Op timeout Ar secs
.Bl -enum
.It
.Ar Name
@ -1644,6 +1644,15 @@ flags are only allowed when
is set to
.Sq tcp ,
and represent the TH_ACK, TH_SYN and TH_FIN or TH_RST TCP flags respectively.
.It
The timeout value adjusts the current idle timeout to at least
.Ar secs
seconds.
If a timeout is given in the alive filter as well as in the in/out
filter, the in/out value is used. If no timeout is given, the default
timeout (set using
.Ic set timeout
and defaulting to 180 seconds) is used.
.El
.Pp
.It
@ -1651,8 +1660,9 @@ Each filter can hold up to 40 rules, starting from rule 0.
The entire rule set is not effective until rule 0 is defined,
i.e., the default is to allow everything through.
.It
If no rule is matched to a packet, that packet will be discarded
(blocked).
If no rule in a defined set of rules matches a packet, that packet will
be discarded (blocked).
If there are no rules in a given filter, the packet will be permitted.
.It
It's possible to filter based on the payload of UDP frames where those
frames contain a
@ -4385,7 +4395,7 @@ as they travel across the link.
.Op estab
.Op syn
.Op finrst
.Oc
.Oc Op timeout Ar secs
.Xc
.Nm
supports four filter sets.
@ -4410,7 +4420,7 @@ filter specifies packets that are allowed out of the machine.
Filtering is done prior to any IP alterations that might be done by the
NAT engine on outgoing packets and after any IP alterations that might
be done by the NAT engine on incoming packets.
By default all filter sets allow all packets to pass.
By default all empty filter sets allow all packets to pass.
Rules are processed in order according to
.Ar rule-no
(unless skipped by specifying a rule number as the
@ -4425,8 +4435,12 @@ and
filters, this means that the packet is dropped.
In the case of
.Em alive
filters it means that the packet will not reset the idle timer and in
the case of
filters it means that the packet will not reset the idle timer (even if
the
.Ar in Ns No / Ns Ar out
filter has a
.Dq timeout
value) and in the case of
.Em dial
filters it means that the packet will not trigger a dial.
A packet failing to trigger a dial will be dropped rather than queued.

View File

@ -27,7 +27,10 @@
*/
struct tun_data {
u_int32_t family;
union {
u_int32_t family;
u_int32_t timeout;
} header;
u_char data[MAX_MRU];
};