87 |
|
|
88 |
iphdr = header; |
iphdr = header; |
89 |
|
|
90 |
/* Refuse anything that isn't IPv4. */ |
/* not IP v4? */ |
91 |
if(IPH_V(iphdr) != 4) { |
if(IPH_V(iphdr) != 4) { |
92 |
return 0; |
return 0; |
93 |
} |
} |
137 |
ip_route(struct ip_addr *dest) |
ip_route(struct ip_addr *dest) |
138 |
{ |
{ |
139 |
struct netif *netif; |
struct netif *netif; |
140 |
|
|
141 |
|
/* iterate through netifs */ |
142 |
for(netif = netif_list; netif != NULL; netif = netif->next) { |
for(netif = netif_list; netif != NULL; netif = netif->next) { |
143 |
|
/* network mask matches? */ |
144 |
if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) { |
if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) { |
145 |
|
/* return netif on which to forward IP packet */ |
146 |
return netif; |
return netif; |
147 |
} |
} |
148 |
} |
} |
149 |
|
/* no matching netif found, use default netif */ |
150 |
return netif_default; |
return netif_default; |
151 |
} |
} |
152 |
#if IP_FORWARD |
#if IP_FORWARD |
164 |
struct netif *netif; |
struct netif *netif; |
165 |
|
|
166 |
PERF_START; |
PERF_START; |
167 |
|
/* Find network interface where to forward this IP packet to. */ |
168 |
if((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) { |
netif = ip_route((struct ip_addr *)&(iphdr->dest)); |
169 |
|
if(netif == NULL) { |
170 |
DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n", |
DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n", |
171 |
iphdr->dest.addr)); |
iphdr->dest.addr)); |
|
|
|
172 |
#if LWIP_SNMP > 0 |
#if LWIP_SNMP > 0 |
173 |
snmp_inc_ipnoroutes(); |
snmp_inc_ipnoroutes(); |
174 |
#endif |
#endif |
175 |
return; |
return; |
176 |
} |
} |
177 |
|
/* Do not forward packets onto the same network interface on which |
|
/* Don't forward packets onto the same network interface on which |
|
178 |
they arrived. */ |
they arrived. */ |
179 |
if(netif == inp) { |
if(netif == inp) { |
180 |
DEBUGF(IP_DEBUG, ("ip_forward: not forward packets back on incoming interface.\n")); |
DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); |
|
|
|
181 |
#if LWIP_SNMP > 0 |
#if LWIP_SNMP > 0 |
182 |
snmp_inc_ipnoroutes(); |
snmp_inc_ipnoroutes(); |
183 |
#endif |
#endif |
184 |
return; |
return; |
185 |
} |
} |
186 |
|
|
187 |
/* Decrement TTL and send ICMP if ttl == 0. */ |
/* decrement TTL */ |
188 |
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); |
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); |
189 |
|
/* send ICMP if TTL == 0 */ |
190 |
if(IPH_TTL(iphdr) == 0) { |
if(IPH_TTL(iphdr) == 0) { |
191 |
/* Don't send ICMP messages in response to ICMP messages */ |
/* Don't send ICMP messages in response to ICMP messages */ |
192 |
if(IPH_PROTO(iphdr) != IP_PROTO_ICMP) { |
if(IPH_PROTO(iphdr) != IP_PROTO_ICMP) { |
198 |
return; |
return; |
199 |
} |
} |
200 |
|
|
201 |
/* Incremental update of the IP checksum. */ |
/* Incrementally update the IP checksum. */ |
202 |
if(IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) { |
if(IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) { |
203 |
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1); |
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1); |
204 |
} else { |
} else { |
217 |
#endif |
#endif |
218 |
|
|
219 |
PERF_STOP("ip_forward"); |
PERF_STOP("ip_forward"); |
220 |
|
/* transmit pbuf on chosen interface */ |
221 |
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); |
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); |
222 |
} |
} |
223 |
#endif /* IP_FORWARD */ |
#endif /* IP_FORWARD */ |
237 |
ip_input(struct pbuf *p, struct netif *inp) { |
ip_input(struct pbuf *p, struct netif *inp) { |
238 |
static struct ip_hdr *iphdr; |
static struct ip_hdr *iphdr; |
239 |
static struct netif *netif; |
static struct netif *netif; |
240 |
static u8_t hl; |
static u16_t iphdrlen; |
|
|
|
|
|
|
241 |
|
|
242 |
#ifdef IP_STATS |
#ifdef IP_STATS |
243 |
++lwip_stats.ip.recv; |
++lwip_stats.ip.recv; |
263 |
#endif |
#endif |
264 |
return ERR_OK; |
return ERR_OK; |
265 |
} |
} |
266 |
|
/* obtain IP header length in number of 32-bit words */ |
267 |
hl = IPH_HL(iphdr); |
iphdrlen = IPH_HL(iphdr); |
268 |
|
/* calculate IP header length in bytes */ |
269 |
if(hl * 4 > p->len) { |
iphdrlen *= 4; |
270 |
DEBUGF(IP_DEBUG, ("IP packet dropped due to too short packet %d\n", p->len)); |
|
271 |
|
/* header length exceeds first pbuf length? */ |
272 |
|
if(iphdrlen > p->len) { |
273 |
|
DEBUGF(IP_DEBUG, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n", |
274 |
|
iphdrlen, p->len)); |
275 |
|
/* free (drop) packet pbufs */ |
276 |
pbuf_free(p); |
pbuf_free(p); |
277 |
#ifdef IP_STATS |
#ifdef IP_STATS |
278 |
++lwip_stats.ip.lenerr; |
++lwip_stats.ip.lenerr; |
285 |
} |
} |
286 |
|
|
287 |
/* verify checksum */ |
/* verify checksum */ |
288 |
if(inet_chksum(iphdr, hl * 4) != 0) { |
if(inet_chksum(iphdr, iphdrlen) != 0) { |
289 |
|
|
290 |
DEBUGF(IP_DEBUG, ("IP packet dropped due to failing checksum 0x%x\n", inet_chksum(iphdr, hl * 4))); |
DEBUGF(IP_DEBUG, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen))); |
291 |
#if IP_DEBUG |
#if IP_DEBUG |
292 |
ip_debug_print(p); |
ip_debug_print(p); |
293 |
#endif /* IP_DEBUG */ |
#endif /* IP_DEBUG */ |
320 |
{ |
{ |
321 |
/* unicast to this interface address? */ |
/* unicast to this interface address? */ |
322 |
if(ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) || |
if(ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) || |
323 |
/* or broadcast on this interface network address ? */ |
/* or broadcast matching this interface network address? */ |
324 |
(ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) && |
(ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) && |
325 |
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) || |
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) || |
326 |
/* or restricted broadcast? */ |
/* or restricted broadcast? */ |
327 |
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) { |
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) { |
328 |
|
DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", |
329 |
|
netif->name[0], netif->name[1])); |
330 |
/* break out of for loop */ |
/* break out of for loop */ |
331 |
break; |
break; |
332 |
} |
} |
333 |
} |
} |
334 |
|
} |
335 |
#if LWIP_DHCP |
#if LWIP_DHCP |
336 |
/* Pass DHCP messages in case of an unconfigured (0.0.0.0) interface, regardless |
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed |
337 |
of destination address. (DHCP replies are sent to the IP address-to-be. This |
using link layer addressing (such as Ethernet MAC) so we must not filter on IP. |
338 |
is according to RFC 1542 section 3.1.1, referred by RFC 2131). */ |
According to RFC 1542 section 3.1.1, referred by RFC 2131). */ |
339 |
|
if(netif == NULL) { |
340 |
/* interface unconfigured (0.0.0.0) */ |
/* remote port is DHCP server? */ |
341 |
else { |
if(IPH_PROTO(iphdr) == IP_PROTO_UDP) { |
342 |
/* remote port is DHCP server? */ |
DEBUGF(IP_DEBUG, ("ip_input: UDP packet to DHCP client port %u\n", |
343 |
if(IPH_PROTO(iphdr) == IP_PROTO_UDP && |
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest))); |
344 |
((struct udp_hdr *)((u8_t *)iphdr + IPH_HL(iphdr) * 4))->src == DHCP_SERVER_PORT) { |
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) { |
345 |
netif = inp; |
DEBUGF(IP_DEBUG, ("ip_input: DHCP packet accepted.\n")); |
346 |
/* break out of for loop */ |
netif = inp; |
|
break; |
|
347 |
} |
} |
348 |
} |
} |
|
#endif /* LWIP_DHCP */ |
|
349 |
} |
} |
350 |
|
#endif /* LWIP_DHCP */ |
351 |
|
/* packet not for us? */ |
352 |
if(netif == NULL) { |
if(netif == NULL) { |
353 |
/* packet not for us, route or discard */ |
/* packet not for us, route or discard */ |
354 |
DEBUGF(IP_DEBUG, ("ip_input: packet not for us.\n")); |
DEBUGF(IP_DEBUG, ("ip_input: packet not for us.\n")); |
355 |
#if IP_FORWARD |
#if IP_FORWARD |
356 |
|
/* non-broadcast packet? */ |
357 |
if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) { |
if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) { |
358 |
|
/* try to forward IP packet on (other) interfaces */ |
359 |
ip_forward(p, iphdr, inp); |
ip_forward(p, iphdr, inp); |
360 |
} |
} |
361 |
else |
else |
380 |
#else /* IP_REASSEMBLY */ |
#else /* IP_REASSEMBLY */ |
381 |
if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { |
if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { |
382 |
pbuf_free(p); |
pbuf_free(p); |
383 |
DEBUGF(IP_DEBUG, ("IP packet dropped since it was fragmented (0x%x).\n", |
DEBUGF(IP_DEBUG, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n", |
384 |
ntohs(IPH_OFFSET(iphdr)))); |
ntohs(IPH_OFFSET(iphdr)))); |
385 |
#ifdef IP_STATS |
#ifdef IP_STATS |
386 |
++lwip_stats.ip.opterr; |
++lwip_stats.ip.opterr; |
387 |
++lwip_stats.ip.drop; |
++lwip_stats.ip.drop; |
394 |
#endif /* IP_REASSEMBLY */ |
#endif /* IP_REASSEMBLY */ |
395 |
|
|
396 |
#if IP_OPTIONS == 0 |
#if IP_OPTIONS == 0 |
397 |
if(hl * 4 > IP_HLEN) { |
if(iphdrlen > IP_HLEN) { |
398 |
DEBUGF(IP_DEBUG, ("IP packet dropped since there were IP options.\n")); |
DEBUGF(IP_DEBUG, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n")); |
|
|
|
399 |
pbuf_free(p); |
pbuf_free(p); |
400 |
#ifdef IP_STATS |
#ifdef IP_STATS |
401 |
++lwip_stats.ip.opterr; |
++lwip_stats.ip.opterr; |
408 |
} |
} |
409 |
#endif /* IP_OPTIONS == 0 */ |
#endif /* IP_OPTIONS == 0 */ |
410 |
|
|
|
|
|
411 |
/* send to upper layers */ |
/* send to upper layers */ |
412 |
#if IP_DEBUG |
#if IP_DEBUG |
413 |
DEBUGF(IP_DEBUG, ("ip_input: \n")); |
DEBUGF(IP_DEBUG, ("ip_input: \n")); |
535 |
ip_debug_print(p); |
ip_debug_print(p); |
536 |
#endif /* IP_DEBUG */ |
#endif /* IP_DEBUG */ |
537 |
|
|
538 |
DEBUGF(IP_DEBUG, ("netif->output()")); |
DEBUGF(IP_DEBUG, ("netif->output()")); |
539 |
|
|
540 |
return netif->output(netif, p, dest); |
return netif->output(netif, p, dest); |
541 |
} |
} |