X-Git-Url: https://git.llucax.com/z.facultad/66.09/etherled.git/blobdiff_plain/63fb8e8cb0d82dcef936ae5bee2e3374c907c297..db76f3270c5bee0eb1b5ee71fa1946e8d5132d43:/src/udp.c?ds=sidebyside diff --git a/src/udp.c b/src/udp.c index 9738341..bd6f9c2 100644 --- a/src/udp.c +++ b/src/udp.c @@ -1,5 +1,6 @@ // vim: set et sw=4 sts=4 : +#include "debug.h" #include "netdev.h" #include "ip.h" #include "udp.h" @@ -12,6 +13,8 @@ byte udp_dgram_len; /* para calcular checksum */ static uint16 checksum; +static byte byte_count; +static byte last_byte; /* agrega un word al checksum calculado */ static void sum(uint16 w) @@ -24,8 +27,11 @@ static void sum(uint16 w) bool udp_read_dgram_header() { byte tmp; + bit ok = true; + netdev_read_start(UDP_HEADER_SIZE); /* reseteamos checksum */ checksum = 0; + byte_count = 0; /* el UDP tiene un checksum que incluye parte de la cabecera IP */ /* ip de origen */ sum(WORD(ip_addr_remote[0], ip_addr_remote[1])); @@ -35,50 +41,69 @@ bool udp_read_dgram_header() sum(WORD(ip_addr_local[2], ip_addr_local[3])); /* protocolo expresado en 16 bits (0x11 es UDP) */ sum(0x0011); - /* tamaño del paquete UDP (sin las cabeceras que son 20 bytes) */ - sum(ip_packet_len - 20); + /* tamaño del paquete UDP (IP ya está sin las cabeceras) */ + sum(ip_packet_len); /* de ahora en más todos los datos del checksum corresponden a UDP */ /* puerto origen (remoto) */ - udp_port_remote = netdev_recv_word(); + udp_port_remote = netdev_read_word(); /* agregamos puerto de origen al checksum */ sum(udp_port_remote); /* sólo aceptamos datagramas a nuestro puerto */ - if (netdev_recv_word() != udp_port_local) - return false; /* drop */ + if (netdev_read_word() != udp_port_local) + ok = false; /* drop */ /* agregamos puerto de destino al checksum */ sum(udp_port_local); /* tamaño del datagrama */ - if (tmp = netdev_recv_byte()) /* no soportamos más de 255 bytes */ - return false; /* drop */ - udp_dgram_len = netdev_recv_byte(); /* parte baja */ - if (udp_dgram_len < 8) /* no puede ser más chico que sus cabeceras */ - return false; /* drop */ + if (tmp = netdev_read_byte()) /* no soportamos más de 255 bytes */ + ok = false; /* drop */ + udp_dgram_len = netdev_read_byte(); /* parte baja */ + /* no puede ser más chico que sus cabeceras */ + if (udp_dgram_len < UDP_HEADER_SIZE) + ok = false; /* drop */ /* agregamos tamaño al checksum */ sum(WORD(tmp, udp_dgram_len)); + /* sacamos la cabecera al tamaño */ + udp_dgram_len -= UDP_HEADER_SIZE; /* agregamos checksum al checksum */ - sum(netdev_recv_word()); + sum(netdev_read_word()); /* falta agregar el cuerpo del mensaje para verificar la suma * esto debe hacerlo el protocolo que sigue para poder seguir obteniendo * los datos de la placa de red byte a byte */ + netdev_read_end(); return true; } -uint16 udp_read_word() +byte udp_read_byte() { - uint16 w = netdev_recv_word(); - sum(w); - return w; + byte b; + if (byte_count % 2) // impar, tengo 2, sumo + { + b = netdev_read_byte(); + sum(WORD(last_byte, b)); + } + else // par, guardo para sumar cuando tenga 2 + { + b = netdev_read_byte(); + last_byte = b; + } + ++byte_count; + return b; } bool udp_checksum_ok() { - return (uint16)~checksum; + // Verifico si falta sumar algo (UDP debe sumar de a un word) + if (byte_count % 2) + sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00 + return !(uint16)~checksum; } void udp_write_dgram_header() { + netdev_write_start(UDP_HEADER_SIZE); /* reseteamos checksum */ checksum = 0; + byte_count = 0; /* el UDP tiene un checksum que incluye parte de la cabecera IP */ /* ip de origen */ sum(WORD(ip_addr_remote[0], ip_addr_remote[1])); @@ -88,32 +113,48 @@ void udp_write_dgram_header() sum(WORD(ip_addr_local[2], ip_addr_local[3])); /* protocolo expresado en 16 bits (0x11 es UDP) */ sum(0x0011); - /* tamaño del paquete UDP (IP sin las cabeceras, que son 20 bytes) */ - sum(ip_packet_len - 20); // FIXME + /* tamaño del paquete UDP */ + sum(WORD(0x00, udp_dgram_len + UDP_HEADER_SIZE)); /* puerto origen */ - netdev_send_word(udp_port_local); + netdev_write_word(udp_port_local); sum(udp_port_local); /* puerto destino */ - netdev_send_word(udp_port_remote); + netdev_write_word(udp_port_remote); sum(udp_port_remote); /* tamaño del datagrama */ - netdev_send_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */ - netdev_send_byte(udp_dgram_len); - sum(WORD(0x00, udp_dgram_len)); + netdev_write_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */ + netdev_write_byte(udp_dgram_len + UDP_HEADER_SIZE); + sum(WORD(0x00, udp_dgram_len + UDP_HEADER_SIZE)); /* indicamos que no se usa checksum */ - netdev_send_word(0x0000); + netdev_write_word(0x0000); sum(0x0000); + netdev_write_end(); } -void udp_write_word(uint16 w) +void udp_write_byte(byte b) { - sum(w); - netdev_send_word(w); + if (byte_count % 2) // impar, tengo 2, sumo + { + netdev_write_byte(b); + sum(WORD(last_byte, b)); + } + else // par, guardo para sumar cuando tenga 2 + { + netdev_write_byte(b); + last_byte = b; + } + ++byte_count; } -void udp_write_checksum() +void udp_write_checksum(byte offset) { - // XXX TODO FIXME + // Verifico si falta sumar algo (UDP debe sumar de a un word) + if (byte_count % 2) + sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00 + // Escribo checksum en el buffer de la placa de red + netdev_write_start_at(offset + 6, 2); // 6 bytes de offset hasta el checksum + netdev_write_word((uint16)~checksum); // Guardo checksum + netdev_write_end(); return; }