]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/udp.c
La placa ya está recibiendo (es decir, recibiendo la placa y parseando Ethernet,
[z.facultad/66.09/etherled.git] / src / udp.c
1 // vim: set et sw=4 sts=4 :     
2
3 #include "netdev.h"
4 #include "ip.h"
5 #include "udp.h"
6
7 uint16 udp_port_local;
8
9 uint16 udp_port_remote;
10
11 byte udp_dgram_len;
12
13 /* para calcular checksum */
14 static uint16 checksum;
15
16 /* agrega un word al checksum calculado */
17 static void sum(uint16 w)
18 {
19     checksum += w;
20     if (checksum < w) /* corrección de carry (hubo OV) */
21         ++checksum;
22 }
23
24 bool udp_read_dgram_header()
25 {
26     uint16 p;
27     /* reseteamos checksum */
28     checksum = 0;
29     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
30     /* ip de origen */
31     sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
32     sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
33     /* ip de destino */
34     sum(WORD(ip_addr_local[0], ip_addr_local[1]));
35     sum(WORD(ip_addr_local[2], ip_addr_local[3]));
36     /* protocolo expresado en 16 bits (0x11 es UDP) */
37     sum(0x0011);
38     /* tamaño del paquete UDP (sin las cabeceras que son 20 bytes) */
39     sum(ip_packet_len - 20);
40     /* de ahora en más todos los datos del checksum corresponden a UDP */
41     /* puerto origen (remoto) */
42     udp_port_remote = netdev_recv_word();
43     /* agregamos puerto de origen al checksum */
44     sum(udp_port_remote);
45     /* sólo aceptamos datagramas a nuestro puerto */
46     p = netdev_recv_word();
47     if (p != udp_port_local)
48         return false; /* drop */
49     /* agregamos puerto de destino al checksum */
50     sum(udp_port_local);
51     /* tamaño del datagrama */
52     if (netdev_recv_byte()) /* no soportamos más de 255 bytes */
53         return false; /* drop */
54     udp_dgram_len = netdev_recv_byte();
55     if (udp_dgram_len < 8) /* no puede ser más chico que sus cabeceras */
56         return false; /* drop */
57     /* agregamos tamaño al checksum */
58     sum(udp_dgram_len);
59     /* agregamos checksum al checksum */
60     sum(netdev_recv_word());
61     /* falta agregar el cuerpo del mensaje para verificar la suma
62      * esto debe hacerlo el protocolo que sigue para poder seguir obteniendo
63      * los datos de la placa de red byte a byte */
64     return true;
65 }
66
67 uint16 udp_read_word()
68 {
69     uint16 w = netdev_recv_word();
70     sum(w);
71     return w;
72 }
73
74 bool udp_checksum_ok()
75 {
76     return (uint16)~checksum;
77 }
78
79 void udp_write_dgram_header()
80 {
81     /* reseteamos checksum */
82     checksum = 0;
83     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
84     /* ip de origen */
85     sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
86     sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
87     /* ip de destino */
88     sum(WORD(ip_addr_local[0], ip_addr_local[1]));
89     sum(WORD(ip_addr_local[2], ip_addr_local[3]));
90     /* protocolo expresado en 16 bits (0x11 es UDP) */
91     sum(0x0011);
92     /* tamaño del paquete UDP (IP sin las cabeceras, que son 20 bytes) */
93     sum(ip_packet_len - 20); // FIXME
94     /* puerto origen */
95     netdev_send_word(udp_port_local);
96     sum(udp_port_local);
97     /* puerto destino */
98     netdev_send_word(udp_port_remote);
99     sum(udp_port_remote);
100     /* tamaño del datagrama */
101     netdev_send_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */
102     netdev_send_byte(udp_dgram_len);
103     sum(WORD(0x00, udp_dgram_len));
104     /* indicamos que no se usa checksum */
105     netdev_send_word(0x0000);
106     sum(0x0000);
107 }
108
109 void udp_write_word(uint16 w)
110 {
111     sum(w);
112     netdev_send_word(w);
113 }
114
115 void udp_write_checksum()
116 {
117     // XXX TODO FIXME
118     return;
119 }
120