Resumen

  • Las funciones principales aceptaban un puntero opaco y una longitud, de modo que podían conservar su sintaxis. La compatibilidad IPv6 exigía, aun así, PF_INET6, sockaddr_in6 y nuevas rutinas de nombres y conversiones.
  • Un programa antiguo PF_INET que sigue hablando con IPv4 y uno nuevo PF_INET6 que representa a un par IPv4 mediante ::FFFF: ejercen capacidades distintas; ninguna demuestra por sí sola una conexión IPv6 funcional.

Pensemos en una aplicación que hereda un socket abierto. Puede invocar accept() sin error y, sin embargo, interpretar la dirección devuelta con la estructura equivocada. El problema no está en el verbo de la llamada, sino en el acuerdo sobre sus datos. El RFC 2133 describió ese riesgo en abril de 1997. Era informativo y quedó obsoleto por el RFC 2553; por eso explica una decisión histórica, no prescribe cómo programar hoy.

Una dirección IPv4 tiene 32 bits y una IPv6, 128. Las funciones socket ya transportaban las direcciones como punteros opacos junto a su longitud, lo que permitía mantener bind(), connect(), sendto() y otras firmas. Pero sockaddr_in no tenía espacio suficiente para la dirección IPv6 completa, la familia y el puerto. Hacían falta una familia AF_INET6, una familia de protocolo PF_INET6, una estructura sockaddr_in6 y formas de resolver y convertir direcciones. El RFC incluso registró variantes de la estructura en BSD 4.3 y 4.4. Quien había supuesto un tamaño fijo o había forzado tipos sin mirar la longitud no quedaba protegido por el mero hecho de conservar el nombre de la función.

El primer compromiso era no romper lo anterior. La interfaz ampliada debía seguir aceptando PF_INET y sockaddr_in, tanto para fuentes recompiladas como para binarios ya existentes; esos programas continuarían comunicándose con nodos IPv4. No se volvían aplicaciones IPv6 por instalar un sistema nuevo. El segundo compromiso se dirigía al software adaptado: un socket PF_INET6 podía representar un nodo IPv4 dentro de sockaddr_in6 con una dirección mapeada ::FFFF:<dirección IPv4>. Es una forma de presentar un par IPv4 a la API. El aspecto de 128 bits no verifica que el par o los paquetes hayan usado IPv6.

Las direcciones comodín y de bucle local delimitan todavía más la afirmación. La dirección IPv6 no especificada permite que el sistema elija una dirección local; la de bucle local apunta al propio equipo. Ninguna garantiza que clientes remotos puedan llegar a un servicio, y el RFC no aporta mediciones de despliegue que permitan inferirlo.

La sección sobre IPV6_ADDRFORM muestra la fricción menos visible. En Unix, un descriptor abierto podía pasar por exec() a otro proceso. Si el receptor esperaba otra familia, podría descodificar mal las direcciones que devuelven las funciones socket. La opción propuesta permitía convertir la vista de un socket entre PF_INET y PF_INET6. La conversión hacia IPv4 solo era válida cuando todas las direcciones no comodín ya asociadas eran IPv4 mapeadas. La condición depende del estado del socket, no de una declaración comercial de compatibilidad. Tampoco autoriza a asumir que el mecanismo obsoleto esté disponible de forma uniforme hoy.

Los índices de interfaz eran igualmente locales. El RFC relacionaba nombres con números asignados por el núcleo mediante funciones como if_nametoindex; las opciones de multidifusión elegían la interfaz de salida o la pertenencia a un grupo. Son decisiones dentro del host. No prueban entrega a otro equipo ni procesamiento por una aplicación. Resolver un nombre entrega un candidato para conectar, no una confirmación de conexión.

La enseñanza histórica es separar interfaz, representación y resultado. La columna de Lu Heng sobre la primacía del código en funcionamiento aporta una perspectiva editorial para exigir observación del sistema real; los detalles técnicos proceden del RFC, no de esa opinión.

Fuentes: RFC 2133, ficha del RFC Editor y RFC 2553.