3b2902ec2e7e7c5802264d3a7663d841dae3482e
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

1) #include "arp.h"
2) #include "checksum.h"
3) #include "config.h"
4) #include "ethernet.h"
5) #include "icmp.h"
6) #include "ip.h"
7) #include "macros.h"
8) #include "memcpy.h"
9) #include "nethelp.h"
10) #include "udp.h"
11) 
12) // timing parameters
13) #define IP_BUFFER_TICKS_MAX 50 // maximum age of buffered IP packet (in 200ms)
14) 
15) /**
16)  * buffers for IP packets to transmit
17)  *  - used if MAC is unknown when packet shall be transmitted
18)  *  - packet is sent when MAC becomes known
19)  *  - some buffers with different length (packets have different lengths)
20)  */
21) //@{
22) unsigned int ip_buffer0[20];
23) unsigned int ip_buffer1[20];
24) unsigned int ip_buffer2[40];
25) unsigned int ip_buffer3[80];
26) //@}
27) /// table with buffers
28) struct ip_buffer_table
29) {
30)   void *ptr; ///< pointer to buffer for packet
31)   unsigned int buf_sz; ///< size of buffer
32)   unsigned int pkg_sz; ///< size of packet in buffer, 0 for packet
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

33)   unsigned int ticks; ///< age of entry (in 200ms)
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

34) } ip_buffer_tab[] =
35) { // put smaller buffers in front of larger buffers
36)   //  - then short packets will use smaller buffers more often
37)   { ip_buffer0, sizeof(ip_buffer0), 0, 0 },
38)   { ip_buffer1, sizeof(ip_buffer1), 0, 0 },
39)   { ip_buffer2, sizeof(ip_buffer2), 0, 0 },
40)   { ip_buffer3, sizeof(ip_buffer3), 0, 0 },
41) };
42) 
43) /// initialize
44) void ip_init(void)
45) {
46)   unsigned int i;
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

47)   for (i = 0; i < count(ip_buffer_tab); i++)
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

48)     ip_buffer_tab[i].pkg_sz = 0;
49) }
50) 
51) /// tick procedure - call every 200ms
52) void ip_tick200(void)
53) {
54)   unsigned int i;
55) 
56)   // increase age of buffered IP packets and remove timed out ones
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

57)   for (i = 0; i < count(ip_buffer_tab); i++) {
58)     if (ip_buffer_tab[i].pkg_sz > 0) { // buffer in use
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

59)       ip_buffer_tab[i].ticks++; // increase age
60)       if (ip_buffer_tab[i].ticks > IP_BUFFER_TICKS_MAX) // too old
61)         ip_buffer_tab[i].pkg_sz = 0; // discard packet
62)     }
63)   }
64) }
65) 
66) /**
67)  * @brief process a received IP packet
68)  * @param[in] ptr pointer to data of packet
69)  * @param[in] sz size of packet
70)  */
71) void ip_recv(void *ptr, unsigned int sz)
72) {
73)   struct ip_packet *ip_pack;
74)   unsigned int len;
75) 
76)   // packet too short
77)   if (sz < sizeof(struct ip_packet))
78)     return;
79) 
80)   ip_pack = ptr;
81) 
82)   // not IPv4 -> drop
83)   if (ip_pack->ip_hdr.ver__hdr_len != 0x45) // IPv4 with no options present
84)     return;
85) 
86)   // not to own IP / broadcast -> drop
87)   while (1) {
88)     // own IP -> accept
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

89)     if (ip_eq(ip_pack->ip_hdr.dest, config_ip.ip))
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

90)       break;
91)     // local network's broadcast address -> accept
92)     if ((ip_pack->ip_hdr.dest[0] & config_ip.mask[0]) ==
93)           (config_ip.ip[0] & config_ip.mask[0]) &&
94)         (ip_pack->ip_hdr.dest[1] & config_ip.mask[1]) ==
95)           (config_ip.ip[1] & config_ip.mask[1]) &&
96)         (ip_pack->ip_hdr.dest[2] & config_ip.mask[2]) ==
97)           (config_ip.ip[2] & config_ip.mask[2]) &&
98)         (ip_pack->ip_hdr.dest[3] & config_ip.mask[3]) ==
99)           (config_ip.ip[3] & config_ip.mask[3]) &&
100)         (ip_pack->ip_hdr.dest[0] & ~config_ip.mask[0]) ==
101)           ~config_ip.mask[0] &&
102)         (ip_pack->ip_hdr.dest[1] & ~config_ip.mask[1]) ==
103)           ~config_ip.mask[1] &&
104)         (ip_pack->ip_hdr.dest[2] & ~config_ip.mask[2]) ==
105)           ~config_ip.mask[2] &&
106)         (ip_pack->ip_hdr.dest[3] & ~config_ip.mask[3]) ==
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

