Provided by: manpages-es_1.55-9_all bug

NOMBRE

       packet, PF_PACKET - Interfaz de paquetes a nivel de dispositivo.

SINOPSIS

       #include <sys/socket.h>
       #include <features.h>    /* para el número de versión de glibc */
       #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
       #include <netpacket/packet.h>
       #include <net/ethernet.h>     /* los protocolos de nivel 2 */
       #else
       #include <asm/types.h>
       #include <linux/if_packet.h>
       #include <linux/if_ether.h>   /* los protocolos de nivel 2 */
       #endif

       packet_socket = socket(PF_PACKET, int socket_type, int protocol);

DESCRIPCIÓN

       Los  conectores  de  paquetes  (packet  sockets) se usan para recibir o
       enviar paquetes directos (raw) en el nivel del manejador de dispositivo
       (Nivel  2 de OSI). Permiten al usuario implementar módulos de protocolo
       en el espacio de usuario por encima de la capa física.

       socket_type es o bien SOCK_RAW para  paquetes  directos  incluyendo  la
       cabecera del nivel de enlace o bien SOCK_DGRAM para paquetes preparados
       con la cabecera del nivel de enlace eliminada.  La  información  de  la
       cabecera del nivel de enlace está disponible en un formato común en una
       estructura sockaddr_ll.  protocol es el protocolo IEEE  802.3  con  los
       bytes  en orden de red. Vea el fichero cabecera <linux/if_ether.h> para
       una lista de los protocolos permitidos. Cuando se asigna a protocol  el
       valor  htons(ETH_P_ALL),  se  reciben  todos los protocolos.  Todos los
       paquetes de entrada con el tipo de protocolo  indicado  se  pasarán  al
       conector  de  paquetes  antes  de  que  sean  pasados  a los protocolos
       implementados dentro del núcleo.

       Sólo los procesos con uid efectivo 0 o la capacidad CAP_NET_RAW  pueden
       abrir conectores de paquetes.

       Los  paquetes  SOCK_RAW  se pasan a y desde el manejador de dispositivo
       sin ningún cambio en  los  datos  del  paquete.  Cuando  se  recibe  un
       paquete, la dirección todavía se analiza y se pasa en una estructura de
       dirección sockaddr_ll estándar. Cuando  se  transmite  un  paquete,  el
       buffer  proporcionado por el usuario debería contener la cabecera de la
       capa física. A continuación, ese paquete se encola sin modificar en  la
       tarjeta  de  red  de  la interfaz definida por la dirección de destino.
       Algunos manejadores (‘drivers’) de  dispositivo  siempre  añaden  otras
       cabeceras.   SOCK_RAW  es  similar  pero  no compatible con el obsoleto
       SOCK_PACKET de la versión 2.0 de Linux.

       SOCK_DGRAM opera en  un  nivel  ligeramente  superior.  Se  elimina  la
       cabecera  física  antes  de  que  el  paquete  se  pase al usuario. Los
       paquetes enviados a  través  de  un  conector  de  paquetes  SOCK_DGRAM
       obtienen  una  cabecera adecuada de la capa física según la información
       de la dirección de destino sockaddr_ll, antes de ser encolados.

       Por defecto, todos los paquetes del tipo de protocolo  especificado  se
       pasan  a un conector de paquetes. Para obtener sólo los paquetes de una
       interfaz específica, use bind(2) especificando  una  dirección  en  una
       estructura  struct  sockaddr_ll  para enlazar el conector de paquetes a
       una interfaz. Sólo se usan para propósitos  de  enlace  los  campos  de
       dirección sll_protocol y sll_ifindex.

       La operación connect(2) no está soportada en conectores de paquetes.

       Cuando  se  pasa la opción MSG_TRUNC a recvmsg(2), recv(2), recvfrom(2)
       se devuelve siempre en última instancia la longitud real  del  paquete,
       incluso cuando es mayor que la del buffer.

TIPOS DE DIRECCIONES

       sockaddr_ll  es  una  dirección  de  la  capa  física independiente del
       dispositivo.

              struct sockaddr_ll {
                  unsigned short  sll_family;    /* Siempre es AF_PACKET */
                  unsigned short  sll_protocol;  /* Protocolo de la capa física */
                  int             sll_ifindex;   /* Número de la interfaz */
                  unsigned short  sll_hatype;    /* Tipo de cabecera */
                  unsigned char   sll_pkttype;   /* Tipo de paquete */
                  unsigned char   sll_halen;     /* Longitud de la dirección */
                  unsigned char   sll_addr[8];   /* Dirección de la capa física */
              };

       sll_protocol es el tipo del protocolo ethernet estándar dado  en  orden
       de  red definido en el fichero cabecera linux/if_ether.h.  Su valor por
       defecto es el protocolo del conector.  sll_ifindex es el índice  de  la
       interfaz  (vea  netdevice(7));  el  valor  0  concuerda  con  cualquier
       interfaz (sólo legal para enlazar).  sll_hatype es un tipo ARP  de  los
       definidos  en el fichero cabecera linux/if_arp.h.  sll_pkttype contiene
       el tipo del paquete. Los tipos válidos son PACKET_HOST para un  paquete
       aplicado al anfitrión (host) local, PACKET_BROADCAST para un paquete de
       difusión de la capa física, PACKET_MULTICAST para un paquete enviado  a
       una  dirección multidestino de la capa física, PACKET_OTHERHOST para un
       paquete destinado a otros anfitriones que  ha  sido  capturado  por  el
       manejador  del  dispositivo en modo promiscuo y PACKET_OUTGOING para un
       paquete originado desde el anfitrión local que es devuelto de regreso a
       un  conector de paquetes. Estos tipos sólo tienen sentido para recibir.
       sll_addr y sll_halen contienen la dirección  de  la  capa  física  (por
       ejemplo,  IEEE  802.3)  y su longitud. La interpretación exacta depende
       del dispositivo.

       Cuando se envían paquetes es  suficiente  con  especificar  sll_family,
       sll_addr, sll_halen, sll_ifindex.  Los otros campos deberían estar a 0.
       sll_hatype y sll_pkttype toman sus valores en  los  paquetes  recibidos
       para  su  información.   Para  enlazar  sólo se utilizan sll_protocol y
       sll_ifindex.

OPCIONES DE LOS CONECTORES

       Los conectores de paquetes sólo se pueden usar para configurar el envío
       multidestino  de  la  capa  física  y  el modo promíscuo. Esto funciona
       llamando a setsockopt(2) con SOL_PACKET, para un conector de  paquetes,
       y  una  de  las  opciones PACKET_ADD_MEMBERSHIP para añadir un enlace o
       PACKET_DROP_MEMBERSHIP para eliminarlo.  Ambas esperan  una  estructura
       packet_mreq como argumento:

              struct packet_mreq
              {
                  int             mr_ifindex;    /* índice de la interfaz */
                  unsigned short  mr_type;       /* acción */
                  unsigned short  mr_alen;       /* longitud de la dirección */
                  unsigned char   mr_address[8]; /* dirección de la capa física */
              };

       mr_ifindex contien el índice de la interfaz cuyo estado debe cambiarse.
       El parámetro mr_type indica la acción  a  realizar.   PACKET_MR_PROMISC
       habilita  la  recepción de todos los paquetes sobre un medio compartido
       (conocido normalmente  como  ‘‘modo  promiscuo’’),  PACKET_MR_MULTICAST
       enlaza  el conector al grupo multidestino de la capa física indicado en
       mr_address y mr_alen, y PACKET_MR_ALLMULTI configura el  conector  para
       recibir todos los paquetes multidestino que lleguen a la interfaz.

       Además,   se   pueden  usar  las  ioctls  tradicionales,  SIOCSIFFLAGS,
       SIOCADDMULTI y SIOCDELMULTI, para el mismo propósito.

IOCTLS

       SIOCGSTAMP se puede usar para recibir la marca  de  tiempo  del  último
       paquete recibido.  El argumento es una esctructura struct timeval.

       Además,  todas  las  ioctls  estándares  definidas  en  netdevice(7)  y
       socket(7) son válidas en los conectores de paquetes.

MANEJO DE ERRORES

       Los conectores de paquetes no manejan otros errores que  los  ocurridos
       al pasar el paquete al manejador del dispositivo. No poseen el concepto
       de error pendiente.

