]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/c/ip.c
Arregla net.h y agrega net.c que faltaba.
[z.facultad/66.09/etherled.git] / src / c / ip.c
1 #include "ip.h"
2
3 /** protocolos soportados */
4 enum { ICMP = 0x01, UDP = 0x11 };
5
6 extern byte ip_addr_local[IP_ADDR_SIZE];
7
8 extern byte ip_addr_remote[IP_ADDR_SIZE];
9
10 byte ip_packet_len;
11
12 bool ip_proto_icmp;
13
14 bool ip_read_packet_header()
15 {
16         /* variable para utilitaria (iterar y/o buffer) */
17         byte c;
18         /* versión y tamaño de cabecera vienen en el 1er byte */
19         c = net_getb();
20         /* sólo soportamos versión 4 */
21         if ((c >> 4) != 4)
22                 return false; /* drop */
23         /* tamaño de cabecera */
24         if ((c & 0x0F) != 5) /* no aceptamos opciones raras =) */
25                 return false; /* drop */
26         /* ignoramos el TOS */
27         net_getb();
28         /* obtenemos tamaño del paquete */
29         if (net_getb()) /* tiene más de 255 bytes (no lo soportamos) */
30                 return false; /* drop */
31         ip_packet_len = net_getb(); /* hasta 255 bytes tienen los nuestros */
32         /* ignoramos identificación */
33         net_getb(); net_getb(); /* 2 bytes */
34         /* si tiene prendido el bit de MF (More Fragments, bit 5 del byte, bit 2
35          * de los flags de la cabecera) o si tiene un offset de fragmento (bits
36          * del 4 al 0 y todos los bits del byte siguiente), dropeamos (no
37          * soportamos fragmentación) */
38         if (net_getw() & 0x3FFF)
39                 return false; /* drop */
40         /* no le damos bola al TTL (no le vamos a hacer lío si ya llegó hasta
41          * acá el pobre =) */
42         net_getb();
43         /* protocolo (sólo soportamos UDP e ICMP) */
44         switch (net_getb())
45         {
46                 case ICMP:
47                         ip_proto_icmp = true;
48                         break;
49                 case UDP:
50                         ip_proto_icmp = false;
51                         break;
52                 default:
53                         return false; /* drop */
54         }
55         /* checksum */
56         net_getb(); net_getb(); /* TODO: verificar checksum */
57         /* obtenemos IP de origen */
58         for (c = 0; c < IP_ADDR_SIZE; ++c)
59                 ip_addr_remote[c] = net_getb();
60         /* vemos si el paquete es para nosotros (ningún soportar broadcast =) */
61         for (c = 0; c < IP_ADDR_SIZE; ++c)
62                 if (ip_addr_local[c] != net_getb()) 
63                         return false; /* no es para nosotros */
64         return true;
65 }
66
67 void ip_write_packet_header()
68 {
69         /* variable para iterar */
70         byte i;
71         /* identificador del paquete IP (incrementa con cada paquete) */
72         static uint16 id = 0;
73         /* versión (4) y tamaño de cabecera (5 words de 4 bytes = 20 bytes) */
74         net_putb(0x45);
75         /* TOS */
76         if (ip_proto_icmp)
77                 net_putb(0xc0); /* Precedence: Internetwork Control */
78         else
79                 net_putb(0x00); /* Precedence: Normal */
80         net_getb();
81         /* escribimos tamaño del paquete */
82         net_putb(0x00); /* nunca vamos a mandar algo de más de 255 bytes */
83         net_putb(ip_packet_len);
84         /* identificación (sirve para reensamblar paquetes) */
85         net_putw(id);
86         /* pedimos que no se fragmente */
87         net_putb(0x40); /* Don't Fragment (DF) = 1 */
88         net_putb(0x00); /* offset de fragmento = 0 */
89         /* TTL de 64 saltos porque está de moda */
90         net_putb(0x40);
91         /* protocolo (sólo soportamos UDP e ICMP) */
92         if (ip_proto_icmp)
93                 net_putb(ICMP);
94         else
95                 net_putb(UDP);
96         /* checksum */
97         net_putb(0x00); net_putb(0x00); /* TODO: calcular checksum */
98         /* ponemos como dirección IP de origen la nuestra */
99         for (i = 0; i < IP_ADDR_SIZE; ++i)
100                 net_putb(ip_addr_local[i]);
101         /* IP de destino, la remota */
102         for (i = 0; i < IP_ADDR_SIZE; ++i)
103                 net_putb(ip_addr_remote[i]);
104 }
105