Resolve conflicts created during the import of pf 3.7 Some features are
missing and will be implemented in a second step. This is functional as is. Tested by: freebsd-pf, pfsense.org Obtained from: OpenBSD
This commit is contained in:
parent
f9e60af500
commit
b28479dfe2
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authpf.c,v 1.75 2004/01/29 01:55:10 deraadt Exp $ */
|
||||
/* $OpenBSD: authpf.c,v 1.89 2005/02/10 04:24:15 joel Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
|
||||
@ -32,7 +32,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/pfvar.h>
|
||||
@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <login_cap.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
@ -48,9 +51,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pfctl_parser.h>
|
||||
#include <pfctl.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
extern int symset(const char *, const char *, int);
|
||||
@ -61,11 +61,13 @@ static int allowed_luser(char *);
|
||||
static int check_luser(char *, char *);
|
||||
static int remove_stale_rulesets(void);
|
||||
static int change_filter(int, const char *, const char *);
|
||||
static int change_table(int, const char *, const char *);
|
||||
static void authpf_kill_states(void);
|
||||
|
||||
int dev; /* pf device */
|
||||
char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
|
||||
char rulesetname[PF_RULESET_NAME_SIZE];
|
||||
char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
|
||||
char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
|
||||
|
||||
FILE *pidfp;
|
||||
char *infile; /* file name printed by yyerror() in parse.y */
|
||||
@ -94,10 +96,12 @@ main(int argc, char *argv[])
|
||||
{
|
||||
int lockcnt = 0, n, pidfd;
|
||||
FILE *config;
|
||||
struct in_addr ina;
|
||||
struct in6_addr ina;
|
||||
struct passwd *pw;
|
||||
char *cp;
|
||||
uid_t uid;
|
||||
char *shell;
|
||||
login_cap_t *lc;
|
||||
|
||||
config = fopen(PATH_CONFFILE, "r");
|
||||
|
||||
@ -121,7 +125,8 @@ main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
*cp = '\0';
|
||||
if (inet_pton(AF_INET, ipsrc, &ina) != 1) {
|
||||
if (inet_pton(AF_INET, ipsrc, &ina) != 1 &&
|
||||
inet_pton(AF_INET6, ipsrc, &ina) != 1) {
|
||||
syslog(LOG_ERR,
|
||||
"cannot determine IP from SSH_CLIENT %s", ipsrc);
|
||||
exit(1);
|
||||
@ -135,16 +140,31 @@ main(int argc, char *argv[])
|
||||
|
||||
uid = getuid();
|
||||
pw = getpwuid(uid);
|
||||
endpwent();
|
||||
if (pw == NULL) {
|
||||
syslog(LOG_ERR, "cannot find user for uid %u", uid);
|
||||
goto die;
|
||||
}
|
||||
if (strcmp(pw->pw_shell, PATH_AUTHPF_SHELL)) {
|
||||
|
||||
if ((lc = login_getclass(pw->pw_class)) != NULL)
|
||||
shell = (char *)login_getcapstr(lc, "shell", pw->pw_shell,
|
||||
pw->pw_shell);
|
||||
else
|
||||
shell = pw->pw_shell;
|
||||
|
||||
login_close(lc);
|
||||
|
||||
if (strcmp(shell, PATH_AUTHPF_SHELL)) {
|
||||
syslog(LOG_ERR, "wrong shell for user %s, uid %u",
|
||||
pw->pw_name, pw->pw_uid);
|
||||
if (shell != pw->pw_shell)
|
||||
free(shell);
|
||||
goto die;
|
||||
}
|
||||
|
||||
if (shell != pw->pw_shell)
|
||||
free(shell);
|
||||
|
||||
/*
|
||||
* Paranoia, but this data _does_ come from outside authpf, and
|
||||
* truncation would be bad.
|
||||
@ -155,11 +175,11 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)",
|
||||
luser, (long)getpid())) < 0 || n >= sizeof(rulesetname)) {
|
||||
luser, (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
|
||||
syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld",
|
||||
luser, (long)getpid(), (long)getpid());
|
||||
if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
|
||||
(long)getpid())) < 0 || n >= sizeof(rulesetname)) {
|
||||
(long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
|
||||
syslog(LOG_ERR, "pid too large for ruleset name");
|
||||
goto die;
|
||||
}
|
||||
@ -269,12 +289,17 @@ main(int argc, char *argv[])
|
||||
rewind(pidfp);
|
||||
fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser);
|
||||
fflush(pidfp);
|
||||
(void) ftruncate(fileno(pidfp), ftell(pidfp));
|
||||
(void) ftruncate(fileno(pidfp), ftello(pidfp));
|
||||
|
||||
if (change_filter(1, luser, ipsrc) == -1) {
|
||||
printf("Unable to modify filters\r\n");
|
||||
do_death(0);
|
||||
}
|
||||
if (change_table(1, luser, 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);
|
||||
@ -284,7 +309,7 @@ main(int argc, char *argv[])
|
||||
signal(SIGSTOP, need_death);
|
||||
signal(SIGTSTP, need_death);
|
||||
while (1) {
|
||||
printf("\r\nHello %s, ", luser);
|
||||
printf("\r\nHello %s. ", luser);
|
||||
printf("You are authenticated from host \"%s\"\r\n", ipsrc);
|
||||
setproctitle("%s@%s", luser, ipsrc);
|
||||
print_message(PATH_MESSAGE);
|
||||
@ -359,6 +384,11 @@ read_config(FILE *f)
|
||||
sizeof(anchorname)) >= sizeof(anchorname))
|
||||
goto parse_error;
|
||||
}
|
||||
if (strcasecmp(pair[0], "table") == 0) {
|
||||
if (!pair[1][0] || strlcpy(tablename, pair[1],
|
||||
sizeof(tablename)) >= sizeof(tablename))
|
||||
goto parse_error;
|
||||
}
|
||||
} while (!feof(f) && !ferror(f));
|
||||
fclose(f);
|
||||
return (0);
|
||||
@ -542,12 +572,10 @@ static int
|
||||
remove_stale_rulesets(void)
|
||||
{
|
||||
struct pfioc_ruleset prs;
|
||||
const int action[PF_RULESET_MAX] = { PF_SCRUB,
|
||||
PF_PASS, PF_NAT, PF_BINAT, PF_RDR };
|
||||
u_int32_t nr, mnr;
|
||||
|
||||
memset(&prs, 0, sizeof(prs));
|
||||
strlcpy(prs.anchor, anchorname, sizeof(prs.anchor));
|
||||
strlcpy(prs.path, anchorname, sizeof(prs.path));
|
||||
if (ioctl(dev, DIOCGETRULESETS, &prs)) {
|
||||
if (errno == EINVAL)
|
||||
return (0);
|
||||
@ -574,20 +602,25 @@ remove_stale_rulesets(void)
|
||||
(*s && (t == prs.name || *s != ')')))
|
||||
return (1);
|
||||
if (kill(pid, 0) && errno != EPERM) {
|
||||
int i;
|
||||
int i;
|
||||
struct pfioc_trans_e t_e[PF_RULESET_MAX+1];
|
||||
struct pfioc_trans t;
|
||||
|
||||
for (i = 0; i < PF_RULESET_MAX; ++i) {
|
||||
struct pfioc_rule pr;
|
||||
|
||||
memset(&pr, 0, sizeof(pr));
|
||||
memcpy(pr.anchor, prs.anchor, sizeof(pr.anchor));
|
||||
memcpy(pr.ruleset, prs.name, sizeof(pr.ruleset));
|
||||
pr.rule.action = action[i];
|
||||
if ((ioctl(dev, DIOCBEGINRULES, &pr) ||
|
||||
ioctl(dev, DIOCCOMMITRULES, &pr)) &&
|
||||
errno != EINVAL)
|
||||
return (1);
|
||||
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)
|
||||
return (1);
|
||||
mnr--;
|
||||
} else
|
||||
nr++;
|
||||
@ -601,85 +634,67 @@ remove_stale_rulesets(void)
|
||||
static int
|
||||
change_filter(int add, const char *luser, const char *ipsrc)
|
||||
{
|
||||
char fn[MAXPATHLEN];
|
||||
FILE *f = NULL;
|
||||
struct pfctl pf;
|
||||
struct pfr_buffer t;
|
||||
int i;
|
||||
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;
|
||||
int s;
|
||||
|
||||
if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
|
||||
syslog(LOG_ERR, "invalid luser/ipsrc");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
if ((i = snprintf(fn, sizeof(fn), "%s/%s/authpf.rules",
|
||||
PATH_USER_DIR, luser)) < 0 || i >= sizeof(fn)) {
|
||||
syslog(LOG_ERR, "user rule path too long");
|
||||
goto error;
|
||||
}
|
||||
if ((f = fopen(fn, "r")) == NULL && errno != ENOENT) {
|
||||
syslog(LOG_ERR, "cannot open %s (%m)", fn);
|
||||
goto error;
|
||||
}
|
||||
if (f == NULL) {
|
||||
if (strlcpy(fn, PATH_PFRULES, sizeof(fn)) >=
|
||||
sizeof(fn)) {
|
||||
syslog(LOG_ERR, "rule path too long");
|
||||
goto error;
|
||||
}
|
||||
if ((f = fopen(fn, "r")) == NULL) {
|
||||
syslog(LOG_ERR, "cannot open %s (%m)", fn);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pfctl_load_fingerprints(dev, 0)) {
|
||||
syslog(LOG_ERR, "unable to load kernel's OS fingerprints");
|
||||
goto error;
|
||||
}
|
||||
bzero(&t, sizeof(t));
|
||||
t.pfrb_type = PFRB_TRANS;
|
||||
memset(&pf, 0, sizeof(pf));
|
||||
for (i = 0; i < PF_RULESET_MAX; ++i) {
|
||||
if (pfctl_add_trans(&t, i, anchorname, rulesetname)) {
|
||||
syslog(LOG_ERR, "pfctl_add_trans %m");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) {
|
||||
syslog(LOG_ERR, "DIOCXBEGIN (%s) %m", add?"add":"remove");
|
||||
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) {
|
||||
if (symset("user_ip", ipsrc, 0) ||
|
||||
symset("user_id", luser, 0)) {
|
||||
syslog(LOG_ERR, "symset");
|
||||
goto error;
|
||||
struct stat sb;
|
||||
|
||||
if (asprintf(&fn, "%s/%s/authpf.rules", PATH_USER_DIR, luser)
|
||||
== -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;
|
||||
|
||||
pf.dev = dev;
|
||||
pf.trans = &t;
|
||||
pf.anchor = anchorname;
|
||||
pf.ruleset = rulesetname;
|
||||
|
||||
infile = fn;
|
||||
if (parse_rules(f, &pf) < 0) {
|
||||
syslog(LOG_ERR, "syntax error in rule file: "
|
||||
"authpf rules not loaded");
|
||||
goto error;
|
||||
}
|
||||
|
||||
infile = NULL;
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
err(1, "fork failed");
|
||||
case 0:
|
||||
execvp(PATH_PFCTL, pargv);
|
||||
warn("exec of %s failed", PATH_PFCTL);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) {
|
||||
syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove");
|
||||
goto error;
|
||||
/* parent */
|
||||
waitpid(pid, &s, 0);
|
||||
if (s != 0) {
|
||||
if (WIFEXITED(s)) {
|
||||
syslog(LOG_ERR, "pfctl exited abnormally");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (add) {
|
||||
@ -691,17 +706,62 @@ change_filter(int add, const char *luser, const char *ipsrc)
|
||||
ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
|
||||
}
|
||||
return (0);
|
||||
|
||||
no_mem:
|
||||
syslog(LOG_ERR, "malloc failed");
|
||||
error:
|
||||
if (f != NULL)
|
||||
fclose(f);
|
||||
if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0))
|
||||
syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove");
|
||||
|
||||
free(fdpath);
|
||||
fdpath = NULL;
|
||||
free(rsn);
|
||||
rsn = NULL;
|
||||
free(userstr);
|
||||
userstr = NULL;
|
||||
free(ipstr);
|
||||
ipstr = NULL;
|
||||
free(fn);
|
||||
fn = NULL;
|
||||
infile = NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add/remove this IP from the "authpf_users" table.
|
||||
*/
|
||||
static int
|
||||
change_table(int add, const char *luser, const char *ipsrc)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
struct pfr_addr addr;
|
||||
|
||||
bzero(&io, sizeof(io));
|
||||
strlcpy(io.pfrio_table.pfrt_name, tablename, sizeof(io.pfrio_table));
|
||||
io.pfrio_buffer = &addr;
|
||||
io.pfrio_esize = sizeof(addr);
|
||||
io.pfrio_size = 1;
|
||||
|
||||
bzero(&addr, sizeof(addr));
|
||||
if (ipsrc == NULL || !ipsrc[0])
|
||||
return (-1);
|
||||
if (inet_pton(AF_INET, ipsrc, &addr.pfra_ip4addr) == 1) {
|
||||
addr.pfra_af = AF_INET;
|
||||
addr.pfra_net = 32;
|
||||
} else if (inet_pton(AF_INET6, ipsrc, &addr.pfra_ip6addr) == 1) {
|
||||
addr.pfra_af = AF_INET6;
|
||||
addr.pfra_net = 128;
|
||||
} else {
|
||||
syslog(LOG_ERR, "invalid ipsrc");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (ioctl(dev, add ? DIOCRADDADDRS : DIOCRDELADDRS, &io) &&
|
||||
errno != ESRCH) {
|
||||
syslog(LOG_ERR, "cannot %s %s from table %s: %s",
|
||||
add ? "add" : "remove", ipsrc, tablename,
|
||||
strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is to kill off states that would otherwise be left behind stateful
|
||||
* rules. This means we don't need to allow in more traffic than we really
|
||||
@ -713,24 +773,32 @@ static void
|
||||
authpf_kill_states(void)
|
||||
{
|
||||
struct pfioc_state_kill psk;
|
||||
struct in_addr target;
|
||||
struct pf_addr target;
|
||||
|
||||
memset(&psk, 0, sizeof(psk));
|
||||
psk.psk_af = AF_INET;
|
||||
memset(&target, 0, sizeof(target));
|
||||
|
||||
inet_pton(AF_INET, ipsrc, &target);
|
||||
if (inet_pton(AF_INET, ipsrc, &target.v4) == 1)
|
||||
psk.psk_af = AF_INET;
|
||||
else if (inet_pton(AF_INET6, ipsrc, &target.v6) == 1)
|
||||
psk.psk_af = AF_INET6;
|
||||
else {
|
||||
syslog(LOG_ERR, "inet_pton(%s) failed", ipsrc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Kill all states from ipsrc */
|
||||
psk.psk_src.addr.v.a.addr.v4 = target;
|
||||
memcpy(&psk.psk_src.addr.v.a.addr, &target,
|
||||
sizeof(psk.psk_src.addr.v.a.addr));
|
||||
memset(&psk.psk_src.addr.v.a.mask, 0xff,
|
||||
sizeof(psk.psk_src.addr.v.a.mask));
|
||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||
syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)");
|
||||
|
||||
/* Kill all states to ipsrc */
|
||||
psk.psk_af = AF_INET;
|
||||
memset(&psk.psk_src, 0, sizeof(psk.psk_src));
|
||||
psk.psk_dst.addr.v.a.addr.v4 = target;
|
||||
memcpy(&psk.psk_dst.addr.v.a.addr, &target,
|
||||
sizeof(psk.psk_dst.addr.v.a.addr));
|
||||
memset(&psk.psk_dst.addr.v.a.mask, 0xff,
|
||||
sizeof(psk.psk_dst.addr.v.a.mask));
|
||||
if (ioctl(dev, DIOCKILLSTATES, &psk))
|
||||
@ -758,6 +826,7 @@ do_death(int active)
|
||||
|
||||
if (active) {
|
||||
change_filter(0, luser, ipsrc);
|
||||
change_table(0, luser, ipsrc);
|
||||
authpf_kill_states();
|
||||
remove_stale_rulesets();
|
||||
}
|
||||
@ -768,157 +837,3 @@ do_death(int active)
|
||||
syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* callbacks for parse_rules(void)
|
||||
*/
|
||||
|
||||
int
|
||||
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
|
||||
{
|
||||
u_int8_t rs_num;
|
||||
struct pfioc_rule pr;
|
||||
|
||||
switch (r->action) {
|
||||
case PF_PASS:
|
||||
case PF_DROP:
|
||||
rs_num = PF_RULESET_FILTER;
|
||||
break;
|
||||
case PF_SCRUB:
|
||||
rs_num = PF_RULESET_SCRUB;
|
||||
break;
|
||||
case PF_NAT:
|
||||
case PF_NONAT:
|
||||
rs_num = PF_RULESET_NAT;
|
||||
break;
|
||||
case PF_RDR:
|
||||
case PF_NORDR:
|
||||
rs_num = PF_RULESET_RDR;
|
||||
break;
|
||||
case PF_BINAT:
|
||||
case PF_NOBINAT:
|
||||
rs_num = PF_RULESET_BINAT;
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "invalid rule action %d", r->action);
|
||||
return (1);
|
||||
}
|
||||
|
||||
bzero(&pr, sizeof(pr));
|
||||
strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor));
|
||||
strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset));
|
||||
if (pfctl_add_pool(pf, &r->rpool, r->af))
|
||||
return (1);
|
||||
pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
|
||||
pf->ruleset);
|
||||
pr.pool_ticket = pf->paddr.ticket;
|
||||
memcpy(&pr.rule, r, sizeof(pr.rule));
|
||||
if (ioctl(pf->dev, DIOCADDRULE, &pr)) {
|
||||
syslog(LOG_ERR, "DIOCADDRULE %m");
|
||||
return (1);
|
||||
}
|
||||
pfctl_clear_pool(&r->rpool);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
|
||||
{
|
||||
struct pf_pooladdr *pa;
|
||||
|
||||
if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) {
|
||||
syslog(LOG_ERR, "DIOCBEGINADDRS %m");
|
||||
return (1);
|
||||
}
|
||||
pf->paddr.af = af;
|
||||
TAILQ_FOREACH(pa, &p->list, entries) {
|
||||
memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
|
||||
if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) {
|
||||
syslog(LOG_ERR, "DIOCADDADDR %m");
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_clear_pool(struct pf_pool *pool)
|
||||
{
|
||||
struct pf_pooladdr *pa;
|
||||
|
||||
while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
|
||||
TAILQ_REMOVE(&pool->list, pa, entries);
|
||||
free(pa);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
|
||||
{
|
||||
fprintf(stderr, "altq rules not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_optimization(struct pfctl *pf, const char *opt)
|
||||
{
|
||||
fprintf(stderr, "set optimization not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_logif(struct pfctl *pf, char *ifname)
|
||||
{
|
||||
fprintf(stderr, "set loginterface not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
|
||||
{
|
||||
fprintf(stderr, "set hostid not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
||||
{
|
||||
fprintf(stderr, "set timeout not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
||||
{
|
||||
fprintf(stderr, "set limit not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_debug(struct pfctl *pf, char *d)
|
||||
{
|
||||
fprintf(stderr, "set debug not supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
|
||||
{
|
||||
fprintf(stderr, "table definitions not yet supported in authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
|
||||
char *rulesetname, struct pfr_buffer *t)
|
||||
{
|
||||
/* never called, no anchors inside anchors, but we need the stub */
|
||||
fprintf(stderr, "load anchor not supported from authpf\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_print_title(char *title)
|
||||
{
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: ftp-proxy.8,v 1.40 2004/03/16 08:50:07 jmc Exp $
|
||||
.\" $OpenBSD: ftp-proxy.8,v 1.42 2004/11/19 00:47:23 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1996-2001
|
||||
.\" Obtuse Systems Corporation, All rights reserved.
|
||||
@ -37,14 +37,18 @@
|
||||
.Nd Internet File Transfer Protocol proxy server
|
||||
.Sh SYNOPSIS
|
||||
.Nm ftp-proxy
|
||||
.Bk -words
|
||||
.Op Fl AnrVw
|
||||
.Op Fl a Ar address
|
||||
.Op Fl D Ar debuglevel
|
||||
.Op Fl g Ar group
|
||||
.Op Fl M Ar maxport
|
||||
.Op Fl m Ar minport
|
||||
.Op Fl R Ar address[:port]
|
||||
.Op Fl S Ar address
|
||||
.Op Fl t Ar timeout
|
||||
.Op Fl u Ar user
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a proxy for the Internet File Transfer Protocol.
|
||||
@ -139,12 +143,27 @@ Without this flag,
|
||||
does not require any IP forwarding or NAT beyond the
|
||||
.Em rdr
|
||||
necessary to capture the FTP control connection.
|
||||
.It Fl R Ar address:[port]
|
||||
Reverse proxy mode for FTP servers running behind a NAT gateway.
|
||||
In this mode, no redirection is needed.
|
||||
The proxy is run from
|
||||
.Xr inetd 8
|
||||
on the port that external clients connect to (usually 21).
|
||||
Control connections and passive data connections are forwarded
|
||||
to the server.
|
||||
.It Fl r
|
||||
Use reverse host
|
||||
.Pq reverse DNS
|
||||
lookups for logging and libwrap use.
|
||||
By default,
|
||||
the proxy does not look up hostnames for libwrap or logging purposes.
|
||||
.It Fl S Ar address
|
||||
Source address to use for data connections made by the proxy.
|
||||
Useful when there are multiple addresses (aliases) available
|
||||
to the proxy.
|
||||
Clients may expect data connections to have the same source
|
||||
address as the control connections, and reject or drop other
|
||||
connections.
|
||||
.It Fl t Ar timeout
|
||||
Specifies a timeout, in seconds.
|
||||
The proxy will exit and close open connections if it sees no data
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ftp-proxy.c,v 1.35 2004/03/14 21:51:44 dhartmei Exp $ */
|
||||
/* $OpenBSD: ftp-proxy.c,v 1.41 2005/03/05 23:11:19 cloder Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-2001
|
||||
@ -131,6 +131,8 @@ double xfer_start_time;
|
||||
struct sockaddr_in real_server_sa;
|
||||
struct sockaddr_in client_listen_sa;
|
||||
struct sockaddr_in server_listen_sa;
|
||||
struct sockaddr_in proxy_sa;
|
||||
struct in_addr src_addr;
|
||||
|
||||
int client_listen_socket = -1; /* Only used in PASV mode */
|
||||
int client_data_socket = -1; /* Connected socket to real client */
|
||||
@ -141,13 +143,14 @@ int client_data_bytes, server_data_bytes;
|
||||
int AnonFtpOnly;
|
||||
int Verbose;
|
||||
int NatMode;
|
||||
int ReverseMode;
|
||||
|
||||
char ClientName[NI_MAXHOST];
|
||||
char RealServerName[NI_MAXHOST];
|
||||
char OurName[NI_MAXHOST];
|
||||
|
||||
char *User = "proxy";
|
||||
char *Group;
|
||||
const char *User = "proxy";
|
||||
const char *Group;
|
||||
|
||||
extern int Debug_Level;
|
||||
extern int Use_Rdns;
|
||||
@ -175,8 +178,9 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
syslog(LOG_NOTICE,
|
||||
"usage: %s [-AnrVw] [-a address] [-D debuglevel [-g group]"
|
||||
" [-M maxport] [-m minport] [-t timeout] [-u user]", __progname);
|
||||
"usage: %s [-AnrVw] [-a address] [-D debuglevel] [-g group]"
|
||||
" [-M maxport] [-m minport] [-R address[:port]] [-S address]"
|
||||
" [-t timeout] [-u user]", __progname);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
@ -316,7 +320,7 @@ show_xfer_stats(void)
|
||||
char tbuf[1000];
|
||||
double delta;
|
||||
size_t len;
|
||||
int i;
|
||||
int i = -1;
|
||||
|
||||
if (!Verbose)
|
||||
return;
|
||||
@ -343,21 +347,21 @@ show_xfer_stats(void)
|
||||
"data transfer complete (%dh %dm %ds",
|
||||
idelta / (60*60), (idelta % (60*60)) / 60,
|
||||
idelta % 60);
|
||||
if (i >= len)
|
||||
if (i == -1 || i >= len)
|
||||
goto logit;
|
||||
len -= i;
|
||||
} else {
|
||||
i = snprintf(tbuf, len,
|
||||
"data transfer complete (%dm %ds", idelta / 60,
|
||||
idelta % 60);
|
||||
if (i >= len)
|
||||
if (i == -1 || i >= len)
|
||||
goto logit;
|
||||
len -= i;
|
||||
}
|
||||
} else {
|
||||
i = snprintf(tbuf, len, "data transfer complete (%.1fs",
|
||||
delta);
|
||||
if (i >= len)
|
||||
if (i == -1 || i >= len)
|
||||
goto logit;
|
||||
len -= i;
|
||||
}
|
||||
@ -366,7 +370,7 @@ show_xfer_stats(void)
|
||||
i = snprintf(&tbuf[strlen(tbuf)], len,
|
||||
", %d bytes to server) (%.1fKB/s", client_data_bytes,
|
||||
(client_data_bytes / delta) / (double)1024);
|
||||
if (i >= len)
|
||||
if (i == -1 || i >= len)
|
||||
goto logit;
|
||||
len -= i;
|
||||
}
|
||||
@ -374,20 +378,21 @@ show_xfer_stats(void)
|
||||
i = snprintf(&tbuf[strlen(tbuf)], len,
|
||||
", %d bytes to client) (%.1fKB/s", server_data_bytes,
|
||||
(server_data_bytes / delta) / (double)1024);
|
||||
if (i >= len)
|
||||
if (i == -1 || i >= len)
|
||||
goto logit;
|
||||
len -= i;
|
||||
}
|
||||
strlcat(tbuf, ")", sizeof(tbuf));
|
||||
logit:
|
||||
syslog(LOG_INFO, "%s", tbuf);
|
||||
if (i != -1)
|
||||
syslog(LOG_INFO, "%s", tbuf);
|
||||
}
|
||||
|
||||
void
|
||||
log_control_command (char *cmd, int client)
|
||||
{
|
||||
/* log an ftp control command or reply */
|
||||
char *logstring;
|
||||
const char *logstring;
|
||||
int level = LOG_DEBUG;
|
||||
|
||||
if (!Verbose)
|
||||
@ -540,7 +545,7 @@ connect_port_backchannel(void)
|
||||
* getting one bound to port 20 - This is deliberately
|
||||
* not RFC compliant.
|
||||
*/
|
||||
bzero(&listen_sa.sin_addr, sizeof(struct in_addr));
|
||||
bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr));
|
||||
client_data_socket = get_backchannel_socket(SOCK_STREAM,
|
||||
min_port, max_port, -1, 1, &listen_sa);
|
||||
if (client_data_socket < 0) {
|
||||
@ -558,7 +563,7 @@ connect_port_backchannel(void)
|
||||
|
||||
salen = 1;
|
||||
listen_sa.sin_family = AF_INET;
|
||||
bzero(&listen_sa.sin_addr, sizeof(struct in_addr));
|
||||
bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr));
|
||||
listen_sa.sin_port = htons(20);
|
||||
|
||||
if (setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR,
|
||||
@ -928,7 +933,10 @@ do_server_reply(struct csiob *server, struct csiob *client)
|
||||
|
||||
new_dataconn(0);
|
||||
connection_mode = PASV_MODE;
|
||||
iap = &(server->sa.sin_addr);
|
||||
if (ReverseMode)
|
||||
iap = &(proxy_sa.sin_addr);
|
||||
else
|
||||
iap = &(server->sa.sin_addr);
|
||||
|
||||
debuglog(1, "we want client to use %s:%u", inet_ntoa(*iap),
|
||||
htons(client_listen_sa.sin_port));
|
||||
@ -976,7 +984,7 @@ main(int argc, char *argv[])
|
||||
int use_tcpwrapper = 0;
|
||||
#endif /* LIBWRAP */
|
||||
|
||||
while ((ch = getopt(argc, argv, "a:D:g:m:M:t:u:AnVwr")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "a:D:g:m:M:R:S:t:u:AnVwr")) != -1) {
|
||||
char *p;
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
@ -1019,6 +1027,41 @@ main(int argc, char *argv[])
|
||||
case 'r':
|
||||
Use_Rdns = 1; /* look up hostnames */
|
||||
break;
|
||||
case 'R': {
|
||||
char *s, *t;
|
||||
|
||||
if (!*optarg)
|
||||
usage();
|
||||
if ((s = strdup(optarg)) == NULL) {
|
||||
syslog (LOG_NOTICE,
|
||||
"Insufficient memory (malloc failed)");
|
||||
exit(EX_UNAVAILABLE);
|
||||
}
|
||||
memset(&real_server_sa, 0, sizeof(real_server_sa));
|
||||
real_server_sa.sin_len = sizeof(struct sockaddr_in);
|
||||
real_server_sa.sin_family = AF_INET;
|
||||
t = strchr(s, ':');
|
||||
if (t == NULL)
|
||||
real_server_sa.sin_port = htons(21);
|
||||
else {
|
||||
long port = strtol(t + 1, &p, 10);
|
||||
|
||||
if (*p || port <= 0 || port > 65535)
|
||||
usage();
|
||||
real_server_sa.sin_port = htons(port);
|
||||
*t = 0;
|
||||
}
|
||||
real_server_sa.sin_addr.s_addr = inet_addr(s);
|
||||
if (real_server_sa.sin_addr.s_addr == INADDR_NONE)
|
||||
usage();
|
||||
free(s);
|
||||
ReverseMode = 1;
|
||||
break;
|
||||
}
|
||||
case 'S':
|
||||
if (!inet_aton(optarg, &src_addr))
|
||||
usage();
|
||||
break;
|
||||
case 't':
|
||||
timeout_seconds = strtol(optarg, &p, 10);
|
||||
if (!*optarg || *p)
|
||||
@ -1054,7 +1097,8 @@ main(int argc, char *argv[])
|
||||
memset(&client_iob, 0, sizeof(client_iob));
|
||||
memset(&server_iob, 0, sizeof(server_iob));
|
||||
|
||||
if (get_proxy_env(0, &real_server_sa, &client_iob.sa) == -1)
|
||||
if (get_proxy_env(0, &real_server_sa, &client_iob.sa,
|
||||
&proxy_sa) == -1)
|
||||
exit(EX_PROTOCOL);
|
||||
|
||||
/*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -230,7 +230,7 @@ command.
|
||||
.Bl -tag -width xxxx
|
||||
.It Ar set timeout
|
||||
.Pp
|
||||
.Bl -tag -width interval -compact
|
||||
.Bl -tag -width "src.track" -compact
|
||||
.It Ar interval
|
||||
Interval between purging expired states and fragments.
|
||||
.It Ar frag
|
||||
@ -484,6 +484,16 @@ For example:
|
||||
.Pp
|
||||
.Dl set fingerprints \&"/etc/pf.os.devel\&"
|
||||
.Pp
|
||||
.It Ar set skip on <ifspec>
|
||||
List interfaces for which packets should not be filtered.
|
||||
Packets passing in or out on such interfaces are passed as if pf was
|
||||
disabled, i.e. pf does not process them in any way.
|
||||
This can be useful on loopback and other virtual interfaces, when
|
||||
packet filtering is not desired and can have unexpected effects.
|
||||
For example:
|
||||
.Pp
|
||||
.Dl set skip on lo0
|
||||
.Pp
|
||||
.It Ar set debug
|
||||
Set the debug
|
||||
.Ar level
|
||||
@ -548,7 +558,7 @@ Enforces a maximum MSS for matching TCP packets.
|
||||
.It Ar random-id
|
||||
Replaces the IP identification field with random values to compensate
|
||||
for predictable values generated by many hosts.
|
||||
This option only applies to outgoing packets that are not fragmented
|
||||
This option only applies to packets that are not fragmented
|
||||
after the optional fragment reassembly.
|
||||
.It Ar fragment reassemble
|
||||
Using
|
||||
@ -602,7 +612,7 @@ the firewall state, and expires before reaching the destination host.
|
||||
.Ar reassemble tcp
|
||||
will raise the TTL of all packets back up to the highest value seen on
|
||||
the connection.
|
||||
.It timeout modulation
|
||||
.It timestamp modulation
|
||||
Modern TCP stacks will send a timestamp on every TCP packet and echo
|
||||
the other endpoint's timestamp back to them.
|
||||
Many operating systems will merely start the timestamp at zero when
|
||||
@ -619,6 +629,24 @@ guessable base time.
|
||||
will cause
|
||||
.Ar scrub
|
||||
to modulate the TCP timestamps with a random number.
|
||||
.It extended PAWS checks
|
||||
There is a problem with TCP on long fat pipes, in that a packet might get
|
||||
delayed for longer than it takes the connection to wrap its 32-bit sequence
|
||||
space.
|
||||
In such an occurrence, the old packet would be indistinguishable from a
|
||||
new packet and would be accepted as such.
|
||||
The solution to this is called PAWS: Protection Against Wrapped Sequence
|
||||
numbers.
|
||||
It protects against it by making sure the timestamp on each packet does
|
||||
not go backwards.
|
||||
.Ar reassemble tcp
|
||||
also makes sure the timestamp on the packet does not go forward more
|
||||
than the RFC allows.
|
||||
By doing this,
|
||||
.Xr pf 4
|
||||
artificially extends the security of TCP sequence numbers by 10 to 18
|
||||
bits when the host uses appropriately randomized timestamps, since a
|
||||
blind attacker would have to guess the timestamp as well.
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
@ -626,6 +654,15 @@ For example,
|
||||
.Bd -literal -offset indent
|
||||
scrub in on $ext_if all fragment reassemble
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Ar no
|
||||
option prefixed to a scrub rule causes matching packets to remain unscrubbed,
|
||||
much in the same way as
|
||||
.Ar drop quick
|
||||
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
|
||||
The ALTQ system is currently not available in the GENERIC kernel nor as
|
||||
loadable modules.
|
||||
@ -673,6 +710,18 @@ assigned.
|
||||
mainly controls the time packets take to get sent out, while
|
||||
.Ar bandwidth
|
||||
has primarily effects on throughput.
|
||||
.Ar cbq
|
||||
achieves both partitioning and sharing of link bandwidth
|
||||
by hierarchically structured classes.
|
||||
Each class has its own
|
||||
.Ar queue
|
||||
and is assigned its share of
|
||||
.Ar bandwidth .
|
||||
A child class can borrow bandwidth from its parent class
|
||||
as long as excess bandwidth is available
|
||||
(see the option
|
||||
.Ar borrow ,
|
||||
below).
|
||||
.It Ar priq
|
||||
Priority Queueing.
|
||||
.Ar Queues
|
||||
@ -706,6 +755,14 @@ assigned.
|
||||
mainly controls the time packets take to get sent out, while
|
||||
.Ar bandwidth
|
||||
has primarily effects on throughput.
|
||||
.Ar hfsc
|
||||
supports both link-sharing and guaranteed real-time services.
|
||||
It employs a service curve based QoS model,
|
||||
and its unique feature is an ability to decouple
|
||||
.Ar delay
|
||||
and
|
||||
.Ar bandwidth
|
||||
allocation.
|
||||
.El
|
||||
.Pp
|
||||
The interfaces on which queueing should be activated are declared using
|
||||
@ -791,6 +848,7 @@ This value must not exceed the value of the parent
|
||||
.Ar queue
|
||||
and can be specified as an absolute value or a percentage of the parent
|
||||
queue's bandwidth.
|
||||
If not specified, defaults to 100% of the parent queue's bandwidth.
|
||||
The
|
||||
.Ar priq
|
||||
scheduler does not support bandwidth specification.
|
||||
@ -919,8 +977,8 @@ queue developers bandwidth 75% cbq(borrow)
|
||||
queue employees bandwidth 15%
|
||||
queue mail bandwidth 10% priority 0 cbq(borrow ecn)
|
||||
queue ssh bandwidth 20% cbq(borrow) { ssh_interactive, ssh_bulk }
|
||||
queue ssh_interactive priority 7
|
||||
queue ssh_bulk priority 0
|
||||
queue ssh_interactive bandwidth 50% priority 7 cbq(borrow)
|
||||
queue ssh_bulk bandwidth 50% priority 0 cbq(borrow)
|
||||
|
||||
block return out on dc0 inet all queue std
|
||||
pass out on dc0 inet proto tcp from $developerhosts to any port 80 \e
|
||||
@ -944,8 +1002,8 @@ the packet filter for evaluation.
|
||||
.Pp
|
||||
Since translation occurs before filtering the filter
|
||||
engine will see packets as they look after any
|
||||
addresses and ports have been translated. Filter rules
|
||||
will therefore have to filter based on the translated
|
||||
addresses and ports have been translated.
|
||||
Filter rules will therefore have to filter based on the translated
|
||||
address and port number.
|
||||
Packets that match a translation rule are only automatically passed if
|
||||
the
|
||||
@ -1107,10 +1165,11 @@ This causes a TCP RST to be returned for
|
||||
packets and an ICMP UNREACHABLE for UDP and other packets.
|
||||
.El
|
||||
.Pp
|
||||
Options returning packets have no effect if
|
||||
Options returning ICMP packets currently have no effect if
|
||||
.Xr pf 4
|
||||
operates on a
|
||||
.Xr bridge 4 .
|
||||
.Xr bridge 4 ,
|
||||
as the code to support this feature has not yet been implemented.
|
||||
.It Ar pass
|
||||
The packet is passed.
|
||||
.El
|
||||
@ -1221,9 +1280,16 @@ addresses and ports.
|
||||
Addresses can be specified in CIDR notation (matching netblocks), as
|
||||
symbolic host names or interface names, or as any of the following keywords:
|
||||
.Pp
|
||||
.Bl -tag -width xxxxxxxxxxxx -compact
|
||||
.Bl -tag -width xxxxxxxxxxxxxx -compact
|
||||
.It Ar any
|
||||
Any address.
|
||||
.It Ar route <label>
|
||||
Any address whose associated route has label
|
||||
.Ar <label> .
|
||||
See
|
||||
.Xr route 4
|
||||
and
|
||||
.Xr route 8 .
|
||||
.It Ar no-route
|
||||
Any address which is not currently routable.
|
||||
.It Ar <table>
|
||||
@ -1317,6 +1383,7 @@ pass in proto tcp from any to any port 25
|
||||
pass in proto tcp from 10.0.0.0/8 port > 1024 \e
|
||||
to ! 10.1.2.3 port != ssh
|
||||
pass in proto tcp from any os "OpenBSD" flags S/SA
|
||||
pass in proto tcp from route "DTAG"
|
||||
.Ed
|
||||
.It Ar all
|
||||
This is equivalent to "from any to any".
|
||||
@ -1412,9 +1479,18 @@ All of SYN, FIN, RST and ACK must be unset.
|
||||
.It Ar icmp6-type <type> code <code>
|
||||
This rule only applies to ICMP or ICMPv6 packets with the specified type
|
||||
and code.
|
||||
Text names for ICMP types and codes are listed in
|
||||
.Xr icmp 4
|
||||
and
|
||||
.Xr icmp6 4 .
|
||||
This parameter is only valid for rules that cover protocols ICMP or
|
||||
ICMP6.
|
||||
The protocol and the ICMP type indicator (icmp-type or icmp6-type)
|
||||
The protocol and the ICMP type indicator
|
||||
.Po
|
||||
.Ar icmp-type
|
||||
or
|
||||
.Ar icmp6-type
|
||||
.Pc
|
||||
must match.
|
||||
.It Ar allow-opts
|
||||
By default, packets which contain IP options are blocked.
|
||||
@ -1520,7 +1596,7 @@ or
|
||||
rules in addition to filter rules.
|
||||
Tags take the same macros as labels (see above).
|
||||
.It Ar tagged <string>
|
||||
Used with filter rules to specify that packets must already
|
||||
Used with filter or translation 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
|
||||
@ -1528,6 +1604,15 @@ by specifying the
|
||||
operator before the
|
||||
.Ar tagged
|
||||
keyword.
|
||||
.It Ar probability <number>
|
||||
A probability attribute can be attached to a rule, with a value set between
|
||||
0 and 1, bounds not included.
|
||||
In that case, the rule will be honoured using the given probability value
|
||||
only.
|
||||
For example, the following rule will drop 20% of incoming ICMP packets:
|
||||
.Bd -literal -offset indent
|
||||
block in proto icmp probability 20%
|
||||
.Ed
|
||||
.El
|
||||
.Sh ROUTING
|
||||
If a packet matches a rule with a route option set, the packet filter will
|
||||
@ -1558,7 +1643,7 @@ option is similar to
|
||||
but routes packets that pass in the opposite direction (replies) to the
|
||||
specified interface.
|
||||
Opposite direction is only defined in the context of a state entry, and
|
||||
.Ar route-to
|
||||
.Ar reply-to
|
||||
is useful only in rules that create state.
|
||||
It can be used on systems with multiple external connections to
|
||||
route all outgoing packets of a connection through the interface
|
||||
@ -1875,32 +1960,96 @@ Prevent state changes for states created by this rule from appearing on the
|
||||
interface.
|
||||
.It Ar <timeout> <seconds>
|
||||
Changes the timeout values used for states created by this rule.
|
||||
.Pp
|
||||
When the
|
||||
.Ar source-track
|
||||
keyword is specified, the number of states per source IP is tracked.
|
||||
The following limits can be set:
|
||||
.Pp
|
||||
.Bl -tag -width xxxx -compact
|
||||
.It Ar max-src-nodes
|
||||
Limits the maximum number of source addresses which can simultaneously
|
||||
have state table entries.
|
||||
.It Ar max-src-states
|
||||
Limits the maximum number of simultaneous state entries that a single
|
||||
source address can create with this rule.
|
||||
.El
|
||||
For a list of all valid timeout names, see
|
||||
.Sx OPTIONS
|
||||
above.
|
||||
.El
|
||||
.Pp
|
||||
Multiple options can be specified, separated by commas:
|
||||
.Bd -literal
|
||||
.Bd -literal -offset indent
|
||||
pass in proto tcp from any to any \e
|
||||
port www flags S/SA keep state \e
|
||||
(max 100, source-track rule, max-src-nodes 75, \e
|
||||
max-src-states 3, tcp.established 60, tcp.closing 5)
|
||||
.Ed
|
||||
.Pp
|
||||
When the
|
||||
.Ar source-track
|
||||
keyword is specified, the number of states per source IP is tracked.
|
||||
.Pp
|
||||
.Bl -tag -width xxxx -compact
|
||||
.It Ar source-track rule
|
||||
The maximum number of states created by this rule is limited by the rule's
|
||||
.Ar max-src-nodes
|
||||
and
|
||||
.Ar max-src-state
|
||||
options.
|
||||
Only state entries created by this particular rule count toward the rule's
|
||||
limits.
|
||||
.It Ar source-track global
|
||||
The number of states created by all rules that use this option is limited.
|
||||
Each rule can specify different
|
||||
.Ar max-src-nodes
|
||||
and
|
||||
.Ar max-src-states
|
||||
options, however state entries created by any participating rule count towards
|
||||
each individual rule's limits.
|
||||
.El
|
||||
.Pp
|
||||
The following limits can be set:
|
||||
.Pp
|
||||
.Bl -tag -width xxxx -compact
|
||||
.It Ar max-src-nodes <number>
|
||||
Limits the maximum number of source addresses which can simultaneously
|
||||
have state table entries.
|
||||
.It Ar max-src-states <number>
|
||||
Limits the maximum number of simultaneous state entries that a single
|
||||
source address can create with this rule.
|
||||
.El
|
||||
.Pp
|
||||
For stateful TCP connections, limits on established connections (connections
|
||||
which have completed the TCP 3-way handshake) can also be enforced
|
||||
per source IP.
|
||||
.Pp
|
||||
.Bl -tag -width xxxx -compact
|
||||
.It Ar max-src-conn <number>
|
||||
Limits the maximum number of simultaneous TCP connections which have
|
||||
completed the 3-way handshake that a single host can make.
|
||||
.It Ar max-src-conn-rate <number> / <seconds>
|
||||
Limit the rate of new connections over a time interval.
|
||||
The connection rate is an approximation calculated as a moving average.
|
||||
.El
|
||||
.Pp
|
||||
Because the 3-way handshake ensures that the source address is not being
|
||||
spoofed, more aggressive action can be taken based on these limits.
|
||||
With the
|
||||
.Ar overload <table>
|
||||
state option, source IP addresses which hit either of the limits on
|
||||
established connections will be added to the named table.
|
||||
This table can be used in the ruleset to block further activity from
|
||||
the offending host, redirect it to a tarpit process, or restrict its
|
||||
bandwidth.
|
||||
.Pp
|
||||
The optional
|
||||
.Ar flush
|
||||
keyword kills all states created by the matching rule which originate
|
||||
from the host which exceeds these limits.
|
||||
The
|
||||
.Ar global
|
||||
modifier to the flush command kills all states originating from the
|
||||
offending host, regardless of which rule created the state.
|
||||
.Pp
|
||||
For example, the following rules will protect the webserver against
|
||||
hosts making more than 100 connections in 10 seconds.
|
||||
Any host which connects faster than this rate will have its address added
|
||||
to the <bad_hosts> table and have all states originating from it flushed.
|
||||
Any new packets arriving from this host will be dropped unconditionally
|
||||
by the block rule.
|
||||
.Bd -literal -offset indent
|
||||
block quick from <bad_hosts>
|
||||
pass in on $ext_if proto tcp to $webserver port www flags S/SA keep state \e
|
||||
(max-src-conn-rate 100/10, overload <bad_hosts> flush global)
|
||||
.Ed
|
||||
.Sh OPERATING SYSTEM FINGERPRINTING
|
||||
Passive OS Fingerprinting is a mechanism to inspect nuances of a TCP
|
||||
connection's initial SYN packet and guess at the host's operating system.
|
||||
@ -1911,7 +2060,7 @@ upon.
|
||||
.Pp
|
||||
The fingerprints may be specified by operating system class, by
|
||||
version, or by subtype/patchlevel.
|
||||
The class of an operating system is typically the vender or genre
|
||||
The class of an operating system is typically the vendor or genre
|
||||
and would be OpenBSD for the
|
||||
.Xr pf 4
|
||||
firewall itself.
|
||||
@ -2076,84 +2225,87 @@ The timeout value can also be adjusted.
|
||||
.Pp
|
||||
Currently, only IPv4 fragments are supported and IPv6 fragments
|
||||
are blocked unconditionally.
|
||||
.Sh ANCHORS AND NAMED RULESETS
|
||||
.Sh ANCHORS
|
||||
Besides the main ruleset,
|
||||
.Xr pfctl 8
|
||||
can load named rulesets into
|
||||
can load rulesets into
|
||||
.Ar anchor
|
||||
attachment points.
|
||||
An
|
||||
.Ar anchor
|
||||
contains a list of named rulesets.
|
||||
is a container that can hold rules, address tables, and other anchors.
|
||||
.Pp
|
||||
An
|
||||
.Ar anchor
|
||||
has a name which specifies where
|
||||
has a name which specifies the path where
|
||||
.Xr pfctl 8
|
||||
can be used to attach sub-rulesets.
|
||||
A named ruleset contains filter and translation rules, like the
|
||||
main ruleset.
|
||||
The main ruleset can reference
|
||||
can be used to access the anchor to perform operations on it, such as
|
||||
attaching child anchors to it or loading rules into it.
|
||||
Anchors may be nested, with components separated by
|
||||
.Sq /
|
||||
characters, similar to how file system hierarchies are laid out.
|
||||
The main ruleset is actually the default anchor, so filter and
|
||||
translation rules, for example, may also be contained in any anchor.
|
||||
.Pp
|
||||
An anchor can reference another
|
||||
.Ar anchor
|
||||
attachment points
|
||||
attachment point
|
||||
using the following kinds
|
||||
of rules:
|
||||
.Bl -tag -width xxxx
|
||||
.It Ar nat-anchor <name>
|
||||
Evaluates the
|
||||
.Ar nat
|
||||
rules of all named rulesets in the specified
|
||||
rules in the specified
|
||||
.Ar anchor .
|
||||
.It Ar rdr-anchor <name>
|
||||
Evaluates the
|
||||
.Ar rdr
|
||||
rules of all named rulesets in the specified
|
||||
rules in the specified
|
||||
.Ar anchor .
|
||||
.It Ar binat-anchor <name>
|
||||
Evaluates the
|
||||
.Ar binat
|
||||
rules of all named rulesets in the specified
|
||||
rules in the specified
|
||||
.Ar anchor .
|
||||
.It Ar anchor <name>
|
||||
Evaluates the filter rules of all named rulesets in the specified
|
||||
Evaluates the filter rules in the specified
|
||||
.Ar anchor .
|
||||
.It Ar load anchor <name>:<ruleset> from <file>
|
||||
Loads the rules from the specified file into the named
|
||||
ruleset
|
||||
.Ar <ruleset>
|
||||
attached to the anchor
|
||||
.Ar <name> .
|
||||
.It Ar load anchor <name> from <file>
|
||||
Loads the rules from the specified file into the
|
||||
anchor
|
||||
.Ar name .
|
||||
.El
|
||||
.Pp
|
||||
When evaluation of the main ruleset reaches an
|
||||
.Ar anchor
|
||||
rule,
|
||||
.Xr pf 4
|
||||
will proceed to evaluate all rules specified in the
|
||||
named rulesets attached to that
|
||||
.Ar anchor .
|
||||
will proceed to evaluate all rules specified in that anchor.
|
||||
.Pp
|
||||
Matching filter rules in named rulesets with the
|
||||
Matching filter and translation rules in anchors with the
|
||||
.Ar quick
|
||||
option and matching translation rules are final and abort the
|
||||
evaluation of both the rules in the
|
||||
.Ar anchor
|
||||
option are final and abort the evaluation of the rules in other
|
||||
anchors
|
||||
and the main ruleset.
|
||||
.Pp
|
||||
Only the main ruleset can contain
|
||||
.Ar anchor
|
||||
rules.
|
||||
.Pp
|
||||
When an
|
||||
rules are evaluated relative to the anchor in which they are contained.
|
||||
For example, all
|
||||
.Ar anchor
|
||||
contains more than one named ruleset, they are evaluated
|
||||
in the alphabetical order of their names.
|
||||
rules specified in the main ruleset will reference anchor
|
||||
attachment points underneath the main ruleset, and
|
||||
.Ar anchor
|
||||
rules specified in a file loaded from a
|
||||
.Ar load anchor
|
||||
rule will be attached under that anchor point.
|
||||
.Pp
|
||||
Rules may contain
|
||||
Rules may be contained in
|
||||
.Ar anchor
|
||||
attachment points which do not contain any rules when the main ruleset
|
||||
is loaded, and later such named rulesets can be manipulated through
|
||||
is loaded, and later such anchors can be manipulated through
|
||||
.Xr pfctl 8
|
||||
without reloading the main ruleset.
|
||||
without reloading the main ruleset or other anchors.
|
||||
For example,
|
||||
.Bd -literal -offset indent
|
||||
ext_if = \&"kue0\&"
|
||||
@ -2165,27 +2317,27 @@ pass in on $ext_if proto tcp from any \e
|
||||
.Ed
|
||||
.Pp
|
||||
blocks all packets on the external interface by default, then evaluates
|
||||
all rulesets in the
|
||||
all rules in the
|
||||
.Ar anchor
|
||||
named "spam", and finally passes all outgoing connections and
|
||||
incoming connections to port 25.
|
||||
.Bd -literal -offset indent
|
||||
# echo \&"block in quick from 1.2.3.4 to any\&" \&| \e
|
||||
pfctl -a spam:manual -f -
|
||||
pfctl -a spam -f -
|
||||
.Ed
|
||||
.Pp
|
||||
loads a single ruleset containing a single rule into the
|
||||
This loads a single rule into the
|
||||
.Ar anchor ,
|
||||
which blocks all packets from a specific address.
|
||||
.Pp
|
||||
The named ruleset can also be populated by adding a
|
||||
The anchor can also be populated by adding a
|
||||
.Ar load anchor
|
||||
rule after the
|
||||
.Ar anchor
|
||||
rule:
|
||||
.Bd -literal -offset indent
|
||||
anchor spam
|
||||
load anchor spam:manual from "/etc/pf-spam.conf"
|
||||
load anchor spam from "/etc/pf-spam.conf"
|
||||
.Ed
|
||||
.Pp
|
||||
When
|
||||
@ -2194,7 +2346,7 @@ loads
|
||||
.Nm pf.conf ,
|
||||
it will also load all the rules from the file
|
||||
.Pa /etc/pf-spam.conf
|
||||
into the named ruleset.
|
||||
into the anchor.
|
||||
.Pp
|
||||
Optionally,
|
||||
.Ar anchor
|
||||
@ -2205,7 +2357,7 @@ using the same syntax as filter rules.
|
||||
When parameters are used, the
|
||||
.Ar anchor
|
||||
rule is only evaluated for matching packets.
|
||||
This allows conditional evaluation of named rulesets, like:
|
||||
This allows conditional evaluation of anchors, like:
|
||||
.Bd -literal -offset indent
|
||||
block on $ext_if all
|
||||
anchor spam proto tcp from any to any port smtp
|
||||
@ -2221,10 +2373,56 @@ packets with destination port 25.
|
||||
Hence,
|
||||
.Bd -literal -offset indent
|
||||
# echo \&"block in quick from 1.2.3.4 to any" \&| \e
|
||||
pfctl -a spam:manual -f -
|
||||
pfctl -a spam -f -
|
||||
.Ed
|
||||
.Pp
|
||||
will only block connections from 1.2.3.4 to port 25.
|
||||
.Pp
|
||||
Anchors may end with the asterisk
|
||||
.Pq Sq *
|
||||
character, which signifies that all anchors attached at that point
|
||||
should be evaluated in the alphabetical ordering of their anchor name.
|
||||
For example,
|
||||
.Bd -literal -offset indent
|
||||
anchor "spam/*"
|
||||
.Ed
|
||||
.Pp
|
||||
will evaluate each rule in each anchor attached to the
|
||||
.Li spam
|
||||
anchor.
|
||||
Note that it will only evaluate anchors that are directly attached to the
|
||||
.Li spam
|
||||
anchor, and will not descend to evaluate anchors recursively.
|
||||
.Pp
|
||||
Since anchors are evaluated relative to the anchor in which they are
|
||||
contained, there is a mechanism for accessing the parent and ancestor
|
||||
anchors of a given anchor.
|
||||
Similar to file system path name resolution, if the sequence
|
||||
.Dq ..
|
||||
appears as an anchor path component, the parent anchor of the current
|
||||
anchor in the path evaluation at that point will become the new current
|
||||
anchor.
|
||||
As an example, consider the following:
|
||||
.Bd -literal -offset indent
|
||||
# echo ' anchor "spam/allowed" ' | pfctl -f -
|
||||
# echo -e ' anchor "../banned" \en pass' | \e
|
||||
pfctl -a spam/allowed -f -
|
||||
.Ed
|
||||
.Pp
|
||||
Evaluation of the main ruleset will lead into the
|
||||
.Li spam/allowed
|
||||
anchor, which will evaluate the rules in the
|
||||
.Li spam/banned
|
||||
anchor, if any, before finally evaluating the
|
||||
.Ar pass
|
||||
rule.
|
||||
.Pp
|
||||
Since the parser specification for anchor names is a string, any
|
||||
reference to an anchor name containing solidus
|
||||
.Pq Sq /
|
||||
characters will require double quote
|
||||
.Pq Sq \&"
|
||||
characters around the anchor name.
|
||||
.Sh TRANSLATION EXAMPLES
|
||||
This example maps incoming requests on port 80 to port 8080, on
|
||||
which a daemon is running (because, for example, it is not run as root,
|
||||
@ -2301,7 +2499,7 @@ nat on $ext_if inet proto udp from any port = isakmp to any -> ($ext_if) \e
|
||||
# Translate outgoing packets' source address (any protocol).
|
||||
# Translate incoming packets' destination address to an internal machine
|
||||
# (bidirectional).
|
||||
binat on $ext_if from 10.1.2.150 to any -> ($ext_if)
|
||||
binat on $ext_if from 10.1.2.150 to any -> $ext_if
|
||||
|
||||
# RDR
|
||||
# Translate incoming packets' destination addresses.
|
||||
@ -2415,7 +2613,7 @@ pass in on $wifi_if from any to any keep state
|
||||
|
||||
block out on $ext_if from any to any
|
||||
pass out quick on $ext_if tagged INTNET keep state
|
||||
pass out on $ext_if from any to any port 80 keep state
|
||||
pass out on $ext_if proto tcp from any to any port 80 keep state
|
||||
|
||||
# tag incoming packets as they are redirected to spamd(8). use the tag
|
||||
# to pass those packets through the packet filter.
|
||||
@ -2442,7 +2640,7 @@ option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
|
||||
[ "limit" ( limit-item | "{" limit-list "}" ) ] |
|
||||
[ "loginterface" ( interface-name | "none" ) ] |
|
||||
[ "block-policy" ( "drop" | "return" ) ] |
|
||||
[ "state-policy" ( "if-bound" | "group-bound" |
|
||||
[ "state-policy" ( "if-bound" | "group-bound" |
|
||||
"floating" ) ]
|
||||
[ "require-order" ( "yes" | "no" ) ]
|
||||
[ "fingerprints" filename ] |
|
||||
@ -2461,21 +2659,22 @@ filteropt = user | group | flags | icmp-type | icmp6-type | tos |
|
||||
"max-mss" number | "random-id" | "reassemble tcp" |
|
||||
fragmentation | "allow-opts" |
|
||||
"label" string | "tag" string | [ ! ] "tagged" string
|
||||
"queue" ( string | "(" string [ [ "," ] string ] ")" )
|
||||
"queue" ( string | "(" string [ [ "," ] string ] ")" ) |
|
||||
"probability" number"%"
|
||||
|
||||
nat-rule = [ "no" ] "nat" [ "pass" ] [ "on" ifspec ] [ af ]
|
||||
[ protospec ] hosts [ "tag" string ]
|
||||
[ protospec ] hosts [ "tag" string ] [ "tagged" string ]
|
||||
[ "->" ( redirhost | "{" redirhost-list "}" )
|
||||
[ portspec ] [ pooltype ] [ "static-port" ] ]
|
||||
|
||||
binat-rule = [ "no" ] "binat" [ "pass" ] [ "on" interface-name ]
|
||||
[ af ] [ "proto" ( proto-name | proto-number ) ]
|
||||
"from" address [ "/" mask-bits ] "to" ipspec
|
||||
[ "tag" string ]
|
||||
[ "tag" string ] [ "tagged" string ]
|
||||
[ "->" address [ "/" mask-bits ] ]
|
||||
|
||||
rdr-rule = [ "no" ] "rdr" [ "pass" ] [ "on" ifspec ] [ af ]
|
||||
[ protospec ] hosts [ "tag" string ]
|
||||
[ protospec ] hosts [ "tag" string ] [ "tagged" string ]
|
||||
[ "->" ( redirhost | "{" redirhost-list "}" )
|
||||
[ portspec ] [ pooltype ] ]
|
||||
|
||||
@ -2503,7 +2702,7 @@ anchor-rule = "anchor" string [ ( "in" | "out" ) ] [ "on" ifspec ]
|
||||
trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string
|
||||
[ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ]
|
||||
|
||||
load-anchor = "load anchor" anchorname:rulesetname "from" filename
|
||||
load-anchor = "load anchor" string "from" filename
|
||||
|
||||
queueopts-list = queueopts-list queueopts | queueopts
|
||||
queueopts = [ "bandwidth" bandwidth-spec ] |
|
||||
@ -2512,7 +2711,7 @@ queueopts = [ "bandwidth" bandwidth-spec ] |
|
||||
schedulers = ( cbq-def | priq-def | hfsc-def )
|
||||
bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" )
|
||||
|
||||
action = "pass" | "block" [ return ] | "scrub"
|
||||
action = "pass" | "block" [ return ] | [ "no" ] "scrub"
|
||||
return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
|
||||
"return-icmp" [ "(" icmpcode ["," icmp6code ] ")" ] |
|
||||
"return-icmp6" [ "(" icmp6code ")" ]
|
||||
@ -2533,9 +2732,9 @@ proto-list = ( proto-name | proto-number ) [ [ "," ] proto-list ]
|
||||
|
||||
hosts = "all" |
|
||||
"from" ( "any" | "no-route" | "self" | host |
|
||||
"{" host-list "}" ) [ port ] [ os ]
|
||||
"{" host-list "}" | "route" string ) [ port ] [ os ]
|
||||
"to" ( "any" | "no-route" | "self" | host |
|
||||
"{" host-list "}" ) [ port ]
|
||||
"{" host-list "}" | "route" string ) [ port ]
|
||||
|
||||
ipspec = "any" | host | "{" host-list "}"
|
||||
host = [ "!" ] ( address [ "/" mask-bits ] | "<" string ">" )
|
||||
@ -2577,7 +2776,10 @@ tos = "tos" ( "lowdelay" | "throughput" | "reliability" |
|
||||
state-opts = state-opt [ [ "," ] state-opts ]
|
||||
state-opt = ( "max" number | "no-sync" | timeout |
|
||||
"source-track" [ ( "rule" | "global" ) ] |
|
||||
"max-src-nodes" number | "max-src-states" number |
|
||||
"max-src-nodes" number | "max-src-states" number |
|
||||
"max-src-conn" number |
|
||||
"max-src-conn-rate" number "/" number |
|
||||
"overload" "<" string ">" [ "flush" ] |
|
||||
"if-bound" | "group-bound" | "floating" )
|
||||
|
||||
fragmentation = [ "fragment reassemble" | "fragment crop" |
|
||||
@ -2657,6 +2859,7 @@ deadlock.
|
||||
.Xr ip6 4 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr pfsync 4 ,
|
||||
.Xr route 4 ,
|
||||
.Xr tcp 4 ,
|
||||
.Xr udp 4 ,
|
||||
.Xr hosts 5 ,
|
||||
@ -2665,7 +2868,8 @@ deadlock.
|
||||
.Xr services 5 ,
|
||||
.Xr ftp-proxy 8 ,
|
||||
.Xr pfctl 8 ,
|
||||
.Xr pflogd 8
|
||||
.Xr pflogd 8 ,
|
||||
.Xr route 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
|
@ -1,6 +1,7 @@
|
||||
.\" $OpenBSD: pfsync.4,v 1.16 2004/03/22 21:04:36 jmc Exp $
|
||||
.\" $OpenBSD: pfsync.4,v 1.22 2005/02/24 15:53:17 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2002 Michael Shalayeff
|
||||
.\" Copyright (c) 2003-2004 Ryan McBride
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -30,7 +31,7 @@
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pfsync
|
||||
.Nd packet filter states table logging interface
|
||||
.Nd packet filter state table logging interface
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device pfsync"
|
||||
.Sh DESCRIPTION
|
||||
@ -71,20 +72,20 @@ state into one message where possible.
|
||||
The maximum number of times this can be done before the update is sent out
|
||||
is controlled by the
|
||||
.Ar maxupd
|
||||
to ifconfig.
|
||||
parameter to ifconfig
|
||||
(see
|
||||
.Xr ifconfig 8
|
||||
and the example below for more details)
|
||||
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
|
||||
action taken on the following states, and the number of state
|
||||
table entries attached in this packet.
|
||||
This structure, defined in
|
||||
This structure is defined in
|
||||
.Aq Pa net/if_pfsync.h
|
||||
looks like:
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
struct pfsync_header {
|
||||
u_int8_t version;
|
||||
@ -98,21 +99,35 @@ States can be synchronised between two or more firewalls using this
|
||||
interface, by specifying a synchronisation interface using
|
||||
.Xr ifconfig 8 .
|
||||
For example, the following command sets fxp0 as the synchronisation
|
||||
interface.
|
||||
interface:
|
||||
.Bd -literal -offset indent
|
||||
# ifconfig pfsync0 syncif fxp0
|
||||
# ifconfig pfsync0 syncdev fxp0
|
||||
.Ed
|
||||
.Pp
|
||||
State change messages are sent out on the synchronisation
|
||||
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
|
||||
.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 .
|
||||
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,
|
||||
e.g.:
|
||||
.Bd -literal -offset indent
|
||||
# ifconfig pfsync0 syncpeer 10.0.0.2 syncdev enc0
|
||||
.Ed
|
||||
.Pp
|
||||
It is important that the synchronisation interface be on a trusted
|
||||
network as there is no authentication on the protocol and it would
|
||||
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.
|
||||
Ideally, this is a network dedicated to pfsync messages,
|
||||
i.e. a crossover cable between two firewalls.
|
||||
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
|
||||
.\" XXX: not yet!
|
||||
.\" There is a one-to-one correspondence between packets seen by
|
||||
@ -139,8 +154,8 @@ is shut down, the second firewall takes over automatically.
|
||||
Both firewalls in this example have three
|
||||
.Xr sis 4
|
||||
interfaces.
|
||||
sis0 is the external interface, on the 10.0.0.0/24 subnet, sis1 is the
|
||||
internal interface, on the 192.168.0.0/24 subnet, and sis2 is the
|
||||
sis0 is the external interface, on the 10.0.0.0/24 subnet; sis1 is the
|
||||
internal interface, on the 192.168.0.0/24 subnet; and sis2 is the
|
||||
.Nm
|
||||
interface, using the 192.168.254.0/24 subnet.
|
||||
A crossover cable connects the two firewalls via their sis2 interfaces.
|
||||
@ -200,10 +215,12 @@ has not been ported from
|
||||
.Ox
|
||||
yet.
|
||||
.Sh SEE ALSO
|
||||
.Xr bpf 4 ,
|
||||
.Xr carp 4 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr inet 4 ,
|
||||
.Xr inet6 4 ,
|
||||
.Xr ipsec 4 ,
|
||||
.Xr netintro 4 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr pf.conf 5 ,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_print_state.c,v 1.39 2004/02/10 17:48:08 henning Exp $ */
|
||||
/* $OpenBSD: pf_print_state.c,v 1.40 2004/12/10 22:13:26 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -100,6 +100,9 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
||||
case PF_ADDR_NOROUTE:
|
||||
printf("no-route");
|
||||
return;
|
||||
case PF_ADDR_RTLABEL:
|
||||
printf("route \"%s\"", addr->v.rtlabelname);
|
||||
return;
|
||||
default:
|
||||
printf("?");
|
||||
return;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl.h,v 1.33 2004/02/19 21:37:01 cedric Exp $ */
|
||||
/* $OpenBSD: pfctl.h,v 1.37 2005/01/05 18:23:10 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -65,8 +65,6 @@ 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_begin(struct pfr_table *, int *, int *, int);
|
||||
int pfr_ina_commit(struct pfr_table *, 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 *);
|
||||
@ -80,13 +78,14 @@ int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
|
||||
int pfi_clr_istats(const char *, int *, int);
|
||||
|
||||
void pfctl_print_title(char *);
|
||||
int pfctl_clear_tables(const char *, const char *, int);
|
||||
int pfctl_show_tables(const char *, const char *, int);
|
||||
int pfctl_clear_tables(const char *, int);
|
||||
int pfctl_show_tables(const char *, int);
|
||||
int pfctl_command_tables(int, char *[], char *, const char *, char *,
|
||||
const char *, const char *, int);
|
||||
const char *, int);
|
||||
int pfctl_show_altq(int, const char *, int, int);
|
||||
void warn_namespace_collision(const char *);
|
||||
int pfctl_show_ifaces(const char *, int);
|
||||
FILE *pfctl_fopen(const char *, const char *);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
extern int altqsupport;
|
||||
@ -108,6 +107,8 @@ struct segment {
|
||||
double x, y, d, m;
|
||||
};
|
||||
|
||||
extern int loadopt;
|
||||
|
||||
int check_commit_altq(int, int);
|
||||
void pfaltq_store(struct pf_altq *);
|
||||
void pfaltq_free(struct pf_altq *);
|
||||
@ -121,9 +122,9 @@ void print_state(struct pf_state *, int);
|
||||
int unmask(struct pf_addr *, sa_family_t);
|
||||
|
||||
int pfctl_cmdline_symset(char *);
|
||||
int pfctl_add_trans(struct pfr_buffer *, int, const char *, const char *);
|
||||
int pfctl_add_trans(struct pfr_buffer *, int, const char *);
|
||||
u_int32_t
|
||||
pfctl_get_ticket(struct pfr_buffer *, int, const char *, const char *);
|
||||
pfctl_get_ticket(struct pfr_buffer *, int, const char *);
|
||||
int pfctl_trans(int, struct pfr_buffer *, u_long, int);
|
||||
|
||||
#endif /* _PFCTL_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.83 2004/03/14 21:51:44 dhartmei Exp $ */
|
||||
/* $OpenBSD: pfctl_altq.c,v 1.86 2005/02/28 14:04:51 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002
|
||||
@ -315,7 +315,8 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
||||
struct node_queue_opt *opts)
|
||||
{
|
||||
/* should be merged with expand_queue */
|
||||
struct pf_altq *if_pa, *parent;
|
||||
struct pf_altq *if_pa, *parent, *altq;
|
||||
u_int32_t bwsum;
|
||||
int error = 0;
|
||||
|
||||
/* find the corresponding interface and copy fields used by queues */
|
||||
@ -347,22 +348,35 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
|
||||
pa->qlimit = DEFAULT_QLIMIT;
|
||||
|
||||
if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC) {
|
||||
if ((pa->bandwidth = eval_bwspec(bw,
|
||||
parent == NULL ? 0 : parent->bandwidth)) == 0) {
|
||||
fprintf(stderr, "bandwidth for %s invalid (%d / %d)\n",
|
||||
pa->qname, bw->bw_absolute, bw->bw_percent);
|
||||
return (1);
|
||||
}
|
||||
pa->bandwidth = eval_bwspec(bw,
|
||||
parent == NULL ? 0 : parent->bandwidth);
|
||||
|
||||
if (pa->bandwidth > pa->ifbandwidth) {
|
||||
fprintf(stderr, "bandwidth for %s higher than "
|
||||
"interface\n", pa->qname);
|
||||
return (1);
|
||||
}
|
||||
if (parent != NULL && pa->bandwidth > parent->bandwidth) {
|
||||
fprintf(stderr, "bandwidth for %s higher than parent\n",
|
||||
pa->qname);
|
||||
return (1);
|
||||
/* check the sum of the child bandwidth is under parent's */
|
||||
if (parent != NULL) {
|
||||
if (pa->bandwidth > parent->bandwidth) {
|
||||
warnx("bandwidth for %s higher than parent",
|
||||
pa->qname);
|
||||
return (1);
|
||||
}
|
||||
bwsum = 0;
|
||||
TAILQ_FOREACH(altq, &altqs, entries) {
|
||||
if (strncmp(altq->ifname, pa->ifname,
|
||||
IFNAMSIZ) == 0 &&
|
||||
altq->qname[0] != 0 &&
|
||||
strncmp(altq->parent, pa->parent,
|
||||
PF_QNAME_SIZE) == 0)
|
||||
bwsum += altq->bandwidth;
|
||||
}
|
||||
bwsum += pa->bandwidth;
|
||||
if (bwsum > parent->bandwidth) {
|
||||
warnx("the sum of the child bandwidth higher"
|
||||
" than parent \"%s\"", parent->qname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,7 +720,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
* for the real-time service curve, the sum of the service curves
|
||||
* should not exceed 80% of the interface bandwidth. 20% is reserved
|
||||
* not to over-commit the actual interface bandwidth.
|
||||
* for the link-sharing service curve, the sum of the child service
|
||||
* for the linkshare service curve, the sum of the child service
|
||||
* curve should not exceed the parent service curve.
|
||||
* for the upper-limit service curve, the assigned bandwidth should
|
||||
* be smaller than the interface bandwidth, and the upper-limit should
|
||||
@ -733,7 +747,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0)
|
||||
continue;
|
||||
|
||||
/* if the class has a link-sharing service curve, add it. */
|
||||
/* if the class has a linkshare service curve, add it. */
|
||||
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
|
||||
sc.m1 = altq->pq_u.hfsc_opts.lssc_m1;
|
||||
sc.d = altq->pq_u.hfsc_opts.lssc_d;
|
||||
@ -744,22 +758,35 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
|
||||
|
||||
/* check the real-time service curve. reserve 20% of interface bw */
|
||||
if (opts->rtsc_m2 != 0) {
|
||||
/* add this queue to the sum */
|
||||
sc.m1 = opts->rtsc_m1;
|
||||
sc.d = opts->rtsc_d;
|
||||
sc.m2 = opts->rtsc_m2;
|
||||
gsc_add_sc(&rtsc, &sc);
|
||||
/* compare the sum with 80% of the interface */
|
||||
sc.m1 = 0;
|
||||
sc.d = 0;
|
||||
sc.m2 = pa->ifbandwidth / 100 * 80;
|
||||
if (!is_gsc_under_sc(&rtsc, &sc)) {
|
||||
warnx("real-time sc exceeds the interface bandwidth");
|
||||
warnx("real-time sc exceeds 80%% of the interface "
|
||||
"bandwidth (%s)", rate2str((double)sc.m2));
|
||||
goto err_ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* check the link-sharing service curve. */
|
||||
/* check the linkshare service curve. */
|
||||
if (opts->lssc_m2 != 0) {
|
||||
/* add this queue to the child sum */
|
||||
sc.m1 = opts->lssc_m1;
|
||||
sc.d = opts->lssc_d;
|
||||
sc.m2 = opts->lssc_m2;
|
||||
gsc_add_sc(&lssc, &sc);
|
||||
/* compare the sum of the children with parent's sc */
|
||||
sc.m1 = parent->pq_u.hfsc_opts.lssc_m1;
|
||||
sc.d = parent->pq_u.hfsc_opts.lssc_d;
|
||||
sc.m2 = parent->pq_u.hfsc_opts.lssc_m2;
|
||||
if (!is_gsc_under_sc(&lssc, &sc)) {
|
||||
warnx("link-sharing sc exceeds parent's sc");
|
||||
warnx("linkshare sc exceeds parent's sc");
|
||||
goto err_ret;
|
||||
}
|
||||
}
|
||||
@ -1108,6 +1135,7 @@ getifspeed(char *ifname)
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
err(1, "socket");
|
||||
bzero(&ifr, sizeof(ifr));
|
||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
||||
sizeof(ifr.ifr_name))
|
||||
errx(1, "getifspeed: strlcpy");
|
||||
@ -1130,6 +1158,7 @@ getifmtu(char *ifname)
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
err(1, "socket");
|
||||
bzero(&ifr, sizeof(ifr));
|
||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
||||
sizeof(ifr.ifr_name))
|
||||
errx(1, "getifmtu: strlcpy");
|
||||
|
@ -16,6 +16,9 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
@ -815,7 +818,11 @@ block_feedback(struct pfctl *pf, struct superblock *block)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
if (por2 == NULL)
|
||||
#else
|
||||
if (por2 == TAILQ_END(&block->sb_rules))
|
||||
#endif
|
||||
TAILQ_INSERT_TAIL(&block->sb_rules, por1, por_entry);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_parser.c,v 1.194 2004/03/15 15:25:44 dhartmei Exp $ */
|
||||
/* $OpenBSD: pfctl_parser.c,v 1.211 2004/12/07 10:33:41 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
@ -66,6 +68,7 @@ void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned);
|
||||
void print_flags (u_int8_t);
|
||||
void print_fromto(struct pf_rule_addr *, pf_osfp_t,
|
||||
struct pf_rule_addr *, u_int8_t, u_int8_t, int);
|
||||
int ifa_skip_if(const char *filter, struct node_host *p);
|
||||
|
||||
struct node_host *host_if(const char *, int);
|
||||
struct node_host *host_v4(const char *, int);
|
||||
@ -186,6 +189,7 @@ const struct pf_timeout pf_timeouts[] = {
|
||||
{ "tcp.closing", PFTM_TCP_CLOSING },
|
||||
{ "tcp.finwait", PFTM_TCP_FIN_WAIT },
|
||||
{ "tcp.closed", PFTM_TCP_CLOSED },
|
||||
{ "tcp.tsdiff", PFTM_TS_DIFF },
|
||||
{ "udp.first", PFTM_UDP_FIRST_PACKET },
|
||||
{ "udp.single", PFTM_UDP_SINGLE },
|
||||
{ "udp.multiple", PFTM_UDP_MULTIPLE },
|
||||
@ -366,13 +370,13 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
|
||||
PF_AZERO(&src->addr.v.a.mask, AF_INET6) &&
|
||||
PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
|
||||
PF_AZERO(&dst->addr.v.a.mask, AF_INET6) &&
|
||||
!src->not && !dst->not &&
|
||||
!src->neg && !dst->neg &&
|
||||
!src->port_op && !dst->port_op &&
|
||||
osfp == PF_OSFP_ANY)
|
||||
printf(" all");
|
||||
else {
|
||||
printf(" from ");
|
||||
if (src->not)
|
||||
if (src->neg)
|
||||
printf("! ");
|
||||
print_addr(&src->addr, af, verbose);
|
||||
if (src->port_op)
|
||||
@ -384,7 +388,7 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
|
||||
sizeof(buf)));
|
||||
|
||||
printf(" to ");
|
||||
if (dst->not)
|
||||
if (dst->neg)
|
||||
printf("! ");
|
||||
print_addr(&dst->addr, af, verbose);
|
||||
if (dst->port_op)
|
||||
@ -472,6 +476,7 @@ print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
|
||||
}
|
||||
|
||||
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
|
||||
const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
|
||||
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||
const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
|
||||
|
||||
@ -574,6 +579,22 @@ print_status(struct pf_status *s, int opts)
|
||||
else
|
||||
printf("%14s\n", "");
|
||||
}
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
printf("Limit Counters\n");
|
||||
for (i = 0; i < LCNT_MAX; i++) {
|
||||
printf(" %-25s %14lld ", pf_lcounters[i],
|
||||
#ifdef __FreeBSD__
|
||||
(unsigned long long)s->lcounters[i]);
|
||||
#else
|
||||
s->lcounters[i]);
|
||||
#endif
|
||||
if (runtime > 0)
|
||||
printf("%14.1f/s\n",
|
||||
(double)s->lcounters[i] / (double)runtime);
|
||||
else
|
||||
printf("%14s\n", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -593,7 +614,9 @@ print_src_node(struct pf_src_node *sn, int opts)
|
||||
printf(" -> ");
|
||||
aw.v.a.addr = sn->raddr;
|
||||
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
|
||||
printf(" (%d states)\n", sn->states);
|
||||
printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states,
|
||||
sn->conn, sn->conn_rate.count / 1000,
|
||||
(sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds);
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
sec = sn->creation % 60;
|
||||
sn->creation /= 60;
|
||||
@ -628,21 +651,22 @@ print_src_node(struct pf_src_node *sn, int opts)
|
||||
}
|
||||
|
||||
void
|
||||
print_rule(struct pf_rule *r, int verbose)
|
||||
print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
|
||||
{
|
||||
static const char *actiontypes[] = { "pass", "block", "scrub", "nat",
|
||||
"no nat", "binat", "no binat", "rdr", "no rdr" };
|
||||
static const char *actiontypes[] = { "pass", "block", "scrub",
|
||||
"no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
|
||||
static const char *anchortypes[] = { "anchor", "anchor", "anchor",
|
||||
"nat-anchor", "nat-anchor", "binat-anchor", "binat-anchor",
|
||||
"rdr-anchor", "rdr-anchor" };
|
||||
"anchor", "nat-anchor", "nat-anchor", "binat-anchor",
|
||||
"binat-anchor", "rdr-anchor", "rdr-anchor" };
|
||||
int i, opts;
|
||||
|
||||
if (verbose)
|
||||
printf("@%d ", r->nr);
|
||||
if (r->action > PF_NORDR)
|
||||
printf("action(%d)", r->action);
|
||||
else if (r->anchorname[0])
|
||||
printf("%s %s", anchortypes[r->action], r->anchorname);
|
||||
else if (anchor_call[0])
|
||||
printf("%s \"%s\"", anchortypes[r->action],
|
||||
anchor_call);
|
||||
else {
|
||||
printf("%s", actiontypes[r->action]);
|
||||
if (r->natpass)
|
||||
@ -782,6 +806,21 @@ print_rule(struct pf_rule *r, int verbose)
|
||||
printf(" modulate state");
|
||||
else if (r->keep_state == PF_STATE_SYNPROXY)
|
||||
printf(" synproxy state");
|
||||
if (r->prob) {
|
||||
char buf[20];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0));
|
||||
for (i = strlen(buf)-1; i > 0; i--) {
|
||||
if (buf[i] == '0')
|
||||
buf[i] = '\0';
|
||||
else {
|
||||
if (buf[i] == '.')
|
||||
buf[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf(" probability %s%%", buf);
|
||||
}
|
||||
opts = 0;
|
||||
if (r->max_states || r->max_src_nodes || r->max_src_states)
|
||||
opts = 1;
|
||||
@ -822,12 +861,35 @@ print_rule(struct pf_rule *r, int verbose)
|
||||
printf("max-src-states %u", r->max_src_states);
|
||||
opts = 0;
|
||||
}
|
||||
if (r->max_src_conn) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("max-src-conn %u", r->max_src_conn);
|
||||
opts = 0;
|
||||
}
|
||||
if (r->max_src_conn_rate.limit) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("max-src-conn-rate %u/%u",
|
||||
r->max_src_conn_rate.limit,
|
||||
r->max_src_conn_rate.seconds);
|
||||
opts = 0;
|
||||
}
|
||||
if (r->max_src_nodes) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("max-src-nodes %u", r->max_src_nodes);
|
||||
opts = 0;
|
||||
}
|
||||
if (r->overload_tblname[0]) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("overload <%s>", r->overload_tblname);
|
||||
if (r->flush)
|
||||
printf(" flush");
|
||||
if (r->flush & PF_FLUSH_GLOBAL)
|
||||
printf(" global");
|
||||
}
|
||||
if (r->rule_flag & PFRULE_IFBOUND) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
@ -842,11 +904,17 @@ print_rule(struct pf_rule *r, int verbose)
|
||||
}
|
||||
for (i = 0; i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i]) {
|
||||
int j;
|
||||
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
opts = 0;
|
||||
printf("%s %u", pf_timeouts[i].name,
|
||||
r->timeout[i]);
|
||||
for (j = 0; j < sizeof(pf_timeouts) /
|
||||
sizeof(pf_timeouts[0]); ++j)
|
||||
if (pf_timeouts[j].timeout == i)
|
||||
break;
|
||||
printf("%s %u", j == PFTM_MAX ? "inv.timeout" :
|
||||
pf_timeouts[j].name, r->timeout[i]);
|
||||
}
|
||||
printf(")");
|
||||
}
|
||||
@ -886,7 +954,7 @@ print_rule(struct pf_rule *r, int verbose)
|
||||
printf(" !");
|
||||
printf(" tagged %s", r->match_tagname);
|
||||
}
|
||||
if (!r->anchorname[0] && (r->action == PF_NAT ||
|
||||
if (!anchor_call[0] && (r->action == PF_NAT ||
|
||||
r->action == PF_BINAT || r->action == PF_RDR)) {
|
||||
printf(" -> ");
|
||||
print_pool(&r->rpool, r->rpool.proxy_port[0],
|
||||
@ -953,9 +1021,7 @@ set_ipmask(struct node_host *h, u_int8_t b)
|
||||
int i, j = 0;
|
||||
|
||||
m = &h->addr.v.a.mask;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
m->addr32[i] = 0;
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
while (b >= 32) {
|
||||
m->addr32[j++] = 0xffffffff;
|
||||
@ -1007,8 +1073,6 @@ ifa_load(void)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct node_host *n = NULL, *h = NULL;
|
||||
struct pfr_buffer b;
|
||||
struct pfi_if *p;
|
||||
|
||||
if (getifaddrs(&ifap) < 0)
|
||||
err(1, "getifaddrs");
|
||||
@ -1084,43 +1148,6 @@ ifa_load(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* add interface groups, including clonable and dynamic stuff */
|
||||
bzero(&b, sizeof(b));
|
||||
b.pfrb_type = PFRB_IFACES;
|
||||
for (;;) {
|
||||
if (pfr_buf_grow(&b, b.pfrb_size))
|
||||
err(1, "ifa_load: pfr_buf_grow");
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (pfi_get_ifaces(NULL, b.pfrb_caddr, &b.pfrb_size,
|
||||
PFI_FLAG_GROUP))
|
||||
err(1, "ifa_load: pfi_get_ifaces");
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
PFRB_FOREACH(p, &b) {
|
||||
n = calloc(1, sizeof(struct node_host));
|
||||
if (n == NULL)
|
||||
err(1, "address: calloc");
|
||||
n->af = AF_LINK;
|
||||
n->ifa_flags = PF_IFA_FLAG_GROUP;
|
||||
if (p->pfif_flags & PFI_IFLAG_DYNAMIC)
|
||||
n->ifa_flags |= PF_IFA_FLAG_DYNAMIC;
|
||||
if (p->pfif_flags & PFI_IFLAG_CLONABLE)
|
||||
n->ifa_flags |= PF_IFA_FLAG_CLONABLE;
|
||||
if (!strcmp(p->pfif_name, "lo"))
|
||||
n->ifa_flags |= IFF_LOOPBACK;
|
||||
if ((n->ifname = strdup(p->pfif_name)) == NULL)
|
||||
err(1, "ifa_load: strdup");
|
||||
n->next = NULL;
|
||||
n->tail = n;
|
||||
if (h == NULL)
|
||||
h = n;
|
||||
else {
|
||||
h->tail->next = n;
|
||||
h->tail = n;
|
||||
}
|
||||
}
|
||||
|
||||
iftab = h;
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
@ -1129,12 +1156,7 @@ struct node_host *
|
||||
ifa_exists(const char *ifa_name, int group_ok)
|
||||
{
|
||||
struct node_host *n;
|
||||
char *p, buf[IFNAMSIZ];
|
||||
int group;
|
||||
|
||||
group = !isdigit(ifa_name[strlen(ifa_name) - 1]);
|
||||
if (group && !group_ok)
|
||||
return (NULL);
|
||||
if (iftab == NULL)
|
||||
ifa_load();
|
||||
|
||||
@ -1142,19 +1164,7 @@ ifa_exists(const char *ifa_name, int group_ok)
|
||||
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
|
||||
return (n);
|
||||
}
|
||||
if (!group) {
|
||||
/* look for clonable and/or dynamic interface */
|
||||
strlcpy(buf, ifa_name, sizeof(buf));
|
||||
for (p = buf + strlen(buf) - 1; p > buf && isdigit(*p); p--)
|
||||
*p = '\0';
|
||||
for (n = iftab; n != NULL; n = n->next)
|
||||
if (n->af == AF_LINK &&
|
||||
!strncmp(n->ifname, buf, IFNAMSIZ))
|
||||
break;
|
||||
if (n != NULL && n->ifa_flags &
|
||||
(PF_IFA_FLAG_DYNAMIC | PF_IFA_FLAG_CLONABLE))
|
||||
return (n); /* XXX */
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -1162,19 +1172,17 @@ struct node_host *
|
||||
ifa_lookup(const char *ifa_name, int flags)
|
||||
{
|
||||
struct node_host *p = NULL, *h = NULL, *n = NULL;
|
||||
int return_all = 0, got4 = 0, got6 = 0;
|
||||
int got4 = 0, got6 = 0;
|
||||
const char *last_if = NULL;
|
||||
|
||||
if (!strncmp(ifa_name, "self", IFNAMSIZ))
|
||||
return_all = 1;
|
||||
ifa_name = NULL;
|
||||
|
||||
if (iftab == NULL)
|
||||
ifa_load();
|
||||
|
||||
for (p = iftab; p; p = p->next) {
|
||||
if (!((p->af == AF_INET || p->af == AF_INET6) &&
|
||||
(!strncmp(p->ifname, ifa_name, strlen(ifa_name)) ||
|
||||
return_all)))
|
||||
if (ifa_skip_if(ifa_name, p))
|
||||
continue;
|
||||
if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
|
||||
continue;
|
||||
@ -1238,6 +1246,28 @@ ifa_lookup(const char *ifa_name, int flags)
|
||||
return (h);
|
||||
}
|
||||
|
||||
int
|
||||
ifa_skip_if(const char *filter, struct node_host *p)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (p->af != AF_INET && p->af != AF_INET6)
|
||||
return (1);
|
||||
if (filter == NULL || !*filter)
|
||||
return (0);
|
||||
if (!strcmp(p->ifname, filter))
|
||||
return (0); /* exact match */
|
||||
n = strlen(filter);
|
||||
if (n < 1 || n >= IFNAMSIZ)
|
||||
return (1); /* sanity check */
|
||||
if (filter[n-1] >= '0' && filter[n-1] <= '9')
|
||||
return (1); /* only do exact match in that case */
|
||||
if (strncmp(p->ifname, filter, n))
|
||||
return (1); /* prefix doesn't match */
|
||||
return (p->ifname[n] < '0' || p->ifname[n] > '9');
|
||||
}
|
||||
|
||||
|
||||
struct node_host *
|
||||
host(const char *s)
|
||||
{
|
||||
@ -1248,7 +1278,7 @@ host(const char *s)
|
||||
if ((p = strrchr(s, '/')) != NULL) {
|
||||
mask = strtol(p+1, &q, 0);
|
||||
if (!q || *q || mask > 128 || q == (p+1)) {
|
||||
fprintf(stderr, "invalid netmask\n");
|
||||
fprintf(stderr, "invalid netmask '%s'\n", p);
|
||||
return (NULL);
|
||||
}
|
||||
if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
|
||||
@ -1402,7 +1432,7 @@ host_dns(const char *s, int v4mask, int v6mask)
|
||||
char *p, *ps;
|
||||
|
||||
if ((ps = strdup(s)) == NULL)
|
||||
err(1, "host_if: strdup");
|
||||
err(1, "host_dns: strdup");
|
||||
if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) {
|
||||
noalias = 1;
|
||||
*p = '\0';
|
||||
@ -1411,8 +1441,10 @@ host_dns(const char *s, int v4mask, int v6mask)
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
|
||||
error = getaddrinfo(ps, NULL, &hints, &res0);
|
||||
if (error)
|
||||
if (error) {
|
||||
free(ps);
|
||||
return (h);
|
||||
}
|
||||
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if (res->ai_family != AF_INET &&
|
||||
@ -1536,33 +1568,28 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor,
|
||||
const char *ruleset)
|
||||
pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor)
|
||||
{
|
||||
struct pfioc_trans_e trans;
|
||||
|
||||
bzero(&trans, sizeof(trans));
|
||||
trans.rs_num = rs_num;
|
||||
if (strlcpy(trans.anchor, anchor,
|
||||
sizeof(trans.anchor)) >= sizeof(trans.anchor) ||
|
||||
strlcpy(trans.ruleset, ruleset,
|
||||
sizeof(trans.ruleset)) >= sizeof(trans.ruleset))
|
||||
sizeof(trans.anchor)) >= sizeof(trans.anchor))
|
||||
errx(1, "pfctl_add_trans: strlcpy");
|
||||
|
||||
return pfr_buf_add(buf, &trans);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor,
|
||||
const char *ruleset)
|
||||
pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor)
|
||||
{
|
||||
struct pfioc_trans_e *p;
|
||||
|
||||
PFRB_FOREACH(p, buf)
|
||||
if (rs_num == p->rs_num && !strcmp(anchor, p->anchor) &&
|
||||
!strcmp(ruleset, p->ruleset))
|
||||
if (rs_num == p->rs_num && !strcmp(anchor, p->anchor))
|
||||
return (p->ticket);
|
||||
errx(1, "pfr_get_ticket: assertion failed");
|
||||
errx(1, "pfctl_get_ticket: assertion failed");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_parser.h,v 1.74 2004/02/10 22:26:56 dhartmei Exp $ */
|
||||
/* $OpenBSD: pfctl_parser.h,v 1.80 2005/02/07 18:18:14 david Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -47,6 +47,9 @@
|
||||
#define PF_OPT_DUMMYACTION 0x0100
|
||||
#define PF_OPT_DEBUG 0x0200
|
||||
#define PF_OPT_SHOWALL 0x0400
|
||||
#define PF_OPT_OPTIMIZE 0x0800
|
||||
#define PF_OPT_OPTIMIZE_PROFILE 0x1000
|
||||
#define PF_OPT_MERGE 0x2000
|
||||
|
||||
#define PF_TH_ALL 0xFF
|
||||
|
||||
@ -60,6 +63,11 @@
|
||||
NULL \
|
||||
}
|
||||
|
||||
struct pfr_buffer; /* forward definition */
|
||||
struct pf_opt_rule;
|
||||
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
|
||||
|
||||
|
||||
struct pfctl {
|
||||
int dev;
|
||||
int opts;
|
||||
@ -73,11 +81,26 @@ struct pfctl {
|
||||
struct pfr_buffer *trans;
|
||||
const char *anchor;
|
||||
const char *ruleset;
|
||||
struct pf_opt_queue opt_queue;
|
||||
|
||||
/* 'set foo' options */
|
||||
u_int32_t timeout[PFTM_MAX];
|
||||
u_int32_t limit[PF_LIMIT_MAX];
|
||||
u_int32_t debug;
|
||||
u_int32_t hostid;
|
||||
char *ifname;
|
||||
|
||||
u_int8_t timeout_set[PFTM_MAX];
|
||||
u_int8_t limit_set[PF_LIMIT_MAX];
|
||||
u_int8_t debug_set;
|
||||
u_int8_t hostid_set;
|
||||
u_int8_t ifname_set;
|
||||
};
|
||||
|
||||
struct node_if {
|
||||
char ifname[IFNAMSIZ];
|
||||
u_int8_t not;
|
||||
u_int8_t dynamic; /* antispoof */
|
||||
u_int ifa_flags;
|
||||
struct node_if *next;
|
||||
struct node_if *tail;
|
||||
@ -166,11 +189,33 @@ struct node_tinit { /* table initializer */
|
||||
char *file;
|
||||
};
|
||||
|
||||
struct pfr_buffer; /* forward definition */
|
||||
|
||||
int pfctl_rules(int, char *, int, char *, char *, struct pfr_buffer *);
|
||||
/* optimizer created tables */
|
||||
struct pf_opt_tbl {
|
||||
char pt_name[PF_TABLE_NAME_SIZE];
|
||||
int pt_rulecount;
|
||||
int pt_generated;
|
||||
struct node_tinithead pt_nodes;
|
||||
struct pfr_buffer *pt_buf;
|
||||
};
|
||||
#define PF_OPT_TABLE_PREFIX "__automatic_"
|
||||
|
||||
int pfctl_add_rule(struct pfctl *, struct pf_rule *);
|
||||
/* optimizer pf_rule container */
|
||||
struct pf_opt_rule {
|
||||
struct pf_rule por_rule;
|
||||
struct pf_opt_tbl *por_src_tbl;
|
||||
struct pf_opt_tbl *por_dst_tbl;
|
||||
char por_anchor[MAXPATHLEN];
|
||||
u_int64_t por_profile_count;
|
||||
TAILQ_ENTRY(pf_opt_rule) por_entry;
|
||||
TAILQ_ENTRY(pf_opt_rule) por_skip_entry[PF_SKIP_COUNT];
|
||||
};
|
||||
|
||||
|
||||
int pfctl_rules(int, char *, int, char *, struct pfr_buffer *);
|
||||
int pfctl_optimize_rules(struct pfctl *);
|
||||
|
||||
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
|
||||
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
||||
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t);
|
||||
void pfctl_clear_pool(struct pf_pool *);
|
||||
@ -181,6 +226,7 @@ int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
||||
int pfctl_set_logif(struct pfctl *, char *);
|
||||
int pfctl_set_hostid(struct pfctl *, u_int32_t);
|
||||
int pfctl_set_debug(struct pfctl *, char *);
|
||||
int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
|
||||
|
||||
int parse_rules(FILE *, struct pfctl *);
|
||||
int parse_flags(char *);
|
||||
@ -188,7 +234,7 @@ int pfctl_load_anchors(int, int, struct pfr_buffer *);
|
||||
|
||||
void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int);
|
||||
void print_src_node(struct pf_src_node *, int);
|
||||
void print_rule(struct pf_rule *, int);
|
||||
void print_rule(struct pf_rule *, const char *, int);
|
||||
void print_tabledef(const char *, int, int, struct node_tinithead *);
|
||||
void print_status(struct pf_status *, int);
|
||||
|
||||
@ -202,8 +248,8 @@ void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
||||
void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
||||
int, struct node_queue_opt *);
|
||||
|
||||
int pfctl_define_table(char *, int, int, const char *, const char *,
|
||||
struct pfr_buffer *, u_int32_t);
|
||||
int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *,
|
||||
u_int32_t);
|
||||
|
||||
void pfctl_clear_fingerprints(int, int);
|
||||
int pfctl_file_fingerprints(int, int, const char *);
|
||||
@ -244,6 +290,7 @@ extern const struct pf_timeout pf_timeouts[];
|
||||
|
||||
void set_ipmask(struct node_host *, u_int8_t);
|
||||
int check_netmask(struct node_host *, sa_family_t);
|
||||
int unmask(struct pf_addr *, sa_family_t);
|
||||
void ifa_load(void);
|
||||
struct node_host *ifa_exists(const char *, int);
|
||||
struct node_host *ifa_lookup(const char *, int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pfctl_qstats.c,v 1.29 2004/03/15 15:25:44 dhartmei Exp $ */
|
||||
/* $OpenBSD: pfctl_qstats.c,v 1.30 2004/04/27 21:47:32 kjc Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) Henning Brauer <henning@openbsd.org>
|
||||
@ -97,6 +97,8 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
|
||||
if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
|
||||
return (-1);
|
||||
|
||||
if (nodes == 0)
|
||||
printf("No queue in use\n");
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||
continue;
|
||||
@ -107,11 +109,11 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
|
||||
pfctl_print_altq_node(dev, node, 0, opts);
|
||||
}
|
||||
|
||||
while (verbose2) {
|
||||
while (verbose2 && nodes > 0) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
sleep(STAT_INTERVAL);
|
||||
if (pfctl_update_qstats(dev, &root) == -1)
|
||||
if ((nodes = pfctl_update_qstats(dev, &root)) == -1)
|
||||
return (-1);
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* $OpenBSD: pfctl_table.c,v 1.59 2004/03/15 15:25:44 dhartmei Exp $ */
|
||||
/* add $OpenBSD: pfctl_table.c,v 1.61 2004/06/12 22:22:44 cedric Exp $ */
|
||||
/* $OpenBSD: pfctl_table.c,v 1.62 2004/12/22 17:17:55 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Cedric Berger
|
||||
@ -57,7 +56,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
extern void usage(void);
|
||||
static int pfctl_table(int, char *[], char *, const char *, char *,
|
||||
const char *, const char *, int);
|
||||
const char *, int);
|
||||
static void print_table(struct pfr_table *, int, int);
|
||||
static void print_tstats(struct pfr_tstats *, int);
|
||||
static int load_addr(struct pfr_buffer *, int, char *[], char *, int);
|
||||
@ -106,31 +105,29 @@ static const char *istats_text[2][2][2] = {
|
||||
} while(0)
|
||||
|
||||
int
|
||||
pfctl_clear_tables(const char *anchor, const char *ruleset, int opts)
|
||||
pfctl_clear_tables(const char *anchor, int opts)
|
||||
{
|
||||
return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, ruleset, opts);
|
||||
return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_tables(const char *anchor, const char *ruleset, int opts)
|
||||
pfctl_show_tables(const char *anchor, int opts)
|
||||
{
|
||||
return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, ruleset, opts);
|
||||
return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_command_tables(int argc, char *argv[], char *tname,
|
||||
const char *command, char *file, const char *anchor, const char *ruleset,
|
||||
int opts)
|
||||
const char *command, char *file, const char *anchor, int opts)
|
||||
{
|
||||
if (tname == NULL || command == NULL)
|
||||
usage();
|
||||
return pfctl_table(argc, argv, tname, command, file, anchor, ruleset,
|
||||
opts);
|
||||
return pfctl_table(argc, argv, tname, command, file, anchor, opts);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
char *file, const char *anchor, const char *ruleset, int opts)
|
||||
char *file, const char *anchor, int opts)
|
||||
{
|
||||
struct pfr_table table;
|
||||
struct pfr_buffer b, b2;
|
||||
@ -155,9 +152,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
errx(1, "pfctl_table: strlcpy");
|
||||
}
|
||||
if (strlcpy(table.pfrt_anchor, anchor,
|
||||
sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor) ||
|
||||
strlcpy(table.pfrt_ruleset, ruleset,
|
||||
sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset))
|
||||
sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor))
|
||||
errx(1, "pfctl_table: strlcpy");
|
||||
|
||||
if (!strcmp(command, "-F")) {
|
||||
@ -347,8 +342,6 @@ print_table(struct pfr_table *ta, int verbose, int debug)
|
||||
ta->pfrt_name);
|
||||
if (ta->pfrt_anchor[0])
|
||||
printf("\t%s", ta->pfrt_anchor);
|
||||
if (ta->pfrt_ruleset[0])
|
||||
printf(":%s", ta->pfrt_ruleset);
|
||||
puts("");
|
||||
} else
|
||||
puts(ta->pfrt_name);
|
||||
@ -466,16 +459,14 @@ radix_perror(void)
|
||||
|
||||
int
|
||||
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
|
||||
struct pfr_buffer *ab, u_int32_t ticket)
|
||||
{
|
||||
struct pfr_table tbl;
|
||||
|
||||
bzero(&tbl, sizeof(tbl));
|
||||
if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
|
||||
sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
|
||||
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) ||
|
||||
strlcpy(tbl.pfrt_ruleset, ruleset, sizeof(tbl.pfrt_ruleset)) >=
|
||||
sizeof(tbl.pfrt_ruleset))
|
||||
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor))
|
||||
errx(1, "pfctl_define_table: strlcpy");
|
||||
tbl.pfrt_flags = flags;
|
||||
|
||||
@ -589,7 +580,8 @@ print_iface(struct pfi_if *p, int opts)
|
||||
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 1);
|
||||
oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0);
|
||||
oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1);
|
||||
#ifdef __FreeBSD__
|
||||
first = 1;
|
||||
oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pflogd.c,v 1.27 2004/02/13 19:01:57 otto Exp $ */
|
||||
/* $OpenBSD: pflogd.c,v 1.33 2005/02/09 12:09:30 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Theo de Raadt
|
||||
@ -271,16 +271,19 @@ reset_dump(void)
|
||||
fp = fdopen(fd, "a+");
|
||||
|
||||
if (fp == NULL) {
|
||||
close(fd);
|
||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
if (fstat(fileno(fp), &st) == -1) {
|
||||
fclose(fp);
|
||||
logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* set FILE unbuffered, we do our own buffering */
|
||||
if (setvbuf(fp, NULL, _IONBF, 0)) {
|
||||
fclose(fp);
|
||||
logmsg(LOG_ERR, "Failed to set output buffers");
|
||||
return (1);
|
||||
}
|
||||
@ -291,6 +294,7 @@ reset_dump(void)
|
||||
if (snaplen != cur_snaplen) {
|
||||
logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
|
||||
if (set_snaplen(snaplen)) {
|
||||
fclose(fp);
|
||||
logmsg(LOG_WARNING,
|
||||
"Failed, using old settings");
|
||||
}
|
||||
@ -418,8 +422,9 @@ dump_packet_nobuf(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
|
||||
#else
|
||||
if (fwrite((char *)h, sizeof(*h), 1, f) != 1) {
|
||||
#endif
|
||||
/* try to undo header to prevent corruption */
|
||||
off_t pos = ftello(f);
|
||||
|
||||
/* try to undo header to prevent corruption */
|
||||
#ifdef __FreeBSD__
|
||||
if (pos < sizeof(sh) ||
|
||||
ftruncate(fileno(f), pos - sizeof(sh))) {
|
||||
@ -554,6 +559,7 @@ main(int argc, char **argv)
|
||||
struct pcap_stat pstat;
|
||||
int ch, np, Xflag = 0;
|
||||
pcap_handler phandler = dump_packet;
|
||||
char *errstr = NULL;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* another ?paranoid? safety measure we do not have */
|
||||
@ -567,19 +573,35 @@ main(int argc, char **argv)
|
||||
Debug = 1;
|
||||
break;
|
||||
case 'd':
|
||||
delay = atoi(optarg);
|
||||
if (delay < 5 || delay > 60*60)
|
||||
#ifdef __OpenBSD__
|
||||
delay = strtonum(optarg, 5, 60*60, &errstr);
|
||||
if (errstr)
|
||||
#else
|
||||
delay = strtol(optarg, &errstr, 10);
|
||||
if ((delay < 5) || (delay > 60*60) ||
|
||||
((errstr != NULL) && (*errstr != '\0')))
|
||||
#endif
|
||||
usage();
|
||||
break;
|
||||
case 'f':
|
||||
filename = optarg;
|
||||
break;
|
||||
case 's':
|
||||
snaplen = atoi(optarg);
|
||||
#ifdef __OpenBSD__
|
||||
snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
|
||||
&errstr);
|
||||
if (snaplen <= 0)
|
||||
snaplen = DEF_SNAPLEN;
|
||||
if (snaplen > PFLOGD_MAXSNAPLEN)
|
||||
if (errstr)
|
||||
snaplen = PFLOGD_MAXSNAPLEN;
|
||||
#else
|
||||
snaplen = strtol(optarg, &errstr, 10);
|
||||
if (snaplen <= 0)
|
||||
snaplen = DEF_SNAPLEN;
|
||||
if ((snaplen > PFLOGD_MAXSNAPLEN) ||
|
||||
((errstr != NULL) && (*errstr != '\0')))
|
||||
snaplen = PFLOGD_MAXSNAPLEN;
|
||||
#endif
|
||||
break;
|
||||
case 'x':
|
||||
Xflag++;
|
||||
@ -603,6 +625,7 @@ main(int argc, char **argv)
|
||||
pidfile(NULL);
|
||||
}
|
||||
|
||||
tzset();
|
||||
(void)umask(S_IRWXG | S_IRWXO);
|
||||
|
||||
/* filter will be used by the privileged process */
|
||||
@ -655,7 +678,7 @@ main(int argc, char **argv)
|
||||
|
||||
while (1) {
|
||||
np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
|
||||
dump_packet, (u_char *)dpcap);
|
||||
phandler, (u_char *)dpcap);
|
||||
if (np < 0) {
|
||||
#ifdef __FreeBSD__
|
||||
if (errno == ENXIO) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: privsep.c,v 1.8 2004/03/14 19:17:05 otto Exp $ */
|
||||
/* $OpenBSD: privsep.c,v 1.13 2004/12/22 09:21:02 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Can Erkin Acar
|
||||
@ -69,7 +69,7 @@ int
|
||||
priv_init(void)
|
||||
{
|
||||
int i, fd, socks[2], cmd;
|
||||
int snaplen, ret;
|
||||
int snaplen, ret, olderrno;
|
||||
struct passwd *pw;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
@ -118,10 +118,12 @@ priv_init(void)
|
||||
}
|
||||
|
||||
/* Father */
|
||||
/* Pass ALRM/TERM/HUP through to child, and accept CHLD */
|
||||
/* Pass ALRM/TERM/HUP/INT/QUIT through to child, and accept CHLD */
|
||||
signal(SIGALRM, sig_pass_to_chld);
|
||||
signal(SIGTERM, sig_pass_to_chld);
|
||||
signal(SIGHUP, sig_pass_to_chld);
|
||||
signal(SIGINT, sig_pass_to_chld);
|
||||
signal(SIGQUIT, sig_pass_to_chld);
|
||||
signal(SIGCHLD, sig_chld);
|
||||
|
||||
setproctitle("[priv]");
|
||||
@ -153,12 +155,14 @@ priv_init(void)
|
||||
fd = open(filename,
|
||||
O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW,
|
||||
0600);
|
||||
olderrno = errno;
|
||||
send_fd(socks[0], fd);
|
||||
if (fd < 0)
|
||||
logmsg(LOG_NOTICE,
|
||||
"[priv]: failed to open %s: %s",
|
||||
filename, strerror(errno));
|
||||
send_fd(socks[0], fd);
|
||||
close(fd);
|
||||
filename, strerror(olderrno));
|
||||
else
|
||||
close(fd);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -217,7 +221,7 @@ priv_open_log(void)
|
||||
int cmd, fd;
|
||||
|
||||
if (priv_fd < 0)
|
||||
errx(1, "%s: called from privileged portion\n", __func__);
|
||||
errx(1, "%s: called from privileged portion", __func__);
|
||||
|
||||
cmd = PRIV_OPEN_LOG;
|
||||
must_write(priv_fd, &cmd, sizeof(int));
|
||||
|
Loading…
x
Reference in New Issue
Block a user