getaddrinfo


De Wikipedia, la enciclopedia libre
  (Redirigido desde Getnameinfo )
Saltar a navegación Saltar a búsqueda

Las funciones getaddrinfo () y getnameinfo () convierten nombres de dominio , nombres de host y direcciones IP entre representaciones de texto legibles por humanos y formatos binarios estructurados para la API de red del sistema operativo . Ambas funciones están contenidas en la interfaz de programación de aplicaciones (API) estándar POSIX .

getaddrinfo y getnameinfo son funciones inversas entre sí. Son independientes del protocolo de red y admiten tanto IPv4 como IPv6 . Es la interfaz recomendada para la resolución de nombres en la creación de aplicaciones independientes del protocolo y para la transición del código IPv4 heredado a Internet IPv6.

Internamente, las funciones realizan resoluciones utilizando el Sistema de nombres de dominio (DNS) llamando a otras funciones de nivel inferior, como gethostbyname () .

El 16 de febrero de 2016 se anunció un error de seguridad en la implementación glibc de getaddrinfo (), utilizando una técnica de desbordamiento de búfer , que puede permitir la ejecución de código arbitrario por parte del atacante. [1]

estructura addrinfo

La estructura de datos de C que se utiliza para representar direcciones y nombres de host dentro de la API de red es la siguiente:

struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; socklen_t ai_addrlen; struct sockaddr * ai_addr; char * ai_canonname; /* nombre Canonico */ struct addrinfo * ai_next; / * esta estructura puede formar una lista enlazada * /
};

En algunos sistemas más antiguos, el tipo de ai_addrlen es size_t en lugar de socklen_t . La mayoría de las funciones de socket, como accept () y getpeername () , requieren que el parámetro tenga el tipo socklen_t * y los programadores a menudo pasan la dirección al elemento ai_addrlen de la estructura addrinfo . Si los tipos son incompatibles, por ejemplo, en un sistema Solaris 9 de 64 bits donde size_t es de 8 bytes y socklen_t es de 4 bytes, pueden producirse errores de tiempo de ejecución.

La estructura contiene estructuras ai_family y sockaddr con su propio sa_family campo. Estos se establecen en el mismo valor cuando la estructura se crea con la función getaddrinfo en algunas implementaciones.

getaddrinfo ()

getaddrinfo () convierte cadenas de texto legibles por humanos que representan nombres de host o direcciones IP en una lista enlazada asignada dinámicamente de estructuras struct addrinfo. El prototipo de función para esta función se especifica de la siguiente manera:

int getaddrinfo (const char * nombre de host, servicio const char *, const struct addrinfo * sugerencias, struct addrinfo ** res);
nombre de host
puede ser un nombre de dominio, como "example.com", una cadena de direcciones, como "127.0.0.1", o NULL, en cuyo caso se asigna la dirección 0.0.0.0 o 127.0.0.1 dependiendo de los indicadores de pistas.
Servicio
puede ser un número de puerto pasado como una cadena, como "80", o un nombre de servicio, por ejemplo, "echo". En el último caso, una implementación típica usa getservbyname () para consultar el archivo / etc / services para resolver el servicio en un número de puerto.
pistas
puede ser NULL o una estructura adicional con el tipo de servicio solicitado.
res
es un puntero que apunta a una nueva estructura de addrinfo con la información solicitada después de completar con éxito la función. [2] La función devuelve 0 en caso de éxito y un valor de error distinto de cero si falla. [3]

