this allows us to get rid of the nasty NATLOOKUP ioctl and get
the original server address right from the socket.  also this
paves the way to the transparent ftp-proxy mode.

if you will like this diff and nobody objects, i'll try to rip
NATLOOKUP out from the other places too.

note, that it requires you to change your rdr-to rule to do
divert:

 -pass in quick proto tcp to port ftp rdr-to 127.0.0.1 port 8021
 +pass in quick proto tcp to port ftp divert-to 127.0.0.1 port 8021


Index: filter.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/ftp-proxy/filter.c,v
retrieving revision 1.14
diff -u -p -r1.14 filter.c
--- filter.c    25 Mar 2011 14:51:31 -0000      1.14
+++ filter.c    7 Apr 2011 16:31:30 -0000
@@ -42,10 +42,6 @@
 int add_addr(struct sockaddr *, struct pf_pool *);
 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 *, int *);
-int server_lookup6(struct sockaddr_in6 *, struct sockaddr_in6 *,
-    struct sockaddr_in6 *, int *);
 
 static struct pfioc_rule       pfr;
 static struct pfioc_trans      pft;
@@ -252,82 +248,6 @@ prepare_rule(u_int32_t id, struct sockad
                strlcpy(pfr.rule.tagname, tagname,
                                sizeof pfr.rule.tagname);
        }
-
-       return (0);
-}
-
-int
-server_lookup(struct sockaddr *client, struct sockaddr *proxy,
-    struct sockaddr *server, int *cdomain)
-{
-       if (client->sa_family == AF_INET)
-               return (server_lookup4(satosin(client), satosin(proxy),
-                   satosin(server), cdomain));
-       
-       if (client->sa_family == AF_INET6)
-               return (server_lookup6(satosin6(client), satosin6(proxy),
-                   satosin6(server), cdomain));
-
-       errno = EPROTONOSUPPORT;
-       return (-1);
-}
-
-int
-server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy,
-    struct sockaddr_in *server, int *cdomain)
-{
-       struct pfioc_natlook pnl;
-
-       memset(&pnl, 0, sizeof pnl);
-       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;
-       pnl.dport = proxy->sin_port;
-       
-       if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
-               return (-1);
-
-       memset(server, 0, sizeof(struct sockaddr_in));
-       server->sin_len = sizeof(struct sockaddr_in);
-       server->sin_family = AF_INET;
-       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, int *cdomain)
-{
-       struct pfioc_natlook pnl;
-
-       memset(&pnl, 0, sizeof pnl);
-       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;
-       pnl.dport = proxy->sin6_port;
-       
-       if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
-               return (-1);
-
-       memset(server, 0, sizeof(struct sockaddr_in6));
-       server->sin6_len = sizeof(struct sockaddr_in6);
-       server->sin6_family = AF_INET6;
-       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: /home/cvs/src/usr.sbin/ftp-proxy/filter.h,v
retrieving revision 1.6
diff -u -p -r1.6 filter.h
--- filter.h    25 Mar 2011 14:51:31 -0000      1.6
+++ filter.h    7 Apr 2011 16:31:38 -0000
@@ -26,5 +26,3 @@ 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 *);
Index: ftp-proxy.8
===================================================================
RCS file: /home/cvs/src/usr.sbin/ftp-proxy/ftp-proxy.8,v
retrieving revision 1.14
diff -u -p -r1.14 ftp-proxy.8
--- ftp-proxy.8 21 Nov 2009 13:59:31 -0000      1.14
+++ ftp-proxy.8 7 Apr 2011 16:49:56 -0000
@@ -40,7 +40,7 @@
 is a proxy for the Internet File Transfer Protocol.
 FTP control connections should be redirected into the proxy using the
 .Xr pf 4
-.Ar rdr-to
+.Ar divert-to
 command, after which the proxy connects to the server on behalf of
 the client.
 .Pp
@@ -169,7 +169,7 @@ needs the following rules.
 Adjust the rules as needed.
 .Bd -literal -offset 2n
 anchor "ftp-proxy/*"
-pass in quick proto tcp to port ftp rdr-to 127.0.0.1 port 8021
+pass in quick proto tcp to port ftp divert-to 127.0.0.1 port 8021
 .Ed
 .Sh SEE ALSO
 .Xr ftp 1 ,
Index: ftp-proxy.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/ftp-proxy/ftp-proxy.c,v
retrieving revision 1.21
diff -u -p -r1.21 ftp-proxy.c
--- ftp-proxy.c 25 Mar 2011 14:51:31 -0000      1.21
+++ ftp-proxy.c 7 Apr 2011 16:47:06 -0000
@@ -423,14 +423,22 @@ handle_connection(const int listen_fd, s
         * Find out the real server and port that the client wanted.
         */
        len = sizeof(struct sockaddr_storage);
-       if ((getsockname(s->client_fd, client_to_proxy_sa, &len)) < 0) {
+       if ((getsockname(s->client_fd, server_sa, &len)) < 0) {
                logmsg(LOG_CRIT, "#%d getsockname failed: %s", s->id,
                    strerror(errno));
                goto fail;
        }
-       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);
+       len = sizeof(struct sockaddr_storage);
+       if (getpeername(s->client_fd, client_to_proxy_sa, &len) < 0) {
+               logmsg(LOG_CRIT, "#%d getpeername failed: %s", s->id,
+                   strerror(errno));
+               goto fail;
+       }
+       len = sizeof(s->client_rd);
+       if (getsockopt(s->client_fd, SOL_SOCKET, SO_RTABLE, &s->client_rd,
+           &len)) {
+               logmsg(LOG_CRIT, "#%d getsockopt failed: %s", s->id,
+                   strerror(errno));
                goto fail;
        }
        if (fixed_server) {

Reply via email to