Commit resolved import of OpenBSD 4.1 pf userland from perforce.
Approved by: re (kensmith)
This commit is contained in:
parent
fc515400ab
commit
5ee7cd2107
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=171172
@ -1,29 +1,19 @@
|
|||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\" $OpenBSD: authpf.8,v 1.38 2005/01/04 09:57:04 jmc Exp $
|
.\" $OpenBSD: authpf.8,v 1.43 2007/02/24 17:21:04 beck Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2002 Bob Beck (beck@openbsd.org>. All rights reserved.
|
.\" Copyright (c) 1998-2007 Bob Beck (beck@openbsd.org>. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
.\" modification, are permitted provided that the following conditions
|
.\" purpose with or without fee is hereby granted, provided that the above
|
||||||
.\" are met:
|
.\" copyright notice and this permission notice appear in all copies.
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\" 2. 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.
|
|
||||||
.\" 3. The name of the author may not be used to endorse or promote products
|
|
||||||
.\" derived from this software without specific prior written permission.
|
|
||||||
.\"
|
.\"
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\" 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.
|
|
||||||
.\"
|
.\"
|
||||||
.Dd March 28, 2006
|
.Dd March 28, 2006
|
||||||
.Dt AUTHPF 8
|
.Dt AUTHPF 8
|
||||||
@ -230,8 +220,11 @@ it becomes unresponsive, or if arp or address spoofing is used to
|
|||||||
hijack the session.
|
hijack the session.
|
||||||
Note that TCP keepalives are not sufficient for
|
Note that TCP keepalives are not sufficient for
|
||||||
this, since they are not secure.
|
this, since they are not secure.
|
||||||
Also note that
|
Also note that the various SSH tunnelling mechanisms,
|
||||||
|
such as
|
||||||
.Ar AllowTcpForwarding
|
.Ar AllowTcpForwarding
|
||||||
|
and
|
||||||
|
.Ar PermitTunnel ,
|
||||||
should be disabled for
|
should be disabled for
|
||||||
.Nm
|
.Nm
|
||||||
users to prevent them from circumventing restrictions imposed by the
|
users to prevent them from circumventing restrictions imposed by the
|
||||||
@ -429,8 +422,7 @@ TCP connections.
|
|||||||
external_if = "xl0"
|
external_if = "xl0"
|
||||||
internal_if = "fxp0"
|
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
|
||||||
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
|
||||||
@ -445,16 +437,15 @@ 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
|
||||||
-> 127.0.0.1 port 8081
|
-> 127.0.0.1 port 8021
|
||||||
|
|
||||||
# allow out ftp, ssh, www and https only, and allow user to negotiate
|
# allow out ftp, ssh, www and https only, and allow user to negotiate
|
||||||
# ipsec with the ipsec server.
|
# ipsec with the ipsec server.
|
||||||
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
|
||||||
port { 21, 22, 80, 443 } flags S/SA
|
port { 21, 22, 80, 443 }
|
||||||
pass in quick on $internal_if proto tcp from $user_ip to any \e
|
pass in quick on $internal_if proto tcp from $user_ip to any \e
|
||||||
port { 21, 22, 80, 443 }
|
port { 21, 22, 80, 443 }
|
||||||
pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e
|
pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp
|
||||||
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
|
.Pp
|
||||||
@ -469,7 +460,7 @@ int_if = "fxp0"
|
|||||||
# nat and tag connections...
|
# nat and tag connections...
|
||||||
nat on $ext_if from $user_ip to any tag $user_ip -> $ext_addr
|
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 in quick on $int_if from $user_ip to any
|
||||||
pass out log quick on $ext_if tagged $user_ip keep state
|
pass out log quick on $ext_if tagged $user_ip
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
With the above rules added by
|
With the above rules added by
|
||||||
@ -495,7 +486,7 @@ lines will give SMTP and IMAP access to logged in users:
|
|||||||
.Bd -literal
|
.Bd -literal
|
||||||
table <authpf_users> persist
|
table <authpf_users> persist
|
||||||
pass in on $ext_if proto tcp from <authpf_users> \e
|
pass in on $ext_if proto tcp from <authpf_users> \e
|
||||||
to port { smtp imap } keep state
|
to port { smtp imap }
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
It is also possible to use the "authpf_users"
|
It is also possible to use the "authpf_users"
|
||||||
@ -522,6 +513,7 @@ rdr-anchor "authpf/*" from <authpf_users>
|
|||||||
.Xr pf 4 ,
|
.Xr pf 4 ,
|
||||||
.Xr pf.conf 5 ,
|
.Xr pf.conf 5 ,
|
||||||
.Xr fdescfs 5 ,
|
.Xr fdescfs 5 ,
|
||||||
|
.Xr securelevel 7 ,
|
||||||
.Xr ftp-proxy 8
|
.Xr ftp-proxy 8
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
/* $OpenBSD: authpf.c,v 1.89 2005/02/10 04:24:15 joel Exp $ */
|
/* $OpenBSD: authpf.c,v 1.104 2007/02/24 17:35:08 beck Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
|
* Copyright (C) 1998 - 2007 Bob Beck (beck@openbsd.org).
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* modification, are permitted provided that the following conditions
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* are met:
|
* copyright notice and this permission notice appear in all copies.
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
* 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/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
@ -56,15 +47,13 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
extern int symset(const char *, const char *, int);
|
|
||||||
|
|
||||||
static int read_config(FILE *);
|
static int read_config(FILE *);
|
||||||
static void print_message(char *);
|
static void print_message(char *);
|
||||||
static int allowed_luser(char *);
|
static int allowed_luser(char *);
|
||||||
static int check_luser(char *, char *);
|
static int check_luser(char *, char *);
|
||||||
static int remove_stale_rulesets(void);
|
static int remove_stale_rulesets(void);
|
||||||
static int change_filter(int, const char *, const char *);
|
static int change_filter(int, const char *, const char *);
|
||||||
static int change_table(int, const char *, const char *);
|
static int change_table(int, const char *);
|
||||||
static void authpf_kill_states(void);
|
static void authpf_kill_states(void);
|
||||||
|
|
||||||
int dev; /* pf device */
|
int dev; /* pf device */
|
||||||
@ -73,7 +62,6 @@ char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
|
|||||||
char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
|
char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
|
||||||
|
|
||||||
FILE *pidfp;
|
FILE *pidfp;
|
||||||
char *infile; /* file name printed by yyerror() in parse.y */
|
|
||||||
char luser[MAXLOGNAME]; /* username */
|
char luser[MAXLOGNAME]; /* username */
|
||||||
char ipsrc[256]; /* ip as a string */
|
char ipsrc[256]; /* ip as a string */
|
||||||
char pidfile[MAXPATHLEN]; /* we save pid in this file. */
|
char pidfile[MAXPATHLEN]; /* we save pid in this file. */
|
||||||
@ -102,11 +90,16 @@ main(int argc, char *argv[])
|
|||||||
struct in6_addr ina;
|
struct in6_addr ina;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
gid_t gid;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
char *shell;
|
char *shell;
|
||||||
login_cap_t *lc;
|
login_cap_t *lc;
|
||||||
|
|
||||||
config = fopen(PATH_CONFFILE, "r");
|
config = fopen(PATH_CONFFILE, "r");
|
||||||
|
if (config == NULL) {
|
||||||
|
syslog(LOG_ERR, "can not open %s (%m)", PATH_CONFFILE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((cp = getenv("SSH_TTY")) == NULL) {
|
if ((cp = getenv("SSH_TTY")) == NULL) {
|
||||||
syslog(LOG_ERR, "non-interactive session connection for authpf");
|
syslog(LOG_ERR, "non-interactive session connection for authpf");
|
||||||
@ -143,7 +136,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
uid = getuid();
|
uid = getuid();
|
||||||
pw = getpwuid(uid);
|
pw = getpwuid(uid);
|
||||||
endpwent();
|
|
||||||
if (pw == NULL) {
|
if (pw == NULL) {
|
||||||
syslog(LOG_ERR, "cannot find user for uid %u", uid);
|
syslog(LOG_ERR, "cannot find user for uid %u", uid);
|
||||||
goto die;
|
goto die;
|
||||||
@ -256,6 +248,8 @@ main(int argc, char *argv[])
|
|||||||
if (++lockcnt > 10) {
|
if (++lockcnt > 10) {
|
||||||
syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
|
syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
|
||||||
otherpid);
|
otherpid);
|
||||||
|
fclose(pidfp);
|
||||||
|
pidfp = NULL;
|
||||||
goto dogdeath;
|
goto dogdeath;
|
||||||
}
|
}
|
||||||
sleep(1);
|
sleep(1);
|
||||||
@ -265,12 +259,22 @@ main(int argc, char *argv[])
|
|||||||
* it's lock, giving us a chance to get it now
|
* it's lock, giving us a chance to get it now
|
||||||
*/
|
*/
|
||||||
fclose(pidfp);
|
fclose(pidfp);
|
||||||
|
pidfp = NULL;
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
|
/* whack the group list */
|
||||||
|
gid = getegid();
|
||||||
|
if (setgroups(1, &gid) == -1) {
|
||||||
|
syslog(LOG_INFO, "setgroups: %s", strerror(errno));
|
||||||
|
do_death(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* revoke privs */
|
/* revoke privs */
|
||||||
seteuid(getuid());
|
uid = getuid();
|
||||||
setuid(getuid());
|
if (setresuid(uid, uid, uid) == -1) {
|
||||||
|
syslog(LOG_INFO, "setresuid: %s", strerror(errno));
|
||||||
|
do_death(0);
|
||||||
|
}
|
||||||
openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||||
|
|
||||||
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
|
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
|
||||||
@ -278,8 +282,8 @@ main(int argc, char *argv[])
|
|||||||
do_death(0);
|
do_death(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config == NULL || read_config(config)) {
|
if (read_config(config)) {
|
||||||
syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE);
|
syslog(LOG_ERR, "invalid config file %s", PATH_CONFFILE);
|
||||||
do_death(0);
|
do_death(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +302,7 @@ main(int argc, char *argv[])
|
|||||||
printf("Unable to modify filters\r\n");
|
printf("Unable to modify filters\r\n");
|
||||||
do_death(0);
|
do_death(0);
|
||||||
}
|
}
|
||||||
if (change_table(1, luser, ipsrc) == -1) {
|
if (change_table(1, ipsrc) == -1) {
|
||||||
printf("Unable to modify table\r\n");
|
printf("Unable to modify table\r\n");
|
||||||
change_filter(0, luser, ipsrc);
|
change_filter(0, luser, ipsrc);
|
||||||
do_death(0);
|
do_death(0);
|
||||||
@ -309,7 +313,7 @@ main(int argc, char *argv[])
|
|||||||
signal(SIGALRM, need_death);
|
signal(SIGALRM, need_death);
|
||||||
signal(SIGPIPE, need_death);
|
signal(SIGPIPE, need_death);
|
||||||
signal(SIGHUP, need_death);
|
signal(SIGHUP, need_death);
|
||||||
signal(SIGSTOP, need_death);
|
signal(SIGQUIT, need_death);
|
||||||
signal(SIGTSTP, need_death);
|
signal(SIGTSTP, need_death);
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("\r\nHello %s. ", luser);
|
printf("\r\nHello %s. ", luser);
|
||||||
@ -559,9 +563,11 @@ check_luser(char *luserdir, char *luser)
|
|||||||
while (fputs(tmp, stdout) != EOF && !feof(f)) {
|
while (fputs(tmp, stdout) != EOF && !feof(f)) {
|
||||||
if (fgets(tmp, sizeof(tmp), f) == NULL) {
|
if (fgets(tmp, sizeof(tmp), f) == NULL) {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
fclose(f);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fclose(f);
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return (0);
|
return (0);
|
||||||
@ -645,6 +651,7 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
char *fdpath = NULL, *userstr = NULL, *ipstr = NULL;
|
char *fdpath = NULL, *userstr = NULL, *ipstr = NULL;
|
||||||
char *rsn = NULL, *fn = NULL;
|
char *rsn = NULL, *fn = NULL;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
gid_t gid;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
|
if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
|
||||||
@ -684,8 +691,14 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
|
|
||||||
switch (pid = fork()) {
|
switch (pid = fork()) {
|
||||||
case -1:
|
case -1:
|
||||||
err(1, "fork failed");
|
syslog(LOG_ERR, "fork failed");
|
||||||
|
goto error;
|
||||||
case 0:
|
case 0:
|
||||||
|
/* revoke group privs before exec */
|
||||||
|
gid = getgid();
|
||||||
|
if (setregid(gid, gid) == -1) {
|
||||||
|
err(1, "setregid");
|
||||||
|
}
|
||||||
execvp(PATH_PFCTL, pargv);
|
execvp(PATH_PFCTL, pargv);
|
||||||
warn("exec of %s failed", PATH_PFCTL);
|
warn("exec of %s failed", PATH_PFCTL);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
@ -694,10 +707,8 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
/* parent */
|
/* parent */
|
||||||
waitpid(pid, &s, 0);
|
waitpid(pid, &s, 0);
|
||||||
if (s != 0) {
|
if (s != 0) {
|
||||||
if (WIFEXITED(s)) {
|
syslog(LOG_ERR, "pfctl exited abnormally");
|
||||||
syslog(LOG_ERR, "pfctl exited abnormally");
|
goto error;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add) {
|
if (add) {
|
||||||
@ -718,16 +729,10 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
syslog(LOG_ERR, "malloc failed");
|
syslog(LOG_ERR, "malloc failed");
|
||||||
error:
|
error:
|
||||||
free(fdpath);
|
free(fdpath);
|
||||||
fdpath = NULL;
|
|
||||||
free(rsn);
|
free(rsn);
|
||||||
rsn = NULL;
|
|
||||||
free(userstr);
|
free(userstr);
|
||||||
userstr = NULL;
|
|
||||||
free(ipstr);
|
free(ipstr);
|
||||||
ipstr = NULL;
|
|
||||||
free(fn);
|
free(fn);
|
||||||
fn = NULL;
|
|
||||||
infile = NULL;
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,13 +740,14 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
|||||||
* Add/remove this IP from the "authpf_users" table.
|
* Add/remove this IP from the "authpf_users" table.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
change_table(int add, const char *luser, const char *ipsrc)
|
change_table(int add, const char *ipsrc)
|
||||||
{
|
{
|
||||||
struct pfioc_table io;
|
struct pfioc_table io;
|
||||||
struct pfr_addr addr;
|
struct pfr_addr addr;
|
||||||
|
|
||||||
bzero(&io, sizeof(io));
|
bzero(&io, sizeof(io));
|
||||||
strlcpy(io.pfrio_table.pfrt_name, tablename, sizeof(io.pfrio_table));
|
strlcpy(io.pfrio_table.pfrt_name, tablename,
|
||||||
|
sizeof(io.pfrio_table.pfrt_name));
|
||||||
io.pfrio_buffer = &addr;
|
io.pfrio_buffer = &addr;
|
||||||
io.pfrio_esize = sizeof(addr);
|
io.pfrio_esize = sizeof(addr);
|
||||||
io.pfrio_size = 1;
|
io.pfrio_size = 1;
|
||||||
@ -834,13 +840,11 @@ do_death(int active)
|
|||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
change_filter(0, luser, ipsrc);
|
change_filter(0, luser, ipsrc);
|
||||||
change_table(0, luser, ipsrc);
|
change_table(0, ipsrc);
|
||||||
authpf_kill_states();
|
authpf_kill_states();
|
||||||
remove_stale_rulesets();
|
remove_stale_rulesets();
|
||||||
}
|
}
|
||||||
if (pidfp)
|
if (pidfile[0] && (pidfp != NULL))
|
||||||
ftruncate(fileno(pidfp), 0);
|
|
||||||
if (pidfile[0])
|
|
||||||
if (unlink(pidfile) == -1)
|
if (unlink(pidfile) == -1)
|
||||||
syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
|
syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
|
||||||
exit(ret);
|
exit(ret);
|
||||||
|
@ -1,295 +1,185 @@
|
|||||||
.\" $OpenBSD: ftp-proxy.8,v 1.42 2004/11/19 00:47:23 jmc Exp $
|
.\" $OpenBSD: ftp-proxy.8,v 1.7 2006/12/30 13:01:54 camield Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1996-2001
|
.\" Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
||||||
.\" Obtuse Systems Corporation, All rights reserved.
|
|
||||||
.\"
|
.\"
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
.\" modification, are permitted provided that the following conditions
|
.\" purpose with or without fee is hereby granted, provided that the above
|
||||||
.\" are met:
|
.\" copyright notice and this permission notice appear in all copies.
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\" 2. 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.
|
|
||||||
.\" 3. Neither the name of the University nor the names of its contributors
|
|
||||||
.\" may be used to endorse or promote products derived from this software
|
|
||||||
.\" without specific prior written permission.
|
|
||||||
.\"
|
.\"
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY OBTUSE SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
|
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL OBTUSE OR CONTRIBUTORS BE LIABLE
|
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\" 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.
|
|
||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd August 17, 2001
|
.Dd November 28, 2004
|
||||||
.Dt FTP-PROXY 8
|
.Dt FTP-PROXY 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm ftp-proxy
|
.Nm ftp-proxy
|
||||||
.Nd Internet File Transfer Protocol proxy server
|
.Nd Internet File Transfer Protocol proxy daemon
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm ftp-proxy
|
.Nm ftp-proxy
|
||||||
.Bk -words
|
.Op Fl 6Adrv
|
||||||
.Op Fl AnrVw
|
|
||||||
.Op Fl a Ar address
|
.Op Fl a Ar address
|
||||||
.Op Fl D Ar debuglevel
|
.Op Fl b Ar address
|
||||||
.Op Fl g Ar group
|
.Op Fl D Ar level
|
||||||
.Op Fl M Ar maxport
|
.Op Fl m Ar maxsessions
|
||||||
.Op Fl m Ar minport
|
.Op Fl P Ar port
|
||||||
.Op Fl R Ar address[:port]
|
.Op Fl p Ar port
|
||||||
.Op Fl S Ar address
|
.Op Fl q Ar queue
|
||||||
|
.Op Fl R Ar address
|
||||||
.Op Fl t Ar timeout
|
.Op Fl t Ar timeout
|
||||||
.Op Fl u Ar user
|
|
||||||
.Ek
|
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
is a proxy for the Internet File Transfer Protocol.
|
is a proxy for the Internet File Transfer Protocol.
|
||||||
The proxy uses
|
FTP control connections should be redirected into the proxy using the
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
and expects to have the FTP control connection as described in
|
.Ar rdr
|
||||||
.Xr services 5
|
command, after which the proxy connects to the server on behalf of
|
||||||
redirected to it via a
|
the client.
|
||||||
|
.Pp
|
||||||
|
The proxy allows data connections to pass, rewriting and redirecting
|
||||||
|
them so that the right addresses are used.
|
||||||
|
All connections from the client to the server have their source
|
||||||
|
address rewritten so they appear to come from the proxy.
|
||||||
|
Consequently, all connections from the server to the proxy have
|
||||||
|
their destination address rewritten, so they are redirected to the
|
||||||
|
client.
|
||||||
|
The proxy uses the
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
.Em rdr
|
.Ar anchor
|
||||||
command.
|
facility for this.
|
||||||
An example of how to do that is further down in this document.
|
.Pp
|
||||||
|
Assuming the FTP control connection is from $client to $server, the
|
||||||
|
proxy connected to the server using the $proxy source address, and
|
||||||
|
$port is negotiated, then
|
||||||
|
.Nm ftp-proxy
|
||||||
|
adds the following rules to the various anchors.
|
||||||
|
(These example rules use inet, but the proxy also supports inet6.)
|
||||||
|
.Pp
|
||||||
|
In case of active mode (PORT or EPRT):
|
||||||
|
.Bd -literal -offset 2n
|
||||||
|
rdr from $server to $proxy port $port -> $client
|
||||||
|
pass quick inet proto tcp \e
|
||||||
|
from $server to $client port $port
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
In case of passive mode (PASV or EPSV):
|
||||||
|
.Bd -literal -offset 2n
|
||||||
|
nat from $client to $server port $port -> $proxy
|
||||||
|
pass in quick inet proto tcp \e
|
||||||
|
from $client to $server port $port
|
||||||
|
pass out quick inet proto tcp \e
|
||||||
|
from $proxy to $server port $port
|
||||||
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
.It Fl 6
|
||||||
|
IPv6 mode.
|
||||||
|
The proxy will expect and use IPv6 addresses for all communication.
|
||||||
|
Only the extended FTP modes EPSV and EPRT are allowed with IPv6.
|
||||||
|
The proxy is in IPv4 mode by default.
|
||||||
.It Fl A
|
.It Fl A
|
||||||
Permit only anonymous FTP connections.
|
Only permit anonymous FTP connections.
|
||||||
The proxy will allow connections to log in to other sites as the user
|
Either user "ftp" or user "anonymous" is allowed.
|
||||||
.Qq ftp
|
|
||||||
or
|
|
||||||
.Qq anonymous
|
|
||||||
only.
|
|
||||||
Any attempt to log in as another user will be blocked by the proxy.
|
|
||||||
.It Fl a Ar address
|
.It Fl a Ar address
|
||||||
Specify the local IP address to use in
|
The proxy will use this as the source address for the control
|
||||||
.Xr bind 2
|
connection to a server.
|
||||||
as the source for connections made by
|
.It Fl b Ar address
|
||||||
.Nm ftp-proxy
|
Address where the proxy will listen for redirected control connections.
|
||||||
when connecting to destination FTP servers.
|
The default is 127.0.0.1, or ::1 in IPv6 mode.
|
||||||
This may be necessary if the interface address of
|
.It Fl D Ar level
|
||||||
your default route is not reachable from the destinations
|
Debug level, ranging from 0 to 7.
|
||||||
.Nm
|
Higher is more verbose.
|
||||||
is attempting connections to, or this address is different from the one
|
The default is 5.
|
||||||
connections are being NATed to.
|
(These levels correspond to the
|
||||||
In the usual case this means that
|
.Xr syslog 3
|
||||||
.Ar address
|
levels.)
|
||||||
should be a publicly visible IP address assigned to one of
|
.It Fl d
|
||||||
the interfaces on the machine running
|
Do not daemonize.
|
||||||
.Nm
|
The process will stay in the foreground, logging to standard error.
|
||||||
and should be the same address to which you are translating traffic
|
.It Fl m Ar maxsessions
|
||||||
if you are using the
|
Maximum number of concurrent FTP sessions.
|
||||||
.Fl n
|
When the proxy reaches this limit, new connections are denied.
|
||||||
option.
|
The default is 100 sessions.
|
||||||
.It Fl D Ar debuglevel
|
The limit can be lowered to a minimum of 1, or raised to a maximum of 500.
|
||||||
Specify a debug level, where the proxy emits verbose debug output
|
.It Fl P Ar port
|
||||||
into
|
Fixed server port.
|
||||||
.Xr syslogd 8
|
Only used in combination with
|
||||||
at level
|
.Fl R .
|
||||||
.Dv LOG_DEBUG .
|
The default is port 21.
|
||||||
Meaningful values of debuglevel are 0-3, where 0 is no debug output and
|
.It Fl p Ar port
|
||||||
3 is lots of debug output, the default being 0.
|
Port where the proxy will listen for redirected connections.
|
||||||
.It Fl g Ar group
|
The default is port 8021.
|
||||||
Specify the named group to drop group privileges to, after doing
|
.It Fl q Ar queue
|
||||||
.Xr pf 4
|
Create rules with queue
|
||||||
lookups which require root.
|
.Ar queue
|
||||||
By default,
|
appended, so that data connections can be queued.
|
||||||
.Nm
|
.It Fl R Ar address
|
||||||
uses the default group of the user it drops privilege to.
|
Fixed server address, also known as reverse mode.
|
||||||
.It Fl M Ar maxport
|
The proxy will always connect to the same server, regardless of
|
||||||
Specify the upper end of the port range the proxy will use for the
|
where the client wanted to connect to (before it was redirected).
|
||||||
data connections it establishes.
|
Use this option to proxy for a server behind NAT, or to forward all
|
||||||
The default is
|
connections to another proxy.
|
||||||
.Dv IPPORT_HILASTAUTO
|
|
||||||
defined in
|
|
||||||
.Aq Pa netinet/in.h
|
|
||||||
as 65535.
|
|
||||||
.It Fl m Ar minport
|
|
||||||
Specify the lower end of the port range the proxy will use for all
|
|
||||||
data connections it establishes.
|
|
||||||
The default is
|
|
||||||
.Dv IPPORT_HIFIRSTAUTO
|
|
||||||
defined in
|
|
||||||
.Aq Pa netinet/in.h
|
|
||||||
as 49152.
|
|
||||||
.It Fl n
|
|
||||||
Activate network address translation
|
|
||||||
.Pq NAT
|
|
||||||
mode.
|
|
||||||
In this mode, the proxy will not attempt to proxy passive mode
|
|
||||||
.Pq PASV or EPSV
|
|
||||||
data connections.
|
|
||||||
In order for this to work, the machine running the proxy will need to
|
|
||||||
be forwarding packets and doing network address translation to allow
|
|
||||||
the outbound passive connections from the client to reach the server.
|
|
||||||
See
|
|
||||||
.Xr pf.conf 5
|
|
||||||
for more details on NAT.
|
|
||||||
The proxy only ignores passive mode data connections when using this flag;
|
|
||||||
it will still proxy PORT and EPRT mode data connections.
|
|
||||||
Without this flag,
|
|
||||||
.Nm
|
|
||||||
does not require any IP forwarding or NAT beyond the
|
|
||||||
.Em rdr
|
|
||||||
necessary to capture the FTP control connection.
|
|
||||||
.It Fl R Ar address:[port]
|
|
||||||
Reverse proxy mode for FTP servers running behind a NAT gateway.
|
|
||||||
In this mode, no redirection is needed.
|
|
||||||
The proxy is run from
|
|
||||||
.Xr inetd 8
|
|
||||||
on the port that external clients connect to (usually 21).
|
|
||||||
Control connections and passive data connections are forwarded
|
|
||||||
to the server.
|
|
||||||
.It Fl r
|
.It Fl r
|
||||||
Use reverse host
|
Rewrite sourceport to 20 in active mode to suit ancient clients that insist
|
||||||
.Pq reverse DNS
|
on this RFC property.
|
||||||
lookups for logging and libwrap use.
|
|
||||||
By default,
|
|
||||||
the proxy does not look up hostnames for libwrap or logging purposes.
|
|
||||||
.It Fl S Ar address
|
|
||||||
Source address to use for data connections made by the proxy.
|
|
||||||
Useful when there are multiple addresses (aliases) available
|
|
||||||
to the proxy.
|
|
||||||
Clients may expect data connections to have the same source
|
|
||||||
address as the control connections, and reject or drop other
|
|
||||||
connections.
|
|
||||||
.It Fl t Ar timeout
|
.It Fl t Ar timeout
|
||||||
Specifies a timeout, in seconds.
|
Number of seconds that the control connection can be idle, before the
|
||||||
The proxy will exit and close open connections if it sees no data
|
proxy will disconnect.
|
||||||
for the duration of the timeout.
|
The maximum is 86400 seconds, which is also the default.
|
||||||
The default is 0, which means the proxy will not time out.
|
Do not set this too low, because the control connection is usually
|
||||||
.It Fl u Ar user
|
idle when large data transfers are taking place.
|
||||||
Specify the named user to drop privilege to, after doing
|
.It Fl v
|
||||||
.Xr pf 4
|
Set the 'log' flag on pf rules committed by
|
||||||
lookups which require root privilege.
|
.Nm .
|
||||||
By default,
|
Use twice to set the 'log-all' flag.
|
||||||
.Nm
|
The pf rules do not log by default.
|
||||||
drops privilege to the user
|
|
||||||
.Em proxy .
|
|
||||||
.Pp
|
|
||||||
Running as root means that the source of data connections the proxy makes
|
|
||||||
for PORT and EPRT will be the RFC mandated port 20.
|
|
||||||
When running as a non-root user, the source of the data connections from
|
|
||||||
.Nm
|
|
||||||
will be chosen randomly from the range
|
|
||||||
.Ar minport
|
|
||||||
to
|
|
||||||
.Ar maxport
|
|
||||||
as described above.
|
|
||||||
.It Fl V
|
|
||||||
Be verbose.
|
|
||||||
With this option the proxy logs the control commands
|
|
||||||
sent by clients and the replies sent by the servers to
|
|
||||||
.Xr syslogd 8 .
|
|
||||||
.It Fl w
|
|
||||||
Use the tcp wrapper access control library
|
|
||||||
.Xr hosts_access 3 ,
|
|
||||||
allowing connections to be allowed or denied based on the tcp wrapper's
|
|
||||||
.Xr hosts.allow 5
|
|
||||||
and
|
|
||||||
.Xr hosts.deny 5
|
|
||||||
files.
|
|
||||||
The proxy does libwrap operations after determining the destination
|
|
||||||
of the captured control connection, so that tcp wrapper rules may
|
|
||||||
be written based on the destination as well as the source of FTP connections.
|
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Sh CONFIGURATION
|
||||||
.Nm ftp-proxy
|
To make use of the proxy,
|
||||||
is run from
|
|
||||||
.Xr inetd 8
|
|
||||||
and requires that FTP connections are redirected to it using a
|
|
||||||
.Em rdr
|
|
||||||
rule.
|
|
||||||
A typical way to do this would be to use a
|
|
||||||
.Xr pf.conf 5
|
.Xr pf.conf 5
|
||||||
rule such as
|
needs the following rules.
|
||||||
|
All anchors are mandatory.
|
||||||
|
Adjust the rules as needed.
|
||||||
|
.Pp
|
||||||
|
In the NAT section:
|
||||||
.Bd -literal -offset 2n
|
.Bd -literal -offset 2n
|
||||||
int_if = \&"xl0\&"
|
nat-anchor "ftp-proxy/*"
|
||||||
rdr pass on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
rdr-anchor "ftp-proxy/*"
|
||||||
|
rdr pass on $int_if proto tcp from $lan to any port 21 -> \e
|
||||||
|
127.0.0.1 port 8021
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
.Xr inetd 8
|
In the rule section:
|
||||||
must then be configured to run
|
|
||||||
.Nm
|
|
||||||
on the port from above using
|
|
||||||
.Bd -literal -offset 2n
|
.Bd -literal -offset 2n
|
||||||
ftp-proxy stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy
|
anchor "ftp-proxy/*"
|
||||||
|
pass out proto tcp from $proxy to any port 21
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
|
||||||
in
|
|
||||||
.Xr inetd.conf 5 .
|
|
||||||
.Pp
|
|
||||||
.Nm
|
|
||||||
accepts the redirected control connections and forwards them
|
|
||||||
to the server.
|
|
||||||
The proxy replaces the address and port number that the client
|
|
||||||
sends through the control connection to the server with its own
|
|
||||||
address and proxy port, where it listens for the data connection.
|
|
||||||
When the server opens the data connection back to this port, the
|
|
||||||
proxy forwards it to the client.
|
|
||||||
The
|
|
||||||
.Xr pf.conf 5
|
|
||||||
rules need to let pass connections to these proxy ports
|
|
||||||
(see options
|
|
||||||
.Fl u , m ,
|
|
||||||
and
|
|
||||||
.Fl M
|
|
||||||
above) in on the external interface.
|
|
||||||
The following example allows only ports 49152 to 65535 to pass in
|
|
||||||
statefully:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
block in on $ext_if proto tcp all
|
|
||||||
pass in on $ext_if inet proto tcp from any to $ext_if \e
|
|
||||||
port > 49151 keep state
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Alternatively, rules can make use of the fact that by default,
|
|
||||||
.Nm
|
|
||||||
runs as user
|
|
||||||
.Qq proxy
|
|
||||||
to allow the backchannel connections, as in the following example:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
block in on $ext_if proto tcp all
|
|
||||||
pass in on $ext_if inet proto tcp from any to $ext_if \e
|
|
||||||
user proxy keep state
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
These examples do not cover the connections from the proxy to the
|
|
||||||
foreign FTP server.
|
|
||||||
If one does not pass outgoing connections by default additional rules
|
|
||||||
are needed.
|
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr ftp 1 ,
|
.Xr ftp 1 ,
|
||||||
.Xr pf 4 ,
|
.Xr pf 4 ,
|
||||||
.Xr hosts.allow 5 ,
|
|
||||||
.Xr hosts.deny 5 ,
|
|
||||||
.Xr inetd.conf 5 ,
|
|
||||||
.Xr pf.conf 5 ,
|
|
||||||
.Xr inetd 8 ,
|
|
||||||
.Xr pfctl 8 ,
|
|
||||||
.Xr syslogd 8
|
|
||||||
.Sh BUGS
|
|
||||||
Extended Passive mode
|
|
||||||
.Pq EPSV
|
|
||||||
is not supported by the proxy and will not work unless the proxy is run
|
|
||||||
in network address translation mode.
|
|
||||||
When not in network address translation mode, the proxy returns an error
|
|
||||||
to the client, hopefully forcing the client to revert to passive mode
|
|
||||||
.Pq PASV
|
|
||||||
which is supported.
|
|
||||||
EPSV will work in network address translation mode, assuming a
|
|
||||||
.Xr pf.conf 5
|
.Xr pf.conf 5
|
||||||
setup which allows the EPSV connections through to their destinations.
|
.Sh CAVEATS
|
||||||
|
.Xr pf 4
|
||||||
|
does not allow the ruleset to be modified if the system is running at a
|
||||||
|
.Xr securelevel 7
|
||||||
|
higher than 1.
|
||||||
|
At that level
|
||||||
|
.Nm ftp-proxy
|
||||||
|
cannot add rules to the anchors and FTP data connections may get blocked.
|
||||||
.Pp
|
.Pp
|
||||||
IPv6 is not yet supported.
|
Negotiated data connection ports below 1024 are not allowed.
|
||||||
|
.Pp
|
||||||
|
The negotiated IP address for active modes is ignored for security
|
||||||
|
reasons.
|
||||||
|
This makes third party file transfers impossible.
|
||||||
|
.Pp
|
||||||
|
.Nm ftp-proxy
|
||||||
|
chroots to "/var/empty" and changes to user "proxy" to drop privileges.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,259 +0,0 @@
|
|||||||
/* $OpenBSD: getline.c,v 1.16 2004/09/16 04:50:51 deraadt Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1985, 1988 Regents of the University of California.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. 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.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
|
||||||
*
|
|
||||||
* @(#)ftpcmd.y 5.24 (Berkeley) 2/25/91
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/telnet.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sysexits.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
int refill_buffer(struct csiob *iobp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refill the io buffer if we KNOW that data is available
|
|
||||||
*
|
|
||||||
* Returns 1 if any new data was obtained, 0 otherwise.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
refill_buffer(struct csiob *iobp)
|
|
||||||
{
|
|
||||||
int rqlen, rlen;
|
|
||||||
|
|
||||||
if (!(iobp->data_available))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
if (iobp->got_eof)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The buffer has been entirely consumed if next_byte == io_buffer_len.
|
|
||||||
* Otherwise, there is some still-to-be-used data in io_buffer.
|
|
||||||
* Shuffle it to the start of the buffer.
|
|
||||||
* Note that next_byte will never exceed io_buffer_len.
|
|
||||||
* Also, note that we MUST use bcopy because the two regions could
|
|
||||||
* overlap (memcpy isn't defined to work properly with overlapping
|
|
||||||
* regions).
|
|
||||||
*/
|
|
||||||
if (iobp->next_byte < iobp->io_buffer_len) {
|
|
||||||
int dst_ix = 0;
|
|
||||||
int src_ix = iobp->next_byte;
|
|
||||||
int amount = iobp->io_buffer_len - iobp->next_byte;
|
|
||||||
|
|
||||||
bcopy(&iobp->io_buffer[src_ix], &iobp->io_buffer[dst_ix],
|
|
||||||
amount);
|
|
||||||
iobp->io_buffer_len = amount;
|
|
||||||
} else if (iobp->next_byte == iobp->io_buffer_len)
|
|
||||||
iobp->io_buffer_len = 0;
|
|
||||||
else {
|
|
||||||
syslog(LOG_ERR, "next_byte(%d) > io_buffer_len(%d)",
|
|
||||||
iobp->next_byte, iobp->io_buffer_len);
|
|
||||||
exit(EX_OSERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
iobp->next_byte = 0;
|
|
||||||
|
|
||||||
/* don't do tiny reads, grow first if we need to */
|
|
||||||
rqlen = iobp->io_buffer_size - iobp->io_buffer_len;
|
|
||||||
if (rqlen <= 128) {
|
|
||||||
unsigned char *tmp;
|
|
||||||
|
|
||||||
iobp->io_buffer_size += 128;
|
|
||||||
tmp = realloc(iobp->io_buffer, iobp->io_buffer_size);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
syslog(LOG_INFO, "Insufficient memory");
|
|
||||||
exit(EX_UNAVAILABLE);
|
|
||||||
}
|
|
||||||
iobp->io_buffer = tmp;
|
|
||||||
rqlen = iobp->io_buffer_size - iobp->io_buffer_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Always leave an unused byte at the end of the buffer
|
|
||||||
* because the debug output uses that byte from time to time
|
|
||||||
* to ensure that something that is being printed is \0 terminated.
|
|
||||||
*/
|
|
||||||
rqlen -= 1;
|
|
||||||
|
|
||||||
doread:
|
|
||||||
rlen = read(iobp->fd, &iobp->io_buffer[iobp->io_buffer_len], rqlen);
|
|
||||||
iobp->data_available = 0;
|
|
||||||
switch (rlen) {
|
|
||||||
case -1:
|
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
goto doread;
|
|
||||||
if (errno != ECONNRESET) {
|
|
||||||
syslog(LOG_INFO, "read() failed on socket from %s (%m)",
|
|
||||||
iobp->who);
|
|
||||||
exit(EX_DATAERR);
|
|
||||||
}
|
|
||||||
/* fall through to EOF case */
|
|
||||||
case 0:
|
|
||||||
iobp->got_eof = 1;
|
|
||||||
return(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
iobp->io_buffer_len += rlen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* telnet_getline - a hacked up version of fgets to ignore TELNET escape codes.
|
|
||||||
*
|
|
||||||
* This code is derived from the getline routine found in the UC Berkeley
|
|
||||||
* ftpd code.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
telnet_getline(struct csiob *iobp, struct csiob *telnet_passthrough)
|
|
||||||
{
|
|
||||||
unsigned char ch;
|
|
||||||
int ix;
|
|
||||||
unsigned char tbuf[100];
|
|
||||||
|
|
||||||
iobp->line_buffer[0] = '\0';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the buffer is empty then refill it right away.
|
|
||||||
*/
|
|
||||||
if (iobp->next_byte == iobp->io_buffer_len)
|
|
||||||
if (!refill_buffer(iobp))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Is there a telnet command in the buffer?
|
|
||||||
*/
|
|
||||||
ch = iobp->io_buffer[iobp->next_byte];
|
|
||||||
if (ch == IAC) {
|
|
||||||
/*
|
|
||||||
* Yes - buffer must have at least three bytes in it
|
|
||||||
*/
|
|
||||||
if (iobp->io_buffer_len - iobp->next_byte < 3) {
|
|
||||||
if (!refill_buffer(iobp))
|
|
||||||
return(0);
|
|
||||||
if (iobp->io_buffer_len - iobp->next_byte < 3)
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
iobp->next_byte++;
|
|
||||||
ch = iobp->io_buffer[iobp->next_byte++];
|
|
||||||
|
|
||||||
switch (ch) {
|
|
||||||
case WILL:
|
|
||||||
case WONT:
|
|
||||||
case DO:
|
|
||||||
case DONT:
|
|
||||||
tbuf[0] = IAC;
|
|
||||||
tbuf[1] = ch;
|
|
||||||
tbuf[2] = iobp->io_buffer[iobp->next_byte++];
|
|
||||||
(void)send(telnet_passthrough->fd, tbuf, 3,
|
|
||||||
telnet_passthrough->send_oob_flags);
|
|
||||||
break;
|
|
||||||
case IAC:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return(1);
|
|
||||||
} else {
|
|
||||||
int clen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Is there a newline in the buffer?
|
|
||||||
*/
|
|
||||||
for (ix = iobp->next_byte; ix < iobp->io_buffer_len;
|
|
||||||
ix += 1) {
|
|
||||||
if (iobp->io_buffer[ix] == '\n')
|
|
||||||
break;
|
|
||||||
if (iobp->io_buffer[ix] == '\0') {
|
|
||||||
syslog(LOG_INFO,
|
|
||||||
"got NUL byte from %s - bye!",
|
|
||||||
iobp->who);
|
|
||||||
exit(EX_DATAERR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ix == iobp->io_buffer_len) {
|
|
||||||
if (!refill_buffer(iobp))
|
|
||||||
return(0);
|
|
||||||
/*
|
|
||||||
* Empty line returned
|
|
||||||
* will try again soon!
|
|
||||||
*/
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Expand the line buffer if it isn't big enough. We
|
|
||||||
* use a fudge factor of 5 rather than trying to
|
|
||||||
* figure out exactly how to account for the '\0 \r\n' and
|
|
||||||
* such. The correct fudge factor is 0, 1 or 2 but
|
|
||||||
* anything higher also works. We also grow it by a
|
|
||||||
* bunch to avoid having to do this often. Yes this is
|
|
||||||
* nasty.
|
|
||||||
*/
|
|
||||||
if (ix - iobp->next_byte > iobp->line_buffer_size - 5) {
|
|
||||||
unsigned char *tmp;
|
|
||||||
|
|
||||||
iobp->line_buffer_size = 256 + ix - iobp->next_byte;
|
|
||||||
tmp = realloc(iobp->line_buffer,
|
|
||||||
iobp->line_buffer_size);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
syslog(LOG_INFO, "Insufficient memory");
|
|
||||||
exit(EX_UNAVAILABLE);
|
|
||||||
}
|
|
||||||
iobp->line_buffer = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* +1 is for the newline */
|
|
||||||
clen = (ix+1) - iobp->next_byte;
|
|
||||||
memcpy(iobp->line_buffer, &iobp->io_buffer[iobp->next_byte],
|
|
||||||
clen);
|
|
||||||
iobp->next_byte += clen;
|
|
||||||
iobp->line_buffer[clen] = '\0';
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,306 +0,0 @@
|
|||||||
/* $OpenBSD: util.c,v 1.19 2004/07/06 19:49:11 dhartmei Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1996-2001
|
|
||||||
* Obtuse Systems Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. 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.
|
|
||||||
* 3. Neither the name of the Obtuse Systems nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE OBTUSE SYSTEMS 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 OBTUSE
|
|
||||||
* SYSTEMS CORPORATION 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/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/file.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/in_systm.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/pfvar.h>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <sysexits.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
extern int ReverseMode;
|
|
||||||
|
|
||||||
int Debug_Level;
|
|
||||||
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, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
|
|
||||||
if (Debug_Level >= debug_level)
|
|
||||||
vsyslog(LOG_DEBUG, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr,
|
|
||||||
struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr)
|
|
||||||
{
|
|
||||||
struct pfioc_natlook natlook;
|
|
||||||
socklen_t slen;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
slen = sizeof(*proxy_sa_ptr);
|
|
||||||
if (getsockname(connected_fd, (struct sockaddr *)proxy_sa_ptr,
|
|
||||||
&slen) != 0) {
|
|
||||||
syslog(LOG_ERR, "getsockname() failed (%m)");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
slen = sizeof(*client_sa_ptr);
|
|
||||||
if (getpeername(connected_fd, (struct sockaddr *)client_sa_ptr,
|
|
||||||
&slen) != 0) {
|
|
||||||
syslog(LOG_ERR, "getpeername() failed (%m)");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ReverseMode)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Build up the pf natlook structure.
|
|
||||||
* Just for IPv4 right now
|
|
||||||
*/
|
|
||||||
memset((void *)&natlook, 0, sizeof(natlook));
|
|
||||||
natlook.af = AF_INET;
|
|
||||||
natlook.saddr.addr32[0] = client_sa_ptr->sin_addr.s_addr;
|
|
||||||
natlook.daddr.addr32[0] = proxy_sa_ptr->sin_addr.s_addr;
|
|
||||||
natlook.proto = IPPROTO_TCP;
|
|
||||||
natlook.sport = client_sa_ptr->sin_port;
|
|
||||||
natlook.dport = proxy_sa_ptr->sin_port;
|
|
||||||
natlook.direction = PF_OUT;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open the pf device and lookup the mapping pair to find
|
|
||||||
* the original address we were supposed to connect to.
|
|
||||||
*/
|
|
||||||
fd = open("/dev/pf", O_RDWR);
|
|
||||||
if (fd == -1) {
|
|
||||||
syslog(LOG_ERR, "cannot open /dev/pf (%m)");
|
|
||||||
exit(EX_UNAVAILABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(fd, DIOCNATLOOK, &natlook) == -1) {
|
|
||||||
syslog(LOG_INFO,
|
|
||||||
"pf nat lookup failed %s:%hu (%m)",
|
|
||||||
inet_ntoa(client_sa_ptr->sin_addr),
|
|
||||||
ntohs(client_sa_ptr->sin_port));
|
|
||||||
close(fd);
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now jam the original address and port back into the into
|
|
||||||
* destination sockaddr_in for the proxy to deal with.
|
|
||||||
*/
|
|
||||||
memset((void *)real_server_sa_ptr, 0, sizeof(struct sockaddr_in));
|
|
||||||
real_server_sa_ptr->sin_port = natlook.rdport;
|
|
||||||
real_server_sa_ptr->sin_addr.s_addr = natlook.rdaddr.addr32[0];
|
|
||||||
real_server_sa_ptr->sin_len = sizeof(struct sockaddr_in);
|
|
||||||
real_server_sa_ptr->sin_family = AF_INET;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transfer one unit of data across a pair of sockets
|
|
||||||
*
|
|
||||||
* A unit of data is as much as we get with a single read(2) call.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xfer_data(const char *what_read,int from_fd, int to_fd, struct in_addr from,
|
|
||||||
struct in_addr to)
|
|
||||||
{
|
|
||||||
int rlen, offset, xerrno, mark, flags = 0;
|
|
||||||
char tbuf[4096];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Are we at the OOB mark?
|
|
||||||
*/
|
|
||||||
if (ioctl(from_fd, SIOCATMARK, &mark) < 0) {
|
|
||||||
xerrno = errno;
|
|
||||||
syslog(LOG_ERR, "cannot ioctl(SIOCATMARK) socket from %s (%m)",
|
|
||||||
what_read);
|
|
||||||
errno = xerrno;
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
if (mark)
|
|
||||||
flags = MSG_OOB; /* Yes - at the OOB mark */
|
|
||||||
|
|
||||||
snarf:
|
|
||||||
rlen = recv(from_fd, tbuf, sizeof(tbuf), flags);
|
|
||||||
if (rlen == -1 && flags == MSG_OOB && errno == EINVAL) {
|
|
||||||
/* OOB didn't work */
|
|
||||||
flags = 0;
|
|
||||||
rlen = recv(from_fd, tbuf, sizeof(tbuf), flags);
|
|
||||||
}
|
|
||||||
if (rlen == 0) {
|
|
||||||
debuglog(3, "EOF on read socket");
|
|
||||||
return(0);
|
|
||||||
} else if (rlen == -1) {
|
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
goto snarf;
|
|
||||||
xerrno = errno;
|
|
||||||
syslog(LOG_ERR, "xfer_data (%s): failed (%m) with flags 0%o",
|
|
||||||
what_read, flags);
|
|
||||||
errno = xerrno;
|
|
||||||
return(-1);
|
|
||||||
} else {
|
|
||||||
offset = 0;
|
|
||||||
debuglog(3, "got %d bytes from socket", rlen);
|
|
||||||
|
|
||||||
while (offset < rlen) {
|
|
||||||
int wlen;
|
|
||||||
fling:
|
|
||||||
wlen = send(to_fd, &tbuf[offset], rlen - offset,
|
|
||||||
flags);
|
|
||||||
if (wlen == 0) {
|
|
||||||
debuglog(3, "zero-length write");
|
|
||||||
goto fling;
|
|
||||||
} else if (wlen == -1) {
|
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
goto fling;
|
|
||||||
xerrno = errno;
|
|
||||||
syslog(LOG_INFO, "write failed (%m)");
|
|
||||||
errno = xerrno;
|
|
||||||
return(-1);
|
|
||||||
} else {
|
|
||||||
debuglog(3, "wrote %d bytes to socket",wlen);
|
|
||||||
offset += wlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get_backchannel_socket gets us a socket bound somewhere in a
|
|
||||||
* particular range of ports
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
get_backchannel_socket(int type, int min_port, int max_port, int start_port,
|
|
||||||
int direction, struct sockaddr_in *sap)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure that direction is 'defined' and that min_port is not
|
|
||||||
* greater than max_port.
|
|
||||||
*/
|
|
||||||
if (direction != -1)
|
|
||||||
direction = 1;
|
|
||||||
|
|
||||||
/* by default we go up by one port until we find one */
|
|
||||||
if (min_port > max_port) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = 1 + max_port - min_port;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pick a port we can bind to from within the range we want.
|
|
||||||
* If the caller specifies -1 as the starting port number then
|
|
||||||
* we pick one somewhere in the range to try.
|
|
||||||
* This is an optimization intended to speedup port selection and
|
|
||||||
* has NOTHING to do with security.
|
|
||||||
*/
|
|
||||||
if (start_port == -1)
|
|
||||||
start_port = (arc4random() % count) + min_port;
|
|
||||||
|
|
||||||
if (start_port < min_port || start_port > max_port) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (count-- > 0) {
|
|
||||||
struct sockaddr_in sa;
|
|
||||||
int one, fd;
|
|
||||||
|
|
||||||
fd = socket(AF_INET, type, 0);
|
|
||||||
|
|
||||||
bzero(&sa, sizeof sa);
|
|
||||||
sa.sin_family = AF_INET;
|
|
||||||
if (Bind_Addr == INADDR_NONE)
|
|
||||||
if (sap == NULL)
|
|
||||||
sa.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
else
|
|
||||||
sa.sin_addr.s_addr = sap->sin_addr.s_addr;
|
|
||||||
else
|
|
||||||
sa.sin_addr.s_addr = Bind_Addr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indicate that we want to reuse a port if it happens that the
|
|
||||||
* port in question was a listen port recently.
|
|
||||||
*/
|
|
||||||
one = 1;
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one,
|
|
||||||
sizeof(one)) == -1)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
sa.sin_port = htons(start_port);
|
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == 0) {
|
|
||||||
if (sap != NULL)
|
|
||||||
*sap = sa;
|
|
||||||
return(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno != EADDRINUSE)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
/* if it's in use, try the next port */
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
start_port += direction;
|
|
||||||
if (start_port < min_port)
|
|
||||||
start_port = max_port;
|
|
||||||
else if (start_port > max_port)
|
|
||||||
start_port = min_port;
|
|
||||||
}
|
|
||||||
errno = EAGAIN;
|
|
||||||
return(-1);
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
/* $OpenBSD: util.h,v 1.5 2005/02/24 15:49:08 dhartmei Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1996-2001
|
|
||||||
* Obtuse Systems Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. 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.
|
|
||||||
* 4. Neither the name of the Obtuse Systems nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 OBTUSE SYSTEMS CORPORATION 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct proxy_channel {
|
|
||||||
int pc_to_fd, pc_from_fd;
|
|
||||||
int pc_alive;
|
|
||||||
int pc_nextbyte;
|
|
||||||
int pc_flags;
|
|
||||||
int pc_length;
|
|
||||||
int pc_size;
|
|
||||||
struct sockaddr_in pc_from_sa, pc_to_sa;
|
|
||||||
int (*pc_filter)( void ** databuf, int datalen);
|
|
||||||
char *pc_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct csiob {
|
|
||||||
int fd;
|
|
||||||
int line_buffer_size, io_buffer_size, io_buffer_len, next_byte;
|
|
||||||
unsigned char *io_buffer, *line_buffer;
|
|
||||||
struct sockaddr_in sa, real_sa;
|
|
||||||
const char *who;
|
|
||||||
char alive, got_eof, data_available;
|
|
||||||
int send_oob_flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int telnet_getline(struct csiob *iobp,
|
|
||||||
struct csiob *telnet_passthrough);
|
|
||||||
|
|
||||||
extern int get_proxy_env(int fd, struct sockaddr_in *server_sa_ptr,
|
|
||||||
struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr);
|
|
||||||
|
|
||||||
extern int get_backchannel_socket(int type, int min_port, int max_port,
|
|
||||||
int start_port, int direction, struct sockaddr_in *sap);
|
|
||||||
|
|
||||||
extern int xfer_data(const char *what_read, int from_fd, int to_fd,
|
|
||||||
struct in_addr from, struct in_addr to);
|
|
||||||
|
|
||||||
extern char *ProgName;
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pf.4,v 1.54 2004/12/22 17:17:55 dhartmei Exp $
|
.\" $OpenBSD: pf.4,v 1.58 2007/02/09 11:39:06 henning Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (C) 2001, Kjell Wooding. All rights reserved.
|
.\" Copyright (C) 2001, Kjell Wooding. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -186,6 +186,11 @@ using the
|
|||||||
obtained through a preceding
|
obtained through a preceding
|
||||||
.Dv DIOCGETRULES
|
.Dv DIOCGETRULES
|
||||||
call.
|
call.
|
||||||
|
If
|
||||||
|
.Va action
|
||||||
|
is set to
|
||||||
|
.Dv PF_GET_CLR_CNTR ,
|
||||||
|
the per-rule statistics on the requested rule are cleared.
|
||||||
.It Dv DIOCGETADDRS Fa "struct pfioc_pooladdr *pp"
|
.It Dv DIOCGETADDRS Fa "struct pfioc_pooladdr *pp"
|
||||||
Get a
|
Get a
|
||||||
.Va ticket
|
.Va ticket
|
||||||
@ -348,6 +353,7 @@ struct pf_status {
|
|||||||
u_int32_t debug;
|
u_int32_t debug;
|
||||||
u_int32_t hostid;
|
u_int32_t hostid;
|
||||||
char ifname[IFNAMSIZ];
|
char ifname[IFNAMSIZ];
|
||||||
|
u_int8_t pf_chksum[MD5_DIGEST_LENGTH];
|
||||||
};
|
};
|
||||||
.Ed
|
.Ed
|
||||||
.It Dv DIOCCLRSTATUS
|
.It Dv DIOCCLRSTATUS
|
||||||
@ -391,19 +397,14 @@ struct pfioc_states {
|
|||||||
.Pp
|
.Pp
|
||||||
If
|
If
|
||||||
.Va ps_len
|
.Va ps_len
|
||||||
is zero, all states will be gathered into
|
is non-zero on entry, as many states as possible that can fit into this
|
||||||
.Va pf_states
|
size will be copied into the supplied buffer
|
||||||
and
|
.Va ps_states .
|
||||||
|
On exit,
|
||||||
.Va ps_len
|
.Va ps_len
|
||||||
will be set to the size they take in memory (i.e.,
|
is always set to the total size required to hold all state table entries
|
||||||
|
(i.e., it is set to
|
||||||
.Li sizeof(struct pf_state) * nr ) .
|
.Li sizeof(struct pf_state) * nr ) .
|
||||||
If
|
|
||||||
.Va ps_len
|
|
||||||
is non-zero, as many states that can fit into
|
|
||||||
.Va ps_len
|
|
||||||
as possible will be gathered, and
|
|
||||||
.Va ps_len
|
|
||||||
will be updated to the size those rules take in memory.
|
|
||||||
.It Dv DIOCCHANGERULE Fa "struct pfioc_rule *pcr"
|
.It Dv DIOCCHANGERULE Fa "struct pfioc_rule *pcr"
|
||||||
Add or remove the
|
Add or remove the
|
||||||
.Va rule
|
.Va rule
|
||||||
@ -485,7 +486,8 @@ struct pfioc_limit {
|
|||||||
unsigned limit;
|
unsigned limit;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS };
|
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS,
|
||||||
|
PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX };
|
||||||
.Ed
|
.Ed
|
||||||
.It Dv DIOCGETLIMIT Fa "struct pfioc_limit *pl"
|
.It Dv DIOCGETLIMIT Fa "struct pfioc_limit *pl"
|
||||||
Get the hard
|
Get the hard
|
||||||
@ -523,10 +525,15 @@ struct pfioc_table {
|
|||||||
.It Dv DIOCRADDTABLES Fa "struct pfioc_table *io"
|
.It Dv DIOCRADDTABLES Fa "struct pfioc_table *io"
|
||||||
Create one or more tables.
|
Create one or more tables.
|
||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains a table of
|
must point to an array of
|
||||||
.Vt pfr_table
|
.Vt struct pfr_table
|
||||||
structures.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_table .
|
||||||
On exit,
|
On exit,
|
||||||
.Va pfrio_nadd
|
.Va pfrio_nadd
|
||||||
contains the number of tables effectively created.
|
contains the number of tables effectively created.
|
||||||
@ -541,12 +548,17 @@ struct pfr_table {
|
|||||||
.It Dv DIOCRDELTABLES Fa "struct pfioc_table *io"
|
.It Dv DIOCRDELTABLES Fa "struct pfioc_table *io"
|
||||||
Delete one or more tables.
|
Delete one or more tables.
|
||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains a table of
|
must point to an array of
|
||||||
.Vt pfr_table
|
.Vt struct pfr_table
|
||||||
structures.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_table .
|
||||||
On exit,
|
On exit,
|
||||||
.Va pfrio_nadd
|
.Va pfrio_ndel
|
||||||
contains the number of tables effectively deleted.
|
contains the number of tables effectively deleted.
|
||||||
.It Dv DIOCRGETTABLES Fa "struct pfioc_table *io"
|
.It Dv DIOCRGETTABLES Fa "struct pfioc_table *io"
|
||||||
Get the list of all tables.
|
Get the list of all tables.
|
||||||
@ -585,10 +597,15 @@ struct pfr_tstats {
|
|||||||
.It Dv DIOCRCLRTSTATS Fa "struct pfioc_table *io"
|
.It Dv DIOCRCLRTSTATS Fa "struct pfioc_table *io"
|
||||||
Clear the statistics of one or more tables.
|
Clear the statistics of one or more tables.
|
||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains a table of
|
must point to an array of
|
||||||
.Vt pfr_table
|
.Vt struct pfr_table
|
||||||
structures.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_table .
|
||||||
On exit,
|
On exit,
|
||||||
.Va pfrio_nzero
|
.Va pfrio_nzero
|
||||||
contains the number of tables effectively cleared.
|
contains the number of tables effectively cleared.
|
||||||
@ -605,10 +622,15 @@ Add one or more addresses to a table.
|
|||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_table
|
.Va pfrio_table
|
||||||
contains the table ID and
|
contains the table ID and
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains the list of
|
must point to an array of
|
||||||
.Vt pfr_addr
|
.Vt struct pfr_addr
|
||||||
structures to add.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements to add to the table.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_addr .
|
||||||
On exit,
|
On exit,
|
||||||
.Va pfrio_nadd
|
.Va pfrio_nadd
|
||||||
contains the number of addresses effectively added.
|
contains the number of addresses effectively added.
|
||||||
@ -631,10 +653,15 @@ Delete one or more addresses from a table.
|
|||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_table
|
.Va pfrio_table
|
||||||
contains the table ID and
|
contains the table ID and
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains the list of
|
must point to an array of
|
||||||
.Vt pfr_addr
|
.Vt struct pfr_addr
|
||||||
structures to delete.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements to delete from the table.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_addr .
|
||||||
On exit,
|
On exit,
|
||||||
.Va pfrio_ndel
|
.Va pfrio_ndel
|
||||||
contains the number of addresses effectively deleted.
|
contains the number of addresses effectively deleted.
|
||||||
@ -645,10 +672,15 @@ This is the most complicated command, which uses all the structure members.
|
|||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_table
|
.Va pfrio_table
|
||||||
contains the table ID and
|
contains the table ID and
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains the new list of
|
must point to an array of
|
||||||
.Vt pfr_addr
|
.Vt struct pfr_addr
|
||||||
structures.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements which become the new contents of the table.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_addr .
|
||||||
Additionally, if
|
Additionally, if
|
||||||
.Va pfrio_size2
|
.Va pfrio_size2
|
||||||
is non-zero,
|
is non-zero,
|
||||||
@ -703,10 +735,15 @@ Clear the statistics of one or more addresses.
|
|||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_table
|
.Va pfrio_table
|
||||||
contains the table ID and
|
contains the table ID and
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains a table of
|
must point to an array of
|
||||||
.Vt pfr_addr
|
.Vt struct pfr_addr
|
||||||
structures to clear.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements to be cleared from the table.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_addr .
|
||||||
On exit,
|
On exit,
|
||||||
.Va pfrio_nzero
|
.Va pfrio_nzero
|
||||||
contains the number of addresses effectively cleared.
|
contains the number of addresses effectively cleared.
|
||||||
@ -715,13 +752,18 @@ Test if the given addresses match a table.
|
|||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_table
|
.Va pfrio_table
|
||||||
contains the table ID and
|
contains the table ID and
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains a table of
|
must point to an array of
|
||||||
.Vt pfr_addr
|
.Vt struct pfr_addr
|
||||||
structures to test.
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements, each of which will be tested for a match in the table.
|
||||||
|
.Vt pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_addr .
|
||||||
On exit, the kernel updates the
|
On exit, the kernel updates the
|
||||||
.Vt pfr_addr
|
.Vt pfr_addr
|
||||||
table by setting the
|
array by setting the
|
||||||
.Va pfra_fback
|
.Va pfra_fback
|
||||||
member appropriately.
|
member appropriately.
|
||||||
.It Dv DIOCRSETTFLAGS Fa "struct pfioc_table *io"
|
.It Dv DIOCRSETTFLAGS Fa "struct pfioc_table *io"
|
||||||
@ -731,14 +773,19 @@ or
|
|||||||
.Dv PFR_TFLAG_PERSIST
|
.Dv PFR_TFLAG_PERSIST
|
||||||
flags of a table.
|
flags of a table.
|
||||||
On entry,
|
On entry,
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer
|
||||||
contains a table of
|
must point to an array of
|
||||||
.Vt pfr_table
|
.Vt struct pfr_table
|
||||||
structures, and
|
containing at least
|
||||||
|
.Vt pfrio_size
|
||||||
|
elements.
|
||||||
|
.Va pfrio_esize
|
||||||
|
must be the size of
|
||||||
|
.Vt struct pfr_table .
|
||||||
.Va pfrio_setflag
|
.Va pfrio_setflag
|
||||||
contains the flags to add, while
|
must contain the flags to add, while
|
||||||
.Va pfrio_clrflag
|
.Va pfrio_clrflag
|
||||||
contains the flags to remove.
|
must contain the flags to remove.
|
||||||
On exit,
|
On exit,
|
||||||
.Va pfrio_nchange
|
.Va pfrio_nchange
|
||||||
and
|
and
|
||||||
@ -753,7 +800,7 @@ On entry,
|
|||||||
.Va pfrio_table
|
.Va pfrio_table
|
||||||
contains the table ID and
|
contains the table ID and
|
||||||
.Va pfrio_buffer[pfrio_size]
|
.Va pfrio_buffer[pfrio_size]
|
||||||
contains the list of
|
contains an array of
|
||||||
.Vt pfr_addr
|
.Vt pfr_addr
|
||||||
structures to put in the table.
|
structures to put in the table.
|
||||||
A valid ticket must also be supplied to
|
A valid ticket must also be supplied to
|
||||||
@ -955,10 +1002,6 @@ struct pfioc_iface {
|
|||||||
int pfiio_nzero;
|
int pfiio_nzero;
|
||||||
int pfiio_flags;
|
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
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
If not empty,
|
If not empty,
|
||||||
@ -968,61 +1011,45 @@ can be used to restrict the search to a specific interface or driver.
|
|||||||
is the user-supplied buffer for returning the data.
|
is the user-supplied buffer for returning the data.
|
||||||
On entry,
|
On entry,
|
||||||
.Va pfiio_size
|
.Va pfiio_size
|
||||||
represents the number of
|
contains the number of
|
||||||
.Va pfi_if
|
.Vt pfi_kif
|
||||||
entries that can fit into the buffer.
|
entries that can fit into the buffer.
|
||||||
The kernel will replace this value by the real number of entries it wants
|
The kernel will replace this value by the real number of entries it wants
|
||||||
to return.
|
to return.
|
||||||
.Va pfiio_esize
|
.Va pfiio_esize
|
||||||
should be set to
|
should be set to
|
||||||
.Li sizeof(struct pfi_if) .
|
.Li sizeof(struct pfi_kif) .
|
||||||
.Va pfiio_flags
|
.Pp
|
||||||
should be set to
|
|
||||||
.Dv PFI_FLAG_GROUP ,
|
|
||||||
.Dv 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
|
The data is returned in the
|
||||||
.Vt pfi_if
|
.Vt pfi_kif
|
||||||
structure described below:
|
structure described below:
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
struct pfi_if {
|
struct pfi_kif {
|
||||||
char pfif_name[IFNAMSIZ];
|
RB_ENTRY(pfi_kif) pfik_tree;
|
||||||
u_int64_t pfif_packets[2][2][2];
|
char pfik_name[IFNAMSIZ];
|
||||||
u_int64_t pfif_bytes[2][2][2];
|
u_int64_t pfik_packets[2][2][2];
|
||||||
u_int64_t pfif_addcnt;
|
u_int64_t pfik_bytes[2][2][2];
|
||||||
u_int64_t pfif_delcnt;
|
u_int32_t pfik_tzero;
|
||||||
long pfif_tzero;
|
int pfik_flags;
|
||||||
int pfif_states;
|
struct pf_state_tree_lan_ext pfik_lan_ext;
|
||||||
int pfif_rules;
|
struct pf_state_tree_ext_gwy pfik_ext_gwy;
|
||||||
int pfif_flags;
|
TAILQ_ENTRY(pfi_kif) pfik_w_states;
|
||||||
|
void *pfik_ah_cookie;
|
||||||
|
struct ifnet *pfik_ifp;
|
||||||
|
struct ifg_group *pfik_group;
|
||||||
|
int pfik_states;
|
||||||
|
int pfik_rules;
|
||||||
|
TAILQ_HEAD(, pfi_dynaddr) pfik_dynaddrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#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 */
|
|
||||||
.Ed
|
.Ed
|
||||||
.It Dv DIOCICLRISTATS Fa "struct pfioc_iface *io"
|
|
||||||
Clear the statistics counters of one or more interfaces.
|
|
||||||
.Va pfiio_name
|
|
||||||
and
|
|
||||||
.Va pfiio_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.
|
|
||||||
.It Dv DIOCSETIFFLAG Fa "struct pfioc_iface *io"
|
.It Dv DIOCSETIFFLAG Fa "struct pfioc_iface *io"
|
||||||
Set the user setable flags (described below) of the pf internal interface
|
Set the user setable flags (described above) of the
|
||||||
description.
|
.Nm
|
||||||
|
internal interface description.
|
||||||
The filtering process is the same as for
|
The filtering process is the same as for
|
||||||
.Dv DIOCIGETIFACES .
|
.Dv DIOCIGETIFACES .
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
#define PFI_IFLAG_SKIP 0x0100 /* skip interface */
|
#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */
|
||||||
#define PFI_IFLAG_SETABLE_MASK 0x0100 /* mask */
|
|
||||||
.Ed
|
.Ed
|
||||||
.It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io"
|
.It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io"
|
||||||
Works as
|
Works as
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pf.os.5,v 1.6 2004/03/31 11:13:03 dhartmei Exp $
|
.\" $OpenBSD: pf.os.5,v 1.7 2005/11/16 20:07:18 stevesk Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
.\" Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
||||||
.\"
|
.\"
|
||||||
@ -207,37 +207,15 @@ The
|
|||||||
output of
|
output of
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# tcpdump -s128 -c1 -nv 'tcp[13] == 2'
|
# tcpdump -s128 -c1 -nv 'tcp[13] == 2'
|
||||||
03:13:48.118526 10.0.0.1.3377 > 10.0.0.0.2: S [tcp sum ok] \e
|
03:13:48.118526 10.0.0.1.3377 > 10.0.0.2.80: S [tcp sum ok] \e
|
||||||
534596083:534596083(0) win 57344 <mss 1460> (DF) [tos 0x10] \e
|
534596083:534596083(0) win 57344 <mss 1460> (DF) [tos 0x10] \e
|
||||||
(ttl 64, id 11315)
|
(ttl 64, id 11315, len 44)
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
almost translates into the following fingerprint
|
almost translates into the following fingerprint
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
57344:64:1:44:M1460: exampleOS:1.0::exampleOS 1.0
|
57344:64:1:44:M1460: exampleOS:1.0::exampleOS 1.0
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
|
||||||
.Xr tcpdump 1
|
|
||||||
does not explicitly give the packet length.
|
|
||||||
But it can usually be derived by adding the size of the IPv4 header to
|
|
||||||
the size of the TCP header to the size of the TCP options.
|
|
||||||
The size of both headers is typically twenty each and the usual
|
|
||||||
sizes of the TCP options are:
|
|
||||||
.Pp
|
|
||||||
.Bl -tag -width timestamp -offset indent -compact
|
|
||||||
.It mss
|
|
||||||
four bytes.
|
|
||||||
.It nop
|
|
||||||
1 byte.
|
|
||||||
.It sackOK
|
|
||||||
two bytes.
|
|
||||||
.It timestamp
|
|
||||||
ten bytes.
|
|
||||||
.It wscale
|
|
||||||
three bytes.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
In the above example, the packet size comes out to 44 bytes.
|
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr tcpdump 1 ,
|
.Xr tcpdump 1 ,
|
||||||
.Xr pf 4 ,
|
.Xr pf 4 ,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pflog.4,v 1.7 2004/03/21 19:47:59 miod Exp $
|
.\" $OpenBSD: pflog.4,v 1.9 2006/10/25 12:51:31 jmc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2001 Tobias Weingartner
|
.\" Copyright (c) 2001 Tobias Weingartner
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
@ -47,6 +47,14 @@ on the
|
|||||||
interface, or stored to disk using
|
interface, or stored to disk using
|
||||||
.Xr pflogd 8 .
|
.Xr pflogd 8 .
|
||||||
.Pp
|
.Pp
|
||||||
|
The pflog0 interface is created automatically at boot if both
|
||||||
|
.Xr pf 4
|
||||||
|
and
|
||||||
|
.Xr pflogd 8
|
||||||
|
are enabled;
|
||||||
|
further instances can be created using
|
||||||
|
.Xr ifconfig 8 .
|
||||||
|
.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
|
||||||
.Dv PFLOG_HDRLEN .
|
.Dv PFLOG_HDRLEN .
|
||||||
@ -65,14 +73,22 @@ struct pfloghdr {
|
|||||||
char ruleset[PF_RULESET_NAME_SIZE];
|
char ruleset[PF_RULESET_NAME_SIZE];
|
||||||
u_int32_t rulenr;
|
u_int32_t rulenr;
|
||||||
u_int32_t subrulenr;
|
u_int32_t subrulenr;
|
||||||
|
uid_t uid;
|
||||||
|
pid_t pid;
|
||||||
|
uid_t rule_uid;
|
||||||
|
pid_t rule_pid;
|
||||||
u_int8_t dir;
|
u_int8_t dir;
|
||||||
u_int8_t pad[3];
|
u_int8_t pad[3];
|
||||||
};
|
};
|
||||||
.Ed
|
.Ed
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
|
Create a
|
||||||
|
.Nm
|
||||||
|
interface
|
||||||
|
and monitor all packets logged on it:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# ifconfig pflog0 up
|
# ifconfig pflog1 up
|
||||||
# tcpdump -n -e -ttt -i pflog0
|
# tcpdump -n -e -ttt -i pflog1
|
||||||
.Ed
|
.Ed
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr tcpdump 1
|
.Xr tcpdump 1
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pfsync.4,v 1.22 2005/02/24 15:53:17 jmc Exp $
|
.\" $OpenBSD: pfsync.4,v 1.24 2006/10/23 07:05:49 jmc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2002 Michael Shalayeff
|
.\" Copyright (c) 2002 Michael Shalayeff
|
||||||
.\" Copyright (c) 2003-2004 Ryan McBride
|
.\" Copyright (c) 2003-2004 Ryan McBride
|
||||||
@ -209,7 +209,7 @@ The following should be added to the top of
|
|||||||
.Pa /etc/pf.conf :
|
.Pa /etc/pf.conf :
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
pass quick on { sis2 } proto pfsync
|
pass quick on { sis2 } proto pfsync
|
||||||
pass quick on { sis0 sis1 } proto carp keep state
|
pass on { sis0 sis1 } proto carp
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
If it is preferable that one firewall handle the traffic,
|
If it is preferable that one firewall handle the traffic,
|
||||||
@ -248,6 +248,9 @@ yet.
|
|||||||
.Xr pf.conf 5 ,
|
.Xr pf.conf 5 ,
|
||||||
.Xr protocols 5 ,
|
.Xr protocols 5 ,
|
||||||
.Xr rc.conf 5
|
.Xr rc.conf 5
|
||||||
|
.Xr ifconfig 8 ,
|
||||||
|
.Xr ifstated 8 ,
|
||||||
|
.Xr tcpdump 8
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pf_print_state.c,v 1.40 2004/12/10 22:13:26 henning Exp $ */
|
/* $OpenBSD: pf_print_state.c,v 1.44 2007/03/01 17:20:53 deraadt Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -100,6 +100,9 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
|||||||
case PF_ADDR_NOROUTE:
|
case PF_ADDR_NOROUTE:
|
||||||
printf("no-route");
|
printf("no-route");
|
||||||
return;
|
return;
|
||||||
|
case PF_ADDR_URPFFAILED:
|
||||||
|
printf("urpf-failed");
|
||||||
|
return;
|
||||||
case PF_ADDR_RTLABEL:
|
case PF_ADDR_RTLABEL:
|
||||||
printf("route \"%s\"", addr->v.rtlabelname);
|
printf("route \"%s\"", addr->v.rtlabelname);
|
||||||
return;
|
return;
|
||||||
@ -278,8 +281,15 @@ print_state(struct pf_state *s, int opts)
|
|||||||
min = s->expire % 60;
|
min = s->expire % 60;
|
||||||
s->expire /= 60;
|
s->expire /= 60;
|
||||||
printf(", expires in %.2u:%.2u:%.2u", s->expire, min, sec);
|
printf(", expires in %.2u:%.2u:%.2u", s->expire, min, sec);
|
||||||
printf(", %u:%u pkts, %u:%u bytes",
|
printf(", %llu:%llu pkts, %llu:%llu bytes",
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
(unsigned long long)s->packets[0],
|
||||||
|
(unsigned long long)s->packets[1],
|
||||||
|
(unsigned long long)s->bytes[0],
|
||||||
|
(unsigned long long)s->bytes[1]);
|
||||||
|
#else
|
||||||
s->packets[0], s->packets[1], s->bytes[0], s->bytes[1]);
|
s->packets[0], s->packets[1], s->bytes[0], s->bytes[1]);
|
||||||
|
#endif
|
||||||
if (s->anchor.nr != -1)
|
if (s->anchor.nr != -1)
|
||||||
printf(", anchor %u", s->anchor.nr);
|
printf(", anchor %u", s->anchor.nr);
|
||||||
if (s->rule.nr != -1)
|
if (s->rule.nr != -1)
|
||||||
@ -291,13 +301,13 @@ print_state(struct pf_state *s, int opts)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
if (opts & PF_OPT_VERBOSE2) {
|
if (opts & PF_OPT_VERBOSE2) {
|
||||||
|
printf(" id: %016llx creatorid: %08x%s\n",
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
printf(" id: %016llx creatorid: %08x\n",
|
(unsigned long long)be64toh(s->id), ntohl(s->creatorid),
|
||||||
(long long)be64toh(s->id), ntohl(s->creatorid));
|
|
||||||
#else
|
#else
|
||||||
printf(" id: %016llx creatorid: %08x\n",
|
betoh64(s->id), ntohl(s->creatorid),
|
||||||
betoh64(s->id), ntohl(s->creatorid));
|
|
||||||
#endif
|
#endif
|
||||||
|
((s->sync_flags & PFSTATE_NOSYNC) ? " (no-sync)" : ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: pfctl.8,v 1.118 2005/01/05 23:41:45 jmc Exp $
|
.\" $OpenBSD: pfctl.8,v 1.128 2007/01/30 21:01:56 jmc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
|
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -35,23 +35,23 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm pfctl
|
.Nm pfctl
|
||||||
.Bk -words
|
.Bk -words
|
||||||
.Op Fl AdeghmNnOoqRrvz
|
.Op Fl AdeghmNnOqRrvz
|
||||||
.Op Fl a Ar anchor
|
.Op Fl a Ar anchor
|
||||||
.Xo
|
.Oo Fl D Ar macro Ns =
|
||||||
.Oo Fl D
|
.Ar value Oc
|
||||||
.Ar macro Ns = Ns Ar value Oc
|
|
||||||
.Xc
|
|
||||||
.Op Fl F Ar modifier
|
.Op Fl F Ar modifier
|
||||||
.Op Fl f Ar file
|
.Op Fl f Ar file
|
||||||
.Op Fl i Ar interface
|
.Op Fl i Ar interface
|
||||||
.Op Fl k Ar host
|
.Op Fl K Ar host | network
|
||||||
|
.Op Fl k Ar host | network
|
||||||
|
.Op Fl o Op Ar level
|
||||||
.Op Fl p Ar device
|
.Op Fl p Ar device
|
||||||
.Op Fl s Ar modifier
|
.Op Fl s Ar modifier
|
||||||
.Oo Xo
|
.Oo
|
||||||
.Fl t Ar table
|
.Fl t Ar table
|
||||||
.Fl T Ar command
|
.Fl T Ar command
|
||||||
.Op Ar address ... Oc
|
.Op Ar address ...
|
||||||
.Xc
|
.Oc
|
||||||
.Op Fl x Ar level
|
.Op Fl x Ar level
|
||||||
.Ek
|
.Ek
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -140,8 +140,10 @@ rules from the main ruleset is described in
|
|||||||
For example, the following will show all filter rules (see the
|
For example, the following will show all filter rules (see the
|
||||||
.Fl s
|
.Fl s
|
||||||
flag below) inside the anchor
|
flag below) inside the anchor
|
||||||
.Li authpf/smith(1234) ,
|
.Dq authpf/smith(1234) ,
|
||||||
which would have been created for user smith by
|
which would have been created for user
|
||||||
|
.Dq smith
|
||||||
|
by
|
||||||
.Xr authpf 8 ,
|
.Xr authpf 8 ,
|
||||||
PID 1234:
|
PID 1234:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
@ -163,6 +165,27 @@ This is similar to C rules for variable scope.
|
|||||||
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.
|
||||||
|
.Pp
|
||||||
|
By default, recursive inline printing of anchors applies only to unnamed
|
||||||
|
anchors specified inline in the ruleset.
|
||||||
|
If the anchor name is terminated with a
|
||||||
|
.Sq *
|
||||||
|
character, the
|
||||||
|
.Fl s
|
||||||
|
flag will recursively print all anchors in a brace delimited block.
|
||||||
|
For example the following will print the
|
||||||
|
.Dq authpf
|
||||||
|
ruleset recursively:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
# pfctl -a 'authpf/*' -sr
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
To print the main ruleset recursively, specify only
|
||||||
|
.Sq *
|
||||||
|
as the anchor name:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
# pfctl -a '*' -sr
|
||||||
|
.Ed
|
||||||
.It Fl D Ar macro Ns = Ns Ar value
|
.It Fl D Ar macro Ns = Ns Ar value
|
||||||
Define
|
Define
|
||||||
.Ar macro
|
.Ar macro
|
||||||
@ -217,29 +240,49 @@ Help.
|
|||||||
.It Fl i Ar interface
|
.It Fl i Ar interface
|
||||||
Restrict the operation to the given
|
Restrict the operation to the given
|
||||||
.Ar interface .
|
.Ar interface .
|
||||||
.It Fl k Ar host
|
.It Fl K Ar host | network
|
||||||
|
Kill all of the source tracking entries originating from the specified
|
||||||
|
.Ar host
|
||||||
|
or
|
||||||
|
.Ar network .
|
||||||
|
A second
|
||||||
|
.Fl K Ar host
|
||||||
|
or
|
||||||
|
.Fl K Ar network
|
||||||
|
option may be specified, which will kill all the source tracking
|
||||||
|
entries from the first host/network to the second.
|
||||||
|
.It Fl k Ar host | network
|
||||||
Kill all of the state entries originating from the specified
|
Kill all of the state entries originating from the specified
|
||||||
.Ar host .
|
.Ar host
|
||||||
|
or
|
||||||
|
.Ar network .
|
||||||
A second
|
A second
|
||||||
.Fl k Ar host
|
.Fl k Ar host
|
||||||
|
or
|
||||||
|
.Fl k Ar network
|
||||||
option may be specified, which will kill all the state entries
|
option may be specified, which will kill all the state entries
|
||||||
from the first
|
from the first host/network to the second.
|
||||||
.Ar host
|
|
||||||
to the second
|
|
||||||
.Ar host .
|
|
||||||
For example, to kill all of the state entries originating from
|
For example, to kill all of the state entries originating from
|
||||||
.Li host :
|
.Dq host :
|
||||||
.Bd -literal -offset indent
|
.Pp
|
||||||
# pfctl -k host
|
.Dl # pfctl -k host
|
||||||
.Ed
|
|
||||||
.Pp
|
.Pp
|
||||||
To kill all of the state entries from
|
To kill all of the state entries from
|
||||||
.Li host1
|
.Dq host1
|
||||||
to
|
to
|
||||||
.Li host2 :
|
.Dq host2 :
|
||||||
.Bd -literal -offset indent
|
.Pp
|
||||||
# pfctl -k host1 -k host2
|
.Dl # pfctl -k host1 -k host2
|
||||||
.Ed
|
.Pp
|
||||||
|
To kill all states originating from 192.168.1.0/24 to 172.16.0.0/16:
|
||||||
|
.Pp
|
||||||
|
.Dl # pfctl -k 192.168.1.0/24 -k 172.16.0.0/16
|
||||||
|
.Pp
|
||||||
|
A network prefix length of 0 can be used as a wildcard.
|
||||||
|
To kill all states with the target
|
||||||
|
.Dq host2 :
|
||||||
|
.Pp
|
||||||
|
.Dl # pfctl -k 0.0.0.0/0 -k host2
|
||||||
.It Fl m
|
.It Fl m
|
||||||
Merge in explicitly given options without resetting those
|
Merge in explicitly given options without resetting those
|
||||||
which are omitted.
|
which are omitted.
|
||||||
@ -255,11 +298,22 @@ Do not actually load rules, just parse them.
|
|||||||
.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 o
|
.It Fl o Op Ar level
|
||||||
Enable the ruleset optimizer.
|
Control the ruleset optimizer.
|
||||||
The ruleset optimizer attempts to improve rulesets by removing rule
|
The ruleset optimizer attempts to improve rulesets by removing rule
|
||||||
duplication and making better use of rule ordering.
|
duplication and making better use of rule ordering.
|
||||||
Specifically, it does four things:
|
.Pp
|
||||||
|
.Bl -tag -width xxxxxxxxxxxx -compact
|
||||||
|
.It Fl o Cm none
|
||||||
|
Disable the ruleset optimizer.
|
||||||
|
.It Fl o Cm basic
|
||||||
|
Enable basic ruleset optimizations.
|
||||||
|
.It Fl o Cm profile
|
||||||
|
Enable basic ruleset optimizations with profiling.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
.Cm basic
|
||||||
|
optimization does does four things:
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -enum -compact
|
.Bl -enum -compact
|
||||||
.It
|
.It
|
||||||
@ -272,10 +326,10 @@ combine multiple rules into a table when advantageous
|
|||||||
re-order the rules to improve evaluation performance
|
re-order the rules to improve evaluation performance
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
A second
|
If
|
||||||
.Fl o
|
.Cm profile
|
||||||
may be specified to use the currently loaded ruleset as a feedback profile
|
is specified, the currently loaded ruleset will be examined as a feedback
|
||||||
to tailor the optimization of the
|
profile to tailor the optimization of the
|
||||||
.Ar quick
|
.Ar quick
|
||||||
rules to the actual network behavior.
|
rules to the actual network behavior.
|
||||||
.Pp
|
.Pp
|
||||||
@ -288,6 +342,14 @@ the ruleset optimizer should not be used or a
|
|||||||
.Ar label
|
.Ar label
|
||||||
field should be added to all of the accounting rules to act as optimization
|
field should be added to all of the accounting rules to act as optimization
|
||||||
barriers.
|
barriers.
|
||||||
|
.Pp
|
||||||
|
To retain compatibility with previous behaviour, a single
|
||||||
|
.Fl o
|
||||||
|
without any options will enable
|
||||||
|
.Cm basic
|
||||||
|
optimizations, and a second
|
||||||
|
.Fl o
|
||||||
|
will enable profiling.
|
||||||
.It Fl p Ar device
|
.It Fl p Ar device
|
||||||
Use the device file
|
Use the device file
|
||||||
.Ar device
|
.Ar device
|
||||||
@ -352,7 +414,8 @@ When used together with
|
|||||||
.Fl v ,
|
.Fl v ,
|
||||||
source tracking statistics are also shown.
|
source tracking statistics are also shown.
|
||||||
.It Fl s Cm labels
|
.It Fl s Cm labels
|
||||||
Show per-rule statistics (label, evaluations, packets, bytes) of
|
Show per-rule statistics (label, evaluations, packets total, bytes total,
|
||||||
|
packets in, bytes in, packets out, bytes out) of
|
||||||
filter rules with labels, useful for accounting.
|
filter rules with labels, useful for accounting.
|
||||||
.It Fl s Cm timeouts
|
.It Fl s Cm timeouts
|
||||||
Show the current global timeouts.
|
Show the current global timeouts.
|
||||||
@ -364,8 +427,11 @@ Show the list of tables.
|
|||||||
Show the list of operating system fingerprints.
|
Show the list of operating system fingerprints.
|
||||||
.It Fl s Cm Interfaces
|
.It Fl s Cm Interfaces
|
||||||
Show the list of interfaces and interface drivers available to PF.
|
Show the list of interfaces and interface drivers available to PF.
|
||||||
When used together with a double
|
When used together with
|
||||||
.Fl v ,
|
.Fl v ,
|
||||||
|
it additionally lists which interfaces have skip rules activated.
|
||||||
|
When used together with
|
||||||
|
.Fl vv ,
|
||||||
interface statistics are also shown.
|
interface statistics are also shown.
|
||||||
.Fl i
|
.Fl i
|
||||||
can be used to select an interface or a group of interfaces.
|
can be used to select an interface or a group of interfaces.
|
||||||
@ -389,6 +455,13 @@ Add one or more addresses in a table.
|
|||||||
Automatically create a nonexisting table.
|
Automatically create a nonexisting table.
|
||||||
.It Fl T Cm delete
|
.It Fl T Cm delete
|
||||||
Delete one or more addresses from a table.
|
Delete one or more addresses from a table.
|
||||||
|
.It Fl T Cm expire Ar number
|
||||||
|
Delete addresses which had their statistics cleared more than
|
||||||
|
.Ar number
|
||||||
|
seconds ago.
|
||||||
|
For entries which have never had their statistics cleared,
|
||||||
|
.Ar number
|
||||||
|
refers to the time they were added to the table.
|
||||||
.It Fl T Cm replace
|
.It Fl T Cm replace
|
||||||
Replace the addresses of the table.
|
Replace the addresses of the table.
|
||||||
Automatically create a nonexisting table.
|
Automatically create a nonexisting table.
|
||||||
@ -465,7 +538,7 @@ 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>\en" | pfctl -f-
|
||||||
# ping -qc10 ftp.openbsd.org
|
# ping -qc10 ftp.openbsd.org
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl.h,v 1.37 2005/01/05 18:23:10 mcbride Exp $ */
|
/* $OpenBSD: pfctl.h,v 1.40 2007/02/09 11:25:27 henning Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -34,6 +34,8 @@
|
|||||||
#ifndef _PFCTL_H_
|
#ifndef _PFCTL_H_
|
||||||
#define _PFCTL_H_
|
#define _PFCTL_H_
|
||||||
|
|
||||||
|
enum pfctl_show { PFCTL_SHOW_RULES, PFCTL_SHOW_LABELS, PFCTL_SHOW_NOTHING };
|
||||||
|
|
||||||
enum { PFRB_TABLES = 1, PFRB_TSTATS, PFRB_ADDRS, PFRB_ASTATS,
|
enum { PFRB_TABLES = 1, PFRB_TSTATS, PFRB_ADDRS, PFRB_ASTATS,
|
||||||
PFRB_IFACES, PFRB_TRANS, PFRB_MAX };
|
PFRB_IFACES, PFRB_TRANS, PFRB_MAX };
|
||||||
struct pfr_buffer {
|
struct pfr_buffer {
|
||||||
@ -74,7 +76,7 @@ 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_get_ifaces(const char *, struct pfi_kif *, int *);
|
||||||
int pfi_clr_istats(const char *, int *, int);
|
int pfi_clr_istats(const char *, int *, int);
|
||||||
|
|
||||||
void pfctl_print_title(char *);
|
void pfctl_print_title(char *);
|
||||||
@ -111,7 +113,6 @@ extern int loadopt;
|
|||||||
|
|
||||||
int check_commit_altq(int, int);
|
int check_commit_altq(int, int);
|
||||||
void pfaltq_store(struct pf_altq *);
|
void pfaltq_store(struct pf_altq *);
|
||||||
void pfaltq_free(struct pf_altq *);
|
|
||||||
struct pf_altq *pfaltq_lookup(const char *);
|
struct pf_altq *pfaltq_lookup(const char *);
|
||||||
char *rate2str(double);
|
char *rate2str(double);
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_altq.c,v 1.86 2005/02/28 14:04:51 henning Exp $ */
|
/* $OpenBSD: pfctl_altq.c,v 1.91 2006/11/28 00:08:50 henning Exp $ */
|
||||||
/* add: $OpenBSD: pfctl_altq.c,v 1.91 2006/11/28 00:08:50 henning Exp $ */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002
|
* Copyright (c) 2002
|
||||||
@ -101,21 +100,6 @@ pfaltq_store(struct pf_altq *a)
|
|||||||
TAILQ_INSERT_TAIL(&altqs, altq, entries);
|
TAILQ_INSERT_TAIL(&altqs, altq, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
pfaltq_free(struct pf_altq *a)
|
|
||||||
{
|
|
||||||
struct pf_altq *altq;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(altq, &altqs, entries) {
|
|
||||||
if (strncmp(a->ifname, altq->ifname, IFNAMSIZ) == 0 &&
|
|
||||||
strncmp(a->qname, altq->qname, PF_QNAME_SIZE) == 0) {
|
|
||||||
TAILQ_REMOVE(&altqs, altq, entries);
|
|
||||||
free(altq);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pf_altq *
|
struct pf_altq *
|
||||||
pfaltq_lookup(const char *ifname)
|
pfaltq_lookup(const char *ifname)
|
||||||
{
|
{
|
||||||
@ -165,7 +149,7 @@ 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] != 0) {
|
if (a->qname[0] != 0) {
|
||||||
print_queue(a, level, bw, 0, qopts);
|
print_queue(a, level, bw, 1, qopts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,8 +234,8 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
|||||||
#else
|
#else
|
||||||
if ((rate = getifspeed(pa->ifname)) == 0) {
|
if ((rate = getifspeed(pa->ifname)) == 0) {
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "cannot determine interface bandwidth "
|
fprintf(stderr, "interface %s does not know its bandwidth, "
|
||||||
"for %s, specify an absolute bandwidth\n",
|
"please specify an absolute bandwidth\n",
|
||||||
pa->ifname);
|
pa->ifname);
|
||||||
errors++;
|
errors++;
|
||||||
} else if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0)
|
} else if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0)
|
||||||
@ -502,10 +486,7 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa)
|
|||||||
maxidle = ptime * maxidle;
|
maxidle = ptime * maxidle;
|
||||||
else
|
else
|
||||||
maxidle = ptime * maxidle_s;
|
maxidle = ptime * maxidle_s;
|
||||||
if (minburst)
|
offtime = cptime * (1.0 + 1.0/(1.0 - g) * (1.0 - gtom) / gtom);
|
||||||
offtime = cptime * (1.0 + 1.0/(1.0 - g) * (1.0 - gtom) / gtom);
|
|
||||||
else
|
|
||||||
offtime = cptime;
|
|
||||||
minidle = -((double)opts->maxpktsize * (double)nsPerByte);
|
minidle = -((double)opts->maxpktsize * (double)nsPerByte);
|
||||||
|
|
||||||
/* scale parameters */
|
/* scale parameters */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_optimize.c,v 1.5 2005/01/03 15:18:10 frantzen Exp $ */
|
/* $OpenBSD: pfctl_optimize.c,v 1.13 2006/10/31 14:17:45 mcbride Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org>
|
* Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org>
|
||||||
@ -112,6 +112,10 @@ struct pf_rule_field {
|
|||||||
PF_RULE_FIELD(prob, BARRIER),
|
PF_RULE_FIELD(prob, BARRIER),
|
||||||
PF_RULE_FIELD(max_states, BARRIER),
|
PF_RULE_FIELD(max_states, BARRIER),
|
||||||
PF_RULE_FIELD(max_src_nodes, BARRIER),
|
PF_RULE_FIELD(max_src_nodes, BARRIER),
|
||||||
|
PF_RULE_FIELD(max_src_states, BARRIER),
|
||||||
|
PF_RULE_FIELD(max_src_conn, BARRIER),
|
||||||
|
PF_RULE_FIELD(max_src_conn_rate, BARRIER),
|
||||||
|
PF_RULE_FIELD(anchor, BARRIER), /* for now */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These fields must be the same between all rules in the same superblock.
|
* These fields must be the same between all rules in the same superblock.
|
||||||
@ -123,10 +127,18 @@ struct pf_rule_field {
|
|||||||
PF_RULE_FIELD(tagname, BREAK),
|
PF_RULE_FIELD(tagname, BREAK),
|
||||||
PF_RULE_FIELD(keep_state, BREAK),
|
PF_RULE_FIELD(keep_state, BREAK),
|
||||||
PF_RULE_FIELD(qname, BREAK),
|
PF_RULE_FIELD(qname, BREAK),
|
||||||
|
PF_RULE_FIELD(pqname, BREAK),
|
||||||
PF_RULE_FIELD(rt, BREAK),
|
PF_RULE_FIELD(rt, BREAK),
|
||||||
PF_RULE_FIELD(allow_opts, BREAK),
|
PF_RULE_FIELD(allow_opts, BREAK),
|
||||||
PF_RULE_FIELD(rule_flag, BREAK),
|
PF_RULE_FIELD(rule_flag, BREAK),
|
||||||
PF_RULE_FIELD(action, BREAK),
|
PF_RULE_FIELD(action, BREAK),
|
||||||
|
PF_RULE_FIELD(log, BREAK),
|
||||||
|
PF_RULE_FIELD(quick, BREAK),
|
||||||
|
PF_RULE_FIELD(return_ttl, BREAK),
|
||||||
|
PF_RULE_FIELD(overload_tblname, BREAK),
|
||||||
|
PF_RULE_FIELD(flush, BREAK),
|
||||||
|
PF_RULE_FIELD(rpool, BREAK),
|
||||||
|
PF_RULE_FIELD(logif, BREAK),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Any fields not listed in this structure act as BREAK fields
|
* Any fields not listed in this structure act as BREAK fields
|
||||||
@ -140,7 +152,7 @@ struct pf_rule_field {
|
|||||||
*/
|
*/
|
||||||
PF_RULE_FIELD(af, NOMERGE),
|
PF_RULE_FIELD(af, NOMERGE),
|
||||||
PF_RULE_FIELD(ifnot, NOMERGE),
|
PF_RULE_FIELD(ifnot, NOMERGE),
|
||||||
PF_RULE_FIELD(ifname, NOMERGE),
|
PF_RULE_FIELD(ifname, NOMERGE), /* hack for IF groups */
|
||||||
PF_RULE_FIELD(match_tag_not, NOMERGE),
|
PF_RULE_FIELD(match_tag_not, NOMERGE),
|
||||||
PF_RULE_FIELD(match_tagname, NOMERGE),
|
PF_RULE_FIELD(match_tagname, NOMERGE),
|
||||||
PF_RULE_FIELD(os_fingerprint, NOMERGE),
|
PF_RULE_FIELD(os_fingerprint, NOMERGE),
|
||||||
@ -173,7 +185,6 @@ struct pf_rule_field {
|
|||||||
PF_RULE_FIELD(packets, DC),
|
PF_RULE_FIELD(packets, DC),
|
||||||
PF_RULE_FIELD(bytes, DC),
|
PF_RULE_FIELD(bytes, DC),
|
||||||
PF_RULE_FIELD(kif, DC),
|
PF_RULE_FIELD(kif, DC),
|
||||||
PF_RULE_FIELD(anchor, DC),
|
|
||||||
PF_RULE_FIELD(states, DC),
|
PF_RULE_FIELD(states, DC),
|
||||||
PF_RULE_FIELD(src_nodes, DC),
|
PF_RULE_FIELD(src_nodes, DC),
|
||||||
PF_RULE_FIELD(nr, DC),
|
PF_RULE_FIELD(nr, DC),
|
||||||
@ -182,6 +193,9 @@ struct pf_rule_field {
|
|||||||
PF_RULE_FIELD(pqid, DC),
|
PF_RULE_FIELD(pqid, DC),
|
||||||
PF_RULE_FIELD(anchor_relative, DC),
|
PF_RULE_FIELD(anchor_relative, DC),
|
||||||
PF_RULE_FIELD(anchor_wildcard, DC),
|
PF_RULE_FIELD(anchor_wildcard, DC),
|
||||||
|
PF_RULE_FIELD(tag, DC),
|
||||||
|
PF_RULE_FIELD(match_tag, DC),
|
||||||
|
PF_RULE_FIELD(overload_tbl, DC),
|
||||||
|
|
||||||
/* These fields should never be set in a PASS/BLOCK rule */
|
/* These fields should never be set in a PASS/BLOCK rule */
|
||||||
PF_RULE_FIELD(natpass, NEVER),
|
PF_RULE_FIELD(natpass, NEVER),
|
||||||
@ -201,6 +215,7 @@ void comparable_rule(struct pf_rule *, const struct pf_rule *, int);
|
|||||||
int construct_superblocks(struct pfctl *, struct pf_opt_queue *,
|
int construct_superblocks(struct pfctl *, struct pf_opt_queue *,
|
||||||
struct superblocks *);
|
struct superblocks *);
|
||||||
void exclude_supersets(struct pf_rule *, struct pf_rule *);
|
void exclude_supersets(struct pf_rule *, struct pf_rule *);
|
||||||
|
int interface_group(const char *);
|
||||||
int load_feedback_profile(struct pfctl *, struct superblocks *);
|
int load_feedback_profile(struct pfctl *, struct superblocks *);
|
||||||
int optimize_superblock(struct pfctl *, struct superblock *);
|
int optimize_superblock(struct pfctl *, struct superblock *);
|
||||||
int pf_opt_create_table(struct pfctl *, struct pf_opt_tbl *);
|
int pf_opt_create_table(struct pfctl *, struct pf_opt_tbl *);
|
||||||
@ -243,25 +258,52 @@ int table_identifier;
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
pfctl_optimize_rules(struct pfctl *pf)
|
pfctl_optimize_ruleset(struct pfctl *pf, struct pf_ruleset *rs)
|
||||||
{
|
{
|
||||||
struct superblocks superblocks;
|
struct superblocks superblocks;
|
||||||
|
struct pf_opt_queue opt_queue;
|
||||||
struct superblock *block;
|
struct superblock *block;
|
||||||
struct pf_opt_rule *por;
|
struct pf_opt_rule *por;
|
||||||
int nr;
|
struct pf_rule *r;
|
||||||
|
struct pf_rulequeue *old_rules;
|
||||||
|
|
||||||
DEBUG("optimizing ruleset");
|
DEBUG("optimizing ruleset");
|
||||||
memset(&table_buffer, 0, sizeof(table_buffer));
|
memset(&table_buffer, 0, sizeof(table_buffer));
|
||||||
skip_init();
|
skip_init();
|
||||||
|
TAILQ_INIT(&opt_queue);
|
||||||
|
|
||||||
if (TAILQ_FIRST(&pf->opt_queue))
|
old_rules = rs->rules[PF_RULESET_FILTER].active.ptr;
|
||||||
nr = TAILQ_FIRST(&pf->opt_queue)->por_rule.nr;
|
rs->rules[PF_RULESET_FILTER].active.ptr =
|
||||||
|
rs->rules[PF_RULESET_FILTER].inactive.ptr;
|
||||||
|
rs->rules[PF_RULESET_FILTER].inactive.ptr = old_rules;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX expanding the pf_opt_rule format throughout pfctl might allow
|
||||||
|
* us to avoid all this copying.
|
||||||
|
*/
|
||||||
|
while ((r = TAILQ_FIRST(rs->rules[PF_RULESET_FILTER].inactive.ptr))
|
||||||
|
!= NULL) {
|
||||||
|
TAILQ_REMOVE(rs->rules[PF_RULESET_FILTER].inactive.ptr, r,
|
||||||
|
entries);
|
||||||
|
if ((por = calloc(1, sizeof(*por))) == NULL)
|
||||||
|
err(1, "calloc");
|
||||||
|
memcpy(&por->por_rule, r, sizeof(*r));
|
||||||
|
if (TAILQ_FIRST(&r->rpool.list) != NULL) {
|
||||||
|
TAILQ_INIT(&por->por_rule.rpool.list);
|
||||||
|
pfctl_move_pool(&r->rpool, &por->por_rule.rpool);
|
||||||
|
} else
|
||||||
|
bzero(&por->por_rule.rpool,
|
||||||
|
sizeof(por->por_rule.rpool));
|
||||||
|
|
||||||
|
|
||||||
|
TAILQ_INSERT_TAIL(&opt_queue, por, por_entry);
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_INIT(&superblocks);
|
TAILQ_INIT(&superblocks);
|
||||||
if (construct_superblocks(pf, &pf->opt_queue, &superblocks))
|
if (construct_superblocks(pf, &opt_queue, &superblocks))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (pf->opts & PF_OPT_OPTIMIZE_PROFILE) {
|
if (pf->optimize & PF_OPTIMIZE_PROFILE) {
|
||||||
if (load_feedback_profile(pf, &superblocks))
|
if (load_feedback_profile(pf, &superblocks))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -271,24 +313,21 @@ pfctl_optimize_rules(struct pfctl *pf)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rs->anchor->refcnt = 0;
|
||||||
/*
|
|
||||||
* Optimizations are done so we turn off the optimization flag and
|
|
||||||
* put the rules right back into the regular codepath.
|
|
||||||
*/
|
|
||||||
pf->opts &= ~PF_OPT_OPTIMIZE;
|
|
||||||
|
|
||||||
while ((block = TAILQ_FIRST(&superblocks))) {
|
while ((block = TAILQ_FIRST(&superblocks))) {
|
||||||
TAILQ_REMOVE(&superblocks, block, sb_entry);
|
TAILQ_REMOVE(&superblocks, block, sb_entry);
|
||||||
|
|
||||||
while ((por = TAILQ_FIRST(&block->sb_rules))) {
|
while ((por = TAILQ_FIRST(&block->sb_rules))) {
|
||||||
TAILQ_REMOVE(&block->sb_rules, por, por_entry);
|
TAILQ_REMOVE(&block->sb_rules, por, por_entry);
|
||||||
por->por_rule.nr = nr++;
|
por->por_rule.nr = rs->anchor->refcnt++;
|
||||||
if (pfctl_add_rule(pf, &por->por_rule,
|
if ((r = calloc(1, sizeof(*r))) == NULL)
|
||||||
por->por_anchor)) {
|
err(1, "calloc");
|
||||||
free(por);
|
memcpy(r, &por->por_rule, sizeof(*r));
|
||||||
goto error;
|
TAILQ_INIT(&r->rpool.list);
|
||||||
}
|
pfctl_move_pool(&por->por_rule.rpool, &r->rpool);
|
||||||
|
TAILQ_INSERT_TAIL(
|
||||||
|
rs->rules[PF_RULESET_FILTER].active.ptr,
|
||||||
|
r, entries);
|
||||||
free(por);
|
free(por);
|
||||||
}
|
}
|
||||||
free(block);
|
free(block);
|
||||||
@ -297,8 +336,8 @@ pfctl_optimize_rules(struct pfctl *pf)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
while ((por = TAILQ_FIRST(&pf->opt_queue))) {
|
while ((por = TAILQ_FIRST(&opt_queue))) {
|
||||||
TAILQ_REMOVE(&pf->opt_queue, por, por_entry);
|
TAILQ_REMOVE(&opt_queue, por, por_entry);
|
||||||
if (por->por_src_tbl) {
|
if (por->por_src_tbl) {
|
||||||
pfr_buf_clear(por->por_src_tbl->pt_buf);
|
pfr_buf_clear(por->por_src_tbl->pt_buf);
|
||||||
free(por->por_src_tbl->pt_buf);
|
free(por->por_src_tbl->pt_buf);
|
||||||
@ -367,7 +406,8 @@ optimize_superblock(struct pfctl *pf, struct superblock *block)
|
|||||||
printf("--- Superblock ---\n");
|
printf("--- Superblock ---\n");
|
||||||
TAILQ_FOREACH(por, &block->sb_rules, por_entry) {
|
TAILQ_FOREACH(por, &block->sb_rules, por_entry) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
print_rule(&por->por_rule, por->por_anchor, 1);
|
print_rule(&por->por_rule, por->por_rule.anchor ?
|
||||||
|
por->por_rule.anchor->name : "", 1);
|
||||||
}
|
}
|
||||||
#endif /* OPT_DEBUG */
|
#endif /* OPT_DEBUG */
|
||||||
|
|
||||||
@ -376,7 +416,7 @@ optimize_superblock(struct pfctl *pf, struct superblock *block)
|
|||||||
return (1);
|
return (1);
|
||||||
if (combine_rules(pf, block))
|
if (combine_rules(pf, block))
|
||||||
return (1);
|
return (1);
|
||||||
if ((pf->opts & PF_OPT_OPTIMIZE_PROFILE) &&
|
if ((pf->optimize & PF_OPTIMIZE_PROFILE) &&
|
||||||
TAILQ_FIRST(&block->sb_rules)->por_rule.quick &&
|
TAILQ_FIRST(&block->sb_rules)->por_rule.quick &&
|
||||||
block->sb_profiled_block) {
|
block->sb_profiled_block) {
|
||||||
if (block_feedback(pf, block))
|
if (block_feedback(pf, block))
|
||||||
@ -783,14 +823,16 @@ block_feedback(struct pfctl *pf, struct superblock *block)
|
|||||||
*/
|
*/
|
||||||
TAILQ_FOREACH(por1, &block->sb_profiled_block->sb_rules, por_entry) {
|
TAILQ_FOREACH(por1, &block->sb_profiled_block->sb_rules, por_entry) {
|
||||||
comparable_rule(&a, &por1->por_rule, DC);
|
comparable_rule(&a, &por1->por_rule, DC);
|
||||||
total_count += por1->por_rule.packets;
|
total_count += por1->por_rule.packets[0] +
|
||||||
|
por1->por_rule.packets[1];
|
||||||
TAILQ_FOREACH(por2, &block->sb_rules, por_entry) {
|
TAILQ_FOREACH(por2, &block->sb_rules, por_entry) {
|
||||||
if (por2->por_profile_count)
|
if (por2->por_profile_count)
|
||||||
continue;
|
continue;
|
||||||
comparable_rule(&b, &por2->por_rule, DC);
|
comparable_rule(&b, &por2->por_rule, DC);
|
||||||
if (memcmp(&a, &b, sizeof(a)) == 0) {
|
if (memcmp(&a, &b, sizeof(a)) == 0) {
|
||||||
por2->por_profile_count =
|
por2->por_profile_count =
|
||||||
por1->por_rule.packets;
|
por1->por_rule.packets[0] +
|
||||||
|
por1->por_rule.packets[1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -858,6 +900,7 @@ load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks)
|
|||||||
|
|
||||||
DEBUG("Loading %d active rules for a feedback profile", mnr);
|
DEBUG("Loading %d active rules for a feedback profile", mnr);
|
||||||
for (nr = 0; nr < mnr; ++nr) {
|
for (nr = 0; nr < mnr; ++nr) {
|
||||||
|
struct pf_ruleset *rs;
|
||||||
if ((por = calloc(1, sizeof(*por))) == NULL) {
|
if ((por = calloc(1, sizeof(*por))) == NULL) {
|
||||||
warn("calloc");
|
warn("calloc");
|
||||||
return (1);
|
return (1);
|
||||||
@ -868,8 +911,8 @@ load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule));
|
memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule));
|
||||||
strlcpy(por->por_anchor, pr.anchor_call,
|
rs = pf_find_or_create_ruleset(pr.anchor_call);
|
||||||
sizeof(por->por_anchor));
|
por->por_rule.anchor = rs->anchor;
|
||||||
if (TAILQ_EMPTY(&por->por_rule.rpool.list))
|
if (TAILQ_EMPTY(&por->por_rule.rpool.list))
|
||||||
memset(&por->por_rule.rpool, 0,
|
memset(&por->por_rule.rpool, 0,
|
||||||
sizeof(por->por_rule.rpool));
|
sizeof(por->por_rule.rpool));
|
||||||
@ -1052,6 +1095,7 @@ skip_cmp_dst_addr(struct pf_rule *a, struct pf_rule *b)
|
|||||||
return (1);
|
return (1);
|
||||||
return (0);
|
return (0);
|
||||||
case PF_ADDR_NOROUTE:
|
case PF_ADDR_NOROUTE:
|
||||||
|
case PF_ADDR_URPFFAILED:
|
||||||
return (0);
|
return (0);
|
||||||
case PF_ADDR_TABLE:
|
case PF_ADDR_TABLE:
|
||||||
return (strcmp(a->dst.addr.v.tblname, b->dst.addr.v.tblname));
|
return (strcmp(a->dst.addr.v.tblname, b->dst.addr.v.tblname));
|
||||||
@ -1123,6 +1167,7 @@ skip_cmp_src_addr(struct pf_rule *a, struct pf_rule *b)
|
|||||||
return (1);
|
return (1);
|
||||||
return (0);
|
return (0);
|
||||||
case PF_ADDR_NOROUTE:
|
case PF_ADDR_NOROUTE:
|
||||||
|
case PF_ADDR_URPFFAILED:
|
||||||
return (0);
|
return (0);
|
||||||
case PF_ADDR_TABLE:
|
case PF_ADDR_TABLE:
|
||||||
return (strcmp(a->src.addr.v.tblname, b->src.addr.v.tblname));
|
return (strcmp(a->src.addr.v.tblname, b->src.addr.v.tblname));
|
||||||
@ -1274,8 +1319,8 @@ pf_opt_create_table(struct pfctl *pf, struct pf_opt_tbl *tbl)
|
|||||||
tablenum++;
|
tablenum++;
|
||||||
|
|
||||||
|
|
||||||
if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1, pf->anchor,
|
if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1,
|
||||||
tbl->pt_buf, pf->tticket)) {
|
pf->anchor->name, tbl->pt_buf, pf->anchor->ruleset.tticket)) {
|
||||||
warn("failed to create table %s", tbl->pt_name);
|
warn("failed to create table %s", tbl->pt_name);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -1374,15 +1419,34 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'anchor' heads and per-rule src-track are also hard breaks */
|
/* per-rule src-track is also a hard break */
|
||||||
if (por->por_anchor[0] != '\0' ||
|
if (por->por_rule.rule_flag & PFRULE_RULESRCTRACK)
|
||||||
(por->por_rule.rule_flag & PFRULE_RULESRCTRACK))
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have to handle interface groups seperately. Consider the following
|
||||||
|
* rules:
|
||||||
|
* block on EXTIFS to any port 22
|
||||||
|
* pass on em0 to any port 22
|
||||||
|
* (where EXTIFS is an arbitrary interface group)
|
||||||
|
* The optimizer may decide to re-order the pass rule in front of the
|
||||||
|
* block rule. But what if EXTIFS includes em0??? Such a reordering
|
||||||
|
* would change the meaning of the ruleset.
|
||||||
|
* We can't just lookup the EXTIFS group and check if em0 is a member
|
||||||
|
* because the user is allowed to add interfaces to a group during
|
||||||
|
* runtime.
|
||||||
|
* Ergo interface groups become a defacto superblock break :-(
|
||||||
|
*/
|
||||||
|
if (interface_group(por->por_rule.ifname) ||
|
||||||
|
interface_group(TAILQ_FIRST(&block->sb_rules)->por_rule.ifname)) {
|
||||||
|
if (strcasecmp(por->por_rule.ifname,
|
||||||
|
TAILQ_FIRST(&block->sb_rules)->por_rule.ifname) != 0)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
comparable_rule(&a, &TAILQ_FIRST(&block->sb_rules)->por_rule, NOMERGE);
|
comparable_rule(&a, &TAILQ_FIRST(&block->sb_rules)->por_rule, NOMERGE);
|
||||||
comparable_rule(&b, &por->por_rule, NOMERGE);
|
comparable_rule(&b, &por->por_rule, NOMERGE);
|
||||||
if (strcmp(TAILQ_FIRST(&block->sb_rules)->por_anchor,
|
if (memcmp(&a, &b, sizeof(a)) == 0)
|
||||||
por->por_anchor) == 0 && memcmp(&a, &b, sizeof(a)) == 0)
|
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
#ifdef OPT_DEBUG
|
#ifdef OPT_DEBUG
|
||||||
@ -1425,6 +1489,24 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure out if an interface name is an actual interface or actually a
|
||||||
|
* group of interfaces.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
interface_group(const char *ifname)
|
||||||
|
{
|
||||||
|
if (ifname == NULL || !ifname[0])
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Real interfaces must end in a number, interface groups do not */
|
||||||
|
if (isdigit(ifname[strlen(ifname) - 1]))
|
||||||
|
return (0);
|
||||||
|
else
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make a rule that can directly compared by memcmp()
|
* Make a rule that can directly compared by memcmp()
|
||||||
*/
|
*/
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_parser.c,v 1.211 2004/12/07 10:33:41 dhartmei Exp $ */
|
/* $OpenBSD: pfctl_parser.c,v 1.234 2006/10/31 23:46:24 mcbride Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "pfctl_parser.h"
|
#include "pfctl_parser.h"
|
||||||
#include "pfctl.h"
|
#include "pfctl.h"
|
||||||
@ -70,6 +71,7 @@ void print_fromto(struct pf_rule_addr *, pf_osfp_t,
|
|||||||
struct pf_rule_addr *, u_int8_t, u_int8_t, int);
|
struct pf_rule_addr *, u_int8_t, u_int8_t, int);
|
||||||
int ifa_skip_if(const char *filter, struct node_host *p);
|
int ifa_skip_if(const char *filter, struct node_host *p);
|
||||||
|
|
||||||
|
struct node_host *ifa_grouplookup(const char *, int);
|
||||||
struct node_host *host_if(const char *, int);
|
struct node_host *host_if(const char *, int);
|
||||||
struct node_host *host_v4(const char *, int);
|
struct node_host *host_v4(const char *, int);
|
||||||
struct node_host *host_v6(const char *, int);
|
struct node_host *host_v6(const char *, int);
|
||||||
@ -483,9 +485,11 @@ const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
|
|||||||
void
|
void
|
||||||
print_status(struct pf_status *s, int opts)
|
print_status(struct pf_status *s, int opts)
|
||||||
{
|
{
|
||||||
char statline[80], *running;
|
char statline[80], *running;
|
||||||
time_t runtime;
|
time_t runtime;
|
||||||
int i;
|
int i;
|
||||||
|
char buf[PF_MD5_DIGEST_LENGTH * 2 + 1];
|
||||||
|
static const char hex[] = "0123456789abcdef";
|
||||||
|
|
||||||
runtime = time(NULL) - s->since;
|
runtime = time(NULL) - s->since;
|
||||||
running = s->running ? "Enabled" : "Disabled";
|
running = s->running ? "Enabled" : "Disabled";
|
||||||
@ -519,7 +523,18 @@ print_status(struct pf_status *s, int opts)
|
|||||||
printf("%15s\n\n", "Debug: Loud");
|
printf("%15s\n\n", "Debug: Loud");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("Hostid: 0x%08x\n\n", ntohl(s->hostid));
|
|
||||||
|
if (opts & PF_OPT_VERBOSE) {
|
||||||
|
printf("Hostid: 0x%08x\n", ntohl(s->hostid));
|
||||||
|
|
||||||
|
for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) {
|
||||||
|
buf[i + i] = hex[s->pf_chksum[i] >> 4];
|
||||||
|
buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f];
|
||||||
|
}
|
||||||
|
buf[i + i] = '\0';
|
||||||
|
printf("Checksum: 0x%s\n\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
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");
|
||||||
@ -631,7 +646,14 @@ print_src_node(struct pf_src_node *sn, int opts)
|
|||||||
printf(", expires in %.2u:%.2u:%.2u",
|
printf(", expires in %.2u:%.2u:%.2u",
|
||||||
sn->expire, min, sec);
|
sn->expire, min, sec);
|
||||||
}
|
}
|
||||||
printf(", %u pkts, %u bytes", sn->packets, sn->bytes);
|
printf(", %llu pkts, %llu bytes",
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
(unsigned long long)(sn->packets[0] + sn->packets[1]),
|
||||||
|
(unsigned long long)(sn->bytes[0] + sn->bytes[1]));
|
||||||
|
#else
|
||||||
|
sn->packets[0] + sn->packets[1],
|
||||||
|
sn->bytes[0] + sn->bytes[1]);
|
||||||
|
#endif
|
||||||
switch (sn->ruletype) {
|
switch (sn->ruletype) {
|
||||||
case PF_NAT:
|
case PF_NAT:
|
||||||
if (sn->rule.nr != -1)
|
if (sn->rule.nr != -1)
|
||||||
@ -664,10 +686,13 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
printf("@%d ", r->nr);
|
printf("@%d ", r->nr);
|
||||||
if (r->action > PF_NORDR)
|
if (r->action > PF_NORDR)
|
||||||
printf("action(%d)", r->action);
|
printf("action(%d)", r->action);
|
||||||
else if (anchor_call[0])
|
else if (anchor_call[0]) {
|
||||||
printf("%s \"%s\"", anchortypes[r->action],
|
if (anchor_call[0] == '_') {
|
||||||
anchor_call);
|
printf("%s", anchortypes[r->action]);
|
||||||
else {
|
} else
|
||||||
|
printf("%s \"%s\"", anchortypes[r->action],
|
||||||
|
anchor_call);
|
||||||
|
} else {
|
||||||
printf("%s", actiontypes[r->action]);
|
printf("%s", actiontypes[r->action]);
|
||||||
if (r->natpass)
|
if (r->natpass)
|
||||||
printf(" pass");
|
printf(" pass");
|
||||||
@ -722,10 +747,22 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
printf(" in");
|
printf(" in");
|
||||||
else if (r->direction == PF_OUT)
|
else if (r->direction == PF_OUT)
|
||||||
printf(" out");
|
printf(" out");
|
||||||
if (r->log == 1)
|
if (r->log) {
|
||||||
printf(" log");
|
printf(" log");
|
||||||
else if (r->log == 2)
|
if (r->log & ~PF_LOG || r->logif) {
|
||||||
printf(" log-all");
|
int count = 0;
|
||||||
|
|
||||||
|
printf(" (");
|
||||||
|
if (r->log & PF_LOG_ALL)
|
||||||
|
printf("%sall", count++ ? ", " : "");
|
||||||
|
if (r->log & PF_LOG_SOCKET_LOOKUP)
|
||||||
|
printf("%suser", count++ ? ", " : "");
|
||||||
|
if (r->logif)
|
||||||
|
printf("%sto pflog%u", count++ ? ", " : "",
|
||||||
|
r->logif);
|
||||||
|
printf(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (r->quick)
|
if (r->quick)
|
||||||
printf(" quick");
|
printf(" quick");
|
||||||
if (r->ifname[0]) {
|
if (r->ifname[0]) {
|
||||||
@ -775,7 +812,11 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
print_flags(r->flags);
|
print_flags(r->flags);
|
||||||
printf("/");
|
printf("/");
|
||||||
print_flags(r->flagset);
|
print_flags(r->flagset);
|
||||||
}
|
} else if (r->action == PF_PASS &&
|
||||||
|
(!r->proto || r->proto == IPPROTO_TCP) &&
|
||||||
|
!(r->rule_flag & PFRULE_FRAGMENT) &&
|
||||||
|
!anchor_call[0] && r->keep_state)
|
||||||
|
printf(" flags any");
|
||||||
if (r->type) {
|
if (r->type) {
|
||||||
const struct icmptypeent *it;
|
const struct icmptypeent *it;
|
||||||
|
|
||||||
@ -800,7 +841,9 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
}
|
}
|
||||||
if (r->tos)
|
if (r->tos)
|
||||||
printf(" tos 0x%2.2x", r->tos);
|
printf(" tos 0x%2.2x", r->tos);
|
||||||
if (r->keep_state == PF_STATE_NORMAL)
|
if (!r->keep_state && r->action == PF_PASS && !anchor_call[0])
|
||||||
|
printf(" no state");
|
||||||
|
else if (r->keep_state == PF_STATE_NORMAL)
|
||||||
printf(" keep state");
|
printf(" keep state");
|
||||||
else if (r->keep_state == PF_STATE_MODULATE)
|
else if (r->keep_state == PF_STATE_MODULATE)
|
||||||
printf(" modulate state");
|
printf(" modulate state");
|
||||||
@ -828,7 +871,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
opts = 1;
|
opts = 1;
|
||||||
if (r->rule_flag & PFRULE_SRCTRACK)
|
if (r->rule_flag & PFRULE_SRCTRACK)
|
||||||
opts = 1;
|
opts = 1;
|
||||||
if (r->rule_flag & (PFRULE_IFBOUND | PFRULE_GRBOUND))
|
if (r->rule_flag & PFRULE_IFBOUND)
|
||||||
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])
|
||||||
@ -896,12 +939,6 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
printf("if-bound");
|
printf("if-bound");
|
||||||
opts = 0;
|
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]) {
|
||||||
int j;
|
int j;
|
||||||
@ -909,12 +946,13 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
if (!opts)
|
if (!opts)
|
||||||
printf(", ");
|
printf(", ");
|
||||||
opts = 0;
|
opts = 0;
|
||||||
for (j = 0; j < sizeof(pf_timeouts) /
|
for (j = 0; pf_timeouts[j].name != NULL;
|
||||||
sizeof(pf_timeouts[0]); ++j)
|
++j)
|
||||||
if (pf_timeouts[j].timeout == i)
|
if (pf_timeouts[j].timeout == i)
|
||||||
break;
|
break;
|
||||||
printf("%s %u", j == PFTM_MAX ? "inv.timeout" :
|
printf("%s %u", pf_timeouts[j].name == NULL ?
|
||||||
pf_timeouts[j].name, r->timeout[i]);
|
"inv.timeout" : pf_timeouts[j].name,
|
||||||
|
r->timeout[i]);
|
||||||
}
|
}
|
||||||
printf(")");
|
printf(")");
|
||||||
}
|
}
|
||||||
@ -954,13 +992,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
|||||||
printf(" !");
|
printf(" !");
|
||||||
printf(" tagged %s", r->match_tagname);
|
printf(" tagged %s", r->match_tagname);
|
||||||
}
|
}
|
||||||
|
if (r->rtableid != -1)
|
||||||
|
printf(" rtable %u", r->rtableid);
|
||||||
if (!anchor_call[0] && (r->action == PF_NAT ||
|
if (!anchor_call[0] && (r->action == PF_NAT ||
|
||||||
r->action == PF_BINAT || r->action == PF_RDR)) {
|
r->action == PF_BINAT || r->action == PF_RDR)) {
|
||||||
printf(" -> ");
|
printf(" -> ");
|
||||||
print_pool(&r->rpool, r->rpool.proxy_port[0],
|
print_pool(&r->rpool, r->rpool.proxy_port[0],
|
||||||
r->rpool.proxy_port[1], r->af, r->action);
|
r->rpool.proxy_port[1], r->af, r->action);
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1153,13 +1192,31 @@ ifa_load(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct node_host *
|
struct node_host *
|
||||||
ifa_exists(const char *ifa_name, int group_ok)
|
ifa_exists(const char *ifa_name)
|
||||||
{
|
{
|
||||||
struct node_host *n;
|
struct node_host *n;
|
||||||
|
struct ifgroupreq ifgr;
|
||||||
|
int s;
|
||||||
|
|
||||||
if (iftab == NULL)
|
if (iftab == NULL)
|
||||||
ifa_load();
|
ifa_load();
|
||||||
|
|
||||||
|
/* check wether this is a group */
|
||||||
|
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||||
|
err(1, "socket");
|
||||||
|
bzero(&ifgr, sizeof(ifgr));
|
||||||
|
strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
|
||||||
|
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) {
|
||||||
|
/* fake a node_host */
|
||||||
|
if ((n = calloc(1, sizeof(*n))) == NULL)
|
||||||
|
err(1, "calloc");
|
||||||
|
if ((n->ifname = strdup(ifa_name)) == NULL)
|
||||||
|
err(1, "strdup");
|
||||||
|
close(s);
|
||||||
|
return (n);
|
||||||
|
}
|
||||||
|
close(s);
|
||||||
|
|
||||||
for (n = iftab; n; n = n->next) {
|
for (n = iftab; n; n = n->next) {
|
||||||
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);
|
||||||
@ -1168,6 +1225,47 @@ ifa_exists(const char *ifa_name, int group_ok)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct node_host *
|
||||||
|
ifa_grouplookup(const char *ifa_name, int flags)
|
||||||
|
{
|
||||||
|
struct ifg_req *ifg;
|
||||||
|
struct ifgroupreq ifgr;
|
||||||
|
int s, len;
|
||||||
|
struct node_host *n, *h = NULL;
|
||||||
|
|
||||||
|
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||||
|
err(1, "socket");
|
||||||
|
bzero(&ifgr, sizeof(ifgr));
|
||||||
|
strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
|
||||||
|
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
|
||||||
|
close(s);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ifgr.ifgr_len;
|
||||||
|
if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
|
||||||
|
err(1, "calloc");
|
||||||
|
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
|
||||||
|
err(1, "SIOCGIFGMEMB");
|
||||||
|
|
||||||
|
for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
|
||||||
|
ifg++) {
|
||||||
|
len -= sizeof(struct ifg_req);
|
||||||
|
if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL)
|
||||||
|
continue;
|
||||||
|
if (h == NULL)
|
||||||
|
h = n;
|
||||||
|
else {
|
||||||
|
h->tail->next = n;
|
||||||
|
h->tail = n->tail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(ifgr.ifgr_groups);
|
||||||
|
close(s);
|
||||||
|
|
||||||
|
return (h);
|
||||||
|
}
|
||||||
|
|
||||||
struct node_host *
|
struct node_host *
|
||||||
ifa_lookup(const char *ifa_name, int flags)
|
ifa_lookup(const char *ifa_name, int flags)
|
||||||
{
|
{
|
||||||
@ -1175,6 +1273,9 @@ ifa_lookup(const char *ifa_name, int flags)
|
|||||||
int got4 = 0, got6 = 0;
|
int got4 = 0, got6 = 0;
|
||||||
const char *last_if = NULL;
|
const char *last_if = NULL;
|
||||||
|
|
||||||
|
if ((h = ifa_grouplookup(ifa_name, flags)) != NULL)
|
||||||
|
return (h);
|
||||||
|
|
||||||
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
||||||
ifa_name = NULL;
|
ifa_name = NULL;
|
||||||
|
|
||||||
@ -1352,7 +1453,7 @@ host_if(const char *s, int mask)
|
|||||||
free(ps);
|
free(ps);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (ifa_exists(ps, 1) || !strncmp(ps, "self", IFNAMSIZ)) {
|
if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
|
||||||
/* interface with this name exists */
|
/* interface with this name exists */
|
||||||
h = ifa_lookup(ps, flags);
|
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)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_parser.h,v 1.80 2005/02/07 18:18:14 david Exp $ */
|
/* $OpenBSD: pfctl_parser.h,v 1.86 2006/10/31 23:46:25 mcbride Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Daniel Hartmeier
|
* Copyright (c) 2001 Daniel Hartmeier
|
||||||
@ -48,14 +48,17 @@
|
|||||||
#define PF_OPT_DEBUG 0x0200
|
#define PF_OPT_DEBUG 0x0200
|
||||||
#define PF_OPT_SHOWALL 0x0400
|
#define PF_OPT_SHOWALL 0x0400
|
||||||
#define PF_OPT_OPTIMIZE 0x0800
|
#define PF_OPT_OPTIMIZE 0x0800
|
||||||
#define PF_OPT_OPTIMIZE_PROFILE 0x1000
|
|
||||||
#define PF_OPT_MERGE 0x2000
|
#define PF_OPT_MERGE 0x2000
|
||||||
|
#define PF_OPT_RECURSE 0x4000
|
||||||
|
|
||||||
#define PF_TH_ALL 0xFF
|
#define PF_TH_ALL 0xFF
|
||||||
|
|
||||||
#define PF_NAT_PROXY_PORT_LOW 50001
|
#define PF_NAT_PROXY_PORT_LOW 50001
|
||||||
#define PF_NAT_PROXY_PORT_HIGH 65535
|
#define PF_NAT_PROXY_PORT_HIGH 65535
|
||||||
|
|
||||||
|
#define PF_OPTIMIZE_BASIC 0x0001
|
||||||
|
#define PF_OPTIMIZE_PROFILE 0x0002
|
||||||
|
|
||||||
#define FCNT_NAMES { \
|
#define FCNT_NAMES { \
|
||||||
"searches", \
|
"searches", \
|
||||||
"inserts", \
|
"inserts", \
|
||||||
@ -64,24 +67,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct pfr_buffer; /* forward definition */
|
struct pfr_buffer; /* forward definition */
|
||||||
struct pf_opt_rule;
|
|
||||||
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
|
|
||||||
|
|
||||||
|
|
||||||
struct pfctl {
|
struct pfctl {
|
||||||
int dev;
|
int dev;
|
||||||
int opts;
|
int opts;
|
||||||
|
int optimize;
|
||||||
int loadopt;
|
int loadopt;
|
||||||
u_int32_t tticket; /* table ticket */
|
int asd; /* anchor stack depth */
|
||||||
|
int bn; /* brace number */
|
||||||
|
int brace;
|
||||||
int tdirty; /* kernel dirty */
|
int tdirty; /* kernel dirty */
|
||||||
u_int32_t rule_nr;
|
#define PFCTL_ANCHOR_STACK_DEPTH 64
|
||||||
|
struct pf_anchor *astack[PFCTL_ANCHOR_STACK_DEPTH];
|
||||||
struct pfioc_pooladdr paddr;
|
struct pfioc_pooladdr paddr;
|
||||||
struct pfioc_altq *paltq;
|
struct pfioc_altq *paltq;
|
||||||
struct pfioc_queue *pqueue;
|
struct pfioc_queue *pqueue;
|
||||||
struct pfr_buffer *trans;
|
struct pfr_buffer *trans;
|
||||||
const char *anchor;
|
struct pf_anchor *anchor, *alast;
|
||||||
const char *ruleset;
|
const char *ruleset;
|
||||||
struct pf_opt_queue opt_queue;
|
|
||||||
|
|
||||||
/* 'set foo' options */
|
/* 'set foo' options */
|
||||||
u_int32_t timeout[PFTM_MAX];
|
u_int32_t timeout[PFTM_MAX];
|
||||||
@ -118,10 +122,6 @@ 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;
|
||||||
@ -205,19 +205,20 @@ struct pf_opt_rule {
|
|||||||
struct pf_rule por_rule;
|
struct pf_rule por_rule;
|
||||||
struct pf_opt_tbl *por_src_tbl;
|
struct pf_opt_tbl *por_src_tbl;
|
||||||
struct pf_opt_tbl *por_dst_tbl;
|
struct pf_opt_tbl *por_dst_tbl;
|
||||||
char por_anchor[MAXPATHLEN];
|
|
||||||
u_int64_t por_profile_count;
|
u_int64_t por_profile_count;
|
||||||
TAILQ_ENTRY(pf_opt_rule) por_entry;
|
TAILQ_ENTRY(pf_opt_rule) por_entry;
|
||||||
TAILQ_ENTRY(pf_opt_rule) por_skip_entry[PF_SKIP_COUNT];
|
TAILQ_ENTRY(pf_opt_rule) por_skip_entry[PF_SKIP_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
|
||||||
|
|
||||||
int pfctl_rules(int, char *, int, char *, struct pfr_buffer *);
|
int pfctl_rules(int, char *, FILE *, int, int, char *, struct pfr_buffer *);
|
||||||
int pfctl_optimize_rules(struct pfctl *);
|
int pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *);
|
||||||
|
|
||||||
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
|
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
|
||||||
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
||||||
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t);
|
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t);
|
||||||
|
void pfctl_move_pool(struct pf_pool *, struct pf_pool *);
|
||||||
void pfctl_clear_pool(struct pf_pool *);
|
void pfctl_clear_pool(struct pf_pool *);
|
||||||
|
|
||||||
int pfctl_set_timeout(struct pfctl *, const char *, int, int);
|
int pfctl_set_timeout(struct pfctl *, const char *, int, int);
|
||||||
@ -230,7 +231,7 @@ int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
|
|||||||
|
|
||||||
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, struct pfr_buffer *);
|
int pfctl_load_anchors(int, struct pfctl *, 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_src_node(struct pf_src_node *, int);
|
||||||
@ -292,7 +293,7 @@ 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);
|
||||||
int unmask(struct pf_addr *, sa_family_t);
|
int unmask(struct pf_addr *, sa_family_t);
|
||||||
void ifa_load(void);
|
void ifa_load(void);
|
||||||
struct node_host *ifa_exists(const char *, int);
|
struct node_host *ifa_exists(const char *);
|
||||||
struct node_host *ifa_lookup(const char *, int);
|
struct node_host *ifa_lookup(const char *, int);
|
||||||
struct node_host *host(const char *);
|
struct node_host *host(const char *);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pfctl_table.c,v 1.62 2004/12/22 17:17:55 dhartmei Exp $ */
|
/* $OpenBSD: pfctl_table.c,v 1.66 2007/03/01 17:20:54 deraadt Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002 Cedric Berger
|
* Copyright (c) 2002 Cedric Berger
|
||||||
@ -64,8 +64,7 @@ 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 print_iface(struct pfi_kif *, 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:" },
|
||||||
@ -178,7 +177,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts & PF_OPT_SHOWALL && b.pfrb_size > 0)
|
if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
|
||||||
pfctl_print_title("TABLES:");
|
pfctl_print_title("TABLES:");
|
||||||
|
|
||||||
PFRB_FOREACH(p, &b)
|
PFRB_FOREACH(p, &b)
|
||||||
@ -257,6 +256,42 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
|||||||
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
|
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
|
||||||
print_addrx(a, NULL,
|
print_addrx(a, NULL,
|
||||||
opts & PF_OPT_USEDNS);
|
opts & PF_OPT_USEDNS);
|
||||||
|
} else if (!strcmp(command, "expire")) {
|
||||||
|
const char *errstr;
|
||||||
|
u_int lifetime;
|
||||||
|
|
||||||
|
b.pfrb_type = PFRB_ASTATS;
|
||||||
|
b2.pfrb_type = PFRB_ADDRS;
|
||||||
|
if (argc != 1 || file != NULL)
|
||||||
|
usage();
|
||||||
|
lifetime = strtonum(*argv, 0, UINT_MAX, &errstr);
|
||||||
|
if (errstr)
|
||||||
|
errx(1, "expiry time: %s", errstr);
|
||||||
|
for (;;) {
|
||||||
|
pfr_buf_grow(&b, b.pfrb_size);
|
||||||
|
b.pfrb_size = b.pfrb_msize;
|
||||||
|
RVTEST(pfr_get_astats(&table, b.pfrb_caddr,
|
||||||
|
&b.pfrb_size, flags));
|
||||||
|
if (b.pfrb_size <= b.pfrb_msize)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PFRB_FOREACH(p, &b)
|
||||||
|
if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero >
|
||||||
|
lifetime)
|
||||||
|
if (pfr_buf_add(&b2,
|
||||||
|
&((struct pfr_astats *)p)->pfras_a))
|
||||||
|
err(1, "duplicate buffer");
|
||||||
|
|
||||||
|
if (opts & PF_OPT_VERBOSE)
|
||||||
|
flags |= PFR_FLAG_FEEDBACK;
|
||||||
|
RVTEST(pfr_del_addrs(&table, b2.pfrb_caddr, b2.pfrb_size,
|
||||||
|
&ndel, flags));
|
||||||
|
xprintf(opts, "%d/%d addresses expired", ndel, b2.pfrb_size);
|
||||||
|
if (opts & PF_OPT_VERBOSE)
|
||||||
|
PFRB_FOREACH(a, &b2)
|
||||||
|
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
|
||||||
|
print_addrx(a, NULL,
|
||||||
|
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;
|
||||||
@ -294,7 +329,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
|||||||
RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size,
|
RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size,
|
||||||
&nmatch, flags));
|
&nmatch, flags));
|
||||||
xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size);
|
xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size);
|
||||||
if (opts & PF_OPT_VERBOSE && !(opts & PF_OPT_VERBOSE2))
|
if ((opts & PF_OPT_VERBOSE) && !(opts & PF_OPT_VERBOSE2))
|
||||||
PFRB_FOREACH(a, &b)
|
PFRB_FOREACH(a, &b)
|
||||||
if (a->pfra_fback == PFR_FB_MATCH)
|
if (a->pfra_fback == PFR_FB_MATCH)
|
||||||
print_addrx(a, NULL,
|
print_addrx(a, NULL,
|
||||||
@ -542,17 +577,15 @@ int
|
|||||||
pfctl_show_ifaces(const char *filter, int opts)
|
pfctl_show_ifaces(const char *filter, int opts)
|
||||||
{
|
{
|
||||||
struct pfr_buffer b;
|
struct pfr_buffer b;
|
||||||
struct pfi_if *p;
|
struct pfi_kif *p;
|
||||||
int i = 0, f = PFI_FLAG_GROUP|PFI_FLAG_INSTANCE;
|
int i = 0;
|
||||||
|
|
||||||
if (filter != NULL && *filter && !isdigit(filter[strlen(filter)-1]))
|
|
||||||
f &= ~PFI_FLAG_INSTANCE;
|
|
||||||
bzero(&b, sizeof(b));
|
bzero(&b, sizeof(b));
|
||||||
b.pfrb_type = PFRB_IFACES;
|
b.pfrb_type = PFRB_IFACES;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pfr_buf_grow(&b, b.pfrb_size);
|
pfr_buf_grow(&b, b.pfrb_size);
|
||||||
b.pfrb_size = b.pfrb_msize;
|
b.pfrb_size = b.pfrb_msize;
|
||||||
if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size, f)) {
|
if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) {
|
||||||
radix_perror();
|
radix_perror();
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -568,50 +601,30 @@ pfctl_show_ifaces(const char *filter, int opts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_iface(struct pfi_if *p, int opts)
|
print_iface(struct pfi_kif *p, int opts)
|
||||||
{
|
{
|
||||||
time_t tzero = p->pfif_tzero;
|
time_t tzero = p->pfik_tzero;
|
||||||
int flags = (opts & PF_OPT_VERBOSE) ? p->pfif_flags : 0;
|
|
||||||
int first = 1;
|
|
||||||
int i, af, dir, act;
|
int i, af, dir, act;
|
||||||
|
|
||||||
printf("%s", p->pfif_name);
|
printf("%s", p->pfik_name);
|
||||||
oprintf(flags, PFI_IFLAG_INSTANCE, "instance", &first, 0);
|
if (opts & PF_OPT_VERBOSE) {
|
||||||
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
|
if (p->pfik_flags & PFI_IFLAG_SKIP)
|
||||||
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
|
printf(" (skip)");
|
||||||
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
|
}
|
||||||
oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0);
|
|
||||||
oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1);
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
first = 1;
|
|
||||||
oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1);
|
|
||||||
#endif
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (!(opts & PF_OPT_VERBOSE2))
|
if (!(opts & PF_OPT_VERBOSE2))
|
||||||
return;
|
return;
|
||||||
printf("\tCleared: %s", ctime(&tzero));
|
printf("\tCleared: %s", ctime(&tzero));
|
||||||
printf("\tReferences: [ States: %-18d Rules: %-18d ]\n",
|
printf("\tReferences: [ States: %-18d Rules: %-18d ]\n",
|
||||||
p->pfif_states, p->pfif_rules);
|
p->pfik_states, p->pfik_rules);
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
af = (i>>2) & 1;
|
af = (i>>2) & 1;
|
||||||
dir = (i>>1) &1;
|
dir = (i>>1) &1;
|
||||||
act = i & 1;
|
act = i & 1;
|
||||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||||
istats_text[af][dir][act],
|
istats_text[af][dir][act],
|
||||||
(unsigned long long)p->pfif_packets[af][dir][act],
|
(unsigned long long)p->pfik_packets[af][dir][act],
|
||||||
(unsigned long long)p->pfif_bytes[af][dir][act]);
|
(unsigned long long)p->pfik_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.25 2005/01/02 18:15:02 jmc Exp $
|
.\" $OpenBSD: pflogd.8,v 1.32 2006/12/08 10:26:38 joel Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2001 Can Erkin Acar. All rights reserved.
|
.\" Copyright (c) 2001 Can Erkin Acar. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -37,14 +37,17 @@
|
|||||||
.Op Fl Dx
|
.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 i Ar interface
|
||||||
.Op Fl s Ar snaplen
|
.Op Fl s Ar snaplen
|
||||||
.Op Ar expression
|
.Op Ar expression
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
is a background daemon which reads packets logged by
|
is a background daemon which reads packets logged by
|
||||||
.Xr pf 4
|
.Xr pf 4
|
||||||
to the packet logging interface
|
to a
|
||||||
.Pa pflog0
|
.Xr pflog 4
|
||||||
|
interface, normally
|
||||||
|
.Pa pflog0 ,
|
||||||
and writes the packets to a logfile (normally
|
and writes the packets to a logfile (normally
|
||||||
.Pa /var/log/pflog )
|
.Pa /var/log/pflog )
|
||||||
in
|
in
|
||||||
@ -83,7 +86,9 @@ temporarily uses the old snaplen to keep the log file consistent.
|
|||||||
tries to preserve the integrity of the log file against I/O errors.
|
tries to preserve the integrity of the log file against I/O errors.
|
||||||
Furthermore, integrity of an existing log file is verified before
|
Furthermore, integrity of an existing log file is verified before
|
||||||
appending.
|
appending.
|
||||||
If there is an invalid log file or an I/O error, logging is suspended until a
|
If there is an invalid log file or an I/O error, the log file is moved
|
||||||
|
out of the way and a new one is created.
|
||||||
|
If a new file cannot be created, logging is suspended until a
|
||||||
.Dv SIGHUP
|
.Dv SIGHUP
|
||||||
or a
|
or a
|
||||||
.Dv SIGALRM
|
.Dv SIGALRM
|
||||||
@ -103,11 +108,19 @@ If not specified, the default is 60 seconds.
|
|||||||
Log output filename.
|
Log output filename.
|
||||||
Default is
|
Default is
|
||||||
.Pa /var/log/pflog .
|
.Pa /var/log/pflog .
|
||||||
|
.It Fl i Ar interface
|
||||||
|
Specifies the
|
||||||
|
.Xr pflog 4
|
||||||
|
interface to use.
|
||||||
|
By default,
|
||||||
|
.Nm
|
||||||
|
will use
|
||||||
|
.Ar pflog0 .
|
||||||
.It Fl s Ar snaplen
|
.It Fl s Ar snaplen
|
||||||
Analyze at most the first
|
Analyze at most the first
|
||||||
.Ar snaplen
|
.Ar snaplen
|
||||||
bytes of data from each packet rather than the default of 96.
|
bytes of data from each packet rather than the default of 116.
|
||||||
The default of 96 is adequate for IP, ICMP, TCP, and UDP headers but may
|
The default of 116 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
|
.It Fl x
|
||||||
@ -131,6 +144,13 @@ Log specific tcp packets to a different log file with a large snaplen
|
|||||||
# pflogd -s 1600 -f suspicious.log port 80 and host evilhost
|
# pflogd -s 1600 -f suspicious.log port 80 and host evilhost
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
|
Log from another
|
||||||
|
.Xr pflog 4
|
||||||
|
interface, excluding specific packets:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
# pflogd -i pflog3 -f network3.log "not (tcp and port 23)"
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
Display binary logs:
|
Display binary logs:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
# tcpdump -n -e -ttt -r /var/log/pflog
|
# tcpdump -n -e -ttt -r /var/log/pflog
|
||||||
@ -150,7 +170,7 @@ 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 "ruleset authpf " -compact
|
||||||
.It ip
|
.It ip
|
||||||
Address family equals IPv4.
|
Address family equals IPv4.
|
||||||
.It ip6
|
.It ip6
|
||||||
@ -159,12 +179,16 @@ Address family equals IPv6.
|
|||||||
Interface name equals "kue0".
|
Interface name equals "kue0".
|
||||||
.It on kue0
|
.It on kue0
|
||||||
Interface name equals "kue0".
|
Interface name equals "kue0".
|
||||||
|
.It ruleset authpf
|
||||||
|
Ruleset name equals "authpf".
|
||||||
.It rulenum 10
|
.It rulenum 10
|
||||||
Rule number equals 10.
|
Rule number equals 10.
|
||||||
.It reason match
|
.It reason match
|
||||||
Reason equals match.
|
Reason equals match.
|
||||||
Also accepts "bad-offset", "fragment", "bad-timestamp", "short",
|
Also accepts "bad-offset", "fragment", "bad-timestamp", "short",
|
||||||
"normalize" and "memory".
|
"normalize", "memory", "congestion", "ip-option", "proto-cksum",
|
||||||
|
"state-mismatch", "state-insert", "state-limit", "src-limit",
|
||||||
|
and "synproxy".
|
||||||
.It action pass
|
.It action pass
|
||||||
Action equals pass.
|
Action equals pass.
|
||||||
Also accepts "block".
|
Also accepts "block".
|
||||||
@ -192,4 +216,6 @@ The
|
|||||||
command appeared in
|
command appeared in
|
||||||
.Ox 3.0 .
|
.Ox 3.0 .
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
Can Erkin Acar
|
.Nm
|
||||||
|
was written by
|
||||||
|
.An Can Erkin Acar Aq canacar@openbsd.org .
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pflogd.c,v 1.33 2005/02/09 12:09:30 henning Exp $ */
|
/* $OpenBSD: pflogd.c,v 1.37 2006/10/26 13:34:47 jmc Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Theo de Raadt
|
* Copyright (c) 2001 Theo de Raadt
|
||||||
@ -81,7 +81,7 @@ int flush_buffer(FILE *);
|
|||||||
int init_pcap(void);
|
int init_pcap(void);
|
||||||
void logmsg(int, const char *, ...);
|
void logmsg(int, const char *, ...);
|
||||||
void purge_buffer(void);
|
void purge_buffer(void);
|
||||||
int reset_dump(void);
|
int reset_dump(int);
|
||||||
int scan_dump(FILE *, off_t);
|
int scan_dump(FILE *, off_t);
|
||||||
int set_snaplen(int);
|
int set_snaplen(int);
|
||||||
void set_suspended(int);
|
void set_suspended(int);
|
||||||
@ -90,6 +90,8 @@ void sig_close(int);
|
|||||||
void sig_hup(int);
|
void sig_hup(int);
|
||||||
void usage(void);
|
void usage(void);
|
||||||
|
|
||||||
|
static int try_reset_dump(int);
|
||||||
|
|
||||||
/* buffer must always be greater than snaplen */
|
/* buffer must always be greater than snaplen */
|
||||||
static int bufpkt = 0; /* number of packets in buffer */
|
static int bufpkt = 0; /* number of packets in buffer */
|
||||||
static int buflen = 0; /* allocated size of buffer */
|
static int buflen = 0; /* allocated size of buffer */
|
||||||
@ -108,8 +110,9 @@ set_suspended(int s)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
suspended = s;
|
suspended = s;
|
||||||
setproctitle("[%s] -s %d -f %s",
|
setproctitle("[%s] -s %d -i %s -f %s",
|
||||||
suspended ? "suspended" : "running", cur_snaplen, filename);
|
suspended ? "suspended" : "running",
|
||||||
|
cur_snaplen, interface, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
@ -159,8 +162,9 @@ __dead void
|
|||||||
#endif
|
#endif
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename] ");
|
fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename]");
|
||||||
fprintf(stderr, "[-s snaplen] [expression]\n");
|
fprintf(stderr, " [-i interface] [-s snaplen]\n");
|
||||||
|
fprintf(stderr, " [expression]\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +244,25 @@ set_snaplen(int snap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
reset_dump(void)
|
reset_dump(int nomove)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
ret = try_reset_dump(nomove);
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tries to (re)open log file, nomove flag is used with -x switch
|
||||||
|
* returns 0: success, 1: retry (log moved), -1: error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
try_reset_dump(int nomove)
|
||||||
{
|
{
|
||||||
struct pcap_file_header hdr;
|
struct pcap_file_header hdr;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -262,26 +284,26 @@ reset_dump(void)
|
|||||||
*/
|
*/
|
||||||
fd = priv_open_log();
|
fd = priv_open_log();
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return (1);
|
return (-1);
|
||||||
|
|
||||||
fp = fdopen(fd, "a+");
|
fp = fdopen(fd, "a+");
|
||||||
|
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
close(fd);
|
|
||||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||||
return (1);
|
close(fd);
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
if (fstat(fileno(fp), &st) == -1) {
|
if (fstat(fileno(fp), &st) == -1) {
|
||||||
fclose(fp);
|
|
||||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||||
return (1);
|
fclose(fp);
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set FILE unbuffered, we do our own buffering */
|
/* set FILE unbuffered, we do our own buffering */
|
||||||
if (setvbuf(fp, NULL, _IONBF, 0)) {
|
if (setvbuf(fp, NULL, _IONBF, 0)) {
|
||||||
fclose(fp);
|
|
||||||
logmsg(LOG_ERR, "Failed to set output buffers");
|
logmsg(LOG_ERR, "Failed to set output buffers");
|
||||||
return (1);
|
fclose(fp);
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||||
@ -289,11 +311,9 @@ reset_dump(void)
|
|||||||
if (st.st_size == 0) {
|
if (st.st_size == 0) {
|
||||||
if (snaplen != cur_snaplen) {
|
if (snaplen != cur_snaplen) {
|
||||||
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
||||||
if (set_snaplen(snaplen)) {
|
if (set_snaplen(snaplen))
|
||||||
fclose(fp);
|
|
||||||
logmsg(LOG_WARNING,
|
logmsg(LOG_WARNING,
|
||||||
"Failed, using old settings");
|
"Failed, using old settings");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hdr.magic = TCPDUMP_MAGIC;
|
hdr.magic = TCPDUMP_MAGIC;
|
||||||
hdr.version_major = PCAP_VERSION_MAJOR;
|
hdr.version_major = PCAP_VERSION_MAJOR;
|
||||||
@ -305,11 +325,15 @@ reset_dump(void)
|
|||||||
|
|
||||||
if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
|
if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return (1);
|
return (-1);
|
||||||
}
|
}
|
||||||
} else if (scan_dump(fp, st.st_size)) {
|
} else if (scan_dump(fp, st.st_size)) {
|
||||||
/* XXX move file and continue? */
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
if (nomove || priv_move_log()) {
|
||||||
|
logmsg(LOG_ERR,
|
||||||
|
"Invalid/incompatible log file, move it away");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +376,6 @@ scan_dump(FILE *fp, off_t size)
|
|||||||
hdr.version_minor != PCAP_VERSION_MINOR ||
|
hdr.version_minor != PCAP_VERSION_MINOR ||
|
||||||
hdr.linktype != hpcap->linktype ||
|
hdr.linktype != hpcap->linktype ||
|
||||||
hdr.snaplen > PFLOGD_MAXSNAPLEN) {
|
hdr.snaplen > PFLOGD_MAXSNAPLEN) {
|
||||||
logmsg(LOG_ERR, "Invalid/incompatible log file, move it away");
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +586,7 @@ main(int argc, char **argv)
|
|||||||
closefrom(STDERR_FILENO + 1);
|
closefrom(STDERR_FILENO + 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "Dxd:s:f:")) != -1) {
|
while ((ch = getopt(argc, argv, "Dxd:f:i:s:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'D':
|
case 'D':
|
||||||
Debug = 1;
|
Debug = 1;
|
||||||
@ -576,6 +599,9 @@ main(int argc, char **argv)
|
|||||||
case 'f':
|
case 'f':
|
||||||
filename = optarg;
|
filename = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
interface = optarg;
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
|
snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
|
||||||
&errstr);
|
&errstr);
|
||||||
@ -648,7 +674,7 @@ main(int argc, char **argv)
|
|||||||
bufpkt = 0;
|
bufpkt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reset_dump()) {
|
if (reset_dump(Xflag) < 0) {
|
||||||
if (Xflag)
|
if (Xflag)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
@ -674,7 +700,7 @@ main(int argc, char **argv)
|
|||||||
if (gotsig_close)
|
if (gotsig_close)
|
||||||
break;
|
break;
|
||||||
if (gotsig_hup) {
|
if (gotsig_hup) {
|
||||||
if (reset_dump()) {
|
if (reset_dump(0)) {
|
||||||
logmsg(LOG_ERR,
|
logmsg(LOG_ERR,
|
||||||
"Logging suspended: open error");
|
"Logging suspended: open error");
|
||||||
set_suspended(1);
|
set_suspended(1);
|
||||||
@ -685,6 +711,8 @@ main(int argc, char **argv)
|
|||||||
if (gotsig_alrm) {
|
if (gotsig_alrm) {
|
||||||
if (dpcap)
|
if (dpcap)
|
||||||
flush_buffer(dpcap);
|
flush_buffer(dpcap);
|
||||||
|
else
|
||||||
|
gotsig_hup = 1;
|
||||||
gotsig_alrm = 0;
|
gotsig_alrm = 0;
|
||||||
alarm(delay);
|
alarm(delay);
|
||||||
}
|
}
|
||||||
|
@ -1,122 +0,0 @@
|
|||||||
/* $FreeBSD$ */
|
|
||||||
/* $OpenBSD: pidfile.c,v 1.5 2002/05/26 09:29:02 deraadt Exp $ */
|
|
||||||
/* $NetBSD: pidfile.c,v 1.4 2001/02/19 22:43:42 cgd Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Jason R. Thorpe.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. 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.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the NetBSD
|
|
||||||
* Foundation, Inc. and its contributors.
|
|
||||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static const char rcsid[] = "$OpenBSD: pidfile.c,v 1.5 2002/05/26 09:29:02 deraadt Exp $";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <paths.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
#include "pidfile.h"
|
|
||||||
#else
|
|
||||||
#include <util.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char *pidfile_path;
|
|
||||||
static pid_t pidfile_pid;
|
|
||||||
|
|
||||||
static void pidfile_cleanup(void);
|
|
||||||
|
|
||||||
extern char *__progname;
|
|
||||||
|
|
||||||
int
|
|
||||||
pidfile(const char *basename)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
int save_errno;
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
if (basename == NULL)
|
|
||||||
basename = __progname;
|
|
||||||
|
|
||||||
if (pidfile_path != NULL) {
|
|
||||||
free(pidfile_path);
|
|
||||||
pidfile_path = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _PATH_VARRUN includes trailing / */
|
|
||||||
(void) asprintf(&pidfile_path, "%s%s.pid", _PATH_VARRUN, basename);
|
|
||||||
if (pidfile_path == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
if ((f = fopen(pidfile_path, "w")) == NULL) {
|
|
||||||
save_errno = errno;
|
|
||||||
free(pidfile_path);
|
|
||||||
pidfile_path = NULL;
|
|
||||||
errno = save_errno;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = getpid();
|
|
||||||
if (fprintf(f, "%ld\n", (long)pid) <= 0 || fclose(f) != 0) {
|
|
||||||
save_errno = errno;
|
|
||||||
(void) unlink(pidfile_path);
|
|
||||||
free(pidfile_path);
|
|
||||||
pidfile_path = NULL;
|
|
||||||
errno = save_errno;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pidfile_pid = pid;
|
|
||||||
if (atexit(pidfile_cleanup) < 0) {
|
|
||||||
save_errno = errno;
|
|
||||||
(void) unlink(pidfile_path);
|
|
||||||
free(pidfile_path);
|
|
||||||
pidfile_path = NULL;
|
|
||||||
pidfile_pid = 0;
|
|
||||||
errno = save_errno;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
pidfile_cleanup(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (pidfile_path != NULL && pidfile_pid == getpid())
|
|
||||||
(void) unlink(pidfile_path);
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
int pidfile(const char *);
|
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: privsep.c,v 1.13 2004/12/22 09:21:02 otto Exp $ */
|
/* $OpenBSD: privsep.c,v 1.16 2006/10/25 20:55:04 moritz Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003 Can Erkin Acar
|
* Copyright (c) 2003 Can Erkin Acar
|
||||||
@ -20,7 +20,7 @@
|
|||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
@ -30,19 +30,28 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#ifndef __FreeBSD__
|
||||||
|
#include <pcap.h>
|
||||||
|
#include <pcap-int.h>
|
||||||
|
#endif
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
/* XXX: pcap pollutes namespace with strlcpy if not present previously */
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
#include <pcap-int.h>
|
#include <pcap-int.h>
|
||||||
|
#endif
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "pflogd.h"
|
#include "pflogd.h"
|
||||||
|
|
||||||
enum cmd_types {
|
enum cmd_types {
|
||||||
PRIV_SET_SNAPLEN, /* set the snaplength */
|
PRIV_SET_SNAPLEN, /* set the snaplength */
|
||||||
|
PRIV_MOVE_LOG, /* move logfile away */
|
||||||
PRIV_OPEN_LOG /* open logfile for appending */
|
PRIV_OPEN_LOG /* open logfile for appending */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,10 +66,8 @@ static int may_read(int, void *, size_t);
|
|||||||
static void must_read(int, void *, size_t);
|
static void must_read(int, void *, size_t);
|
||||||
static void must_write(int, void *, size_t);
|
static void must_write(int, void *, size_t);
|
||||||
static int set_snaplen(int snap);
|
static int set_snaplen(int snap);
|
||||||
|
static int move_log(const char *name);
|
||||||
|
|
||||||
/* bpf filter expression common to parent and child */
|
|
||||||
extern char *filter;
|
|
||||||
extern char *errbuf;
|
|
||||||
extern char *filename;
|
extern char *filename;
|
||||||
extern pcap_t *hpcap;
|
extern pcap_t *hpcap;
|
||||||
|
|
||||||
@ -102,16 +109,12 @@ priv_init(void)
|
|||||||
err(1, "unable to chdir");
|
err(1, "unable to chdir");
|
||||||
|
|
||||||
gidset[0] = pw->pw_gid;
|
gidset[0] = pw->pw_gid;
|
||||||
|
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
|
||||||
|
err(1, "setresgid() failed");
|
||||||
if (setgroups(1, gidset) == -1)
|
if (setgroups(1, gidset) == -1)
|
||||||
err(1, "setgroups() failed");
|
err(1, "setgroups() failed");
|
||||||
if (setegid(pw->pw_gid) == -1)
|
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
|
||||||
err(1, "setegid() failed");
|
err(1, "setresuid() 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]);
|
close(socks[0]);
|
||||||
priv_fd = socks[1];
|
priv_fd = socks[1];
|
||||||
return 0;
|
return 0;
|
||||||
@ -165,6 +168,13 @@ priv_init(void)
|
|||||||
close(fd);
|
close(fd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PRIV_MOVE_LOG:
|
||||||
|
logmsg(LOG_DEBUG,
|
||||||
|
"[priv]: msg PRIV_MOVE_LOG received");
|
||||||
|
ret = move_log(filename);
|
||||||
|
must_write(socks[0], &ret, sizeof(int));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logmsg(LOG_ERR, "[priv]: unknown command %d", cmd);
|
logmsg(LOG_ERR, "[priv]: unknown command %d", cmd);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
@ -188,6 +198,47 @@ set_snaplen(int snap)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
move_log(const char *name)
|
||||||
|
{
|
||||||
|
char ren[PATH_MAX];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
len = snprintf(ren, sizeof(ren), "%s.bad.%08x",
|
||||||
|
name, arc4random());
|
||||||
|
if (len >= sizeof(ren)) {
|
||||||
|
logmsg(LOG_ERR, "[priv] new name too long");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lock destinanion */
|
||||||
|
fd = open(ren, O_CREAT|O_EXCL, 0);
|
||||||
|
if (fd >= 0) {
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* if file exists, try another name */
|
||||||
|
if (errno != EEXIST && errno != EINTR) {
|
||||||
|
logmsg(LOG_ERR, "[priv] failed to create new name: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rename(name, ren)) {
|
||||||
|
logmsg(LOG_ERR, "[priv] failed to rename %s to %s: %s",
|
||||||
|
name, ren, strerror(errno));
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
logmsg(LOG_NOTICE,
|
||||||
|
"[priv]: log file %s moved to %s", name, ren);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* send the snaplength to privileged process
|
* send the snaplength to privileged process
|
||||||
@ -229,6 +280,21 @@ priv_open_log(void)
|
|||||||
|
|
||||||
return (fd);
|
return (fd);
|
||||||
}
|
}
|
||||||
|
/* Move-away and reopen log-file */
|
||||||
|
int
|
||||||
|
priv_move_log(void)
|
||||||
|
{
|
||||||
|
int cmd, ret;
|
||||||
|
|
||||||
|
if (priv_fd < 0)
|
||||||
|
errx(1, "%s: called from privileged portion\n", __func__);
|
||||||
|
|
||||||
|
cmd = PRIV_MOVE_LOG;
|
||||||
|
must_write(priv_fd, &cmd, sizeof(int));
|
||||||
|
must_read(priv_fd, &ret, sizeof(int));
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
/* If priv parent gets a TERM or HUP, pass it through to child instead */
|
/* If priv parent gets a TERM or HUP, pass it through to child instead */
|
||||||
static void
|
static void
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* $OpenBSD: filter.c,v 1.1 2005/12/28 19:07:07 jcs Exp $ */
|
/* $OpenBSD: filter.c,v 1.1 2005/12/28 19:07:07 jcs Exp $ */
|
||||||
|
/* $FreeBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
||||||
@ -297,9 +298,15 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
|
|||||||
pfr.rule.quick = 1;
|
pfr.rule.quick = 1;
|
||||||
pfr.rule.log = rule_log;
|
pfr.rule.log = rule_log;
|
||||||
pfr.rule.keep_state = 1;
|
pfr.rule.keep_state = 1;
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
pfr.rule.flags = (proto == IPPROTO_TCP ? TH_SYN : 0);
|
||||||
|
pfr.rule.flagset = (proto == IPPROTO_TCP ?
|
||||||
|
(TH_SYN|TH_ACK|TH_FIN|TH_RST) : 0);
|
||||||
|
#else
|
||||||
pfr.rule.flags = (proto == IPPROTO_TCP ? TH_SYN : NULL);
|
pfr.rule.flags = (proto == IPPROTO_TCP ? TH_SYN : NULL);
|
||||||
pfr.rule.flagset = (proto == IPPROTO_TCP ?
|
pfr.rule.flagset = (proto == IPPROTO_TCP ?
|
||||||
(TH_SYN|TH_ACK|TH_FIN|TH_RST) : NULL);
|
(TH_SYN|TH_ACK|TH_FIN|TH_RST) : NULL);
|
||||||
|
#endif
|
||||||
pfr.rule.max_states = 1;
|
pfr.rule.max_states = 1;
|
||||||
if (qname != NULL)
|
if (qname != NULL)
|
||||||
strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
|
strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
|
||||||
|
Loading…
Reference in New Issue
Block a user