2a4b80d0fbe03ad69747e148b5fd93b0ed7f3f0c
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
33)   unsigned int ticks; //< age of entry (in 200ms)
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;
47)   for (i = 0; i < count(ip_buffer_tab ); i++)
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
57)   for (i = 0; i < count( ip_buffer_tab ); i++) {
58)     if (ip_buffer_tab[i].pkg_sz > 0 ) { // buffer in use
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
89)     if (ip_eq(ip_pack->ip_hdr.dest, config_ip.ip) )
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]) ==
107)           ~config_ip.mask[3] )
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 &&
113)         ip_pack->ip_hdr.dest[3] == 0xFF )
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
123)       ip_eq(ip_pack->ip_hdr.src, "\x00\x00\x00\x00" )) // IP 0.0.0.0
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]) ==
133)         (config_ip.ip[3] & config_ip.mask[3]))
134)   {
135)     // local network address
136)     if ((ip_pack->ip_hdr.src[0] & ~config_ip.mask[0]) == 0x00 &&
137)         (ip_pack->ip_hdr.src[1] & ~config_ip.mask[1]) == 0x00 &&
138)         (ip_pack->ip_hdr.src[2] & ~config_ip.mask[2]) == 0x00 &&
139)         (ip_pack->ip_hdr.src[3] & ~config_ip.mask[3]) == 0x00 )
140)       return;
141)     // local broadcast address
142)     if ((ip_pack->ip_hdr.src[0] & ~config_ip.mask[0]) == 0xFF &&
143)         (ip_pack->ip_hdr.src[1] & ~config_ip.mask[1]) == 0xFF &&
144)         (ip_pack->ip_hdr.src[2] & ~config_ip.mask[2]) == 0xFF &&
145)         (ip_pack->ip_hdr.src[3] & ~config_ip.mask[3]) == 0xFF )
146)       return;
147)   }
148)   // ignore packets sent from own IP address
149)   if (ip_eq(ip_pack->ip_hdr.src, config_ip.ip))
150)     return;
151) 
152)   // ignore fragmented packets
153)   // BUG: fragmentation must be supported according to RFC781
154)   //      but there is not enough RAM for assembling packets with up to 64kB
155)   // fragment offset 0, more_frags=0, dont_frag=x, reserved_flag=0
156)   if ((ntohs(ip_pack->ip_hdr.frag_ofs) & 0xBFFF) != 0x0000)
157)     return;
158) 
159)   // check total length
160)   len = sizeof(struct ethernet_header ) + ntohs(ip_pack->ip_hdr.total_len);
161)   if (sz < len) // packet is truncated
162)     return;
163)   sz = len; // remove ethernet padding from packet (maybe sz > len)
164) 
165)   // test header checksum
166)   if (checksum(&ip_pack->ip_hdr, sizeof(struct ip_header), 0x0000, 0x0000))
167)     return;
168) 
169)   // branch according to protocol
170)   switch(ip_pack->ip_hdr.proto) {
171)     // ICMP
172)     case 0x01:
173)       icmp_recv(ptr, sz);
174)       break;
175)     // UDP
176)     case 0x11:
177)       udp_recv(ptr, sz);
178)       break;
179)   }
180) }
181) 
182) /**
183)  * @brief send an IP packet
184)  * @param[in] ptr pointer to data of packet
185)  * @param[in] sz size of packet
186)  *
Stefan Schuermans handle padding to minimum e...

Stefan Schuermans authored 12 years ago

187)  * ptr must point to a ip_packet