aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tftpd/recvfrom.c43
-rw-r--r--tftpd/recvfrom.h3
-rw-r--r--tftpd/tftpd.c5
3 files changed, 25 insertions, 26 deletions
diff --git a/tftpd/recvfrom.c b/tftpd/recvfrom.c
index b613823..83ef29a 100644
--- a/tftpd/recvfrom.c
+++ b/tftpd/recvfrom.c
@@ -113,14 +113,15 @@ err:
return rv;
}
-#ifdef HAVE_IPV6
static void normalize_ip6_compat(union sock_addr *myaddr)
{
+#ifdef HAVE_IPV6
static const uint8_t ip6_compat_prefix[12] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
struct sockaddr_in in;
- if (!memcmp(&myaddr->s6.sin6_addr, ip6_compat_prefix,
+ if (myaddr->sa.sa_family == AF_INET6 &&
+ !memcmp(&myaddr->s6.sin6_addr, ip6_compat_prefix,
sizeof ip6_compat_prefix)) {
bzero(&in, sizeof in);
in.sin_family = AF_INET;
@@ -129,13 +130,14 @@ static void normalize_ip6_compat(union sock_addr *myaddr)
sizeof ip6_compat_prefix, sizeof in.sin_addr);
memcpy(&myaddr->si, &in, sizeof in);
}
-}
+#else
+ (void)myaddr;
#endif
+}
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t * fromlen,
- union sock_addr *myaddr)
+ union sock_addr *from, union sock_addr *myaddr)
{
struct msghdr msg;
struct iovec iov;
@@ -168,16 +170,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
/* Try to enable getting the return address */
#ifdef IP_RECVDSTADDR
- if (from->sa_family == AF_INET)
+ if (from->sa.sa_family == AF_INET)
setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
#endif
#ifdef IP_PKTINFO
- if (from->sa_family == AF_INET)
+ if (from->sa.sa_family == AF_INET)
setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
#endif
#ifdef HAVE_IPV6
#ifdef IPV6_RECVPKTINFO
- if (from->sa_family == AF_INET6)
+ if (from->sa.sa_family == AF_INET6)
setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
#endif
#endif
@@ -186,8 +188,8 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
msg.msg_controllen = sizeof(control_un);
msg.msg_flags = 0;
- msg.msg_name = from;
- msg.msg_namelen = *fromlen;
+ msg.msg_name = &from->sa;
+ msg.msg_namelen = sizeof(*from);
iov.iov_base = buf;
iov.iov_len = len;
msg.msg_iov = &iov;
@@ -196,11 +198,9 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
if ((n = recvmsg(s, &msg, flags)) < 0)
return n; /* Error */
- *fromlen = msg.msg_namelen;
-
if (myaddr) {
bzero(myaddr, sizeof(*myaddr));
- myaddr->sa.sa_family = from->sa_family;
+ myaddr->sa.sa_family = from->sa.sa_family;
if (msg.msg_controllen < sizeof(struct cmsghdr) ||
(msg.msg_flags & MSG_CTRUNC))
@@ -209,7 +209,7 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
cmptr = CMSG_NXTHDR(&msg, cmptr)) {
- if (from->sa_family == AF_INET) {
+ if (from->sa.sa_family == AF_INET) {
myaddr->sa.sa_family = AF_INET;
#ifdef IP_RECVDSTADDR
if (cmptr->cmsg_level == IPPROTO_IP &&
@@ -230,7 +230,7 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
#endif
}
#ifdef HAVE_IPV6
- else if (from->sa_family == AF_INET6) {
+ else if (from->sa.sa_family == AF_INET6) {
myaddr->sa.sa_family = AF_INET6;
#ifdef IP6_RECVDSTADDR
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
@@ -252,7 +252,6 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
sizeof(struct in6_addr));
}
#endif
- normalize_ip6_compat(myaddr);
}
#endif
}
@@ -268,6 +267,10 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
#endif
}
}
+
+ normalize_ip6_compat(myaddr);
+ normalize_ip6_compat(from);
+
return n;
}
@@ -275,16 +278,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t * fromlen,
- union sock_addr *myaddr)
+ union sock_addr *from, union sock_addr *myaddr)
{
/* There is no way we can get the local address, fudge it */
+ socklen_t fromlen = sizeof(*from);
bzero(myaddr, sizeof(*myaddr));
- myaddr->sa.sa_family = from->sa_family;
+ myaddr->sa.sa_family = from->sa.sa_family;
sa_set_port(myaddr, htons(IPPORT_TFTP));
- return recvfrom(s, buf, len, flags, from, fromlen);
+ return recvfrom(s, buf, len, flags, from, &fromlen);
}
#endif
diff --git a/tftpd/recvfrom.h b/tftpd/recvfrom.h
index e3c4055..7773a0d 100644
--- a/tftpd/recvfrom.h
+++ b/tftpd/recvfrom.h
@@ -19,5 +19,4 @@
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen,
- union sock_addr *myaddr);
+ union sock_addr *from, union sock_addr *myaddr);
diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
index 91f5ae1..364e7d2 100644
--- a/tftpd/tftpd.c
+++ b/tftpd/tftpd.c
@@ -93,7 +93,6 @@ static unsigned int max_blksize = MAX_SEGSIZE;
static char tmpbuf[INET6_ADDRSTRLEN], *tmp_p;
static union sock_addr from;
-static socklen_t fromlen;
static off_t tsize;
static int tsize_ok;
@@ -874,9 +873,7 @@ int main(int argc, char **argv)
set_socket_nonblock(fd, 0);
#endif
- fromlen = sizeof(from);
- n = myrecvfrom(fd, buf, sizeof(buf), 0,
- (struct sockaddr *)&from, &fromlen, &myaddr);
+ n = myrecvfrom(fd, buf, sizeof(buf), 0, &from, &myaddr);
if (n < 0) {
if (E_WOULD_BLOCK(errno) || errno == EINTR) {