// vim: set et sw=4 sts=4 :
+#include "debug.h"
#include "netdev.h"
#include "ip.h"
#include "udp.h"
/* 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)
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]));
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_read_word();
if (tmp = netdev_read_byte()) /* no soportamos más de 255 bytes */
ok = false; /* drop */
udp_dgram_len = netdev_read_byte(); /* parte baja */
- if (udp_dgram_len < 8) /* no puede ser más chico que sus cabeceras */
+ /* 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_read_word());
/* falta agregar el cuerpo del mensaje para verificar la suma
return true;
}
-uint16 udp_read_word()
+byte udp_read_byte()
{
- uint16 w = netdev_read_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]));
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_write_word(udp_port_local);
sum(udp_port_local);
sum(udp_port_remote);
/* tamaño del datagrama */
netdev_write_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */
- netdev_write_byte(udp_dgram_len);
- sum(WORD(0x00, udp_dgram_len));
+ 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_write_word(0x0000);
sum(0x0000);
netdev_write_end();
}
-void udp_write_word(uint16 w)
+void udp_write_byte(byte b)
{
- sum(w);
- netdev_write_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;
}