This allows to do so magically twisted things like running ftp-proxy in
rdomain 7 and proxy connections from rdomain 3 over it.

pf setup is:
anchor "ftp-proxy/*"
pass in quick proto tcp to port ftp rtable 7 rdr-to 127.0.0.1 port 8021

and ftp-proxy is startet with
route -T 7 exec ftp-proxy

The rules added by ftp proxy will add the needed "rtable" statements to
the rules (but I left them out in the man page to not confuse people even
more).

Normal operation should not be affected.
This needs a kernel with the DIOCNATLOOK diff applied.
-- 
:wq Claudio


Index: filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/ftp-proxy/filter.c,v
retrieving revision 1.13
diff -u -p -r1.13 filter.c
--- filter.c    13 Jan 2010 01:07:34 -0000      1.13
+++ filter.c    24 Mar 2011 18:59:04 -0000
@@ -43,9 +43,9 @@ int add_addr(struct sockaddr *, struct p
 int prepare_rule(u_int32_t, struct sockaddr *, struct sockaddr *,
     u_int16_t);
 int server_lookup4(struct sockaddr_in *, struct sockaddr_in *,
-    struct sockaddr_in *);
+    struct sockaddr_in *, int *);
 int server_lookup6(struct sockaddr_in6 *, struct sockaddr_in6 *,
-    struct sockaddr_in6 *);
+    struct sockaddr_in6 *, int *);
 
 static struct pfioc_rule       pfr;
 static struct pfioc_trans      pft;
@@ -70,7 +70,7 @@ add_addr(struct sockaddr *addr, struct p
 }
 
 int
