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:
parent
f2a2857bb3
commit
0a4b6c5c5c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=62977
@ -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
|
||||
|
@ -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 *);
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user