Cómo almacenar direcciones compatibles con IPv6 en una base de datos relacional

StackOverflow https://stackoverflow.com/questions/420680

  •  05-07-2019
  •  | 
  •  

Pregunta

¿Cómo hago eso?

En este momento, IPv6 no se utilizará, pero necesito diseñar la aplicación para que esté lista para IPv6. Es necesario almacenar direcciones IP y bloques CIDR (también BGP NLRI, pero esta es otra historia) en una base de datos MySQL. Siempre he usado un INT para IPv4 + un TINYINT para masklen, pero IPv6 es de 128 bits.

¿Qué enfoque será mejor para eso? 2xBIGINT ? CHAR (16) para almacenamiento binario? CHAR (39) para almacenamiento de texto? 8xSMALLINT en una tabla dedicada?

¿Qué recomendarías?

¿Fue útil?

Solución

No estoy seguro de cuál es la respuesta correcta para MySQL dado que aún no admite formatos de dirección IPv6 de forma nativa (aunque mientras que " WL # 798: Soporte de MySQL IPv6 " sugiere que iba a estar en MySQL v6.0, la documentación actual no t respaldar eso).

Sin embargo, de los que has propuesto, te sugiero que vayas por 2 * BIGINT, pero asegúrate de que estén SIN FIRMAR. Hay una especie de división natural en el límite de dirección / 64 en IPv6 (ya que a / 64 es el tamaño de bloque de red más pequeño) que se alinearía muy bien con eso.

Otros consejos

Tenga en cuenta que la longitud máxima de una dirección IPv6, incluido el identificador de alcance, es de 46 bytes según lo definido por INET6_ADDRSTRLEN en los encabezados C estándar. Para el uso de Internet, debe poder ignorar el identificador de zona (% 10, # eth0, etc.), pero tenga en cuenta cuando getaddrinfo devuelve un resultado más largo de lo esperado.

Si te inclinas hacia char (16), definitivamente usa binary (16) en su lugar. binary (n) no tiene un concepto de colación o conjunto de caracteres (o más bien, es un char (n) con un conjunto de caracteres / colación de 'binary'). El valor predeterminado para char en mysql es latin1_swedish_ci, lo que significa que intentará ordenar y hacer comparaciones entre mayúsculas y minúsculas para valores de bytes que son puntos de código válidos en latin1, lo que le causará toda clase de problemas inesperados.

Otra opción es usar zerofill decimal (39, 0) sin signo, no tan eficiente como dos bigints (decimal usará 4 bytes por nueve dígitos en las versiones actuales de mysql), pero le permitirá mantenerlo todo en uno columna e imprima bien.

Yo elegiría los 39 caracteres completos "estándar" formato impreso: -

"2001:0db8:85a3:0000:0000:8a2e:0370:7334"

40 con un terminador nulo.

Este es el formato utilizado por las herramientas de línea de comandos * nix, y el formato en el que se informa normalmente una dirección IPV6 (?).

¿La dirección IP será utilizada por un programa para el que el binario tiene sentido? ¿O sería mejor almacenar una representación de texto? Además, con IPv6, es menos probable que use la dirección en general y más probabilidades de usar nombres de host. Si eso es relevante depende de la aplicación, en parte. CHAR (16) sería una mala elección; char es para datos de caracteres y no le gustarán grandes secuencias de cero bytes que prevalecen en las direcciones IPv6. 2 x BIGINT sería incómodo: dos campos que son realmente uno (¿además el valor almacenado es big-endian o little-endian?). Había usado un tipo BINARY de tamaño fijo, o si no está disponible, un tipo de blob.

Estoy trabajando con un proyecto de coincidencia de prefijo más largo, por lo que separo la dirección en 4 enteros para las direcciones IPv4. Funciona bien. Extendería eso a las direcciones IPv6.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top