summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2006-10-04 21:54:04 -0700
committerH. Peter Anvin <hpa@zytor.com>2006-10-04 21:54:04 -0700
commit14993bc916942d01e5fb9c5f4c084121dfdfd41c (patch)
tree8a0db875e567f0ff32a9d864336e4703a367b389
parentf3beb3a11954044a99c998979cb72ca1b6e6a661 (diff)
downloadtftp-hpa-14993bc916942d01e5fb9c5f4c084121dfdfd41c.tar.gz
Introduce socklen_t; detect non-local (e.g. broadcast) receive addresses
-rw-r--r--common/tftpsubs.c2
-rw-r--r--config.h7
-rw-r--r--configure.in9
-rw-r--r--tftp/tftp.c6
-rw-r--r--tftpd/recvfrom.c47
-rw-r--r--tftpd/recvfrom.h5
-rw-r--r--tftpd/tftpd.c12
7 files changed, 68 insertions, 20 deletions
diff --git a/common/tftpsubs.c b/common/tftpsubs.c
index 3dd34bd..9103106 100644
--- a/common/tftpsubs.c
+++ b/common/tftpsubs.c
@@ -250,7 +250,7 @@ synchnet(int f) /* socket to flush */
int pktcount = 0;
char rbuf[PKTSIZE];
struct sockaddr_in from;
- int fromlen;
+ socklen_t fromlen;
fd_set socketset;
struct timeval notime;
diff --git a/config.h b/config.h
index 6e2125b..8869134 100644
--- a/config.h
+++ b/config.h
@@ -1,6 +1,6 @@
/* -*- c -*- ------------------------------------------------------------- *
*
- * Copyright 2001 H. Peter Anvin - All Rights Reserved
+ * Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
* as the "OpenBSD" operating system, distributed at
@@ -217,6 +217,11 @@ typedef unsigned long u_long;
#endif
#endif
+/* socklen_t */
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
/* sysexits.h */
#ifdef HAVE_SYSEXITS_H
diff --git a/configure.in b/configure.in
index faff15e..c40d4c8 100644
--- a/configure.in
+++ b/configure.in
@@ -81,16 +81,17 @@ AC_CHECK_HEADERS(sys/socket.h)
AC_CHECK_HEADERS(winsock2.h)
AC_CHECK_HEADERS(winsock.h)
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_MODE_T
+AC_TYPE_SIZE_T
AC_CHECK_TYPES(intmax_t)
AC_CHECK_TYPES(long long)
AC_CHECK_TYPES(uint16_t)
AC_CHECK_TYPES(uint32_t)
AC_CHECK_TYPES(u_short)
AC_CHECK_TYPES(u_long)
-AC_TYPE_OFF_T
-AC_TYPE_PID_T
-AC_TYPE_MODE_T
-AC_TYPE_SIZE_T
+AC_CHECK_TYPES(socklen_t)
AC_SEARCH_LIBS(socket, [socket ws2_32 wsock32], , [AC_MSG_ERROR(socket library not found)])
AC_SEARCH_LIBS(gethostbyname, [nsl resolv], , [AC_MSG_ERROR(gethostbyname not found)])
diff --git a/tftp/tftp.c b/tftp/tftp.c
index 97b10dc..8dfec29 100644
--- a/tftp/tftp.c
+++ b/tftp/tftp.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/* $OpenBSD: tftp.c,v 1.4 1997/08/06 06:43:45 deraadt Exp $ */
/* $NetBSD: tftp.c,v 1.5 1995/04/29 05:55:25 cgd Exp $ */
@@ -87,7 +85,7 @@ tftp_sendfile(int fd, const char *name, const char *mode)
volatile int size, convert;
volatile off_t amount;
struct sockaddr_in from;
- int fromlen;
+ socklen_t fromlen;
FILE *file;
u_short ap_opcode, ap_block;
@@ -195,7 +193,7 @@ tftp_recvfile(int fd, const char *name, const char *mode)
volatile int size, firsttrip;
volatile unsigned long amount;
struct sockaddr_in from;
- int fromlen;
+ socklen_t fromlen;
FILE *file;
volatile int convert; /* true if converting crlf -> lf */
u_short dp_opcode, dp_block;
diff --git a/tftpd/recvfrom.c b/tftpd/recvfrom.c
index 0b3456e..ba8d648 100644
--- a/tftpd/recvfrom.c
+++ b/tftpd/recvfrom.c
@@ -50,9 +50,50 @@ struct in_pktinfo {
# define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size))
#endif
+/*
+ * Check to see if this is a valid local address. If so, we should
+ * end up having the same local and remote address when trying to
+ * bind to it.
+ */
+static int address_is_local(const struct sockaddr_in *addr)
+{
+ struct sockaddr_in sin;
+ int sockfd = -1;
+ int e;
+ int rv = 0;
+ socklen_t addrlen;
+
+ /* Multicast or universal broadcast address? */
+ if (ntohl(addr->sin_addr.s_addr) >= (224UL << 24))
+ return 0;
+
+ sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ goto err;
+
+ if (connect(sockfd, (const struct sockaddr *)addr, sizeof *addr))
+ goto err;
+
+ addrlen = sizeof sin;
+ if (getsockname(sockfd, (struct sockaddr *)&sin, &addrlen))
+ goto err;
+
+ rv = sin.sin_addr.s_addr == addr->sin_addr.s_addr;
+
+ err:
+ e = errno;
+
+ if (sockfd >= 0)
+ close(sockfd);
+
+ errno = e;
+ return rv;
+}
+
+
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, int *fromlen,
+ struct sockaddr *from, socklen_t *fromlen,
struct sockaddr_in *myaddr)
{
struct msghdr msg;
@@ -128,6 +169,10 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
}
}
+ /* If the address is not a valid local address, then bind to any address... */
+ if (address_is_local(myaddr) != 1)
+ myaddr->sin_addr.s_addr = INADDR_ANY;
+
return n;
}
diff --git a/tftpd/recvfrom.h b/tftpd/recvfrom.h
index 1177981..35ad05b 100644
--- a/tftpd/recvfrom.h
+++ b/tftpd/recvfrom.h
@@ -1,7 +1,6 @@
-/* $Id$ */
/* ----------------------------------------------------------------------- *
*
- * Copyright 2001 H. Peter Anvin - All Rights Reserved
+ * Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
* as the "OpenBSD" operating system, distributed at
@@ -20,5 +19,5 @@
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, int *fromlen,
+ struct sockaddr *from, socklen_t *fromlen,
struct sockaddr_in *myaddr);
diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
index 47b85d9..6018850 100644
--- a/tftpd/tftpd.c
+++ b/tftpd/tftpd.c
@@ -96,13 +96,13 @@ char buf[PKTSIZE];
char ackbuf[PKTSIZE];
unsigned int max_blksize = MAX_SEGSIZE;
-struct sockaddr_in from;
-int fromlen;
-off_t tsize;
-int tsize_ok;
+struct sockaddr_in from;
+socklen_t fromlen;
+off_t tsize;
+int tsize_ok;
-int ndirs;
-const char **dirs;
+int ndirs;
+const char **dirs;
int secure = 0;
int cancreate = 0;