From b28479dfe2b344764dddb58a31df37c21423cfde Mon Sep 17 00:00:00 2001 From: mlaier Date: Tue, 3 May 2005 16:55:20 +0000 Subject: 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 --- contrib/pf/authpf/authpf.c | 439 +++++++---------- contrib/pf/ftp-proxy/ftp-proxy.8 | 21 +- contrib/pf/ftp-proxy/ftp-proxy.c | 80 +++- contrib/pf/man/pf.4 | 970 ++++++++++++++++++++++++-------------- contrib/pf/man/pf.conf.5 | 370 +++++++++++---- contrib/pf/man/pfsync.4 | 49 +- contrib/pf/pfctl/parse.y | 644 +++++++++++++++++-------- contrib/pf/pfctl/pf_print_state.c | 5 +- contrib/pf/pfctl/pfctl.c | 722 ++++++++++++++++------------ contrib/pf/pfctl/pfctl.h | 17 +- contrib/pf/pfctl/pfctl_altq.c | 63 ++- contrib/pf/pfctl/pfctl_optimize.c | 7 + contrib/pf/pfctl/pfctl_parser.c | 213 +++++---- contrib/pf/pfctl/pfctl_parser.h | 61 ++- contrib/pf/pfctl/pfctl_qstats.c | 8 +- contrib/pf/pfctl/pfctl_table.c | 36 +- contrib/pf/pflogd/pflogd.c | 37 +- contrib/pf/pflogd/privsep.c | 18 +- 18 files changed, 2370 insertions(+), 1390 deletions(-) (limited to 'contrib/pf') diff --git a/contrib/pf/authpf/authpf.c b/contrib/pf/authpf/authpf.c index 097e8f0..af75027 100644 --- a/contrib/pf/authpf/authpf.c +++ b/contrib/pf/authpf/authpf.c @@ -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 #include #include +#include #include +#include #include #include @@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -48,9 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include - #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; - - 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); + int i; + struct pfioc_trans_e t_e[PF_RULESET_MAX+1]; + struct pfioc_trans t; + + bzero(&t, sizeof(t)); + bzero(t_e, sizeof(t_e)); + t.size = PF_RULESET_MAX+1; + t.esize = sizeof(t_e[0]); + t.array = t_e; + for (i = 0; i < PF_RULESET_MAX+1; ++i) { + t_e[i].rs_num = i; + snprintf(t_e[i].anchor, sizeof(t_e[i].anchor), + "%s/%s", anchorname, prs.name); } + t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE; + if ((ioctl(dev, DIOCXBEGIN, &t) || + ioctl(dev, DIOCXCOMMIT, &t)) && + errno != EINVAL) + 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; } - - 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"); + } + pargv[2] = fdpath; + pargv[5] = rsn; + pargv[7] = userstr; + pargv[9] = ipstr; + if (!add) + pargv[11] = "/dev/null"; + else + pargv[11] = fn; + + switch (pid = fork()) { + case -1: + err(1, "fork failed"); + case 0: + execvp(PATH_PFCTL, pargv); + warn("exec of %s failed", PATH_PFCTL); + _exit(1); + } + + /* parent */ + waitpid(pid, &s, 0); + if (s != 0) { + if (WIFEXITED(s)) { + syslog(LOG_ERR, "pfctl exited abnormally"); goto error; } - - infile = NULL; - fclose(f); - f = NULL; - } - - if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) { - syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove"); - goto error; } if (add) { @@ -691,18 +706,63 @@ 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 * want to, since we don't have to worry about any luser sessions lasting @@ -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) -{ -} diff --git a/contrib/pf/ftp-proxy/ftp-proxy.8 b/contrib/pf/ftp-proxy/ftp-proxy.8 index db043cd..125c5e8 100644 --- a/contrib/pf/ftp-proxy/ftp-proxy.8 +++ b/contrib/pf/ftp-proxy/ftp-proxy.8 @@ -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 diff --git a/contrib/pf/ftp-proxy/ftp-proxy.c b/contrib/pf/ftp-proxy/ftp-proxy.c index 344ca27..ea4245a 100644 --- a/contrib/pf/ftp-proxy/ftp-proxy.c +++ b/contrib/pf/ftp-proxy/ftp-proxy.c @@ -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); /* diff --git a/contrib/pf/man/pf.4 b/contrib/pf/man/pf.4 index a91f041..a78f8b3 100644 --- a/contrib/pf/man/pf.4 +++ b/contrib/pf/man/pf.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pf.4,v 1.48 2004/03/27 17:15:30 henning Exp $ +.\" $OpenBSD: pf.4,v 1.54 2004/12/22 17:17:55 dhartmei Exp $ .\" .\" Copyright (C) 2001, Kjell Wooding. All rights reserved. .\" @@ -51,30 +51,47 @@ The most commonly used functions are covered by .Xr pfctl 8 . .Pp Manipulations like loading a ruleset that involve more than a single -ioctl call require a so-called ticket, which prevents the occurrence of +.Xr ioctl 2 +call require a so-called +.Em ticket , +which prevents the occurrence of multiple concurrent manipulations. .Pp -Fields of ioctl parameter structures that refer to packet data (like +Fields of +.Xr ioctl 2 +parameter structures that refer to packet data (like addresses and ports) are generally expected in network byte-order. -.Sh FILES -.Bl -tag -width /dev/pf -compact -.It Pa /dev/pf -packet filtering device. -.El +.Pp +Rules and address tables are contained in so-called +.Em anchors . +When servicing an +.Xr ioctl 2 +request, if the anchor field of the argument structure is empty, +the kernel will use the default anchor (i.e., the main ruleset) +in operations. +Anchors are specified by name and may be nested, with components +separated by +.Sq / +characters, similar to how file system hierarchies are laid out. +The final component of the anchor path is the anchor under which +operations will be performed. .Sh IOCTL INTERFACE -pf supports the following +.Nm +supports the following .Xr ioctl 2 -commands: +commands, available through +.Aq Pa net/pfvar.h : .Bl -tag -width xxxxxx .It Dv DIOCSTART -Starts the packet filter. +Start the packet filter. .It Dv DIOCSTOP -Stops the packet filter. +Stop the packet filter. .It Dv DIOCSTARTALTQ -Starts the ALTQ bandwidth control system. +Start the ALTQ bandwidth control system (see +.Xr altq 9 ) . .It Dv DIOCSTOPALTQ -Stops the ALTQ bandwidth control system. -.It Dv DIOCBEGINADDRS Fa "struct pfioc_pooladdr" +Stop the ALTQ bandwidth control system. +.It Dv DIOCBEGINADDRS Fa "struct pfioc_pooladdr *pp" .Bd -literal struct pfioc_pooladdr { u_int32_t action; @@ -84,119 +101,138 @@ struct pfioc_pooladdr { u_int8_t r_action; u_int8_t r_last; u_int8_t af; - char anchor[PF_ANCHOR_NAME_SIZE]; - char ruleset[PF_RULESET_NAME_SIZE]; + char anchor[MAXPATHLEN]; struct pf_pooladdr addr; }; .Ed .Pp -Clears the buffer address pool -and returns a +Clear the buffer address pool and get a .Va ticket -for subsequent DIOCADDADDR, DIOCADDRULE and DIOCCHANGERULE calls. -.It Dv DIOCADDADDR Fa "struct pfioc_pooladdr" +for subsequent +.Dv DIOCADDADDR , +.Dv DIOCADDRULE , +and +.Dv DIOCCHANGERULE +calls. +.It Dv DIOCADDADDR Fa "struct pfioc_pooladdr *pp" .Pp -Adds pool address +Add the pool address .Va addr to the buffer address pool to be used in the following -DIOCADDRULE or DIOCCHANGERULE call. +.Dv DIOCADDRULE +or +.Dv DIOCCHANGERULE +call. All other members of the structure are ignored. -.It Dv DIOCADDRULE Fa "struct pfioc_rule" +.It Dv DIOCADDRULE Fa "struct pfioc_rule *pr" .Bd -literal struct pfioc_rule { u_int32_t action; u_int32_t ticket; u_int32_t pool_ticket; u_int32_t nr; - char anchor[PF_ANCHOR_NAME_SIZE]; - char ruleset[PF_RULESET_NAME_SIZE]; + char anchor[MAXPATHLEN]; + char anchor_call[MAXPATHLEN]; struct pf_rule rule; }; .Ed .Pp -Adds +Add .Va rule at the end of the inactive ruleset. -Requires +This call requires a .Va ticket -obtained through preceding DIOCXBEGIN call, and +obtained through a preceding +.Dv DIOCXBEGIN +call and a .Va pool_ticket -obtained through DIOCBEGINADDRS call. -DIOCADDADDR must also be called if any pool addresses are required. +obtained through a +.Dv DIOCBEGINADDRS +call. +.Dv DIOCADDADDR +must also be called if any pool addresses are required. The optional .Va anchor -and -.Va ruleset -names indicate the anchor and ruleset in which to append the rule. +name indicates the anchor in which to append the rule. .Va nr and .Va action are ignored. -.It Dv DIOCADDALTQ Fa "struct pfioc_altq" -Adds +.It Dv DIOCADDALTQ Fa "struct pfioc_altq *pa" +Add an ALTQ discipline or queue. .Bd -literal struct pfioc_altq { u_int32_t action; u_int32_t ticket; u_int32_t nr; - struct pf_altq altq; + struct pf_altq altq; }; .Ed -.It Dv DIOCGETRULES Fa "struct pfioc_rule" -Returns +.It Dv DIOCGETRULES Fa "struct pfioc_rule *pr" +Get a .Va ticket -for subsequent DIOCGETRULE calls and +for subsequent +.Dv DIOCGETRULE +calls and the number .Va nr of rules in the active ruleset. -.It Dv DIOCGETRULE Fa "struct pfioc_rule" -Returns +.It Dv DIOCGETRULE Fa "struct pfioc_rule *pr" +Get a .Va rule -number +by its number .Va nr -using +using the .Va ticket -obtained through a preceding DIOCGETRULES call. -.It Dv DIOCGETADDRS Fa "struct pfioc_pooladdr" -Returns +obtained through a preceding +.Dv DIOCGETRULES +call. +.It Dv DIOCGETADDRS Fa "struct pfioc_pooladdr *pp" +Get a .Va ticket -for subsequent DIOCGETADDR calls and +for subsequent +.Dv DIOCGETADDR +calls and the number .Va nr of pool addresses in the rule specified with .Va r_action , .Va r_num , -.Va anchor and -.Va ruleset . -.It Dv DIOCGETADDR Fa "struct pfioc_pooladdr" -Returns pool address +.Va anchor . +.It Dv DIOCGETADDR Fa "struct pfioc_pooladdr *pp" +Get the pool address .Va addr -number +by its number .Va nr from the rule specified with .Va r_action , .Va r_num , -.Va anchor and -.Va ruleset -using +.Va anchor +using the .Va ticket -obtained through a preceding DIOCGETADDRS call. -.It Dv DIOCGETALTQS Fa "struct pfioc_altq" -Returns +obtained through a preceding +.Dv DIOCGETADDRS +call. +.It Dv DIOCGETALTQS Fa "struct pfioc_altq *pa" +Get a .Va ticket -for subsequent DIOCGETALTQ calls and +for subsequent +.Dv DIOCGETALTQ +calls and the number .Va nr of queues in the active list. -.It Dv DIOCGETALTQ Fa "struct pfioc_altq" -Returns +.It Dv DIOCGETALTQ Fa "struct pfioc_altq *pa" +Get the queueing discipline .Va altq -number +by its number .Va nr -using +using the .Va ticket -obtained through a preceding DIOCGETALTQS call. -.It Dv DIOCGETQSTATS Fa "struct pfioc_qstats" -Returns statistics on a queue. +obtained through a preceding +.Dv DIOCGETALTQS +call. +.It Dv DIOCGETQSTATS Fa "struct pfioc_qstats *pq" +Get the statistics on a queue. .Bd -literal struct pfioc_qstats { u_int32_t ticket; @@ -207,54 +243,99 @@ struct pfioc_qstats { }; .Ed .Pp -A pointer to a buffer of statistics -.Va buf +This call fills in a pointer to the buffer of statistics +.Va buf , of length -.Va nbytes +.Va nbytes , for the queue specified by .Va nr . -.It Dv DIOCADDSTATE Fa "struct pfioc_state" -Adds a state entry. -.It Dv DIOCGETSTATE Fa "struct pfioc_state" +.It Dv DIOCGETRULESETS Fa "struct pfioc_ruleset *pr" +.Bd -literal +struct pfioc_ruleset { + u_int32_t nr; + char path[MAXPATHLEN]; + char name[PF_ANCHOR_NAME_SIZE]; +}; +.Ed +.Pp +Get the number +.Va nr +of rulesets (i.e., anchors) directly attached to the anchor named by +.Va path +for use in subsequent +.Dv DIOCGETRULESET +calls. +Nested anchors, since they are not directly attached to the given +anchor, will not be included. +This ioctl returns +.Er EINVAL +if the given anchor does not exist. +.It Dv DIOCGETRULESET Fa "struct pfioc_ruleset *pr" +Get a ruleset (i.e., an anchor) +.Va name +by its number +.Va nr +from the given anchor +.Va path , +the maximum number of which can be obtained from a preceding +.Dv DIOCGETRULESETS +call. +This ioctl returns +.Er EINVAL +if the given anchor does not exist or +.Er EBUSY +if another process is concurrently updating a ruleset. +.It Dv DIOCADDSTATE Fa "struct pfioc_state *ps" +Add a state entry. .Bd -literal struct pfioc_state { u_int32_t nr; struct pf_state state; }; .Ed -.Pp -Extracts the entry with the specified number from the state table. -.It Dv DIOCKILLSTATES Fa "struct pfioc_state_kill" -Removes matching entries from the state table. -Returns the number of killed states in psk_af. +.It Dv DIOCGETSTATE Fa "struct pfioc_state *ps" +Extract the entry with the specified number +.Va nr +from the state table. +.It Dv DIOCKILLSTATES Fa "struct pfioc_state_kill *psk" +Remove matching entries from the state table. +This ioctl returns the number of killed states in +.Va psk_af . .Bd -literal struct pfioc_state_kill { - int psk_af; + sa_family_t psk_af; int psk_proto; struct pf_rule_addr psk_src; struct pf_rule_addr psk_dst; char psk_ifname[IFNAMSIZ]; }; .Ed -.It Dv DIOCCLRSTATES Fa "struct pfioc_state_kill" -Clears all states. +.It Dv DIOCCLRSTATES Fa "struct pfioc_state_kill *psk" +Clear all states. It works like .Dv DIOCKILLSTATES , -but ignores the psk_af, psk_proto, psk_src and psk_dst fields of the -.Fa pfioc_state_kill +but ignores the +.Va psk_af , +.Va psk_proto , +.Va psk_src , +and +.Va psk_dst +fields of the +.Vt pfioc_state_kill structure. -.It Dv DIOCSETSTATUSIF Fa "struct pfioc_if" +.It Dv DIOCSETSTATUSIF Fa "struct pfioc_if *pi" +Specify the interface for which statistics are accumulated. .Bd -literal struct pfioc_if { char ifname[IFNAMSIZ]; }; .Ed -.Pp -Specifies the interface for which statistics are accumulated. -.It Dv DIOCGETSTATUS Fa "struct pf_status" +.It Dv DIOCGETSTATUS Fa "struct pf_status *s" +Get the internal packet filter statistics. .Bd -literal struct pf_status { u_int64_t counters[PFRES_MAX]; + u_int64_t lcounters[LCNT_MAX]; u_int64_t fcounters[FCNT_MAX]; u_int64_t scounters[SCNT_MAX]; u_int64_t pcounters[2][2][3]; @@ -269,12 +350,10 @@ struct pf_status { char ifname[IFNAMSIZ]; }; .Ed -.Pp -Gets the internal packet filter statistics. .It Dv DIOCCLRSTATUS -Clears the internal packet filter statistics. -.It Dv DIOCNATLOOK Fa "struct pfioc_natlook" -Looks up a state table entry by source and destination addresses and ports. +Clear the internal packet filter statistics. +.It Dv DIOCNATLOOK Fa "struct pfioc_natlook *pnl" +Look up a state table entry by source and destination addresses and ports. .Bd -literal struct pfioc_natlook { struct pf_addr saddr; @@ -290,98 +369,149 @@ struct pfioc_natlook { u_int8_t direction; }; .Ed -.It Dv DIOCSETDEBUG Fa "u_int32_t" -Sets the debug level. +.It Dv DIOCSETDEBUG Fa "u_int32_t *level" +Set the debug level. .Bd -literal -enum { PF_DEBUG_NONE=0, PF_DEBUG_URGENT=1, PF_DEBUG_MISC=2 }; +enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC, + PF_DEBUG_NOISY }; .Ed -.It Dv DIOCGETSTATES Fa "struct pfioc_states" +.It Dv DIOCGETSTATES Fa "struct pfioc_states *ps" +Get state table entries. .Bd -literal struct pfioc_states { int ps_len; union { - caddr_t psu_buf; + caddr_t psu_buf; struct pf_state *psu_states; } ps_u; #define ps_buf ps_u.psu_buf #define ps_states ps_u.psu_states }; .Ed -.It Dv DIOCCHANGERULE Fa "struct pfioc_rule" -Adds or removes the +.Pp +If +.Va ps_len +is zero, all states will be gathered into +.Va pf_states +and +.Va ps_len +will be set to the size they take in memory (i.e., +.Li sizeof(struct pf_state) * nr ) . +If +.Va ps_len +is non-zero, as many states that can fit into +.Va ps_len +as possible will be gathered, and +.Va ps_len +will be updated to the size those rules take in memory. +.It Dv DIOCCHANGERULE Fa "struct pfioc_rule *pcr" +Add or remove the .Va rule in the ruleset specified by .Va rule.action . -.Bd -literal -enum { PF_CHANGE_ADD_HEAD=1, PF_CHANGE_ADD_TAIL=2, - PF_CHANGE_ADD_BEFORE=3, PF_CHANGE_ADD_AFTER=4, - PF_CHANGE_REMOVE=5, PF_CHANGE_GET_TICKET=6 }; -.Ed .Pp The type of operation to be performed is indicated by -.Va action . +.Va action , +which can be any of the following: +.Bd -literal +enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL, + PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER, + PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET }; +.Ed .Pp .Va ticket -must be set to the value obtained with PF_CHANGE_GET_TICKET -for all actions except PF_CHANGE_GET_TICKET. +must be set to the value obtained with +.Dv PF_CHANGE_GET_TICKET +for all actions except +.Dv PF_CHANGE_GET_TICKET . .Va pool_ticket -must be set to the value obtained with the DIOCBEGINADDRS call -for all actions except PF_CHANGE_REMOVE and PF_CHANGE_GET_TICKET. -.Pp -.Va anchor +must be set to the value obtained with the +.Dv DIOCBEGINADDRS +call for all actions except +.Dv PF_CHANGE_REMOVE and -.Va ruleset -indicate which anchor and ruleset the operation applies to. +.Dv PF_CHANGE_GET_TICKET . +.Va anchor +indicates to which anchor the operation applies. .Va nr -indicates the rule number against which PF_CHANGE_ADD_BEFORE, -PF_CHANGE_ADD_AFTER or PF_CHANGE_REMOVE actions are applied. -.It Dv DIOCCHANGEADDR Fa "struct pfioc_pooladdr" -Adds or removes a pool address +indicates the rule number against which +.Dv PF_CHANGE_ADD_BEFORE , +.Dv PF_CHANGE_ADD_AFTER , +or +.Dv PF_CHANGE_REMOVE +actions are applied. +.\" It Dv DIOCCHANGEALTQ Fa "struct pfioc_altq *pcr" +.It Dv DIOCCHANGEADDR Fa "struct pfioc_pooladdr *pca" +Add or remove the pool address .Va addr -from a rule specified with +from the rule specified by .Va r_action , .Va r_num , -.Va anchor and -.Va ruleset . -.It Dv DIOCSETTIMEOUT Fa "struct pfioc_tm" +.Va anchor . +.It Dv DIOCSETTIMEOUT Fa "struct pfioc_tm *pt" .Bd -literal struct pfioc_tm { int timeout; int seconds; }; .Ed -.It Dv DIOCGETTIMEOUT Fa "struct pfioc_tm" +.Pp +Set the state timeout of +.Va timeout +to +.Va seconds . +The old value will be placed into +.Va seconds . +For possible values of +.Va timeout , +consult the +.Dv PFTM_* +values in +.Aq Pa net/pfvar.h . +.It Dv DIOCGETTIMEOUT Fa "struct pfioc_tm *pt" +Get the state timeout of +.Va timeout . +The value will be placed into the +.Va seconds +field. .It Dv DIOCCLRRULECTRS Clear per-rule statistics. -.It Dv DIOCSETLIMIT Fa "struct pfioc_limit" -Sets hard limits on the memory pools used by the packet filter. +.It Dv DIOCSETLIMIT Fa "struct pfioc_limit *pl" +Set the hard limits on the memory pools used by the packet filter. .Bd -literal struct pfioc_limit { int index; unsigned limit; }; + +enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS }; .Ed -.It Dv DIOCGETLIMIT Fa "struct pfioc_limit" -.It Dv DIOCRCLRTABLES Fa "struct pfioc_table" +.It Dv DIOCGETLIMIT Fa "struct pfioc_limit *pl" +Get the hard +.Va limit +for the memory pool indicated by +.Va index . +.It Dv DIOCRCLRTABLES Fa "struct pfioc_table *io" Clear all tables. -All the IOCTLs that manipulate radix tables +All the ioctls that manipulate radix tables use the same structure described below. For -.Dv DIOCRCLRTABLES, pfrio_ndel contains on exit the number -of tables deleted. +.Dv DIOCRCLRTABLES , +.Va pfrio_ndel +contains on exit the number of tables deleted. .Bd -literal struct pfioc_table { - struct pfr_table pfrio_table; - void *pfrio_buffer; - int pfrio_esize; - int pfrio_size; - int pfrio_size2; - int pfrio_nadd; - int pfrio_ndel; - int pfrio_nchange; - int pfrio_flags; - int pfrio_ticket; + struct pfr_table pfrio_table; + void *pfrio_buffer; + int pfrio_esize; + int pfrio_size; + int pfrio_size2; + int pfrio_nadd; + int pfrio_ndel; + int pfrio_nchange; + int pfrio_flags; + u_int32_t pfrio_ticket; }; #define pfrio_exists pfrio_nadd #define pfrio_nzero pfrio_nadd @@ -390,192 +520,314 @@ struct pfioc_table { #define pfrio_setflag pfrio_size2 #define pfrio_clrflag pfrio_nadd .Ed -.It Dv DIOCRADDTABLES Fa "struct pfioc_table" -Creates one or more tables. -On entry, pfrio_buffer[pfrio_size] contains a table of pfr_table structures. -On exit, pfrio_nadd contains the number of tables effectively created. +.It Dv DIOCRADDTABLES Fa "struct pfioc_table *io" +Create one or more tables. +On entry, +.Va pfrio_buffer[pfrio_size] +contains a table of +.Vt pfr_table +structures. +On exit, +.Va pfrio_nadd +contains the number of tables effectively created. .Bd -literal struct pfr_table { - char pfrt_anchor[PF_ANCHOR_NAME_SIZE]; - char pfrt_ruleset[PF_RULESET_NAME_SIZE]; - char pfrt_name[PF_TABLE_NAME_SIZE]; - u_int32_t pfrt_flags; - u_int8_t pfrt_fback; + char pfrt_anchor[MAXPATHLEN]; + char pfrt_name[PF_TABLE_NAME_SIZE]; + u_int32_t pfrt_flags; + u_int8_t pfrt_fback; }; .Ed -.It Dv DIOCRDELTABLES Fa "struct pfioc_table" -Deletes one or more tables. -On entry, pfrio_buffer[pfrio_size] contains a table of pfr_table structures. -On exit, pfrio_nadd contains the number of tables effectively deleted. -.It Dv DIOCRGETTABLES Fa "struct pfioc_table" +.It Dv DIOCRDELTABLES Fa "struct pfioc_table *io" +Delete one or more tables. +On entry, +.Va pfrio_buffer[pfrio_size] +contains a table of +.Vt pfr_table +structures. +On exit, +.Va pfrio_nadd +contains the number of tables effectively deleted. +.It Dv DIOCRGETTABLES Fa "struct pfioc_table *io" Get the list of all tables. -On entry, pfrio_buffer[pfrio_size] contains a valid writeable buffer for -pfr_table structures. -On exit, pfrio_size contains the number of tables written into the buffer. +On entry, +.Va pfrio_buffer[pfrio_size] +contains a valid writeable buffer for +.Vt pfr_table +structures. +On exit, +.Va pfrio_size +contains the number of tables written into the buffer. If the buffer is too small, the kernel does not store anything but just returns the required buffer size, without error. -.It Dv DIOCRGETTSTATS Fa "struct pfioc_table" -Like -.Dv DIOCRGETTABLES , -but returns an array of pfr_tstats structures. +.It Dv DIOCRGETTSTATS Fa "struct pfioc_table *io" +This call is like +.Dv DIOCRGETTABLES +but is used to get an array of +.Vt pfr_tstats +structures. .Bd -literal struct pfr_tstats { - struct pfr_table pfrts_t; - u_int64_t pfrts_packets - [PFR_DIR_MAX][PFR_OP_TABLE_MAX]; - u_int64_t pfrts_bytes - [PFR_DIR_MAX][PFR_OP_TABLE_MAX]; - u_int64_t pfrts_match; - u_int64_t pfrts_nomatch; - long pfrts_tzero; - int pfrts_cnt; - int pfrts_refcnt[PFR_REFCNT_MAX]; + struct pfr_table pfrts_t; + u_int64_t pfrts_packets + [PFR_DIR_MAX][PFR_OP_TABLE_MAX]; + u_int64_t pfrts_bytes + [PFR_DIR_MAX][PFR_OP_TABLE_MAX]; + u_int64_t pfrts_match; + u_int64_t pfrts_nomatch; + long pfrts_tzero; + int pfrts_cnt; + int pfrts_refcnt[PFR_REFCNT_MAX]; }; -#define pfrts_name pfrts_t.pfrt_name -#define pfrts_flags pfrts_t.pfrt_flags +#define pfrts_name pfrts_t.pfrt_name +#define pfrts_flags pfrts_t.pfrt_flags .Ed -.It Dv DIOCRCLRTSTATS Fa "struct pfioc_table" -Clears the statistics of one or more tables. -On entry, pfrio_buffer[pfrio_size] contains a table of pfr_table structures. -On exit, pfrio_nzero contains the number of tables effectively cleared. -.It Dv DIOCRCLRADDRS Fa "struct pfioc_table" +.It Dv DIOCRCLRTSTATS Fa "struct pfioc_table *io" +Clear the statistics of one or more tables. +On entry, +.Va pfrio_buffer[pfrio_size] +contains a table of +.Vt pfr_table +structures. +On exit, +.Va pfrio_nzero +contains the number of tables effectively cleared. +.It Dv DIOCRCLRADDRS Fa "struct pfioc_table *io" Clear all addresses in a table. -On entry, pfrio_table contains the table to clear. -On exit, pfrio_ndel contains the number of addresses removed. -.It Dv DIOCRADDADDRS Fa "struct pfioc_table" +On entry, +.Va pfrio_table +contains the table to clear. +On exit, +.Va pfrio_ndel +contains the number of addresses removed. +.It Dv DIOCRADDADDRS Fa "struct pfioc_table *io" Add one or more addresses to a table. -On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size] -contains the list of pfr_addr structures to add. -On exit, pfrio_nadd contains the number of addresses effectively added. +On entry, +.Va pfrio_table +contains the table ID and +.Va pfrio_buffer[pfrio_size] +contains the list of +.Vt pfr_addr +structures to add. +On exit, +.Va pfrio_nadd +contains the number of addresses effectively added. .Bd -literal struct pfr_addr { - union { - struct in_addr _pfra_ip4addr; - struct in6_addr _pfra_ip6addr; - } pfra_u; - u_int8_t pfra_af; - u_int8_t pfra_net; - u_int8_t pfra_not; - u_int8_t pfra_fback; + union { + struct in_addr _pfra_ip4addr; + struct in6_addr _pfra_ip6addr; + } pfra_u; + u_int8_t pfra_af; + u_int8_t pfra_net; + u_int8_t pfra_not; + u_int8_t pfra_fback; }; #define pfra_ip4addr pfra_u._pfra_ip4addr #define pfra_ip6addr pfra_u._pfra_ip6addr .Ed -.It Dv DIOCRDELADDRS Fa "struct pfioc_table" +.It Dv DIOCRDELADDRS Fa "struct pfioc_table *io" Delete one or more addresses from a table. -On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size] -contains the list of pfr_addr structures to delete. -On exit, pfrio_ndel contains the number of addresses effectively deleted. -.It Dv DIOCRSETADDRS Fa "struct pfioc_table" +On entry, +.Va pfrio_table +contains the table ID and +.Va pfrio_buffer[pfrio_size] +contains the list of +.Vt pfr_addr +structures to delete. +On exit, +.Va pfrio_ndel +contains the number of addresses effectively deleted. +.It Dv DIOCRSETADDRS Fa "struct pfioc_table *io" Replace the content of a table by a new address list. This is the most complicated command, which uses all the structure members. -On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size] -contains the new list of pfr_addr structures. -In addition to that, if size2 is nonzero, pfrio_buffer[pfrio_size..pfrio_size2] -must be a writeable buffer, into which the kernel can copy the addresses that -have been deleted during the replace operation. -On exit, pfrio_ndel, pfrio_nadd and pfrio_nchange contain the number of -addresses deleted, added and changed by the kernel. -If pfrio_size2 was set on -entry, pfrio_size2 will point to the size of the buffer used, exactly like +.Pp +On entry, +.Va pfrio_table +contains the table ID and +.Va pfrio_buffer[pfrio_size] +contains the new list of +.Vt pfr_addr +structures. +Additionally, if +.Va pfrio_size2 +is non-zero, +.Va pfrio_buffer[pfrio_size..pfrio_size2] +must be a writeable buffer, into which the kernel can copy the +addresses that have been deleted during the replace operation. +On exit, +.Va pfrio_ndel , +.Va pfrio_nadd , +and +.Va pfrio_nchange +contain the number of addresses deleted, added, and changed by the +kernel. +If +.Va pfrio_size2 +was set on entry, +.Va pfrio_size2 +will point to the size of the buffer used, exactly like .Dv DIOCRGETADDRS . -.It Dv DIOCRGETADDRS Fa "struct pfioc_table" +.It Dv DIOCRGETADDRS Fa "struct pfioc_table *io" Get all the addresses of a table. -On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size] -contains a valid writeable buffer for pfr_addr structures. -On exit, pfrio_size contains the number of addresses written into the buffer. +On entry, +.Va pfrio_table +contains the table ID and +.Va pfrio_buffer[pfrio_size] +contains a valid writeable buffer for +.Vt pfr_addr +structures. +On exit, +.Va pfrio_size +contains the number of addresses written into the buffer. If the buffer was too small, the kernel does not store anything but just -return the required buffer size, without returning an error. -.It Dv DIOCRGETASTATS Fa "struct pfioc_table" -Like -.Dv DIOCRGETADDRS , -but returns an array of pfr_astats structures. +returns the required buffer size, without returning an error. +.It Dv DIOCRGETASTATS Fa "struct pfioc_table *io" +This call is like +.Dv DIOCRGETADDRS +but is used to get an array of +.Vt pfr_astats +structures. .Bd -literal struct pfr_astats { - struct pfr_addr pfras_a; - u_int64_t pfras_packets - [PFR_DIR_MAX][PFR_OP_ADDR_MAX]; - u_int64_t pfras_bytes - [PFR_DIR_MAX][PFR_OP_ADDR_MAX]; - long pfras_tzero; + struct pfr_addr pfras_a; + u_int64_t pfras_packets + [PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + u_int64_t pfras_bytes + [PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + long pfras_tzero; }; .Ed -.It Dv DIOCRCLRASTATS Fa "struct pfioc_table" -Clears the statistics of one or more addresses. -On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size] -contains a table of pfr_addr structures to clear. -On exit, pfrio_nzero contains the number of addresses effectively cleared. -.It Dv DIOCRTSTADDRS Fa "struct pfioc_table" +.It Dv DIOCRCLRASTATS Fa "struct pfioc_table *io" +Clear the statistics of one or more addresses. +On entry, +.Va pfrio_table +contains the table ID and +.Va pfrio_buffer[pfrio_size] +contains a table of +.Vt pfr_addr +structures to clear. +On exit, +.Va pfrio_nzero +contains the number of addresses effectively cleared. +.It Dv DIOCRTSTADDRS Fa "struct pfioc_table *io" Test if the given addresses match a table. -On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size] -contains a table of pfr_addr structures to test. -On exit, the kernel updates the pfr_addr table by setting the pfra_fback +On entry, +.Va pfrio_table +contains the table ID and +.Va pfrio_buffer[pfrio_size] +contains a table of +.Vt pfr_addr +structures to test. +On exit, the kernel updates the +.Vt pfr_addr +table by setting the +.Va pfra_fback member appropriately. -.It Dv DIOCRSETTFLAGS Fa "struct pfioc_table" +.It Dv DIOCRSETTFLAGS Fa "struct pfioc_table *io" Change the -.Va const +.Dv PFR_TFLAG_CONST or -.Va persist -flag of a table. -On entry, pfrio_buffer[pfrio_size] contains a table of pfr_table structures, -and pfrio_setflag contains the flags to add, while pfrio_clrflag contains the -flags to remove. -On exit, pfrio_nchange and pfrio_ndel contain the number of tables altered -or deleted by the kernel. +.Dv PFR_TFLAG_PERSIST +flags of a table. +On entry, +.Va pfrio_buffer[pfrio_size] +contains a table of +.Vt pfr_table +structures, and +.Va pfrio_setflag +contains the flags to add, while +.Va pfrio_clrflag +contains the flags to remove. +On exit, +.Va pfrio_nchange +and +.Va pfrio_ndel +contain the number of tables altered or deleted by the kernel. Yes, tables can be deleted if one removes the -.Va persist +.Dv PFR_TFLAG_PERSIST flag of an unreferenced table. -.It Dv DIOCRINADEFINE Fa "struct pfioc_table" +.It Dv DIOCRINADEFINE Fa "struct pfioc_table *io" Defines a table in the inactive set. -On entry, pfrio_table contains the table id and pfrio_buffer[pfrio_size] -contains the list of pfr_addr structures to put in the table. -A valid ticket must also be supplied to pfrio_ticket. -On exit, pfrio_nadd contains 0 if the table was already defined in the -inactive list, or 1 if a new table has been created. -pfrio_naddr contains the number of addresses effectively put in the table. -.It Dv DIOCXBEGIN Fa "struct pfioc_trans" +On entry, +.Va pfrio_table +contains the table ID and +.Va pfrio_buffer[pfrio_size] +contains the list of +.Vt pfr_addr +structures to put in the table. +A valid ticket must also be supplied to +.Va pfrio_ticket . +On exit, +.Va pfrio_nadd +contains 0 if the table was already defined in the inactive list +or 1 if a new table has been created. +.Va pfrio_naddr +contains the number of addresses effectively put in the table. +.It Dv DIOCXBEGIN Fa "struct pfioc_trans *io" .Bd -literal -#define PF_RULESET_ALTQ (PF_RULESET_MAX) -#define PF_RULESET_TABLE (PF_RULESET_MAX+1) struct pfioc_trans { - int size; /* number of elements */ - int esize; /* size of each element in bytes */ - struct pfioc_trans_e { - int rs_num; - char anchor[PF_ANCHOR_NAME_SIZE]; - char ruleset[PF_RULESET_NAME_SIZE]; - u_int32_t ticket; - } *array; + int size; /* number of elements */ + int esize; /* size of each element in bytes */ + struct pfioc_trans_e { + int rs_num; + char anchor[MAXPATHLEN]; + u_int32_t ticket; + } *array; }; .Ed .Pp -Clears all the inactive rulesets specified in the -.Fa "struct pfioc_trans_e" +Clear all the inactive rulesets specified in the +.Vt pfioc_trans_e array. -For each ruleset, a ticket is returned for subsequent "add rule" IOCTLs, +For each ruleset, a ticket is returned for subsequent "add rule" ioctls, as well as for the .Dv DIOCXCOMMIT and .Dv DIOCXROLLBACK calls. -.It Dv DIOCXCOMMIT Fa "struct pfioc_trans" +.Pp +Ruleset types, identified by +.Va rs_num , +include the following: +.Pp +.Bl -tag -width PF_RULESET_FILTER -offset ind -compact +.It Dv PF_RULESET_SCRUB +Scrub (packet normalization) rules. +.It Dv PF_RULESET_FILTER +Filter rules. +.It Dv PF_RULESET_NAT +NAT (Network Address Translation) rules. +.It Dv PF_RULESET_BINAT +Bidirectional NAT rules. +.It Dv PF_RULESET_RDR +Redirect rules. +.It Dv PF_RULESET_ALTQ +ALTQ disciplines. +.It Dv PF_RULESET_TABLE +Address tables. +.El +.It Dv DIOCXCOMMIT Fa "struct pfioc_trans *io" Atomically switch a vector of inactive rulesets to the active rulesets. -Implemented as a standard 2-phase commit, which will either fail for all -rulesets or completely succeed. +This call is implemented as a standard two-phase commit, which will either +fail for all rulesets or completely succeed. All tickets need to be valid. -Returns -.Dv EBUSY -if a concurrent process is trying to update some of the same rulesets -concurrently. -.It Dv DIOCXROLLBACK Fa "struct pfioc_trans" +This ioctl returns +.Er EBUSY +if another process is concurrently updating some of the same rulesets. +.It Dv DIOCXROLLBACK Fa "struct pfioc_trans *io" Clean up the kernel by undoing all changes that have taken place on the inactive rulesets since the last .Dv DIOCXBEGIN . .Dv DIOCXROLLBACK will silently ignore rulesets for which the ticket is invalid. -.It Dv DIOCFPFLUSH +.It Dv DIOCSETHOSTID Fa "u_int32_t *hostid" +Set the host ID, which is used by +.Xr pfsync 4 +to identify which host created state table entries. +.It Dv DIOCOSFPFLUSH Flush the passive OS fingerprint table. -.It Dv DIOCFPADD Fa "struct pf_osfp_ioctl" +.It Dv DIOCOSFPADD Fa "struct pf_osfp_ioctl *io" .Bd -literal struct pf_osfp_ioctl { struct pf_osfp_entry { @@ -585,12 +837,14 @@ struct pf_osfp_ioctl { char fp_version_nm[PF_OSFP_LEN]; char fp_subtype_nm[PF_OSFP_LEN]; } fp_os; - u_int16_t fp_mss; + pf_tcpopts_t fp_tcpopts; u_int16_t fp_wsize; u_int16_t fp_psize; - u_int8_t fp_ttl; + u_int16_t fp_mss; + u_int16_t fp_flags; + u_int8_t fp_optcnt; u_int8_t fp_wscale; - u_int8_t fp_flags; + u_int8_t fp_ttl; int fp_getnum; }; .Ed @@ -610,64 +864,65 @@ The members .Va fp_wsize , .Va fp_psize , .Va fp_ttl , +.Va fp_optcnt , and .Va fp_wscale -are set to the TCP MSS, the TCP window size, the IP length and the IP TTL of -the TCP SYN packet respectively. +are set to the TCP MSS, the TCP window size, the IP length, the IP TTL, +the number of TCP options, and the TCP window scaling constant of the +TCP SYN packet, respectively. +.Pp The .Va fp_flags -member is filled according to the net/pfvar.h include file PF_OSFP_* defines. +member is filled according to the +.Aq Pa net/pfvar.h +include file +.Dv PF_OSFP_* +defines. +The +.Va fp_tcpopts +member contains packed TCP options. +Each option uses +.Dv PF_OSFP_TCPOPT_BITS +bits in the packed value. +Options include any of +.Dv PF_OSFP_TCPOPT_NOP , +.Dv PF_OSFP_TCPOPT_SACK , +.Dv PF_OSFP_TCPOPT_WSCALE , +.Dv PF_OSFP_TCPOPT_MSS , +or +.Dv PF_OSFP_TCPOPT_TS . +.Pp The .Va fp_getnum -is not used with this ioctl. +member is not used with this ioctl. .Pp -The structure's slack space must be zeroed for correct operation; memset +The structure's slack space must be zeroed for correct operation; +.Xr memset 3 the whole structure to zero before filling and sending to the kernel. -.It Dv DIOCFPGET Fa "struct pf_osfp_ioctl" -.Bd -literal -struct pf_osfp_ioctl { - struct pf_osfp_entry { - SLIST_ENTRY(pf_osfp_entry) fp_entry; - pf_osfp_t fp_os; - char fp_class_nm[PF_OSFP_LEN]; - char fp_version_nm[PF_OSFP_LEN]; - char fp_subtype_nm[PF_OSFP_LEN]; - } fp_os; - u_int16_t fp_mss; - u_int16_t fp_wsize; - u_int16_t fp_psize; - u_int8_t fp_ttl; - u_int8_t fp_wscale; - u_int8_t fp_flags; - int fp_getnum; -}; -.Ed -.Pp +.It Dv DIOCOSFPGET Fa "struct pf_osfp_ioctl *io" Get the passive OS fingerprint number .Va fp_getnum from the kernel's fingerprint list. The rest of the structure members will come back filled. Get the whole list by repeatedly incrementing the .Va fp_getnum -number until the ioctl returns EBUSY. -.It Dv DIOCGETSRCNODES Fa "struct pfioc_src_nodes" +number until the ioctl returns +.Er EBUSY . +.It Dv DIOCGETSRCNODES Fa "struct pfioc_src_nodes *psn" .Bd -literal struct pfioc_src_nodes { - int psn_len; - union { - caddr_t psu_buf; - struct pf_src_node *psu_src_nodes; - } psn_u; -#define psn_buf psn_u.psu_buf -#define psn_src_nodes psn_u.psu_src_nodes + int psn_len; + union { + caddr_t psu_buf; + struct pf_src_node *psu_src_nodes; + } psn_u; +#define psn_buf psn_u.psu_buf +#define psn_src_nodes psn_u.psu_src_nodes }; .Ed .Pp -Get the list of source nodes kept by the -.Ar sticky-address -and -.Ar source-track -options. +Get the list of source nodes kept by sticky addresses and source +tracking. The ioctl must be called once with .Va psn_len set to 0. @@ -681,24 +936,24 @@ placed in .Va psn_buf . The ioctl must then be called again to fill this buffer with the actual source node data. -After the ioctl call +After that call, .Va psn_len will be set to the length of the buffer actually used. -.It Dv DIOCCLRSRCNODES Fa "struct pfioc_table" +.It Dv DIOCCLRSRCNODES Clear the tree of source tracking nodes. -.It Dv DIOCIGETIFACES Fa "struct pfioc_iface" -Gets the list of interfaces and interface drivers known to +.It Dv DIOCIGETIFACES Fa "struct pfioc_iface *io" +Get the list of interfaces and interface drivers known to .Nm . -All the IOCTLs that manipulate interfaces +All the ioctls that manipulate interfaces use the same structure described below: .Bd -literal struct pfioc_iface { - char pfiio_name[IFNAMSIZ]; - void *pfiio_buffer; - int pfiio_esize; - int pfiio_size; - int pfiio_nzero; - int pfiio_flags; + char pfiio_name[IFNAMSIZ]; + void *pfiio_buffer; + int pfiio_esize; + int pfiio_size; + int pfiio_nzero; + int pfiio_flags; }; #define PFI_FLAG_GROUP 0x0001 /* gets groups of interfaces */ @@ -719,50 +974,70 @@ entries that can fit into the buffer. The kernel will replace this value by the real number of entries it wants to return. .Va pfiio_esize -should be set to sizeof(struct pfi_if). +should be set to +.Li sizeof(struct pfi_if) . .Va pfiio_flags should be set to -.Dv PFI_FLAG_GROUP , PFI_FLAG_INSTANCE , -or both to tell the kernel to return a group of interfaces +.Dv PFI_FLAG_GROUP , +.Dv PFI_FLAG_INSTANCE , +or both, to tell the kernel to return a group of interfaces (drivers, like "fxp"), real interface instances (like "fxp1") or both. The data is returned in the -.Va pfi_if +.Vt pfi_if structure described below: .Bd -literal struct pfi_if { - char pfif_name[IFNAMSIZ]; - u_int64_t pfif_packets[2][2][2]; - u_int64_t pfif_bytes[2][2][2]; - u_int64_t pfif_addcnt; - u_int64_t pfif_delcnt; - long pfif_tzero; - int pfif_states; - int pfif_rules; - int pfif_flags; + char pfif_name[IFNAMSIZ]; + u_int64_t pfif_packets[2][2][2]; + u_int64_t pfif_bytes[2][2][2]; + u_int64_t pfif_addcnt; + u_int64_t pfif_delcnt; + long pfif_tzero; + int pfif_states; + int pfif_rules; + int pfif_flags; }; -#define PFI_IFLAG_GROUP 0x0001 /* group of interfaces */ -#define PFI_IFLAG_INSTANCE 0x0002 /* single instance */ -#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */ -#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */ -#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */ -#define PFI_IFLAG_REFERENCED 0x0080 /* referenced by rules */ +#define PFI_IFLAG_GROUP 0x0001 /* group of interfaces */ +#define PFI_IFLAG_INSTANCE 0x0002 /* single instance */ +#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */ +#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */ +#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */ .Ed -.It Dv DIOCICLRISTATS Fa "struct pfioc_iface" +.It Dv DIOCICLRISTATS Fa "struct pfioc_iface *io" Clear the statistics counters of one or more interfaces. .Va pfiio_name and -.Va pfrio_flags +.Va pfiio_flags can be used to select which interfaces need to be cleared. The filtering process is the same as for .Dv DIOCIGETIFACES . .Va pfiio_nzero will be set by the kernel to the number of interfaces and drivers that have been cleared. +.It Dv DIOCSETIFFLAG Fa "struct pfioc_iface *io" +Set the user setable flags (described below) of the pf internal interface +description. +The filtering process is the same as for +.Dv DIOCIGETIFACES . +.Bd -literal +#define PFI_IFLAG_SKIP 0x0100 /* skip interface */ +#define PFI_IFLAG_SETABLE_MASK 0x0100 /* mask */ +.Ed +.It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io" +Works as +.Dv DIOCSETIFFLAG +above but clears the flags. +.El +.Sh FILES +.Bl -tag -width /dev/pf -compact +.It Pa /dev/pf +packet filtering device. .El .Sh EXAMPLES -The following example demonstrates how to use the DIOCNATLOOK command -to find the internal host/port of a NATed connection. +The following example demonstrates how to use the +.Dv DIOCNATLOOK +command to find the internal host/port of a NATed connection: .Bd -literal #include #include @@ -832,7 +1107,8 @@ main(int argc, char *argv[]) .Xr bridge 4 , .Xr pflog 4 , .Xr pfsync 4 , -.Xr pfctl 8 +.Xr pfctl 8 , +.Xr altq 9 .Sh HISTORY The .Nm diff --git a/contrib/pf/man/pf.conf.5 b/contrib/pf/man/pf.conf.5 index cbe3b52..d7d5d82 100644 --- a/contrib/pf/man/pf.conf.5 +++ b/contrib/pf/man/pf.conf.5 @@ -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 +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