mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-28 13:22:48 +00:00
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$
|
||||
.\" $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
|
||||
.\" 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. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd March 28, 2006
|
||||
.Dt AUTHPF 8
|
||||
@ -230,8 +220,11 @@ it becomes unresponsive, or if arp or address spoofing is used to
|
||||
hijack the session.
|
||||
Note that TCP keepalives are not sufficient for
|
||||
this, since they are not secure.
|
||||
Also note that
|
||||
Also note that the various SSH tunnelling mechanisms,
|
||||
such as
|
||||
.Ar AllowTcpForwarding
|
||||
and
|
||||
.Ar PermitTunnel ,
|
||||
should be disabled for
|
||||
.Nm
|
||||
users to prevent them from circumventing restrictions imposed by the
|
||||
@ -429,8 +422,7 @@ TCP connections.
|
||||
external_if = "xl0"
|
||||
internal_if = "fxp0"
|
||||
|
||||
pass in log quick on $internal_if proto tcp from $user_ip to any \e
|
||||
keep state
|
||||
pass in log quick on $internal_if proto tcp from $user_ip to any
|
||||
pass in quick on $internal_if from $user_ip to any
|
||||
.Ed
|
||||
.Pp
|
||||
@ -445,16 +437,15 @@ ipsec_gw="10.2.3.4"
|
||||
|
||||
# rdr ftp for proxying by ftp-proxy(8)
|
||||
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
|
||||
# ipsec with the ipsec server.
|
||||
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
|
||||
port { 21, 22, 80, 443 }
|
||||
pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e
|
||||
keep state
|
||||
pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp
|
||||
pass in quick proto esp from $user_ip to $ipsec_gw
|
||||
.Ed
|
||||
.Pp
|
||||
@ -469,7 +460,7 @@ int_if = "fxp0"
|
||||
# nat and tag connections...
|
||||
nat on $ext_if from $user_ip to any tag $user_ip -> $ext_addr
|
||||
pass in quick on $int_if from $user_ip to any
|
||||
pass out log quick on $ext_if tagged $user_ip keep state
|
||||
pass out log quick on $ext_if tagged $user_ip
|
||||
.Ed
|
||||
.Pp
|
||||
With the above rules added by
|
||||
@ -495,7 +486,7 @@ lines will give SMTP and IMAP access to logged in users:
|
||||
.Bd -literal
|
||||
table <authpf_users> persist
|
||||
pass in on $ext_if proto tcp from <authpf_users> \e
|
||||
to port { smtp imap } keep state
|
||||
to port { smtp imap }
|
||||
.Ed
|
||||
.Pp
|
||||
It is also possible to use the "authpf_users"
|
||||
@ -522,6 +513,7 @@ rdr-anchor "authpf/*" from <authpf_users>
|
||||
.Xr pf 4 ,
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr fdescfs 5 ,
|
||||
.Xr securelevel 7 ,
|
||||
.Xr ftp-proxy 8
|
||||
.Sh HISTORY
|
||||
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
|
||||
* 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.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@ -56,15 +47,13 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
extern int symset(const char *, const char *, int);
|
||||
|
||||
static int read_config(FILE *);
|
||||
static void print_message(char *);
|
||||
static int allowed_luser(char *);
|
||||
static int check_luser(char *, char *);
|
||||
static int remove_stale_rulesets(void);
|
||||
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);
|
||||
|
||||
int dev; /* pf device */
|
||||
@ -73,7 +62,6 @@ char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
|
||||
char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
|
||||
|
||||
FILE *pidfp;
|
||||
char *infile; /* file name printed by yyerror() in parse.y */
|
||||
char luser[MAXLOGNAME]; /* username */
|
||||
char ipsrc[256]; /* ip as a string */
|
||||
char pidfile[MAXPATHLEN]; /* we save pid in this file. */
|
||||
@ -102,11 +90,16 @@ main(int argc, char *argv[])
|
||||
struct in6_addr ina;
|
||||
struct passwd *pw;
|
||||
char *cp;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
char *shell;
|
||||
login_cap_t *lc;
|
||||
|
||||
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) {
|
||||
syslog(LOG_ERR, "non-interactive session connection for authpf");
|
||||
@ -143,7 +136,6 @@ main(int argc, char *argv[])
|
||||
|
||||
uid = getuid();
|
||||
pw = getpwuid(uid);
|
||||
endpwent();
|
||||
if (pw == NULL) {
|
||||
syslog(LOG_ERR, "cannot find user for uid %u", uid);
|
||||
goto die;
|
||||
@ -256,6 +248,8 @@ main(int argc, char *argv[])
|
||||
if (++lockcnt > 10) {
|
||||
syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
|
||||
otherpid);
|
||||
fclose(pidfp);
|
||||
pidfp = NULL;
|
||||
goto dogdeath;
|
||||
}
|
||||
sleep(1);
|
||||
@ -265,12 +259,22 @@ main(int argc, char *argv[])
|
||||
* it's lock, giving us a chance to get it now
|
||||
*/
|
||||
fclose(pidfp);
|
||||
pidfp = NULL;
|
||||
} 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 */
|
||||
seteuid(getuid());
|
||||
setuid(getuid());
|
||||
|
||||
uid = 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);
|
||||
|
||||
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
|
||||
@ -278,8 +282,8 @@ main(int argc, char *argv[])
|
||||
do_death(0);
|
||||
}
|
||||
|
||||
if (config == NULL || read_config(config)) {
|
||||
syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE);
|
||||
if (read_config(config)) {
|
||||
syslog(LOG_ERR, "invalid config file %s", PATH_CONFFILE);
|
||||
do_death(0);
|
||||
}
|
||||
|
||||
@ -298,7 +302,7 @@ main(int argc, char *argv[])
|
||||
printf("Unable to modify filters\r\n");
|
||||
do_death(0);
|
||||
}
|
||||
if (change_table(1, luser, ipsrc) == -1) {
|
||||
if (change_table(1, ipsrc) == -1) {
|
||||
printf("Unable to modify table\r\n");
|
||||
change_filter(0, luser, ipsrc);
|
||||
do_death(0);
|
||||
@ -309,7 +313,7 @@ main(int argc, char *argv[])
|
||||
signal(SIGALRM, need_death);
|
||||
signal(SIGPIPE, need_death);
|
||||
signal(SIGHUP, need_death);
|
||||
signal(SIGSTOP, need_death);
|
||||
signal(SIGQUIT, need_death);
|
||||
signal(SIGTSTP, need_death);
|
||||
while (1) {
|
||||
printf("\r\nHello %s. ", luser);
|
||||
@ -559,9 +563,11 @@ check_luser(char *luserdir, char *luser)
|
||||
while (fputs(tmp, stdout) != EOF && !feof(f)) {
|
||||
if (fgets(tmp, sizeof(tmp), f) == NULL) {
|
||||
fflush(stdout);
|
||||
fclose(f);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
fflush(stdout);
|
||||
return (0);
|
||||
@ -645,6 +651,7 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
char *fdpath = NULL, *userstr = NULL, *ipstr = NULL;
|
||||
char *rsn = NULL, *fn = NULL;
|
||||
pid_t pid;
|
||||
gid_t gid;
|
||||
int s;
|
||||
|
||||
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()) {
|
||||
case -1:
|
||||
err(1, "fork failed");
|
||||
syslog(LOG_ERR, "fork failed");
|
||||
goto error;
|
||||
case 0:
|
||||
/* revoke group privs before exec */
|
||||
gid = getgid();
|
||||
if (setregid(gid, gid) == -1) {
|
||||
err(1, "setregid");
|
||||
}
|
||||
execvp(PATH_PFCTL, pargv);
|
||||
warn("exec of %s failed", PATH_PFCTL);
|
||||
_exit(1);
|
||||
@ -694,10 +707,8 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
/* parent */
|
||||
waitpid(pid, &s, 0);
|
||||
if (s != 0) {
|
||||
if (WIFEXITED(s)) {
|
||||
syslog(LOG_ERR, "pfctl exited abnormally");
|
||||
goto error;
|
||||
}
|
||||
syslog(LOG_ERR, "pfctl exited abnormally");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
@ -718,16 +729,10 @@ no_mem:
|
||||
syslog(LOG_ERR, "malloc failed");
|
||||
error:
|
||||
free(fdpath);
|
||||
fdpath = NULL;
|
||||
free(rsn);
|
||||
rsn = NULL;
|
||||
free(userstr);
|
||||
userstr = NULL;
|
||||
free(ipstr);
|
||||
ipstr = NULL;
|
||||
free(fn);
|
||||
fn = NULL;
|
||||
infile = NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -735,13 +740,14 @@ error:
|
||||
* Add/remove this IP from the "authpf_users" table.
|
||||
*/
|
||||
static int
|
||||
change_table(int add, const char *luser, const char *ipsrc)
|
||||
change_table(int add, const char *ipsrc)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
struct pfr_addr addr;
|
||||
|
||||
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_esize = sizeof(addr);
|
||||
io.pfrio_size = 1;
|
||||
@ -834,13 +840,11 @@ do_death(int active)
|
||||
|
||||
if (active) {
|
||||
change_filter(0, luser, ipsrc);
|
||||
change_table(0, luser, ipsrc);
|
||||
change_table(0, ipsrc);
|
||||
authpf_kill_states();
|
||||
remove_stale_rulesets();
|
||||
}
|
||||
if (pidfp)
|
||||
ftruncate(fileno(pidfp), 0);
|
||||
if (pidfile[0])
|
||||
if (pidfile[0] && (pidfp != NULL))
|
||||
if (unlink(pidfile) == -1)
|
||||
syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
|
||||
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
|
||||
.\" Obtuse Systems Corporation, All rights reserved.
|
||||
.\" Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY 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 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.
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 17, 2001
|
||||
.Dd November 28, 2004
|
||||
.Dt FTP-PROXY 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ftp-proxy
|
||||
.Nd Internet File Transfer Protocol proxy server
|
||||
.Nd Internet File Transfer Protocol proxy daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm ftp-proxy
|
||||
.Bk -words
|
||||
.Op Fl AnrVw
|
||||
.Op Fl 6Adrv
|
||||
.Op Fl a Ar address
|
||||
.Op Fl D Ar debuglevel
|
||||
.Op Fl g Ar group
|
||||
.Op Fl M Ar maxport
|
||||
.Op Fl m Ar minport
|
||||
.Op Fl R Ar address[:port]
|
||||
.Op Fl S Ar address
|
||||
.Op Fl b Ar address
|
||||
.Op Fl D Ar level
|
||||
.Op Fl m Ar maxsessions
|
||||
.Op Fl P Ar port
|
||||
.Op Fl p Ar port
|
||||
.Op Fl q Ar queue
|
||||
.Op Fl R Ar address
|
||||
.Op Fl t Ar timeout
|
||||
.Op Fl u Ar user
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
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
|
||||
and expects to have the FTP control connection as described in
|
||||
.Xr services 5
|
||||
redirected to it via a
|
||||
.Ar rdr
|
||||
command, after which the proxy connects to the server on behalf of
|
||||
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
|
||||
.Em rdr
|
||||
command.
|
||||
An example of how to do that is further down in this document.
|
||||
.Ar anchor
|
||||
facility for this.
|
||||
.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
|
||||
The options are as follows:
|
||||
.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
|
||||
Permit only anonymous FTP connections.
|
||||
The proxy will allow connections to log in to other sites as the user
|
||||
.Qq ftp
|
||||
or
|
||||
.Qq anonymous
|
||||
only.
|
||||
Any attempt to log in as another user will be blocked by the proxy.
|
||||
Only permit anonymous FTP connections.
|
||||
Either user "ftp" or user "anonymous" is allowed.
|
||||
.It Fl a Ar address
|
||||
Specify the local IP address to use in
|
||||
.Xr bind 2
|
||||
as the source for connections made by
|
||||
.Nm ftp-proxy
|
||||
when connecting to destination FTP servers.
|
||||
This may be necessary if the interface address of
|
||||
your default route is not reachable from the destinations
|
||||
.Nm
|
||||
is attempting connections to, or this address is different from the one
|
||||
connections are being NATed to.
|
||||
In the usual case this means that
|
||||
.Ar address
|
||||
should be a publicly visible IP address assigned to one of
|
||||
the interfaces on the machine running
|
||||
.Nm
|
||||
and should be the same address to which you are translating traffic
|
||||
if you are using the
|
||||
.Fl n
|
||||
option.
|
||||
.It Fl D Ar debuglevel
|
||||
Specify a debug level, where the proxy emits verbose debug output
|
||||
into
|
||||
.Xr syslogd 8
|
||||
at level
|
||||
.Dv LOG_DEBUG .
|
||||
Meaningful values of debuglevel are 0-3, where 0 is no debug output and
|
||||
3 is lots of debug output, the default being 0.
|
||||
.It Fl g Ar group
|
||||
Specify the named group to drop group privileges to, after doing
|
||||
.Xr pf 4
|
||||
lookups which require root.
|
||||
By default,
|
||||
.Nm
|
||||
uses the default group of the user it drops privilege to.
|
||||
.It Fl M Ar maxport
|
||||
Specify the upper end of the port range the proxy will use for the
|
||||
data connections it establishes.
|
||||
The default is
|
||||
.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.
|
||||
The proxy will use this as the source address for the control
|
||||
connection to a server.
|
||||
.It Fl b Ar address
|
||||
Address where the proxy will listen for redirected control connections.
|
||||
The default is 127.0.0.1, or ::1 in IPv6 mode.
|
||||
.It Fl D Ar level
|
||||
Debug level, ranging from 0 to 7.
|
||||
Higher is more verbose.
|
||||
The default is 5.
|
||||
(These levels correspond to the
|
||||
.Xr syslog 3
|
||||
levels.)
|
||||
.It Fl d
|
||||
Do not daemonize.
|
||||
The process will stay in the foreground, logging to standard error.
|
||||
.It Fl m Ar maxsessions
|
||||
Maximum number of concurrent FTP sessions.
|
||||
When the proxy reaches this limit, new connections are denied.
|
||||
The default is 100 sessions.
|
||||
The limit can be lowered to a minimum of 1, or raised to a maximum of 500.
|
||||
.It Fl P Ar port
|
||||
Fixed server port.
|
||||
Only used in combination with
|
||||
.Fl R .
|
||||
The default is port 21.
|
||||
.It Fl p Ar port
|
||||
Port where the proxy will listen for redirected connections.
|
||||
The default is port 8021.
|
||||
.It Fl q Ar queue
|
||||
Create rules with queue
|
||||
.Ar queue
|
||||
appended, so that data connections can be queued.
|
||||
.It Fl R Ar address
|
||||
Fixed server address, also known as reverse mode.
|
||||
The proxy will always connect to the same server, regardless of
|
||||
where the client wanted to connect to (before it was redirected).
|
||||
Use this option to proxy for a server behind NAT, or to forward all
|
||||
connections to another proxy.
|
||||
.It Fl r
|
||||
Use reverse host
|
||||
.Pq reverse DNS
|
||||
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.
|
||||
Rewrite sourceport to 20 in active mode to suit ancient clients that insist
|
||||
on this RFC property.
|
||||
.It Fl t Ar timeout
|
||||
Specifies a timeout, in seconds.
|
||||
The proxy will exit and close open connections if it sees no data
|
||||
for the duration of the timeout.
|
||||
The default is 0, which means the proxy will not time out.
|
||||
.It Fl u Ar user
|
||||
Specify the named user to drop privilege to, after doing
|
||||
.Xr pf 4
|
||||
lookups which require root privilege.
|
||||
By default,
|
||||
.Nm
|
||||
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.
|
||||
Number of seconds that the control connection can be idle, before the
|
||||
proxy will disconnect.
|
||||
The maximum is 86400 seconds, which is also the default.
|
||||
Do not set this too low, because the control connection is usually
|
||||
idle when large data transfers are taking place.
|
||||
.It Fl v
|
||||
Set the 'log' flag on pf rules committed by
|
||||
.Nm .
|
||||
Use twice to set the 'log-all' flag.
|
||||
The pf rules do not log by default.
|
||||
.El
|
||||
.Pp
|
||||
.Nm ftp-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
|
||||
.Sh CONFIGURATION
|
||||
To make use of the proxy,
|
||||
.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
|
||||
int_if = \&"xl0\&"
|
||||
rdr pass on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
|
||||
nat-anchor "ftp-proxy/*"
|
||||
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
|
||||
.Pp
|
||||
.Xr inetd 8
|
||||
must then be configured to run
|
||||
.Nm
|
||||
on the port from above using
|
||||
In the rule section:
|
||||
.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
|
||||
.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
|
||||
.Xr ftp 1 ,
|
||||
.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
|
||||
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
|
||||
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.
|
||||
.\"
|
||||
@ -186,6 +186,11 @@ using the
|
||||
obtained through a preceding
|
||||
.Dv DIOCGETRULES
|
||||
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"
|
||||
Get a
|
||||
.Va ticket
|
||||
@ -348,6 +353,7 @@ struct pf_status {
|
||||
u_int32_t debug;
|
||||
u_int32_t hostid;
|
||||
char ifname[IFNAMSIZ];
|
||||
u_int8_t pf_chksum[MD5_DIGEST_LENGTH];
|
||||
};
|
||||
.Ed
|
||||
.It Dv DIOCCLRSTATUS
|
||||
@ -391,19 +397,14 @@ struct pfioc_states {
|
||||
.Pp
|
||||
If
|
||||
.Va ps_len
|
||||
is zero, all states will be gathered into
|
||||
.Va pf_states
|
||||
and
|
||||
is non-zero on entry, as many states as possible that can fit into this
|
||||
size will be copied into the supplied buffer
|
||||
.Va ps_states .
|
||||
On exit,
|
||||
.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 ) .
|
||||
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"
|
||||
Add or remove the
|
||||
.Va rule
|
||||
@ -485,7 +486,8 @@ struct pfioc_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
|
||||
.It Dv DIOCGETLIMIT Fa "struct pfioc_limit *pl"
|
||||
Get the hard
|
||||
@ -523,10 +525,15 @@ struct pfioc_table {
|
||||
.It Dv DIOCRADDTABLES Fa "struct pfioc_table *io"
|
||||
Create one or more tables.
|
||||
On entry,
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains a table of
|
||||
.Vt pfr_table
|
||||
structures.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_table
|
||||
containing at least
|
||||
.Vt pfrio_size
|
||||
elements.
|
||||
.Vt pfrio_esize
|
||||
must be the size of
|
||||
.Vt struct pfr_table .
|
||||
On exit,
|
||||
.Va pfrio_nadd
|
||||
contains the number of tables effectively created.
|
||||
@ -541,12 +548,17 @@ struct pfr_table {
|
||||
.It Dv DIOCRDELTABLES Fa "struct pfioc_table *io"
|
||||
Delete one or more tables.
|
||||
On entry,
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains a table of
|
||||
.Vt pfr_table
|
||||
structures.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_table
|
||||
containing at least
|
||||
.Vt pfrio_size
|
||||
elements.
|
||||
.Vt pfrio_esize
|
||||
must be the size of
|
||||
.Vt struct pfr_table .
|
||||
On exit,
|
||||
.Va pfrio_nadd
|
||||
.Va pfrio_ndel
|
||||
contains the number of tables effectively deleted.
|
||||
.It Dv DIOCRGETTABLES Fa "struct pfioc_table *io"
|
||||
Get the list of all tables.
|
||||
@ -585,10 +597,15 @@ struct pfr_tstats {
|
||||
.It Dv DIOCRCLRTSTATS Fa "struct pfioc_table *io"
|
||||
Clear the statistics of one or more tables.
|
||||
On entry,
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains a table of
|
||||
.Vt pfr_table
|
||||
structures.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_table
|
||||
containing at least
|
||||
.Vt pfrio_size
|
||||
elements.
|
||||
.Vt pfrio_esize
|
||||
must be the size of
|
||||
.Vt struct pfr_table .
|
||||
On exit,
|
||||
.Va pfrio_nzero
|
||||
contains the number of tables effectively cleared.
|
||||
@ -605,10 +622,15 @@ Add one or more addresses to a table.
|
||||
On entry,
|
||||
.Va pfrio_table
|
||||
contains the table ID and
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains the list of
|
||||
.Vt pfr_addr
|
||||
structures to add.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_addr
|
||||
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,
|
||||
.Va pfrio_nadd
|
||||
contains the number of addresses effectively added.
|
||||
@ -631,10 +653,15 @@ Delete one or more addresses from a table.
|
||||
On entry,
|
||||
.Va pfrio_table
|
||||
contains the table ID and
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains the list of
|
||||
.Vt pfr_addr
|
||||
structures to delete.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_addr
|
||||
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,
|
||||
.Va pfrio_ndel
|
||||
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,
|
||||
.Va pfrio_table
|
||||
contains the table ID and
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains the new list of
|
||||
.Vt pfr_addr
|
||||
structures.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_addr
|
||||
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
|
||||
.Va pfrio_size2
|
||||
is non-zero,
|
||||
@ -703,10 +735,15 @@ Clear the statistics of one or more addresses.
|
||||
On entry,
|
||||
.Va pfrio_table
|
||||
contains the table ID and
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains a table of
|
||||
.Vt pfr_addr
|
||||
structures to clear.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_addr
|
||||
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,
|
||||
.Va pfrio_nzero
|
||||
contains the number of addresses effectively cleared.
|
||||
@ -715,13 +752,18 @@ Test if the given addresses match a table.
|
||||
On entry,
|
||||
.Va pfrio_table
|
||||
contains the table ID and
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains a table of
|
||||
.Vt pfr_addr
|
||||
structures to test.
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_addr
|
||||
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
|
||||
.Vt pfr_addr
|
||||
table by setting the
|
||||
array by setting the
|
||||
.Va pfra_fback
|
||||
member appropriately.
|
||||
.It Dv DIOCRSETTFLAGS Fa "struct pfioc_table *io"
|
||||
@ -731,14 +773,19 @@ or
|
||||
.Dv PFR_TFLAG_PERSIST
|
||||
flags of a table.
|
||||
On entry,
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains a table of
|
||||
.Vt pfr_table
|
||||
structures, and
|
||||
.Va pfrio_buffer
|
||||
must point to an array of
|
||||
.Vt struct pfr_table
|
||||
containing at least
|
||||
.Vt pfrio_size
|
||||
elements.
|
||||
.Va pfrio_esize
|
||||
must be the size of
|
||||
.Vt struct pfr_table .
|
||||
.Va pfrio_setflag
|
||||
contains the flags to add, while
|
||||
must contain the flags to add, while
|
||||
.Va pfrio_clrflag
|
||||
contains the flags to remove.
|
||||
must contain the flags to remove.
|
||||
On exit,
|
||||
.Va pfrio_nchange
|
||||
and
|
||||
@ -753,7 +800,7 @@ On entry,
|
||||
.Va pfrio_table
|
||||
contains the table ID and
|
||||
.Va pfrio_buffer[pfrio_size]
|
||||
contains the list of
|
||||
contains an array of
|
||||
.Vt pfr_addr
|
||||
structures to put in the table.
|
||||
A valid ticket must also be supplied to
|
||||
@ -955,10 +1002,6 @@ struct pfioc_iface {
|
||||
int pfiio_nzero;
|
||||
int pfiio_flags;
|
||||
};
|
||||
|
||||
#define PFI_FLAG_GROUP 0x0001 /* gets groups of interfaces */
|
||||
#define PFI_FLAG_INSTANCE 0x0002 /* gets single interfaces */
|
||||
#define PFI_FLAG_ALLMASK 0x0003
|
||||
.Ed
|
||||
.Pp
|
||||
If not empty,
|
||||
@ -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.
|
||||
On entry,
|
||||
.Va pfiio_size
|
||||
represents the number of
|
||||
.Va pfi_if
|
||||
contains the number of
|
||||
.Vt pfi_kif
|
||||
entries that can fit into the buffer.
|
||||
The kernel will replace this value by the real number of entries it wants
|
||||
to return.
|
||||
.Va pfiio_esize
|
||||
should be set to
|
||||
.Li sizeof(struct pfi_if) .
|
||||
.Va pfiio_flags
|
||||
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.
|
||||
.Li sizeof(struct pfi_kif) .
|
||||
.Pp
|
||||
The data is returned in the
|
||||
.Vt pfi_if
|
||||
.Vt pfi_kif
|
||||
structure described below:
|
||||
.Bd -literal
|
||||
struct pfi_if {
|
||||
char pfif_name[IFNAMSIZ];
|
||||
u_int64_t pfif_packets[2][2][2];
|
||||
u_int64_t pfif_bytes[2][2][2];
|
||||
u_int64_t pfif_addcnt;
|
||||
u_int64_t pfif_delcnt;
|
||||
long pfif_tzero;
|
||||
int pfif_states;
|
||||
int pfif_rules;
|
||||
int pfif_flags;
|
||||
struct pfi_kif {
|
||||
RB_ENTRY(pfi_kif) pfik_tree;
|
||||
char pfik_name[IFNAMSIZ];
|
||||
u_int64_t pfik_packets[2][2][2];
|
||||
u_int64_t pfik_bytes[2][2][2];
|
||||
u_int32_t pfik_tzero;
|
||||
int pfik_flags;
|
||||
struct pf_state_tree_lan_ext pfik_lan_ext;
|
||||
struct pf_state_tree_ext_gwy pfik_ext_gwy;
|
||||
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
|
||||
.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"
|
||||
Set the user setable flags (described below) of the pf internal interface
|
||||
description.
|
||||
Set the user setable flags (described above) of the
|
||||
.Nm
|
||||
internal interface description.
|
||||
The filtering process is the same as for
|
||||
.Dv DIOCIGETIFACES .
|
||||
.Bd -literal
|
||||
#define PFI_IFLAG_SKIP 0x0100 /* skip interface */
|
||||
#define PFI_IFLAG_SETABLE_MASK 0x0100 /* mask */
|
||||
#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */
|
||||
.Ed
|
||||
.It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io"
|
||||
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>
|
||||
.\"
|
||||
@ -207,37 +207,15 @@ The
|
||||
output of
|
||||
.Bd -literal
|
||||
# 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
|
||||
(ttl 64, id 11315)
|
||||
(ttl 64, id 11315, len 44)
|
||||
.Ed
|
||||
.Pp
|
||||
almost translates into the following fingerprint
|
||||
.Bd -literal
|
||||
57344:64:1:44:M1460: exampleOS:1.0::exampleOS 1.0
|
||||
.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
|
||||
.Xr tcpdump 1 ,
|
||||
.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
|
||||
.\" All rights reserved.
|
||||
@ -47,6 +47,14 @@ on the
|
||||
interface, or stored to disk using
|
||||
.Xr pflogd 8 .
|
||||
.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
|
||||
with it of length
|
||||
.Dv PFLOG_HDRLEN .
|
||||
@ -65,14 +73,22 @@ struct pfloghdr {
|
||||
char ruleset[PF_RULESET_NAME_SIZE];
|
||||
u_int32_t rulenr;
|
||||
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 pad[3];
|
||||
};
|
||||
.Ed
|
||||
.Sh EXAMPLES
|
||||
Create a
|
||||
.Nm
|
||||
interface
|
||||
and monitor all packets logged on it:
|
||||
.Bd -literal -offset indent
|
||||
# ifconfig pflog0 up
|
||||
# tcpdump -n -e -ttt -i pflog0
|
||||
# ifconfig pflog1 up
|
||||
# tcpdump -n -e -ttt -i pflog1
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.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) 2003-2004 Ryan McBride
|
||||
@ -209,7 +209,7 @@ The following should be added to the top of
|
||||
.Pa /etc/pf.conf :
|
||||
.Bd -literal -offset indent
|
||||
pass quick on { sis2 } proto pfsync
|
||||
pass quick on { sis0 sis1 } proto carp keep state
|
||||
pass on { sis0 sis1 } proto carp
|
||||
.Ed
|
||||
.Pp
|
||||
If it is preferable that one firewall handle the traffic,
|
||||
@ -248,6 +248,9 @@ yet.
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr protocols 5 ,
|
||||
.Xr rc.conf 5
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr ifstated 8 ,
|
||||
.Xr tcpdump 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.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
|
||||
@ -100,6 +100,9 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
||||
case PF_ADDR_NOROUTE:
|
||||
printf("no-route");
|
||||
return;
|
||||
case PF_ADDR_URPFFAILED:
|
||||
printf("urpf-failed");
|
||||
return;
|
||||
case PF_ADDR_RTLABEL:
|
||||
printf("route \"%s\"", addr->v.rtlabelname);
|
||||
return;
|
||||
@ -278,8 +281,15 @@ print_state(struct pf_state *s, int opts)
|
||||
min = s->expire % 60;
|
||||
s->expire /= 60;
|
||||
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]);
|
||||
#endif
|
||||
if (s->anchor.nr != -1)
|
||||
printf(", anchor %u", s->anchor.nr);
|
||||
if (s->rule.nr != -1)
|
||||
@ -291,13 +301,13 @@ print_state(struct pf_state *s, int opts)
|
||||
printf("\n");
|
||||
}
|
||||
if (opts & PF_OPT_VERBOSE2) {
|
||||
printf(" id: %016llx creatorid: %08x%s\n",
|
||||
#ifdef __FreeBSD__
|
||||
printf(" id: %016llx creatorid: %08x\n",
|
||||
(long long)be64toh(s->id), ntohl(s->creatorid));
|
||||
(unsigned long long)be64toh(s->id), ntohl(s->creatorid),
|
||||
#else
|
||||
printf(" id: %016llx creatorid: %08x\n",
|
||||
betoh64(s->id), ntohl(s->creatorid));
|
||||
betoh64(s->id), ntohl(s->creatorid),
|
||||
#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.
|
||||
.\"
|
||||
@ -35,23 +35,23 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm pfctl
|
||||
.Bk -words
|
||||
.Op Fl AdeghmNnOoqRrvz
|
||||
.Op Fl AdeghmNnOqRrvz
|
||||
.Op Fl a Ar anchor
|
||||
.Xo
|
||||
.Oo Fl D
|
||||
.Ar macro Ns = Ns Ar value Oc
|
||||
.Xc
|
||||
.Oo Fl D Ar macro Ns =
|
||||
.Ar value Oc
|
||||
.Op Fl F Ar modifier
|
||||
.Op Fl f Ar file
|
||||
.Op Fl i Ar interface
|
||||
.Op Fl k Ar host
|
||||
.Op Fl K Ar host | network
|
||||
.Op Fl k Ar host | network
|
||||
.Op Fl o Op Ar level
|
||||
.Op Fl p Ar device
|
||||
.Op Fl s Ar modifier
|
||||
.Oo Xo
|
||||
.Oo
|
||||
.Fl t Ar table
|
||||
.Fl T Ar command
|
||||
.Op Ar address ... Oc
|
||||
.Xc
|
||||
.Op Ar address ...
|
||||
.Oc
|
||||
.Op Fl x Ar level
|
||||
.Ek
|
||||
.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
|
||||
.Fl s
|
||||
flag below) inside the anchor
|
||||
.Li authpf/smith(1234) ,
|
||||
which would have been created for user smith by
|
||||
.Dq authpf/smith(1234) ,
|
||||
which would have been created for user
|
||||
.Dq smith
|
||||
by
|
||||
.Xr authpf 8 ,
|
||||
PID 1234:
|
||||
.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
|
||||
ruleset and in an anchor, but this is often bad design and a warning will be
|
||||
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
|
||||
Define
|
||||
.Ar macro
|
||||
@ -217,29 +240,49 @@ Help.
|
||||
.It Fl i Ar interface
|
||||
Restrict the operation to the given
|
||||
.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
|
||||
.Ar host .
|
||||
.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 state entries
|
||||
from the first
|
||||
.Ar host
|
||||
to the second
|
||||
.Ar host .
|
||||
from the first host/network to the second.
|
||||
For example, to kill all of the state entries originating from
|
||||
.Li host :
|
||||
.Bd -literal -offset indent
|
||||
# pfctl -k host
|
||||
.Ed
|
||||
.Dq host :
|
||||
.Pp
|
||||
.Dl # pfctl -k host
|
||||
.Pp
|
||||
To kill all of the state entries from
|
||||
.Li host1
|
||||
.Dq host1
|
||||
to
|
||||
.Li host2 :
|
||||
.Bd -literal -offset indent
|
||||
# pfctl -k host1 -k host2
|
||||
.Ed
|
||||
.Dq host2 :
|
||||
.Pp
|
||||
.Dl # pfctl -k host1 -k host2
|
||||
.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
|
||||
Merge in explicitly given options without resetting those
|
||||
which are omitted.
|
||||
@ -255,11 +298,22 @@ Do not actually load rules, just parse them.
|
||||
.It Fl O
|
||||
Load only the options present in the rule file.
|
||||
Other rules and options are ignored.
|
||||
.It Fl o
|
||||
Enable the ruleset optimizer.
|
||||
.It Fl o Op Ar level
|
||||
Control the ruleset optimizer.
|
||||
The ruleset optimizer attempts to improve rulesets by removing rule
|
||||
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
|
||||
.Bl -enum -compact
|
||||
.It
|
||||
@ -272,10 +326,10 @@ combine multiple rules into a table when advantageous
|
||||
re-order the rules to improve evaluation performance
|
||||
.El
|
||||
.Pp
|
||||
A second
|
||||
.Fl o
|
||||
may be specified to use the currently loaded ruleset as a feedback profile
|
||||
to tailor the optimization of the
|
||||
If
|
||||
.Cm profile
|
||||
is specified, the currently loaded ruleset will be examined as a feedback
|
||||
profile to tailor the optimization of the
|
||||
.Ar quick
|
||||
rules to the actual network behavior.
|
||||
.Pp
|
||||
@ -288,6 +342,14 @@ the ruleset optimizer should not be used or a
|
||||
.Ar label
|
||||
field should be added to all of the accounting rules to act as optimization
|
||||
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
|
||||
Use the device file
|
||||
.Ar device
|
||||
@ -352,7 +414,8 @@ When used together with
|
||||
.Fl v ,
|
||||
source tracking statistics are also shown.
|
||||
.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.
|
||||
.It Fl s Cm timeouts
|
||||
Show the current global timeouts.
|
||||
@ -364,8 +427,11 @@ Show the list of tables.
|
||||
Show the list of operating system fingerprints.
|
||||
.It Fl s Cm Interfaces
|
||||
Show the list of interfaces and interface drivers available to PF.
|
||||
When used together with a double
|
||||
When used together with
|
||||
.Fl v ,
|
||||
it additionally lists which interfaces have skip rules activated.
|
||||
When used together with
|
||||
.Fl vv ,
|
||||
interface statistics are also shown.
|
||||
.Fl i
|
||||
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.
|
||||
.It Fl T Cm delete
|
||||
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
|
||||
Replace the addresses of the table.
|
||||
Automatically create a nonexisting table.
|
||||
@ -465,7 +538,7 @@ The following commands configure the firewall and send 10 pings to the FTP
|
||||
server:
|
||||
.Bd -literal -offset indent
|
||||
# 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
|
||||
.Ed
|
||||
.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
|
||||
@ -34,6 +34,8 @@
|
||||
#ifndef _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,
|
||||
PFRB_IFACES, PFRB_TRANS, PFRB_MAX };
|
||||
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 (*)(struct pfr_buffer *, char *, 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);
|
||||
|
||||
void pfctl_print_title(char *);
|
||||
@ -111,7 +113,6 @@ extern int loadopt;
|
||||
|
||||
int check_commit_altq(int, int);
|
||||
void pfaltq_store(struct pf_altq *);
|
||||
void pfaltq_free(struct pf_altq *);
|
||||
struct pf_altq *pfaltq_lookup(const char *);
|
||||
char *rate2str(double);
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.86 2005/02/28 14:04:51 henning Exp $ */
|
||||
/* add: $OpenBSD: pfctl_altq.c,v 1.91 2006/11/28 00:08:50 henning Exp $ */
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.91 2006/11/28 00:08:50 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002
|
||||
@ -101,21 +100,6 @@ pfaltq_store(struct pf_altq *a)
|
||||
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 *
|
||||
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)
|
||||
{
|
||||
if (a->qname[0] != 0) {
|
||||
print_queue(a, level, bw, 0, qopts);
|
||||
print_queue(a, level, bw, 1, qopts);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -250,8 +234,8 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
||||
#else
|
||||
if ((rate = getifspeed(pa->ifname)) == 0) {
|
||||
#endif
|
||||
fprintf(stderr, "cannot determine interface bandwidth "
|
||||
"for %s, specify an absolute bandwidth\n",
|
||||
fprintf(stderr, "interface %s does not know its bandwidth, "
|
||||
"please specify an absolute bandwidth\n",
|
||||
pa->ifname);
|
||||
errors++;
|
||||
} 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;
|
||||
else
|
||||
maxidle = ptime * maxidle_s;
|
||||
if (minburst)
|
||||
offtime = cptime * (1.0 + 1.0/(1.0 - g) * (1.0 - gtom) / gtom);
|
||||
else
|
||||
offtime = cptime;
|
||||
offtime = cptime * (1.0 + 1.0/(1.0 - g) * (1.0 - gtom) / gtom);
|
||||
minidle = -((double)opts->maxpktsize * (double)nsPerByte);
|
||||
|
||||
/* 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>
|
||||
@ -112,6 +112,10 @@ struct pf_rule_field {
|
||||
PF_RULE_FIELD(prob, BARRIER),
|
||||
PF_RULE_FIELD(max_states, 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.
|
||||
@ -123,10 +127,18 @@ struct pf_rule_field {
|
||||
PF_RULE_FIELD(tagname, BREAK),
|
||||
PF_RULE_FIELD(keep_state, BREAK),
|
||||
PF_RULE_FIELD(qname, BREAK),
|
||||
PF_RULE_FIELD(pqname, BREAK),
|
||||
PF_RULE_FIELD(rt, BREAK),
|
||||
PF_RULE_FIELD(allow_opts, BREAK),
|
||||
PF_RULE_FIELD(rule_flag, 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
|
||||
@ -140,7 +152,7 @@ struct pf_rule_field {
|
||||
*/
|
||||
PF_RULE_FIELD(af, 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_tagname, NOMERGE),
|
||||
PF_RULE_FIELD(os_fingerprint, NOMERGE),
|
||||
@ -173,7 +185,6 @@ struct pf_rule_field {
|
||||
PF_RULE_FIELD(packets, DC),
|
||||
PF_RULE_FIELD(bytes, DC),
|
||||
PF_RULE_FIELD(kif, DC),
|
||||
PF_RULE_FIELD(anchor, DC),
|
||||
PF_RULE_FIELD(states, DC),
|
||||
PF_RULE_FIELD(src_nodes, DC),
|
||||
PF_RULE_FIELD(nr, DC),
|
||||
@ -182,6 +193,9 @@ struct pf_rule_field {
|
||||
PF_RULE_FIELD(pqid, DC),
|
||||
PF_RULE_FIELD(anchor_relative, 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 */
|
||||
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 *,
|
||||
struct superblocks *);
|
||||
void exclude_supersets(struct pf_rule *, struct pf_rule *);
|
||||
int interface_group(const char *);
|
||||
int load_feedback_profile(struct pfctl *, struct superblocks *);
|
||||
int optimize_superblock(struct pfctl *, struct superblock *);
|
||||
int pf_opt_create_table(struct pfctl *, struct pf_opt_tbl *);
|
||||
@ -243,25 +258,52 @@ int table_identifier;
|
||||
|
||||
|
||||
int
|
||||
pfctl_optimize_rules(struct pfctl *pf)
|
||||
pfctl_optimize_ruleset(struct pfctl *pf, struct pf_ruleset *rs)
|
||||
{
|
||||
struct superblocks superblocks;
|
||||
struct pf_opt_queue opt_queue;
|
||||
struct superblock *block;
|
||||
struct pf_opt_rule *por;
|
||||
int nr;
|
||||
struct pf_rule *r;
|
||||
struct pf_rulequeue *old_rules;
|
||||
|
||||
DEBUG("optimizing ruleset");
|
||||
memset(&table_buffer, 0, sizeof(table_buffer));
|
||||
skip_init();
|
||||
TAILQ_INIT(&opt_queue);
|
||||
|
||||
if (TAILQ_FIRST(&pf->opt_queue))
|
||||
nr = TAILQ_FIRST(&pf->opt_queue)->por_rule.nr;
|
||||
old_rules = rs->rules[PF_RULESET_FILTER].active.ptr;
|
||||
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);
|
||||
if (construct_superblocks(pf, &pf->opt_queue, &superblocks))
|
||||
if (construct_superblocks(pf, &opt_queue, &superblocks))
|
||||
goto error;
|
||||
|
||||
if (pf->opts & PF_OPT_OPTIMIZE_PROFILE) {
|
||||
if (pf->optimize & PF_OPTIMIZE_PROFILE) {
|
||||
if (load_feedback_profile(pf, &superblocks))
|
||||
goto error;
|
||||
}
|
||||
@ -271,24 +313,21 @@ pfctl_optimize_rules(struct pfctl *pf)
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
rs->anchor->refcnt = 0;
|
||||
while ((block = TAILQ_FIRST(&superblocks))) {
|
||||
TAILQ_REMOVE(&superblocks, block, sb_entry);
|
||||
|
||||
while ((por = TAILQ_FIRST(&block->sb_rules))) {
|
||||
TAILQ_REMOVE(&block->sb_rules, por, por_entry);
|
||||
por->por_rule.nr = nr++;
|
||||
if (pfctl_add_rule(pf, &por->por_rule,
|
||||
por->por_anchor)) {
|
||||
free(por);
|
||||
goto error;
|
||||
}
|
||||
por->por_rule.nr = rs->anchor->refcnt++;
|
||||
if ((r = calloc(1, sizeof(*r))) == NULL)
|
||||
err(1, "calloc");
|
||||
memcpy(r, &por->por_rule, sizeof(*r));
|
||||
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(block);
|
||||
@ -297,8 +336,8 @@ pfctl_optimize_rules(struct pfctl *pf)
|
||||
return (0);
|
||||
|
||||
error:
|
||||
while ((por = TAILQ_FIRST(&pf->opt_queue))) {
|
||||
TAILQ_REMOVE(&pf->opt_queue, por, por_entry);
|
||||
while ((por = TAILQ_FIRST(&opt_queue))) {
|
||||
TAILQ_REMOVE(&opt_queue, por, por_entry);
|
||||
if (por->por_src_tbl) {
|
||||
pfr_buf_clear(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");
|
||||
TAILQ_FOREACH(por, &block->sb_rules, por_entry) {
|
||||
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 */
|
||||
|
||||
@ -376,7 +416,7 @@ optimize_superblock(struct pfctl *pf, struct superblock *block)
|
||||
return (1);
|
||||
if (combine_rules(pf, block))
|
||||
return (1);
|
||||
if ((pf->opts & PF_OPT_OPTIMIZE_PROFILE) &&
|
||||
if ((pf->optimize & PF_OPTIMIZE_PROFILE) &&
|
||||
TAILQ_FIRST(&block->sb_rules)->por_rule.quick &&
|
||||
block->sb_profiled_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) {
|
||||
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) {
|
||||
if (por2->por_profile_count)
|
||||
continue;
|
||||
comparable_rule(&b, &por2->por_rule, DC);
|
||||
if (memcmp(&a, &b, sizeof(a)) == 0) {
|
||||
por2->por_profile_count =
|
||||
por1->por_rule.packets;
|
||||
por1->por_rule.packets[0] +
|
||||
por1->por_rule.packets[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -858,6 +900,7 @@ load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks)
|
||||
|
||||
DEBUG("Loading %d active rules for a feedback profile", mnr);
|
||||
for (nr = 0; nr < mnr; ++nr) {
|
||||
struct pf_ruleset *rs;
|
||||
if ((por = calloc(1, sizeof(*por))) == NULL) {
|
||||
warn("calloc");
|
||||
return (1);
|
||||
@ -868,8 +911,8 @@ load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks)
|
||||
return (1);
|
||||
}
|
||||
memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule));
|
||||
strlcpy(por->por_anchor, pr.anchor_call,
|
||||
sizeof(por->por_anchor));
|
||||
rs = pf_find_or_create_ruleset(pr.anchor_call);
|
||||
por->por_rule.anchor = rs->anchor;
|
||||
if (TAILQ_EMPTY(&por->por_rule.rpool.list))
|
||||
memset(&por->por_rule.rpool, 0,
|
||||
sizeof(por->por_rule.rpool));
|
||||
@ -1052,6 +1095,7 @@ skip_cmp_dst_addr(struct pf_rule *a, struct pf_rule *b)
|
||||
return (1);
|
||||
return (0);
|
||||
case PF_ADDR_NOROUTE:
|
||||
case PF_ADDR_URPFFAILED:
|
||||
return (0);
|
||||
case PF_ADDR_TABLE:
|
||||
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 (0);
|
||||
case PF_ADDR_NOROUTE:
|
||||
case PF_ADDR_URPFFAILED:
|
||||
return (0);
|
||||
case PF_ADDR_TABLE:
|
||||
return (strcmp(a->src.addr.v.tblname, b->src.addr.v.tblname));
|
||||
@ -1274,8 +1319,8 @@ again:
|
||||
tablenum++;
|
||||
|
||||
|
||||
if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1, pf->anchor,
|
||||
tbl->pt_buf, pf->tticket)) {
|
||||
if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1,
|
||||
pf->anchor->name, tbl->pt_buf, pf->anchor->ruleset.tticket)) {
|
||||
warn("failed to create table %s", tbl->pt_name);
|
||||
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 */
|
||||
if (por->por_anchor[0] != '\0' ||
|
||||
(por->por_rule.rule_flag & PFRULE_RULESRCTRACK))
|
||||
/* per-rule src-track is also a hard break */
|
||||
if (por->por_rule.rule_flag & PFRULE_RULESRCTRACK)
|
||||
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(&b, &por->por_rule, NOMERGE);
|
||||
if (strcmp(TAILQ_FIRST(&block->sb_rules)->por_anchor,
|
||||
por->por_anchor) == 0 && memcmp(&a, &b, sizeof(a)) == 0)
|
||||
if (memcmp(&a, &b, sizeof(a)) == 0)
|
||||
return (1);
|
||||
|
||||
#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()
|
||||
*/
|
||||
|
@ -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
|
||||
@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pfctl_parser.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);
|
||||
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_v4(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
|
||||
print_status(struct pf_status *s, int opts)
|
||||
{
|
||||
char statline[80], *running;
|
||||
time_t runtime;
|
||||
int i;
|
||||
char statline[80], *running;
|
||||
time_t runtime;
|
||||
int i;
|
||||
char buf[PF_MD5_DIGEST_LENGTH * 2 + 1];
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
|
||||
runtime = time(NULL) - s->since;
|
||||
running = s->running ? "Enabled" : "Disabled";
|
||||
@ -519,7 +523,18 @@ print_status(struct pf_status *s, int opts)
|
||||
printf("%15s\n\n", "Debug: Loud");
|
||||
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) {
|
||||
printf("Interface Stats for %-16s %5s %16s\n",
|
||||
s->ifname, "IPv4", "IPv6");
|
||||
@ -631,7 +646,14 @@ print_src_node(struct pf_src_node *sn, int opts)
|
||||
printf(", expires in %.2u:%.2u:%.2u",
|
||||
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) {
|
||||
case PF_NAT:
|
||||
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);
|
||||
if (r->action > PF_NORDR)
|
||||
printf("action(%d)", r->action);
|
||||
else if (anchor_call[0])
|
||||
printf("%s \"%s\"", anchortypes[r->action],
|
||||
anchor_call);
|
||||
else {
|
||||
else if (anchor_call[0]) {
|
||||
if (anchor_call[0] == '_') {
|
||||
printf("%s", anchortypes[r->action]);
|
||||
} else
|
||||
printf("%s \"%s\"", anchortypes[r->action],
|
||||
anchor_call);
|
||||
} else {
|
||||
printf("%s", actiontypes[r->action]);
|
||||
if (r->natpass)
|
||||
printf(" pass");
|
||||
@ -722,10 +747,22 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
printf(" in");
|
||||
else if (r->direction == PF_OUT)
|
||||
printf(" out");
|
||||
if (r->log == 1)
|
||||
if (r->log) {
|
||||
printf(" log");
|
||||
else if (r->log == 2)
|
||||
printf(" log-all");
|
||||
if (r->log & ~PF_LOG || r->logif) {
|
||||
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)
|
||||
printf(" quick");
|
||||
if (r->ifname[0]) {
|
||||
@ -775,7 +812,11 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
print_flags(r->flags);
|
||||
printf("/");
|
||||
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) {
|
||||
const struct icmptypeent *it;
|
||||
|
||||
@ -800,7 +841,9 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
}
|
||||
if (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");
|
||||
else if (r->keep_state == PF_STATE_MODULATE)
|
||||
printf(" modulate state");
|
||||
@ -828,7 +871,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
opts = 1;
|
||||
if (r->rule_flag & PFRULE_SRCTRACK)
|
||||
opts = 1;
|
||||
if (r->rule_flag & (PFRULE_IFBOUND | PFRULE_GRBOUND))
|
||||
if (r->rule_flag & PFRULE_IFBOUND)
|
||||
opts = 1;
|
||||
for (i = 0; !opts && i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i])
|
||||
@ -896,12 +939,6 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
printf("if-bound");
|
||||
opts = 0;
|
||||
}
|
||||
if (r->rule_flag & PFRULE_GRBOUND) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("group-bound");
|
||||
opts = 0;
|
||||
}
|
||||
for (i = 0; i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i]) {
|
||||
int j;
|
||||
@ -909,12 +946,13 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
opts = 0;
|
||||
for (j = 0; j < sizeof(pf_timeouts) /
|
||||
sizeof(pf_timeouts[0]); ++j)
|
||||
for (j = 0; pf_timeouts[j].name != NULL;
|
||||
++j)
|
||||
if (pf_timeouts[j].timeout == i)
|
||||
break;
|
||||
printf("%s %u", j == PFTM_MAX ? "inv.timeout" :
|
||||
pf_timeouts[j].name, r->timeout[i]);
|
||||
printf("%s %u", pf_timeouts[j].name == NULL ?
|
||||
"inv.timeout" : pf_timeouts[j].name,
|
||||
r->timeout[i]);
|
||||
}
|
||||
printf(")");
|
||||
}
|
||||
@ -954,13 +992,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
printf(" !");
|
||||
printf(" tagged %s", r->match_tagname);
|
||||
}
|
||||
if (r->rtableid != -1)
|
||||
printf(" rtable %u", r->rtableid);
|
||||
if (!anchor_call[0] && (r->action == PF_NAT ||
|
||||
r->action == PF_BINAT || r->action == PF_RDR)) {
|
||||
printf(" -> ");
|
||||
print_pool(&r->rpool, r->rpool.proxy_port[0],
|
||||
r->rpool.proxy_port[1], r->af, r->action);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
@ -1153,13 +1192,31 @@ ifa_load(void)
|
||||
}
|
||||
|
||||
struct node_host *
|
||||
ifa_exists(const char *ifa_name, int group_ok)
|
||||
ifa_exists(const char *ifa_name)
|
||||
{
|
||||
struct node_host *n;
|
||||
struct ifgroupreq ifgr;
|
||||
int s;
|
||||
|
||||
if (iftab == NULL)
|
||||
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) {
|
||||
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
|
||||
return (n);
|
||||
@ -1168,6 +1225,47 @@ ifa_exists(const char *ifa_name, int group_ok)
|
||||
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 *
|
||||
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;
|
||||
const char *last_if = NULL;
|
||||
|
||||
if ((h = ifa_grouplookup(ifa_name, flags)) != NULL)
|
||||
return (h);
|
||||
|
||||
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
||||
ifa_name = NULL;
|
||||
|
||||
@ -1352,7 +1453,7 @@ host_if(const char *s, int mask)
|
||||
free(ps);
|
||||
return (NULL);
|
||||
}
|
||||
if (ifa_exists(ps, 1) || !strncmp(ps, "self", IFNAMSIZ)) {
|
||||
if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
|
||||
/* interface with this name exists */
|
||||
h = ifa_lookup(ps, flags);
|
||||
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
|
||||
@ -48,14 +48,17 @@
|
||||
#define PF_OPT_DEBUG 0x0200
|
||||
#define PF_OPT_SHOWALL 0x0400
|
||||
#define PF_OPT_OPTIMIZE 0x0800
|
||||
#define PF_OPT_OPTIMIZE_PROFILE 0x1000
|
||||
#define PF_OPT_MERGE 0x2000
|
||||
#define PF_OPT_RECURSE 0x4000
|
||||
|
||||
#define PF_TH_ALL 0xFF
|
||||
|
||||
#define PF_NAT_PROXY_PORT_LOW 50001
|
||||
#define PF_NAT_PROXY_PORT_HIGH 65535
|
||||
|
||||
#define PF_OPTIMIZE_BASIC 0x0001
|
||||
#define PF_OPTIMIZE_PROFILE 0x0002
|
||||
|
||||
#define FCNT_NAMES { \
|
||||
"searches", \
|
||||
"inserts", \
|
||||
@ -64,24 +67,25 @@
|
||||
}
|
||||
|
||||
struct pfr_buffer; /* forward definition */
|
||||
struct pf_opt_rule;
|
||||
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
|
||||
|
||||
|
||||
struct pfctl {
|
||||
int dev;
|
||||
int opts;
|
||||
int optimize;
|
||||
int loadopt;
|
||||
u_int32_t tticket; /* table ticket */
|
||||
int asd; /* anchor stack depth */
|
||||
int bn; /* brace number */
|
||||
int brace;
|
||||
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_altq *paltq;
|
||||
struct pfioc_queue *pqueue;
|
||||
struct pfr_buffer *trans;
|
||||
const char *anchor;
|
||||
struct pf_anchor *anchor, *alast;
|
||||
const char *ruleset;
|
||||
struct pf_opt_queue opt_queue;
|
||||
|
||||
/* 'set foo' options */
|
||||
u_int32_t timeout[PFTM_MAX];
|
||||
@ -118,10 +122,6 @@ struct node_host {
|
||||
struct node_host *next;
|
||||
struct node_host *tail;
|
||||
};
|
||||
/* special flags used by ifa_exists */
|
||||
#define PF_IFA_FLAG_GROUP 0x10000
|
||||
#define PF_IFA_FLAG_DYNAMIC 0x20000
|
||||
#define PF_IFA_FLAG_CLONABLE 0x40000
|
||||
|
||||
struct node_os {
|
||||
char *os;
|
||||
@ -205,19 +205,20 @@ struct pf_opt_rule {
|
||||
struct pf_rule por_rule;
|
||||
struct pf_opt_tbl *por_src_tbl;
|
||||
struct pf_opt_tbl *por_dst_tbl;
|
||||
char por_anchor[MAXPATHLEN];
|
||||
u_int64_t por_profile_count;
|
||||
TAILQ_ENTRY(pf_opt_rule) por_entry;
|
||||
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_optimize_rules(struct pfctl *);
|
||||
int pfctl_rules(int, char *, FILE *, int, int, char *, struct pfr_buffer *);
|
||||
int pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *);
|
||||
|
||||
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
|
||||
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
||||
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 *);
|
||||
|
||||
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_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_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 unmask(struct pf_addr *, sa_family_t);
|
||||
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 *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
|
||||
@ -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 radix_perror(void);
|
||||
static void xprintf(int, const char *, ...);
|
||||
static void print_iface(struct pfi_if *, int);
|
||||
static void oprintf(int, int, const char *, int *, int);
|
||||
static void print_iface(struct pfi_kif *, int);
|
||||
|
||||
static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = {
|
||||
{ "In/Block:", "In/Pass:", "In/XPass:" },
|
||||
@ -178,7 +177,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
break;
|
||||
}
|
||||
|
||||
if (opts & PF_OPT_SHOWALL && b.pfrb_size > 0)
|
||||
if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
|
||||
pfctl_print_title("TABLES:");
|
||||
|
||||
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)
|
||||
print_addrx(a, NULL,
|
||||
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")) {
|
||||
b.pfrb_type = (opts & PF_OPT_VERBOSE) ?
|
||||
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,
|
||||
&nmatch, flags));
|
||||
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)
|
||||
if (a->pfra_fback == PFR_FB_MATCH)
|
||||
print_addrx(a, NULL,
|
||||
@ -542,17 +577,15 @@ int
|
||||
pfctl_show_ifaces(const char *filter, int opts)
|
||||
{
|
||||
struct pfr_buffer b;
|
||||
struct pfi_if *p;
|
||||
int i = 0, f = PFI_FLAG_GROUP|PFI_FLAG_INSTANCE;
|
||||
struct pfi_kif *p;
|
||||
int i = 0;
|
||||
|
||||
if (filter != NULL && *filter && !isdigit(filter[strlen(filter)-1]))
|
||||
f &= ~PFI_FLAG_INSTANCE;
|
||||
bzero(&b, sizeof(b));
|
||||
b.pfrb_type = PFRB_IFACES;
|
||||
for (;;) {
|
||||
pfr_buf_grow(&b, b.pfrb_size);
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size, f)) {
|
||||
if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) {
|
||||
radix_perror();
|
||||
return (1);
|
||||
}
|
||||
@ -568,50 +601,30 @@ pfctl_show_ifaces(const char *filter, int opts)
|
||||
}
|
||||
|
||||
void
|
||||
print_iface(struct pfi_if *p, int opts)
|
||||
print_iface(struct pfi_kif *p, int opts)
|
||||
{
|
||||
time_t tzero = p->pfif_tzero;
|
||||
int flags = (opts & PF_OPT_VERBOSE) ? p->pfif_flags : 0;
|
||||
int first = 1;
|
||||
time_t tzero = p->pfik_tzero;
|
||||
int i, af, dir, act;
|
||||
|
||||
printf("%s", p->pfif_name);
|
||||
oprintf(flags, PFI_IFLAG_INSTANCE, "instance", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1);
|
||||
#ifdef __FreeBSD__
|
||||
first = 1;
|
||||
oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1);
|
||||
#endif
|
||||
printf("%s", p->pfik_name);
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
if (p->pfik_flags & PFI_IFLAG_SKIP)
|
||||
printf(" (skip)");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (!(opts & PF_OPT_VERBOSE2))
|
||||
return;
|
||||
printf("\tCleared: %s", ctime(&tzero));
|
||||
printf("\tReferences: [ States: %-18d Rules: %-18d ]\n",
|
||||
p->pfif_states, p->pfif_rules);
|
||||
p->pfik_states, p->pfik_rules);
|
||||
for (i = 0; i < 8; i++) {
|
||||
af = (i>>2) & 1;
|
||||
dir = (i>>1) &1;
|
||||
act = i & 1;
|
||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||
istats_text[af][dir][act],
|
||||
(unsigned long long)p->pfif_packets[af][dir][act],
|
||||
(unsigned long long)p->pfif_bytes[af][dir][act]);
|
||||
(unsigned long long)p->pfik_packets[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.
|
||||
.\"
|
||||
@ -37,14 +37,17 @@
|
||||
.Op Fl Dx
|
||||
.Op Fl d Ar delay
|
||||
.Op Fl f Ar filename
|
||||
.Op Fl i Ar interface
|
||||
.Op Fl s Ar snaplen
|
||||
.Op Ar expression
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a background daemon which reads packets logged by
|
||||
.Xr pf 4
|
||||
to the packet logging interface
|
||||
.Pa pflog0
|
||||
to a
|
||||
.Xr pflog 4
|
||||
interface, normally
|
||||
.Pa pflog0 ,
|
||||
and writes the packets to a logfile (normally
|
||||
.Pa /var/log/pflog )
|
||||
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.
|
||||
Furthermore, integrity of an existing log file is verified before
|
||||
appending.
|
||||
If there is an invalid log file or an I/O error, logging is suspended until a
|
||||
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
|
||||
or a
|
||||
.Dv SIGALRM
|
||||
@ -103,11 +108,19 @@ If not specified, the default is 60 seconds.
|
||||
Log output filename.
|
||||
Default is
|
||||
.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
|
||||
Analyze at most the first
|
||||
.Ar snaplen
|
||||
bytes of data from each packet rather than the default of 96.
|
||||
The default of 96 is adequate for IP, ICMP, TCP, and UDP headers but may
|
||||
bytes of data from each packet rather than the default of 116.
|
||||
The default of 116 is adequate for IP, ICMP, TCP, and UDP headers but may
|
||||
truncate protocol information for other protocols.
|
||||
Other file parsers may desire a higher snaplen.
|
||||
.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
|
||||
.Ed
|
||||
.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:
|
||||
.Bd -literal -offset indent
|
||||
# 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,
|
||||
a direction, an IP family or an action.
|
||||
.Pp
|
||||
.Bl -tag -width "reason match " -compact
|
||||
.Bl -tag -width "ruleset authpf " -compact
|
||||
.It ip
|
||||
Address family equals IPv4.
|
||||
.It ip6
|
||||
@ -159,12 +179,16 @@ Address family equals IPv6.
|
||||
Interface name equals "kue0".
|
||||
.It on kue0
|
||||
Interface name equals "kue0".
|
||||
.It ruleset authpf
|
||||
Ruleset name equals "authpf".
|
||||
.It rulenum 10
|
||||
Rule number equals 10.
|
||||
.It reason match
|
||||
Reason equals match.
|
||||
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
|
||||
Action equals pass.
|
||||
Also accepts "block".
|
||||
@ -192,4 +216,6 @@ The
|
||||
command appeared in
|
||||
.Ox 3.0 .
|
||||
.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
|
||||
@ -81,7 +81,7 @@ int flush_buffer(FILE *);
|
||||
int init_pcap(void);
|
||||
void logmsg(int, const char *, ...);
|
||||
void purge_buffer(void);
|
||||
int reset_dump(void);
|
||||
int reset_dump(int);
|
||||
int scan_dump(FILE *, off_t);
|
||||
int set_snaplen(int);
|
||||
void set_suspended(int);
|
||||
@ -90,6 +90,8 @@ void sig_close(int);
|
||||
void sig_hup(int);
|
||||
void usage(void);
|
||||
|
||||
static int try_reset_dump(int);
|
||||
|
||||
/* buffer must always be greater than snaplen */
|
||||
static int bufpkt = 0; /* number of packets in buffer */
|
||||
static int buflen = 0; /* allocated size of buffer */
|
||||
@ -108,8 +110,9 @@ set_suspended(int s)
|
||||
return;
|
||||
|
||||
suspended = s;
|
||||
setproctitle("[%s] -s %d -f %s",
|
||||
suspended ? "suspended" : "running", cur_snaplen, filename);
|
||||
setproctitle("[%s] -s %d -i %s -f %s",
|
||||
suspended ? "suspended" : "running",
|
||||
cur_snaplen, interface, filename);
|
||||
}
|
||||
|
||||
char *
|
||||
@ -159,8 +162,9 @@ __dead void
|
||||
#endif
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename] ");
|
||||
fprintf(stderr, "[-s snaplen] [expression]\n");
|
||||
fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename]");
|
||||
fprintf(stderr, " [-i interface] [-s snaplen]\n");
|
||||
fprintf(stderr, " [expression]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -240,7 +244,25 @@ set_snaplen(int snap)
|
||||
}
|
||||
|
||||
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 stat st;
|
||||
@ -262,26 +284,26 @@ reset_dump(void)
|
||||
*/
|
||||
fd = priv_open_log();
|
||||
if (fd < 0)
|
||||
return (1);
|
||||
return (-1);
|
||||
|
||||
fp = fdopen(fd, "a+");
|
||||
|
||||
if (fp == NULL) {
|
||||
close(fd);
|
||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||
return (1);
|
||||
close(fd);
|
||||
return (-1);
|
||||
}
|
||||
if (fstat(fileno(fp), &st) == -1) {
|
||||
fclose(fp);
|
||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||
return (1);
|
||||
fclose(fp);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* set FILE unbuffered, we do our own buffering */
|
||||
if (setvbuf(fp, NULL, _IONBF, 0)) {
|
||||
fclose(fp);
|
||||
logmsg(LOG_ERR, "Failed to set output buffers");
|
||||
return (1);
|
||||
fclose(fp);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||
@ -289,11 +311,9 @@ reset_dump(void)
|
||||
if (st.st_size == 0) {
|
||||
if (snaplen != cur_snaplen) {
|
||||
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
||||
if (set_snaplen(snaplen)) {
|
||||
fclose(fp);
|
||||
if (set_snaplen(snaplen))
|
||||
logmsg(LOG_WARNING,
|
||||
"Failed, using old settings");
|
||||
}
|
||||
}
|
||||
hdr.magic = TCPDUMP_MAGIC;
|
||||
hdr.version_major = PCAP_VERSION_MAJOR;
|
||||
@ -305,11 +325,15 @@ reset_dump(void)
|
||||
|
||||
if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
|
||||
fclose(fp);
|
||||
return (1);
|
||||
return (-1);
|
||||
}
|
||||
} else if (scan_dump(fp, st.st_size)) {
|
||||
/* XXX move file and continue? */
|
||||
fclose(fp);
|
||||
if (nomove || priv_move_log()) {
|
||||
logmsg(LOG_ERR,
|
||||
"Invalid/incompatible log file, move it away");
|
||||
return (-1);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -352,7 +376,6 @@ scan_dump(FILE *fp, off_t size)
|
||||
hdr.version_minor != PCAP_VERSION_MINOR ||
|
||||
hdr.linktype != hpcap->linktype ||
|
||||
hdr.snaplen > PFLOGD_MAXSNAPLEN) {
|
||||
logmsg(LOG_ERR, "Invalid/incompatible log file, move it away");
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -563,7 +586,7 @@ main(int argc, char **argv)
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
#endif
|
||||
|
||||
while ((ch = getopt(argc, argv, "Dxd:s:f:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "Dxd:f:i:s:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'D':
|
||||
Debug = 1;
|
||||
@ -576,6 +599,9 @@ main(int argc, char **argv)
|
||||
case 'f':
|
||||
filename = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
interface = optarg;
|
||||
break;
|
||||
case 's':
|
||||
snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
|
||||
&errstr);
|
||||
@ -648,7 +674,7 @@ main(int argc, char **argv)
|
||||
bufpkt = 0;
|
||||
}
|
||||
|
||||
if (reset_dump()) {
|
||||
if (reset_dump(Xflag) < 0) {
|
||||
if (Xflag)
|
||||
return (1);
|
||||
|
||||
@ -674,7 +700,7 @@ main(int argc, char **argv)
|
||||
if (gotsig_close)
|
||||
break;
|
||||
if (gotsig_hup) {
|
||||
if (reset_dump()) {
|
||||
if (reset_dump(0)) {
|
||||
logmsg(LOG_ERR,
|
||||
"Logging suspended: open error");
|
||||
set_suspended(1);
|
||||
@ -685,6 +711,8 @@ main(int argc, char **argv)
|
||||
if (gotsig_alrm) {
|
||||
if (dpcap)
|
||||
flush_buffer(dpcap);
|
||||
else
|
||||
gotsig_hup = 1;
|
||||
gotsig_alrm = 0;
|
||||
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
|
||||
@ -20,7 +20,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@ -30,19 +30,28 @@ __FBSDID("$FreeBSD$");
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#ifndef __FreeBSD__
|
||||
#include <pcap.h>
|
||||
#include <pcap-int.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __FreeBSD__
|
||||
/* XXX: pcap pollutes namespace with strlcpy if not present previously */
|
||||
#include <pcap.h>
|
||||
#include <pcap-int.h>
|
||||
#endif
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "pflogd.h"
|
||||
|
||||
enum cmd_types {
|
||||
PRIV_SET_SNAPLEN, /* set the snaplength */
|
||||
PRIV_MOVE_LOG, /* move logfile away */
|
||||
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_write(int, void *, size_t);
|
||||
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 pcap_t *hpcap;
|
||||
|
||||
@ -102,16 +109,12 @@ priv_init(void)
|
||||
err(1, "unable to chdir");
|
||||
|
||||
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)
|
||||
err(1, "setgroups() failed");
|
||||
if (setegid(pw->pw_gid) == -1)
|
||||
err(1, "setegid() failed");
|
||||
if (setgid(pw->pw_gid) == -1)
|
||||
err(1, "setgid() failed");
|
||||
if (seteuid(pw->pw_uid) == -1)
|
||||
err(1, "seteuid() failed");
|
||||
if (setuid(pw->pw_uid) == -1)
|
||||
err(1, "setuid() failed");
|
||||
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
|
||||
err(1, "setresuid() failed");
|
||||
close(socks[0]);
|
||||
priv_fd = socks[1];
|
||||
return 0;
|
||||
@ -165,6 +168,13 @@ priv_init(void)
|
||||
close(fd);
|
||||
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:
|
||||
logmsg(LOG_ERR, "[priv]: unknown command %d", cmd);
|
||||
_exit(1);
|
||||
@ -188,6 +198,47 @@ set_snaplen(int snap)
|
||||
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
|
||||
@ -229,6 +280,21 @@ priv_open_log(void)
|
||||
|
||||
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 */
|
||||
static void
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* $OpenBSD: filter.c,v 1.1 2005/12/28 19:07:07 jcs Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* 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.log = rule_log;
|
||||
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.flagset = (proto == IPPROTO_TCP ?
|
||||
(TH_SYN|TH_ACK|TH_FIN|TH_RST) : NULL);
|
||||
#endif
|
||||
pfr.rule.max_states = 1;
|
||||
if (qname != NULL)
|
||||
strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
|
||||
|
Loading…
Reference in New Issue
Block a user