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.