Provided by: manpages-es_1.55-4_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 imple‐
        mentados 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 paque‐
        tes 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.
        sockaddr_ll  es  una dirección de la capa física independiente del dis‐
        positivo.
 
               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 inter‐
        faz (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.
        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 lla‐
        mando 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, SIOCADD     
        MULTI 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.
        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 especi‐
        fica 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 paque‐
        tes  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  proto‐
        colo 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 tam‐
        poco 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.
        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.