--- tftpd/tftpd.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) Index: tftp-hpa-5.2/tftpd/tftpd.c =================================================================== --- tftp-hpa-5.2.orig/tftpd/tftpd.c +++ tftp-hpa-5.2/tftpd/tftpd.c @@ -1353,6 +1353,21 @@ static void do_opt(const char *opt, cons #ifdef WITH_REGEX +#ifdef HAVE_IPV6 +static inline int is_v6_mapped(const union sock_addr* pa) +{ + const char v6_mapped[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF }; + + if (from.sa.sa_family != AF_INET6) + return 0; + if (memcmp(&pa->s6.sin6_addr.s6_addr, v6_mapped, sizeof(v6_mapped))) + return 0; + + return 1; +} +#endif + /* * This is called by the remap engine when it encounters macros such * as \i. It should write the output in "output" if non-NULL, and @@ -1364,10 +1379,20 @@ static int rewrite_macros(char macro, ch { char *p, tb[INET6_ADDRSTRLEN]; int l=0; + const union sock_addr *pfrom = &from; + +#ifdef HAVE_IPV6 + union sock_addr ipv4_from; + if (is_v6_mapped(&from)) { + ipv4_from.si.sin_family = AF_INET; + memcpy(&ipv4_from.si.sin_addr, from.s6.sin6_addr.s6_addr + 12, 4); + pfrom = &ipv4_from; + } +#endif switch (macro) { case 'i': - p = (char *)inet_ntop(from.sa.sa_family, SOCKADDR_P(&from), + p = (char *)inet_ntop(pfrom->sa.sa_family, SOCKADDR_P(pfrom), tb, INET6_ADDRSTRLEN); if (output && p) strcpy(output, p); @@ -1377,14 +1402,14 @@ static int rewrite_macros(char macro, ch return strlen(p); case 'x': - if (from.sa.sa_family == AF_INET) { + if (pfrom->sa.sa_family == AF_INET) { if (output) sprintf(output, "%08lX", - (unsigned long)ntohl(from.si.sin_addr.s_addr)); + (unsigned long)ntohl(pfrom->si.sin_addr.s_addr)); l = 8; #ifdef HAVE_IPV6 } else { - unsigned char *c = (unsigned char *)SOCKADDR_P(&from); + unsigned char *c = (unsigned char *)SOCKADDR_P(pfrom); p = tb; for (l = 0; l < 16; l++) { sprintf(p, "%02X", *c);