1 /* $NetBSD: normalize_v4mapped_addr.c,v 1.2 2026/05/09 18:49:23 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* normalize_v4mapped_addr 3 6 /* SUMMARY 7 /* normalize v4mapped IPv6 address 8 /* SYNOPSIS 9 /* #include <stringops.h> 10 /* 11 /* int normalize_v4mapped_sockaddr( 12 /* struct sockaddr *sa, 13 /* SOCKADDR_SIZE *sa_len) 14 /* 15 /* int normalize_v4mapped_hostaddr( 16 /* MAI_HOSTADDR_STR *addr) 17 /* DESCRIPTION 18 /* The functions in this module convert IPV6 addresses containing a 19 /* mapped IPv4 address to the IPv4 form, but only if IPv4 support 20 /* is enabled. 21 /* 22 /* normalize_v4mapped_sockaddr converts a V4mapped IPv6 sockaddr 23 /* structure (struct sockaddr_in6) to the IPv4 form (struct 24 /* sockaddr_in) and reduces *sa_len to (sizeof(struct sockaddr_in)). 25 /* 26 /* normalize_v4mapped_hostaddr converts a V4mapped IPv6 printable 27 /* address (:ffff:d.d.d.d) to the IPv4 form (d.d.d.d). 28 /* 29 /* Both functions return 0 (false) when no input was converted, 30 /* and return 1 (true) when input was converted. 31 /* BUGS 32 /* normalize_v4mapped_hostaddr() converts only canonical address 33 /* forms, not all equivalent forms. 34 /* LICENSE 35 /* .ad 36 /* .fi 37 /* The Secure Mailer license must be distributed with this software. 38 /* AUTHOR(S) 39 /* Wietse Venema 40 /* porcupine.org 41 /* New York, NY 10011, USA 42 /*--*/ 43 44 /* 45 * System library. 46 */ 47 #include <sys_defs.h> 48 49 /* 50 * Utility library. 51 */ 52 #include <inet_proto.h> 53 #include <sock_addr.h> 54 #include <normalize_v4mapped_addr.h> 55 56 /* normalize_v4mapped_sockaddr - normalize V4mapped IPv6 sockaddr */ 57 58 int normalize_v4mapped_sockaddr(struct sockaddr *sa, SOCKADDR_SIZE *sa_len) 59 { 60 #ifdef HAS_IPV6 61 struct sockaddr_in sin; 62 63 if (sa->sa_family == AF_INET6 64 && IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa)) 65 && strchr((char *) inet_proto_info()->sa_family_list, AF_INET) != 0) { 66 memset((void *) &sin, 0, sizeof(sin)); 67 sin.sin_family = AF_INET; 68 sin.sin_port = SOCK_ADDR_IN6_PORT(sa); 69 memcpy((void *) &sin.sin_addr, ((void *) &SOCK_ADDR_IN6_ADDR(sa)) + 12, 70 sizeof(sin.sin_addr)); 71 *(struct sockaddr_in *) sa = sin; 72 *sa_len = sizeof(sin); 73 return (1); 74 } 75 #endif 76 return (0); 77 } 78 79 /* normalize_v4mapped_hostaddr - normalize V4mapped IPv6 printable address */ 80 81 int normalize_v4mapped_hostaddr(MAI_HOSTADDR_STR *addr) 82 { 83 #ifdef HAS_IPV6 84 if (addr->buf[0] == ':' 85 && strncasecmp("::ffff:", addr->buf, 7) == 0 86 && strchr((char *) inet_proto_info()->sa_family_list, AF_INET) != 0) { 87 memmove(addr->buf, addr->buf + 7, strlen(addr->buf) + 1 - 7); 88 return (1); 89 } 90 #endif 91 return (0); 92 } 93