c2b040193a777c09bdc595c95492b57a2521db87
Stefan Schuermans added file headers

Stefan Schuermans authored 12 years ago

1) /* MIPS I system
2)  * Copyright 2011-2012 Stefan Schuermans <stefan@schuermans.info>
3)  * Copyleft GNU public license V2 or later
4)  *          http://www.gnu.org/copyleft/gpl.html
5)  */
6) 
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

7) #include "arp.h"
8) #include "config.h"
9) #include "ethernet.h"
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

11) #include "macros.h"
12) #include "nethelp.h"
13) 
14) // timing parameters
15) #define ARP_TICKS_MAX        (150) /**< maximum age of ARP table entries
16)                                         (in 200ms steps) */
17) #define ARP_NO_MAC_TICKS_MAX  (50) /**< maximum age of ARP table entries
18)                                         without MAC (in 200ms steps) */
19) #define ARP_RETRY_TICKS        (8) /**< time after which to retry ARP query
20)                                         (must be power of 2, in 200ms steps) */
21) 
22) /// ARP table
23) #define ARP_TAB_FLAG_IN_USE (1)
24) #define ARP_TAB_FLAG_MAC_OK (2)
25) struct arp_table
26) {
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

32) 
33) /**
34)  * @brief send an ARP request
35)  * @param[in] ip IP address to query MAC for
36)  */
37) static void arp_send_request(unsigned char ip[4])
38) {
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

40) 
41)   // build ARP request
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

42)   arp_request.arp_hdr.hw_type = htons(0x0001); // ethernet
43)   arp_request.arp_hdr.proto_type = htons(0x0800); // IP
44)   arp_request.arp_hdr.hw_len = 0x06; // length of a MAC address
45)   arp_request.arp_hdr.proto_len = 0x04; // length of an IP address
46)   arp_request.arp_hdr.op = htons(0x0001); // ARP request
47)   mac_cpy(arp_request.arp_hdr.src_mac, config_mac.mac); // own MAC
48)   ip_cpy(arp_request.arp_hdr.src_ip, config_ip.ip); // own IP
49)   mac_cpy(arp_request.arp_hdr.dest_mac,
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

52) 
53)   // send ARP request
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

54)   mac_cpy(arp_request.eth_hdr.dest, arp_request.arp_hdr.dest_mac);
55)   arp_request.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
56)   ethernet_send(&arp_request, sizeof(arp_request));
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

57) }
58) 
59) /// initialize
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

61) {
62)   unsigned int i;
63) 
64)   // empty ARP table
65)   for (i = 0; i < count(arp_tab); ++i)
66)     arp_tab[i].flags = 0;
67) }
68) 
69) /// tick procedure - call every 200ms
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

71) {
72)   unsigned int i;
73) 
74)   // increase age of ARP table entires and remove timed out ones
75)   for (i = 0; i < count(arp_tab); ++i) {
76)     // entry in use
77)     if (arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) {
78)       arp_tab[i].ticks++; // increase age
79)       // entry has a MAC
80)       if (arp_tab[i].flags & ARP_TAB_FLAG_MAC_OK) {
81)         if (arp_tab[i].ticks > ARP_TICKS_MAX) // too old
82)           arp_tab[i].flags = 0; // remove entry
83)       }
84)       // entry does not have a MAC
85)       else {
86)         if (arp_tab[i].ticks > ARP_NO_MAC_TICKS_MAX) // too old
87)           arp_tab[i].flags = 0; // remove entry
88)         else if ((arp_tab[i].ticks & (ARP_RETRY_TICKS - 1)) == 0) // re-request
89)           arp_send_request(arp_tab[i].ip);
90)       }
91)     }
92)   }
93) }
94) 
95) /**
96)  * @brief process a received ARP packet
97)  * @param[in] ptr pointer to data of packet
98)  * @param[in] sz size of packet
99)  */
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

101) {
102)   struct arp_packet *arp_pack;
103) 
104)   // packet too short
105)   if (sz < sizeof(struct arp_packet))
106)     return;
107) 
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

109) 
110)   // not IP over ethernet
111)   if (arp_pack->arp_hdr.hw_type != htons(0x0001) || // ethernet
112)       arp_pack->arp_hdr.proto_type != htons(0x0800) || // IP
113)       arp_pack->arp_hdr.hw_len != 0x06 || // length of a MAC address
114)       arp_pack->arp_hdr.proto_len != 0x04) // length of an IP address
115)     // we do not support other protocols than IP over ethernet
116)     return;
117) 
118)   // source MAC is broadcast MAC -> broken packet / attac -> get lost
Stefan Schuermans do not store boradcast addr...

Stefan Schuermans authored 12 years ago

119)   if (arp_pack->arp_hdr.src_mac[0] == 0xFF &&
120)       arp_pack->arp_hdr.src_mac[1] == 0xFF &&
121)       arp_pack->arp_hdr.src_mac[2] == 0xFF &&
122)       arp_pack->arp_hdr.src_mac[3] == 0xFF &&
123)       arp_pack->arp_hdr.src_mac[4] == 0xFF &&
124)       arp_pack->arp_hdr.src_mac[5] == 0xFF)
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

125)     return;
126) 
127)   // ARP request for own IP address
128)   if (arp_pack->arp_hdr.op == htons(0x0001) && // ARP request
129)       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

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

Stefan Schuermans authored 12 years ago

131) 
132)     // build ARP reply
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

133)     arp_reply.arp_hdr.hw_type = htons(0x0001); // ethernet
134)     arp_reply.arp_hdr.proto_type = htons(0x0800); // IP
135)     arp_reply.arp_hdr.hw_len = 0x06; // length of a MAC address
136)     arp_reply.arp_hdr.proto_len = 0x04; // length of an IP address
137)     arp_reply.arp_hdr.op = htons(0x0002); // ARP reply
138)     mac_cpy(arp_reply.arp_hdr.src_mac, config_mac.mac); // own MAC
139)     ip_cpy(arp_reply.arp_hdr.src_ip, config_ip.ip); // own IP
140)     mac_cpy(arp_reply.arp_hdr.dest_mac,
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

143)            arp_pack->arp_hdr.src_ip); // requestor's IP
144) 
145)     // send ARP reply
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

146)     mac_cpy(arp_reply.eth_hdr.dest,
147)             arp_reply.arp_hdr.dest_mac); // ethernet destination address
148)     arp_reply.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
149)     ethernet_send(&arp_reply, sizeof(arp_reply));
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

150) 
151)     return;
152)   }
153) 
154)   // ARP reply to own MAC address and own IP address
155)   if (arp_pack->arp_hdr.op == htons(0x0002) && // ARP reply
156)       mac_eq(arp_pack->arp_hdr.dest_mac, config_mac.mac) && // own MAC address
157)       ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
158) 
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

159)     // store MAC for IP
160)     arp_store(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
161) 
162)     // notify IP
163)     //  - IP might be waiting for the MAC to transmit a packet
164)     ip_got_mac(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
165) 
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

166)     return;
167)   }
168) }
169) 
170) /**
171)  * @brief look up the MAC for an IP address
172)  * @param[in] ip IP address to look up
173)  * @param[out] mac MAC address for this IP address
174)  * @return 0 in case of success, 1 if the MAC address is unknown
175)  */
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

227) /**
228)  * @brief store the MAC for an IP address
229)  * @param[in] ip IP address to store MAC for
230)  * @param[out] mac MAC address for this IP address
231)  */
232) void arp_store(unsigned char ip[4], unsigned char mac[6])
233) {
234)   unsigned int i, j;
235) 
Stefan Schuermans do not store boradcast addr...

Stefan Schuermans authored 12 years ago

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