--- ftp-proxy.c.orig 2009-08-03 08:13:06.000000000 +0000 +++ ftp-proxy.c 2010-07-13 12:56:07.000000000 +0000 @@ -116,7 +116,7 @@ struct sockaddr_storage fixed_server_ss, fixed_proxy_ss; char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port, - *qname; + *qname, *tname; int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions, rfc_mode, session_count, timeout, verbose; extern char *__progname; @@ -601,6 +601,7 @@ loglevel = LOG_NOTICE; max_sessions = 100; qname = NULL; + tname = NULL; rfc_mode = 0; timeout = 24 * 3600; verbose = 0; @@ -609,7 +610,7 @@ id_count = 1; session_count = 0; - while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rt:v")) != -1) { + while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rt:T:v")) != -1) { switch (ch) { case '6': ipv6_mode = 1; @@ -647,8 +648,9 @@ if (strlen(optarg) >= PF_QNAME_SIZE) errx(1, "queuename too long"); qname = optarg; + tname = NULL; break; - case 'R': + case 'R': fixed_server = optarg; break; case 'r': @@ -659,6 +661,12 @@ if (errstr) errx(1, "timeout %s", errstr); break; + case 'T': + if (strlen(optarg) >= PF_TAG_NAME_SIZE) + errx(1, "tagname too long"); + tname = optarg; + qname = NULL; + break; case 'v': verbose++; if (verbose > 2) @@ -734,7 +742,8 @@ freeaddrinfo(res); /* Initialize pf. */ - init_filter(qname, verbose); + init_filter_q(qname, verbose); + init_filter_t(tname, verbose); if (daemonize) { if (daemon(0, 0) == -1) @@ -1102,6 +1111,6 @@ { fprintf(stderr, "usage: %s [-6Adrv] [-a address] [-b address]" " [-D level] [-m maxsessions]\n [-P port]" - " [-p port] [-q queue] [-R address] [-t timeout]\n", __progname); + " [-p port] [-q queue] [-R address] [-t timeout] [-T tag]\n", __progname); exit(1); } --- filter.c.orig 2007-07-03 12:21:51.000000000 +0000 +++ filter.c 2010-07-13 05:57:20.000000000 +0000 @@ -54,6 +54,7 @@ static struct pfioc_trans_e pfte[TRANS_SIZE]; static int dev, rule_log; static char *qname; +static char *tname; int add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src, @@ -159,7 +160,7 @@ } void -init_filter(char *opt_qname, int opt_verbose) +init_filter_q(char *opt_qname, int opt_verbose) { struct pf_status status; @@ -179,6 +180,28 @@ errx(1, "pf is disabled"); } +void +init_filter_t(char *opt_tname, int opt_verbose) +{ + struct pf_status status; + + tname = opt_tname; + + if (opt_verbose == 1) + rule_log = PF_LOG; + else if (opt_verbose == 2) + rule_log = PF_LOG_ALL; + + dev = open("/dev/pf", O_RDWR); + if (dev == -1) + err(1, "/dev/pf"); + if (ioctl(dev, DIOCGETSTATUS, &status) == -1) + err(1, "DIOCGETSTATUS"); + if (!status.running) + errx(1, "pf is disabled"); +} + + int prepare_commit(u_int32_t id) { @@ -279,20 +302,29 @@ switch (rs_num) { case PF_RULESET_FILTER: - /* - * pass quick [log] inet[6] proto tcp \ - * from $src to $dst port = $d_port flags S/SA keep state - * (max 1) [queue qname] - */ - pfr.rule.action = PF_PASS; - pfr.rule.quick = 1; - pfr.rule.log = rule_log; - pfr.rule.keep_state = 1; - pfr.rule.flags = TH_SYN; - pfr.rule.flagset = (TH_SYN|TH_ACK); - pfr.rule.max_states = 1; - if (qname != NULL) - strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname); + + /* + * pass quick [log] inet[6] proto tcp \ + * from $src to $dst port = $d_port flags S/SA keep state + * (max 1) [queue qname] + */ + + pfr.rule.action = PF_PASS; + pfr.rule.log = rule_log; + pfr.rule.keep_state = 1; + pfr.rule.flags = TH_SYN; + pfr.rule.flagset = (TH_SYN|TH_ACK); + pfr.rule.max_states = 1; + pfr.rule.quick = 1; + + if (qname != NULL) { + strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname); + } else { + if (tname != NULL) { + pfr.rule.quick = 0; + strlcpy(pfr.rule.tagname, tname, sizeof pfr.rule.tagname); + } + } break; case PF_RULESET_NAT: /* --- filter.h.orig 2007-07-03 12:21:50.000000000 +0000 +++ filter.h 2010-07-13 05:25:52.000000000 +0000 @@ -26,6 +26,7 @@ struct sockaddr *, u_int16_t); int do_commit(void); int do_rollback(void); -void init_filter(char *, int); +void init_filter_q(char *, int); +void init_filter_t(char *, int); int prepare_commit(u_int32_t); int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *); --- ftp-proxy.8.orig 2009-08-03 08:13:06.000000000 +0000 +++ ftp-proxy.8 2010-07-13 13:22:58.000000000 +0000 @@ -120,7 +120,9 @@ .It Fl q Ar queue Create rules with queue .Ar queue -appended, so that data connections can be queued. +appended, so that data connections can be queued. The -T option +is automatically cancelled. If -T and -q are both present, the +last on the command line prevails. .It Fl R Ar address Fixed server address, also known as reverse mode. The proxy will always connect to the same server, regardless of @@ -136,6 +138,12 @@ The maximum is 86400 seconds, which is also the default. Do not set this too low, because the control connection is usually idle when large data transfers are taking place. +.It Fl T Ar tag +The filter rules will add tag +.Ar tag +to data connections, and not match quick. This way, alternative rules +that use the tagged keyword can be implemented. The -q option is +is automatically cancelled. .It Fl v Set the 'log' flag on pf rules committed by .Nm .