55a4ef917532453cc39576073284cfb60d9752af
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

1) #include "arp.h"
2) #include "config.h"
3) #include "ethernet.h"
4) // TODO #include "ip.h"
5) #include "macros.h"
6) #include "nethelp.h"
7) 
8) // timing parameters
9) #define ARP_TICKS_MAX        (150) /**< maximum age of ARP table entries
10)                                         (in 200ms steps) */
11) #define ARP_NO_MAC_TICKS_MAX  (50) /**< maximum age of ARP table entries
12)                                         without MAC (in 200ms steps) */
13) #define ARP_RETRY_TICKS        (8) /**< time after which to retry ARP query
14)                                         (must be power of 2, in 200ms steps) */
15) 
16) /// ARP table
17) #define ARP_TAB_FLAG_IN_USE (1)
18) #define ARP_TAB_FLAG_MAC_OK (2)
19) struct arp_table
20) {
21)   unsigned char flags; /// flags - see constants
22)   unsigned char ticks; /// age of entry in 200ms steps
23)   unsigned char mac[6];
24)   unsigned char ip[4];
25) } arp_tab[12];
26) 
27) /**
28)  * @brief send an ARP request
29)  * @param[in] ip IP address to query MAC for
30)  */
31) static void arp_send_request(unsigned char ip[4])
32) {
33)   struct arp_packet arp_request;
34) 
35)   // build ARP request
36)   arp_request.arp_hdr.hw_type = htons(0x0001); // ethernet
37)   arp_request.arp_hdr.proto_type = htons(0x0800); // IP
38)   arp_request.arp_hdr.hw_len = 0x06; // length of a MAC address
39)   arp_request.arp_hdr.proto_len = 0x04; // length of an IP address
40)   arp_request.arp_hdr.op = htons(0x0001); // ARP request
41)   mac_cpy(arp_request.arp_hdr.src_mac, config_mac.mac); // own MAC
42)   ip_cpy(arp_request.arp_hdr.src_ip, config_ip.ip); // own IP
43)   mac_cpy(arp_request.arp_hdr.dest_mac,
44)           "\xFF\xFF\xFF\xFF\xFF\xFF"); // broadcast MAC
45)   ip_cpy(arp_request.arp_hdr.dest_ip, ip); // requested IP
46) 
47)   // send ARP request
48)   mac_cpy(arp_request.eth_hdr.dest, arp_request.arp_hdr.dest_mac);
49)   arp_request.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
50)   ethernet_send(&arp_request, sizeof(arp_request));
51) }
52) 
53) /// initialize
54) /* extern */ void arp_init(void)
55) {
56)   unsigned int i;
57) 
58)   // empty ARP table
59)   for (i = 0; i < count(arp_tab); ++i)
60)     arp_tab[i].flags = 0;
61) }
62) 
63) /// tick procedure - call every 200ms
64) /* extern */ void arp_tick200(void)
65) {
66)   unsigned int i;
67) 
68)   // increase age of ARP table entires and remove timed out ones
69)   for (i = 0; i < count(arp_tab); ++i) {
70)     // entry in use
71)     if (arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) {
72)       arp_tab[i].ticks++; // increase age
73)       // entry has a MAC
74)       if (arp_tab[i].flags & ARP_TAB_FLAG_MAC_OK) {
75)         if (arp_tab[i].ticks > ARP_TICKS_MAX) // too old
76)           arp_tab[i].flags = 0; // remove entry
77)       }
78)       // entry does not have a MAC
79)       else {
80)         if (arp_tab[i].ticks > ARP_NO_MAC_TICKS_MAX) // too old
81)           arp_tab[i].flags = 0; // remove entry
82)         else if ((arp_tab[i].ticks & (ARP_RETRY_TICKS - 1)) == 0) // re-request
83)           arp_send_request(arp_tab[i].ip);
84)       }
85)     }
86)   }
87) }
88) 
89) /**
90)  * @brief process a received ARP packet
91)  * @param[in] ptr pointer to data of packet
92)  * @param[in] sz size of packet
93)  */
94) /* extern */ void arp_recv(void *ptr, unsigned int sz)
95) {
96)   struct arp_packet *arp_pack;
97) 
98)   // packet too short
99)   if (sz < sizeof(struct arp_packet))
100)     return;
101) 
102)   arp_pack = (struct arp_packet *)ptr;
103) 
104)   // not IP over ethernet
105)   if (arp_pack->arp_hdr.hw_type != htons(0x0001) || // ethernet
106)       arp_pack->arp_hdr.proto_type != htons(0x0800) || // IP
107)       arp_pack->arp_hdr.hw_len != 0x06 || // length of a MAC address
108)       arp_pack->arp_hdr.proto_len != 0x04) // length of an IP address
109)     // we do not support other protocols than IP over ethernet
110)     return;
111) 
112)   // source MAC is broadcast MAC -> broken packet / attac -> get lost
113)   if (mac_eq(arp_pack->arp_hdr.src_mac, "\xFF\xFF\xFF\xFF\xFF\xFF"))
114)     return;
115) 
116)   // ARP request for own IP address
117)   if (arp_pack->arp_hdr.op == htons(0x0001) && // ARP request
118)       ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
Stefan Schuermans added padding of ethernet p...

Stefan Schuermans authored 12 years ago

119)     struct arp_packet_pad arp_reply;
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

120) 
121)     // build ARP reply
Stefan Schuermans added padding of ethernet p...

Stefan Schuermans authored 12 years ago

122)     arp_reply.p.arp_hdr.hw_type = htons(0x0001); // ethernet
123)     arp_reply.p.arp_hdr.proto_type = htons(0x0800); // IP
124)     arp_reply.p.arp_hdr.hw_len = 0x06; // length of a MAC address
125)     arp_reply.p.arp_hdr.proto_len = 0x04; // length of an IP address
126)     arp_reply.p.arp_hdr.op = htons(0x0002); // ARP reply
127)     mac_cpy(arp_reply.p.arp_hdr.src_mac, config_mac.mac); // own MAC
128)     ip_cpy(arp_reply.p.arp_hdr.src_ip, config_ip.ip); // own IP
129)     mac_cpy(arp_reply.p.arp_hdr.dest_mac,
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

130)             arp_pack->arp_hdr.src_mac); // requestor's MAC
Stefan Schuermans added padding of ethernet p...

Stefan Schuermans authored 12 years ago

131)     ip_cpy(arp_reply.p.arp_hdr.dest_ip,
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

132)            arp_pack->arp_hdr.src_ip); // requestor's IP
133) 
134)     // send ARP reply
Stefan Schuermans added padding of ethernet p...

Stefan Schuermans authored 12 years ago

135)     mac_cpy(arp_reply.p.eth_hdr.dest,
136)             arp_reply.p.arp_hdr.dest_mac); // ethernet destination address
137)     arp_reply.p.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP