raw(7) | Miscellaneous Information Manual | raw(7) |
NOME
raw - 'sockets' IPv4 diretos
SINOPSE
#include <sys/socket.h> #include <netinet/in.h> raw_socket = socket(AF_INET, SOCK_RAW, int protocolo);
DESCRIÇÃO
Os sockets diretos (não processados) permitem a implementação de novos protocolos sob o IPv4. Um socket direto recebe ou envia o datagrama bruto, sem incluir cabeçalhos de ligação.
A camada IPv4 gera um cabeçalho IP ao enviar um pacote a menos que se ative a opção IP_HDRINCL do socket. Quando ela está habilitada, o pacote deve conter um cabeçalho IP. Um pacote IP que seja recebido terá sempre o cabeçalho IP.
Para criar um socket direto, um processo deve ter a capacidade CAP_NET_RAW no espaço de nomes do usuário que governa seu espaço de nomes de rede.
Todos os pacotes ou erros relacionados ao número de protocolo especificado para o socket direto são passados para este socket. Para uma lista dos protocolos atribuídos em http://www.iana.org/assignments/protocol-numbers/ e getprotobyname(3).
Um protocolo de IPPROTO_RAW implica que o IP_HDRINCL está habilitado e é capaz de enviar qualquer protocolo IP que é especificado no cabeçalho passado. Receber de todos os protocolos IP via IPPROTO_RAW não é possível usando sockets diretos.
Cabeçalhos IP são modificados quando enviados pelo IP_HDRINCL | |
Soma de verificação do IP | Sempre preenchido |
Endereço de origem | Preenchido quando zero |
ID do pacote | Preenchido quando zero |
Tamanho total | Sempre preenchido |
Se for especificado IP_HDRINCL e o cabeçalho IP tiver um endereço de destino diferente de zero, este endereço de destino é usado para rotear o pacote. Quando for especificado MSG_DONTROUTE o endereço de destino deve apontar para uma interface local, caso contrário é feita uma consulta à tabela de roteamento, mas as rotas com gateways são ignoradas.
Se não for especificado IP_HDRINCL as opções do cabeçalho IP podem ser ajustadas nos sockets diretos com setsockopt(2); ver ip(7) para mais informações.
A partir do Linux 2.2, todos as opções e campos de cabeçalho IP podem ser configuradas usando as opções para sockets IP. Isto significa que os sockets diretos normalmente só são necessários para protocolos novos ou protocolos sem interface de usuário, como o ICMP.
Um pacote recebido é passado para quaisquer sockets diretos que tenham sido atrelados ao seu protocolo antes de ser passado para outros manipuladores deste protocolo (ex. módulos de protocolo do kernel).
Formato de endereço
Para enviar e receber datagramas (sendto(2), recvfrom(2) e similares), os sockets direto usam a estrutura de endereço padrão sockaddr_in definida em ip(7). O campo sin_port pode ser usado para especificar o número do protocolo IP, mas é ignorado pelo Linux 2.2 e versões mais novas, e deve ser sempre ajustado para zero (veja BUGS). Para pacotes de entrada. sin_port é definido com zero.
Opções de socket
As opções de sockets diretos podem ser ajustadas com setsockopt(2) ou lidas com getsockopt(2) passando-se o sinalizador designador de família IPPROTO_RAW.
- ICMP_FILTER
- Habilita um filtro especial para sockets diretos ligados ao protocolo IPPROTO_ICMP. Cada bit deste campo designa um tipo de mensagem ICMP a ser excluída. O padrão é não filtrar nenhuma mensagem ICMP.
Além disso, todas as opções de socket IPPROTO_IP ip(7) válidas para sockets de datagrama são suportadas.
Tratamento de erros
Erros originários da rede só são passados para o usuário quando o socket está conectado ou o sinalizador IP_RECVERR está habilitado. Os sockets conectados recebem apenas EMSGSIZE e EPROTO para manter a compatibilidade. Com IP_RECVERR todos os erros de rede são enviados para a fila de erros.
ERROS
- EACCES
- O usuário tentou transmitir para um endereço de broadcast sem que o socket tivesse um sinalizador de broadcast.
- EFAULT
- Foi fornecido um endereço de memória inválido.
- EINVAL
- Argumento inválido.
- EMSGSIZE
- O pacote é grande demais. Ou a pesquisa de MTU do caminho está habilitada (com o sinalizador IP_MTU_DISCOVER) ou o tamanho do pacote excede o máximo de 64 kB permitido pelo IPv4.
- EOPNOTSUPP
- Um sinalizador inválido foi passado para uma chamada de socket (como MSG_OOB).
- EPERM
- O usuário não tem permissão para abrir sockets diretos. Apenas processos com ID efetivo de usuário com valor 0 ou o atributo CAP_NET_RAW podem fazer isto.
- EPROTO
- Um mensagem ICMP chegou reportando um erro de parâmetros.
VERSÕES
IP_RECVERR e ICMP_FILTER surgiram no Linux 2.2. São extensões Linux e não devem ser usadas em programas portáveis.
O Linux 2.0 criou alguma compatibilidade "bug a bug" com o BSD no código dos sockets diretos, quandoa opção de socket SO_BSDCOMPAT estava configurada. Desde o Linux 2.2, essa opção não possui mais efeito.
NOTAS
Por padrão, os sockets diretos fazem a pesquisa de MTU (Unidade Máxima de Transmissão) do caminho. Isso significa que o kernel rastreará o MTU para um endereço IP de destino específico e retornará EMSGSIZE quando uma gravação de pacote direto o exceder. Quando isso acontecer, o aplicativo deverá diminuir o tamanho do pacote. A pesquisa de MTU do caminho também pode ser desativada usando a opção de socket IP_MTU_DISCOVER ou o arquivo /proc/sys/net/ipv4/ip_no_pmtu_disc, consulte ip(7) para obter detalhes. Quando desativados, os soquetes brutos fragmentarão os pacotes de saída que excedem o MTU da interface. No entanto, desativá-lo não é recomendado por motivos de desempenho e confiabilidade.
Um socket direto pode ser ligado a um endereço local específico usando a chamada bind(2). Caso contrário, todos os pacotes com o protocolo IP especificado são recebidos. Além disso, um socket direto pode ser associado a um dispositivo de rede específico usando SO_BINDTODEVICE; veja socket(7).
Um socket IPPROTO_RAW é transmissor apenas. Se você realmente quiser receber todos os pacotes IP, use um socket packet(7) com o protocolo ETH_P_IP. Observe que pacotes de sockets não remontam fragmentos IP, ao contrário dos sockets diretos.
Se você quiser receber todos os pacotes ICMP de um socket de datagrama, é muitas vezes melhor usar IP_RECVERR neste socket. Veja ip(7).
Os sockets diretos podem ler todos os protocolos IP no Linux, mesmo protocolos como ICMP ou TCP, que têm um módulo de protocolo no kernel. Neste caso, os pacotes são passados tanto para o módulo do kernel e para o(s) socket(s) diretos. Não se deve contar com isso em programas portáveis, porque muitas implementações de sockets em BSD têm limitações aqui.
O Linux nunca modifica cabeçalhos enviados pelo usuário, exceto para preencher alguns campos zerados conforme descrito em IP_HDRINCL. Muitas implementações de sockets diretos não se comportam assim.
Os sockets diretos geralmente são pouco portáveis, devendo ser evitados em programas que se deseje portar.
Os sockets diretos enviados leem o protocolo IP de sin_port; esta capacidade foi perdida no Linux 2.2. A solução é usar IP_HDRINCL.
BUGS
Extensões transparentes de proxy não estão incluídas.
Quando a opção IP_HDRINCL está habilitada os datagramas não serão fragmentados, e ficam limitados ao MTU da interface.
O ajuste do protocolo IP para envio no campo sin_port foi perdido no Linux 2.2. O protocolo que foi atrelado a este socket ou que foi especificado na chamada inicial à socket(2) é usado sempre.
VEJA TAMBÉM
recvmsg(2), sendmsg(2), capabilities(7), ip(7), socket(7)
RFC 1191 para pesquisa de MTU do caminho. RFC 791 e arquivo de cabeçalho <linux/ip.h> para o protocolo IP.
TRADUÇÃO
A tradução para português brasileiro desta página man foi criada por Paulo César Mendes <drpc@ism.com.br>, André Luiz Fassone <lonely_wolf@ig.com.br> e Rafael Fontenelle <rafaelff@gnome.org>.
Esta tradução é uma documentação livre; leia a Licença Pública Geral GNU Versão 3 ou posterior para as condições de direitos autorais. Nenhuma responsabilidade é aceita.
Se você encontrar algum erro na tradução desta página de manual, envie um e-mail para a lista de discussão de tradutores.
2 maio 2024 | Linux man-pages 6.8 |