COMPATIBILIDAD

       En la versión 2.0 de Linux, la única forma de obtener  un  conector  de
       paquetes  era  llamando a socket(PF_INET, SOCK_PACKET, protocol).  Esto
       todavía está soportado pero se desaprueba  fuertemente.   La  principal
       diferencia  entre  los dos métodos es que SOCK_PACKET, para especificar
       una interfaz, usa la antigua struct  sockaddr_pkt  que  no  proporciona
       independencia de la capa física.

              struct sockaddr_pkt
              {
                  unsigned short  spkt_family;
                  unsigned char   spkt_device[14];
                  unsigned short  spkt_protocol;
              };

       spkt_family  contiene el tipo del dispositivo, spkt_protocol es el tipo
       del protocolo  IEEE  802.3  de  los  definidos  en  <sys/if_ether.h>  y
       spkt_device es el nombre del dispositivo dado como una cadena terminada
       en un nulo, por ejemplo, eth0.

       Esta estructura está obsoleta y no debería usarse en código nuevo.

OBSERVACIONES

       Se sugiere que los programas transportables usen PF_PACKET a través  de
       pcap(3),  aunque  esto sólo cubre un subconjunto de las características
       de PF_PACKET.

       Los conectores de paquetes SOCK_DGRAM no intentan crear o  analizar  la
       cabecera  LLC  IEEE  802.2  para  una  trama  IEEE  802.3.   Cuando  se
       especifica ETH_P_802_3 como protocolo para enviar, el  núcleo  crea  la
       trama  802.3  y  rellena  el  campo  de  longitud. El usuario tiene que
       proporcionar  la  cabecera  LLC  para  obtener  un  paquete  totalmente
       conforme.  Los  paquetes  802.3  de entrada no son multiplexados en los
       campos DSAP/SSAP del protocolo. En su lugar,  se  entregan  al  usuario
       como  protocolo  ETH_P_802_2 con la cabecera LLC añadida. Por tanto, es
       imposible enlazar con ETH_P_802_3.  Enlace en su lugar con  ETH_P_802_2
       y  haga  usted  mismo  la multiplexación del protocolo. Para enviar por
       omisión se utiliza la encapsulación estándar Ethernet DIX con  el  dato
       del protocolo lleno.

       Los conectores de paquetes no están sujetos a las cadenas de entrada ni
       de salida del cortafuegos.

ERRORES

       ENETDOWN
              La interfaz no está activa.

       ENOTCONN
              No se ha pasado una dirección de interfaz.

       ENODEV Nombre de dispositivo o índice de interfaz, especificados en  la
              dirección de interfaz, desconocidos.

       EMSGSIZE
              El paquete es más grande que la MTU de la interfaz.

       ENOBUFS
              No hay suficiente memoria para colocar el paquete.

       EFAULT El usuario ha pasado una dirección de memoria inválida.

       EINVAL Argumento inválido.

       ENXIO  La  dirección de interfaz contiene un índice de interfaz ilegal.

       EPERM  El usuario no tiene privilegios suficientes para llevar  a  cabo
              esta operación.

       EADDRNOTAVAIL
              Se ha pasado una dirección desconocida de grupo multidestino.

       ENOENT No se ha recibido ningún paquete.

              Además,  el manejador de bajo nivel puede generar otros errores.

VERSIONES

       PF_PACKET es una nueva característica de la versión 2.2 de  Linux.  Las
       primeras versiones de Linux sólo soportaban SOCK_PACKET.

FALLOS

       glibc  2.1  no  posee  una macro "define" para SOL_PACKET.  La solución
       sugerida es usar
              #ifndef SOL_PACKET
              #define SOL_PACKET 263
              #endif
       Esto se soluciona en versiones  posteriores  de  glibc.  Este  problema
       tampoco se produce en sistemas libc5.

       El  tratamiento del IEEE 802.2/803.3 LLC se podría considerar un fallo.

       No se han documentado los filtros de los conectores.

       La extensión MSG_TRUNC de recvmsg es una solución chapucera  y  debería
       ser  reemplazada por un mensaje de control.  Actualmente no hay ninguna
       manera de obtener la dirección de  destino  original  de  paquetes  via
       SOCK_DGRAM.

CREDITOS

       Esta  página  de  manual  fue  escrita  por  Andi Kleen con la ayuda de
       Matthew Wilcox.

       Alexey Kuznetsov implementó la característica PF_PACKET de  la  versión
       2.2 de Linux basándose en el código de Alan Cox y otros.

VÉASE TAMBIÉN

       ip(7), socket(7), socket(2), raw(7), pcap(3)

       RFC 894 for the standard IP Ethernet encapsulation.

       RFC 1700 for the IEEE 802.3 IP encapsulation.

       El  fichero  cabecera <linux/if_ether.h> para los protocolos de la capa
       física.