// vim: set et sw=4 sts=4 :
#include "netdev.h"
+#include "debug.h"
#include "ip.h"
/** protocolos soportados */
{
/* variables utilitarias (iterar y/o buffer) */
byte h, l;
+ bit ok = true;
+ netdev_read_start(IP_HEADER_SIZE);
/* reseteamos checksum */
checksum = 0;
/* versión y tamaño de cabecera vienen en el 1er byte */
- h = netdev_recv_byte();
+ h = netdev_read_byte();
/* sólo soportamos versión 4 */
if ((h >> 4) != 4)
- return false; /* drop */
+ ok = false;
/* tamaño de cabecera */
if ((h & 0x0F) != 5) /* no aceptamos opciones raras =) */
- return false; /* drop */
+ ok = false;
/* ignoramos el TOS y vamos calculando checksum */
- sum(WORD(h, netdev_recv_byte()));
+ sum(WORD(h, netdev_read_byte()));
/* obtenemos tamaño del paquete */
- if (h = netdev_recv_byte()) /* tiene más de 255 bytes (no lo soportamos) */
- return false; /* drop */
- ip_packet_len = netdev_recv_byte(); /* hasta 255 bytes tienen los nuestros */
+ if (h = netdev_read_byte()) /* tiene más de 255 bytes (no lo soportamos) */
+ ok = false;
+ ip_packet_len = netdev_read_byte(); /* hasta 255 bytes tienen los nuestros */
+ /* no puede ser más chico que sus cabeceras */
+ if (ip_packet_len < IP_HEADER_SIZE)
+ ok = false; /* drop */
/* vamos calculando checksum */
sum(WORD(h, ip_packet_len));
+ /* sacamos la cabecera al tamaño */
+ ip_packet_len -= IP_HEADER_SIZE;
/* ignoramos identificación (2 bytes) y vamos calculando checksum */
- sum(netdev_recv_word());
+ sum(netdev_read_word());
/* si tiene prendido el bit de MF (More Fragments, bit 5 del byte, bit 2
* de los flags de la cabecera) o si tiene un offset de fragmento (bits
* del 4 al 0 y todos los bits del byte siguiente), dropeamos (no
* soportamos fragmentación) */
- h = netdev_recv_byte();
- l = netdev_recv_byte();
+ h = netdev_read_byte();
+ l = netdev_read_byte();
if ((h & 0x3F) || l)
- return false; /* drop */
+ ok = false;
/* seguimos calculando checksum */
sum(WORD(h, l));
/* no le damos bola al TTL (no le vamos a hacer lío si ya llegó hasta
* acá el pobre =) */
- h = netdev_recv_byte();
+ h = netdev_read_byte();
/* protocolo (sólo soportamos UDP e ICMP) */
- l = netdev_recv_byte();
+ l = netdev_read_byte();
switch (l)
{
case ICMP:
ip_proto = IP_UDP;
break;
default:
- return false; /* drop */
+ ok = false;
}
/* sigo calculando checksum */
sum(WORD(h, l));
/* obtenemos checksum y seguimos el cálculo */
- sum(netdev_recv_word());
+ sum(netdev_read_word());
/* obtenemos IP de origen (mientras seguimos calculando el checksum) */
for (l = 0; l < IP_ADDR_SIZE; ++l)
{
- ip_addr_remote[l] = netdev_recv_byte();
+ ip_addr_remote[l] = netdev_read_byte();
if (l % 2)
sum(WORD(h, ip_addr_remote[l]));
else
// TODO si soportamos DHCP hay que aceptar broadcasts!
for (l = 0; l < IP_ADDR_SIZE; ++l)
{
- if (ip_addr_local[l] != netdev_recv_byte())
- return false; /* drop (no es para nosotros) */
+ if (ip_addr_local[l] != netdev_read_byte())
+ ok = false;
if (l % 2)
sum(WORD(h, ip_addr_local[l]));
else
}
/* verificamos checksum */
if ((uint16)~checksum)
- return false; /* checksum malo, drop */
- return true;
+ ok = false;
+ netdev_read_end();
+ return ok;
}
void ip_write_packet_header()
static uint16 id;
/* reseteamos checksum */
checksum = 0;
+ netdev_write_start(IP_HEADER_SIZE);
/* versión (4) y tamaño de cabecera (5 words de 4 bytes = 20 bytes) */
- netdev_send_byte(h = 0x45);
+ netdev_write_byte(h = 0x45);
/* TOS (0xc0 = Internetwork Control, 0x00 = normal) */
l = (ip_proto == IP_ICMP) ? 0xc0 : 0x00;
- netdev_send_byte(l);
+ netdev_write_byte(l);
sum(WORD(h, l)); /* actualizamos checksum */
/* escribimos tamaño del paquete */
- netdev_send_byte(h = 0x00); /* nunca vamos a mandar algo de más de 255 bytes */
- netdev_send_byte(ip_packet_len);
- sum(WORD(h, ip_packet_len)); /* actualizamos checksum */
+ netdev_write_byte(h = 0x00); /* nunca vamos a mandar algo de más de 255 bytes */
+ netdev_write_byte(ip_packet_len + IP_HEADER_SIZE);
+ sum(WORD(h, ip_packet_len + IP_HEADER_SIZE)); /* actualizamos checksum */
/* identificación (sirve para reensamblar paquetes) */
- netdev_send_word(id);
+ netdev_write_word(++id);
sum(id); /* actualizamos checksum */
/* pedimos que no se fragmente */
- netdev_send_byte(h = 0x40); /* Don't Fragment (DF) = 1 */
- netdev_send_byte(l = 0x00); /* offset de fragmento = 0 */
+ netdev_write_byte(h = 0x40); /* Don't Fragment (DF) = 1 */
+ netdev_write_byte(l = 0x00); /* offset de fragmento = 0 */
sum(WORD(h, l)); /* actualizamos checksum */
/* TTL de 64 saltos porque está de moda */
- netdev_send_byte(h = 0x40);
+ netdev_write_byte(h = 0x40);
/* protocolo (sólo soportamos UDP e ICMP) */
l = (ip_proto == IP_ICMP) ? ICMP : UDP;
- netdev_send_byte(l);
+ netdev_write_byte(l);
sum(WORD(h, l)); /* actualizamos checksum */
/* checksum: antes de poder escribir el checksum hay que terminar de
* calcularlo según las direcciones IP de origen y destino, así que eso
else
h = ip_addr_remote[l];
/* ahora sí grabamos el checksum */
- netdev_send_word(~checksum);
+ netdev_write_word(~checksum);
/* ahora sí, continuamos poniendo las direcciones */
/* ponemos como dirección IP de origen la nuestra */
for (l = 0; l < IP_ADDR_SIZE; ++l)
- netdev_send_byte(ip_addr_local[l]);
+ netdev_write_byte(ip_addr_local[l]);
/* IP de destino, la remota */
for (l = 0; l < IP_ADDR_SIZE; ++l)
- netdev_send_byte(ip_addr_remote[l]);
+ netdev_write_byte(ip_addr_remote[l]);
+ netdev_write_end();
}