3b2902ec2e7e7c5802264d3a7663d841dae3482e
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
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 handle padding to minimum e...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

120) 
121)     // build ARP reply
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

122)     arp_reply.arp_hdr.hw_type = htons(0x0001); // ethernet
123)     arp_reply.arp_hdr.proto_type = htons(0x0800); // IP
124)     arp_reply.arp_hdr.hw_len = 0x06; // length of a MAC address
125)     arp_reply.arp_hdr.proto_len = 0x04; // length of an IP address
126)     arp_reply.arp_hdr.op = htons(0x0002); // ARP reply
127)     mac_cpy(arp_reply.arp_hdr.src_mac, config_mac.mac); // own MAC
128)     ip_cpy(arp_reply.arp_hdr.src_ip, config_ip.ip); // own IP
129)     mac_cpy(arp_reply.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 handle padding to minimum e...

Stefan Schuermans authored 12 years ago

131)     ip_cpy(arp_reply.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 handle padding to minimum e...

Stefan Schuermans authored 12 years ago

135)     mac_cpy(arp_reply.eth_hdr.dest,
136)             arp_reply.arp_hdr.dest_mac); // ethernet destination address
137)     arp_reply.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
138)     ethernet_send(&arp_reply, sizeof(arp_reply));
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

148)     // store MAC for IP
149)     arp_store(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
150) 
151)     // notify IP
152)     //  - IP might be waiting for the MAC to transmit a packet
153)     ip_got_mac(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
154) 
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

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