BadVPN – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /** |
2 | * @file |
||
3 | * |
||
4 | * IPv6 layer. |
||
5 | */ |
||
6 | |||
7 | /* |
||
8 | * Copyright (c) 2010 Inico Technologies Ltd. |
||
9 | * All rights reserved. |
||
10 | * |
||
11 | * Redistribution and use in source and binary forms, with or without modification, |
||
12 | * are permitted provided that the following conditions are met: |
||
13 | * |
||
14 | * 1. Redistributions of source code must retain the above copyright notice, |
||
15 | * this list of conditions and the following disclaimer. |
||
16 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
||
17 | * this list of conditions and the following disclaimer in the documentation |
||
18 | * and/or other materials provided with the distribution. |
||
19 | * 3. The name of the author may not be used to endorse or promote products |
||
20 | * derived from this software without specific prior written permission. |
||
21 | * |
||
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||
24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||
25 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||
26 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||
27 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||
30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||
31 | * OF SUCH DAMAGE. |
||
32 | * |
||
33 | * This file is part of the lwIP TCP/IP stack. |
||
34 | * |
||
35 | * Author: Ivan Delamer <delamer@inicotech.com> |
||
36 | * |
||
37 | * |
||
38 | * Please coordinate changes and requests with Ivan Delamer |
||
39 | * <delamer@inicotech.com> |
||
40 | */ |
||
41 | |||
42 | #include "lwip/opt.h" |
||
43 | |||
44 | #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ |
||
45 | |||
46 | #include "lwip/def.h" |
||
47 | #include "lwip/mem.h" |
||
48 | #include "lwip/netif.h" |
||
49 | #include "lwip/ip.h" |
||
50 | #include "lwip/ip6.h" |
||
51 | #include "lwip/ip6_addr.h" |
||
52 | #include "lwip/ip6_frag.h" |
||
53 | #include "lwip/icmp6.h" |
||
54 | #include "lwip/raw.h" |
||
55 | #include "lwip/udp.h" |
||
56 | #include "lwip/priv/tcp_priv.h" |
||
57 | #include "lwip/dhcp6.h" |
||
58 | #include "lwip/nd6.h" |
||
59 | #include "lwip/mld6.h" |
||
60 | #include "lwip/debug.h" |
||
61 | #include "lwip/stats.h" |
||
62 | |||
63 | #ifdef LWIP_HOOK_FILENAME |
||
64 | #include LWIP_HOOK_FILENAME |
||
65 | #endif |
||
66 | |||
67 | /** |
||
68 | * Finds the appropriate network interface for a given IPv6 address. It tries to select |
||
69 | * a netif following a sequence of heuristics: |
||
70 | * 1) if there is only 1 netif, return it |
||
71 | * 2) if the destination is a zoned address, match its zone to a netif |
||
72 | * 3) if the either the source or destination address is a scoped address, |
||
73 | * match the source address's zone (if set) or address (if not) to a netif |
||
74 | * 4) tries to match the destination subnet to a configured address |
||
75 | * 5) tries to find a router-announced route |
||
76 | * 6) tries to match the (unscoped) source address to the netif |
||
77 | * 7) returns the default netif, if configured |
||
78 | * |
||
79 | * Note that each of the two given addresses may or may not be properly zoned. |
||
80 | * |
||
81 | * @param src the source IPv6 address, if known |
||
82 | * @param dest the destination IPv6 address for which to find the route |
||
83 | * @return the netif on which to send to reach dest |
||
84 | */ |
||
85 | struct netif * |
||
86 | ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) |
||
87 | { |
||
88 | #if LWIP_SINGLE_NETIF |
||
89 | LWIP_UNUSED_ARG(src); |
||
90 | LWIP_UNUSED_ARG(dest); |
||
91 | #else /* LWIP_SINGLE_NETIF */ |
||
92 | struct netif *netif; |
||
93 | s8_t i; |
||
94 | |||
95 | /* If single netif configuration, fast return. */ |
||
96 | if ((netif_list != NULL) && (netif_list->next == NULL)) { |
||
97 | if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list) || |
||
98 | (ip6_addr_has_zone(dest) && !ip6_addr_test_zone(dest, netif_list))) { |
||
99 | return NULL; |
||
100 | } |
||
101 | return netif_list; |
||
102 | } |
||
103 | |||
104 | #if LWIP_IPV6_SCOPES |
||
105 | /* Special processing for zoned destination addresses. This includes link- |
||
106 | * local unicast addresses and interface/link-local multicast addresses. Use |
||
107 | * the zone to find a matching netif. If the address is not zoned, then there |
||
108 | * is technically no "wrong" netif to choose, and we leave routing to other |
||
109 | * rules; in most cases this should be the scoped-source rule below. */ |
||
110 | if (ip6_addr_has_zone(dest)) { |
||
111 | IP6_ADDR_ZONECHECK(dest); |
||
112 | /* Find a netif based on the zone. For custom mappings, one zone may map |
||
113 | * to multiple netifs, so find one that can actually send a packet. */ |
||
114 | for (netif = netif_list; netif != NULL; netif = netif->next) { |
||
115 | if (ip6_addr_test_zone(dest, netif) && |
||
116 | netif_is_up(netif) && netif_is_link_up(netif)) { |
||
117 | return netif; |
||
118 | } |
||
119 | } |
||
120 | /* No matching netif found. Do no try to route to a different netif, |
||
121 | * as that would be a zone violation, resulting in any packets sent to |
||
122 | * that netif being dropped on output. */ |
||
123 | return NULL; |
||
124 | } |
||
125 | #endif /* LWIP_IPV6_SCOPES */ |
||
126 | |||
127 | /* Special processing for scoped source and destination addresses. If we get |
||
128 | * here, the destination address does not have a zone, so either way we need |
||
129 | * to look at the source address, which may or may not have a zone. If it |
||
130 | * does, the zone is restrictive: there is (typically) only one matching |
||
131 | * netif for it, and we should avoid routing to any other netif as that would |
||
132 | * result in guaranteed zone violations. For scoped source addresses that do |
||
133 | * not have a zone, use (only) a netif that has that source address locally |
||
134 | * assigned. This case also applies to the loopback source address, which has |
||
135 | * an implied link-local scope. If only the destination address is scoped |
||
136 | * (but, again, not zoned), we still want to use only the source address to |
||
137 | * determine its zone because that's most likely what the user/application |
||
138 | * wants, regardless of whether the source address is scoped. Finally, some |
||
139 | * of this story also applies if scoping is disabled altogether. */ |
||
140 | #if LWIP_IPV6_SCOPES |
||
141 | if (ip6_addr_has_scope(dest, IP6_UNKNOWN) || |
||
142 | ip6_addr_has_scope(src, IP6_UNICAST) || |
||
143 | #else /* LWIP_IPV6_SCOPES */ |
||
144 | if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_iflocal(dest) || |
||
145 | ip6_addr_ismulticast_linklocal(dest) || ip6_addr_islinklocal(src) || |
||
146 | #endif /* LWIP_IPV6_SCOPES */ |
||
147 | ip6_addr_isloopback(src)) { |
||
148 | #if LWIP_IPV6_SCOPES |
||
149 | if (ip6_addr_has_zone(src)) { |
||
150 | /* Find a netif matching the source zone (relatively cheap). */ |
||
151 | for (netif = netif_list; netif != NULL; netif = netif->next) { |
||
152 | if (netif_is_up(netif) && netif_is_link_up(netif) && |
||
153 | ip6_addr_test_zone(src, netif)) { |
||
154 | return netif; |
||
155 | } |
||
156 | } |
||
157 | } else |
||
158 | #endif /* LWIP_IPV6_SCOPES */ |
||
159 | { |
||
160 | /* Find a netif matching the source address (relatively expensive). */ |
||
161 | for (netif = netif_list; netif != NULL; netif = netif->next) { |
||
162 | if (!netif_is_up(netif) || !netif_is_link_up(netif)) { |
||
163 | continue; |
||
164 | } |
||
165 | for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { |
||
166 | if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && |
||
167 | ip6_addr_cmp_zoneless(src, netif_ip6_addr(netif, i))) { |
||
168 | return netif; |
||
169 | } |
||
170 | } |
||
171 | } |
||
172 | } |
||
173 | /* Again, do not use any other netif in this case, as that could result in |
||
174 | * zone boundary violations. */ |
||
175 | return NULL; |
||
176 | } |
||
177 | |||
178 | /* We come here only if neither source nor destination is scoped. */ |
||
179 | IP6_ADDR_ZONECHECK(src); |
||
180 | |||
181 | #ifdef LWIP_HOOK_IP6_ROUTE |
||
182 | netif = LWIP_HOOK_IP6_ROUTE(src, dest); |
||
183 | if (netif != NULL) { |
||
184 | return netif; |
||
185 | } |
||
186 | #endif |
||
187 | |||
188 | /* See if the destination subnet matches a configured address. In accordance |
||
189 | * with RFC 5942, dynamically configured addresses do not have an implied |
||
190 | * local subnet, and thus should be considered /128 assignments. However, as |
||
191 | * such, the destination address may still match a local address, and so we |
||
192 | * still need to check for exact matches here. By (lwIP) policy, statically |
||
193 | * configured addresses do always have an implied local /64 subnet. */ |
||
194 | for (netif = netif_list; netif != NULL; netif = netif->next) { |
||
195 | if (!netif_is_up(netif) || !netif_is_link_up(netif)) { |
||
196 | continue; |
||
197 | } |
||
198 | for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { |
||
199 | if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && |
||
200 | ip6_addr_netcmp(dest, netif_ip6_addr(netif, i)) && |
||
201 | (netif_ip6_addr_isstatic(netif, i) || |
||
202 | ip6_addr_nethostcmp(dest, netif_ip6_addr(netif, i)))) { |
||
203 | return netif; |
||
204 | } |
||
205 | } |
||
206 | } |
||
207 | |||
208 | /* Get the netif for a suitable router-announced route. */ |
||
209 | netif = nd6_find_route(dest); |
||
210 | if (netif != NULL) { |
||
211 | return netif; |
||
212 | } |
||
213 | |||
214 | /* Try with the netif that matches the source address. Given the earlier rule |
||
215 | * for scoped source addresses, this applies to unscoped addresses only. */ |
||
216 | if (!ip6_addr_isany(src)) { |
||
217 | for (netif = netif_list; netif != NULL; netif = netif->next) { |
||
218 | if (!netif_is_up(netif) || !netif_is_link_up(netif)) { |
||
219 | continue; |
||
220 | } |
||
221 | for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { |
||
222 | if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && |
||
223 | ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { |
||
224 | return netif; |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | } |
||
229 | |||
230 | #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF |
||
231 | /* loopif is disabled, loopback traffic is passed through any netif */ |
||
232 | if (ip6_addr_isloopback(dest)) { |
||
233 | /* don't check for link on loopback traffic */ |
||
234 | if (netif_default != NULL && netif_is_up(netif_default)) { |
||
235 | return netif_default; |
||
236 | } |
||
237 | /* default netif is not up, just use any netif for loopback traffic */ |
||
238 | for (netif = netif_list; netif != NULL; netif = netif->next) { |
||
239 | if (netif_is_up(netif)) { |
||
240 | return netif; |
||
241 | } |
||
242 | } |
||
243 | return NULL; |
||
244 | } |
||
245 | #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ |
||
246 | #endif /* !LWIP_SINGLE_NETIF */ |
||
247 | |||
248 | /* no matching netif found, use default netif, if up */ |
||
249 | if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { |
||
250 | return NULL; |
||
251 | } |
||
252 | return netif_default; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * @ingroup ip6 |
||
257 | * Select the best IPv6 source address for a given destination IPv6 address. |
||
258 | * |
||
259 | * This implementation follows RFC 6724 Sec. 5 to the following extent: |
||
260 | * - Rules 1, 2, 3: fully implemented |
||
261 | * - Rules 4, 5, 5.5: not applicable |
||
262 | * - Rule 6: not implemented |
||
263 | * - Rule 7: not applicable |
||
264 | * - Rule 8: limited to "prefer /64 subnet match over non-match" |
||
265 | * |
||
266 | * For Rule 2, we deliberately deviate from RFC 6724 Sec. 3.1 by considering |
||
267 | * ULAs to be of smaller scope than global addresses, to avoid that a preferred |
||
268 | * ULA is picked over a deprecated global address when given a global address |
||
269 | * as destination, as that would likely result in broken two-way communication. |
||
270 | * |
||
271 | * As long as temporary addresses are not supported (as used in Rule 7), a |
||
272 | * proper implementation of Rule 8 would obviate the need to implement Rule 6. |
||
273 | * |
||
274 | * @param netif the netif on which to send a packet |
||
275 | * @param dest the destination we are trying to reach (possibly not properly |
||
276 | * zoned) |
||
277 | * @return the most suitable source address to use, or NULL if no suitable |
||
278 | * source address is found |
||
279 | */ |
||
280 | const ip_addr_t * |
||
281 | ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) |
||
282 | { |
||
283 | const ip_addr_t *best_addr; |
||
284 | const ip6_addr_t *cand_addr; |
||
285 | s8_t dest_scope, cand_scope; |
||
286 | s8_t best_scope = IP6_MULTICAST_SCOPE_RESERVED; |
||
287 | u8_t i, cand_pref, cand_bits; |
||
288 | u8_t best_pref = 0; |
||
289 | u8_t best_bits = 0; |
||
290 | |||
291 | /* Start by determining the scope of the given destination address. These |
||
292 | * tests are hopefully (roughly) in order of likeliness to match. */ |
||
293 | if (ip6_addr_isglobal(dest)) { |
||
294 | dest_scope = IP6_MULTICAST_SCOPE_GLOBAL; |
||
295 | } else if (ip6_addr_islinklocal(dest) || ip6_addr_isloopback(dest)) { |
||
296 | dest_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL; |
||
297 | } else if (ip6_addr_isuniquelocal(dest)) { |
||
298 | dest_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL; |
||
299 | } else if (ip6_addr_ismulticast(dest)) { |
||
300 | dest_scope = ip6_addr_multicast_scope(dest); |
||
301 | } else if (ip6_addr_issitelocal(dest)) { |
||
302 | dest_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL; |
||
303 | } else { |
||
304 | /* no match, consider scope global */ |
||
305 | dest_scope = IP6_MULTICAST_SCOPE_GLOBAL; |
||
306 | } |
||
307 | |||
308 | best_addr = NULL; |
||
309 | |||
310 | for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { |
||
311 | /* Consider only valid (= preferred and deprecated) addresses. */ |
||
312 | if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { |
||
313 | continue; |
||
314 | } |
||
315 | /* Determine the scope of this candidate address. Same ordering idea. */ |
||
316 | cand_addr = netif_ip6_addr(netif, i); |
||
317 | if (ip6_addr_isglobal(cand_addr)) { |
||
318 | cand_scope = IP6_MULTICAST_SCOPE_GLOBAL; |
||
319 | } else if (ip6_addr_islinklocal(cand_addr)) { |
||
320 | cand_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL; |
||
321 | } else if (ip6_addr_isuniquelocal(cand_addr)) { |
||
322 | cand_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL; |
||
323 | } else if (ip6_addr_issitelocal(cand_addr)) { |
||
324 | cand_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL; |
||
325 | } else { |
||
326 | /* no match, treat as low-priority global scope */ |
||
327 | cand_scope = IP6_MULTICAST_SCOPE_RESERVEDF; |
||
328 | } |
||
329 | cand_pref = ip6_addr_ispreferred(netif_ip6_addr_state(netif, i)); |
||
330 | /* @todo compute the actual common bits, for longest matching prefix. */ |
||
331 | /* We cannot count on the destination address having a proper zone |
||
332 | * assignment, so do not compare zones in this case. */ |
||
333 | cand_bits = ip6_addr_netcmp_zoneless(cand_addr, dest); /* just 1 or 0 for now */ |
||
334 | if (cand_bits && ip6_addr_nethostcmp(cand_addr, dest)) { |
||
335 | return netif_ip_addr6(netif, i); /* Rule 1 */ |
||
336 | } |
||
337 | if ((best_addr == NULL) || /* no alternative yet */ |
||
338 | ((cand_scope < best_scope) && (cand_scope >= dest_scope)) || |
||
339 | ((cand_scope > best_scope) && (best_scope < dest_scope)) || /* Rule 2 */ |
||
340 | ((cand_scope == best_scope) && ((cand_pref > best_pref) || /* Rule 3 */ |
||
341 | ((cand_pref == best_pref) && (cand_bits > best_bits))))) { /* Rule 8 */ |
||
342 | /* We found a new "winning" candidate. */ |
||
343 | best_addr = netif_ip_addr6(netif, i); |
||
344 | best_scope = cand_scope; |
||
345 | best_pref = cand_pref; |
||
346 | best_bits = cand_bits; |
||
347 | } |
||
348 | } |
||
349 | |||
350 | return best_addr; /* may be NULL */ |
||
351 | } |
||
352 | |||
353 | #if LWIP_IPV6_FORWARD |
||
354 | /** |
||
355 | * Forwards an IPv6 packet. It finds an appropriate route for the |
||
356 | * packet, decrements the HL value of the packet, and outputs |
||
357 | * the packet on the appropriate interface. |
||
358 | * |
||
359 | * @param p the packet to forward (p->payload points to IP header) |
||
360 | * @param iphdr the IPv6 header of the input packet |
||
361 | * @param inp the netif on which this packet was received |
||
362 | */ |
||
363 | static void |
||
364 | ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) |
||
365 | { |
||
366 | struct netif *netif; |
||
367 | |||
368 | /* do not forward link-local or loopback addresses */ |
||
369 | if (ip6_addr_islinklocal(ip6_current_dest_addr()) || |
||
370 | ip6_addr_isloopback(ip6_current_dest_addr())) { |
||
371 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); |
||
372 | IP6_STATS_INC(ip6.rterr); |
||
373 | IP6_STATS_INC(ip6.drop); |
||
374 | return; |
||
375 | } |
||
376 | |||
377 | /* Find network interface where to forward this IP packet to. */ |
||
378 | netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); |
||
379 | if (netif == NULL) { |
||
380 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", |
||
381 | IP6_ADDR_BLOCK1(ip6_current_dest_addr()), |
||
382 | IP6_ADDR_BLOCK2(ip6_current_dest_addr()), |
||
383 | IP6_ADDR_BLOCK3(ip6_current_dest_addr()), |
||
384 | IP6_ADDR_BLOCK4(ip6_current_dest_addr()), |
||
385 | IP6_ADDR_BLOCK5(ip6_current_dest_addr()), |
||
386 | IP6_ADDR_BLOCK6(ip6_current_dest_addr()), |
||
387 | IP6_ADDR_BLOCK7(ip6_current_dest_addr()), |
||
388 | IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); |
||
389 | #if LWIP_ICMP6 |
||
390 | /* Don't send ICMP messages in response to ICMP messages */ |
||
391 | if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { |
||
392 | icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); |
||
393 | } |
||
394 | #endif /* LWIP_ICMP6 */ |
||
395 | IP6_STATS_INC(ip6.rterr); |
||
396 | IP6_STATS_INC(ip6.drop); |
||
397 | return; |
||
398 | } |
||
399 | #if LWIP_IPV6_SCOPES |
||
400 | /* Do not forward packets with a zoned (e.g., link-local) source address |
||
401 | * outside of their zone. We determined the zone a bit earlier, so we know |
||
402 | * that the address is properly zoned here, so we can safely use has_zone. |
||
403 | * Also skip packets with a loopback source address (link-local implied). */ |
||
404 | if ((ip6_addr_has_zone(ip6_current_src_addr()) && |
||
405 | !ip6_addr_test_zone(ip6_current_src_addr(), netif)) || |
||
406 | ip6_addr_isloopback(ip6_current_src_addr())) { |
||
407 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding packet beyond its source address zone.\n")); |
||
408 | IP6_STATS_INC(ip6.rterr); |
||
409 | IP6_STATS_INC(ip6.drop); |
||
410 | return; |
||
411 | } |
||
412 | #endif /* LWIP_IPV6_SCOPES */ |
||
413 | /* Do not forward packets onto the same network interface on which |
||
414 | * they arrived. */ |
||
415 | if (netif == inp) { |
||
416 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); |
||
417 | IP6_STATS_INC(ip6.rterr); |
||
418 | IP6_STATS_INC(ip6.drop); |
||
419 | return; |
||
420 | } |
||
421 | |||
422 | /* decrement HL */ |
||
423 | IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); |
||
424 | /* send ICMP6 if HL == 0 */ |
||
425 | if (IP6H_HOPLIM(iphdr) == 0) { |
||
426 | #if LWIP_ICMP6 |
||
427 | /* Don't send ICMP messages in response to ICMP messages */ |
||
428 | if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { |
||
429 | icmp6_time_exceeded(p, ICMP6_TE_HL); |
||
430 | } |
||
431 | #endif /* LWIP_ICMP6 */ |
||
432 | IP6_STATS_INC(ip6.drop); |
||
433 | return; |
||
434 | } |
||
435 | |||
436 | if (netif->mtu && (p->tot_len > netif->mtu)) { |
||
437 | #if LWIP_ICMP6 |
||
438 | /* Don't send ICMP messages in response to ICMP messages */ |
||
439 | if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { |
||
440 | icmp6_packet_too_big(p, netif->mtu); |
||
441 | } |
||
442 | #endif /* LWIP_ICMP6 */ |
||
443 | IP6_STATS_INC(ip6.drop); |
||
444 | return; |
||
445 | } |
||
446 | |||
447 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", |
||
448 | IP6_ADDR_BLOCK1(ip6_current_dest_addr()), |
||
449 | IP6_ADDR_BLOCK2(ip6_current_dest_addr()), |
||
450 | IP6_ADDR_BLOCK3(ip6_current_dest_addr()), |
||
451 | IP6_ADDR_BLOCK4(ip6_current_dest_addr()), |
||
452 | IP6_ADDR_BLOCK5(ip6_current_dest_addr()), |
||
453 | IP6_ADDR_BLOCK6(ip6_current_dest_addr()), |
||
454 | IP6_ADDR_BLOCK7(ip6_current_dest_addr()), |
||
455 | IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); |
||
456 | |||
457 | /* transmit pbuf on chosen interface */ |
||
458 | netif->output_ip6(netif, p, ip6_current_dest_addr()); |
||
459 | IP6_STATS_INC(ip6.fw); |
||
460 | IP6_STATS_INC(ip6.xmit); |
||
461 | return; |
||
462 | } |
||
463 | #endif /* LWIP_IPV6_FORWARD */ |
||
464 | |||
465 | /** Return true if the current input packet should be accepted on this netif */ |
||
466 | static int |
||
467 | ip6_input_accept(struct netif *netif) |
||
468 | { |
||
469 | /* interface is up? */ |
||
470 | if (netif_is_up(netif)) { |
||
471 | u8_t i; |
||
472 | /* unicast to this interface address? address configured? */ |
||
473 | /* If custom scopes are used, the destination zone will be tested as |
||
474 | * part of the local-address comparison, but we need to test the source |
||
475 | * scope as well (e.g., is this interface on the same link?). */ |
||
476 | for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { |
||
477 | if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && |
||
478 | ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i)) |
||
479 | #if IPV6_CUSTOM_SCOPES |
||
480 | && (!ip6_addr_has_zone(ip6_current_src_addr()) || |
||
481 | ip6_addr_test_zone(ip6_current_src_addr(), netif)) |
||
482 | #endif /* IPV6_CUSTOM_SCOPES */ |
||
483 | ) { |
||
484 | /* accept on this netif */ |
||
485 | return 1; |
||
486 | } |
||
487 | } |
||
488 | } |
||
489 | return 0; |
||
490 | } |
||
491 | |||
492 | /** |
||
493 | * This function is called by the network interface device driver when |
||
494 | * an IPv6 packet is received. The function does the basic checks of the |
||
495 | * IP header such as packet size being at least larger than the header |
||
496 | * size etc. If the packet was not destined for us, the packet is |
||
497 | * forwarded (using ip6_forward). |
||
498 | * |
||
499 | * Finally, the packet is sent to the upper layer protocol input function. |
||
500 | * |
||
501 | * @param p the received IPv6 packet (p->payload points to IPv6 header) |
||
502 | * @param inp the netif on which this packet was received |
||
503 | * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't |
||
504 | * processed, but currently always returns ERR_OK) |
||
505 | */ |
||
506 | err_t |
||
507 | ip6_input(struct pbuf *p, struct netif *inp) |
||
508 | { |
||
509 | struct ip6_hdr *ip6hdr; |
||
510 | struct netif *netif; |
||
511 | const u8_t *nexth; |
||
512 | u16_t hlen, hlen_tot; /* the current header length */ |
||
513 | #if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ |
||
514 | @todo |
||
515 | int check_ip_src=1; |
||
516 | #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ |
||
517 | |||
518 | IP6_STATS_INC(ip6.recv); |
||
519 | |||
520 | /* identify the IP header */ |
||
521 | ip6hdr = (struct ip6_hdr *)p->payload; |
||
522 | if (IP6H_V(ip6hdr) != 6) { |
||
523 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", |
||
524 | IP6H_V(ip6hdr))); |
||
525 | pbuf_free(p); |
||
526 | IP6_STATS_INC(ip6.err); |
||
527 | IP6_STATS_INC(ip6.drop); |
||
528 | return ERR_OK; |
||
529 | } |
||
530 | |||
531 | #ifdef LWIP_HOOK_IP6_INPUT |
||
532 | if (LWIP_HOOK_IP6_INPUT(p, inp)) { |
||
533 | /* the packet has been eaten */ |
||
534 | return ERR_OK; |
||
535 | } |
||
536 | #endif |
||
537 | |||
538 | /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ |
||
539 | if ((IP6_HLEN > p->len) || (IP6H_PLEN(ip6hdr) > (p->tot_len - IP6_HLEN))) { |
||
540 | if (IP6_HLEN > p->len) { |
||
541 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, |
||
542 | ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", |
||
543 | (u16_t)IP6_HLEN, p->len)); |
||
544 | } |
||
545 | if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { |
||
546 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, |
||
547 | ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", |
||
548 | (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len)); |
||
549 | } |
||
550 | /* free (drop) packet pbufs */ |
||
551 | pbuf_free(p); |
||
552 | IP6_STATS_INC(ip6.lenerr); |
||
553 | IP6_STATS_INC(ip6.drop); |
||
554 | return ERR_OK; |
||
555 | } |
||
556 | |||
557 | /* Trim pbuf. This should have been done at the netif layer, |
||
558 | * but we'll do it anyway just to be sure that its done. */ |
||
559 | pbuf_realloc(p, (u16_t)(IP6_HLEN + IP6H_PLEN(ip6hdr))); |
||
560 | |||
561 | /* copy IP addresses to aligned ip6_addr_t */ |
||
562 | ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_dest, ip6hdr->dest); |
||
563 | ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_src, ip6hdr->src); |
||
564 | |||
565 | /* Don't accept virtual IPv4 mapped IPv6 addresses. |
||
566 | * Don't accept multicast source addresses. */ |
||
567 | if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) || |
||
568 | ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) || |
||
569 | ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) { |
||
570 | IP6_STATS_INC(ip6.err); |
||
571 | IP6_STATS_INC(ip6.drop); |
||
572 | return ERR_OK; |
||
573 | } |
||
574 | |||
575 | /* Set the appropriate zone identifier on the addresses. */ |
||
576 | ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_dest), IP6_UNKNOWN, inp); |
||
577 | ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_src), IP6_UNICAST, inp); |
||
578 | |||
579 | /* current header pointer. */ |
||
580 | ip_data.current_ip6_header = ip6hdr; |
||
581 | |||
582 | /* In netif, used in case we need to send ICMPv6 packets back. */ |
||
583 | ip_data.current_netif = inp; |
||
584 | ip_data.current_input_netif = inp; |
||
585 | |||
586 | /* match packet against an interface, i.e. is this packet for us? */ |
||
587 | if (ip6_addr_ismulticast(ip6_current_dest_addr())) { |
||
588 | /* Always joined to multicast if-local and link-local all-nodes group. */ |
||
589 | if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || |
||
590 | ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { |
||
591 | netif = inp; |
||
592 | } |
||
593 | #if LWIP_IPV6_MLD |
||
594 | else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { |
||
595 | netif = inp; |
||
596 | } |
||
597 | #else /* LWIP_IPV6_MLD */ |
||
598 | else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { |
||
599 | u8_t i; |
||
600 | /* Filter solicited node packets when MLD is not enabled |
||
601 | * (for Neighbor discovery). */ |
||
602 | netif = NULL; |
||
603 | for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { |
||
604 | if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && |
||
605 | ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { |
||
606 | netif = inp; |
||
607 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", |
||
608 | netif->name[0], netif->name[1])); |
||
609 | break; |
||
610 | } |
||
611 | } |
||
612 | } |
||
613 | #endif /* LWIP_IPV6_MLD */ |
||
614 | else { |
||
615 | netif = NULL; |
||
616 | } |
||
617 | } else { |
||
618 | /* start trying with inp. if that's not acceptable, start walking the |
||
619 | list of configured netifs. */ |
||
620 | if (ip6_input_accept(inp)) { |
||
621 | netif = inp; |
||
622 | } else { |
||
623 | netif = NULL; |
||
624 | #if !IPV6_CUSTOM_SCOPES |
||
625 | /* Shortcut: stop looking for other interfaces if either the source or |
||
626 | * the destination has a scope constrained to this interface. Custom |
||
627 | * scopes may break the 1:1 link/interface mapping, however. */ |
||
628 | if (ip6_addr_islinklocal(ip6_current_dest_addr()) || |
||
629 | ip6_addr_islinklocal(ip6_current_src_addr())) { |
||
630 | goto netif_found; |
||
631 | } |
||
632 | #endif /* !IPV6_CUSTOM_SCOPES */ |
||
633 | #if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF |
||
634 | /* The loopback address is to be considered link-local. Packets to it |
||
635 | * should be dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. |
||
636 | * Its implied scope means packets *from* the loopback address should |
||
637 | * not be accepted on other interfaces, either. These requirements |
||
638 | * cannot be implemented in the case that loopback traffic is sent |
||
639 | * across a non-loopback interface, however. */ |
||
640 | if (ip6_addr_isloopback(ip6_current_dest_addr()) || |
||
641 | ip6_addr_isloopback(ip6_current_src_addr())) { |
||
642 | goto netif_found; |
||
643 | } |
||
644 | #endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ |
||
645 | #if !LWIP_SINGLE_NETIF |
||
646 | NETIF_FOREACH(netif) { |
||
647 | if (netif == inp) { |
||
648 | /* we checked that before already */ |
||
649 | continue; |
||
650 | } |
||
651 | if (ip6_input_accept(netif)) { |
||
652 | break; |
||
653 | } |
||
654 | } |
||
655 | #endif /* !LWIP_SINGLE_NETIF */ |
||
656 | } |
||
657 | netif_found: |
||
658 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", |
||
659 | netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); |
||
660 | } |
||
661 | |||
662 | /* "::" packet source address? (used in duplicate address detection) */ |
||
663 | if (ip6_addr_isany(ip6_current_src_addr()) && |
||
664 | (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { |
||
665 | /* packet source is not valid */ |
||
666 | /* free (drop) packet pbufs */ |
||
667 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); |
||
668 | pbuf_free(p); |
||
669 | IP6_STATS_INC(ip6.drop); |
||
670 | goto ip6_input_cleanup; |
||
671 | } |
||
672 | |||
673 | /* if we're pretending we are everyone for TCP, assume the packet is for source interface if it |
||
674 | isn't for a local address */ |
||
675 | if (netif == NULL && (inp->flags & NETIF_FLAG_PRETEND_TCP) && IP6H_NEXTH(ip6hdr) == IP6_NEXTH_TCP) { |
||
676 | netif = inp; |
||
677 | } |
||
678 | |||
679 | /* packet not for us? */ |
||
680 | if (netif == NULL) { |
||
681 | /* packet not for us, route or discard */ |
||
682 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); |
||
683 | #if LWIP_IPV6_FORWARD |
||
684 | /* non-multicast packet? */ |
||
685 | if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { |
||
686 | /* try to forward IP packet on (other) interfaces */ |
||
687 | ip6_forward(p, ip6hdr, inp); |
||
688 | } |
||
689 | #endif /* LWIP_IPV6_FORWARD */ |
||
690 | pbuf_free(p); |
||
691 | goto ip6_input_cleanup; |
||
692 | } |
||
693 | |||
694 | /* current netif pointer. */ |
||
695 | ip_data.current_netif = netif; |
||
696 | |||
697 | /* Save next header type. */ |
||
698 | nexth = &IP6H_NEXTH(ip6hdr); |
||
699 | |||
700 | /* Init header length. */ |
||
701 | hlen = hlen_tot = IP6_HLEN; |
||
702 | |||
703 | /* Move to payload. */ |
||
704 | pbuf_remove_header(p, IP6_HLEN); |
||
705 | |||
706 | /* Process known option extension headers, if present. */ |
||
707 | while (*nexth != IP6_NEXTH_NONE) |
||
708 | { |
||
709 | switch (*nexth) { |
||
710 | case IP6_NEXTH_HOPBYHOP: |
||
711 | { |
||
712 | s32_t opt_offset; |
||
713 | struct ip6_hbh_hdr *hbh_hdr; |
||
714 | struct ip6_opt_hdr *opt_hdr; |
||
715 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); |
||
716 | |||
717 | /* Get and check the header length, while staying in packet bounds. */ |
||
718 | hbh_hdr = (struct ip6_hbh_hdr *)p->payload; |
||
719 | |||
720 | /* Get next header type. */ |
||
721 | nexth = &IP6_HBH_NEXTH(hbh_hdr); |
||
722 | |||
723 | /* Get the header length. */ |
||
724 | hlen = (u16_t)(8 * (1 + hbh_hdr->_hlen)); |
||
725 | |||
726 | if ((p->len < 8) || (hlen > p->len)) { |
||
727 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, |
||
728 | ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", |
||
729 | hlen, p->len)); |
||
730 | /* free (drop) packet pbufs */ |
||
731 | pbuf_free(p); |
||
732 | IP6_STATS_INC(ip6.lenerr); |
||
733 | IP6_STATS_INC(ip6.drop); |
||
734 | goto ip6_input_cleanup; |
||
735 | } |
||
736 | |||
737 | hlen_tot = (u16_t)(hlen_tot + hlen); |
||
738 | |||
739 | /* The extended option header starts right after Hop-by-Hop header. */ |
||
740 | opt_offset = IP6_HBH_HLEN; |
||
741 | while (opt_offset < hlen) |
||
742 | { |
||
743 | s32_t opt_dlen = 0; |
||
744 | |||
745 | opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + opt_offset); |
||
746 | |||
747 | switch (IP6_OPT_TYPE(opt_hdr)) { |
||
748 | /* @todo: process IPV6 Hop-by-Hop option data */ |
||
749 | case IP6_PAD1_OPTION: |
||
750 | /* PAD1 option doesn't have length and value field */ |
||
751 | opt_dlen = -1; |
||
752 | break; |
||
753 | case IP6_PADN_OPTION: |
||
754 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
755 | break; |
||
756 | case IP6_ROUTER_ALERT_OPTION: |
||
757 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
758 | break; |
||
759 | case IP6_JUMBO_OPTION: |
||
760 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
761 | break; |
||
762 | default: |
||
763 | /* Check 2 MSB of Hop-by-Hop header type. */ |
||
764 | switch (IP6_OPT_TYPE_ACTION(opt_hdr)) { |
||
765 | case 1: |
||
766 | /* Discard the packet. */ |
||
767 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n")); |
||
768 | pbuf_free(p); |
||
769 | IP6_STATS_INC(ip6.drop); |
||
770 | goto ip6_input_cleanup; |
||
771 | case 2: |
||
772 | /* Send ICMP Parameter Problem */ |
||
773 | icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); |
||
774 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n")); |
||
775 | pbuf_free(p); |
||
776 | IP6_STATS_INC(ip6.drop); |
||
777 | goto ip6_input_cleanup; |
||
778 | case 3: |
||
779 | /* Send ICMP Parameter Problem if destination address is not a multicast address */ |
||
780 | if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { |
||
781 | icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); |
||
782 | } |
||
783 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n")); |
||
784 | pbuf_free(p); |
||
785 | IP6_STATS_INC(ip6.drop); |
||
786 | goto ip6_input_cleanup; |
||
787 | default: |
||
788 | /* Skip over this option. */ |
||
789 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
790 | break; |
||
791 | } |
||
792 | break; |
||
793 | } |
||
794 | |||
795 | /* Adjust the offset to move to the next extended option header */ |
||
796 | opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen; |
||
797 | } |
||
798 | pbuf_remove_header(p, hlen); |
||
799 | break; |
||
800 | } |
||
801 | case IP6_NEXTH_DESTOPTS: |
||
802 | { |
||
803 | s32_t opt_offset; |
||
804 | struct ip6_dest_hdr *dest_hdr; |
||
805 | struct ip6_opt_hdr *opt_hdr; |
||
806 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); |
||
807 | |||
808 | dest_hdr = (struct ip6_dest_hdr *)p->payload; |
||
809 | |||
810 | /* Get next header type. */ |
||
811 | nexth = &IP6_DEST_NEXTH(dest_hdr); |
||
812 | |||
813 | /* Get the header length. */ |
||
814 | hlen = 8 * (1 + dest_hdr->_hlen); |
||
815 | if ((p->len < 8) || (hlen > p->len)) { |
||
816 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, |
||
817 | ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", |
||
818 | hlen, p->len)); |
||
819 | /* free (drop) packet pbufs */ |
||
820 | pbuf_free(p); |
||
821 | IP6_STATS_INC(ip6.lenerr); |
||
822 | IP6_STATS_INC(ip6.drop); |
||
823 | goto ip6_input_cleanup; |
||
824 | } |
||
825 | |||
826 | hlen_tot = (u16_t)(hlen_tot + hlen); |
||
827 | |||
828 | /* The extended option header starts right after Destination header. */ |
||
829 | opt_offset = IP6_DEST_HLEN; |
||
830 | while (opt_offset < hlen) |
||
831 | { |
||
832 | s32_t opt_dlen = 0; |
||
833 | |||
834 | opt_hdr = (struct ip6_opt_hdr *)((u8_t *)dest_hdr + opt_offset); |
||
835 | |||
836 | switch (IP6_OPT_TYPE(opt_hdr)) |
||
837 | { |
||
838 | /* @todo: process IPV6 Destination option data */ |
||
839 | case IP6_PAD1_OPTION: |
||
840 | /* PAD1 option deosn't have length and value field */ |
||
841 | opt_dlen = -1; |
||
842 | break; |
||
843 | case IP6_PADN_OPTION: |
||
844 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
845 | break; |
||
846 | case IP6_ROUTER_ALERT_OPTION: |
||
847 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
848 | break; |
||
849 | case IP6_JUMBO_OPTION: |
||
850 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
851 | break; |
||
852 | case IP6_HOME_ADDRESS_OPTION: |
||
853 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
854 | break; |
||
855 | default: |
||
856 | /* Check 2 MSB of Destination header type. */ |
||
857 | switch (IP6_OPT_TYPE_ACTION(opt_hdr)) |
||
858 | { |
||
859 | case 1: |
||
860 | /* Discard the packet. */ |
||
861 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n")); |
||
862 | pbuf_free(p); |
||
863 | IP6_STATS_INC(ip6.drop); |
||
864 | goto ip6_input_cleanup; |
||
865 | case 2: |
||
866 | /* Send ICMP Parameter Problem */ |
||
867 | icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); |
||
868 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n")); |
||
869 | pbuf_free(p); |
||
870 | IP6_STATS_INC(ip6.drop); |
||
871 | goto ip6_input_cleanup; |
||
872 | case 3: |
||
873 | /* Send ICMP Parameter Problem if destination address is not a multicast address */ |
||
874 | if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { |
||
875 | icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); |
||
876 | } |
||
877 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n")); |
||
878 | pbuf_free(p); |
||
879 | IP6_STATS_INC(ip6.drop); |
||
880 | goto ip6_input_cleanup; |
||
881 | default: |
||
882 | /* Skip over this option. */ |
||
883 | opt_dlen = IP6_OPT_DLEN(opt_hdr); |
||
884 | break; |
||
885 | } |
||
886 | break; |
||
887 | } |
||
888 | |||
889 | /* Adjust the offset to move to the next extended option header */ |
||
890 | opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen; |
||
891 | } |
||
892 | |||
893 | pbuf_remove_header(p, hlen); |
||
894 | break; |
||
895 | } |
||
896 | case IP6_NEXTH_ROUTING: |
||
897 | { |
||
898 | struct ip6_rout_hdr *rout_hdr; |
||
899 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); |
||
900 | |||
901 | rout_hdr = (struct ip6_rout_hdr *)p->payload; |
||
902 | |||
903 | /* Get next header type. */ |
||
904 | nexth = &IP6_ROUT_NEXTH(rout_hdr); |
||
905 | |||
906 | /* Get the header length. */ |
||
907 | hlen = 8 * (1 + rout_hdr->_hlen); |
||
908 | |||
909 | if ((p->len < 8) || (hlen > p->len)) { |
||
910 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, |
||
911 | ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", |
||
912 | hlen, p->len)); |
||
913 | /* free (drop) packet pbufs */ |
||
914 | pbuf_free(p); |
||
915 | IP6_STATS_INC(ip6.lenerr); |
||
916 | IP6_STATS_INC(ip6.drop); |
||
917 | goto ip6_input_cleanup; |
||
918 | } |
||
919 | |||
920 | /* Skip over this header. */ |
||
921 | hlen_tot = (u16_t)(hlen_tot + hlen); |
||
922 | |||
923 | /* if segment left value is 0 in routing header, ignore the option */ |
||
924 | if (IP6_ROUT_SEG_LEFT(rout_hdr)) { |
||
925 | /* The length field of routing option header must be even */ |
||
926 | if (rout_hdr->_hlen & 0x1) { |
||
927 | /* Discard and send parameter field error */ |
||
928 | icmp6_param_problem(p, ICMP6_PP_FIELD, &rout_hdr->_hlen); |
||
929 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n")); |
||
930 | pbuf_free(p); |
||
931 | IP6_STATS_INC(ip6.drop); |
||
932 | goto ip6_input_cleanup; |
||
933 | } |
||
934 | |||
935 | switch (IP6_ROUT_TYPE(rout_hdr)) |
||
936 | { |
||
937 | /* TODO: process routing by the type */ |
||
938 | case IP6_ROUT_TYPE2: |
||
939 | break; |
||
940 | case IP6_ROUT_RPL: |
||
941 | break; |
||
942 | default: |
||
943 | /* Discard unrecognized routing type and send parameter field error */ |
||
944 | icmp6_param_problem(p, ICMP6_PP_FIELD, &IP6_ROUT_TYPE(rout_hdr)); |
||
945 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n")); |
||
946 | pbuf_free(p); |
||
947 | IP6_STATS_INC(ip6.drop); |
||
948 | goto ip6_input_cleanup; |
||
949 | } |
||
950 | } |
||
951 | |||
952 | pbuf_remove_header(p, hlen); |
||
953 | break; |
||
954 | } |
||
955 | case IP6_NEXTH_FRAGMENT: |
||
956 | { |
||
957 | struct ip6_frag_hdr *frag_hdr; |
||
958 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); |
||
959 | |||
960 | frag_hdr = (struct ip6_frag_hdr *)p->payload; |
||
961 | |||
962 | /* Get next header type. */ |
||
963 | nexth = &IP6_FRAG_NEXTH(frag_hdr); |
||
964 | |||
965 | /* Fragment Header length. */ |
||
966 | hlen = 8; |
||
967 | |||
968 | /* Make sure this header fits in current pbuf. */ |
||
969 | if (hlen > p->len) { |
||
970 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, |
||
971 | ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", |
||
972 | hlen, p->len)); |
||
973 | /* free (drop) packet pbufs */ |
||
974 | pbuf_free(p); |
||
975 | IP6_FRAG_STATS_INC(ip6_frag.lenerr); |
||
976 | IP6_FRAG_STATS_INC(ip6_frag.drop); |
||
977 | goto ip6_input_cleanup; |
||
978 | } |
||
979 | |||
980 | hlen_tot = (u16_t)(hlen_tot + hlen); |
||
981 | |||
982 | /* check payload length is multiple of 8 octets when mbit is set */ |
||
983 | if (IP6_FRAG_MBIT(frag_hdr) && (IP6H_PLEN(ip6hdr) & 0x7)) { |
||
984 | /* ipv6 payload length is not multiple of 8 octets */ |
||
985 | icmp6_param_problem(p, ICMP6_PP_FIELD, &ip6hdr->_plen); |
||
986 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid payload length dropped\n")); |
||
987 | pbuf_free(p); |
||
988 | IP6_STATS_INC(ip6.drop); |
||
989 | goto ip6_input_cleanup; |
||
990 | } |
||
991 | |||
992 | /* Offset == 0 and more_fragments == 0? */ |
||
993 | if ((frag_hdr->_fragment_offset & |
||
994 | PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { |
||
995 | /* This is a 1-fragment packet. Skip this header and continue. */ |
||
996 | pbuf_remove_header(p, hlen); |
||
997 | } else { |
||
998 | #if LWIP_IPV6_REASS |
||
999 | /* reassemble the packet */ |
||
1000 | ip_data.current_ip_header_tot_len = hlen_tot; |
||
1001 | p = ip6_reass(p); |
||
1002 | /* packet not fully reassembled yet? */ |
||
1003 | if (p == NULL) { |
||
1004 | goto ip6_input_cleanup; |
||
1005 | } |
||
1006 | |||
1007 | /* Returned p point to IPv6 header. |
||
1008 | * Update all our variables and pointers and continue. */ |
||
1009 | ip6hdr = (struct ip6_hdr *)p->payload; |
||
1010 | nexth = &IP6H_NEXTH(ip6hdr); |
||
1011 | hlen = hlen_tot = IP6_HLEN; |
||
1012 | pbuf_remove_header(p, IP6_HLEN); |
||
1013 | |||
1014 | #else /* LWIP_IPV6_REASS */ |
||
1015 | /* free (drop) packet pbufs */ |
||
1016 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); |
||
1017 | pbuf_free(p); |
||
1018 | IP6_STATS_INC(ip6.opterr); |
||
1019 | IP6_STATS_INC(ip6.drop); |
||
1020 | goto ip6_input_cleanup; |
||
1021 | #endif /* LWIP_IPV6_REASS */ |
||
1022 | } |
||
1023 | break; |
||
1024 | } |
||
1025 | default: |
||
1026 | goto options_done; |
||
1027 | } |
||
1028 | |||
1029 | if (*nexth == IP6_NEXTH_HOPBYHOP) { |
||
1030 | /* Hop-by-Hop header comes only as a first option */ |
||
1031 | icmp6_param_problem(p, ICMP6_PP_HEADER, nexth); |
||
1032 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header dropped (only valid as a first option)\n")); |
||
1033 | pbuf_free(p); |
||
1034 | IP6_STATS_INC(ip6.drop); |
||
1035 | goto ip6_input_cleanup; |
||
1036 | } |
||
1037 | } |
||
1038 | |||
1039 | options_done: |
||
1040 | if (hlen_tot >= 0x8000) { |
||
1041 | /* s16_t overflow */ |
||
1042 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: header length overflow: %"U16_F"\n", hlen_tot)); |
||
1043 | pbuf_free(p); |
||
1044 | IP6_STATS_INC(ip6.proterr); |
||
1045 | IP6_STATS_INC(ip6.drop); |
||
1046 | goto options_done; |
||
1047 | } |
||
1048 | |||
1049 | /* send to upper layers */ |
||
1050 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); |
||
1051 | ip6_debug_print(p); |
||
1052 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); |
||
1053 | |||
1054 | ip_data.current_ip_header_tot_len = hlen_tot; |
||
1055 | |||
1056 | #if LWIP_RAW |
||
1057 | /* p points to IPv6 header again for raw_input. */ |
||
1058 | pbuf_header_force(p, (s16_t)hlen_tot); |
||
1059 | /* raw input did not eat the packet? */ |
||
1060 | if (raw_input(p, inp) == 0) |
||
1061 | { |
||
1062 | /* Point to payload. */ |
||
1063 | pbuf_remove_header(p, hlen_tot); |
||
1064 | #else /* LWIP_RAW */ |
||
1065 | { |
||
1066 | #endif /* LWIP_RAW */ |
||
1067 | switch (*nexth) { |
||
1068 | case IP6_NEXTH_NONE: |
||
1069 | pbuf_free(p); |
||
1070 | break; |
||
1071 | #if LWIP_UDP |
||
1072 | case IP6_NEXTH_UDP: |
||
1073 | #if LWIP_UDPLITE |
||
1074 | case IP6_NEXTH_UDPLITE: |
||
1075 | #endif /* LWIP_UDPLITE */ |
||
1076 | udp_input(p, inp); |
||
1077 | break; |
||
1078 | #endif /* LWIP_UDP */ |
||
1079 | #if LWIP_TCP |
||
1080 | case IP6_NEXTH_TCP: |
||
1081 | tcp_input(p, inp); |
||
1082 | break; |
||
1083 | #endif /* LWIP_TCP */ |
||
1084 | #if LWIP_ICMP6 |
||
1085 | case IP6_NEXTH_ICMP6: |
||
1086 | icmp6_input(p, inp); |
||
1087 | break; |
||
1088 | #endif /* LWIP_ICMP */ |
||
1089 | default: |
||
1090 | #if LWIP_ICMP6 |
||
1091 | /* p points to IPv6 header again for raw_input. */ |
||
1092 | pbuf_header_force(p, (s16_t)hlen_tot); |
||
1093 | /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ |
||
1094 | if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && |
||
1095 | (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { |
||
1096 | icmp6_param_problem(p, ICMP6_PP_HEADER, nexth); |
||
1097 | } |
||
1098 | #endif /* LWIP_ICMP */ |
||
1099 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr))); |
||
1100 | pbuf_free(p); |
||
1101 | IP6_STATS_INC(ip6.proterr); |
||
1102 | IP6_STATS_INC(ip6.drop); |
||
1103 | break; |
||
1104 | } |
||
1105 | } |
||
1106 | |||
1107 | ip6_input_cleanup: |
||
1108 | ip_data.current_netif = NULL; |
||
1109 | ip_data.current_input_netif = NULL; |
||
1110 | ip_data.current_ip6_header = NULL; |
||
1111 | ip_data.current_ip_header_tot_len = 0; |
||
1112 | ip6_addr_set_zero(ip6_current_src_addr()); |
||
1113 | ip6_addr_set_zero(ip6_current_dest_addr()); |
||
1114 | |||
1115 | return ERR_OK; |
||
1116 | } |
||
1117 | |||
1118 | |||
1119 | /** |
||
1120 | * Sends an IPv6 packet on a network interface. This function constructs |
||
1121 | * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is |
||
1122 | * used as source (usually during network startup). If the source IPv6 address it |
||
1123 | * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network |
||
1124 | * interface is filled in as source address. If the destination IPv6 address is |
||
1125 | * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and |
||
1126 | * p->payload points to it instead of the data. |
||
1127 | * |
||
1128 | * @param p the packet to send (p->payload points to the data, e.g. next |
||
1129 | protocol header; if dest == LWIP_IP_HDRINCL, p already includes an |
||
1130 | IPv6 header and p->payload points to that IPv6 header) |
||
1131 | * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an |
||
1132 | * IP address of the netif is selected and used as source address. |
||
1133 | * if src == NULL, IP6_ADDR_ANY is used as source) (src is possibly not |
||
1134 | * properly zoned) |
||
1135 | * @param dest the destination IPv6 address to send the packet to (possibly not |
||
1136 | * properly zoned) |
||
1137 | * @param hl the Hop Limit value to be set in the IPv6 header |
||
1138 | * @param tc the Traffic Class value to be set in the IPv6 header |
||
1139 | * @param nexth the Next Header to be set in the IPv6 header |
||
1140 | * @param netif the netif on which to send this packet |
||
1141 | * @return ERR_OK if the packet was sent OK |
||
1142 | * ERR_BUF if p doesn't have enough space for IPv6/LINK headers |
||
1143 | * returns errors returned by netif->output |
||
1144 | */ |
||
1145 | err_t |
||
1146 | ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, |
||
1147 | u8_t hl, u8_t tc, |
||
1148 | u8_t nexth, struct netif *netif) |
||
1149 | { |
||
1150 | const ip6_addr_t *src_used = src; |
||
1151 | if (dest != LWIP_IP_HDRINCL) { |
||
1152 | if (src != NULL && ip6_addr_isany(src)) { |
||
1153 | src_used = ip_2_ip6(ip6_select_source_address(netif, dest)); |
||
1154 | if ((src_used == NULL) || ip6_addr_isany(src_used)) { |
||
1155 | /* No appropriate source address was found for this packet. */ |
||
1156 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); |
||
1157 | IP6_STATS_INC(ip6.rterr); |
||
1158 | return ERR_RTE; |
||
1159 | } |
||
1160 | } |
||
1161 | } |
||
1162 | return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); |
||
1163 | } |
||
1164 | |||
1165 | /** |
||
1166 | * Same as ip6_output_if() but 'src' address is not replaced by netif address |
||
1167 | * when it is 'any'. |
||
1168 | */ |
||
1169 | err_t |
||
1170 | ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, |
||
1171 | u8_t hl, u8_t tc, |
||
1172 | u8_t nexth, struct netif *netif) |
||
1173 | { |
||
1174 | struct ip6_hdr *ip6hdr; |
||
1175 | ip6_addr_t dest_addr; |
||
1176 | |||
1177 | LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); |
||
1178 | |||
1179 | /* Should the IPv6 header be generated or is it already included in p? */ |
||
1180 | if (dest != LWIP_IP_HDRINCL) { |
||
1181 | #if LWIP_IPV6_SCOPES |
||
1182 | /* If the destination address is scoped but lacks a zone, add a zone now, |
||
1183 | * based on the outgoing interface. The lower layers (e.g., nd6) absolutely |
||
1184 | * require addresses to be properly zoned for correctness. In some cases, |
||
1185 | * earlier attempts will have been made to add a zone to the destination, |
||
1186 | * but this function is the only one that is called in all (other) cases, |
||
1187 | * so we must do this here. */ |
||
1188 | if (ip6_addr_lacks_zone(dest, IP6_UNKNOWN)) { |
||
1189 | ip6_addr_copy(dest_addr, *dest); |
||
1190 | ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif); |
||
1191 | dest = &dest_addr; |
||
1192 | } |
||
1193 | #endif /* LWIP_IPV6_SCOPES */ |
||
1194 | |||
1195 | /* generate IPv6 header */ |
||
1196 | if (pbuf_add_header(p, IP6_HLEN)) { |
||
1197 | LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); |
||
1198 | IP6_STATS_INC(ip6.err); |
||
1199 | return ERR_BUF; |
||
1200 | } |
||
1201 | |||
1202 | ip6hdr = (struct ip6_hdr *)p->payload; |
||
1203 | LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", |
||
1204 | (p->len >= sizeof(struct ip6_hdr))); |
||
1205 | |||
1206 | IP6H_HOPLIM_SET(ip6hdr, hl); |
||
1207 | IP6H_NEXTH_SET(ip6hdr, nexth); |
||
1208 | |||
1209 | /* dest cannot be NULL here */ |
||
1210 | ip6_addr_copy_to_packed(ip6hdr->dest, *dest); |
||
1211 | |||
1212 | IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); |
||
1213 | IP6H_PLEN_SET(ip6hdr, (u16_t)(p->tot_len - IP6_HLEN)); |
||
1214 | |||
1215 | if (src == NULL) { |
||
1216 | src = IP6_ADDR_ANY6; |
||
1217 | } |
||
1218 | /* src cannot be NULL here */ |
||
1219 | ip6_addr_copy_to_packed(ip6hdr->src, *src); |
||
1220 | |||
1221 | } else { |
||
1222 | /* IP header already included in p */ |
||
1223 | ip6hdr = (struct ip6_hdr *)p->payload; |
||
1224 | ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); |
||
1225 | ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif); |
||
1226 | dest = &dest_addr; |
||
1227 | } |
||
1228 | |||
1229 | IP6_STATS_INC(ip6.xmit); |
||
1230 | |||
1231 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); |
||
1232 | ip6_debug_print(p); |
||
1233 | |||
1234 | #if ENABLE_LOOPBACK |
||
1235 | { |
||
1236 | int i; |
||
1237 | #if !LWIP_HAVE_LOOPIF |
||
1238 | if (ip6_addr_isloopback(dest)) { |
||
1239 | return netif_loop_output(netif, p); |
||
1240 | } |
||
1241 | #endif /* !LWIP_HAVE_LOOPIF */ |
||
1242 | for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { |
||
1243 | if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && |
||
1244 | ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { |
||
1245 | /* Packet to self, enqueue it for loopback */ |
||
1246 | LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); |
||
1247 | return netif_loop_output(netif, p); |
||
1248 | } |
||
1249 | } |
||
1250 | } |
||
1251 | #if LWIP_MULTICAST_TX_OPTIONS |
||
1252 | if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { |
||
1253 | netif_loop_output(netif, p); |
||
1254 | } |
||
1255 | #endif /* LWIP_MULTICAST_TX_OPTIONS */ |
||
1256 | #endif /* ENABLE_LOOPBACK */ |
||
1257 | #if LWIP_IPV6_FRAG |
||
1258 | /* don't fragment if interface has mtu set to 0 [loopif] */ |
||
1259 | if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { |
||
1260 | return ip6_frag(p, netif, dest); |
||
1261 | } |
||
1262 | #endif /* LWIP_IPV6_FRAG */ |
||
1263 | |||
1264 | LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); |
||
1265 | return netif->output_ip6(netif, p, dest); |
||
1266 | } |
||
1267 | |||
1268 | /** |
||
1269 | * Simple interface to ip6_output_if. It finds the outgoing network |
||
1270 | * interface and calls upon ip6_output_if to do the actual work. |
||
1271 | * |
||
1272 | * @param p the packet to send (p->payload points to the data, e.g. next |
||
1273 | protocol header; if dest == LWIP_IP_HDRINCL, p already includes an |
||
1274 | IPv6 header and p->payload points to that IPv6 header) |
||
1275 | * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an |
||
1276 | * IP address of the netif is selected and used as source address. |
||
1277 | * if src == NULL, IP6_ADDR_ANY is used as source) |
||
1278 | * @param dest the destination IPv6 address to send the packet to |
||
1279 | * @param hl the Hop Limit value to be set in the IPv6 header |
||
1280 | * @param tc the Traffic Class value to be set in the IPv6 header |
||
1281 | * @param nexth the Next Header to be set in the IPv6 header |
||
1282 | * |
||
1283 | * @return ERR_RTE if no route is found |
||
1284 | * see ip_output_if() for more return values |
||
1285 | */ |
||
1286 | err_t |
||
1287 | ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, |
||
1288 | u8_t hl, u8_t tc, u8_t nexth) |
||
1289 | { |
||
1290 | struct netif *netif; |
||
1291 | struct ip6_hdr *ip6hdr; |
||
1292 | ip6_addr_t src_addr, dest_addr; |
||
1293 | |||
1294 | LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); |
||
1295 | |||
1296 | if (dest != LWIP_IP_HDRINCL) { |
||
1297 | netif = ip6_route(src, dest); |
||
1298 | } else { |
||
1299 | /* IP header included in p, read addresses. */ |
||
1300 | ip6hdr = (struct ip6_hdr *)p->payload; |
||
1301 | ip6_addr_copy_from_packed(src_addr, ip6hdr->src); |
||
1302 | ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); |
||
1303 | netif = ip6_route(&src_addr, &dest_addr); |
||
1304 | } |
||
1305 | |||
1306 | if (netif == NULL) { |
||
1307 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", |
||
1308 | IP6_ADDR_BLOCK1(dest), |
||
1309 | IP6_ADDR_BLOCK2(dest), |
||
1310 | IP6_ADDR_BLOCK3(dest), |
||
1311 | IP6_ADDR_BLOCK4(dest), |
||
1312 | IP6_ADDR_BLOCK5(dest), |
||
1313 | IP6_ADDR_BLOCK6(dest), |
||
1314 | IP6_ADDR_BLOCK7(dest), |
||
1315 | IP6_ADDR_BLOCK8(dest))); |
||
1316 | IP6_STATS_INC(ip6.rterr); |
||
1317 | return ERR_RTE; |
||
1318 | } |
||
1319 | |||
1320 | return ip6_output_if(p, src, dest, hl, tc, nexth, netif); |
||
1321 | } |
||
1322 | |||
1323 | |||
1324 | #if LWIP_NETIF_USE_HINTS |
||
1325 | /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint |
||
1326 | * before calling ip6_output_if. |
||
1327 | * |
||
1328 | * @param p the packet to send (p->payload points to the data, e.g. next |
||
1329 | protocol header; if dest == LWIP_IP_HDRINCL, p already includes an |
||
1330 | IPv6 header and p->payload points to that IPv6 header) |
||
1331 | * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an |
||
1332 | * IP address of the netif is selected and used as source address. |
||
1333 | * if src == NULL, IP6_ADDR_ANY is used as source) |
||
1334 | * @param dest the destination IPv6 address to send the packet to |
||
1335 | * @param hl the Hop Limit value to be set in the IPv6 header |
||
1336 | * @param tc the Traffic Class value to be set in the IPv6 header |
||
1337 | * @param nexth the Next Header to be set in the IPv6 header |
||
1338 | * @param netif_hint netif output hint pointer set to netif->hint before |
||
1339 | * calling ip_output_if() |
||
1340 | * |
||
1341 | * @return ERR_RTE if no route is found |
||
1342 | * see ip_output_if() for more return values |
||
1343 | */ |
||
1344 | err_t |
||
1345 | ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, |
||
1346 | u8_t hl, u8_t tc, u8_t nexth, struct netif_hint *netif_hint) |
||
1347 | { |
||
1348 | struct netif *netif; |
||
1349 | struct ip6_hdr *ip6hdr; |
||
1350 | ip6_addr_t src_addr, dest_addr; |
||
1351 | err_t err; |
||
1352 | |||
1353 | LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); |
||
1354 | |||
1355 | if (dest != LWIP_IP_HDRINCL) { |
||
1356 | netif = ip6_route(src, dest); |
||
1357 | } else { |
||
1358 | /* IP header included in p, read addresses. */ |
||
1359 | ip6hdr = (struct ip6_hdr *)p->payload; |
||
1360 | ip6_addr_copy_from_packed(src_addr, ip6hdr->src); |
||
1361 | ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); |
||
1362 | netif = ip6_route(&src_addr, &dest_addr); |
||
1363 | } |
||
1364 | |||
1365 | if (netif == NULL) { |
||
1366 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", |
||
1367 | IP6_ADDR_BLOCK1(dest), |
||
1368 | IP6_ADDR_BLOCK2(dest), |
||
1369 | IP6_ADDR_BLOCK3(dest), |
||
1370 | IP6_ADDR_BLOCK4(dest), |
||
1371 | IP6_ADDR_BLOCK5(dest), |
||
1372 | IP6_ADDR_BLOCK6(dest), |
||
1373 | IP6_ADDR_BLOCK7(dest), |
||
1374 | IP6_ADDR_BLOCK8(dest))); |
||
1375 | IP6_STATS_INC(ip6.rterr); |
||
1376 | return ERR_RTE; |
||
1377 | } |
||
1378 | |||
1379 | NETIF_SET_HINTS(netif, netif_hint); |
||
1380 | err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); |
||
1381 | NETIF_RESET_HINTS(netif); |
||
1382 | |||
1383 | return err; |
||
1384 | } |
||
1385 | #endif /* LWIP_NETIF_USE_HINTS*/ |
||
1386 | |||
1387 | #if LWIP_IPV6_MLD |
||
1388 | /** |
||
1389 | * Add a hop-by-hop options header with a router alert option and padding. |
||
1390 | * |
||
1391 | * Used by MLD when sending a Multicast listener report/done message. |
||
1392 | * |
||
1393 | * @param p the packet to which we will prepend the options header |
||
1394 | * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) |
||
1395 | * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) |
||
1396 | * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise |
||
1397 | */ |
||
1398 | err_t |
||
1399 | ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) |
||
1400 | { |
||
1401 | u8_t *opt_data; |
||
1402 | u32_t offset = 0; |
||
1403 | struct ip6_hbh_hdr *hbh_hdr; |
||
1404 | struct ip6_opt_hdr *opt_hdr; |
||
1405 | |||
1406 | /* fixed 4 bytes for router alert option and 2 bytes padding */ |
||
1407 | const u8_t hlen = (sizeof(struct ip6_opt_hdr) * 2) + IP6_ROUTER_ALERT_DLEN; |
||
1408 | /* Move pointer to make room for hop-by-hop options header. */ |
||
1409 | if (pbuf_add_header(p, sizeof(struct ip6_hbh_hdr) + hlen)) { |
||
1410 | LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); |
||
1411 | IP6_STATS_INC(ip6.err); |
||
1412 | return ERR_BUF; |
||
1413 | } |
||
1414 | |||
1415 | /* Set fields of Hop-by-Hop header */ |
||
1416 | hbh_hdr = (struct ip6_hbh_hdr *)p->payload; |
||
1417 | IP6_HBH_NEXTH(hbh_hdr) = nexth; |
||
1418 | hbh_hdr->_hlen = 0; |
||
1419 | offset = IP6_HBH_HLEN; |
||
1420 | |||
1421 | /* Set router alert options to Hop-by-Hop extended option header */ |
||
1422 | opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset); |
||
1423 | IP6_OPT_TYPE(opt_hdr) = IP6_ROUTER_ALERT_OPTION; |
||
1424 | IP6_OPT_DLEN(opt_hdr) = IP6_ROUTER_ALERT_DLEN; |
||
1425 | offset += IP6_OPT_HLEN; |
||
1426 | |||
1427 | /* Set router alert option data */ |
||
1428 | opt_data = (u8_t *)hbh_hdr + offset; |
||
1429 | opt_data[0] = value; |
||
1430 | opt_data[1] = 0; |
||
1431 | offset += IP6_OPT_DLEN(opt_hdr); |
||
1432 | |||
1433 | /* add 2 bytes padding to make 8 bytes Hop-by-Hop header length */ |
||
1434 | opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset); |
||
1435 | IP6_OPT_TYPE(opt_hdr) = IP6_PADN_OPTION; |
||
1436 | IP6_OPT_DLEN(opt_hdr) = 0; |
||
1437 | |||
1438 | return ERR_OK; |
||
1439 | } |
||
1440 | #endif /* LWIP_IPV6_MLD */ |
||
1441 | |||
1442 | #if IP6_DEBUG |
||
1443 | /* Print an IPv6 header by using LWIP_DEBUGF |
||
1444 | * @param p an IPv6 packet, p->payload pointing to the IPv6 header |
||
1445 | */ |
||
1446 | void |
||
1447 | ip6_debug_print(struct pbuf *p) |
||
1448 | { |
||
1449 | struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; |
||
1450 | |||
1451 | LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); |
||
1452 | LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); |
||
1453 | LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", |
||
1454 | IP6H_V(ip6hdr), |
||
1455 | IP6H_TC(ip6hdr), |
||
1456 | IP6H_FL(ip6hdr))); |
||
1457 | LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); |
||
1458 | LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", |
||
1459 | IP6H_PLEN(ip6hdr), |
||
1460 | IP6H_NEXTH(ip6hdr), |
||
1461 | IP6H_HOPLIM(ip6hdr))); |
||
1462 | LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); |
||
1463 | LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", |
||
1464 | IP6_ADDR_BLOCK1(&(ip6hdr->src)), |
||
1465 | IP6_ADDR_BLOCK2(&(ip6hdr->src)), |
||
1466 | IP6_ADDR_BLOCK3(&(ip6hdr->src)), |
||
1467 | IP6_ADDR_BLOCK4(&(ip6hdr->src)))); |
||
1468 | LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", |
||
1469 | IP6_ADDR_BLOCK5(&(ip6hdr->src)), |
||
1470 | IP6_ADDR_BLOCK6(&(ip6hdr->src)), |
||
1471 | IP6_ADDR_BLOCK7(&(ip6hdr->src)), |
||
1472 | IP6_ADDR_BLOCK8(&(ip6hdr->src)))); |
||
1473 | LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); |
||
1474 | LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", |
||
1475 | IP6_ADDR_BLOCK1(&(ip6hdr->dest)), |
||
1476 | IP6_ADDR_BLOCK2(&(ip6hdr->dest)), |
||
1477 | IP6_ADDR_BLOCK3(&(ip6hdr->dest)), |
||
1478 | IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); |
||
1479 | LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", |
||
1480 | IP6_ADDR_BLOCK5(&(ip6hdr->dest)), |
||
1481 | IP6_ADDR_BLOCK6(&(ip6hdr->dest)), |
||
1482 | IP6_ADDR_BLOCK7(&(ip6hdr->dest)), |
||
1483 | IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); |
||
1484 | LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); |
||
1485 | } |
||
1486 | #endif /* IP6_DEBUG */ |
||
1487 | |||
1488 | #endif /* LWIP_IPV6 */ |