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;