Import userland of pf 3.5 from OpenBSD (OPENBSD_3_5_BASE).
This commit is contained in:
parent
c9eda2a3d0
commit
6a32f6ec2e
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: authpf.8,v 1.30 2003/08/17 23:24:47 henning Exp $
|
.\" $OpenBSD: authpf.8,v 1.31 2003/12/10 04:10:37 beck Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2002 Bob Beck (beck@openbsd.org>. All rights reserved.
|
.\" Copyright (c) 2002 Bob Beck (beck@openbsd.org>. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -84,9 +84,9 @@ shared by all
|
|||||||
processes.
|
processes.
|
||||||
By default, the
|
By default, the
|
||||||
.Pa anchor
|
.Pa anchor
|
||||||
name "authpf" is used, and the ruleset names equal the PIDs of the
|
name "authpf" is used, and the ruleset names equal the username and PID of the
|
||||||
.Nm
|
.Nm
|
||||||
processes.
|
processes as "username(pid)".
|
||||||
The following rules need to be added to the main ruleset
|
The following rules need to be added to the main ruleset
|
||||||
.Pa /etc/pf.conf
|
.Pa /etc/pf.conf
|
||||||
in order to cause evaluation of any
|
in order to cause evaluation of any
|
||||||
@ -263,7 +263,8 @@ by creating an appropriate
|
|||||||
.Pa /etc/authpf/authpf.conf
|
.Pa /etc/authpf/authpf.conf
|
||||||
file.
|
file.
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
\fBControl Files\fP - To illustrate the user-specific access control
|
.Sy Control Files
|
||||||
|
\- To illustrate the user-specific access control
|
||||||
mechanisms, let us consider a typical user named bob.
|
mechanisms, let us consider a typical user named bob.
|
||||||
Normally, as long as bob can authenticate himself, the
|
Normally, as long as bob can authenticate himself, the
|
||||||
.Nm
|
.Nm
|
||||||
@ -298,7 +299,8 @@ file.
|
|||||||
Though bob is listed in the allow file, he is prevented from using
|
Though bob is listed in the allow file, he is prevented from using
|
||||||
this gateway due to the existence of a ban file.
|
this gateway due to the existence of a ban file.
|
||||||
.Pp
|
.Pp
|
||||||
\fBDistributed Authentication\fP - It is often desirable to interface with a
|
.Sy Distributed Authentication
|
||||||
|
\- It is often desirable to interface with a
|
||||||
distributed password system rather than forcing the sysadmins to keep a large
|
distributed password system rather than forcing the sysadmins to keep a large
|
||||||
number of local password files in sync.
|
number of local password files in sync.
|
||||||
The
|
The
|
||||||
@ -332,7 +334,8 @@ Using a default password file, all users will get
|
|||||||
as their shell except for root who will get
|
as their shell except for root who will get
|
||||||
.Pa /bin/csh .
|
.Pa /bin/csh .
|
||||||
.Pp
|
.Pp
|
||||||
\fBSSH Configuration\fP - As stated earlier,
|
.Sy SSH Configuration
|
||||||
|
\- As stated earlier,
|
||||||
.Xr sshd 8
|
.Xr sshd 8
|
||||||
must be properly configured to detect and defeat network attacks.
|
must be properly configured to detect and defeat network attacks.
|
||||||
To that end, the following options should be added to
|
To that end, the following options should be added to
|
||||||
@ -346,7 +349,8 @@ ClientAliveCountMax 3
|
|||||||
This ensures that unresponsive or spoofed sessions are terminated within a
|
This ensures that unresponsive or spoofed sessions are terminated within a
|
||||||
minute, since a hijacker should not be able to spoof ssh keepalive messages.
|
minute, since a hijacker should not be able to spoof ssh keepalive messages.
|
||||||
.Pp
|
.Pp
|
||||||
\fBBanners\fP - Once authenticated, the user is shown the contents of
|
.Sy Banners
|
||||||
|
\- Once authenticated, the user is shown the contents of
|
||||||
.Pa /etc/authpf/authpf.message .
|
.Pa /etc/authpf/authpf.message .
|
||||||
This message may be a screen-full of the appropriate use policy, the contents
|
This message may be a screen-full of the appropriate use policy, the contents
|
||||||
of
|
of
|
||||||
@ -366,7 +370,8 @@ problem so we can fix it, please phone 1-900-314-1597 or send
|
|||||||
an email to remove@bulkmailerz.net.
|
an email to remove@bulkmailerz.net.
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
\fBPacket Filter Rules\fP - In areas where this gateway is used to protect a
|
.Sy Packet Filter Rules
|
||||||
|
\- In areas where this gateway is used to protect a
|
||||||
wireless network (a hub with several hundred ports), the default rule set as
|
wireless network (a hub with several hundred ports), the default rule set as
|
||||||
well as the per-user rules should probably allow very few things beyond
|
well as the per-user rules should probably allow very few things beyond
|
||||||
encrypted protocols like
|
encrypted protocols like
|
||||||
@ -378,15 +383,14 @@ On a securely switched network, with plug-in jacks for visitors who are
|
|||||||
given authentication accounts, you might want to allow out everything.
|
given authentication accounts, you might want to allow out everything.
|
||||||
In this context, a secure switch is one that tries to prevent address table
|
In this context, a secure switch is one that tries to prevent address table
|
||||||
overflow attacks.
|
overflow attacks.
|
||||||
The examples below assume a switched wired net.
|
|
||||||
.Pp
|
.Pp
|
||||||
Example
|
Example
|
||||||
.Pa /etc/pf.conf :
|
.Pa /etc/pf.conf :
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# by default we allow internal clients to talk to us using
|
# by default we allow internal clients to talk to us using
|
||||||
# ssh and use us as a dns server.
|
# ssh and use us as a dns server.
|
||||||
internal_if=\&"fxp1\&"
|
internal_if="fxp1"
|
||||||
gateway_addr=\&"10.0.1.1\&"
|
gateway_addr="10.0.1.1"
|
||||||
nat-anchor authpf
|
nat-anchor authpf
|
||||||
rdr-anchor authpf
|
rdr-anchor authpf
|
||||||
binat-anchor authpf
|
binat-anchor authpf
|
||||||
@ -398,26 +402,28 @@ pass in quick on $internal_if proto udp from any to $gateway_addr \e
|
|||||||
anchor authpf
|
anchor authpf
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Example
|
.Sy For a switched, wired net
|
||||||
.Pa /etc/authpf/authpf.rules :
|
\- This example
|
||||||
|
.Pa /etc/authpf/authpf.rules
|
||||||
|
makes no real restrictions; it turns the IP address on and off, logging
|
||||||
|
TCP connections.
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# no real restrictions here, basically turn the network jack off or on.
|
external_if = "xl0"
|
||||||
|
internal_if = "fxp0"
|
||||||
external_if = \&"xl0\&"
|
|
||||||
internal_if = \&"fxp0\&"
|
|
||||||
|
|
||||||
pass in log quick on $internal_if proto tcp from $user_ip to any \e
|
pass in log quick on $internal_if proto tcp from $user_ip to any \e
|
||||||
keep state
|
keep state
|
||||||
pass in quick on $internal_if from $user_ip to any
|
pass in quick on $internal_if from $user_ip to any
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Another example
|
.Sy For a wireless or shared net
|
||||||
|
\- This example
|
||||||
.Pa /etc/authpf/authpf.rules
|
.Pa /etc/authpf/authpf.rules
|
||||||
for an insecure network (such as a public wireless network) where
|
could be used for an insecure network (such as a public wireless network) where
|
||||||
we might need to be a bit more restrictive.
|
we might need to be a bit more restrictive.
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
internal_if=\&"fxp1\&"
|
internal_if="fxp1"
|
||||||
ipsec_gw=\&"10.2.3.4\&"
|
ipsec_gw="10.2.3.4"
|
||||||
|
|
||||||
# rdr ftp for proxying by ftp-proxy(8)
|
# rdr ftp for proxying by ftp-proxy(8)
|
||||||
rdr on $internal_if proto tcp from $user_ip to any port 21 \e
|
rdr on $internal_if proto tcp from $user_ip to any port 21 \e
|
||||||
@ -433,6 +439,32 @@ pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e
|
|||||||
keep state
|
keep state
|
||||||
pass in quick proto esp from $user_ip to $ipsec_gw
|
pass in quick proto esp from $user_ip to $ipsec_gw
|
||||||
.Ed
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Sy Dealing with NAT
|
||||||
|
\- The following
|
||||||
|
.Pa /etc/authpf/authpf.rules
|
||||||
|
shows how to deal with NAT, using tags:
|
||||||
|
.Bd -literal
|
||||||
|
ext_if = "fxp1"
|
||||||
|
ext_addr = 129.128.11.10
|
||||||
|
int_if = "fxp0"
|
||||||
|
# nat and tag connections...
|
||||||
|
nat on $ext_if from $user_ip to any tag $user_ip -> $ext_addr
|
||||||
|
pass in quick on $int_if from $user_ip to any
|
||||||
|
pass out log quick on $ext_if tagged $user_ip keep state
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
With the above rules added by
|
||||||
|
.Nm ,
|
||||||
|
outbound connections corresponding to each users NAT'ed connections
|
||||||
|
will be logged as in the example below, where the user may be identified
|
||||||
|
from the ruleset name.
|
||||||
|
.Bd -literal
|
||||||
|
# tcpdump -n -e -ttt -i pflog0
|
||||||
|
Oct 31 19:42:30.296553 rule 0.bbeck(20267).1/0(match): pass out on fxp1: \e
|
||||||
|
129.128.11.10.60539 > 198.137.240.92.22: S 2131494121:2131494121(0) win \e
|
||||||
|
16384 <mss 1460,nop,nop,sackOK> (DF)
|
||||||
|
.Ed
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width "/etc/authpf/authpf.conf" -compact
|
.Bl -tag -width "/etc/authpf/authpf.conf" -compact
|
||||||
.It Pa /etc/authpf/authpf.conf
|
.It Pa /etc/authpf/authpf.conf
|
||||||
|
@ -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).
|
* Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
|
||||||
@ -46,6 +46,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <pfctl_parser.h>
|
#include <pfctl_parser.h>
|
||||||
|
#include <pfctl.h>
|
||||||
|
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
@ -91,12 +92,6 @@ main(int argc, char *argv[])
|
|||||||
char *cp;
|
char *cp;
|
||||||
uid_t uid;
|
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");
|
config = fopen(PATH_CONFFILE, "r");
|
||||||
|
|
||||||
if ((cp = getenv("SSH_TTY")) == NULL) {
|
if ((cp = getenv("SSH_TTY")) == NULL) {
|
||||||
@ -124,7 +119,6 @@ main(int argc, char *argv[])
|
|||||||
"cannot determine IP from SSH_CLIENT %s", ipsrc);
|
"cannot determine IP from SSH_CLIENT %s", ipsrc);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open the pf device */
|
/* open the pf device */
|
||||||
dev = open(PATH_DEVFILE, O_RDWR);
|
dev = open(PATH_DEVFILE, O_RDWR);
|
||||||
if (dev == -1) {
|
if (dev == -1) {
|
||||||
@ -153,6 +147,18 @@ main(int argc, char *argv[])
|
|||||||
goto die;
|
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 */
|
/* Make our entry in /var/authpf as /var/authpf/ipaddr */
|
||||||
n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc);
|
n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc);
|
||||||
if (n < 0 || (u_int)n >= sizeof(pidfile)) {
|
if (n < 0 || (u_int)n >= sizeof(pidfile)) {
|
||||||
@ -235,15 +241,22 @@ main(int argc, char *argv[])
|
|||||||
seteuid(getuid());
|
seteuid(getuid());
|
||||||
setuid(getuid());
|
setuid(getuid());
|
||||||
|
|
||||||
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser))
|
|
||||||
do_death(0);
|
|
||||||
|
|
||||||
openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
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);
|
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 */
|
/* We appear to be making headway, so actually mark our pid */
|
||||||
rewind(pidfp);
|
rewind(pidfp);
|
||||||
@ -253,7 +266,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (change_filter(1, luser, ipsrc) == -1) {
|
if (change_filter(1, luser, ipsrc) == -1) {
|
||||||
printf("Unable to modify filters\r\n");
|
printf("Unable to modify filters\r\n");
|
||||||
do_death(1);
|
do_death(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGTERM, need_death);
|
signal(SIGTERM, need_death);
|
||||||
@ -536,15 +549,20 @@ remove_stale_rulesets(void)
|
|||||||
mnr = prs.nr;
|
mnr = prs.nr;
|
||||||
nr = 0;
|
nr = 0;
|
||||||
while (nr < mnr) {
|
while (nr < mnr) {
|
||||||
char *s;
|
char *s, *t;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
prs.nr = nr;
|
prs.nr = nr;
|
||||||
if (ioctl(dev, DIOCGETRULESET, &prs))
|
if (ioctl(dev, DIOCGETRULESET, &prs))
|
||||||
return (1);
|
return (1);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
pid = strtoul(prs.name, &s, 10);
|
if ((t = strchr(prs.name, '(')) == NULL)
|
||||||
if (!prs.name[0] || errno || *s)
|
t = prs.name;
|
||||||
|
else
|
||||||
|
t++;
|
||||||
|
pid = strtoul(t, &s, 10);
|
||||||
|
if (!prs.name[0] || errno ||
|
||||||
|
(*s && (t == prs.name || *s != ')')))
|
||||||
return (1);
|
return (1);
|
||||||
if (kill(pid, 0) && errno != EPERM) {
|
if (kill(pid, 0) && errno != EPERM) {
|
||||||
int i;
|
int i;
|
||||||
@ -576,14 +594,11 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
{
|
{
|
||||||
char fn[MAXPATHLEN];
|
char fn[MAXPATHLEN];
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
const int action[PF_RULESET_MAX] = { PF_SCRUB,
|
|
||||||
PF_PASS, PF_NAT, PF_BINAT, PF_RDR };
|
|
||||||
struct pfctl pf;
|
struct pfctl pf;
|
||||||
struct pfioc_rule pr[PF_RULESET_MAX];
|
struct pfr_buffer t;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (luser == NULL || !luser[0] || strlen(luser) >=
|
if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
|
||||||
PF_RULESET_NAME_SIZE || ipsrc == NULL || !ipsrc[0]) {
|
|
||||||
syslog(LOG_ERR, "invalid luser/ipsrc");
|
syslog(LOG_ERR, "invalid luser/ipsrc");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -615,18 +630,18 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
syslog(LOG_ERR, "unable to load kernel's OS fingerprints");
|
syslog(LOG_ERR, "unable to load kernel's OS fingerprints");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
bzero(&t, sizeof(t));
|
||||||
|
t.pfrb_type = PFRB_TRANS;
|
||||||
memset(&pf, 0, sizeof(pf));
|
memset(&pf, 0, sizeof(pf));
|
||||||
for (i = 0; i < PF_RULESET_MAX; ++i) {
|
for (i = 0; i < PF_RULESET_MAX; ++i) {
|
||||||
memset(&pr[i], 0, sizeof(pr[i]));
|
if (pfctl_add_trans(&t, i, anchorname, rulesetname)) {
|
||||||
pr[i].rule.action = action[i];
|
syslog(LOG_ERR, "pfctl_add_trans %m");
|
||||||
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");
|
|
||||||
goto error;
|
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) {
|
if (add) {
|
||||||
@ -637,6 +652,10 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pf.dev = dev;
|
pf.dev = dev;
|
||||||
|
pf.trans = &t;
|
||||||
|
pf.anchor = anchorname;
|
||||||
|
pf.ruleset = rulesetname;
|
||||||
|
|
||||||
infile = fn;
|
infile = fn;
|
||||||
if (parse_rules(f, &pf) < 0) {
|
if (parse_rules(f, &pf) < 0) {
|
||||||
syslog(LOG_ERR, "syntax error in rule file: "
|
syslog(LOG_ERR, "syntax error in rule file: "
|
||||||
@ -649,16 +668,10 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
f = NULL;
|
f = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < PF_RULESET_MAX; ++i)
|
if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) {
|
||||||
/*
|
syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove");
|
||||||
* ignore EINVAL on removal, it means the anchor was
|
goto error;
|
||||||
* already automatically removed by the kernel.
|
}
|
||||||
*/
|
|
||||||
if (ioctl(dev, DIOCCOMMITRULES, &pr[i]) &&
|
|
||||||
(add || errno != EINVAL)) {
|
|
||||||
syslog(LOG_ERR, "DIOCCOMMITRULES %m");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (add) {
|
if (add) {
|
||||||
gettimeofday(&Tstart, NULL);
|
gettimeofday(&Tstart, NULL);
|
||||||
@ -673,6 +686,8 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
error:
|
error:
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0))
|
||||||
|
syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove");
|
||||||
|
|
||||||
infile = NULL;
|
infile = NULL;
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -748,37 +763,44 @@ do_death(int active)
|
|||||||
int
|
int
|
||||||
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
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) {
|
switch (r->action) {
|
||||||
case PF_PASS:
|
case PF_PASS:
|
||||||
case PF_DROP:
|
case PF_DROP:
|
||||||
pr = pf->prule[PF_RULESET_FILTER];
|
rs_num = PF_RULESET_FILTER;
|
||||||
break;
|
break;
|
||||||
case PF_SCRUB:
|
case PF_SCRUB:
|
||||||
pr = pf->prule[PF_RULESET_SCRUB];
|
rs_num = PF_RULESET_SCRUB;
|
||||||
break;
|
break;
|
||||||
case PF_NAT:
|
case PF_NAT:
|
||||||
case PF_NONAT:
|
case PF_NONAT:
|
||||||
pr = pf->prule[PF_RULESET_NAT];
|
rs_num = PF_RULESET_NAT;
|
||||||
break;
|
break;
|
||||||
case PF_RDR:
|
case PF_RDR:
|
||||||
case PF_NORDR:
|
case PF_NORDR:
|
||||||
pr = pf->prule[PF_RULESET_RDR];
|
rs_num = PF_RULESET_RDR;
|
||||||
break;
|
break;
|
||||||
case PF_BINAT:
|
case PF_BINAT:
|
||||||
case PF_NOBINAT:
|
case PF_NOBINAT:
|
||||||
pr = pf->prule[PF_RULESET_BINAT];
|
rs_num = PF_RULESET_BINAT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syslog(LOG_ERR, "invalid rule action %d", r->action);
|
syslog(LOG_ERR, "invalid rule action %d", r->action);
|
||||||
return (1);
|
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))
|
if (pfctl_add_pool(pf, &r->rpool, r->af))
|
||||||
return (1);
|
return (1);
|
||||||
pr->pool_ticket = pf->paddr.ticket;
|
pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
|
||||||
memcpy(&pr->rule, r, sizeof(pr->rule));
|
pf->ruleset);
|
||||||
if (ioctl(pf->dev, DIOCADDRULE, pr)) {
|
pr.pool_ticket = pf->paddr.ticket;
|
||||||
|
memcpy(&pr.rule, r, sizeof(pr.rule));
|
||||||
|
if (ioctl(pf->dev, DIOCADDRULE, &pr)) {
|
||||||
syslog(LOG_ERR, "DIOCADDRULE %m");
|
syslog(LOG_ERR, "DIOCADDRULE %m");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -838,6 +860,13 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
|
|||||||
return (1);
|
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
|
int
|
||||||
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
||||||
{
|
{
|
||||||
@ -852,6 +881,13 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pfctl_set_debug(struct pfctl *pf, char *d)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "set debug not supported in authpf\n");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||||
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
|
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
|
||||||
@ -862,10 +898,14 @@ pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
|||||||
|
|
||||||
int
|
int
|
||||||
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
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 */
|
/* never called, no anchors inside anchors, but we need the stub */
|
||||||
fprintf(stderr, "load anchor not supported from authpf\n");
|
fprintf(stderr, "load anchor not supported from authpf\n");
|
||||||
return (1);
|
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
|
.\" Copyright (c) 1996-2001
|
||||||
.\" Obtuse Systems Corporation, All rights reserved.
|
.\" Obtuse Systems Corporation, All rights reserved.
|
||||||
@ -36,10 +36,11 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm ftp-proxy
|
.Nm ftp-proxy
|
||||||
.Op Fl AnrVw
|
.Op Fl AnrVw
|
||||||
|
.Op Fl a Ar address
|
||||||
.Op Fl D Ar debuglevel
|
.Op Fl D Ar debuglevel
|
||||||
.Op Fl g Ar group
|
.Op Fl g Ar group
|
||||||
.Op Fl m Ar minport
|
|
||||||
.Op Fl M Ar maxport
|
.Op Fl M Ar maxport
|
||||||
|
.Op Fl m Ar minport
|
||||||
.Op Fl t Ar timeout
|
.Op Fl t Ar timeout
|
||||||
.Op Fl u Ar user
|
.Op Fl u Ar user
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -65,6 +66,26 @@ or
|
|||||||
.Qq anonymous
|
.Qq anonymous
|
||||||
only.
|
only.
|
||||||
Any attempt to log in as another user will be blocked by the proxy.
|
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
|
.It Fl D Ar debuglevel
|
||||||
Specify a debug level, where the proxy emits verbose debug output
|
Specify a debug level, where the proxy emits verbose debug output
|
||||||
into
|
into
|
||||||
@ -80,14 +101,6 @@ lookups which require root.
|
|||||||
By default,
|
By default,
|
||||||
.Nm
|
.Nm
|
||||||
uses the default group of the user it drops privilege to.
|
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
|
.It Fl M Ar maxport
|
||||||
Specify the upper end of the port range the proxy will use for the
|
Specify the upper end of the port range the proxy will use for the
|
||||||
data connections it establishes.
|
data connections it establishes.
|
||||||
@ -96,6 +109,14 @@ The default is
|
|||||||
defined in
|
defined in
|
||||||
.Aq Pa netinet/in.h
|
.Aq Pa netinet/in.h
|
||||||
as 65535.
|
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
|
.It Fl n
|
||||||
Activate network address translation
|
Activate network address translation
|
||||||
.Pq NAT
|
.Pq NAT
|
||||||
@ -173,8 +194,8 @@ A typical way to do this would be to use a
|
|||||||
.Xr pf.conf 5
|
.Xr pf.conf 5
|
||||||
rule such as
|
rule such as
|
||||||
.Bd -literal -offset 2n
|
.Bd -literal -offset 2n
|
||||||
int_if = xl0
|
int_if = \&"xl0\&"
|
||||||
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
rdr pass on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
.Xr inetd 8
|
.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
|
* Copyright (c) 1996-2001
|
||||||
@ -67,7 +67,7 @@
|
|||||||
* - per-user rules perhaps.
|
* - per-user rules perhaps.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
@ -148,6 +148,7 @@ char *Group;
|
|||||||
|
|
||||||
extern int Debug_Level;
|
extern int Debug_Level;
|
||||||
extern int Use_Rdns;
|
extern int Use_Rdns;
|
||||||
|
extern in_addr_t Bind_Addr;
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -171,9 +172,8 @@ static void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE,
|
syslog(LOG_NOTICE,
|
||||||
"usage: %s [-AnrVw] [-D debuglevel] [-g group] %s %s",
|
"usage: %s [-AnrVw] [-a address] [-D debuglevel [-g group]"
|
||||||
__progname, "[-m minport] [-M maxport] [-t timeout]",
|
" [-M maxport] [-m minport] [-t timeout] [-u user]", __progname);
|
||||||
"[-u user]");
|
|
||||||
exit(EX_USAGE);
|
exit(EX_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,9 +973,18 @@ main(int argc, char *argv[])
|
|||||||
int use_tcpwrapper = 0;
|
int use_tcpwrapper = 0;
|
||||||
#endif /* LIBWRAP */
|
#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;
|
char *p;
|
||||||
switch (ch) {
|
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':
|
case 'A':
|
||||||
AnonFtpOnly = 1; /* restrict to anon usernames only */
|
AnonFtpOnly = 1; /* restrict to anon usernames only */
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: util.c,v 1.16 2003/06/28 01:04:57 deraadt Exp $ */
|
/* $OpenBSD: util.c,v 1.18 2004/01/22 16:10:30 beck Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996-2001
|
* Copyright (c) 1996-2001
|
||||||
@ -58,6 +58,7 @@
|
|||||||
|
|
||||||
int Debug_Level;
|
int Debug_Level;
|
||||||
int Use_Rdns;
|
int Use_Rdns;
|
||||||
|
in_addr_t Bind_Addr = INADDR_NONE;
|
||||||
|
|
||||||
void debuglog(int debug_level, const char *fmt, ...);
|
void debuglog(int debug_level, const char *fmt, ...);
|
||||||
|
|
||||||
@ -77,7 +78,8 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr,
|
|||||||
struct sockaddr_in *client_sa_ptr)
|
struct sockaddr_in *client_sa_ptr)
|
||||||
{
|
{
|
||||||
struct pfioc_natlook natlook;
|
struct pfioc_natlook natlook;
|
||||||
int slen, fd;
|
socklen_t slen;
|
||||||
|
int fd;
|
||||||
|
|
||||||
slen = sizeof(*real_server_sa_ptr);
|
slen = sizeof(*real_server_sa_ptr);
|
||||||
if (getsockname(connected_fd, (struct sockaddr *)real_server_sa_ptr,
|
if (getsockname(connected_fd, (struct sockaddr *)real_server_sa_ptr,
|
||||||
@ -257,10 +259,13 @@ get_backchannel_socket(int type, int min_port, int max_port, int start_port,
|
|||||||
|
|
||||||
bzero(&sa, sizeof sa);
|
bzero(&sa, sizeof sa);
|
||||||
sa.sin_family = AF_INET;
|
sa.sin_family = AF_INET;
|
||||||
if (sap == NULL)
|
if (Bind_Addr == INADDR_NONE)
|
||||||
sa.sin_addr.s_addr = INADDR_ANY;
|
if (sap == NULL)
|
||||||
|
sa.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
else
|
||||||
|
sa.sin_addr.s_addr = sap->sin_addr.s_addr;
|
||||||
else
|
else
|
||||||
sa.sin_addr.s_addr = sap->sin_addr.s_addr;
|
sa.sin_addr.s_addr = Bind_Addr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Indicate that we want to reuse a port if it happens that the
|
* Indicate that we want to reuse a port if it happens that the
|
||||||
|
@ -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.
|
.\" Copyright (C) 2001, Kjell Wooding. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -33,7 +33,7 @@
|
|||||||
.Nm pf
|
.Nm pf
|
||||||
.Nd packet filter
|
.Nd packet filter
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Cd "pseudo-device pf 1"
|
.Cd "pseudo-device pf"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
Packet filtering takes place in the kernel.
|
Packet filtering takes place in the kernel.
|
||||||
A pseudo-device,
|
A pseudo-device,
|
||||||
@ -72,11 +72,7 @@ Stops the packet filter.
|
|||||||
Starts the ALTQ bandwidth control system.
|
Starts the ALTQ bandwidth control system.
|
||||||
.It Dv DIOCSTOPALTQ
|
.It Dv DIOCSTOPALTQ
|
||||||
Stops the ALTQ bandwidth control system.
|
Stops the ALTQ bandwidth control system.
|
||||||
.It Dv DIOCBEGINADDRS Fa "u_int32_t"
|
.It Dv DIOCBEGINADDRS Fa "struct pfioc_pooladdr"
|
||||||
Clears the buffer address pool
|
|
||||||
and returns a ticket for subsequent DIOCADDADDR, DIOCADDRULE and
|
|
||||||
DIOCCHANGERULE calls.
|
|
||||||
.It Dv DIOCADDADDR Fa "struct pfioc_pooladdr"
|
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
struct pfioc_pooladdr {
|
struct pfioc_pooladdr {
|
||||||
u_int32_t action;
|
u_int32_t action;
|
||||||
@ -92,16 +88,17 @@ struct pfioc_pooladdr {
|
|||||||
};
|
};
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.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
|
Adds pool address
|
||||||
.Va addr
|
.Va addr
|
||||||
to the buffer address pool to be used in the following
|
to the buffer address pool to be used in the following
|
||||||
DIOCADDRULE or DIOCCHANGERULE call.
|
DIOCADDRULE or DIOCCHANGERULE call.
|
||||||
All other members of the structure are ignored.
|
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"
|
.It Dv DIOCADDRULE Fa "struct pfioc_rule"
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
struct pfioc_rule {
|
struct pfioc_rule {
|
||||||
@ -120,7 +117,7 @@ Adds
|
|||||||
at the end of the inactive ruleset.
|
at the end of the inactive ruleset.
|
||||||
Requires
|
Requires
|
||||||
.Va ticket
|
.Va ticket
|
||||||
obtained through preceding DIOCBEGINRULES call, and
|
obtained through preceding DIOCXBEGIN call, and
|
||||||
.Va pool_ticket
|
.Va pool_ticket
|
||||||
obtained through DIOCBEGINADDRS call.
|
obtained through DIOCBEGINADDRS call.
|
||||||
DIOCADDADDR must also be called if any pool addresses are required.
|
DIOCADDADDR must also be called if any pool addresses are required.
|
||||||
@ -133,26 +130,16 @@ names indicate the anchor and ruleset in which to append the rule.
|
|||||||
and
|
and
|
||||||
.Va action
|
.Va action
|
||||||
are ignored.
|
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"
|
.It Dv DIOCADDALTQ Fa "struct pfioc_altq"
|
||||||
Adds
|
Adds
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
struct pfioc_altq {
|
struct pfioc_altq {
|
||||||
|
u_int32_t action;
|
||||||
u_int32_t ticket;
|
u_int32_t ticket;
|
||||||
u_int32_t nr;
|
u_int32_t nr;
|
||||||
struct pf_altq altq;
|
struct pf_altq altq;
|
||||||
};
|
};
|
||||||
.Ed
|
.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"
|
.It Dv DIOCGETRULES Fa "struct pfioc_rule"
|
||||||
Returns
|
Returns
|
||||||
.Va ticket
|
.Va ticket
|
||||||
@ -224,8 +211,6 @@ of length
|
|||||||
.Va nbytes
|
.Va nbytes
|
||||||
for the queue specified by
|
for the queue specified by
|
||||||
.Va nr .
|
.Va nr .
|
||||||
.It Dv DIOCCLRSTATES
|
|
||||||
Clears the state table.
|
|
||||||
.It Dv DIOCADDSTATE Fa "struct pfioc_state"
|
.It Dv DIOCADDSTATE Fa "struct pfioc_state"
|
||||||
Adds a state entry.
|
Adds a state entry.
|
||||||
.It Dv DIOCGETSTATE Fa "struct pfioc_state"
|
.It Dv DIOCGETSTATE Fa "struct pfioc_state"
|
||||||
@ -246,8 +231,16 @@ struct pfioc_state_kill {
|
|||||||
int psk_proto;
|
int psk_proto;
|
||||||
struct pf_rule_addr psk_src;
|
struct pf_rule_addr psk_src;
|
||||||
struct pf_rule_addr psk_dst;
|
struct pf_rule_addr psk_dst;
|
||||||
|
char psk_ifname[IFNAMSIZ];
|
||||||
};
|
};
|
||||||
.Ed
|
.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"
|
.It Dv DIOCSETSTATUSIF Fa "struct pfioc_if"
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
struct pfioc_if {
|
struct pfioc_if {
|
||||||
@ -259,14 +252,19 @@ Specifies the interface for which statistics are accumulated.
|
|||||||
.It Dv DIOCGETSTATUS Fa "struct pf_status"
|
.It Dv DIOCGETSTATUS Fa "struct pf_status"
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
struct pf_status {
|
struct pf_status {
|
||||||
u_int64_t counters[PFRES_MAX];
|
u_int64_t counters[PFRES_MAX];
|
||||||
u_int64_t fcounters[FCNT_MAX];
|
u_int64_t fcounters[FCNT_MAX];
|
||||||
u_int64_t pcounters[2][2][3];
|
u_int64_t scounters[SCNT_MAX];
|
||||||
u_int64_t bcounters[2][2];
|
u_int64_t pcounters[2][2][3];
|
||||||
u_int32_t running;
|
u_int64_t bcounters[2][2];
|
||||||
u_int32_t states;
|
u_int64_t stateid;
|
||||||
u_int32_t since;
|
u_int32_t running;
|
||||||
u_int32_t debug;
|
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
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
@ -285,7 +283,7 @@ struct pfioc_natlook {
|
|||||||
u_int16_t dport;
|
u_int16_t dport;
|
||||||
u_int16_t rsport;
|
u_int16_t rsport;
|
||||||
u_int16_t rdport;
|
u_int16_t rdport;
|
||||||
u_int8_t af;
|
sa_family_t af;
|
||||||
u_int8_t proto;
|
u_int8_t proto;
|
||||||
u_int8_t direction;
|
u_int8_t direction;
|
||||||
};
|
};
|
||||||
@ -525,19 +523,6 @@ or deleted by the kernel.
|
|||||||
Yes, tables can be deleted if one removes the
|
Yes, tables can be deleted if one removes the
|
||||||
.Va persist
|
.Va persist
|
||||||
flag of an unreferenced table.
|
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"
|
.It Dv DIOCRINADEFINE Fa "struct pfioc_table"
|
||||||
Defines a table in the inactive set.
|
Defines a table in the inactive set.
|
||||||
On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size]
|
On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size]
|
||||||
@ -546,6 +531,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
|
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.
|
inactive list, or 1 if a new table has been created.
|
||||||
pfrio_naddr contains the number of addresses effectively put in the table.
|
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
|
.It Dv DIOCFPFLUSH
|
||||||
Flush the passive OS fingerprint table.
|
Flush the passive OS fingerprint table.
|
||||||
.It Dv DIOCFPADD Fa "struct pf_osfp_ioctl"
|
.It Dv DIOCFPADD Fa "struct pf_osfp_ioctl"
|
||||||
@ -623,6 +648,115 @@ The rest of the structure members will come back filled.
|
|||||||
Get the whole list by repeatedly incrementing the
|
Get the whole list by repeatedly incrementing the
|
||||||
.Va fp_getnum
|
.Va fp_getnum
|
||||||
number until the ioctl returns EBUSY.
|
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
|
.El
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
The following example demonstrates how to use the DIOCNATLOOK command
|
The following example demonstrates how to use the DIOCNATLOOK command
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pf.conf.5,v 1.271 2003/09/02 18:37:08 jmc Exp $
|
.\" $OpenBSD: pf.conf.5,v 1.292 2004/02/24 05:44:48 mcbride Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2002, Daniel Hartmeier
|
.\" Copyright (c) 2002, Daniel Hartmeier
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
@ -234,6 +234,9 @@ command.
|
|||||||
Interval between purging expired states and fragments.
|
Interval between purging expired states and fragments.
|
||||||
.It Ar frag
|
.It Ar frag
|
||||||
Seconds before an unassembled fragment is expired.
|
Seconds before an unassembled fragment is expired.
|
||||||
|
.It Ar src.track
|
||||||
|
Length of time to retain a source tracking entry after the last state
|
||||||
|
expires.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
When a packet matches a stateful connection, the seconds to live for the
|
When a packet matches a stateful connection, the seconds to live for the
|
||||||
@ -366,10 +369,21 @@ sets the maximum number of entries in the memory pool used for fragment
|
|||||||
reassembly (generated by
|
reassembly (generated by
|
||||||
.Ar scrub
|
.Ar scrub
|
||||||
rules) to 20000.
|
rules) to 20000.
|
||||||
|
Finally,
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
set limit src-nodes 2000
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
sets the maximum number of entries in the memory pool used for tracking
|
||||||
|
source IP addresses (generated by the
|
||||||
|
.Ar sticky-address
|
||||||
|
and
|
||||||
|
.Ar source-track
|
||||||
|
options) to 2000.
|
||||||
.Pp
|
.Pp
|
||||||
These can be combined:
|
These can be combined:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
set limit { states 20000, frags 20000 }
|
set limit { states 20000, frags 20000, src-nodes 2000 }
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
.It Ar set optimization
|
.It Ar set optimization
|
||||||
@ -420,6 +434,24 @@ For example:
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
set block-policy return
|
set block-policy return
|
||||||
.Ed
|
.Ed
|
||||||
|
.It Ar set state-policy
|
||||||
|
The
|
||||||
|
.Ar state-policy
|
||||||
|
option sets the default behaviour for states:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width group-bound -compact
|
||||||
|
.It Ar if-bound
|
||||||
|
States are bound to interface.
|
||||||
|
.It Ar group-bound
|
||||||
|
States are bound to interface group (i.e. ppp)
|
||||||
|
.It Ar floating
|
||||||
|
States can match packets on any interfaces (the default).
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
For example:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
set state-policy if-bound
|
||||||
|
.Ed
|
||||||
.It Ar set require-order
|
.It Ar set require-order
|
||||||
By default
|
By default
|
||||||
.Xr pfctl 8
|
.Xr pfctl 8
|
||||||
@ -450,6 +482,22 @@ ruleset finishes loading.
|
|||||||
For example:
|
For example:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl set fingerprints \&"/etc/pf.os.devel\&"
|
.Dl set fingerprints \&"/etc/pf.os.devel\&"
|
||||||
|
.Pp
|
||||||
|
.It Ar set debug
|
||||||
|
Set the debug
|
||||||
|
.Ar level
|
||||||
|
to one of the following:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width xxxxxxxxxxxx -compact
|
||||||
|
.It Ar none
|
||||||
|
Don't generate debug messages.
|
||||||
|
.It Ar urgent
|
||||||
|
Generate debug messages only for serious errors.
|
||||||
|
.It Ar misc
|
||||||
|
Generate debug messages for various errors.
|
||||||
|
.It Ar loud
|
||||||
|
Generate debug messages for common conditions.
|
||||||
|
.El
|
||||||
.El
|
.El
|
||||||
.Sh TRAFFIC NORMALIZATION
|
.Sh TRAFFIC NORMALIZATION
|
||||||
Traffic normalization is used to sanitize packet content in such
|
Traffic normalization is used to sanitize packet content in such
|
||||||
@ -1092,15 +1140,17 @@ are specified, the rule will match packets in both directions.
|
|||||||
.It Ar log
|
.It Ar log
|
||||||
In addition to the action specified, a log message is generated.
|
In addition to the action specified, a log message is generated.
|
||||||
All packets for that connection are logged, unless the
|
All packets for that connection are logged, unless the
|
||||||
.Ar keep state
|
.Ar keep state ,
|
||||||
or
|
|
||||||
.Ar modulate state
|
.Ar modulate state
|
||||||
|
or
|
||||||
|
.Ar synproxy state
|
||||||
options are specified, in which case only the
|
options are specified, in which case only the
|
||||||
packet that establishes the state is logged.
|
packet that establishes the state is logged.
|
||||||
(See
|
(See
|
||||||
.Ar keep state
|
.Ar keep state ,
|
||||||
and
|
|
||||||
.Ar modulate state
|
.Ar modulate state
|
||||||
|
and
|
||||||
|
.Ar synproxy state
|
||||||
below).
|
below).
|
||||||
The logged packets are sent to the
|
The logged packets are sent to the
|
||||||
.Xr pflog 4
|
.Xr pflog 4
|
||||||
@ -1114,9 +1164,10 @@ in
|
|||||||
binary format.
|
binary format.
|
||||||
.It Ar log-all
|
.It Ar log-all
|
||||||
Used with
|
Used with
|
||||||
.Ar keep state
|
.Ar keep state ,
|
||||||
or
|
|
||||||
.Ar modulate state
|
.Ar modulate state
|
||||||
|
or
|
||||||
|
.Ar synproxy state
|
||||||
rules to force logging of all packets for a connection.
|
rules to force logging of all packets for a connection.
|
||||||
As with
|
As with
|
||||||
.Ar log ,
|
.Ar log ,
|
||||||
@ -1131,6 +1182,8 @@ is skipped.
|
|||||||
.It Ar on <interface>
|
.It Ar on <interface>
|
||||||
This rule applies only to packets coming in on, or going out through, this
|
This rule applies only to packets coming in on, or going out through, this
|
||||||
particular interface.
|
particular interface.
|
||||||
|
It is also possible to simply give the interface driver name, like ppp or fxp,
|
||||||
|
to make the rule match packets flowing through a group of interfaces.
|
||||||
.It Ar <af>
|
.It Ar <af>
|
||||||
This rule applies only to packets of this address family.
|
This rule applies only to packets of this address family.
|
||||||
Supported values are
|
Supported values are
|
||||||
@ -1175,14 +1228,24 @@ Interface names can have modifiers appended:
|
|||||||
Translates to the network(s) attached to the interface.
|
Translates to the network(s) attached to the interface.
|
||||||
.It Ar :broadcast
|
.It Ar :broadcast
|
||||||
Translates to the interface's broadcast address(es).
|
Translates to the interface's broadcast address(es).
|
||||||
|
.It Ar :peer
|
||||||
|
Translates to the point to point interface's peer address(es).
|
||||||
|
.It Ar :0
|
||||||
|
Do not include interface aliases.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
Host names may also have the
|
||||||
|
.Ar :0
|
||||||
|
option appended to restrict the name resolution to the first of each
|
||||||
|
v4 and v6 address found.
|
||||||
|
.Pp
|
||||||
Host name resolution and interface to address translation are done at
|
Host name resolution and interface to address translation are done at
|
||||||
ruleset load-time.
|
ruleset load-time.
|
||||||
When the address of an interface (or host name) changes (under DHCP or PPP,
|
When the address of an interface (or host name) changes (under DHCP or PPP,
|
||||||
for instance), the ruleset must be reloaded for the change to be reflected
|
for instance), the ruleset must be reloaded for the change to be reflected
|
||||||
in the kernel.
|
in the kernel.
|
||||||
Surrounding the interface name in parentheses changes this behaviour.
|
Surrounding the interface name (and optional modifiers) in parentheses
|
||||||
|
changes this behaviour.
|
||||||
When the interface name is surrounded by parentheses, the rule is
|
When the interface name is surrounded by parentheses, the rule is
|
||||||
automatically updated whenever the interface changes its address.
|
automatically updated whenever the interface changes its address.
|
||||||
The ruleset does not need to be reloaded.
|
The ruleset does not need to be reloaded.
|
||||||
@ -1205,15 +1268,19 @@ Ports and ranges of ports are specified by using these operators:
|
|||||||
<= (less than or equal)
|
<= (less than or equal)
|
||||||
> (greater than)
|
> (greater than)
|
||||||
>= (greater than or equal)
|
>= (greater than or equal)
|
||||||
>< (range)
|
: (range including boundaries)
|
||||||
|
>< (range excluding boundaries)
|
||||||
<> (except range)
|
<> (except range)
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
>< and <>
|
><, <> and :
|
||||||
are binary operators (they take two arguments), and the range
|
are binary operators (they take two arguments).
|
||||||
does not include the limits.
|
|
||||||
For instance:
|
For instance:
|
||||||
.Bl -tag -width Fl
|
.Bl -tag -width Fl
|
||||||
|
.It Ar port 2000:2004
|
||||||
|
means
|
||||||
|
.Sq all ports >= 2000 and <= 2004 ,
|
||||||
|
hence ports 2000, 2001, 2002, 2003 and 2004.
|
||||||
.It Ar port 2000 >< 2004
|
.It Ar port 2000 >< 2004
|
||||||
means
|
means
|
||||||
.Sq all ports > 2000 and < 2004 ,
|
.Sq all ports > 2000 and < 2004 ,
|
||||||
@ -1421,13 +1488,17 @@ A packet is only ever assigned one tag at a time.
|
|||||||
rules that use the
|
rules that use the
|
||||||
.Ar tag
|
.Ar tag
|
||||||
keyword must also use
|
keyword must also use
|
||||||
.Ar keep state .
|
.Ar keep state ,
|
||||||
|
.Ar modulate state
|
||||||
|
or
|
||||||
|
.Ar synproxy state .
|
||||||
Packet tagging can be done during
|
Packet tagging can be done during
|
||||||
.Ar nat ,
|
.Ar nat ,
|
||||||
.Ar rdr ,
|
.Ar rdr ,
|
||||||
or
|
or
|
||||||
.Ar binat
|
.Ar binat
|
||||||
rules in addition to filter rules.
|
rules in addition to filter rules.
|
||||||
|
Tags take the same macros as labels (see above).
|
||||||
.It Ar tagged <string>
|
.It Ar tagged <string>
|
||||||
Used with filter rules to specify that packets must already
|
Used with filter rules to specify that packets must already
|
||||||
be tagged with the given tag in order to match the rule.
|
be tagged with the given tag in order to match the rule.
|
||||||
@ -1533,6 +1604,23 @@ option prevents
|
|||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
from modifying the source port on TCP and UDP packets.
|
from modifying the source port on TCP and UDP packets.
|
||||||
.El
|
.El
|
||||||
|
.Pp
|
||||||
|
Additionally, the
|
||||||
|
.Ar sticky-address
|
||||||
|
option can be specified to help ensure that multiple connections from the
|
||||||
|
same source are mapped to the same redirection address.
|
||||||
|
This option can be used with the
|
||||||
|
.Ar random
|
||||||
|
and
|
||||||
|
.Ar round-robin
|
||||||
|
pool options.
|
||||||
|
Note that by default these associations are destroyed as soon as there are
|
||||||
|
no longer states which refer to them; in order to make the mappings last
|
||||||
|
beyond the lifetime of the states, increase the global options with
|
||||||
|
.Ar set timeout source-track
|
||||||
|
See
|
||||||
|
.Sx STATEFUL TRACKING OPTIONS
|
||||||
|
for more ways to control the source tracking.
|
||||||
.Sh STATEFUL INSPECTION
|
.Sh STATEFUL INSPECTION
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
is a stateful packet filter, which means it can track the state of
|
is a stateful packet filter, which means it can track the state of
|
||||||
@ -1579,6 +1667,37 @@ The initial packet of each connection has the SYN
|
|||||||
flag set, will be passed and creates state.
|
flag set, will be passed and creates state.
|
||||||
All further packets of these connections are passed if they match a state.
|
All further packets of these connections are passed if they match a state.
|
||||||
.Pp
|
.Pp
|
||||||
|
By default, packets coming in and out of any interface can match a state,
|
||||||
|
but it is also possible to change that behaviour by assigning states to a
|
||||||
|
single interface or a group of interfaces.
|
||||||
|
.Pp
|
||||||
|
The default policy is specified by the
|
||||||
|
.Ar state-policy
|
||||||
|
global option, but this can be adjusted on a per-rule basis by adding one
|
||||||
|
of the
|
||||||
|
.Ar if-bound ,
|
||||||
|
.Ar group-bound
|
||||||
|
or
|
||||||
|
.Ar floating
|
||||||
|
keywords to the
|
||||||
|
.Ar keep state
|
||||||
|
option.
|
||||||
|
For example, if a rule is defined as:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
pass out on ppp from any to 10.12/16 keep state (group-bound)
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
A state created on ppp0 would match packets an all PPP interfaces,
|
||||||
|
but not packets flowing through fxp0 or any other interface.
|
||||||
|
.Pp
|
||||||
|
Keeping rules
|
||||||
|
.Ar floating
|
||||||
|
is the more flexible option when the firewall is in a dynamic routing
|
||||||
|
environment.
|
||||||
|
However, this has some security implications since a state created by one
|
||||||
|
trusted network could allow potentially hostile packets coming in from other
|
||||||
|
interfaces.
|
||||||
|
.Pp
|
||||||
Specifying
|
Specifying
|
||||||
.Ar flags S/SA
|
.Ar flags S/SA
|
||||||
restricts state creation to the initial SYN
|
restricts state creation to the initial SYN
|
||||||
@ -1695,7 +1814,7 @@ handshake.
|
|||||||
The proxy is transparent to both endpoints, they each see a single
|
The proxy is transparent to both endpoints, they each see a single
|
||||||
connection from/to the other endpoint.
|
connection from/to the other endpoint.
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
choses random initial sequence numbers for both handshakes.
|
chooses random initial sequence numbers for both handshakes.
|
||||||
Once the handshakes are completed, the sequence number modulators
|
Once the handshakes are completed, the sequence number modulators
|
||||||
(see previous section) are used to translate further packets of the
|
(see previous section) are used to translate further packets of the
|
||||||
connection.
|
connection.
|
||||||
@ -1730,8 +1849,26 @@ support the following options:
|
|||||||
Limits the number of concurrent states the rule may create.
|
Limits the number of concurrent states the rule may create.
|
||||||
When this limit is reached, further packets matching the rule that would
|
When this limit is reached, further packets matching the rule that would
|
||||||
create state are dropped, until existing states time out.
|
create state are dropped, until existing states time out.
|
||||||
|
.It Ar no-sync
|
||||||
|
Prevent state changes for states created by this rule from appearing on the
|
||||||
|
.Xr pfsync 4
|
||||||
|
interface.
|
||||||
.It Ar <timeout> <seconds>
|
.It Ar <timeout> <seconds>
|
||||||
Changes the timeout values used for states created by this rule.
|
Changes the timeout values used for states created by this rule.
|
||||||
|
.Pp
|
||||||
|
When the
|
||||||
|
.Ar source-track
|
||||||
|
keyword is specified, the number of states per source IP is tracked.
|
||||||
|
The following limits can be set:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width xxxx -compact
|
||||||
|
.It Ar max-src-nodes
|
||||||
|
Limits the maximum number of source addresses which can simultaneously
|
||||||
|
have state table entries.
|
||||||
|
.It Ar max-src-states
|
||||||
|
Limits the maximum number of simultaneous state entries that a single
|
||||||
|
source address can create with this rule.
|
||||||
|
.El
|
||||||
For a list of all valid timeout names, see
|
For a list of all valid timeout names, see
|
||||||
.Sx OPTIONS
|
.Sx OPTIONS
|
||||||
above.
|
above.
|
||||||
@ -1740,7 +1877,8 @@ Multiple options can be specified, separated by commas:
|
|||||||
.Bd -literal
|
.Bd -literal
|
||||||
pass in proto tcp from any to any \e
|
pass in proto tcp from any to any \e
|
||||||
port www flags S/SA keep state \e
|
port www flags S/SA keep state \e
|
||||||
(max 100, tcp.established 60, tcp.closing 5)
|
(max 100, source-track rule, max-src-nodes 75, \e
|
||||||
|
max-src-states 3, tcp.established 60, tcp.closing 5)
|
||||||
.Ed
|
.Ed
|
||||||
.El
|
.El
|
||||||
.Sh OPERATING SYSTEM FINGERPRINTING
|
.Sh OPERATING SYSTEM FINGERPRINTING
|
||||||
@ -1853,7 +1991,7 @@ to local addresses.
|
|||||||
One should pass these explicitly.
|
One should pass these explicitly.
|
||||||
.Sh FRAGMENT HANDLING
|
.Sh FRAGMENT HANDLING
|
||||||
The size of IP datagrams (packets) can be significantly larger than the
|
The size of IP datagrams (packets) can be significantly larger than the
|
||||||
the maximum transmission unit (MTU) of the network.
|
maximum transmission unit (MTU) of the network.
|
||||||
In cases when it is necessary or more efficient to send such large packets,
|
In cases when it is necessary or more efficient to send such large packets,
|
||||||
the large packet will be fragmented into many smaller packets that will each
|
the large packet will be fragmented into many smaller packets that will each
|
||||||
fit onto the wire.
|
fit onto the wire.
|
||||||
@ -2027,7 +2165,7 @@ rule after the
|
|||||||
rule:
|
rule:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
anchor spam
|
anchor spam
|
||||||
load anchor spam:manual from /etc/pf-spam.conf
|
load anchor spam:manual from "/etc/pf-spam.conf"
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
When
|
When
|
||||||
@ -2072,8 +2210,11 @@ This example maps incoming requests on port 80 to port 8080, on
|
|||||||
which a daemon is running (because, for example, it is not run as root,
|
which a daemon is running (because, for example, it is not run as root,
|
||||||
and therefore lacks permission to bind to port 80).
|
and therefore lacks permission to bind to port 80).
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
|
# use a macro for the interface name, so it can be changed easily
|
||||||
|
ext_if = \&"ne3\&"
|
||||||
|
|
||||||
# map daemon on 8080 to appear to be on 80
|
# map daemon on 8080 to appear to be on 80
|
||||||
rdr on ne3 proto tcp from any to any port 80 -> 127.0.0.1 port 8080
|
rdr on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 port 8080
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
If the
|
If the
|
||||||
@ -2081,7 +2222,8 @@ If the
|
|||||||
modifier is given, packets matching the translation rule are passed without
|
modifier is given, packets matching the translation rule are passed without
|
||||||
inspecting the filter rules:
|
inspecting the filter rules:
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
rdr pass on ne3 proto tcp from any to any port 80 -> 127.0.0.1 port 8080
|
rdr pass on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 \e
|
||||||
|
port 8080
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
In the example below, vlan12 is configured as 192.168.168.1;
|
In the example below, vlan12 is configured as 192.168.168.1;
|
||||||
@ -2096,83 +2238,80 @@ for the nodes on vlan12.
|
|||||||
nat on ! vlan12 from 192.168.168.0/24 to any -> 204.92.77.111
|
nat on ! vlan12 from 192.168.168.0/24 to any -> 204.92.77.111
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
In the example below, fxp1 is the outside interface; the machine sits between a
|
In the example below, the machine sits between a fake internal 144.19.74.*
|
||||||
fake internal 144.19.74.* network, and a routable external IP of 204.92.77.100.
|
network, and a routable external IP of 204.92.77.100.
|
||||||
The
|
The
|
||||||
.Ar no nat
|
.Ar no nat
|
||||||
rule excludes protocol AH from being translated.
|
rule excludes protocol AH from being translated.
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# NO NAT
|
# NO NAT
|
||||||
no nat on fxp1 proto ah from 144.19.74.0/24 to any
|
no nat on $ext_if proto ah from 144.19.74.0/24 to any
|
||||||
nat on fxp1 from 144.19.74.0/24 to any -> 204.92.77.100
|
nat on $ext_if from 144.19.74.0/24 to any -> 204.92.77.100
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
In the example below, fxp0 is the internal interface.
|
In the example below, packets bound for one specific server, as well as those
|
||||||
Packets bound
|
generated by the sysadmins are not proxied; all other connections are.
|
||||||
for one specific server, as well as those generated by the sysadmins
|
|
||||||
are not proxied; all other connections are.
|
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# NO RDR
|
# NO RDR
|
||||||
no rdr on fxp0 proto { tcp, udp } from any to $server port 80
|
no rdr on $int_if proto { tcp, udp } from any to $server port 80
|
||||||
no rdr on fxp0 proto { tcp, udp } from $sysadmins to any port 80
|
no rdr on $int_if proto { tcp, udp } from $sysadmins to any port 80
|
||||||
rdr on fxp0 proto { tcp, udp } from any to any port 80 -> 127.0.0.1 port 80
|
rdr on $int_if proto { tcp, udp } from any to any port 80 -> 127.0.0.1 \e
|
||||||
|
port 80
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
This longer example uses both a NAT and a redirection.
|
This longer example uses both a NAT and a redirection.
|
||||||
Interface kue0 is the outside interface, and its external address is
|
The external interface has the address 157.161.48.183.
|
||||||
157.161.48.183.
|
On the internal interface, we are running
|
||||||
Interface fxp0 is the inside interface, and we are running
|
|
||||||
.Xr ftp-proxy 8 ,
|
.Xr ftp-proxy 8 ,
|
||||||
listening for outbound ftp sessions captured to port 8021.
|
listening for outbound ftp sessions captured to port 8021.
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# NAT
|
# NAT
|
||||||
# Translate outgoing packets' source addresses (any protocol).
|
# Translate outgoing packets' source addresses (any protocol).
|
||||||
# In this case, any address but the gateway's external address is mapped.
|
# In this case, any address but the gateway's external address is mapped.
|
||||||
nat on kue0 inet from ! (kue0) to any -> (kue0)
|
nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if)
|
||||||
|
|
||||||
# NAT PROXYING
|
# NAT PROXYING
|
||||||
# Map outgoing packets' source port to an assigned proxy port instead of
|
# Map outgoing packets' source port to an assigned proxy port instead of
|
||||||
# an arbitrary port.
|
# an arbitrary port.
|
||||||
# In this case, proxy outgoing isakmp with port 500 on the gateway.
|
# In this case, proxy outgoing isakmp with port 500 on the gateway.
|
||||||
nat on kue0 inet proto udp from any port = isakmp to any -> (kue0) \e
|
nat on $ext_if inet proto udp from any port = isakmp to any -> ($ext_if) \e
|
||||||
port 500
|
port 500
|
||||||
|
|
||||||
# BINAT
|
# BINAT
|
||||||
# Translate outgoing packets' source address (any protocol).
|
# Translate outgoing packets' source address (any protocol).
|
||||||
# Translate incoming packets' destination address to an internal machine
|
# Translate incoming packets' destination address to an internal machine
|
||||||
# (bidirectional).
|
# (bidirectional).
|
||||||
binat on kue0 from 10.1.2.150 to any -> (kue0)
|
binat on $ext_if from 10.1.2.150 to any -> ($ext_if)
|
||||||
|
|
||||||
# RDR
|
# RDR
|
||||||
# Translate incoming packets' destination addresses.
|
# Translate incoming packets' destination addresses.
|
||||||
# As an example, redirect a TCP and UDP port to an internal machine.
|
# As an example, redirect a TCP and UDP port to an internal machine.
|
||||||
rdr on kue0 inet proto tcp from any to (kue0) port 8080 -> 10.1.2.151 \e
|
rdr on $ext_if inet proto tcp from any to ($ext_if) port 8080 \e
|
||||||
port 22
|
-> 10.1.2.151 port 22
|
||||||
rdr on kue0 inet proto udp from any to (kue0) port 8080 -> 10.1.2.151 \e
|
rdr on $ext_if inet proto udp from any to ($ext_if) port 8080 \e
|
||||||
port 53
|
-> 10.1.2.151 port 53
|
||||||
|
|
||||||
# RDR
|
# RDR
|
||||||
# Translate outgoing ftp control connections to send them to localhost
|
# Translate outgoing ftp control connections to send them to localhost
|
||||||
# for proxying with ftp-proxy(8) running on port 8021.
|
# for proxying with ftp-proxy(8) running on port 8021.
|
||||||
rdr on fxp0 proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
In this example, a NAT gateway is set up to translate internal addresses
|
In this example, a NAT gateway is set up to translate internal addresses
|
||||||
using a pool of public addresses (192.0.2.16/28) and to redirect
|
using a pool of public addresses (192.0.2.16/28) and to redirect
|
||||||
incoming web server connections to a group of web servers on the internal
|
incoming web server connections to a group of web servers on the internal
|
||||||
network.
|
network.
|
||||||
Interface fxp0 is the external interface.
|
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# NAT LOAD BALANCE
|
# NAT LOAD BALANCE
|
||||||
# Translate outgoing packets' source addresses using an address pool.
|
# Translate outgoing packets' source addresses using an address pool.
|
||||||
# A given source address is always translated to the same pool address by
|
# A given source address is always translated to the same pool address by
|
||||||
# using the source-hash keyword.
|
# using the source-hash keyword.
|
||||||
nat on fxp0 inet from any to any -> 192.0.2.16/28 source-hash
|
nat on $ext_if inet from any to any -> 192.0.2.16/28 source-hash
|
||||||
|
|
||||||
# RDR ROUND ROBIN
|
# RDR ROUND ROBIN
|
||||||
# Translate incoming web server connections to a group of web servers on
|
# Translate incoming web server connections to a group of web servers on
|
||||||
# the internal network.
|
# the internal network.
|
||||||
rdr on fxp0 proto tcp from any to any port 80 \e
|
rdr on $ext_if proto tcp from any to any port 80 \e
|
||||||
-> { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin
|
-> { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin
|
||||||
.Ed
|
.Ed
|
||||||
.Sh FILTER EXAMPLES
|
.Sh FILTER EXAMPLES
|
||||||
@ -2283,8 +2422,11 @@ option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
|
|||||||
[ "limit" ( limit-item | "{" limit-list "}" ) ] |
|
[ "limit" ( limit-item | "{" limit-list "}" ) ] |
|
||||||
[ "loginterface" ( interface-name | "none" ) ] |
|
[ "loginterface" ( interface-name | "none" ) ] |
|
||||||
[ "block-policy" ( "drop" | "return" ) ] |
|
[ "block-policy" ( "drop" | "return" ) ] |
|
||||||
|
[ "state-policy" ( "if-bound" | "group-bound" |
|
||||||
|
"floating" ) ]
|
||||||
[ "require-order" ( "yes" | "no" ) ]
|
[ "require-order" ( "yes" | "no" ) ]
|
||||||
[ "fingerprints" filename ] )
|
[ "fingerprints" filename ] |
|
||||||
|
[ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] )
|
||||||
|
|
||||||
pf-rule = action [ ( "in" | "out" ) ]
|
pf-rule = action [ ( "in" | "out" ) ]
|
||||||
[ "log" | "log-all" ] [ "quick" ]
|
[ "log" | "log-all" ] [ "quick" ]
|
||||||
@ -2299,7 +2441,7 @@ filteropt = user | group | flags | icmp-type | icmp6-type | tos |
|
|||||||
"max-mss" number | "random-id" | "reassemble tcp" |
|
"max-mss" number | "random-id" | "reassemble tcp" |
|
||||||
fragmentation | "allow-opts" |
|
fragmentation | "allow-opts" |
|
||||||
"label" string | "tag" string | [ ! ] "tagged" string
|
"label" string | "tag" string | [ ! ] "tagged" string
|
||||||
"queue" "(" string | ( string [ [ "," ] string ] ) ")"
|
"queue" ( string | "(" string [ [ "," ] string ] ")" )
|
||||||
|
|
||||||
nat-rule = [ "no" ] "nat" [ "pass" ] [ "on" ifspec ] [ af ]
|
nat-rule = [ "no" ] "nat" [ "pass" ] [ "on" ifspec ] [ af ]
|
||||||
[ protospec ] hosts [ "tag" string ]
|
[ protospec ] hosts [ "tag" string ]
|
||||||
@ -2341,7 +2483,7 @@ anchor-rule = "anchor" string [ ( "in" | "out" ) ] [ "on" ifspec ]
|
|||||||
trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string
|
trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string
|
||||||
[ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ]
|
[ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ]
|
||||||
|
|
||||||
load-anchor = "load" anchorname:rulesetname "from" filename
|
load-anchor = "load anchor" anchorname:rulesetname "from" filename
|
||||||
|
|
||||||
queueopts-list = queueopts-list queueopts | queueopts
|
queueopts-list = queueopts-list queueopts | queueopts
|
||||||
queueopts = [ "bandwidth" bandwidth-spec ] |
|
queueopts = [ "bandwidth" bandwidth-spec ] |
|
||||||
@ -2350,7 +2492,7 @@ queueopts = [ "bandwidth" bandwidth-spec ] |
|
|||||||
schedulers = ( cbq-def | priq-def | hfsc-def )
|
schedulers = ( cbq-def | priq-def | hfsc-def )
|
||||||
bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" )
|
bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" )
|
||||||
|
|
||||||
action = "pass" | "block" [ "return" ] | "scrub"
|
action = "pass" | "block" [ return ] | "scrub"
|
||||||
return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
|
return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
|
||||||
"return-icmp" [ "(" icmpcode ["," icmp6code ] ")" ] |
|
"return-icmp" [ "(" icmpcode ["," icmp6code ] ")" ] |
|
||||||
"return-icmp6" [ "(" icmp6code ")" ]
|
"return-icmp6" [ "(" icmp6code ")" ]
|
||||||
@ -2413,7 +2555,10 @@ tos = "tos" ( "lowdelay" | "throughput" | "reliability" |
|
|||||||
[ "0x" ] number )
|
[ "0x" ] number )
|
||||||
|
|
||||||
state-opts = state-opt [ [ "," ] state-opts ]
|
state-opts = state-opt [ [ "," ] state-opts ]
|
||||||
state-opt = ( "max" number ) | ( timeout )
|
state-opt = ( "max" number | "no-sync" | timeout |
|
||||||
|
"source-track" [ ( "rule" | "global" ) ] |
|
||||||
|
"max-src-nodes" number | "max-src-states" number |
|
||||||
|
"if-bound" | "group-bound" | "floating" )
|
||||||
|
|
||||||
fragmentation = [ "fragment reassemble" | "fragment crop" |
|
fragmentation = [ "fragment reassemble" | "fragment crop" |
|
||||||
"fragment drop-ovl" ]
|
"fragment drop-ovl" ]
|
||||||
@ -2424,15 +2569,15 @@ timeout = ( "tcp.first" | "tcp.opening" | "tcp.established" |
|
|||||||
"udp.first" | "udp.single" | "udp.multiple" |
|
"udp.first" | "udp.single" | "udp.multiple" |
|
||||||
"icmp.first" | "icmp.error" |
|
"icmp.first" | "icmp.error" |
|
||||||
"other.first" | "other.single" | "other.multiple" |
|
"other.first" | "other.single" | "other.multiple" |
|
||||||
"frag" | "interval" |
|
"frag" | "interval" | "src.track" |
|
||||||
"adaptive.start" | "adaptive.end" ) number
|
"adaptive.start" | "adaptive.end" ) number
|
||||||
|
|
||||||
limit-list = limit-item [ [ "," ] limit-list ]
|
limit-list = limit-item [ [ "," ] limit-list ]
|
||||||
limit-item = ( "states" | "frags" ) number
|
limit-item = ( "states" | "frags" | "src-nodes" ) number
|
||||||
|
|
||||||
pooltype = ( "bitmask" | "random" |
|
pooltype = ( "bitmask" | "random" |
|
||||||
"source-hash" [ ( hex-key | string-key ) ] |
|
"source-hash" [ ( hex-key | string-key ) ] |
|
||||||
"round-robin" )
|
"round-robin" ) [ sticky-address ]
|
||||||
|
|
||||||
subqueue = string | "{" queue-list "}"
|
subqueue = string | "{" queue-list "}"
|
||||||
queue-list = string [ [ "," ] string ]
|
queue-list = string [ [ "," ] string ]
|
||||||
@ -2470,6 +2615,7 @@ Example rulesets.
|
|||||||
.Xr ip 4 ,
|
.Xr ip 4 ,
|
||||||
.Xr ip6 4 ,
|
.Xr ip6 4 ,
|
||||||
.Xr pf 4 ,
|
.Xr pf 4 ,
|
||||||
|
.Xr pfsync 4 ,
|
||||||
.Xr tcp 4 ,
|
.Xr tcp 4 ,
|
||||||
.Xr udp 4 ,
|
.Xr udp 4 ,
|
||||||
.Xr hosts 5 ,
|
.Xr hosts 5 ,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pf.os.5,v 1.4 2003/08/28 09:41:23 jmc Exp $
|
.\" $OpenBSD: pf.os.5,v 1.5 2003/10/25 07:55:27 jmc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
.\" Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
||||||
.\"
|
.\"
|
||||||
@ -77,7 +77,7 @@ Allow any window size which is a multiple of the maximum transmission unit
|
|||||||
The
|
The
|
||||||
.Ar ttl
|
.Ar ttl
|
||||||
value is the initial time to live in the IP header.
|
value is the initial time to live in the IP header.
|
||||||
The fingerprint code will account for the volatility of the packets's TTL
|
The fingerprint code will account for the volatility of the packet's TTL
|
||||||
as it traverses a network.
|
as it traverses a network.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
|
@ -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
|
.\" Copyright (c) 2001 Tobias Weingartner
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
@ -30,19 +30,20 @@
|
|||||||
.Nm pflog
|
.Nm pflog
|
||||||
.Nd packet filter logging interface
|
.Nd packet filter logging interface
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Sy pseudo-device Nm pflog Em <number>
|
.Cd "pseudo-device pflog"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Nm pflog
|
.Nm pflog
|
||||||
interface is the interface the packet filter,
|
interface is a pseudo-device which makes visible all packets logged by
|
||||||
.Xr pf 4 ,
|
the packet filter,
|
||||||
copies all the packets to which it has been configured to log.
|
.Xr pf 4 .
|
||||||
In this way, all logged packets can easily be monitored in real
|
Logged packets can easily be monitored in real
|
||||||
time by invoking
|
time by invoking
|
||||||
.Xr tcpdump 8
|
.Xr tcpdump 8
|
||||||
on the
|
on the
|
||||||
.Nm
|
.Nm
|
||||||
interface.
|
interface, or stored to disk using
|
||||||
|
.Xr pflogd 8 .
|
||||||
.Pp
|
.Pp
|
||||||
Each packet retrieved on this interface has a header associated
|
Each packet retrieved on this interface has a header associated
|
||||||
with it of length
|
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
|
.\" Copyright (c) 2002 Michael Shalayeff
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
@ -30,19 +30,48 @@
|
|||||||
.Nm pfsync
|
.Nm pfsync
|
||||||
.Nd packet filter states table logging interface
|
.Nd packet filter states table logging interface
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Sy pseudo-device Nm pfsync
|
.Cd "pseudo-device pfsync"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Nm pfsync
|
.Nm
|
||||||
interface is the interface to the packet filter,
|
interface is a pseudo-device which exposes certain changes to the state
|
||||||
.Xr pf 4 ,
|
table used by
|
||||||
exposing all the changes to the state table.
|
.Xr pf 4 .
|
||||||
This allows for both debugging of rulesets and monitoring
|
State changes can be viewed by invoking
|
||||||
for changes in the table by invoking
|
|
||||||
.Xr tcpdump 8
|
.Xr tcpdump 8
|
||||||
on the
|
on the
|
||||||
.Nm
|
.Nm
|
||||||
interface.
|
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
|
.Pp
|
||||||
Each packet retrieved on this interface has a header associated
|
Each packet retrieved on this interface has a header associated
|
||||||
with it of length
|
with it of length
|
||||||
@ -61,16 +90,133 @@ struct pfsync_header {
|
|||||||
u_int8_t count;
|
u_int8_t count;
|
||||||
};
|
};
|
||||||
.Ed
|
.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
|
.Bd -literal -offset indent
|
||||||
# ifconfig pfsync0 up
|
# ifconfig pfsync0 syncif fxp0
|
||||||
# tcpdump -s1500 -evtni pfsync0
|
.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
|
.Ed
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
.Xr bpf 4 ,
|
||||||
.Xr inet 4 ,
|
.Xr inet 4 ,
|
||||||
.Xr inet6 4 ,
|
.Xr inet6 4 ,
|
||||||
.Xr netintro 4 ,
|
.Xr netintro 4 ,
|
||||||
.Xr pf 4 ,
|
.Xr pf 4 ,
|
||||||
|
.Xr hostname.if 5 ,
|
||||||
|
.Xr pf.conf 5 ,
|
||||||
|
.Xr protocols 5 ,
|
||||||
.Xr ifconfig 8 ,
|
.Xr ifconfig 8 ,
|
||||||
.Xr tcpdump 8
|
.Xr tcpdump 8
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pf_print_state.c,v 1.33 2003/07/06 22:01:28 deraadt Exp $ */
|
/* $OpenBSD: pf_print_state.c,v 1.39 2004/02/10 17:48:08 henning Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -50,9 +50,24 @@ void print_name(struct pf_addr *, sa_family_t);
|
|||||||
void
|
void
|
||||||
print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
||||||
{
|
{
|
||||||
switch(addr->type) {
|
switch (addr->type) {
|
||||||
case PF_ADDR_DYNIFTL:
|
case PF_ADDR_DYNIFTL:
|
||||||
printf("(%s)", addr->v.ifname);
|
printf("(%s", addr->v.ifname);
|
||||||
|
if (addr->iflags & PFI_AFLAG_NETWORK)
|
||||||
|
printf(":network");
|
||||||
|
if (addr->iflags & PFI_AFLAG_BROADCAST)
|
||||||
|
printf(":broadcast");
|
||||||
|
if (addr->iflags & PFI_AFLAG_PEER)
|
||||||
|
printf(":peer");
|
||||||
|
if (addr->iflags & PFI_AFLAG_NOALIAS)
|
||||||
|
printf(":0");
|
||||||
|
if (verbose) {
|
||||||
|
if (addr->p.dyncnt <= 0)
|
||||||
|
printf(":*");
|
||||||
|
else
|
||||||
|
printf(":%d", addr->p.dyncnt);
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
break;
|
break;
|
||||||
case PF_ADDR_TABLE:
|
case PF_ADDR_TABLE:
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -85,7 +100,10 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
|||||||
printf("?");
|
printf("?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (! PF_AZERO(&addr->v.a.mask, af)) {
|
|
||||||
|
/* mask if not _both_ address and mask are zero */
|
||||||
|
if (!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
|
||||||
|
PF_AZERO(&addr->v.a.mask, AF_INET6))) {
|
||||||
int bits = unmask(&addr->v.a.mask, af);
|
int bits = unmask(&addr->v.a.mask, af);
|
||||||
|
|
||||||
if (bits != (af == AF_INET ? 32 : 128))
|
if (bits != (af == AF_INET ? 32 : 128))
|
||||||
@ -140,8 +158,10 @@ print_host(struct pf_state_host *h, sa_family_t af, int opts)
|
|||||||
aw.v.a.addr = h->addr;
|
aw.v.a.addr = h->addr;
|
||||||
if (af == AF_INET)
|
if (af == AF_INET)
|
||||||
aw.v.a.mask.addr32[0] = 0xffffffff;
|
aw.v.a.mask.addr32[0] = 0xffffffff;
|
||||||
else
|
else {
|
||||||
memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
|
memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
|
||||||
|
af = AF_INET6;
|
||||||
|
}
|
||||||
print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
|
print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +197,7 @@ print_state(struct pf_state *s, int opts)
|
|||||||
src = &s->dst;
|
src = &s->dst;
|
||||||
dst = &s->src;
|
dst = &s->src;
|
||||||
}
|
}
|
||||||
|
printf("%s ", s->u.ifname);
|
||||||
if ((p = getprotobynumber(s->proto)) != NULL)
|
if ((p = getprotobynumber(s->proto)) != NULL)
|
||||||
printf("%s ", p->p_name);
|
printf("%s ", p->p_name);
|
||||||
else
|
else
|
||||||
@ -256,8 +277,16 @@ print_state(struct pf_state *s, int opts)
|
|||||||
printf(", anchor %u", s->anchor.nr);
|
printf(", anchor %u", s->anchor.nr);
|
||||||
if (s->rule.nr != -1)
|
if (s->rule.nr != -1)
|
||||||
printf(", rule %u", s->rule.nr);
|
printf(", rule %u", s->rule.nr);
|
||||||
|
if (s->src_node != NULL)
|
||||||
|
printf(", source-track");
|
||||||
|
if (s->nat_src_node != NULL)
|
||||||
|
printf(", sticky-address");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
if (opts & PF_OPT_VERBOSE2) {
|
||||||
|
printf(" id: %016llx creatorid: %08x\n",
|
||||||
|
betoh64(s->id), ntohl(s->creatorid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pfctl.8,v 1.102 2003/09/18 09:18:51 jmc Exp $
|
.\" $OpenBSD: pfctl.8,v 1.110 2004/03/20 09:31:42 david Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
|
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -33,15 +33,17 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm pfctl
|
.Nm pfctl
|
||||||
.Bk -words
|
.Bk -words
|
||||||
.Op Fl AdeghnNqrROvz
|
.Op Fl AdeghNnOqRrvz
|
||||||
.Op Fl a Ar anchor Ns Op Ar :ruleset
|
.Op Fl a Ar anchor Ns Op Ar :ruleset
|
||||||
.Op Fl D Ar macro=value
|
.Op Fl D Ar macro=value
|
||||||
.Op Fl f Ar file
|
|
||||||
.Op Fl F Ar modifier
|
.Op Fl F Ar modifier
|
||||||
|
.Op Fl f Ar file
|
||||||
|
.Op Fl i Ar interface
|
||||||
.Op Fl k Ar host
|
.Op Fl k Ar host
|
||||||
|
.Op Fl p Ar device
|
||||||
.Op Fl s Ar modifier
|
.Op Fl s Ar modifier
|
||||||
.Op Fl t Ar table
|
|
||||||
.Op Fl T Ar command Op Ar address ...
|
.Op Fl T Ar command Op Ar address ...
|
||||||
|
.Op Fl t Ar table
|
||||||
.Op Fl x Ar level
|
.Op Fl x Ar level
|
||||||
.Ek
|
.Ek
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -93,6 +95,9 @@ The
|
|||||||
utility provides several commands.
|
utility provides several commands.
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
.It Fl A
|
||||||
|
Load only the queue rules present in the rule file.
|
||||||
|
Other rules and options are ignored.
|
||||||
.It Fl a Ar anchor Ns Op Ar :ruleset
|
.It Fl a Ar anchor Ns Op Ar :ruleset
|
||||||
Apply flags
|
Apply flags
|
||||||
.Fl f ,
|
.Fl f ,
|
||||||
@ -134,11 +139,6 @@ This is similar to C rules for variables.
|
|||||||
It is possible to create distinct tables with the same name in the global
|
It is possible to create distinct tables with the same name in the global
|
||||||
ruleset and in an anchor, but this is often bad design and a warning will be
|
ruleset and in an anchor, but this is often bad design and a warning will be
|
||||||
issued in that case.
|
issued in that case.
|
||||||
.It Fl A
|
|
||||||
Load only the queue rules present in the rule file.
|
|
||||||
Other rules and options are ignored.
|
|
||||||
.It Fl d
|
|
||||||
Disable the packet filter.
|
|
||||||
.It Fl D Ar macro=value
|
.It Fl D Ar macro=value
|
||||||
Define
|
Define
|
||||||
.Ar macro
|
.Ar macro
|
||||||
@ -148,17 +148,10 @@ on the command line.
|
|||||||
Overrides the definition of
|
Overrides the definition of
|
||||||
.Ar macro
|
.Ar macro
|
||||||
in the ruleset.
|
in the ruleset.
|
||||||
|
.It Fl d
|
||||||
|
Disable the packet filter.
|
||||||
.It Fl e
|
.It Fl e
|
||||||
Enable the packet filter.
|
Enable the packet filter.
|
||||||
.It Fl f Ar file
|
|
||||||
Load the rules contained in
|
|
||||||
.Ar file .
|
|
||||||
This
|
|
||||||
.Ar file
|
|
||||||
may contain macros, tables, options, and normalization, queueing,
|
|
||||||
translation, and filtering rules.
|
|
||||||
With the exception of macros and tables, the statements must appear in that
|
|
||||||
order.
|
|
||||||
.It Fl F Ar modifier
|
.It Fl F Ar modifier
|
||||||
Flush the filter parameters specified by
|
Flush the filter parameters specified by
|
||||||
.Ar modifier
|
.Ar modifier
|
||||||
@ -173,6 +166,8 @@ Flush the queue rules.
|
|||||||
Flush the filter rules.
|
Flush the filter rules.
|
||||||
.It Fl F Ar state
|
.It Fl F Ar state
|
||||||
Flush the state table (NAT and filter).
|
Flush the state table (NAT and filter).
|
||||||
|
.It Fl F Ar Sources
|
||||||
|
Flush the source tracking table.
|
||||||
.It Fl F Ar info
|
.It Fl F Ar info
|
||||||
Flush the filter information (statistics that are not bound to rules).
|
Flush the filter information (statistics that are not bound to rules).
|
||||||
.It Fl F Ar Tables
|
.It Fl F Ar Tables
|
||||||
@ -182,8 +177,22 @@ Flush the passive operating system fingerprints.
|
|||||||
.It Fl F Ar all
|
.It Fl F Ar all
|
||||||
Flush all of the above.
|
Flush all of the above.
|
||||||
.El
|
.El
|
||||||
|
.It Fl f Ar file
|
||||||
|
Load the rules contained in
|
||||||
|
.Ar file .
|
||||||
|
This
|
||||||
|
.Ar file
|
||||||
|
may contain macros, tables, options, and normalization, queueing,
|
||||||
|
translation, and filtering rules.
|
||||||
|
With the exception of macros and tables, the statements must appear in that
|
||||||
|
order.
|
||||||
.It Fl g
|
.It Fl g
|
||||||
Include output helpful for debugging.
|
Include output helpful for debugging.
|
||||||
|
.It Fl h
|
||||||
|
Help.
|
||||||
|
.It Fl i Ar interface
|
||||||
|
Restrict the operation to the given
|
||||||
|
.Ar interface .
|
||||||
.It Fl k Ar host
|
.It Fl k Ar host
|
||||||
Kill all of the state entries originating from the specified
|
Kill all of the state entries originating from the specified
|
||||||
.Ar host .
|
.Ar host .
|
||||||
@ -207,29 +216,32 @@ to
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# pfctl -k host1 -k host2
|
# pfctl -k host1 -k host2
|
||||||
.Ed
|
.Ed
|
||||||
.It Fl h
|
|
||||||
Help.
|
|
||||||
.It Fl n
|
|
||||||
Do not actually load rules, just parse them.
|
|
||||||
.It Fl N
|
.It Fl N
|
||||||
Load only the NAT rules present in the rule file.
|
Load only the NAT rules present in the rule file.
|
||||||
Other rules and options are ignored.
|
Other rules and options are ignored.
|
||||||
.It Fl q
|
.It Fl n
|
||||||
Only print errors and warnings.
|
Do not actually load rules, just parse them.
|
||||||
.It Fl r
|
|
||||||
Perform reverse DNS lookups on states when displaying them.
|
|
||||||
.It Fl R
|
|
||||||
Load only the filter rules present in the rule file.
|
|
||||||
Other rules and options are ignored.
|
|
||||||
.It Fl O
|
.It Fl O
|
||||||
Load only the options present in the rule file.
|
Load only the options present in the rule file.
|
||||||
Other rules and options are ignored.
|
Other rules and options are ignored.
|
||||||
|
.It Fl p Ar device
|
||||||
|
Use the device file
|
||||||
|
.Ar device
|
||||||
|
instead of the default
|
||||||
|
.Pa /dev/pf .
|
||||||
|
.It Fl q
|
||||||
|
Only print errors and warnings.
|
||||||
|
.It Fl R
|
||||||
|
Load only the filter rules present in the rule file.
|
||||||
|
Other rules and options are ignored.
|
||||||
|
.It Fl r
|
||||||
|
Perform reverse DNS lookups on states when displaying them.
|
||||||
.It Fl s Ar modifier
|
.It Fl s Ar modifier
|
||||||
Show the filter parameters specified by
|
Show the filter parameters specified by
|
||||||
.Ar modifier
|
.Ar modifier
|
||||||
(may be abbreviated):
|
(may be abbreviated):
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width xxxxxxxxxxxx -compact
|
.Bl -tag -width xxxxxxxxxxxxx -compact
|
||||||
.It Fl s Ar nat
|
.It Fl s Ar nat
|
||||||
Show the currently loaded NAT rules.
|
Show the currently loaded NAT rules.
|
||||||
.It Fl s Ar queue
|
.It Fl s Ar queue
|
||||||
@ -261,8 +273,13 @@ is specified as well, the named rulesets currently loaded in the specified
|
|||||||
anchor are shown instead.
|
anchor are shown instead.
|
||||||
.It Fl s Ar state
|
.It Fl s Ar state
|
||||||
Show the contents of the state table.
|
Show the contents of the state table.
|
||||||
|
.It Fl s Ar Sources
|
||||||
|
Show the contents of the source tracking table.
|
||||||
.It Fl s Ar info
|
.It Fl s Ar info
|
||||||
Show filter information (statistics and counters).
|
Show filter information (statistics and counters).
|
||||||
|
When used together with
|
||||||
|
.Fl v ,
|
||||||
|
source tracking statistics are also shown.
|
||||||
.It Fl s Ar labels
|
.It Fl s Ar labels
|
||||||
Show per-rule statistics (label, evaluations, packets, bytes) of
|
Show per-rule statistics (label, evaluations, packets, bytes) of
|
||||||
filter rules with labels, useful for accounting.
|
filter rules with labels, useful for accounting.
|
||||||
@ -274,16 +291,17 @@ Show the current pool memory hard limits.
|
|||||||
Show the list of tables.
|
Show the list of tables.
|
||||||
.It Fl s Ar osfp
|
.It Fl s Ar osfp
|
||||||
Show the list of operating system fingerprints.
|
Show the list of operating system fingerprints.
|
||||||
Can be used in combination with
|
.It Fl s Ar Interfaces
|
||||||
.Fl o Ar file
|
Show the list of interfaces and interface drivers available to PF.
|
||||||
to list the fingerprints in a
|
When used together with a double
|
||||||
.Xr pf.os 5
|
.Fl v ,
|
||||||
file.
|
interface statistics are also shown.
|
||||||
|
.Fl i
|
||||||
|
can be used to select an interface or a group of interfaces.
|
||||||
.It Fl s Ar all
|
.It Fl s Ar all
|
||||||
Show all of the above.
|
Show all of the above, except for the lists of interfaces and operating
|
||||||
|
system fingerprints.
|
||||||
.El
|
.El
|
||||||
.It Fl t Ar table
|
|
||||||
Specify the name of the table.
|
|
||||||
.It Fl T Ar command Op Ar address ...
|
.It Fl T Ar command Op Ar address ...
|
||||||
Specify the
|
Specify the
|
||||||
.Ar command
|
.Ar command
|
||||||
@ -334,7 +352,7 @@ Comments starting with a "#" are allowed in the text file.
|
|||||||
With these commands, the
|
With these commands, the
|
||||||
.Fl v
|
.Fl v
|
||||||
flag can also be used once or twice, in which case
|
flag can also be used once or twice, in which case
|
||||||
.Nm pfctl
|
.Nm
|
||||||
will print the
|
will print the
|
||||||
detailed result of the operation for each individual address, prefixed by
|
detailed result of the operation for each individual address, prefixed by
|
||||||
one of the following letters:
|
one of the following letters:
|
||||||
@ -359,7 +377,7 @@ The address/network has been cleared (statistics).
|
|||||||
Each table maintains a set of counters that can be retrieved using the
|
Each table maintains a set of counters that can be retrieved using the
|
||||||
.Fl v
|
.Fl v
|
||||||
flag of
|
flag of
|
||||||
.Nm pfctl .
|
.Nm .
|
||||||
For example, the following commands define a wide open firewall which will keep
|
For example, the following commands define a wide open firewall which will keep
|
||||||
track of packets going to or coming from the
|
track of packets going to or coming from the
|
||||||
.Ox
|
.Ox
|
||||||
@ -367,8 +385,8 @@ ftp server.
|
|||||||
The following commands configure the firewall and send 10 pings to the ftp
|
The following commands configure the firewall and send 10 pings to the ftp
|
||||||
server:
|
server:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# printf \&"table <test> { ftp.openbsd.org }\en \e
|
# printf "table <test> { ftp.openbsd.org }\en \e
|
||||||
\ \ pass out to <test> keep state\en" \&| pfctl -f-
|
pass out to <test> keep state\en" | pfctl -f-
|
||||||
# ping -qc10 ftp.openbsd.org
|
# ping -qc10 ftp.openbsd.org
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
@ -381,12 +399,12 @@ The time at which the current accounting started is also shown with the
|
|||||||
line.
|
line.
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# pfctl -t test -vTshow
|
# pfctl -t test -vTshow
|
||||||
\ \ \ 129.128.5.191
|
129.128.5.191
|
||||||
\ \ \ \ Cleared: \ \ \ \ Thu Feb 13 18:55:18 2003
|
Cleared: Thu Feb 13 18:55:18 2003
|
||||||
\ \ \ \ In/Block: \ \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ]
|
In/Block: [ Packets: 0 Bytes: 0 ]
|
||||||
\ \ \ \ In/Pass: \ \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ]
|
In/Pass: [ Packets: 10 Bytes: 840 ]
|
||||||
\ \ \ \ Out/Block: \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ]
|
Out/Block: [ Packets: 0 Bytes: 0 ]
|
||||||
\ \ \ \ Out/Pass: \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ]
|
Out/Pass: [ Packets: 10 Bytes: 840 ]
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Similarly, it is possible to view global information about the tables
|
Similarly, it is possible to view global information about the tables
|
||||||
@ -401,19 +419,19 @@ packet statistics for the whole table:
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# pfctl -vvsTables
|
# pfctl -vvsTables
|
||||||
--a-r- test
|
--a-r- test
|
||||||
\ \ \ \ Addresses: \ \ 1
|
Addresses: 1
|
||||||
\ \ \ \ Cleared: \ \ \ \ Thu Feb 13 18:55:18 2003
|
Cleared: Thu Feb 13 18:55:18 2003
|
||||||
\ \ \ \ References: \ [ Anchors: 0 \ \ \ \ \ \ \ Rules: 1 \ \ \ \ \ \ \ ]
|
References: [ Anchors: 0 Rules: 1 ]
|
||||||
\ \ \ \ Evaluations: [ NoMatch: 3496 \ \ \ \ Match: 1 \ \ \ \ \ \ \ ]
|
Evaluations: [ NoMatch: 3496 Match: 1 ]
|
||||||
\ \ \ \ In/Block: \ \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ]
|
In/Block: [ Packets: 0 Bytes: 0 ]
|
||||||
\ \ \ \ In/Pass: \ \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ]
|
In/Pass: [ Packets: 10 Bytes: 840 ]
|
||||||
\ \ \ \ In/XPass: \ \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ]
|
In/XPass: [ Packets: 0 Bytes: 0 ]
|
||||||
\ \ \ \ Out/Block: \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ]
|
Out/Block: [ Packets: 0 Bytes: 0 ]
|
||||||
\ \ \ \ Out/Pass: \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ]
|
Out/Pass: [ Packets: 10 Bytes: 840 ]
|
||||||
\ \ \ \ Out/XPass: \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ]
|
Out/XPass: [ Packets: 0 Bytes: 0 ]
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
As we can see here, only one packet - the initial ping request - matched the
|
As we can see here, only one packet \- the initial ping request \- matched the
|
||||||
table; but all packets passing as the result of the state are correctly
|
table; but all packets passing as the result of the state are correctly
|
||||||
accounted for.
|
accounted for.
|
||||||
Reloading the table(s) or ruleset will not affect packet accounting in any way.
|
Reloading the table(s) or ruleset will not affect packet accounting in any way.
|
||||||
@ -421,14 +439,14 @@ The two
|
|||||||
.Ar XPass
|
.Ar XPass
|
||||||
counters are incremented instead of the
|
counters are incremented instead of the
|
||||||
.Ar Pass
|
.Ar Pass
|
||||||
counters when a \&"stateful\&" packet is passed but doesn't match the table
|
counters when a "stateful" packet is passed but doesn't match the table
|
||||||
anymore.
|
anymore.
|
||||||
This will happen in our example if someone flushes the table while the ping
|
This will happen in our example if someone flushes the table while the ping
|
||||||
command is running.
|
command is running.
|
||||||
.Pp
|
.Pp
|
||||||
When used with a single
|
When used with a single
|
||||||
.Fl v ,
|
.Fl v ,
|
||||||
.Nm pfctl
|
.Nm
|
||||||
will only display the first line containing the table flags and name.
|
will only display the first line containing the table flags and name.
|
||||||
The flags are defined as follows:
|
The flags are defined as follows:
|
||||||
.Pp
|
.Pp
|
||||||
@ -459,6 +477,8 @@ For tables which are referenced (used) by rules.
|
|||||||
This flag is set when a table in the main ruleset is hidden by one or more
|
This flag is set when a table in the main ruleset is hidden by one or more
|
||||||
tables of the same name in sub-rulesets (anchors).
|
tables of the same name in sub-rulesets (anchors).
|
||||||
.El
|
.El
|
||||||
|
.It Fl t Ar table
|
||||||
|
Specify the name of the table.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Produce more verbose output.
|
Produce more verbose output.
|
||||||
A second use of
|
A second use of
|
||||||
|
@ -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) 2001 Daniel Hartmeier
|
||||||
|
* Copyright (c) 2002,2003 Henning Brauer
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -60,17 +61,19 @@ int pfctl_clear_stats(int, int);
|
|||||||
int pfctl_clear_rules(int, int, char *, char *);
|
int pfctl_clear_rules(int, int, char *, char *);
|
||||||
int pfctl_clear_nat(int, int, char *, char *);
|
int pfctl_clear_nat(int, int, char *, char *);
|
||||||
int pfctl_clear_altq(int, int);
|
int pfctl_clear_altq(int, int);
|
||||||
int pfctl_clear_states(int, int);
|
int pfctl_clear_src_nodes(int, int);
|
||||||
int pfctl_kill_states(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,
|
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);
|
void pfctl_print_rule_counters(struct pf_rule *, int);
|
||||||
int pfctl_show_rules(int, int, int, char *, char *);
|
int pfctl_show_rules(int, int, int, char *, char *);
|
||||||
int pfctl_show_nat(int, int, char *, char *);
|
int pfctl_show_nat(int, int, char *, char *);
|
||||||
int pfctl_show_states(int, u_int8_t, int);
|
int pfctl_show_src_nodes(int, int);
|
||||||
int pfctl_show_status(int);
|
int pfctl_show_states(int, const char *, int);
|
||||||
int pfctl_show_timeouts(int);
|
int pfctl_show_status(int, int);
|
||||||
int pfctl_show_limits(int);
|
int pfctl_show_timeouts(int, int);
|
||||||
|
int pfctl_show_limits(int, int);
|
||||||
int pfctl_debug(int, u_int32_t, int);
|
int pfctl_debug(int, u_int32_t, int);
|
||||||
int pfctl_clear_rule_counters(int, int);
|
int pfctl_clear_rule_counters(int, int);
|
||||||
int pfctl_test_altqsupport(int, int);
|
int pfctl_test_altqsupport(int, int);
|
||||||
@ -82,6 +85,8 @@ char *rulesopt;
|
|||||||
const char *showopt;
|
const char *showopt;
|
||||||
const char *debugopt;
|
const char *debugopt;
|
||||||
char *anchoropt;
|
char *anchoropt;
|
||||||
|
char *pf_device = "/dev/pf";
|
||||||
|
char *ifaceopt;
|
||||||
char *tableopt;
|
char *tableopt;
|
||||||
const char *tblcmdopt;
|
const char *tblcmdopt;
|
||||||
int state_killers;
|
int state_killers;
|
||||||
@ -90,6 +95,8 @@ int loadopt;
|
|||||||
int altqsupport;
|
int altqsupport;
|
||||||
|
|
||||||
int dev = -1;
|
int dev = -1;
|
||||||
|
int first_title = 1;
|
||||||
|
int labels = 0;
|
||||||
|
|
||||||
const char *infile;
|
const char *infile;
|
||||||
|
|
||||||
@ -98,6 +105,7 @@ static const struct {
|
|||||||
int index;
|
int index;
|
||||||
} pf_limits[] = {
|
} pf_limits[] = {
|
||||||
{ "states", PF_LIMIT_STATES },
|
{ "states", PF_LIMIT_STATES },
|
||||||
|
{ "src-nodes", PF_LIMIT_SRC_NODES },
|
||||||
{ "frags", PF_LIMIT_FRAGS },
|
{ "frags", PF_LIMIT_FRAGS },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
@ -156,12 +164,14 @@ static const struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char *clearopt_list[] = {
|
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[] = {
|
static const char *showopt_list[] = {
|
||||||
"nat", "queue", "rules", "Anchors", "state", "info", "labels",
|
"nat", "queue", "rules", "Anchors", "Sources", "state", "info",
|
||||||
"timeouts", "memory", "Tables", "osfp", "all", NULL
|
"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
|
||||||
|
"all", NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *tblcmdopt_list[] = {
|
static const char *tblcmdopt_list[] = {
|
||||||
@ -179,12 +189,14 @@ usage(void)
|
|||||||
{
|
{
|
||||||
extern char *__progname;
|
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, "[-a anchor[:ruleset]] [-D macro=value]\n");
|
||||||
fprintf(stderr, " ");
|
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, " ");
|
||||||
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +251,7 @@ pfctl_clear_stats(int dev, int opts)
|
|||||||
int
|
int
|
||||||
pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
|
pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
|
||||||
{
|
{
|
||||||
struct pfioc_rule pr;
|
struct pfr_buffer t;
|
||||||
|
|
||||||
if (*anchorname && !*rulesetname) {
|
if (*anchorname && !*rulesetname) {
|
||||||
struct pfioc_ruleset pr;
|
struct pfioc_ruleset pr;
|
||||||
@ -269,19 +281,13 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
|
|||||||
fprintf(stderr, "rules cleared\n");
|
fprintf(stderr, "rules cleared\n");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
memset(&pr, 0, sizeof(pr));
|
memset(&t, 0, sizeof(t));
|
||||||
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
|
t.pfrb_type = PFRB_TRANS;
|
||||||
memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
|
if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname, rulesetname) ||
|
||||||
pr.rule.action = PF_SCRUB;
|
pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname, rulesetname) ||
|
||||||
if (ioctl(dev, DIOCBEGINRULES, &pr))
|
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
|
||||||
err(1, "DIOCBEGINRULES");
|
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
|
||||||
else if (ioctl(dev, DIOCCOMMITRULES, &pr))
|
err(1, "pfctl_clear_rules");
|
||||||
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");
|
|
||||||
if ((opts & PF_OPT_QUIET) == 0)
|
if ((opts & PF_OPT_QUIET) == 0)
|
||||||
fprintf(stderr, "rules cleared\n");
|
fprintf(stderr, "rules cleared\n");
|
||||||
return (0);
|
return (0);
|
||||||
@ -290,7 +296,7 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
|
|||||||
int
|
int
|
||||||
pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
||||||
{
|
{
|
||||||
struct pfioc_rule pr;
|
struct pfr_buffer t;
|
||||||
|
|
||||||
if (*anchorname && !*rulesetname) {
|
if (*anchorname && !*rulesetname) {
|
||||||
struct pfioc_ruleset pr;
|
struct pfioc_ruleset pr;
|
||||||
@ -320,24 +326,14 @@ pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
|||||||
fprintf(stderr, "nat cleared\n");
|
fprintf(stderr, "nat cleared\n");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
memset(&pr, 0, sizeof(pr));
|
memset(&t, 0, sizeof(t));
|
||||||
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
|
t.pfrb_type = PFRB_TRANS;
|
||||||
memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
|
if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname, rulesetname) ||
|
||||||
pr.rule.action = PF_NAT;
|
pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname, rulesetname) ||
|
||||||
if (ioctl(dev, DIOCBEGINRULES, &pr))
|
pfctl_add_trans(&t, PF_RULESET_RDR, anchorname, rulesetname) ||
|
||||||
err(1, "DIOCBEGINRULES");
|
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
|
||||||
else if (ioctl(dev, DIOCCOMMITRULES, &pr))
|
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
|
||||||
err(1, "DIOCCOMMITRULES");
|
err(1, "pfctl_clear_nat");
|
||||||
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");
|
|
||||||
if ((opts & PF_OPT_QUIET) == 0)
|
if ((opts & PF_OPT_QUIET) == 0)
|
||||||
fprintf(stderr, "nat cleared\n");
|
fprintf(stderr, "nat cleared\n");
|
||||||
return (0);
|
return (0);
|
||||||
@ -346,32 +342,50 @@ pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
|||||||
int
|
int
|
||||||
pfctl_clear_altq(int dev, int opts)
|
pfctl_clear_altq(int dev, int opts)
|
||||||
{
|
{
|
||||||
struct pfioc_altq pa;
|
struct pfr_buffer t;
|
||||||
|
|
||||||
if (!altqsupport)
|
if (!altqsupport)
|
||||||
return (-1);
|
return (-1);
|
||||||
memset(&pa, 0, sizeof(pa));
|
memset(&t, 0, sizeof(t));
|
||||||
if (ioctl(dev, DIOCBEGINALTQS, &pa.ticket))
|
t.pfrb_type = PFRB_TRANS;
|
||||||
err(1, "DIOCBEGINALTQS");
|
if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "", "") ||
|
||||||
else if (ioctl(dev, DIOCCOMMITALTQS, &pa.ticket))
|
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
|
||||||
err(1, "DIOCCOMMITALTQS");
|
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
|
||||||
|
err(1, "pfctl_clear_altq");
|
||||||
if ((opts & PF_OPT_QUIET) == 0)
|
if ((opts & PF_OPT_QUIET) == 0)
|
||||||
fprintf(stderr, "altq cleared\n");
|
fprintf(stderr, "altq cleared\n");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_clear_states(int dev, int opts)
|
pfctl_clear_src_nodes(int dev, int opts)
|
||||||
{
|
{
|
||||||
if (ioctl(dev, DIOCCLRSTATES))
|
if (ioctl(dev, DIOCCLRSRCNODES))
|
||||||
err(1, "DIOCCLRSTATES");
|
err(1, "DIOCCLRSRCNODES");
|
||||||
if ((opts & PF_OPT_QUIET) == 0)
|
if ((opts & PF_OPT_QUIET) == 0)
|
||||||
fprintf(stderr, "states cleared\n");
|
fprintf(stderr, "source tracking entries cleared\n");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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 pfioc_state_kill psk;
|
||||||
struct addrinfo *res[2], *resp[2];
|
struct addrinfo *res[2], *resp[2];
|
||||||
@ -386,6 +400,9 @@ pfctl_kill_states(int dev, int opts)
|
|||||||
sizeof(psk.psk_src.addr.v.a.mask));
|
sizeof(psk.psk_src.addr.v.a.mask));
|
||||||
memset(&last_src, 0xff, sizeof(last_src));
|
memset(&last_src, 0xff, sizeof(last_src));
|
||||||
memset(&last_dst, 0xff, sizeof(last_dst));
|
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]))) {
|
if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
|
||||||
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
|
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
|
||||||
@ -419,7 +436,8 @@ pfctl_kill_states(int dev, int opts)
|
|||||||
memset(&last_dst, 0xff, sizeof(last_dst));
|
memset(&last_dst, 0xff, sizeof(last_dst));
|
||||||
if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
|
if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
|
||||||
&res[1]))) {
|
&res[1]))) {
|
||||||
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
|
errx(1, "getaddrinfo: %s",
|
||||||
|
gai_strerror(ret_ga));
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
for (resp[1] = res[1]; resp[1];
|
for (resp[1] = res[1]; resp[1];
|
||||||
@ -545,8 +563,18 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts)
|
|||||||
if (opts & PF_OPT_VERBOSE)
|
if (opts & PF_OPT_VERBOSE)
|
||||||
printf(" [ Evaluations: %-8llu Packets: %-8llu "
|
printf(" [ Evaluations: %-8llu Packets: %-8llu "
|
||||||
"Bytes: %-10llu States: %-6u]\n",
|
"Bytes: %-10llu States: %-6u]\n",
|
||||||
rule->evaluations, rule->packets,
|
(unsigned long long)rule->evaluations,
|
||||||
rule->bytes, rule->states);
|
(unsigned long long)rule->packets,
|
||||||
|
(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
|
int
|
||||||
@ -554,7 +582,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
|||||||
char *rulesetname)
|
char *rulesetname)
|
||||||
{
|
{
|
||||||
struct pfioc_rule pr;
|
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);
|
int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
|
||||||
|
|
||||||
if (*anchorname && !*rulesetname) {
|
if (*anchorname && !*rulesetname) {
|
||||||
@ -571,6 +599,8 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
|||||||
err(1, "DIOCGETRULESETS");
|
err(1, "DIOCGETRULESETS");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
if (opts & PF_OPT_SHOWALL && pr.nr)
|
||||||
|
pfctl_print_title("FILTER RULES:");
|
||||||
mnr = pr.nr;
|
mnr = pr.nr;
|
||||||
for (nr = 0; nr < mnr; ++nr) {
|
for (nr = 0; nr < mnr; ++nr) {
|
||||||
pr.nr = nr;
|
pr.nr = nr;
|
||||||
@ -587,11 +617,25 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
|||||||
memset(&pr, 0, sizeof(pr));
|
memset(&pr, 0, sizeof(pr));
|
||||||
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
|
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
|
||||||
memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
|
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;
|
pr.rule.action = PF_SCRUB;
|
||||||
if (ioctl(dev, DIOCGETRULES, &pr)) {
|
if (ioctl(dev, DIOCGETRULES, &pr)) {
|
||||||
warn("DIOCGETRULES");
|
warn("DIOCGETRULES");
|
||||||
return (-1);
|
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;
|
mnr = pr.nr;
|
||||||
for (nr = 0; nr < mnr; ++nr) {
|
for (nr = 0; nr < mnr; ++nr) {
|
||||||
pr.nr = nr;
|
pr.nr = nr;
|
||||||
@ -609,11 +653,14 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
|||||||
if (pr.rule.label[0]) {
|
if (pr.rule.label[0]) {
|
||||||
printf("%s ", pr.rule.label);
|
printf("%s ", pr.rule.label);
|
||||||
printf("%llu %llu %llu\n",
|
printf("%llu %llu %llu\n",
|
||||||
pr.rule.evaluations, pr.rule.packets,
|
(unsigned long long)pr.rule.evaluations,
|
||||||
pr.rule.bytes);
|
(unsigned long long)pr.rule.packets,
|
||||||
|
(unsigned long long)pr.rule.bytes);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
|
||||||
|
labels = 1;
|
||||||
print_rule(&pr.rule, rule_numbers);
|
print_rule(&pr.rule, rule_numbers);
|
||||||
pfctl_print_rule_counters(&pr.rule, opts);
|
pfctl_print_rule_counters(&pr.rule, opts);
|
||||||
}
|
}
|
||||||
@ -641,11 +688,14 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
|
|||||||
if (pr.rule.label[0]) {
|
if (pr.rule.label[0]) {
|
||||||
printf("%s ", pr.rule.label);
|
printf("%s ", pr.rule.label);
|
||||||
printf("%llu %llu %llu\n",
|
printf("%llu %llu %llu\n",
|
||||||
pr.rule.evaluations, pr.rule.packets,
|
(unsigned long long)pr.rule.evaluations,
|
||||||
pr.rule.bytes);
|
(unsigned long long)pr.rule.packets,
|
||||||
|
(unsigned long long)pr.rule.bytes);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
|
||||||
|
labels = 1;
|
||||||
print_rule(&pr.rule, rule_numbers);
|
print_rule(&pr.rule, rule_numbers);
|
||||||
pfctl_print_rule_counters(&pr.rule, opts);
|
pfctl_print_rule_counters(&pr.rule, opts);
|
||||||
}
|
}
|
||||||
@ -660,7 +710,7 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
|||||||
struct pfioc_rule pr;
|
struct pfioc_rule pr;
|
||||||
u_int32_t mnr, nr;
|
u_int32_t mnr, nr;
|
||||||
static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
|
static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
|
||||||
int i;
|
int i, dotitle = opts & PF_OPT_SHOWALL;
|
||||||
|
|
||||||
if (*anchorname && !*rulesetname) {
|
if (*anchorname && !*rulesetname) {
|
||||||
struct pfioc_ruleset pr;
|
struct pfioc_ruleset pr;
|
||||||
@ -708,6 +758,10 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
|||||||
pr.ticket, nattype[i], anchorname,
|
pr.ticket, nattype[i], anchorname,
|
||||||
rulesetname) != 0)
|
rulesetname) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
if (dotitle) {
|
||||||
|
pfctl_print_title("TRANSLATION RULES:");
|
||||||
|
dotitle = 0;
|
||||||
|
}
|
||||||
print_rule(&pr.rule, opts & PF_OPT_VERBOSE2);
|
print_rule(&pr.rule, opts & PF_OPT_VERBOSE2);
|
||||||
pfctl_print_rule_counters(&pr.rule, opts);
|
pfctl_print_rule_counters(&pr.rule, opts);
|
||||||
pfctl_clear_pool(&pr.rule.rpool);
|
pfctl_clear_pool(&pr.rule.rpool);
|
||||||
@ -717,21 +771,64 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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 pfioc_states ps;
|
||||||
struct pf_state *p;
|
struct pf_state *p;
|
||||||
char *inbuf = NULL;
|
char *inbuf = NULL, *newinbuf = NULL;
|
||||||
unsigned len = 0;
|
unsigned len = 0;
|
||||||
int i;
|
int i, dotitle = (opts & PF_OPT_SHOWALL);
|
||||||
|
|
||||||
memset(&ps, 0, sizeof(ps));
|
memset(&ps, 0, sizeof(ps));
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ps.ps_len = len;
|
ps.ps_len = len;
|
||||||
if (len) {
|
if (len) {
|
||||||
ps.ps_buf = inbuf = realloc(inbuf, len);
|
newinbuf = realloc(inbuf, len);
|
||||||
if (inbuf == NULL)
|
if (newinbuf == NULL)
|
||||||
err(1, "realloc");
|
err(1, "realloc");
|
||||||
|
ps.ps_buf = inbuf = newinbuf;
|
||||||
}
|
}
|
||||||
if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
|
if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
|
||||||
warn("DIOCGETSTATES");
|
warn("DIOCGETSTATES");
|
||||||
@ -748,16 +845,20 @@ pfctl_show_states(int dev, u_int8_t proto, int opts)
|
|||||||
len *= 2;
|
len *= 2;
|
||||||
}
|
}
|
||||||
p = ps.ps_states;
|
p = ps.ps_states;
|
||||||
for (i = 0; i < ps.ps_len; i += sizeof(*p)) {
|
for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
|
||||||
if (!proto || (p->proto == proto))
|
if (iface != NULL && strcmp(p->u.ifname, iface))
|
||||||
print_state(p, opts);
|
continue;
|
||||||
p++;
|
if (dotitle) {
|
||||||
|
pfctl_print_title("STATES:");
|
||||||
|
dotitle = 0;
|
||||||
|
}
|
||||||
|
print_state(p, opts);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_show_status(int dev)
|
pfctl_show_status(int dev, int opts)
|
||||||
{
|
{
|
||||||
struct pf_status status;
|
struct pf_status status;
|
||||||
|
|
||||||
@ -765,16 +866,20 @@ pfctl_show_status(int dev)
|
|||||||
warn("DIOCGETSTATUS");
|
warn("DIOCGETSTATUS");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
print_status(&status);
|
if (opts & PF_OPT_SHOWALL)
|
||||||
|
pfctl_print_title("INFO:");
|
||||||
|
print_status(&status, opts);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_show_timeouts(int dev)
|
pfctl_show_timeouts(int dev, int opts)
|
||||||
{
|
{
|
||||||
struct pfioc_tm pt;
|
struct pfioc_tm pt;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (opts & PF_OPT_SHOWALL)
|
||||||
|
pfctl_print_title("TIMEOUTS:");
|
||||||
memset(&pt, 0, sizeof(pt));
|
memset(&pt, 0, sizeof(pt));
|
||||||
for (i = 0; pf_timeouts[i].name; i++) {
|
for (i = 0; pf_timeouts[i].name; i++) {
|
||||||
pt.timeout = pf_timeouts[i].timeout;
|
pt.timeout = pf_timeouts[i].timeout;
|
||||||
@ -792,14 +897,16 @@ pfctl_show_timeouts(int dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_show_limits(int dev)
|
pfctl_show_limits(int dev, int opts)
|
||||||
{
|
{
|
||||||
struct pfioc_limit pl;
|
struct pfioc_limit pl;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (opts & PF_OPT_SHOWALL)
|
||||||
|
pfctl_print_title("LIMITS:");
|
||||||
memset(&pl, 0, sizeof(pl));
|
memset(&pl, 0, sizeof(pl));
|
||||||
for (i = 0; pf_limits[i].name; i++) {
|
for (i = 0; pf_limits[i].name; i++) {
|
||||||
pl.index = i;
|
pl.index = pf_limits[i].index;
|
||||||
if (ioctl(dev, DIOCGETLIMIT, &pl))
|
if (ioctl(dev, DIOCGETLIMIT, &pl))
|
||||||
err(1, "DIOCGETLIMIT");
|
err(1, "DIOCGETLIMIT");
|
||||||
printf("%-10s ", pf_limits[i].name);
|
printf("%-10s ", pf_limits[i].name);
|
||||||
@ -836,7 +943,8 @@ pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
|
|||||||
int
|
int
|
||||||
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
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) {
|
switch (r->action) {
|
||||||
case PF_SCRUB:
|
case PF_SCRUB:
|
||||||
@ -874,12 +982,19 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((pf->opts & PF_OPT_NOACTION) == 0) {
|
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))
|
if (pfctl_add_pool(pf, &r->rpool, r->af))
|
||||||
return (1);
|
return (1);
|
||||||
memcpy(&pf->prule[rs_num]->rule, r,
|
pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
|
||||||
sizeof(pf->prule[rs_num]->rule));
|
pf->ruleset);
|
||||||
pf->prule[rs_num]->pool_ticket = pf->paddr.ticket;
|
pr.pool_ticket = pf->paddr.ticket;
|
||||||
if (ioctl(pf->dev, DIOCADDRULE, pf->prule[rs_num]))
|
memcpy(&pr.rule, r, sizeof(pr.rule));
|
||||||
|
if (ioctl(pf->dev, DIOCADDRULE, &pr))
|
||||||
err(1, "DIOCADDRULE");
|
err(1, "DIOCADDRULE");
|
||||||
}
|
}
|
||||||
if (pf->opts & PF_OPT_VERBOSE)
|
if (pf->opts & PF_OPT_VERBOSE)
|
||||||
@ -912,26 +1027,31 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
|
|||||||
|
|
||||||
int
|
int
|
||||||
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
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 ERR(x) do { warn(x); goto _error; } while(0)
|
||||||
#define ERRX(x) do { warnx(x); goto _error; } while(0)
|
#define ERRX(x) do { warnx(x); goto _error; } while(0)
|
||||||
|
|
||||||
FILE *fin;
|
FILE *fin;
|
||||||
struct pfioc_rule pr[PF_RULESET_MAX];
|
struct pfr_buffer *t, buf;
|
||||||
struct pfioc_altq pa;
|
struct pfioc_altq pa;
|
||||||
struct pfctl pf;
|
struct pfctl pf;
|
||||||
struct pfr_table trs;
|
struct pfr_table trs;
|
||||||
int i;
|
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(&pa, 0, sizeof(pa));
|
||||||
memset(&pf, 0, sizeof(pf));
|
memset(&pf, 0, sizeof(pf));
|
||||||
memset(&trs, 0, sizeof(trs));
|
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,
|
if (strlcpy(trs.pfrt_anchor, anchorname,
|
||||||
sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) ||
|
sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) ||
|
||||||
strlcpy(trs.pfrt_ruleset, rulesetname,
|
strlcpy(trs.pfrt_ruleset, rulesetname,
|
||||||
@ -947,46 +1067,53 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
|||||||
}
|
}
|
||||||
infile = filename;
|
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.dev = dev;
|
||||||
pf.opts = opts;
|
pf.opts = opts;
|
||||||
pf.loadopt = loadopt;
|
pf.loadopt = loadopt;
|
||||||
|
if (anchorname[0])
|
||||||
|
pf.loadopt &= ~PFCTL_FLAG_ALTQ;
|
||||||
pf.paltq = &pa;
|
pf.paltq = &pa;
|
||||||
for (i = 0; i < PF_RULESET_MAX; i++) {
|
pf.trans = t;
|
||||||
pf.prule[i] = &pr[i];
|
|
||||||
}
|
|
||||||
pf.rule_nr = 0;
|
pf.rule_nr = 0;
|
||||||
pf.anchor = anchorname;
|
pf.anchor = anchorname;
|
||||||
pf.ruleset = rulesetname;
|
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 (parse_rules(fin, &pf) < 0) {
|
||||||
if ((opts & PF_OPT_NOACTION) == 0)
|
if ((opts & PF_OPT_NOACTION) == 0)
|
||||||
ERRX("Syntax error in config file: "
|
ERRX("Syntax error in config file: "
|
||||||
@ -994,57 +1121,30 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
|||||||
else
|
else
|
||||||
goto _error;
|
goto _error;
|
||||||
}
|
}
|
||||||
if ((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0))
|
if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
|
||||||
if (check_commit_altq(dev, opts) != 0)
|
if (check_commit_altq(dev, opts) != 0)
|
||||||
ERRX("errors in altq config");
|
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)
|
if (fin != stdin)
|
||||||
fclose(fin);
|
fclose(fin);
|
||||||
|
|
||||||
/* process "load anchor" directives */
|
/* process "load anchor" directives */
|
||||||
if (!anchorname[0] && !rulesetname[0])
|
if (!anchorname[0] && !rulesetname[0])
|
||||||
if (pfctl_load_anchors(dev, opts) == -1)
|
if (pfctl_load_anchors(dev, opts, t) == -1)
|
||||||
ERRX("load anchors");
|
ERRX("load anchors");
|
||||||
|
|
||||||
|
if (trans == NULL && (opts & PF_OPT_NOACTION) == 0)
|
||||||
|
if (pfctl_trans(dev, t, DIOCXCOMMIT, 0))
|
||||||
|
ERR("DIOCXCOMMIT");
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
_error:
|
_error:
|
||||||
if (pf.tdirty) /* cleanup kernel leftover */
|
if (trans == NULL) { /* main ruleset */
|
||||||
pfr_ina_begin(&trs, NULL, NULL, 0);
|
if ((opts & PF_OPT_NOACTION) == 0)
|
||||||
exit(1);
|
if (pfctl_trans(dev, t, DIOCXROLLBACK, 0))
|
||||||
|
err(1, "DIOCXROLLBACK");
|
||||||
|
exit(1);
|
||||||
|
} else /* sub ruleset */
|
||||||
|
return (-1);
|
||||||
|
|
||||||
#undef ERR
|
#undef ERR
|
||||||
#undef ERRX
|
#undef ERRX
|
||||||
@ -1062,7 +1162,7 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
|||||||
memset(&pl, 0, sizeof(pl));
|
memset(&pl, 0, sizeof(pl));
|
||||||
for (i = 0; pf_limits[i].name; i++) {
|
for (i = 0; pf_limits[i].name; i++) {
|
||||||
if (strcasecmp(opt, pf_limits[i].name) == 0) {
|
if (strcasecmp(opt, pf_limits[i].name) == 0) {
|
||||||
pl.index = i;
|
pl.index = pf_limits[i].index;
|
||||||
pl.limit = limit;
|
pl.limit = limit;
|
||||||
if ((pf->opts & PF_OPT_NOACTION) == 0) {
|
if ((pf->opts & PF_OPT_NOACTION) == 0) {
|
||||||
if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
|
if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
|
||||||
@ -1180,6 +1280,55 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
|
|||||||
return (0);
|
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
|
int
|
||||||
pfctl_debug(int dev, u_int32_t level, int opts)
|
pfctl_debug(int dev, u_int32_t level, int opts)
|
||||||
{
|
{
|
||||||
@ -1250,14 +1399,15 @@ pfctl_show_anchors(int dev, int opts, char *anchorname)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
mnr = pa.nr;
|
mnr = pa.nr;
|
||||||
if (!(opts & PF_OPT_QUIET))
|
|
||||||
printf("%u anchors:\n", mnr);
|
|
||||||
for (nr = 0; nr < mnr; ++nr) {
|
for (nr = 0; nr < mnr; ++nr) {
|
||||||
pa.nr = nr;
|
pa.nr = nr;
|
||||||
if (ioctl(dev, DIOCGETANCHOR, &pa)) {
|
if (ioctl(dev, DIOCGETANCHOR, &pa)) {
|
||||||
warn("DIOCGETANCHOR");
|
warn("DIOCGETANCHOR");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
if (!(opts & PF_OPT_VERBOSE) &&
|
||||||
|
!strcmp(pa.name, PF_RESERVED_ANCHOR))
|
||||||
|
continue;
|
||||||
printf(" %s\n", pa.name);
|
printf(" %s\n", pa.name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1274,8 +1424,6 @@ pfctl_show_anchors(int dev, int opts, char *anchorname)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
mnr = pr.nr;
|
mnr = pr.nr;
|
||||||
if (!(opts & PF_OPT_QUIET))
|
|
||||||
printf("%u rulesets in anchor %s:\n", mnr, anchorname);
|
|
||||||
for (nr = 0; nr < mnr; ++nr) {
|
for (nr = 0; nr < mnr; ++nr) {
|
||||||
pr.nr = nr;
|
pr.nr = nr;
|
||||||
if (ioctl(dev, DIOCGETRULESET, &pr))
|
if (ioctl(dev, DIOCGETRULESET, &pr))
|
||||||
@ -1309,8 +1457,8 @@ main(int argc, char *argv[])
|
|||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "a:AdD:eqf:F:ghk:nNOrRs:t:T:vx:z")) !=
|
while ((ch = getopt(argc, argv,
|
||||||
-1) {
|
"a:AdD:eqf:F:ghi:k:nNOp:rRs:t:T:vx:z")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'a':
|
case 'a':
|
||||||
anchoropt = optarg;
|
anchoropt = optarg;
|
||||||
@ -1339,6 +1487,9 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
mode = O_RDWR;
|
mode = O_RDWR;
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
ifaceopt = optarg;
|
||||||
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
if (state_killers >= 2) {
|
if (state_killers >= 2) {
|
||||||
warnx("can only specify -k twice");
|
warnx("can only specify -k twice");
|
||||||
@ -1373,6 +1524,9 @@ main(int argc, char *argv[])
|
|||||||
case 'O':
|
case 'O':
|
||||||
loadopt |= PFCTL_FLAG_OPTION;
|
loadopt |= PFCTL_FLAG_OPTION;
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
pf_device = optarg;
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
showopt = pfctl_lookup_option(optarg, showopt_list);
|
showopt = pfctl_lookup_option(optarg, showopt_list);
|
||||||
if (showopt == NULL) {
|
if (showopt == NULL) {
|
||||||
@ -1422,14 +1576,8 @@ main(int argc, char *argv[])
|
|||||||
if (ch == 'l') {
|
if (ch == 'l') {
|
||||||
loadopt |= PFCTL_FLAG_TABLE;
|
loadopt |= PFCTL_FLAG_TABLE;
|
||||||
tblcmdopt = NULL;
|
tblcmdopt = NULL;
|
||||||
} else {
|
} else
|
||||||
mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY;
|
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) {
|
} else if (argc != optind) {
|
||||||
warnx("unknown command line argument: %s ...", argv[optind]);
|
warnx("unknown command line argument: %s ...", argv[optind]);
|
||||||
usage();
|
usage();
|
||||||
@ -1468,11 +1616,14 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((opts & PF_OPT_NOACTION) == 0) {
|
if ((opts & PF_OPT_NOACTION) == 0) {
|
||||||
dev = open("/dev/pf", mode);
|
dev = open(pf_device, mode);
|
||||||
if (dev == -1)
|
if (dev == -1)
|
||||||
err(1, "/dev/pf");
|
err(1, "%s", pf_device);
|
||||||
altqsupport = pfctl_test_altqsupport(dev, opts);
|
altqsupport = pfctl_test_altqsupport(dev, opts);
|
||||||
} else {
|
} else {
|
||||||
|
dev = open(pf_device, O_RDONLY);
|
||||||
|
if (dev >= 0)
|
||||||
|
opts |= PF_OPT_DUMMYACTION;
|
||||||
/* turn off options */
|
/* turn off options */
|
||||||
opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
|
opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
|
||||||
clearopt = showopt = debugopt = NULL;
|
clearopt = showopt = debugopt = NULL;
|
||||||
@ -1503,32 +1654,38 @@ main(int argc, char *argv[])
|
|||||||
pfctl_show_nat(dev, opts, anchorname, rulesetname);
|
pfctl_show_nat(dev, opts, anchorname, rulesetname);
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
pfctl_show_altq(dev, opts, opts & PF_OPT_VERBOSE2);
|
pfctl_show_altq(dev, ifaceopt, opts,
|
||||||
|
opts & PF_OPT_VERBOSE2);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
pfctl_show_states(dev, 0, opts);
|
pfctl_show_states(dev, ifaceopt, opts);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
pfctl_show_src_nodes(dev, opts);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
pfctl_show_status(dev);
|
pfctl_show_status(dev, opts);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
pfctl_show_timeouts(dev);
|
pfctl_show_timeouts(dev, opts);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
pfctl_show_limits(dev);
|
pfctl_show_limits(dev, opts);
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
|
opts |= PF_OPT_SHOWALL;
|
||||||
pfctl_load_fingerprints(dev, opts);
|
pfctl_load_fingerprints(dev, opts);
|
||||||
|
|
||||||
|
pfctl_show_nat(dev, opts, anchorname, rulesetname);
|
||||||
pfctl_show_rules(dev, opts, 0, anchorname,
|
pfctl_show_rules(dev, opts, 0, anchorname,
|
||||||
rulesetname);
|
rulesetname);
|
||||||
pfctl_show_nat(dev, opts, anchorname, rulesetname);
|
pfctl_show_altq(dev, ifaceopt, opts, 0);
|
||||||
pfctl_show_altq(dev, opts, 0);
|
pfctl_show_states(dev, ifaceopt, opts);
|
||||||
pfctl_show_states(dev, 0, opts);
|
pfctl_show_src_nodes(dev, opts);
|
||||||
pfctl_show_status(dev);
|
pfctl_show_status(dev, opts);
|
||||||
pfctl_show_rules(dev, opts, 1, anchorname, rulesetname);
|
pfctl_show_rules(dev, opts, 1, anchorname, rulesetname);
|
||||||
pfctl_show_timeouts(dev);
|
pfctl_show_timeouts(dev, opts);
|
||||||
pfctl_show_limits(dev);
|
pfctl_show_limits(dev, opts);
|
||||||
pfctl_show_tables(anchorname, rulesetname, opts);
|
pfctl_show_tables(anchorname, rulesetname, opts);
|
||||||
pfctl_show_fingerprints(opts);
|
pfctl_show_fingerprints(opts);
|
||||||
break;
|
break;
|
||||||
@ -1539,6 +1696,9 @@ main(int argc, char *argv[])
|
|||||||
pfctl_load_fingerprints(dev, opts);
|
pfctl_load_fingerprints(dev, opts);
|
||||||
pfctl_show_fingerprints(opts);
|
pfctl_show_fingerprints(opts);
|
||||||
break;
|
break;
|
||||||
|
case 'I':
|
||||||
|
pfctl_show_ifaces(ifaceopt, opts);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1554,7 +1714,10 @@ main(int argc, char *argv[])
|
|||||||
pfctl_clear_altq(dev, opts);
|
pfctl_clear_altq(dev, opts);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
pfctl_clear_states(dev, opts);
|
pfctl_clear_states(dev, ifaceopt, opts);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
pfctl_clear_src_nodes(dev, opts);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
pfctl_clear_stats(dev, opts);
|
pfctl_clear_stats(dev, opts);
|
||||||
@ -1562,11 +1725,14 @@ main(int argc, char *argv[])
|
|||||||
case 'a':
|
case 'a':
|
||||||
pfctl_clear_rules(dev, opts, anchorname, rulesetname);
|
pfctl_clear_rules(dev, opts, anchorname, rulesetname);
|
||||||
pfctl_clear_nat(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_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;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
pfctl_clear_fingerprints(dev, opts);
|
pfctl_clear_fingerprints(dev, opts);
|
||||||
@ -1577,7 +1743,7 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state_killers)
|
if (state_killers)
|
||||||
pfctl_kill_states(dev, opts);
|
pfctl_kill_states(dev, ifaceopt, opts);
|
||||||
|
|
||||||
if (tblcmdopt != NULL) {
|
if (tblcmdopt != NULL) {
|
||||||
error = pfctl_command_tables(argc, argv, tableopt,
|
error = pfctl_command_tables(argc, argv, tableopt,
|
||||||
@ -1590,7 +1756,8 @@ main(int argc, char *argv[])
|
|||||||
error = 1;
|
error = 1;
|
||||||
|
|
||||||
if (rulesopt != NULL) {
|
if (rulesopt != NULL) {
|
||||||
if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname))
|
if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname,
|
||||||
|
NULL))
|
||||||
error = 1;
|
error = 1;
|
||||||
else if (!(opts & PF_OPT_NOACTION) &&
|
else if (!(opts & PF_OPT_NOACTION) &&
|
||||||
(loadopt & PFCTL_FLAG_TABLE))
|
(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
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -33,7 +33,8 @@
|
|||||||
#ifndef _PFCTL_H_
|
#ifndef _PFCTL_H_
|
||||||
#define _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 {
|
struct pfr_buffer {
|
||||||
int pfrb_type; /* type of content, see enum above */
|
int pfrb_type; /* type of content, see enum above */
|
||||||
int pfrb_size; /* number of objects in buffer */
|
int pfrb_size; /* number of objects in buffer */
|
||||||
@ -57,7 +58,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_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_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||||
int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, 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_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
|
||||||
int pfr_get_astats(struct pfr_table *, struct pfr_astats *, 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);
|
int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||||
@ -74,13 +75,17 @@ int pfr_buf_grow(struct pfr_buffer *, int);
|
|||||||
int pfr_buf_load(struct pfr_buffer *, char *, int,
|
int pfr_buf_load(struct pfr_buffer *, char *, int,
|
||||||
int (*)(struct pfr_buffer *, char *, int));
|
int (*)(struct pfr_buffer *, char *, int));
|
||||||
char *pfr_strerror(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_clear_tables(const char *, const char *, int);
|
||||||
int pfctl_show_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 *,
|
int pfctl_command_tables(int, char *[], char *, const char *, char *,
|
||||||
const char *, const char *, int);
|
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 *);
|
void warn_namespace_collision(const char *);
|
||||||
|
int pfctl_show_ifaces(const char *, int);
|
||||||
|
|
||||||
#ifndef DEFAULT_PRIORITY
|
#ifndef DEFAULT_PRIORITY
|
||||||
#define DEFAULT_PRIORITY 1
|
#define DEFAULT_PRIORITY 1
|
||||||
@ -111,5 +116,9 @@ void print_state(struct pf_state *, int);
|
|||||||
int unmask(struct pf_addr *, sa_family_t);
|
int unmask(struct pf_addr *, sa_family_t);
|
||||||
|
|
||||||
int pfctl_cmdline_symset(char *);
|
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_ */
|
#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
|
* Copyright (c) 2002
|
||||||
@ -21,7 +21,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/limits.h>
|
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -29,6 +28,7 @@
|
|||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -82,8 +82,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,
|
void print_hfsc_sc(const char *, u_int, u_int, u_int,
|
||||||
const struct node_hfsc_sc *);
|
const struct node_hfsc_sc *);
|
||||||
|
|
||||||
static u_int32_t max_qid = 1;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pfaltq_store(struct pf_altq *a)
|
pfaltq_store(struct pf_altq *a)
|
||||||
{
|
{
|
||||||
@ -158,14 +156,14 @@ void
|
|||||||
print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
|
print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
|
||||||
struct node_queue_opt *qopts)
|
struct node_queue_opt *qopts)
|
||||||
{
|
{
|
||||||
if (a->qname[0] != NULL) {
|
if (a->qname[0] != 0) {
|
||||||
print_queue(a, level, bw, 0, qopts);
|
print_queue(a, level, bw, 0, qopts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("altq on %s ", a->ifname);
|
printf("altq on %s ", a->ifname);
|
||||||
|
|
||||||
switch(a->scheduler) {
|
switch (a->scheduler) {
|
||||||
case ALTQT_CBQ:
|
case ALTQT_CBQ:
|
||||||
if (!print_cbq_opts(a))
|
if (!print_cbq_opts(a))
|
||||||
printf("cbq ");
|
printf("cbq ");
|
||||||
@ -261,6 +259,8 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
|||||||
else
|
else
|
||||||
size = 24;
|
size = 24;
|
||||||
size = size * getifmtu(pa->ifname);
|
size = size * getifmtu(pa->ifname);
|
||||||
|
if (size > 0xffff)
|
||||||
|
size = 0xffff;
|
||||||
pa->tbrsize = size;
|
pa->tbrsize = size;
|
||||||
}
|
}
|
||||||
return (errors);
|
return (errors);
|
||||||
@ -410,8 +410,6 @@ eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
|
|
||||||
if (pa->parent[0] == 0)
|
if (pa->parent[0] == 0)
|
||||||
opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR);
|
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);
|
cbq_compute_idletime(pf, pa);
|
||||||
return (0);
|
return (0);
|
||||||
@ -485,9 +483,12 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
minidle = -((double)opts->maxpktsize * (double)nsPerByte);
|
minidle = -((double)opts->maxpktsize * (double)nsPerByte);
|
||||||
|
|
||||||
/* scale parameters */
|
/* scale parameters */
|
||||||
maxidle = ((maxidle * 8.0) / nsPerByte) * pow(2.0, (double)RM_FILTER_GAIN);
|
maxidle = ((maxidle * 8.0) / nsPerByte) *
|
||||||
offtime = (offtime * 8.0) / nsPerByte * pow(2.0, (double)RM_FILTER_GAIN);
|
pow(2.0, (double)RM_FILTER_GAIN);
|
||||||
minidle = ((minidle * 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;
|
maxidle = maxidle / 1000.0;
|
||||||
offtime = offtime / 1000.0;
|
offtime = offtime / 1000.0;
|
||||||
@ -495,10 +496,10 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
|
|
||||||
opts->minburst = minburst;
|
opts->minburst = minburst;
|
||||||
opts->maxburst = maxburst;
|
opts->maxburst = maxburst;
|
||||||
opts->ns_per_byte = (u_int) nsPerByte;
|
opts->ns_per_byte = (u_int)nsPerByte;
|
||||||
opts->maxidle = (u_int) fabs(maxidle);
|
opts->maxidle = (u_int)fabs(maxidle);
|
||||||
opts->minidle = (int)minidle;
|
opts->minidle = (int)minidle;
|
||||||
opts->offtime = (u_int) fabs(offtime);
|
opts->offtime = (u_int)fabs(offtime);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -593,9 +594,6 @@ eval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pa->qid == 0)
|
|
||||||
pa->qid = ++max_qid;
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,13 +663,11 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
|
|
||||||
if (pa->parent[0] == 0) {
|
if (pa->parent[0] == 0) {
|
||||||
/* root queue */
|
/* root queue */
|
||||||
pa->qid = HFSC_ROOTCLASS_HANDLE;
|
|
||||||
opts->lssc_m1 = pa->ifbandwidth;
|
opts->lssc_m1 = pa->ifbandwidth;
|
||||||
opts->lssc_m2 = pa->ifbandwidth;
|
opts->lssc_m2 = pa->ifbandwidth;
|
||||||
opts->lssc_d = 0;
|
opts->lssc_d = 0;
|
||||||
return (0);
|
return (0);
|
||||||
} else if (pa->qid == 0)
|
}
|
||||||
pa->qid = ++max_qid;
|
|
||||||
|
|
||||||
LIST_INIT(&rtsc);
|
LIST_INIT(&rtsc);
|
||||||
LIST_INIT(&lssc);
|
LIST_INIT(&lssc);
|
||||||
@ -718,7 +714,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
/* if the class has a real-time service curve, add it. */
|
/* if the class has a real-time service curve, add it. */
|
||||||
if (opts->rtsc_m2 != 0 && altq->pq_u.hfsc_opts.rtsc_m2 != 0) {
|
if (opts->rtsc_m2 != 0 && altq->pq_u.hfsc_opts.rtsc_m2 != 0) {
|
||||||
sc.m1 = altq->pq_u.hfsc_opts.rtsc_m1;
|
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;
|
sc.m2 = altq->pq_u.hfsc_opts.rtsc_m2;
|
||||||
gsc_add_sc(&rtsc, &sc);
|
gsc_add_sc(&rtsc, &sc);
|
||||||
}
|
}
|
||||||
@ -729,7 +725,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
/* if the class has a link-sharing service curve, add it. */
|
/* if the class has a link-sharing service curve, add it. */
|
||||||
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
|
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
|
||||||
sc.m1 = altq->pq_u.hfsc_opts.lssc_m1;
|
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;
|
sc.m2 = altq->pq_u.hfsc_opts.lssc_m2;
|
||||||
gsc_add_sc(&lssc, &sc);
|
gsc_add_sc(&lssc, &sc);
|
||||||
}
|
}
|
||||||
@ -738,7 +734,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
/* check the real-time service curve. reserve 20% of interface bw */
|
/* check the real-time service curve. reserve 20% of interface bw */
|
||||||
if (opts->rtsc_m2 != 0) {
|
if (opts->rtsc_m2 != 0) {
|
||||||
sc.m1 = 0;
|
sc.m1 = 0;
|
||||||
sc.d = 0;
|
sc.d = 0;
|
||||||
sc.m2 = pa->ifbandwidth / 100 * 80;
|
sc.m2 = pa->ifbandwidth / 100 * 80;
|
||||||
if (!is_gsc_under_sc(&rtsc, &sc)) {
|
if (!is_gsc_under_sc(&rtsc, &sc)) {
|
||||||
warnx("real-time sc exceeds the interface bandwidth");
|
warnx("real-time sc exceeds the interface bandwidth");
|
||||||
@ -749,7 +745,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
/* check the link-sharing service curve. */
|
/* check the link-sharing service curve. */
|
||||||
if (opts->lssc_m2 != 0) {
|
if (opts->lssc_m2 != 0) {
|
||||||
sc.m1 = parent->pq_u.hfsc_opts.lssc_m1;
|
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;
|
sc.m2 = parent->pq_u.hfsc_opts.lssc_m2;
|
||||||
if (!is_gsc_under_sc(&lssc, &sc)) {
|
if (!is_gsc_under_sc(&lssc, &sc)) {
|
||||||
warnx("link-sharing sc exceeds parent's sc");
|
warnx("link-sharing sc exceeds parent's sc");
|
||||||
@ -1007,7 +1003,7 @@ gsc_add_seg(struct gen_sc *gsc, double x, double y, double d, double m)
|
|||||||
else
|
else
|
||||||
x2 = x + d;
|
x2 = x + d;
|
||||||
start = gsc_getentry(gsc, x);
|
start = gsc_getentry(gsc, x);
|
||||||
end = gsc_getentry(gsc, x2);
|
end = gsc_getentry(gsc, x2);
|
||||||
if (start == NULL || end == NULL)
|
if (start == NULL || end == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_osfp.c,v 1.4 2003/08/27 17:42:00 frantzen Exp $ */
|
/* $OpenBSD: pfctl_osfp.c,v 1.8 2004/02/27 10:42:00 henning Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003 Mike Frantzen <frantzen@openbsd.org>
|
* Copyright (c) 2003 Mike Frantzen <frantzen@openbsd.org>
|
||||||
@ -31,6 +31,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "pfctl_parser.h"
|
#include "pfctl_parser.h"
|
||||||
|
#include "pfctl.h"
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
@ -308,11 +309,17 @@ pfctl_load_fingerprints(int dev, int opts)
|
|||||||
void
|
void
|
||||||
pfctl_show_fingerprints(int opts)
|
pfctl_show_fingerprints(int opts)
|
||||||
{
|
{
|
||||||
printf("Passive OS Fingerprints:\n");
|
if (LIST_FIRST(&classes) != NULL) {
|
||||||
printf("\tClass\tVersion\tSubtype(subversion)\n");
|
if (opts & PF_OPT_SHOWALL) {
|
||||||
printf("\t-----\t-------\t-------------------\n");
|
pfctl_print_title("OS FINGERPRINTS:");
|
||||||
sort_name_list(opts, &classes);
|
printf("%u fingerprints loaded\n", fingerprint_count);
|
||||||
print_name_list(opts, &classes, "\t");
|
} else {
|
||||||
|
printf("Class\tVersion\tSubtype(subversion)\n");
|
||||||
|
printf("-----\t-------\t-------------------\n");
|
||||||
|
sort_name_list(opts, &classes);
|
||||||
|
print_name_list(opts, &classes, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup a fingerprint */
|
/* Lookup a fingerprint */
|
||||||
@ -825,7 +832,7 @@ get_int(char **line, size_t *len, int *var, int *mod,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (; i < fieldlen; i++) {
|
for (; i < fieldlen; i++) {
|
||||||
if (field[i] < '0' || field[i] > '9') {
|
if (field[i] < '0' || field[i] > '9') {
|
||||||
fprintf(stderr, "%s:%d non-digit character in %s\n",
|
fprintf(stderr, "%s:%d non-digit character in %s\n",
|
||||||
filename, lineno, name);
|
filename, lineno, name);
|
||||||
return (1);
|
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) 2001 Daniel Hartmeier
|
||||||
|
* Copyright (c) 2002,2003 Henning Brauer
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -192,6 +194,7 @@ const struct pf_timeout pf_timeouts[] = {
|
|||||||
{ "interval", PFTM_INTERVAL },
|
{ "interval", PFTM_INTERVAL },
|
||||||
{ "adaptive.start", PFTM_ADAPTIVE_START },
|
{ "adaptive.start", PFTM_ADAPTIVE_START },
|
||||||
{ "adaptive.end", PFTM_ADAPTIVE_END },
|
{ "adaptive.end", PFTM_ADAPTIVE_END },
|
||||||
|
{ "src.track", PFTM_SRC_NODE },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -251,7 +254,7 @@ geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i=0; i < (sizeof (icmp6_code) /
|
for (i=0; i < (sizeof (icmp6_code) /
|
||||||
sizeof(icmp6_code[0])); i++) {
|
sizeof(icmp6_code[0])); i++) {
|
||||||
if (type == icmp6_code[i].type &&
|
if (type == icmp6_code[i].type &&
|
||||||
code == icmp6_code[i].code)
|
code == icmp6_code[i].code)
|
||||||
return (&icmp6_code[i]);
|
return (&icmp6_code[i]);
|
||||||
@ -458,23 +461,27 @@ print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
|
|||||||
printf(" round-robin");
|
printf(" round-robin");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (pool->opts & PF_POOL_STICKYADDR)
|
||||||
|
printf(" sticky-address");
|
||||||
if (id == PF_NAT && p1 == 0 && p2 == 0)
|
if (id == PF_NAT && p1 == 0 && p2 == 0)
|
||||||
printf(" static-port");
|
printf(" static-port");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
|
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
|
||||||
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
|
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||||
|
const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||||
|
|
||||||
void
|
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;
|
time_t runtime;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
runtime = time(NULL) - s->since;
|
runtime = time(NULL) - s->since;
|
||||||
|
running = s->running ? "Enabled" : "Disabled";
|
||||||
|
|
||||||
if (s->running) {
|
if (s->since) {
|
||||||
unsigned sec, min, hrs, day = runtime;
|
unsigned sec, min, hrs, day = runtime;
|
||||||
|
|
||||||
sec = day % 60;
|
sec = day % 60;
|
||||||
@ -484,48 +491,54 @@ print_status(struct pf_status *s)
|
|||||||
hrs = day % 24;
|
hrs = day % 24;
|
||||||
day /= 24;
|
day /= 24;
|
||||||
snprintf(statline, sizeof(statline),
|
snprintf(statline, sizeof(statline),
|
||||||
"Status: Enabled for %u days %.2u:%.2u:%.2u",
|
"Status: %s for %u days %.2u:%.2u:%.2u",
|
||||||
day, hrs, min, sec);
|
running, day, hrs, min, sec);
|
||||||
} else
|
} else
|
||||||
snprintf(statline, sizeof(statline), "Status: Disabled");
|
snprintf(statline, sizeof(statline), "Status: %s", running);
|
||||||
printf("%-44s", statline);
|
printf("%-44s", statline);
|
||||||
switch (s->debug) {
|
switch (s->debug) {
|
||||||
case 0:
|
case PF_DEBUG_NONE:
|
||||||
printf("%15s\n\n", "Debug: None");
|
printf("%15s\n\n", "Debug: None");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case PF_DEBUG_URGENT:
|
||||||
printf("%15s\n\n", "Debug: Urgent");
|
printf("%15s\n\n", "Debug: Urgent");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case PF_DEBUG_MISC:
|
||||||
printf("%15s\n\n", "Debug: Misc");
|
printf("%15s\n\n", "Debug: Misc");
|
||||||
break;
|
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) {
|
if (s->ifname[0] != 0) {
|
||||||
printf("Interface Stats for %-16s %5s %16s\n",
|
printf("Interface Stats for %-16s %5s %16s\n",
|
||||||
s->ifname, "IPv4", "IPv6");
|
s->ifname, "IPv4", "IPv6");
|
||||||
printf(" %-25s %14llu %16llu\n", "Bytes In",
|
printf(" %-25s %14llu %16llu\n", "Bytes In",
|
||||||
s->bcounters[0][0], s->bcounters[1][0]);
|
(unsigned long long)s->bcounters[0][0],
|
||||||
|
(unsigned long long)s->bcounters[1][0]);
|
||||||
printf(" %-25s %14llu %16llu\n", "Bytes Out",
|
printf(" %-25s %14llu %16llu\n", "Bytes Out",
|
||||||
s->bcounters[0][1], s->bcounters[1][1]);
|
(unsigned long long)s->bcounters[0][1],
|
||||||
|
(unsigned long long)s->bcounters[1][1]);
|
||||||
printf(" Packets In\n");
|
printf(" Packets In\n");
|
||||||
printf(" %-23s %14llu %16llu\n", "Passed",
|
printf(" %-23s %14llu %16llu\n", "Passed",
|
||||||
s->pcounters[0][0][PF_PASS],
|
(unsigned long long)s->pcounters[0][0][PF_PASS],
|
||||||
s->pcounters[1][0][PF_PASS]);
|
(unsigned long long)s->pcounters[1][0][PF_PASS]);
|
||||||
printf(" %-23s %14llu %16llu\n", "Blocked",
|
printf(" %-23s %14llu %16llu\n", "Blocked",
|
||||||
s->pcounters[0][0][PF_DROP],
|
(unsigned long long)s->pcounters[0][0][PF_DROP],
|
||||||
s->pcounters[1][0][PF_DROP]);
|
(unsigned long long)s->pcounters[1][0][PF_DROP]);
|
||||||
printf(" Packets Out\n");
|
printf(" Packets Out\n");
|
||||||
printf(" %-23s %14llu %16llu\n", "Passed",
|
printf(" %-23s %14llu %16llu\n", "Passed",
|
||||||
s->pcounters[0][1][PF_PASS],
|
(unsigned long long)s->pcounters[0][1][PF_PASS],
|
||||||
s->pcounters[1][1][PF_PASS]);
|
(unsigned long long)s->pcounters[1][1][PF_PASS]);
|
||||||
printf(" %-23s %14llu %16llu\n\n", "Blocked",
|
printf(" %-23s %14llu %16llu\n\n", "Blocked",
|
||||||
s->pcounters[0][1][PF_DROP],
|
(unsigned long long)s->pcounters[0][1][PF_DROP],
|
||||||
s->pcounters[1][1][PF_DROP]);
|
(unsigned long long)s->pcounters[1][1][PF_DROP]);
|
||||||
}
|
}
|
||||||
printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
|
printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
|
||||||
printf(" %-25s %14u %14s\n", "current entries", s->states, "");
|
printf(" %-25s %14u %14s\n", "current entries", s->states, "");
|
||||||
for (i = 0; i < FCNT_MAX; i++) {
|
for (i = 0; i < FCNT_MAX; i++) {
|
||||||
printf(" %-25s %14llu", pf_fcounters[i],
|
printf(" %-25s %14llu ", pf_fcounters[i],
|
||||||
(unsigned long long)s->fcounters[i]);
|
(unsigned long long)s->fcounters[i]);
|
||||||
if (runtime > 0)
|
if (runtime > 0)
|
||||||
printf("%14.1f/s\n",
|
printf("%14.1f/s\n",
|
||||||
@ -533,6 +546,20 @@ print_status(struct pf_status *s)
|
|||||||
else
|
else
|
||||||
printf("%14s\n", "");
|
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");
|
printf("Counters\n");
|
||||||
for (i = 0; i < PFRES_MAX; i++) {
|
for (i = 0; i < PFRES_MAX; i++) {
|
||||||
printf(" %-25s %14llu ", pf_reasons[i],
|
printf(" %-25s %14llu ", pf_reasons[i],
|
||||||
@ -545,6 +572,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
|
void
|
||||||
print_rule(struct pf_rule *r, int verbose)
|
print_rule(struct pf_rule *r, int verbose)
|
||||||
{
|
{
|
||||||
@ -582,7 +660,7 @@ print_rule(struct pf_rule *r, int verbose)
|
|||||||
ic6 = geticmpcodebynumber(r->return_icmp6 >> 8,
|
ic6 = geticmpcodebynumber(r->return_icmp6 >> 8,
|
||||||
r->return_icmp6 & 255, AF_INET6);
|
r->return_icmp6 & 255, AF_INET6);
|
||||||
|
|
||||||
switch(r->af) {
|
switch (r->af) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
printf(" return-icmp");
|
printf(" return-icmp");
|
||||||
if (ic == NULL)
|
if (ic == NULL)
|
||||||
@ -701,7 +779,13 @@ print_rule(struct pf_rule *r, int verbose)
|
|||||||
else if (r->keep_state == PF_STATE_SYNPROXY)
|
else if (r->keep_state == PF_STATE_SYNPROXY)
|
||||||
printf(" synproxy state");
|
printf(" synproxy state");
|
||||||
opts = 0;
|
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;
|
opts = 1;
|
||||||
for (i = 0; !opts && i < PFTM_MAX; ++i)
|
for (i = 0; !opts && i < PFTM_MAX; ++i)
|
||||||
if (r->timeout[i])
|
if (r->timeout[i])
|
||||||
@ -712,6 +796,46 @@ print_rule(struct pf_rule *r, int verbose)
|
|||||||
printf("max %u", r->max_states);
|
printf("max %u", r->max_states);
|
||||||
opts = 0;
|
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)
|
for (i = 0; i < PFTM_MAX; ++i)
|
||||||
if (r->timeout[i]) {
|
if (r->timeout[i]) {
|
||||||
if (!opts)
|
if (!opts)
|
||||||
@ -879,6 +1003,8 @@ ifa_load(void)
|
|||||||
{
|
{
|
||||||
struct ifaddrs *ifap, *ifa;
|
struct ifaddrs *ifap, *ifa;
|
||||||
struct node_host *n = NULL, *h = NULL;
|
struct node_host *n = NULL, *h = NULL;
|
||||||
|
struct pfr_buffer b;
|
||||||
|
struct pfi_if *p;
|
||||||
|
|
||||||
if (getifaddrs(&ifap) < 0)
|
if (getifaddrs(&ifap) < 0)
|
||||||
err(1, "getifaddrs");
|
err(1, "getifaddrs");
|
||||||
@ -897,7 +1023,8 @@ ifa_load(void)
|
|||||||
if (n->af == AF_INET6 &&
|
if (n->af == AF_INET6 &&
|
||||||
IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
|
IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
|
||||||
ifa->ifa_addr)->sin6_addr) &&
|
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;
|
struct sockaddr_in6 *sin6;
|
||||||
|
|
||||||
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||||
@ -919,6 +1046,10 @@ ifa_load(void)
|
|||||||
memcpy(&n->bcast, &((struct sockaddr_in *)
|
memcpy(&n->bcast, &((struct sockaddr_in *)
|
||||||
ifa->ifa_broadaddr)->sin_addr.s_addr,
|
ifa->ifa_broadaddr)->sin_addr.s_addr,
|
||||||
sizeof(struct in_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) {
|
} else if (n->af == AF_INET6) {
|
||||||
memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *)
|
memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *)
|
||||||
ifa->ifa_addr)->sin6_addr.s6_addr,
|
ifa->ifa_addr)->sin6_addr.s6_addr,
|
||||||
@ -930,6 +1061,10 @@ ifa_load(void)
|
|||||||
memcpy(&n->bcast, &((struct sockaddr_in6 *)
|
memcpy(&n->bcast, &((struct sockaddr_in6 *)
|
||||||
ifa->ifa_broadaddr)->sin6_addr.s6_addr,
|
ifa->ifa_broadaddr)->sin6_addr.s6_addr,
|
||||||
sizeof(struct in6_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 *)
|
n->ifindex = ((struct sockaddr_in6 *)
|
||||||
ifa->ifa_addr)->sin6_scope_id;
|
ifa->ifa_addr)->sin6_scope_id;
|
||||||
}
|
}
|
||||||
@ -944,15 +1079,58 @@ ifa_load(void)
|
|||||||
h->tail = n;
|
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;
|
iftab = h;
|
||||||
freeifaddrs(ifap);
|
freeifaddrs(ifap);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_host *
|
struct node_host *
|
||||||
ifa_exists(const char *ifa_name)
|
ifa_exists(const char *ifa_name, int group_ok)
|
||||||
{
|
{
|
||||||
struct node_host *n;
|
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)
|
if (iftab == NULL)
|
||||||
ifa_load();
|
ifa_load();
|
||||||
|
|
||||||
@ -960,14 +1138,28 @@ ifa_exists(const char *ifa_name)
|
|||||||
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
|
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
|
||||||
return (n);
|
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);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_host *
|
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;
|
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))
|
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
||||||
return_all = 1;
|
return_all = 1;
|
||||||
@ -977,23 +1169,44 @@ ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode)
|
|||||||
|
|
||||||
for (p = iftab; p; p = p->next) {
|
for (p = iftab; p; p = p->next) {
|
||||||
if (!((p->af == AF_INET || p->af == AF_INET6) &&
|
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;
|
continue;
|
||||||
if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
|
if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
|
||||||
continue;
|
continue;
|
||||||
if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
|
if ((flags & PFI_AFLAG_BROADCAST) &&
|
||||||
|
!(p->ifa_flags & IFF_BROADCAST))
|
||||||
continue;
|
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));
|
n = calloc(1, sizeof(struct node_host));
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
err(1, "address: calloc");
|
err(1, "address: calloc");
|
||||||
n->af = p->af;
|
n->af = p->af;
|
||||||
if (mode == PFCTL_IFLOOKUP_BCAST)
|
if (flags & PFI_AFLAG_BROADCAST)
|
||||||
memcpy(&n->addr.v.a.addr, &p->bcast,
|
memcpy(&n->addr.v.a.addr, &p->bcast,
|
||||||
sizeof(struct pf_addr));
|
sizeof(struct pf_addr));
|
||||||
|
else if (flags & PFI_AFLAG_PEER)
|
||||||
|
memcpy(&n->addr.v.a.addr, &p->peer,
|
||||||
|
sizeof(struct pf_addr));
|
||||||
else
|
else
|
||||||
memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr,
|
memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr,
|
||||||
sizeof(struct pf_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));
|
set_ipmask(n, unmask(&p->addr.v.a.mask, n->af));
|
||||||
else {
|
else {
|
||||||
if (n->af == AF_INET) {
|
if (n->af == AF_INET) {
|
||||||
@ -1018,9 +1231,6 @@ ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode)
|
|||||||
h->tail = n;
|
h->tail = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) {
|
|
||||||
fprintf(stderr, "no IP address found for %s\n", ifa_name);
|
|
||||||
}
|
|
||||||
return (h);
|
return (h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1078,29 +1288,39 @@ host_if(const char *s, int mask)
|
|||||||
{
|
{
|
||||||
struct node_host *n, *h = NULL;
|
struct node_host *n, *h = NULL;
|
||||||
char *p, *ps;
|
char *p, *ps;
|
||||||
int mode = PFCTL_IFLOOKUP_HOST;
|
int flags = 0;
|
||||||
|
|
||||||
if ((p = strrchr(s, ':')) != NULL &&
|
if ((ps = strdup(s)) == NULL)
|
||||||
(!strcmp(p+1, "network") || !strcmp(p+1, "broadcast"))) {
|
err(1, "host_if: strdup");
|
||||||
|
while ((p = strrchr(ps, ':')) != NULL) {
|
||||||
if (!strcmp(p+1, "network"))
|
if (!strcmp(p+1, "network"))
|
||||||
mode = PFCTL_IFLOOKUP_NET;
|
flags |= PFI_AFLAG_NETWORK;
|
||||||
if (!strcmp(p+1, "broadcast"))
|
else if (!strcmp(p+1, "broadcast"))
|
||||||
mode = PFCTL_IFLOOKUP_BCAST;
|
flags |= PFI_AFLAG_BROADCAST;
|
||||||
if (mask > -1) {
|
else if (!strcmp(p+1, "peer"))
|
||||||
fprintf(stderr, "network or broadcast lookup, but "
|
flags |= PFI_AFLAG_PEER;
|
||||||
"extra netmask given\n");
|
else if (!strcmp(p+1, "0"))
|
||||||
|
flags |= PFI_AFLAG_NOALIAS;
|
||||||
|
else {
|
||||||
|
free(ps);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
|
*p = '\0';
|
||||||
err(1, "host: malloc");
|
}
|
||||||
strlcpy(ps, s, strlen(s) - strlen(p) + 1);
|
if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */
|
||||||
} else
|
fprintf(stderr, "illegal combination of interface modifiers\n");
|
||||||
if ((ps = strdup(s)) == NULL)
|
free(ps);
|
||||||
err(1, "host_if: strdup");
|
return (NULL);
|
||||||
|
}
|
||||||
if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
|
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 */
|
/* 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)
|
for (n = h; n != NULL && mask > -1; n = n->next)
|
||||||
set_ipmask(n, mask);
|
set_ipmask(n, mask);
|
||||||
}
|
}
|
||||||
@ -1114,21 +1334,27 @@ host_v4(const char *s, int mask)
|
|||||||
{
|
{
|
||||||
struct node_host *h = NULL;
|
struct node_host *h = NULL;
|
||||||
struct in_addr ina;
|
struct in_addr ina;
|
||||||
int bits;
|
int bits = 32;
|
||||||
|
|
||||||
memset(&ina, 0, sizeof(struct in_addr));
|
memset(&ina, 0, sizeof(struct in_addr));
|
||||||
if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) > -1) {
|
if (strrchr(s, '/') != NULL) {
|
||||||
h = calloc(1, sizeof(struct node_host));
|
if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
|
||||||
if (h == NULL)
|
return (NULL);
|
||||||
err(1, "address: calloc");
|
} else {
|
||||||
h->ifname = NULL;
|
if (inet_pton(AF_INET, s, &ina) != 1)
|
||||||
h->af = AF_INET;
|
return (NULL);
|
||||||
h->addr.v.a.addr.addr32[0] = ina.s_addr;
|
|
||||||
set_ipmask(h, bits);
|
|
||||||
h->next = NULL;
|
|
||||||
h->tail = h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
return (h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1167,12 +1393,20 @@ host_dns(const char *s, int v4mask, int v6mask)
|
|||||||
{
|
{
|
||||||
struct addrinfo hints, *res0, *res;
|
struct addrinfo hints, *res0, *res;
|
||||||
struct node_host *n, *h = NULL;
|
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));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = PF_UNSPEC;
|
hints.ai_family = PF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
|
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
|
||||||
error = getaddrinfo(s, NULL, &hints, &res0);
|
error = getaddrinfo(ps, NULL, &hints, &res0);
|
||||||
if (error)
|
if (error)
|
||||||
return (h);
|
return (h);
|
||||||
|
|
||||||
@ -1180,6 +1414,17 @@ host_dns(const char *s, int v4mask, int v6mask)
|
|||||||
if (res->ai_family != AF_INET &&
|
if (res->ai_family != AF_INET &&
|
||||||
res->ai_family != AF_INET6)
|
res->ai_family != AF_INET6)
|
||||||
continue;
|
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));
|
n = calloc(1, sizeof(struct node_host));
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
err(1, "host_dns: calloc");
|
err(1, "host_dns: calloc");
|
||||||
@ -1211,6 +1456,7 @@ host_dns(const char *s, int v4mask, int v6mask)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
|
free(ps);
|
||||||
|
|
||||||
return (h);
|
return (h);
|
||||||
}
|
}
|
||||||
@ -1284,3 +1530,45 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
|
|||||||
|
|
||||||
return (0);
|
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
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -45,6 +45,7 @@
|
|||||||
#define PF_OPT_VERBOSE2 0x0080
|
#define PF_OPT_VERBOSE2 0x0080
|
||||||
#define PF_OPT_DUMMYACTION 0x0100
|
#define PF_OPT_DUMMYACTION 0x0100
|
||||||
#define PF_OPT_DEBUG 0x0200
|
#define PF_OPT_DEBUG 0x0200
|
||||||
|
#define PF_OPT_SHOWALL 0x0400
|
||||||
|
|
||||||
#define PF_TH_ALL 0xFF
|
#define PF_TH_ALL 0xFF
|
||||||
|
|
||||||
@ -66,19 +67,13 @@ struct pfctl {
|
|||||||
int tdirty; /* kernel dirty */
|
int tdirty; /* kernel dirty */
|
||||||
u_int32_t rule_nr;
|
u_int32_t rule_nr;
|
||||||
struct pfioc_pooladdr paddr;
|
struct pfioc_pooladdr paddr;
|
||||||
struct pfioc_rule *prule[PF_RULESET_MAX];
|
|
||||||
struct pfioc_altq *paltq;
|
struct pfioc_altq *paltq;
|
||||||
struct pfioc_queue *pqueue;
|
struct pfioc_queue *pqueue;
|
||||||
|
struct pfr_buffer *trans;
|
||||||
const char *anchor;
|
const char *anchor;
|
||||||
const char *ruleset;
|
const char *ruleset;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pfctl_iflookup_mode {
|
|
||||||
PFCTL_IFLOOKUP_HOST,
|
|
||||||
PFCTL_IFLOOKUP_NET,
|
|
||||||
PFCTL_IFLOOKUP_BCAST
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node_if {
|
struct node_if {
|
||||||
char ifname[IFNAMSIZ];
|
char ifname[IFNAMSIZ];
|
||||||
u_int8_t not;
|
u_int8_t not;
|
||||||
@ -90,6 +85,7 @@ struct node_if {
|
|||||||
struct node_host {
|
struct node_host {
|
||||||
struct pf_addr_wrap addr;
|
struct pf_addr_wrap addr;
|
||||||
struct pf_addr bcast;
|
struct pf_addr bcast;
|
||||||
|
struct pf_addr peer;
|
||||||
sa_family_t af;
|
sa_family_t af;
|
||||||
u_int8_t not;
|
u_int8_t not;
|
||||||
u_int32_t ifindex; /* link-local IPv6 addrs */
|
u_int32_t ifindex; /* link-local IPv6 addrs */
|
||||||
@ -98,6 +94,10 @@ struct node_host {
|
|||||||
struct node_host *next;
|
struct node_host *next;
|
||||||
struct node_host *tail;
|
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 {
|
struct node_os {
|
||||||
char *os;
|
char *os;
|
||||||
@ -143,7 +143,7 @@ struct node_tinit { /* table initializer */
|
|||||||
|
|
||||||
struct pfr_buffer; /* forward definition */
|
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_rule(struct pfctl *, struct pf_rule *);
|
||||||
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
||||||
@ -154,15 +154,18 @@ int pfctl_set_timeout(struct pfctl *, const char *, int, int);
|
|||||||
int pfctl_set_optimization(struct pfctl *, const char *);
|
int pfctl_set_optimization(struct pfctl *, const char *);
|
||||||
int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
||||||
int pfctl_set_logif(struct pfctl *, char *);
|
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_rules(FILE *, struct pfctl *);
|
||||||
int parse_flags(char *);
|
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_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_rule(struct pf_rule *, int);
|
||||||
void print_tabledef(const char *, int, int, struct node_tinithead *);
|
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 *,
|
int eval_pfaltq(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
|
||||||
struct node_queue_opt *);
|
struct node_queue_opt *);
|
||||||
@ -170,9 +173,9 @@ int eval_pfqueue(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
|
|||||||
struct node_queue_opt *);
|
struct node_queue_opt *);
|
||||||
|
|
||||||
void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
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 *,
|
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 *,
|
int pfctl_define_table(char *, int, int, const char *, const char *,
|
||||||
struct pfr_buffer *, u_int32_t);
|
struct pfr_buffer *, u_int32_t);
|
||||||
@ -217,8 +220,8 @@ extern const struct pf_timeout pf_timeouts[];
|
|||||||
void set_ipmask(struct node_host *, u_int8_t);
|
void set_ipmask(struct node_host *, u_int8_t);
|
||||||
int check_netmask(struct node_host *, sa_family_t);
|
int check_netmask(struct node_host *, sa_family_t);
|
||||||
void ifa_load(void);
|
void ifa_load(void);
|
||||||
struct node_host *ifa_exists(const char *);
|
struct node_host *ifa_exists(const char *, int);
|
||||||
struct node_host *ifa_lookup(const char *, enum pfctl_iflookup_mode);
|
struct node_host *ifa_lookup(const char *, int);
|
||||||
struct node_host *host(const char *);
|
struct node_host *host(const char *);
|
||||||
|
|
||||||
int append_addr(struct pfr_buffer *, char *, int);
|
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>
|
* Copyright (c) Henning Brauer <henning@openbsd.org>
|
||||||
@ -81,24 +81,36 @@ void pfctl_print_altq_nodestat(int,
|
|||||||
void update_avg(struct pf_altq_node *);
|
void update_avg(struct pf_altq_node *);
|
||||||
|
|
||||||
int
|
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;
|
struct pf_altq_node *root = NULL, *node;
|
||||||
|
int nodes, dotitle = (opts & PF_OPT_SHOWALL);
|
||||||
|
|
||||||
if (pfctl_update_qstats(dev, &root))
|
|
||||||
|
if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
|
||||||
return (-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;
|
||||||
|
if (dotitle) {
|
||||||
|
pfctl_print_title("ALTQ:");
|
||||||
|
dotitle = 0;
|
||||||
|
}
|
||||||
pfctl_print_altq_node(dev, node, 0, opts);
|
pfctl_print_altq_node(dev, node, 0, opts);
|
||||||
|
}
|
||||||
|
|
||||||
while (verbose2) {
|
while (verbose2) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
sleep(STAT_INTERVAL);
|
sleep(STAT_INTERVAL);
|
||||||
if (pfctl_update_qstats(dev, &root))
|
if (pfctl_update_qstats(dev, &root) == -1)
|
||||||
return (-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_print_altq_node(dev, node, 0, opts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pfctl_free_altq_node(root);
|
pfctl_free_altq_node(root);
|
||||||
return (0);
|
return (0);
|
||||||
@ -155,7 +167,7 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (0);
|
return (mnr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -245,12 +257,13 @@ pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned level,
|
|||||||
pfctl_print_altq_nodestat(dev, node);
|
pfctl_print_altq_nodestat(dev, node);
|
||||||
|
|
||||||
if (opts & PF_OPT_DEBUG)
|
if (opts & PF_OPT_DEBUG)
|
||||||
printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n", node->altq.qid,
|
printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n",
|
||||||
node->altq.ifname, rate2str((double)(node->altq.ifbandwidth)));
|
node->altq.qid, node->altq.ifname,
|
||||||
|
rate2str((double)(node->altq.ifbandwidth)));
|
||||||
|
|
||||||
for (child = node->children; child != NULL;
|
for (child = node->children; child != NULL;
|
||||||
child = child->next)
|
child = child->next)
|
||||||
pfctl_print_altq_node(dev, child, level+1, opts);
|
pfctl_print_altq_node(dev, child, level + 1, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -277,10 +290,10 @@ print_cbqstats(struct queue_stats cur)
|
|||||||
{
|
{
|
||||||
printf(" [ pkts: %10llu bytes: %10llu "
|
printf(" [ pkts: %10llu bytes: %10llu "
|
||||||
"dropped pkts: %6llu bytes: %6llu ]\n",
|
"dropped pkts: %6llu bytes: %6llu ]\n",
|
||||||
cur.data.cbq_stats.xmit_cnt.packets,
|
(unsigned long long)cur.data.cbq_stats.xmit_cnt.packets,
|
||||||
cur.data.cbq_stats.xmit_cnt.bytes,
|
(unsigned long long)cur.data.cbq_stats.xmit_cnt.bytes,
|
||||||
cur.data.cbq_stats.drop_cnt.packets,
|
(unsigned long long)cur.data.cbq_stats.drop_cnt.packets,
|
||||||
cur.data.cbq_stats.drop_cnt.bytes);
|
(unsigned long long)cur.data.cbq_stats.drop_cnt.bytes);
|
||||||
printf(" [ qlength: %3d/%3d borrows: %6u suspends: %6u ]\n",
|
printf(" [ qlength: %3d/%3d borrows: %6u suspends: %6u ]\n",
|
||||||
cur.data.cbq_stats.qcnt, cur.data.cbq_stats.qmax,
|
cur.data.cbq_stats.qcnt, cur.data.cbq_stats.qmax,
|
||||||
cur.data.cbq_stats.borrows, cur.data.cbq_stats.delays);
|
cur.data.cbq_stats.borrows, cur.data.cbq_stats.delays);
|
||||||
@ -298,10 +311,10 @@ print_priqstats(struct queue_stats cur)
|
|||||||
{
|
{
|
||||||
printf(" [ pkts: %10llu bytes: %10llu "
|
printf(" [ pkts: %10llu bytes: %10llu "
|
||||||
"dropped pkts: %6llu bytes: %6llu ]\n",
|
"dropped pkts: %6llu bytes: %6llu ]\n",
|
||||||
cur.data.priq_stats.xmitcnt.packets,
|
(unsigned long long)cur.data.priq_stats.xmitcnt.packets,
|
||||||
cur.data.priq_stats.xmitcnt.bytes,
|
(unsigned long long)cur.data.priq_stats.xmitcnt.bytes,
|
||||||
cur.data.priq_stats.dropcnt.packets,
|
(unsigned long long)cur.data.priq_stats.dropcnt.packets,
|
||||||
cur.data.priq_stats.dropcnt.bytes);
|
(unsigned long long)cur.data.priq_stats.dropcnt.bytes);
|
||||||
printf(" [ qlength: %3d/%3d ]\n",
|
printf(" [ qlength: %3d/%3d ]\n",
|
||||||
cur.data.priq_stats.qlength, cur.data.priq_stats.qlimit);
|
cur.data.priq_stats.qlength, cur.data.priq_stats.qlimit);
|
||||||
|
|
||||||
@ -318,10 +331,10 @@ print_hfscstats(struct queue_stats cur)
|
|||||||
{
|
{
|
||||||
printf(" [ pkts: %10llu bytes: %10llu "
|
printf(" [ pkts: %10llu bytes: %10llu "
|
||||||
"dropped pkts: %6llu bytes: %6llu ]\n",
|
"dropped pkts: %6llu bytes: %6llu ]\n",
|
||||||
cur.data.hfsc_stats.xmit_cnt.packets,
|
(unsigned long long)cur.data.hfsc_stats.xmit_cnt.packets,
|
||||||
cur.data.hfsc_stats.xmit_cnt.bytes,
|
(unsigned long long)cur.data.hfsc_stats.xmit_cnt.bytes,
|
||||||
cur.data.hfsc_stats.drop_cnt.packets,
|
(unsigned long long)cur.data.hfsc_stats.drop_cnt.packets,
|
||||||
cur.data.hfsc_stats.drop_cnt.bytes);
|
(unsigned long long)cur.data.hfsc_stats.drop_cnt.bytes);
|
||||||
printf(" [ qlength: %3d/%3d ]\n",
|
printf(" [ qlength: %3d/%3d ]\n",
|
||||||
cur.data.hfsc_stats.qlength, cur.data.hfsc_stats.qlimit);
|
cur.data.hfsc_stats.qlength, cur.data.hfsc_stats.qlimit);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_radix.c,v 1.21 2003/09/24 09:12:35 cedric Exp $ */
|
/* $OpenBSD: pfctl_radix.c,v 1.24 2004/02/10 18:29:30 henning Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002 Cedric Berger
|
* Copyright (c) 2002 Cedric Berger
|
||||||
@ -259,7 +259,8 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
|
|||||||
{
|
{
|
||||||
struct pfioc_table io;
|
struct pfioc_table io;
|
||||||
|
|
||||||
if (tbl == NULL || size == NULL || *size < 0 || (*size && addr == NULL)) {
|
if (tbl == NULL || size == NULL || *size < 0 ||
|
||||||
|
(*size && addr == NULL)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@ -281,7 +282,8 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
|
|||||||
{
|
{
|
||||||
struct pfioc_table io;
|
struct pfioc_table io;
|
||||||
|
|
||||||
if (tbl == NULL || size == NULL || *size < 0 || (*size && addr == NULL)) {
|
if (tbl == NULL || size == NULL || *size < 0 ||
|
||||||
|
(*size && addr == NULL)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@ -454,11 +456,40 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* interface management code */
|
||||||
|
|
||||||
|
int
|
||||||
|
pfi_get_ifaces(const char *filter, struct pfi_if *buf, int *size, int flags)
|
||||||
|
{
|
||||||
|
struct pfioc_iface io;
|
||||||
|
|
||||||
|
if (size == NULL || *size < 0 || (*size && buf == NULL)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
bzero(&io, sizeof io);
|
||||||
|
io.pfiio_flags = flags;
|
||||||
|
if (filter != NULL)
|
||||||
|
if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
|
||||||
|
sizeof(io.pfiio_name)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
io.pfiio_buffer = buf;
|
||||||
|
io.pfiio_esize = sizeof(*buf);
|
||||||
|
io.pfiio_size = *size;
|
||||||
|
if (ioctl(dev, DIOCIGETIFACES, &io))
|
||||||
|
return (-1);
|
||||||
|
*size = io.pfiio_size;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/* buffer management code */
|
/* buffer management code */
|
||||||
|
|
||||||
size_t buf_esize[PFRB_MAX] = { 0,
|
size_t buf_esize[PFRB_MAX] = { 0,
|
||||||
sizeof(struct pfr_table), sizeof(struct pfr_tstats),
|
sizeof(struct pfr_table), sizeof(struct pfr_tstats),
|
||||||
sizeof(struct pfr_addr), sizeof(struct pfr_astats),
|
sizeof(struct pfr_addr), sizeof(struct pfr_astats),
|
||||||
|
sizeof(struct pfi_if), sizeof(struct pfioc_trans_e)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
* Copyright (c) 2002 Cedric Berger
|
||||||
@ -61,12 +61,19 @@ static void print_addrx(struct pfr_addr *, struct pfr_addr *, int);
|
|||||||
static void print_astats(struct pfr_astats *, int);
|
static void print_astats(struct pfr_astats *, int);
|
||||||
static void radix_perror(void);
|
static void radix_perror(void);
|
||||||
static void xprintf(int, const char *, ...);
|
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] = {
|
static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = {
|
||||||
{ "In/Block:", "In/Pass:", "In/XPass:" },
|
{ "In/Block:", "In/Pass:", "In/XPass:" },
|
||||||
{ "Out/Block:", "Out/Pass:", "Out/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 { \
|
#define RVTEST(fct) do { \
|
||||||
if ((!(opts & PF_OPT_NOACTION) || \
|
if ((!(opts & PF_OPT_NOACTION) || \
|
||||||
(opts & PF_OPT_DUMMYACTION)) && \
|
(opts & PF_OPT_DUMMYACTION)) && \
|
||||||
@ -115,12 +122,12 @@ int
|
|||||||
pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||||
char *file, const char *anchor, const char *ruleset, int opts)
|
char *file, const char *anchor, const char *ruleset, int opts)
|
||||||
{
|
{
|
||||||
struct pfr_table table;
|
struct pfr_table table;
|
||||||
struct pfr_buffer b, b2;
|
struct pfr_buffer b, b2;
|
||||||
struct pfr_addr *a, *a2;
|
struct pfr_addr *a, *a2;
|
||||||
int nadd = 0, ndel = 0, nchange = 0, nzero = 0;
|
int nadd = 0, ndel = 0, nchange = 0, nzero = 0;
|
||||||
int rv = 0, flags = 0, nmatch = 0;
|
int rv = 0, flags = 0, nmatch = 0;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
if (command == NULL)
|
if (command == NULL)
|
||||||
usage();
|
usage();
|
||||||
@ -165,6 +172,10 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
|||||||
if (b.pfrb_size <= b.pfrb_msize)
|
if (b.pfrb_size <= b.pfrb_msize)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts & PF_OPT_SHOWALL && b.pfrb_size > 0)
|
||||||
|
pfctl_print_title("TABLES:");
|
||||||
|
|
||||||
PFRB_FOREACH(p, &b)
|
PFRB_FOREACH(p, &b)
|
||||||
if (opts & PF_OPT_VERBOSE2)
|
if (opts & PF_OPT_VERBOSE2)
|
||||||
print_tstats(p, opts & PF_OPT_DEBUG);
|
print_tstats(p, opts & PF_OPT_DEBUG);
|
||||||
@ -243,7 +254,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
|||||||
opts & PF_OPT_USEDNS);
|
opts & PF_OPT_USEDNS);
|
||||||
} else if (!strcmp(command, "show")) {
|
} else if (!strcmp(command, "show")) {
|
||||||
b.pfrb_type = (opts & PF_OPT_VERBOSE) ?
|
b.pfrb_type = (opts & PF_OPT_VERBOSE) ?
|
||||||
PFRB_ASTATS : PFRB_ADDRS;
|
PFRB_ASTATS : PFRB_ADDRS;
|
||||||
if (argc || file != NULL)
|
if (argc || file != NULL)
|
||||||
usage();
|
usage();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -325,9 +336,9 @@ print_table(struct pfr_table *ta, int verbose, int debug)
|
|||||||
(ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
|
(ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
|
||||||
ta->pfrt_name);
|
ta->pfrt_name);
|
||||||
if (ta->pfrt_anchor[0])
|
if (ta->pfrt_anchor[0])
|
||||||
printf("\t%s", ta->pfrt_anchor);
|
printf("\t%s", ta->pfrt_anchor);
|
||||||
if (ta->pfrt_ruleset[0])
|
if (ta->pfrt_ruleset[0])
|
||||||
printf(":%s", ta->pfrt_ruleset);
|
printf(":%s", ta->pfrt_ruleset);
|
||||||
puts("");
|
puts("");
|
||||||
} else
|
} else
|
||||||
puts(ta->pfrt_name);
|
puts(ta->pfrt_name);
|
||||||
@ -348,13 +359,14 @@ print_tstats(struct pfr_tstats *ts, int debug)
|
|||||||
ts->pfrts_refcnt[PFR_REFCNT_ANCHOR],
|
ts->pfrts_refcnt[PFR_REFCNT_ANCHOR],
|
||||||
ts->pfrts_refcnt[PFR_REFCNT_RULE]);
|
ts->pfrts_refcnt[PFR_REFCNT_RULE]);
|
||||||
printf("\tEvaluations: [ NoMatch: %-18llu Match: %-18llu ]\n",
|
printf("\tEvaluations: [ NoMatch: %-18llu Match: %-18llu ]\n",
|
||||||
ts->pfrts_nomatch, ts->pfrts_match);
|
(unsigned long long)ts->pfrts_nomatch,
|
||||||
|
(unsigned long long)ts->pfrts_match);
|
||||||
for (dir = 0; dir < PFR_DIR_MAX; dir++)
|
for (dir = 0; dir < PFR_DIR_MAX; dir++)
|
||||||
for (op = 0; op < PFR_OP_TABLE_MAX; op++)
|
for (op = 0; op < PFR_OP_TABLE_MAX; op++)
|
||||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||||
stats_text[dir][op],
|
stats_text[dir][op],
|
||||||
ts->pfrts_packets[dir][op],
|
(unsigned long long)ts->pfrts_packets[dir][op],
|
||||||
ts->pfrts_bytes[dir][op]);
|
(unsigned long long)ts->pfrts_bytes[dir][op]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -431,8 +443,8 @@ print_astats(struct pfr_astats *as, int dns)
|
|||||||
for (op = 0; op < PFR_OP_ADDR_MAX; op++)
|
for (op = 0; op < PFR_OP_ADDR_MAX; op++)
|
||||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||||
stats_text[dir][op],
|
stats_text[dir][op],
|
||||||
as->pfras_packets[dir][op],
|
(unsigned long long)as->pfras_packets[dir][op],
|
||||||
as->pfras_bytes[dir][op]);
|
(unsigned long long)as->pfras_bytes[dir][op]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -449,12 +461,11 @@ pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
|||||||
struct pfr_table tbl;
|
struct pfr_table tbl;
|
||||||
|
|
||||||
bzero(&tbl, sizeof(tbl));
|
bzero(&tbl, sizeof(tbl));
|
||||||
if (strlcpy(tbl.pfrt_name, name,
|
if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
|
||||||
sizeof(tbl.pfrt_name)) >= sizeof(tbl.pfrt_name) ||
|
sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
|
||||||
strlcpy(tbl.pfrt_anchor, anchor,
|
|
||||||
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) ||
|
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) ||
|
||||||
strlcpy(tbl.pfrt_ruleset, ruleset,
|
strlcpy(tbl.pfrt_ruleset, ruleset, sizeof(tbl.pfrt_ruleset)) >=
|
||||||
sizeof(tbl.pfrt_ruleset)) >= sizeof(tbl.pfrt_ruleset))
|
sizeof(tbl.pfrt_ruleset))
|
||||||
errx(1, "pfctl_define_table: strlcpy");
|
errx(1, "pfctl_define_table: strlcpy");
|
||||||
tbl.pfrt_flags = flags;
|
tbl.pfrt_flags = flags;
|
||||||
|
|
||||||
@ -477,7 +488,7 @@ warn_namespace_collision(const char *filter)
|
|||||||
b.pfrb_size = b.pfrb_msize;
|
b.pfrb_size = b.pfrb_msize;
|
||||||
if (pfr_get_tables(NULL, b.pfrb_caddr,
|
if (pfr_get_tables(NULL, b.pfrb_caddr,
|
||||||
&b.pfrb_size, PFR_FLAG_ALLRSETS))
|
&b.pfrb_size, PFR_FLAG_ALLRSETS))
|
||||||
err(1, "pfr_get_tables");
|
err(1, "pfr_get_tables");
|
||||||
if (b.pfrb_size <= b.pfrb_msize)
|
if (b.pfrb_size <= b.pfrb_msize)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -522,3 +533,79 @@ xprintf(int opts, const char *fmt, ...)
|
|||||||
else
|
else
|
||||||
fprintf(stderr, ".\n");
|
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);
|
||||||
|
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.8,v 1.22 2003/06/03 13:16:08 jmc Exp $
|
.\" $OpenBSD: pflogd.8,v 1.24 2004/01/16 10:45:49 jmc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2001 Can Erkin Acar. All rights reserved.
|
.\" Copyright (c) 2001 Can Erkin Acar. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -32,7 +32,7 @@
|
|||||||
.Nd packet filter logging daemon
|
.Nd packet filter logging daemon
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm pflogd
|
.Nm pflogd
|
||||||
.Op Fl D
|
.Op Fl Dx
|
||||||
.Op Fl d Ar delay
|
.Op Fl d Ar delay
|
||||||
.Op Fl f Ar filename
|
.Op Fl f Ar filename
|
||||||
.Op Fl s Ar snaplen
|
.Op Fl s Ar snaplen
|
||||||
@ -57,11 +57,11 @@ hopefully offline in case there are bugs in the packet parsing code of
|
|||||||
.Pp
|
.Pp
|
||||||
.Nm
|
.Nm
|
||||||
closes and then re-opens the log file when it receives
|
closes and then re-opens the log file when it receives
|
||||||
.Va SIGHUP ,
|
.Dv SIGHUP ,
|
||||||
permitting
|
permitting
|
||||||
.Xr newsyslog 8
|
.Xr newsyslog 8
|
||||||
to rotate logfiles automatically.
|
to rotate logfiles automatically.
|
||||||
.Va SIGALRM
|
.Dv SIGALRM
|
||||||
causes
|
causes
|
||||||
.Nm
|
.Nm
|
||||||
to flush the current logfile buffers to the disk, thus making the most
|
to flush the current logfile buffers to the disk, thus making the most
|
||||||
@ -71,22 +71,32 @@ The buffers are also flushed every
|
|||||||
seconds.
|
seconds.
|
||||||
.Pp
|
.Pp
|
||||||
If the log file contains data after a restart or a
|
If the log file contains data after a restart or a
|
||||||
.Va SIGHUP ,
|
.Dv SIGHUP ,
|
||||||
new logs are appended to the existing file.
|
new logs are appended to the existing file.
|
||||||
If the existing log file was created with a different snaplen,
|
If the existing log file was created with a different snaplen,
|
||||||
.Nm
|
.Nm
|
||||||
temporarily uses the old snaplen to keep the log file consistent.
|
temporarily uses the old snaplen to keep the log file consistent.
|
||||||
.Pp
|
.Pp
|
||||||
|
.Nm
|
||||||
|
tries to preserve the integrity of the log file against I/O errors.
|
||||||
|
Furthermore, integrity of an existing log file is verified before
|
||||||
|
appending.
|
||||||
|
If there is an invalid log file or an I/O error, logging is suspended until a
|
||||||
|
.Dv SIGHUP
|
||||||
|
or a
|
||||||
|
.Dv SIGALRM
|
||||||
|
is received.
|
||||||
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl d Ar delay
|
|
||||||
Time in seconds to delay between automatic flushes of the file.
|
|
||||||
This may be specified with a value between 5 and 3600 seconds.
|
|
||||||
If not specified, the default is 60 seconds.
|
|
||||||
.It Fl D
|
.It Fl D
|
||||||
Debugging mode.
|
Debugging mode.
|
||||||
.Nm
|
.Nm
|
||||||
does not disassociate from the controlling terminal.
|
does not disassociate from the controlling terminal.
|
||||||
|
.It Fl d Ar delay
|
||||||
|
Time in seconds to delay between automatic flushes of the file.
|
||||||
|
This may be specified with a value between 5 and 3600 seconds.
|
||||||
|
If not specified, the default is 60 seconds.
|
||||||
.It Fl f Ar filename
|
.It Fl f Ar filename
|
||||||
Log output filename.
|
Log output filename.
|
||||||
Default is
|
Default is
|
||||||
@ -98,6 +108,8 @@ bytes of data from each packet rather than the default of 96.
|
|||||||
The default of 96 is adequate for IP, ICMP, TCP, and UDP headers but may
|
The default of 96 is adequate for IP, ICMP, TCP, and UDP headers but may
|
||||||
truncate protocol information for other protocols.
|
truncate protocol information for other protocols.
|
||||||
Other file parsers may desire a higher snaplen.
|
Other file parsers may desire a higher snaplen.
|
||||||
|
.It Fl x
|
||||||
|
Check the integrity of an existing log file, and return.
|
||||||
.It Ar expression
|
.It Ar expression
|
||||||
Selects which packets will be dumped, using the regular language of
|
Selects which packets will be dumped, using the regular language of
|
||||||
.Xr tcpdump 8 .
|
.Xr tcpdump 8 .
|
||||||
@ -106,13 +118,13 @@ Selects which packets will be dumped, using the regular language of
|
|||||||
.Bl -tag -width /var/run/pflogd.pid -compact
|
.Bl -tag -width /var/run/pflogd.pid -compact
|
||||||
.It Pa /var/run/pflogd.pid
|
.It Pa /var/run/pflogd.pid
|
||||||
Process ID of the currently running
|
Process ID of the currently running
|
||||||
.Nm pflogd .
|
.Nm .
|
||||||
.It Pa /var/log/pflog
|
.It Pa /var/log/pflog
|
||||||
Default log file.
|
Default log file.
|
||||||
.El
|
.El
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
Log specific tcp packets to a different log file with a large snaplen
|
Log specific tcp packets to a different log file with a large snaplen
|
||||||
(useful with a log-all rule to dump complete sessions)
|
(useful with a log-all rule to dump complete sessions):
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# pflogd -s 1600 -f suspicious.log port 80 and host evilhost
|
# pflogd -s 1600 -f suspicious.log port 80 and host evilhost
|
||||||
.Ed
|
.Ed
|
||||||
@ -123,7 +135,8 @@ Display binary logs:
|
|||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Display the logs in real time (this does not interfere with the
|
Display the logs in real time (this does not interfere with the
|
||||||
operation of pflogd):
|
operation of
|
||||||
|
.Nm ) :
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# tcpdump -n -e -ttt -i pflog0
|
# tcpdump -n -e -ttt -i pflog0
|
||||||
.Ed
|
.Ed
|
||||||
@ -133,7 +146,7 @@ structure defined in
|
|||||||
.Aq Ar net/if_pflog.h .
|
.Aq Ar net/if_pflog.h .
|
||||||
Tcpdump can restrict the output
|
Tcpdump can restrict the output
|
||||||
to packets logged on a specified interface, a rule number, a reason,
|
to packets logged on a specified interface, a rule number, a reason,
|
||||||
a direction, an ip family or an action.
|
a direction, an IP family or an action.
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width "reason match " -compact
|
.Bl -tag -width "reason match " -compact
|
||||||
.It ip
|
.It ip
|
||||||
@ -141,9 +154,9 @@ Address family equals IPv4.
|
|||||||
.It ip6
|
.It ip6
|
||||||
Address family equals IPv6.
|
Address family equals IPv6.
|
||||||
.It ifname kue0
|
.It ifname kue0
|
||||||
Interface name equals "kue0"
|
Interface name equals "kue0".
|
||||||
.It on kue0
|
.It on kue0
|
||||||
Interface name equals "kue0"
|
Interface name equals "kue0".
|
||||||
.It rulenum 10
|
.It rulenum 10
|
||||||
Rule number equals 10.
|
Rule number equals 10.
|
||||||
.It reason match
|
.It reason match
|
||||||
|
@ -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
|
* Copyright (c) 2001 Theo de Raadt
|
||||||
@ -31,6 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -45,21 +46,14 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
#include "pflogd.h"
|
||||||
#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"
|
|
||||||
|
|
||||||
pcap_t *hpcap;
|
pcap_t *hpcap;
|
||||||
pcap_dumper_t *dpcap;
|
static FILE *dpcap;
|
||||||
|
|
||||||
int Debug = 0;
|
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;
|
volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup;
|
||||||
|
|
||||||
@ -72,15 +66,43 @@ char errbuf[PCAP_ERRBUF_SIZE];
|
|||||||
int log_debug = 0;
|
int log_debug = 0;
|
||||||
unsigned int delay = FLUSH_DELAY;
|
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);
|
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 reset_dump(void);
|
||||||
|
int scan_dump(FILE *, off_t);
|
||||||
|
int set_snaplen(int);
|
||||||
|
void set_suspended(int);
|
||||||
void sig_alrm(int);
|
void sig_alrm(int);
|
||||||
void sig_close(int);
|
void sig_close(int);
|
||||||
void sig_hup(int);
|
void sig_hup(int);
|
||||||
void usage(void);
|
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 *
|
char *
|
||||||
copy_argv(char * const *argv)
|
copy_argv(char * const *argv)
|
||||||
@ -125,7 +147,7 @@ logmsg(int pri, const char *message, ...)
|
|||||||
__dead void
|
__dead void
|
||||||
usage(void)
|
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");
|
fprintf(stderr, "[-s snaplen] [expression]\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -148,37 +170,60 @@ sig_alrm(int sig)
|
|||||||
gotsig_alrm = 1;
|
gotsig_alrm = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
init_pcap(void)
|
set_pcap_filter(void)
|
||||||
{
|
{
|
||||||
struct bpf_program bprog;
|
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)
|
if (pcap_compile(hpcap, &bprog, filter, PCAP_OPT_FIL, 0) < 0)
|
||||||
logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
|
logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
|
||||||
else if (pcap_setfilter(hpcap, &bprog) < 0)
|
else {
|
||||||
logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
|
if (pcap_setfilter(hpcap, &bprog) < 0)
|
||||||
if (filter != NULL)
|
logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
|
||||||
free(filter);
|
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) {
|
if (pcap_datalink(hpcap) != DLT_PFLOG) {
|
||||||
logmsg(LOG_ERR, "Invalid datalink type");
|
logmsg(LOG_ERR, "Invalid datalink type");
|
||||||
pcap_close(hpcap);
|
pcap_close(hpcap);
|
||||||
hpcap = oldhpcap;
|
hpcap = NULL;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldhpcap)
|
set_pcap_filter();
|
||||||
pcap_close(oldhpcap);
|
|
||||||
|
cur_snaplen = snaplen = pcap_snapshot(hpcap);
|
||||||
|
|
||||||
|
/* lock */
|
||||||
|
if (ioctl(pcap_fileno(hpcap), BIOCLOCK) < 0) {
|
||||||
|
logmsg(LOG_ERR, "BIOCLOCK: %s", strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,45 +232,51 @@ reset_dump(void)
|
|||||||
{
|
{
|
||||||
struct pcap_file_header hdr;
|
struct pcap_file_header hdr;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int tmpsnap;
|
int fd;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (hpcap == NULL)
|
if (hpcap == NULL)
|
||||||
return (1);
|
return (-1);
|
||||||
|
|
||||||
if (dpcap) {
|
if (dpcap) {
|
||||||
pcap_dump_close(dpcap);
|
flush_buffer(dpcap);
|
||||||
dpcap = 0;
|
fclose(dpcap);
|
||||||
|
dpcap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Basically reimplement pcap_dump_open() because it truncates
|
* Basically reimplement pcap_dump_open() because it truncates
|
||||||
* files and duplicates headers and such.
|
* 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) {
|
if (fp == NULL) {
|
||||||
snprintf(hpcap->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
|
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||||
filename, pcap_strerror(errno));
|
|
||||||
logmsg(LOG_ERR, "Error: %s", pcap_geterr(hpcap));
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (fstat(fileno(fp), &st) == -1) {
|
if (fstat(fileno(fp), &st) == -1) {
|
||||||
snprintf(hpcap->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
|
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||||
filename, pcap_strerror(errno));
|
|
||||||
logmsg(LOG_ERR, "Error: %s", pcap_geterr(hpcap));
|
|
||||||
return (1);
|
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
|
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||||
|
|
||||||
if (st.st_size == 0) {
|
if (st.st_size == 0) {
|
||||||
if (snaplen != pcap_snapshot(hpcap)) {
|
if (snaplen != cur_snaplen) {
|
||||||
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
||||||
if (init_pcap()) {
|
if (set_snaplen(snaplen)) {
|
||||||
logmsg(LOG_ERR, "Failed to initialize");
|
logmsg(LOG_WARNING,
|
||||||
if (hpcap == NULL) return (-1);
|
"Failed, using old settings");
|
||||||
logmsg(LOG_NOTICE, "Using old settings");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hdr.magic = TCPDUMP_MAGIC;
|
hdr.magic = TCPDUMP_MAGIC;
|
||||||
@ -237,58 +288,224 @@ reset_dump(void)
|
|||||||
hdr.linktype = hpcap->linktype;
|
hdr.linktype = hpcap->linktype;
|
||||||
|
|
||||||
if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
|
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);
|
fclose(fp);
|
||||||
return (1);
|
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,
|
logmsg(LOG_WARNING,
|
||||||
"Existing file specifies a snaplen of %u, using it",
|
"Failed, using old settings, offset %llu",
|
||||||
hdr.snaplen);
|
(unsigned long long) size);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) fseek(fp, 0L, SEEK_END);
|
|
||||||
return (0);
|
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
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct pcap_stat pstat;
|
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) {
|
closefrom(STDERR_FILENO + 1);
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "Dxd:s:f:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'D':
|
case 'D':
|
||||||
Debug = 1;
|
Debug = 1;
|
||||||
@ -305,6 +522,11 @@ main(int argc, char **argv)
|
|||||||
snaplen = atoi(optarg);
|
snaplen = atoi(optarg);
|
||||||
if (snaplen <= 0)
|
if (snaplen <= 0)
|
||||||
snaplen = DEF_SNAPLEN;
|
snaplen = DEF_SNAPLEN;
|
||||||
|
if (snaplen > PFLOGD_MAXSNAPLEN)
|
||||||
|
snaplen = PFLOGD_MAXSNAPLEN;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
Xflag++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
@ -327,6 +549,27 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
(void)umask(S_IRWXG | S_IRWXO);
|
(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(SIGTERM, sig_close);
|
||||||
signal(SIGINT, sig_close);
|
signal(SIGINT, sig_close);
|
||||||
signal(SIGQUIT, sig_close);
|
signal(SIGQUIT, sig_close);
|
||||||
@ -334,25 +577,29 @@ main(int argc, char **argv)
|
|||||||
signal(SIGHUP, sig_hup);
|
signal(SIGHUP, sig_hup);
|
||||||
alarm(delay);
|
alarm(delay);
|
||||||
|
|
||||||
if (argc) {
|
buffer = malloc(PFLOGD_BUFSIZE);
|
||||||
filter = copy_argv(argv);
|
|
||||||
if (filter == NULL)
|
|
||||||
logmsg(LOG_NOTICE, "Failed to form filter expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init_pcap()) {
|
if (buffer == NULL) {
|
||||||
logmsg(LOG_ERR, "Exiting, init failure");
|
logmsg(LOG_WARNING, "Failed to allocate output buffer");
|
||||||
exit(1);
|
phandler = dump_packet_nobuf;
|
||||||
|
} else {
|
||||||
|
bufleft = buflen = PFLOGD_BUFSIZE;
|
||||||
|
bufpos = buffer;
|
||||||
|
bufpkt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reset_dump()) {
|
if (reset_dump()) {
|
||||||
logmsg(LOG_ERR, "Failed to open log file %s", filename);
|
if (Xflag)
|
||||||
pcap_close(hpcap);
|
return (1);
|
||||||
exit(1);
|
|
||||||
}
|
logmsg(LOG_ERR, "Logging suspended: open error");
|
||||||
|
set_suspended(1);
|
||||||
|
} else if (Xflag)
|
||||||
|
return (0);
|
||||||
|
|
||||||
while (1) {
|
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)
|
if (np < 0)
|
||||||
logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
|
logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
|
||||||
|
|
||||||
@ -360,38 +607,34 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
if (gotsig_hup) {
|
if (gotsig_hup) {
|
||||||
if (reset_dump()) {
|
if (reset_dump()) {
|
||||||
logmsg(LOG_ERR, "Failed to open log file!");
|
logmsg(LOG_ERR,
|
||||||
break;
|
"Logging suspended: open error");
|
||||||
|
set_suspended(1);
|
||||||
}
|
}
|
||||||
logmsg(LOG_NOTICE, "Reopened logfile");
|
|
||||||
gotsig_hup = 0;
|
gotsig_hup = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gotsig_alrm) {
|
if (gotsig_alrm) {
|
||||||
/* XXX pcap_dumper is an incomplete type which libpcap
|
if (dpcap)
|
||||||
* casts to a FILE* currently. For now it is safe to
|
flush_buffer(dpcap);
|
||||||
* make the same assumption, however this may change
|
|
||||||
* in the future.
|
|
||||||
*/
|
|
||||||
if (dpcap) {
|
|
||||||
if (fflush((FILE *)dpcap) == EOF) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gotsig_alrm = 0;
|
gotsig_alrm = 0;
|
||||||
alarm(delay);
|
alarm(delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logmsg(LOG_NOTICE, "Exiting due to signal");
|
logmsg(LOG_NOTICE, "Exiting");
|
||||||
if (dpcap)
|
if (dpcap) {
|
||||||
pcap_dump_close(dpcap);
|
flush_buffer(dpcap);
|
||||||
|
fclose(dpcap);
|
||||||
|
}
|
||||||
|
purge_buffer();
|
||||||
|
|
||||||
if (pcap_stats(hpcap, &pstat) < 0)
|
if (pcap_stats(hpcap, &pstat) < 0)
|
||||||
logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
|
logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
|
||||||
else
|
else
|
||||||
logmsg(LOG_NOTICE, "%u packets received, %u dropped",
|
logmsg(LOG_NOTICE,
|
||||||
pstat.ps_recv, pstat.ps_drop);
|
"%u packets received, %u/%u dropped (kernel/pflogd)",
|
||||||
|
pstat.ps_recv, pstat.ps_drop, packets_dropped);
|
||||||
|
|
||||||
pcap_close(hpcap);
|
pcap_close(hpcap);
|
||||||
if (!Debug)
|
if (!Debug)
|
||||||
|
47
contrib/pf/pflogd/pflogd.h
Normal file
47
contrib/pf/pflogd/pflogd.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* $OpenBSD: pflogd.h,v 1.2 2004/01/15 20:15:14 canacar Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Can Erkin Acar
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/limits.h>
|
||||||
|
#include <pcap.h>
|
||||||
|
|
||||||
|
#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 1 /* filter optimization */
|
||||||
|
#define FLUSH_DELAY 60 /* flush delay */
|
||||||
|
|
||||||
|
#define PFLOGD_LOG_FILE "/var/log/pflog"
|
||||||
|
#define PFLOGD_DEFAULT_IF "pflog0"
|
||||||
|
|
||||||
|
#define PFLOGD_MAXSNAPLEN INT_MAX
|
||||||
|
#define PFLOGD_BUFSIZE 65536 /* buffer size for incoming packets */
|
||||||
|
|
||||||
|
void logmsg(int priority, const char *message, ...);
|
||||||
|
|
||||||
|
/* Privilege separation */
|
||||||
|
int priv_init(void);
|
||||||
|
int priv_set_snaplen(int snaplen);
|
||||||
|
int priv_open_log(void);
|
||||||
|
pcap_t *pcap_open_live_fd(int fd, int snaplen, char *ebuf);
|
||||||
|
|
||||||
|
void set_pcap_filter(void);
|
||||||
|
/* File descriptor send/recv */
|
||||||
|
void send_fd(int, int);
|
||||||
|
int receive_fd(int);
|
||||||
|
|
||||||
|
extern int Debug;
|
305
contrib/pf/pflogd/privsep.c
Normal file
305
contrib/pf/pflogd/privsep.c
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
/* $OpenBSD: privsep.c,v 1.8 2004/03/14 19:17:05 otto Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Can Erkin Acar
|
||||||
|
* Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* 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/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/bpf.h>
|
||||||
|
|
||||||
|
#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 <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "pflogd.h"
|
||||||
|
|
||||||
|
enum cmd_types {
|
||||||
|
PRIV_SET_SNAPLEN, /* set the snaplength */
|
||||||
|
PRIV_OPEN_LOG /* open logfile for appending */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int priv_fd = -1;
|
||||||
|
static volatile pid_t child_pid = -1;
|
||||||
|
|
||||||
|
volatile sig_atomic_t gotsig_chld = 0;
|
||||||
|
|
||||||
|
static void sig_pass_to_chld(int);
|
||||||
|
static void sig_chld(int);
|
||||||
|
static int may_read(int, void *, size_t);
|
||||||
|
static void must_read(int, void *, size_t);
|
||||||
|
static void must_write(int, void *, size_t);
|
||||||
|
static int set_snaplen(int snap);
|
||||||
|
|
||||||
|
/* bpf filter expression common to parent and child */
|
||||||
|
extern char *filter;
|
||||||
|
extern char *errbuf;
|
||||||
|
extern char *filename;
|
||||||
|
extern pcap_t *hpcap;
|
||||||
|
|
||||||
|
/* based on syslogd privsep */
|
||||||
|
int
|
||||||
|
priv_init(void)
|
||||||
|
{
|
||||||
|
int i, fd, socks[2], cmd;
|
||||||
|
int snaplen, ret;
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
|
for (i = 1; i < _NSIG; i++)
|
||||||
|
signal(i, SIG_DFL);
|
||||||
|
|
||||||
|
/* Create sockets */
|
||||||
|
if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1)
|
||||||
|
err(1, "socketpair() failed");
|
||||||
|
|
||||||
|
pw = getpwnam("_pflogd");
|
||||||
|
if (pw == NULL)
|
||||||
|
errx(1, "unknown user _pflogd");
|
||||||
|
endpwent();
|
||||||
|
|
||||||
|
child_pid = fork();
|
||||||
|
if (child_pid < 0)
|
||||||
|
err(1, "fork() failed");
|
||||||
|
|
||||||
|
if (!child_pid) {
|
||||||
|
gid_t gidset[1];
|
||||||
|
|
||||||
|
/* Child - drop privileges and return */
|
||||||
|
if (chroot(pw->pw_dir) != 0)
|
||||||
|
err(1, "unable to chroot");
|
||||||
|
if (chdir("/") != 0)
|
||||||
|
err(1, "unable to chdir");
|
||||||
|
|
||||||
|
gidset[0] = pw->pw_gid;
|
||||||
|
if (setgroups(1, gidset) == -1)
|
||||||
|
err(1, "setgroups() failed");
|
||||||
|
if (setegid(pw->pw_gid) == -1)
|
||||||
|
err(1, "setegid() failed");
|
||||||
|
if (setgid(pw->pw_gid) == -1)
|
||||||
|
err(1, "setgid() failed");
|
||||||
|
if (seteuid(pw->pw_uid) == -1)
|
||||||
|
err(1, "seteuid() failed");
|
||||||
|
if (setuid(pw->pw_uid) == -1)
|
||||||
|
err(1, "setuid() failed");
|
||||||
|
close(socks[0]);
|
||||||
|
priv_fd = socks[1];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Father */
|
||||||
|
/* Pass ALRM/TERM/HUP through to child, and accept CHLD */
|
||||||
|
signal(SIGALRM, sig_pass_to_chld);
|
||||||
|
signal(SIGTERM, sig_pass_to_chld);
|
||||||
|
signal(SIGHUP, sig_pass_to_chld);
|
||||||
|
signal(SIGCHLD, sig_chld);
|
||||||
|
|
||||||
|
setproctitle("[priv]");
|
||||||
|
close(socks[1]);
|
||||||
|
|
||||||
|
while (!gotsig_chld) {
|
||||||
|
if (may_read(socks[0], &cmd, sizeof(int)))
|
||||||
|
break;
|
||||||
|
switch (cmd) {
|
||||||
|
case PRIV_SET_SNAPLEN:
|
||||||
|
logmsg(LOG_DEBUG,
|
||||||
|
"[priv]: msg PRIV_SET_SNAPLENGTH received");
|
||||||
|
must_read(socks[0], &snaplen, sizeof(int));
|
||||||
|
|
||||||
|
ret = set_snaplen(snaplen);
|
||||||
|
if (ret) {
|
||||||
|
logmsg(LOG_NOTICE,
|
||||||
|
"[priv]: set_snaplen failed for snaplen %d",
|
||||||
|
snaplen);
|
||||||
|
}
|
||||||
|
|
||||||
|
must_write(socks[0], &ret, sizeof(int));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRIV_OPEN_LOG:
|
||||||
|
logmsg(LOG_DEBUG,
|
||||||
|
"[priv]: msg PRIV_OPEN_LOG received");
|
||||||
|
/* create or append logs but do not follow symlinks */
|
||||||
|
fd = open(filename,
|
||||||
|
O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW,
|
||||||
|
0600);
|
||||||
|
if (fd < 0)
|
||||||
|
logmsg(LOG_NOTICE,
|
||||||
|
"[priv]: failed to open %s: %s",
|
||||||
|
filename, strerror(errno));
|
||||||
|
send_fd(socks[0], fd);
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logmsg(LOG_ERR, "[priv]: unknown command %d", cmd);
|
||||||
|
_exit(1);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is called from parent */
|
||||||
|
static int
|
||||||
|
set_snaplen(int snap)
|
||||||
|
{
|
||||||
|
if (hpcap == NULL)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
hpcap->snapshot = snap;
|
||||||
|
set_pcap_filter();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send the snaplength to privileged process
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
priv_set_snaplen(int snaplen)
|
||||||
|
{
|
||||||
|
int cmd, ret;
|
||||||
|
|
||||||
|
if (priv_fd < 0)
|
||||||
|
errx(1, "%s: called from privileged portion", __func__);
|
||||||
|
|
||||||
|
cmd = PRIV_SET_SNAPLEN;
|
||||||
|
|
||||||
|
must_write(priv_fd, &cmd, sizeof(int));
|
||||||
|
must_write(priv_fd, &snaplen, sizeof(int));
|
||||||
|
|
||||||
|
must_read(priv_fd, &ret, sizeof(int));
|
||||||
|
|
||||||
|
/* also set hpcap->snapshot in child */
|
||||||
|
if (ret == 0)
|
||||||
|
hpcap->snapshot = snaplen;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open log-file */
|
||||||
|
int
|
||||||
|
priv_open_log(void)
|
||||||
|
{
|
||||||
|
int cmd, fd;
|
||||||
|
|
||||||
|
if (priv_fd < 0)
|
||||||
|
errx(1, "%s: called from privileged portion\n", __func__);
|
||||||
|
|
||||||
|
cmd = PRIV_OPEN_LOG;
|
||||||
|
must_write(priv_fd, &cmd, sizeof(int));
|
||||||
|
fd = receive_fd(priv_fd);
|
||||||
|
|
||||||
|
return (fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If priv parent gets a TERM or HUP, pass it through to child instead */
|
||||||
|
static void
|
||||||
|
sig_pass_to_chld(int sig)
|
||||||
|
{
|
||||||
|
int oerrno = errno;
|
||||||
|
|
||||||
|
if (child_pid != -1)
|
||||||
|
kill(child_pid, sig);
|
||||||
|
errno = oerrno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if parent gets a SIGCHLD, it will exit */
|
||||||
|
static void
|
||||||
|
sig_chld(int sig)
|
||||||
|
{
|
||||||
|
gotsig_chld = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read all data or return 1 for error. */
|
||||||
|
static int
|
||||||
|
may_read(int fd, void *buf, size_t n)
|
||||||
|
{
|
||||||
|
char *s = buf;
|
||||||
|
ssize_t res, pos = 0;
|
||||||
|
|
||||||
|
while (n > pos) {
|
||||||
|
res = read(fd, s + pos, n - pos);
|
||||||
|
switch (res) {
|
||||||
|
case -1:
|
||||||
|
if (errno == EINTR || errno == EAGAIN)
|
||||||
|
continue;
|
||||||
|
case 0:
|
||||||
|
return (1);
|
||||||
|
default:
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read data with the assertion that it all must come through, or
|
||||||
|
* else abort the process. Based on atomicio() from openssh. */
|
||||||
|
static void
|
||||||
|
must_read(int fd, void *buf, size_t n)
|
||||||
|
{
|
||||||
|
char *s = buf;
|
||||||
|
ssize_t res, pos = 0;
|
||||||
|
|
||||||
|
while (n > pos) {
|
||||||
|
res = read(fd, s + pos, n - pos);
|
||||||
|
switch (res) {
|
||||||
|
case -1:
|
||||||
|
if (errno == EINTR || errno == EAGAIN)
|
||||||
|
continue;
|
||||||
|
case 0:
|
||||||
|
_exit(0);
|
||||||
|
default:
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write data with the assertion that it all has to be written, or
|
||||||
|
* else abort the process. Based on atomicio() from openssh. */
|
||||||
|
static void
|
||||||
|
must_write(int fd, void *buf, size_t n)
|
||||||
|
{
|
||||||
|
char *s = buf;
|
||||||
|
ssize_t res, pos = 0;
|
||||||
|
|
||||||
|
while (n > pos) {
|
||||||
|
res = write(fd, s + pos, n - pos);
|
||||||
|
switch (res) {
|
||||||
|
case -1:
|
||||||
|
if (errno == EINTR || errno == EAGAIN)
|
||||||
|
continue;
|
||||||
|
case 0:
|
||||||
|
_exit(0);
|
||||||
|
default:
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
120
contrib/pf/pflogd/privsep_fdpass.c
Normal file
120
contrib/pf/pflogd/privsep_fdpass.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/* $OpenBSD: privsep_fdpass.c,v 1.1 2003/10/22 18:51:55 canacar Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002 Matthieu Herrb
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials provided
|
||||||
|
* with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "pflogd.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
send_fd(int sock, int fd)
|
||||||
|
{
|
||||||
|
struct msghdr msg;
|
||||||
|
char tmp[CMSG_SPACE(sizeof(int))];
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
struct iovec vec;
|
||||||
|
int result = 0;
|
||||||
|
ssize_t n;
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
|
||||||
|
if (fd >= 0) {
|
||||||
|
msg.msg_control = (caddr_t)tmp;
|
||||||
|
msg.msg_controllen = CMSG_LEN(sizeof(int));
|
||||||
|
cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
|
cmsg->cmsg_level = SOL_SOCKET;
|
||||||
|
cmsg->cmsg_type = SCM_RIGHTS;
|
||||||
|
*(int *)CMSG_DATA(cmsg) = fd;
|
||||||
|
} else {
|
||||||
|
result = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec.iov_base = &result;
|
||||||
|
vec.iov_len = sizeof(int);
|
||||||
|
msg.msg_iov = &vec;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
|
||||||
|
if ((n = sendmsg(sock, &msg, 0)) == -1)
|
||||||
|
warn("%s: sendmsg(%d)", __func__, sock);
|
||||||
|
if (n != sizeof(int))
|
||||||
|
warnx("%s: sendmsg: expected sent 1 got %ld",
|
||||||
|
__func__, (long)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
receive_fd(int sock)
|
||||||
|
{
|
||||||
|
struct msghdr msg;
|
||||||
|
char tmp[CMSG_SPACE(sizeof(int))];
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
struct iovec vec;
|
||||||
|
ssize_t n;
|
||||||
|
int result;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
vec.iov_base = &result;
|
||||||
|
vec.iov_len = sizeof(int);
|
||||||
|
msg.msg_iov = &vec;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_control = tmp;
|
||||||
|
msg.msg_controllen = sizeof(tmp);
|
||||||
|
|
||||||
|
if ((n = recvmsg(sock, &msg, 0)) == -1)
|
||||||
|
warn("%s: recvmsg", __func__);
|
||||||
|
if (n != sizeof(int))
|
||||||
|
warnx("%s: recvmsg: expected received 1 got %ld",
|
||||||
|
__func__, (long)n);
|
||||||
|
if (result == 0) {
|
||||||
|
cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
if (cmsg->cmsg_type != SCM_RIGHTS)
|
||||||
|
warnx("%s: expected type %d got %d", __func__,
|
||||||
|
SCM_RIGHTS, cmsg->cmsg_type);
|
||||||
|
fd = (*(int *)CMSG_DATA(cmsg));
|
||||||
|
return fd;
|
||||||
|
} else {
|
||||||
|
errno = result;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user