On Thu, Apr 07, 2011 at 18:58 +0200, Mike Belopuhov wrote:
> 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
> 
> 

new version.  correct operation with rdomains requires the divert-to
rdomain diff.

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:52:05 -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 8 Apr 2011 10:29:57 -0000
@@ -423,14 +423,23 @@ 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 (client_to_proxy_sa->sa_family == AF_INET &&
+           getsockopt(s->client_fd, IPPROTO_IP, 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