>Number:         148686
>Category:       bin
>Synopsis:       ftp-proxy -T tag patch for FBSD
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jul 16 16:10:07 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Mario Lobo
>Release:        8.1-PRERELEASE
>Organization:
>Environment:
FreeBSD Papi 8.1-PRERELEASE FreeBSD 8.1-PRERELEASE #0: Sat Jul  3 13:06:10 UTC 
2010     r...@papi:/usr/src/sys/amd64/compile/LOBO  amd64
>Description:
I felt sorry the -T tag option was present in Linux and not on FBSD because I 
got to a situation where it would really be useful for me. So I decided to 
stuff my hands on the grease can.

What this does is to give the option to put a tag instead of a queue, to the 
dynamic rules that ftp-proxy creates on the fly. The option to put a queue is 
nice but it confines the rule to THAT queue only, and you cannot create queues 
with the same name on different interfaces. You could specify 2 interfaces on 
the same altq rule, but then again, both interfaces will be confined to the 
same queue tunings.

The -T "tag" option  however, besides tagging the packets for the rule, takes 
the "quick" keyword out of it, so rule processing can continue, to later find 
a rule that has the keyword "tagged tag", and be sent to any queue you want. A 
really welcomed flexibility.

The lines bellow were taken during an ftp session to ftp.openbsd.com from a 
LAN client station.

================================
# Server [20:14:03]
[~]>pfctl -vv -sA
  ftp-proxy
  ftp-proxy/15780.1

# Server [20:15:01]
[~]> pfctl -vv -a ftp-proxy/15780.1 -sr
@0 pass in log inet proto tcp from 172.16.3.145 to 129.128.5.191 port = 61076 
flags S/SA keep state (max 1) tag ftp_proxy rtable 0
  [ Evaluations: 4         Packets: 0         Bytes: 0           States: 0     
]
  [ Inserted: uid 62 pid 15780 ]
@1 pass out log inet proto tcp from 189.12.120.67 to 129.128.5.191 port = 
61076 flags S/SA keep state (max 1) tag ftp_proxy rtable 0
  [ Evaluations: 4         Packets: 0         Bytes: 0           States: 0     
]
  [ Inserted: uid 62 pid 15780 ]

# Server [20:15:11]
[~]>pfctl -vv -sA
  ftp-proxy
  ftp-proxy/15780.1

# Server [20:15:16]
[~]> pfctl -vv -a ftp-proxy/15780.1 -sn
@0 nat inet proto tcp from 172.16.3.145 to 129.128.5.191 port = 61076 rtable 0 
-> 189.12.120.67
  [ Evaluations: 1         Packets: 0         Bytes: 0           States: 0     
]
  [ Inserted: uid 62 pid 15780 ]
@0 rdr inet proto tcp from 172.16.3.145 to 129.128.5.191 port = 51973 rtable 0 
-> 129.128.5.191 port 61076
  [ Evaluations: 6         Packets: 8         Bytes: 1485        States: 0     
]
  [ Inserted: uid 62 pid 15780 ]

# Server [20:15:23]
[~]> pfctl -vv -a ftp-proxy/15780.1 -sn
pfctl: DIOCGETRULES: Invalid argument

# Server [20:16:12]
[~]>pfctl -vv -sA
  ftp-proxy

================================
The nat, rdr and pass rules are correctly created and tagged.
Observe the times to see that ftp-proxy removes the rule really fast.

To apply the patch, copy it to 
/usr/src/contrib/pf/ftp-proxy/
then,
cd /usr/src/usr.sbin/ftp-proxy/ftp-proxy

make [clean]
make install
>How-To-Repeat:
NA
>Fix:


Patch attached with submission follows:

--- 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 .


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to