diff options
author | brian <brian@FreeBSD.org> | 2000-07-11 22:11:36 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 2000-07-11 22:11:36 +0000 |
commit | 7bc7c104eeee992d6a92297317b9f35e89e9096c (patch) | |
tree | df8dd7356dce1ca25dbb18c53c87fd96e8dc3265 /usr.sbin | |
parent | a3d0c189ea25a7af3dfab30112f5d8d65e214e1c (diff) | |
download | FreeBSD-src-7bc7c104eeee992d6a92297317b9f35e89e9096c.zip FreeBSD-src-7bc7c104eeee992d6a92297317b9f35e89e9096c.tar.gz |
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.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ppp/bundle.c | 37 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.h | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/filter.c | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/filter.h | 1 | ||||
-rw-r--r-- | usr.sbin/ppp/ip.c | 395 | ||||
-rw-r--r-- | usr.sbin/ppp/ip.h | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/nat_cmd.c | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8 | 28 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8.m4 | 28 | ||||
-rw-r--r-- | usr.sbin/ppp/tun.h | 5 |
10 files changed, 295 insertions, 212 deletions
diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index a1bcbbf..b6ed5ff 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -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); + + if (secs == 0) + secs = bundle->cfg.idle.timeout; - 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 diff --git a/usr.sbin/ppp/bundle.h b/usr.sbin/ppp/bundle.h index 5f0efc3..3bc6034 100644 --- a/usr.sbin/ppp/bundle.h +++ b/usr.sbin/ppp/bundle.h @@ -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 *); diff --git a/usr.sbin/ppp/filter.c b/usr.sbin/ppp/filter.c index bed986e..3f0293b 100644 --- a/usr.sbin/ppp/filter.c +++ b/usr.sbin/ppp/filter.c @@ -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"); } } diff --git a/usr.sbin/ppp/filter.h b/usr.sbin/ppp/filter.h index 0bfa560..6b452d8 100644 --- a/usr.sbin/ppp/filter.h +++ b/usr.sbin/ppp/filter.h @@ -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 */ diff --git a/usr.sbin/ppp/ip.c b/usr.sbin/ppp/ip.c index 7d2a082..ca87cc9 100644 --- a/usr.sbin/ppp/ip.c +++ b/usr.sbin/ppp/ip.c @@ -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 */ - - 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; + 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; #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 */ - } - - 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)); - } - - 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; - } - } + 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'; + + 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; + } + } } 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; - - 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); - } + 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); + } } } 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; diff --git a/usr.sbin/ppp/ip.h b/usr.sbin/ppp/ip.h index 6ef9872..b393943 100644 --- a/usr.sbin/ppp/ip.h +++ b/usr.sbin/ppp/ip.h @@ -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 *); diff --git a/usr.sbin/ppp/nat_cmd.c b/usr.sbin/ppp/nat_cmd.c index 4024bfe..f5ff49e 100644 --- a/usr.sbin/ppp/nat_cmd.c +++ b/usr.sbin/ppp/nat_cmd.c @@ -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; diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index 3cc6203..d53014d 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -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. diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4 index 3cc6203..d53014d 100644 --- a/usr.sbin/ppp/ppp.8.m4 +++ b/usr.sbin/ppp/ppp.8.m4 @@ -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. diff --git a/usr.sbin/ppp/tun.h b/usr.sbin/ppp/tun.h index f8a8289..06d1ae8 100644 --- a/usr.sbin/ppp/tun.h +++ b/usr.sbin/ppp/tun.h @@ -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]; }; |