raw - Conectores directos (raw) IPv4 de Linux
#include <sys/socket.h>
#include <netinet/in.h>
raw_socket = socket(AF_INET, SOCK_RAW, int protocolo);
Los conectores directos permiten implementar nuevos protocolos IPv4 en el
espacio de usuario. Un conector directo recibe o envía el datagrama
crudo sin incluir cabeceras del nivel de enlace.
La capa IPv4 genera una cabecera IP cuando se envía un paquete, a menos
que se active la opción
IP_HDRINCL en el conector. Cuando se
activa, el paquete debe contener una cabecera IP. En la recepción, la
cabecera IP siempre está incluida en el paquete.
Para crea un conector directo, un proceso tiene que poseer la capacidad
CAP_NET_RAW en la red y con el usuario que lo ejecute.
Todos los paquetes o errores cuyo protocolo coinciden con el número de
protocolo especificado por el conector directo, se pasan a este
conector. Para una lista de los protocolos permitidos vea los números
asignados en
http://www.iana.org/assignments/protocol-numbers/
y
getprotobyname(3).
Un protocolo
IPPROTO_RAW implica que
IP_HDRINCL está activa
y preparada para enviar cualquier protocolo IP especificado en la cabecera
pasada. Recibir todos los protocolos IP via
IPPROTO_RAW no es posible
con conectores directos.
Campos de cabecera IP modificados en el envío por
IP_HDRINCL
|
|
Suma de comprobación IP |
Siempre se rellena |
Dirección fuente |
Se rellena cuando es cero |
Identificador del paquete |
Se rellena cuando es cero |
Longitud total |
Siempre se rellena |
Si se especifica
IP_HDRINCL y la cabecera IP tiene una dirección
de destino distinta de cero, la dirección de destino del conector se
utiliza para enrutar el paquete. Cuando se especifica
MSG_DONTROUTE, la
dirección de destino debe referirse a una interfaz local, de lo
contrario, se realiza una búsqueda en la tabla de enrutamiento, aunque
se ignoran las rutas que se dirigen a enrutadores.
Si no se activa
IP_HDRINCL, se pueden configurar las opciones de la
cabecera IP de los conectores directos con
setsockopt(2). Vea
ip(7) para más información.
A partir de Linux 2.2 todas las opciones y campos de las cabeceras IP se pueden
configurar usando las opciones de los conectores IP. Esto significa que los
conectores directos suelen ser necesarios sólo para protocolos nuevos o
protocolos sin interfaz de usuario (como ICMP).
Cuando se recibe un paquete, se pasa a cualquier conector directo que haya sido
asociado a su protocolo antes de que sea pasado al manejador de cualquier otro
protocolo (por ejemplo, los módulos de protocolo del núcleo).
Para el envío y la recepción de datagramas (
sendto(2),
recvfrom(2) y similar) los conectores directos usan la estructura de
direcciones estándar
sockaddr_in definida en
ip(7). El
campo
sin_port se podría usar para especificar el número
de protocolo IP, pero en Linux 2.2 se ignora al enviar y siempre
debería valer 0 (vea FALLOS). Para los paquetes de entrada, a
sin_port se le asigna el protocolo del paquete. Vea el fichero cabecera
<netinet/in.h> para protocolos IP válidos.
Las opciones de los conectores directos se pueden configurar con
setsockopt(2) y leer con
getsockopt(2), pasando la opción
de familia
IPPROTO_RAW.
- ICMP_FILTER
- Activa un filtro especial para los conectores directos
asociados al protocolo IPPROTO_ICMP. El valor tiene un bit activo
para cada tipo de mensaje ICMP que debe filtrarse. Por defecto, no se
filtra ningún mensaje ICMP.
Además, todas las opciones
ip(7) del conector
IPPROTO_IP
válidas para conectores de datagramas están implementadas.
Sólo se pasan al usuario los errores generados por la red cuando el
conector está conectado o está activa la opción
IP_RECVERR. Para conectores conectados, sólo se pasan
EMSGSIZE y
EPROTO por compatibilidad. Con
IP_RECVERR
todos los errores de red se guardan en la cola de errores.
- EACCES
- El usuario ha intentado enviar a una dirección de
difusión sin tener activa la opción de difusión en el
conector.
- EFAULT
- Se ha pasado una dirección de memoria
inválida.
- EINVAL
- Argumento inválido.
- EMSGSIZE
- Paquete demasiado grande. O bien el descubrimiento del MTU
de la ruta está activo (la opción IP_MTU_DISCOVER de
los conectores) o bien el tamaño del paquete excede el
máximo tamaño de 64 kB permitido por IPv4.
- EOPNOTSUPP
- Se ha pasado a la llamada socket una opción
inválida (como MSG_OOB).
- EPERM
- El usuario no tiene permiso para abrir conectores directos.
Sólo los procesos con un identificador de usuario efectivo de 0 o
el atributo CAP_NET_RAW pueden hacerlo.
- EPROTO
- Ha llegado un error ICMP informando de un problema de
parámetros.
IP_RECVERR y
ICMP_FILTER son nuevos en la versión 2.2 de
Linux. Ambos son extensiones de Linux y no deberían usarse en programas
transportables.
La versión 2.0 de Linux activaba cierta compatibilidad con BSD en el
código de los conectores directos cuando se activaba la opción
SO_BSDCOMPAT. Ésto se ha eliminado en la versión 2.2.
Por defecto, los conectores directos averiguan el MTU de la ruta (unidad
máxima de transmisión) por lo que el núcleo realiza un
seguimiento del MTU hacia una IP de destino emitiendo
EMSGSIZE cuando
la escritura deun conector directo lo sobrepasa. Cuando esto ocurre, la
aplicación deberá reducir el tamaño de sus paquetes. La
averiguación del MTU de las rutas puede desactivarse mediante la
opción
IP_MTU_DISCOVER del conector o en el archivo
/proc/sys/net/ipv4/ip_no_pmtu_disc, consulte
ip(7) para
más información. Si está desactivada, los conectores
directores fragmentarán los paquetes salientes que sobrepasen el MTU de
la interfaz. Por razones de rendimiento y fiabilidad, no se recomienda
desactivarlo.
Se puede asociar un conector directo a una dirección local concreta
mediante la llamada
bind(2). Si no está asociado, se
recibirán todos los paquetes con el protocolo IP especificado.
Además, se puede asociar un conector directo a un dispositivo de red
específico usando
SO_BINDTODEVICE. Vea
socket(7).
Un conector
IPPROTO_RAW es sólo de envío. Si verdaderamente
quiere recibir todos los paquetes IP, use un conector
packet(7) con el
protocolo
ETH_P_IP. Dése cuenta que, a diferencia de los
conectores directos, los conectores de paquete no reensamblan fragmentos IP.
Si quiere recibir todos los paquetes ICMP para un conector de datagramas,
normalmente es mejor usar
IP_RECVERR en ese conector particular. Vea
ip(7).
Los conectores directos pueden interceptar todos los protocolos IP de Linux,
incluso protocolos como ICMP o TCP que poseen un módulo de protocolo
dentro del núcleo. En este caso, los paquetes se pasan tanto al
módulo del núcleo como al conector (o conectores) directo. No se
debería confiar en esto en programas transportables ya que muchas otras
implementaciones de conectores BSD tienen limitaciones aquí.
Linux nunca cambia las cabeceras pasadas por el usuario (salvo para rellenar
algunos campos de valor 0 como se ha descrito en
IP_HDRINCL). Esto es
diferente de muchas otras implementaciones de conectores directos.
Generalmente, los conectores directos son bastante específicos y
deberían evitarse en programas que pretendan ser portables.
En el envío a través de conectores directos se debería
tomar el protocolo IP de
sin_port. Esta capacidad se perdió en
Linux 2.2. La forma de solucionar esto es usar
IP_HDRINCL.
No se han descrito las extensiones de proxy transparente.
Cuando se activa la opción
IP_HDRINCL, los datagramas no se
fragmentan y están limitados por la MTU de la interfaz.
La posibilidad de especificar el protocolo IP en
sin_port durante el
envío desapareció en Linux 2.2. Siempre se usa el protocolo al
que se enlazó el conector o el que se especificó en la llamada
inicial a
socket(2).
recvmsg(2),
sendmsg(2),
capabilities(7),
ip(7),
socket(7)
RFC 1191 para el descubrimiento del MTU de la ruta.
RFC 791 y el fichero cabecera
<linux/ip.h> para el
protocolo IP.
La traducción al español de esta página del manual fue
creada por Juan Piernas <
[email protected]> y Marcos Fouces
<
[email protected]>
Esta traducción es documentación libre; lea la
GNU
General Public License Version 3 o posterior con respecto a las
condiciones de copyright. No existe NINGUNA RESPONSABILIDAD.
Si encuentra algún error en la traducción de esta página
del manual, envíe un correo electrónico a
[email protected]