2a4b80d0fbe03ad69747e148b5fd93b0ed7f3f0c
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) {
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) {
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)     unsigned int i;
148) 
149)     // search IP in ARP tabale
150)     for (i = 0; i < count(arp_tab); ++i)
151)       if ((arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) &&
152)           ip_eq(arp_pack->arp_hdr.src_ip, arp_tab[i].ip))
153)         break;
154)     // if found in ARP table
155)     // (we do not want to put an entry in the ARP table
156)     //  if we have not asked for the MAC of this IP)
157)     if (i < count(arp_tab)) {
158)       // update ARP table entry
159)       arp_tab[i].flags = ARP_TAB_FLAG_IN_USE | ARP_TAB_FLAG_MAC_OK;
160)       arp_tab[i].ticks = 0;
161)       mac_cpy(arp_tab[i].mac, arp_pack->arp_hdr.src_mac);
162)       // notify IP
163)       //  - IP might be waiting for the MAC to transmit a packet
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

164)       ip_got_mac(arp_tab[i].ip, arp_tab[i].mac);
Stefan Schuermans implementation of ethernet...

Stefan Schuermans authored 12 years ago

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

Stefan Schuermans authored 12 years ago

177) int arp_lookup(unsigned char ip[4], unsigned char mac[6])