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) {