Commit userland part of pf version 3.5 from OpenBSD (OPENBSD_3_5_BASE).
This commit is contained in:
parent
a5725614a7
commit
f60cf9b58b
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authpf.c,v 1.68 2003/08/21 19:13:23 frantzen Exp $ */
|
||||
/* $OpenBSD: authpf.c,v 1.75 2004/01/29 01:55:10 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
|
||||
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pfctl_parser.h>
|
||||
#include <pfctl.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
@ -98,12 +99,6 @@ main(int argc, char *argv[])
|
||||
char *cp;
|
||||
uid_t uid;
|
||||
|
||||
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
|
||||
(long)getpid())) < 0 || n >= sizeof(rulesetname)) {
|
||||
syslog(LOG_ERR, "pid too large for ruleset name");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
config = fopen(PATH_CONFFILE, "r");
|
||||
|
||||
if ((cp = getenv("SSH_TTY")) == NULL) {
|
||||
@ -131,7 +126,6 @@ main(int argc, char *argv[])
|
||||
"cannot determine IP from SSH_CLIENT %s", ipsrc);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* open the pf device */
|
||||
dev = open(PATH_DEVFILE, O_RDWR);
|
||||
if (dev == -1) {
|
||||
@ -160,6 +154,18 @@ main(int argc, char *argv[])
|
||||
goto die;
|
||||
}
|
||||
|
||||
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)",
|
||||
luser, (long)getpid())) < 0 || n >= sizeof(rulesetname)) {
|
||||
syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld",
|
||||
luser, (long)getpid(), (long)getpid());
|
||||
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
|
||||
(long)getpid())) < 0 || n >= sizeof(rulesetname)) {
|
||||
syslog(LOG_ERR, "pid too large for ruleset name");
|
||||
goto die;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Make our entry in /var/authpf as /var/authpf/ipaddr */
|
||||
n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc);
|
||||
if (n < 0 || (u_int)n >= sizeof(pidfile)) {
|
||||
@ -242,15 +248,22 @@ main(int argc, char *argv[])
|
||||
seteuid(getuid());
|
||||
setuid(getuid());
|
||||
|
||||
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser))
|
||||
do_death(0);
|
||||
|
||||
openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
if (config == NULL || read_config(config))
|
||||
do_death(0);
|
||||
|
||||
if (remove_stale_rulesets())
|
||||
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
|
||||
syslog(LOG_INFO, "user %s prohibited", luser);
|
||||
do_death(0);
|
||||
}
|
||||
|
||||
if (config == NULL || read_config(config)) {
|
||||
syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE);
|
||||
do_death(0);
|
||||
}
|
||||
|
||||
if (remove_stale_rulesets()) {
|
||||
syslog(LOG_INFO, "error removing stale rulesets");
|
||||
do_death(0);
|
||||
}
|
||||
|
||||
/* We appear to be making headway, so actually mark our pid */
|
||||
rewind(pidfp);
|
||||
@ -260,7 +273,7 @@ main(int argc, char *argv[])
|
||||
|
||||
if (change_filter(1, luser, ipsrc) == -1) {
|
||||
printf("Unable to modify filters\r\n");
|
||||
do_death(1);
|
||||
do_death(0);
|
||||
}
|
||||
|
||||
signal(SIGTERM, need_death);
|
||||
@ -545,15 +558,20 @@ remove_stale_rulesets(void)
|
||||
mnr = prs.nr;
|
||||
nr = 0;
|
||||
while (nr < mnr) {
|
||||
char *s;
|
||||
char *s, *t;
|
||||
pid_t pid;
|
||||
|
||||
prs.nr = nr;
|
||||
if (ioctl(dev, DIOCGETRULESET, &prs))
|
||||
return (1);
|
||||
errno = 0;
|
||||
pid = strtoul(prs.name, &s, 10);
|
||||
if (!prs.name[0] || errno || *s)
|
||||
if ((t = strchr(prs.name, '(')) == NULL)
|
||||
t = prs.name;
|
||||
else
|
||||
t++;
|
||||
pid = strtoul(t, &s, 10);
|
||||
if (!prs.name[0] || errno ||
|
||||
(*s && (t == prs.name || *s != ')')))
|
||||
return (1);
|
||||
if (kill(pid, 0) && errno != EPERM) {
|
||||
int i;
|
||||
@ -585,14 +603,11 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
{
|
||||
char fn[MAXPATHLEN];
|
||||
FILE *f = NULL;
|
||||
const int action[PF_RULESET_MAX] = { PF_SCRUB,
|
||||
PF_PASS, PF_NAT, PF_BINAT, PF_RDR };
|
||||
struct pfctl pf;
|
||||
struct pfioc_rule pr[PF_RULESET_MAX];
|
||||
struct pfr_buffer t;
|
||||
int i;
|
||||
|
||||
if (luser == NULL || !luser[0] || strlen(luser) >=
|
||||
PF_RULESET_NAME_SIZE || ipsrc == NULL || !ipsrc[0]) {
|
||||
if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
|
||||
syslog(LOG_ERR, "invalid luser/ipsrc");
|
||||
goto error;
|
||||
}
|
||||
@ -624,18 +639,18 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
syslog(LOG_ERR, "unable to load kernel's OS fingerprints");
|
||||
goto error;
|
||||
}
|
||||
|
||||
bzero(&t, sizeof(t));
|
||||
t.pfrb_type = PFRB_TRANS;
|
||||
memset(&pf, 0, sizeof(pf));
|
||||
for (i = 0; i < PF_RULESET_MAX; ++i) {
|
||||
memset(&pr[i], 0, sizeof(pr[i]));
|
||||
pr[i].rule.action = action[i];
|
||||
strlcpy(pr[i].anchor, anchorname, sizeof(pr[i].anchor));
|
||||
strlcpy(pr[i].ruleset, rulesetname, sizeof(pr[i].ruleset));
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr[i])) {
|
||||
syslog(LOG_ERR, "DIOCBEGINRULES %m");
|
||||
if (pfctl_add_trans(&t, i, anchorname, rulesetname)) {
|
||||
syslog(LOG_ERR, "pfctl_add_trans %m");
|
||||
goto error;
|
||||
}
|
||||
pf.prule[i] = &pr[i];
|
||||
}
|
||||
if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) {
|
||||
syslog(LOG_ERR, "DIOCXBEGIN (%s) %m", add?"add":"remove");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
@ -646,6 +661,10 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
}
|
||||
|
||||
pf.dev = dev;
|
||||
pf.trans = &t;
|
||||
pf.anchor = anchorname;
|
||||
pf.ruleset = rulesetname;
|
||||
|
||||
infile = fn;
|
||||
if (parse_rules(f, &pf) < 0) {
|
||||
syslog(LOG_ERR, "syntax error in rule file: "
|
||||
@ -658,16 +677,10 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
f = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < PF_RULESET_MAX; ++i)
|
||||
/*
|
||||
* ignore EINVAL on removal, it means the anchor was
|
||||
* already automatically removed by the kernel.
|
||||
*/
|
||||
if (ioctl(dev, DIOCCOMMITRULES, &pr[i]) &&
|
||||
(add || errno != EINVAL)) {
|
||||
syslog(LOG_ERR, "DIOCCOMMITRULES %m");
|
||||
goto error;
|
||||
}
|
||||
if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) {
|
||||
syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
gettimeofday(&Tstart, NULL);
|
||||
@ -682,6 +695,8 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
error:
|
||||
if (f != NULL)
|
||||
fclose(f);
|
||||
if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0))
|
||||
syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove");
|
||||
|
||||
infile = NULL;
|
||||
return (-1);
|
||||
@ -761,37 +776,44 @@ do_death(int active)
|
||||
int
|
||||
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
||||
{
|
||||
struct pfioc_rule *pr;
|
||||
u_int8_t rs_num;
|
||||
struct pfioc_rule pr;
|
||||
|
||||
switch (r->action) {
|
||||
case PF_PASS:
|
||||
case PF_DROP:
|
||||
pr = pf->prule[PF_RULESET_FILTER];
|
||||
rs_num = PF_RULESET_FILTER;
|
||||
break;
|
||||
case PF_SCRUB:
|
||||
pr = pf->prule[PF_RULESET_SCRUB];
|
||||
rs_num = PF_RULESET_SCRUB;
|
||||
break;
|
||||
case PF_NAT:
|
||||
case PF_NONAT:
|
||||
pr = pf->prule[PF_RULESET_NAT];
|
||||
rs_num = PF_RULESET_NAT;
|
||||
break;
|
||||
case PF_RDR:
|
||||
case PF_NORDR:
|
||||
pr = pf->prule[PF_RULESET_RDR];
|
||||
rs_num = PF_RULESET_RDR;
|
||||
break;
|
||||
case PF_BINAT:
|
||||
case PF_NOBINAT:
|
||||
pr = pf->prule[PF_RULESET_BINAT];
|
||||
rs_num = PF_RULESET_BINAT;
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "invalid rule action %d", r->action);
|
||||
return (1);
|
||||
}
|
||||
|
||||
bzero(&pr, sizeof(pr));
|
||||
strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor));
|
||||
strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset));
|
||||
if (pfctl_add_pool(pf, &r->rpool, r->af))
|
||||
return (1);
|
||||
pr->pool_ticket = pf->paddr.ticket;
|
||||
memcpy(&pr->rule, r, sizeof(pr->rule));
|
||||
if (ioctl(pf->dev, DIOCADDRULE, pr)) {
|
||||
pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
|
||||
pf->ruleset);
|
||||
pr.pool_ticket = pf->paddr.ticket;
|
||||
memcpy(&pr.rule, r, sizeof(pr.rule));
|
||||
if (ioctl(pf->dev, DIOCADDRULE, &pr)) {
|
||||
syslog(LOG_ERR, "DIOCADDRULE %m");
|
||||
return (1);
|
||||
}
|
||||
@ -851,6 +873,13 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
|
||||
{
|
||||
fprintf(stderr, "set hostid not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
||||
{
|
||||
@ -865,6 +894,13 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_debug(struct pfctl *pf, char *d)
|
||||
{
|
||||
fprintf(stderr, "set debug not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
|
||||
@ -875,10 +911,14 @@ pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||
|
||||
int
|
||||
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
||||
char *rulesetname)
|
||||
char *rulesetname, struct pfr_buffer *t)
|
||||
{
|
||||
/* never called, no anchors inside anchors, but we need the stub */
|
||||
fprintf(stderr, "load anchor not supported from authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_print_title(char *title)
|
||||
{
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: ftp-proxy.8,v 1.37 2003/09/05 12:27:47 jmc Exp $
|
||||
.\" $OpenBSD: ftp-proxy.8,v 1.40 2004/03/16 08:50:07 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1996-2001
|
||||
.\" Obtuse Systems Corporation, All rights reserved.
|
||||
@ -38,10 +38,11 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm ftp-proxy
|
||||
.Op Fl AnrVw
|
||||
.Op Fl a Ar address
|
||||
.Op Fl D Ar debuglevel
|
||||
.Op Fl g Ar group
|
||||
.Op Fl m Ar minport
|
||||
.Op Fl M Ar maxport
|
||||
.Op Fl m Ar minport
|
||||
.Op Fl t Ar timeout
|
||||
.Op Fl u Ar user
|
||||
.Sh DESCRIPTION
|
||||
@ -67,6 +68,26 @@ or
|
||||
.Qq anonymous
|
||||
only.
|
||||
Any attempt to log in as another user will be blocked by the proxy.
|
||||
.It Fl a Ar address
|
||||
Specify the local IP address to use in
|
||||
.Xr bind 2
|
||||
as the source for connections made by
|
||||
.Nm ftp-proxy
|
||||
when connecting to destination FTP servers.
|
||||
This may be necessary if the interface address of
|
||||
your default route is not reachable from the destinations
|
||||
.Nm
|
||||
is attempting connections to, or this address is different from the one
|
||||
connections are being NATed to.
|
||||
In the usual case this means that
|
||||
.Ar address
|
||||
should be a publicly visible IP address assigned to one of
|
||||
the interfaces on the machine running
|
||||
.Nm
|
||||
and should be the same address to which you are translating traffic
|
||||
if you are using the
|
||||
.Fl n
|
||||
option.
|
||||
.It Fl D Ar debuglevel
|
||||
Specify a debug level, where the proxy emits verbose debug output
|
||||
into
|
||||
@ -82,14 +103,6 @@ lookups which require root.
|
||||
By default,
|
||||
.Nm
|
||||
uses the default group of the user it drops privilege to.
|
||||
.It Fl m Ar minport
|
||||
Specify the lower end of the port range the proxy will use for all
|
||||
data connections it establishes.
|
||||
The default is
|
||||
.Dv IPPORT_HIFIRSTAUTO
|
||||
defined in
|
||||
.Aq Pa netinet/in.h
|
||||
as 49152.
|
||||
.It Fl M Ar maxport
|
||||
Specify the upper end of the port range the proxy will use for the
|
||||
data connections it establishes.
|
||||
@ -98,6 +111,14 @@ The default is
|
||||
defined in
|
||||
.Aq Pa netinet/in.h
|
||||
as 65535.
|
||||
.It Fl m Ar minport
|
||||
Specify the lower end of the port range the proxy will use for all
|
||||
data connections it establishes.
|
||||
The default is
|
||||
.Dv IPPORT_HIFIRSTAUTO
|
||||
defined in
|
||||
.Aq Pa netinet/in.h
|
||||
as 49152.
|
||||
.It Fl n
|
||||
Activate network address translation
|
||||
.Pq NAT
|
||||
@ -175,8 +196,8 @@ A typical way to do this would be to use a
|
||||
.Xr pf.conf 5
|
||||
rule such as
|
||||
.Bd -literal -offset 2n
|
||||
int_if = xl0
|
||||
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
||||
int_if = \&"xl0\&"
|
||||
rdr pass on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
||||
.Ed
|
||||
.Pp
|
||||
.Xr inetd 8
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ftp-proxy.c,v 1.33 2003/08/22 21:50:34 david Exp $ */
|
||||
/* $OpenBSD: ftp-proxy.c,v 1.35 2004/03/14 21:51:44 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-2001
|
||||
@ -151,6 +151,7 @@ char *Group;
|
||||
|
||||
extern int Debug_Level;
|
||||
extern int Use_Rdns;
|
||||
extern in_addr_t Bind_Addr;
|
||||
extern char *__progname;
|
||||
|
||||
typedef enum {
|
||||
@ -174,9 +175,8 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
syslog(LOG_NOTICE,
|
||||
"usage: %s [-AnrVw] [-D debuglevel] [-g group] %s %s",
|
||||
__progname, "[-m minport] [-M maxport] [-t timeout]",
|
||||
"[-u user]");
|
||||
"usage: %s [-AnrVw] [-a address] [-D debuglevel [-g group]"
|
||||
" [-M maxport] [-m minport] [-t timeout] [-u user]", __progname);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
@ -976,9 +976,18 @@ main(int argc, char *argv[])
|
||||
int use_tcpwrapper = 0;
|
||||
#endif /* LIBWRAP */
|
||||
|
||||
while ((ch = getopt(argc, argv, "D:g:m:M:t:u:AnVwr")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "a:D:g:m:M:t:u:AnVwr")) != -1) {
|
||||
char *p;
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
if (!*optarg)
|
||||
usage();
|
||||
if ((Bind_Addr = inet_addr(optarg)) == INADDR_NONE) {
|
||||
syslog(LOG_NOTICE,
|
||||
"%s: invalid address", optarg);
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
AnonFtpOnly = 1; /* restrict to anon usernames only */
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pf.4,v 1.37 2003/08/28 09:41:22 jmc Exp $
|
||||
.\" $OpenBSD: pf.4,v 1.48 2004/03/27 17:15:30 henning Exp $
|
||||
.\"
|
||||
.\" Copyright (C) 2001, Kjell Wooding. All rights reserved.
|
||||
.\"
|
||||
@ -75,11 +75,7 @@ Stops the packet filter.
|
||||
Starts the ALTQ bandwidth control system.
|
||||
.It Dv DIOCSTOPALTQ
|
||||
Stops the ALTQ bandwidth control system.
|
||||
.It Dv DIOCBEGINADDRS Fa "u_int32_t"
|
||||
Clears the buffer address pool
|
||||
and returns a ticket for subsequent DIOCADDADDR, DIOCADDRULE and
|
||||
DIOCCHANGERULE calls.
|
||||
.It Dv DIOCADDADDR Fa "struct pfioc_pooladdr"
|
||||
.It Dv DIOCBEGINADDRS Fa "struct pfioc_pooladdr"
|
||||
.Bd -literal
|
||||
struct pfioc_pooladdr {
|
||||
u_int32_t action;
|
||||
@ -95,16 +91,17 @@ struct pfioc_pooladdr {
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Clears the buffer address pool
|
||||
and returns a
|
||||
.Va ticket
|
||||
for subsequent DIOCADDADDR, DIOCADDRULE and DIOCCHANGERULE calls.
|
||||
.It Dv DIOCADDADDR Fa "struct pfioc_pooladdr"
|
||||
.Pp
|
||||
Adds pool address
|
||||
.Va addr
|
||||
to the buffer address pool to be used in the following
|
||||
DIOCADDRULE or DIOCCHANGERULE call.
|
||||
All other members of the structure are ignored.
|
||||
.It Dv DIOCBEGINRULES Fa "u_int32_t"
|
||||
Clears the inactive ruleset for the type of rule indicated by
|
||||
.Va rule.action
|
||||
and returns a ticket for subsequent
|
||||
DIOCADDRULE and DIOCCOMMITRULES calls.
|
||||
.It Dv DIOCADDRULE Fa "struct pfioc_rule"
|
||||
.Bd -literal
|
||||
struct pfioc_rule {
|
||||
@ -123,7 +120,7 @@ Adds
|
||||
at the end of the inactive ruleset.
|
||||
Requires
|
||||
.Va ticket
|
||||
obtained through preceding DIOCBEGINRULES call, and
|
||||
obtained through preceding DIOCXBEGIN call, and
|
||||
.Va pool_ticket
|
||||
obtained through DIOCBEGINADDRS call.
|
||||
DIOCADDADDR must also be called if any pool addresses are required.
|
||||
@ -136,26 +133,16 @@ names indicate the anchor and ruleset in which to append the rule.
|
||||
and
|
||||
.Va action
|
||||
are ignored.
|
||||
.It Dv DIOCCOMMITRULES Fa "u_int32_t"
|
||||
Switch inactive to active filter ruleset.
|
||||
Requires
|
||||
.Va ticket .
|
||||
.It Dv DIOCBEGINALTQS Fa "u_int32_t"
|
||||
Clears the inactive list of queues and returns a ticket for subsequent
|
||||
DIOCADDALTQ and DIOCCOMMITALTQS calls.
|
||||
.It Dv DIOCADDALTQ Fa "struct pfioc_altq"
|
||||
Adds
|
||||
.Bd -literal
|
||||
struct pfioc_altq {
|
||||
u_int32_t action;
|
||||
u_int32_t ticket;
|
||||
u_int32_t nr;
|
||||
struct pf_altq altq;
|
||||
};
|
||||
.Ed
|
||||
.It Dv DIOCCOMMITALTQS Fa "u_int32_t"
|
||||
Switch inactive to active list of queues.
|
||||
Requires
|
||||
.Va ticket .
|
||||
.It Dv DIOCGETRULES Fa "struct pfioc_rule"
|
||||
Returns
|
||||
.Va ticket
|
||||
@ -227,8 +214,6 @@ of length
|
||||
.Va nbytes
|
||||
for the queue specified by
|
||||
.Va nr .
|
||||
.It Dv DIOCCLRSTATES
|
||||
Clears the state table.
|
||||
.It Dv DIOCADDSTATE Fa "struct pfioc_state"
|
||||
Adds a state entry.
|
||||
.It Dv DIOCGETSTATE Fa "struct pfioc_state"
|
||||
@ -249,8 +234,16 @@ struct pfioc_state_kill {
|
||||
int psk_proto;
|
||||
struct pf_rule_addr psk_src;
|
||||
struct pf_rule_addr psk_dst;
|
||||
char psk_ifname[IFNAMSIZ];
|
||||
};
|
||||
.Ed
|
||||
.It Dv DIOCCLRSTATES Fa "struct pfioc_state_kill"
|
||||
Clears all states.
|
||||
It works like
|
||||
.Dv DIOCKILLSTATES ,
|
||||
but ignores the psk_af, psk_proto, psk_src and psk_dst fields of the
|
||||
.Fa pfioc_state_kill
|
||||
structure.
|
||||
.It Dv DIOCSETSTATUSIF Fa "struct pfioc_if"
|
||||
.Bd -literal
|
||||
struct pfioc_if {
|
||||
@ -262,14 +255,19 @@ Specifies the interface for which statistics are accumulated.
|
||||
.It Dv DIOCGETSTATUS Fa "struct pf_status"
|
||||
.Bd -literal
|
||||
struct pf_status {
|
||||
u_int64_t counters[PFRES_MAX];
|
||||
u_int64_t fcounters[FCNT_MAX];
|
||||
u_int64_t pcounters[2][2][3];
|
||||
u_int64_t bcounters[2][2];
|
||||
u_int32_t running;
|
||||
u_int32_t states;
|
||||
u_int32_t since;
|
||||
u_int32_t debug;
|
||||
u_int64_t counters[PFRES_MAX];
|
||||
u_int64_t fcounters[FCNT_MAX];
|
||||
u_int64_t scounters[SCNT_MAX];
|
||||
u_int64_t pcounters[2][2][3];
|
||||
u_int64_t bcounters[2][2];
|
||||
u_int64_t stateid;
|
||||
u_int32_t running;
|
||||
u_int32_t states;
|
||||
u_int32_t src_nodes;
|
||||
u_int32_t since;
|
||||
u_int32_t debug;
|
||||
u_int32_t hostid;
|
||||
char ifname[IFNAMSIZ];
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
@ -288,7 +286,7 @@ struct pfioc_natlook {
|
||||
u_int16_t dport;
|
||||
u_int16_t rsport;
|
||||
u_int16_t rdport;
|
||||
u_int8_t af;
|
||||
sa_family_t af;
|
||||
u_int8_t proto;
|
||||
u_int8_t direction;
|
||||
};
|
||||
@ -528,19 +526,6 @@ or deleted by the kernel.
|
||||
Yes, tables can be deleted if one removes the
|
||||
.Va persist
|
||||
flag of an unreferenced table.
|
||||
.It Dv DIOCRINABEGIN Fa "struct pfioc_table"
|
||||
Starts a transaction with the inactive set of tables.
|
||||
Cleans up any leftover from a previously aborted transaction, and returns
|
||||
a new ticket.
|
||||
On exit, pfrio_ndel contains the number of leftover table deleted, and
|
||||
pfrio_ticket contains a valid ticket to use for the following two IOCTLs.
|
||||
.It Dv DIOCRINACOMMIT Fa "struct pfioc_table"
|
||||
Commit the inactive set of tables into the active set.
|
||||
While copying the addresses, do a best effort to keep statistics for
|
||||
addresses present before and after the commit.
|
||||
On entry, io->pfrio_ticket takes a valid ticket.
|
||||
On exit, io->pfrio_nadd and io->pfrio_nchange contain the number of tables
|
||||
added and altered by the commit operation.
|
||||
.It Dv DIOCRINADEFINE Fa "struct pfioc_table"
|
||||
Defines a table in the inactive set.
|
||||
On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size]
|
||||
@ -549,6 +534,46 @@ A valid ticket must also be supplied to pfrio_ticket.
|
||||
On exit, pfrio_nadd contains 0 if the table was already defined in the
|
||||
inactive list, or 1 if a new table has been created.
|
||||
pfrio_naddr contains the number of addresses effectively put in the table.
|
||||
.It Dv DIOCXBEGIN Fa "struct pfioc_trans"
|
||||
.Bd -literal
|
||||
#define PF_RULESET_ALTQ (PF_RULESET_MAX)
|
||||
#define PF_RULESET_TABLE (PF_RULESET_MAX+1)
|
||||
struct pfioc_trans {
|
||||
int size; /* number of elements */
|
||||
int esize; /* size of each element in bytes */
|
||||
struct pfioc_trans_e {
|
||||
int rs_num;
|
||||
char anchor[PF_ANCHOR_NAME_SIZE];
|
||||
char ruleset[PF_RULESET_NAME_SIZE];
|
||||
u_int32_t ticket;
|
||||
} *array;
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Clears all the inactive rulesets specified in the
|
||||
.Fa "struct pfioc_trans_e"
|
||||
array.
|
||||
For each ruleset, a ticket is returned for subsequent "add rule" IOCTLs,
|
||||
as well as for the
|
||||
.Dv DIOCXCOMMIT
|
||||
and
|
||||
.Dv DIOCXROLLBACK
|
||||
calls.
|
||||
.It Dv DIOCXCOMMIT Fa "struct pfioc_trans"
|
||||
Atomically switch a vector of inactive rulesets to the active rulesets.
|
||||
Implemented as a standard 2-phase commit, which will either fail for all
|
||||
rulesets or completely succeed.
|
||||
All tickets need to be valid.
|
||||
Returns
|
||||
.Dv EBUSY
|
||||
if a concurrent process is trying to update some of the same rulesets
|
||||
concurrently.
|
||||
.It Dv DIOCXROLLBACK Fa "struct pfioc_trans"
|
||||
Clean up the kernel by undoing all changes that have taken place on the
|
||||
inactive rulesets since the last
|
||||
.Dv DIOCXBEGIN .
|
||||
.Dv DIOCXROLLBACK
|
||||
will silently ignore rulesets for which the ticket is invalid.
|
||||
.It Dv DIOCFPFLUSH
|
||||
Flush the passive OS fingerprint table.
|
||||
.It Dv DIOCFPADD Fa "struct pf_osfp_ioctl"
|
||||
@ -626,6 +651,115 @@ The rest of the structure members will come back filled.
|
||||
Get the whole list by repeatedly incrementing the
|
||||
.Va fp_getnum
|
||||
number until the ioctl returns EBUSY.
|
||||
.It Dv DIOCGETSRCNODES Fa "struct pfioc_src_nodes"
|
||||
.Bd -literal
|
||||
struct pfioc_src_nodes {
|
||||
int psn_len;
|
||||
union {
|
||||
caddr_t psu_buf;
|
||||
struct pf_src_node *psu_src_nodes;
|
||||
} psn_u;
|
||||
#define psn_buf psn_u.psu_buf
|
||||
#define psn_src_nodes psn_u.psu_src_nodes
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Get the list of source nodes kept by the
|
||||
.Ar sticky-address
|
||||
and
|
||||
.Ar source-track
|
||||
options.
|
||||
The ioctl must be called once with
|
||||
.Va psn_len
|
||||
set to 0.
|
||||
If the ioctl returns without error,
|
||||
.Va psn_len
|
||||
will be set to the size of the buffer required to hold all the
|
||||
.Va pf_src_node
|
||||
structures held in the table.
|
||||
A buffer of this size should then be allocated, and a pointer to this buffer
|
||||
placed in
|
||||
.Va psn_buf .
|
||||
The ioctl must then be called again to fill this buffer with the actual
|
||||
source node data.
|
||||
After the ioctl call
|
||||
.Va psn_len
|
||||
will be set to the length of the buffer actually used.
|
||||
.It Dv DIOCCLRSRCNODES Fa "struct pfioc_table"
|
||||
Clear the tree of source tracking nodes.
|
||||
.It Dv DIOCIGETIFACES Fa "struct pfioc_iface"
|
||||
Gets the list of interfaces and interface drivers known to
|
||||
.Nm .
|
||||
All the IOCTLs that manipulate interfaces
|
||||
use the same structure described below:
|
||||
.Bd -literal
|
||||
struct pfioc_iface {
|
||||
char pfiio_name[IFNAMSIZ];
|
||||
void *pfiio_buffer;
|
||||
int pfiio_esize;
|
||||
int pfiio_size;
|
||||
int pfiio_nzero;
|
||||
int pfiio_flags;
|
||||
};
|
||||
|
||||
#define PFI_FLAG_GROUP 0x0001 /* gets groups of interfaces */
|
||||
#define PFI_FLAG_INSTANCE 0x0002 /* gets single interfaces */
|
||||
#define PFI_FLAG_ALLMASK 0x0003
|
||||
.Ed
|
||||
.Pp
|
||||
If not empty,
|
||||
.Va pfiio_name
|
||||
can be used to restrict the search to a specific interface or driver.
|
||||
.Va pfiio_buffer[pfiio_size]
|
||||
is the user-supplied buffer for returning the data.
|
||||
On entry,
|
||||
.Va pfiio_size
|
||||
represents the number of
|
||||
.Va pfi_if
|
||||
entries that can fit into the buffer.
|
||||
The kernel will replace this value by the real number of entries it wants
|
||||
to return.
|
||||
.Va pfiio_esize
|
||||
should be set to sizeof(struct pfi_if).
|
||||
.Va pfiio_flags
|
||||
should be set to
|
||||
.Dv PFI_FLAG_GROUP , PFI_FLAG_INSTANCE ,
|
||||
or both to tell the kernel to return a group of interfaces
|
||||
(drivers, like "fxp"), real interface instances (like "fxp1") or both.
|
||||
The data is returned in the
|
||||
.Va pfi_if
|
||||
structure described below:
|
||||
.Bd -literal
|
||||
struct pfi_if {
|
||||
char pfif_name[IFNAMSIZ];
|
||||
u_int64_t pfif_packets[2][2][2];
|
||||
u_int64_t pfif_bytes[2][2][2];
|
||||
u_int64_t pfif_addcnt;
|
||||
u_int64_t pfif_delcnt;
|
||||
long pfif_tzero;
|
||||
int pfif_states;
|
||||
int pfif_rules;
|
||||
int pfif_flags;
|
||||
};
|
||||
|
||||
#define PFI_IFLAG_GROUP 0x0001 /* group of interfaces */
|
||||
#define PFI_IFLAG_INSTANCE 0x0002 /* single instance */
|
||||
#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */
|
||||
#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */
|
||||
#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */
|
||||
#define PFI_IFLAG_REFERENCED 0x0080 /* referenced by rules */
|
||||
.Ed
|
||||
.It Dv DIOCICLRISTATS Fa "struct pfioc_iface"
|
||||
Clear the statistics counters of one or more interfaces.
|
||||
.Va pfiio_name
|
||||
and
|
||||
.Va pfrio_flags
|
||||
can be used to select which interfaces need to be cleared.
|
||||
The filtering process is the same as for
|
||||
.Dv DIOCIGETIFACES .
|
||||
.Va pfiio_nzero
|
||||
will be set by the kernel to the number of interfaces and drivers
|
||||
that have been cleared.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The following example demonstrates how to use the DIOCNATLOOK command
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pflog.4,v 1.4 2003/09/22 04:53:15 jmc Exp $
|
||||
.\" $OpenBSD: pflog.4,v 1.7 2004/03/21 19:47:59 miod Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Tobias Weingartner
|
||||
.\" All rights reserved.
|
||||
@ -32,19 +32,20 @@
|
||||
.Nm pflog
|
||||
.Nd packet filter logging interface
|
||||
.Sh SYNOPSIS
|
||||
.Sy device pflog
|
||||
.Cd "device pflog"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm pflog
|
||||
interface is the interface the packet filter,
|
||||
.Xr pf 4 ,
|
||||
copies all the packets to which it has been configured to log.
|
||||
In this way, all logged packets can easily be monitored in real
|
||||
interface is a pseudo-device which makes visible all packets logged by
|
||||
the packet filter,
|
||||
.Xr pf 4 .
|
||||
Logged packets can easily be monitored in real
|
||||
time by invoking
|
||||
.Xr tcpdump 8
|
||||
on the
|
||||
.Nm
|
||||
interface.
|
||||
interface, or stored to disk using
|
||||
.Xr pflogd 8 .
|
||||
.Pp
|
||||
Each packet retrieved on this interface has a header associated
|
||||
with it of length
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pfsync.4,v 1.6 2003/06/06 10:29:41 jmc Exp $
|
||||
.\" $OpenBSD: pfsync.4,v 1.16 2004/03/22 21:04:36 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2002 Michael Shalayeff
|
||||
.\" All rights reserved.
|
||||
@ -32,19 +32,48 @@
|
||||
.Nm pfsync
|
||||
.Nd packet filter states table logging interface
|
||||
.Sh SYNOPSIS
|
||||
.Sy device pfsync
|
||||
.Cd "device pfsync"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm pfsync
|
||||
interface is the interface to the packet filter,
|
||||
.Xr pf 4 ,
|
||||
exposing all the changes to the state table.
|
||||
This allows for both debugging of rulesets and monitoring
|
||||
for changes in the table by invoking
|
||||
.Nm
|
||||
interface is a pseudo-device which exposes certain changes to the state
|
||||
table used by
|
||||
.Xr pf 4 .
|
||||
State changes can be viewed by invoking
|
||||
.Xr tcpdump 8
|
||||
on the
|
||||
.Nm
|
||||
interface.
|
||||
If configured with a physical synchronisation interface,
|
||||
.Nm
|
||||
will also send state changes out on that interface using IP multicast,
|
||||
and insert state changes received on that interface from other systems
|
||||
into the state table.
|
||||
.Pp
|
||||
By default, all local changes to the state table are exposed via
|
||||
.Nm .
|
||||
However, state changes from packets received by
|
||||
.Nm
|
||||
over the network are not rebroadcast.
|
||||
States created by a rule marked with the
|
||||
.Ar no-sync
|
||||
keyword are omitted from the
|
||||
.Nm
|
||||
interface (see
|
||||
.Xr pf.conf 5
|
||||
for details).
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
interface will attempt to collapse multiple updates of the same
|
||||
state into one message where possible.
|
||||
The maximum number of times this can be done before the update is sent out
|
||||
is controlled by the
|
||||
.Ar maxupd
|
||||
to ifconfig.
|
||||
(see
|
||||
.Xr ifconfig 8
|
||||
and the example below for more details)
|
||||
.Pp
|
||||
Each packet retrieved on this interface has a header associated
|
||||
with it of length
|
||||
@ -63,16 +92,133 @@ struct pfsync_header {
|
||||
u_int8_t count;
|
||||
};
|
||||
.Ed
|
||||
.Sh EXAMPLES
|
||||
.Sh NETWORK SYNCHRONISATION
|
||||
States can be synchronised between two or more firewalls using this
|
||||
interface, by specifying a synchronisation interface using
|
||||
.Xr ifconfig 8 .
|
||||
For example, the following command sets fxp0 as the synchronisation
|
||||
interface.
|
||||
.Bd -literal -offset indent
|
||||
# ifconfig pfsync0 up
|
||||
# tcpdump -s1500 -evtni pfsync0
|
||||
# ifconfig pfsync0 syncif fxp0
|
||||
.Ed
|
||||
.Pp
|
||||
State change messages are sent out on the synchronisation
|
||||
interface using IP multicast packets.
|
||||
The protocol is IP protocol 240, PFSYNC, and the multicast group
|
||||
used is 224.0.0.240.
|
||||
.Pp
|
||||
It is important that the synchronisation interface be on a trusted
|
||||
network as there is no authentication on the protocol and it would
|
||||
be trivial to spoof packets which create states, bypassing the pf ruleset.
|
||||
Ideally, this is a network dedicated to pfsync messages,
|
||||
i.e. a crossover cable between two firewalls.
|
||||
.Pp
|
||||
There is a one-to-one correspondence between packets seen by
|
||||
.Xr bpf 4
|
||||
on the
|
||||
.Nm
|
||||
interface, and packets sent out on the synchronisation interface, i.e.\&
|
||||
a packet with 4 state deletion messages on
|
||||
.Nm
|
||||
means that the same 4 deletions were sent out on the synchronisation
|
||||
interface.
|
||||
However, the actual packet contents may differ as the messages
|
||||
sent over the network are "compressed" where possible, containing
|
||||
only the necessary information.
|
||||
.Sh EXAMPLES
|
||||
.Nm
|
||||
and
|
||||
.Xr carp 4
|
||||
can be used together to provide automatic failover of a pair of firewalls
|
||||
configured in parallel.
|
||||
One firewall handles all traffic \- if it dies or
|
||||
is shut down, the second firewall takes over automatically.
|
||||
.Pp
|
||||
Both firewalls in this example have three
|
||||
.Xr sis 4
|
||||
interfaces.
|
||||
sis0 is the external interface, on the 10.0.0.0/24 subnet, sis1 is the
|
||||
internal interface, on the 192.168.0.0/24 subnet, and sis2 is the
|
||||
.Nm
|
||||
interface, using the 192.168.254.0/24 subnet.
|
||||
A crossover cable connects the two firewalls via their sis2 interfaces.
|
||||
On all three interfaces, firewall A uses the .254 address, while firewall B
|
||||
uses .253.
|
||||
The interfaces are configured as follows (firewall A unless otherwise
|
||||
indicated):
|
||||
.Pp
|
||||
.Pa /etc/hostname.sis0 :
|
||||
.Bd -literal -offset indent
|
||||
inet 10.0.0.254 255.255.255.0 NONE
|
||||
.Ed
|
||||
.Pp
|
||||
.Pa /etc/hostname.sis1 :
|
||||
.Bd -literal -offset indent
|
||||
inet 192.168.0.254 255.255.255.0 NONE
|
||||
.Ed
|
||||
.Pp
|
||||
.Pa /etc/hostname.sis2 :
|
||||
.Bd -literal -offset indent
|
||||
inet 192.168.254.254 255.255.255.0 NONE
|
||||
.Ed
|
||||
.Pp
|
||||
.Pa /etc/hostname.carp0 :
|
||||
.Bd -literal -offset indent
|
||||
inet 10.0.0.1 255.255.255.0 10.0.0.255 vhid 1 pass foo
|
||||
.Ed
|
||||
.Pp
|
||||
.Pa /etc/hostname.carp1 :
|
||||
.Bd -literal -offset indent
|
||||
inet 192.168.0.1 255.255.255.0 192.168.0.255 vhid 2 pass bar
|
||||
.Ed
|
||||
.Pp
|
||||
.Pa /etc/hostname.pfsync0 :
|
||||
.Bd -literal -offset indent
|
||||
up syncif sis2
|
||||
.Ed
|
||||
.Pp
|
||||
.Xr pf 4
|
||||
must also be configured to allow
|
||||
.Nm
|
||||
and
|
||||
.Xr carp 4
|
||||
traffic through.
|
||||
The following should be added to the top of
|
||||
.Pa /etc/pf.conf :
|
||||
.Bd -literal -offset indent
|
||||
pass quick on { sis2 } proto pfsync
|
||||
pass on { sis0 sis1 } proto carp keep state
|
||||
.Ed
|
||||
.Pp
|
||||
If it is preferable that one firewall handle the traffic,
|
||||
the
|
||||
.Ar advskew
|
||||
on the backup firewall's
|
||||
.Xr carp 4
|
||||
interfaces should be set to something higher than
|
||||
the primary's.
|
||||
For example, if firewall B is the backup, its
|
||||
.Pa /etc/hostname.carp1
|
||||
would look like this:
|
||||
.Bd -literal -offset indent
|
||||
inet 192.168.0.1 255.255.255.0 192.168.0.255 vhid 2 pass bar \e
|
||||
advskew 100
|
||||
.Ed
|
||||
.Pp
|
||||
The following must also be added to
|
||||
.Pa /etc/sysctl.conf :
|
||||
.Bd -literal -offset indent
|
||||
net.inet.carp.preempt=1
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr bpf 4 ,
|
||||
.Xr inet 4 ,
|
||||
.Xr inet6 4 ,
|
||||
.Xr netintro 4 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr hostname.if 5 ,
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr protocols 5 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr tcpdump 8
|
||||
.Sh HISTORY
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,8 +30,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/endian.h>
|
||||
#include <net/if.h>
|
||||
#define TCPSTATES
|
||||
#include <netinet/tcp_fsm.h>
|
||||
@ -284,8 +288,13 @@ print_state(struct pf_state *s, int opts)
|
||||
printf("\n");
|
||||
}
|
||||
if (opts & PF_OPT_VERBOSE2) {
|
||||
#ifdef __FreeBSD__
|
||||
printf(" id: %016llx creatorid: %08x\n",
|
||||
(long long)be64toh(s->id), ntohl(s->creatorid));
|
||||
#else
|
||||
printf(" id: %016llx creatorid: %08x\n",
|
||||
betoh64(s->id), ntohl(s->creatorid));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* $OpenBSD: pfctl.c,v 1.188 2003/08/29 21:47:36 cedric Exp $ */
|
||||
/* $OpenBSD: pfctl.c,v 1.213 2004/03/20 09:31:42 david Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
* Copyright (c) 2002,2003 Henning Brauer
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -56,6 +57,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include "pfctl_parser.h"
|
||||
#include "pfctl.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define HTONL(x) (x) = htonl((__uint32_t)(x))
|
||||
#endif
|
||||
|
||||
void usage(void);
|
||||
int pfctl_enable(int, int);
|
||||
int pfctl_disable(int, int);
|
||||
@ -63,17 +68,19 @@ int pfctl_clear_stats(int, int);
|
||||
int pfctl_clear_rules(int, int, char *, char *);
|
||||
int pfctl_clear_nat(int, int, char *, char *);
|
||||
int pfctl_clear_altq(int, int);
|
||||
int pfctl_clear_states(int, int);
|
||||
int pfctl_kill_states(int, int);
|
||||
int pfctl_clear_src_nodes(int, int);
|
||||
int pfctl_clear_states(int, const char *, int);
|
||||
int pfctl_kill_states(int, const char *, int);
|
||||
int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
|
||||
char *, char *);
|
||||
char *, char *);
|
||||
void pfctl_print_rule_counters(struct pf_rule *, int);
|
||||
int pfctl_show_rules(int, int, int, char *, char *);
|
||||
int pfctl_show_nat(int, int, char *, char *);
|
||||
int pfctl_show_states(int, u_int8_t, int);
|
||||
int pfctl_show_status(int);
|
||||
int pfctl_show_timeouts(int);
|
||||
int pfctl_show_limits(int);
|
||||
int pfctl_show_src_nodes(int, int);
|
||||
int pfctl_show_states(int, const char *, int);
|
||||
int pfctl_show_status(int, int);
|
||||
int pfctl_show_timeouts(int, int);
|
||||
int pfctl_show_limits(int, int);
|
||||
int pfctl_debug(int, u_int32_t, int);
|
||||
int pfctl_clear_rule_counters(int, int);
|
||||
int pfctl_test_altqsupport(int, int);
|
||||
@ -85,6 +92,8 @@ char *rulesopt;
|
||||
const char *showopt;
|
||||
const char *debugopt;
|
||||
char *anchoropt;
|
||||
char *pf_device = "/dev/pf";
|
||||
char *ifaceopt;
|
||||
char *tableopt;
|
||||
const char *tblcmdopt;
|
||||
int state_killers;
|
||||
@ -93,6 +102,8 @@ int loadopt;
|
||||
int altqsupport;
|
||||
|
||||
int dev = -1;
|
||||
int first_title = 1;
|
||||
int labels = 0;
|
||||
|
||||
const char *infile;
|
||||
|
||||
@ -101,6 +112,7 @@ static const struct {
|
||||
int index;
|
||||
} pf_limits[] = {
|
||||
{ "states", PF_LIMIT_STATES },
|
||||
{ "src-nodes", PF_LIMIT_SRC_NODES },
|
||||
{ "frags", PF_LIMIT_FRAGS },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
@ -159,12 +171,14 @@ static const struct {
|
||||
};
|
||||
|
||||
static const char *clearopt_list[] = {
|
||||
"nat", "queue", "rules", "state", "info", "Tables", "osfp", "all", NULL
|
||||
"nat", "queue", "rules", "Sources",
|
||||
"state", "info", "Tables", "osfp", "all", NULL
|
||||
};
|
||||
|
||||
static const char *showopt_list[] = {
|
||||
"nat", "queue", "rules", "Anchors", "state", "info", "labels",
|
||||
"timeouts", "memory", "Tables", "osfp", "all", NULL
|
||||
"nat", "queue", "rules", "Anchors", "Sources", "state", "info",
|
||||
"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
|
||||
"all", NULL
|
||||
};
|
||||
|
||||
static const char *tblcmdopt_list[] = {
|
||||
@ -182,12 +196,14 @@ usage(void)
|
||||
{
|
||||
extern char *__progname;
|
||||
|
||||
fprintf(stderr, "usage: %s [-AdeghnNqrROvz] ", __progname);
|
||||
fprintf(stderr, "usage: %s [-AdeghNnOqRrvz] ", __progname);
|
||||
fprintf(stderr, "[-a anchor[:ruleset]] [-D macro=value]\n");
|
||||
fprintf(stderr, " ");
|
||||
fprintf(stderr, "[-f file] [-F modifier] [-k host] [-s modifier]\n");
|
||||
fprintf(stderr, "[-F modifier] [-f file] [-i interface] ");
|
||||
fprintf(stderr, "[-k host] [-p device]\n");
|
||||
fprintf(stderr, " ");
|
||||
fprintf(stderr, "[-t table] [-T command [address ...]] [-x level]\n");
|
||||
fprintf(stderr, "[-s modifier] [-T command [address ...]] ");
|
||||
fprintf(stderr, "[-t table] [-x level]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -246,7 +262,7 @@ pfctl_clear_stats(int dev, int opts)
|
||||
int
|
||||
pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
{
|
||||
struct pfioc_rule pr;
|
||||
struct pfr_buffer t;
|
||||
|
||||
if (*anchorname && !*rulesetname) {
|
||||
struct pfioc_ruleset pr;
|
||||
@ -276,19 +292,13 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
fprintf(stderr, "rules cleared\n");
|
||||
return (0);
|
||||
}
|
||||
memset(&pr, 0, sizeof(pr));
|
||||
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
|
||||
memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
|
||||
pr.rule.action = PF_SCRUB;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr))
|
||||
err(1, "DIOCBEGINRULES");
|
||||
else if (ioctl(dev, DIOCCOMMITRULES, &pr))
|
||||
err(1, "DIOCCOMMITRULES");
|
||||
pr.rule.action = PF_PASS;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr))
|
||||
err(1, "DIOCBEGINRULES");
|
||||
else if (ioctl(dev, DIOCCOMMITRULES, &pr))
|
||||
err(1, "DIOCCOMMITRULES");
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.pfrb_type = PFRB_TRANS;
|
||||
if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname, rulesetname) ||
|
||||
pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname, rulesetname) ||
|
||||
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
|
||||
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
|
||||
err(1, "pfctl_clear_rules");
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "rules cleared\n");
|
||||
return (0);
|
||||
@ -297,7 +307,7 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
int
|
||||
pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
{
|
||||
struct pfioc_rule pr;
|
||||
struct pfr_buffer t;
|
||||
|
||||
if (*anchorname && !*rulesetname) {
|
||||
struct pfioc_ruleset pr;
|
||||
@ -327,24 +337,14 @@ pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
fprintf(stderr, "nat cleared\n");
|
||||
return (0);
|
||||
}
|
||||
memset(&pr, 0, sizeof(pr));
|
||||
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
|
||||
memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
|
||||
pr.rule.action = PF_NAT;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr))
|
||||
err(1, "DIOCBEGINRULES");
|
||||
else if (ioctl(dev, DIOCCOMMITRULES, &pr))
|
||||
err(1, "DIOCCOMMITRULES");
|
||||
pr.rule.action = PF_BINAT;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr))
|
||||
err(1, "DIOCBEGINRULES");
|
||||
else if (ioctl(dev, DIOCCOMMITRULES, &pr))
|
||||
err(1, "DIOCCOMMITRULES");
|
||||
pr.rule.action = PF_RDR;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr))
|
||||
err(1, "DIOCBEGINRULES");
|
||||
else if (ioctl(dev, DIOCCOMMITRULES, &pr))
|
||||
err(1, "DIOCCOMMITRULES");
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.pfrb_type = PFRB_TRANS;
|
||||
if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname, rulesetname) ||
|
||||
pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname, rulesetname) ||
|
||||
pfctl_add_trans(&t, PF_RULESET_RDR, anchorname, rulesetname) ||
|
||||
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
|
||||
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
|
||||
err(1, "pfctl_clear_nat");
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "nat cleared\n");
|
||||
return (0);
|
||||
@ -353,32 +353,50 @@ pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
int
|
||||
pfctl_clear_altq(int dev, int opts)
|
||||
{
|
||||
struct pfioc_altq pa;
|
||||
struct pfr_buffer t;
|
||||
|
||||
if (!altqsupport)
|
||||
return (-1);
|
||||
memset(&pa, 0, sizeof(pa));
|
||||
if (ioctl(dev, DIOCBEGINALTQS, &pa.ticket))
|
||||
err(1, "DIOCBEGINALTQS");
|
||||
else if (ioctl(dev, DIOCCOMMITALTQS, &pa.ticket))
|
||||
err(1, "DIOCCOMMITALTQS");
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.pfrb_type = PFRB_TRANS;
|
||||
if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "", "") ||
|
||||
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
|
||||
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
|
||||
err(1, "pfctl_clear_altq");
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "altq cleared\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_clear_states(int dev, int opts)
|
||||
pfctl_clear_src_nodes(int dev, int opts)
|
||||
{
|
||||
if (ioctl(dev, DIOCCLRSTATES))
|
||||
err(1, "DIOCCLRSTATES");
|
||||
if (ioctl(dev, DIOCCLRSRCNODES))
|
||||
err(1, "DIOCCLRSRCNODES");
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "states cleared\n");
|
||||
fprintf(stderr, "source tracking entries cleared\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_kill_states(int dev, int opts)
|
||||
pfctl_clear_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfioc_state_kill psk;
|
||||
|
||||
memset(&psk, 0, sizeof(psk));
|
||||
if (iface != NULL && strlcpy(psk.psk_ifname, iface,
|
||||
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
|
||||
errx(1, "invalid interface: %s", iface);
|
||||
|
||||
if (ioctl(dev, DIOCCLRSTATES, &psk))
|
||||
err(1, "DIOCCLRSTATES");
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "%d states cleared\n", psk.psk_af);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_kill_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfioc_state_kill psk;
|
||||
struct addrinfo *res[2], *resp[2];
|
||||
@ -393,6 +411,9 @@ pfctl_kill_states(int dev, int opts)
|
||||
sizeof(psk.psk_src.addr.v.a.mask));
|
||||
memset(&last_src, 0xff, sizeof(last_src));
|
||||
memset(&last_dst, 0xff, sizeof(last_dst));
|
||||
if (iface != NULL && strlcpy(psk.psk_ifname, iface,
|
||||
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
|
||||
errx(1, "invalid interface: %s", iface);
|
||||
|
||||
if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
|
||||
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
|
||||
@ -426,7 +447,8 @@ pfctl_kill_states(int dev, int opts)
|
||||
memset(&last_dst, 0xff, sizeof(last_dst));
|
||||
if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
|
||||
&res[1]))) {
|
||||
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
|
||||
errx(1, "getaddrinfo: %s",
|
||||
gai_strerror(ret_ga));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
for (resp[1] = res[1]; resp[1];
|
||||
@ -557,12 +579,21 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts)
|
||||
(unsigned long long)rule->bytes, rule->states);
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_print_title(char *title)
|
||||
{
|
||||
if (!first_title)
|
||||
printf("\n");
|
||||
first_title = 0;
|
||||
printf("%s\n", title);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
||||
char *rulesetname)
|
||||
{
|
||||
struct pfioc_rule pr;
|
||||
u_int32_t nr, mnr;
|
||||
u_int32_t nr, mnr, header = 0;
|
||||
int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
|
||||
|
||||
if (*anchorname && !*rulesetname) {
|
||||
@ -579,6 +610,8 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
||||
err(1, "DIOCGETRULESETS");
|
||||
return (-1);
|
||||
}
|
||||
if (opts & PF_OPT_SHOWALL && pr.nr)
|
||||
pfctl_print_title("FILTER RULES:");
|
||||
mnr = pr.nr;
|
||||
for (nr = 0; nr < mnr; ++nr) {
|
||||
pr.nr = nr;
|
||||
@ -595,11 +628,25 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
||||
memset(&pr, 0, sizeof(pr));
|
||||
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
|
||||
memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
|
||||
if (opts & PF_OPT_SHOWALL) {
|
||||
pr.rule.action = PF_PASS;
|
||||
if (ioctl(dev, DIOCGETRULES, &pr)) {
|
||||
warn("DIOCGETRULES");
|
||||
return (-1);
|
||||
}
|
||||
header++;
|
||||
}
|
||||
pr.rule.action = PF_SCRUB;
|
||||
if (ioctl(dev, DIOCGETRULES, &pr)) {
|
||||
warn("DIOCGETRULES");
|
||||
return (-1);
|
||||
}
|
||||
if (opts & PF_OPT_SHOWALL) {
|
||||
if (format == 0 && (pr.nr > 0 || header))
|
||||
pfctl_print_title("FILTER RULES:");
|
||||
else if (format == 1 && labels)
|
||||
pfctl_print_title("LABEL COUNTERS:");
|
||||
}
|
||||
mnr = pr.nr;
|
||||
for (nr = 0; nr < mnr; ++nr) {
|
||||
pr.nr = nr;
|
||||
@ -623,6 +670,8 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
|
||||
labels = 1;
|
||||
print_rule(&pr.rule, rule_numbers);
|
||||
pfctl_print_rule_counters(&pr.rule, opts);
|
||||
}
|
||||
@ -656,6 +705,8 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
|
||||
labels = 1;
|
||||
print_rule(&pr.rule, rule_numbers);
|
||||
pfctl_print_rule_counters(&pr.rule, opts);
|
||||
}
|
||||
@ -670,7 +721,7 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
struct pfioc_rule pr;
|
||||
u_int32_t mnr, nr;
|
||||
static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
|
||||
int i;
|
||||
int i, dotitle = opts & PF_OPT_SHOWALL;
|
||||
|
||||
if (*anchorname && !*rulesetname) {
|
||||
struct pfioc_ruleset pr;
|
||||
@ -718,6 +769,10 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
pr.ticket, nattype[i], anchorname,
|
||||
rulesetname) != 0)
|
||||
return (-1);
|
||||
if (dotitle) {
|
||||
pfctl_print_title("TRANSLATION RULES:");
|
||||
dotitle = 0;
|
||||
}
|
||||
print_rule(&pr.rule, opts & PF_OPT_VERBOSE2);
|
||||
pfctl_print_rule_counters(&pr.rule, opts);
|
||||
pfctl_clear_pool(&pr.rule.rpool);
|
||||
@ -727,21 +782,64 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_states(int dev, u_int8_t proto, int opts)
|
||||
pfctl_show_src_nodes(int dev, int opts)
|
||||
{
|
||||
struct pfioc_src_nodes psn;
|
||||
struct pf_src_node *p;
|
||||
char *inbuf = NULL, *newinbuf = NULL;
|
||||
unsigned len = 0;
|
||||
int i;
|
||||
|
||||
memset(&psn, 0, sizeof(psn));
|
||||
for (;;) {
|
||||
psn.psn_len = len;
|
||||
if (len) {
|
||||
newinbuf = realloc(inbuf, len);
|
||||
if (newinbuf == NULL)
|
||||
err(1, "realloc");
|
||||
psn.psn_buf = inbuf = newinbuf;
|
||||
}
|
||||
if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) {
|
||||
warn("DIOCGETSRCNODES");
|
||||
return (-1);
|
||||
}
|
||||
if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
|
||||
break;
|
||||
if (len == 0 && psn.psn_len == 0)
|
||||
return (0);
|
||||
if (len == 0 && psn.psn_len != 0)
|
||||
len = psn.psn_len;
|
||||
if (psn.psn_len == 0)
|
||||
return (0); /* no src_nodes */
|
||||
len *= 2;
|
||||
}
|
||||
p = psn.psn_src_nodes;
|
||||
if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL))
|
||||
pfctl_print_title("SOURCE TRACKING NODES:");
|
||||
for (i = 0; i < psn.psn_len; i += sizeof(*p)) {
|
||||
print_src_node(p, opts);
|
||||
p++;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfioc_states ps;
|
||||
struct pf_state *p;
|
||||
char *inbuf = NULL;
|
||||
char *inbuf = NULL, *newinbuf = NULL;
|
||||
unsigned len = 0;
|
||||
int i;
|
||||
int i, dotitle = (opts & PF_OPT_SHOWALL);
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
for (;;) {
|
||||
ps.ps_len = len;
|
||||
if (len) {
|
||||
ps.ps_buf = inbuf = realloc(inbuf, len);
|
||||
if (inbuf == NULL)
|
||||
newinbuf = realloc(inbuf, len);
|
||||
if (newinbuf == NULL)
|
||||
err(1, "realloc");
|
||||
ps.ps_buf = inbuf = newinbuf;
|
||||
}
|
||||
if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
|
||||
warn("DIOCGETSTATES");
|
||||
@ -758,16 +856,20 @@ pfctl_show_states(int dev, u_int8_t proto, int opts)
|
||||
len *= 2;
|
||||
}
|
||||
p = ps.ps_states;
|
||||
for (i = 0; i < ps.ps_len; i += sizeof(*p)) {
|
||||
if (!proto || (p->proto == proto))
|
||||
print_state(p, opts);
|
||||
p++;
|
||||
for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
|
||||
if (iface != NULL && strcmp(p->u.ifname, iface))
|
||||
continue;
|
||||
if (dotitle) {
|
||||
pfctl_print_title("STATES:");
|
||||
dotitle = 0;
|
||||
}
|
||||
print_state(p, opts);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_status(int dev)
|
||||
pfctl_show_status(int dev, int opts)
|
||||
{
|
||||
struct pf_status status;
|
||||
|
||||
@ -775,16 +877,20 @@ pfctl_show_status(int dev)
|
||||
warn("DIOCGETSTATUS");
|
||||
return (-1);
|
||||
}
|
||||
print_status(&status);
|
||||
if (opts & PF_OPT_SHOWALL)
|
||||
pfctl_print_title("INFO:");
|
||||
print_status(&status, opts);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_timeouts(int dev)
|
||||
pfctl_show_timeouts(int dev, int opts)
|
||||
{
|
||||
struct pfioc_tm pt;
|
||||
int i;
|
||||
|
||||
if (opts & PF_OPT_SHOWALL)
|
||||
pfctl_print_title("TIMEOUTS:");
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
for (i = 0; pf_timeouts[i].name; i++) {
|
||||
pt.timeout = pf_timeouts[i].timeout;
|
||||
@ -802,14 +908,16 @@ pfctl_show_timeouts(int dev)
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_limits(int dev)
|
||||
pfctl_show_limits(int dev, int opts)
|
||||
{
|
||||
struct pfioc_limit pl;
|
||||
int i;
|
||||
|
||||
if (opts & PF_OPT_SHOWALL)
|
||||
pfctl_print_title("LIMITS:");
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
for (i = 0; pf_limits[i].name; i++) {
|
||||
pl.index = i;
|
||||
pl.index = pf_limits[i].index;
|
||||
if (ioctl(dev, DIOCGETLIMIT, &pl))
|
||||
err(1, "DIOCGETLIMIT");
|
||||
printf("%-10s ", pf_limits[i].name);
|
||||
@ -846,7 +954,8 @@ pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
|
||||
int
|
||||
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
||||
{
|
||||
u_int8_t rs_num;
|
||||
u_int8_t rs_num;
|
||||
struct pfioc_rule pr;
|
||||
|
||||
switch (r->action) {
|
||||
case PF_SCRUB:
|
||||
@ -884,12 +993,19 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
||||
}
|
||||
|
||||
if ((pf->opts & PF_OPT_NOACTION) == 0) {
|
||||
bzero(&pr, sizeof(pr));
|
||||
if (strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)) >=
|
||||
sizeof(pr.anchor) ||
|
||||
strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset)) >=
|
||||
sizeof(pr.ruleset))
|
||||
errx(1, "pfctl_add_rule: strlcpy");
|
||||
if (pfctl_add_pool(pf, &r->rpool, r->af))
|
||||
return (1);
|
||||
memcpy(&pf->prule[rs_num]->rule, r,
|
||||
sizeof(pf->prule[rs_num]->rule));
|
||||
pf->prule[rs_num]->pool_ticket = pf->paddr.ticket;
|
||||
if (ioctl(pf->dev, DIOCADDRULE, pf->prule[rs_num]))
|
||||
pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
|
||||
pf->ruleset);
|
||||
pr.pool_ticket = pf->paddr.ticket;
|
||||
memcpy(&pr.rule, r, sizeof(pr.rule));
|
||||
if (ioctl(pf->dev, DIOCADDRULE, &pr))
|
||||
err(1, "DIOCADDRULE");
|
||||
}
|
||||
if (pf->opts & PF_OPT_VERBOSE)
|
||||
@ -922,26 +1038,31 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
|
||||
|
||||
int
|
||||
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
||||
char *rulesetname)
|
||||
char *rulesetname, struct pfr_buffer *trans)
|
||||
{
|
||||
#define ERR(x) do { warn(x); goto _error; } while(0)
|
||||
#define ERRX(x) do { warnx(x); goto _error; } while(0)
|
||||
|
||||
FILE *fin;
|
||||
struct pfioc_rule pr[PF_RULESET_MAX];
|
||||
struct pfioc_altq pa;
|
||||
struct pfctl pf;
|
||||
struct pfr_table trs;
|
||||
int i;
|
||||
FILE *fin;
|
||||
struct pfr_buffer *t, buf;
|
||||
struct pfioc_altq pa;
|
||||
struct pfctl pf;
|
||||
struct pfr_table trs;
|
||||
int osize;
|
||||
|
||||
if (trans == NULL) {
|
||||
bzero(&buf, sizeof(buf));
|
||||
buf.pfrb_type = PFRB_TRANS;
|
||||
t = &buf;
|
||||
osize = 0;
|
||||
} else {
|
||||
t = trans;
|
||||
osize = t->pfrb_size;
|
||||
}
|
||||
|
||||
memset(&pa, 0, sizeof(pa));
|
||||
memset(&pf, 0, sizeof(pf));
|
||||
memset(&trs, 0, sizeof(trs));
|
||||
for (i = 0; i < PF_RULESET_MAX; i++) {
|
||||
memset(&pr[i], 0, sizeof(pr[i]));
|
||||
memcpy(pr[i].anchor, anchorname, sizeof(pr[i].anchor));
|
||||
memcpy(pr[i].ruleset, rulesetname, sizeof(pr[i].ruleset));
|
||||
}
|
||||
if (strlcpy(trs.pfrt_anchor, anchorname,
|
||||
sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) ||
|
||||
strlcpy(trs.pfrt_ruleset, rulesetname,
|
||||
@ -957,46 +1078,53 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
||||
}
|
||||
infile = filename;
|
||||
}
|
||||
if ((opts & PF_OPT_NOACTION) == 0) {
|
||||
if ((loadopt & PFCTL_FLAG_NAT) != 0) {
|
||||
pr[PF_RULESET_NAT].rule.action = PF_NAT;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_NAT]))
|
||||
ERR("DIOCBEGINRULES");
|
||||
pr[PF_RULESET_RDR].rule.action = PF_RDR;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_RDR]))
|
||||
ERR("DIOCBEGINRULES");
|
||||
pr[PF_RULESET_BINAT].rule.action = PF_BINAT;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_BINAT]))
|
||||
ERR("DIOCBEGINRULES");
|
||||
}
|
||||
if (((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) &&
|
||||
ioctl(dev, DIOCBEGINALTQS, &pa.ticket)) {
|
||||
ERR("DIOCBEGINALTQS");
|
||||
}
|
||||
if ((loadopt & PFCTL_FLAG_FILTER) != 0) {
|
||||
pr[PF_RULESET_SCRUB].rule.action = PF_SCRUB;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_SCRUB]))
|
||||
ERR("DIOCBEGINRULES");
|
||||
pr[PF_RULESET_FILTER].rule.action = PF_PASS;
|
||||
if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_FILTER]))
|
||||
ERR("DIOCBEGINRULES");
|
||||
}
|
||||
if (loadopt & PFCTL_FLAG_TABLE) {
|
||||
if (pfr_ina_begin(&trs, &pf.tticket, NULL, 0) != 0)
|
||||
ERR("begin table");
|
||||
}
|
||||
}
|
||||
/* fill in callback data */
|
||||
pf.dev = dev;
|
||||
pf.opts = opts;
|
||||
pf.loadopt = loadopt;
|
||||
if (anchorname[0])
|
||||
pf.loadopt &= ~PFCTL_FLAG_ALTQ;
|
||||
pf.paltq = &pa;
|
||||
for (i = 0; i < PF_RULESET_MAX; i++) {
|
||||
pf.prule[i] = &pr[i];
|
||||
}
|
||||
pf.trans = t;
|
||||
pf.rule_nr = 0;
|
||||
pf.anchor = anchorname;
|
||||
pf.ruleset = rulesetname;
|
||||
|
||||
if ((opts & PF_OPT_NOACTION) == 0) {
|
||||
if ((pf.loadopt & PFCTL_FLAG_NAT) != 0) {
|
||||
if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname,
|
||||
rulesetname) ||
|
||||
pfctl_add_trans(t, PF_RULESET_BINAT, anchorname,
|
||||
rulesetname) ||
|
||||
pfctl_add_trans(t, PF_RULESET_RDR, anchorname,
|
||||
rulesetname))
|
||||
ERR("pfctl_rules");
|
||||
}
|
||||
if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) {
|
||||
if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname,
|
||||
rulesetname))
|
||||
ERR("pfctl_rules");
|
||||
}
|
||||
if ((pf.loadopt & PFCTL_FLAG_FILTER) != 0) {
|
||||
if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname,
|
||||
rulesetname) ||
|
||||
pfctl_add_trans(t, PF_RULESET_FILTER, anchorname,
|
||||
rulesetname))
|
||||
ERR("pfctl_rules");
|
||||
}
|
||||
if (pf.loadopt & PFCTL_FLAG_TABLE) {
|
||||
if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname,
|
||||
rulesetname))
|
||||
ERR("pfctl_rules");
|
||||
}
|
||||
if (pfctl_trans(dev, t, DIOCXBEGIN, osize))
|
||||
ERR("DIOCXBEGIN");
|
||||
if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
|
||||
pa.ticket = pfctl_get_ticket(t, PF_RULESET_ALTQ,
|
||||
anchorname, rulesetname);
|
||||
if (pf.loadopt & PFCTL_FLAG_TABLE)
|
||||
pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE,
|
||||
anchorname, rulesetname);
|
||||
}
|
||||
if (parse_rules(fin, &pf) < 0) {
|
||||
if ((opts & PF_OPT_NOACTION) == 0)
|
||||
ERRX("Syntax error in config file: "
|
||||
@ -1004,57 +1132,30 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
||||
else
|
||||
goto _error;
|
||||
}
|
||||
if ((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0))
|
||||
if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
|
||||
if (check_commit_altq(dev, opts) != 0)
|
||||
ERRX("errors in altq config");
|
||||
if ((opts & PF_OPT_NOACTION) == 0) {
|
||||
if ((loadopt & PFCTL_FLAG_NAT) != 0) {
|
||||
pr[PF_RULESET_NAT].rule.action = PF_NAT;
|
||||
if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_NAT]) &&
|
||||
(errno != EINVAL || pf.rule_nr))
|
||||
ERR("DIOCCOMMITRULES NAT");
|
||||
pr[PF_RULESET_RDR].rule.action = PF_RDR;
|
||||
if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_RDR]) &&
|
||||
(errno != EINVAL || pf.rule_nr))
|
||||
ERR("DIOCCOMMITRULES RDR");
|
||||
pr[PF_RULESET_BINAT].rule.action = PF_BINAT;
|
||||
if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_BINAT]) &&
|
||||
(errno != EINVAL || pf.rule_nr))
|
||||
ERR("DIOCCOMMITRULES BINAT");
|
||||
}
|
||||
if (((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) &&
|
||||
ioctl(dev, DIOCCOMMITALTQS, &pa.ticket))
|
||||
ERR("DIOCCOMMITALTQS");
|
||||
if ((loadopt & PFCTL_FLAG_FILTER) != 0) {
|
||||
pr[PF_RULESET_SCRUB].rule.action = PF_SCRUB;
|
||||
if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_SCRUB]) &&
|
||||
(errno != EINVAL || pf.rule_nr))
|
||||
ERR("DIOCCOMMITRULES SCRUB");
|
||||
pr[PF_RULESET_FILTER].rule.action = PF_PASS;
|
||||
if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_FILTER]) &&
|
||||
(errno != EINVAL || pf.rule_nr))
|
||||
ERR("DIOCCOMMITRULES FILTER");
|
||||
}
|
||||
if (loadopt & PFCTL_FLAG_TABLE) {
|
||||
if (pfr_ina_commit(&trs, pf.tticket, NULL, NULL, 0))
|
||||
ERR("commit table");
|
||||
pf.tdirty = 0;
|
||||
}
|
||||
}
|
||||
if (fin != stdin)
|
||||
fclose(fin);
|
||||
|
||||
/* process "load anchor" directives */
|
||||
if (!anchorname[0] && !rulesetname[0])
|
||||
if (pfctl_load_anchors(dev, opts) == -1)
|
||||
if (pfctl_load_anchors(dev, opts, t) == -1)
|
||||
ERRX("load anchors");
|
||||
|
||||
if (trans == NULL && (opts & PF_OPT_NOACTION) == 0)
|
||||
if (pfctl_trans(dev, t, DIOCXCOMMIT, 0))
|
||||
ERR("DIOCXCOMMIT");
|
||||
return (0);
|
||||
|
||||
_error:
|
||||
if (pf.tdirty) /* cleanup kernel leftover */
|
||||
pfr_ina_begin(&trs, NULL, NULL, 0);
|
||||
exit(1);
|
||||
if (trans == NULL) { /* main ruleset */
|
||||
if ((opts & PF_OPT_NOACTION) == 0)
|
||||
if (pfctl_trans(dev, t, DIOCXROLLBACK, 0))
|
||||
err(1, "DIOCXROLLBACK");
|
||||
exit(1);
|
||||
} else /* sub ruleset */
|
||||
return (-1);
|
||||
|
||||
#undef ERR
|
||||
#undef ERRX
|
||||
@ -1072,7 +1173,7 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
for (i = 0; pf_limits[i].name; i++) {
|
||||
if (strcasecmp(opt, pf_limits[i].name) == 0) {
|
||||
pl.index = i;
|
||||
pl.index = pf_limits[i].index;
|
||||
pl.limit = limit;
|
||||
if ((pf->opts & PF_OPT_NOACTION) == 0) {
|
||||
if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
|
||||
@ -1190,6 +1291,55 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
|
||||
{
|
||||
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
|
||||
return (0);
|
||||
|
||||
HTONL(hostid);
|
||||
|
||||
if ((pf->opts & PF_OPT_NOACTION) == 0)
|
||||
if (ioctl(dev, DIOCSETHOSTID, &hostid))
|
||||
err(1, "DIOCSETHOSTID");
|
||||
|
||||
if (pf->opts & PF_OPT_VERBOSE)
|
||||
printf("set hostid 0x%08x\n", ntohl(hostid));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_debug(struct pfctl *pf, char *d)
|
||||
{
|
||||
u_int32_t level;
|
||||
|
||||
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
|
||||
return (0);
|
||||
|
||||
if (!strcmp(d, "none"))
|
||||
level = PF_DEBUG_NONE;
|
||||
else if (!strcmp(d, "urgent"))
|
||||
level = PF_DEBUG_URGENT;
|
||||
else if (!strcmp(d, "misc"))
|
||||
level = PF_DEBUG_MISC;
|
||||
else if (!strcmp(d, "loud"))
|
||||
level = PF_DEBUG_NOISY;
|
||||
else {
|
||||
warnx("unknown debug level \"%s\"", d);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((pf->opts & PF_OPT_NOACTION) == 0)
|
||||
if (ioctl(dev, DIOCSETDEBUG, &level))
|
||||
err(1, "DIOCSETDEBUG");
|
||||
|
||||
if (pf->opts & PF_OPT_VERBOSE)
|
||||
printf("set debug %s\n", d);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_debug(int dev, u_int32_t level, int opts)
|
||||
{
|
||||
@ -1264,14 +1414,15 @@ pfctl_show_anchors(int dev, int opts, char *anchorname)
|
||||
return (-1);
|
||||
}
|
||||
mnr = pa.nr;
|
||||
if (!(opts & PF_OPT_QUIET))
|
||||
printf("%u anchors:\n", mnr);
|
||||
for (nr = 0; nr < mnr; ++nr) {
|
||||
pa.nr = nr;
|
||||
if (ioctl(dev, DIOCGETANCHOR, &pa)) {
|
||||
warn("DIOCGETANCHOR");
|
||||
return (-1);
|
||||
}
|
||||
if (!(opts & PF_OPT_VERBOSE) &&
|
||||
!strcmp(pa.name, PF_RESERVED_ANCHOR))
|
||||
continue;
|
||||
printf(" %s\n", pa.name);
|
||||
}
|
||||
} else {
|
||||
@ -1288,8 +1439,6 @@ pfctl_show_anchors(int dev, int opts, char *anchorname)
|
||||
return (-1);
|
||||
}
|
||||
mnr = pr.nr;
|
||||
if (!(opts & PF_OPT_QUIET))
|
||||
printf("%u rulesets in anchor %s:\n", mnr, anchorname);
|
||||
for (nr = 0; nr < mnr; ++nr) {
|
||||
pr.nr = nr;
|
||||
if (ioctl(dev, DIOCGETRULESET, &pr))
|
||||
@ -1323,8 +1472,8 @@ main(int argc, char *argv[])
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
while ((ch = getopt(argc, argv, "a:AdD:eqf:F:ghk:nNOrRs:t:T:vx:z")) !=
|
||||
-1) {
|
||||
while ((ch = getopt(argc, argv,
|
||||
"a:AdD:eqf:F:ghi:k:nNOp:rRs:t:T:vx:z")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
anchoropt = optarg;
|
||||
@ -1353,6 +1502,9 @@ main(int argc, char *argv[])
|
||||
}
|
||||
mode = O_RDWR;
|
||||
break;
|
||||
case 'i':
|
||||
ifaceopt = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
if (state_killers >= 2) {
|
||||
warnx("can only specify -k twice");
|
||||
@ -1387,6 +1539,9 @@ main(int argc, char *argv[])
|
||||
case 'O':
|
||||
loadopt |= PFCTL_FLAG_OPTION;
|
||||
break;
|
||||
case 'p':
|
||||
pf_device = optarg;
|
||||
break;
|
||||
case 's':
|
||||
showopt = pfctl_lookup_option(optarg, showopt_list);
|
||||
if (showopt == NULL) {
|
||||
@ -1436,14 +1591,8 @@ main(int argc, char *argv[])
|
||||
if (ch == 'l') {
|
||||
loadopt |= PFCTL_FLAG_TABLE;
|
||||
tblcmdopt = NULL;
|
||||
} else {
|
||||
} else
|
||||
mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY;
|
||||
if (opts & PF_OPT_NOACTION) {
|
||||
dev = open("/dev/pf", mode);
|
||||
if (dev >= 0)
|
||||
opts |= PF_OPT_DUMMYACTION;
|
||||
}
|
||||
}
|
||||
} else if (argc != optind) {
|
||||
warnx("unknown command line argument: %s ...", argv[optind]);
|
||||
usage();
|
||||
@ -1482,11 +1631,14 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if ((opts & PF_OPT_NOACTION) == 0) {
|
||||
dev = open("/dev/pf", mode);
|
||||
dev = open(pf_device, mode);
|
||||
if (dev == -1)
|
||||
err(1, "/dev/pf");
|
||||
err(1, "%s", pf_device);
|
||||
altqsupport = pfctl_test_altqsupport(dev, opts);
|
||||
} else {
|
||||
dev = open(pf_device, O_RDONLY);
|
||||
if (dev >= 0)
|
||||
opts |= PF_OPT_DUMMYACTION;
|
||||
/* turn off options */
|
||||
opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
|
||||
clearopt = showopt = debugopt = NULL;
|
||||
@ -1521,32 +1673,38 @@ main(int argc, char *argv[])
|
||||
pfctl_show_nat(dev, opts, anchorname, rulesetname);
|
||||
break;
|
||||
case 'q':
|
||||
pfctl_show_altq(dev, opts, opts & PF_OPT_VERBOSE2);
|
||||
pfctl_show_altq(dev, ifaceopt, opts,
|
||||
opts & PF_OPT_VERBOSE2);
|
||||
break;
|
||||
case 's':
|
||||
pfctl_show_states(dev, 0, opts);
|
||||
pfctl_show_states(dev, ifaceopt, opts);
|
||||
break;
|
||||
case 'S':
|
||||
pfctl_show_src_nodes(dev, opts);
|
||||
break;
|
||||
case 'i':
|
||||
pfctl_show_status(dev);
|
||||
pfctl_show_status(dev, opts);
|
||||
break;
|
||||
case 't':
|
||||
pfctl_show_timeouts(dev);
|
||||
pfctl_show_timeouts(dev, opts);
|
||||
break;
|
||||
case 'm':
|
||||
pfctl_show_limits(dev);
|
||||
pfctl_show_limits(dev, opts);
|
||||
break;
|
||||
case 'a':
|
||||
opts |= PF_OPT_SHOWALL;
|
||||
pfctl_load_fingerprints(dev, opts);
|
||||
|
||||
pfctl_show_nat(dev, opts, anchorname, rulesetname);
|
||||
pfctl_show_rules(dev, opts, 0, anchorname,
|
||||
rulesetname);
|
||||
pfctl_show_nat(dev, opts, anchorname, rulesetname);
|
||||
pfctl_show_altq(dev, opts, 0);
|
||||
pfctl_show_states(dev, 0, opts);
|
||||
pfctl_show_status(dev);
|
||||
pfctl_show_altq(dev, ifaceopt, opts, 0);
|
||||
pfctl_show_states(dev, ifaceopt, opts);
|
||||
pfctl_show_src_nodes(dev, opts);
|
||||
pfctl_show_status(dev, opts);
|
||||
pfctl_show_rules(dev, opts, 1, anchorname, rulesetname);
|
||||
pfctl_show_timeouts(dev);
|
||||
pfctl_show_limits(dev);
|
||||
pfctl_show_timeouts(dev, opts);
|
||||
pfctl_show_limits(dev, opts);
|
||||
pfctl_show_tables(anchorname, rulesetname, opts);
|
||||
pfctl_show_fingerprints(opts);
|
||||
break;
|
||||
@ -1557,6 +1715,9 @@ main(int argc, char *argv[])
|
||||
pfctl_load_fingerprints(dev, opts);
|
||||
pfctl_show_fingerprints(opts);
|
||||
break;
|
||||
case 'I':
|
||||
pfctl_show_ifaces(ifaceopt, opts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1572,7 +1733,10 @@ main(int argc, char *argv[])
|
||||
pfctl_clear_altq(dev, opts);
|
||||
break;
|
||||
case 's':
|
||||
pfctl_clear_states(dev, opts);
|
||||
pfctl_clear_states(dev, ifaceopt, opts);
|
||||
break;
|
||||
case 'S':
|
||||
pfctl_clear_src_nodes(dev, opts);
|
||||
break;
|
||||
case 'i':
|
||||
pfctl_clear_stats(dev, opts);
|
||||
@ -1580,11 +1744,14 @@ main(int argc, char *argv[])
|
||||
case 'a':
|
||||
pfctl_clear_rules(dev, opts, anchorname, rulesetname);
|
||||
pfctl_clear_nat(dev, opts, anchorname, rulesetname);
|
||||
pfctl_clear_altq(dev, opts);
|
||||
pfctl_clear_states(dev, opts);
|
||||
pfctl_clear_stats(dev, opts);
|
||||
pfctl_clear_tables(anchorname, rulesetname, opts);
|
||||
pfctl_clear_fingerprints(dev, opts);
|
||||
if (!*anchorname && !*rulesetname) {
|
||||
pfctl_clear_altq(dev, opts);
|
||||
pfctl_clear_states(dev, ifaceopt, opts);
|
||||
pfctl_clear_src_nodes(dev, opts);
|
||||
pfctl_clear_stats(dev, opts);
|
||||
pfctl_clear_fingerprints(dev, opts);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
pfctl_clear_fingerprints(dev, opts);
|
||||
@ -1595,7 +1762,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
if (state_killers)
|
||||
pfctl_kill_states(dev, opts);
|
||||
pfctl_kill_states(dev, ifaceopt, opts);
|
||||
|
||||
if (tblcmdopt != NULL) {
|
||||
error = pfctl_command_tables(argc, argv, tableopt,
|
||||
@ -1608,7 +1775,8 @@ main(int argc, char *argv[])
|
||||
error = 1;
|
||||
|
||||
if (rulesopt != NULL) {
|
||||
if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname))
|
||||
if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname,
|
||||
NULL))
|
||||
error = 1;
|
||||
else if (!(opts & PF_OPT_NOACTION) &&
|
||||
(loadopt & PFCTL_FLAG_TABLE))
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl.h,v 1.25 2003/08/29 21:47:36 cedric Exp $ */
|
||||
/* $OpenBSD: pfctl.h,v 1.33 2004/02/19 21:37:01 cedric Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -34,7 +34,8 @@
|
||||
#ifndef _PFCTL_H_
|
||||
#define _PFCTL_H_
|
||||
|
||||
enum { PFRB_TABLES = 1, PFRB_TSTATS, PFRB_ADDRS, PFRB_ASTATS, PFRB_MAX };
|
||||
enum { PFRB_TABLES = 1, PFRB_TSTATS, PFRB_ADDRS, PFRB_ASTATS,
|
||||
PFRB_IFACES, PFRB_TRANS, PFRB_MAX };
|
||||
struct pfr_buffer {
|
||||
int pfrb_type; /* type of content, see enum above */
|
||||
int pfrb_size; /* number of objects in buffer */
|
||||
@ -58,7 +59,7 @@ int pfr_clr_addrs(struct pfr_table *, int *, int);
|
||||
int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||
int *, int *, int *, int);
|
||||
int *, int *, int *, int);
|
||||
int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
|
||||
int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
|
||||
int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
@ -75,13 +76,17 @@ int pfr_buf_grow(struct pfr_buffer *, int);
|
||||
int pfr_buf_load(struct pfr_buffer *, char *, int,
|
||||
int (*)(struct pfr_buffer *, char *, int));
|
||||
char *pfr_strerror(int);
|
||||
int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
|
||||
int pfi_clr_istats(const char *, int *, int);
|
||||
|
||||
void pfctl_print_title(char *);
|
||||
int pfctl_clear_tables(const char *, const char *, int);
|
||||
int pfctl_show_tables(const char *, const char *, int);
|
||||
int pfctl_command_tables(int, char *[], char *, const char *, char *,
|
||||
const char *, const char *, int);
|
||||
int pfctl_show_altq(int, int, int);
|
||||
int pfctl_show_altq(int, const char *, int, int);
|
||||
void warn_namespace_collision(const char *);
|
||||
int pfctl_show_ifaces(const char *, int);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
extern int altqsupport;
|
||||
@ -116,5 +121,9 @@ void print_state(struct pf_state *, int);
|
||||
int unmask(struct pf_addr *, sa_family_t);
|
||||
|
||||
int pfctl_cmdline_symset(char *);
|
||||
int pfctl_add_trans(struct pfr_buffer *, int, const char *, const char *);
|
||||
u_int32_t
|
||||
pfctl_get_ticket(struct pfr_buffer *, int, const char *, const char *);
|
||||
int pfctl_trans(int, struct pfr_buffer *, u_long, int);
|
||||
|
||||
#endif /* _PFCTL_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.77 2003/08/22 21:50:34 david Exp $ */
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.83 2004/03/14 21:51:44 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002
|
||||
@ -89,8 +89,6 @@ u_int32_t eval_bwspec(struct node_queue_bw *, u_int32_t);
|
||||
void print_hfsc_sc(const char *, u_int, u_int, u_int,
|
||||
const struct node_hfsc_sc *);
|
||||
|
||||
static u_int32_t max_qid = 1;
|
||||
|
||||
void
|
||||
pfaltq_store(struct pf_altq *a)
|
||||
{
|
||||
@ -165,14 +163,14 @@ void
|
||||
print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
|
||||
struct node_queue_opt *qopts)
|
||||
{
|
||||
if (a->qname[0] != '\0') {
|
||||
if (a->qname[0] != 0) {
|
||||
print_queue(a, level, bw, 0, qopts);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("altq on %s ", a->ifname);
|
||||
|
||||
switch(a->scheduler) {
|
||||
switch (a->scheduler) {
|
||||
case ALTQT_CBQ:
|
||||
if (!print_cbq_opts(a))
|
||||
printf("cbq ");
|
||||
@ -272,6 +270,8 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
||||
else
|
||||
size = 24;
|
||||
size = size * getifmtu(pa->ifname);
|
||||
if (size > 0xffff)
|
||||
size = 0xffff;
|
||||
pa->tbrsize = size;
|
||||
}
|
||||
return (errors);
|
||||
@ -421,8 +421,6 @@ eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa)
|
||||
|
||||
if (pa->parent[0] == 0)
|
||||
opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR);
|
||||
else if (pa->qid == 0 && (opts->flags & CBQCLF_DEFCLASS) == 0)
|
||||
pa->qid = ++max_qid;
|
||||
|
||||
cbq_compute_idletime(pf, pa);
|
||||
return (0);
|
||||
@ -496,9 +494,12 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa)
|
||||
minidle = -((double)opts->maxpktsize * (double)nsPerByte);
|
||||
|
||||
/* scale parameters */
|
||||
maxidle = ((maxidle * 8.0) / nsPerByte) * pow(2.0, (double)RM_FILTER_GAIN);
|
||||
offtime = (offtime * 8.0) / nsPerByte * pow(2.0, (double)RM_FILTER_GAIN);
|
||||
minidle = ((minidle * 8.0) / nsPerByte) * pow(2.0, (double)RM_FILTER_GAIN);
|
||||
maxidle = ((maxidle * 8.0) / nsPerByte) *
|
||||
pow(2.0, (double)RM_FILTER_GAIN);
|
||||
offtime = (offtime * 8.0) / nsPerByte *
|
||||
pow(2.0, (double)RM_FILTER_GAIN);
|
||||
minidle = ((minidle * 8.0) / nsPerByte) *
|
||||
pow(2.0, (double)RM_FILTER_GAIN);
|
||||
|
||||
maxidle = maxidle / 1000.0;
|
||||
offtime = offtime / 1000.0;
|
||||
@ -506,10 +507,10 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa)
|
||||
|
||||
opts->minburst = minburst;
|
||||
opts->maxburst = maxburst;
|
||||
opts->ns_per_byte = (u_int) nsPerByte;
|
||||
opts->maxidle = (u_int) fabs(maxidle);
|
||||
opts->ns_per_byte = (u_int)nsPerByte;
|
||||
opts->maxidle = (u_int)fabs(maxidle);
|
||||
opts->minidle = (int)minidle;
|
||||
opts->offtime = (u_int) fabs(offtime);
|
||||
opts->offtime = (u_int)fabs(offtime);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -604,9 +605,6 @@ eval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa)
|
||||
}
|
||||
}
|
||||
|
||||
if (pa->qid == 0)
|
||||
pa->qid = ++max_qid;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -676,13 +674,11 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
|
||||
if (pa->parent[0] == 0) {
|
||||
/* root queue */
|
||||
pa->qid = HFSC_ROOTCLASS_HANDLE;
|
||||
opts->lssc_m1 = pa->ifbandwidth;
|
||||
opts->lssc_m2 = pa->ifbandwidth;
|
||||
opts->lssc_d = 0;
|
||||
return (0);
|
||||
} else if (pa->qid == 0)
|
||||
pa->qid = ++max_qid;
|
||||
}
|
||||
|
||||
LIST_INIT(&rtsc);
|
||||
LIST_INIT(&lssc);
|
||||
@ -729,7 +725,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
/* if the class has a real-time service curve, add it. */
|
||||
if (opts->rtsc_m2 != 0 && altq->pq_u.hfsc_opts.rtsc_m2 != 0) {
|
||||
sc.m1 = altq->pq_u.hfsc_opts.rtsc_m1;
|
||||
sc.d = altq->pq_u.hfsc_opts.rtsc_d;
|
||||
sc.d = altq->pq_u.hfsc_opts.rtsc_d;
|
||||
sc.m2 = altq->pq_u.hfsc_opts.rtsc_m2;
|
||||
gsc_add_sc(&rtsc, &sc);
|
||||
}
|
||||
@ -740,7 +736,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
/* if the class has a link-sharing service curve, add it. */
|
||||
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
|
||||
sc.m1 = altq->pq_u.hfsc_opts.lssc_m1;
|
||||
sc.d = altq->pq_u.hfsc_opts.lssc_d;
|
||||
sc.d = altq->pq_u.hfsc_opts.lssc_d;
|
||||
sc.m2 = altq->pq_u.hfsc_opts.lssc_m2;
|
||||
gsc_add_sc(&lssc, &sc);
|
||||
}
|
||||
@ -749,7 +745,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
/* check the real-time service curve. reserve 20% of interface bw */
|
||||
if (opts->rtsc_m2 != 0) {
|
||||
sc.m1 = 0;
|
||||
sc.d = 0;
|
||||
sc.d = 0;
|
||||
sc.m2 = pa->ifbandwidth / 100 * 80;
|
||||
if (!is_gsc_under_sc(&rtsc, &sc)) {
|
||||
warnx("real-time sc exceeds the interface bandwidth");
|
||||
@ -760,7 +756,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
/* check the link-sharing service curve. */
|
||||
if (opts->lssc_m2 != 0) {
|
||||
sc.m1 = parent->pq_u.hfsc_opts.lssc_m1;
|
||||
sc.d = parent->pq_u.hfsc_opts.lssc_d;
|
||||
sc.d = parent->pq_u.hfsc_opts.lssc_d;
|
||||
sc.m2 = parent->pq_u.hfsc_opts.lssc_m2;
|
||||
if (!is_gsc_under_sc(&lssc, &sc)) {
|
||||
warnx("link-sharing sc exceeds parent's sc");
|
||||
@ -1020,7 +1016,7 @@ gsc_add_seg(struct gen_sc *gsc, double x, double y, double d, double m)
|
||||
else
|
||||
x2 = x + d;
|
||||
start = gsc_getentry(gsc, x);
|
||||
end = gsc_getentry(gsc, x2);
|
||||
end = gsc_getentry(gsc, x2);
|
||||
if (start == NULL || end == NULL)
|
||||
return (-1);
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* $OpenBSD: pfctl_parser.c,v 1.175 2003/09/18 20:27:58 cedric Exp $ */
|
||||
/* $OpenBSD: pfctl_parser.c,v 1.194 2004/03/15 15:25:44 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
* Copyright (c) 2002,2003 Henning Brauer
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -34,6 +35,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
@ -196,6 +198,7 @@ const struct pf_timeout pf_timeouts[] = {
|
||||
{ "interval", PFTM_INTERVAL },
|
||||
{ "adaptive.start", PFTM_ADAPTIVE_START },
|
||||
{ "adaptive.end", PFTM_ADAPTIVE_END },
|
||||
{ "src.track", PFTM_SRC_NODE },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@ -255,7 +258,7 @@ geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af)
|
||||
}
|
||||
} else {
|
||||
for (i=0; i < (sizeof (icmp6_code) /
|
||||
sizeof(icmp6_code[0])); i++) {
|
||||
sizeof(icmp6_code[0])); i++) {
|
||||
if (type == icmp6_code[i].type &&
|
||||
code == icmp6_code[i].code)
|
||||
return (&icmp6_code[i]);
|
||||
@ -462,23 +465,27 @@ print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
|
||||
printf(" round-robin");
|
||||
break;
|
||||
}
|
||||
if (pool->opts & PF_POOL_STICKYADDR)
|
||||
printf(" sticky-address");
|
||||
if (id == PF_NAT && p1 == 0 && p2 == 0)
|
||||
printf(" static-port");
|
||||
}
|
||||
|
||||
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
|
||||
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||
const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||
|
||||
void
|
||||
print_status(struct pf_status *s)
|
||||
print_status(struct pf_status *s, int opts)
|
||||
{
|
||||
char statline[80];
|
||||
char statline[80], *running;
|
||||
time_t runtime;
|
||||
int i;
|
||||
|
||||
runtime = time(NULL) - s->since;
|
||||
running = s->running ? "Enabled" : "Disabled";
|
||||
|
||||
if (s->running) {
|
||||
if (s->since) {
|
||||
unsigned sec, min, hrs, day = runtime;
|
||||
|
||||
sec = day % 60;
|
||||
@ -488,22 +495,26 @@ print_status(struct pf_status *s)
|
||||
hrs = day % 24;
|
||||
day /= 24;
|
||||
snprintf(statline, sizeof(statline),
|
||||
"Status: Enabled for %u days %.2u:%.2u:%.2u",
|
||||
day, hrs, min, sec);
|
||||
"Status: %s for %u days %.2u:%.2u:%.2u",
|
||||
running, day, hrs, min, sec);
|
||||
} else
|
||||
snprintf(statline, sizeof(statline), "Status: Disabled");
|
||||
snprintf(statline, sizeof(statline), "Status: %s", running);
|
||||
printf("%-44s", statline);
|
||||
switch (s->debug) {
|
||||
case 0:
|
||||
case PF_DEBUG_NONE:
|
||||
printf("%15s\n\n", "Debug: None");
|
||||
break;
|
||||
case 1:
|
||||
case PF_DEBUG_URGENT:
|
||||
printf("%15s\n\n", "Debug: Urgent");
|
||||
break;
|
||||
case 2:
|
||||
case PF_DEBUG_MISC:
|
||||
printf("%15s\n\n", "Debug: Misc");
|
||||
break;
|
||||
case PF_DEBUG_NOISY:
|
||||
printf("%15s\n\n", "Debug: Loud");
|
||||
break;
|
||||
}
|
||||
printf("Hostid: 0x%08x\n\n", ntohl(s->hostid));
|
||||
if (s->ifname[0] != 0) {
|
||||
printf("Interface Stats for %-16s %5s %16s\n",
|
||||
s->ifname, "IPv4", "IPv6");
|
||||
@ -539,6 +550,20 @@ print_status(struct pf_status *s)
|
||||
else
|
||||
printf("%14s\n", "");
|
||||
}
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
printf("Source Tracking Table\n");
|
||||
printf(" %-25s %14u %14s\n", "current entries",
|
||||
s->src_nodes, "");
|
||||
for (i = 0; i < SCNT_MAX; i++) {
|
||||
printf(" %-25s %14lld ", pf_scounters[i],
|
||||
s->scounters[i]);
|
||||
if (runtime > 0)
|
||||
printf("%14.1f/s\n",
|
||||
(double)s->scounters[i] / (double)runtime);
|
||||
else
|
||||
printf("%14s\n", "");
|
||||
}
|
||||
}
|
||||
printf("Counters\n");
|
||||
for (i = 0; i < PFRES_MAX; i++) {
|
||||
printf(" %-25s %14llu ", pf_reasons[i],
|
||||
@ -551,6 +576,57 @@ print_status(struct pf_status *s)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_src_node(struct pf_src_node *sn, int opts)
|
||||
{
|
||||
struct pf_addr_wrap aw;
|
||||
int min, sec;
|
||||
|
||||
memset(&aw, 0, sizeof(aw));
|
||||
if (sn->af == AF_INET)
|
||||
aw.v.a.mask.addr32[0] = 0xffffffff;
|
||||
else
|
||||
memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
|
||||
|
||||
aw.v.a.addr = sn->addr;
|
||||
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
|
||||
printf(" -> ");
|
||||
aw.v.a.addr = sn->raddr;
|
||||
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
|
||||
printf(" (%d states)\n", sn->states);
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
sec = sn->creation % 60;
|
||||
sn->creation /= 60;
|
||||
min = sn->creation % 60;
|
||||
sn->creation /= 60;
|
||||
printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec);
|
||||
if (sn->states == 0) {
|
||||
sec = sn->expire % 60;
|
||||
sn->expire /= 60;
|
||||
min = sn->expire % 60;
|
||||
sn->expire /= 60;
|
||||
printf(", expires in %.2u:%.2u:%.2u",
|
||||
sn->expire, min, sec);
|
||||
}
|
||||
printf(", %u pkts, %u bytes", sn->packets, sn->bytes);
|
||||
switch (sn->ruletype) {
|
||||
case PF_NAT:
|
||||
if (sn->rule.nr != -1)
|
||||
printf(", nat rule %u", sn->rule.nr);
|
||||
break;
|
||||
case PF_RDR:
|
||||
if (sn->rule.nr != -1)
|
||||
printf(", rdr rule %u", sn->rule.nr);
|
||||
break;
|
||||
case PF_PASS:
|
||||
if (sn->rule.nr != -1)
|
||||
printf(", filter rule %u", sn->rule.nr);
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_rule(struct pf_rule *r, int verbose)
|
||||
{
|
||||
@ -588,7 +664,7 @@ print_rule(struct pf_rule *r, int verbose)
|
||||
ic6 = geticmpcodebynumber(r->return_icmp6 >> 8,
|
||||
r->return_icmp6 & 255, AF_INET6);
|
||||
|
||||
switch(r->af) {
|
||||
switch (r->af) {
|
||||
case AF_INET:
|
||||
printf(" return-icmp");
|
||||
if (ic == NULL)
|
||||
@ -707,7 +783,13 @@ print_rule(struct pf_rule *r, int verbose)
|
||||
else if (r->keep_state == PF_STATE_SYNPROXY)
|
||||
printf(" synproxy state");
|
||||
opts = 0;
|
||||
if (r->max_states)
|
||||
if (r->max_states || r->max_src_nodes || r->max_src_states)
|
||||
opts = 1;
|
||||
if (r->rule_flag & PFRULE_NOSYNC)
|
||||
opts = 1;
|
||||
if (r->rule_flag & PFRULE_SRCTRACK)
|
||||
opts = 1;
|
||||
if (r->rule_flag & (PFRULE_IFBOUND | PFRULE_GRBOUND))
|
||||
opts = 1;
|
||||
for (i = 0; !opts && i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i])
|
||||
@ -718,6 +800,46 @@ print_rule(struct pf_rule *r, int verbose)
|
||||
printf("max %u", r->max_states);
|
||||
opts = 0;
|
||||
}
|
||||
if (r->rule_flag & PFRULE_NOSYNC) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("no-sync");
|
||||
opts = 0;
|
||||
}
|
||||
if (r->rule_flag & PFRULE_SRCTRACK) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("source-track");
|
||||
if (r->rule_flag & PFRULE_RULESRCTRACK)
|
||||
printf(" rule");
|
||||
else
|
||||
printf(" global");
|
||||
opts = 0;
|
||||
}
|
||||
if (r->max_src_states) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("max-src-states %u", r->max_src_states);
|
||||
opts = 0;
|
||||
}
|
||||
if (r->max_src_nodes) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("max-src-nodes %u", r->max_src_nodes);
|
||||
opts = 0;
|
||||
}
|
||||
if (r->rule_flag & PFRULE_IFBOUND) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("if-bound");
|
||||
opts = 0;
|
||||
}
|
||||
if (r->rule_flag & PFRULE_GRBOUND) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("group-bound");
|
||||
opts = 0;
|
||||
}
|
||||
for (i = 0; i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i]) {
|
||||
if (!opts)
|
||||
@ -885,6 +1007,8 @@ ifa_load(void)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct node_host *n = NULL, *h = NULL;
|
||||
struct pfr_buffer b;
|
||||
struct pfi_if *p;
|
||||
|
||||
if (getifaddrs(&ifap) < 0)
|
||||
err(1, "getifaddrs");
|
||||
@ -903,7 +1027,8 @@ ifa_load(void)
|
||||
if (n->af == AF_INET6 &&
|
||||
IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
|
||||
ifa->ifa_addr)->sin6_addr) &&
|
||||
((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) {
|
||||
((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id ==
|
||||
0) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
@ -925,6 +1050,10 @@ ifa_load(void)
|
||||
memcpy(&n->bcast, &((struct sockaddr_in *)
|
||||
ifa->ifa_broadaddr)->sin_addr.s_addr,
|
||||
sizeof(struct in_addr));
|
||||
if (ifa->ifa_dstaddr != NULL)
|
||||
memcpy(&n->peer, &((struct sockaddr_in *)
|
||||
ifa->ifa_dstaddr)->sin_addr.s_addr,
|
||||
sizeof(struct in_addr));
|
||||
} else if (n->af == AF_INET6) {
|
||||
memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *)
|
||||
ifa->ifa_addr)->sin6_addr.s6_addr,
|
||||
@ -936,6 +1065,10 @@ ifa_load(void)
|
||||
memcpy(&n->bcast, &((struct sockaddr_in6 *)
|
||||
ifa->ifa_broadaddr)->sin6_addr.s6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
if (ifa->ifa_dstaddr != NULL)
|
||||
memcpy(&n->peer, &((struct sockaddr_in6 *)
|
||||
ifa->ifa_dstaddr)->sin6_addr.s6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
n->ifindex = ((struct sockaddr_in6 *)
|
||||
ifa->ifa_addr)->sin6_scope_id;
|
||||
}
|
||||
@ -950,15 +1083,58 @@ ifa_load(void)
|
||||
h->tail = n;
|
||||
}
|
||||
}
|
||||
|
||||
/* add interface groups, including clonable and dynamic stuff */
|
||||
bzero(&b, sizeof(b));
|
||||
b.pfrb_type = PFRB_IFACES;
|
||||
for (;;) {
|
||||
if (pfr_buf_grow(&b, b.pfrb_size))
|
||||
err(1, "ifa_load: pfr_buf_grow");
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (pfi_get_ifaces(NULL, b.pfrb_caddr, &b.pfrb_size,
|
||||
PFI_FLAG_GROUP))
|
||||
err(1, "ifa_load: pfi_get_ifaces");
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
PFRB_FOREACH(p, &b) {
|
||||
n = calloc(1, sizeof(struct node_host));
|
||||
if (n == NULL)
|
||||
err(1, "address: calloc");
|
||||
n->af = AF_LINK;
|
||||
n->ifa_flags = PF_IFA_FLAG_GROUP;
|
||||
if (p->pfif_flags & PFI_IFLAG_DYNAMIC)
|
||||
n->ifa_flags |= PF_IFA_FLAG_DYNAMIC;
|
||||
if (p->pfif_flags & PFI_IFLAG_CLONABLE)
|
||||
n->ifa_flags |= PF_IFA_FLAG_CLONABLE;
|
||||
if (!strcmp(p->pfif_name, "lo"))
|
||||
n->ifa_flags |= IFF_LOOPBACK;
|
||||
if ((n->ifname = strdup(p->pfif_name)) == NULL)
|
||||
err(1, "ifa_load: strdup");
|
||||
n->next = NULL;
|
||||
n->tail = n;
|
||||
if (h == NULL)
|
||||
h = n;
|
||||
else {
|
||||
h->tail->next = n;
|
||||
h->tail = n;
|
||||
}
|
||||
}
|
||||
|
||||
iftab = h;
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
|
||||
struct node_host *
|
||||
ifa_exists(const char *ifa_name)
|
||||
ifa_exists(const char *ifa_name, int group_ok)
|
||||
{
|
||||
struct node_host *n;
|
||||
char *p, buf[IFNAMSIZ];
|
||||
int group;
|
||||
|
||||
group = !isdigit(ifa_name[strlen(ifa_name) - 1]);
|
||||
if (group && !group_ok)
|
||||
return (NULL);
|
||||
if (iftab == NULL)
|
||||
ifa_load();
|
||||
|
||||
@ -966,14 +1142,28 @@ ifa_exists(const char *ifa_name)
|
||||
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
|
||||
return (n);
|
||||
}
|
||||
if (!group) {
|
||||
/* look for clonable and/or dynamic interface */
|
||||
strlcpy(buf, ifa_name, sizeof(buf));
|
||||
for (p = buf + strlen(buf) - 1; p > buf && isdigit(*p); p--)
|
||||
*p = '\0';
|
||||
for (n = iftab; n != NULL; n = n->next)
|
||||
if (n->af == AF_LINK &&
|
||||
!strncmp(n->ifname, buf, IFNAMSIZ))
|
||||
break;
|
||||
if (n != NULL && n->ifa_flags &
|
||||
(PF_IFA_FLAG_DYNAMIC | PF_IFA_FLAG_CLONABLE))
|
||||
return (n); /* XXX */
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct node_host *
|
||||
ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode)
|
||||
ifa_lookup(const char *ifa_name, int flags)
|
||||
{
|
||||
struct node_host *p = NULL, *h = NULL, *n = NULL;
|
||||
int return_all = 0;
|
||||
int return_all = 0, got4 = 0, got6 = 0;
|
||||
const char *last_if = NULL;
|
||||
|
||||
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
||||
return_all = 1;
|
||||
@ -983,23 +1173,44 @@ ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode)
|
||||
|
||||
for (p = iftab; p; p = p->next) {
|
||||
if (!((p->af == AF_INET || p->af == AF_INET6) &&
|
||||
(!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all)))
|
||||
(!strncmp(p->ifname, ifa_name, strlen(ifa_name)) ||
|
||||
return_all)))
|
||||
continue;
|
||||
if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
|
||||
if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
|
||||
continue;
|
||||
if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
|
||||
if ((flags & PFI_AFLAG_BROADCAST) &&
|
||||
!(p->ifa_flags & IFF_BROADCAST))
|
||||
continue;
|
||||
if ((flags & PFI_AFLAG_PEER) &&
|
||||
!(p->ifa_flags & IFF_POINTOPOINT))
|
||||
continue;
|
||||
if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0)
|
||||
continue;
|
||||
if (last_if == NULL || strcmp(last_if, p->ifname))
|
||||
got4 = got6 = 0;
|
||||
last_if = p->ifname;
|
||||
if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4)
|
||||
continue;
|
||||
if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6)
|
||||
continue;
|
||||
if (p->af == AF_INET)
|
||||
got4 = 1;
|
||||
else
|
||||
got6 = 1;
|
||||
n = calloc(1, sizeof(struct node_host));
|
||||
if (n == NULL)
|
||||
err(1, "address: calloc");
|
||||
n->af = p->af;
|
||||
if (mode == PFCTL_IFLOOKUP_BCAST)
|
||||
if (flags & PFI_AFLAG_BROADCAST)
|
||||
memcpy(&n->addr.v.a.addr, &p->bcast,
|
||||
sizeof(struct pf_addr));
|
||||
else if (flags & PFI_AFLAG_PEER)
|
||||
memcpy(&n->addr.v.a.addr, &p->peer,
|
||||
sizeof(struct pf_addr));
|
||||
else
|
||||
memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr,
|
||||
sizeof(struct pf_addr));
|
||||
if (mode == PFCTL_IFLOOKUP_NET)
|
||||
if (flags & PFI_AFLAG_NETWORK)
|
||||
set_ipmask(n, unmask(&p->addr.v.a.mask, n->af));
|
||||
else {
|
||||
if (n->af == AF_INET) {
|
||||
@ -1024,9 +1235,6 @@ ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode)
|
||||
h->tail = n;
|
||||
}
|
||||
}
|
||||
if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) {
|
||||
fprintf(stderr, "no IP address found for %s\n", ifa_name);
|
||||
}
|
||||
return (h);
|
||||
}
|
||||
|
||||
@ -1084,29 +1292,39 @@ host_if(const char *s, int mask)
|
||||
{
|
||||
struct node_host *n, *h = NULL;
|
||||
char *p, *ps;
|
||||
int mode = PFCTL_IFLOOKUP_HOST;
|
||||
int flags = 0;
|
||||
|
||||
if ((p = strrchr(s, ':')) != NULL &&
|
||||
(!strcmp(p+1, "network") || !strcmp(p+1, "broadcast"))) {
|
||||
if ((ps = strdup(s)) == NULL)
|
||||
err(1, "host_if: strdup");
|
||||
while ((p = strrchr(ps, ':')) != NULL) {
|
||||
if (!strcmp(p+1, "network"))
|
||||
mode = PFCTL_IFLOOKUP_NET;
|
||||
if (!strcmp(p+1, "broadcast"))
|
||||
mode = PFCTL_IFLOOKUP_BCAST;
|
||||
if (mask > -1) {
|
||||
fprintf(stderr, "network or broadcast lookup, but "
|
||||
"extra netmask given\n");
|
||||
flags |= PFI_AFLAG_NETWORK;
|
||||
else if (!strcmp(p+1, "broadcast"))
|
||||
flags |= PFI_AFLAG_BROADCAST;
|
||||
else if (!strcmp(p+1, "peer"))
|
||||
flags |= PFI_AFLAG_PEER;
|
||||
else if (!strcmp(p+1, "0"))
|
||||
flags |= PFI_AFLAG_NOALIAS;
|
||||
else {
|
||||
free(ps);
|
||||
return (NULL);
|
||||
}
|
||||
if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
|
||||
err(1, "host: malloc");
|
||||
strlcpy(ps, s, strlen(s) - strlen(p) + 1);
|
||||
} else
|
||||
if ((ps = strdup(s)) == NULL)
|
||||
err(1, "host_if: strdup");
|
||||
|
||||
if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
|
||||
*p = '\0';
|
||||
}
|
||||
if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */
|
||||
fprintf(stderr, "illegal combination of interface modifiers\n");
|
||||
free(ps);
|
||||
return (NULL);
|
||||
}
|
||||
if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) {
|
||||
fprintf(stderr, "network or broadcast lookup, but "
|
||||
"extra netmask given\n");
|
||||
free(ps);
|
||||
return (NULL);
|
||||
}
|
||||
if (ifa_exists(ps, 1) || !strncmp(ps, "self", IFNAMSIZ)) {
|
||||
/* interface with this name exists */
|
||||
h = ifa_lookup(ps, mode);
|
||||
h = ifa_lookup(ps, flags);
|
||||
for (n = h; n != NULL && mask > -1; n = n->next)
|
||||
set_ipmask(n, mask);
|
||||
}
|
||||
@ -1120,27 +1338,27 @@ host_v4(const char *s, int mask)
|
||||
{
|
||||
struct node_host *h = NULL;
|
||||
struct in_addr ina;
|
||||
int bits;
|
||||
int bits = 32;
|
||||
|
||||
memset(&ina, 0, sizeof(struct in_addr));
|
||||
if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) > -1) {
|
||||
h = calloc(1, sizeof(struct node_host));
|
||||
if (h == NULL)
|
||||
err(1, "address: calloc");
|
||||
h->ifname = NULL;
|
||||
h->af = AF_INET;
|
||||
h->addr.v.a.addr.addr32[0] = ina.s_addr;
|
||||
#if defined(__FreeBSD__) && (__FreeBSD_version <= 501106)
|
||||
/* inet_net_pton acts strange w/ multicast addresses, RFC1112 */
|
||||
if (mask == -1 && h->addr.v.a.addr.addr8[0] >= 224 &&
|
||||
h->addr.v.a.addr.addr8[0] < 240)
|
||||
bits = 32;
|
||||
#endif
|
||||
set_ipmask(h, bits);
|
||||
h->next = NULL;
|
||||
h->tail = h;
|
||||
if (strrchr(s, '/') != NULL) {
|
||||
if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
|
||||
return (NULL);
|
||||
} else {
|
||||
if (inet_pton(AF_INET, s, &ina) != 1)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
h = calloc(1, sizeof(struct node_host));
|
||||
if (h == NULL)
|
||||
err(1, "address: calloc");
|
||||
h->ifname = NULL;
|
||||
h->af = AF_INET;
|
||||
h->addr.v.a.addr.addr32[0] = ina.s_addr;
|
||||
set_ipmask(h, bits);
|
||||
h->next = NULL;
|
||||
h->tail = h;
|
||||
|
||||
return (h);
|
||||
}
|
||||
|
||||
@ -1179,12 +1397,20 @@ host_dns(const char *s, int v4mask, int v6mask)
|
||||
{
|
||||
struct addrinfo hints, *res0, *res;
|
||||
struct node_host *n, *h = NULL;
|
||||
int error;
|
||||
int error, noalias = 0;
|
||||
int got4 = 0, got6 = 0;
|
||||
char *p, *ps;
|
||||
|
||||
if ((ps = strdup(s)) == NULL)
|
||||
err(1, "host_if: strdup");
|
||||
if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) {
|
||||
noalias = 1;
|
||||
*p = '\0';
|
||||
}
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
|
||||
error = getaddrinfo(s, NULL, &hints, &res0);
|
||||
error = getaddrinfo(ps, NULL, &hints, &res0);
|
||||
if (error)
|
||||
return (h);
|
||||
|
||||
@ -1192,6 +1418,17 @@ host_dns(const char *s, int v4mask, int v6mask)
|
||||
if (res->ai_family != AF_INET &&
|
||||
res->ai_family != AF_INET6)
|
||||
continue;
|
||||
if (noalias) {
|
||||
if (res->ai_family == AF_INET) {
|
||||
if (got4)
|
||||
continue;
|
||||
got4 = 1;
|
||||
} else {
|
||||
if (got6)
|
||||
continue;
|
||||
got6 = 1;
|
||||
}
|
||||
}
|
||||
n = calloc(1, sizeof(struct node_host));
|
||||
if (n == NULL)
|
||||
err(1, "host_dns: calloc");
|
||||
@ -1223,6 +1460,7 @@ host_dns(const char *s, int v4mask, int v6mask)
|
||||
}
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
free(ps);
|
||||
|
||||
return (h);
|
||||
}
|
||||
@ -1296,3 +1534,45 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor,
|
||||
const char *ruleset)
|
||||
{
|
||||
struct pfioc_trans_e trans;
|
||||
|
||||
bzero(&trans, sizeof(trans));
|
||||
trans.rs_num = rs_num;
|
||||
if (strlcpy(trans.anchor, anchor,
|
||||
sizeof(trans.anchor)) >= sizeof(trans.anchor) ||
|
||||
strlcpy(trans.ruleset, ruleset,
|
||||
sizeof(trans.ruleset)) >= sizeof(trans.ruleset))
|
||||
errx(1, "pfctl_add_trans: strlcpy");
|
||||
|
||||
return pfr_buf_add(buf, &trans);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor,
|
||||
const char *ruleset)
|
||||
{
|
||||
struct pfioc_trans_e *p;
|
||||
|
||||
PFRB_FOREACH(p, buf)
|
||||
if (rs_num == p->rs_num && !strcmp(anchor, p->anchor) &&
|
||||
!strcmp(ruleset, p->ruleset))
|
||||
return (p->ticket);
|
||||
errx(1, "pfr_get_ticket: assertion failed");
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from)
|
||||
{
|
||||
struct pfioc_trans trans;
|
||||
|
||||
bzero(&trans, sizeof(trans));
|
||||
trans.size = buf->pfrb_size - from;
|
||||
trans.esize = sizeof(struct pfioc_trans_e);
|
||||
trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from;
|
||||
return ioctl(dev, cmd, &trans);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_parser.h,v 1.67 2003/08/21 19:12:09 frantzen Exp $ */
|
||||
/* $OpenBSD: pfctl_parser.h,v 1.74 2004/02/10 22:26:56 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -46,6 +46,7 @@
|
||||
#define PF_OPT_VERBOSE2 0x0080
|
||||
#define PF_OPT_DUMMYACTION 0x0100
|
||||
#define PF_OPT_DEBUG 0x0200
|
||||
#define PF_OPT_SHOWALL 0x0400
|
||||
|
||||
#define PF_TH_ALL 0xFF
|
||||
|
||||
@ -67,19 +68,13 @@ struct pfctl {
|
||||
int tdirty; /* kernel dirty */
|
||||
u_int32_t rule_nr;
|
||||
struct pfioc_pooladdr paddr;
|
||||
struct pfioc_rule *prule[PF_RULESET_MAX];
|
||||
struct pfioc_altq *paltq;
|
||||
struct pfioc_queue *pqueue;
|
||||
struct pfr_buffer *trans;
|
||||
const char *anchor;
|
||||
const char *ruleset;
|
||||
};
|
||||
|
||||
enum pfctl_iflookup_mode {
|
||||
PFCTL_IFLOOKUP_HOST,
|
||||
PFCTL_IFLOOKUP_NET,
|
||||
PFCTL_IFLOOKUP_BCAST
|
||||
};
|
||||
|
||||
struct node_if {
|
||||
char ifname[IFNAMSIZ];
|
||||
u_int8_t not;
|
||||
@ -91,6 +86,7 @@ struct node_if {
|
||||
struct node_host {
|
||||
struct pf_addr_wrap addr;
|
||||
struct pf_addr bcast;
|
||||
struct pf_addr peer;
|
||||
sa_family_t af;
|
||||
u_int8_t not;
|
||||
u_int32_t ifindex; /* link-local IPv6 addrs */
|
||||
@ -99,6 +95,10 @@ struct node_host {
|
||||
struct node_host *next;
|
||||
struct node_host *tail;
|
||||
};
|
||||
/* special flags used by ifa_exists */
|
||||
#define PF_IFA_FLAG_GROUP 0x10000
|
||||
#define PF_IFA_FLAG_DYNAMIC 0x20000
|
||||
#define PF_IFA_FLAG_CLONABLE 0x40000
|
||||
|
||||
struct node_os {
|
||||
char *os;
|
||||
@ -168,7 +168,7 @@ struct node_tinit { /* table initializer */
|
||||
|
||||
struct pfr_buffer; /* forward definition */
|
||||
|
||||
int pfctl_rules(int, char *, int, char *, char *);
|
||||
int pfctl_rules(int, char *, int, char *, char *, struct pfr_buffer *);
|
||||
|
||||
int pfctl_add_rule(struct pfctl *, struct pf_rule *);
|
||||
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
||||
@ -179,15 +179,18 @@ int pfctl_set_timeout(struct pfctl *, const char *, int, int);
|
||||
int pfctl_set_optimization(struct pfctl *, const char *);
|
||||
int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
||||
int pfctl_set_logif(struct pfctl *, char *);
|
||||
int pfctl_set_hostid(struct pfctl *, u_int32_t);
|
||||
int pfctl_set_debug(struct pfctl *, char *);
|
||||
|
||||
int parse_rules(FILE *, struct pfctl *);
|
||||
int parse_flags(char *);
|
||||
int pfctl_load_anchors(int, int);
|
||||
int pfctl_load_anchors(int, int, struct pfr_buffer *);
|
||||
|
||||
void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int);
|
||||
void print_src_node(struct pf_src_node *, int);
|
||||
void print_rule(struct pf_rule *, int);
|
||||
void print_tabledef(const char *, int, int, struct node_tinithead *);
|
||||
void print_status(struct pf_status *);
|
||||
void print_status(struct pf_status *, int);
|
||||
|
||||
int eval_pfaltq(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
|
||||
struct node_queue_opt *);
|
||||
@ -195,9 +198,9 @@ int eval_pfqueue(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
|
||||
struct node_queue_opt *);
|
||||
|
||||
void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
||||
struct node_queue_opt *);
|
||||
struct node_queue_opt *);
|
||||
void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
||||
int, struct node_queue_opt *);
|
||||
int, struct node_queue_opt *);
|
||||
|
||||
int pfctl_define_table(char *, int, int, const char *, const char *,
|
||||
struct pfr_buffer *, u_int32_t);
|
||||
@ -242,8 +245,8 @@ extern const struct pf_timeout pf_timeouts[];
|
||||
void set_ipmask(struct node_host *, u_int8_t);
|
||||
int check_netmask(struct node_host *, sa_family_t);
|
||||
void ifa_load(void);
|
||||
struct node_host *ifa_exists(const char *);
|
||||
struct node_host *ifa_lookup(const char *, enum pfctl_iflookup_mode);
|
||||
struct node_host *ifa_exists(const char *, int);
|
||||
struct node_host *ifa_lookup(const char *, int);
|
||||
struct node_host *host(const char *);
|
||||
|
||||
int append_addr(struct pfr_buffer *, char *, int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_qstats.c,v 1.24 2003/07/31 09:46:08 kjc Exp $ */
|
||||
/* $OpenBSD: pfctl_qstats.c,v 1.29 2004/03/15 15:25:44 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) Henning Brauer <henning@openbsd.org>
|
||||
@ -84,28 +84,40 @@ void pfctl_print_altq_nodestat(int,
|
||||
void update_avg(struct pf_altq_node *);
|
||||
|
||||
int
|
||||
pfctl_show_altq(int dev, int opts, int verbose2)
|
||||
pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
|
||||
{
|
||||
struct pf_altq_node *root = NULL, *node;
|
||||
int nodes, dotitle = (opts & PF_OPT_SHOWALL);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (!altqsupport)
|
||||
return (-1);
|
||||
#endif
|
||||
if (pfctl_update_qstats(dev, &root))
|
||||
|
||||
if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
|
||||
return (-1);
|
||||
|
||||
for (node = root; node != NULL; node = node->next)
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||
continue;
|
||||
if (dotitle) {
|
||||
pfctl_print_title("ALTQ:");
|
||||
dotitle = 0;
|
||||
}
|
||||
pfctl_print_altq_node(dev, node, 0, opts);
|
||||
}
|
||||
|
||||
while (verbose2) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
sleep(STAT_INTERVAL);
|
||||
if (pfctl_update_qstats(dev, &root))
|
||||
if (pfctl_update_qstats(dev, &root) == -1)
|
||||
return (-1);
|
||||
for (node = root; node != NULL; node = node->next)
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||
continue;
|
||||
pfctl_print_altq_node(dev, node, 0, opts);
|
||||
}
|
||||
}
|
||||
pfctl_free_altq_node(root);
|
||||
return (0);
|
||||
@ -162,7 +174,7 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
return (mnr);
|
||||
}
|
||||
|
||||
void
|
||||
@ -252,12 +264,13 @@ pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned level,
|
||||
pfctl_print_altq_nodestat(dev, node);
|
||||
|
||||
if (opts & PF_OPT_DEBUG)
|
||||
printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n", node->altq.qid,
|
||||
node->altq.ifname, rate2str((double)(node->altq.ifbandwidth)));
|
||||
printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n",
|
||||
node->altq.qid, node->altq.ifname,
|
||||
rate2str((double)(node->altq.ifbandwidth)));
|
||||
|
||||
for (child = node->children; child != NULL;
|
||||
child = child->next)
|
||||
pfctl_print_altq_node(dev, child, level+1, opts);
|
||||
pfctl_print_altq_node(dev, child, level + 1, opts);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_table.c,v 1.50 2003/08/29 21:47:36 cedric Exp $ */
|
||||
/* $OpenBSD: pfctl_table.c,v 1.59 2004/03/15 15:25:44 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Cedric Berger
|
||||
@ -64,12 +64,19 @@ static void print_addrx(struct pfr_addr *, struct pfr_addr *, int);
|
||||
static void print_astats(struct pfr_astats *, int);
|
||||
static void radix_perror(void);
|
||||
static void xprintf(int, const char *, ...);
|
||||
static void print_iface(struct pfi_if *, int);
|
||||
static void oprintf(int, int, const char *, int *, int);
|
||||
|
||||
static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = {
|
||||
{ "In/Block:", "In/Pass:", "In/XPass:" },
|
||||
{ "Out/Block:", "Out/Pass:", "Out/XPass:" }
|
||||
};
|
||||
|
||||
static const char *istats_text[2][2][2] = {
|
||||
{ { "In4/Pass:", "In4/Block:" }, { "Out4/Pass:", "Out4/Block:" } },
|
||||
{ { "In6/Pass:", "In6/Block:" }, { "Out6/Pass:", "Out6/Block:" } }
|
||||
};
|
||||
|
||||
#define RVTEST(fct) do { \
|
||||
if ((!(opts & PF_OPT_NOACTION) || \
|
||||
(opts & PF_OPT_DUMMYACTION)) && \
|
||||
@ -118,12 +125,12 @@ int
|
||||
pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
char *file, const char *anchor, const char *ruleset, int opts)
|
||||
{
|
||||
struct pfr_table table;
|
||||
struct pfr_buffer b, b2;
|
||||
struct pfr_addr *a, *a2;
|
||||
int nadd = 0, ndel = 0, nchange = 0, nzero = 0;
|
||||
int rv = 0, flags = 0, nmatch = 0;
|
||||
void *p;
|
||||
struct pfr_table table;
|
||||
struct pfr_buffer b, b2;
|
||||
struct pfr_addr *a, *a2;
|
||||
int nadd = 0, ndel = 0, nchange = 0, nzero = 0;
|
||||
int rv = 0, flags = 0, nmatch = 0;
|
||||
void *p;
|
||||
|
||||
if (command == NULL)
|
||||
usage();
|
||||
@ -168,6 +175,10 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
|
||||
if (opts & PF_OPT_SHOWALL && b.pfrb_size > 0)
|
||||
pfctl_print_title("TABLES:");
|
||||
|
||||
PFRB_FOREACH(p, &b)
|
||||
if (opts & PF_OPT_VERBOSE2)
|
||||
print_tstats(p, opts & PF_OPT_DEBUG);
|
||||
@ -246,7 +257,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
opts & PF_OPT_USEDNS);
|
||||
} else if (!strcmp(command, "show")) {
|
||||
b.pfrb_type = (opts & PF_OPT_VERBOSE) ?
|
||||
PFRB_ASTATS : PFRB_ADDRS;
|
||||
PFRB_ASTATS : PFRB_ADDRS;
|
||||
if (argc || file != NULL)
|
||||
usage();
|
||||
for (;;) {
|
||||
@ -328,9 +339,9 @@ print_table(struct pfr_table *ta, int verbose, int debug)
|
||||
(ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
|
||||
ta->pfrt_name);
|
||||
if (ta->pfrt_anchor[0])
|
||||
printf("\t%s", ta->pfrt_anchor);
|
||||
printf("\t%s", ta->pfrt_anchor);
|
||||
if (ta->pfrt_ruleset[0])
|
||||
printf(":%s", ta->pfrt_ruleset);
|
||||
printf(":%s", ta->pfrt_ruleset);
|
||||
puts("");
|
||||
} else
|
||||
puts(ta->pfrt_name);
|
||||
@ -453,12 +464,11 @@ pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||
struct pfr_table tbl;
|
||||
|
||||
bzero(&tbl, sizeof(tbl));
|
||||
if (strlcpy(tbl.pfrt_name, name,
|
||||
sizeof(tbl.pfrt_name)) >= sizeof(tbl.pfrt_name) ||
|
||||
strlcpy(tbl.pfrt_anchor, anchor,
|
||||
if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
|
||||
sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
|
||||
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) ||
|
||||
strlcpy(tbl.pfrt_ruleset, ruleset,
|
||||
sizeof(tbl.pfrt_ruleset)) >= sizeof(tbl.pfrt_ruleset))
|
||||
strlcpy(tbl.pfrt_ruleset, ruleset, sizeof(tbl.pfrt_ruleset)) >=
|
||||
sizeof(tbl.pfrt_ruleset))
|
||||
errx(1, "pfctl_define_table: strlcpy");
|
||||
tbl.pfrt_flags = flags;
|
||||
|
||||
@ -481,7 +491,7 @@ warn_namespace_collision(const char *filter)
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (pfr_get_tables(NULL, b.pfrb_caddr,
|
||||
&b.pfrb_size, PFR_FLAG_ALLRSETS))
|
||||
err(1, "pfr_get_tables");
|
||||
err(1, "pfr_get_tables");
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
@ -526,3 +536,83 @@ xprintf(int opts, const char *fmt, ...)
|
||||
else
|
||||
fprintf(stderr, ".\n");
|
||||
}
|
||||
|
||||
|
||||
/* interface stuff */
|
||||
|
||||
int
|
||||
pfctl_show_ifaces(const char *filter, int opts)
|
||||
{
|
||||
struct pfr_buffer b;
|
||||
struct pfi_if *p;
|
||||
int i = 0, f = PFI_FLAG_GROUP|PFI_FLAG_INSTANCE;
|
||||
|
||||
if (filter != NULL && *filter && !isdigit(filter[strlen(filter)-1]))
|
||||
f &= ~PFI_FLAG_INSTANCE;
|
||||
bzero(&b, sizeof(b));
|
||||
b.pfrb_type = PFRB_IFACES;
|
||||
for (;;) {
|
||||
pfr_buf_grow(&b, b.pfrb_size);
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size, f)) {
|
||||
radix_perror();
|
||||
return (1);
|
||||
}
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (opts & PF_OPT_SHOWALL)
|
||||
pfctl_print_title("INTERFACES:");
|
||||
PFRB_FOREACH(p, &b)
|
||||
print_iface(p, opts);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
print_iface(struct pfi_if *p, int opts)
|
||||
{
|
||||
time_t tzero = p->pfif_tzero;
|
||||
int flags = (opts & PF_OPT_VERBOSE) ? p->pfif_flags : 0;
|
||||
int first = 1;
|
||||
int i, af, dir, act;
|
||||
|
||||
printf("%s", p->pfif_name);
|
||||
oprintf(flags, PFI_IFLAG_INSTANCE, "instance", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 1);
|
||||
#ifdef __FreeBSD__
|
||||
first = 1;
|
||||
oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1);
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
if (!(opts & PF_OPT_VERBOSE2))
|
||||
return;
|
||||
printf("\tCleared: %s", ctime(&tzero));
|
||||
printf("\tReferences: [ States: %-18d Rules: %-18d ]\n",
|
||||
p->pfif_states, p->pfif_rules);
|
||||
for (i = 0; i < 8; i++) {
|
||||
af = (i>>2) & 1;
|
||||
dir = (i>>1) &1;
|
||||
act = i & 1;
|
||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||
istats_text[af][dir][act],
|
||||
(unsigned long long)p->pfif_packets[af][dir][act],
|
||||
(unsigned long long)p->pfif_bytes[af][dir][act]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
oprintf(int flags, int flag, const char *s, int *first, int last)
|
||||
{
|
||||
if (flags & flag) {
|
||||
printf(*first ? "\t(%s" : ", %s", s);
|
||||
*first = 0;
|
||||
}
|
||||
if (last && !*first)
|
||||
printf(")");
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pflogd.c,v 1.21 2003/08/22 21:50:34 david Exp $ */
|
||||
/* $OpenBSD: pflogd.c,v 1.27 2004/02/13 19:01:57 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Theo de Raadt
|
||||
@ -34,6 +34,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
@ -53,20 +54,14 @@ __FBSDID("$FreeBSD$");
|
||||
#include <util.h>
|
||||
#endif
|
||||
|
||||
#define DEF_SNAPLEN 116 /* default plus allow for larger header of pflog */
|
||||
#define PCAP_TO_MS 500 /* pcap read timeout (ms) */
|
||||
#define PCAP_NUM_PKTS 1000 /* max number of packets to process at each loop */
|
||||
#define PCAP_OPT_FIL 0 /* filter optimization */
|
||||
#define FLUSH_DELAY 60 /* flush delay */
|
||||
|
||||
#define PFLOGD_LOG_FILE "/var/log/pflog"
|
||||
#define PFLOGD_DEFAULT_IF "pflog0"
|
||||
#include "pflogd.h"
|
||||
|
||||
pcap_t *hpcap;
|
||||
pcap_dumper_t *dpcap;
|
||||
static FILE *dpcap;
|
||||
|
||||
int Debug = 0;
|
||||
int snaplen = DEF_SNAPLEN;
|
||||
static int snaplen = DEF_SNAPLEN;
|
||||
static int cur_snaplen = DEF_SNAPLEN;
|
||||
|
||||
volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup;
|
||||
|
||||
@ -79,15 +74,43 @@ char errbuf[PCAP_ERRBUF_SIZE];
|
||||
int log_debug = 0;
|
||||
unsigned int delay = FLUSH_DELAY;
|
||||
|
||||
char *copy_argv(char * const *argv);
|
||||
char *copy_argv(char * const *);
|
||||
void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
|
||||
void dump_packet_nobuf(u_char *, const struct pcap_pkthdr *, const u_char *);
|
||||
int flush_buffer(FILE *);
|
||||
int init_pcap(void);
|
||||
void logmsg(int priority, const char *message, ...);
|
||||
void logmsg(int, const char *, ...);
|
||||
void purge_buffer(void);
|
||||
int reset_dump(void);
|
||||
int scan_dump(FILE *, off_t);
|
||||
int set_snaplen(int);
|
||||
void set_suspended(int);
|
||||
void sig_alrm(int);
|
||||
void sig_close(int);
|
||||
void sig_hup(int);
|
||||
void usage(void);
|
||||
|
||||
/* buffer must always be greater than snaplen */
|
||||
static int bufpkt = 0; /* number of packets in buffer */
|
||||
static int buflen = 0; /* allocated size of buffer */
|
||||
static char *buffer = NULL; /* packet buffer */
|
||||
static char *bufpos = NULL; /* position in buffer */
|
||||
static int bufleft = 0; /* bytes left in buffer */
|
||||
|
||||
/* if error, stop logging but count dropped packets */
|
||||
static int suspended = -1;
|
||||
static long packets_dropped = 0;
|
||||
|
||||
void
|
||||
set_suspended(int s)
|
||||
{
|
||||
if (suspended == s)
|
||||
return;
|
||||
|
||||
suspended = s;
|
||||
setproctitle("[%s] -s %d -f %s",
|
||||
suspended ? "suspended" : "running", cur_snaplen, filename);
|
||||
}
|
||||
|
||||
char *
|
||||
copy_argv(char * const *argv)
|
||||
@ -136,7 +159,7 @@ __dead void
|
||||
#endif
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: pflogd [-D] [-d delay] [-f filename] ");
|
||||
fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename] ");
|
||||
fprintf(stderr, "[-s snaplen] [expression]\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -159,37 +182,64 @@ sig_alrm(int sig)
|
||||
gotsig_alrm = 1;
|
||||
}
|
||||
|
||||
int
|
||||
init_pcap(void)
|
||||
void
|
||||
set_pcap_filter(void)
|
||||
{
|
||||
struct bpf_program bprog;
|
||||
pcap_t *oldhpcap = hpcap;
|
||||
|
||||
hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf);
|
||||
if (hpcap == NULL) {
|
||||
logmsg(LOG_ERR, "Failed to initialize: %s", errbuf);
|
||||
hpcap = oldhpcap;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (pcap_compile(hpcap, &bprog, filter, PCAP_OPT_FIL, 0) < 0)
|
||||
logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
|
||||
else if (pcap_setfilter(hpcap, &bprog) < 0)
|
||||
logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
|
||||
if (filter != NULL)
|
||||
free(filter);
|
||||
else {
|
||||
if (pcap_setfilter(hpcap, &bprog) < 0)
|
||||
logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
|
||||
pcap_freecode(&bprog);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
init_pcap(void)
|
||||
{
|
||||
hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf);
|
||||
if (hpcap == NULL) {
|
||||
logmsg(LOG_ERR, "Failed to initialize: %s", errbuf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (pcap_datalink(hpcap) != DLT_PFLOG) {
|
||||
logmsg(LOG_ERR, "Invalid datalink type");
|
||||
pcap_close(hpcap);
|
||||
hpcap = oldhpcap;
|
||||
hpcap = NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (oldhpcap)
|
||||
pcap_close(oldhpcap);
|
||||
set_pcap_filter();
|
||||
|
||||
cur_snaplen = snaplen = pcap_snapshot(hpcap);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* We can not lock bpf devices ... yet */
|
||||
#else
|
||||
/* lock */
|
||||
if (ioctl(pcap_fileno(hpcap), BIOCLOCK) < 0) {
|
||||
logmsg(LOG_ERR, "BIOCLOCK: %s", strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
set_snaplen(int snap)
|
||||
{
|
||||
if (priv_set_snaplen(snap))
|
||||
return (1);
|
||||
|
||||
if (cur_snaplen > snap)
|
||||
purge_buffer();
|
||||
|
||||
cur_snaplen = snap;
|
||||
|
||||
snaplen = pcap_snapshot(hpcap);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -198,45 +248,51 @@ reset_dump(void)
|
||||
{
|
||||
struct pcap_file_header hdr;
|
||||
struct stat st;
|
||||
int tmpsnap;
|
||||
int fd;
|
||||
FILE *fp;
|
||||
|
||||
if (hpcap == NULL)
|
||||
return (1);
|
||||
return (-1);
|
||||
|
||||
if (dpcap) {
|
||||
pcap_dump_close(dpcap);
|
||||
dpcap = 0;
|
||||
flush_buffer(dpcap);
|
||||
fclose(dpcap);
|
||||
dpcap = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Basically reimplement pcap_dump_open() because it truncates
|
||||
* files and duplicates headers and such.
|
||||
*/
|
||||
fp = fopen(filename, "a+");
|
||||
fd = priv_open_log();
|
||||
if (fd < 0)
|
||||
return (1);
|
||||
|
||||
fp = fdopen(fd, "a+");
|
||||
|
||||
if (fp == NULL) {
|
||||
snprintf(hpcap->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
|
||||
filename, pcap_strerror(errno));
|
||||
logmsg(LOG_ERR, "Error: %s", pcap_geterr(hpcap));
|
||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
if (fstat(fileno(fp), &st) == -1) {
|
||||
snprintf(hpcap->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
|
||||
filename, pcap_strerror(errno));
|
||||
logmsg(LOG_ERR, "Error: %s", pcap_geterr(hpcap));
|
||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
dpcap = (pcap_dumper_t *)fp;
|
||||
/* set FILE unbuffered, we do our own buffering */
|
||||
if (setvbuf(fp, NULL, _IONBF, 0)) {
|
||||
logmsg(LOG_ERR, "Failed to set output buffers");
|
||||
return (1);
|
||||
}
|
||||
|
||||
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||
|
||||
if (st.st_size == 0) {
|
||||
if (snaplen != pcap_snapshot(hpcap)) {
|
||||
if (snaplen != cur_snaplen) {
|
||||
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
||||
if (init_pcap()) {
|
||||
logmsg(LOG_ERR, "Failed to initialize");
|
||||
if (hpcap == NULL) return (-1);
|
||||
logmsg(LOG_NOTICE, "Using old settings");
|
||||
if (set_snaplen(snaplen)) {
|
||||
logmsg(LOG_WARNING,
|
||||
"Failed, using old settings");
|
||||
}
|
||||
}
|
||||
hdr.magic = TCPDUMP_MAGIC;
|
||||
@ -248,58 +304,228 @@ reset_dump(void)
|
||||
hdr.linktype = hpcap->linktype;
|
||||
|
||||
if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
|
||||
dpcap = NULL;
|
||||
fclose(fp);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Must read the file, compare the header against our new
|
||||
* options (in particular, snaplen) and adjust our options so
|
||||
* that we generate a correct file.
|
||||
*/
|
||||
(void) fseek(fp, 0L, SEEK_SET);
|
||||
if (fread((char *)&hdr, sizeof(hdr), 1, fp) == 1) {
|
||||
if (hdr.magic != TCPDUMP_MAGIC ||
|
||||
hdr.version_major != PCAP_VERSION_MAJOR ||
|
||||
hdr.version_minor != PCAP_VERSION_MINOR ||
|
||||
hdr.linktype != hpcap->linktype) {
|
||||
logmsg(LOG_ERR,
|
||||
"Invalid/incompatible log file, move it away");
|
||||
fclose(fp);
|
||||
return (1);
|
||||
}
|
||||
if (hdr.snaplen != snaplen) {
|
||||
}
|
||||
} else if (scan_dump(fp, st.st_size)) {
|
||||
/* XXX move file and continue? */
|
||||
fclose(fp);
|
||||
return (1);
|
||||
}
|
||||
|
||||
dpcap = fp;
|
||||
|
||||
set_suspended(0);
|
||||
flush_buffer(fp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
scan_dump(FILE *fp, off_t size)
|
||||
{
|
||||
struct pcap_file_header hdr;
|
||||
struct pcap_pkthdr ph;
|
||||
off_t pos;
|
||||
|
||||
/*
|
||||
* Must read the file, compare the header against our new
|
||||
* options (in particular, snaplen) and adjust our options so
|
||||
* that we generate a correct file. Furthermore, check the file
|
||||
* for consistency so that we can append safely.
|
||||
*
|
||||
* XXX this may take a long time for large logs.
|
||||
*/
|
||||
(void) fseek(fp, 0L, SEEK_SET);
|
||||
|
||||
if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
|
||||
logmsg(LOG_ERR, "Short file header");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (hdr.magic != TCPDUMP_MAGIC ||
|
||||
hdr.version_major != PCAP_VERSION_MAJOR ||
|
||||
hdr.version_minor != PCAP_VERSION_MINOR ||
|
||||
hdr.linktype != hpcap->linktype ||
|
||||
hdr.snaplen > PFLOGD_MAXSNAPLEN) {
|
||||
logmsg(LOG_ERR, "Invalid/incompatible log file, move it away");
|
||||
return (1);
|
||||
}
|
||||
|
||||
pos = sizeof(hdr);
|
||||
|
||||
while (!feof(fp)) {
|
||||
off_t len = fread((char *)&ph, 1, sizeof(ph), fp);
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
if (len != sizeof(ph))
|
||||
goto error;
|
||||
if (ph.caplen > hdr.snaplen || ph.caplen > PFLOGD_MAXSNAPLEN)
|
||||
goto error;
|
||||
pos += sizeof(ph) + ph.caplen;
|
||||
if (pos > size)
|
||||
goto error;
|
||||
fseek(fp, ph.caplen, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (pos != size)
|
||||
goto error;
|
||||
|
||||
if (hdr.snaplen != cur_snaplen) {
|
||||
logmsg(LOG_WARNING,
|
||||
"Existing file has different snaplen %u, using it",
|
||||
hdr.snaplen);
|
||||
if (set_snaplen(hdr.snaplen)) {
|
||||
logmsg(LOG_WARNING,
|
||||
"Existing file specifies a snaplen of %u, using it",
|
||||
hdr.snaplen);
|
||||
tmpsnap = snaplen;
|
||||
snaplen = hdr.snaplen;
|
||||
if (init_pcap()) {
|
||||
logmsg(LOG_ERR, "Failed to re-initialize");
|
||||
if (hpcap == 0)
|
||||
return (-1);
|
||||
logmsg(LOG_NOTICE,
|
||||
"Using old settings, offset: %llu",
|
||||
(unsigned long long)st.st_size);
|
||||
}
|
||||
snaplen = tmpsnap;
|
||||
"Failed, using old settings, offset %llu",
|
||||
(unsigned long long) size);
|
||||
}
|
||||
}
|
||||
|
||||
(void) fseek(fp, 0L, SEEK_END);
|
||||
return (0);
|
||||
|
||||
error:
|
||||
logmsg(LOG_ERR, "Corrupted log file.");
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* dump a packet directly to the stream, which is unbuffered */
|
||||
void
|
||||
dump_packet_nobuf(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
|
||||
{
|
||||
FILE *f = (FILE *)user;
|
||||
|
||||
if (suspended) {
|
||||
packets_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrite((char *)h, sizeof(*h), 1, f) != 1) {
|
||||
/* try to undo header to prevent corruption */
|
||||
off_t pos = ftello(f);
|
||||
if (pos < sizeof(*h) ||
|
||||
ftruncate(fileno(f), pos - sizeof(*h))) {
|
||||
logmsg(LOG_ERR, "Write failed, corrupted logfile!");
|
||||
set_suspended(1);
|
||||
gotsig_close = 1;
|
||||
return;
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (fwrite((char *)sp, h->caplen, 1, f) != 1)
|
||||
goto error;
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
set_suspended(1);
|
||||
packets_dropped ++;
|
||||
logmsg(LOG_ERR, "Logging suspended: fwrite: %s", strerror(errno));
|
||||
}
|
||||
|
||||
int
|
||||
flush_buffer(FILE *f)
|
||||
{
|
||||
off_t offset;
|
||||
int len = bufpos - buffer;
|
||||
|
||||
if (len <= 0)
|
||||
return (0);
|
||||
|
||||
offset = ftello(f);
|
||||
if (offset == (off_t)-1) {
|
||||
set_suspended(1);
|
||||
logmsg(LOG_ERR, "Logging suspended: ftello: %s",
|
||||
strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (fwrite(buffer, len, 1, f) != 1) {
|
||||
set_suspended(1);
|
||||
logmsg(LOG_ERR, "Logging suspended: fwrite: %s",
|
||||
strerror(errno));
|
||||
ftruncate(fileno(f), offset);
|
||||
return (1);
|
||||
}
|
||||
|
||||
set_suspended(0);
|
||||
bufpos = buffer;
|
||||
bufleft = buflen;
|
||||
bufpkt = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
purge_buffer(void)
|
||||
{
|
||||
packets_dropped += bufpkt;
|
||||
|
||||
set_suspended(0);
|
||||
bufpos = buffer;
|
||||
bufleft = buflen;
|
||||
bufpkt = 0;
|
||||
}
|
||||
|
||||
/* append packet to the buffer, flushing if necessary */
|
||||
void
|
||||
dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
|
||||
{
|
||||
FILE *f = (FILE *)user;
|
||||
size_t len = sizeof(*h) + h->caplen;
|
||||
|
||||
if (len < sizeof(*h) || h->caplen > (size_t)cur_snaplen) {
|
||||
logmsg(LOG_NOTICE, "invalid size %u (%u/%u), packet dropped",
|
||||
len, cur_snaplen, snaplen);
|
||||
packets_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len <= bufleft)
|
||||
goto append;
|
||||
|
||||
if (suspended) {
|
||||
packets_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (flush_buffer(f)) {
|
||||
packets_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > bufleft) {
|
||||
dump_packet_nobuf(user, h, sp);
|
||||
return;
|
||||
}
|
||||
|
||||
append:
|
||||
memcpy(bufpos, h, sizeof(*h));
|
||||
memcpy(bufpos + sizeof(*h), sp, h->caplen);
|
||||
|
||||
bufpos += len;
|
||||
bufleft -= len;
|
||||
bufpkt++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct pcap_stat pstat;
|
||||
int ch, np;
|
||||
int ch, np, Xflag = 0;
|
||||
pcap_handler phandler = dump_packet;
|
||||
|
||||
while ((ch = getopt(argc, argv, "Dd:s:f:")) != -1) {
|
||||
#ifdef __FreeBSD__
|
||||
/* another ?paranoid? safety measure we do not have */
|
||||
#else
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
#endif
|
||||
|
||||
while ((ch = getopt(argc, argv, "Dxd:s:f:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'D':
|
||||
Debug = 1;
|
||||
@ -316,6 +542,11 @@ main(int argc, char **argv)
|
||||
snaplen = atoi(optarg);
|
||||
if (snaplen <= 0)
|
||||
snaplen = DEF_SNAPLEN;
|
||||
if (snaplen > PFLOGD_MAXSNAPLEN)
|
||||
snaplen = PFLOGD_MAXSNAPLEN;
|
||||
break;
|
||||
case 'x':
|
||||
Xflag++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
@ -338,6 +569,27 @@ main(int argc, char **argv)
|
||||
|
||||
(void)umask(S_IRWXG | S_IRWXO);
|
||||
|
||||
/* filter will be used by the privileged process */
|
||||
if (argc) {
|
||||
filter = copy_argv(argv);
|
||||
if (filter == NULL)
|
||||
logmsg(LOG_NOTICE, "Failed to form filter expression");
|
||||
}
|
||||
|
||||
/* initialize pcap before dropping privileges */
|
||||
if (init_pcap()) {
|
||||
logmsg(LOG_ERR, "Exiting, init failure");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Privilege separation begins here */
|
||||
if (priv_init()) {
|
||||
logmsg(LOG_ERR, "unable to privsep");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setproctitle("[initializing]");
|
||||
/* Process is now unprivileged and inside a chroot */
|
||||
signal(SIGTERM, sig_close);
|
||||
signal(SIGINT, sig_close);
|
||||
signal(SIGQUIT, sig_close);
|
||||
@ -345,25 +597,29 @@ main(int argc, char **argv)
|
||||
signal(SIGHUP, sig_hup);
|
||||
alarm(delay);
|
||||
|
||||
if (argc) {
|
||||
filter = copy_argv(argv);
|
||||
if (filter == NULL)
|
||||
logmsg(LOG_NOTICE, "Failed to form filter expression");
|
||||
}
|
||||
buffer = malloc(PFLOGD_BUFSIZE);
|
||||
|
||||
if (init_pcap()) {
|
||||
logmsg(LOG_ERR, "Exiting, init failure");
|
||||
exit(1);
|
||||
if (buffer == NULL) {
|
||||
logmsg(LOG_WARNING, "Failed to allocate output buffer");
|
||||
phandler = dump_packet_nobuf;
|
||||
} else {
|
||||
bufleft = buflen = PFLOGD_BUFSIZE;
|
||||
bufpos = buffer;
|
||||
bufpkt = 0;
|
||||
}
|
||||
|
||||
if (reset_dump()) {
|
||||
logmsg(LOG_ERR, "Failed to open log file %s", filename);
|
||||
pcap_close(hpcap);
|
||||
exit(1);
|
||||
}
|
||||
if (Xflag)
|
||||
return (1);
|
||||
|
||||
logmsg(LOG_ERR, "Logging suspended: open error");
|
||||
set_suspended(1);
|
||||
} else if (Xflag)
|
||||
return (0);
|
||||
|
||||
while (1) {
|
||||
np = pcap_dispatch(hpcap, PCAP_NUM_PKTS, pcap_dump, (u_char *)dpcap);
|
||||
np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
|
||||
dump_packet, (u_char *)dpcap);
|
||||
if (np < 0)
|
||||
logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
|
||||
|
||||
@ -371,38 +627,34 @@ main(int argc, char **argv)
|
||||
break;
|
||||
if (gotsig_hup) {
|
||||
if (reset_dump()) {
|
||||
logmsg(LOG_ERR, "Failed to open log file!");
|
||||
break;
|
||||
logmsg(LOG_ERR,
|
||||
"Logging suspended: open error");
|
||||
set_suspended(1);
|
||||
}
|
||||
logmsg(LOG_NOTICE, "Reopened logfile");
|
||||
gotsig_hup = 0;
|
||||
}
|
||||
|
||||
if (gotsig_alrm) {
|
||||
/* XXX pcap_dumper is an incomplete type which libpcap
|
||||
* casts to a FILE* currently. For now it is safe to
|
||||
* make the same assumption, however this may change
|
||||
* in the future.
|
||||
*/
|
||||
if (dpcap) {
|
||||
if (fflush((FILE *)dpcap) == EOF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dpcap)
|
||||
flush_buffer(dpcap);
|
||||
gotsig_alrm = 0;
|
||||
alarm(delay);
|
||||
}
|
||||
}
|
||||
|
||||
logmsg(LOG_NOTICE, "Exiting due to signal");
|
||||
if (dpcap)
|
||||
pcap_dump_close(dpcap);
|
||||
logmsg(LOG_NOTICE, "Exiting");
|
||||
if (dpcap) {
|
||||
flush_buffer(dpcap);
|
||||
fclose(dpcap);
|
||||
}
|
||||
purge_buffer();
|
||||
|
||||
if (pcap_stats(hpcap, &pstat) < 0)
|
||||
logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
|
||||
else
|
||||
logmsg(LOG_NOTICE, "%u packets received, %u dropped",
|
||||
pstat.ps_recv, pstat.ps_drop);
|
||||
logmsg(LOG_NOTICE,
|
||||
"%u packets received, %u/%u dropped (kernel/pflogd)",
|
||||
pstat.ps_recv, pstat.ps_drop, packets_dropped);
|
||||
|
||||
pcap_close(hpcap);
|
||||
if (!Debug)
|
||||
|
@ -16,11 +16,13 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/bpf.h>
|
||||
@ -28,13 +30,13 @@
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pcap.h>
|
||||
#include <pcap-int.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pcap.h>
|
||||
#include <pcap-int.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "pflogd.h"
|
||||
@ -70,7 +72,11 @@ priv_init(void)
|
||||
int snaplen, ret;
|
||||
struct passwd *pw;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
for (i = 1; i < NSIG; i++)
|
||||
#else
|
||||
for (i = 1; i < _NSIG; i++)
|
||||
#endif
|
||||
signal(i, SIG_DFL);
|
||||
|
||||
/* Create sockets */
|
||||
|
@ -12,10 +12,11 @@ SRCS+= pfctl_osfp.c pfctl_radix.c pfctl_table.c pfctl_qstats.c
|
||||
|
||||
CFLAGS+= -Wall -Wmissing-prototypes -Wno-uninitialized
|
||||
CFLAGS+= -Wstrict-prototypes -I${.CURDIR}/../../contrib/pf/pfctl
|
||||
CFLAGS+= -I${.CURDIR}/../../sys/contrib/pf
|
||||
|
||||
# XXX ALTQ
|
||||
#CFLAGS+= -DENABLE_ALTQ
|
||||
CFLAGS+= -I${.CURDIR}/missing
|
||||
CFLAGS+= -DENABLE_ALTQ
|
||||
#CFLAGS+= -I${.CURDIR}/missing
|
||||
|
||||
YFLAGS=
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
.PATH: ${.CURDIR}/../../contrib/pf/pflogd
|
||||
|
||||
PROG= pflogd
|
||||
SRCS= pflogd.c pidfile.c
|
||||
SRCS= pflogd.c pidfile.c privsep.c privsep_fdpass.c
|
||||
MAN= pflogd.8
|
||||
|
||||
CFLAGS+=-Wall -Werror -Wmissing-prototypes -Wshadow
|
||||
|
@ -41,6 +41,7 @@ BEGIN {
|
||||
print "#include <net/ethernet.h>"
|
||||
print "#include <net/if.h>"
|
||||
print "#include <net/if_var.h>"
|
||||
print "#include <net/pfvar.h>"
|
||||
print "#include <net/route.h>"
|
||||
print "#include <netatm/atm.h>"
|
||||
print "#include <netatm/atm_if.h>"
|
||||
|
Loading…
Reference in New Issue
Block a user