Aunque las implementaciones varían entre las plataformas, la función primero intenta obtener un número de puerto generalmente mediante la ramificación en el servicio . Si el valor de la cadena es un número, lo convierte en un entero y llama a htons () . Si es un nombre de servicio, como www , el servicio se busca con getservbyname () , usando el protocolo derivado de hints-> ai_socktype como segundo parámetro de esa función. Luego, si se proporciona el nombre de host (no NULL), una llamada a gethostbyname () lo resuelve, o de lo contrario, se usa la dirección 0.0.0.0 , si hints-> ai_flags se establece en AI_PASSIVE y 127.0.0.1de lo contrario. Asignó una nueva estructura de addrinfo llena con el sockaddr_in apropiado en una de estas condiciones y también le agrega el puerto recuperado al principio. Finalmente, se elimina la referencia al parámetro ** res para que apunte a una estructura addrinfo recién asignada . [4] En algunas implementaciones, como la versión Unix para Mac OS, hints-> ai_protocol anula el valor hints-> ai_socktype mientras que en otras es lo opuesto, por lo que ambos deben definirse con valores equivalentes para que el código sea trabajar en múltiples plataformas.

freeaddrinfo ()

Esta función libera la memoria asignada por la función getaddrinfo () . Como el resultado de este último es una lista enlazada de estructuras addrinfo que comienzan en la dirección ai , freeaddrinfo () recorre la lista y libera cada una a su vez.

void freeaddrinfo (struct addrinfo * ai);

getnameinfo ()

La función getnameinfo () convierte la representación binaria interna de una dirección IP en forma de puntero en una estructura sockaddr en cadenas de texto que consisten en el nombre de host o, si la dirección no se puede resolver en un nombre, una representación textual de la dirección IP, como así como el nombre o número del puerto de servicio. El prototipo de función se especifica de la siguiente manera:

int getnameinfo (const struct sockaddr * sa, socklen_t salen, char * host, size_t hostlen, char * serv, size_t servlen, int banderas);

Ejemplo

El siguiente ejemplo usa getaddrinfo () para resolver el nombre de dominio www.example.com en su lista de direcciones y luego llama a getnameinfo () en cada resultado para devolver el nombre canónico de la dirección. En general, esto produce el nombre de host original , a menos que la dirección particular tenga varios nombres, en cuyo caso se devuelve el nombre canónico . En este ejemplo, el nombre de dominio se imprime tres veces, una por cada uno de los tres resultados obtenidos.

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet / in.h>
#include <sys / socket.h>
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#terminara si
int main (vacío)
{ struct addrinfo * resultado; struct addrinfo * res; en terror; / * resuelve el nombre de dominio en una lista de direcciones * / error = getaddrinfo ("www.example.com", NULL, NULL y resultado); if (error! = 0) { si (error == EAI_SYSTEM) { perror ("getaddrinfo"); } demás { fprintf (stderr, "error en getaddrinfo:% s \ n", gai_strerror (error)); } salir (EXIT_FAILURE); } / * recorrer todos los resultados devueltos y realizar una búsqueda inversa * / for (res = resultado; res! = NULL; res = res-> ai_next) { char nombre de host [NI_MAXHOST]; error = getnameinfo (res-> ai_addr, res-> ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0);  if (error! = 0) { fprintf (stderr, "error en getnameinfo:% s \ n", gai_strerror (error)); Seguir; } if (* nombre de host! = '\ 0') printf ("nombre de host:% s \ n", nombre de host); }  freeaddrinfo (resultado); return 0;
}

Ver también

Referencias

  1. ^ https://googleonlinesecurity.blogspot.ca/2016/02/cve-2015-7547-glibc-getaddrinfo-stack.html
  2. ^ Stevens R., Fenner, Rudoff [2003] Programación de red UNIX® Volumen 1, tercera edición: API de redes de sockets. Editorial: Addison-Wesley Professional. Pub. Fecha: 14 de noviembre de 2003 p. 256
  3. ^ http://pubs.opengroup.org/onlinepubs/9699919799/ Consultado el 31 de mayo de 2018
  4. ^ Hajimu UMEMOTO [2000] getaddrinfo.c Acceso desde: https://opensource.apple.com/source/passwordserver_sasl/passwordserver_sasl-14/cyrus_sasl/lib/getaddrinfo.c

enlaces externos

  • RFC 3493, Extensiones de interfaz de socket básicas para IPv6