2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
37 * This is the code for the IP layer.
48 #include "lwip/ip_frag.h"
49 #include "lwip/inet.h"
50 #include "lwip/netif.h"
51 #include "lwip/icmp.h"
56 #include "lwip/stats.h"
58 #include "lwip/snmp.h"
60 # include "lwip/dhcp.h"
61 #endif /* LWIP_DHCP */
66 * Initializes the IP layer.
76 * An experimental feature that will be changed in future versions. Do
77 * not depend on it yet...
82 ip_lookup(void *header
, struct netif
*inp
)
89 if (IPH_V(iphdr
) != 4) {
94 if (IPH_HL(iphdr
) != 5) {
97 #endif /* IP_OPTIONS == 0 */
99 switch (IPH_PROTO(iphdr
)) {
102 case IP_PROTO_UDPLITE
:
103 return udp_lookup(iphdr
, inp
);
104 #endif /* LWIP_UDP */
108 #endif /* LWIP_TCP */
115 #endif /* LWIP_DEBUG */
119 * Finds the appropriate network interface for a given IP address. It
120 * searches the list of network interfaces linearly. A match is found
121 * if the masked IP address of the network interface equals the masked
122 * IP address given to the function.
126 ip_route(struct ip_addr
*dest
)
130 /* iterate through netifs */
131 for(netif
= netif_list
; netif
!= NULL
; netif
= netif
->next
) {
132 /* network mask matches? */
133 if (ip_addr_maskcmp(dest
, &(netif
->ip_addr
), &(netif
->netmask
))) {
134 /* return netif on which to forward IP packet */
138 /* no matching netif found, use default netif */
139 return netif_default
;
145 * Forwards an IP packet. It finds an appropriate route for the
146 * packet, decrements the TTL value of the packet, adjusts the
147 * checksum and outputs the packet on the appropriate interface.
151 ip_forward(struct pbuf
*p
, struct ip_hdr
*iphdr
, struct netif
*inp
)
156 /* Find network interface where to forward this IP packet to. */
157 netif
= ip_route((struct ip_addr
*)&(iphdr
->dest
));
159 LWIP_DEBUGF(IP_DEBUG
, ("ip_forward: no forwarding route for 0x%lx found\n",
161 snmp_inc_ipnoroutes();
164 /* Do not forward packets onto the same network interface on which
167 LWIP_DEBUGF(IP_DEBUG
, ("ip_forward: not bouncing packets back on incoming interface.\n"));
168 snmp_inc_ipnoroutes();
173 IPH_TTL_SET(iphdr
, IPH_TTL(iphdr
) - 1);
174 /* send ICMP if TTL == 0 */
175 if (IPH_TTL(iphdr
) == 0) {
176 /* Don't send ICMP messages in response to ICMP messages */
177 if (IPH_PROTO(iphdr
) != IP_PROTO_ICMP
) {
178 icmp_time_exceeded(p
, ICMP_TE_TTL
);
179 snmp_inc_icmpouttimeexcds();
183 /* Incrementally update the IP checksum. */
184 if (IPH_CHKSUM(iphdr
) >= htons(0xffff - 0x100)) {
185 IPH_CHKSUM_SET(iphdr
, IPH_CHKSUM(iphdr
) + 2 );
187 IPH_CHKSUM_SET(iphdr
, IPH_CHKSUM(iphdr
) + 1 );
190 LWIP_DEBUGF(IP_DEBUG
, ("ip_forward: forwarding packet to 0x%lx\n",
194 IP_STATS_INC(ip
.xmit
);
195 snmp_inc_ipforwdatagrams();
197 PERF_STOP("ip_forward");
198 /* transmit pbuf on chosen interface */
199 netif
->output(netif
, p
, (struct ip_addr
*)&(iphdr
->dest
));
201 #endif /* IP_FORWARD */
205 * This function is called by the network interface device driver when
206 * an IP packet is received. The function does the basic checks of the
207 * IP header such as packet size being at least larger than the header
208 * size etc. If the packet was not destined for us, the packet is
209 * forwarded (using ip_forward). The IP checksum is always checked.
211 * Finally, the packet is sent to the upper layer protocol input function.
213 err_t
ip_input ( struct pbuf
* p
, struct netif
* inp
) {
215 static struct ip_hdr
* iphdr
;
216 static struct netif
* netif
;
217 static u16_t iphdrlen
;
219 iphdr
= p
-> payload
;
221 if ( IPH_V( iphdr
) != 4 ) {
226 iphdrlen
= IPH_HL( iphdr
);
229 if ( iphdrlen
> p
-> len
) {
234 if ( inet_chksum ( iphdr
, iphdrlen
) ) {
239 pbuf_realloc ( p
, ntohs ( IPH_LEN( iphdr
) ) );
241 for ( netif
= netif_list
; netif
; netif
= netif
-> next
)
243 if ( !ip_addr_isany ( &netif
-> ip_addr
) ) {
245 if ( ip_addr_cmp ( &iphdr
-> dest
, &netif
-> ip_addr
) || (
246 ip_addr_isbroadcast ( &iphdr
-> dest
, &netif
-> netmask
) &&
247 ip_addr_maskcmp ( &iphdr
-> dest
, &netif
-> ip_addr
, &netif
-> netmask
)
248 ) || ip_addr_cmp ( &iphdr
-> dest
, IP_ADDR_BROADCAST
)
254 if ( IPH_PROTO( iphdr
) == IP_PROTO_UDP
) {
256 ( ( struct udp_hdr
* )( ( u8_t
* )iphdr
+ iphdrlen
) ) -> dest
257 ) == DHCP_CLIENT_PORT
261 #endif /* LWIP_DHCP */
264 if ( !ip_addr_isbroadcast ( &iphdr
-> dest
, &inp
-> netmask
) ) ip_forward ( p
, iphdr
, inp
);
265 #endif /* IP_FORWARD */
270 if ( ( IPH_OFFSET( iphdr
) & 0xFF3F ) != 0 ) {
272 if ( p
== NULL
) return ERR_OK
;
273 iphdr
= p
-> payload
;
275 #else /* IP_REASSEMBLY */
276 if ( ( IPH_OFFSET( iphdr
) & 0xFF3F ) != 0 ) {
280 #endif /* IP_REASSEMBLY */
282 if (iphdrlen
> IP_HLEN
) {
283 LWIP_DEBUGF(IP_DEBUG
| 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
285 IP_STATS_INC(ip
.opterr
);
286 IP_STATS_INC(ip
.drop
);
287 snmp_inc_ipunknownprotos();
290 #endif /* IP_OPTIONS == 0 */
292 if (!raw_input(p
, inp
)) {
293 #endif /* LWIP_RAW */
295 switch (IPH_PROTO(iphdr
)) {
298 case IP_PROTO_UDPLITE
:
299 snmp_inc_ipindelivers();
302 #endif /* LWIP_UDP */
305 snmp_inc_ipindelivers();
308 #endif /* LWIP_TCP */
310 snmp_inc_ipindelivers();
314 /* send ICMP destination protocol unreachable unless is was a broadcast */
315 if (!ip_addr_isbroadcast(&(iphdr
->dest
), &(inp
->netmask
)) &&
316 !ip_addr_ismulticast(&(iphdr
->dest
))) {
318 icmp_dest_unreach(p
, ICMP_DUR_PROTO
);
332 * Sends an IP packet on a network interface. This function constructs
333 * the IP header and calculates the IP header checksum. If the source
334 * IP address is NULL, the IP address of the outgoing network
335 * interface is filled in as source address.
339 ip_output_if(struct pbuf
*p
, struct ip_addr
*src
, struct ip_addr
*dest
,
341 u8_t proto
, struct netif
*netif
)
343 static struct ip_hdr
*iphdr
;
344 static u16_t ip_id
= 0;
346 snmp_inc_ipoutrequests();
348 if (dest
!= IP_HDRINCL
) {
349 if (pbuf_header(p
, IP_HLEN
)) {
350 LWIP_DEBUGF(IP_DEBUG
| 2, ("ip_output: not enough room for IP header in pbuf\n"));
352 IP_STATS_INC(ip
.err
);
353 snmp_inc_ipoutdiscards();
359 IPH_TTL_SET(iphdr
, ttl
);
360 IPH_PROTO_SET(iphdr
, proto
);
362 ip_addr_set(&(iphdr
->dest
), dest
);
364 IPH_VHLTOS_SET(iphdr
, 4, IP_HLEN
/ 4, tos
);
365 IPH_LEN_SET(iphdr
, htons(p
->tot_len
));
366 IPH_OFFSET_SET(iphdr
, 0x0040);
367 IPH_ID_SET(iphdr
, htons(ip_id
));
370 if (ip_addr_isany(src
)) {
371 ip_addr_set(&(iphdr
->src
), &(netif
->ip_addr
));
373 ip_addr_set(&(iphdr
->src
), src
);
376 IPH_CHKSUM_SET(iphdr
, 0);
377 IPH_CHKSUM_SET(iphdr
, inet_chksum(iphdr
, IP_HLEN
));
380 dest
= &(iphdr
->dest
);
384 /* don't fragment if interface has mtu set to 0 [loopif] */
385 if (netif
->mtu
&& (p
->tot_len
> netif
->mtu
))
386 return ip_frag(p
,netif
,dest
);
388 return netif
->output(netif
, p
, dest
);
392 * Simple interface to ip_output_if. It finds the outgoing network
393 * interface and calls upon ip_output_if to do the actual work.
395 err_t
ip_output ( struct pbuf
* p
, struct ip_addr
* src
, struct ip_addr
* dest
, u8_t ttl
, u8_t tos
, u8_t proto
) {
399 if ( !( netif
= ip_route ( dest
) ) ) return ERR_RTE
;
401 return ip_output_if ( p
, src
, dest
, ttl
, tos
, proto
, netif
);
403 } /* end ip_output */