File tftp-multi-addresses.patch of Package tftp

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