9a81f6c7687e739ac6cf41fbd06e037fa7eeed52
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

1) #include "arp.h"
2) #include "config.h"
3) #include "ethernet.h"
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

4) #include "ip.h"
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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) {
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

21)   unsigned int flags; /// flags - see constants
22)   unsigned int ticks; /// age of entry in 200ms steps
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

23)   unsigned char mac[6];
24)   unsigned char ip[4];
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

25) } arp_tab[16];
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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) {
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

33)   struct arp_packet arp_request;
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

34) 
35)   // build ARP request
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

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,
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

44)           "\xFF\xFF\xFF\xFF\xFF\xFF"); // broadcast MAC
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

45)   ip_cpy(arp_request.arp_hdr.dest_ip, ip); // requested IP
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

46) 
47)   // send ARP request
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

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));
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

51) }
52) 
53) /// initialize
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

54) void arp_init(void)
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

64) void arp_tick200(void)
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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)  */
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

94) void arp_recv(void *ptr, unsigned int sz)
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

95) {
96)   struct arp_packet *arp_pack;
97) 
98)   // packet too short
99)   if (sz < sizeof(struct arp_packet))
100)     return;
101) 
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

102)   arp_pack = ptr;
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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
Stefan Schuermans do not store boradcast addr...

Stefan Schuermans authored 12 years ago

113)   if (arp_pack->arp_hdr.src_mac[0] == 0xFF &&
114)       arp_pack->arp_hdr.src_mac[1] == 0xFF &&
115)       arp_pack->arp_hdr.src_mac[2] == 0xFF &&
116)       arp_pack->arp_hdr.src_mac[3] == 0xFF &&
117)       arp_pack->arp_hdr.src_mac[4] == 0xFF &&
118)       arp_pack->arp_hdr.src_mac[5] == 0xFF)
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

119)     return;
120) 
121)   // ARP request for own IP address
122)   if (arp_pack->arp_hdr.op == htons(0x0001) && // ARP request
123)       ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

124)     struct arp_packet arp_reply;
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

125) 
126)     // build ARP reply
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

135)             arp_pack->arp_hdr.src_mac); // requestor's MAC
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

137)            arp_pack->arp_hdr.src_ip); // requestor's IP
138) 
139)     // send ARP reply
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

140)     mac_cpy(arp_reply.eth_hdr.dest,
141)             arp_reply.arp_hdr.dest_mac); // ethernet destination address
142)     arp_reply.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
143)     ethernet_send(&arp_reply, sizeof(arp_reply));
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

144) 
145)     return;
146)   }
147) 
148)   // ARP reply to own MAC address and own IP address
149)   if (arp_pack->arp_hdr.op == htons(0x0002) && // ARP reply
150)       mac_eq(arp_pack->arp_hdr.dest_mac, config_mac.mac) && // own MAC address
151)       ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
152) 
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

153)     // store MAC for IP
154)     arp_store(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
155) 
156)     // notify IP
157)     //  - IP might be waiting for the MAC to transmit a packet
158)     ip_got_mac(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
159) 
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

160)     return;
161)   }
162) }
163) 
164) /**
165)  * @brief look up the MAC for an IP address
166)  * @param[in] ip IP address to look up
167)  * @param[out] mac MAC address for this IP address
168)  * @return 0 in case of success, 1 if the MAC address is unknown
169)  */
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

170) int arp_lookup(unsigned char ip[4], unsigned char mac[6])
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

171) {
172)   unsigned int i, j;
173) 
174)   // own IP
175)   if (ip_eq(ip, config_ip.ip))
176)     // own IP may not be looked up via ARP
177)     return 1;
178) 
179)   // search IP in ARP tabale
180)   for (i = 0; i < count(arp_tab); ++i)
181)     if ((arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) &&
182)         ip_eq(ip, arp_tab[i].ip))
183)       break;
184) 
185)   // not found
186)   if (i >= count(arp_tab)) {
187)     // find a free entry
188)     for (i = 0; i < count(arp_tab); ++i)
189)       if (!(arp_tab[i].flags & ARP_TAB_FLAG_IN_USE))
190)         break;
191) 
192)     // no free entry
193)     if (i >= count(arp_tab)) {
194)       // find oldest entry
195)       i = 0;
196)       for (j = 1; j < count(arp_tab); ++j)
197)         if (arp_tab[j].ticks > arp_tab[i].ticks )
198)           i = j;
199)     }
200) 
201)     // set up this entry
202)     arp_tab[i].flags = ARP_TAB_FLAG_IN_USE;
203)     arp_tab[i].ticks = 0;
204)     ip_cpy(arp_tab[i].ip, ip);
205)   }
206) 
207)   // MAC available
208)   if (arp_tab[i].flags & ARP_TAB_FLAG_MAC_OK) {
209)     // return MAC and success
210)     mac_cpy(mac, arp_tab[i].mac);
211)     return 0;
212)   }
213) 
214)   // send ARP request
215)   arp_send_request(ip);
216) 
217)   // no success yet
218)   return 1;
219) }
220) 
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

221) /**
222)  * @brief store the MAC for an IP address
223)  * @param[in] ip IP address to store MAC for
224)  * @param[out] mac MAC address for this IP address
225)  */
226) void arp_store(unsigned char ip[4], unsigned char mac[6])
227) {
228)   unsigned int i, j;
229) 
Stefan Schuermans do not store boradcast addr...

Stefan Schuermans authored 12 years ago

230)   // do not store broadcast MAC
231)   if (mac[0] == 0xFF && mac[1] == 0xFF && mac[2] == 0xFF &&
232)       mac[3] == 0xFF && mac[4] == 0xFF && mac[5] == 0xFF)
233)     return;
234) 
235)   // do not store link-local broadcast IP
236)   if (ip[0] == 0xFF && ip[1] == 0xFF && ip[2] == 0xFF && ip[3] == 0xFF)
237)     return;
238)   // do not store non-local IPs
239)   if ((ip[0] & config_ip.mask[0]) != (config_ip.ip[0] & config_ip.mask[0]) ||
240)       (ip[1] & config_ip.mask[1]) != (config_ip.ip[1] & config_ip.mask[1]) ||
241)       (ip[2] & config_ip.mask[2]) != (config_ip.ip[2] & config_ip.mask[2]) ||
242)       (ip[3] & config_ip.mask[3]) != (config_ip.ip[3] & config_ip.mask[3]))
243)     return;
244)   // do not store broadcast IP
245)   if (ip[0] == (config_ip.ip[0] | ~config_ip.mask[0]) &&
246)       ip[1] == (config_ip.ip[1] | ~config_ip.mask[1]) &&
247)       ip[2] == (config_ip.ip[2] | ~config_ip.mask[2]) &&
248)       ip[3] == (config_ip.ip[3] | ~config_ip.mask[3]))
249)     return;
250)