UDP
- El Protocolo de Datagramas de Usuario (UDP) es un protocolo de transporte ligero, parte del conjunto TCP/IP.
- A diferencia de TCP, no proporciona mecanismos de comprobación de errores ni garantiza la entrega.
DNS
El Sistema de Nombres de Dominio (DNS) traduce nombres de dominio legibles
para humanos (como example.com) en direcciones IP entendibles
por los sistemas de red.
Para qué sirve: Facilita la navegación en Internet al permitir que los usuarios usen nombres amigables en lugar de memorizar direcciones IP numéricas.
Ejemplo en lenguaje C
Ejemplo en lenguaje C, que implementa parte de los estándares relacionados con UDP y DNS. Para los demás protocolos (como IMAP), necesitarías bibliotecas específicas que cumplan con los estándares de la IETF:
Código: Cliente DNS usando UDP
Este programa consulta un servidor DNS para resolver un nombre de dominio en su dirección IP.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define DNS_SERVER "8.8.8.8" // Servidor DNS público de Google
#define DNS_PORT 53 // Puerto estándar de DNS
#define BUFFER_SIZE 512 // Tamaño del buffer para mensajes DNS
void build_dns_query(unsigned char *buffer, const char *hostname);
void parse_dns_response(unsigned char *buffer);
int main() {
int sockfd;
struct sockaddr_in server_addr;
unsigned char buffer[BUFFER_SIZE];
// Crear socket UDP
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Error al crear socket");
exit(EXIT_FAILURE);
}
// Configurar dirección del servidor DNS
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(DNS_PORT);
server_addr.sin_addr.s_addr = inet_addr(DNS_SERVER);
// Construir consulta DNS
const char *hostname = "example.com"; // Dominio a resolver
memset(buffer, 0, BUFFER_SIZE);
build_dns_query(buffer, hostname);
// Enviar consulta al servidor DNS
if (sendto(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Error al enviar consulta DNS");
close(sockfd);
exit(EXIT_FAILURE);
}
// Recibir respuesta del servidor DNS
socklen_t addr_len = sizeof(server_addr);
if (recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len) < 0) {
perror("Error al recibir respuesta DNS");
close(sockfd);
exit(EXIT_FAILURE);
}
// Parsear respuesta DNS
parse_dns_response(buffer);
// Cerrar socket
close(sockfd);
return 0;
}
void build_dns_query(unsigned char *buffer, const char *hostname) {
// Cabecera DNS
buffer[0] = 0xAB; // ID de la consulta
buffer[1] = 0xCD;
buffer[2] = 0x01; // Flags: consulta estándar
buffer[3] = 0x00;
buffer[4] = 0x00; // Número de preguntas
buffer[5] = 0x01;
buffer[6] = 0x00; // Respuestas, autoritativas, adicionales
buffer[7] = 0x00;
buffer[8] = 0x00;
buffer[9] = 0x00;
// Pregunta DNS
unsigned char *qname = &buffer[12];
const char *token = strtok((char *)hostname, ".");
while (token) {
size_t len = strlen(token);
*qname++ = len;
memcpy(qname, token, len);
qname += len;
token = strtok(NULL, ".");
}
*qname++ = 0x00; // Fin del nombre de dominio
buffer[qname - buffer] = 0x00; // Tipo de consulta A (dirección IPv4)
buffer[qname - buffer + 1] = 0x01;
buffer[qname - buffer + 2] = 0x00; // Clase IN (Internet)
buffer[qname - buffer + 3] = 0x01;
}
void parse_dns_response(unsigned char *buffer) {
printf("Respuesta DNS recibida.\n");
// Aquí puedes implementar lógica para analizar la respuesta DNS
// y extraer direcciones IP, CNAME, etc.
}
Explicación del código
- Construcción de una consulta DNS: El programa construye un paquete DNS, que incluye la cabecera y el nombre de dominio a resolver.
- Comunicación UDP: Utiliza sockets UDP para enviar y recibir paquetes DNS hacia/desde el servidor.
- Parseo de respuesta DNS: Después de recibir la respuesta, el programa puede analizarla para extraer la dirección IP asociada al dominio.
