On Mon, Apr 11, 2011 at 16:59 +0200, Mike Belopuhov wrote:
> 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.
>
as the divert-to rdomain diff is in, i'm looking for OKs for this one.
> 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) {