]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/udp.c
Se implementa un sistema primitivo de 'locking' para los leds. Cada vez que se
[z.facultad/66.09/etherled.git] / src / udp.c
1 // vim: set et sw=4 sts=4 :     
2
3 #include "debug.h"
4 #include "netdev.h"
5 #include "ip.h"
6 #include "udp.h"
7
8 uint16 udp_port_local;
9
10 uint16 udp_port_remote;
11
12 byte udp_dgram_len;
13
14 /* para calcular checksum */
15 static uint16 checksum;
16 static byte byte_count;
17 static byte last_byte;
18
19 /* agrega un word al checksum calculado */
20 static void sum(uint16 w)
21 {
22     checksum += w;
23     if (checksum < w) /* corrección de carry (hubo OV) */
24         ++checksum;
25 }
26
27 bool udp_read_dgram_header()
28 {
29     byte tmp;
30     bit ok = true;
31     netdev_read_start(UDP_HEADER_SIZE);
32     /* reseteamos checksum */
33     checksum = 0;
34     byte_count = 0;
35     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
36     /* ip de origen */
37     sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
38     sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
39     /* ip de destino */
40     sum(WORD(ip_addr_local[0], ip_addr_local[1]));
41     sum(WORD(ip_addr_local[2], ip_addr_local[3]));
42     /* protocolo expresado en 16 bits (0x11 es UDP) */
43     sum(0x0011);
44     /* tamaño del paquete UDP (IP ya está sin las cabeceras) */
45     sum(ip_packet_len);
46     /* de ahora en más todos los datos del checksum corresponden a UDP */
47     /* puerto origen (remoto) */
48     udp_port_remote = netdev_read_word();
49     /* agregamos puerto de origen al checksum */
50     sum(udp_port_remote);
51     /* sólo aceptamos datagramas a nuestro puerto */
52     if (netdev_read_word() != udp_port_local)
53         ok = false; /* drop */
54     /* agregamos puerto de destino al checksum */
55     sum(udp_port_local);
56     /* tamaño del datagrama */
57     if (tmp = netdev_read_byte()) /* no soportamos más de 255 bytes */
58         ok = false; /* drop */
59     udp_dgram_len = netdev_read_byte(); /* parte baja */
60     /* no puede ser más chico que sus cabeceras */
61     if (udp_dgram_len < UDP_HEADER_SIZE)
62         ok = false; /* drop */
63     /* agregamos tamaño al checksum */
64     sum(WORD(tmp, udp_dgram_len));
65     /* sacamos la cabecera al tamaño */
66     udp_dgram_len -= UDP_HEADER_SIZE;
67     /* agregamos checksum al checksum */
68     sum(netdev_read_word());
69     /* falta agregar el cuerpo del mensaje para verificar la suma
70      * esto debe hacerlo el protocolo que sigue para poder seguir obteniendo
71      * los datos de la placa de red byte a byte */
72     netdev_read_end();
73     return true;
74 }
75
76 byte udp_read_byte()
77 {
78     byte b;
79     if (byte_count % 2) // impar, tengo 2, sumo
80     {
81         b = netdev_read_byte();
82         sum(WORD(last_byte, b));
83     }
84     else // par, guardo para sumar cuando tenga 2
85     {
86         b = netdev_read_byte();
87         last_byte = b;
88     }
89     ++byte_count;
90     return b;
91 }
92
93 bool udp_checksum_ok()
94 {
95     // Verifico si falta sumar algo (UDP debe sumar de a un word)
96     if (byte_count % 2)
97         sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00
98     return !(uint16)~checksum;
99 }
100
101 void udp_write_dgram_header()
102 {
103     netdev_write_start(UDP_HEADER_SIZE);
104     /* reseteamos checksum */
105     checksum = 0;
106     byte_count = 0;
107     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
108     /* ip de origen */
109     sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
110     sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
111     /* ip de destino */
112     sum(WORD(ip_addr_local[0], ip_addr_local[1]));
113     sum(WORD(ip_addr_local[2], ip_addr_local[3]));
114     /* protocolo expresado en 16 bits (0x11 es UDP) */
115     sum(0x0011);
116     /* tamaño del paquete UDP */
117     sum(WORD(0x00, udp_dgram_len + UDP_HEADER_SIZE));
118     /* puerto origen */
119     netdev_write_word(udp_port_local);
120     sum(udp_port_local);
121     /* puerto destino */
122     netdev_write_word(udp_port_remote);
123     sum(udp_port_remote);
124     /* tamaño del datagrama */
125     netdev_write_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */
126     netdev_write_byte(udp_dgram_len + UDP_HEADER_SIZE);
127     sum(WORD(0x00, udp_dgram_len + UDP_HEADER_SIZE));
128     /* indicamos que no se usa checksum */
129     netdev_write_word(0x0000);
130     sum(0x0000);
131     netdev_write_end();
132 }
133
134 void udp_write_byte(byte b)
135 {
136     if (byte_count % 2) // impar, tengo 2, sumo
137     {
138         netdev_write_byte(b);
139         sum(WORD(last_byte, b));
140     }
141     else // par, guardo para sumar cuando tenga 2
142     {
143         netdev_write_byte(b);
144         last_byte = b;
145     }
146     ++byte_count;
147 }
148
149 void udp_write_checksum(byte offset)
150 {
151     // Verifico si falta sumar algo (UDP debe sumar de a un word)
152     if (byte_count % 2)
153         sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00
154     // Escribo checksum en el buffer de la placa de red
155     netdev_write_start_at(offset + 6, 2); // 6 bytes de offset hasta el checksum
156     netdev_write_word((uint16)~checksum); // Guardo checksum
157     netdev_write_end();
158     return;
159 }
160