107)           ~config_ip.mask[3])
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

108)       break;
109)     // link local boradcast address -> accept
110)     if (ip_pack->ip_hdr.dest[0] == 0xFF &&
111)         ip_pack->ip_hdr.dest[1] == 0xFF &&
112)         ip_pack->ip_hdr.dest[2] == 0xFF &&
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

113)         ip_pack->ip_hdr.dest[3] == 0xFF)
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

114)       break;
115)     // drop
116)     return;
117)   }
118) 
119)   // ignore packets sent from invalid source adresses
120)   //  - this might be some attack or some router fault
121)   if (ip_pack->ip_hdr.src[0] >= 0xE0 || // broadcast, reserved or multicast
122)       ip_pack->ip_hdr.src[0] == 0x7F || // loopback network
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

123)       ip_eq(ip_pack->ip_hdr.src, "\x00\x00\x00\x00")) // IP 0.0.0.0
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

124)     return;
125)   // ignore packets sent from local network or broadcast address
126)   if ((ip_pack->ip_hdr.src[0] & config_ip.mask[0]) ==
127)         (config_ip.ip[0] & config_ip.mask[0]) && // source IP is in own subnet
128)       (ip_pack->ip_hdr.src[1] & config_ip.mask[1]) ==
129)         (config_ip.ip[1] & config_ip.mask[1]) &&
130)       (ip_pack->ip_hdr.src[2] & config_ip.mask[2]) ==
131)         (config_ip.ip[2] & config_ip.mask[2]) &&
132)       (ip_pack->ip_hdr.src[3] & config_ip.mask[3]) ==
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

133)         (config_ip.ip[3] & config_ip.mask[3])) {
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

134)     // local network address
135)     if ((ip_pack->ip_hdr.src[0] & ~config_ip.mask[0]) == 0x00 &&
136)         (ip_pack->ip_hdr.src[1] & ~config_ip.mask[1]) == 0x00 &&
137)         (ip_pack->ip_hdr.src[2] & ~config_ip.mask[2]) == 0x00 &&
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

138)         (ip_pack->ip_hdr.src[3] & ~config_ip.mask[3]) == 0x00)
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

139)       return;
140)     // local broadcast address
141)     if ((ip_pack->ip_hdr.src[0] & ~config_ip.mask[0]) == 0xFF &&
142)         (ip_pack->ip_hdr.src[1] & ~config_ip.mask[1]) == 0xFF &&
143)         (ip_pack->ip_hdr.src[2] & ~config_ip.mask[2]) == 0xFF &&
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

144)         (ip_pack->ip_hdr.src[3] & ~config_ip.mask[3]) == 0xFF)
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

145)       return;
146)   }
147)   // ignore packets sent from own IP address
148)   if (ip_eq(ip_pack->ip_hdr.src, config_ip.ip))
149)     return;
150) 
151)   // ignore fragmented packets
152)   // BUG: fragmentation must be supported according to RFC781
153)   //      but there is not enough RAM for assembling packets with up to 64kB
154)   // fragment offset 0, more_frags=0, dont_frag=x, reserved_flag=0
155)   if ((ntohs(ip_pack->ip_hdr.frag_ofs) & 0xBFFF) != 0x0000)
156)     return;
157) 
158)   // check total length
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

159)   len = sizeof(struct ethernet_header) + ntohs(ip_pack->ip_hdr.total_len);
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

160)   if (sz < len) // packet is truncated
161)     return;
162)   sz = len; // remove ethernet padding from packet (maybe sz > len)
163) 
164)   // test header checksum
165)   if (checksum(&ip_pack->ip_hdr, sizeof(struct ip_header), 0x0000, 0x0000))
166)     return;
167) 
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

168)   // save MAC/IP information in ARP table
169)   arp_store(ip_pack->ip_hdr.src, ip_pack->eth_hdr.src);
170) 
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

171)   // branch according to protocol
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

