Update packet filter (pf) code to OpenBSD 4.5.
You need to update userland (world and ports) tools to be in sync with the kernel. Submitted by: mlaier Submitted by: eri
This commit is contained in:
commit
e0bfbfce79
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223637
4
UPDATING
4
UPDATING
@ -22,6 +22,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
|
||||
machines to maximize performance. (To disable malloc debugging, run
|
||||
ln -s aj /etc/malloc.conf.)
|
||||
|
||||
20110628:
|
||||
The packet filter (pf) code has been updated to OpenBSD 4.5.
|
||||
You need to update userland tools to be in sync with kernel.
|
||||
|
||||
20110608:
|
||||
The following sysctls and tunables are retired on x86 platforms:
|
||||
machdep.hlt_cpus
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" $FreeBSD$
|
||||
.\" $OpenBSD: authpf.8,v 1.43 2007/02/24 17:21:04 beck Exp $
|
||||
.\" $OpenBSD: authpf.8,v 1.47 2009/01/06 03:11:50 mcbride Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1998-2007 Bob Beck (beck@openbsd.org>. All rights reserved.
|
||||
.\"
|
||||
@ -15,14 +15,16 @@
|
||||
.\" 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
|
||||
.Dd January 6 2009
|
||||
.Dt AUTHPF 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm authpf
|
||||
.Nm authpf ,
|
||||
.Nm authpf-noip
|
||||
.Nd authenticating gateway user shell
|
||||
.Sh SYNOPSIS
|
||||
.Nm authpf
|
||||
.Nm authpf-noip
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a user shell for authenticating gateways.
|
||||
@ -31,47 +33,63 @@ It is used to change
|
||||
rules when a user authenticates and starts a session with
|
||||
.Xr sshd 8
|
||||
and to undo these changes when the user's session exits.
|
||||
It is designed for changing filter and translation rules for an individual
|
||||
source IP address as long as a user maintains an active
|
||||
.Xr ssh 1
|
||||
session.
|
||||
Typical use would be for a gateway that authenticates users before
|
||||
allowing them Internet use, or a gateway that allows different users into
|
||||
different places.
|
||||
Combined with properly set up filter rules and secure switches,
|
||||
.Nm
|
||||
logs the successful start and end of a session to
|
||||
.Xr syslogd 8 .
|
||||
This, combined with properly set up filter rules and secure switches,
|
||||
can be used to ensure users are held accountable for their network traffic.
|
||||
.Pp
|
||||
.Nm
|
||||
can add filter and translation rules using the syntax described in
|
||||
.Xr pf.conf 5 .
|
||||
.Nm
|
||||
requires that the
|
||||
.Xr pf 4
|
||||
system be enabled and a
|
||||
.Xr fdescfs 5
|
||||
file system be mounted at
|
||||
.Pa /dev/fd
|
||||
before use.
|
||||
.Nm
|
||||
can also maintain the list of IP address of connected users
|
||||
in the "authpf_users"
|
||||
.Pa table .
|
||||
.Pp
|
||||
.Nm
|
||||
is meant to be used with users who can connect via
|
||||
It is meant to be used with users who can connect via
|
||||
.Xr ssh 1
|
||||
only.
|
||||
On startup,
|
||||
only, and requires the
|
||||
.Xr pf 4
|
||||
subsystem to be enabled.
|
||||
.Pp
|
||||
.Nm authpf-noip
|
||||
is a user shell
|
||||
which allows multiple connections to take
|
||||
place from the same IP address.
|
||||
It is useful primarily in cases where connections are tunneled via
|
||||
the gateway system, and can be directly associated with the user name.
|
||||
It cannot ensure accountability when
|
||||
classifying connections by IP address;
|
||||
in this case the client's IP address
|
||||
is not provided to the packet filter via the
|
||||
.Ar client_ip
|
||||
macro or the
|
||||
.Ar authpf_users
|
||||
table.
|
||||
Additionally, states associated with the client IP address
|
||||
are not purged when the session is ended.
|
||||
.Pp
|
||||
To use either
|
||||
.Nm
|
||||
or
|
||||
.Nm authpf-noip ,
|
||||
the user's shell needs to be set to
|
||||
.Pa /usr/sbin/authpf
|
||||
or
|
||||
.Pa /usr/sbin/authpf-noip .
|
||||
.Pp
|
||||
.Nm
|
||||
uses the
|
||||
.Xr pf.conf 5
|
||||
syntax to change filter and translation rules for an individual
|
||||
user or client IP address as long as a user maintains an active
|
||||
.Xr ssh 1
|
||||
session, and logs the successful start and end of a session to
|
||||
.Xr syslogd 8 .
|
||||
.Nm
|
||||
retrieves the client's connecting IP address via the
|
||||
.Ev SSH_CLIENT
|
||||
environment variable and, after performing additional access checks,
|
||||
reads a template file to determine what filter and translation rules
|
||||
(if any) to add.
|
||||
On session exit the same rules that were added at startup are removed.
|
||||
(if any) to add, and
|
||||
maintains the list of IP addresses of connected users in the
|
||||
.Ar authpf_users
|
||||
table.
|
||||
On session exit the same rules and table entries that were added at startup
|
||||
are removed, and all states associated with the client's IP address are purged.
|
||||
.Pp
|
||||
Each
|
||||
.Nm
|
||||
@ -185,6 +203,9 @@ It is also possible to configure
|
||||
to only allow specific users access.
|
||||
This is done by listing their login names, one per line, in
|
||||
.Pa /etc/authpf/authpf.allow .
|
||||
A group of users can also be indicated by prepending "%" to the group name,
|
||||
and all members of a login class can be indicated by prepending "@" to the
|
||||
login class name.
|
||||
If "*" is found on a line, then all usernames match.
|
||||
If
|
||||
.Nm
|
||||
@ -297,7 +318,8 @@ They have a
|
||||
wireless network which they would like to protect from unauthorized use.
|
||||
To accomplish this, they create the file
|
||||
.Pa /etc/authpf/authpf.allow
|
||||
which lists their login ids, one per line.
|
||||
which lists their login ids, group prepended with "%", or login class
|
||||
prepended with "@", one per line.
|
||||
At this point, even if eve could authenticate to
|
||||
.Xr sshd 8 ,
|
||||
she would not be allowed to use the gateway.
|
||||
@ -501,6 +523,31 @@ table <authpf_users> persist
|
||||
anchor "authpf/*" from <authpf_users>
|
||||
rdr-anchor "authpf/*" from <authpf_users>
|
||||
.Ed
|
||||
.Pp
|
||||
.Sy Tunneled users
|
||||
\- normally
|
||||
.Nm
|
||||
allows only one session per client IP address.
|
||||
However in some cases, such as when connections are tunneled via
|
||||
.Xr ssh 1
|
||||
or
|
||||
.Xr ipsec 4 ,
|
||||
the connections can be authorized based on the userid of the user instead of
|
||||
the client IP address.
|
||||
In this case it is appropriate to use
|
||||
.Nm authpf-noip
|
||||
to allow multiple users behind a NAT gateway to connect.
|
||||
In the
|
||||
.Pa /etc/authpf/authpf.rules
|
||||
example below, the remote user could tunnel a remote desktop session to their
|
||||
workstation:
|
||||
.Bd -literal
|
||||
internal_if="bge0"
|
||||
workstation_ip="10.2.3.4"
|
||||
|
||||
pass out on $internal_if from (self) to $workstation_ip port 3389 \e
|
||||
user $user_id
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/etc/authpf/authpf.conf" -compact
|
||||
.It Pa /etc/authpf/authpf.conf
|
||||
@ -512,7 +559,6 @@ rdr-anchor "authpf/*" from <authpf_users>
|
||||
.Sh SEE ALSO
|
||||
.Xr pf 4 ,
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr fdescfs 5 ,
|
||||
.Xr securelevel 7 ,
|
||||
.Xr ftp-proxy 8
|
||||
.Sh HISTORY
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authpf.c,v 1.104 2007/02/24 17:35:08 beck Exp $ */
|
||||
/* $OpenBSD: authpf.c,v 1.112 2009/01/10 19:08:53 miod Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998 - 2007 Bob Beck (beck@openbsd.org).
|
||||
@ -19,7 +19,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
#include <login_cap.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -48,10 +49,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include "pathnames.h"
|
||||
|
||||
static int read_config(FILE *);
|
||||
static void print_message(char *);
|
||||
static int allowed_luser(char *);
|
||||
static int check_luser(char *, char *);
|
||||
static void print_message(const char *);
|
||||
static int allowed_luser(struct passwd *);
|
||||
static int check_luser(const char *, char *);
|
||||
static int remove_stale_rulesets(void);
|
||||
static int recursive_ruleset_purge(char *, char *);
|
||||
static int change_filter(int, const char *, const char *);
|
||||
static int change_table(int, const char *);
|
||||
static void authpf_kill_states(void);
|
||||
@ -60,8 +62,10 @@ int dev; /* pf device */
|
||||
char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
|
||||
char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
|
||||
char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
|
||||
int user_ip = 1; /* controls whether $user_ip is set */
|
||||
|
||||
FILE *pidfp;
|
||||
int pidfd = -1;
|
||||
char luser[MAXLOGNAME]; /* username */
|
||||
char ipsrc[256]; /* ip as a string */
|
||||
char pidfile[MAXPATHLEN]; /* we save pid in this file. */
|
||||
@ -75,6 +79,7 @@ static __dead2 void do_death(int);
|
||||
#else
|
||||
static __dead void do_death(int);
|
||||
#endif
|
||||
extern char *__progname; /* program name */
|
||||
|
||||
/*
|
||||
* User shell for authenticating gateways. Sole purpose is to allow
|
||||
@ -83,21 +88,24 @@ static __dead void do_death(int);
|
||||
* up. Meant to be used only from ssh(1) connections.
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
main(void)
|
||||
{
|
||||
int lockcnt = 0, n, pidfd;
|
||||
int lockcnt = 0, n;
|
||||
FILE *config;
|
||||
struct in6_addr ina;
|
||||
struct passwd *pw;
|
||||
char *cp;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
char *shell;
|
||||
const char *shell;
|
||||
login_cap_t *lc;
|
||||
|
||||
if (strcmp(__progname, "-authpf-noip") == 0)
|
||||
user_ip = 0;
|
||||
|
||||
config = fopen(PATH_CONFFILE, "r");
|
||||
if (config == NULL) {
|
||||
syslog(LOG_ERR, "can not open %s (%m)", PATH_CONFFILE);
|
||||
syslog(LOG_ERR, "cannot open %s (%m)", PATH_CONFFILE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -142,23 +150,34 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if ((lc = login_getclass(pw->pw_class)) != NULL)
|
||||
shell = (char *)login_getcapstr(lc, "shell", pw->pw_shell,
|
||||
shell = login_getcapstr(lc, "shell", pw->pw_shell,
|
||||
pw->pw_shell);
|
||||
else
|
||||
shell = pw->pw_shell;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
login_close(lc);
|
||||
#endif
|
||||
|
||||
if (strcmp(shell, PATH_AUTHPF_SHELL)) {
|
||||
if (strcmp(shell, PATH_AUTHPF_SHELL) &&
|
||||
strcmp(shell, PATH_AUTHPF_SHELL_NOIP)) {
|
||||
syslog(LOG_ERR, "wrong shell for user %s, uid %u",
|
||||
pw->pw_name, pw->pw_uid);
|
||||
#ifdef __FreeBSD__
|
||||
login_close(lc);
|
||||
#else
|
||||
if (shell != pw->pw_shell)
|
||||
free(shell);
|
||||
#endif
|
||||
goto die;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
login_close(lc);
|
||||
#else
|
||||
if (shell != pw->pw_shell)
|
||||
free(shell);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Paranoia, but this data _does_ come from outside authpf, and
|
||||
@ -181,13 +200,22 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
/* Make our entry in /var/authpf as /var/authpf/ipaddr */
|
||||
n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc);
|
||||
/* Make our entry in /var/authpf as ipaddr or username */
|
||||
n = snprintf(pidfile, sizeof(pidfile), "%s/%s",
|
||||
PATH_PIDFILE, user_ip ? ipsrc : luser);
|
||||
if (n < 0 || (u_int)n >= sizeof(pidfile)) {
|
||||
syslog(LOG_ERR, "path to pidfile too long");
|
||||
goto die;
|
||||
}
|
||||
|
||||
signal(SIGTERM, need_death);
|
||||
signal(SIGINT, need_death);
|
||||
signal(SIGALRM, need_death);
|
||||
signal(SIGPIPE, need_death);
|
||||
signal(SIGHUP, need_death);
|
||||
signal(SIGQUIT, need_death);
|
||||
signal(SIGTSTP, need_death);
|
||||
|
||||
/*
|
||||
* If someone else is already using this ip, then this person
|
||||
* wants to switch users - so kill the old process and exit
|
||||
@ -241,15 +269,17 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/*
|
||||
* we try to kill the previous process and acquire the lock
|
||||
* We try to kill the previous process and acquire the lock
|
||||
* for 10 seconds, trying once a second. if we can't after
|
||||
* 10 attempts we log an error and give up
|
||||
* 10 attempts we log an error and give up.
|
||||
*/
|
||||
if (++lockcnt > 10) {
|
||||
syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
|
||||
otherpid);
|
||||
if (want_death || ++lockcnt > 10) {
|
||||
if (!want_death)
|
||||
syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
|
||||
otherpid);
|
||||
fclose(pidfp);
|
||||
pidfp = NULL;
|
||||
pidfd = -1;
|
||||
goto dogdeath;
|
||||
}
|
||||
sleep(1);
|
||||
@ -260,6 +290,7 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
fclose(pidfp);
|
||||
pidfp = NULL;
|
||||
pidfd = -1;
|
||||
} while (1);
|
||||
|
||||
/* whack the group list */
|
||||
@ -277,7 +308,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
|
||||
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
|
||||
if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(pw)) {
|
||||
syslog(LOG_INFO, "user %s prohibited", luser);
|
||||
do_death(0);
|
||||
}
|
||||
@ -302,19 +333,12 @@ main(int argc, char *argv[])
|
||||
printf("Unable to modify filters\r\n");
|
||||
do_death(0);
|
||||
}
|
||||
if (change_table(1, ipsrc) == -1) {
|
||||
if (user_ip && change_table(1, ipsrc) == -1) {
|
||||
printf("Unable to modify table\r\n");
|
||||
change_filter(0, luser, ipsrc);
|
||||
do_death(0);
|
||||
}
|
||||
|
||||
signal(SIGTERM, need_death);
|
||||
signal(SIGINT, need_death);
|
||||
signal(SIGALRM, need_death);
|
||||
signal(SIGPIPE, need_death);
|
||||
signal(SIGHUP, need_death);
|
||||
signal(SIGQUIT, need_death);
|
||||
signal(SIGTSTP, need_death);
|
||||
while (1) {
|
||||
printf("\r\nHello %s. ", luser);
|
||||
printf("You are authenticated from host \"%s\"\r\n", ipsrc);
|
||||
@ -337,8 +361,6 @@ main(int argc, char *argv[])
|
||||
sleep(180); /* them lusers read reaaaaal slow */
|
||||
die:
|
||||
do_death(0);
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -361,6 +383,8 @@ read_config(FILE *f)
|
||||
}
|
||||
i++;
|
||||
len = strlen(buf);
|
||||
if (len == 0)
|
||||
continue;
|
||||
if (buf[len - 1] != '\n' && !feof(f)) {
|
||||
syslog(LOG_ERR, "line %d too long in %s", i,
|
||||
PATH_CONFFILE);
|
||||
@ -413,7 +437,7 @@ read_config(FILE *f)
|
||||
* they've been bad or we're unavailable.
|
||||
*/
|
||||
static void
|
||||
print_message(char *filename)
|
||||
print_message(const char *filename)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *f;
|
||||
@ -436,6 +460,7 @@ print_message(char *filename)
|
||||
* allowed_luser checks to see if user "luser" is allowed to
|
||||
* use this gateway by virtue of being listed in an allowed
|
||||
* users file, namely /etc/authpf/authpf.allow .
|
||||
* Users may be listed by <username>, %<group>, or @<login_class>.
|
||||
*
|
||||
* If /etc/authpf/authpf.allow does not exist, then we assume that
|
||||
* all users who are allowed in by sshd(8) are permitted to
|
||||
@ -444,9 +469,9 @@ print_message(char *filename)
|
||||
* the session terminates in the same manner as being banned.
|
||||
*/
|
||||
static int
|
||||
allowed_luser(char *luser)
|
||||
allowed_luser(struct passwd *pw)
|
||||
{
|
||||
char *buf, *lbuf;
|
||||
char *buf,*lbuf;
|
||||
int matched;
|
||||
size_t len;
|
||||
FILE *f;
|
||||
@ -476,8 +501,14 @@ allowed_luser(char *luser)
|
||||
* "public" gateway, such as it is, so let
|
||||
* everyone use it.
|
||||
*/
|
||||
int gl_init = 0, ngroups = NGROUPS + 1;
|
||||
gid_t groups[NGROUPS + 1];
|
||||
|
||||
lbuf = NULL;
|
||||
matched = 0;
|
||||
|
||||
while ((buf = fgetln(f, &len))) {
|
||||
|
||||
if (buf[len - 1] == '\n')
|
||||
buf[len - 1] = '\0';
|
||||
else {
|
||||
@ -488,7 +519,40 @@ allowed_luser(char *luser)
|
||||
buf = lbuf;
|
||||
}
|
||||
|
||||
matched = strcmp(luser, buf) == 0 || strcmp("*", buf) == 0;
|
||||
if (buf[0] == '@') {
|
||||
/* check login class */
|
||||
if (strcmp(pw->pw_class, buf + 1) == 0)
|
||||
matched++;
|
||||
} else if (buf[0] == '%') {
|
||||
/* check group membership */
|
||||
int cnt;
|
||||
struct group *group;
|
||||
|
||||
if ((group = getgrnam(buf + 1)) == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"invalid group '%s' in %s (%s)",
|
||||
buf + 1, PATH_ALLOWFILE,
|
||||
strerror(errno));
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!gl_init) {
|
||||
(void) getgrouplist(pw->pw_name,
|
||||
pw->pw_gid, groups, &ngroups);
|
||||
gl_init++;
|
||||
}
|
||||
|
||||
for ( cnt = 0; cnt < ngroups; cnt++) {
|
||||
if (group->gr_gid == groups[cnt]) {
|
||||
matched++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* check username and wildcard */
|
||||
matched = strcmp(pw->pw_name, buf) == 0 ||
|
||||
strcmp("*", buf) == 0;
|
||||
}
|
||||
|
||||
if (lbuf != NULL) {
|
||||
free(lbuf);
|
||||
@ -496,13 +560,13 @@ allowed_luser(char *luser)
|
||||
}
|
||||
|
||||
if (matched)
|
||||
return (1); /* matched an allowed username */
|
||||
return (1); /* matched an allowed user/group */
|
||||
}
|
||||
syslog(LOG_INFO, "denied access to %s: not listed in %s",
|
||||
luser, PATH_ALLOWFILE);
|
||||
pw->pw_name, PATH_ALLOWFILE);
|
||||
|
||||
/* reuse buf */
|
||||
buf = "\n\nSorry, you are not allowed to use this facility!\n";
|
||||
sprintf(buf, "%s", "\n\nSorry, you are not allowed to use this facility!\n");
|
||||
fputs(buf, stdout);
|
||||
}
|
||||
fflush(stdout);
|
||||
@ -520,13 +584,13 @@ allowed_luser(char *luser)
|
||||
* going to be un-banned.)
|
||||
*/
|
||||
static int
|
||||
check_luser(char *luserdir, char *luser)
|
||||
check_luser(const char *luserdir, char *l_user)
|
||||
{
|
||||
FILE *f;
|
||||
int n;
|
||||
char tmp[MAXPATHLEN];
|
||||
|
||||
n = snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, luser);
|
||||
n = snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, l_user);
|
||||
if (n < 0 || (u_int)n >= sizeof(tmp)) {
|
||||
syslog(LOG_ERR, "provided banned directory line too long (%s)",
|
||||
luserdir);
|
||||
@ -555,7 +619,7 @@ check_luser(char *luserdir, char *luser)
|
||||
* tell what they can do and where they can go.
|
||||
*/
|
||||
syslog(LOG_INFO, "denied access to %s: %s exists",
|
||||
luser, tmp);
|
||||
l_user, tmp);
|
||||
|
||||
/* reuse tmp */
|
||||
strlcpy(tmp, "\n\n-**- Sorry, you have been banned! -**-\n\n",
|
||||
@ -581,7 +645,7 @@ static int
|
||||
remove_stale_rulesets(void)
|
||||
{
|
||||
struct pfioc_ruleset prs;
|
||||
u_int32_t nr, mnr;
|
||||
u_int32_t nr;
|
||||
|
||||
memset(&prs, 0, sizeof(prs));
|
||||
strlcpy(prs.path, anchorname, sizeof(prs.path));
|
||||
@ -592,13 +656,12 @@ remove_stale_rulesets(void)
|
||||
return (1);
|
||||
}
|
||||
|
||||
mnr = prs.nr;
|
||||
nr = 0;
|
||||
while (nr < mnr) {
|
||||
nr = prs.nr;
|
||||
while (nr) {
|
||||
char *s, *t;
|
||||
pid_t pid;
|
||||
|
||||
prs.nr = nr;
|
||||
prs.nr = nr - 1;
|
||||
if (ioctl(dev, DIOCGETRULESET, &prs))
|
||||
return (1);
|
||||
errno = 0;
|
||||
@ -610,119 +673,159 @@ remove_stale_rulesets(void)
|
||||
if (!prs.name[0] || errno ||
|
||||
(*s && (t == prs.name || *s != ')')))
|
||||
return (1);
|
||||
if (kill(pid, 0) && errno != EPERM) {
|
||||
int i;
|
||||
struct pfioc_trans_e t_e[PF_RULESET_MAX+1];
|
||||
struct pfioc_trans t;
|
||||
|
||||
bzero(&t, sizeof(t));
|
||||
bzero(t_e, sizeof(t_e));
|
||||
t.size = PF_RULESET_MAX+1;
|
||||
t.esize = sizeof(t_e[0]);
|
||||
t.array = t_e;
|
||||
for (i = 0; i < PF_RULESET_MAX+1; ++i) {
|
||||
t_e[i].rs_num = i;
|
||||
snprintf(t_e[i].anchor, sizeof(t_e[i].anchor),
|
||||
"%s/%s", anchorname, prs.name);
|
||||
}
|
||||
t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE;
|
||||
if ((ioctl(dev, DIOCXBEGIN, &t) ||
|
||||
ioctl(dev, DIOCXCOMMIT, &t)) &&
|
||||
errno != EINVAL)
|
||||
if ((kill(pid, 0) && errno != EPERM) || pid == getpid()) {
|
||||
if (recursive_ruleset_purge(anchorname, prs.name))
|
||||
return (1);
|
||||
mnr--;
|
||||
} else
|
||||
nr++;
|
||||
}
|
||||
nr--;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
recursive_ruleset_purge(char *an, char *rs)
|
||||
{
|
||||
struct pfioc_trans_e *t_e = NULL;
|
||||
struct pfioc_trans *t = NULL;
|
||||
struct pfioc_ruleset *prs = NULL;
|
||||
int i;
|
||||
|
||||
|
||||
/* purge rules */
|
||||
errno = 0;
|
||||
if ((t = calloc(1, sizeof(struct pfioc_trans))) == NULL)
|
||||
goto no_mem;
|
||||
if ((t_e = calloc(PF_RULESET_MAX+1,
|
||||
sizeof(struct pfioc_trans_e))) == NULL)
|
||||
goto no_mem;
|
||||
t->size = PF_RULESET_MAX+1;
|
||||
t->esize = sizeof(struct pfioc_trans_e);
|
||||
t->array = t_e;
|
||||
for (i = 0; i < PF_RULESET_MAX+1; ++i) {
|
||||
t_e[i].rs_num = i;
|
||||
snprintf(t_e[i].anchor, sizeof(t_e[i].anchor), "%s/%s", an, rs);
|
||||
}
|
||||
t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE;
|
||||
if ((ioctl(dev, DIOCXBEGIN, t) ||
|
||||
ioctl(dev, DIOCXCOMMIT, t)) &&
|
||||
errno != EINVAL)
|
||||
goto cleanup;
|
||||
|
||||
/* purge any children */
|
||||
if ((prs = calloc(1, sizeof(struct pfioc_ruleset))) == NULL)
|
||||
goto no_mem;
|
||||
snprintf(prs->path, sizeof(prs->path), "%s/%s", an, rs);
|
||||
if (ioctl(dev, DIOCGETRULESETS, prs)) {
|
||||
if (errno != EINVAL)
|
||||
goto cleanup;
|
||||
errno = 0;
|
||||
} else {
|
||||
int nr = prs->nr;
|
||||
|
||||
while (nr) {
|
||||
prs->nr = 0;
|
||||
if (ioctl(dev, DIOCGETRULESET, prs))
|
||||
goto cleanup;
|
||||
|
||||
if (recursive_ruleset_purge(prs->path, prs->name))
|
||||
goto cleanup;
|
||||
nr--;
|
||||
}
|
||||
}
|
||||
|
||||
no_mem:
|
||||
if (errno == ENOMEM)
|
||||
syslog(LOG_ERR, "calloc failed");
|
||||
|
||||
cleanup:
|
||||
free(t);
|
||||
free(t_e);
|
||||
free(prs);
|
||||
return (errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add/remove filter entries for user "luser" from ip "ipsrc"
|
||||
*/
|
||||
static int
|
||||
change_filter(int add, const char *luser, const char *ipsrc)
|
||||
change_filter(int add, const char *l_user, const char *ip_src)
|
||||
{
|
||||
char *pargv[13] = {
|
||||
"pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
|
||||
"-D", "user_ip=X", "-D", "user_id=X", "-f",
|
||||
"file", NULL
|
||||
};
|
||||
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]) {
|
||||
syslog(LOG_ERR, "invalid luser/ipsrc");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)
|
||||
goto no_mem;
|
||||
if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1)
|
||||
goto no_mem;
|
||||
if (asprintf(&ipstr, "user_ip=%s", ipsrc) == -1)
|
||||
goto no_mem;
|
||||
if (asprintf(&userstr, "user_id=%s", luser) == -1)
|
||||
goto no_mem;
|
||||
|
||||
if (add) {
|
||||
struct stat sb;
|
||||
char *pargv[13] = {
|
||||
"pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
|
||||
"-D", "user_id=X", "-D", "user_ip=X", "-f", "file", NULL
|
||||
};
|
||||
|
||||
if (asprintf(&fn, "%s/%s/authpf.rules", PATH_USER_DIR, luser)
|
||||
== -1)
|
||||
if (l_user == NULL || !l_user[0] || ip_src == NULL || !ip_src[0]) {
|
||||
syslog(LOG_ERR, "invalid luser/ipsrc");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)
|
||||
goto no_mem;
|
||||
if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1)
|
||||
goto no_mem;
|
||||
if (asprintf(&ipstr, "user_ip=%s", ip_src) == -1)
|
||||
goto no_mem;
|
||||
if (asprintf(&userstr, "user_id=%s", l_user) == -1)
|
||||
goto no_mem;
|
||||
if (asprintf(&fn, "%s/%s/authpf.rules",
|
||||
PATH_USER_DIR, l_user) == -1)
|
||||
goto no_mem;
|
||||
if (stat(fn, &sb) == -1) {
|
||||
free(fn);
|
||||
if ((fn = strdup(PATH_PFRULES)) == NULL)
|
||||
goto no_mem;
|
||||
}
|
||||
}
|
||||
pargv[2] = fdpath;
|
||||
pargv[5] = rsn;
|
||||
pargv[7] = userstr;
|
||||
pargv[9] = ipstr;
|
||||
if (!add)
|
||||
pargv[11] = "/dev/null";
|
||||
else
|
||||
pargv[11] = fn;
|
||||
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
syslog(LOG_ERR, "fork failed");
|
||||
goto error;
|
||||
case 0:
|
||||
/* revoke group privs before exec */
|
||||
gid = getgid();
|
||||
if (setregid(gid, gid) == -1) {
|
||||
err(1, "setregid");
|
||||
pargv[2] = fdpath;
|
||||
pargv[5] = rsn;
|
||||
pargv[7] = userstr;
|
||||
if (user_ip) {
|
||||
pargv[9] = ipstr;
|
||||
pargv[11] = fn;
|
||||
} else {
|
||||
pargv[8] = "-f";
|
||||
pargv[9] = fn;
|
||||
pargv[10] = NULL;
|
||||
}
|
||||
execvp(PATH_PFCTL, pargv);
|
||||
warn("exec of %s failed", PATH_PFCTL);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
waitpid(pid, &s, 0);
|
||||
if (s != 0) {
|
||||
syslog(LOG_ERR, "pfctl exited abnormally");
|
||||
goto error;
|
||||
}
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
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);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
waitpid(pid, &s, 0);
|
||||
if (s != 0) {
|
||||
syslog(LOG_ERR, "pfctl exited abnormally");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
gettimeofday(&Tstart, NULL);
|
||||
syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser);
|
||||
syslog(LOG_INFO, "allowing %s, user %s", ip_src, l_user);
|
||||
} else {
|
||||
remove_stale_rulesets();
|
||||
|
||||
gettimeofday(&Tend, NULL);
|
||||
#ifdef __FreeBSD__
|
||||
syslog(LOG_INFO, "removed %s, user %s - duration %jd seconds",
|
||||
ipsrc, luser, (intmax_t)(Tend.tv_sec - Tstart.tv_sec));
|
||||
#else
|
||||
syslog(LOG_INFO, "removed %s, user %s - duration %ld seconds",
|
||||
ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
|
||||
#endif
|
||||
syslog(LOG_INFO, "removed %s, user %s - duration %ju seconds",
|
||||
ip_src, l_user, (uintmax_t)(Tend.tv_sec - Tstart.tv_sec));
|
||||
}
|
||||
return (0);
|
||||
no_mem:
|
||||
@ -740,7 +843,7 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
* Add/remove this IP from the "authpf_users" table.
|
||||
*/
|
||||
static int
|
||||
change_table(int add, const char *ipsrc)
|
||||
change_table(int add, const char *ip_src)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
struct pfr_addr addr;
|
||||
@ -753,12 +856,12 @@ change_table(int add, const char *ipsrc)
|
||||
io.pfrio_size = 1;
|
||||
|
||||
bzero(&addr, sizeof(addr));
|
||||
if (ipsrc == NULL || !ipsrc[0])
|
||||
if (ip_src == NULL || !ip_src[0])
|
||||
return (-1);
|
||||
if (inet_pton(AF_INET, ipsrc, &addr.pfra_ip4addr) == 1) {
|
||||
if (inet_pton(AF_INET, ip_src, &addr.pfra_ip4addr) == 1) {
|
||||
addr.pfra_af = AF_INET;
|
||||
addr.pfra_net = 32;
|
||||
} else if (inet_pton(AF_INET6, ipsrc, &addr.pfra_ip6addr) == 1) {
|
||||
} else if (inet_pton(AF_INET6, ip_src, &addr.pfra_ip6addr) == 1) {
|
||||
addr.pfra_af = AF_INET6;
|
||||
addr.pfra_net = 128;
|
||||
} else {
|
||||
@ -769,7 +872,7 @@ change_table(int add, const char *ipsrc)
|
||||
if (ioctl(dev, add ? DIOCRADDADDRS : DIOCRDELADDRS, &io) &&
|
||||
errno != ESRCH) {
|
||||
syslog(LOG_ERR, "cannot %s %s from table %s: %s",
|
||||
add ? "add" : "remove", ipsrc, tablename,
|
||||
add ? "add" : "remove", ip_src, tablename,
|
||||
strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
@ -821,7 +924,7 @@ authpf_kill_states(void)
|
||||
|
||||
/* signal handler that makes us go away properly */
|
||||
static void
|
||||
need_death(int signo)
|
||||
need_death(int signo __unused)
|
||||
{
|
||||
want_death = 1;
|
||||
}
|
||||
@ -840,11 +943,12 @@ do_death(int active)
|
||||
|
||||
if (active) {
|
||||
change_filter(0, luser, ipsrc);
|
||||
change_table(0, ipsrc);
|
||||
authpf_kill_states();
|
||||
remove_stale_rulesets();
|
||||
if (user_ip) {
|
||||
change_table(0, ipsrc);
|
||||
authpf_kill_states();
|
||||
}
|
||||
}
|
||||
if (pidfile[0] && (pidfp != NULL))
|
||||
if (pidfile[0] && pidfd != -1)
|
||||
if (unlink(pidfile) == -1)
|
||||
syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
|
||||
exit(ret);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pathnames.h,v 1.7 2004/04/25 18:40:42 beck Exp $ */
|
||||
/* $OpenBSD: pathnames.h,v 1.8 2008/02/14 01:49:17 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Chris Kuethe (ckuethe@ualberta.ca)
|
||||
@ -35,4 +35,5 @@
|
||||
#define PATH_DEVFILE "/dev/pf"
|
||||
#define PATH_PIDFILE "/var/authpf"
|
||||
#define PATH_AUTHPF_SHELL "/usr/sbin/authpf"
|
||||
#define PATH_AUTHPF_SHELL_NOIP "/usr/sbin/authpf-noip"
|
||||
#define PATH_PFCTL "/sbin/pfctl"
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: filter.c,v 1.5 2006/12/01 07:31:21 camield Exp $ */
|
||||
/* $OpenBSD: filter.c,v 1.8 2008/06/13 07:25:26 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
||||
@ -53,7 +53,7 @@ static struct pfioc_rule pfr;
|
||||
static struct pfioc_trans pft;
|
||||
static struct pfioc_trans_e pfte[TRANS_SIZE];
|
||||
static int dev, rule_log;
|
||||
static char *qname;
|
||||
static const char *qname, *tagname;
|
||||
|
||||
int
|
||||
add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src,
|
||||
@ -159,11 +159,12 @@ do_rollback(void)
|
||||
}
|
||||
|
||||
void
|
||||
init_filter(char *opt_qname, int opt_verbose)
|
||||
init_filter(const char *opt_qname, const char *opt_tagname, int opt_verbose)
|
||||
{
|
||||
struct pf_status status;
|
||||
|
||||
qname = opt_qname;
|
||||
tagname = opt_tagname;
|
||||
|
||||
if (opt_verbose == 1)
|
||||
rule_log = PF_LOG;
|
||||
@ -172,7 +173,7 @@ init_filter(char *opt_qname, int opt_verbose)
|
||||
|
||||
dev = open("/dev/pf", O_RDWR);
|
||||
if (dev == -1)
|
||||
err(1, "/dev/pf");
|
||||
err(1, "open /dev/pf");
|
||||
if (ioctl(dev, DIOCGETSTATUS, &status) == -1)
|
||||
err(1, "DIOCGETSTATUS");
|
||||
if (!status.running)
|
||||
@ -280,9 +281,9 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
|
||||
switch (rs_num) {
|
||||
case PF_RULESET_FILTER:
|
||||
/*
|
||||
* pass quick [log] inet[6] proto tcp \
|
||||
* pass [quick] [log] inet[6] proto tcp \
|
||||
* from $src to $dst port = $d_port flags S/SA keep state
|
||||
* (max 1) [queue qname]
|
||||
* (max 1) [queue qname] [tag tagname]
|
||||
*/
|
||||
pfr.rule.action = PF_PASS;
|
||||
pfr.rule.quick = 1;
|
||||
@ -293,6 +294,11 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
|
||||
pfr.rule.max_states = 1;
|
||||
if (qname != NULL)
|
||||
strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
|
||||
if (tagname != NULL) {
|
||||
pfr.rule.quick = 0;
|
||||
strlcpy(pfr.rule.tagname, tagname,
|
||||
sizeof pfr.rule.tagname);
|
||||
}
|
||||
break;
|
||||
case PF_RULESET_NAT:
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: filter.h,v 1.3 2005/06/07 14:12:07 camield Exp $ */
|
||||
/* $OpenBSD: filter.h,v 1.4 2007/08/01 09:31:41 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
||||
@ -26,6 +26,6 @@ int add_rdr(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
|
||||
struct sockaddr *, u_int16_t);
|
||||
int do_commit(void);
|
||||
int do_rollback(void);
|
||||
void init_filter(char *, int);
|
||||
void init_filter(const char *, const char *, int);
|
||||
int prepare_commit(u_int32_t);
|
||||
int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: ftp-proxy.8,v 1.7 2006/12/30 13:01:54 camield Exp $
|
||||
.\" $OpenBSD: ftp-proxy.8,v 1.11 2008/02/26 18:52:53 henning Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
||||
.\"
|
||||
@ -16,14 +16,15 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 28, 2004
|
||||
.Dd February 26, 2008
|
||||
.Dt FTP-PROXY 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ftp-proxy
|
||||
.Nd Internet File Transfer Protocol proxy daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm ftp-proxy
|
||||
.Nm
|
||||
.Bk -words
|
||||
.Op Fl 6Adrv
|
||||
.Op Fl a Ar address
|
||||
.Op Fl b Ar address
|
||||
@ -33,7 +34,9 @@
|
||||
.Op Fl p Ar port
|
||||
.Op Fl q Ar queue
|
||||
.Op Fl R Ar address
|
||||
.Op Fl T Ar tag
|
||||
.Op Fl t Ar timeout
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a proxy for the Internet File Transfer Protocol.
|
||||
@ -58,7 +61,7 @@ facility for this.
|
||||
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
|
||||
.Nm
|
||||
adds the following rules to the various anchors.
|
||||
(These example rules use inet, but the proxy also supports inet6.)
|
||||
.Pp
|
||||
@ -130,6 +133,20 @@ connections to another proxy.
|
||||
.It Fl r
|
||||
Rewrite sourceport to 20 in active mode to suit ancient clients that insist
|
||||
on this RFC property.
|
||||
.It Fl T Ar tag
|
||||
The filter rules will add tag
|
||||
.Ar tag
|
||||
to data connections, and not match quick.
|
||||
This way alternative rules that use the
|
||||
.Ar tagged
|
||||
keyword can be implemented following the
|
||||
.Nm
|
||||
anchor.
|
||||
These rules can use special
|
||||
.Xr pf 4
|
||||
features like route-to, reply-to, label, rtable, overload, etc. that
|
||||
.Nm
|
||||
does not implement itself.
|
||||
.It Fl t Ar timeout
|
||||
Number of seconds that the control connection can be idle, before the
|
||||
proxy will disconnect.
|
||||
@ -172,7 +189,7 @@ 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
|
||||
.Nm
|
||||
cannot add rules to the anchors and FTP data connections may get blocked.
|
||||
.Pp
|
||||
Negotiated data connection ports below 1024 are not allowed.
|
||||
@ -181,5 +198,5 @@ The negotiated IP address for active modes is ignored for security
|
||||
reasons.
|
||||
This makes third party file transfers impossible.
|
||||
.Pp
|
||||
.Nm ftp-proxy
|
||||
.Nm
|
||||
chroots to "/var/empty" and changes to user "proxy" to drop privileges.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ftp-proxy.c,v 1.13 2006/12/30 13:24:00 camield Exp $ */
|
||||
/* $OpenBSD: ftp-proxy.c,v 1.19 2008/06/13 07:25:26 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
|
||||
@ -61,6 +61,14 @@ __FBSDID("$FreeBSD$");
|
||||
#define PF_NAT_PROXY_PORT_LOW 50001
|
||||
#define PF_NAT_PROXY_PORT_HIGH 65535
|
||||
|
||||
#ifndef LIST_END
|
||||
#define LIST_END(a) NULL
|
||||
#endif
|
||||
|
||||
#ifndef getrtable
|
||||
#define getrtable(a) 0
|
||||
#endif
|
||||
|
||||
#define sstosa(ss) ((struct sockaddr *)(ss))
|
||||
|
||||
enum { CMD_NONE = 0, CMD_PORT, CMD_EPRT, CMD_PASV, CMD_EPSV };
|
||||
@ -94,7 +102,7 @@ int client_parse_cmd(struct session *s);
|
||||
void client_read(struct bufferevent *, void *);
|
||||
int drop_privs(void);
|
||||
void end_session(struct session *);
|
||||
int exit_daemon(void);
|
||||
void exit_daemon(void);
|
||||
int getline(char *, size_t *);
|
||||
void handle_connection(const int, short, void *);
|
||||
void handle_signal(int, short, void *);
|
||||
@ -105,6 +113,7 @@ u_int16_t pick_proxy_port(void);
|
||||
void proxy_reply(int, struct sockaddr *, u_int16_t);
|
||||
void server_error(struct bufferevent *, short, void *);
|
||||
int server_parse(struct session *s);
|
||||
int allow_data_connection(struct session *s);
|
||||
void server_read(struct bufferevent *, void *);
|
||||
const char *sock_ntop(struct sockaddr *);
|
||||
void usage(void);
|
||||
@ -115,14 +124,14 @@ size_t linelen;
|
||||
char ntop_buf[NTOP_BUFS][INET6_ADDRSTRLEN];
|
||||
|
||||
struct sockaddr_storage fixed_server_ss, fixed_proxy_ss;
|
||||
char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port,
|
||||
*qname;
|
||||
const char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port,
|
||||
*qname, *tagname;
|
||||
int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions,
|
||||
rfc_mode, session_count, timeout, verbose;
|
||||
extern char *__progname;
|
||||
|
||||
void
|
||||
client_error(struct bufferevent *bufev, short what, void *arg)
|
||||
client_error(struct bufferevent *bufev __unused, short what, void *arg)
|
||||
{
|
||||
struct session *s = arg;
|
||||
|
||||
@ -152,8 +161,19 @@ client_parse(struct session *s)
|
||||
return (1);
|
||||
|
||||
if (linebuf[0] == 'P' || linebuf[0] == 'p' ||
|
||||
linebuf[0] == 'E' || linebuf[0] == 'e')
|
||||
return (client_parse_cmd(s));
|
||||
linebuf[0] == 'E' || linebuf[0] == 'e') {
|
||||
if (!client_parse_cmd(s))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Allow active mode connections immediately, instead of
|
||||
* waiting for a positive reply from the server. Some
|
||||
* rare servers/proxies try to probe or setup the data
|
||||
* connection before an actual transfer request.
|
||||
*/
|
||||
if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT)
|
||||
return (allow_data_connection(s));
|
||||
}
|
||||
|
||||
if (anonymous_only && (linebuf[0] == 'U' || linebuf[0] == 'u'))
|
||||
return (client_parse_anon(s));
|
||||
@ -220,14 +240,14 @@ void
|
||||
client_read(struct bufferevent *bufev, void *arg)
|
||||
{
|
||||
struct session *s = arg;
|
||||
size_t buf_avail, read;
|
||||
size_t buf_avail, clientread;
|
||||
int n;
|
||||
|
||||
do {
|
||||
buf_avail = sizeof s->cbuf - s->cbuf_valid;
|
||||
read = bufferevent_read(bufev, s->cbuf + s->cbuf_valid,
|
||||
clientread = bufferevent_read(bufev, s->cbuf + s->cbuf_valid,
|
||||
buf_avail);
|
||||
s->cbuf_valid += read;
|
||||
s->cbuf_valid += clientread;
|
||||
|
||||
while ((n = getline(s->cbuf, &s->cbuf_valid)) > 0) {
|
||||
logmsg(LOG_DEBUG, "#%d client: %s", s->id, linebuf);
|
||||
@ -244,7 +264,7 @@ client_read(struct bufferevent *bufev, void *arg)
|
||||
end_session(s);
|
||||
return;
|
||||
}
|
||||
} while (read == buf_avail);
|
||||
} while (clientread == buf_avail);
|
||||
}
|
||||
|
||||
int
|
||||
@ -269,10 +289,16 @@ drop_privs(void)
|
||||
void
|
||||
end_session(struct session *s)
|
||||
{
|
||||
int err;
|
||||
int serr;
|
||||
|
||||
logmsg(LOG_INFO, "#%d ending session", s->id);
|
||||
|
||||
/* Flush output buffers. */
|
||||
if (s->client_bufev && s->client_fd != -1)
|
||||
evbuffer_write(s->client_bufev->output, s->client_fd);
|
||||
if (s->server_bufev && s->server_fd != -1)
|
||||
evbuffer_write(s->server_bufev->output, s->server_fd);
|
||||
|
||||
if (s->client_fd != -1)
|
||||
close(s->client_fd);
|
||||
if (s->server_fd != -1)
|
||||
@ -284,33 +310,29 @@ end_session(struct session *s)
|
||||
bufferevent_free(s->server_bufev);
|
||||
|
||||
/* Remove rulesets by commiting empty ones. */
|
||||
err = 0;
|
||||
serr = 0;
|
||||
if (prepare_commit(s->id) == -1)
|
||||
err = errno;
|
||||
serr = errno;
|
||||
else if (do_commit() == -1) {
|
||||
err = errno;
|
||||
serr = errno;
|
||||
do_rollback();
|
||||
}
|
||||
if (err)
|
||||
if (serr)
|
||||
logmsg(LOG_ERR, "#%d pf rule removal failed: %s", s->id,
|
||||
strerror(err));
|
||||
strerror(serr));
|
||||
|
||||
LIST_REMOVE(s, entry);
|
||||
free(s);
|
||||
session_count--;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
exit_daemon(void)
|
||||
{
|
||||
struct session *s, *next;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
LIST_FOREACH_SAFE(s, &sessions, entry, next) {
|
||||
#else
|
||||
for (s = LIST_FIRST(&sessions); s != LIST_END(&sessions); s = next) {
|
||||
next = LIST_NEXT(s, entry);
|
||||
#endif
|
||||
end_session(s);
|
||||
}
|
||||
|
||||
@ -318,9 +340,6 @@ exit_daemon(void)
|
||||
closelog();
|
||||
|
||||
exit(0);
|
||||
|
||||
/* NOTREACHED */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
@ -361,7 +380,7 @@ getline(char *buf, size_t *valid)
|
||||
}
|
||||
|
||||
void
|
||||
handle_connection(const int listen_fd, short event, void *ev)
|
||||
handle_connection(const int listen_fd, short event __unused, void *ev __unused)
|
||||
{
|
||||
struct sockaddr_storage tmp_ss;
|
||||
struct sockaddr *client_sa, *server_sa, *fixed_server_sa;
|
||||
@ -508,13 +527,13 @@ handle_connection(const int listen_fd, short event, void *ev)
|
||||
}
|
||||
|
||||
void
|
||||
handle_signal(int sig, short event, void *arg)
|
||||
handle_signal(int sig, short event __unused, void *arg __unused)
|
||||
{
|
||||
/*
|
||||
* Signal handler rules don't apply, libevent decouples for us.
|
||||
*/
|
||||
|
||||
logmsg(LOG_ERR, "%s exiting on signal %d", __progname, sig);
|
||||
logmsg(LOG_ERR, "exiting on signal %d", sig);
|
||||
|
||||
exit_daemon();
|
||||
}
|
||||
@ -567,10 +586,7 @@ logmsg(int pri, const char *message, ...)
|
||||
/* We don't care about truncation. */
|
||||
vsnprintf(buf, sizeof buf, message, ap);
|
||||
#ifdef __FreeBSD__
|
||||
/* XXX: strnvis might be nice to have */
|
||||
strvisx(visbuf, buf,
|
||||
MIN((sizeof(visbuf) / 4) - 1, strlen(buf)),
|
||||
VIS_CSTYLE | VIS_NL);
|
||||
strvis(visbuf, buf, VIS_CSTYLE | VIS_NL);
|
||||
#else
|
||||
strnvis(visbuf, buf, sizeof visbuf, VIS_CSTYLE | VIS_NL);
|
||||
#endif
|
||||
@ -602,6 +618,7 @@ main(int argc, char *argv[])
|
||||
max_sessions = 100;
|
||||
qname = NULL;
|
||||
rfc_mode = 0;
|
||||
tagname = NULL;
|
||||
timeout = 24 * 3600;
|
||||
verbose = 0;
|
||||
|
||||
@ -609,7 +626,7 @@ main(int argc, char *argv[])
|
||||
id_count = 1;
|
||||
session_count = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rt:v")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rT:t:v")) != -1) {
|
||||
switch (ch) {
|
||||
case '6':
|
||||
ipv6_mode = 1;
|
||||
@ -654,6 +671,11 @@ main(int argc, char *argv[])
|
||||
case 'r':
|
||||
rfc_mode = 1;
|
||||
break;
|
||||
case 'T':
|
||||
if (strlen(optarg) >= PF_TAG_NAME_SIZE)
|
||||
errx(1, "tagname too long");
|
||||
tagname = optarg;
|
||||
break;
|
||||
case 't':
|
||||
timeout = strtonum(optarg, 0, 86400, &errstr);
|
||||
if (errstr)
|
||||
@ -734,7 +756,7 @@ main(int argc, char *argv[])
|
||||
freeaddrinfo(res);
|
||||
|
||||
/* Initialize pf. */
|
||||
init_filter(qname, verbose);
|
||||
init_filter(qname, tagname, verbose);
|
||||
|
||||
if (daemonize) {
|
||||
if (daemon(0, 0) == -1)
|
||||
@ -830,14 +852,15 @@ u_int16_t
|
||||
pick_proxy_port(void)
|
||||
{
|
||||
/* Random should be good enough for avoiding port collisions. */
|
||||
return (IPPORT_HIFIRSTAUTO + (arc4random() %
|
||||
(IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO)));
|
||||
return (IPPORT_HIFIRSTAUTO +
|
||||
arc4random_uniform(IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO));
|
||||
}
|
||||
|
||||
void
|
||||
proxy_reply(int cmd, struct sockaddr *sa, u_int16_t port)
|
||||
{
|
||||
int i, r;
|
||||
u_int i;
|
||||
int r = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case CMD_PORT:
|
||||
@ -864,7 +887,7 @@ proxy_reply(int cmd, struct sockaddr *sa, u_int16_t port)
|
||||
break;
|
||||
}
|
||||
|
||||
if (r < 0 || r >= sizeof linebuf) {
|
||||
if (r < 0 || ((u_int)r) >= sizeof linebuf) {
|
||||
logmsg(LOG_ERR, "proxy_reply failed: %d", r);
|
||||
linebuf[0] = '\0';
|
||||
linelen = 0;
|
||||
@ -881,7 +904,7 @@ proxy_reply(int cmd, struct sockaddr *sa, u_int16_t port)
|
||||
}
|
||||
|
||||
void
|
||||
server_error(struct bufferevent *bufev, short what, void *arg)
|
||||
server_error(struct bufferevent *bufev __unused, short what, void *arg)
|
||||
{
|
||||
struct session *s = arg;
|
||||
|
||||
@ -902,12 +925,26 @@ server_error(struct bufferevent *bufev, short what, void *arg)
|
||||
int
|
||||
server_parse(struct session *s)
|
||||
{
|
||||
struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
|
||||
int prepared = 0;
|
||||
|
||||
if (s->cmd == CMD_NONE || linelen < 4 || linebuf[0] != '2')
|
||||
goto out;
|
||||
|
||||
if ((s->cmd == CMD_PASV && strncmp("227 ", linebuf, 4) == 0) ||
|
||||
(s->cmd == CMD_EPSV && strncmp("229 ", linebuf, 4) == 0))
|
||||
return (allow_data_connection(s));
|
||||
|
||||
out:
|
||||
s->cmd = CMD_NONE;
|
||||
s->port = 0;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
allow_data_connection(struct session *s)
|
||||
{
|
||||
struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
|
||||
int prepared = 0;
|
||||
|
||||
/*
|
||||
* The pf rules below do quite some NAT rewriting, to keep up
|
||||
* appearances. Points to keep in mind:
|
||||
@ -932,8 +969,7 @@ server_parse(struct session *s)
|
||||
orig_sa = sstosa(&s->server_ss);
|
||||
|
||||
/* Passive modes. */
|
||||
if ((s->cmd == CMD_PASV && strncmp("227 ", linebuf, 4) == 0) ||
|
||||
(s->cmd == CMD_EPSV && strncmp("229 ", linebuf, 4) == 0)) {
|
||||
if (s->cmd == CMD_PASV || s->cmd == CMD_EPSV) {
|
||||
s->port = parse_port(s->cmd);
|
||||
if (s->port < MIN_PORT) {
|
||||
logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id,
|
||||
@ -974,8 +1010,7 @@ server_parse(struct session *s)
|
||||
}
|
||||
|
||||
/* Active modes. */
|
||||
if ((s->cmd == CMD_PORT || s->cmd == CMD_EPRT) &&
|
||||
strncmp("200 ", linebuf, 4) == 0) {
|
||||
if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) {
|
||||
logmsg(LOG_INFO, "#%d active: server to client port %d"
|
||||
" via port %d", s->id, s->port, s->proxy_port);
|
||||
|
||||
@ -1025,7 +1060,6 @@ server_parse(struct session *s)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
out:
|
||||
s->cmd = CMD_NONE;
|
||||
s->port = 0;
|
||||
|
||||
@ -1042,16 +1076,16 @@ void
|
||||
server_read(struct bufferevent *bufev, void *arg)
|
||||
{
|
||||
struct session *s = arg;
|
||||
size_t buf_avail, read;
|
||||
size_t buf_avail, srvread;
|
||||
int n;
|
||||
|
||||
bufferevent_settimeout(bufev, timeout, 0);
|
||||
|
||||
do {
|
||||
buf_avail = sizeof s->sbuf - s->sbuf_valid;
|
||||
read = bufferevent_read(bufev, s->sbuf + s->sbuf_valid,
|
||||
srvread = bufferevent_read(bufev, s->sbuf + s->sbuf_valid,
|
||||
buf_avail);
|
||||
s->sbuf_valid += read;
|
||||
s->sbuf_valid += srvread;
|
||||
|
||||
while ((n = getline(s->sbuf, &s->sbuf_valid)) > 0) {
|
||||
logmsg(LOG_DEBUG, "#%d server: %s", s->id, linebuf);
|
||||
@ -1068,7 +1102,7 @@ server_read(struct bufferevent *bufev, void *arg)
|
||||
end_session(s);
|
||||
return;
|
||||
}
|
||||
} while (read == buf_avail);
|
||||
} while (srvread == buf_avail);
|
||||
}
|
||||
|
||||
const char *
|
||||
@ -1102,6 +1136,7 @@ usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-6Adrv] [-a address] [-b address]"
|
||||
" [-D level] [-m maxsessions]\n [-P port]"
|
||||
" [-p port] [-q queue] [-R address] [-t timeout]\n", __progname);
|
||||
" [-p port] [-q queue] [-R address] [-T tag]\n"
|
||||
" [-t timeout]\n", __progname);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pf.4,v 1.58 2007/02/09 11:39:06 henning Exp $
|
||||
.\" $OpenBSD: pf.4,v 1.62 2008/09/10 14:57:37 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (C) 2001, Kjell Wooding. All rights reserved.
|
||||
.\"
|
||||
@ -28,7 +28,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 7, 2005
|
||||
.Dd September 10 2008
|
||||
.Dt PF 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -294,14 +294,17 @@ if another process is concurrently updating a ruleset.
|
||||
Add a state entry.
|
||||
.Bd -literal
|
||||
struct pfioc_state {
|
||||
u_int32_t nr;
|
||||
struct pf_state state;
|
||||
struct pfsync_state state;
|
||||
};
|
||||
.Ed
|
||||
.It Dv DIOCGETSTATE Fa "struct pfioc_state *ps"
|
||||
Extract the entry with the specified number
|
||||
.Va nr
|
||||
from the state table.
|
||||
Extract the entry identified by the
|
||||
.Va id
|
||||
and
|
||||
.Va creatorid
|
||||
fields of the
|
||||
.Va state
|
||||
structure from the state table.
|
||||
.It Dv DIOCKILLSTATES Fa "struct pfioc_state_kill *psk"
|
||||
Remove matching entries from the state table.
|
||||
This ioctl returns the number of killed states in
|
||||
@ -1049,12 +1052,14 @@ internal interface description.
|
||||
The filtering process is the same as for
|
||||
.Dv DIOCIGETIFACES .
|
||||
.Bd -literal
|
||||
#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */
|
||||
#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */
|
||||
.Ed
|
||||
.It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io"
|
||||
Works as
|
||||
.Dv DIOCSETIFFLAG
|
||||
above but clears the flags.
|
||||
.It Dv DIOCKILLSRCNODES Fa "struct pfioc_iface *io"
|
||||
Explicitly remove source tracking nodes.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /dev/pf -compact
|
||||
@ -1133,6 +1138,7 @@ main(int argc, char *argv[])
|
||||
.Xr altq 4 ,
|
||||
.Xr if_bridge 4 ,
|
||||
.Xr pflog 4 ,
|
||||
.Xr pflow 4 ,
|
||||
.Xr pfsync 4 ,
|
||||
.Xr pfctl 8 ,
|
||||
.Xr altq 9
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" $FreeBSD$
|
||||
.\" $OpenBSD: pf.conf.5,v 1.393 2008/02/11 07:46:32 jmc Exp $
|
||||
.\" $FreeBSD$
|
||||
.\" $OpenBSD: pf.conf.5,v 1.406 2009/01/31 19:37:12 sobrado Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2002, Daniel Hartmeier
|
||||
.\" All rights reserved.
|
||||
@ -28,7 +28,7 @@
|
||||
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd June 10, 2008
|
||||
.Dd January 31 2009
|
||||
.Dt PF.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -79,6 +79,17 @@ By default
|
||||
enforces this order (see
|
||||
.Ar set require-order
|
||||
below).
|
||||
.Pp
|
||||
Comments can be put anywhere in the file using a hash mark
|
||||
.Pq Sq # ,
|
||||
and extend to the end of the current line.
|
||||
.Pp
|
||||
Additional configuration files can be included with the
|
||||
.Ic include
|
||||
keyword, for example:
|
||||
.Bd -literal -offset indent
|
||||
include "/etc/pf/sub.filter.conf"
|
||||
.Ed
|
||||
.Sh MACROS
|
||||
Macros can be defined that will later be expanded in context.
|
||||
Macro names must start with a letter, and may contain letters, digits
|
||||
@ -154,7 +165,7 @@ A table initialized with the empty list,
|
||||
will be cleared on load.
|
||||
.El
|
||||
.Pp
|
||||
Tables may be defined with the following two attributes:
|
||||
Tables may be defined with the following attributes:
|
||||
.Bl -tag -width persist
|
||||
.It Ar persist
|
||||
The
|
||||
@ -173,6 +184,11 @@ can be used to add or remove addresses from the table at any time, even
|
||||
when running with
|
||||
.Xr securelevel 7
|
||||
= 2.
|
||||
.It Ar counters
|
||||
The
|
||||
.Ar counters
|
||||
flag enables per-address packet and byte counters which can be displayed with
|
||||
.Xr pfctl 8 .
|
||||
.El
|
||||
.Pp
|
||||
For example,
|
||||
@ -328,7 +344,8 @@ With 9000 state table entries, the timeout values are scaled to 50%
|
||||
(tcp.first 60, tcp.established 43200).
|
||||
.Pp
|
||||
.It Ar set loginterface
|
||||
Enable collection of packet and byte count statistics for the given interface.
|
||||
Enable collection of packet and byte count statistics for the given
|
||||
interface or interface group.
|
||||
These statistics can be viewed using
|
||||
.Bd -literal -offset indent
|
||||
# pfctl -s info
|
||||
@ -403,9 +420,10 @@ set limit { states 20000, frags 20000, src-nodes 2000 }
|
||||
.Bl -tag -width xxxxxxxx -compact
|
||||
.It Ar none
|
||||
Disable the ruleset optimizer.
|
||||
This is the default behaviour.
|
||||
.It Ar basic
|
||||
Enable basic ruleset optimization, which does four things to improve the
|
||||
Enable basic ruleset optimization.
|
||||
This is the default behaviour.
|
||||
Basic ruleset optimization does four things to improve the
|
||||
performance of ruleset evaluations:
|
||||
.Pp
|
||||
.Bl -enum -compact
|
||||
@ -500,6 +518,16 @@ For example:
|
||||
.Bd -literal -offset indent
|
||||
set state-policy if-bound
|
||||
.Ed
|
||||
.It Ar set state-defaults
|
||||
The
|
||||
.Ar state-defaults
|
||||
option sets the state options for states created from rules
|
||||
without an explicit
|
||||
.Ar keep state .
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
set state-defaults pflow, no-sync
|
||||
.Ed
|
||||
.It Ar set hostid
|
||||
The 32-bit
|
||||
.Ar hostid
|
||||
@ -617,6 +645,19 @@ modifier to ensure unique IP identifiers.
|
||||
Enforces a minimum TTL for matching IP packets.
|
||||
.It Ar max-mss Aq Ar number
|
||||
Enforces a maximum MSS for matching TCP packets.
|
||||
.It Xo Ar set-tos Aq Ar string
|
||||
.No \*(Ba Aq Ar number
|
||||
.Xc
|
||||
Enforces a
|
||||
.Em TOS
|
||||
for matching IP packets.
|
||||
.Em TOS
|
||||
may be
|
||||
given as one of
|
||||
.Ar lowdelay ,
|
||||
.Ar throughput ,
|
||||
.Ar reliability ,
|
||||
or as either hex or decimal.
|
||||
.It Ar random-id
|
||||
Replaces the IP identification field with random values to compensate
|
||||
for predictable values generated by many hosts.
|
||||
@ -725,7 +766,7 @@ much in the same way as
|
||||
works in the packet filter (see below).
|
||||
This mechanism should be used when it is necessary to exclude specific packets
|
||||
from broader scrub rules.
|
||||
.Sh QUEUEING/ALTQ
|
||||
.Sh QUEUEING
|
||||
The ALTQ system is currently not available in the GENERIC kernel nor as
|
||||
loadable modules.
|
||||
In order to use the herein after called queueing options one has to use a
|
||||
@ -816,7 +857,7 @@ assigned.
|
||||
.Ar Priority
|
||||
mainly controls the time packets take to get sent out, while
|
||||
.Ar bandwidth
|
||||
has primarily effects on throughput.
|
||||
primarily affects throughput.
|
||||
.Ar hfsc
|
||||
supports both link-sharing and guaranteed real-time services.
|
||||
It employs a service curve based QoS model,
|
||||
@ -879,7 +920,7 @@ Defines a list of subqueues to create on an interface.
|
||||
.El
|
||||
.Pp
|
||||
In the following example, the interface dc0
|
||||
should queue up to 5 Mbit/s in four second-level queues using
|
||||
should queue up to 5Mbps in four second-level queues using
|
||||
Class Based Queueing.
|
||||
Those four queues will be shown in a later example.
|
||||
.Bd -literal -offset indent
|
||||
@ -1171,7 +1212,7 @@ or to the firewall itself.
|
||||
Note that redirecting external incoming connections to the loopback
|
||||
address, as in
|
||||
.Bd -literal -offset indent
|
||||
rdr on ne3 inet proto tcp to port spamd -\*(Gt 127.0.0.1 port smtp
|
||||
rdr on ne3 inet proto tcp to port smtp -\*(Gt 127.0.0.1 port spamd
|
||||
.Ed
|
||||
.Pp
|
||||
will effectively allow an external host to connect to daemons
|
||||
@ -1256,7 +1297,7 @@ block all
|
||||
.Ed
|
||||
.It Ar pass
|
||||
The packet is passed;
|
||||
state is created state unless the
|
||||
state is created unless the
|
||||
.Ar no state
|
||||
option is specified.
|
||||
.El
|
||||
@ -1432,7 +1473,8 @@ This rule applies only to packets with the specified source and destination
|
||||
addresses and ports.
|
||||
.Pp
|
||||
Addresses can be specified in CIDR notation (matching netblocks), as
|
||||
symbolic host names or interface names, or as any of the following keywords:
|
||||
symbolic host names, interface names or interface group names, or as any
|
||||
of the following keywords:
|
||||
.Pp
|
||||
.Bl -tag -width xxxxxxxxxxxxxx -compact
|
||||
.It Ar any
|
||||
@ -1454,7 +1496,15 @@ the route back to the packet's source address.
|
||||
Any address that matches the given table.
|
||||
.El
|
||||
.Pp
|
||||
Interface names can have modifiers appended:
|
||||
Ranges of addresses are specified by using the
|
||||
.Sq -
|
||||
operator.
|
||||
For instance:
|
||||
.Dq 10.1.1.10 - 10.1.1.12
|
||||
means all addresses from 10.1.1.10 to 10.1.1.12,
|
||||
hence addresses 10.1.1.10, 10.1.1.11, and 10.1.1.12.
|
||||
.Pp
|
||||
Interface names and interface group names can have modifiers appended:
|
||||
.Pp
|
||||
.Bl -tag -width xxxxxxxxxxxx -compact
|
||||
.It Ar :network
|
||||
@ -1462,7 +1512,7 @@ Translates to the network(s) attached to the interface.
|
||||
.It Ar :broadcast
|
||||
Translates to the interface's broadcast address(es).
|
||||
.It Ar :peer
|
||||
Translates to the point to point interface's peer address(es).
|
||||
Translates to the point-to-point interface's peer address(es).
|
||||
.It Ar :0
|
||||
Do not include interface aliases.
|
||||
.El
|
||||
@ -1552,17 +1602,6 @@ This is equivalent to "from any to any".
|
||||
Similar to
|
||||
.Ar user ,
|
||||
this rule only applies to packets of sockets owned by the specified group.
|
||||
.Pp
|
||||
The use of
|
||||
.Ar group
|
||||
or
|
||||
.Ar user
|
||||
in
|
||||
.Va debug.mpsafenet Ns = Ns 1
|
||||
environments may result in a deadlock.
|
||||
Please see the
|
||||
.Sx BUGS
|
||||
section for details.
|
||||
.It Ar user Aq Ar user
|
||||
This rule only applies to packets of sockets owned by the specified user.
|
||||
For outgoing connections initiated from the firewall, this is the user
|
||||
@ -1628,7 +1667,7 @@ Flags not specified in
|
||||
are ignored.
|
||||
For stateful connections, the default is
|
||||
.Ar flags S/SA .
|
||||
To indicate that flags should not be checkd at all, specify
|
||||
To indicate that flags should not be checked at all, specify
|
||||
.Ar flags any .
|
||||
The flags are: (F)IN, (S)YN, (R)ST, (P)USH, (A)CK, (U)RG, (E)CE, and C(W)R.
|
||||
.Bl -tag -width Fl
|
||||
@ -1780,7 +1819,7 @@ of
|
||||
.Em lowdelay
|
||||
and TCP ACKs with no data payload will be assigned to the second one.
|
||||
See
|
||||
.Sx QUEUEING/ALTQ
|
||||
.Sx QUEUEING
|
||||
for setup details.
|
||||
.Pp
|
||||
For example:
|
||||
@ -1811,7 +1850,8 @@ or
|
||||
rules in addition to filter rules.
|
||||
Tags take the same macros as labels (see above).
|
||||
.It Ar tagged Aq Ar string
|
||||
Used with filter or translation rules to specify that packets must already
|
||||
Used with filter, translation or scrub rules
|
||||
to specify that packets must already
|
||||
be tagged with the given tag in order to match the rule.
|
||||
Inverse tag matching can also be done
|
||||
by specifying the
|
||||
@ -1822,6 +1862,22 @@ keyword.
|
||||
.It Ar rtable Aq Ar number
|
||||
Used to select an alternate routing table for the routing lookup.
|
||||
Only effective before the route lookup happened, i.e. when filtering inbound.
|
||||
.It Xo Ar divert-to Aq Ar host
|
||||
.Ar port Aq Ar port
|
||||
.Xc
|
||||
Used to redirect packets to a local socket bound to
|
||||
.Ar host
|
||||
and
|
||||
.Ar port .
|
||||
The packets will not be modified, so
|
||||
.Xr getsockname 2
|
||||
on the socket will return the original destination address of the packet.
|
||||
.It Ar divert-reply
|
||||
Used to receive replies for sockets that are bound to addresses
|
||||
which are not local to the machine.
|
||||
See
|
||||
.Xr setsockopt 2
|
||||
for information on how to bind these sockets.
|
||||
.It Ar probability Aq Ar number
|
||||
A probability attribute can be attached to a rule, with a value set between
|
||||
0 and 1, bounds not included.
|
||||
@ -1940,7 +1996,7 @@ pool options.
|
||||
Note that by default these associations are destroyed as soon as there are
|
||||
no longer states which refer to them; in order to make the mappings last
|
||||
beyond the lifetime of the states, increase the global options with
|
||||
.Ar set timeout source-track
|
||||
.Ar set timeout src.track .
|
||||
See
|
||||
.Sx STATEFUL TRACKING OPTIONS
|
||||
for more ways to control the source tracking.
|
||||
@ -2026,7 +2082,7 @@ Rules with
|
||||
will not work if
|
||||
.Xr pf 4
|
||||
operates on a
|
||||
.Xr if_bridge 4 .
|
||||
.Xr bridge 4 .
|
||||
.Pp
|
||||
Example:
|
||||
.Bd -literal -offset indent
|
||||
@ -2046,8 +2102,8 @@ must be specified explicitly to apply options to a rule.
|
||||
.Bl -tag -width xxxx -compact
|
||||
.It Ar max Aq Ar number
|
||||
Limits the number of concurrent states the rule may create.
|
||||
When this limit is reached, further packets matching the rule that would
|
||||
create state are dropped, until existing states time out.
|
||||
When this limit is reached, further packets that would create
|
||||
state will not match this rule until existing states time out.
|
||||
.It Ar no-sync
|
||||
Prevent state changes for states created by this rule from appearing on the
|
||||
.Xr pfsync 4
|
||||
@ -2064,8 +2120,12 @@ Uses a sloppy TCP connection tracker that does not check sequence
|
||||
numbers at all, which makes insertion and ICMP teardown attacks way
|
||||
easier.
|
||||
This is intended to be used in situations where one does not see all
|
||||
packets of a connection, i.e. in asymmetric routing situations.
|
||||
packets of a connection, e.g. in asymmetric routing situations.
|
||||
Cannot be used with modulate or synproxy state.
|
||||
.It Ar pflow
|
||||
States created by this rule are exported on the
|
||||
.Xr pflow 4
|
||||
interface.
|
||||
.El
|
||||
.Pp
|
||||
Multiple options can be specified, separated by commas:
|
||||
@ -2472,10 +2532,8 @@ into the anchor.
|
||||
.Pp
|
||||
Optionally,
|
||||
.Ar anchor
|
||||
rules can specify the parameter's
|
||||
direction, interface, address family, protocol and source/destination
|
||||
address/port
|
||||
using the same syntax as filter rules.
|
||||
rules can specify packet filtering parameters using the same syntax as
|
||||
filter rules.
|
||||
When parameters are used, the
|
||||
.Ar anchor
|
||||
rule is only evaluated for matching packets.
|
||||
@ -2779,10 +2837,11 @@ in BNF:
|
||||
.Bd -literal
|
||||
line = ( option | pf-rule | nat-rule | binat-rule | rdr-rule |
|
||||
antispoof-rule | altq-rule | queue-rule | trans-anchors |
|
||||
anchor-rule | anchor-close | load-anchor | table-rule | )
|
||||
anchor-rule | anchor-close | load-anchor | table-rule |
|
||||
include )
|
||||
|
||||
option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
|
||||
[ "ruleset-optimization" [ "none" | "basic" | "profile" ]] |
|
||||
[ "ruleset-optimization" [ "none" | "basic" | "profile" ]] |
|
||||
[ "optimization" [ "default" | "normal" |
|
||||
"high-latency" | "satellite" |
|
||||
"aggressive" | "conservative" ] ]
|
||||
@ -2790,9 +2849,10 @@ option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
|
||||
[ "loginterface" ( interface-name | "none" ) ] |
|
||||
[ "block-policy" ( "drop" | "return" ) ] |
|
||||
[ "state-policy" ( "if-bound" | "floating" ) ]
|
||||
[ "state-defaults" state-opts ]
|
||||
[ "require-order" ( "yes" | "no" ) ]
|
||||
[ "fingerprints" filename ] |
|
||||
[ "skip on" ( interface-name | "{" interface-list "}" ) ] |
|
||||
[ "skip on" ifspec ] |
|
||||
[ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] )
|
||||
|
||||
pf-rule = action [ ( "in" | "out" ) ]
|
||||
@ -2804,10 +2864,10 @@ logopts = logopt [ "," logopts ]
|
||||
logopt = "all" | "user" | "to" interface-name
|
||||
|
||||
filteropt-list = filteropt-list filteropt | filteropt
|
||||
filteropt = user | group | flags | icmp-type | icmp6-type | tos |
|
||||
filteropt = user | group | flags | icmp-type | icmp6-type | "tos" tos |
|
||||
( "no" | "keep" | "modulate" | "synproxy" ) "state"
|
||||
[ "(" state-opts ")" ] |
|
||||
"fragment" | "no-df" | "min-ttl" number |
|
||||
"fragment" | "no-df" | "min-ttl" number | "set-tos" tos |
|
||||
"max-mss" number | "random-id" | "reassemble tcp" |
|
||||
fragmentation | "allow-opts" |
|
||||
"label" string | "tag" string | [ ! ] "tagged" string |
|
||||
@ -2834,17 +2894,16 @@ rdr-rule = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
|
||||
[ portspec ] [ pooltype ] ]
|
||||
|
||||
antispoof-rule = "antispoof" [ "log" ] [ "quick" ]
|
||||
"for" ( interface-name | "{" interface-list "}" )
|
||||
[ af ] [ "label" string ]
|
||||
"for" ifspec [ af ] [ "label" string ]
|
||||
|
||||
table-rule = "table" "\*(Lt" string "\*(Gt" [ tableopts-list ]
|
||||
tableopts-list = tableopts-list tableopts | tableopts
|
||||
tableopts = "persist" | "const" | "file" string |
|
||||
tableopts = "persist" | "const" | "counters" | "file" string |
|
||||
"{" [ tableaddr-list ] "}"
|
||||
tableaddr-list = tableaddr-list [ "," ] tableaddr-spec | tableaddr-spec
|
||||
tableaddr-spec = [ "!" ] tableaddr [ "/" mask-bits ]
|
||||
tableaddr = hostname | ipv4-dotted-quad | ipv6-coloned-hex |
|
||||
interface-name | "self"
|
||||
tableaddr = hostname | ifspec | "self" |
|
||||
ipv4-dotted-quad | ipv6-coloned-hex
|
||||
|
||||
altq-rule = "altq on" interface-name queueopts-list
|
||||
"queue" subqueue
|
||||
@ -2852,7 +2911,7 @@ queue-rule = "queue" string [ "on" interface-name ] queueopts-list
|
||||
subqueue
|
||||
|
||||
anchor-rule = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ]
|
||||
[ af ] [ protospec ] [ hosts ] [ "{" ]
|
||||
[ af ] [ protospec ] [ hosts ] [ filteropt-list ] [ "{" ]
|
||||
|
||||
anchor-close = "}"
|
||||
|
||||
@ -2875,8 +2934,10 @@ return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
|
||||
icmpcode = ( icmp-code-name | icmp-code-number )
|
||||
icmp6code = ( icmp6-code-name | icmp6-code-number )
|
||||
|
||||
ifspec = ( [ "!" ] interface-name ) | "{" interface-list "}"
|
||||
interface-list = [ "!" ] interface-name [ [ "," ] interface-list ]
|
||||
ifspec = ( [ "!" ] ( interface-name | interface-group ) ) |
|
||||
"{" interface-list "}"
|
||||
interface-list = [ "!" ] ( interface-name | interface-group )
|
||||
[ [ "," ] interface-list ]
|
||||
route = ( "route-to" | "reply-to" | "dup-to" )
|
||||
( routehost | "{" routehost-list "}" )
|
||||
[ pooltype ]
|
||||
@ -2896,8 +2957,9 @@ ipspec = "any" | host | "{" host-list "}"
|
||||
host = [ "!" ] ( address [ "/" mask-bits ] | "\*(Lt" string "\*(Gt" )
|
||||
redirhost = address [ "/" mask-bits ]
|
||||
routehost = "(" interface-name [ address [ "/" mask-bits ] ] ")"
|
||||
address = ( interface-name | "(" interface-name ")" | hostname |
|
||||
ipv4-dotted-quad | ipv6-coloned-hex )
|
||||
address = ( interface-name | interface-group |
|
||||
"(" ( interface-name | interface-group ) ")" |
|
||||
hostname | ipv4-dotted-quad | ipv6-coloned-hex )
|
||||
host-list = host [ [ "," ] host-list ]
|
||||
redirhost-list = redirhost [ [ "," ] redirhost-list ]
|
||||
routehost-list = routehost [ [ "," ] routehost-list ]
|
||||
@ -2926,11 +2988,11 @@ icmp-type-code = ( icmp-type-name | icmp-type-number )
|
||||
[ "code" ( icmp-code-name | icmp-code-number ) ]
|
||||
icmp-list = icmp-type-code [ [ "," ] icmp-list ]
|
||||
|
||||
tos = "tos" ( "lowdelay" | "throughput" | "reliability" |
|
||||
tos = ( "lowdelay" | "throughput" | "reliability" |
|
||||
[ "0x" ] number )
|
||||
|
||||
state-opts = state-opt [ [ "," ] state-opts ]
|
||||
state-opt = ( "max" number | "no-sync" | timeout | sloppy |
|
||||
state-opt = ( "max" number | "no-sync" | timeout | "sloppy" | "pflow" |
|
||||
"source-track" [ ( "rule" | "global" ) ] |
|
||||
"max-src-nodes" number | "max-src-states" number |
|
||||
"max-src-conn" number |
|
||||
@ -2971,9 +3033,10 @@ realtime-sc = "realtime" sc-spec
|
||||
upperlimit-sc = "upperlimit" sc-spec
|
||||
sc-spec = ( bandwidth-spec |
|
||||
"(" bandwidth-spec number bandwidth-spec ")" )
|
||||
include = "include" filename
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/usr/share/examples/pf" -compact
|
||||
.Bl -tag -width "/etc/protocols" -compact
|
||||
.It Pa /etc/hosts
|
||||
Host name database.
|
||||
.It Pa /etc/pf.conf
|
||||
@ -2984,8 +3047,6 @@ Default location of OS fingerprints.
|
||||
Protocol name database.
|
||||
.It Pa /etc/services
|
||||
Service name database.
|
||||
.It Pa /usr/share/examples/pf
|
||||
Example rulesets.
|
||||
.El
|
||||
.Sh BUGS
|
||||
Due to a lock order reversal (LOR) with the socket layer, the use of the
|
||||
@ -3017,6 +3078,7 @@ Rules with a route label do not match any traffic.
|
||||
.Xr ip 4 ,
|
||||
.Xr ip6 4 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr pflow 4 ,
|
||||
.Xr pfsync 4 ,
|
||||
.Xr route 4 ,
|
||||
.Xr tcp 4 ,
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pf.os.5,v 1.7 2005/11/16 20:07:18 stevesk Exp $
|
||||
.\" $OpenBSD: pf.os.5,v 1.8 2007/05/31 19:19:58 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
||||
.\"
|
||||
@ -16,7 +16,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 18, 2003
|
||||
.Dd May 31 2007
|
||||
.Dt PF.OS 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -217,7 +217,7 @@ almost translates into the following fingerprint
|
||||
57344:64:1:44:M1460: exampleOS:1.0::exampleOS 1.0
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr tcpdump 1 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr pfctl 8
|
||||
.Xr pfctl 8 ,
|
||||
.Xr tcpdump 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pflog.4,v 1.9 2006/10/25 12:51:31 jmc Exp $
|
||||
.\" $OpenBSD: pflog.4,v 1.10 2007/05/31 19:19:51 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Tobias Weingartner
|
||||
.\" All rights reserved.
|
||||
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 10, 2001
|
||||
.Dd May 31 2007
|
||||
.Dt PFLOG 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -36,7 +36,7 @@
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm pflog
|
||||
interface is a pseudo-device which makes visible all packets logged by
|
||||
interface is a device which makes visible all packets logged by
|
||||
the packet filter,
|
||||
.Xr pf 4 .
|
||||
Logged packets can easily be monitored in real
|
||||
@ -91,13 +91,13 @@ and monitor all packets logged on it:
|
||||
# tcpdump -n -e -ttt -i pflog1
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr tcpdump 1
|
||||
.Xr inet 4 ,
|
||||
.Xr inet6 4 ,
|
||||
.Xr netintro 4 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr pflogd 8
|
||||
.Xr pflogd 8 ,
|
||||
.Xr tcpdump 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pfsync.4,v 1.24 2006/10/23 07:05:49 jmc Exp $
|
||||
.\" $OpenBSD: pfsync.4,v 1.28 2009/02/17 10:05:18 dlg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2002 Michael Shalayeff
|
||||
.\" Copyright (c) 2003-2004 Ryan McBride
|
||||
@ -26,12 +26,12 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 6, 2006
|
||||
.Dd February 17 2009
|
||||
.Dt PFSYNC 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pfsync
|
||||
.Nd packet filter state table logging interface
|
||||
.Nd packet filter state table sychronisation interface
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device pfsync"
|
||||
.Sh DESCRIPTION
|
||||
@ -40,26 +40,25 @@ The
|
||||
interface is a pseudo-device which exposes certain changes to the state
|
||||
table used by
|
||||
.Xr pf 4 .
|
||||
.\" XXX: not yet!
|
||||
.\" State changes can be viewed by invoking
|
||||
.\" .Xr tcpdump 1
|
||||
.\" on the
|
||||
.\" .Nm
|
||||
.\" interface.
|
||||
State changes can be viewed by invoking
|
||||
.Xr tcpdump 1
|
||||
on the
|
||||
.Nm
|
||||
interface.
|
||||
If configured with a physical synchronisation interface,
|
||||
.Nm
|
||||
will send state changes out on that interface using IP multicast,
|
||||
will also send state changes out on that interface,
|
||||
and insert state changes received on that interface from other systems
|
||||
into the state table.
|
||||
.Pp
|
||||
By default, all local changes to the state table are exposed via
|
||||
.Nm .
|
||||
However, state changes from packets received by
|
||||
State changes from packets received by
|
||||
.Nm
|
||||
over the network are not rebroadcast.
|
||||
States created by a rule marked with the
|
||||
Updates to states created by a rule marked with the
|
||||
.Ar no-sync
|
||||
keyword are omitted from the
|
||||
keyword are ignored by the
|
||||
.Nm
|
||||
interface (see
|
||||
.Xr pf.conf 5
|
||||
@ -67,33 +66,19 @@ for details).
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
interface will attempt to collapse multiple updates of the same
|
||||
state into one message where possible.
|
||||
The maximum number of times this can be done before the update is sent out
|
||||
is controlled by the
|
||||
interface will attempt to collapse multiple state updates into a single
|
||||
packet where possible.
|
||||
The maximum number of times a single state can be updated before a
|
||||
.Nm
|
||||
packet will be sent out is controlled by the
|
||||
.Ar maxupd
|
||||
parameter to ifconfig
|
||||
(see
|
||||
.Xr ifconfig 8
|
||||
and the example below for more details).
|
||||
.Pp
|
||||
Each packet retrieved on this interface has a header associated
|
||||
with it of length
|
||||
.Dv PFSYNC_HDRLEN .
|
||||
The header indicates the version of the protocol, address family,
|
||||
action taken on the following states, and the number of state
|
||||
table entries attached in this packet.
|
||||
This structure is defined in
|
||||
.Aq Pa net/if_pfsync.h
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
struct pfsync_header {
|
||||
u_int8_t version;
|
||||
u_int8_t af;
|
||||
u_int8_t action;
|
||||
u_int8_t count;
|
||||
};
|
||||
.Ed
|
||||
The sending out of a
|
||||
.Nm
|
||||
packet will be delayed by a maximum of one second.
|
||||
.Sh NETWORK SYNCHRONISATION
|
||||
States can be synchronised between two or more firewalls using this
|
||||
interface, by specifying a synchronisation interface using
|
||||
@ -104,18 +89,16 @@ interface:
|
||||
# ifconfig pfsync0 syncdev fxp0
|
||||
.Ed
|
||||
.Pp
|
||||
It is important that the underlying synchronisation interface is up
|
||||
and has an IP address assigned.
|
||||
.Pp
|
||||
By default, state change messages are sent out on the synchronisation
|
||||
interface using IP multicast packets.
|
||||
The protocol is IP protocol 240, PFSYNC, and the multicast group
|
||||
used is 224.0.0.240.
|
||||
When a peer address is specified using the
|
||||
interface using IP multicast packets to the 244.0.0.240 group address.
|
||||
An alternative destination address for
|
||||
.Nm
|
||||
packets can be specified using the
|
||||
.Ic syncpeer
|
||||
keyword, the peer address is used as a destination for the pfsync traffic,
|
||||
and the traffic can then be protected using
|
||||
.Xr ipsec 4 .
|
||||
keyword.
|
||||
This can be used in combination with
|
||||
.Xr ipsec 4
|
||||
to protect the synchronisation traffic.
|
||||
In such a configuration, the syncdev should be set to the
|
||||
.Xr enc 4
|
||||
interface, as this is where the traffic arrives when it is decapsulated,
|
||||
@ -127,50 +110,19 @@ e.g.:
|
||||
It is important that the pfsync traffic be well secured
|
||||
as there is no authentication on the protocol and it would
|
||||
be trivial to spoof packets which create states, bypassing the pf ruleset.
|
||||
Either run the pfsync protocol on a trusted network \- ideally a network
|
||||
Either run the pfsync protocol on a trusted network \- ideally a network
|
||||
dedicated to pfsync messages such as a crossover cable between two firewalls,
|
||||
or specify a peer address and protect the traffic with
|
||||
.Xr ipsec 4 .
|
||||
.Pp
|
||||
For
|
||||
.Nm
|
||||
to start its operation automatically at the system boot time,
|
||||
.Va pfsync_enable
|
||||
and
|
||||
.Va pfsync_syncdev
|
||||
variables should be used in
|
||||
.Xr rc.conf 5 .
|
||||
It is not advisable to set up
|
||||
.Nm
|
||||
with common network interface configuration variables of
|
||||
.Xr rc.conf 5
|
||||
because
|
||||
.Nm
|
||||
must start after its
|
||||
.Cm syncdev ,
|
||||
which cannot be always ensured in the latter case.
|
||||
.\" XXX: not yet!
|
||||
.\" .Pp
|
||||
.\" There is a one-to-one correspondence between packets seen by
|
||||
.\" .Xr bpf 4
|
||||
.\" on the
|
||||
.\" .Nm
|
||||
.\" interface, and packets sent out on the synchronisation interface, i.e.\&
|
||||
.\" a packet with 4 state deletion messages on
|
||||
.\" .Nm
|
||||
.\" means that the same 4 deletions were sent out on the synchronisation
|
||||
.\" interface.
|
||||
.\" However, the actual packet contents may differ as the messages
|
||||
.\" sent over the network are "compressed" where possible, containing
|
||||
.\" only the necessary information.
|
||||
.Sh EXAMPLES
|
||||
.Nm
|
||||
and
|
||||
.Xr carp 4
|
||||
can be used together to provide automatic failover of a pair of firewalls
|
||||
configured in parallel.
|
||||
One firewall handles all traffic \- if it dies or
|
||||
is shut down, the second firewall takes over automatically.
|
||||
One firewall will handle all traffic until it dies, is shut down, or is
|
||||
manually demoted, at which point the second firewall will take over
|
||||
automatically.
|
||||
.Pp
|
||||
Both firewalls in this example have three
|
||||
.Xr sis 4
|
||||
@ -208,12 +160,12 @@ traffic through.
|
||||
The following should be added to the top of
|
||||
.Pa /etc/pf.conf :
|
||||
.Bd -literal -offset indent
|
||||
pass quick on { sis2 } proto pfsync
|
||||
pass on { sis0 sis1 } proto carp
|
||||
pass quick on { sis2 } proto pfsync keep state (no-sync)
|
||||
pass on { sis0 sis1 } proto carp keep state (no-sync)
|
||||
.Ed
|
||||
.Pp
|
||||
If it is preferable that one firewall handle the traffic,
|
||||
the
|
||||
It is preferable that one firewall handle the forwarding of all the traffic,
|
||||
therefore the
|
||||
.Ar advskew
|
||||
on the backup firewall's
|
||||
.Xr carp 4
|
||||
@ -221,6 +173,7 @@ interfaces should be set to something higher than
|
||||
the primary's.
|
||||
For example, if firewall B is the backup, its
|
||||
carp1 configuration would look like this:
|
||||
would look like this:
|
||||
.Bd -literal -offset indent
|
||||
ifconfig_carp1="vhid 2 pass bar advskew 100 192.168.0.1/24"
|
||||
.Ed
|
||||
@ -230,16 +183,10 @@ The following must also be added to
|
||||
.Bd -literal -offset indent
|
||||
net.inet.carp.preempt=1
|
||||
.Ed
|
||||
.Sh BUGS
|
||||
Possibility to view state changes using
|
||||
.Xr tcpdump 1
|
||||
has not been ported from
|
||||
.Ox
|
||||
yet.
|
||||
.Sh SEE ALSO
|
||||
.Xr bpf 4 ,
|
||||
.Xr carp 4 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr enc 4 ,
|
||||
.Xr inet 4 ,
|
||||
.Xr inet6 4 ,
|
||||
.Xr ipsec 4 ,
|
||||
@ -247,16 +194,20 @@ yet.
|
||||
.Xr pf 4 ,
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr protocols 5 ,
|
||||
.Xr rc.conf 5
|
||||
.Xr rc.conf 5 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr ifstated 8 ,
|
||||
.Xr tcpdump 8
|
||||
.Xr tcpdump 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
device first appeared in
|
||||
.Ox 3.3 .
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
device was imported to
|
||||
.Fx 5.3 .
|
||||
protocol and kernel implementation were significantly modified between
|
||||
.Ox 4.4
|
||||
and
|
||||
.Ox 4.5 .
|
||||
The two protocols are incompatible and will not interoperate.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_print_state.c,v 1.44 2007/03/01 17:20:53 deraadt Exp $ */
|
||||
/* $OpenBSD: pf_print_state.c,v 1.52 2008/08/12 16:40:18 david Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -35,7 +35,10 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#define betoh64 be64toh
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
#define TCPSTATES
|
||||
#include <netinet/tcp_fsm.h>
|
||||
@ -83,6 +86,19 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
||||
else
|
||||
printf("<%s>", addr->v.tblname);
|
||||
return;
|
||||
case PF_ADDR_RANGE: {
|
||||
char buf[48];
|
||||
|
||||
if (inet_ntop(af, &addr->v.a.addr, buf, sizeof(buf)) == NULL)
|
||||
printf("?");
|
||||
else
|
||||
printf("%s", buf);
|
||||
if (inet_ntop(af, &addr->v.a.mask, buf, sizeof(buf)) == NULL)
|
||||
printf(" - ?");
|
||||
else
|
||||
printf(" - %s", buf);
|
||||
break;
|
||||
}
|
||||
case PF_ADDR_ADDRMASK:
|
||||
if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
|
||||
PF_AZERO(&addr->v.a.mask, AF_INET6))
|
||||
@ -112,7 +128,8 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
||||
}
|
||||
|
||||
/* mask if not _both_ address and mask are zero */
|
||||
if (!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
|
||||
if (addr->type != PF_ADDR_RANGE &&
|
||||
!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
|
||||
PF_AZERO(&addr->v.a.mask, AF_INET6))) {
|
||||
int bits = unmask(&addr->v.a.mask, af);
|
||||
|
||||
@ -155,17 +172,15 @@ print_name(struct pf_addr *addr, sa_family_t af)
|
||||
}
|
||||
|
||||
void
|
||||
print_host(struct pf_state_host *h, sa_family_t af, int opts)
|
||||
print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts)
|
||||
{
|
||||
u_int16_t p = ntohs(h->port);
|
||||
|
||||
if (opts & PF_OPT_USEDNS)
|
||||
print_name(&h->addr, af);
|
||||
print_name(addr, af);
|
||||
else {
|
||||
struct pf_addr_wrap aw;
|
||||
|
||||
memset(&aw, 0, sizeof(aw));
|
||||
aw.v.a.addr = h->addr;
|
||||
aw.v.a.addr = *addr;
|
||||
if (af == AF_INET)
|
||||
aw.v.a.mask.addr32[0] = 0xffffffff;
|
||||
else {
|
||||
@ -175,57 +190,72 @@ print_host(struct pf_state_host *h, sa_family_t af, int opts)
|
||||
print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
|
||||
}
|
||||
|
||||
if (p) {
|
||||
if (port) {
|
||||
if (af == AF_INET)
|
||||
printf(":%u", p);
|
||||
printf(":%u", ntohs(port));
|
||||
else
|
||||
printf("[%u]", p);
|
||||
printf("[%u]", ntohs(port));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_seq(struct pf_state_peer *p)
|
||||
print_seq(struct pfsync_state_peer *p)
|
||||
{
|
||||
if (p->seqdiff)
|
||||
printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
|
||||
p->seqdiff);
|
||||
printf("[%u + %u](+%u)", ntohl(p->seqlo),
|
||||
ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
|
||||
else
|
||||
printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
|
||||
printf("[%u + %u]", ntohl(p->seqlo),
|
||||
ntohl(p->seqhi) - ntohl(p->seqlo));
|
||||
}
|
||||
|
||||
void
|
||||
print_state(struct pf_state *s, int opts)
|
||||
print_state(struct pfsync_state *s, int opts)
|
||||
{
|
||||
struct pf_state_peer *src, *dst;
|
||||
struct pfsync_state_peer *src, *dst;
|
||||
struct pfsync_state_key *sk, *nk;
|
||||
struct protoent *p;
|
||||
int min, sec;
|
||||
|
||||
if (s->direction == PF_OUT) {
|
||||
src = &s->src;
|
||||
dst = &s->dst;
|
||||
sk = &s->key[PF_SK_STACK];
|
||||
nk = &s->key[PF_SK_WIRE];
|
||||
if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
|
||||
sk->port[0] = nk->port[0];
|
||||
} else {
|
||||
src = &s->dst;
|
||||
dst = &s->src;
|
||||
sk = &s->key[PF_SK_WIRE];
|
||||
nk = &s->key[PF_SK_STACK];
|
||||
if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
|
||||
sk->port[1] = nk->port[1];
|
||||
}
|
||||
printf("%s ", s->u.ifname);
|
||||
printf("%s ", s->ifname);
|
||||
if ((p = getprotobynumber(s->proto)) != NULL)
|
||||
printf("%s ", p->p_name);
|
||||
else
|
||||
printf("%u ", s->proto);
|
||||
if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
|
||||
(s->lan.port != s->gwy.port)) {
|
||||
print_host(&s->lan, s->af, opts);
|
||||
if (s->direction == PF_OUT)
|
||||
printf(" -> ");
|
||||
else
|
||||
printf(" <- ");
|
||||
|
||||
print_host(&nk->addr[1], nk->port[1], s->af, opts);
|
||||
if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
|
||||
nk->port[1] != sk->port[1]) {
|
||||
printf(" (");
|
||||
print_host(&sk->addr[1], sk->port[1], s->af, opts);
|
||||
printf(")");
|
||||
}
|
||||
print_host(&s->gwy, s->af, opts);
|
||||
if (s->direction == PF_OUT)
|
||||
printf(" -> ");
|
||||
else
|
||||
printf(" <- ");
|
||||
print_host(&s->ext, s->af, opts);
|
||||
print_host(&nk->addr[0], nk->port[0], s->af, opts);
|
||||
if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
|
||||
nk->port[0] != sk->port[0]) {
|
||||
printf(" (");
|
||||
print_host(&sk->addr[0], sk->port[0], s->af, opts);
|
||||
printf(")");
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
if (s->proto == IPPROTO_TCP) {
|
||||
@ -271,45 +301,63 @@ print_state(struct pf_state *s, int opts)
|
||||
}
|
||||
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
sec = s->creation % 60;
|
||||
s->creation /= 60;
|
||||
min = s->creation % 60;
|
||||
s->creation /= 60;
|
||||
printf(" age %.2u:%.2u:%.2u", s->creation, min, sec);
|
||||
sec = s->expire % 60;
|
||||
s->expire /= 60;
|
||||
min = s->expire % 60;
|
||||
s->expire /= 60;
|
||||
printf(", expires in %.2u:%.2u:%.2u", s->expire, min, sec);
|
||||
u_int64_t packets[2];
|
||||
u_int64_t bytes[2];
|
||||
u_int32_t creation = ntohl(s->creation);
|
||||
u_int32_t expire = ntohl(s->expire);
|
||||
|
||||
sec = creation % 60;
|
||||
creation /= 60;
|
||||
min = creation % 60;
|
||||
creation /= 60;
|
||||
printf(" age %.2u:%.2u:%.2u", creation, min, sec);
|
||||
sec = expire % 60;
|
||||
expire /= 60;
|
||||
min = expire % 60;
|
||||
expire /= 60;
|
||||
printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
|
||||
|
||||
bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
|
||||
bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
|
||||
bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
|
||||
bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
|
||||
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]);
|
||||
(unsigned long long)betoh64(packets[0]),
|
||||
(unsigned long long)betoh64(packets[1]),
|
||||
(unsigned long long)betoh64(bytes[0]),
|
||||
(unsigned long long)betoh64(bytes[1]));
|
||||
#else
|
||||
s->packets[0], s->packets[1], s->bytes[0], s->bytes[1]);
|
||||
betoh64(packets[0]),
|
||||
betoh64(packets[1]),
|
||||
betoh64(bytes[0]),
|
||||
betoh64(bytes[1]));
|
||||
#endif
|
||||
if (s->anchor.nr != -1)
|
||||
printf(", anchor %u", s->anchor.nr);
|
||||
if (s->rule.nr != -1)
|
||||
printf(", rule %u", s->rule.nr);
|
||||
if (ntohl(s->anchor) != -1)
|
||||
printf(", anchor %u", ntohl(s->anchor));
|
||||
if (ntohl(s->rule) != -1)
|
||||
printf(", rule %u", ntohl(s->rule));
|
||||
if (s->state_flags & PFSTATE_SLOPPY)
|
||||
printf(", sloppy");
|
||||
if (s->src_node != NULL)
|
||||
if (s->state_flags & PFSTATE_PFLOW)
|
||||
printf(", pflow");
|
||||
if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
|
||||
printf(", source-track");
|
||||
if (s->nat_src_node != NULL)
|
||||
if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
|
||||
printf(", sticky-address");
|
||||
printf("\n");
|
||||
}
|
||||
if (opts & PF_OPT_VERBOSE2) {
|
||||
printf(" id: %016llx creatorid: %08x%s\n",
|
||||
u_int64_t id;
|
||||
|
||||
bcopy(&s->id, &id, sizeof(u_int64_t));
|
||||
printf(" id: %016llx creatorid: %08x",
|
||||
#ifdef __FreeBSD__
|
||||
(unsigned long long)be64toh(s->id), ntohl(s->creatorid),
|
||||
(unsigned long long)betoh64(id), ntohl(s->creatorid));
|
||||
#else
|
||||
betoh64(s->id), ntohl(s->creatorid),
|
||||
betoh64(id), ntohl(s->creatorid));
|
||||
#endif
|
||||
((s->sync_flags & PFSTATE_NOSYNC) ? " (no-sync)" : ""));
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pfctl.8,v 1.128 2007/01/30 21:01:56 jmc Exp $
|
||||
.\" $OpenBSD: pfctl.8,v 1.138 2008/06/10 20:55:02 mcbride Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
|
||||
.\"
|
||||
@ -26,12 +26,12 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 13, 2011
|
||||
.Dd June 21, 2011
|
||||
.Dt PFCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pfctl
|
||||
.Nd "control the packet filter (PF) and network address translation (NAT) device"
|
||||
.Nd control the packet filter (PF) device
|
||||
.Sh SYNOPSIS
|
||||
.Nm pfctl
|
||||
.Bk -words
|
||||
@ -43,15 +43,18 @@
|
||||
.Op Fl f Ar file
|
||||
.Op Fl i Ar interface
|
||||
.Op Fl K Ar host | network
|
||||
.Op Fl k Ar host | network
|
||||
.Op Fl o Op Ar level
|
||||
.Xo
|
||||
.Oo Fl k
|
||||
.Ar host | network | label | id
|
||||
.Oc Xc
|
||||
.Op Fl o Ar level
|
||||
.Op Fl p Ar device
|
||||
.Op Fl s Ar modifier
|
||||
.Oo
|
||||
.Fl t Ar table
|
||||
.Xo
|
||||
.Oo Fl t Ar table
|
||||
.Fl T Ar command
|
||||
.Op Ar address ...
|
||||
.Oc
|
||||
.Op Ar address ... Oc
|
||||
.Xc
|
||||
.Op Fl x Ar level
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
@ -85,7 +88,7 @@ When the variable
|
||||
is set to
|
||||
.Dv YES
|
||||
in
|
||||
.Xr rc.conf.local 5 ,
|
||||
.Xr rc.conf.local 8 ,
|
||||
the rule file specified with the variable
|
||||
.Va pf_rules
|
||||
is loaded automatically by the
|
||||
@ -211,7 +214,7 @@ Flush the NAT rules.
|
||||
Flush the queue rules.
|
||||
.It Fl F Cm rules
|
||||
Flush the filter rules.
|
||||
.It Fl F Cm state
|
||||
.It Fl F Cm states
|
||||
Flush the state table (NAT and filter).
|
||||
.It Fl F Cm Sources
|
||||
Flush the source tracking table.
|
||||
@ -251,22 +254,28 @@ 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
|
||||
.It Xo
|
||||
.Fl k
|
||||
.Ar host | network | label | id
|
||||
.Xc
|
||||
Kill all of the state entries matching the specified
|
||||
.Ar host ,
|
||||
.Ar network ,
|
||||
.Ar label ,
|
||||
or
|
||||
.Ar network .
|
||||
.Ar id .
|
||||
.Pp
|
||||
For example, to kill all of the state entries originating from
|
||||
.Dq host :
|
||||
.Pp
|
||||
.Dl # pfctl -k host
|
||||
.Pp
|
||||
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 host/network to the second.
|
||||
For example, to kill all of the state entries originating from
|
||||
.Dq host :
|
||||
.Pp
|
||||
.Dl # pfctl -k host
|
||||
.Pp
|
||||
To kill all of the state entries from
|
||||
.Dq host1
|
||||
to
|
||||
@ -283,6 +292,32 @@ To kill all states with the target
|
||||
.Dq host2 :
|
||||
.Pp
|
||||
.Dl # pfctl -k 0.0.0.0/0 -k host2
|
||||
.Pp
|
||||
It is also possible to kill states by rule label or state ID.
|
||||
In this mode the first
|
||||
.Fl k
|
||||
argument is used to specify the type
|
||||
of the second argument.
|
||||
The following command would kill all states that have been created
|
||||
from rules carrying the label
|
||||
.Dq foobar :
|
||||
.Pp
|
||||
.Dl # pfctl -k label -k foobar
|
||||
.Pp
|
||||
To kill one specific state by its unique state ID
|
||||
(as shown by pfctl -s state -vv),
|
||||
use the
|
||||
.Ar id
|
||||
modifier and as a second argument the state ID and optional creator ID.
|
||||
To kill a state with ID 4823e84500000003 use:
|
||||
.Pp
|
||||
.Dl # pfctl -k id -k 4823e84500000003
|
||||
.Pp
|
||||
To kill a state with ID 4823e84500000018 created from a backup
|
||||
firewall with hostid 00000002 use:
|
||||
.Pp
|
||||
.Dl # pfctl -k id -k 4823e84500000018/2
|
||||
.Pp
|
||||
.It Fl m
|
||||
Merge in explicitly given options without resetting those
|
||||
which are omitted.
|
||||
@ -298,58 +333,20 @@ 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 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.
|
||||
.It Fl o Ar level
|
||||
Control the ruleset optimizer, overriding any rule file settings.
|
||||
.Pp
|
||||
.Bl -tag -width xxxxxxxxxxxx -compact
|
||||
.It Fl o Cm none
|
||||
Disable the ruleset optimizer.
|
||||
.It Fl o Cm basic
|
||||
Enable basic ruleset optimizations.
|
||||
This is the default behaviour.
|
||||
.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
|
||||
remove duplicate rules
|
||||
.It
|
||||
remove rules that are a subset of another rule
|
||||
.It
|
||||
combine multiple rules into a table when advantageous
|
||||
.It
|
||||
re-order the rules to improve evaluation performance
|
||||
.El
|
||||
.Pp
|
||||
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
|
||||
It is important to note that the ruleset optimizer will modify the ruleset
|
||||
to improve performance.
|
||||
A side effect of the ruleset modification is that per-rule accounting
|
||||
statistics will have different meanings than before.
|
||||
If per-rule accounting is important for billing purposes or whatnot, either
|
||||
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.
|
||||
For further information on the ruleset optimizer, see
|
||||
.Xr pf.conf 5 .
|
||||
.It Fl P
|
||||
Do not perform service name lookup for port specific rules,
|
||||
instead display the ports numerically.
|
||||
@ -407,7 +404,7 @@ If
|
||||
.Fl v
|
||||
is specified, all anchors attached under the target anchor will be
|
||||
displayed recursively.
|
||||
.It Fl s Cm state
|
||||
.It Fl s Cm states
|
||||
Show the contents of the state table.
|
||||
.It Fl s Cm Sources
|
||||
Show the contents of the source tracking table.
|
||||
@ -418,7 +415,7 @@ When used together with
|
||||
source tracking statistics are also shown.
|
||||
.It Fl s Cm labels
|
||||
Show per-rule statistics (label, evaluations, packets total, bytes total,
|
||||
packets in, bytes in, packets out, bytes out) of
|
||||
packets in, bytes in, packets out, bytes out, state creations) of
|
||||
filter rules with labels, useful for accounting.
|
||||
.It Fl s Cm timeouts
|
||||
Show the current global timeouts.
|
||||
@ -529,7 +526,7 @@ attributes.
|
||||
The address/network has been cleared (statistics).
|
||||
.El
|
||||
.Pp
|
||||
Each table maintains a set of counters that can be retrieved using the
|
||||
Each table can maintain a set of counters that can be retrieved using the
|
||||
.Fl v
|
||||
flag of
|
||||
.Nm .
|
||||
@ -540,7 +537,7 @@ FTP server.
|
||||
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
|
||||
# printf "table <test> counters { ftp.openbsd.org }\en \e
|
||||
pass out to <test>\en" | pfctl -f-
|
||||
# ping -qc10 ftp.openbsd.org
|
||||
.Ed
|
||||
@ -574,7 +571,7 @@ the number of rules which reference the table, and the global
|
||||
packet statistics for the whole table:
|
||||
.Bd -literal -offset indent
|
||||
# pfctl -vvsTables
|
||||
--a-r- test
|
||||
--a-r-C test
|
||||
Addresses: 1
|
||||
Cleared: Thu Feb 13 18:55:18 2003
|
||||
References: [ Anchors: 0 Rules: 1 ]
|
||||
@ -634,6 +631,8 @@ For tables which are referenced (used) by rules.
|
||||
.It h
|
||||
This flag is set when a table in the main ruleset is hidden by one or more
|
||||
tables of the same name from anchors attached below it.
|
||||
.It C
|
||||
This flag is set when per-address counters are enabled on the table.
|
||||
.El
|
||||
.It Fl t Ar table
|
||||
Specify the name of the table.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl.c,v 1.262 2007/03/01 17:20:53 deraadt Exp $ */
|
||||
/* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -39,6 +39,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/pfvar.h>
|
||||
@ -59,10 +63,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include "pfctl_parser.h"
|
||||
#include "pfctl.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define HTONL(x) (x) = htonl((__uint32_t)(x))
|
||||
#endif
|
||||
|
||||
void usage(void);
|
||||
int pfctl_enable(int, int);
|
||||
int pfctl_disable(int, int);
|
||||
@ -75,7 +75,9 @@ int pfctl_clear_src_nodes(int, int);
|
||||
int pfctl_clear_states(int, const char *, int);
|
||||
void pfctl_addrprefix(char *, struct pf_addr *);
|
||||
int pfctl_kill_src_nodes(int, const char *, int);
|
||||
int pfctl_kill_states(int, const char *, int);
|
||||
int pfctl_net_kill_states(int, const char *, int);
|
||||
int pfctl_label_kill_states(int, const char *, int);
|
||||
int pfctl_id_kill_states(int, const char *, int);
|
||||
void pfctl_init_options(struct pfctl *);
|
||||
int pfctl_load_options(struct pfctl *);
|
||||
int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
|
||||
@ -126,8 +128,6 @@ int dev = -1;
|
||||
int first_title = 1;
|
||||
int labels = 0;
|
||||
|
||||
const char *infile;
|
||||
|
||||
#define INDENT(d, o) do { \
|
||||
if (o) { \
|
||||
int i; \
|
||||
@ -208,11 +208,11 @@ static const struct {
|
||||
|
||||
static const char *clearopt_list[] = {
|
||||
"nat", "queue", "rules", "Sources",
|
||||
"state", "info", "Tables", "osfp", "all", NULL
|
||||
"states", "info", "Tables", "osfp", "all", NULL
|
||||
};
|
||||
|
||||
static const char *showopt_list[] = {
|
||||
"nat", "queue", "rules", "Anchors", "Sources", "state", "info",
|
||||
"nat", "queue", "rules", "Anchors", "Sources", "states", "info",
|
||||
"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
|
||||
"all", NULL
|
||||
};
|
||||
@ -227,7 +227,7 @@ static const char *debugopt_list[] = {
|
||||
};
|
||||
|
||||
static const char *optiopt_list[] = {
|
||||
"o", "none", "basic", "profile", NULL
|
||||
"none", "basic", "profile", NULL
|
||||
};
|
||||
|
||||
void
|
||||
@ -237,10 +237,11 @@ usage(void)
|
||||
|
||||
fprintf(stderr, "usage: %s [-AdeghmNnOPqRrvz] ", __progname);
|
||||
fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
|
||||
fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] ");
|
||||
fprintf(stderr, "[-k host | network ]\n");
|
||||
fprintf(stderr, "\t[-o [level]] [-p device] [-s modifier ]\n");
|
||||
fprintf(stderr, "\t[-t table -T command [address ...]] [-x level]\n");
|
||||
fprintf(stderr, "\t[-f file] [-i interface] [-K host | network]\n");
|
||||
fprintf(stderr, "\t[-k host | network | label | id] ");
|
||||
fprintf(stderr, "[-o level] [-p device]\n");
|
||||
fprintf(stderr, "\t[-s modifier] ");
|
||||
fprintf(stderr, "[-t table -T command [address ...]] [-x level]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -389,7 +390,7 @@ pfctl_clear_states(int dev, const char *iface, int opts)
|
||||
if (ioctl(dev, DIOCCLRSTATES, &psk))
|
||||
err(1, "DIOCCLRSTATES");
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "%d states cleared\n", psk.psk_af);
|
||||
fprintf(stderr, "%d states cleared\n", psk.psk_killed);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -528,17 +529,13 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
|
||||
|
||||
if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
|
||||
err(1, "DIOCKILLSRCNODES");
|
||||
killed += psnk.psnk_af;
|
||||
/* fixup psnk.psnk_af */
|
||||
psnk.psnk_af = resp[1]->ai_family;
|
||||
killed += psnk.psnk_killed;
|
||||
}
|
||||
freeaddrinfo(res[1]);
|
||||
} else {
|
||||
if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
|
||||
err(1, "DIOCKILLSRCNODES");
|
||||
killed += psnk.psnk_af;
|
||||
/* fixup psnk.psnk_af */
|
||||
psnk.psnk_af = res[0]->ai_family;
|
||||
killed += psnk.psnk_killed;
|
||||
}
|
||||
}
|
||||
|
||||
@ -551,7 +548,7 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_kill_states(int dev, const char *iface, int opts)
|
||||
pfctl_net_kill_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfioc_state_kill psk;
|
||||
struct addrinfo *res[2], *resp[2];
|
||||
@ -638,17 +635,13 @@ pfctl_kill_states(int dev, const char *iface, int opts)
|
||||
|
||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||
err(1, "DIOCKILLSTATES");
|
||||
killed += psk.psk_af;
|
||||
/* fixup psk.psk_af */
|
||||
psk.psk_af = resp[1]->ai_family;
|
||||
killed += psk.psk_killed;
|
||||
}
|
||||
freeaddrinfo(res[1]);
|
||||
} else {
|
||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||
err(1, "DIOCKILLSTATES");
|
||||
killed += psk.psk_af;
|
||||
/* fixup psk.psk_af */
|
||||
psk.psk_af = res[0]->ai_family;
|
||||
killed += psk.psk_killed;
|
||||
}
|
||||
}
|
||||
|
||||
@ -660,6 +653,68 @@ pfctl_kill_states(int dev, const char *iface, int opts)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_label_kill_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfioc_state_kill psk;
|
||||
|
||||
if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
|
||||
warnx("no label specified");
|
||||
usage();
|
||||
}
|
||||
memset(&psk, 0, sizeof(psk));
|
||||
if (iface != NULL && strlcpy(psk.psk_ifname, iface,
|
||||
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
|
||||
errx(1, "invalid interface: %s", iface);
|
||||
|
||||
if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >=
|
||||
sizeof(psk.psk_label))
|
||||
errx(1, "label too long: %s", state_kill[1]);
|
||||
|
||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||
err(1, "DIOCKILLSTATES");
|
||||
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "killed %d states\n", psk.psk_killed);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_id_kill_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfioc_state_kill psk;
|
||||
|
||||
if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
|
||||
warnx("no id specified");
|
||||
usage();
|
||||
}
|
||||
|
||||
memset(&psk, 0, sizeof(psk));
|
||||
if ((sscanf(state_kill[1], "%jx/%x",
|
||||
&psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2)
|
||||
HTONL(psk.psk_pfcmp.creatorid);
|
||||
else if ((sscanf(state_kill[1], "%jx", &psk.psk_pfcmp.id)) == 1) {
|
||||
psk.psk_pfcmp.creatorid = 0;
|
||||
} else {
|
||||
warnx("wrong id format specified");
|
||||
usage();
|
||||
}
|
||||
if (psk.psk_pfcmp.id == 0) {
|
||||
warnx("cannot kill id 0");
|
||||
usage();
|
||||
}
|
||||
|
||||
psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id);
|
||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||
err(1, "DIOCKILLSTATES");
|
||||
|
||||
if ((opts & PF_OPT_QUIET) == 0)
|
||||
fprintf(stderr, "killed %d states\n", psk.psk_killed);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
|
||||
u_int32_t ticket, int r_action, char *anchorname)
|
||||
@ -747,10 +802,12 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts)
|
||||
(unsigned long long)(rule->packets[0] +
|
||||
rule->packets[1]),
|
||||
(unsigned long long)(rule->bytes[0] +
|
||||
rule->bytes[1]), rule->states);
|
||||
rule->bytes[1]), rule->states_cur);
|
||||
if (!(opts & PF_OPT_DEBUG))
|
||||
printf(" [ Inserted: uid %u pid %u ]\n",
|
||||
(unsigned)rule->cuid, (unsigned)rule->cpid);
|
||||
printf(" [ Inserted: uid %u pid %u "
|
||||
"State Creations: %-6u]\n",
|
||||
(unsigned)rule->cuid, (unsigned)rule->cpid,
|
||||
rule->states_tot);
|
||||
}
|
||||
}
|
||||
|
||||
@ -818,19 +875,6 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
|
||||
|
||||
switch (format) {
|
||||
case PFCTL_SHOW_LABELS:
|
||||
if (pr.rule.label[0]) {
|
||||
printf("%s ", pr.rule.label);
|
||||
printf("%llu %llu %llu %llu %llu %llu %llu\n",
|
||||
(unsigned long long)pr.rule.evaluations,
|
||||
(unsigned long long)(pr.rule.packets[0] +
|
||||
pr.rule.packets[1]),
|
||||
(unsigned long long)(pr.rule.bytes[0] +
|
||||
pr.rule.bytes[1]),
|
||||
(unsigned long long)pr.rule.packets[0],
|
||||
(unsigned long long)pr.rule.bytes[0],
|
||||
(unsigned long long)pr.rule.packets[1],
|
||||
(unsigned long long)pr.rule.bytes[1]);
|
||||
}
|
||||
break;
|
||||
case PFCTL_SHOW_RULES:
|
||||
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
|
||||
@ -864,8 +908,9 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
|
||||
switch (format) {
|
||||
case PFCTL_SHOW_LABELS:
|
||||
if (pr.rule.label[0]) {
|
||||
printf("%s ", pr.rule.label);
|
||||
printf("%llu %llu %llu %llu %llu %llu %llu\n",
|
||||
printf("%s %llu %llu %llu %llu"
|
||||
" %llu %llu %llu %llu\n",
|
||||
pr.rule.label,
|
||||
(unsigned long long)pr.rule.evaluations,
|
||||
(unsigned long long)(pr.rule.packets[0] +
|
||||
pr.rule.packets[1]),
|
||||
@ -874,7 +919,8 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
|
||||
(unsigned long long)pr.rule.packets[0],
|
||||
(unsigned long long)pr.rule.bytes[0],
|
||||
(unsigned long long)pr.rule.packets[1],
|
||||
(unsigned long long)pr.rule.bytes[1]);
|
||||
(unsigned long long)pr.rule.bytes[1],
|
||||
(unsigned long long)pr.rule.states_tot);
|
||||
}
|
||||
break;
|
||||
case PFCTL_SHOW_RULES:
|
||||
@ -967,7 +1013,7 @@ pfctl_show_src_nodes(int dev, int opts)
|
||||
struct pfioc_src_nodes psn;
|
||||
struct pf_src_node *p;
|
||||
char *inbuf = NULL, *newinbuf = NULL;
|
||||
unsigned len = 0;
|
||||
unsigned int len = 0;
|
||||
int i;
|
||||
|
||||
memset(&psn, 0, sizeof(psn));
|
||||
@ -1010,9 +1056,9 @@ int
|
||||
pfctl_show_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfioc_states ps;
|
||||
struct pf_state *p;
|
||||
struct pfsync_state *p;
|
||||
char *inbuf = NULL, *newinbuf = NULL;
|
||||
unsigned len = 0;
|
||||
unsigned int len = 0;
|
||||
int i, dotitle = (opts & PF_OPT_SHOWALL);
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
@ -1041,7 +1087,7 @@ pfctl_show_states(int dev, const char *iface, int opts)
|
||||
}
|
||||
p = ps.ps_states;
|
||||
for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
|
||||
if (iface != NULL && strcmp(p->u.ifname, iface))
|
||||
if (iface != NULL && strcmp(p->ifname, iface))
|
||||
continue;
|
||||
if (dotitle) {
|
||||
pfctl_print_title("STATES:");
|
||||
@ -1163,7 +1209,7 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
|
||||
r->anchor->ruleset.anchor = r->anchor;
|
||||
if (strlcpy(r->anchor->path, anchor_call,
|
||||
sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
|
||||
errx(1, "pfctl_add_rule: strlcpy");
|
||||
errx(1, "pfctl_add_rule: strlcpy");
|
||||
if ((p = strrchr(anchor_call, '/')) != NULL) {
|
||||
if (!strlen(p))
|
||||
err(1, "pfctl_add_rule: bad anchor name %s",
|
||||
@ -1172,7 +1218,7 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
|
||||
p = (char *)anchor_call;
|
||||
if (strlcpy(r->anchor->name, p,
|
||||
sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
|
||||
errx(1, "pfctl_add_rule: strlcpy");
|
||||
errx(1, "pfctl_add_rule: strlcpy");
|
||||
}
|
||||
|
||||
if ((rule = calloc(1, sizeof(*rule))) == NULL)
|
||||
@ -1197,7 +1243,7 @@ pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
|
||||
return (1);
|
||||
}
|
||||
if (a == pf->astack[0] && ((altqsupport &&
|
||||
(pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
|
||||
(pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
|
||||
if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path))
|
||||
return (2);
|
||||
}
|
||||
@ -1350,7 +1396,7 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
|
||||
pfctl_rules(int dev, char *filename, int opts, int optimize,
|
||||
char *anchorname, struct pfr_buffer *trans)
|
||||
{
|
||||
#define ERR(x) do { warn(x); goto _error; } while(0)
|
||||
@ -1386,7 +1432,6 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
|
||||
if (strlcpy(trs.pfrt_anchor, anchorname,
|
||||
sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
|
||||
ERRX("pfctl_rules: strlcpy");
|
||||
infile = filename;
|
||||
pf.dev = dev;
|
||||
pf.opts = opts;
|
||||
pf.optimize = optimize;
|
||||
@ -1430,7 +1475,7 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
|
||||
pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname);
|
||||
}
|
||||
|
||||
if (parse_rules(fin, &pf) < 0) {
|
||||
if (parse_config(filename, &pf) < 0) {
|
||||
if ((opts & PF_OPT_NOACTION) == 0)
|
||||
ERRX("Syntax error in config file: "
|
||||
"pf rules not loaded");
|
||||
@ -1456,11 +1501,6 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
|
||||
if (check_commit_altq(dev, opts) != 0)
|
||||
ERRX("errors in altq config");
|
||||
|
||||
if (fin != stdin) {
|
||||
fclose(fin);
|
||||
fin = NULL;
|
||||
}
|
||||
|
||||
/* process "load anchor" directives */
|
||||
if (!anchorname[0])
|
||||
if (pfctl_load_anchors(dev, &pf, t) == -1)
|
||||
@ -1482,8 +1522,6 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
|
||||
err(1, "DIOCXROLLBACK");
|
||||
exit(1);
|
||||
} else { /* sub ruleset */
|
||||
if (fin != NULL && fin != stdin)
|
||||
fclose(fin);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -1515,7 +1553,8 @@ pfctl_fopen(const char *name, const char *mode)
|
||||
void
|
||||
pfctl_init_options(struct pfctl *pf)
|
||||
{
|
||||
int mib[2], mem;
|
||||
int64_t mem;
|
||||
int mib[2];
|
||||
size_t size;
|
||||
|
||||
pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
|
||||
@ -1546,9 +1585,14 @@ pfctl_init_options(struct pfctl *pf)
|
||||
pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
|
||||
|
||||
mib[0] = CTL_HW;
|
||||
#ifdef __FreeBSD__
|
||||
mib[1] = HW_PHYSMEM;
|
||||
#else
|
||||
mib[1] = HW_PHYSMEM64;
|
||||
#endif
|
||||
size = sizeof(mem);
|
||||
(void) sysctl(mib, 2, &mem, &size, NULL, 0);
|
||||
if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1)
|
||||
err(1, "sysctl");
|
||||
if (mem <= 100*1024*1024)
|
||||
pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL;
|
||||
|
||||
@ -1572,7 +1616,7 @@ pfctl_load_options(struct pfctl *pf)
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've set the limit, but havn't explicitly set adaptive
|
||||
* If we've set the limit, but haven't explicitly set adaptive
|
||||
* timeouts, do it now with a start of 60% and end of 120%.
|
||||
*/
|
||||
if (pf->limit_set[PF_LIMIT_STATES] &&
|
||||
@ -1897,9 +1941,6 @@ pfctl_debug(int dev, u_int32_t level, int opts)
|
||||
int
|
||||
pfctl_test_altqsupport(int dev, int opts)
|
||||
{
|
||||
#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ)
|
||||
return (0);
|
||||
#else
|
||||
struct pfioc_altq pa;
|
||||
|
||||
if (ioctl(dev, DIOCGETALTQS, &pa)) {
|
||||
@ -1912,7 +1953,6 @@ pfctl_test_altqsupport(int dev, int opts)
|
||||
err(1, "DIOCGETALTQS");
|
||||
}
|
||||
return (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@ -1971,16 +2011,15 @@ main(int argc, char *argv[])
|
||||
int ch;
|
||||
int mode = O_RDONLY;
|
||||
int opts = 0;
|
||||
int optimize = 0;
|
||||
int optimize = PF_OPTIMIZE_BASIC;
|
||||
char anchorname[MAXPATHLEN];
|
||||
char *path;
|
||||
FILE *fin = NULL;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
while ((ch = getopt(argc, argv,
|
||||
"a:AdD:eqf:F:ghi:k:K:mnNOo::Pp:rRs:t:T:vx:z")) != -1) {
|
||||
"a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
anchoropt = optarg;
|
||||
@ -2056,24 +2095,11 @@ main(int argc, char *argv[])
|
||||
loadopt |= PFCTL_FLAG_FILTER;
|
||||
break;
|
||||
case 'o':
|
||||
if (optarg) {
|
||||
optiopt = pfctl_lookup_option(optarg,
|
||||
optiopt_list);
|
||||
if (optiopt == NULL) {
|
||||
warnx("Unknown optimization '%s'",
|
||||
optarg);
|
||||
usage();
|
||||
}
|
||||
optiopt = pfctl_lookup_option(optarg, optiopt_list);
|
||||
if (optiopt == NULL) {
|
||||
warnx("Unknown optimization '%s'", optarg);
|
||||
usage();
|
||||
}
|
||||
if (opts & PF_OPT_OPTIMIZE) {
|
||||
if (optiopt != NULL) {
|
||||
warnx("Cannot specify -o multiple times"
|
||||
"with optimizer level");
|
||||
usage();
|
||||
}
|
||||
optimize |= PF_OPTIMIZE_PROFILE;
|
||||
}
|
||||
optimize |= PF_OPTIMIZE_BASIC;
|
||||
opts |= PF_OPT_OPTIMIZE;
|
||||
break;
|
||||
case 'O':
|
||||
@ -2303,8 +2329,14 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state_killers)
|
||||
pfctl_kill_states(dev, ifaceopt, opts);
|
||||
if (state_killers) {
|
||||
if (!strcmp(state_kill[0], "label"))
|
||||
pfctl_label_kill_states(dev, ifaceopt, opts);
|
||||
else if (!strcmp(state_kill[0], "id"))
|
||||
pfctl_id_kill_states(dev, ifaceopt, opts);
|
||||
else
|
||||
pfctl_net_kill_states(dev, ifaceopt, opts);
|
||||
}
|
||||
|
||||
if (src_node_killers)
|
||||
pfctl_kill_src_nodes(dev, ifaceopt, opts);
|
||||
@ -2329,15 +2361,6 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (rulesopt != NULL) {
|
||||
if (strcmp(rulesopt, "-") == 0) {
|
||||
fin = stdin;
|
||||
rulesopt = "stdin";
|
||||
} else {
|
||||
if ((fin = pfctl_fopen(rulesopt, "r")) == NULL)
|
||||
err(1, "%s", rulesopt);
|
||||
}
|
||||
}
|
||||
if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
|
||||
!anchorname[0])
|
||||
if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
|
||||
@ -2352,7 +2375,7 @@ main(int argc, char *argv[])
|
||||
if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
|
||||
errx(1, "anchor names beginning with '_' cannot "
|
||||
"be modified from the command line");
|
||||
if (pfctl_rules(dev, rulesopt, fin, opts, optimize,
|
||||
if (pfctl_rules(dev, rulesopt, opts, optimize,
|
||||
anchorname, NULL))
|
||||
error = 1;
|
||||
else if (!(opts & PF_OPT_NOACTION) &&
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl.h,v 1.40 2007/02/09 11:25:27 henning Exp $ */
|
||||
/* $OpenBSD: pfctl.h,v 1.42 2007/12/05 12:01:47 chl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -49,7 +49,6 @@ struct pfr_buffer {
|
||||
(var) != NULL; \
|
||||
(var) = pfr_buf_next((buf), (var)))
|
||||
|
||||
void pfr_set_fd(int);
|
||||
int pfr_get_fd(void);
|
||||
int pfr_clr_tables(struct pfr_table *, int *, int);
|
||||
int pfr_add_tables(struct pfr_table *, int, int *, int);
|
||||
@ -64,9 +63,7 @@ int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||
int *, int *, int *, int);
|
||||
int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
|
||||
int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
|
||||
int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
|
||||
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||
int *, int, int);
|
||||
void pfr_buf_clear(struct pfr_buffer *);
|
||||
@ -91,6 +88,8 @@ FILE *pfctl_fopen(const char *, const char *);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
extern int altqsupport;
|
||||
extern int dummynetsupport;
|
||||
#define HTONL(x) (x) = htonl((__uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_PRIORITY
|
||||
@ -117,9 +116,9 @@ struct pf_altq *pfaltq_lookup(const char *);
|
||||
char *rate2str(double);
|
||||
|
||||
void print_addr(struct pf_addr_wrap *, sa_family_t, int);
|
||||
void print_host(struct pf_state_host *, sa_family_t, int);
|
||||
void print_seq(struct pf_state_peer *);
|
||||
void print_state(struct pf_state *, int);
|
||||
void print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
|
||||
void print_seq(struct pfsync_state_peer *);
|
||||
void print_state(struct pfsync_state *, int);
|
||||
int unmask(struct pf_addr *, sa_family_t);
|
||||
|
||||
int pfctl_cmdline_symset(char *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.91 2006/11/28 00:08:50 henning Exp $ */
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.93 2007/10/15 02:16:35 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002
|
||||
@ -21,7 +21,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@ -78,7 +78,7 @@ static int gsc_add_seg(struct gen_sc *, double, double, double,
|
||||
static double sc_x2y(struct service_curve *, double);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
u_int32_t getifspeed(int, char *);
|
||||
u_int32_t getifspeed(int, char *);
|
||||
#else
|
||||
u_int32_t getifspeed(char *);
|
||||
#endif
|
||||
@ -145,8 +145,8 @@ qname_to_qid(const char *qname)
|
||||
}
|
||||
|
||||
void
|
||||
print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
|
||||
struct node_queue_opt *qopts)
|
||||
print_altq(const struct pf_altq *a, unsigned int level,
|
||||
struct node_queue_bw *bw, struct node_queue_opt *qopts)
|
||||
{
|
||||
if (a->qname[0] != 0) {
|
||||
print_queue(a, level, bw, 1, qopts);
|
||||
@ -157,6 +157,7 @@ print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
|
||||
if (a->local_flags & PFALTQ_FLAG_IF_REMOVED)
|
||||
printf("INACTIVE ");
|
||||
#endif
|
||||
|
||||
printf("altq on %s ", a->ifname);
|
||||
|
||||
switch (a->scheduler) {
|
||||
@ -186,10 +187,11 @@ print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
|
||||
}
|
||||
|
||||
void
|
||||
print_queue(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
|
||||
int print_interface, struct node_queue_opt *qopts)
|
||||
print_queue(const struct pf_altq *a, unsigned int level,
|
||||
struct node_queue_bw *bw, int print_interface,
|
||||
struct node_queue_opt *qopts)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (a->local_flags & PFALTQ_FLAG_IF_REMOVED)
|
||||
@ -893,9 +895,6 @@ print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
|
||||
/*
|
||||
* admission control using generalized service curve
|
||||
*/
|
||||
#ifndef INFINITY
|
||||
#define INFINITY HUGE_VAL /* positive infinity defined in <math.h> */
|
||||
#endif
|
||||
|
||||
/* add a new service curve to a generalized service curve */
|
||||
static void
|
||||
@ -1132,8 +1131,6 @@ getifspeed(char *ifname)
|
||||
ifr.ifr_data = (caddr_t)&ifrdat;
|
||||
if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGIFDATA");
|
||||
if (shutdown(s, SHUT_RDWR) == -1)
|
||||
err(1, "shutdown");
|
||||
if (close(s))
|
||||
err(1, "close");
|
||||
return ((u_int32_t)ifrdat.ifi_baudrate);
|
||||
@ -1158,8 +1155,6 @@ getifmtu(char *ifname)
|
||||
#else
|
||||
err(1, "SIOCGIFMTU");
|
||||
#endif
|
||||
if (shutdown(s, SHUT_RDWR) == -1)
|
||||
err(1, "shutdown");
|
||||
if (close(s))
|
||||
err(1, "close");
|
||||
if (ifr.ifr_mtu > 0)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_optimize.c,v 1.13 2006/10/31 14:17:45 mcbride Exp $ */
|
||||
/* $OpenBSD: pfctl_optimize.c,v 1.17 2008/05/06 03:45:21 mpf Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org>
|
||||
@ -185,7 +185,8 @@ struct pf_rule_field {
|
||||
PF_RULE_FIELD(packets, DC),
|
||||
PF_RULE_FIELD(bytes, DC),
|
||||
PF_RULE_FIELD(kif, DC),
|
||||
PF_RULE_FIELD(states, DC),
|
||||
PF_RULE_FIELD(states_cur, DC),
|
||||
PF_RULE_FIELD(states_tot, DC),
|
||||
PF_RULE_FIELD(src_nodes, DC),
|
||||
PF_RULE_FIELD(nr, DC),
|
||||
PF_RULE_FIELD(entries, DC),
|
||||
@ -201,6 +202,7 @@ struct pf_rule_field {
|
||||
PF_RULE_FIELD(natpass, NEVER),
|
||||
PF_RULE_FIELD(max_mss, NEVER),
|
||||
PF_RULE_FIELD(min_ttl, NEVER),
|
||||
PF_RULE_FIELD(set_tos, NEVER),
|
||||
};
|
||||
|
||||
|
||||
@ -398,7 +400,7 @@ optimize_superblock(struct pfctl *pf, struct superblock *block)
|
||||
* out rules.
|
||||
*/
|
||||
|
||||
/* shortcut. there will be alot of 1-rule superblocks */
|
||||
/* shortcut. there will be a lot of 1-rule superblocks */
|
||||
if (!TAILQ_NEXT(TAILQ_FIRST(&block->sb_rules), por_entry))
|
||||
return (0);
|
||||
|
||||
@ -1320,8 +1322,9 @@ pf_opt_create_table(struct pfctl *pf, struct pf_opt_tbl *tbl)
|
||||
|
||||
|
||||
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);
|
||||
pf->astack[0]->name, tbl->pt_buf, pf->astack[0]->ruleset.tticket)) {
|
||||
warn("failed to create table %s in %s",
|
||||
tbl->pt_name, pf->astack[0]->name);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
@ -1424,7 +1427,7 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Have to handle interface groups seperately. Consider the following
|
||||
* Have to handle interface groups separately. Consider the following
|
||||
* rules:
|
||||
* block on EXTIFS to any port 22
|
||||
* pass on em0 to any port 22
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_osfp.c,v 1.15 2006/12/13 05:10:15 itojun Exp $ */
|
||||
/* $OpenBSD: pfctl_osfp.c,v 1.14 2006/04/08 02:13:14 ray Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Mike Frantzen <frantzen@openbsd.org>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_parser.c,v 1.234 2006/10/31 23:46:24 mcbride Exp $ */
|
||||
/* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
@ -500,7 +499,7 @@ print_status(struct pf_status *s, int opts)
|
||||
running = s->running ? "Enabled" : "Disabled";
|
||||
|
||||
if (s->since) {
|
||||
unsigned sec, min, hrs, day = runtime;
|
||||
unsigned int sec, min, hrs, day = runtime;
|
||||
|
||||
sec = day % 60;
|
||||
day /= 60;
|
||||
@ -581,7 +580,11 @@ print_status(struct pf_status *s, int opts)
|
||||
s->src_nodes, "");
|
||||
for (i = 0; i < SCNT_MAX; i++) {
|
||||
printf(" %-25s %14lld ", pf_scounters[i],
|
||||
(unsigned long long)s->scounters[i]);
|
||||
#ifdef __FreeBSD__
|
||||
(long long)s->scounters[i]);
|
||||
#else
|
||||
s->scounters[i]);
|
||||
#endif
|
||||
if (runtime > 0)
|
||||
printf("%14.1f/s\n",
|
||||
(double)s->scounters[i] / (double)runtime);
|
||||
@ -952,6 +955,12 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
|
||||
printf("sloppy");
|
||||
opts = 0;
|
||||
}
|
||||
if (r->rule_flag & PFRULE_PFLOW) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("pflow");
|
||||
opts = 0;
|
||||
}
|
||||
for (i = 0; i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i]) {
|
||||
int j;
|
||||
@ -979,6 +988,8 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
|
||||
printf(" min-ttl %d", r->min_ttl);
|
||||
if (r->max_mss)
|
||||
printf(" max-mss %d", r->max_mss);
|
||||
if (r->rule_flag & PFRULE_SET_TOS)
|
||||
printf(" set-tos 0x%2.2x", r->set_tos);
|
||||
if (r->allow_opts)
|
||||
printf(" allow-opts");
|
||||
if (r->action == PF_SCRUB) {
|
||||
@ -1007,6 +1018,26 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
|
||||
}
|
||||
if (r->rtableid != -1)
|
||||
printf(" rtable %u", r->rtableid);
|
||||
if (r->divert.port) {
|
||||
#ifdef __FreeBSD__
|
||||
printf(" divert-to %u", ntohs(r->divert.port));
|
||||
#else
|
||||
if (PF_AZERO(&r->divert.addr, r->af)) {
|
||||
printf(" divert-reply");
|
||||
} else {
|
||||
/* XXX cut&paste from print_addr */
|
||||
char buf[48];
|
||||
|
||||
printf(" divert-to ");
|
||||
if (inet_ntop(r->af, &r->divert.addr, buf,
|
||||
sizeof(buf)) == NULL)
|
||||
printf("?");
|
||||
else
|
||||
printf("%s", buf);
|
||||
printf(" port %u", ntohs(r->divert.port));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!anchor_call[0] && (r->action == PF_NAT ||
|
||||
r->action == PF_BINAT || r->action == PF_RDR)) {
|
||||
printf(" -> ");
|
||||
@ -1027,6 +1058,8 @@ print_tabledef(const char *name, int flags, int addrs,
|
||||
printf(" const");
|
||||
if (flags & PFR_TFLAG_PERSIST)
|
||||
printf(" persist");
|
||||
if (flags & PFR_TFLAG_COUNTERS)
|
||||
printf(" counters");
|
||||
SIMPLEQ_FOREACH(ti, nodes, entries) {
|
||||
if (ti->file) {
|
||||
printf(" file \"%s\"", ti->file);
|
||||
|
@ -172,10 +172,10 @@ struct node_queue_opt {
|
||||
#define SIMPLEQ_END(head) NULL
|
||||
#define SIMPLEQ_EMPTY STAILQ_EMPTY
|
||||
#define SIMPLEQ_NEXT STAILQ_NEXT
|
||||
/*#define SIMPLEQ_FOREACH STAILQ_FOREACH*/
|
||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||
for((var) = SIMPLEQ_FIRST(head); \
|
||||
(var) != SIMPLEQ_END(head); \
|
||||
/*#define SIMPLEQ_FOREACH STAILQ_FOREACH*/
|
||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||
for((var) = SIMPLEQ_FIRST(head); \
|
||||
(var) != SIMPLEQ_END(head); \
|
||||
(var) = SIMPLEQ_NEXT(var, field))
|
||||
#define SIMPLEQ_INIT STAILQ_INIT
|
||||
#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD
|
||||
@ -213,7 +213,7 @@ struct pf_opt_rule {
|
||||
|
||||
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
|
||||
|
||||
int pfctl_rules(int, char *, FILE *, int, int, char *, struct pfr_buffer *);
|
||||
int pfctl_rules(int, char *, 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 *);
|
||||
@ -230,7 +230,7 @@ int pfctl_set_hostid(struct pfctl *, u_int32_t);
|
||||
int pfctl_set_debug(struct pfctl *, char *);
|
||||
int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
|
||||
|
||||
int parse_rules(FILE *, struct pfctl *);
|
||||
int parse_config(char *, struct pfctl *);
|
||||
int parse_flags(char *);
|
||||
int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *);
|
||||
|
||||
|
@ -73,7 +73,7 @@ void pfctl_insert_altq_node(struct pf_altq_node **,
|
||||
struct pf_altq_node *pfctl_find_altq_node(struct pf_altq_node *,
|
||||
const char *, const char *);
|
||||
void pfctl_print_altq_node(int, const struct pf_altq_node *,
|
||||
unsigned, int);
|
||||
unsigned, int);
|
||||
void print_cbqstats(struct queue_stats);
|
||||
void print_priqstats(struct queue_stats);
|
||||
void print_hfscstats(struct queue_stats);
|
||||
@ -185,8 +185,8 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
|
||||
}
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
|
||||
memset(&qstats.data, 0, sizeof(qstats.data));
|
||||
else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
|
||||
memset(&qstats.data, 0, sizeof(qstats.data));
|
||||
if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
|
||||
pa.altq.ifname)) != NULL) {
|
||||
memcpy(&node->qstats.data, &qstats.data,
|
||||
@ -262,8 +262,8 @@ pfctl_find_altq_node(struct pf_altq_node *root, const char *qname,
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned level,
|
||||
int opts)
|
||||
pfctl_print_altq_node(int dev, const struct pf_altq_node *node,
|
||||
unsigned int level, int opts)
|
||||
{
|
||||
const struct pf_altq_node *child;
|
||||
|
||||
@ -302,11 +302,11 @@ pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
|
||||
{
|
||||
if (a->altq.qid == 0)
|
||||
return;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (a->altq.local_flags & PFALTQ_FLAG_IF_REMOVED)
|
||||
return;
|
||||
#endif
|
||||
|
||||
switch (a->altq.scheduler) {
|
||||
case ALTQT_CBQ:
|
||||
print_cbqstats(a->qstats);
|
||||
|
@ -30,6 +30,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
@ -299,29 +302,6 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
int *nzero, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size < 0 || (size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRCLRASTATS, &io))
|
||||
return (-1);
|
||||
if (nzero != NULL)
|
||||
*nzero = io.pfrio_nzero;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
|
||||
{
|
||||
@ -343,32 +323,6 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
|
||||
int *nchange, int *ndel, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size < 0 || (size && !tbl)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = size;
|
||||
io.pfrio_setflag = setflag;
|
||||
io.pfrio_clrflag = clrflag;
|
||||
if (ioctl(dev, DIOCRSETTFLAGS, &io))
|
||||
return (-1);
|
||||
if (nchange)
|
||||
*nchange = io.pfrio_nchange;
|
||||
if (ndel)
|
||||
*ndel = io.pfrio_ndel;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
int *nmatch, int flags)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_table.c,v 1.66 2007/03/01 17:20:54 deraadt Exp $ */
|
||||
/* $OpenBSD: pfctl_table.c,v 1.67 2008/06/10 20:55:02 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Cedric Berger
|
||||
@ -275,12 +275,14 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
PFRB_FOREACH(p, &b)
|
||||
PFRB_FOREACH(p, &b) {
|
||||
((struct pfr_astats *)p)->pfras_a.pfra_fback = 0;
|
||||
if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero >
|
||||
lifetime)
|
||||
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;
|
||||
@ -367,13 +369,14 @@ print_table(struct pfr_table *ta, int verbose, int debug)
|
||||
if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
|
||||
return;
|
||||
if (verbose) {
|
||||
printf("%c%c%c%c%c%c\t%s",
|
||||
printf("%c%c%c%c%c%c%c\t%s",
|
||||
(ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-',
|
||||
ta->pfrt_name);
|
||||
if (ta->pfrt_anchor[0])
|
||||
printf("\t%s", ta->pfrt_anchor);
|
||||
@ -428,7 +431,7 @@ void
|
||||
print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns)
|
||||
{
|
||||
char ch, buf[256] = "{error}";
|
||||
char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y' };
|
||||
char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y', ' ' };
|
||||
unsigned int fback, hostnet;
|
||||
|
||||
fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback;
|
||||
@ -477,6 +480,8 @@ print_astats(struct pfr_astats *as, int dns)
|
||||
|
||||
print_addrx(&as->pfras_a, NULL, dns);
|
||||
printf("\tCleared: %s", ctime(&time));
|
||||
if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT)
|
||||
return;
|
||||
for (dir = 0; dir < PFR_DIR_MAX; dir++)
|
||||
for (op = 0; op < PFR_OP_ADDR_MAX; op++)
|
||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: pflogd.8,v 1.32 2006/12/08 10:26:38 joel Exp $
|
||||
.\" $OpenBSD: pflogd.8,v 1.37 2008/10/22 08:16:49 henning Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Can Erkin Acar. All rights reserved.
|
||||
.\"
|
||||
@ -26,7 +26,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 9, 2001
|
||||
.Dd October 22 2008
|
||||
.Dt PFLOGD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -34,12 +34,14 @@
|
||||
.Nd packet filter logging daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm pflogd
|
||||
.Bk -words
|
||||
.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
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a background daemon which reads packets logged by
|
||||
@ -94,6 +96,13 @@ or a
|
||||
.Dv SIGALRM
|
||||
is received.
|
||||
.Pp
|
||||
.Nm
|
||||
will also log the pcap statistics for the
|
||||
.Xr pflog 4
|
||||
interface to syslog when a
|
||||
.Dv SIGUSR1
|
||||
is received.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl D
|
||||
@ -116,6 +125,11 @@ By default,
|
||||
.Nm
|
||||
will use
|
||||
.Ar pflog0 .
|
||||
Writes a file containing the process ID of the program to
|
||||
.Pa /var/run .
|
||||
The file name has the form
|
||||
The default is
|
||||
.Ar pflogd .
|
||||
.It Fl s Ar snaplen
|
||||
Analyze at most the first
|
||||
.Ar snaplen
|
||||
@ -204,12 +218,12 @@ the wi0 interface:
|
||||
# tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr tcpdump 1 ,
|
||||
.Xr pcap 3 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr pflog 4 ,
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr newsyslog 8
|
||||
.Xr newsyslog 8 ,
|
||||
.Xr tcpdump 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pflogd.c,v 1.37 2006/10/26 13:34:47 jmc Exp $ */
|
||||
/* $OpenBSD: pflogd.c,v 1.46 2008/10/22 08:16:49 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Theo de Raadt
|
||||
@ -37,9 +37,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <net/bpf.h> /* BIOCLOCK */
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -48,15 +47,16 @@ __FBSDID("$FreeBSD$");
|
||||
#include <pcap.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <ifaddrs.h>
|
||||
#include "pidfile.h"
|
||||
#else
|
||||
#include <util.h>
|
||||
#endif
|
||||
|
||||
#include "pflogd.h"
|
||||
|
||||
pcap_t *hpcap;
|
||||
@ -66,7 +66,7 @@ int Debug = 0;
|
||||
static int snaplen = DEF_SNAPLEN;
|
||||
static int cur_snaplen = DEF_SNAPLEN;
|
||||
|
||||
volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup;
|
||||
volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup, gotsig_usr1;
|
||||
|
||||
char *filename = PFLOGD_LOG_FILE;
|
||||
char *interface = PFLOGD_DEFAULT_IF;
|
||||
@ -80,7 +80,9 @@ unsigned int delay = FLUSH_DELAY;
|
||||
char *copy_argv(char * const *);
|
||||
void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
|
||||
void dump_packet_nobuf(u_char *, const struct pcap_pkthdr *, const u_char *);
|
||||
void log_pcap_stats(void);
|
||||
int flush_buffer(FILE *);
|
||||
int if_exists(char *);
|
||||
int init_pcap(void);
|
||||
void logmsg(int, const char *, ...);
|
||||
void purge_buffer(void);
|
||||
@ -89,6 +91,7 @@ int scan_dump(FILE *, off_t);
|
||||
int set_snaplen(int);
|
||||
void set_suspended(int);
|
||||
void sig_alrm(int);
|
||||
void sig_usr1(int);
|
||||
void sig_close(int);
|
||||
void sig_hup(int);
|
||||
void usage(void);
|
||||
@ -166,8 +169,8 @@ __dead void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename]");
|
||||
fprintf(stderr, " [-i interface] [-s snaplen]\n");
|
||||
fprintf(stderr, " [expression]\n");
|
||||
fprintf(stderr, " [-i interface] [-p pidfile]\n");
|
||||
fprintf(stderr, " [-s snaplen] [expression]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -189,6 +192,12 @@ sig_alrm(int sig)
|
||||
gotsig_alrm = 1;
|
||||
}
|
||||
|
||||
void
|
||||
sig_usr1(int sig)
|
||||
{
|
||||
gotsig_usr1 = 1;
|
||||
}
|
||||
|
||||
void
|
||||
set_pcap_filter(void)
|
||||
{
|
||||
@ -203,6 +212,51 @@ set_pcap_filter(void)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
if_exists(char *ifname)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
struct ifaddrs *ifdata, *mb;
|
||||
int exists = 0;
|
||||
|
||||
getifaddrs(&ifdata);
|
||||
if (ifdata == NULL)
|
||||
return (0);
|
||||
|
||||
for (mb = ifdata; mb != NULL; mb = mb->ifa_next) {
|
||||
if (mb == NULL)
|
||||
continue;
|
||||
if (strlen(ifname) != strlen(mb->ifa_name))
|
||||
continue;
|
||||
if (strncmp(ifname, mb->ifa_name, strlen(ifname)) != 0)
|
||||
continue;
|
||||
exists = 1;
|
||||
break;
|
||||
}
|
||||
freeifaddrs(ifdata);
|
||||
|
||||
return (exists);
|
||||
#else
|
||||
int s;
|
||||
struct ifreq ifr;
|
||||
struct if_data ifrdat;
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
err(1, "socket");
|
||||
bzero(&ifr, sizeof(ifr));
|
||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
||||
sizeof(ifr.ifr_name))
|
||||
errx(1, "main ifr_name: strlcpy");
|
||||
ifr.ifr_data = (caddr_t)&ifrdat;
|
||||
if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1)
|
||||
return (0);
|
||||
if (close(s))
|
||||
err(1, "close");
|
||||
|
||||
return (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
init_pcap(void)
|
||||
{
|
||||
@ -556,8 +610,8 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
|
||||
|
||||
append:
|
||||
#ifdef __FreeBSD__
|
||||
sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
|
||||
sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
|
||||
sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
|
||||
sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
|
||||
sh.caplen = h->caplen;
|
||||
sh.len = h->len;
|
||||
|
||||
@ -575,17 +629,31 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
log_pcap_stats(void)
|
||||
{
|
||||
struct pcap_stat pstat;
|
||||
if (pcap_stats(hpcap, &pstat) < 0)
|
||||
logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
|
||||
else
|
||||
logmsg(LOG_NOTICE,
|
||||
"%u packets received, %u/%u dropped (kernel/pflogd)",
|
||||
pstat.ps_recv, pstat.ps_drop, packets_dropped);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct pcap_stat pstat;
|
||||
int ch, np, Xflag = 0;
|
||||
int ch, np, ret, Xflag = 0;
|
||||
pcap_handler phandler = dump_packet;
|
||||
const char *errstr = NULL;
|
||||
char *pidf = NULL;
|
||||
|
||||
ret = 0;
|
||||
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
while ((ch = getopt(argc, argv, "Dxd:f:i:s:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "Dxd:f:i:p:s:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'D':
|
||||
Debug = 1;
|
||||
@ -601,6 +669,9 @@ main(int argc, char **argv)
|
||||
case 'i':
|
||||
interface = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
pidf = optarg;
|
||||
break;
|
||||
case 's':
|
||||
snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
|
||||
&errstr);
|
||||
@ -622,13 +693,21 @@ main(int argc, char **argv)
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* does interface exist */
|
||||
if (!if_exists(interface)) {
|
||||
warn("Failed to initialize: %s", interface);
|
||||
logmsg(LOG_ERR, "Failed to initialize: %s", interface);
|
||||
logmsg(LOG_ERR, "Exiting, init failure");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!Debug) {
|
||||
openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
|
||||
if (daemon(0, 0)) {
|
||||
logmsg(LOG_WARNING, "Failed to become daemon: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
pidfile(NULL);
|
||||
pidfile(pidf);
|
||||
}
|
||||
|
||||
tzset();
|
||||
@ -659,6 +738,7 @@ main(int argc, char **argv)
|
||||
signal(SIGINT, sig_close);
|
||||
signal(SIGQUIT, sig_close);
|
||||
signal(SIGALRM, sig_alrm);
|
||||
signal(SIGUSR1, sig_usr1);
|
||||
signal(SIGHUP, sig_hup);
|
||||
alarm(delay);
|
||||
|
||||
@ -686,13 +766,12 @@ main(int argc, char **argv)
|
||||
np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
|
||||
phandler, (u_char *)dpcap);
|
||||
if (np < 0) {
|
||||
#ifdef __FreeBSD__
|
||||
if (errno == ENXIO) {
|
||||
logmsg(LOG_ERR,
|
||||
"Device not/no longer configured");
|
||||
if (!if_exists(interface) == -1) {
|
||||
logmsg(LOG_NOTICE, "interface %s went away",
|
||||
interface);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
|
||||
}
|
||||
|
||||
@ -715,6 +794,11 @@ main(int argc, char **argv)
|
||||
gotsig_alrm = 0;
|
||||
alarm(delay);
|
||||
}
|
||||
|
||||
if (gotsig_usr1) {
|
||||
log_pcap_stats();
|
||||
gotsig_usr1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
logmsg(LOG_NOTICE, "Exiting");
|
||||
@ -724,15 +808,9 @@ main(int argc, char **argv)
|
||||
}
|
||||
purge_buffer();
|
||||
|
||||
if (pcap_stats(hpcap, &pstat) < 0)
|
||||
logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
|
||||
else
|
||||
logmsg(LOG_NOTICE,
|
||||
"%u packets received, %u/%u dropped (kernel/pflogd)",
|
||||
pstat.ps_recv, pstat.ps_drop, packets_dropped);
|
||||
|
||||
log_pcap_stats();
|
||||
pcap_close(hpcap);
|
||||
if (!Debug)
|
||||
closelog();
|
||||
return (0);
|
||||
return (ret);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/bpf.h>
|
||||
@ -31,20 +32,13 @@ __FBSDID("$FreeBSD$");
|
||||
#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"
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: privsep_fdpass.c,v 1.2 2004/08/13 02:51:48 djm Exp $ */
|
||||
/* $OpenBSD: privsep_fdpass.c,v 1.5 2008/03/24 16:11:08 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
@ -50,7 +50,10 @@ void
|
||||
send_fd(int sock, int fd)
|
||||
{
|
||||
struct msghdr msg;
|
||||
char tmp[CMSG_SPACE(sizeof(int))];
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
char buf[CMSG_SPACE(sizeof(int))];
|
||||
} cmsgbuf;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec vec;
|
||||
int result = 0;
|
||||
@ -59,8 +62,8 @@ send_fd(int sock, int fd)
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
if (fd >= 0) {
|
||||
msg.msg_control = (caddr_t)tmp;
|
||||
msg.msg_controllen = CMSG_LEN(sizeof(int));
|
||||
msg.msg_control = (caddr_t)&cmsgbuf.buf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf.buf);
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
@ -86,7 +89,10 @@ int
|
||||
receive_fd(int sock)
|
||||
{
|
||||
struct msghdr msg;
|
||||
char tmp[CMSG_SPACE(sizeof(int))];
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
char buf[CMSG_SPACE(sizeof(int))];
|
||||
} cmsgbuf;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec vec;
|
||||
ssize_t n;
|
||||
@ -98,8 +104,8 @@ receive_fd(int sock)
|
||||
vec.iov_len = sizeof(int);
|
||||
msg.msg_iov = &vec;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = tmp;
|
||||
msg.msg_controllen = sizeof(tmp);
|
||||
msg.msg_control = &cmsgbuf.buf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf.buf);
|
||||
|
||||
if ((n = recvmsg(sock, &msg, 0)) == -1)
|
||||
warn("%s: recvmsg", __func__);
|
||||
|
@ -8,7 +8,7 @@ MAN= pflogd.8
|
||||
|
||||
CFLAGS+=-include ${.CURDIR}/../../lib/libpcap/config.h
|
||||
|
||||
LDADD= -lpcap -lutil
|
||||
LDADD= -lpcap
|
||||
DPADD= ${LIBPCAP} ${LIBUTIL}
|
||||
|
||||
WARNS?= 2
|
||||
|
@ -386,14 +386,14 @@ contrib/pf/net/pf_if.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/net/pf_ioctl.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/net/pf_lb.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/net/pf_norm.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/net/pf_osfp.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/net/pf_ruleset.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/net/pf_subr.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/net/pf_table.c optional pf inet \
|
||||
compile-with "${NORMAL_C} -I$S/contrib/pf"
|
||||
contrib/pf/netinet/in4_cksum.c optional pf inet
|
||||
|
@ -514,11 +514,9 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
|
||||
struct mbuf *m0;
|
||||
struct pf_mtag *at;
|
||||
void *hdr;
|
||||
int af;
|
||||
|
||||
at = pf_find_mtag(m);
|
||||
if (at != NULL) {
|
||||
af = at->af;
|
||||
hdr = at->hdr;
|
||||
#ifdef ALTQ3_COMPAT
|
||||
} else if (pktattr != NULL) {
|
||||
@ -528,9 +526,6 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
|
||||
} else
|
||||
return (0);
|
||||
|
||||
if (af != AF_INET && af != AF_INET6)
|
||||
return (0);
|
||||
|
||||
/* verify that pattr_hdr is within the mbuf data */
|
||||
for (m0 = m; m0 != NULL; m0 = m0->m_next)
|
||||
if (((caddr_t)hdr >= m0->m_data) &&
|
||||
@ -541,8 +536,8 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
switch (((struct ip *)hdr)->ip_v) {
|
||||
case IPVERSION:
|
||||
if (flags & REDF_ECN4) {
|
||||
struct ip *ip = hdr;
|
||||
u_int8_t otos;
|
||||
@ -575,7 +570,7 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
|
||||
}
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
case (IPV6_VERSION >> 4):
|
||||
if (flags & REDF_ECN6) {
|
||||
struct ip6_hdr *ip6 = hdr;
|
||||
u_int32_t flowlabel;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: if_pflog.c,v 1.22 2006/12/15 09:31:20 otto Exp $ */
|
||||
/* $OpenBSD: if_pflog.c,v 1.26 2007/10/18 21:58:18 mpf Exp $ */
|
||||
/*
|
||||
* The authors of this code are John Ioannidis (ji@tla.org),
|
||||
* Angelos D. Keromytis (kermit@csd.uch.gr) and
|
||||
@ -99,11 +99,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pflog.h>
|
||||
|
||||
#ifdef INET
|
||||
#ifdef __FreeBSD__
|
||||
#ifdef INET
|
||||
#include <machine/in_cksum.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif /* INET */
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#define PFLOGMTU (32768 + MHLEN + MLEN)
|
||||
|
||||
@ -115,7 +115,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
void pflogattach(int);
|
||||
int pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct route *);
|
||||
#ifdef __FreeBSD__
|
||||
struct route *);
|
||||
#else
|
||||
struct rtentry *);
|
||||
#endif
|
||||
int pflogioctl(struct ifnet *, u_long, caddr_t);
|
||||
void pflogstart(struct ifnet *);
|
||||
#ifdef __FreeBSD__
|
||||
@ -136,10 +140,6 @@ struct if_clone pflog_cloner =
|
||||
|
||||
struct ifnet *pflogifs[PFLOGIFS_MAX]; /* for fast access */
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
extern int ifqmaxlen;
|
||||
#endif
|
||||
|
||||
void
|
||||
pflogattach(int npflog)
|
||||
{
|
||||
@ -147,9 +147,6 @@ pflogattach(int npflog)
|
||||
LIST_INIT(&pflogif_list);
|
||||
for (i = 0; i < PFLOGIFS_MAX; i++)
|
||||
pflogifs[i] = NULL;
|
||||
#ifndef __FreeBSD__
|
||||
(void) pflog_clone_create(&pflog_cloner, 0);
|
||||
#endif
|
||||
if_clone_attach(&pflog_cloner);
|
||||
}
|
||||
|
||||
@ -168,9 +165,9 @@ pflog_clone_create(struct if_clone *ifc, int unit)
|
||||
if (unit >= PFLOGIFS_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
if ((pflogif = malloc(sizeof(*pflogif), M_DEVBUF, M_NOWAIT)) == NULL)
|
||||
if ((pflogif = malloc(sizeof(*pflogif),
|
||||
M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
|
||||
return (ENOMEM);
|
||||
bzero(pflogif, sizeof(*pflogif));
|
||||
|
||||
pflogif->sc_unit = unit;
|
||||
#ifdef __FreeBSD__
|
||||
@ -209,6 +206,7 @@ pflog_clone_create(struct if_clone *ifc, int unit)
|
||||
|
||||
s = splnet();
|
||||
#ifdef __FreeBSD__
|
||||
/* XXX: Why pf(4) lock?! Better add a pflog lock?! */
|
||||
PF_LOCK();
|
||||
#endif
|
||||
LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list);
|
||||
@ -289,7 +287,11 @@ pflogstart(struct ifnet *ifp)
|
||||
|
||||
int
|
||||
pflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
|
||||
struct route *ro)
|
||||
#ifdef __FreeBSD__
|
||||
struct route *rt)
|
||||
#else
|
||||
struct rtentry *rt)
|
||||
#endif
|
||||
{
|
||||
m_freem(m);
|
||||
return (0);
|
||||
@ -300,9 +302,6 @@ int
|
||||
pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDR:
|
||||
case SIOCAIFADDR:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCSIFFLAGS:
|
||||
#ifdef __FreeBSD__
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
@ -317,7 +316,7 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -333,7 +332,7 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
|
||||
struct pfloghdr hdr;
|
||||
|
||||
if (kif == NULL || m == NULL || rm == NULL || pd == NULL)
|
||||
return (-1);
|
||||
return ( 1);
|
||||
|
||||
if ((ifn = pflogifs[rm->logif]) == NULL || !ifn->if_bpf)
|
||||
return (0);
|
||||
@ -347,7 +346,7 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
|
||||
|
||||
if (am == NULL) {
|
||||
hdr.rulenr = htonl(rm->nr);
|
||||
hdr.subrulenr = -1;
|
||||
hdr.subrulenr = 1;
|
||||
} else {
|
||||
hdr.rulenr = htonl(am->nr);
|
||||
hdr.subrulenr = htonl(rm->nr);
|
||||
@ -361,7 +360,7 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
|
||||
* XXX: This should not happen as we force an early lookup
|
||||
* via debug.pfugidhack
|
||||
*/
|
||||
; /* empty */
|
||||
; /* empty */
|
||||
#else
|
||||
pd->lookup.done = pf_socket_lookup(dir, pd);
|
||||
#endif
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: if_pflog.h,v 1.14 2006/10/25 11:27:01 henning Exp $ */
|
||||
/* $OpenBSD: if_pflog.h,v 1.13 2006/10/23 12:46:09 henning Exp $ */
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
@ -26,11 +25,10 @@
|
||||
*/
|
||||
|
||||
#ifndef _NET_IF_PFLOG_H_
|
||||
#define _NET_IF_PFLOG_H_
|
||||
#define _NET_IF_PFLOG_H_
|
||||
|
||||
#define PFLOGIFS_MAX 16
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct pflog_softc {
|
||||
#ifdef __FreeBSD__
|
||||
struct ifnet *sc_ifp; /* the interface pointer */
|
||||
@ -40,9 +38,8 @@ struct pflog_softc {
|
||||
int sc_unit;
|
||||
LIST_ENTRY(pflog_softc) sc_list;
|
||||
};
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#define PFLOG_RULESET_NAME_SIZE 16
|
||||
#define PFLOG_RULESET_NAME_SIZE 16
|
||||
|
||||
struct pfloghdr {
|
||||
u_int8_t length;
|
||||
@ -61,9 +58,9 @@ struct pfloghdr {
|
||||
u_int8_t pad[3];
|
||||
};
|
||||
|
||||
#define PFLOG_HDRLEN sizeof(struct pfloghdr)
|
||||
#define PFLOG_HDRLEN sizeof(struct pfloghdr)
|
||||
/* minus pad, also used as a signature */
|
||||
#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad)
|
||||
#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad)
|
||||
|
||||
/* XXX remove later when old format logs are no longer needed */
|
||||
struct old_pfloghdr {
|
||||
@ -74,23 +71,24 @@ struct old_pfloghdr {
|
||||
u_short action;
|
||||
u_short dir;
|
||||
};
|
||||
#define OLD_PFLOG_HDRLEN sizeof(struct old_pfloghdr)
|
||||
#define OLD_PFLOG_HDRLEN sizeof(struct old_pfloghdr)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
struct pf_rule;
|
||||
struct pf_ruleset;
|
||||
struct pfi_kif;
|
||||
struct pf_pdesc;
|
||||
|
||||
#if 0
|
||||
typedef int pflog_packet_t(struct pfi_kif *, struct mbuf *, sa_family_t,
|
||||
u_int8_t, u_int8_t, struct pf_rule *, struct pf_rule *,
|
||||
struct pf_ruleset *, struct pf_pdesc *);
|
||||
extern pflog_packet_t *pflog_packet_ptr;
|
||||
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) do { \
|
||||
if (pflog_packet_ptr != NULL) \
|
||||
pflog_packet_ptr(i,a,b,c,d,e,f,g,h); \
|
||||
#endif
|
||||
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) do { \
|
||||
if (pflog_packet_ptr != NULL) \
|
||||
pflog_packet_ptr(i,a,b,c,d,e,f,g,h); \
|
||||
} while (0)
|
||||
#else /* ! __FreeBSD__ */
|
||||
#if NPFLOG > 0
|
||||
@ -98,6 +96,6 @@ extern pflog_packet_t *pflog_packet_ptr;
|
||||
#else
|
||||
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) ((void)0)
|
||||
#endif /* NPFLOG > 0 */
|
||||
#endif /* __FreeBSD__ */
|
||||
#endif
|
||||
#endif /* _KERNEL */
|
||||
#endif /* _NET_IF_PFLOG_H_ */
|
||||
|
126
sys/contrib/pf/net/if_pflow.h
Normal file
126
sys/contrib/pf/net/if_pflow.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* $OpenBSD: if_pflow.h,v 1.5 2009/02/27 11:09:36 gollo Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Henning Brauer <henning@openbsd.org>
|
||||
* Copyright (c) 2008 Joerg Goltermann <jg@osn.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, 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$
|
||||
*/
|
||||
|
||||
#ifndef _NET_IF_PFLOW_H_
|
||||
#define _NET_IF_PFLOW_H_
|
||||
|
||||
#define PFLOW_ID_LEN sizeof(u_int64_t)
|
||||
|
||||
#define PFLOW_MAXFLOWS 30
|
||||
#define PFLOW_VERSION 5
|
||||
#define PFLOW_ENGINE_TYPE 42
|
||||
#define PFLOW_ENGINE_ID 42
|
||||
#define PFLOW_MAXBYTES 0xffffffff
|
||||
#define PFLOW_TIMEOUT 30
|
||||
|
||||
struct pflow_flow {
|
||||
u_int32_t src_ip;
|
||||
u_int32_t dest_ip;
|
||||
u_int32_t nexthop_ip;
|
||||
u_int16_t if_index_in;
|
||||
u_int16_t if_index_out;
|
||||
u_int32_t flow_packets;
|
||||
u_int32_t flow_octets;
|
||||
u_int32_t flow_start;
|
||||
u_int32_t flow_finish;
|
||||
u_int16_t src_port;
|
||||
u_int16_t dest_port;
|
||||
u_int8_t pad1;
|
||||
u_int8_t tcp_flags;
|
||||
u_int8_t protocol;
|
||||
u_int8_t tos;
|
||||
u_int16_t src_as;
|
||||
u_int16_t dest_as;
|
||||
u_int8_t src_mask;
|
||||
u_int8_t dest_mask;
|
||||
u_int16_t pad2;
|
||||
} __packed;
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
extern int pflow_ok;
|
||||
|
||||
struct pflow_softc {
|
||||
struct ifnet sc_if;
|
||||
struct ifnet *sc_pflow_ifp;
|
||||
|
||||
unsigned int sc_count;
|
||||
unsigned int sc_maxcount;
|
||||
u_int64_t sc_gcounter;
|
||||
struct ip_moptions sc_imo;
|
||||
#ifdef __FreeBSD__
|
||||
struct callout sc_tmo;
|
||||
#else
|
||||
struct timeout sc_tmo;
|
||||
#endif
|
||||
struct in_addr sc_sender_ip;
|
||||
u_int16_t sc_sender_port;
|
||||
struct in_addr sc_receiver_ip;
|
||||
u_int16_t sc_receiver_port;
|
||||
struct mbuf *sc_mbuf; /* current cumulative mbuf */
|
||||
SLIST_ENTRY(pflow_softc) sc_next;
|
||||
};
|
||||
|
||||
extern struct pflow_softc *pflowif;
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
struct pflow_header {
|
||||
u_int16_t version;
|
||||
u_int16_t count;
|
||||
u_int32_t uptime_ms;
|
||||
u_int32_t time_sec;
|
||||
u_int32_t time_nanosec;
|
||||
u_int32_t flow_sequence;
|
||||
u_int8_t engine_type;
|
||||
u_int8_t engine_id;
|
||||
u_int8_t reserved1;
|
||||
u_int8_t reserved2;
|
||||
} __packed;
|
||||
|
||||
#define PFLOW_HDRLEN sizeof(struct pflow_header)
|
||||
|
||||
struct pflowstats {
|
||||
u_int64_t pflow_flows;
|
||||
u_int64_t pflow_packets;
|
||||
u_int64_t pflow_onomem;
|
||||
u_int64_t pflow_oerrors;
|
||||
};
|
||||
|
||||
/*
|
||||
* Configuration structure for SIOCSETPFLOW SIOCGETPFLOW
|
||||
*/
|
||||
struct pflowreq {
|
||||
struct in_addr sender_ip;
|
||||
struct in_addr receiver_ip;
|
||||
u_int16_t receiver_port;
|
||||
u_int16_t addrmask;
|
||||
#define PFLOW_MASK_SRCIP 0x01
|
||||
#define PFLOW_MASK_DSTIP 0x02
|
||||
#define PFLOW_MASK_DSTPRT 0x04
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
int export_pflow(struct pf_state *);
|
||||
int pflow_sysctl(int *, u_int, void *, size_t *, void *, size_t);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NET_IF_PFLOW_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,4 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: if_pfsync.h,v 1.30 2006/10/31 14:49:01 henning Exp $ */
|
||||
/* $OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Michael Shalayeff
|
||||
@ -27,227 +26,217 @@
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 David Gwynne <dlg@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NET_IF_PFSYNC_H_
|
||||
#define _NET_IF_PFSYNC_H_
|
||||
#define _NET_IF_PFSYNC_H_
|
||||
|
||||
#define PFSYNC_VERSION 5
|
||||
#define PFSYNC_DFLTTL 255
|
||||
|
||||
#define PFSYNC_ID_LEN sizeof(u_int64_t)
|
||||
|
||||
struct pfsync_state_scrub {
|
||||
u_int16_t pfss_flags;
|
||||
u_int8_t pfss_ttl; /* stashed TTL */
|
||||
#define PFSYNC_SCRUB_FLAG_VALID 0x01
|
||||
u_int8_t scrub_flag;
|
||||
u_int32_t pfss_ts_mod; /* timestamp modulation */
|
||||
} __packed;
|
||||
|
||||
struct pfsync_state_host {
|
||||
struct pf_addr addr;
|
||||
u_int16_t port;
|
||||
u_int16_t pad[3];
|
||||
} __packed;
|
||||
|
||||
struct pfsync_state_peer {
|
||||
struct pfsync_state_scrub scrub; /* state is scrubbed */
|
||||
u_int32_t seqlo; /* Max sequence number sent */
|
||||
u_int32_t seqhi; /* Max the other end ACKd + win */
|
||||
u_int32_t seqdiff; /* Sequence number modulator */
|
||||
u_int16_t max_win; /* largest window (pre scaling) */
|
||||
u_int16_t mss; /* Maximum segment size option */
|
||||
u_int8_t state; /* active state level */
|
||||
u_int8_t wscale; /* window scaling factor */
|
||||
u_int8_t pad[6];
|
||||
} __packed;
|
||||
|
||||
struct pfsync_state {
|
||||
u_int32_t id[2];
|
||||
char ifname[IFNAMSIZ];
|
||||
struct pfsync_state_host lan;
|
||||
struct pfsync_state_host gwy;
|
||||
struct pfsync_state_host ext;
|
||||
struct pfsync_state_peer src;
|
||||
struct pfsync_state_peer dst;
|
||||
struct pf_addr rt_addr;
|
||||
u_int32_t rule;
|
||||
u_int32_t anchor;
|
||||
u_int32_t nat_rule;
|
||||
u_int32_t creation;
|
||||
u_int32_t expire;
|
||||
u_int32_t packets[2][2];
|
||||
u_int32_t bytes[2][2];
|
||||
u_int32_t creatorid;
|
||||
sa_family_t af;
|
||||
u_int8_t proto;
|
||||
u_int8_t direction;
|
||||
u_int8_t log;
|
||||
u_int8_t state_flags;
|
||||
u_int8_t timeout;
|
||||
u_int8_t sync_flags;
|
||||
u_int8_t updates;
|
||||
} __packed;
|
||||
|
||||
#define PFSYNC_FLAG_COMPRESS 0x01
|
||||
#define PFSYNC_FLAG_STALE 0x02
|
||||
|
||||
#ifdef PFSYNC_TDB
|
||||
struct pfsync_tdb {
|
||||
u_int32_t spi;
|
||||
union sockaddr_union dst;
|
||||
u_int32_t rpl;
|
||||
u_int64_t cur_bytes;
|
||||
u_int8_t sproto;
|
||||
u_int8_t updates;
|
||||
u_int8_t pad[2];
|
||||
} __packed;
|
||||
#endif
|
||||
|
||||
struct pfsync_state_upd {
|
||||
u_int32_t id[2];
|
||||
struct pfsync_state_peer src;
|
||||
struct pfsync_state_peer dst;
|
||||
u_int32_t creatorid;
|
||||
u_int32_t expire;
|
||||
u_int8_t timeout;
|
||||
u_int8_t updates;
|
||||
u_int8_t pad[6];
|
||||
} __packed;
|
||||
|
||||
struct pfsync_state_del {
|
||||
u_int32_t id[2];
|
||||
u_int32_t creatorid;
|
||||
struct {
|
||||
u_int8_t state;
|
||||
} src;
|
||||
struct {
|
||||
u_int8_t state;
|
||||
} dst;
|
||||
u_int8_t pad[2];
|
||||
} __packed;
|
||||
|
||||
struct pfsync_state_upd_req {
|
||||
u_int32_t id[2];
|
||||
u_int32_t creatorid;
|
||||
u_int32_t pad;
|
||||
} __packed;
|
||||
|
||||
struct pfsync_state_clr {
|
||||
char ifname[IFNAMSIZ];
|
||||
u_int32_t creatorid;
|
||||
u_int32_t pad;
|
||||
} __packed;
|
||||
|
||||
struct pfsync_state_bus {
|
||||
u_int32_t creatorid;
|
||||
u_int32_t endtime;
|
||||
u_int8_t status;
|
||||
#define PFSYNC_BUS_START 1
|
||||
#define PFSYNC_BUS_END 2
|
||||
u_int8_t pad[7];
|
||||
} __packed;
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
union sc_statep {
|
||||
struct pfsync_state *s;
|
||||
struct pfsync_state_upd *u;
|
||||
struct pfsync_state_del *d;
|
||||
struct pfsync_state_clr *c;
|
||||
struct pfsync_state_bus *b;
|
||||
struct pfsync_state_upd_req *r;
|
||||
};
|
||||
|
||||
#ifdef PFSYNC_TDB
|
||||
union sc_tdb_statep {
|
||||
struct pfsync_tdb *t;
|
||||
};
|
||||
#endif
|
||||
|
||||
extern int pfsync_sync_ok;
|
||||
|
||||
struct pfsync_softc {
|
||||
#ifdef __FreeBSD__
|
||||
struct ifnet *sc_ifp;
|
||||
#else
|
||||
struct ifnet sc_if;
|
||||
#endif
|
||||
struct ifnet *sc_sync_ifp;
|
||||
|
||||
struct ip_moptions sc_imo;
|
||||
#ifdef __FreeBSD__
|
||||
struct callout sc_tmo;
|
||||
#ifdef PFSYNC_TDB
|
||||
struct callout sc_tdb_tmo;
|
||||
#endif
|
||||
struct callout sc_bulk_tmo;
|
||||
struct callout sc_bulkfail_tmo;
|
||||
#else
|
||||
struct timeout sc_tmo;
|
||||
struct timeout sc_tdb_tmo;
|
||||
struct timeout sc_bulk_tmo;
|
||||
struct timeout sc_bulkfail_tmo;
|
||||
#endif
|
||||
struct in_addr sc_sync_peer;
|
||||
struct in_addr sc_sendaddr;
|
||||
struct mbuf *sc_mbuf; /* current cumulative mbuf */
|
||||
struct mbuf *sc_mbuf_net; /* current cumulative mbuf */
|
||||
#ifdef PFSYNC_TDB
|
||||
struct mbuf *sc_mbuf_tdb; /* dito for TDB updates */
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
struct ifqueue sc_ifq;
|
||||
struct task sc_send_task;
|
||||
#endif
|
||||
union sc_statep sc_statep;
|
||||
union sc_statep sc_statep_net;
|
||||
#ifdef PFSYNC_TDB
|
||||
union sc_tdb_statep sc_statep_tdb;
|
||||
#endif
|
||||
u_int32_t sc_ureq_received;
|
||||
u_int32_t sc_ureq_sent;
|
||||
struct pf_state *sc_bulk_send_next;
|
||||
struct pf_state *sc_bulk_terminator;
|
||||
int sc_bulk_tries;
|
||||
int sc_maxcount; /* number of states in mtu */
|
||||
int sc_maxupdates; /* number of updates/state */
|
||||
#ifdef __FreeBSD__
|
||||
eventhandler_tag sc_detachtag;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct pfsync_softc *pfsyncif;
|
||||
#endif
|
||||
|
||||
|
||||
struct pfsync_header {
|
||||
u_int8_t version;
|
||||
#define PFSYNC_VERSION 3
|
||||
u_int8_t af;
|
||||
u_int8_t action;
|
||||
#define PFSYNC_ACT_CLR 0 /* clear all states */
|
||||
#define PFSYNC_ACT_INS 1 /* insert state */
|
||||
#define PFSYNC_ACT_UPD 2 /* update state */
|
||||
#define PFSYNC_ACT_DEL 3 /* delete state */
|
||||
#define PFSYNC_ACT_UPD_C 4 /* "compressed" state update */
|
||||
#define PFSYNC_ACT_DEL_C 5 /* "compressed" state delete */
|
||||
#define PFSYNC_ACT_INS_F 6 /* insert fragment */
|
||||
#define PFSYNC_ACT_DEL_F 7 /* delete fragments */
|
||||
#define PFSYNC_ACT_UREQ 8 /* request "uncompressed" state */
|
||||
#define PFSYNC_ACT_BUS 9 /* Bulk Update Status */
|
||||
#define PFSYNC_ACT_TDB_UPD 10 /* TDB replay counter update */
|
||||
#define PFSYNC_ACT_MAX 11
|
||||
u_int8_t count;
|
||||
u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
|
||||
#define PFSYNC_ACT_INS_ACK 2 /* ack of insterted state */
|
||||
#define PFSYNC_ACT_UPD 3 /* update state */
|
||||
#define PFSYNC_ACT_UPD_C 4 /* "compressed" update state */
|
||||
#define PFSYNC_ACT_UPD_REQ 5 /* request "uncompressed" state */
|
||||
#define PFSYNC_ACT_DEL 6 /* delete state */
|
||||
#define PFSYNC_ACT_DEL_C 7 /* "compressed" delete state */
|
||||
#define PFSYNC_ACT_INS_F 8 /* insert fragment */
|
||||
#define PFSYNC_ACT_DEL_F 9 /* delete fragments */
|
||||
#define PFSYNC_ACT_BUS 10 /* bulk update status */
|
||||
#define PFSYNC_ACT_TDB 11 /* TDB replay counter update */
|
||||
#define PFSYNC_ACT_EOF 12 /* end of frame */
|
||||
#define PFSYNC_ACT_MAX 13
|
||||
|
||||
#define PFSYNC_ACTIONS "CLR ST", \
|
||||
"INS ST", \
|
||||
"INS ST ACK", \
|
||||
"UPD ST", \
|
||||
"UPD ST COMP", \
|
||||
"UPD ST REQ", \
|
||||
"DEL ST", \
|
||||
"DEL ST COMP", \
|
||||
"INS FR", \
|
||||
"DEL FR", \
|
||||
"BULK UPD STAT", \
|
||||
"TDB UPD", \
|
||||
"EOF"
|
||||
|
||||
#define PFSYNC_HMAC_LEN 20
|
||||
|
||||
/*
|
||||
* A pfsync frame is built from a header followed by several sections which
|
||||
* are all prefixed with their own subheaders. Frames must be terminated with
|
||||
* an EOF subheader.
|
||||
*
|
||||
* | ... |
|
||||
* | IP header |
|
||||
* +============================+
|
||||
* | pfsync_header |
|
||||
* +----------------------------+
|
||||
* | pfsync_subheader |
|
||||
* +----------------------------+
|
||||
* | first action fields |
|
||||
* | ... |
|
||||
* +----------------------------+
|
||||
* | pfsync_subheader |
|
||||
* +----------------------------+
|
||||
* | second action fields |
|
||||
* | ... |
|
||||
* +----------------------------+
|
||||
* | EOF pfsync_subheader |
|
||||
* +----------------------------+
|
||||
* | HMAC |
|
||||
* +============================+
|
||||
*/
|
||||
|
||||
/*
|
||||
* Frame header
|
||||
*/
|
||||
|
||||
struct pfsync_header {
|
||||
u_int8_t version;
|
||||
u_int8_t _pad;
|
||||
u_int16_t len;
|
||||
u_int8_t pfcksum[PF_MD5_DIGEST_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */
|
||||
#define PFSYNC_MAX_BULKTRIES 12
|
||||
#define PFSYNC_HDRLEN sizeof(struct pfsync_header)
|
||||
#define PFSYNC_ACTIONS \
|
||||
"CLR ST", "INS ST", "UPD ST", "DEL ST", \
|
||||
"UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \
|
||||
"UPD REQ", "BLK UPD STAT", "TDB UPD"
|
||||
/*
|
||||
* Frame region subheader
|
||||
*/
|
||||
|
||||
#define PFSYNC_DFLTTL 255
|
||||
struct pfsync_subheader {
|
||||
u_int8_t action;
|
||||
u_int8_t _pad;
|
||||
u_int16_t count;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* CLR
|
||||
*/
|
||||
|
||||
struct pfsync_clr {
|
||||
char ifname[IFNAMSIZ];
|
||||
u_int32_t creatorid;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* INS, UPD, DEL
|
||||
*/
|
||||
|
||||
/* these use struct pfsync_state in pfvar.h */
|
||||
|
||||
/*
|
||||
* INS_ACK
|
||||
*/
|
||||
|
||||
struct pfsync_ins_ack {
|
||||
u_int64_t id;
|
||||
u_int32_t creatorid;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* UPD_C
|
||||
*/
|
||||
|
||||
struct pfsync_upd_c {
|
||||
u_int64_t id;
|
||||
struct pfsync_state_peer src;
|
||||
struct pfsync_state_peer dst;
|
||||
u_int32_t creatorid;
|
||||
u_int32_t expire;
|
||||
u_int8_t timeout;
|
||||
u_int8_t _pad[3];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* UPD_REQ
|
||||
*/
|
||||
|
||||
struct pfsync_upd_req {
|
||||
u_int64_t id;
|
||||
u_int32_t creatorid;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* DEL_C
|
||||
*/
|
||||
|
||||
struct pfsync_del_c {
|
||||
u_int64_t id;
|
||||
u_int32_t creatorid;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* INS_F, DEL_F
|
||||
*/
|
||||
|
||||
/* not implemented (yet) */
|
||||
|
||||
/*
|
||||
* BUS
|
||||
*/
|
||||
|
||||
struct pfsync_bus {
|
||||
u_int32_t creatorid;
|
||||
u_int32_t endtime;
|
||||
u_int8_t status;
|
||||
#define PFSYNC_BUS_START 1
|
||||
#define PFSYNC_BUS_END 2
|
||||
u_int8_t _pad[3];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* TDB
|
||||
*/
|
||||
|
||||
struct pfsync_tdb {
|
||||
u_int32_t spi;
|
||||
union sockaddr_union dst;
|
||||
u_int32_t rpl;
|
||||
u_int64_t cur_bytes;
|
||||
u_int8_t sproto;
|
||||
u_int8_t updates;
|
||||
u_int8_t _pad[2];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* EOF
|
||||
*/
|
||||
|
||||
struct pfsync_eof {
|
||||
u_int8_t hmac[PFSYNC_HMAC_LEN];
|
||||
} __packed;
|
||||
|
||||
#define PFSYNC_HDRLEN sizeof(struct pfsync_header)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Names for PFSYNC sysctl objects
|
||||
*/
|
||||
#define PFSYNCCTL_STATS 1 /* PFSYNC stats */
|
||||
#define PFSYNCCTL_MAXID 2
|
||||
|
||||
#define PFSYNCCTL_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
{ "stats", CTLTYPE_STRUCT }, \
|
||||
}
|
||||
|
||||
struct pfsyncstats {
|
||||
u_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */
|
||||
@ -280,96 +269,56 @@ struct pfsyncreq {
|
||||
};
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define SIOCSETPFSYNC _IOW('i', 247, struct ifreq)
|
||||
#define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq)
|
||||
#define SIOCSETPFSYNC _IOW('i', 247, struct ifreq)
|
||||
#define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq)
|
||||
#endif
|
||||
|
||||
#define pf_state_peer_hton(s,d) do { \
|
||||
(d)->seqlo = htonl((s)->seqlo); \
|
||||
(d)->seqhi = htonl((s)->seqhi); \
|
||||
(d)->seqdiff = htonl((s)->seqdiff); \
|
||||
(d)->max_win = htons((s)->max_win); \
|
||||
(d)->mss = htons((s)->mss); \
|
||||
(d)->state = (s)->state; \
|
||||
(d)->wscale = (s)->wscale; \
|
||||
if ((s)->scrub) { \
|
||||
(d)->scrub.pfss_flags = \
|
||||
htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \
|
||||
(d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \
|
||||
(d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\
|
||||
(d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define pf_state_peer_ntoh(s,d) do { \
|
||||
(d)->seqlo = ntohl((s)->seqlo); \
|
||||
(d)->seqhi = ntohl((s)->seqhi); \
|
||||
(d)->seqdiff = ntohl((s)->seqdiff); \
|
||||
(d)->max_win = ntohs((s)->max_win); \
|
||||
(d)->mss = ntohs((s)->mss); \
|
||||
(d)->state = (s)->state; \
|
||||
(d)->wscale = (s)->wscale; \
|
||||
if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \
|
||||
(d)->scrub != NULL) { \
|
||||
(d)->scrub->pfss_flags = \
|
||||
ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \
|
||||
(d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \
|
||||
(d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define pf_state_host_hton(s,d) do { \
|
||||
bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
|
||||
(d)->port = (s)->port; \
|
||||
} while (0)
|
||||
|
||||
#define pf_state_host_ntoh(s,d) do { \
|
||||
bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
|
||||
(d)->port = (s)->port; \
|
||||
} while (0)
|
||||
|
||||
#define pf_state_counter_hton(s,d) do { \
|
||||
d[0] = htonl((s>>32)&0xffffffff); \
|
||||
d[1] = htonl(s&0xffffffff); \
|
||||
} while (0)
|
||||
|
||||
#define pf_state_counter_ntoh(s,d) do { \
|
||||
d = ntohl(s[0]); \
|
||||
d = d<<32; \
|
||||
d += ntohl(s[1]); \
|
||||
} while (0)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* this shows where a pf state is with respect to the syncing.
|
||||
*/
|
||||
#define PFSYNC_S_INS 0x00
|
||||
#define PFSYNC_S_IACK 0x01
|
||||
#define PFSYNC_S_UPD 0x02
|
||||
#define PFSYNC_S_UPD_C 0x03
|
||||
#define PFSYNC_S_DEL 0x04
|
||||
#define PFSYNC_S_COUNT 0x05
|
||||
|
||||
#define PFSYNC_S_DEFER 0xfe
|
||||
#define PFSYNC_S_NONE 0xff
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
void pfsync_input(struct mbuf *, __unused int);
|
||||
void pfsync_input(struct mbuf *, __unused int);
|
||||
#else
|
||||
void pfsync_input(struct mbuf *, ...);
|
||||
void pfsync_input(struct mbuf *, ...);
|
||||
#endif
|
||||
int pfsync_clear_states(u_int32_t, char *);
|
||||
int pfsync_pack_state(u_int8_t, struct pf_state *, int);
|
||||
#define pfsync_insert_state(st) do { \
|
||||
if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \
|
||||
(st->proto == IPPROTO_PFSYNC)) \
|
||||
st->sync_flags |= PFSTATE_NOSYNC; \
|
||||
else if (!st->sync_flags) \
|
||||
pfsync_pack_state(PFSYNC_ACT_INS, (st), \
|
||||
PFSYNC_FLAG_COMPRESS); \
|
||||
st->sync_flags &= ~PFSTATE_FROMSYNC; \
|
||||
} while (0)
|
||||
#define pfsync_update_state(st) do { \
|
||||
if (!st->sync_flags) \
|
||||
pfsync_pack_state(PFSYNC_ACT_UPD, (st), \
|
||||
PFSYNC_FLAG_COMPRESS); \
|
||||
st->sync_flags &= ~PFSTATE_FROMSYNC; \
|
||||
} while (0)
|
||||
#define pfsync_delete_state(st) do { \
|
||||
if (!st->sync_flags) \
|
||||
pfsync_pack_state(PFSYNC_ACT_DEL, (st), \
|
||||
PFSYNC_FLAG_COMPRESS); \
|
||||
} while (0)
|
||||
#ifdef PFSYNC_TDB
|
||||
int pfsync_update_tdb(struct tdb *, int);
|
||||
int pfsync_sysctl(int *, u_int, void *, size_t *,
|
||||
void *, size_t);
|
||||
|
||||
#define PFSYNC_SI_IOCTL 0x01
|
||||
#define PFSYNC_SI_CKSUM 0x02
|
||||
#define PFSYNC_SI_ACK 0x04
|
||||
int pfsync_state_import(struct pfsync_state *, u_int8_t);
|
||||
#ifndef __FreeBSD__
|
||||
void pfsync_state_export(struct pfsync_state *,
|
||||
struct pf_state *);
|
||||
#endif
|
||||
|
||||
void pfsync_insert_state(struct pf_state *);
|
||||
void pfsync_update_state(struct pf_state *);
|
||||
void pfsync_delete_state(struct pf_state *);
|
||||
void pfsync_clear_states(u_int32_t, const char *);
|
||||
|
||||
#ifdef notyet
|
||||
void pfsync_update_tdb(struct tdb *, int);
|
||||
void pfsync_delete_tdb(struct tdb *);
|
||||
#endif
|
||||
|
||||
int pfsync_defer(struct pf_state *, struct mbuf *);
|
||||
|
||||
int pfsync_up(void);
|
||||
int pfsync_state_in_use(struct pf_state *);
|
||||
#endif
|
||||
|
||||
#endif /* _NET_IF_PFSYNC_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_if.c,v 1.46 2006/12/13 09:01:59 itojun Exp $ */
|
||||
/* $OpenBSD: pf_if.c,v 1.54 2008/06/14 16:55:28 mk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2005 Henning Brauer <henning@openbsd.org>
|
||||
@ -54,6 +54,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/device.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#ifndef __FreeBSD__
|
||||
#include <sys/pool.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@ -73,25 +76,35 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/ip6.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
struct pfi_kif *pfi_all = NULL;
|
||||
struct pfi_statehead pfi_statehead;
|
||||
#ifdef __FreeBSD__
|
||||
uma_zone_t pfi_addr_pl;
|
||||
VNET_DEFINE(struct pfi_kif *, pfi_all);
|
||||
VNET_DEFINE(uma_zone_t, pfi_addr_pl);
|
||||
VNET_DEFINE(struct pfi_ifhead, pfi_ifs);
|
||||
#define V_pfi_ifs VNET(pfi_ifs)
|
||||
VNET_DEFINE(long, pfi_update);
|
||||
#define V_pfi_update VNET(pfi_update)
|
||||
VNET_DEFINE(struct pfr_addr *, pfi_buffer);
|
||||
#define V_pfi_buffer VNET(pfi_buffer)
|
||||
VNET_DEFINE(int, pfi_buffer_cnt);
|
||||
#define V_pfi_buffer_cnt VNET(pfi_buffer_cnt)
|
||||
VNET_DEFINE(int, pfi_buffer_max);
|
||||
#define V_pfi_buffer_max VNET(pfi_buffer_max)
|
||||
#else
|
||||
struct pfi_kif *pfi_all = NULL;
|
||||
struct pool pfi_addr_pl;
|
||||
#endif
|
||||
struct pfi_ifhead pfi_ifs;
|
||||
long pfi_update = 1;
|
||||
struct pfr_addr *pfi_buffer;
|
||||
int pfi_buffer_cnt;
|
||||
int pfi_buffer_max;
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
eventhandler_tag pfi_attach_cookie = NULL;
|
||||
eventhandler_tag pfi_detach_cookie = NULL;
|
||||
eventhandler_tag pfi_attach_group_cookie = NULL;
|
||||
eventhandler_tag pfi_change_group_cookie = NULL;
|
||||
eventhandler_tag pfi_detach_group_cookie = NULL;
|
||||
eventhandler_tag pfi_ifaddr_event_cookie = NULL;
|
||||
eventhandler_tag pfi_attach_cookie;
|
||||
eventhandler_tag pfi_detach_cookie;
|
||||
eventhandler_tag pfi_attach_group_cookie;
|
||||
eventhandler_tag pfi_change_group_cookie;
|
||||
eventhandler_tag pfi_detach_group_cookie;
|
||||
eventhandler_tag pfi_ifaddr_event_cookie;
|
||||
#endif
|
||||
|
||||
void pfi_kif_update(struct pfi_kif *);
|
||||
@ -107,11 +120,10 @@ int pfi_unmask(void *);
|
||||
#ifdef __FreeBSD__
|
||||
void pfi_attach_ifnet_event(void * __unused, struct ifnet *);
|
||||
void pfi_detach_ifnet_event(void * __unused, struct ifnet *);
|
||||
void pfi_attach_group_event(void * __unused, struct ifg_group *);
|
||||
void pfi_change_group_event(void * __unused, char *);
|
||||
void pfi_detach_group_event(void * __unused, struct ifg_group *);
|
||||
void pfi_attach_group_event(void *, struct ifg_group *);
|
||||
void pfi_change_group_event(void *, char *);
|
||||
void pfi_detach_group_event(void *, struct ifg_group *);
|
||||
void pfi_ifaddr_event(void * __unused, struct ifnet *);
|
||||
|
||||
#endif
|
||||
|
||||
RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
|
||||
@ -123,22 +135,31 @@ RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
|
||||
void
|
||||
pfi_initialize(void)
|
||||
{
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pfi_all != NULL) /* already initialized */
|
||||
#else
|
||||
if (pfi_all != NULL) /* already initialized */
|
||||
#endif
|
||||
return;
|
||||
|
||||
TAILQ_INIT(&pfi_statehead);
|
||||
#ifndef __FreeBSD__
|
||||
pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
|
||||
pool_init(&V_pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
|
||||
"pfiaddrpl", &pool_allocator_nointr);
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_buffer_max = 64;
|
||||
V_pfi_buffer = malloc(V_pfi_buffer_max * sizeof(*V_pfi_buffer),
|
||||
PFI_MTYPE, M_WAITOK);
|
||||
|
||||
if ((V_pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
|
||||
#else
|
||||
pfi_buffer_max = 64;
|
||||
pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer),
|
||||
PFI_MTYPE, M_WAITOK);
|
||||
|
||||
if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
|
||||
#endif
|
||||
panic("pfi_kif_get for pfi_all failed");
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
struct ifg_group *ifg;
|
||||
struct ifnet *ifp;
|
||||
@ -155,11 +176,11 @@ pfi_initialize(void)
|
||||
pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
|
||||
pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
|
||||
pfi_attach_group_cookie = EVENTHANDLER_REGISTER(group_attach_event,
|
||||
pfi_attach_group_event, NULL, EVENTHANDLER_PRI_ANY);
|
||||
pfi_attach_group_event, curvnet, EVENTHANDLER_PRI_ANY);
|
||||
pfi_change_group_cookie = EVENTHANDLER_REGISTER(group_change_event,
|
||||
pfi_change_group_event, NULL, EVENTHANDLER_PRI_ANY);
|
||||
pfi_change_group_event, curvnet, EVENTHANDLER_PRI_ANY);
|
||||
pfi_detach_group_cookie = EVENTHANDLER_REGISTER(group_detach_event,
|
||||
pfi_detach_group_event, NULL, EVENTHANDLER_PRI_ANY);
|
||||
pfi_detach_group_event, curvnet, EVENTHANDLER_PRI_ANY);
|
||||
pfi_ifaddr_event_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
|
||||
pfi_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY);
|
||||
#endif
|
||||
@ -180,18 +201,18 @@ pfi_cleanup(void)
|
||||
EVENTHANDLER_DEREGISTER(ifaddr_event, pfi_ifaddr_event_cookie);
|
||||
PF_LOCK();
|
||||
|
||||
pfi_all = NULL;
|
||||
while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) {
|
||||
V_pfi_all = NULL;
|
||||
while ((p = RB_MIN(pfi_ifhead, &V_pfi_ifs))) {
|
||||
if (p->pfik_rules || p->pfik_states) {
|
||||
printf("pfi_cleanup: dangling refs for %s\n",
|
||||
p->pfik_name);
|
||||
}
|
||||
|
||||
RB_REMOVE(pfi_ifhead, &pfi_ifs, p);
|
||||
RB_REMOVE(pfi_ifhead, &V_pfi_ifs, p);
|
||||
free(p, PFI_MTYPE);
|
||||
}
|
||||
|
||||
free(pfi_buffer, PFI_MTYPE);
|
||||
free(V_pfi_buffer, PFI_MTYPE);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -203,18 +224,21 @@ pfi_kif_get(const char *kif_name)
|
||||
|
||||
bzero(&s, sizeof(s));
|
||||
strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
|
||||
#ifdef __FreeBSD__
|
||||
if ((kif = RB_FIND(pfi_ifhead, &V_pfi_ifs, (struct pfi_kif *)&s)) != NULL)
|
||||
#else
|
||||
if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL)
|
||||
#endif
|
||||
return (kif);
|
||||
|
||||
/* create new one */
|
||||
#ifdef __FreeBSD__
|
||||
if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT)) == NULL)
|
||||
if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT | M_ZERO)) == NULL)
|
||||
#else
|
||||
if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT)) == NULL)
|
||||
if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT|M_ZERO)) == NULL)
|
||||
#endif
|
||||
return (NULL);
|
||||
|
||||
bzero(kif, sizeof(*kif));
|
||||
strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
@ -230,7 +254,12 @@ pfi_kif_get(const char *kif_name)
|
||||
#endif
|
||||
TAILQ_INIT(&kif->pfik_dynaddrs);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
RB_INSERT(pfi_ifhead, &V_pfi_ifs, kif);
|
||||
#else
|
||||
RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
|
||||
#endif
|
||||
|
||||
return (kif);
|
||||
}
|
||||
|
||||
@ -242,8 +271,7 @@ pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
|
||||
kif->pfik_rules++;
|
||||
break;
|
||||
case PFI_KIF_REF_STATE:
|
||||
if (!kif->pfik_states++)
|
||||
TAILQ_INSERT_TAIL(&pfi_statehead, kif, pfik_w_states);
|
||||
kif->pfik_states++;
|
||||
break;
|
||||
default:
|
||||
panic("pfi_kif_ref with unknown type");
|
||||
@ -271,20 +299,27 @@ pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
|
||||
printf("pfi_kif_unref: state refcount <= 0\n");
|
||||
return;
|
||||
}
|
||||
if (!--kif->pfik_states)
|
||||
TAILQ_REMOVE(&pfi_statehead, kif, pfik_w_states);
|
||||
kif->pfik_states--;
|
||||
break;
|
||||
default:
|
||||
panic("pfi_kif_unref with unknown type");
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == V_pfi_all)
|
||||
#else
|
||||
if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
|
||||
#endif
|
||||
return;
|
||||
|
||||
if (kif->pfik_rules || kif->pfik_states)
|
||||
return;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
RB_REMOVE(pfi_ifhead, &V_pfi_ifs, kif);
|
||||
#else
|
||||
RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
|
||||
#endif
|
||||
free(kif, PFI_MTYPE);
|
||||
}
|
||||
|
||||
@ -312,7 +347,11 @@ pfi_attach_ifnet(struct ifnet *ifp)
|
||||
|
||||
pfi_initialize();
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_update++;
|
||||
#else
|
||||
pfi_update++;
|
||||
#endif
|
||||
if ((kif = pfi_kif_get(ifp->if_xname)) == NULL)
|
||||
panic("pfi_kif_get failed");
|
||||
|
||||
@ -341,7 +380,11 @@ pfi_detach_ifnet(struct ifnet *ifp)
|
||||
return;
|
||||
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_update++;
|
||||
#else
|
||||
pfi_update++;
|
||||
#endif
|
||||
#ifndef __FreeBSD__
|
||||
hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie);
|
||||
#endif
|
||||
@ -361,7 +404,11 @@ pfi_attach_ifgroup(struct ifg_group *ifg)
|
||||
|
||||
pfi_initialize();
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_update++;
|
||||
#else
|
||||
pfi_update++;
|
||||
#endif
|
||||
if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL)
|
||||
panic("pfi_kif_get failed");
|
||||
|
||||
@ -381,7 +428,11 @@ pfi_detach_ifgroup(struct ifg_group *ifg)
|
||||
return;
|
||||
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_update++;
|
||||
#else
|
||||
pfi_update++;
|
||||
#endif
|
||||
|
||||
kif->pfik_group = NULL;
|
||||
ifg->ifg_pf_kif = NULL;
|
||||
@ -396,7 +447,11 @@ pfi_group_change(const char *group)
|
||||
int s;
|
||||
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_update++;
|
||||
#else
|
||||
pfi_update++;
|
||||
#endif
|
||||
if ((kif = pfi_kif_get(group)) == NULL)
|
||||
panic("pfi_kif_get failed");
|
||||
|
||||
@ -450,9 +505,14 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
|
||||
|
||||
if (aw->type != PF_ADDR_DYNIFTL)
|
||||
return (0);
|
||||
if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL)
|
||||
#ifdef __FreeBSD__
|
||||
/* XXX: revisit! */
|
||||
if ((dyn = pool_get(&V_pfi_addr_pl, PR_WAITOK | PR_ZERO))
|
||||
#else
|
||||
if ((dyn = pool_get(&pfi_addr_pl, PR_WAITOK | PR_LIMITFAIL | PR_ZERO))
|
||||
#endif
|
||||
== NULL)
|
||||
return (1);
|
||||
bzero(dyn, sizeof(*dyn));
|
||||
|
||||
s = splsoftnet();
|
||||
if (!strcmp(aw->v.ifname, "self"))
|
||||
@ -485,7 +545,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
|
||||
goto _bad;
|
||||
}
|
||||
|
||||
if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) {
|
||||
if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, 1)) == NULL) {
|
||||
rv = 1;
|
||||
goto _bad;
|
||||
}
|
||||
@ -507,7 +567,11 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
|
||||
pf_remove_if_empty_ruleset(ruleset);
|
||||
if (dyn->pfid_kif != NULL)
|
||||
pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pfi_addr_pl, dyn);
|
||||
#else
|
||||
pool_put(&pfi_addr_pl, dyn);
|
||||
#endif
|
||||
splx(s);
|
||||
return (rv);
|
||||
}
|
||||
@ -541,10 +605,18 @@ pfi_dynaddr_update(struct pfi_dynaddr *dyn)
|
||||
kif = dyn->pfid_kif;
|
||||
kt = dyn->pfid_kt;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (kt->pfrkt_larg != V_pfi_update) {
|
||||
#else
|
||||
if (kt->pfrkt_larg != pfi_update) {
|
||||
#endif
|
||||
/* this table needs to be brought up-to-date */
|
||||
pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
|
||||
#ifdef __FreeBSD__
|
||||
kt->pfrkt_larg = V_pfi_update;
|
||||
#else
|
||||
kt->pfrkt_larg = pfi_update;
|
||||
#endif
|
||||
}
|
||||
pfr_dynaddr_update(kt, dyn);
|
||||
}
|
||||
@ -555,7 +627,11 @@ pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
|
||||
int e, size2 = 0;
|
||||
struct ifg_member *ifgm;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_buffer_cnt = 0;
|
||||
#else
|
||||
pfi_buffer_cnt = 0;
|
||||
#endif
|
||||
|
||||
if (kif->pfik_ifp != NULL)
|
||||
pfi_instance_add(kif->pfik_ifp, net, flags);
|
||||
@ -563,10 +639,17 @@ pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
|
||||
TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next)
|
||||
pfi_instance_add(ifgm->ifgm_ifp, net, flags);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if ((e = pfr_set_addrs(&kt->pfrkt_t, V_pfi_buffer, V_pfi_buffer_cnt, &size2,
|
||||
NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
|
||||
printf("pfi_table_update: cannot set %d new addresses "
|
||||
"into table %s: %d\n", V_pfi_buffer_cnt, kt->pfrkt_name, e);
|
||||
#else
|
||||
if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2,
|
||||
NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
|
||||
printf("pfi_table_update: cannot set %d new addresses "
|
||||
"into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -587,9 +670,9 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags)
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
* XXX: For point-to-point interfaces, (ifname:0) and IPv4,
|
||||
* jump over addresses without a proper route to work
|
||||
* around a problem with ppp not fully removing the
|
||||
* address used during IPCP.
|
||||
* jump over addresses without a proper route to work
|
||||
* around a problem with ppp not fully removing the
|
||||
* address used during IPCP.
|
||||
*/
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) &&
|
||||
!(ia->ifa_flags & IFA_ROUTE) &&
|
||||
@ -644,15 +727,24 @@ pfi_address_add(struct sockaddr *sa, int af, int net)
|
||||
struct pfr_addr *p;
|
||||
int i;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pfi_buffer_cnt >= V_pfi_buffer_max) {
|
||||
int new_max = V_pfi_buffer_max * 2;
|
||||
#else
|
||||
if (pfi_buffer_cnt >= pfi_buffer_max) {
|
||||
int new_max = pfi_buffer_max * 2;
|
||||
#endif
|
||||
|
||||
if (new_max > PFI_BUFFER_MAX) {
|
||||
printf("pfi_address_add: address buffer full (%d/%d)\n",
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_buffer_cnt, PFI_BUFFER_MAX);
|
||||
#else
|
||||
pfi_buffer_cnt, PFI_BUFFER_MAX);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
|
||||
p = malloc(new_max * sizeof(*V_pfi_buffer), PFI_MTYPE,
|
||||
#ifdef __FreeBSD__
|
||||
M_NOWAIT);
|
||||
#else
|
||||
@ -660,18 +752,34 @@ pfi_address_add(struct sockaddr *sa, int af, int net)
|
||||
#endif
|
||||
if (p == NULL) {
|
||||
printf("pfi_address_add: no memory to grow buffer "
|
||||
#ifdef __FreeBSD__
|
||||
"(%d/%d)\n", V_pfi_buffer_cnt, PFI_BUFFER_MAX);
|
||||
#else
|
||||
"(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer));
|
||||
#ifdef __FreeBSD__
|
||||
memcpy(V_pfi_buffer, p, V_pfi_buffer_cnt * sizeof(*V_pfi_buffer));
|
||||
/* no need to zero buffer */
|
||||
free(V_pfi_buffer, PFI_MTYPE);
|
||||
V_pfi_buffer = p;
|
||||
V_pfi_buffer_max = new_max;
|
||||
#else
|
||||
memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
|
||||
/* no need to zero buffer */
|
||||
free(pfi_buffer, PFI_MTYPE);
|
||||
pfi_buffer = p;
|
||||
pfi_buffer_max = new_max;
|
||||
#endif
|
||||
}
|
||||
if (af == AF_INET && net > 32)
|
||||
net = 128;
|
||||
#ifdef __FreeBSD__
|
||||
p = V_pfi_buffer + V_pfi_buffer_cnt++;
|
||||
#else
|
||||
p = pfi_buffer + pfi_buffer_cnt++;
|
||||
#endif
|
||||
bzero(p, sizeof(*p));
|
||||
p->pfra_af = af;
|
||||
p->pfra_net = net;
|
||||
@ -704,7 +812,11 @@ pfi_dynaddr_remove(struct pf_addr_wrap *aw)
|
||||
aw->p.dyn->pfid_kif = NULL;
|
||||
pfr_detach_table(aw->p.dyn->pfid_kt);
|
||||
aw->p.dyn->pfid_kt = NULL;
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pfi_addr_pl, aw->p.dyn);
|
||||
#else
|
||||
pool_put(&pfi_addr_pl, aw->p.dyn);
|
||||
#endif
|
||||
aw->p.dyn = NULL;
|
||||
splx(s);
|
||||
}
|
||||
@ -725,7 +837,11 @@ pfi_kifaddr_update(void *v)
|
||||
struct pfi_kif *kif = (struct pfi_kif *)v;
|
||||
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
V_pfi_update++;
|
||||
#else
|
||||
pfi_update++;
|
||||
#endif
|
||||
pfi_kif_update(kif);
|
||||
splx(s);
|
||||
}
|
||||
@ -737,49 +853,61 @@ pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
|
||||
}
|
||||
|
||||
void
|
||||
pfi_fill_oldstatus(struct pf_status *pfs)
|
||||
pfi_update_status(const char *name, struct pf_status *pfs)
|
||||
{
|
||||
struct pfi_kif *p;
|
||||
struct pfi_kif_cmp key;
|
||||
struct pfi_kif_cmp key;
|
||||
struct ifg_member p_member, *ifgm;
|
||||
TAILQ_HEAD(, ifg_member) ifg_members;
|
||||
int i, j, k, s;
|
||||
|
||||
strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name));
|
||||
strlcpy(key.pfik_name, name, sizeof(key.pfik_name));
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
p = RB_FIND(pfi_ifhead, &V_pfi_ifs, (struct pfi_kif *)&key);
|
||||
#else
|
||||
p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key);
|
||||
#endif
|
||||
if (p == NULL) {
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
bzero(pfs->pcounters, sizeof(pfs->pcounters));
|
||||
bzero(pfs->bcounters, sizeof(pfs->bcounters));
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++)
|
||||
for (k = 0; k < 2; k++) {
|
||||
pfs->pcounters[i][j][k] =
|
||||
p->pfik_packets[i][j][k];
|
||||
pfs->bcounters[i][j] +=
|
||||
p->pfik_bytes[i][j][k];
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
int
|
||||
pfi_clr_istats(const char *name)
|
||||
{
|
||||
struct pfi_kif *p;
|
||||
int s;
|
||||
|
||||
s = splsoftnet();
|
||||
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
|
||||
if (pfi_skip_if(name, p))
|
||||
if (p->pfik_group != NULL) {
|
||||
bcopy(&p->pfik_group->ifg_members, &ifg_members,
|
||||
sizeof(ifg_members));
|
||||
} else {
|
||||
/* build a temporary list for p only */
|
||||
bzero(&p_member, sizeof(p_member));
|
||||
p_member.ifgm_ifp = p->pfik_ifp;
|
||||
TAILQ_INIT(&ifg_members);
|
||||
TAILQ_INSERT_TAIL(&ifg_members, &p_member, ifgm_next);
|
||||
}
|
||||
if (pfs) {
|
||||
bzero(pfs->pcounters, sizeof(pfs->pcounters));
|
||||
bzero(pfs->bcounters, sizeof(pfs->bcounters));
|
||||
}
|
||||
TAILQ_FOREACH(ifgm, &ifg_members, ifgm_next) {
|
||||
if (ifgm->ifgm_ifp == NULL)
|
||||
continue;
|
||||
bzero(p->pfik_packets, sizeof(p->pfik_packets));
|
||||
bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
|
||||
p->pfik_tzero = time_second;
|
||||
p = (struct pfi_kif *)ifgm->ifgm_ifp->if_pf_kif;
|
||||
|
||||
/* just clear statistics */
|
||||
if (pfs == NULL) {
|
||||
bzero(p->pfik_packets, sizeof(p->pfik_packets));
|
||||
bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
|
||||
p->pfik_tzero = time_second;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++)
|
||||
for (k = 0; k < 2; k++) {
|
||||
pfs->pcounters[i][j][k] +=
|
||||
p->pfik_packets[i][j][k];
|
||||
pfs->bcounters[i][j] +=
|
||||
p->pfik_bytes[i][j][k];
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -792,8 +920,13 @@ pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
|
||||
#endif
|
||||
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
for (p = RB_MIN(pfi_ifhead, &V_pfi_ifs); p; p = nextp) {
|
||||
nextp = RB_NEXT(pfi_ifhead, &V_pfi_ifs, p);
|
||||
#else
|
||||
for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) {
|
||||
nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
|
||||
#endif
|
||||
if (pfi_skip_if(name, p))
|
||||
continue;
|
||||
if (*size > n++) {
|
||||
@ -810,7 +943,11 @@ pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
|
||||
splx(s);
|
||||
return (EFAULT);
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
nextp = RB_NEXT(pfi_ifhead, &V_pfi_ifs, p);
|
||||
#else
|
||||
nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
|
||||
#endif
|
||||
pfi_kif_unref(p, PFI_KIF_REF_RULE);
|
||||
}
|
||||
}
|
||||
@ -845,7 +982,11 @@ pfi_set_flags(const char *name, int flags)
|
||||
int s;
|
||||
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
RB_FOREACH(p, pfi_ifhead, &V_pfi_ifs) {
|
||||
#else
|
||||
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
|
||||
#endif
|
||||
if (pfi_skip_if(name, p))
|
||||
continue;
|
||||
p->pfik_flags |= flags;
|
||||
@ -861,7 +1002,11 @@ pfi_clear_flags(const char *name, int flags)
|
||||
int s;
|
||||
|
||||
s = splsoftnet();
|
||||
#ifdef __FreeBSD__
|
||||
RB_FOREACH(p, pfi_ifhead, &V_pfi_ifs) {
|
||||
#else
|
||||
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
|
||||
#endif
|
||||
if (pfi_skip_if(name, p))
|
||||
continue;
|
||||
p->pfik_flags &= ~flags;
|
||||
@ -894,55 +1039,73 @@ pfi_unmask(void *addr)
|
||||
void
|
||||
pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp)
|
||||
{
|
||||
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
PF_LOCK();
|
||||
pfi_attach_ifnet(ifp);
|
||||
#ifdef ALTQ
|
||||
pf_altq_ifnet_event(ifp, 0);
|
||||
#endif
|
||||
PF_UNLOCK();
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
void
|
||||
pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp)
|
||||
{
|
||||
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
PF_LOCK();
|
||||
pfi_detach_ifnet(ifp);
|
||||
#ifdef ALTQ
|
||||
pf_altq_ifnet_event(ifp, 1);
|
||||
#endif
|
||||
PF_UNLOCK();
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
void
|
||||
pfi_attach_group_event(void *arg __unused, struct ifg_group *ifg)
|
||||
pfi_attach_group_event(void *arg , struct ifg_group *ifg)
|
||||
{
|
||||
|
||||
CURVNET_SET((struct vnet *)arg);
|
||||
PF_LOCK();
|
||||
pfi_attach_ifgroup(ifg);
|
||||
PF_UNLOCK();
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
void
|
||||
pfi_change_group_event(void *arg __unused, char *gname)
|
||||
pfi_change_group_event(void *arg, char *gname)
|
||||
{
|
||||
|
||||
CURVNET_SET((struct vnet *)arg);
|
||||
PF_LOCK();
|
||||
pfi_group_change(gname);
|
||||
PF_UNLOCK();
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
void
|
||||
pfi_detach_group_event(void *arg __unused, struct ifg_group *ifg)
|
||||
pfi_detach_group_event(void *arg, struct ifg_group *ifg)
|
||||
{
|
||||
|
||||
CURVNET_SET((struct vnet *)arg);
|
||||
PF_LOCK();
|
||||
pfi_detach_ifgroup(ifg);
|
||||
PF_UNLOCK();
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
void
|
||||
pfi_ifaddr_event(void *arg __unused, struct ifnet *ifp)
|
||||
{
|
||||
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
PF_LOCK();
|
||||
if (ifp && ifp->if_pf_kif)
|
||||
pfi_kifaddr_update(ifp->if_pf_kif);
|
||||
PF_UNLOCK();
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
792
sys/contrib/pf/net/pf_lb.c
Normal file
792
sys/contrib/pf/net/pf_lb.c
Normal file
@ -0,0 +1,792 @@
|
||||
/* $OpenBSD: pf_lb.c,v 1.2 2009/02/12 02:13:15 sthen Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
* Copyright (c) 2002 - 2008 Henning Brauer
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Effort sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F30602-01-2-0537.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include "opt_bpf.h"
|
||||
#include "opt_pf.h"
|
||||
|
||||
#ifdef DEV_BPF
|
||||
#define NBPFILTER DEV_BPF
|
||||
#else
|
||||
#define NBPFILTER 0
|
||||
#endif
|
||||
|
||||
#ifdef DEV_PFLOG
|
||||
#define NPFLOG DEV_PFLOG
|
||||
#else
|
||||
#define NPFLOG 0
|
||||
#endif
|
||||
|
||||
#ifdef DEV_PFSYNC
|
||||
#define NPFSYNC DEV_PFSYNC
|
||||
#else
|
||||
#define NPFSYNC 0
|
||||
#endif
|
||||
|
||||
#ifdef DEV_PFLOW
|
||||
#define NPFLOW DEV_PFLOW
|
||||
#else
|
||||
#define NPFLOW 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include "bpfilter.h"
|
||||
#include "pflog.h"
|
||||
#include "pfsync.h"
|
||||
#include "pflow.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/filio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#ifndef __FreeBSD__
|
||||
#include <sys/pool.h>
|
||||
#endif
|
||||
#include <sys/proc.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#else
|
||||
#include <sys/rwlock.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/md5.h>
|
||||
#else
|
||||
#include <crypto/md5.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/route.h>
|
||||
#include <net/radix_mpath.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/tcp_timer.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#include <dev/rndvar.h>
|
||||
#endif
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pflog.h>
|
||||
#include <net/if_pflow.h>
|
||||
|
||||
#if NPFSYNC > 0
|
||||
#include <net/if_pfsync.h>
|
||||
#endif /* NPFSYNC > 0 */
|
||||
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
|
||||
#else
|
||||
#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
|
||||
void pf_hash(struct pf_addr *, struct pf_addr *,
|
||||
struct pf_poolhashkey *, sa_family_t);
|
||||
struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
|
||||
int, int, struct pfi_kif *,
|
||||
struct pf_addr *, u_int16_t, struct pf_addr *,
|
||||
u_int16_t, int);
|
||||
int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
|
||||
struct pf_addr *, struct pf_addr *, u_int16_t,
|
||||
struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
|
||||
struct pf_src_node **);
|
||||
|
||||
#define mix(a,b,c) \
|
||||
do { \
|
||||
a -= b; a -= c; a ^= (c >> 13); \
|
||||
b -= c; b -= a; b ^= (a << 8); \
|
||||
c -= a; c -= b; c ^= (b >> 13); \
|
||||
a -= b; a -= c; a ^= (c >> 12); \
|
||||
b -= c; b -= a; b ^= (a << 16); \
|
||||
c -= a; c -= b; c ^= (b >> 5); \
|
||||
a -= b; a -= c; a ^= (c >> 3); \
|
||||
b -= c; b -= a; b ^= (a << 10); \
|
||||
c -= a; c -= b; c ^= (b >> 15); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* hash function based on bridge_hash in if_bridge.c
|
||||
*/
|
||||
void
|
||||
pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
|
||||
struct pf_poolhashkey *key, sa_family_t af)
|
||||
{
|
||||
u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
|
||||
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
a += inaddr->addr32[0];
|
||||
b += key->key32[1];
|
||||
mix(a, b, c);
|
||||
hash->addr32[0] = c + key->key32[2];
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
a += inaddr->addr32[0];
|
||||
b += inaddr->addr32[2];
|
||||
mix(a, b, c);
|
||||
hash->addr32[0] = c;
|
||||
a += inaddr->addr32[1];
|
||||
b += inaddr->addr32[3];
|
||||
c += key->key32[1];
|
||||
mix(a, b, c);
|
||||
hash->addr32[1] = c;
|
||||
a += inaddr->addr32[2];
|
||||
b += inaddr->addr32[1];
|
||||
c += key->key32[2];
|
||||
mix(a, b, c);
|
||||
hash->addr32[2] = c;
|
||||
a += inaddr->addr32[3];
|
||||
b += inaddr->addr32[0];
|
||||
c += key->key32[3];
|
||||
mix(a, b, c);
|
||||
hash->addr32[3] = c;
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
}
|
||||
|
||||
struct pf_rule *
|
||||
pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
|
||||
int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
|
||||
struct pf_addr *daddr, u_int16_t dport, int rs_num)
|
||||
{
|
||||
struct pf_rule *r, *rm = NULL;
|
||||
struct pf_ruleset *ruleset = NULL;
|
||||
int tag = -1;
|
||||
int rtableid = -1;
|
||||
int asd = 0;
|
||||
|
||||
r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
|
||||
while (r && rm == NULL) {
|
||||
struct pf_rule_addr *src = NULL, *dst = NULL;
|
||||
struct pf_addr_wrap *xdst = NULL;
|
||||
|
||||
if (r->action == PF_BINAT && direction == PF_IN) {
|
||||
src = &r->dst;
|
||||
if (r->rpool.cur != NULL)
|
||||
xdst = &r->rpool.cur->addr;
|
||||
} else {
|
||||
src = &r->src;
|
||||
dst = &r->dst;
|
||||
}
|
||||
|
||||
r->evaluations++;
|
||||
if (pfi_kif_match(r->kif, kif) == r->ifnot)
|
||||
r = r->skip[PF_SKIP_IFP].ptr;
|
||||
else if (r->direction && r->direction != direction)
|
||||
r = r->skip[PF_SKIP_DIR].ptr;
|
||||
else if (r->af && r->af != pd->af)
|
||||
r = r->skip[PF_SKIP_AF].ptr;
|
||||
else if (r->proto && r->proto != pd->proto)
|
||||
r = r->skip[PF_SKIP_PROTO].ptr;
|
||||
else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
|
||||
src->neg, kif))
|
||||
r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
|
||||
PF_SKIP_DST_ADDR].ptr;
|
||||
else if (src->port_op && !pf_match_port(src->port_op,
|
||||
src->port[0], src->port[1], sport))
|
||||
r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
|
||||
PF_SKIP_DST_PORT].ptr;
|
||||
else if (dst != NULL &&
|
||||
PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL))
|
||||
r = r->skip[PF_SKIP_DST_ADDR].ptr;
|
||||
else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
|
||||
0, NULL))
|
||||
r = TAILQ_NEXT(r, entries);
|
||||
else if (dst != NULL && dst->port_op &&
|
||||
!pf_match_port(dst->port_op, dst->port[0],
|
||||
dst->port[1], dport))
|
||||
r = r->skip[PF_SKIP_DST_PORT].ptr;
|
||||
#ifdef __FreeBSD__
|
||||
else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
|
||||
#else
|
||||
else if (r->match_tag && !pf_match_tag(m, r, &tag))
|
||||
#endif
|
||||
r = TAILQ_NEXT(r, entries);
|
||||
else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
|
||||
IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
|
||||
off, pd->hdr.tcp), r->os_fingerprint)))
|
||||
r = TAILQ_NEXT(r, entries);
|
||||
else {
|
||||
if (r->tag)
|
||||
tag = r->tag;
|
||||
if (r->rtableid >= 0)
|
||||
rtableid = r->rtableid;
|
||||
if (r->anchor == NULL) {
|
||||
rm = r;
|
||||
} else
|
||||
pf_step_into_anchor(&asd, &ruleset, rs_num,
|
||||
&r, NULL, NULL);
|
||||
}
|
||||
if (r == NULL)
|
||||
pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
|
||||
NULL, NULL);
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
if (pf_tag_packet(m, tag, rtableid, pd->pf_mtag))
|
||||
#else
|
||||
if (pf_tag_packet(m, tag, rtableid))
|
||||
#endif
|
||||
return (NULL);
|
||||
if (rm != NULL && (rm->action == PF_NONAT ||
|
||||
rm->action == PF_NORDR || rm->action == PF_NOBINAT))
|
||||
return (NULL);
|
||||
return (rm);
|
||||
}
|
||||
|
||||
int
|
||||
pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
|
||||
struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
|
||||
struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
|
||||
struct pf_src_node **sn)
|
||||
{
|
||||
struct pf_state_key_cmp key;
|
||||
struct pf_addr init_addr;
|
||||
u_int16_t cut;
|
||||
|
||||
bzero(&init_addr, sizeof(init_addr));
|
||||
if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
|
||||
return (1);
|
||||
|
||||
if (proto == IPPROTO_ICMP) {
|
||||
low = 1;
|
||||
high = 65535;
|
||||
}
|
||||
|
||||
do {
|
||||
key.af = af;
|
||||
key.proto = proto;
|
||||
PF_ACPY(&key.addr[1], daddr, key.af);
|
||||
PF_ACPY(&key.addr[0], naddr, key.af);
|
||||
key.port[1] = dport;
|
||||
|
||||
/*
|
||||
* port search; start random, step;
|
||||
* similar 2 portloop in in_pcbbind
|
||||
*/
|
||||
if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
|
||||
proto == IPPROTO_ICMP)) {
|
||||
key.port[0] = dport;
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
|
||||
return (0);
|
||||
} else if (low == 0 && high == 0) {
|
||||
key.port[0] = *nport;
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
|
||||
return (0);
|
||||
} else if (low == high) {
|
||||
key.port[0] = htons(low);
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
|
||||
*nport = htons(low);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
u_int16_t tmp;
|
||||
|
||||
if (low > high) {
|
||||
tmp = low;
|
||||
low = high;
|
||||
high = tmp;
|
||||
}
|
||||
/* low < high */
|
||||
#ifdef __FreeBSD__
|
||||
cut = htonl(arc4random()) % (1 + high - low) + low;
|
||||
#else
|
||||
cut = arc4random_uniform(1 + high - low) + low;
|
||||
#endif
|
||||
/* low <= cut <= high */
|
||||
for (tmp = cut; tmp <= high; ++(tmp)) {
|
||||
key.port[0] = htons(tmp);
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) ==
|
||||
#ifdef __FreeBSD__
|
||||
NULL) {
|
||||
#else
|
||||
NULL && !in_baddynamic(tmp, proto)) {
|
||||
#endif
|
||||
*nport = htons(tmp);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
for (tmp = cut - 1; tmp >= low; --(tmp)) {
|
||||
key.port[0] = htons(tmp);
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) ==
|
||||
#ifdef __FreeBSD__
|
||||
NULL) {
|
||||
#else
|
||||
NULL && !in_baddynamic(tmp, proto)) {
|
||||
#endif
|
||||
*nport = htons(tmp);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (r->rpool.opts & PF_POOL_TYPEMASK) {
|
||||
case PF_POOL_RANDOM:
|
||||
case PF_POOL_ROUNDROBIN:
|
||||
if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
|
||||
return (1);
|
||||
break;
|
||||
case PF_POOL_NONE:
|
||||
case PF_POOL_SRCHASH:
|
||||
case PF_POOL_BITMASK:
|
||||
default:
|
||||
return (1);
|
||||
}
|
||||
} while (! PF_AEQ(&init_addr, naddr, af) );
|
||||
return (1); /* none available */
|
||||
}
|
||||
|
||||
int
|
||||
pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
|
||||
struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
|
||||
{
|
||||
unsigned char hash[16];
|
||||
struct pf_pool *rpool = &r->rpool;
|
||||
struct pf_addr *raddr = &rpool->cur->addr.v.a.addr;
|
||||
struct pf_addr *rmask = &rpool->cur->addr.v.a.mask;
|
||||
struct pf_pooladdr *acur = rpool->cur;
|
||||
struct pf_src_node k;
|
||||
|
||||
if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
|
||||
(r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
|
||||
k.af = af;
|
||||
PF_ACPY(&k.addr, saddr, af);
|
||||
if (r->rule_flag & PFRULE_RULESRCTRACK ||
|
||||
r->rpool.opts & PF_POOL_STICKYADDR)
|
||||
k.rule.ptr = r;
|
||||
else
|
||||
k.rule.ptr = NULL;
|
||||
#ifdef __FreeBSD__
|
||||
V_pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
|
||||
*sn = RB_FIND(pf_src_tree, &V_tree_src_tracking, &k);
|
||||
#else
|
||||
pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
|
||||
*sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
|
||||
#endif
|
||||
if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
|
||||
PF_ACPY(naddr, &(*sn)->raddr, af);
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#endif
|
||||
printf("pf_map_addr: src tracking maps ");
|
||||
pf_print_host(&k.addr, 0, af);
|
||||
printf(" to ");
|
||||
pf_print_host(naddr, 0, af);
|
||||
printf("\n");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
|
||||
return (1);
|
||||
if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
|
||||
(rpool->opts & PF_POOL_TYPEMASK) !=
|
||||
PF_POOL_ROUNDROBIN)
|
||||
return (1);
|
||||
raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
|
||||
rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
|
||||
(rpool->opts & PF_POOL_TYPEMASK) !=
|
||||
PF_POOL_ROUNDROBIN)
|
||||
return (1);
|
||||
raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
|
||||
rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
} else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
|
||||
if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
|
||||
return (1); /* unsupported */
|
||||
} else {
|
||||
raddr = &rpool->cur->addr.v.a.addr;
|
||||
rmask = &rpool->cur->addr.v.a.mask;
|
||||
}
|
||||
|
||||
switch (rpool->opts & PF_POOL_TYPEMASK) {
|
||||
case PF_POOL_NONE:
|
||||
PF_ACPY(naddr, raddr, af);
|
||||
break;
|
||||
case PF_POOL_BITMASK:
|
||||
PF_POOLMASK(naddr, raddr, rmask, saddr, af);
|
||||
break;
|
||||
case PF_POOL_RANDOM:
|
||||
if (init_addr != NULL && PF_AZERO(init_addr, af)) {
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
rpool->counter.addr32[0] = htonl(arc4random());
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (rmask->addr32[3] != 0xffffffff)
|
||||
rpool->counter.addr32[3] =
|
||||
htonl(arc4random());
|
||||
else
|
||||
break;
|
||||
if (rmask->addr32[2] != 0xffffffff)
|
||||
rpool->counter.addr32[2] =
|
||||
htonl(arc4random());
|
||||
else
|
||||
break;
|
||||
if (rmask->addr32[1] != 0xffffffff)
|
||||
rpool->counter.addr32[1] =
|
||||
htonl(arc4random());
|
||||
else
|
||||
break;
|
||||
if (rmask->addr32[0] != 0xffffffff)
|
||||
rpool->counter.addr32[0] =
|
||||
htonl(arc4random());
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
|
||||
PF_ACPY(init_addr, naddr, af);
|
||||
|
||||
} else {
|
||||
PF_AINC(&rpool->counter, af);
|
||||
PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
|
||||
}
|
||||
break;
|
||||
case PF_POOL_SRCHASH:
|
||||
pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
|
||||
PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
|
||||
break;
|
||||
case PF_POOL_ROUNDROBIN:
|
||||
if (rpool->cur->addr.type == PF_ADDR_TABLE) {
|
||||
if (!pfr_pool_get(rpool->cur->addr.p.tbl,
|
||||
&rpool->tblidx, &rpool->counter,
|
||||
&raddr, &rmask, af))
|
||||
goto get_addr;
|
||||
} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
|
||||
if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
|
||||
&rpool->tblidx, &rpool->counter,
|
||||
&raddr, &rmask, af))
|
||||
goto get_addr;
|
||||
} else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
|
||||
goto get_addr;
|
||||
|
||||
try_next:
|
||||
if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL)
|
||||
rpool->cur = TAILQ_FIRST(&rpool->list);
|
||||
if (rpool->cur->addr.type == PF_ADDR_TABLE) {
|
||||
rpool->tblidx = -1;
|
||||
if (pfr_pool_get(rpool->cur->addr.p.tbl,
|
||||
&rpool->tblidx, &rpool->counter,
|
||||
&raddr, &rmask, af)) {
|
||||
/* table contains no address of type 'af' */
|
||||
if (rpool->cur != acur)
|
||||
goto try_next;
|
||||
return (1);
|
||||
}
|
||||
} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
|
||||
rpool->tblidx = -1;
|
||||
if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
|
||||
&rpool->tblidx, &rpool->counter,
|
||||
&raddr, &rmask, af)) {
|
||||
/* table contains no address of type 'af' */
|
||||
if (rpool->cur != acur)
|
||||
goto try_next;
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
raddr = &rpool->cur->addr.v.a.addr;
|
||||
rmask = &rpool->cur->addr.v.a.mask;
|
||||
PF_ACPY(&rpool->counter, raddr, af);
|
||||
}
|
||||
|
||||
get_addr:
|
||||
PF_ACPY(naddr, &rpool->counter, af);
|
||||
if (init_addr != NULL && PF_AZERO(init_addr, af))
|
||||
PF_ACPY(init_addr, naddr, af);
|
||||
PF_AINC(&rpool->counter, af);
|
||||
break;
|
||||
}
|
||||
if (*sn != NULL)
|
||||
PF_ACPY(&(*sn)->raddr, naddr, af);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC &&
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC &&
|
||||
#endif
|
||||
(rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
|
||||
printf("pf_map_addr: selected address ");
|
||||
pf_print_host(naddr, 0, af);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct pf_rule *
|
||||
pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
|
||||
struct pfi_kif *kif, struct pf_src_node **sn,
|
||||
struct pf_state_key **skw, struct pf_state_key **sks,
|
||||
struct pf_state_key **skp, struct pf_state_key **nkp,
|
||||
struct pf_addr *saddr, struct pf_addr *daddr,
|
||||
u_int16_t sport, u_int16_t dport)
|
||||
{
|
||||
struct pf_rule *r = NULL;
|
||||
|
||||
|
||||
if (direction == PF_OUT) {
|
||||
r = pf_match_translation(pd, m, off, direction, kif, saddr,
|
||||
sport, daddr, dport, PF_RULESET_BINAT);
|
||||
if (r == NULL)
|
||||
r = pf_match_translation(pd, m, off, direction, kif,
|
||||
saddr, sport, daddr, dport, PF_RULESET_NAT);
|
||||
} else {
|
||||
r = pf_match_translation(pd, m, off, direction, kif, saddr,
|
||||
sport, daddr, dport, PF_RULESET_RDR);
|
||||
if (r == NULL)
|
||||
r = pf_match_translation(pd, m, off, direction, kif,
|
||||
saddr, sport, daddr, dport, PF_RULESET_BINAT);
|
||||
}
|
||||
|
||||
if (r != NULL) {
|
||||
struct pf_addr *naddr;
|
||||
u_int16_t *nport;
|
||||
|
||||
if (pf_state_key_setup(pd, r, skw, sks, skp, nkp,
|
||||
saddr, daddr, sport, dport))
|
||||
return r;
|
||||
|
||||
/* XXX We only modify one side for now. */
|
||||
naddr = &(*nkp)->addr[1];
|
||||
nport = &(*nkp)->port[1];
|
||||
|
||||
switch (r->action) {
|
||||
case PF_NONAT:
|
||||
case PF_NOBINAT:
|
||||
case PF_NORDR:
|
||||
return (NULL);
|
||||
case PF_NAT:
|
||||
if (pf_get_sport(pd->af, pd->proto, r, saddr,
|
||||
daddr, dport, naddr, nport, r->rpool.proxy_port[0],
|
||||
r->rpool.proxy_port[1], sn)) {
|
||||
DPFPRINTF(PF_DEBUG_MISC,
|
||||
("pf: NAT proxy port allocation "
|
||||
"(%u-%u) failed\n",
|
||||
r->rpool.proxy_port[0],
|
||||
r->rpool.proxy_port[1]));
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
case PF_BINAT:
|
||||
switch (direction) {
|
||||
case PF_OUT:
|
||||
if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
|
||||
switch (pd->af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (r->rpool.cur->addr.p.dyn->
|
||||
pfid_acnt4 < 1)
|
||||
return (NULL);
|
||||
PF_POOLMASK(naddr,
|
||||
&r->rpool.cur->addr.p.dyn->
|
||||
pfid_addr4,
|
||||
&r->rpool.cur->addr.p.dyn->
|
||||
pfid_mask4,
|
||||
saddr, AF_INET);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (r->rpool.cur->addr.p.dyn->
|
||||
pfid_acnt6 < 1)
|
||||
return (NULL);
|
||||
PF_POOLMASK(naddr,
|
||||
&r->rpool.cur->addr.p.dyn->
|
||||
pfid_addr6,
|
||||
&r->rpool.cur->addr.p.dyn->
|
||||
pfid_mask6,
|
||||
saddr, AF_INET6);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
} else
|
||||
PF_POOLMASK(naddr,
|
||||
&r->rpool.cur->addr.v.a.addr,
|
||||
&r->rpool.cur->addr.v.a.mask,
|
||||
saddr, pd->af);
|
||||
break;
|
||||
case PF_IN:
|
||||
if (r->src.addr.type == PF_ADDR_DYNIFTL) {
|
||||
switch (pd->af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (r->src.addr.p.dyn->
|
||||
pfid_acnt4 < 1)
|
||||
return (NULL);
|
||||
PF_POOLMASK(naddr,
|
||||
&r->src.addr.p.dyn->
|
||||
pfid_addr4,
|
||||
&r->src.addr.p.dyn->
|
||||
pfid_mask4,
|
||||
daddr, AF_INET);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (r->src.addr.p.dyn->
|
||||
pfid_acnt6 < 1)
|
||||
return (NULL);
|
||||
PF_POOLMASK(naddr,
|
||||
&r->src.addr.p.dyn->
|
||||
pfid_addr6,
|
||||
&r->src.addr.p.dyn->
|
||||
pfid_mask6,
|
||||
daddr, AF_INET6);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
} else
|
||||
PF_POOLMASK(naddr,
|
||||
&r->src.addr.v.a.addr,
|
||||
&r->src.addr.v.a.mask, daddr,
|
||||
pd->af);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PF_RDR: {
|
||||
if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
|
||||
return (NULL);
|
||||
if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
|
||||
PF_POOL_BITMASK)
|
||||
PF_POOLMASK(naddr, naddr,
|
||||
&r->rpool.cur->addr.v.a.mask, daddr,
|
||||
pd->af);
|
||||
|
||||
if (r->rpool.proxy_port[1]) {
|
||||
u_int32_t tmp_nport;
|
||||
|
||||
tmp_nport = ((ntohs(dport) -
|
||||
ntohs(r->dst.port[0])) %
|
||||
(r->rpool.proxy_port[1] -
|
||||
r->rpool.proxy_port[0] + 1)) +
|
||||
r->rpool.proxy_port[0];
|
||||
|
||||
/* wrap around if necessary */
|
||||
if (tmp_nport > 65535)
|
||||
tmp_nport -= 65535;
|
||||
*nport = htons((u_int16_t)tmp_nport);
|
||||
} else if (r->rpool.proxy_port[0])
|
||||
*nport = htons(r->rpool.proxy_port[0]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* Translation was a NOP.
|
||||
* Pretend there was no match.
|
||||
*/
|
||||
if (!bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp))) {
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_state_key_pl, *nkp);
|
||||
pool_put(&V_pf_state_key_pl, *skp);
|
||||
#else
|
||||
pool_put(&pf_state_key_pl, *nkp);
|
||||
pool_put(&pf_state_key_pl, *skp);
|
||||
#endif
|
||||
*skw = *sks = *nkp = *skp = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
@ -37,15 +37,17 @@
|
||||
#define PF_TAG_GENERATED 0x01
|
||||
#define PF_TAG_FRAGCACHE 0x02
|
||||
#define PF_TAG_TRANSLATE_LOCALHOST 0x04
|
||||
#define PF_PACKET_LOOPED 0x08
|
||||
#define PF_FASTFWD_OURS_PRESENT 0x10
|
||||
|
||||
struct pf_mtag {
|
||||
void *hdr; /* saved hdr pos in mbuf, for ECN */
|
||||
u_int rtableid; /* alternate routing table id */
|
||||
void *statekey; /* pf stackside statekey */
|
||||
u_int32_t qid; /* queue id */
|
||||
u_int rtableid; /* alternate routing table id */
|
||||
u_int16_t tag; /* tag id */
|
||||
u_int8_t flags;
|
||||
u_int8_t routed;
|
||||
sa_family_t af; /* for ECN */
|
||||
};
|
||||
|
||||
static __inline struct pf_mtag *pf_find_mtag(struct mbuf *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_norm.c,v 1.107 2006/04/16 00:59:52 pascoe Exp $ */
|
||||
/* $OpenBSD: pf_norm.c,v 1.114 2009/01/29 14:11:45 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
@ -34,9 +34,9 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef DEV_PFLOG
|
||||
#define NPFLOG DEV_PFLOG
|
||||
#define NPFLOG DEV_PFLOG
|
||||
#else
|
||||
#define NPFLOG 0
|
||||
#define NPFLOG 0
|
||||
#endif
|
||||
#else
|
||||
#include "pflog.h"
|
||||
@ -78,8 +78,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/pfvar.h>
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#include <inttypes.h>
|
||||
|
||||
struct pf_frent {
|
||||
LIST_ENTRY(pf_frent) fr_next;
|
||||
struct ip *fr_ip;
|
||||
@ -118,17 +116,35 @@ struct pf_fragment {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
TAILQ_HEAD(pf_fragqueue, pf_fragment);
|
||||
TAILQ_HEAD(pf_cachequeue, pf_fragment);
|
||||
VNET_DEFINE(struct pf_fragqueue, pf_fragqueue);
|
||||
#define V_pf_fragqueue VNET(pf_fragqueue)
|
||||
VNET_DEFINE(struct pf_cachequeue, pf_cachequeue);
|
||||
#define V_pf_cachequeue VNET(pf_cachequeue)
|
||||
#else
|
||||
TAILQ_HEAD(pf_fragqueue, pf_fragment) pf_fragqueue;
|
||||
TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue;
|
||||
#endif
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static __inline int pf_frag_compare(struct pf_fragment *,
|
||||
struct pf_fragment *);
|
||||
#else
|
||||
static int pf_frag_compare(struct pf_fragment *,
|
||||
static int pf_frag_compare(struct pf_fragment *,
|
||||
struct pf_fragment *);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
RB_HEAD(pf_frag_tree, pf_fragment);
|
||||
VNET_DEFINE(struct pf_frag_tree, pf_frag_tree);
|
||||
#define V_pf_frag_tree VNET(pf_frag_tree)
|
||||
VNET_DEFINE(struct pf_frag_tree, pf_cache_tree);
|
||||
#define V_pf_cache_tree VNET(pf_cache_tree)
|
||||
#else
|
||||
RB_HEAD(pf_frag_tree, pf_fragment) pf_frag_tree, pf_cache_tree;
|
||||
#endif
|
||||
RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
|
||||
RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
|
||||
|
||||
@ -143,24 +159,45 @@ struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **,
|
||||
struct mbuf *pf_fragcache(struct mbuf **, struct ip*,
|
||||
struct pf_fragment **, int, int, int *);
|
||||
int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
|
||||
struct tcphdr *, int);
|
||||
|
||||
struct tcphdr *, int, sa_family_t);
|
||||
void pf_scrub_ip(struct mbuf **, u_int32_t, u_int8_t,
|
||||
u_int8_t);
|
||||
#ifdef INET6
|
||||
void pf_scrub_ip6(struct mbuf **, u_int8_t);
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define DPFPRINTF(x) do { \
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC) { \
|
||||
printf("%s: ", __func__); \
|
||||
printf x ; \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define DPFPRINTF(x) do { \
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) { \
|
||||
printf("%s: ", __func__); \
|
||||
printf x ; \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/* Globals */
|
||||
#ifdef __FreeBSD__
|
||||
uma_zone_t pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
|
||||
uma_zone_t pf_state_scrub_pl;
|
||||
VNET_DEFINE(uma_zone_t, pf_frent_pl);
|
||||
VNET_DEFINE(uma_zone_t, pf_frag_pl);
|
||||
VNET_DEFINE(uma_zone_t, pf_cache_pl);
|
||||
VNET_DEFINE(uma_zone_t, pf_cent_pl);
|
||||
VNET_DEFINE(uma_zone_t, pf_state_scrub_pl);
|
||||
|
||||
VNET_DEFINE(int, pf_nfrents);
|
||||
#define V_pf_nfrents VNET(pf_nfrents)
|
||||
VNET_DEFINE(int, pf_ncache);
|
||||
#define V_pf_ncache VNET(pf_ncache)
|
||||
#else
|
||||
struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
|
||||
struct pool pf_state_scrub_pl;
|
||||
#endif
|
||||
int pf_nfrents, pf_ncache;
|
||||
#endif
|
||||
|
||||
void
|
||||
pf_normalize_init(void)
|
||||
@ -171,9 +208,9 @@ pf_normalize_init(void)
|
||||
* No high water mark support(It's hint not hard limit).
|
||||
* uma_zone_set_max(pf_frag_pl, PFFRAG_FRAG_HIWAT);
|
||||
*/
|
||||
uma_zone_set_max(pf_frent_pl, PFFRAG_FRENT_HIWAT);
|
||||
uma_zone_set_max(pf_cache_pl, PFFRAG_FRCACHE_HIWAT);
|
||||
uma_zone_set_max(pf_cent_pl, PFFRAG_FRCENT_HIWAT);
|
||||
uma_zone_set_max(V_pf_frent_pl, PFFRAG_FRENT_HIWAT);
|
||||
uma_zone_set_max(V_pf_cache_pl, PFFRAG_FRCACHE_HIWAT);
|
||||
uma_zone_set_max(V_pf_cent_pl, PFFRAG_FRCENT_HIWAT);
|
||||
#else
|
||||
pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
|
||||
NULL);
|
||||
@ -192,8 +229,13 @@ pf_normalize_init(void)
|
||||
pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
TAILQ_INIT(&V_pf_fragqueue);
|
||||
TAILQ_INIT(&V_pf_cachequeue);
|
||||
#else
|
||||
TAILQ_INIT(&pf_fragqueue);
|
||||
TAILQ_INIT(&pf_cachequeue);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
@ -224,14 +266,20 @@ void
|
||||
pf_purge_expired_fragments(void)
|
||||
{
|
||||
struct pf_fragment *frag;
|
||||
#ifdef __FreeBSD__
|
||||
u_int32_t expire = time_second -
|
||||
V_pf_default_rule.timeout[PFTM_FRAG];
|
||||
#else
|
||||
u_int32_t expire = time_second -
|
||||
pf_default_rule.timeout[PFTM_FRAG];
|
||||
#endif
|
||||
|
||||
while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
|
||||
#ifdef __FreeBSD__
|
||||
while ((frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue)) != NULL) {
|
||||
KASSERT((BUFFER_FRAGMENTS(frag)),
|
||||
("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__));
|
||||
("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__));
|
||||
#else
|
||||
while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
|
||||
KASSERT(BUFFER_FRAGMENTS(frag));
|
||||
#endif
|
||||
if (frag->fr_timeout > expire)
|
||||
@ -241,11 +289,12 @@ pf_purge_expired_fragments(void)
|
||||
pf_free_fragment(frag);
|
||||
}
|
||||
|
||||
while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
|
||||
#ifdef __FreeBSD__
|
||||
while ((frag = TAILQ_LAST(&V_pf_cachequeue, pf_cachequeue)) != NULL) {
|
||||
KASSERT((!BUFFER_FRAGMENTS(frag)),
|
||||
("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__));
|
||||
("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__));
|
||||
#else
|
||||
while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
|
||||
KASSERT(!BUFFER_FRAGMENTS(frag));
|
||||
#endif
|
||||
if (frag->fr_timeout > expire)
|
||||
@ -254,8 +303,8 @@ pf_purge_expired_fragments(void)
|
||||
DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
|
||||
pf_free_fragment(frag);
|
||||
#ifdef __FreeBSD__
|
||||
KASSERT((TAILQ_EMPTY(&pf_cachequeue) ||
|
||||
TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag),
|
||||
KASSERT((TAILQ_EMPTY(&V_pf_cachequeue) ||
|
||||
TAILQ_LAST(&V_pf_cachequeue, pf_cachequeue) != frag),
|
||||
("!(TAILQ_EMPTY() || TAILQ_LAST() == farg): %s",
|
||||
__FUNCTION__));
|
||||
#else
|
||||
@ -275,22 +324,44 @@ pf_flush_fragments(void)
|
||||
struct pf_fragment *frag;
|
||||
int goal;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
goal = V_pf_nfrents * 9 / 10;
|
||||
DPFPRINTF(("trying to free > %d frents\n",
|
||||
V_pf_nfrents - goal));
|
||||
while (goal < V_pf_nfrents) {
|
||||
#else
|
||||
goal = pf_nfrents * 9 / 10;
|
||||
DPFPRINTF(("trying to free > %d frents\n",
|
||||
pf_nfrents - goal));
|
||||
while (goal < pf_nfrents) {
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue);
|
||||
#else
|
||||
frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue);
|
||||
#endif
|
||||
if (frag == NULL)
|
||||
break;
|
||||
pf_free_fragment(frag);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
goal = V_pf_ncache * 9 / 10;
|
||||
DPFPRINTF(("trying to free > %d cache entries\n",
|
||||
V_pf_ncache - goal));
|
||||
while (goal < V_pf_ncache) {
|
||||
#else
|
||||
goal = pf_ncache * 9 / 10;
|
||||
DPFPRINTF(("trying to free > %d cache entries\n",
|
||||
pf_ncache - goal));
|
||||
while (goal < pf_ncache) {
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
frag = TAILQ_LAST(&V_pf_cachequeue, pf_cachequeue);
|
||||
#else
|
||||
frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue);
|
||||
#endif
|
||||
if (frag == NULL)
|
||||
break;
|
||||
pf_free_fragment(frag);
|
||||
@ -312,8 +383,13 @@ pf_free_fragment(struct pf_fragment *frag)
|
||||
LIST_REMOVE(frent, fr_next);
|
||||
|
||||
m_freem(frent->fr_m);
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_frent_pl, frent);
|
||||
V_pf_nfrents--;
|
||||
#else
|
||||
pool_put(&pf_frent_pl, frent);
|
||||
pf_nfrents--;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
for (frcache = LIST_FIRST(&frag->fr_cache); frcache;
|
||||
@ -325,15 +401,18 @@ pf_free_fragment(struct pf_fragment *frag)
|
||||
LIST_FIRST(&frag->fr_cache)->fr_off >
|
||||
frcache->fr_end),
|
||||
("! (LIST_EMPTY() || LIST_FIRST()->fr_off >"
|
||||
" frcache->fr_end): %s", __FUNCTION__));
|
||||
" frcache->fr_end): %s", __FUNCTION__));
|
||||
|
||||
pool_put(&V_pf_cent_pl, frcache);
|
||||
V_pf_ncache--;
|
||||
#else
|
||||
KASSERT(LIST_EMPTY(&frag->fr_cache) ||
|
||||
LIST_FIRST(&frag->fr_cache)->fr_off >
|
||||
frcache->fr_end);
|
||||
#endif
|
||||
|
||||
pool_put(&pf_cent_pl, frcache);
|
||||
pf_ncache--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,11 +441,21 @@ pf_find_fragment(struct ip *ip, struct pf_frag_tree *tree)
|
||||
/* XXX Are we sure we want to update the timeout? */
|
||||
frag->fr_timeout = time_second;
|
||||
if (BUFFER_FRAGMENTS(frag)) {
|
||||
#ifdef __FreeBSD__
|
||||
TAILQ_REMOVE(&V_pf_fragqueue, frag, frag_next);
|
||||
TAILQ_INSERT_HEAD(&V_pf_fragqueue, frag, frag_next);
|
||||
#else
|
||||
TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
|
||||
TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef __FreeBSD__
|
||||
TAILQ_REMOVE(&V_pf_cachequeue, frag, frag_next);
|
||||
TAILQ_INSERT_HEAD(&V_pf_cachequeue, frag, frag_next);
|
||||
#else
|
||||
TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
|
||||
TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,13 +468,25 @@ void
|
||||
pf_remove_fragment(struct pf_fragment *frag)
|
||||
{
|
||||
if (BUFFER_FRAGMENTS(frag)) {
|
||||
#ifdef __FreeBSD__
|
||||
RB_REMOVE(pf_frag_tree, &V_pf_frag_tree, frag);
|
||||
TAILQ_REMOVE(&V_pf_fragqueue, frag, frag_next);
|
||||
pool_put(&V_pf_frag_pl, frag);
|
||||
#else
|
||||
RB_REMOVE(pf_frag_tree, &pf_frag_tree, frag);
|
||||
TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
|
||||
pool_put(&pf_frag_pl, frag);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef __FreeBSD__
|
||||
RB_REMOVE(pf_frag_tree, &V_pf_cache_tree, frag);
|
||||
TAILQ_REMOVE(&V_pf_cachequeue, frag, frag_next);
|
||||
pool_put(&V_pf_cache_pl, frag);
|
||||
#else
|
||||
RB_REMOVE(pf_frag_tree, &pf_cache_tree, frag);
|
||||
TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
|
||||
pool_put(&pf_cache_pl, frag);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,10 +517,18 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
|
||||
|
||||
/* Create a new reassembly queue for this packet */
|
||||
if (*frag == NULL) {
|
||||
#ifdef __FreeBSD__
|
||||
*frag = pool_get(&V_pf_frag_pl, PR_NOWAIT);
|
||||
#else
|
||||
*frag = pool_get(&pf_frag_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (*frag == NULL) {
|
||||
pf_flush_fragments();
|
||||
#ifdef __FreeBSD__
|
||||
*frag = pool_get(&V_pf_frag_pl, PR_NOWAIT);
|
||||
#else
|
||||
*frag = pool_get(&pf_frag_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (*frag == NULL)
|
||||
goto drop_fragment;
|
||||
}
|
||||
@ -433,8 +542,13 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
|
||||
(*frag)->fr_timeout = time_second;
|
||||
LIST_INIT(&(*frag)->fr_queue);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
RB_INSERT(pf_frag_tree, &V_pf_frag_tree, *frag);
|
||||
TAILQ_INSERT_HEAD(&V_pf_fragqueue, *frag, frag_next);
|
||||
#else
|
||||
RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
|
||||
TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next);
|
||||
#endif
|
||||
|
||||
/* We do not have a previous fragment */
|
||||
frep = NULL;
|
||||
@ -499,8 +613,13 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
|
||||
next = LIST_NEXT(frea, fr_next);
|
||||
m_freem(frea->fr_m);
|
||||
LIST_REMOVE(frea, fr_next);
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_frent_pl, frea);
|
||||
V_pf_nfrents--;
|
||||
#else
|
||||
pool_put(&pf_frent_pl, frea);
|
||||
pf_nfrents--;
|
||||
#endif
|
||||
}
|
||||
|
||||
insert:
|
||||
@ -560,26 +679,36 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
|
||||
m2 = m->m_next;
|
||||
m->m_next = NULL;
|
||||
m_cat(m, m2);
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_frent_pl, frent);
|
||||
V_pf_nfrents--;
|
||||
#else
|
||||
pool_put(&pf_frent_pl, frent);
|
||||
pf_nfrents--;
|
||||
#endif
|
||||
for (frent = next; frent != NULL; frent = next) {
|
||||
next = LIST_NEXT(frent, fr_next);
|
||||
|
||||
m2 = frent->fr_m;
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_frent_pl, frent);
|
||||
V_pf_nfrents--;
|
||||
#else
|
||||
pool_put(&pf_frent_pl, frent);
|
||||
pf_nfrents--;
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
m->m_pkthdr.csum_flags &= m2->m_pkthdr.csum_flags;
|
||||
m->m_pkthdr.csum_data += m2->m_pkthdr.csum_data;
|
||||
#endif
|
||||
m_cat(m, m2);
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
while (m->m_pkthdr.csum_data & 0xffff0000)
|
||||
m->m_pkthdr.csum_data = (m->m_pkthdr.csum_data & 0xffff) +
|
||||
(m->m_pkthdr.csum_data >> 16);
|
||||
#endif
|
||||
|
||||
ip->ip_src = (*frag)->fr_src;
|
||||
ip->ip_dst = (*frag)->fr_dst;
|
||||
|
||||
@ -606,8 +735,13 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
|
||||
|
||||
drop_fragment:
|
||||
/* Oops - fail safe - drop packet */
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_frent_pl, frent);
|
||||
V_pf_nfrents--;
|
||||
#else
|
||||
pool_put(&pf_frent_pl, frent);
|
||||
pf_nfrents--;
|
||||
#endif
|
||||
m_freem(m);
|
||||
return (NULL);
|
||||
}
|
||||
@ -632,22 +766,40 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
|
||||
/* Create a new range queue for this packet */
|
||||
if (*frag == NULL) {
|
||||
#ifdef __FreeBSD__
|
||||
*frag = pool_get(&V_pf_cache_pl, PR_NOWAIT);
|
||||
#else
|
||||
*frag = pool_get(&pf_cache_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (*frag == NULL) {
|
||||
pf_flush_fragments();
|
||||
#ifdef __FreeBSD__
|
||||
*frag = pool_get(&V_pf_cache_pl, PR_NOWAIT);
|
||||
#else
|
||||
*frag = pool_get(&pf_cache_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (*frag == NULL)
|
||||
goto no_mem;
|
||||
}
|
||||
|
||||
/* Get an entry for the queue */
|
||||
#ifdef __FreeBSD__
|
||||
cur = pool_get(&V_pf_cent_pl, PR_NOWAIT);
|
||||
if (cur == NULL) {
|
||||
pool_put(&V_pf_cache_pl, *frag);
|
||||
#else
|
||||
cur = pool_get(&pf_cent_pl, PR_NOWAIT);
|
||||
if (cur == NULL) {
|
||||
pool_put(&pf_cache_pl, *frag);
|
||||
#endif
|
||||
*frag = NULL;
|
||||
goto no_mem;
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
V_pf_ncache++;
|
||||
#else
|
||||
pf_ncache++;
|
||||
#endif
|
||||
|
||||
(*frag)->fr_flags = PFFRAG_NOBUFFER;
|
||||
(*frag)->fr_max = 0;
|
||||
@ -662,8 +814,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
LIST_INIT(&(*frag)->fr_cache);
|
||||
LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
RB_INSERT(pf_frag_tree, &V_pf_cache_tree, *frag);
|
||||
TAILQ_INSERT_HEAD(&V_pf_cachequeue, *frag, frag_next);
|
||||
#else
|
||||
RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
|
||||
TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);
|
||||
#endif
|
||||
|
||||
DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max));
|
||||
|
||||
@ -782,10 +939,18 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
h->ip_id, -precut, frp->fr_off, frp->fr_end, off,
|
||||
max));
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
cur = pool_get(&V_pf_cent_pl, PR_NOWAIT);
|
||||
#else
|
||||
cur = pool_get(&pf_cent_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (cur == NULL)
|
||||
goto no_mem;
|
||||
#ifdef __FreeBSD__
|
||||
V_pf_ncache++;
|
||||
#else
|
||||
pf_ncache++;
|
||||
#endif
|
||||
|
||||
cur->fr_off = off;
|
||||
cur->fr_end = max;
|
||||
@ -842,10 +1007,18 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
h->ip_id, -aftercut, off, max, fra->fr_off,
|
||||
fra->fr_end));
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
cur = pool_get(&V_pf_cent_pl, PR_NOWAIT);
|
||||
#else
|
||||
cur = pool_get(&pf_cent_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (cur == NULL)
|
||||
goto no_mem;
|
||||
#ifdef __FreeBSD__
|
||||
V_pf_ncache++;
|
||||
#else
|
||||
pf_ncache++;
|
||||
#endif
|
||||
|
||||
cur->fr_off = off;
|
||||
cur->fr_end = max;
|
||||
@ -863,8 +1036,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
max, fra->fr_off, fra->fr_end));
|
||||
fra->fr_off = cur->fr_off;
|
||||
LIST_REMOVE(cur, fr_next);
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_cent_pl, cur);
|
||||
V_pf_ncache--;
|
||||
#else
|
||||
pool_put(&pf_cent_pl, cur);
|
||||
pf_ncache--;
|
||||
#endif
|
||||
cur = NULL;
|
||||
|
||||
} else if (frp && fra->fr_off <= frp->fr_end) {
|
||||
@ -881,8 +1059,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
max, fra->fr_off, fra->fr_end));
|
||||
fra->fr_off = frp->fr_off;
|
||||
LIST_REMOVE(frp, fr_next);
|
||||
#ifdef __FreeBSD__
|
||||
pool_put(&V_pf_cent_pl, frp);
|
||||
V_pf_ncache--;
|
||||
#else
|
||||
pool_put(&pf_cent_pl, frp);
|
||||
pf_ncache--;
|
||||
#endif
|
||||
frp = NULL;
|
||||
|
||||
}
|
||||
@ -965,6 +1148,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
u_int16_t max;
|
||||
int ip_len;
|
||||
int ip_off;
|
||||
int tag = -1;
|
||||
|
||||
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
|
||||
while (r != NULL) {
|
||||
@ -985,6 +1169,12 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
(struct pf_addr *)&h->ip_dst.s_addr, AF_INET,
|
||||
r->dst.neg, NULL))
|
||||
r = r->skip[PF_SKIP_DST_ADDR].ptr;
|
||||
#ifdef __FreeBSD__
|
||||
else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
|
||||
#else
|
||||
else if (r->match_tag && !pf_match_tag(m, r, &tag))
|
||||
#endif
|
||||
r = TAILQ_NEXT(r, entries);
|
||||
else
|
||||
break;
|
||||
}
|
||||
@ -1043,7 +1233,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0) {
|
||||
/* Fully buffer all of the fragments */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
frag = pf_find_fragment(h, &V_pf_frag_tree);
|
||||
#else
|
||||
frag = pf_find_fragment(h, &pf_frag_tree);
|
||||
#endif
|
||||
|
||||
/* Check if we saw the last fragment already */
|
||||
if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
|
||||
@ -1051,12 +1245,20 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
goto bad;
|
||||
|
||||
/* Get an entry for the fragment queue */
|
||||
#ifdef __FreeBSD__
|
||||
frent = pool_get(&V_pf_frent_pl, PR_NOWAIT);
|
||||
#else
|
||||
frent = pool_get(&pf_frent_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (frent == NULL) {
|
||||
REASON_SET(reason, PFRES_MEMORY);
|
||||
return (PF_DROP);
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
V_pf_nfrents++;
|
||||
#else
|
||||
pf_nfrents++;
|
||||
#endif
|
||||
frent->fr_ip = h;
|
||||
frent->fr_m = m;
|
||||
|
||||
@ -1087,7 +1289,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
/* non-buffering fragment cache (drops or masks overlaps) */
|
||||
int nomem = 0;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (dir == PF_OUT && pd->pf_mtag->flags & PF_TAG_FRAGCACHE) {
|
||||
#else
|
||||
if (dir == PF_OUT && m->m_pkthdr.pf.flags & PF_TAG_FRAGCACHE) {
|
||||
#endif
|
||||
/*
|
||||
* Already passed the fragment cache in the
|
||||
* input direction. If we continued, it would
|
||||
@ -1096,7 +1302,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
goto fragment_pass;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
frag = pf_find_fragment(h, &V_pf_cache_tree);
|
||||
#else
|
||||
frag = pf_find_fragment(h, &pf_cache_tree);
|
||||
#endif
|
||||
|
||||
/* Check if we saw the last fragment already */
|
||||
if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
|
||||
@ -1127,7 +1337,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
}
|
||||
#endif
|
||||
if (dir == PF_IN)
|
||||
#ifdef __FreeBSD__
|
||||
pd->pf_mtag->flags |= PF_TAG_FRAGCACHE;
|
||||
#else
|
||||
m->m_pkthdr.pf.flags |= PF_TAG_FRAGCACHE;
|
||||
#endif
|
||||
|
||||
if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
|
||||
goto drop;
|
||||
@ -1143,33 +1357,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
|
||||
}
|
||||
|
||||
/* Enforce a minimum ttl, may cause endless packet loops */
|
||||
if (r->min_ttl && h->ip_ttl < r->min_ttl) {
|
||||
u_int16_t ip_ttl = h->ip_ttl;
|
||||
|
||||
h->ip_ttl = r->min_ttl;
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
|
||||
}
|
||||
|
||||
if (r->rule_flag & PFRULE_RANDOMID) {
|
||||
u_int16_t ip_id = h->ip_id;
|
||||
|
||||
h->ip_id = ip_randomid();
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0);
|
||||
}
|
||||
if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
|
||||
pd->flags |= PFDESC_IP_REAS;
|
||||
|
||||
return (PF_PASS);
|
||||
/* not missing a return here */
|
||||
|
||||
fragment_pass:
|
||||
/* Enforce a minimum ttl, may cause endless packet loops */
|
||||
if (r->min_ttl && h->ip_ttl < r->min_ttl) {
|
||||
u_int16_t ip_ttl = h->ip_ttl;
|
||||
pf_scrub_ip(&m, r->rule_flag, r->min_ttl, r->set_tos);
|
||||
|
||||
h->ip_ttl = r->min_ttl;
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
|
||||
}
|
||||
if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
|
||||
pd->flags |= PFDESC_IP_REAS;
|
||||
return (PF_PASS);
|
||||
@ -1339,9 +1531,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
|
||||
if (sizeof(struct ip6_hdr) + plen > m->m_pkthdr.len)
|
||||
goto shortpkt;
|
||||
|
||||
/* Enforce a minimum ttl, may cause endless packet loops */
|
||||
if (r->min_ttl && h->ip6_hlim < r->min_ttl)
|
||||
h->ip6_hlim = r->min_ttl;
|
||||
pf_scrub_ip6(&m, r->min_ttl);
|
||||
|
||||
return (PF_PASS);
|
||||
|
||||
@ -1479,12 +1669,16 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
|
||||
}
|
||||
|
||||
/* Process options */
|
||||
if (r->max_mss && pf_normalize_tcpopt(r, m, th, off))
|
||||
if (r->max_mss && pf_normalize_tcpopt(r, m, th, off, pd->af))
|
||||
rewrite = 1;
|
||||
|
||||
/* copy back packet headers if we sanitized */
|
||||
if (rewrite)
|
||||
#ifdef __FreeBSD__
|
||||
m_copyback(m, off, sizeof(*th), (caddr_t)th);
|
||||
#else
|
||||
m_copyback(m, off, sizeof(*th), th);
|
||||
#endif
|
||||
|
||||
return (PF_PASS);
|
||||
|
||||
@ -1506,11 +1700,13 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
#ifdef __FreeBSD__
|
||||
KASSERT((src->scrub == NULL),
|
||||
("pf_normalize_tcp_init: src->scrub != NULL"));
|
||||
|
||||
src->scrub = pool_get(&V_pf_state_scrub_pl, PR_NOWAIT);
|
||||
#else
|
||||
KASSERT(src->scrub == NULL);
|
||||
#endif
|
||||
|
||||
src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
|
||||
#endif
|
||||
if (src->scrub == NULL)
|
||||
return (1);
|
||||
bzero(src->scrub, sizeof(*src->scrub));
|
||||
@ -1586,10 +1782,17 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
void
|
||||
pf_normalize_tcp_cleanup(struct pf_state *state)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
if (state->src.scrub)
|
||||
pool_put(&V_pf_state_scrub_pl, state->src.scrub);
|
||||
if (state->dst.scrub)
|
||||
pool_put(&V_pf_state_scrub_pl, state->dst.scrub);
|
||||
#else
|
||||
if (state->src.scrub)
|
||||
pool_put(&pf_state_scrub_pl, state->src.scrub);
|
||||
if (state->dst.scrub)
|
||||
pool_put(&pf_state_scrub_pl, state->dst.scrub);
|
||||
#endif
|
||||
|
||||
/* Someday... flush the TCP segment reassembly descriptors. */
|
||||
}
|
||||
@ -1667,7 +1870,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
|
||||
if (got_ts) {
|
||||
/* Huh? Multiple timestamps!? */
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#endif
|
||||
DPFPRINTF(("multiple TS??"));
|
||||
pf_print_state(state);
|
||||
printf("\n");
|
||||
@ -1736,7 +1943,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
if (src->scrub && (src->scrub->pfss_flags & PFSS_PAWS) &&
|
||||
(uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
|
||||
time_second - state->creation > TS_MAX_CONN)) {
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#endif
|
||||
DPFPRINTF(("src idled out of PAWS\n"));
|
||||
pf_print_state(state);
|
||||
printf("\n");
|
||||
@ -1746,7 +1957,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
}
|
||||
if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) &&
|
||||
uptime.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) {
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#endif
|
||||
DPFPRINTF(("dst idled out of PAWS\n"));
|
||||
pf_print_state(state);
|
||||
printf("\n");
|
||||
@ -1807,7 +2022,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
* network conditions that re-order packets and
|
||||
* cause our view of them to decrease. For now the
|
||||
* only lowerbound we can safely determine is that
|
||||
* the TS echo will never be less than the orginal
|
||||
* the TS echo will never be less than the original
|
||||
* TS. XXX There is probably a better lowerbound.
|
||||
* Remove TS_MAX_CONN with better lowerbound check.
|
||||
* tescr >= other original TS
|
||||
@ -1830,7 +2045,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
* this packet.
|
||||
*/
|
||||
if ((ts_fudge = state->rule.ptr->timeout[PFTM_TS_DIFF]) == 0)
|
||||
#ifdef __FreeBSD__
|
||||
ts_fudge = V_pf_default_rule.timeout[PFTM_TS_DIFF];
|
||||
#else
|
||||
ts_fudge = pf_default_rule.timeout[PFTM_TS_DIFF];
|
||||
#endif
|
||||
|
||||
|
||||
/* Calculate max ticks since the last timestamp */
|
||||
@ -1838,7 +2057,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
#define TS_MICROSECS 1000000 /* microseconds per second */
|
||||
#ifdef __FreeBSD__
|
||||
#ifndef timersub
|
||||
#define timersub(tvp, uvp, vvp) \
|
||||
#define timersub(tvp, uvp, vvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
||||
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
||||
@ -1895,7 +2114,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
"\n", dst->scrub->pfss_tsval,
|
||||
dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0));
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#endif
|
||||
pf_print_state(state);
|
||||
pf_print_flags(th->th_flags);
|
||||
printf("\n");
|
||||
@ -1943,7 +2166,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
* Hey! Someone tried to sneak a packet in. Or the
|
||||
* stack changed its RFC1323 behavior?!?!
|
||||
*/
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
#endif
|
||||
DPFPRINTF(("Did not receive expected RFC1323 "
|
||||
"timestamp\n"));
|
||||
pf_print_state(state);
|
||||
@ -1970,7 +2197,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
src->scrub->pfss_flags |= PFSS_DATA_TS;
|
||||
else {
|
||||
src->scrub->pfss_flags |= PFSS_DATA_NOTS;
|
||||
#ifdef __FreeBSD__
|
||||
if (V_pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
|
||||
#else
|
||||
if (pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
|
||||
#endif
|
||||
(dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
|
||||
/* Don't warn if other host rejected RFC1323 */
|
||||
DPFPRINTF(("Broken RFC1323 stack did not "
|
||||
@ -2018,17 +2249,25 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
|
||||
int
|
||||
pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
|
||||
int off)
|
||||
int off, sa_family_t af)
|
||||
{
|
||||
u_int16_t *mss;
|
||||
int thoff;
|
||||
int opt, cnt, optlen = 0;
|
||||
int rewrite = 0;
|
||||
u_char *optp;
|
||||
#ifdef __FreeBSD__
|
||||
u_char opts[TCP_MAXOLEN];
|
||||
#else
|
||||
u_char opts[MAX_TCPOPTLEN];
|
||||
#endif
|
||||
u_char *optp = opts;
|
||||
|
||||
thoff = th->th_off << 2;
|
||||
cnt = thoff - sizeof(struct tcphdr);
|
||||
optp = mtod(m, caddr_t) + off + sizeof(struct tcphdr);
|
||||
|
||||
if (cnt > 0 && !pf_pull_hdr(m, off + sizeof(*th), opts, cnt,
|
||||
NULL, NULL, af))
|
||||
return (rewrite);
|
||||
|
||||
for (; cnt > 0; cnt -= optlen, optp += optlen) {
|
||||
opt = optp[0];
|
||||
@ -2058,5 +2297,63 @@ pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
|
||||
}
|
||||
}
|
||||
|
||||
if (rewrite)
|
||||
m_copyback(m, off + sizeof(*th), thoff - sizeof(*th), opts);
|
||||
|
||||
return (rewrite);
|
||||
}
|
||||
|
||||
void
|
||||
pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos)
|
||||
{
|
||||
struct mbuf *m = *m0;
|
||||
struct ip *h = mtod(m, struct ip *);
|
||||
|
||||
/* Clear IP_DF if no-df was requested */
|
||||
if (flags & PFRULE_NODF && h->ip_off & htons(IP_DF)) {
|
||||
u_int16_t ip_off = h->ip_off;
|
||||
|
||||
h->ip_off &= htons(~IP_DF);
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
|
||||
}
|
||||
|
||||
/* Enforce a minimum ttl, may cause endless packet loops */
|
||||
if (min_ttl && h->ip_ttl < min_ttl) {
|
||||
u_int16_t ip_ttl = h->ip_ttl;
|
||||
|
||||
h->ip_ttl = min_ttl;
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
|
||||
}
|
||||
|
||||
/* Enforce tos */
|
||||
if (flags & PFRULE_SET_TOS) {
|
||||
u_int16_t ov, nv;
|
||||
|
||||
ov = *(u_int16_t *)h;
|
||||
h->ip_tos = tos;
|
||||
nv = *(u_int16_t *)h;
|
||||
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ov, nv, 0);
|
||||
}
|
||||
|
||||
/* random-id, but not for fragments */
|
||||
if (flags & PFRULE_RANDOMID && !(h->ip_off & ~htons(IP_DF))) {
|
||||
u_int16_t ip_id = h->ip_id;
|
||||
|
||||
h->ip_id = ip_randomid();
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
void
|
||||
pf_scrub_ip6(struct mbuf **m0, u_int8_t min_ttl)
|
||||
{
|
||||
struct mbuf *m = *m0;
|
||||
struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
|
||||
|
||||
/* Enforce a minimum ttl, may cause endless packet loops */
|
||||
if (min_ttl && h->ip6_hlim < min_ttl)
|
||||
h->ip6_hlim = min_ttl;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_osfp.c,v 1.12 2006/12/13 18:14:10 itojun Exp $ */
|
||||
/* $OpenBSD: pf_osfp.c,v 1.14 2008/06/12 18:17:01 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
||||
@ -25,7 +25,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef _KERNEL
|
||||
# include <sys/systm.h>
|
||||
#include <sys/systm.h>
|
||||
#ifndef __FreeBSD__
|
||||
#include <sys/pool.h>
|
||||
#endif
|
||||
#endif /* _KERNEL */
|
||||
#include <sys/mbuf.h>
|
||||
|
||||
@ -42,10 +45,17 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet6/in6_var.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
# define DPFPRINTF(format, x...) \
|
||||
#ifdef __FreeBSD__
|
||||
#define DPFPRINTF(format, x...) \
|
||||
if (V_pf_status.debug >= PF_DEBUG_NOISY) \
|
||||
printf(format , ##x)
|
||||
#else
|
||||
#define DPFPRINTF(format, x...) \
|
||||
if (pf_status.debug >= PF_DEBUG_NOISY) \
|
||||
printf(format , ##x)
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
typedef uma_zone_t pool_t;
|
||||
#else
|
||||
@ -55,33 +65,43 @@ typedef struct pool pool_t;
|
||||
#else
|
||||
/* Userland equivalents so we can lend code to tcpdump et al. */
|
||||
|
||||
# include <arpa/inet.h>
|
||||
# include <errno.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <netdb.h>
|
||||
# define pool_t int
|
||||
# define pool_get(pool, flags) malloc(*(pool))
|
||||
# define pool_put(pool, item) free(item)
|
||||
# define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#define pool_t int
|
||||
#define pool_get(pool, flags) malloc(*(pool))
|
||||
#define pool_put(pool, item) free(item)
|
||||
#define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
|
||||
|
||||
# ifdef __FreeBSD__
|
||||
# define NTOHS(x) (x) = ntohs((u_int16_t)(x))
|
||||
# endif
|
||||
#ifdef __FreeBSD__
|
||||
#define NTOHS(x) (x) = ntohs((u_int16_t)(x))
|
||||
#endif
|
||||
|
||||
# ifdef PFDEBUG
|
||||
# include <sys/stdarg.h>
|
||||
# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
|
||||
# else
|
||||
# define DPFPRINTF(format, x...) ((void)0)
|
||||
# endif /* PFDEBUG */
|
||||
#ifdef PFDEBUG
|
||||
#include <sys/stdarg.h>
|
||||
#define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
|
||||
#else
|
||||
#define DPFPRINTF(format, x...) ((void)0)
|
||||
#endif /* PFDEBUG */
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
|
||||
VNET_DEFINE(struct pf_osfp_list, pf_osfp_list);
|
||||
#define V_pf_osfp_list VNET(pf_osfp_list)
|
||||
VNET_DEFINE(pool_t, pf_osfp_entry_pl);
|
||||
#define pf_osfp_entry_pl VNET(pf_osfp_entry_pl)
|
||||
VNET_DEFINE(pool_t, pf_osfp_pl);
|
||||
#define pf_osfp_pl VNET(pf_osfp_pl)
|
||||
#else
|
||||
SLIST_HEAD(pf_osfp_list, pf_os_fingerprint) pf_osfp_list;
|
||||
pool_t pf_osfp_entry_pl;
|
||||
pool_t pf_osfp_pl;
|
||||
#endif
|
||||
|
||||
struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
|
||||
struct pf_os_fingerprint *, u_int8_t);
|
||||
@ -264,7 +284,11 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
|
||||
(fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
|
||||
fp.fp_wscale);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if ((fpresult = pf_osfp_find(&V_pf_osfp_list, &fp,
|
||||
#else
|
||||
if ((fpresult = pf_osfp_find(&pf_osfp_list, &fp,
|
||||
#endif
|
||||
PF_OSFP_MAXTTL_OFFSET)))
|
||||
return (&fpresult->fp_oses);
|
||||
return (NULL);
|
||||
@ -317,13 +341,16 @@ pf_osfp_initialize(void)
|
||||
UMA_CREATE(pf_osfp_pl, struct pf_os_fingerprint, "pfosfp");
|
||||
error = 0;
|
||||
} while(0);
|
||||
|
||||
SLIST_INIT(&V_pf_osfp_list);
|
||||
#else
|
||||
pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
|
||||
"pfosfpen", &pool_allocator_nointr);
|
||||
pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
|
||||
"pfosfp", &pool_allocator_nointr);
|
||||
#endif
|
||||
SLIST_INIT(&pf_osfp_list);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#ifdef _KERNEL
|
||||
return (error);
|
||||
@ -337,6 +364,7 @@ pf_osfp_initialize(void)
|
||||
void
|
||||
pf_osfp_cleanup(void)
|
||||
{
|
||||
|
||||
UMA_DESTROY(pf_osfp_entry_pl);
|
||||
UMA_DESTROY(pf_osfp_pl);
|
||||
}
|
||||
@ -349,8 +377,13 @@ pf_osfp_flush(void)
|
||||
struct pf_os_fingerprint *fp;
|
||||
struct pf_osfp_entry *entry;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
while ((fp = SLIST_FIRST(&V_pf_osfp_list))) {
|
||||
SLIST_REMOVE_HEAD(&V_pf_osfp_list, fp_next);
|
||||
#else
|
||||
while ((fp = SLIST_FIRST(&pf_osfp_list))) {
|
||||
SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
|
||||
#endif
|
||||
while ((entry = SLIST_FIRST(&fp->fp_oses))) {
|
||||
SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
|
||||
pool_put(&pf_osfp_entry_pl, entry);
|
||||
@ -377,6 +410,7 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
|
||||
fpadd.fp_wscale = fpioc->fp_wscale;
|
||||
fpadd.fp_ttl = fpioc->fp_ttl;
|
||||
|
||||
#if 0 /* XXX RYAN wants to fix logging */
|
||||
DPFPRINTF("adding osfp %s %s %s = %s%d:%d:%d:%s%d:0x%llx %d "
|
||||
"(TS=%s,M=%s%d,W=%s%d) %x\n",
|
||||
fpioc->fp_os.fp_class_nm, fpioc->fp_os.fp_version_nm,
|
||||
@ -400,17 +434,31 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
|
||||
(fpadd.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
|
||||
fpadd.fp_wscale,
|
||||
fpioc->fp_os.fp_os);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if ((fp = pf_osfp_find_exact(&V_pf_osfp_list, &fpadd))) {
|
||||
#else
|
||||
if ((fp = pf_osfp_find_exact(&pf_osfp_list, &fpadd))) {
|
||||
#endif
|
||||
SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
|
||||
if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
|
||||
return (EEXIST);
|
||||
}
|
||||
if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL)
|
||||
if ((entry = pool_get(&pf_osfp_entry_pl,
|
||||
#ifdef __FreeBSD__
|
||||
PR_NOWAIT)) == NULL)
|
||||
#else
|
||||
PR_WAITOK|PR_LIMITFAIL)) == NULL)
|
||||
#endif
|
||||
return (ENOMEM);
|
||||
} else {
|
||||
if ((fp = pool_get(&pf_osfp_pl, PR_NOWAIT)) == NULL)
|
||||
if ((fp = pool_get(&pf_osfp_pl,
|
||||
#ifdef __FreeBSD__
|
||||
PR_NOWAIT)) == NULL)
|
||||
#else
|
||||
PR_WAITOK|PR_LIMITFAIL)) == NULL)
|
||||
#endif
|
||||
return (ENOMEM);
|
||||
memset(fp, 0, sizeof(*fp));
|
||||
fp->fp_tcpopts = fpioc->fp_tcpopts;
|
||||
@ -422,11 +470,20 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
|
||||
fp->fp_wscale = fpioc->fp_wscale;
|
||||
fp->fp_ttl = fpioc->fp_ttl;
|
||||
SLIST_INIT(&fp->fp_oses);
|
||||
if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL) {
|
||||
if ((entry = pool_get(&pf_osfp_entry_pl,
|
||||
#ifdef __FreeBSD__
|
||||
PR_NOWAIT)) == NULL) {
|
||||
#else
|
||||
PR_WAITOK|PR_LIMITFAIL)) == NULL) {
|
||||
#endif
|
||||
pool_put(&pf_osfp_pl, fp);
|
||||
return (ENOMEM);
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
pf_osfp_insert(&V_pf_osfp_list, fp);
|
||||
#else
|
||||
pf_osfp_insert(&pf_osfp_list, fp);
|
||||
#endif
|
||||
}
|
||||
memcpy(entry, &fpioc->fp_os, sizeof(*entry));
|
||||
|
||||
@ -452,7 +509,7 @@ pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
|
||||
{
|
||||
struct pf_os_fingerprint *f;
|
||||
|
||||
#define MATCH_INT(_MOD, _DC, _field) \
|
||||
#define MATCH_INT(_MOD, _DC, _field) \
|
||||
if ((f->fp_flags & _DC) == 0) { \
|
||||
if ((f->fp_flags & _MOD) == 0) { \
|
||||
if (f->_field != find->_field) \
|
||||
@ -480,10 +537,11 @@ pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
|
||||
if (find->fp_mss == 0)
|
||||
continue;
|
||||
|
||||
/* Some "smart" NAT devices and DSL routers will tweak the MSS size and
|
||||
/*
|
||||
* Some "smart" NAT devices and DSL routers will tweak the MSS size and
|
||||
* will set it to whatever is suitable for the link type.
|
||||
*/
|
||||
#define SMART_MSS 1460
|
||||
#define SMART_MSS 1460
|
||||
if ((find->fp_wsize % find->fp_mss ||
|
||||
find->fp_wsize / find->fp_mss !=
|
||||
f->fp_wsize) &&
|
||||
@ -495,8 +553,8 @@ pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
|
||||
if (find->fp_mss == 0)
|
||||
continue;
|
||||
|
||||
#define MTUOFF (sizeof(struct ip) + sizeof(struct tcphdr))
|
||||
#define SMART_MTU (SMART_MSS + MTUOFF)
|
||||
#define MTUOFF (sizeof(struct ip) + sizeof(struct tcphdr))
|
||||
#define SMART_MTU (SMART_MSS + MTUOFF)
|
||||
if ((find->fp_wsize % (find->fp_mss + MTUOFF) ||
|
||||
find->fp_wsize / (find->fp_mss + MTUOFF) !=
|
||||
f->fp_wsize) &&
|
||||
@ -567,7 +625,11 @@ pf_osfp_get(struct pf_osfp_ioctl *fpioc)
|
||||
|
||||
|
||||
memset(fpioc, 0, sizeof(*fpioc));
|
||||
#ifdef __FreeBSD__
|
||||
SLIST_FOREACH(fp, &V_pf_osfp_list, fp_next) {
|
||||
#else
|
||||
SLIST_FOREACH(fp, &pf_osfp_list, fp_next) {
|
||||
#endif
|
||||
SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
|
||||
if (i++ == num) {
|
||||
fpioc->fp_mss = fp->fp_mss;
|
||||
@ -594,7 +656,11 @@ pf_osfp_validate(void)
|
||||
{
|
||||
struct pf_os_fingerprint *f, *f2, find;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
SLIST_FOREACH(f, &V_pf_osfp_list, fp_next) {
|
||||
#else
|
||||
SLIST_FOREACH(f, &pf_osfp_list, fp_next) {
|
||||
#endif
|
||||
memcpy(&find, f, sizeof(find));
|
||||
|
||||
/* We do a few MSS/th_win percolations to make things unique */
|
||||
@ -606,7 +672,11 @@ pf_osfp_validate(void)
|
||||
find.fp_wsize *= (find.fp_mss + 40);
|
||||
else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
|
||||
find.fp_wsize *= 2;
|
||||
#ifdef __FreeBSD__
|
||||
if (f != (f2 = pf_osfp_find(&V_pf_osfp_list, &find, 0))) {
|
||||
#else
|
||||
if (f != (f2 = pf_osfp_find(&pf_osfp_list, &find, 0))) {
|
||||
#endif
|
||||
if (f2)
|
||||
printf("Found \"%s %s %s\" instead of "
|
||||
"\"%s %s %s\"\n",
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_ruleset.c,v 1.1 2006/10/27 13:56:51 mcbride Exp $ */
|
||||
/* $OpenBSD: pf_ruleset.c,v 1.2 2008/12/18 15:31:37 dhill Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -61,48 +61,55 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
# define DPFPRINTF(format, x...) \
|
||||
if (pf_status.debug >= PF_DEBUG_NOISY) \
|
||||
printf(format , ##x)
|
||||
#ifdef __FreeBSD__
|
||||
#define rs_malloc(x) malloc(x, M_TEMP, M_NOWAIT)
|
||||
#define DPFPRINTF(format, x...) \
|
||||
if (V_pf_status.debug >= PF_DEBUG_NOISY) \
|
||||
printf(format , ##x)
|
||||
#else
|
||||
#define rs_malloc(x) malloc(x, M_TEMP, M_WAITOK)
|
||||
#define DPFPRINTF(format, x...) \
|
||||
if (pf_status.debug >= PF_DEBUG_NOISY) \
|
||||
printf(format , ##x)
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define rs_malloc(x) malloc(x, M_TEMP, M_NOWAIT|M_ZERO)
|
||||
#else
|
||||
#define rs_malloc(x) malloc(x, M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO)
|
||||
#endif
|
||||
#define rs_free(x) free(x, M_TEMP)
|
||||
|
||||
#else
|
||||
/* Userland equivalents so we can lend code to pfctl et al. */
|
||||
|
||||
# include <arpa/inet.h>
|
||||
# include <errno.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# define rs_malloc(x) malloc(x)
|
||||
# define rs_free(x) free(x)
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define rs_malloc(x) calloc(1, x)
|
||||
#define rs_free(x) free(x)
|
||||
|
||||
# ifdef PFDEBUG
|
||||
# include <sys/stdarg.h>
|
||||
# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
|
||||
# else
|
||||
# define DPFPRINTF(format, x...) ((void)0)
|
||||
# endif /* PFDEBUG */
|
||||
#ifdef PFDEBUG
|
||||
#include <sys/stdarg.h>
|
||||
#define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
|
||||
#else
|
||||
#define DPFPRINTF(format, x...) ((void)0)
|
||||
#endif /* PFDEBUG */
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#if defined(__FreeBSD__) && !defined(_KERNEL)
|
||||
#undef V_pf_anchors
|
||||
#define V_pf_anchors pf_anchors
|
||||
|
||||
#undef pf_main_ruleset
|
||||
#define pf_main_ruleset pf_main_anchor.ruleset
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) && defined(_KERNEL)
|
||||
VNET_DEFINE(struct pf_anchor_global, pf_anchors);
|
||||
VNET_DEFINE(struct pf_anchor, pf_main_anchor);
|
||||
#else
|
||||
struct pf_anchor_global pf_anchors;
|
||||
struct pf_anchor pf_main_anchor;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
/* XXX: hum? */
|
||||
int pf_get_ruleset_number(u_int8_t);
|
||||
void pf_init_ruleset(struct pf_ruleset *);
|
||||
int pf_anchor_setup(struct pf_rule *,
|
||||
const struct pf_ruleset *, const char *);
|
||||
int pf_anchor_copyout(const struct pf_ruleset *,
|
||||
const struct pf_rule *, struct pfioc_rule *);
|
||||
void pf_anchor_remove(struct pf_rule *);
|
||||
#endif
|
||||
|
||||
static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
|
||||
@ -168,9 +175,14 @@ pf_find_anchor(const char *path)
|
||||
struct pf_anchor *key, *found;
|
||||
|
||||
key = (struct pf_anchor *)rs_malloc(sizeof(*key));
|
||||
memset(key, 0, sizeof(*key));
|
||||
if (key == NULL)
|
||||
return (NULL);
|
||||
strlcpy(key->path, path, sizeof(key->path));
|
||||
#ifdef __FreeBSD__
|
||||
found = RB_FIND(pf_anchor_global, &V_pf_anchors, key);
|
||||
#else
|
||||
found = RB_FIND(pf_anchor_global, &pf_anchors, key);
|
||||
#endif
|
||||
rs_free(key);
|
||||
return (found);
|
||||
}
|
||||
@ -210,7 +222,8 @@ pf_find_or_create_ruleset(const char *path)
|
||||
if (ruleset != NULL)
|
||||
return (ruleset);
|
||||
p = (char *)rs_malloc(MAXPATHLEN);
|
||||
bzero(p, MAXPATHLEN);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
strlcpy(p, path, MAXPATHLEN);
|
||||
while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
|
||||
*q = 0;
|
||||
@ -242,7 +255,6 @@ pf_find_or_create_ruleset(const char *path)
|
||||
rs_free(p);
|
||||
return (NULL);
|
||||
}
|
||||
memset(anchor, 0, sizeof(*anchor));
|
||||
RB_INIT(&anchor->children);
|
||||
strlcpy(anchor->name, q, sizeof(anchor->name));
|
||||
if (parent != NULL) {
|
||||
@ -251,7 +263,11 @@ pf_find_or_create_ruleset(const char *path)
|
||||
strlcat(anchor->path, "/", sizeof(anchor->path));
|
||||
}
|
||||
strlcat(anchor->path, anchor->name, sizeof(anchor->path));
|
||||
#ifdef __FreeBSD__
|
||||
if ((dup = RB_INSERT(pf_anchor_global, &V_pf_anchors, anchor)) !=
|
||||
#else
|
||||
if ((dup = RB_INSERT(pf_anchor_global, &pf_anchors, anchor)) !=
|
||||
#endif
|
||||
NULL) {
|
||||
printf("pf_find_or_create_ruleset: RB_INSERT1 "
|
||||
"'%s' '%s' collides with '%s' '%s'\n",
|
||||
@ -268,7 +284,11 @@ pf_find_or_create_ruleset(const char *path)
|
||||
"RB_INSERT2 '%s' '%s' collides with "
|
||||
"'%s' '%s'\n", anchor->path, anchor->name,
|
||||
dup->path, dup->name);
|
||||
#ifdef __FreeBSD__
|
||||
RB_REMOVE(pf_anchor_global, &V_pf_anchors,
|
||||
#else
|
||||
RB_REMOVE(pf_anchor_global, &pf_anchors,
|
||||
#endif
|
||||
anchor);
|
||||
rs_free(anchor);
|
||||
rs_free(p);
|
||||
@ -304,7 +324,11 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
|
||||
!TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
|
||||
ruleset->rules[i].inactive.open)
|
||||
return;
|
||||
#ifdef __FreeBSD__
|
||||
RB_REMOVE(pf_anchor_global, &V_pf_anchors, ruleset->anchor);
|
||||
#else
|
||||
RB_REMOVE(pf_anchor_global, &pf_anchors, ruleset->anchor);
|
||||
#endif
|
||||
if ((parent = ruleset->anchor->parent) != NULL)
|
||||
RB_REMOVE(pf_anchor_node, &parent->children,
|
||||
ruleset->anchor);
|
||||
@ -328,7 +352,8 @@ pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
|
||||
if (!name[0])
|
||||
return (0);
|
||||
path = (char *)rs_malloc(MAXPATHLEN);
|
||||
bzero(path, MAXPATHLEN);
|
||||
if (path == NULL)
|
||||
return (1);
|
||||
if (name[0] == '/')
|
||||
strlcpy(path, name + 1, MAXPATHLEN);
|
||||
else {
|
||||
@ -386,7 +411,8 @@ pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r,
|
||||
int i;
|
||||
|
||||
a = (char *)rs_malloc(MAXPATHLEN);
|
||||
bzero(a, MAXPATHLEN);
|
||||
if (a == NULL)
|
||||
return (1);
|
||||
if (rs->anchor == NULL)
|
||||
a[0] = 0;
|
||||
else
|
||||
|
@ -1,168 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
|
||||
* The 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.
|
||||
* 4. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/md5.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/tcp_timer.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/pfvar.h>
|
||||
|
||||
/*
|
||||
* Following is where TCP initial sequence number generation occurs.
|
||||
*
|
||||
* There are two places where we must use initial sequence numbers:
|
||||
* 1. In SYN-ACK packets.
|
||||
* 2. In SYN packets.
|
||||
*
|
||||
* All ISNs for SYN-ACK packets are generated by the syncache. See
|
||||
* tcp_syncache.c for details.
|
||||
*
|
||||
* The ISNs in SYN packets must be monotonic; TIME_WAIT recycling
|
||||
* depends on this property. In addition, these ISNs should be
|
||||
* unguessable so as to prevent connection hijacking. To satisfy
|
||||
* the requirements of this situation, the algorithm outlined in
|
||||
* RFC 1948 is used, with only small modifications.
|
||||
*
|
||||
* Implementation details:
|
||||
*
|
||||
* Time is based off the system timer, and is corrected so that it
|
||||
* increases by one megabyte per second. This allows for proper
|
||||
* recycling on high speed LANs while still leaving over an hour
|
||||
* before rollover.
|
||||
*
|
||||
* As reading the *exact* system time is too expensive to be done
|
||||
* whenever setting up a TCP connection, we increment the time
|
||||
* offset in two ways. First, a small random positive increment
|
||||
* is added to isn_offset for each connection that is set up.
|
||||
* Second, the function tcp_isn_tick fires once per clock tick
|
||||
* and increments isn_offset as necessary so that sequence numbers
|
||||
* are incremented at approximately ISN_BYTES_PER_SECOND. The
|
||||
* random positive increments serve only to ensure that the same
|
||||
* exact sequence number is never sent out twice (as could otherwise
|
||||
* happen when a port is recycled in less than the system tick
|
||||
* interval.)
|
||||
*
|
||||
* net.inet.tcp.isn_reseed_interval controls the number of seconds
|
||||
* between seeding of isn_secret. This is normally set to zero,
|
||||
* as reseeding should not be necessary.
|
||||
*
|
||||
* Locking of the global variables isn_secret, isn_last_reseed, isn_offset,
|
||||
* isn_offset_old, and isn_ctx is performed using the TCP pcbinfo lock. In
|
||||
* general, this means holding an exclusive (write) lock.
|
||||
*/
|
||||
|
||||
#define ISN_BYTES_PER_SECOND 1048576
|
||||
#define ISN_STATIC_INCREMENT 4096
|
||||
#define ISN_RANDOM_INCREMENT (4096 - 1)
|
||||
|
||||
static u_char pf_isn_secret[32];
|
||||
static int pf_isn_last_reseed;
|
||||
static u_int32_t pf_isn_offset;
|
||||
|
||||
u_int32_t
|
||||
pf_new_isn(struct pf_state *s)
|
||||
{
|
||||
MD5_CTX isn_ctx;
|
||||
u_int32_t md5_buffer[4];
|
||||
u_int32_t new_isn;
|
||||
struct pf_state_host *src, *dst;
|
||||
|
||||
/* Seed if this is the first use, reseed if requested. */
|
||||
if (pf_isn_last_reseed == 0) {
|
||||
read_random(&pf_isn_secret, sizeof(pf_isn_secret));
|
||||
pf_isn_last_reseed = ticks;
|
||||
}
|
||||
|
||||
if (s->direction == PF_IN) {
|
||||
src = &s->ext;
|
||||
dst = &s->gwy;
|
||||
} else {
|
||||
src = &s->lan;
|
||||
dst = &s->ext;
|
||||
}
|
||||
|
||||
/* Compute the md5 hash and return the ISN. */
|
||||
MD5Init(&isn_ctx);
|
||||
MD5Update(&isn_ctx, (u_char *) &dst->port, sizeof(u_short));
|
||||
MD5Update(&isn_ctx, (u_char *) &src->port, sizeof(u_short));
|
||||
#ifdef INET6
|
||||
if (s->af == AF_INET6) {
|
||||
MD5Update(&isn_ctx, (u_char *) &dst->addr,
|
||||
sizeof(struct in6_addr));
|
||||
MD5Update(&isn_ctx, (u_char *) &src->addr,
|
||||
sizeof(struct in6_addr));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
MD5Update(&isn_ctx, (u_char *) &dst->addr,
|
||||
sizeof(struct in_addr));
|
||||
MD5Update(&isn_ctx, (u_char *) &src->addr,
|
||||
sizeof(struct in_addr));
|
||||
}
|
||||
MD5Update(&isn_ctx, (u_char *) &pf_isn_secret, sizeof(pf_isn_secret));
|
||||
MD5Final((u_char *) &md5_buffer, &isn_ctx);
|
||||
new_isn = (tcp_seq) md5_buffer[0];
|
||||
pf_isn_offset += ISN_STATIC_INCREMENT +
|
||||
(arc4random() & ISN_RANDOM_INCREMENT);
|
||||
new_isn += pf_isn_offset;
|
||||
return (new_isn);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -241,6 +241,7 @@ SUBDIR= ${_3dfx} \
|
||||
pcn \
|
||||
${_pf} \
|
||||
${_pflog} \
|
||||
${_pfsync} \
|
||||
plip \
|
||||
${_pmc} \
|
||||
portalfs \
|
||||
@ -382,6 +383,9 @@ _netgraph= netgraph
|
||||
${MK_INET6_SUPPORT} != "no")) || defined(ALL_MODULES)
|
||||
_pf= pf
|
||||
_pflog= pflog
|
||||
.if ${MK_INET_SUPPORT} != "no"
|
||||
_pfsync= pfsync
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "i386"
|
||||
|
@ -6,16 +6,18 @@
|
||||
.PATH: ${.CURDIR}/../../contrib/pf/netinet
|
||||
|
||||
KMOD= pf
|
||||
SRCS = pf.c pf_if.c pf_subr.c pf_osfp.c pf_ioctl.c pf_norm.c pf_table.c \
|
||||
SRCS= pf.c pf_if.c pf_lb.c pf_osfp.c pf_ioctl.c pf_norm.c pf_table.c \
|
||||
pf_ruleset.c \
|
||||
in4_cksum.c \
|
||||
opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
|
||||
opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h opt_global.h
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/pf
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/pf
|
||||
|
||||
.if !defined(KERNBUILDDIR)
|
||||
.if ${MK_INET_SUPPORT} != "no"
|
||||
opt_inet.h:
|
||||
echo "#define INET 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
.if ${MK_INET6_SUPPORT} != "no"
|
||||
opt_inet6.h:
|
||||
@ -26,9 +28,17 @@ opt_bpf.h:
|
||||
echo "#define DEV_BPF 1" > ${.TARGET}
|
||||
|
||||
# pflog can be loaded as a module, have the additional checks turned on
|
||||
# pfsync can be loaded as a module, have the additional checks turned on
|
||||
opt_pf.h:
|
||||
echo "#define DEV_PF 1" > ${.TARGET}
|
||||
echo "#define DEV_PFLOG 1" >> ${.TARGET}
|
||||
echo "#define DEV_PFSYNC 1" >> ${.TARGET}
|
||||
echo "#define DEV_PFLOW 1" >> ${.TARGET}
|
||||
|
||||
.if defined(VIMAGE)
|
||||
opt_global.h:
|
||||
echo "#define VIMAGE 1" >> ${.TARGET}
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -5,14 +5,19 @@
|
||||
.PATH: ${.CURDIR}/../../contrib/pf/net
|
||||
|
||||
KMOD= pflog
|
||||
SRCS = if_pflog.c \
|
||||
SRCS= if_pflog.c \
|
||||
opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/pf
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/pf
|
||||
SRCS+= bus_if.h device_if.h
|
||||
|
||||
.if !defined(KERNBUILDDIR)
|
||||
.if defined(KERNBUILDDIR)
|
||||
MKDEP+= -include ${KERNBUILDDIR}/opt_global.h
|
||||
.else
|
||||
.if ${MK_INET_SUPPORT} != "no"
|
||||
opt_inet.h:
|
||||
echo "#define INET 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
.if ${MK_INET6_SUPPORT} != "no"
|
||||
opt_inet6.h:
|
||||
@ -21,6 +26,13 @@ opt_inet6.h:
|
||||
|
||||
opt_bpf.h:
|
||||
echo "#define DEV_BPF 1" > ${.TARGET}
|
||||
|
||||
.if defined(VIMAGE)
|
||||
opt_global.h:
|
||||
echo "#define VIMAGE 1" >> ${.TARGET}
|
||||
CFLAGS+= -include opt_global.h
|
||||
MKDEP+= -include opt_global.h
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
38
sys/modules/pfsync/Makefile
Normal file
38
sys/modules/pfsync/Makefile
Normal file
@ -0,0 +1,38 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
.PATH: ${.CURDIR}/../../contrib/pf/net
|
||||
|
||||
KMOD= pfsync
|
||||
SRCS= if_pfsync.c \
|
||||
opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/pf
|
||||
SRCS+= bus_if.h device_if.h
|
||||
|
||||
.if defined(KERNBUILDDIR)
|
||||
MKDEP+= -include ${KERNBUILDDIR}/opt_global.h
|
||||
.else
|
||||
.if ${MK_INET_SUPPORT} != "no"
|
||||
opt_inet.h:
|
||||
echo "#define INET 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
.if ${MK_INET6_SUPPORT} != "no"
|
||||
opt_inet6.h:
|
||||
echo "#define INET6 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
opt_bpf.h:
|
||||
echo "#define DEV_BPF 1" > ${.TARGET}
|
||||
|
||||
.if defined(VIMAGE)
|
||||
opt_global.h:
|
||||
echo "#define VIMAGE 1" >> ${.TARGET}
|
||||
CFLAGS+= -include opt_global.h
|
||||
MKDEP+= -include opt_global.h
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -256,6 +256,8 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
|
||||
#endif
|
||||
}
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
error = ip_output(m, NULL, &sc->gif_ro, 0, NULL, NULL);
|
||||
|
||||
if (!(GIF2IFP(sc)->if_flags & IFF_LINK0) &&
|
||||
|
@ -675,6 +675,8 @@ icmp_reflect(struct mbuf *m)
|
||||
goto done; /* Ip_output() will check for broadcast */
|
||||
}
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
t = ip->ip_dst;
|
||||
ip->ip_dst = ip->ip_src;
|
||||
|
||||
|
@ -1670,10 +1670,6 @@ do { \
|
||||
break;
|
||||
}
|
||||
at->qid = altq->qid;
|
||||
if (is_ipv4)
|
||||
at->af = AF_INET;
|
||||
else
|
||||
at->af = AF_LINK;
|
||||
at->hdr = ip;
|
||||
break;
|
||||
}
|
||||
|
@ -100,6 +100,9 @@ void (*ip_divert_ptr)(struct mbuf *, int);
|
||||
int (*ng_ipfw_input_p)(struct mbuf **, int,
|
||||
struct ip_fw_args *, int);
|
||||
|
||||
/* Hook for telling pf that the destination address changed */
|
||||
void (*m_addr_chg_pf_p)(struct mbuf *m);
|
||||
|
||||
#ifdef INET
|
||||
/*
|
||||
* Hooks for multicast routing. They all default to NULL, so leave them not
|
||||
|
@ -1177,6 +1177,8 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
|
||||
ip6cp.ip6c_src = &icmp6src;
|
||||
ip6cp.ip6c_nxt = nxt;
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
if (icmp6type == ICMP6_PACKET_TOO_BIG) {
|
||||
notifymtu = ntohl(icmp6->icmp6_mtu);
|
||||
ip6cp.ip6c_cmdarg = (void *)¬ifymtu;
|
||||
@ -2299,6 +2301,8 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
|
||||
m->m_flags &= ~(M_BCAST|M_MCAST);
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
|
||||
if (outif)
|
||||
icmp6_ifoutstat_inc(outif, type, code);
|
||||
|
@ -262,6 +262,8 @@ in6_gif_output(struct ifnet *ifp,
|
||||
#endif
|
||||
}
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
#ifdef IPV6_MINMTU
|
||||
/*
|
||||
* force fragmentation to minimum MTU, to avoid path MTU discovery.
|
||||
|
@ -473,6 +473,8 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
|
||||
|
||||
key_sa_recordxfer(sav, m); /* record data transfer */
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
#ifdef DEV_ENC
|
||||
encif->if_ipackets++;
|
||||
encif->if_ibytes += m->m_pkthdr.len;
|
||||
|
@ -191,6 +191,8 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
|
||||
}
|
||||
key_sa_recordxfer(sav, m); /* record data transfer */
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
/*
|
||||
* We're done with IPsec processing, transmit the packet using the
|
||||
* appropriate network protocol (IP or IPv6). SPD lookup will be
|
||||
|
@ -392,6 +392,8 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
|
||||
panic("%s: bogus ip version %u", __func__, v>>4);
|
||||
}
|
||||
|
||||
m_addr_changed(m);
|
||||
|
||||
if (netisr_queue(isr, m)) { /* (0) on success. */
|
||||
V_ipipstat.ipips_qfull++;
|
||||
DPRINTF(("%s: packet dropped because of full queue\n",
|
||||
|
@ -695,6 +695,16 @@ m_last(struct mbuf *m)
|
||||
return (m);
|
||||
}
|
||||
|
||||
extern void (*m_addr_chg_pf_p)(struct mbuf *m);
|
||||
|
||||
static __inline void
|
||||
m_addr_changed(struct mbuf *m)
|
||||
{
|
||||
|
||||
if (m_addr_chg_pf_p)
|
||||
m_addr_chg_pf_p(m);
|
||||
}
|
||||
|
||||
/*
|
||||
* mbuf, cluster, and external object allocation macros (for compatibility
|
||||
* purposes).
|
||||
|
@ -58,7 +58,7 @@
|
||||
* in the range 5 to 9.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 900038 /* Master, propagated to newvers */
|
||||
#define __FreeBSD_version 900039 /* Master, propagated to newvers */
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define P_OSREL_SIGSEGV 700004
|
||||
|
@ -5,14 +5,14 @@
|
||||
PROG= ftp-proxy
|
||||
MAN= ftp-proxy.8
|
||||
|
||||
SRCS= ftp-proxy.c filter.c
|
||||
SRCS= ftp-proxy.c filter.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../contrib/pf/libevent
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/contrib/pf
|
||||
|
||||
DPADD= ${LIBEVENT}
|
||||
LDADD= ${LIBEVENT}
|
||||
LDADD+= ${LIBEVENT}
|
||||
DPADD+= ${LIBEVENT}
|
||||
|
||||
WARNS?= 2
|
||||
WARNS?= 3
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
Loading…
Reference in New Issue
Block a user