summaryrefslogtreecommitdiffstats
path: root/libexec/tftp-proxy
diff options
context:
space:
mode:
authorsthen <sthen@openbsd.org>2011-05-05 12:25:51 +0000
committersthen <sthen@openbsd.org>2011-05-05 12:25:51 +0000
commit31330dd0376dd9de584ec5a74ad766838f050db7 (patch)
tree782a3158c4a9267333d2613380d7502f085bdc22 /libexec/tftp-proxy
parentrename iked_proc* to privsep_proc*. no functional change. (diff)
downloadwireguard-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.c78
-rw-r--r--libexec/tftp-proxy/filter.h4
-rw-r--r--libexec/tftp-proxy/tftp-proxy.810
-rw-r--r--libexec/tftp-proxy/tftp-proxy.c97
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)
{