Home | History | Annotate | Line # | Download | only in util
      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