ipv6_forward.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /****************************************************************************
  2. * net/ipforward/ipv6_forward.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <string.h>
  25. #include <assert.h>
  26. #include <errno.h>
  27. #include <debug.h>
  28. #include <nuttx/mm/iob.h>
  29. #include <nuttx/net/net.h>
  30. #include <nuttx/net/netdev.h>
  31. #include <nuttx/net/netstats.h>
  32. #include "netdev/netdev.h"
  33. #include "sixlowpan/sixlowpan.h"
  34. #include "devif/devif.h"
  35. #include "ipforward/ipforward.h"
  36. #if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
  37. /****************************************************************************
  38. * Pre-processor Definitions
  39. ****************************************************************************/
  40. #define PACKET_FORWARDED 0
  41. #define PACKET_NOT_FORWARDED 1
  42. /****************************************************************************
  43. * Private Functions
  44. ****************************************************************************/
  45. /****************************************************************************
  46. * Name: ipv6_hdrsize
  47. *
  48. * Description:
  49. * Return the size of the IPv6 header and the following.
  50. *
  51. * Input Parameters:
  52. * ipv6 - A pointer to the IPv6 header in within the IPv6 packet. This
  53. * is immediately followed by the L3 header which may be TCP, UDP,
  54. * or ICMPv6.
  55. *
  56. * Returned Value:
  57. * The size of the combined L2 + L3 headers is returned on success. An
  58. * error is returned only if the prototype is not supported.
  59. *
  60. ****************************************************************************/
  61. #ifdef CONFIG_DEBUG_NET_WARN
  62. static int ipv6_hdrsize(FAR struct ipv6_hdr_s *ipv6)
  63. {
  64. /* Size is determined by the following protocol header, */
  65. switch (ipv6->proto)
  66. {
  67. #ifdef CONFIG_NET_TCP
  68. case IP_PROTO_TCP:
  69. {
  70. FAR struct tcp_hdr_s *tcp =
  71. (FAR struct tcp_hdr_s *)((FAR uint8_t *)ipv6 + IPv6_HDRLEN);
  72. unsigned int tcpsize;
  73. /* The TCP header length is encoded in the top 4 bits of the
  74. * tcpoffset field (in units of 32-bit words).
  75. */
  76. tcpsize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
  77. return IPv6_HDRLEN + tcpsize;
  78. }
  79. break;
  80. #endif
  81. #ifdef CONFIG_NET_UDP
  82. case IP_PROTO_UDP:
  83. return IPv6_HDRLEN + UDP_HDRLEN;
  84. break;
  85. #endif
  86. #ifdef CONFIG_NET_ICMPv6
  87. case IP_PROTO_ICMP6:
  88. return IPv6_HDRLEN + ICMPv6_HDRLEN;
  89. break;
  90. #endif
  91. default:
  92. nwarn("WARNING: Unrecognized proto: %u\n", ipv6->proto);
  93. return -EPROTONOSUPPORT;
  94. }
  95. }
  96. #endif
  97. /****************************************************************************
  98. * Name: ipv6_decr_ttl
  99. *
  100. * Description:
  101. * Decrement the IPv6 TTL (time to live value). TTL field is set by the
  102. * sender of the packet and reduced by every router on the route to its
  103. * destination. If the TTL field reaches zero before the datagram arrives
  104. * at its destination, then the datagram is discarded and an ICMP error
  105. * packet (11 - Time Exceeded) is sent back to the sender.
  106. *
  107. * The purpose of the TTL field is to avoid a situation in which an
  108. * undeliverable datagram keeps circulating on an Internet system, and
  109. * such a system eventually becoming swamped by such "immortals".
  110. *
  111. * Input Parameters:
  112. * ipv6 - A pointer to the IPv6 header in within the IPv6 packet to be
  113. * forwarded.
  114. *
  115. * Returned Value:
  116. * The new TTL value is returned. A value <= 0 means the hop limit has
  117. * expired.
  118. *
  119. ****************************************************************************/
  120. static int ipv6_decr_ttl(FAR struct ipv6_hdr_s *ipv6)
  121. {
  122. int ttl = (int)ipv6->ttl - 1;
  123. if (ttl <= 0)
  124. {
  125. #ifdef CONFIG_NET_ICMPv6
  126. /* Return an ICMPv6 error packet back to the sender. */
  127. # warning Missing logic
  128. #endif
  129. /* Return zero which must cause the packet to be dropped */
  130. return 0;
  131. }
  132. /* Save the updated TTL value */
  133. ipv6->ttl = ttl;
  134. /* NOTE: We do not have to recalculate the IPv6 checksum because (1) the
  135. * IPv6 header does not include a checksum itself and (2) the TTL is not
  136. * included in the sum for the TCP and UDP headers.
  137. */
  138. return ttl;
  139. }
  140. /****************************************************************************
  141. * Name: ipv6_packet_conversion
  142. *
  143. * Description:
  144. * Generic output conversion hook. Only needed for IEEE802.15.4 for now
  145. * but this is a point where support for other conversions may be
  146. * provided.
  147. *
  148. * Returned Value:
  149. * PACKET_FORWARDED - Packet was forwarded
  150. * PACKET_NOT_FORWARDED - Packet was not forwarded
  151. * < 0 - And error occurred (and packet not forwarded).
  152. *
  153. ****************************************************************************/
  154. #ifdef CONFIG_NET_6LOWPAN
  155. static int ipv6_packet_conversion(FAR struct net_driver_s *dev,
  156. FAR struct net_driver_s *fwddev,
  157. FAR struct ipv6_hdr_s *ipv6)
  158. {
  159. int ret = PACKET_NOT_FORWARDED;
  160. if (dev->d_len > 0)
  161. {
  162. /* Check if this is a device served by 6LoWPAN */
  163. if (fwddev->d_lltype != NET_LL_IEEE802154 &&
  164. fwddev->d_lltype != NET_LL_PKTRADIO)
  165. {
  166. nwarn("WARNING: Unsupported link layer... Not forwarded\n");
  167. }
  168. else
  169. #ifdef CONFIG_NET_TCP
  170. if (ipv6->proto == IP_PROTO_TCP)
  171. {
  172. /* Decrement the TTL in the IPv6 header. If it decrements to
  173. * zero, then drop the packet.
  174. */
  175. ret = ipv6_decr_ttl(ipv6);
  176. if (ret < 1)
  177. {
  178. nwarn("WARNING: Hop limit exceeded... Dropping!\n");
  179. ret = -EMULTIHOP;
  180. }
  181. else
  182. {
  183. /* Let 6LoWPAN convert IPv6 TCP output into IEEE802.15.4
  184. * frames.
  185. */
  186. sixlowpan_tcp_send(dev, fwddev, ipv6);
  187. /* The packet was forwarded */
  188. dev->d_len = 0;
  189. return PACKET_FORWARDED;
  190. }
  191. }
  192. else
  193. #endif
  194. #ifdef CONFIG_NET_UDP
  195. if (ipv6->proto == IP_PROTO_UDP)
  196. {
  197. /* Decrement the TTL in the IPv6 header. If it decrements to
  198. * zero, then drop the packet.
  199. */
  200. ret = ipv6_decr_ttl(ipv6);
  201. if (ret < 1)
  202. {
  203. nwarn("WARNING: Hop limit exceeded... Dropping!\n");
  204. ret = -EMULTIHOP;
  205. }
  206. else
  207. {
  208. /* Let 6LoWPAN convert IPv6 UDP output into IEEE802.15.4
  209. * frames.
  210. */
  211. sixlowpan_udp_send(dev, fwddev, ipv6);
  212. /* The packet was forwarded */
  213. dev->d_len = 0;
  214. return PACKET_FORWARDED;
  215. }
  216. }
  217. else
  218. #endif
  219. #ifdef CONFIG_NET_ICMPv6
  220. if (ipv6->proto == IP_PROTO_ICMP6)
  221. {
  222. /* Decrement the TTL in the IPv6 header. If it decrements to
  223. * zero, then drop the packet.
  224. */
  225. ret = ipv6_decr_ttl(ipv6);
  226. if (ret < 1)
  227. {
  228. nwarn("WARNING: Hop limit exceeded... Dropping!\n");
  229. ret = -EMULTIHOP;
  230. }
  231. else
  232. {
  233. /* Let 6LoWPAN convert IPv6 ICMPv6 output into IEEE802.15.4
  234. * frames.
  235. */
  236. sixlowpan_icmpv6_send(dev, fwddev, ipv6);
  237. /* The packet was forwarded */
  238. dev->d_len = 0;
  239. return PACKET_FORWARDED;
  240. }
  241. }
  242. else
  243. #endif
  244. {
  245. /* Otherwise, we cannot forward the packet */
  246. nwarn("WARNING: Dropping. Unsupported 6LoWPAN protocol: %d\n",
  247. ipv6->proto);
  248. }
  249. }
  250. /* The packet was not forwarded (or the HOP limit was exceeded) */
  251. ipv6_dropstats(ipv6);
  252. return ret;
  253. }
  254. #else
  255. # define ipv6_packet_conversion(dev, fwddev, ipv6) (PACKET_NOT_FORWARDED)
  256. #endif /* CONFIG_NET_6LOWPAN */
  257. /****************************************************************************
  258. * Name: ipv6_dev_forward
  259. *
  260. * Description:
  261. * This function is called from ipv6_forward when it is necessary to
  262. * forward a packet from the current device to different device. In this
  263. * case, the forwarding operation must be performed asynchronously when
  264. * the TX poll is received from the forwarding device.
  265. *
  266. * Input Parameters:
  267. * dev - The device on which the packet was received and which
  268. * contains the IPv6 packet.
  269. * fwdddev - The device on which the packet must be forwarded.
  270. * ipv6 - A pointer to the IPv6 header in within the IPv6 packet
  271. *
  272. * Returned Value:
  273. * Zero is returned if the packet was successfully forwarded; A negated
  274. * errno value is returned if the packet is not forwardable. In that
  275. * latter case, the caller (ipv6_input()) should drop the packet.
  276. *
  277. ****************************************************************************/
  278. static int ipv6_dev_forward(FAR struct net_driver_s *dev,
  279. FAR struct net_driver_s *fwddev,
  280. FAR struct ipv6_hdr_s *ipv6)
  281. {
  282. FAR struct forward_s *fwd = NULL;
  283. #ifdef CONFIG_DEBUG_NET_WARN
  284. int hdrsize;
  285. #endif
  286. int ret;
  287. /* If the interface isn't "up", we can't forward. */
  288. if ((fwddev->d_flags & IFF_UP) == 0)
  289. {
  290. nwarn("WARNING: device is DOWN\n");
  291. ret = -EHOSTUNREACH;
  292. goto errout;
  293. }
  294. /* Perform any necessary packet conversions. */
  295. ret = ipv6_packet_conversion(dev, fwddev, ipv6);
  296. if (ret < 0)
  297. {
  298. nwarn("WARNING: ipv6_packet_conversion failed: %d\n", ret);
  299. goto errout;
  300. }
  301. else if (ret == PACKET_NOT_FORWARDED)
  302. {
  303. /* Verify that the full packet will fit within the forwarding devices
  304. * MTU. We provide no support for fragmenting forwarded packets.
  305. */
  306. if (NET_LL_HDRLEN(fwddev) + dev->d_len > NETDEV_PKTSIZE(fwddev))
  307. {
  308. nwarn("WARNING: Packet > MTU... Dropping\n");
  309. ret = -EFBIG;
  310. goto errout;
  311. }
  312. /* Get a pre-allocated forwarding structure, This structure will be
  313. * completely zeroed when we receive it.
  314. */
  315. fwd = ipfwd_alloc();
  316. if (fwd == NULL)
  317. {
  318. nwarn("WARNING: Failed to allocate forwarding structure\n");
  319. ret = -ENOMEM;
  320. goto errout;
  321. }
  322. /* Initialize the easy stuff in the forwarding structure */
  323. fwd->f_dev = fwddev; /* Forwarding device */
  324. #ifdef CONFIG_NET_IPv4
  325. fwd->f_domain = PF_INET6; /* IPv6 address domain */
  326. #endif
  327. #ifdef CONFIG_DEBUG_NET_WARN
  328. /* Get the size of the IPv6 + L3 header. */
  329. hdrsize = ipv6_hdrsize(ipv6);
  330. if (hdrsize < IPv6_HDRLEN)
  331. {
  332. nwarn("WARNING: Could not determine L2+L3 header size\n");
  333. ret = -EPROTONOSUPPORT;
  334. goto errout_with_fwd;
  335. }
  336. /* The L2/L3 headers must fit within one, contiguous IOB. */
  337. if (hdrsize > CONFIG_IOB_BUFSIZE)
  338. {
  339. nwarn("WARNING: Header is too big for pre-allocated structure\n");
  340. ret = -E2BIG;
  341. goto errout_with_fwd;
  342. }
  343. #endif
  344. /* Try to allocate the head of an IOB chain. If this fails, the
  345. * packet will be dropped; we are not operating in a context where
  346. * waiting for an IOB is a good idea
  347. */
  348. fwd->f_iob = iob_tryalloc(false, IOBUSER_NET_IPFORWARD);
  349. if (fwd->f_iob == NULL)
  350. {
  351. nwarn("WARNING: iob_tryalloc() failed\n");
  352. ret = -ENOMEM;
  353. goto errout_with_fwd;
  354. }
  355. /* Copy the L2/L3 headers plus any following payload into an IOB
  356. * chain. iob_trycopin() will not wait, but will fail there are no
  357. * available IOBs.
  358. *
  359. * REVISIT: Consider an alternative design that does not require data
  360. * copying. This would require a pool of d_buf's that are managed by
  361. * the network rather than the network device.
  362. */
  363. ret = iob_trycopyin(fwd->f_iob, (FAR const uint8_t *)ipv6,
  364. dev->d_len, 0, false, IOBUSER_NET_IPFORWARD);
  365. if (ret < 0)
  366. {
  367. nwarn("WARNING: iob_trycopyin() failed: %d\n", ret);
  368. goto errout_with_iobchain;
  369. }
  370. /* Decrement the TTL in the copy of the IPv6 header (retaining the
  371. * original TTL in the sourcee to handle the broadcast case). If the
  372. * TTL decrements to zero, then do not forward the packet.
  373. */
  374. ret = ipv6_decr_ttl((FAR struct ipv6_hdr_s *)fwd->f_iob->io_data);
  375. if (ret < 1)
  376. {
  377. nwarn("WARNING: Hop limit exceeded... Dropping!\n");
  378. ret = -EMULTIHOP;
  379. goto errout_with_iobchain;
  380. }
  381. /* Then set up to forward the packet according to the protocol. */
  382. ret = ipfwd_forward(fwd);
  383. if (ret >= 0)
  384. {
  385. dev->d_len = 0;
  386. return OK;
  387. }
  388. }
  389. errout_with_iobchain:
  390. if (fwd != NULL && fwd->f_iob != NULL)
  391. {
  392. iob_free_chain(fwd->f_iob, IOBUSER_NET_IPFORWARD);
  393. }
  394. errout_with_fwd:
  395. if (fwd != NULL)
  396. {
  397. ipfwd_free(fwd);
  398. }
  399. errout:
  400. return ret;
  401. }
  402. /****************************************************************************
  403. * Name: ipv6_forward_callback
  404. *
  405. * Description:
  406. * This function is a callback from netdev_foreach. It implements the
  407. * the broadcast forwarding action for each network device (other than, of
  408. * course, the device that received the packet).
  409. *
  410. * Input Parameters:
  411. * dev - The device on which the packet was received and which contains
  412. * the IPv6 packet.
  413. * ipv6 - A convenience pointer to the IPv6 header in within the IPv6
  414. * packet
  415. *
  416. * Returned Value:
  417. * Typically returns zero (meaning to continue the enumeration), but will
  418. * return a non-zero to stop the enumeration if an error occurs.
  419. *
  420. ****************************************************************************/
  421. #ifdef CONFIG_NET_IPFORWARD_BROADCAST
  422. int ipv6_forward_callback(FAR struct net_driver_s *fwddev, FAR void *arg)
  423. {
  424. FAR struct net_driver_s *dev = (FAR struct net_driver_s *)arg;
  425. FAR struct ipv6_hdr_s *ipv6;
  426. int ret;
  427. DEBUGASSERT(fwddev != NULL && dev != NULL && dev->d_buf != NULL);
  428. /* Check if we are forwarding on the same device that we received the
  429. * packet from.
  430. */
  431. if (fwddev != dev)
  432. {
  433. /* Recover the pointer to the IPv6 header in the receiving device's
  434. * d_buf.
  435. */
  436. ipv6 = (FAR struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)];
  437. /* Send the packet asynchrously on the forwarding device. */
  438. ret = ipv6_dev_forward(dev, fwddev, ipv6);
  439. if (ret < 0)
  440. {
  441. nwarn("WARNING: ipv6_dev_forward failed: %d\n", ret);
  442. return ret;
  443. }
  444. }
  445. return OK;
  446. }
  447. #endif
  448. /****************************************************************************
  449. * Public Functions
  450. ****************************************************************************/
  451. /****************************************************************************
  452. * Name: ipv6_forward
  453. *
  454. * Description:
  455. * This function is called from ipv6_input when a packet is received that
  456. * is not destined for us. In this case, the packet may need to be
  457. * forwarded to another device (or sent back out the same device)
  458. * depending configuration, routing table information, and the IPv6
  459. * networks served by various network devices.
  460. *
  461. * Input Parameters:
  462. * dev - The device on which the packet was received and which contains
  463. * the IPv6 packet.
  464. * ipv6 - A convenience pointer to the IPv6 header in within the IPv6
  465. * packet
  466. *
  467. * On input:
  468. * - dev->d_buf holds the received packet.
  469. * - dev->d_len holds the length of the received packet MINUS the
  470. * size of the L1 header. That was subtracted out by ipv6_input.
  471. * - ipv6 points to the IPv6 header with dev->d_buf.
  472. *
  473. * Returned Value:
  474. * Zero is returned if the packet was successfully forward; A negated
  475. * errno value is returned if the packet is not forwardable. In that
  476. * latter case, the caller (ipv6_input()) should drop the packet.
  477. *
  478. ****************************************************************************/
  479. int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6)
  480. {
  481. FAR struct net_driver_s *fwddev;
  482. int ret;
  483. /* Search for a device that can forward this packet. */
  484. fwddev = netdev_findby_ripv6addr(ipv6->srcipaddr, ipv6->destipaddr);
  485. if (fwddev == NULL)
  486. {
  487. nwarn("WARNING: Not routable\n");
  488. return (ssize_t)-ENETUNREACH;
  489. }
  490. /* Check if we are forwarding on the same device that we received the
  491. * packet from.
  492. */
  493. if (fwddev != dev)
  494. {
  495. /* Send the packet asynchrously on the forwarding device. */
  496. ret = ipv6_dev_forward(dev, fwddev, ipv6);
  497. if (ret < 0)
  498. {
  499. nwarn("WARNING: ipv6_dev_forward failed: %d\n", ret);
  500. goto drop;
  501. }
  502. }
  503. else
  504. #if defined(CONFIG_NET_6LOWPAN) /* REVISIT: Currently only support for 6LoWPAN */
  505. {
  506. /* Single network device. The use case here is where an endpoint acts
  507. * as a hub in a star configuration. This is typical for a wireless
  508. * star configuration where not all endpoints are accessible from all
  509. * other endpoints, but seems less useful for a wired network.
  510. */
  511. /* Perform any necessary packet conversions. If the packet was handled
  512. * via a backdoor path (or dropped), then dev->d_len will be zero. If
  513. * the packet needs to be forwarded in the normal manner then
  514. * dev->d_len will be unchanged.
  515. */
  516. ret = ipv6_packet_conversion(dev, dev, ipv6);
  517. if (ret < 0)
  518. {
  519. nwarn("WARNING: ipv6_packet_conversion failed: %d\n", ret);
  520. goto drop;
  521. }
  522. else if (ret == PACKET_NOT_FORWARDED)
  523. {
  524. #ifdef CONFIG_NET_ETHERNET
  525. /* REVISIT:
  526. * For Ethernet we may have to fix up the Ethernet header:
  527. * - source MAC, the MAC of the current device.
  528. * - dest MAC, the MAC associated with the destination IPv6
  529. * address.
  530. * This will involve ICMPv6 and Neighbor Discovery.
  531. */
  532. /* Correct dev->d_buf by adding back the L1 header length */
  533. #endif
  534. /* Nothing other 6LoWPAN forwarding is currently handled and that
  535. * case was dealt with in ipv6_packet_conversion().
  536. *
  537. * REVISIT: Is this an issue? Do other use cases make sense?
  538. */
  539. nwarn("WARNING: Packet forwarding supported only for 6LoWPAN\n");
  540. ret = -ENOSYS;
  541. goto drop;
  542. }
  543. }
  544. #else /* CONFIG_NET_6LOWPAN */
  545. {
  546. nwarn(
  547. "WARNING: Packet forwarding not supported in this configuration\n");
  548. ret = -ENOSYS;
  549. goto drop;
  550. }
  551. #endif /* CONFIG_NET_6LOWPAN */
  552. /* Return success. ipv6_input will return to the network driver with
  553. * dev->d_len set to the packet size and the network driver will perform
  554. * the transfer.
  555. */
  556. return OK;
  557. drop:
  558. ipv6_dropstats(ipv6);
  559. dev->d_len = 0;
  560. return ret;
  561. }
  562. /****************************************************************************
  563. * Name: ipv6_forward_broadcast
  564. *
  565. * Description:
  566. * This function is called from ipv6_input when a broadcast or multicast
  567. * packet is received. If CONFIG_NET_IPFORWARD_BROADCAST is enabled, this
  568. * function will forward the broadcast packet to other networks through
  569. * other network devices.
  570. *
  571. * Input Parameters:
  572. * dev - The device on which the packet was received and which contains
  573. * the IPv6 packet.
  574. * ipv6 - A convenience pointer to the IPv6 header in within the IPv6
  575. * packet
  576. *
  577. * On input:
  578. * - dev->d_buf holds the received packet.
  579. * - dev->d_len holds the length of the received packet MINUS the
  580. * size of the L1 header. That was subtracted out by ipv6_input.
  581. * - ipv6 points to the IPv6 header with dev->d_buf.
  582. *
  583. * Returned Value:
  584. * None
  585. *
  586. ****************************************************************************/
  587. #ifdef CONFIG_NET_IPFORWARD_BROADCAST
  588. void ipv6_forward_broadcast(FAR struct net_driver_s *dev,
  589. FAR struct ipv6_hdr_s *ipv6)
  590. {
  591. /* Don't bother if the TTL would expire */
  592. if (ipv6->ttl > 1)
  593. {
  594. /* Forward the the broadcast/multicast packet to all devices except,
  595. * of course, the device that received the packet.
  596. */
  597. netdev_foreach(ipv6_forward_callback, dev);
  598. }
  599. }
  600. #endif
  601. #endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_IPv6 */