tcp binary protocols checksum

tcp - ¿Cómo interpretas esta frase?



binary protocols (4)

¿Cómo interpretas esta frase?

Checksum
Este es el valor para hacer cero al agregar los 8 bits más bajos desde el encabezado a la suma de comprobación.

Con esta descripción de protocolo:

Protocolo
Consisten en encabezado (1 byte) + longitud de datos (1 byte) + datos de comando (13 bytes) + suma de verificación (1 bytes) + ID de conexión (1 byte).

(Literalmente copié esta descripción del protocolo, así que no sé por qué hay 1 bytes (en plural). Pero puedo decir que es solo un byte)

Aquí hay algunos ejemplos de paquetes TCP de este protocolo:

HE:DL:------------Command Data -------------:CS:ID 02:0d:be:ef:03:06:00:19:d3:02:00:00:60:00:00:ed:01 02:0d:be:ef:03:06:00:cd:d2:02:00:00:20:00:00:7a:01 02:0d:be:ef:03:06:00:10:f6:02:00:ba:30:00:00:49:01 02:0d:be:ef:03:06:00:c8:d8:02:00:20:30:00:00:49:01 // Requested Packets 02:0d:be:ef:03:06:00:13:d3:01:00:02:30:01:00:21:01 02:0d:be:ef:03:06:00:c2:ff:02:00:90:10:00:00:d8:01

Dónde

  • HE es el encabezado (que se fija a 0x02 )
  • DL es DataLength (que siempre es 0x0d , porque los paquetes tienen la misma longitud)
  • CS es el CheckSum (de lo que se trata mi pregunta)
  • ID es el ID de conexión (parece ser siempre 01 en mis pruebas)

No puedo entender cómo se calcula la suma de comprobación. Espero haber dado suficiente información.

Gracias por adelantado.


Creo que solo hay un error en la descripción. Parece que suman todos los bytes entre el encabezado y la suma de comprobación. Y la suma de comprobación es solo un número que borra los 8 bits más bajos. Entonces, para el primer ejemplo, la suma de todos los bytes entre el encabezado y la suma de comprobación es 0x0313. O

0x0313 0000 0011 0001 0011 0x00ED 0000 0000 1110 1101

Cuando está alineado así, puedes ver claramente que estarás poniendo a cero los 8 bits más bajos y regresarás:

0x0400 0000 0100 0000 0000

No especificó un idioma, pero también podría calcular rápidamente su propia suma de comprobación haciendo (0 XOR calculateSum) + 1.


Si suma todos los números hexadecimales en el encabezado, DataLength, CommandData y CheckSum, hace 1024.

Por ejemplo, aquí está la suma del segundo ejemplo (salté el 0x00):

0x02+0x0d+0xbe+0xef+0x03+0x06+0xcd+0xd2+0x02+0x20+0x7a = 1024

Captura de pantalla (suma es solo una función de JavaScript que escribí para sumar los valores hexadecimales automáticamente):

EDITAR: No necesariamente sumará a 1024; en cambio, si es válido, sumará a un número donde los 8 bits inferiores son 0, como 1024 (100 00000000 ), 768 (11 00000000 ) y 1280 (101 00000000 ) .


Solo por diversión, tomé esto como un ejercicio al escribir un analizador binario simple usando Boost Spirit (c ++). Incluí la conversión del formato de pregunta y la verificación de suma de comprobación.

Hice que el analizador sintáctico reconociera la longitud de datos real y la elección arbitraria del contenedor STL para los datos del paquete. Salida a continuación:

#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/karma.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/fusion/include/adapt_struct.hpp> namespace qi=boost::spirit::qi; namespace karma=boost::spirit::karma; namespace phx=boost::phoenix; typedef unsigned char uchar; static const auto inbyte = qi::uint_parser<unsigned char, 16, 2, 2>(); static const auto outbyte = karma::right_align(2,''0'') [ karma::hex ]; // for some reason the alignment doesn''t ''take'' with the above, so HACK: #define outbyte karma::right_align(2,''0'') [ karma::hex ] struct packet_t { enum { HEADER = 0x02 }; uchar checksum, id; typedef std::string data_t; /// the following work without modification: // typedef std::vector<uchar> data_t; // typedef std::list<int> data_t; data_t data; uchar do_checksum() const { return (uchar) -std::accumulate(data.begin(), data.end(), HEADER + data.size()); } bool is_valid() const { return checksum == do_checksum(); } }; BOOST_FUSION_ADAPT_STRUCT(packet_t, (packet_t::data_t, data) (uchar, checksum) (uchar, id)); int main() { static const std::string input = "02:0d:be:ef:03:06:00:19:d3:02:00:00:60:00:00:ed:01/n" "02:0d:be:ef:03:06:00:cd:d2:02:00:00:20:00:00:7a:01/n" "02:0d:be:ef:03:06:00:10:f6:02:00:ba:30:00:00:49:01/n" "02:0d:be:ef:03:06:00:c8:d8:02:00:20:30:00:00:49:01/n" "02:08:c8:d8:02:00:20:30:00:00:49:01/n"; // failure test case // convert hex to bytes std::vector<std::vector<char> > rawpackets; if (!qi::parse(input.begin(), input.end(), (inbyte % '':'') % qi::eol, rawpackets)) { std::cerr << "bailing" << std::endl; return 255; } // std::cout << karma::format(karma::eps << outbyte % '':'' % karma::eol, rawpackets) << std::endl; // analyze & checksum packets for (auto raw: rawpackets) { std::cout << karma::format(karma::eps << outbyte % '':'', raw); using namespace qi; rule<decltype(raw.begin()), packet_t(), locals<uchar> > parser; parser %= byte_(packet_t::HEADER) > omit[ byte_ [ _a = _1 ] ] // datalen > repeat(_a)[byte_] // data > byte_ // checksum > byte_; // id packet_t packet; if (!parse(raw.begin(), raw.end(), parser, packet)) { std::cerr << " bailing" << std::endl; return 255; } std::cout << " do_checksum():/t" << karma::format(outbyte, packet.do_checksum()); std::cout << " is_valid():/t" << std::boolalpha << packet.is_valid() << std::endl; } return 0; }

Salida

02:0d:be:ef:03:06:00:19:d3:02:00:00:60:00:00:ed:01 do_checksum(): ed is_valid(): true 02:0d:be:ef:03:06:00:cd:d2:02:00:00:20:00:00:7a:01 do_checksum(): 7a is_valid(): true 02:0d:be:ef:03:06:00:10:f6:02:00:ba:30:00:00:49:01 do_checksum(): 49 is_valid(): true 02:0d:be:ef:03:06:00:c8:d8:02:00:20:30:00:00:49:01 do_checksum(): 49 is_valid(): true 02:08:c8:d8:02:00:20:30:00:00:49:01 do_checksum(): 04 is_valid(): false


  1. Sume todos los bytes antes del campo de suma de verificación.
  2. Extraiga los 8 bits bajos de la suma
  3. Encuentre el valor ("valor para hacer cero") que, cuando se agrega a la suma calculada se convierte en 0 (es decir, resuelve "x + suma calculada = 0")

De todos modos, este código C calcula la suma correcta para todos sus 4 ejemplos:

uint8_t silly_chksum(const uint8_t *data, size_t len) { size_t i; unsigned int chk = -1; for(i = 0; i < len ;i++) { chk += data[i]; } return ~(chk & 0xff); }