64 lines
2.6 KiB
Diff
64 lines
2.6 KiB
Diff
Index: tftp-hpa-5.2/tftpd/recvfrom.c
|
|
===================================================================
|
|
--- tftp-hpa-5.2.orig/tftpd/recvfrom.c 2015-04-30 11:04:45.994568260 +0200
|
|
+++ tftp-hpa-5.2/tftpd/recvfrom.c 2015-05-14 16:02:28.104576816 +0200
|
|
@@ -148,17 +148,17 @@ myrecvfrom(int s, void *buf, int len, un
|
|
#endif
|
|
|
|
/* Try to enable getting the return address */
|
|
+ /* Before the first packet we don't know the address family of the
|
|
+ * connection, so we set both ipv4 and ipv6 socket options
|
|
+ */
|
|
#ifdef IP_RECVDSTADDR
|
|
- if (from->sa_family == AF_INET)
|
|
setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
|
|
#endif
|
|
#ifdef IP_PKTINFO
|
|
- if (from->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)
|
|
setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
|
|
#endif
|
|
#endif
|
|
@@ -190,7 +190,7 @@ myrecvfrom(int s, void *buf, int len, un
|
|
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
|
|
cmptr = CMSG_NXTHDR(&msg, cmptr)) {
|
|
|
|
- if (from->sa_family == AF_INET) {
|
|
+ if (cmptr->cmsg_level == IPPROTO_IP) {
|
|
myaddr->sa.sa_family = AF_INET;
|
|
#ifdef IP_RECVDSTADDR
|
|
if (cmptr->cmsg_level == IPPROTO_IP &&
|
|
@@ -209,15 +209,26 @@ myrecvfrom(int s, void *buf, int len, un
|
|
sizeof(struct in_addr));
|
|
}
|
|
#endif
|
|
+ if (from->sa_family == AF_INET6) {
|
|
+ from->sa_family = AF_INET;
|
|
+ /* Unmap the ipv4 address from ipv6.
|
|
+ * The ipv6 mapped address is in format:
|
|
+ * 10 0x0 bytes, 2 0xff bytes, 4 bytes of the ipv4 address
|
|
+ * so we cut out the first 12 bytes of the ipv6 and
|
|
+ * interpret the rest as the ipv4
|
|
+ */
|
|
+ ((struct sockaddr_in *)from)->sin_addr = *((struct in_addr *)(((struct sockaddr_in6 *)from)->sin6_addr.s6_addr+12));
|
|
+ }
|
|
}
|
|
#ifdef HAVE_IPV6
|
|
- else if (from->sa_family == AF_INET6) {
|
|
+ else if (cmptr->cmsg_level == IPPROTO_IPV6) {
|
|
myaddr->sa.sa_family = AF_INET6;
|
|
#ifdef IP6_RECVDSTADDR
|
|
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
|
|
- cmptr->cmsg_type == IPV6_RECVDSTADDR )
|
|
+ cmptr->cmsg_type == IPV6_RECVDSTADDR ) {
|
|
memcpy(&myaddr->s6.sin6_addr, CMSG_DATA(cmptr),
|
|
sizeof(struct in6_addr));
|
|
+ }
|
|
#endif
|
|
|
|
#ifdef HAVE_STRUCT_IN6_PKTINFO
|