X-Git-Url: https://git.llucax.com/z.facultad/66.09/etherled.git/blobdiff_plain/cbf2122a2f610a2b92f1dfcb0f554b4bf7c4757e..ab12c9208b125b42786a69291a96959cd295b19d:/src/ip.c diff --git a/src/ip.c b/src/ip.c index 0b4b2e2..f60c3d4 100644 --- a/src/ip.c +++ b/src/ip.c @@ -1,6 +1,7 @@ // vim: set et sw=4 sts=4 : #include "netdev.h" +#include "debug.h" #include "ip.h" /** protocolos soportados */ @@ -29,41 +30,43 @@ bool ip_read_packet_header() { /* 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 */ /* vamos calculando checksum */ sum(WORD(h, ip_packet_len)); /* 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: @@ -73,16 +76,16 @@ bool ip_read_packet_header() 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 @@ -93,8 +96,8 @@ bool ip_read_packet_header() // 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 @@ -102,8 +105,9 @@ bool ip_read_packet_header() } /* verificamos checksum */ if ((uint16)~checksum) - return false; /* checksum malo, drop */ - return true; + ok = false; + netdev_read_end(); + return ok; } void ip_write_packet_header() @@ -114,28 +118,29 @@ 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); + netdev_write_byte(h = 0x00); /* nunca vamos a mandar algo de más de 255 bytes */ + netdev_write_byte(ip_packet_len); sum(WORD(h, ip_packet_len)); /* 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 @@ -151,13 +156,14 @@ void ip_write_packet_header() 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(); }