Provided by: manpages-es_1.55-10_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.

Página man de Linux                               29 abril 1999                                        PACKET(7)