]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/udp.c
f8264b12d5b18badf8d4fdad9266f9b7c1f40282
[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     byte tmp;
27     bit ok = true;
28     netdev_read_start(UDP_HEADER_SIZE);
29     /* reseteamos checksum */
30     checksum = 0;
31     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
32     /* ip de origen */
33     sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
34     sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
35     /* ip de destino */
36     sum(WORD(ip_addr_local[0], ip_addr_local[1]));
37     sum(WORD(ip_addr_local[2], ip_addr_local[3]));
38     /* protocolo expresado en 16 bits (0x11 es UDP) */
39     sum(0x0011);
40     /* tamaño del paquete UDP (sin las cabeceras que son 20 bytes) */
41     sum(ip_packet_len - 20);
42     /* de ahora en más todos los datos del checksum corresponden a UDP */
43     /* puerto origen (remoto) */
44     udp_port_remote = netdev_read_word();
45     /* agregamos puerto de origen al checksum */
46     sum(udp_port_remote);
47     /* sólo aceptamos datagramas a nuestro puerto */
48     if (netdev_read_word() != udp_port_local)
49         ok = false; /* drop */
50     /* agregamos puerto de destino al checksum */
51     sum(udp_port_local);
52     /* tamaño del datagrama */
53     if (tmp = netdev_read_byte()) /* no soportamos más de 255 bytes */
54         ok = false; /* drop */
55     udp_dgram_len = netdev_read_byte(); /* parte baja */
56     if (udp_dgram_len < 8) /* no puede ser más chico que sus cabeceras */
57         ok = false; /* drop */
58     /* agregamos tamaño al checksum */
59     sum(WORD(tmp, udp_dgram_len));
60     /* agregamos checksum al checksum */
61     sum(netdev_read_word());
62     /* falta agregar el cuerpo del mensaje para verificar la suma
63      * esto debe hacerlo el protocolo que sigue para poder seguir obteniendo
64      * los datos de la placa de red byte a byte */
65     netdev_read_end();
66     return true;
67 }
68
69 uint16 udp_read_word()
70 {
71     uint16 w = netdev_read_word();
72     sum(w);
73     return w;
74 }
75
76 bool udp_checksum_ok()
77 {
78     return (uint16)~checksum;
79 }
80
81 void udp_write_dgram_header()
82 {
83     netdev_write_start(UDP_HEADER_SIZE);
84     /* reseteamos checksum */
85     checksum = 0;
86     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
87     /* ip de origen */
88     sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
89     sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
90     /* ip de destino */
91     sum(WORD(ip_addr_local[0], ip_addr_local[1]));
92     sum(WORD(ip_addr_local[2], ip_addr_local[3]));
93     /* protocolo expresado en 16 bits (0x11 es UDP) */
94     sum(0x0011);
95     /* tamaño del paquete UDP (IP sin las cabeceras, que son 20 bytes) */
96     sum(ip_packet_len - 20); // FIXME
97     /* puerto origen */
98     netdev_write_word(udp_port_local);
99     sum(udp_port_local);
100     /* puerto destino */
101     netdev_write_word(udp_port_remote);
102     sum(udp_port_remote);
103     /* tamaño del datagrama */
104     netdev_write_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */
105     netdev_write_byte(udp_dgram_len);
106     sum(WORD(0x00, udp_dgram_len));
107     /* indicamos que no se usa checksum */
108     netdev_write_word(0x0000);
109     sum(0x0000);
110     netdev_write_end();
111 }
112
113 void udp_write_word(uint16 w)
114 {
115     sum(w);
116     netdev_write_word(w);
117 }
118
119 void udp_write_checksum()
120 {
121     // XXX TODO FIXME
122     return;
123 }
124