1/*
2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
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.
15 *
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
25 * OF SUCH DAMAGE.
26 *
27 * This file is part of the lwIP TCP/IP stack.
28 *
29 * Author: Adam Dunkels <adam@sics.se>
30 *
31 */
32
33
34
35/* ip.c
36 *
37 * This is the code for the IP layer for IPv6.
38 *
39 */
40
41
42#include "lwip/opt.h"
43
44#include "lwip/def.h"
45#include "lwip/mem.h"
46#include "lwip/ip.h"
47#include "lwip/inet.h"
48#include "lwip/netif.h"
49#include "lwip/icmp.h"
50#include "lwip/udp.h"
51#include "lwip/tcp.h"
52
53#include "lwip/stats.h"
54
55#include "arch/perf.h"
56
57/* ip_init:
58 *
59 * Initializes the IP layer.
60 */
61
62void ip_init(void)
63{
64}
65
66/* ip_route:
67 *
68 * Finds the appropriate network interface for a given IP address. It searches the
69 * list of network interfaces linearly. A match is found if the masked IP address of
70 * the network interface equals the masked IP address given to the function.
71 */
72
73struct netif *ip_route(struct ip_addr *dest)
74{
75    struct netif *netif;
76
77    for (netif = netif_list; netif != NULL; netif = netif->next) {
78        if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
79            return netif;
80        }
81    }
82
83    return netif_default;
84}
85
86/* ip_forward:
87 *
88 * Forwards an IP packet. It finds an appropriate route for the packet, decrements
89 * the TTL value of the packet, adjusts the checksum and outputs the packet on the
90 * appropriate interface.
91 */
92
93static void ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
94{
95    struct netif *netif;
96
97    PERF_START;
98
99    if ((netif = ip_route((struct ip_addr *) &(iphdr->dest))) == NULL) {
100
101        LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for "));
102#if IP_DEBUG
103        ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest)));
104#endif                          /* IP_DEBUG */
105        LWIP_DEBUGF(IP_DEBUG, ("\n"));
106        pbuf_free(p);
107        return;
108    }
109    /* Decrement TTL and send ICMP if ttl == 0. */
110    if (--iphdr->hoplim == 0) {
111#if LWIP_ICMP
112        /* Don't send ICMP messages in response to ICMP messages */
113        if (iphdr->nexthdr != IP_PROTO_ICMP) {
114            icmp_time_exceeded(p, ICMP_TE_TTL);
115        }
116#endif                          /* LWIP_ICMP */
117        pbuf_free(p);
118        return;
119    }
120
121    /* Incremental update of the IP checksum. */
122    /*  if (iphdr->chksum >= htons(0xffff - 0x100)) {
123       iphdr->chksum += htons(0x100) + 1;
124       } else {
125       iphdr->chksum += htons(0x100);
126       } */
127
128
129    LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to "));
130#if IP_DEBUG
131    ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest)));
132#endif                          /* IP_DEBUG */
133    LWIP_DEBUGF(IP_DEBUG, ("\n"));
134
135    IP_STATS_INC(ip.fw);
136    IP_STATS_INC(ip.xmit);
137
138    PERF_STOP("ip_forward");
139
140    netif->output(netif, p, (struct ip_addr *) &(iphdr->dest));
141}
142
143/* ip_input:
144 *
145 * This function is called by the network interface device driver when an IP packet is
146 * received. The function does the basic checks of the IP header such as packet size
147 * being at least larger than the header size etc. If the packet was not destined for
148 * us, the packet is forwarded (using ip_forward). The IP checksum is always checked.
149 *
150 * Finally, the packet is sent to the upper layer protocol input function.
151 */
152
153void ip_input(struct pbuf *p, struct netif *inp)
154{
155    struct ip_hdr *iphdr;
156    struct netif *netif;
157
158
159    PERF_START;
160
161#if IP_DEBUG
162    ip_debug_print(p);
163#endif                          /* IP_DEBUG */
164
165
166    IP_STATS_INC(ip.recv);
167
168    /* identify the IP header */
169    iphdr = p->payload;
170
171
172    if (iphdr->v != 6) {
173        LWIP_DEBUGF(IP_DEBUG,
174                    ("IP packet dropped due to bad version number\n"));
175#if IP_DEBUG
176        ip_debug_print(p);
177#endif                          /* IP_DEBUG */
178        pbuf_free(p);
179        IP_STATS_INC(ip.err);
180        IP_STATS_INC(ip.drop);
181        return;
182    }
183
184    /* is this packet for us? */
185    for (netif = netif_list; netif != NULL; netif = netif->next) {
186#if IP_DEBUG
187        LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest "));
188        ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest)));
189        LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr "));
190        ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest)));
191        LWIP_DEBUGF(IP_DEBUG, ("\n"));
192#endif                          /* IP_DEBUG */
193        if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) {
194            break;
195        }
196    }
197
198
199    if (netif == NULL) {
200        /* packet not for us, route or discard */
201#if IP_FORWARD
202        ip_forward(p, iphdr);
203#endif
204        pbuf_free(p);
205        return;
206    }
207
208    pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len));
209
210    /* send to upper layers */
211#if IP_DEBUG
212    /*  LWIP_DEBUGF("ip_input: \n");
213       ip_debug_print(p);
214       LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len); */
215#endif                          /* IP_DEBUG */
216
217    if (pbuf_header(p, -IP_HLEN)) {
218        LWIP_ASSERT("Can't move over header in packet", 0);
219        return;
220    }
221
222    switch (iphdr->nexthdr) {
223        case IP_PROTO_UDP:
224            udp_input(p, inp);
225            break;
226        case IP_PROTO_TCP:
227            tcp_input(p, inp);
228            break;
229#if LWIP_ICMP
230        case IP_PROTO_ICMP:
231            icmp_input(p, inp);
232            break;
233#endif                          /* LWIP_ICMP */
234        default:
235#if LWIP_ICMP
236            /* send ICMP destination protocol unreachable */
237            icmp_dest_unreach(p, ICMP_DUR_PROTO);
238#endif                          /* LWIP_ICMP */
239            pbuf_free(p);
240            LWIP_DEBUGF(IP_DEBUG,
241                        ("Unsupported transport protocol %" U16_F "\n",
242                         iphdr->nexthdr));
243
244            IP_STATS_INC(ip.proterr);
245            IP_STATS_INC(ip.drop);
246    }
247    PERF_STOP("ip_input");
248}
249
250
251/* ip_output_if:
252 *
253 * Sends an IP packet on a network interface. This function constructs the IP header
254 * and calculates the IP header checksum. If the source IP address is NULL,
255 * the IP address of the outgoing network interface is filled in as source address.
256 */
257
258err_t
259ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
260             u8_t ttl, u8_t proto, struct netif *netif)
261{
262    struct ip_hdr *iphdr;
263
264    PERF_START;
265
266    LWIP_DEBUGF(IP_DEBUG,
267                ("len %" U16_F " tot_len %" U16_F "\n", p->len, p->tot_len));
268    if (pbuf_header(p, IP_HLEN)) {
269        LWIP_DEBUGF(IP_DEBUG,
270                    ("ip_output: not enough room for IP header in pbuf\n"));
271        IP_STATS_INC(ip.err);
272
273        return ERR_BUF;
274    }
275    LWIP_DEBUGF(IP_DEBUG,
276                ("len %" U16_F " tot_len %" U16_F "\n", p->len, p->tot_len));
277
278    iphdr = p->payload;
279
280
281    if (dest != IP_HDRINCL) {
282        LWIP_DEBUGF(IP_DEBUG, ("!IP_HDRLINCL\n"));
283        iphdr->hoplim = ttl;
284        iphdr->nexthdr = proto;
285        iphdr->len = htons(p->tot_len - IP_HLEN);
286        ip_addr_set(&(iphdr->dest), dest);
287
288        iphdr->v = 6;
289
290        if (ip_addr_isany(src)) {
291            ip_addr_set(&(iphdr->src), &(netif->ip_addr));
292        } else {
293            ip_addr_set(&(iphdr->src), src);
294        }
295
296    } else {
297        dest = &(iphdr->dest);
298    }
299
300    IP_STATS_INC(ip.xmit);
301
302    LWIP_DEBUGF(IP_DEBUG,
303                ("ip_output_if: %c%c (len %" U16_F ")\n", netif->name[0],
304                 netif->name[1], p->tot_len));
305#if IP_DEBUG
306    ip_debug_print(p);
307#endif                          /* IP_DEBUG */
308
309    PERF_STOP("ip_output_if");
310    return netif->output(netif, p, dest);
311}
312
313/* ip_output:
314 *
315 * Simple interface to ip_output_if. It finds the outgoing network interface and
316 * calls upon ip_output_if to do the actual work.
317 */
318
319err_t
320ip_output(struct pbuf * p, struct ip_addr * src, struct ip_addr * dest,
321          u8_t ttl, u8_t proto)
322{
323    struct netif *netif;
324
325    if ((netif = ip_route(dest)) == NULL) {
326        LWIP_DEBUGF(IP_DEBUG,
327                    ("ip_output: No route to 0x%" X32_F "\n", dest->addr));
328        IP_STATS_INC(ip.rterr);
329        return ERR_RTE;
330    }
331
332    return ip_output_if(p, src, dest, ttl, proto, netif);
333}
334
335#if LWIP_NETIF_HWADDRHINT
336err_t
337ip_output_hinted(struct pbuf * p, struct ip_addr * src, struct ip_addr * dest,
338                 u8_t ttl, u8_t tos, u8_t proto, u8_t * addr_hint)
339{
340    struct netif *netif;
341    err_t err;
342
343    if ((netif = ip_route(dest)) == NULL) {
344        LWIP_DEBUGF(IP_DEBUG,
345                    ("ip_output: No route to 0x%" X32_F "\n", dest->addr));
346        IP_STATS_INC(ip.rterr);
347        return ERR_RTE;
348    }
349
350    netif->addr_hint = addr_hint;
351    err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
352    netif->addr_hint = NULL;
353
354    return err;
355}
356#endif                          /* LWIP_NETIF_HWADDRHINT */
357
358#if IP_DEBUG
359void ip_debug_print(struct pbuf *p)
360{
361    struct ip_hdr *iphdr = p->payload;
362
363    LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
364    LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
365    LWIP_DEBUGF(IP_DEBUG,
366                ("|%2" S16_F " |  %" X16_F "%" X16_F "  |      %" X16_F "%"
367                 X16_F "           | (v, traffic class, flow label)\n",
368                 iphdr->v, iphdr->tclass1, iphdr->tclass2, iphdr->flow1,
369                 iphdr->flow2));
370    LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
371    LWIP_DEBUGF(IP_DEBUG,
372                ("|    %5" U16_F "      | %2" U16_F "  |  %2" U16_F
373                 "   | (len, nexthdr, hoplim)\n", ntohs(iphdr->len),
374                 iphdr->nexthdr, iphdr->hoplim));
375    LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
376    LWIP_DEBUGF(IP_DEBUG,
377                ("|       %4" X32_F "      |       %4" X32_F "     | (src)\n",
378                 (ntohl(iphdr->src.addr[0]) >> 16) & 0xffff,
379                 ntohl(iphdr->src.addr[0]) & 0xffff));
380    LWIP_DEBUGF(IP_DEBUG,
381                ("|       %4" X32_F "      |       %4" X32_F "     | (src)\n",
382                 (ntohl(iphdr->src.addr[1]) >> 16) & 0xffff,
383                 ntohl(iphdr->src.addr[1]) & 0xffff));
384    LWIP_DEBUGF(IP_DEBUG,
385                ("|       %4" X32_F "      |       %4" X32_F "     | (src)\n",
386                 (ntohl(iphdr->src.addr[2]) >> 16) & 0xffff,
387                 ntohl(iphdr->src.addr[2]) & 0xffff));
388    LWIP_DEBUGF(IP_DEBUG,
389                ("|       %4" X32_F "      |       %4" X32_F "     | (src)\n",
390                 (ntohl(iphdr->src.addr[3]) >> 16) & 0xffff,
391                 ntohl(iphdr->src.addr[3]) & 0xffff));
392    LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
393    LWIP_DEBUGF(IP_DEBUG,
394                ("|       %4" X32_F "      |       %4" X32_F "     | (dest)\n",
395                 (ntohl(iphdr->dest.addr[0]) >> 16) & 0xffff,
396                 ntohl(iphdr->dest.addr[0]) & 0xffff));
397    LWIP_DEBUGF(IP_DEBUG,
398                ("|       %4" X32_F "      |       %4" X32_F "     | (dest)\n",
399                 (ntohl(iphdr->dest.addr[1]) >> 16) & 0xffff,
400                 ntohl(iphdr->dest.addr[1]) & 0xffff));
401    LWIP_DEBUGF(IP_DEBUG,
402                ("|       %4" X32_F "      |       %4" X32_F "     | (dest)\n",
403                 (ntohl(iphdr->dest.addr[2]) >> 16) & 0xffff,
404                 ntohl(iphdr->dest.addr[2]) & 0xffff));
405    LWIP_DEBUGF(IP_DEBUG,
406                ("|       %4" X32_F "      |       %4" X32_F "     | (dest)\n",
407                 (ntohl(iphdr->dest.addr[3]) >> 16) & 0xffff,
408                 ntohl(iphdr->dest.addr[3]) & 0xffff));
409    LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
410}
411#endif                          /* IP_DEBUG */
412