Resumen

  • RFC 3493 permitía que un socket AF_INET6 atendiera nodos IPv4 mediante direcciones IPv4 mapeadas en IPv6. IPV6_V6ONLY podía limitarlo a IPv6, pero el RFC establecía la opción apagada por defecto.
  • Por eso, ver la familia del socket o un proceso activo no demostraba quién poseía el puerto ni qué familia llegaba. El valor efectivo de la opción, el bind y los pares aceptados eran recibos distintos.

Un fallo de reinicio muestra mejor el contrato que un diagrama. El proceso IPv6 abre primero un puerto comodín. Después, el proceso IPv4 intenta ocupar el mismo número y recibe un conflicto. Ambos manifiestos parecen correctos; lo que cambió fue la forma en que el primer socket repartía el espacio de escucha.

RFC 3493 llevaba IPv4 a la interfaz IPv6 mediante direcciones mapeadas. Los 32 bits de IPv4 se alojaban bajo el prefijo ::ffff: dentro de una estructura de 128 bits. Así, una aplicación podía usar AF_INET6 y aun conectar con un nodo IPv4. Al aceptar tráfico, el sistema podía devolver el par dentro de sockaddr_in6, y IN6_IS_ADDR_V4MAPPED() permitía identificarlo.

Ese formato no convierte al par en un nodo IPv6. Tampoco certifica el camino, el firewall o la política de la aplicación. Es una forma de transportar identidad de red entre núcleo y programa. La distinción ya existía en las revisiones anteriores de la API; RFC 3493 añadió un mando explícito sobre el ámbito del listener.

Ese mando era IPV6_V6ONLY. Al activarlo, el socket quedaba restringido a comunicaciones IPv6. El documento decía que el valor predeterminado era apagado. Con ese valor histórico, un bind comodín de AF_INET6 podía admitir tanto IPv6 nativo como IPv4 presentado de forma mapeada.

El caso de uso incluido en el RFC no habla de estética. Al activar la opción, dos versiones del mismo servidor podían usar el mismo puerto: una para IPv6 y otra para IPv4. La opción decidía si un descriptor abarcaba dos familias o si dejaba una parte del espacio de puertos para otro descriptor. El orden de arranque y el resultado del bind pasaban a ser hechos operativos.

Por eso una lista de procesos es insuficiente. Puede mostrar dos servicios aunque uno no haya conseguido escuchar. Una lista de sockets también puede engañar si interpreta AF_INET6 como «solo IPv6». La prueba completa necesita el valor leído de la opción, dirección y namespace de bind, retorno del sistema y muestras de pares realmente aceptados.

Hay además una excepción precisa. RFC 3493 indica que IPV6_V6ONLY no afecta a direcciones mapeadas que entran como IPv6 válido mediante SIIT. RFC 6052 y RFC 6145 describen direcciones incrustadas y traducción de paquetes. Por eso, una apariencia mapeada no revela por sí sola si el núcleo aceptó IPv4 localmente o si la transformación ocurrió antes.

La resolución tampoco entrega el resultado final. getaddrinfo() ofrece candidatos según familia y banderas. RFC 6724 ordena direcciones; RFC 8305 propone competir entre rutas IPv6 e IPv4. Resolver, elegir, conectar, ser autorizado y completar el servicio siguen siendo pasos diferentes.

El «apagado por defecto» debe conservar su fecha. RFC 3493 es Informational, reemplazó RFC 2553 y señaló otra norma como autoridad formal de la API. Los sistemas actuales pueden elegir valores distintos. La historia no autoriza a adivinar la configuración de un host moderno.

La lección es un método de prueba: registrar familia declarada, opción efectiva, alcance del bind, propiedad real del puerto, clase del par, decisión de política y resultado. Saltarse un recibo transforma una etiqueta del código en una afirmación falsa sobre la red.

Fuentes