tftp/tftp-multi-addresses.patch

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