diff options
author | green <green@FreeBSD.org> | 1999-08-01 16:57:24 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 1999-08-01 16:57:24 +0000 |
commit | d848a791d143dcd43bbfd4243df4fe61c62fac41 (patch) | |
tree | 02d5b553f5f87af777c6d66d6b2b25611e79109b /sys/netinet | |
parent | 7263583ccb568e6d5e6e6d32d6e126a50ea4229d (diff) | |
download | FreeBSD-src-d848a791d143dcd43bbfd4243df4fe61c62fac41.zip FreeBSD-src-d848a791d143dcd43bbfd4243df4fe61c62fac41.tar.gz |
Make ipfw's logging more dynamic. Now, log will use the default limit
_or_ you may specify "log logamount number" to set logging specifically
the rule.
In addition, "ipfw resetlog" has been added, which will reset the
logging counters on any/all rule(s). ipfw resetlog does not affect
the packet/byte counters (as ipfw reset does), and is the only "set"
command that can be run at securelevel >= 3.
This should address complaints about not being able to set logging
amounts, not being able to restart logging at a high securelevel,
and not being able to just reset logging without resetting all of the
counters in a rule.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/in.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_fw.c | 89 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 4 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 3 |
4 files changed, 87 insertions, 12 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 1eebb9a..1838def 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in.h 8.3 (Berkeley) 1/3/94 - * $Id: in.h,v 1.41 1999/05/04 16:20:29 luigi Exp $ + * $Id: in.h,v 1.42 1999/05/08 14:28:52 peter Exp $ */ #ifndef _NETINET_IN_H_ @@ -322,6 +322,7 @@ struct ip_opts { #define IP_FW_FLUSH 52 /* flush firewall rule chain */ #define IP_FW_ZERO 53 /* clear single/all firewall counter(s) */ #define IP_FW_GET 54 /* get entire firewall rule chain */ +#define IP_FW_RESETLOG 55 /* reset logging counters */ #define IP_DUMMYNET_CONFIGURE 60 /* add/configure a dummynet pipe */ #define IP_DUMMYNET_DEL 61 /* delete a dummynet pipe from chain */ diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index a9e8288..5543bdf 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -12,7 +12,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.c,v 1.114 1999/06/19 18:43:28 green Exp $ + * $Id: ip_fw.c,v 1.115 1999/07/28 22:27:27 green Exp $ */ /* @@ -106,6 +106,7 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, static int add_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl)); static int del_entry __P((struct ip_fw_head *chainptr, u_short number)); static int zero_entry __P((struct ip_fw *)); +static int resetlog_entry __P((struct ip_fw *)); static int check_ipfw_struct __P((struct ip_fw *m)); static __inline int iface_match __P((struct ifnet *ifp, union ip_fw_if *ifu, @@ -306,10 +307,11 @@ ipfw_report(struct ip_fw *f, struct ip *ip, struct tcphdr *const tcp = (struct tcphdr *) ((u_int32_t *) ip+ ip->ip_hl); struct udphdr *const udp = (struct udphdr *) ((u_int32_t *) ip+ ip->ip_hl); struct icmp *const icmp = (struct icmp *) ((u_int32_t *) ip + ip->ip_hl); - int count; + u_int64_t count; count = f ? f->fw_pcnt : ++counter; - if (fw_verbose_limit != 0 && count > fw_verbose_limit) + if ((f == NULL && fw_verbose_limit != 0 && count > fw_verbose_limit) || + (f && f->fw_logamount != 0 && count > f->fw_loghighest)) return; /* Print command name */ @@ -409,9 +411,11 @@ ipfw_report(struct ip_fw *f, struct ip *ip, if ((ip->ip_off & IP_OFFMASK)) printf(" Fragment = %d",ip->ip_off & IP_OFFMASK); printf("\n"); - if (fw_verbose_limit != 0 && count == fw_verbose_limit) - printf("ipfw: limit reached on rule #%d\n", - f ? f->fw_number : -1); + if ((f ? f->fw_logamount != 0 : 1) && + count == (f ? f->fw_loghighest : fw_verbose_limit)) + printf("ipfw: limit %d reached on rule #%d\n", + f ? f->fw_logamount : fw_verbose_limit, + f ? f->fw_number : -1); } } @@ -1069,6 +1073,7 @@ zero_entry(struct ip_fw *frwl) s = splnet(); for (fcp = LIST_FIRST(&ip_fw_chain); fcp; fcp = LIST_NEXT(fcp, chain)) { fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0; + fcp->rule->fw_loghighest = fcp->rule->fw_logamount; fcp->rule->timestamp = 0; } splx(s); @@ -1086,6 +1091,8 @@ zero_entry(struct ip_fw *frwl) s = splnet(); while (fcp && frwl->fw_number == fcp->rule->fw_number) { fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0; + fcp->rule->fw_loghighest = + fcp->rule->fw_logamount; fcp->rule->timestamp = 0; fcp = LIST_NEXT(fcp, chain); } @@ -1108,6 +1115,55 @@ zero_entry(struct ip_fw *frwl) } static int +resetlog_entry(struct ip_fw *frwl) +{ + struct ip_fw_chain *fcp; + int s, cleared; + + if (frwl == 0) { + s = splnet(); + for (fcp = LIST_FIRST(&ip_fw_chain); fcp; fcp = LIST_NEXT(fcp, chain)) + fcp->rule->fw_loghighest = fcp->rule->fw_pcnt + + fcp->rule->fw_logamount; + splx(s); + } + else { + cleared = 0; + + /* + * It's possible to insert multiple chain entries with the + * same number, so we don't stop after finding the first + * match if zeroing a specific entry. + */ + for (fcp = LIST_FIRST(&ip_fw_chain); fcp; fcp = LIST_NEXT(fcp, chain)) + if (frwl->fw_number == fcp->rule->fw_number) { + s = splnet(); + while (fcp && frwl->fw_number == fcp->rule->fw_number) { + fcp->rule->fw_loghighest = + fcp->rule->fw_pcnt + + fcp->rule->fw_logamount; + fcp = LIST_NEXT(fcp, chain); + } + splx(s); + cleared = 1; + break; + } + if (!cleared) /* we didn't find any matching rules */ + return (EINVAL); + } + + if (fw_verbose) { + if (frwl) + printf("ipfw: Entry %d logging count reset.\n", + frwl->fw_number); + else + printf("ipfw: All logging counts cleared.\n"); + } + + return (0); +} + +static int check_ipfw_struct(struct ip_fw *frwl) { /* Check for invalid flag bits */ @@ -1241,8 +1297,12 @@ ip_fw_ctl(struct sockopt *sopt) struct ip_fw_chain *fcp; struct ip_fw frwl; - /* Disallow sets in really-really secure mode. */ - if (sopt->sopt_dir == SOPT_SET && securelevel >= 3) + /* + * Disallow sets in really-really secure mode, but still allow + * the logging counters to be reset. + */ + if (sopt->sopt_dir == SOPT_SET && securelevel >= 3 && + sopt->sopt_name != IP_FW_RESETLOG) return (EPERM); error = 0; @@ -1320,6 +1380,17 @@ ip_fw_ctl(struct sockopt *sopt) } break; + case IP_FW_RESETLOG: + if (sopt->sopt_val != 0) { + error = sooptcopyin(sopt, &frwl, sizeof frwl, + sizeof frwl); + if (error || (error = resetlog_entry(&frwl))) + break; + } else { + error = resetlog_entry(0); + } + break; + default: printf("ip_fw_ctl invalid option %d\n", sopt->sopt_name); error = EINVAL ; @@ -1373,7 +1444,7 @@ ip_fw_init(void) if (fw_verbose_limit == 0) printf("unlimited logging\n"); else - printf("logging limited to %d packets/entry\n", + printf("logging limited to %d packets/entry by default\n", fw_verbose_limit); #endif } diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index d858040..958eb67 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -11,7 +11,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.h,v 1.38 1999/06/19 18:43:30 green Exp $ + * $Id: ip_fw.h,v 1.39 1999/07/28 22:22:57 green Exp $ */ #ifndef _IP_FW_H @@ -85,6 +85,8 @@ struct ip_fw { void *next_rule_ptr ; /* next rule in case of match */ uid_t fw_uid; /* uid to match */ gid_t fw_gid; /* gid to match */ + int fw_logamount; /* amount to log */ + u_int64_t fw_loghighest; /* highest number packet to log */ }; #define IP_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f) diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index f94cc09..d8117dd 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 - * $Id: raw_ip.c,v 1.58 1999/04/27 11:17:36 phk Exp $ + * $Id: raw_ip.c,v 1.59 1999/05/03 23:57:30 billf Exp $ */ #include <sys/param.h> @@ -293,6 +293,7 @@ rip_ctloutput(so, sopt) case IP_FW_DEL: case IP_FW_FLUSH: case IP_FW_ZERO: + case IP_FW_RESETLOG: if (ip_fw_ctl_ptr == 0) error = ENOPROTOOPT; else |