NOME¶
raw, SOCK_RAW - Sockets IPv4 raw
SINOPSE¶
#include <sys/socket.h>
#include <netinet/in.h>
raw_socket = socket(PF_INET, SOCK_RAW, int protocol);
DESCRIÇÃO¶
Sockets raw (não processados) permitem a implementação de
novos protocolos sob o IPv4. Um socket raw recebe ou envia o datagrama bruto,
sem incluir cabeçalhos de link.
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.
Apenas processos com user id efetivo de 0 ou com capacidade
CAP_NET_RAW
podem abrir sockets raw.
Todos os pacotes ou erros relacionados ao número de
protocolo
especificado para o socket raw são passados para este socket. Para uma
lista dos protocolos permitidos consulte o RFC 1700 e
getprotobyname(3).
Um protocolo
IPPROTO_RAW implica que o
IP_HDRINCL está
habilitado e recebe todos os protocolos IP. transmitir não é
permitido.
Cabeçalhos IP são midificados quando enviados pelo
IP_HDRINCL |
|
IP Checksum |
Sempre preenchido. |
Source Address |
Preenchido quando zero. |
Packet Id |
Preenchido quando zero. |
Total Length |
Sempre preenchido. |
Se for especificado
IP_HDRINCL e o cabeçalho IP tiver um
endereço de destino diferente de zero, este endereço é
usado para rotear o pacote. Quando for especificado ,B 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 socker raw com
setsockopt(2); Ver
ip(7) para mais informações.
No 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 raw 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 raw que tenham sido
atrelados ao seu protocolo antes de ser passado para outros handlers deste
protocolo (ex. módulos de protocolo do kernel).
Sockets raw 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 deve ser sempre ajustado
para zero. (ver PROBLEMAS) O campo
sin_port contém o
número do protocolo de pacotes recebidos. Ver a lista de protocolos IP
válidos em
<netinet/in.h>
OPÇÕES DE SOCKET¶
As opções de sockets raw podem ser ajustadas com
setsockopt(2) ou lidas com
getsockopt(2) passando-se o flag
designador de família
SOL_RAW
- ICMP_FILTER
- Habilita um filtro especial para sockets raw ligados ao protocolo
IPPROTO_ICMP Cada bit deste campo designa um tipo de mensagem ICMP
a ser excluída. O default é não filtrar nenhuma
mensagem ICMP.
Além disso, todas as opções de socket
SOL_IP
ip(7) válidas para sockets de datagrama são suportadas.
NOTAS¶
Sockets raw fragmentam um pacote cujo tamanho total exceda o MTU da interface
(veja, no entanto, a seção PROBLEMAS). Uma alternativa mais
rápida e em sintonia com a rede é implementar a pesquisa do MTU
do caminho na seção
IP_PMTU_DISCOVER do
ip(7).
Um socket raw 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
RAW pode ser associado a um dispositivo de rede específico usando
SO_BINDTODEVICE; Ver
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
Se você quiser receber todos os pacotes ICMP de um socket de datagrama,
é muitas vezes melhor usar
IP_RECVERR neste socket. Ver
ip(7).
Os sockets raw 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) raw. 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 raw não se comportam
assim.
Os sockets RAW geralmente são pouco portáveis, devendo ser
evitados em programas que se deseje portar.
Os sockets raw enviados lêem o protocolo de
sin_port; Esta
capacidade foi perdida no linux 2.2. A solução é usar
IP_HDRINCL.
MANUSEIO DE ERROS¶
Erros originários da rede só são passados para o
usuário quando o socket está conectado ou o flag
IP_RECVERR está habilitado. 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¶
- EMSGSIZE
- O pacote é grande demais. Ou a pesquisa de MTU do caminho
está habilitada (com o sinalizador IP_PMTU_DISCOVER ) ou o
tamanho do pacote excede o máximo de 64KB permitido pelo IPv4.
- EACCES
- O usuário tentou transmitir para um endereço de broadcast
sem que o socket tivesse um flag de broadcast.
- EPROTO
- Um mensagem ICMP chegou reportando um erro de parâmetros.
- EFAULT
- Foi fornecido um endereço de memória inválido.
- EOPNOTSUPP
- Um flag inválido foi passado para uma chamada de socket (como
MSG_OOB).
- EINVAL
- Argumetno inválido.
- EPERM
- O usuário não tem permissão para abrir sockets raw.
Apenas processos com user if efetivo de 0 ou o atributo CAP_NET_RAW
podem fazer isto.
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 raw, que é habilitada com o flag SO_BSDCOMPAT. Isto foi
retirado do 2.2.
PROBLEMAS¶
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 à
interface MTU. Isto é uma limitação do linux 2.2.
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.
AUTORES¶
Esta página foi escrita por Andi Kleen.
VEJA TAMBÉM¶
ip(7),
socket(7),
recvmsg(2),
sendmsg(2).
RFC1191 para pesquisa do MTU do caminho.
RFC791 e o arquivo
<linux/ip.h> para o protocolo IP.
TRADUZIDO POR LDP-BR em 21/08/2000.¶
Paulo César Mendes <drps@ism.com.br> (tradução)
André L. Fassone Canova <lonelywolf@blv.com.br>
(revisão)