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
|
added padding of ethernet p...
Stefan Schuermans authored 12 years ago
|
119) struct arp_packet_pad arp_reply;
|
implementation of ethernet...
Stefan Schuermans authored 12 years ago
|
120)
121) // build ARP reply
|
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,
|
implementation of ethernet...
Stefan Schuermans authored 12 years ago
|
130) arp_pack->arp_hdr.src_mac); // requestor's MAC
|
added padding of ethernet p...
Stefan Schuermans authored 12 years ago
|
131) ip_cpy(arp_reply.p.arp_hdr.dest_ip,
|
implementation of ethernet...
Stefan Schuermans authored 12 years ago
|
132) arp_pack->arp_hdr.src_ip); // requestor's IP
133)
134) // send ARP reply
|
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
|