-add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
+add_nat(u_int32_t id, struct sockaddr *src, int s_rd, struct sockaddr *dst,
     u_int16_t d_port, struct sockaddr *nat, u_int16_t nat_range_low,
     u_int16_t nat_range_high)
 {
@@ -87,6 +87,8 @@ add_nat(u_int32_t id, struct sockaddr *s
                return (-1);
 
        pfr.rule.direction = PF_OUT;
+       /* XXX limit the source routing domain */
+       pfr.rule.rtableid = -1;
        pfr.rule.nat.proxy_port[0] = nat_range_low;
        pfr.rule.nat.proxy_port[1] = nat_range_high;
        if (ioctl(dev, DIOCADDRULE, &pfr) == -1)
@@ -96,8 +98,8 @@ add_nat(u_int32_t id, struct sockaddr *s
 }
 
 int
-add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
-    u_int16_t d_port, struct sockaddr *rdr, u_int16_t rdr_port)
+add_rdr(u_int32_t id, struct sockaddr *src, int s_rd, struct sockaddr *dst,
+    u_int16_t d_port, struct sockaddr *rdr, u_int16_t rdr_port, int d_rd)
 {
        if (!src || !dst || !d_port || !rdr || !rdr_port ||
            (src->sa_family != rdr->sa_family)) {
@@ -112,6 +114,8 @@ add_rdr(u_int32_t id, struct sockaddr *s
                return (-1);
 
        pfr.rule.direction = PF_IN;
+       /* XXX limit the source routing domain */
+       pfr.rule.rtableid = d_rd;
        pfr.rule.rdr.proxy_port[0] = rdr_port;
        if (ioctl(dev, DIOCADDRULE, &pfr) == -1)
                return (-1);
@@ -254,15 +258,15 @@ prepare_rule(u_int32_t id, struct sockad
 
 int
 server_lookup(struct sockaddr *client, struct sockaddr *proxy,
-    struct sockaddr *server)
+    struct sockaddr *server, int *cdomain)
 {
        if (client->sa_family == AF_INET)
                return (server_lookup4(satosin(client), satosin(proxy),
-                   satosin(server)));
+                   satosin(server), cdomain));
        
        if (client->sa_family == AF_INET6)
                return (server_lookup6(satosin6(client), satosin6(proxy),
-                   satosin6(server)));
+                   satosin6(server), cdomain));
 
        errno = EPROTONOSUPPORT;
        return (-1);
@@ -270,7 +274,7 @@ server_lookup(struct sockaddr *client, s
 
 int
 server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy,
-    struct sockaddr_in *server)
+    struct sockaddr_in *server, int *cdomain)
 {
        struct pfioc_natlook pnl;
 
@@ -278,6 +282,7 @@ server_lookup4(struct sockaddr_in *clien
        pnl.direction = PF_OUT;
        pnl.af = AF_INET;
        pnl.proto = IPPROTO_TCP;
+       pnl.rdomain = getrtable();
        memcpy(&pnl.saddr.v4, &client->sin_addr.s_addr, sizeof pnl.saddr.v4);
        memcpy(&pnl.daddr.v4, &proxy->sin_addr.s_addr, sizeof pnl.daddr.v4);
        pnl.sport = client->sin_port;
@@ -292,13 +297,14 @@ server_lookup4(struct sockaddr_in *clien
        memcpy(&server->sin_addr.s_addr, &pnl.rdaddr.v4,
            sizeof server->sin_addr.s_addr);
        server->sin_port = pnl.rdport;
-               
+       *cdomain = pnl.rrdomain;
+
        return (0);
 }
 
 int
 server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy,
-    struct sockaddr_in6 *server)
+    struct sockaddr_in6 *server, int *cdomain)
 {
        struct pfioc_natlook pnl;
 
@@ -306,6 +312,7 @@ server_lookup6(struct sockaddr_in6 *clie
        pnl.direction = PF_OUT;
        pnl.af = AF_INET6;
        pnl.proto = IPPROTO_TCP;
+       pnl.rdomain = getrtable();
        memcpy(&pnl.saddr.v6, &client->sin6_addr.s6_addr, sizeof pnl.saddr.v6);
        memcpy(&pnl.daddr.v6, &proxy->sin6_addr.s6_addr, sizeof pnl.daddr.v6);
        pnl.sport = client->sin6_port;
@@ -320,6 +327,7 @@ server_lookup6(struct sockaddr_in6 *clie
        memcpy(&server->sin6_addr.s6_addr, &pnl.rdaddr.v6,
            sizeof server->sin6_addr);
        server->sin6_port = pnl.rdport;
+       *cdomain = pnl.rrdomain;
 
        return (0);
 }
Index: filter.h
===================================================================
RCS file: /cvs/src/usr.sbin/ftp-proxy/filter.h,v
retrieving revision 1.5
diff -u -p -r1.5 filter.h
--- filter.h    1 Sep 2009 13:46:14 -0000       1.5
+++ filter.h    24 Mar 2011 17:12:35 -0000
@@ -18,12 +18,13 @@
 
 #define        FTP_PROXY_ANCHOR "ftp-proxy"
 
-int add_nat(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
+int add_nat(u_int32_t, struct sockaddr *, int, struct sockaddr *, u_int16_t,
     struct sockaddr *, u_int16_t, u_int16_t);
-int add_rdr(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
-    struct sockaddr *, u_int16_t);
+int add_rdr(u_int32_t, struct sockaddr *, int, struct sockaddr *, u_int16_t,
+    struct sockaddr *, u_int16_t, int);
 int do_commit(void);
 int do_rollback(void);
 void init_filter(char *, char *, int);
 int prepare_commit(u_int32_t);
-int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *);
+int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *,
+    int *);
Index: ftp-proxy.c
===================================================================
RCS file: /cvs/src/usr.sbin/ftp-proxy/ftp-proxy.c,v
retrieving revision 1.20
diff -u -p -r1.20 ftp-proxy.c
--- ftp-proxy.c 1 Sep 2009 13:46:14 -0000       1.20
+++ ftp-proxy.c 24 Mar 2011 21:11:35 -0000
@@ -77,6 +77,7 @@ struct session {
        char                     sbuf[MAX_LINE];
        size_t                   sbuf_valid;
        int                      cmd;
+       int                      client_rd;
        u_int16_t                port;
        u_int16_t                proxy_port;
        LIST_ENTRY(session)      entry;
@@ -427,7 +428,8 @@ handle_connection(const int listen_fd, s
                    strerror(errno));
                goto fail;
        }
-       if (server_lookup(client_sa, client_to_proxy_sa, server_sa) != 0) {
+       if (server_lookup(client_sa, client_to_proxy_sa, server_sa,
+           &s->client_rd) != 0) {
                logmsg(LOG_CRIT, "#%d server lookup failed (no rdr?)", s->id);
                goto fail;
        }
@@ -477,7 +479,7 @@ handle_connection(const int listen_fd, s
        }
 
        logmsg(LOG_INFO, "#%d FTP session %d/%d started: client %s to server "
-           "%s via proxy %s ", s->id, session_count, max_sessions,
+           "%s via proxy %s", s->id, session_count, max_sessions,
            sock_ntop(client_sa), sock_ntop(server_sa),
            sock_ntop(proxy_to_server_sa));
 
@@ -973,13 +975,14 @@ allow_data_connection(struct session *s)
 
                /* pass in from $client to $orig_server port $proxy_port
                    rdr-to $server port $port */
-               if (add_rdr(s->id, client_sa, orig_sa, s->proxy_port,
-                   server_sa, s->port) == -1)
+               if (add_rdr(s->id, client_sa, s->client_rd, orig_sa,
+                   s->proxy_port, server_sa, s->port, getrtable()) == -1)
                        goto fail;
 
                /* pass out from $client to $server port $port nat-to $proxy */
-               if (add_nat(s->id, client_sa, server_sa, s->port, proxy_sa,
-                   PF_NAT_PROXY_PORT_LOW, PF_NAT_PROXY_PORT_HIGH) == -1)
+               if (add_nat(s->id, client_sa, getrtable(), server_sa,
+                   s->port, proxy_sa, PF_NAT_PROXY_PORT_LOW,
+                   PF_NAT_PROXY_PORT_HIGH) == -1)
                        goto fail;
        }
 
@@ -994,21 +997,21 @@ allow_data_connection(struct session *s)
 
                /* pass in from $server to $proxy port $proxy_port
                    rdr-to $client port $port */
-               if (add_rdr(s->id, server_sa, proxy_sa, s->proxy_port,
-                   client_sa, s->port) == -1)
+               if (add_rdr(s->id, server_sa, getrtable(), proxy_sa,
+                   s->proxy_port, client_sa, s->port, s->client_rd) == -1)
                        goto fail;
 
                /* pass out from $server to $client port $port
                    nat-to $orig_server port $natport */
                if (rfc_mode && s->cmd == CMD_PORT) {
                        /* Rewrite sourceport to RFC mandated 20. */
-                       if (add_nat(s->id, server_sa, client_sa, s->port,
-                           orig_sa, 20, 20) == -1)
+                       if (add_nat(s->id, server_sa, s->client_rd, client_sa,
+                           s->port, orig_sa, 20, 20) == -1)
                                goto fail;
                } else {
                        /* Let pf pick a source port from the standard range. */
-                       if (add_nat(s->id, server_sa, client_sa, s->port,
-                           orig_sa, PF_NAT_PROXY_PORT_LOW,
+                       if (add_nat(s->id, server_sa, s->client_rd, client_sa,
+                           s->port, orig_sa, PF_NAT_PROXY_PORT_LOW,
                            PF_NAT_PROXY_PORT_HIGH) == -1)
                                goto fail;
                }

Reply via email to