diff options
| author | 2011-05-05 12:25:51 +0000 | |
|---|---|---|
| committer | 2011-05-05 12:25:51 +0000 | |
| commit | 31330dd0376dd9de584ec5a74ad766838f050db7 (patch) | |
| tree | 782a3158c4a9267333d2613380d7502f085bdc22 /libexec/tftp-proxy | |
| parent | rename iked_proc* to privsep_proc*. no functional change. (diff) | |
| download | wireguard-openbsd-31330dd0376dd9de584ec5a74ad766838f050db7.tar.xz wireguard-openbsd-31330dd0376dd9de584ec5a74ad766838f050db7.zip | |
Switch tftp-proxy over to using divert-to. Based on a diff from oga@
with lots of help from claudio@. Earlier version was ok mikeb@ and looks
good to markus@.
Note: tftp-proxy rdr-to rules must be changed to use divert-to and must
specify the address family.
pass in quick on internal proto udp to port tftp rdr-to 127.0.0.1 port 6969
-changes to-
pass in quick on internal inet proto udp to port tftp divert-to 127.0.0.1 port 6969
Diffstat (limited to 'libexec/tftp-proxy')
| -rw-r--r-- | libexec/tftp-proxy/filter.c | 78 | ||||
| -rw-r--r-- | libexec/tftp-proxy/filter.h | 4 | ||||
| -rw-r--r-- | libexec/tftp-proxy/tftp-proxy.8 | 10 | ||||
| -rw-r--r-- | libexec/tftp-proxy/tftp-proxy.c | 97 |
4 files changed, 28 insertions, 161 deletions
diff --git a/libexec/tftp-proxy/filter.c b/libexec/tftp-proxy/filter.c index e9ca970638f..91752d4b771 100644 --- a/libexec/tftp-proxy/filter.c +++ b/libexec/tftp-proxy/filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: filter.c,v 1.8 2010/01/13 01:08:14 claudio Exp $ */ +/* $OpenBSD: filter.c,v 1.9 2011/05/05 12:25:51 sthen Exp $ */ /* * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> @@ -46,10 +46,6 @@ enum { TRANS_FILTER = 0, TRANS_NAT, TRANS_RDR, TRANS_SIZE }; int prepare_rule(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t, u_int8_t); -int server_lookup4(struct sockaddr_in *, struct sockaddr_in *, - struct sockaddr_in *, u_int8_t); -int server_lookup6(struct sockaddr_in6 *, struct sockaddr_in6 *, - struct sockaddr_in6 *, u_int8_t); static struct pfioc_rule pfr; static struct pfioc_trans pft; @@ -231,75 +227,3 @@ prepare_rule(u_int32_t id, struct sockaddr *src, return (0); } - -int -server_lookup(struct sockaddr *client, struct sockaddr *proxy, - struct sockaddr *server, u_int8_t proto) -{ - if (client->sa_family == AF_INET) - return (server_lookup4(satosin(client), satosin(proxy), - satosin(server), proto)); - - if (client->sa_family == AF_INET6) - return (server_lookup6(satosin6(client), satosin6(proxy), - satosin6(server), proto)); - - errno = EPROTONOSUPPORT; - return (-1); -} - -int -server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy, - struct sockaddr_in *server, u_int8_t proto) -{ - struct pfioc_natlook pnl; - - memset(&pnl, 0, sizeof pnl); - pnl.direction = PF_OUT; - pnl.af = AF_INET; - pnl.proto = proto; - 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; - - return (0); -} - -int -server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy, - struct sockaddr_in6 *server, u_int8_t proto) -{ - struct pfioc_natlook pnl; - - memset(&pnl, 0, sizeof pnl); - pnl.direction = PF_OUT; - pnl.af = AF_INET6; - pnl.proto = proto; - 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; - - return (0); -} diff --git a/libexec/tftp-proxy/filter.h b/libexec/tftp-proxy/filter.h index bc0e6081f8d..0214b76fe0c 100644 --- a/libexec/tftp-proxy/filter.h +++ b/libexec/tftp-proxy/filter.h @@ -1,4 +1,4 @@ -/* $OpenBSD: filter.h,v 1.2 2009/07/30 20:40:27 sthen Exp $ */ +/* $OpenBSD: filter.h,v 1.3 2011/05/05 12:25:51 sthen Exp $ */ /* * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> @@ -26,5 +26,3 @@ int do_commit(void); int do_rollback(void); void init_filter(char *, int); int prepare_commit(u_int32_t); -int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *, - u_int8_t); diff --git a/libexec/tftp-proxy/tftp-proxy.8 b/libexec/tftp-proxy/tftp-proxy.8 index 3e508f5076a..1d7afaf888f 100644 --- a/libexec/tftp-proxy/tftp-proxy.8 +++ b/libexec/tftp-proxy/tftp-proxy.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tftp-proxy.8,v 1.3 2009/09/01 14:15:57 sthen Exp $ +.\" $OpenBSD: tftp-proxy.8,v 1.4 2011/05/05 12:25:51 sthen Exp $ .\" .\" Copyright (c) 2005 joshua stein <jcs@openbsd.org> .\" @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: September 1 2009 $ +.Dd $Mdocdate: May 5 2011 $ .Dt TFTP-PROXY 8 .Os .Sh NAME @@ -44,7 +44,7 @@ internet server. TFTP connections should be redirected to the proxy using a .Xr pf 4 rule using the -.Ar rdr-to +.Ar divert-to option, after which the proxy connects to the server on behalf of the client. .Pp @@ -95,8 +95,8 @@ The anchor is mandatory. Adjust the rule as needed for your configuration. .Bd -literal -offset indent anchor "tftp-proxy/*" -pass in quick on $int_if proto udp from $lan to any port tftp \e - rdr-to 127.0.0.1 port 6969 +pass in quick on $int_if inet proto udp from $lan to any port tftp \e + divert-to 127.0.0.1 port 6969 .Ed .Pp .Xr inetd 8 diff --git a/libexec/tftp-proxy/tftp-proxy.c b/libexec/tftp-proxy/tftp-proxy.c index d2d2875717a..bf592e7d1db 100644 --- a/libexec/tftp-proxy/tftp-proxy.c +++ b/libexec/tftp-proxy/tftp-proxy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tftp-proxy.c,v 1.6 2008/04/13 00:22:17 djm Exp $ +/* $OpenBSD: tftp-proxy.c,v 1.7 2011/05/05 12:25:51 sthen Exp $ * * Copyright (c) 2005 DLS Internet Services * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> @@ -60,7 +60,6 @@ const char *opcode(int); const char *sock_ntop(struct sockaddr *); -u_int16_t pick_proxy_port(void); static void usage(void); extern char *__progname; @@ -70,24 +69,23 @@ int verbose = 0; int main(int argc, char *argv[]) { - int c, fd = 0, on = 1, out_fd = 0, peer, reqsize = 0; + int c, fd = 0, on = 1, out_fd = 0, reqsize = 0; int transwait = DEFTRANSWAIT; char *p; struct tftphdr *tp; struct passwd *pw; union { struct cmsghdr hdr; - char buf[CMSG_SPACE(sizeof(struct sockaddr_storage))]; + char buf[CMSG_SPACE(sizeof(struct sockaddr_storage)) + + CMSG_SPACE(sizeof(in_port_t))]; } cmsgbuf; char req[PKTSIZE]; struct cmsghdr *cmsg; struct msghdr msg; struct iovec iov; - struct sockaddr_storage from, proxy, server, proxy_to_server, s_in; - struct sockaddr_in sock_out; + struct sockaddr_storage from, server, proxy_to_server; socklen_t j; - in_port_t bindport; openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); @@ -140,19 +138,8 @@ main(int argc, char *argv[]) exit(1); } - j = sizeof(s_in); - if (getsockname(fd, (struct sockaddr *)&s_in, &j) == -1) { - syslog(LOG_ERR, "getsockname: %m"); - exit(1); - } - - bindport = ((struct sockaddr_in *)&s_in)->sin_port; - - /* req will be pushed back out at the end, unchanged */ - j = sizeof(from); - if ((reqsize = recvfrom(fd, req, sizeof(req), MSG_PEEK, - (struct sockaddr *)&from, &j)) < 0) { - syslog(LOG_ERR, "recvfrom: %m"); + if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTPORT, &on, sizeof(on)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_RECVDSTPORT): %m"); exit(1); } @@ -166,7 +153,7 @@ main(int argc, char *argv[]) msg.msg_control = &cmsgbuf.buf; msg.msg_controllen = sizeof(cmsgbuf.buf); - if (recvmsg(fd, &msg, 0) < 0) { + if ((reqsize = recvmsg(fd, &msg, 0)) < 0) { syslog(LOG_ERR, "recvmsg: %m"); exit(1); } @@ -174,33 +161,23 @@ main(int argc, char *argv[]) close(fd); close(1); - peer = socket(from.ss_family, SOCK_DGRAM, 0); - if (peer < 0) { - syslog(LOG_ERR, "socket: %m"); - exit(1); - } - memset(&s_in, 0, sizeof(s_in)); - s_in.ss_family = from.ss_family; - s_in.ss_len = from.ss_len; + memset(&server, 0, sizeof(server)); + server.ss_family = from.ss_family; + server.ss_len = from.ss_len; - /* get local address if possible */ + /* get server address and port */ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) { - memcpy(&((struct sockaddr_in *)&s_in)->sin_addr, + memcpy(&((struct sockaddr_in *)&server)->sin_addr, CMSG_DATA(cmsg), sizeof(struct in_addr)); - break; } - } - - if (bind(peer, (struct sockaddr *)&s_in, s_in.ss_len) < 0) { - syslog(LOG_ERR, "bind: %m"); - exit(1); - } - if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) { - syslog(LOG_ERR, "connect: %m"); - exit(1); + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVDSTPORT) { + memcpy(&((struct sockaddr_in *)&server)->sin_port, + CMSG_DATA(cmsg), sizeof(in_port_t)); + } } tp = (struct tftphdr *)req; @@ -214,22 +191,6 @@ main(int argc, char *argv[]) exit(0); } - j = sizeof(struct sockaddr_storage); - if (getsockname(fd, (struct sockaddr *)&proxy, &j) == -1) { - syslog(LOG_ERR, "getsockname: %m"); - exit(1); - } - - ((struct sockaddr_in *)&proxy)->sin_port = bindport; - - /* find the un-rdr'd server and port the client wanted */ - if (server_lookup((struct sockaddr *)&from, - (struct sockaddr *)&proxy, (struct sockaddr *)&server, - IPPROTO_UDP) != 0) { - syslog(LOG_ERR, "pf connection lookup failed (no rdr?)"); - exit(1); - } - /* establish a new outbound connection to the remote server */ if ((out_fd = socket(((struct sockaddr *)&from)->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { @@ -237,14 +198,6 @@ main(int argc, char *argv[]) exit(1); } - bzero((char *)&sock_out, sizeof(sock_out)); - sock_out.sin_family = from.ss_family; - sock_out.sin_port = htons(pick_proxy_port()); - if (bind(out_fd, (struct sockaddr *)&sock_out, sizeof(sock_out)) < 0) { - syslog(LOG_ERR, "couldn't bind to new socket: %m"); - exit(1); - } - if (connect(out_fd, (struct sockaddr *)&server, ((struct sockaddr *)&server)->sa_len) < 0 && errno != EINPROGRESS) { syslog(LOG_ERR, "couldn't connect to remote server: %m"); @@ -259,11 +212,9 @@ main(int argc, char *argv[]) } if (verbose) - syslog(LOG_INFO, "%s:%d -> %s:%d/%s:%d -> %s:%d \"%s %s\"", + syslog(LOG_INFO, "%s:%d -> %s:%d -> %s:%d \"%s %s\"", sock_ntop((struct sockaddr *)&from), ntohs(((struct sockaddr_in *)&from)->sin_port), - sock_ntop((struct sockaddr *)&proxy), - ntohs(((struct sockaddr_in *)&proxy)->sin_port), sock_ntop((struct sockaddr *)&proxy_to_server), ntohs(((struct sockaddr_in *)&proxy_to_server)->sin_port), sock_ntop((struct sockaddr *)&server), @@ -279,7 +230,8 @@ main(int argc, char *argv[]) /* rdr from server to us on our random port -> client on its port */ if (add_rdr(1, (struct sockaddr *)&server, - (struct sockaddr *)&proxy_to_server, ntohs(sock_out.sin_port), + (struct sockaddr *)&proxy_to_server, + ntohs(((struct sockaddr_in *)&proxy_to_server)->sin_port), (struct sockaddr *)&from, ntohs(((struct sockaddr_in *)&from)->sin_port), IPPROTO_UDP) == -1) { @@ -380,13 +332,6 @@ sock_ntop(struct sockaddr *sa) return (NULL); } -u_int16_t -pick_proxy_port(void) -{ - return (IPPORT_HIFIRSTAUTO + - arc4random_uniform(IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO)); -} - static void usage(void) { |
