Resumo

  • A RFC 768 atribuiu dois sentidos diferentes ao zero no campo checksum do UDP: um resultado calculado zero era transmitido como 0xFFFF, enquanto 0x0000 indicava que nenhum checksum havia sido gerado.
  • Os requisitos para hosts de 1989 mantiveram a possibilidade de omiti-lo, mas deixaram o cálculo ativo por padrão. O IPv6 depois tornou o checksum obrigatório e, em 2013, uma atualização permitiu um caso de túnel bem delimitado.

Dois zeros em um só campo

Em agosto de 1980, a RFC 768, escrita por Jon Postel, definiu o User Datagram Protocol para que aplicações trocassem datagramas com o mínimo de mecanismos. O UDP não prometia entrega ordenada, proteção contra duplicatas ou confiabilidade. Seu cabeçalho tinha apenas oito octetos: portas de origem e destino, comprimento e checksum, seguidos pelos dados.

O último campo parece simples até que a aritmética cria um caso especial. O UDP usa o checksum de complemento de um de 16 bits, também empregado pelo TCP. O cálculo cobre o cabeçalho e os dados UDP, além de um pseudocabeçalho com os endereços IP de origem e destino, o número do protocolo e o comprimento UDP. Postel explicou que esse pseudocabeçalho ajudava a proteger contra datagramas encaminhados ao destino errado.

No complemento de um, zero tem duas representações: todos os bits em zero e todos os bits em um. A RFC 768 atribuiu funções diferentes a elas na transmissão. Se o cálculo resultasse em zero, o emissor deveria transmitir todos os bits em um. Já um campo enviado com todos os bits em zero significava que nenhum checksum havia sido gerado. Assim, o formato carregava tanto um resultado quanto um pequeno sinal de estado, sem acrescentar um bit de sinalização.

Esse é o recorte histórico deste artigo. “Checksum UDP zero” não era um checksum calculado cujo resultado fosse zero; era a codificação da ausência. Confundir os dois estados poderia levar uma implementação a descartar um datagrama válido ou a tratar a falta de detecção de erro como se fosse uma validação concluída.

Opcional não significava padrão

A especificação original permitia omitir o checksum, por exemplo para depuração ou quando um protocolo de nível superior não se importasse com ele. Nove anos depois, a RFC 1122, sobre requisitos para hosts da Internet, esclareceu a regra operacional. O host deveria implementar a geração e a validação; a aplicação poderia controlar a geração, mas ela deveria ficar ativada por padrão. O receptor também poderia escolher se entregaria à aplicação datagramas sem checksum.

A RFC 1122 apontou ainda um erro comum de implementação: resultado calculado zero deve ser transmitido como 65535, enquanto o campo todo zero quer dizer “ausente”. O documento relatou que algumas aplicações usadas somente em redes locais haviam desativado checksums por eficiência e que muitos erros não detectados tinham sido relatados. Não apresentou contagem, incidentes identificados ou denominador. É evidência de uma preocupação registrada pelos autores da norma, não uma medição de prevalência.

Checksum nunca foi assinatura. O pseudocabeçalho podia detectar alguns erros de encaminhamento e o cálculo, certas corrupções acidentais. Ele não autenticava o emissor, não impedia alteração deliberada nem provava que os dados da aplicação faziam sentido. “Checksum presente” e “pacote confiável” eram afirmações diferentes.

O IPv6 estreitou o limite

A especificação IPv6 de 1998, RFC 2460, tornou obrigatório o checksum UDP. Se o cálculo resultasse em zero, o valor também deveria ser escrito como 0xFFFF; o receptor deveria descartar um datagrama UDP IPv6 cujo campo checksum fosse zero. O antigo marcador opcional de ausência deixou, assim, de ser aceitável no tráfego UDP IPv6 comum.

Depois surgiu um caso específico de desempenho. Em 2013, a RFC 6935 e a RFC 6936 atualizaram o tratamento do IPv6 para certos túneis UDP. Esses túneis podem carregar pacotes que já têm seus próprios controles de integridade, e calcular um checksum externo pode ter custo. A exceção depende de condições de aplicabilidade, do comportamento dos dois pontos finais e da compatibilidade dos equipamentos intermediários; ela não tornou o checksum zero uma opção geral no IPv6.

A sequência das normas mostra que o padrão de bits ficou igual, enquanto o contexto permitido mudou. No IPv4, zero podia indicar ausência, com cálculo ativado por padrão nos requisitos para hosts. No IPv6, a ausência foi primeiro rejeitada e depois readmitida sob condições, para uma função específica de encapsulamento externo. O valor sozinho nunca informava ao receptor se omitir era aceitável; a versão IP e o contexto de uso também importavam.

Fontes