PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/FNET/fnet_stack/stack/fnet_ip6.c

https://gitlab.com/fuggles/ucos
C | 2199 lines | 1353 code | 333 blank | 513 comment | 279 complexity | fd239a34b17675e53feef3aeb08b5dc7 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /**************************************************************************
  2. *
  3. * Copyright 2011-2015 by Andrey Butok. FNET Community.
  4. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
  5. *
  6. ***************************************************************************
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License Version 3
  9. * or later (the "LGPL").
  10. *
  11. * As a special exception, the copyright holders of the FNET project give you
  12. * permission to link the FNET sources with independent modules to produce an
  13. * executable, regardless of the license terms of these independent modules,
  14. * and to copy and distribute the resulting executable under terms of your
  15. * choice, provided that you also meet, for each linked independent module,
  16. * the terms and conditions of the license of that module.
  17. * An independent module is a module which is not derived from or based
  18. * on this library.
  19. * If you modify the FNET sources, you may extend this exception
  20. * to your version of the FNET sources, but you are not obligated
  21. * to do so. If you do not wish to do so, delete this
  22. * exception statement from your version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  27. *
  28. * You should have received a copy of the GNU General Public License
  29. * and the GNU Lesser General Public License along with this program.
  30. * If not, see <http://www.gnu.org/licenses/>.
  31. *
  32. **********************************************************************/ /*!
  33. *
  34. * @file fnet_ip6.c
  35. *
  36. * @author Andrey Butok
  37. *
  38. * @brief IPv6 protocol implementation.
  39. *
  40. ***************************************************************************/
  41. #include "fnet.h"
  42. #if FNET_CFG_IP6
  43. #include "fnet_ip6_prv.h"
  44. #include "fnet_ip_prv.h"
  45. #include "fnet_icmp.h"
  46. #include "fnet_checksum.h"
  47. #include "fnet_timer_prv.h"
  48. #include "fnet_socket_prv.h"
  49. #include "fnet_netif_prv.h"
  50. #include "fnet_prot.h"
  51. #include "fnet_loop.h"
  52. #include "fnet_igmp.h"
  53. #include "fnet_prot.h"
  54. #include "fnet_raw.h"
  55. #include "fnet_mld.h"
  56. /******************************************************************
  57. * Ext. header handler results.
  58. *******************************************************************/
  59. typedef enum{
  60. FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT, /* Stop processing.*/
  61. FNET_IP6_EXT_HEADER_HANDLER_RESULT_NEXT, /* Go to the next Ext. Header processing.*/
  62. FNET_IP6_EXT_HEADER_HANDLER_RESULT_TRANSPORT /* Go to Transport Layer processing.*/
  63. } fnet_ip6_ext_header_handler_result_t;
  64. /******************************************************************
  65. * Extension Header Handler structure
  66. *******************************************************************/
  67. typedef struct fnet_ip6_ext_header
  68. {
  69. unsigned long type; /* Identifies the type of header. */
  70. fnet_ip6_ext_header_handler_result_t (*handler)(fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb); /* Extension header handler.*/
  71. } fnet_ip6_ext_header_t;
  72. /******************************************************************
  73. * Function Prototypes
  74. *******************************************************************/
  75. static void fnet_ip6_netif_output(struct fnet_netif *netif, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t* nb);
  76. static int fnet_ip6_ext_header_process(fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb);
  77. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_fragment_header(fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb);
  78. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_routing_header(fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb);
  79. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_options (fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb);
  80. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_no_next_header (fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb);
  81. static void fnet_ip6_input_low( void *cookie );
  82. #if FNET_CFG_IP6_FRAGMENTATION
  83. static void fnet_ip6_frag_list_add( fnet_ip6_frag_list_t ** head, fnet_ip6_frag_list_t *fl );
  84. static void fnet_ip6_frag_list_del( fnet_ip6_frag_list_t ** head, fnet_ip6_frag_list_t *fl );
  85. static void fnet_ip6_frag_add( fnet_ip6_frag_header_t ** head, fnet_ip6_frag_header_t *frag, fnet_ip6_frag_header_t *frag_prev );
  86. static void fnet_ip6_frag_del( fnet_ip6_frag_header_t ** head, fnet_ip6_frag_header_t *frag );
  87. static void fnet_ip6_frag_list_free( fnet_ip6_frag_list_t *list );
  88. static fnet_netbuf_t *fnet_ip6_reassembly(fnet_netif_t *netif, fnet_netbuf_t ** nb_ptr, fnet_netbuf_t *ip6_nb, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip );
  89. static void fnet_ip6_timer(void *cookie);
  90. #endif
  91. /******************************************************************
  92. * Extension Header Handler List
  93. *******************************************************************/
  94. fnet_ip6_ext_header_t fnet_ip6_ext_header_list[] =
  95. {
  96. {FNET_IP6_TYPE_NO_NEXT_HEADER, fnet_ip6_ext_header_handler_no_next_header}
  97. ,{FNET_IP6_TYPE_HOP_BY_HOP_OPTIONS, fnet_ip6_ext_header_handler_options}
  98. ,{FNET_IP6_TYPE_DESTINATION_OPTIONS, fnet_ip6_ext_header_handler_options}
  99. ,{FNET_IP6_TYPE_ROUTING_HEADER, fnet_ip6_ext_header_handler_routing_header}
  100. ,{FNET_IP6_TYPE_FRAGMENT_HEADER, fnet_ip6_ext_header_handler_fragment_header}
  101. /* ADD YOUR EXTENSION HEADER HANDLERS HERE.*/
  102. };
  103. #define FNET_IP6_EXT_HEADER_LIST_SIZE (sizeof(fnet_ip6_ext_header_list)/sizeof(fnet_ip6_ext_header_t))
  104. /************************************************************************
  105. * Policy Table (RFC3484)
  106. *************************************************************************/
  107. typedef struct fnet_ip6_if_policy_entry
  108. {
  109. fnet_ip6_addr_t prefix; /* Prefix of an IP address. */
  110. unsigned long prefix_length; /* Prefix length (in bits). The number of leading bits
  111. * in the Prefix that are valid. */
  112. unsigned long precedence; /* Precedence value used for sorting destination addresses.*/
  113. unsigned long label; /* The label value Label(A) allows for policies that prefer a particular
  114. * source address prefix for use with a destination address prefix.*/
  115. } fnet_ip6_if_policy_entry_t;
  116. /* RFC3484 Default policy table:*/
  117. const fnet_ip6_if_policy_entry_t fnet_ip6_if_policy_table[] =
  118. {
  119. {FNET_IP6_ADDR_INIT(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1), 128, 50, 0},
  120. {FNET_IP6_ADDR_INIT(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), 0, 40, 1},
  121. {FNET_IP6_ADDR_INIT(0x20,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0), 16, 30, 2},
  122. {FNET_IP6_ADDR_INIT(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), 96, 20, 3},
  123. {FNET_IP6_ADDR_INIT(0,0,0,0,0,0,0,0,0,0,0xFF,0xFF,0,0,0,0), 96, 10, 4}
  124. };
  125. #define FNET_IP6_IF_POLICY_TABLE_SIZE (sizeof(fnet_ip6_if_policy_table)/sizeof(fnet_ip6_if_policy_entry_t))
  126. static fnet_ip_queue_t ip6_queue;
  127. static fnet_event_desc_t ip6_event;
  128. #if FNET_CFG_IP6_FRAGMENTATION
  129. static fnet_ip6_frag_list_t *ip6_frag_list_head;
  130. static fnet_timer_desc_t ip6_timer_ptr;
  131. #endif
  132. /******************************************************************
  133. * Definitions of some costant IP6 addresses (BSD-like).
  134. *******************************************************************/
  135. const fnet_ip6_addr_t fnet_ip6_addr_any = FNET_IP6_ADDR_ANY_INIT;
  136. const fnet_ip6_addr_t fnet_ip6_addr_loopback = FNET_IP6_ADDR_LOOPBACK_INIT;
  137. const fnet_ip6_addr_t fnet_ip6_addr_nodelocal_allnodes = FNET_IP6_ADDR_NODELOCAL_ALLNODES_INIT;
  138. const fnet_ip6_addr_t fnet_ip6_addr_linklocal_allnodes = FNET_IP6_ADDR_LINKLOCAL_ALLNODES_INIT;
  139. const fnet_ip6_addr_t fnet_ip6_addr_linklocal_allrouters = FNET_IP6_ADDR_LINKLOCAL_ALLROUTERS_INIT;
  140. const fnet_ip6_addr_t fnet_ip6_addr_linklocal_allv2routers = FNET_IP6_ADDR_LINKLOCAL_ALLV2ROUTERS_INIT;
  141. const fnet_ip6_addr_t fnet_ip6_addr_linklocal_prefix = FNET_IP6_ADDR_LINKLOCAL_PREFIX_INIT;
  142. /* IPv6 Multicast list.*/
  143. fnet_ip6_multicast_list_entry_t fnet_ip6_multicast_list[FNET_CFG_MULTICAST_MAX];
  144. /************************************************************************
  145. * NAME: fnet_ip6_init
  146. *
  147. * DESCRIPTION: This function makes initialization of the IPv6 layer.
  148. *************************************************************************/
  149. int fnet_ip6_init( void )
  150. {
  151. int result = FNET_ERR;
  152. #if FNET_CFG_IP6_FRAGMENTATION
  153. ip6_frag_list_head = 0;
  154. ip6_timer_ptr = fnet_timer_new((FNET_IP6_TIMER_PERIOD / FNET_TIMER_PERIOD_MS), fnet_ip6_timer, 0);
  155. if(ip6_timer_ptr)
  156. {
  157. #endif
  158. /* Install IPv6 event handler. */
  159. ip6_event = fnet_event_init(fnet_ip6_input_low, 0);
  160. if(ip6_event != FNET_ERR)
  161. result = FNET_OK;
  162. #if FNET_CFG_IP6_FRAGMENTATION
  163. }
  164. #endif
  165. /* Clear the multicast list.*/
  166. fnet_memset_zero( fnet_ip6_multicast_list, sizeof(fnet_ip6_multicast_list));
  167. return result;
  168. }
  169. /************************************************************************
  170. * NAME: fnet_ip6_release
  171. *
  172. * DESCRIPTION: This function makes release of the all resources
  173. * allocated for IPv6 layer module.
  174. *************************************************************************/
  175. void fnet_ip6_release( void )
  176. {
  177. fnet_ip6_drain();
  178. #if FNET_CFG_IP6_FRAGMENTATION
  179. fnet_timer_free(ip6_timer_ptr);
  180. ip6_timer_ptr = 0;
  181. #endif
  182. }
  183. /************************************************************************
  184. * NAME: fnet_ip6_ext_header_process
  185. *
  186. * DESCRIPTION: Process IPv6 Extension Headers.
  187. *
  188. * RETURNS: FNET_OK - continue processing by transport layer.
  189. * FNET_ERR - stop processing.
  190. *************************************************************************/
  191. static int fnet_ip6_ext_header_process(fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb)
  192. {
  193. int try_upper_layer = FNET_FALSE;
  194. unsigned char next_header;
  195. int ext_header_counter = 0;
  196. fnet_ip6_ext_header_t *ext_header;
  197. /* RFC 2460 4:
  198. * Therefore, extension headers must
  199. * be processed strictly in the order they appear in the packet; a
  200. * receiver must not, for example, scan through a packet looking for a
  201. * particular kind of extension header and process that header prior to
  202. * processing all preceding ones.
  203. */
  204. /* Process headers.*/
  205. do
  206. {
  207. int j;
  208. next_header = **next_header_p;
  209. ext_header = FNET_NULL;
  210. /* IPv6 nodes must accept and attempt to process extension headers in
  211. * any order and occurring any number of times in the same packet,
  212. * except for the Hop-by-Hop Options header which is restricted to
  213. * appear immediately after an IPv6 header only.*/
  214. /*TBD try to put it to main handler */
  215. if( (next_header == FNET_IP6_TYPE_HOP_BY_HOP_OPTIONS) && ext_header_counter)
  216. {
  217. fnet_netbuf_free_chain(*nb_p);
  218. fnet_icmp6_error( netif, FNET_ICMP6_TYPE_PARAM_PROB, FNET_ICMP6_CODE_PP_NEXT_HEADER,
  219. (unsigned long)(*next_header_p) - (unsigned long)(ip6_nb->data_ptr), ip6_nb );
  220. return FNET_ERR;
  221. }
  222. for(j = 0; j < FNET_IP6_EXT_HEADER_LIST_SIZE; j++)
  223. {
  224. if(next_header == fnet_ip6_ext_header_list[j].type)
  225. {
  226. ext_header = &fnet_ip6_ext_header_list[j];
  227. break;
  228. }
  229. }
  230. if(ext_header)
  231. {
  232. fnet_ip6_ext_header_handler_result_t handler_result = ext_header->handler(netif, next_header_p, src_ip, dest_ip, nb_p, ip6_nb);
  233. switch(handler_result)
  234. {
  235. case FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT:
  236. return FNET_ERR;
  237. case FNET_IP6_EXT_HEADER_HANDLER_RESULT_NEXT:
  238. break;
  239. case FNET_IP6_EXT_HEADER_HANDLER_RESULT_TRANSPORT:
  240. try_upper_layer = FNET_TRUE;
  241. break;
  242. };
  243. }
  244. else
  245. {
  246. try_upper_layer = FNET_TRUE;
  247. }
  248. ext_header_counter++;
  249. }
  250. while((try_upper_layer == FNET_FALSE) || (ext_header != FNET_NULL));
  251. return FNET_OK;
  252. }
  253. /************************************************************************
  254. * NAME: fnet_ip6_ext_header_handler_no_next_header
  255. *
  256. * DESCRIPTION: Process No Next Header
  257. *************************************************************************/
  258. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_no_next_header (fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb)
  259. {
  260. FNET_COMP_UNUSED_ARG(netif);
  261. FNET_COMP_UNUSED_ARG(src_ip);
  262. FNET_COMP_UNUSED_ARG(dest_ip);
  263. FNET_COMP_UNUSED_ARG(next_header_p);
  264. /* RFC 2460: The value 59 in the Next Header field of an IPv6 header or any
  265. * extension header indicates that there is nothing following that
  266. * header. If the Payload Length field of the IPv6 header indicates the
  267. * presence of octets past the end of a header whose Next Header field
  268. * contains 59, those octets must be ignored.*/
  269. fnet_netbuf_free_chain(ip6_nb);
  270. fnet_netbuf_free_chain(*nb_p);
  271. return FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT;
  272. }
  273. /************************************************************************
  274. * NAME: fnet_ip6_ext_header_handler_options
  275. *
  276. * DESCRIPTION: Process Hop by Hop Options and Destimation Options
  277. *************************************************************************/
  278. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_options (fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb)
  279. {
  280. fnet_netbuf_t *nb = *nb_p;
  281. fnet_ip6_options_header_t *options_h = nb->data_ptr;
  282. fnet_ip6_option_header_t *option;
  283. unsigned long offset;
  284. unsigned long length = (unsigned long)((options_h->hdr_ext_length<<3) + (8-2));
  285. FNET_COMP_UNUSED_ARG(src_ip);
  286. for(offset = 0; offset < length; )
  287. {
  288. option = (fnet_ip6_option_header_t *)&options_h->options[offset];
  289. /* The RFC2460 supports only PAD0 and PADN options.*/
  290. switch(option->type)
  291. {
  292. /* Pad1 option */
  293. case FNET_IP6_OPTION_TYPE_PAD1:
  294. offset++;
  295. break;
  296. /* Pad1 option */
  297. case FNET_IP6_OPTION_TYPE_PADN:
  298. offset += sizeof(fnet_ip6_option_header_t) + option->data_length;
  299. break;
  300. /* Unrecognized Options.*/
  301. default:
  302. /* The Option Type identifiers are internally encoded such that their
  303. * highest-order two bits specify the action that must be taken if the
  304. * processing IPv6 node does not recognize the Option Type.*/
  305. switch(option->type & FNET_IP6_OPTION_TYPE_UNRECOGNIZED_MASK)
  306. {
  307. /* 00 - skip over this option and continue processing the header.*/
  308. case FNET_IP6_OPTION_TYPE_UNRECOGNIZED_SKIP:
  309. break;
  310. /* 01 - discard the packet. */
  311. case FNET_IP6_OPTION_TYPE_UNRECOGNIZED_DISCARD:
  312. fnet_netbuf_free_chain(nb);
  313. fnet_netbuf_free_chain(ip6_nb);
  314. return FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT;
  315. /* 10 - discard the packet and, regardless of whether or not the
  316. * packet’s Destination Address was a multicast address, send an
  317. * ICMP Parameter Problem, Code 2, message to the packet’s
  318. * Source Address, pointing to the unrecognized Option Type.*/
  319. case FNET_IP6_OPTION_TYPE_UNRECOGNIZED_DISCARD_ICMP:
  320. fnet_netbuf_free_chain(nb);
  321. fnet_icmp6_error( netif, FNET_ICMP6_TYPE_PARAM_PROB, FNET_ICMP6_CODE_PP_OPTION,
  322. (unsigned long)(&option->type) - (unsigned long)(ip6_nb->data_ptr), ip6_nb ); /* TBD not tested.*/
  323. return FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT;
  324. /* 11 - discard the packet and, only if the packet’s Destination
  325. * Address was not a multicast address, send an ICMP Parameter
  326. * Problem, Code 2, message to the packet’s Source Address,
  327. * pointing to the unrecognized Option Type.*/
  328. case FNET_IP6_OPTION_TYPE_UNRECOGNIZED_DISCARD_UICMP:
  329. fnet_netbuf_free_chain(nb);
  330. if(!FNET_IP6_ADDR_IS_MULTICAST(dest_ip))
  331. fnet_icmp6_error( netif, FNET_ICMP6_TYPE_PARAM_PROB, FNET_ICMP6_CODE_PP_OPTION,
  332. (unsigned long)(&option->type) - (unsigned long)(ip6_nb->data_ptr), ip6_nb ); /* TBD not tested.*/
  333. else
  334. fnet_netbuf_free_chain(ip6_nb);
  335. return FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT;
  336. }
  337. offset += sizeof(fnet_ip6_option_header_t) + option->data_length;
  338. break;
  339. }
  340. }
  341. *next_header_p = &options_h->next_header;
  342. fnet_netbuf_trim(nb_p, (int)(length+2));
  343. return FNET_IP6_EXT_HEADER_HANDLER_RESULT_NEXT;
  344. }
  345. /************************************************************************
  346. * NAME: fnet_ip6_ext_header_handler_routing_header
  347. *
  348. * DESCRIPTION: Process Routing header.
  349. *************************************************************************/
  350. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_routing_header(fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb)
  351. {
  352. fnet_ip6_ext_header_handler_result_t result;
  353. fnet_netbuf_t *nb = *nb_p;
  354. fnet_ip6_routing_header_t *routing_h;
  355. FNET_COMP_UNUSED_ARG(src_ip);
  356. FNET_COMP_UNUSED_ARG(dest_ip);
  357. routing_h = nb->data_ptr;
  358. /* RFC 2460 4.4: If, while processing a received packet, a node encounters a Routing
  359. * header with an unrecognized Routing Type value, the required behavior
  360. * of the node depends on the value of the Segments Left field, as
  361. * follows:
  362. * -If Segments Left is non-zero, the node must discard the packet and
  363. * send an ICMP Parameter Problem, Code 0, message to the packet’s
  364. * Source Address, pointing to the unrecognized Routing Type.
  365. */
  366. if( routing_h->segments_left > 0)
  367. {
  368. fnet_netbuf_free_chain(nb);
  369. fnet_icmp6_error( netif, FNET_ICMP6_TYPE_PARAM_PROB, FNET_ICMP6_CODE_PP_HEADER,
  370. (unsigned long)(&routing_h->routing_type) - (unsigned long)(ip6_nb->data_ptr), ip6_nb ); /* TBD not tested.*/
  371. result = FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT;
  372. }
  373. else
  374. {
  375. /* -If Segments Left is zero, the node must ignore the Routing header
  376. * and proceed to process the next header in the packet, whose type
  377. * is identified by the Next Header field in the Routing header.*/
  378. *next_header_p = &routing_h->next_header;
  379. fnet_netbuf_trim(nb_p, (routing_h->hdr_ext_length<<3)+(8));
  380. result = FNET_IP6_EXT_HEADER_HANDLER_RESULT_NEXT;
  381. }
  382. return result;
  383. }
  384. /************************************************************************
  385. * NAME: fnet_ip6_ext_header_handler_fragment_header
  386. *
  387. * DESCRIPTION: Process IPv6 Fragment header.
  388. *************************************************************************/
  389. #if FNET_CFG_IP6_FRAGMENTATION
  390. static fnet_ip6_ext_header_handler_result_t fnet_ip6_ext_header_handler_fragment_header(fnet_netif_t *netif, unsigned char **next_header_p, fnet_ip6_addr_t *src_ip, fnet_ip6_addr_t *dest_ip, fnet_netbuf_t **nb_p, fnet_netbuf_t *ip6_nb)
  391. {
  392. fnet_ip6_ext_header_handler_result_t result;
  393. if( (*nb_p = fnet_ip6_reassembly(netif, nb_p, ip6_nb, src_ip, dest_ip )) != FNET_NULL)
  394. {
  395. fnet_ip6_header_t *ip6_header = ip6_nb->data_ptr;
  396. *next_header_p = &ip6_header->next_header;
  397. result = FNET_IP6_EXT_HEADER_HANDLER_RESULT_TRANSPORT;
  398. }
  399. else
  400. {
  401. result = FNET_IP6_EXT_HEADER_HANDLER_RESULT_EXIT;
  402. }
  403. return result;
  404. }
  405. #endif
  406. /************************************************************************
  407. * NAME: fnet_ip6_set_socket_addr
  408. *
  409. * DESCRIPTION: Prepare sockets addreses for upper protocol.
  410. *************************************************************************/
  411. void fnet_ip6_set_socket_addr(fnet_netif_t *netif, fnet_ip6_header_t *ip_hdr, struct sockaddr *src_addr, struct sockaddr *dest_addr )
  412. {
  413. fnet_memset_zero(src_addr, sizeof(struct sockaddr));
  414. src_addr->sa_family = AF_INET6;
  415. FNET_IP6_ADDR_COPY(&ip_hdr->source_addr, &((struct sockaddr_in6 *)(src_addr))->sin6_addr.s6_addr);
  416. ((struct sockaddr_in6 *)(src_addr))->sin6_scope_id = netif->scope_id;
  417. fnet_memset_zero(dest_addr, sizeof(struct sockaddr));
  418. dest_addr->sa_family = AF_INET6;
  419. FNET_IP6_ADDR_COPY(&ip_hdr->destination_addr, &((struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr);
  420. ((struct sockaddr_in6 *)(dest_addr))->sin6_scope_id = netif->scope_id;
  421. }
  422. /************************************************************************
  423. * NAME: fnet_ip6_input
  424. *
  425. * DESCRIPTION: IPv6 input function.
  426. *************************************************************************/
  427. void fnet_ip6_input( fnet_netif_t *netif, fnet_netbuf_t *nb )
  428. {
  429. if(netif && nb)
  430. {
  431. if(fnet_ip_queue_append(&ip6_queue, netif, nb) != FNET_OK)
  432. {
  433. fnet_netbuf_free_chain(nb);
  434. return;
  435. }
  436. /* Raise IPv6 event.*/
  437. fnet_event_raise(ip6_event);
  438. }
  439. }
  440. /************************************************************************
  441. * NAME: fnet_ip6_input_low
  442. *
  443. * DESCRIPTION: This function performs handling of incoming IPv6 datagrams.
  444. *************************************************************************/
  445. static void fnet_ip6_input_low( void *cookie )
  446. {
  447. fnet_ip6_header_t *hdr;
  448. fnet_netif_t *netif;
  449. fnet_netbuf_t *nb;
  450. fnet_netbuf_t *tmp_nb;
  451. fnet_prot_if_t *protocol;
  452. fnet_ip6_addr_t *source_addr;
  453. fnet_ip6_addr_t *destination_addr;
  454. unsigned short payload_length;
  455. struct sockaddr src_addr;
  456. struct sockaddr dest_addr;
  457. FNET_COMP_UNUSED_ARG(cookie);
  458. fnet_isr_lock();
  459. while((nb = fnet_ip_queue_read(&ip6_queue, &netif)) != 0)
  460. {
  461. nb->next_chain = 0;
  462. /* RFC 4862: By disabling IP operation,
  463. * silently drop any IP packets received on the interface.*/
  464. if(netif->nd6_if_ptr && netif->nd6_if_ptr->ip6_disabled)
  465. {
  466. goto DROP;
  467. }
  468. /* The header must reside in contiguous area of memory. */
  469. if((tmp_nb = fnet_netbuf_pullup(nb, sizeof(fnet_ip6_header_t))) == 0)
  470. {
  471. goto DROP;
  472. }
  473. nb = tmp_nb;
  474. hdr = nb->data_ptr;
  475. source_addr = &hdr->source_addr; /* TBD Save copy or do ICMP copy*/
  476. destination_addr = &hdr->destination_addr;
  477. payload_length = fnet_ntohs(hdr->length);
  478. if(nb->total_length > (sizeof(fnet_ip6_header_t)+ payload_length))
  479. {
  480. /* Logical size and the physical size of the packet should be the same.*/
  481. fnet_netbuf_trim(&nb, (int)sizeof(fnet_ip6_header_t) + (int)payload_length - (int)nb->total_length );
  482. }
  483. /*******************************************************************
  484. * Start IPv6 header processing.
  485. *******************************************************************/
  486. if( (nb->total_length >= sizeof(fnet_ip6_header_t)) /* Check Size of the packet. */
  487. && (nb->total_length >= (sizeof(fnet_ip6_header_t) + payload_length))
  488. && (FNET_IP6_HEADER_GET_VERSION(hdr) == 6) /* Check the IP Version. */
  489. && (!FNET_IP6_ADDR_IS_MULTICAST(&hdr->source_addr)) /* Validate source address. */
  490. && (fnet_netif_is_my_ip6_addr(netif, &hdr->destination_addr) /* Validate destination address. */
  491. || FNET_IP6_ADDR_IS_MULTICAST(&hdr->destination_addr)) /* Pass multicast destination address.*/
  492. )
  493. {
  494. unsigned char *next_header = &hdr->next_header;
  495. fnet_netbuf_t *ip6_nb;
  496. ip6_nb = fnet_netbuf_copy(nb, 0, ((nb->total_length > FNET_IP6_DEFAULT_MTU) ? FNET_IP6_DEFAULT_MTU : FNET_NETBUF_COPYALL),
  497. 0); /* Used mainly for ICMP errors .*/
  498. if(ip6_nb == FNET_NULL)
  499. goto DROP;
  500. #if FNET_CFG_CPU_ETH_HW_RX_PROTOCOL_CHECKSUM
  501. if((netif->features | FNET_NETIF_FEATURE_HW_RX_PROTOCOL_CHECKSUM) &&
  502. ((hdr->next_header == FNET_IP_PROTOCOL_ICMP) ||
  503. (hdr->next_header == FNET_IP_PROTOCOL_UDP) ||
  504. (hdr->next_header == FNET_IP_PROTOCOL_TCP)) )
  505. {
  506. nb->flags |= FNET_NETBUF_FLAG_HW_PROTOCOL_CHECKSUM;
  507. }
  508. #endif
  509. fnet_netbuf_trim(&nb, (int)sizeof(fnet_ip6_header_t));
  510. /********************************************
  511. * Extension headers processing.
  512. *********************************************/
  513. if(fnet_ip6_ext_header_process(netif, &next_header, source_addr, destination_addr, &nb, ip6_nb) == FNET_ERR)
  514. continue;
  515. /* Prepare addreses for upper protocol.*/
  516. fnet_ip6_set_socket_addr(netif, hdr, &src_addr, &dest_addr );
  517. #if FNET_CFG_RAW
  518. /* RAW Sockets input.*/
  519. fnet_raw_input(netif, &src_addr, &dest_addr, nb, ip6_nb);
  520. #endif
  521. /* Note: (http://www.cisco.com/web/about/ac123/ac147/archived_issues/ipj_9-3/ipv6_internals.html)
  522. * Note that there is no standard extension header format, meaning that when a host
  523. * encounters a header that it does not recognize in the protocol chain, the only thing
  524. * it can do is discard the packet. Worse, firewalls and routers configured to filter IPv6
  525. * have the same problem: as soon as they encounter an unknown extension header,
  526. * they must decide to allow or disallow the packet, even though another header deeper
  527. * inside the packet would possibly trigger the opposite behavior. In other words, an IPv6
  528. * packet with a TCP payload that would normally be allowed through could be blocked if
  529. * there is an unknown extension header between the IPv6 and TCP headers.
  530. */
  531. /********************************************
  532. * Transport layer processing (ICMP/TCP/UDP).
  533. *********************************************/
  534. /* Find transport protocol.*/
  535. if((protocol = fnet_prot_find(AF_INET6, SOCK_UNSPEC, *next_header)) != FNET_NULL)
  536. {
  537. protocol->prot_input(netif, &src_addr, &dest_addr, nb, ip6_nb);
  538. /* After that nb may point to wrong place. Do not use it.*/
  539. }
  540. else
  541. /* No protocol found.*/
  542. {
  543. fnet_netbuf_free_chain(nb);
  544. /* RFC 2460 4:If, as a result of processing a header, a node is required to proceed
  545. * to the next header but the Next Header value in the current header is
  546. * unrecognized by the node, it should discard the packet and send an
  547. * ICMP Parameter Problem message to the source of the packet, with an
  548. * ICMP Code value of 1 ("unrecognized Next Header type encountered")
  549. * and the ICMP Pointer field containing the offset of the unrecognized
  550. * value within the original packet. The same action should be taken if
  551. * a node encounters a Next Header value of zero in any header other
  552. * than an IPv6 header.*/
  553. fnet_icmp6_error( netif, FNET_ICMP6_TYPE_PARAM_PROB, FNET_ICMP6_CODE_PP_NEXT_HEADER,
  554. (unsigned long)(next_header) - (unsigned long)(ip6_nb->data_ptr), ip6_nb ); /* TBD not tested.*/
  555. }
  556. }
  557. else
  558. {
  559. DROP:
  560. fnet_netbuf_free_chain(nb);
  561. }
  562. } /* while end */
  563. fnet_isr_unlock();
  564. }
  565. /************************************************************************
  566. * NAME: fnet_ip6_addr_scope
  567. *
  568. * DESCRIPTION: Returns scope of the IPv6 address (Node-local,
  569. * link-local, site-local or global.).
  570. *************************************************************************/
  571. int fnet_ip6_addr_scope(fnet_ip6_addr_t *ip_addr)
  572. {
  573. int result = FNET_IP6_ADDR_SCOPE_GLOBAL;
  574. /* Local Host. */
  575. if(FNET_IP6_ADDR_IS_LINKLOCAL(ip_addr))
  576. {
  577. result = FNET_IP6_ADDR_SCOPE_LINKLOCAL;
  578. }
  579. else if(FNET_IP6_ADDR_IS_SITELOCAL(ip_addr))
  580. {
  581. result = FNET_IP6_ADDR_SCOPE_SITELOCAL;
  582. }
  583. else if(FNET_IP6_ADDR_IS_MULTICAST(ip_addr))/* Multicast. */
  584. {
  585. int scope = FNET_IP6_ADDR_MULTICAST_SCOPE(ip_addr);
  586. switch(scope)
  587. {
  588. case FNET_IP6_ADDR_SCOPE_INTERFACELOCAL:
  589. result = FNET_IP6_ADDR_SCOPE_INTERFACELOCAL;
  590. break;
  591. case FNET_IP6_ADDR_SCOPE_LINKLOCAL:
  592. result = FNET_IP6_ADDR_SCOPE_LINKLOCAL;
  593. break;
  594. case FNET_IP6_ADDR_SCOPE_SITELOCAL:
  595. result = FNET_IP6_ADDR_SCOPE_SITELOCAL;
  596. break;
  597. }
  598. }
  599. else if(FNET_IP6_ADDR_EQUAL(ip_addr, &fnet_ip6_addr_loopback)) /* Loopback interface - special case.*/
  600. {
  601. result = FNET_IP6_ADDR_SCOPE_INTERFACELOCAL;
  602. }
  603. return result;
  604. }
  605. /************************************************************************
  606. * NAME: fnet_ip6_common_prefix_length
  607. *
  608. * DESCRIPTION: RFC3484 2.2. Common Prefix Length
  609. * We define the common prefix length CommonPrefixLen(A, B) of two
  610. * addresses A and B as the length of the longest prefix (looking at the
  611. * most significant, or leftmost, bits) that the two addresses have in
  612. * common. It ranges from 0 to 128.
  613. *************************************************************************/
  614. int fnet_ip6_common_prefix_length(fnet_ip6_addr_t *ip_addr_1, fnet_ip6_addr_t *ip_addr_2)
  615. {
  616. int length = 0;
  617. int i;
  618. int bit_i;
  619. unsigned char byte_xor;
  620. for(i=0; i < sizeof(fnet_ip6_addr_t); i++)
  621. {
  622. /* XOR */
  623. byte_xor = (unsigned char)(ip_addr_1->addr[i] ^ ip_addr_2->addr[i]);
  624. for(bit_i = 0; bit_i<8; bit_i++)
  625. {
  626. if((byte_xor & 0x80) == 0x00)
  627. {
  628. length++;
  629. byte_xor<<=1; /* Shift to the next bit*/
  630. }
  631. else
  632. {
  633. break;
  634. }
  635. }
  636. }
  637. return length;
  638. }
  639. /************************************************************************
  640. * NAME: fnet_ip6_policy_label
  641. *
  642. * DESCRIPTION: Returns label value from policy table.
  643. *************************************************************************/
  644. unsigned long fnet_ip6_policy_label( fnet_ip6_addr_t *addr )
  645. {
  646. int i;
  647. unsigned long label = 0;
  648. int biggest_prefix_length = -1;
  649. /* Find the entry in the list. */
  650. for(i=0; i < FNET_IP6_IF_POLICY_TABLE_SIZE; i++)
  651. {
  652. int prefix_length = (int)(fnet_ip6_if_policy_table[i].prefix_length);
  653. if(fnet_ip6_addr_pefix_cmp((fnet_ip6_addr_t*)&fnet_ip6_if_policy_table[i].prefix, addr, (unsigned long)prefix_length) == FNET_TRUE)
  654. {
  655. if(prefix_length > biggest_prefix_length)
  656. {
  657. biggest_prefix_length = prefix_length;
  658. label = fnet_ip6_if_policy_table[i].label;
  659. }
  660. }
  661. }
  662. return label;
  663. }
  664. /************************************************************************
  665. * NAME: fnet_ip6_addr_pefix_cmp
  666. *
  667. * DESCRIPTION: Compares first "prefix_length" bits of the addresses.
  668. *************************************************************************/
  669. int fnet_ip6_addr_pefix_cmp(fnet_ip6_addr_t *addr_1, fnet_ip6_addr_t *addr_2, unsigned long prefix_length)
  670. {
  671. int result;
  672. unsigned long prefix_length_bytes = prefix_length>>3;
  673. unsigned long prefix_length_bits_mask = ((1<<(prefix_length%8))-1) << (8-(prefix_length%8));
  674. if((prefix_length <= 128)
  675. && (fnet_memcmp(addr_1, addr_2, (int)prefix_length_bytes) == 0)
  676. && ((addr_1->addr[prefix_length_bytes] & prefix_length_bits_mask) == (addr_2->addr[prefix_length_bytes] & prefix_length_bits_mask)) )
  677. {
  678. result = FNET_TRUE;
  679. }
  680. else
  681. {
  682. result = FNET_FALSE;
  683. }
  684. return result;
  685. }
  686. /************************************************************************
  687. * NAME: fnet_ip6_select_src_addr
  688. *
  689. * DESCRIPTION: Selects the best source address to use with a
  690. * destination address, Based on RFC3484.
  691. *************************************************************************/
  692. const fnet_ip6_addr_t *fnet_ip6_select_src_addr(fnet_netif_t *netif /* Optional.*/, fnet_ip6_addr_t *dest_addr)
  693. {
  694. int i;
  695. fnet_ip6_addr_t *best_addr = FNET_NULL;
  696. int best_scope;
  697. int dest_scope;
  698. int new_scope;
  699. int best_prefix_length;
  700. int new_prefix_length;
  701. unsigned long dest_label;
  702. unsigned long best_label;
  703. unsigned long new_label;
  704. fnet_netif_t *if_dest_cur;
  705. fnet_netif_t *if_dest_best = FNET_NULL;
  706. /* Just take the first/last interface.*/
  707. if(dest_addr)
  708. {
  709. for(if_dest_cur = fnet_netif_list; if_dest_cur != FNET_NULL ; if_dest_cur = if_dest_cur->next)
  710. {
  711. dest_scope = fnet_ip6_addr_scope(dest_addr);
  712. dest_label = fnet_ip6_policy_label(dest_addr);
  713. /* Just continue the first loop.*/
  714. for(i=0; i<FNET_NETIF_IP6_ADDR_MAX; i++)
  715. {
  716. /* Skip not used enries. */
  717. if(if_dest_cur->ip6_addr[i].state == FNET_NETIF_IP6_ADDR_STATE_NOT_USED)
  718. {
  719. continue;
  720. }
  721. else if(best_addr == FNET_NULL)
  722. {
  723. /* Just take the first used address, by default.=> Link-local address.*/
  724. best_addr = &if_dest_cur->ip6_addr[i].address;
  725. if_dest_best = if_dest_cur;
  726. }
  727. /* RFC3484 Source Address Selection.*/
  728. /* Rule 1: Prefer same address.*/
  729. if(FNET_IP6_ADDR_EQUAL(dest_addr, &if_dest_cur->ip6_addr[i].address))
  730. {
  731. best_addr = &if_dest_cur->ip6_addr[i].address;
  732. if_dest_best = if_dest_cur;
  733. break;
  734. }
  735. /* Rule 2: Prefer appropriate scope.*/
  736. /* If Scope(SA) < Scope(SB): If Scope(SA) < Scope(D), then prefer SB
  737. * and otherwise prefer SA. Similarly, if Scope(SB) < Scope(SA): If
  738. * Scope(SB) < Scope(D), then prefer SA and otherwise prefer SB.
  739. */
  740. best_scope = fnet_ip6_addr_scope(best_addr);
  741. new_scope = fnet_ip6_addr_scope(&if_dest_cur->ip6_addr[i].address);
  742. if(best_scope < new_scope)
  743. {
  744. if(best_scope < dest_scope)
  745. {
  746. best_addr = &if_dest_cur->ip6_addr[i].address; /* PFI take pointer at the begining.*/
  747. if_dest_best = if_dest_cur;
  748. }
  749. continue;
  750. }
  751. else if( new_scope < best_scope)
  752. {
  753. if( new_scope >= dest_scope)
  754. {
  755. best_addr = &if_dest_cur->ip6_addr[i].address;
  756. if_dest_best = if_dest_cur;
  757. }
  758. continue;
  759. }
  760. /* Rule 3: Avoid deprecated addresses.
  761. * XX: Not implemented - we do not store depricated addresses."*/
  762. /* Rule 4: Prefer home addresses.
  763. * XX: Not implemented - we do not have Mobile IPv6.*/
  764. /* Rule 5: Prefer outgoing interface.
  765. */
  766. if((if_dest_best == netif ) && (if_dest_cur != netif))
  767. {
  768. continue;
  769. }
  770. if((if_dest_best != netif ) && (if_dest_cur == netif))
  771. {
  772. best_addr = &if_dest_cur->ip6_addr[i].address;
  773. if_dest_best = if_dest_cur;
  774. continue;
  775. }
  776. /* Rule 6: Prefer matching label.
  777. * If Label(SA) = Label(D) and Label(SB) <> Label(D), then prefer SA.
  778. * Similarly, if Label(SB) = Label(D) and Label(SA) <> Label(D), then
  779. * prefer SB.
  780. */
  781. best_label = fnet_ip6_policy_label(best_addr);
  782. new_label = fnet_ip6_policy_label(&if_dest_cur->ip6_addr[i].address);
  783. if(best_label == dest_label)
  784. {
  785. if(new_label != dest_label)
  786. continue; /* Prefer SA.*/
  787. }
  788. if(new_label == dest_label)
  789. {
  790. if(new_label != dest_label)
  791. {
  792. best_addr = &if_dest_cur->ip6_addr[i].address;
  793. if_dest_best = if_dest_cur;
  794. continue;
  795. }
  796. }
  797. /* Rule 7: Prefer public addresses.
  798. * If SA is a public address and SB is a temporary address, then prefer
  799. * SA. Similarly, if SB is a public address and SA is a temporary
  800. * address, then prefer SB.
  801. * XX: We do not support "temporary"/"random" addresses.*/
  802. /* Rule 8: Use longest matching prefix.
  803. * If CommonPrefixLen(SA, D) > CommonPrefixLen(SB, D), then prefer SA.
  804. * Similarly, if CommonPrefixLen(SB, D) > CommonPrefixLen(SA, D), then
  805. * prefer SB.
  806. */
  807. best_prefix_length = fnet_ip6_common_prefix_length(best_addr, dest_addr);
  808. new_prefix_length = fnet_ip6_common_prefix_length(&if_dest_cur->ip6_addr[i].address, dest_addr);
  809. if(new_prefix_length > best_prefix_length)
  810. /* Found better one.*/
  811. {
  812. best_addr = &if_dest_cur->ip6_addr[i].address;
  813. if_dest_best = if_dest_cur;
  814. }
  815. } /* for(IP6_IF_ADDRESSES_MAX) */
  816. }/* for(if_dest_cur) */
  817. } /* if(dest_addr) */
  818. return best_addr;
  819. }
  820. /************************************************************************
  821. * NAME: fnet_ip6_mtu
  822. *
  823. * DESCRIPTION: Returns MTU (based on ND and PMTU).
  824. *
  825. * RETURNS: MTU
  826. *************************************************************************/
  827. unsigned long fnet_ip6_mtu( fnet_netif_t *netif)
  828. {
  829. unsigned long mtu;
  830. if(netif)
  831. {
  832. #if FNET_CFG_IP6_PMTU_DISCOVERY
  833. if(netif->pmtu) /* If PMTU is enabled for the interface.*/
  834. {
  835. mtu = netif->pmtu;
  836. }
  837. else
  838. #endif
  839. {
  840. mtu = netif->nd6_if_ptr ? netif->nd6_if_ptr->mtu : netif->mtu;
  841. }
  842. if(mtu < FNET_IP6_DEFAULT_MTU)
  843. mtu = FNET_IP6_DEFAULT_MTU;
  844. }
  845. else
  846. mtu = 0;
  847. return mtu;
  848. }
  849. /************************************************************************
  850. * NAME: fnet_ip6_route
  851. *
  852. * DESCRIPTION: This function performs IPv6 routing
  853. * on an outgoing IP packet.
  854. *************************************************************************/
  855. fnet_netif_t *fnet_ip6_route(fnet_ip6_addr_t *src_ip /*optional*/, fnet_ip6_addr_t *dest_ip)
  856. {
  857. fnet_netif_t *netif = FNET_NULL;
  858. /* Validate destination address. */
  859. /* RFC3513: The unspecified address must not be used as the destination address
  860. * of IPv6 packets or in IPv6 Routing Headers.*/
  861. if(!(dest_ip == FNET_NULL) && !FNET_IP6_ADDR_IS_UNSPECIFIED(dest_ip))
  862. {
  863. /*
  864. * The specified source address may
  865. * influence the candidate set, by affecting the choice of outgoing
  866. * interface. If the application or upper-layer specifies a source
  867. * address that is in the candidate set for the destination, then the
  868. * network layer MUST respect that choice. If the application or
  869. * upper-layer does not specify a source address, then the network layer
  870. * uses the source address selection algorithm
  871. */
  872. if((src_ip == FNET_NULL) || FNET_IP6_ADDR_IS_UNSPECIFIED(src_ip))
  873. /* Determine a source address. */
  874. {
  875. src_ip = (fnet_ip6_addr_t *)fnet_ip6_select_src_addr(FNET_NULL, dest_ip);
  876. }
  877. if(src_ip != FNET_NULL)
  878. {
  879. /* Determine an output interface. */
  880. netif = fnet_netif_get_by_ip6_addr(src_ip);
  881. }
  882. }
  883. return netif;
  884. }
  885. /************************************************************************
  886. * NAME: fnet_ip6_will_fragment
  887. *
  888. * DESCRIPTION: This function returns FNET_TRUE if the protocol message
  889. * will be fragmented by IPv6, and FNET_FALSE otherwise.
  890. *************************************************************************/
  891. int fnet_ip6_will_fragment( fnet_netif_t *netif, unsigned long protocol_message_size)
  892. {
  893. int res;
  894. if(
  895. #if FNET_CFG_IP6_PMTU_DISCOVERY
  896. /*
  897. * In response to an IPv6 packet that is sent to an IPv4 destination
  898. * (i.e., a packet that undergoes translation from IPv6 to IPv4), the
  899. * originating IPv6 node may receive an ICMP Packet Too Big message
  900. * reporting a Next-Hop MTU less than 1280. In that case, the IPv6 node
  901. * is not required to reduce the size of subsequent packets to less than
  902. * 1280, but must include a Fragment header in those packets so that the
  903. * IPv6-to-IPv4 translating router can obtain a suitable Identification
  904. * value to use in resulting IPv4 fragments. Note that this means the
  905. * payload may have to be reduced to 1232 octets (1280 minus 40 for the
  906. * IPv6 header and 8 for the Fragment header), and smaller still if
  907. * additional extension headers are used.
  908. */
  909. (netif->pmtu /* If PMTU is enabled.*/ && ((protocol_message_size + sizeof(fnet_ip6_header_t)) > netif->pmtu)) ||
  910. ( !netif->pmtu &&
  911. #endif
  912. ((protocol_message_size + sizeof(fnet_ip6_header_t)) > fnet_ip6_mtu(netif))
  913. #if FNET_CFG_IP6_PMTU_DISCOVERY
  914. )/* IP Fragmentation. */
  915. #endif
  916. )
  917. {
  918. res = FNET_TRUE;
  919. }
  920. else
  921. {
  922. res = FNET_FALSE;
  923. }
  924. return res;
  925. }
  926. /************************************************************************
  927. * NAME: fnet_ip6_output
  928. *
  929. * DESCRIPTION: IPv6 output function.
  930. *
  931. * RETURNS: FNET_OK=OK
  932. * FNET_ERR_NETUNREACH=No route
  933. * FNET_ERR_MSGSIZE=Size error
  934. * FNET_ERR_NOMEM=No memory
  935. *************************************************************************/
  936. int fnet_ip6_output(fnet_netif_t *netif /*optional*/, fnet_ip6_addr_t *src_ip /*optional*/, fnet_ip6_addr_t *dest_ip,
  937. unsigned char protocol, unsigned char hop_limit /*optional*/, fnet_netbuf_t *nb, FNET_COMP_PACKED_VAR unsigned short *checksum)
  938. {
  939. int error_code;
  940. fnet_netbuf_t *nb_header;
  941. fnet_ip6_header_t *ip6_header;
  942. unsigned long mtu;
  943. /* Check maximum packet size. */
  944. if((nb->total_length + sizeof(fnet_ip6_header_t)) > FNET_IP6_MAX_PACKET)
  945. {
  946. error_code = FNET_ERR_MSGSIZE;
  947. goto DROP;
  948. }
  949. /* Validate destination address. */
  950. /* RFC3513: The unspecified address must not be used as the destination address
  951. * of IPv6 packets or in IPv6 Routing Headers.*/
  952. if((dest_ip == FNET_NULL) || FNET_IP6_ADDR_IS_UNSPECIFIED(dest_ip))
  953. {
  954. error_code = FNET_ERR_DESTADDRREQ;
  955. goto DROP;
  956. }
  957. /*
  958. * The specified source address may
  959. * influence the candidate set, by affecting the choice of outgoing
  960. * interface. If the application or upper-layer specifies a source
  961. * address that is in the candidate set for the destination, then the
  962. * network layer MUST respect that choice. If the application or
  963. * upper-layer does not specify a source address, then the network layer
  964. * uses the source address selection algorithm
  965. */
  966. if(src_ip == FNET_NULL) /* It may be any address.*/
  967. /* Determine a source address. */
  968. {
  969. src_ip = (fnet_ip6_addr_t *)fnet_ip6_select_src_addr(netif, dest_ip);
  970. if(src_ip == FNET_NULL)
  971. {
  972. error_code = FNET_ERR_NETUNREACH;
  973. goto DROP;
  974. }
  975. }
  976. if(netif == FNET_NULL)
  977. /* Determine an output interface. */
  978. {
  979. netif = fnet_netif_get_by_ip6_addr(src_ip);
  980. if(netif == FNET_NULL) /* Ther is no any initializaed IF.*/
  981. {
  982. error_code = FNET_ERR_NETUNREACH;
  983. goto DROP;
  984. }
  985. }
  986. /* RFC 4862: By disabling IP operation, the node will then not
  987. * send any IP packets from the interface.*/
  988. if(netif->nd6_if_ptr && netif->nd6_if_ptr->ip6_disabled)
  989. {
  990. error_code = FNET_ERR_IPDISABLED;
  991. goto DROP;
  992. }
  993. /* Pseudo checksum. */
  994. if(checksum)
  995. *checksum = fnet_checksum_pseudo_end( *checksum, (char *)src_ip, (char *)dest_ip, sizeof(fnet_ip6_addr_t) );
  996. /****** Construct IP header. ******/
  997. if((nb_header = fnet_netbuf_new(sizeof(fnet_ip6_header_t), FNET_TRUE)) == 0)
  998. {
  999. error_code = FNET_ERR_NOMEM;
  1000. goto DROP;
  1001. }
  1002. ip6_header =

Large files files are truncated, but you can click here to view the full file