172)   switch (ip_pack->ip_hdr.proto) {
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

173)     // ICMP
174)     case 0x01:
175)       icmp_recv(ptr, sz);
176)       break;
177)     // UDP
178)     case 0x11:
179)       udp_recv(ptr, sz);
180)       break;
181)   }
182) }
183) 
184) /**
185)  * @brief send an IP packet
186)  * @param[in] ptr pointer to data of packet
187)  * @param[in] sz size of packet
188)  *
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

189)  * ptr must point to a ip_packet
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

190)  * with ip_hdr.proto and ip_hdr.dest already initialized
191)  */
192) void ip_send(void *ptr, unsigned int sz)
193) {
194)   struct ip_packet *ip_pack;
195)   unsigned short chk;
196)   unsigned int i;
197) 
198)   // packet too short
199)   if (sz < sizeof(struct ip_packet))
200)     return;
201) 
202)   ip_pack = ptr;
203) 
204)   // fill in header values
205)   ip_pack->ip_hdr.ver__hdr_len = 0x45;
206)   ip_pack->ip_hdr.tos = 0x00;
207)   ip_pack->ip_hdr.total_len = htons(sz - sizeof(struct ethernet_header));
208)   ip_pack->ip_hdr.id = 0x0000;
209)   ip_pack->ip_hdr.frag_ofs = 0x0000;
210)   ip_pack->ip_hdr.ttl = 0x40;
211)   ip_pack->ip_hdr.hdr_chk = 0x0000;
212)   ip_cpy(ip_pack->ip_hdr.src, config_ip.ip);
213) 
214)   // generate header checksum
215)   chk = checksum(&ip_pack->ip_hdr, sizeof(struct ip_header), 0x0000, 0x0000);
216)   ip_pack->ip_hdr.hdr_chk = htons(chk);
217) 
218)   // destination is in own subnet
219)   if ((ip_pack->ip_hdr.dest[0] & config_ip.mask[0]) ==
220)         (config_ip.ip[0] & config_ip.mask[0]) &&
221)       (ip_pack->ip_hdr.dest[1] & config_ip.mask[1]) ==
222)         (config_ip.ip[1] & config_ip.mask[1]) &&
223)       (ip_pack->ip_hdr.dest[2] & config_ip.mask[2]) ==
224)         (config_ip.ip[2] & config_ip.mask[2]) &&
225)       (ip_pack->ip_hdr.dest[3] & config_ip.mask[3]) ==
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

226)         (config_ip.ip[3] & config_ip.mask[3]))
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

227)     // lookup MAC address of destination
228)     i = arp_lookup(ip_pack->ip_hdr.dest, ip_pack->eth_hdr.dest);
229)   // destination is not in own subnet
230)   else
231)     // lookup MAC address of default gateway
232)     i = arp_lookup(config_ip.gw, ip_pack->eth_hdr.dest);
233) 
234)   // MAC available
235)   if (i == 0x00) {
236)     // sent IP packet
237)     ip_pack->eth_hdr.type = htons(0x0800); // ethernet packet type: IP
238)     ethernet_send(ip_pack, sz);
239)     return;
240)   }
241) 
242)   // find a buffer to store the packet in
243)   for (i = 0; i < count(ip_buffer_tab); i++) {
244)     if (ip_buffer_tab[i].pkg_sz == 0 && // buffer not in use
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

245)         sz <= ip_buffer_tab[i].buf_sz) { // buffer long enough
Stefan Schuermans implemented IP + ICMP, fixe...

Stefan Schuermans authored 12 years ago

246)       // put packet into buffer
247)       memcpy(ip_buffer_tab[i].ptr, ptr, sz);
248)       ip_buffer_tab[i].pkg_sz = sz;
249)       ip_buffer_tab[i].ticks = 0;
250)       break;
251)     }
252)   }
253)   /* if no buffer was found, we cannnot do anything about it
254)      and must discard the packet (i.e. do nothing here) */
255) }
256) 
257) /**
258)  * @brief a MAC address was discovered
259)  * @param[in] ip the IP address the MAC was discovered for
260)  * @param[in] mac the MAC address corresponding to the IP address
261)  *
262)  * called by ARP to notify IP
263)  */
264) void ip_got_mac(unsigned char ip[4], unsigned char mac[6])
265) {
266)   unsigned char i;
267)   struct ip_packet *ip_pack;
268) 
269)   // search for buffered packets that can be sent now
270)   for (i = 0; i < count(ip_buffer_tab); i++) {
271)     if (ip_buffer_tab[i].pkg_sz > 0) { // buffer in use
272)       ip_pack = ip_buffer_tab[i].ptr;
273) 
274)       // destination is in own subnet
275)       if ((ip_pack->ip_hdr.dest[0] & config_ip.mask[0]) ==
276)             (config_ip.ip[0] & config_ip.mask[0]) &&
277)           (ip_pack->ip_hdr.dest[1] & config_ip.mask[1]) ==
278)             (config_ip.ip[1] & config_ip.mask[1]) &&
279)           (ip_pack->ip_hdr.dest[2] & config_ip.mask[2]) ==
280)             (config_ip.ip[2] & config_ip.mask[2]) &&
281)           (ip_pack->ip_hdr.dest[3] & config_ip.mask[3]) ==
282)             (config_ip.ip[3] & config_ip.mask[3])) {
283)         // packet can be sent to destination
Stefan Schuermans use implicit MAC/IP informa...

Stefan Schuermans authored 12 years ago

284)         if (ip_eq(ip_pack->ip_hdr.dest, ip)) {