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.
This commit is contained in:
Brian Feldman 1999-08-01 16:57:24 +00:00
parent 6e7b8c218d
commit 0b6c1a832d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=49350
6 changed files with 184 additions and 23 deletions

View File

@ -1,5 +1,5 @@
.\"
.\" $Id: ipfw.8,v 1.53 1999/06/15 12:56:38 ru Exp $
.\" $Id: ipfw.8,v 1.54 1999/06/19 18:43:18 green Exp $
.\"
.Dd July 20, 1996
.Dt IPFW 8
@ -30,6 +30,12 @@ flush
zero
.Op Ar number ...
.Nm ipfw
.Oo
.Fl q
.Oc
resetlog
.Op Ar number ...
.Nm ipfw
delete
.Ar number ...
.Nm ipfw
@ -49,7 +55,7 @@ show
add
.Op Ar number
.Ar action
.Op log
.Op log Op Ar logamount Ar number
.Ar proto
from
.Ar src
@ -227,6 +233,10 @@ The show command is equivalent to
The zero operation zeroes the counters associated with rule number
.Ar number .
.Pp
The resetlog operation resets the logging counters associated with
rule number
.Ar number .
.Pp
The flush operation removes all rules.
.Pp
Any command beginning with a
@ -265,7 +275,7 @@ Don't ask for confirmation for commands that can cause problems if misused
.Ar Note ,
if there is no tty associated with the process, this is implied.
.It Fl q
While adding, zeroing or flushing, be quiet about actions (implies
While adding, zeroing, resetlogging or flushing, be quiet about actions (implies
.Fl f Ns ).
This is useful for adjusting rules by executing multiple
.Nm
@ -411,15 +421,22 @@ then when a packet matches a rule with the
keyword a message will be printed on the console.
If the kernel was compiled with the
.Dv IPFIREWALL_VERBOSE_LIMIT
option, then logging will cease after the number of packets
specified by the option are received for that particular
chain entry. Logging may then be re-enabled by clearing
the packet counter for that entry.
option, then by default logging will cease after the number
of packets specified by the option are received for that
particular chain entry. However, if
.Ar logamount Ar number
is used, that
.Ar number
will be the default logging limit rather than
.Dv IPFIREWALL_VERBOSE_LIMIT .
Logging may then be re-enabled by clearing the logging counter
or the packet counter for that entry.
.Pp
Console logging and the log limit are adjustable dynamically
through the
.Xr sysctl 8
interface.
interface in the MIB base of
.Dv net.inet.ip.fw .
.Pp
.Ar proto :
.Bl -hang -offset flag -width 1234567890123456

View File

@ -20,13 +20,14 @@
#ifndef lint
static const char rcsid[] =
"$Id: ipfw.c,v 1.70 1999/06/11 09:43:53 ru Exp $";
"$Id: ipfw.c,v 1.71 1999/06/19 18:43:15 green Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/wait.h>
@ -247,8 +248,11 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth)
errx(EX_OSERR, "impossible");
}
if (chain->fw_flg & IP_FW_F_PRN)
if (chain->fw_flg & IP_FW_F_PRN) {
printf(" log");
if (chain->fw_logamount)
printf(" logamount %d", chain->fw_logamount);
}
pe = getprotobynumber(chain->fw_prot);
if (pe)
@ -599,12 +603,13 @@ show_usage(const char *fmt, ...)
" [pipe] list [number ...]\n"
" [pipe] show [number ...]\n"
" zero [number ...]\n"
" resetlog [number ...]\n"
" pipe number config [pipeconfig]\n"
" rule: action proto src dst extras...\n"
" action:\n"
" {allow|permit|accept|pass|deny|drop|reject|unreach code|\n"
" reset|count|skipto num|divert port|tee port|fwd ip|\n"
" pipe num} [log]\n"
" pipe num} [log [logamount count]]\n"
" proto: {ip|tcp|udp|icmp|<number>}\n"
" src: from [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
" dst: to [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
@ -1164,6 +1169,18 @@ add(ac,av)
if (ac && !strncmp(*av,"log",strlen(*av))) {
rule.fw_flg |= IP_FW_F_PRN; av++; ac--;
}
if (ac && !strncmp(*av,"logamount",strlen(*av))) {
if (!(rule.fw_flg & IP_FW_F_PRN))
show_usage("``logamount'' not valid without ``log''");
ac--; av++;
if (!ac)
show_usage("``logamount'' requires argument");
rule.fw_logamount = atoi(*av);
if (rule.fw_logamount <= 0)
show_usage("``logamount'' argument must be greater "
"than 0");
ac--; av++;
}
/* protocol */
if (ac == 0)
@ -1385,6 +1402,17 @@ add(ac,av)
if (rule.fw_nports)
show_usage("can't mix 'frag' and port specifications");
}
if (rule.fw_flg & IP_FW_F_PRN) {
if (!rule.fw_logamount) {
size_t len = sizeof(int);
if (sysctlbyname("net.inet.ip.fw.verbose_limit",
&rule.fw_logamount, &len, NULL, 0) == -1)
errx(1, "sysctlbyname(\"%s\")",
"net.inet.ip.fw.verbose_limit");
}
rule.fw_loghighest = rule.fw_logamount;
}
if (!do_quiet)
show_ipfw(&rule, 10, 10);
@ -1432,6 +1460,45 @@ zero (ac, av)
}
}
static void
resetlog (ac, av)
int ac;
char **av;
{
av++; ac--;
if (!ac) {
/* clear all entries */
if (setsockopt(s,IPPROTO_IP,IP_FW_RESETLOG,NULL,0)<0)
err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_RESETLOG");
if (!do_quiet)
printf("Logging counts reset.\n");
} else {
struct ip_fw rule;
int failed = EX_OK;
memset(&rule, 0, sizeof rule);
while (ac) {
/* Rule number */
if (isdigit(**av)) {
rule.fw_number = atoi(*av); av++; ac--;
if (setsockopt(s, IPPROTO_IP,
IP_FW_RESETLOG, &rule, sizeof rule)) {
warn("rule %u: setsockopt(%s)", rule.fw_number,
"IP_FW_RESETLOG");
failed = EX_UNAVAILABLE;
}
else if (!do_quiet)
printf("Entry %d logging count reset\n",
rule.fw_number);
} else
show_usage("invalid rule number ``%s''", *av);
}
if (failed != EX_OK)
exit(failed);
}
}
static int
ipfw_main(ac,av)
int ac;
@ -1527,6 +1594,8 @@ ipfw_main(ac,av)
}
} else if (!strncmp(*av, "zero", strlen(*av))) {
zero(ac,av);
} else if (!strncmp(*av, "resetlog", strlen(*av))) {
resetlog(ac,av);
} else if (!strncmp(*av, "print", strlen(*av))) {
list(--ac,++av);
} else if (!strncmp(*av, "list", strlen(*av))) {

View File

@ -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 */

View File

@ -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);
}
@ -1107,6 +1114,55 @@ zero_entry(struct ip_fw *frwl)
return (0);
}
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)
{
@ -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
}

View File

@ -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)

View File

@ -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