PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/platform/FNET/fnet_stack/stack/fnet_ip.c

https://gitlab.com/fuggles/ucos
C | 1561 lines | 1041 code | 266 blank | 254 comment | 246 complexity | fd4c5f3657ab89c30b9e319ab0b14ef8 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. * Copyright 2003 by Andrey Butok. Motorola SPS.
  6. *
  7. ***************************************************************************
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License Version 3
  10. * or later (the "LGPL").
  11. *
  12. * As a special exception, the copyright holders of the FNET project give you
  13. * permission to link the FNET sources with independent modules to produce an
  14. * executable, regardless of the license terms of these independent modules,
  15. * and to copy and distribute the resulting executable under terms of your
  16. * choice, provided that you also meet, for each linked independent module,
  17. * the terms and conditions of the license of that module.
  18. * An independent module is a module which is not derived from or based
  19. * on this library.
  20. * If you modify the FNET sources, you may extend this exception
  21. * to your version of the FNET sources, but you are not obligated
  22. * to do so. If you do not wish to do so, delete this
  23. * exception statement from your version.
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  28. *
  29. * You should have received a copy of the GNU General Public License
  30. * and the GNU Lesser General Public License along with this program.
  31. * If not, see <http://www.gnu.org/licenses/>.
  32. *
  33. **********************************************************************/ /*!
  34. *
  35. * @file fnet_ip.c
  36. *
  37. * @author Andrey Butok
  38. *
  39. * @brief IP protocol implementation.
  40. *
  41. ***************************************************************************/
  42. #include "fnet.h"
  43. #include "fnet_ip_prv.h"
  44. #include "fnet_icmp.h"
  45. #include "fnet_checksum.h"
  46. #include "fnet_timer_prv.h"
  47. #include "fnet_socket_prv.h"
  48. #include "fnet_netif_prv.h"
  49. #include "fnet_prot.h"
  50. #include "fnet_loop.h"
  51. #include "fnet_igmp.h"
  52. #include "fnet_raw.h"
  53. #if FNET_CFG_IP4
  54. #if FNET_CFG_IP4_FRAGMENTATION
  55. static fnet_ip_frag_list_t *ip_frag_list_head;
  56. static fnet_timer_desc_t ip_timer_ptr;
  57. #endif
  58. static fnet_ip_queue_t ip_queue;
  59. static fnet_event_desc_t ip_event;
  60. #if FNET_CFG_MULTICAST
  61. fnet_ip4_multicast_list_entry_t fnet_ip_multicast_list[FNET_CFG_MULTICAST_MAX];
  62. #endif /* FNET_CFG_MULTICAST */
  63. /************************************************************************
  64. * Function Prototypes
  65. *************************************************************************/
  66. static void fnet_ip_netif_output(struct fnet_netif *netif, fnet_ip4_addr_t dest_ip_addr, fnet_netbuf_t* nb, int do_not_route);
  67. static void fnet_ip_input_low( void *cookie );
  68. static int fnet_ip4_getsockopt(fnet_socket_t *sock, int optname, char *optval, unsigned int *optlen );
  69. static int fnet_ip4_setsockopt( fnet_socket_t *sock, int optname, char *optval, unsigned int optlen );
  70. #if FNET_CFG_IP4_FRAGMENTATION
  71. fnet_netbuf_t *fnet_ip_reassembly( fnet_netbuf_t ** nb_ptr );
  72. static void fnet_ip_frag_list_add( fnet_ip_frag_list_t ** head, fnet_ip_frag_list_t *fl );
  73. static void fnet_ip_frag_list_del( fnet_ip_frag_list_t ** head, fnet_ip_frag_list_t *fl );
  74. static void fnet_ip_frag_add( fnet_ip_frag_header_t ** head, fnet_ip_frag_header_t *frag, fnet_ip_frag_header_t *frag_prev );
  75. static void fnet_ip_frag_del( fnet_ip_frag_header_t ** head, fnet_ip_frag_header_t *frag );
  76. static void fnet_ip_frag_list_free( fnet_ip_frag_list_t *list );
  77. static void fnet_ip_timer( void *cookie );
  78. #endif
  79. #if FNET_CFG_DEBUG_TRACE_IP
  80. void fnet_ip_trace(char *str, fnet_ip_header_t *ip_hdr);
  81. #else
  82. #define fnet_ip_trace(str, ip_hdr)
  83. #endif
  84. /************************************************************************
  85. * NAME: fnet_ip_init
  86. *
  87. * DESCRIPTION: This function makes initialization of the IP layer.
  88. *************************************************************************/
  89. int fnet_ip_init( void )
  90. {
  91. int result = FNET_ERR;
  92. #if FNET_CFG_IP4_FRAGMENTATION
  93. ip_frag_list_head = 0;
  94. ip_timer_ptr = fnet_timer_new((FNET_IP_TIMER_PERIOD / FNET_TIMER_PERIOD_MS), fnet_ip_timer, 0);
  95. if(ip_timer_ptr)
  96. {
  97. #endif
  98. #if FNET_CFG_MULTICAST
  99. /* Clear the multicast list.*/
  100. fnet_memset_zero(fnet_ip_multicast_list, sizeof(fnet_ip_multicast_list));
  101. #endif /* FNET_CFG_MULTICAST */
  102. /* Install SW Interrupt handler. */
  103. ip_event = fnet_event_init(fnet_ip_input_low, 0);
  104. if(ip_event != FNET_ERR)
  105. result = FNET_OK;
  106. #if FNET_CFG_IP4_FRAGMENTATION
  107. }
  108. #endif
  109. return result;
  110. }
  111. /************************************************************************
  112. * NAME: fnet_ip_release
  113. *
  114. * DESCRIPTION: This function makes release of the all resources
  115. * allocated for IP layer module.
  116. *************************************************************************/
  117. void fnet_ip_release( void )
  118. {
  119. fnet_ip_drain();
  120. #if FNET_CFG_IP4_FRAGMENTATION
  121. fnet_timer_free(ip_timer_ptr);
  122. ip_timer_ptr = 0;
  123. #endif
  124. }
  125. /************************************************************************
  126. * NAME: fnet_ip_route
  127. *
  128. * DESCRIPTION: This function performs IP routing
  129. * on an outgoing IP packet.
  130. *************************************************************************/
  131. fnet_netif_t *fnet_ip_route( fnet_ip4_addr_t dest_ip )
  132. {
  133. fnet_netif_t *netif;
  134. fnet_netif_t *res_netif = fnet_netif_get_default() ;
  135. for (netif = fnet_netif_list; netif != 0; netif = netif->next)
  136. {
  137. if((dest_ip & netif->ip4_addr.subnetmask) == (netif->ip4_addr.address & netif->ip4_addr.subnetmask))
  138. {
  139. res_netif = netif;
  140. break;
  141. }
  142. }
  143. #if FNET_CFG_LOOPBACK
  144. /* Anything sent to one of the host's own IP address is sent to the loopback interface.*/
  145. if(dest_ip == res_netif->ip4_addr.address)
  146. {
  147. res_netif = FNET_LOOP_IF;
  148. }
  149. #endif /* FNET_CFG_LOOPBACK */
  150. return res_netif;
  151. }
  152. /************************************************************************
  153. * NAME: fnet_ip_will_fragment
  154. *
  155. * DESCRIPTION: This function returns FNET_TRUE if the protocol message
  156. * will be fragmented by IPv4, and FNET_FALSE otherwise.
  157. *************************************************************************/
  158. int fnet_ip_will_fragment( fnet_netif_t *netif, unsigned long protocol_message_size)
  159. {
  160. int res;
  161. if((protocol_message_size + sizeof(fnet_ip_header_t)) > netif->mtu)
  162. res = FNET_TRUE;
  163. else
  164. res = FNET_FALSE;
  165. return res;
  166. }
  167. /************************************************************************
  168. * NAME: fnet_ip_output
  169. *
  170. * DESCRIPTION: IP output function.
  171. *
  172. * RETURNS: FNET_OK=OK
  173. * FNET_ERR_NETUNREACH=No route
  174. * FNET_ERR_MSGSIZE=Size error
  175. * FNET_ERR_NOMEM=No memory
  176. *************************************************************************/
  177. int fnet_ip_output( fnet_netif_t *netif, fnet_ip4_addr_t src_ip, fnet_ip4_addr_t dest_ip,
  178. unsigned char protocol, unsigned char tos, unsigned char ttl,
  179. fnet_netbuf_t *nb, int DF, int do_not_route,
  180. FNET_COMP_PACKED_VAR unsigned short *checksum )
  181. {
  182. static unsigned short ip_id = 0;
  183. fnet_netbuf_t *nb_header;
  184. fnet_ip_header_t *ipheader;
  185. unsigned long total_length;
  186. int error_code;
  187. if(netif == 0)
  188. if((netif = fnet_ip_route(dest_ip)) == 0) /* No route */
  189. {
  190. error_code = FNET_ERR_NETUNREACH;
  191. goto DROP;
  192. }
  193. /* If source address not specified, use address of outgoing interface */
  194. if(src_ip == INADDR_ANY)
  195. {
  196. src_ip = netif->ip4_addr.address;
  197. };
  198. if((nb->total_length + sizeof(fnet_ip_header_t)) > FNET_IP_MAX_PACKET)
  199. {
  200. error_code = FNET_ERR_MSGSIZE;
  201. goto DROP;
  202. }
  203. /* Construct IP header */
  204. if((nb_header = fnet_netbuf_new(sizeof(fnet_ip_header_t), FNET_TRUE)) == 0)
  205. {
  206. error_code = FNET_ERR_NOMEM;
  207. goto DROP;
  208. }
  209. /* Pseudo checksum. */
  210. if(checksum)
  211. *checksum = fnet_checksum_pseudo_end( *checksum, (char *)&src_ip, (char *)&dest_ip, sizeof(fnet_ip4_addr_t) );
  212. ipheader = nb_header->data_ptr;
  213. FNET_IP_HEADER_SET_VERSION(ipheader, (unsigned char)FNET_IP_VERSION); /* version =4 */
  214. ipheader->id = fnet_htons(ip_id++); /* Id */
  215. ipheader->tos = tos; /* Type of service */
  216. total_length = (unsigned short)(nb->total_length + sizeof(fnet_ip_header_t)); /* total length*/
  217. FNET_IP_HEADER_SET_HEADER_LENGTH(ipheader, sizeof(fnet_ip_header_t) >> 2);
  218. ipheader->flags_fragment_offset = 0x0000; /* flags & fragment offset field */
  219. if(DF)
  220. ipheader->flags_fragment_offset |= FNET_HTONS(FNET_IP_DF);
  221. ipheader->ttl = ttl; /* time to live */
  222. ipheader->protocol = protocol; /* protocol */
  223. ipheader->source_addr = src_ip; /* source address */
  224. ipheader->desination_addr = dest_ip; /* destination address */
  225. ipheader->total_length = fnet_htons((unsigned short)total_length);
  226. nb = fnet_netbuf_concat(nb_header, nb);
  227. if(total_length > netif->mtu) /* IP Fragmentation. */
  228. {
  229. #if FNET_CFG_IP4_FRAGMENTATION
  230. int first_frag_length, frag_length; /* The number of data in each fragment. */
  231. int offset;
  232. int error = 0;
  233. fnet_netbuf_t *tmp_nb;
  234. fnet_netbuf_t *nb_prev;
  235. fnet_netbuf_t ** nb_next_ptr = &nb->next_chain;
  236. int new_header_length, header_length = FNET_IP_HEADER_GET_HEADER_LENGTH(ipheader) << 2;
  237. fnet_ip_header_t *new_ipheader;
  238. frag_length = (int)(netif->mtu - header_length) & ~7; /* rounded down to an 8-byte boundary.*/
  239. first_frag_length = frag_length;
  240. if((ipheader->flags_fragment_offset & FNET_HTONS(FNET_IP_DF)) || /* The fragmentation is prohibited. */
  241. (frag_length < 8)) /* The MTU is too small.*/
  242. {
  243. error_code = FNET_ERR_MSGSIZE;
  244. goto DROP;
  245. }
  246. /* The header (and options) must reside in contiguous area of memory.*/
  247. if((tmp_nb = fnet_netbuf_pullup(nb, header_length)) == 0)
  248. {
  249. error_code = FNET_ERR_NOMEM;
  250. goto DROP;
  251. }
  252. nb = tmp_nb;
  253. ipheader = nb->data_ptr;
  254. nb_prev = nb;
  255. total_length = fnet_ntohs(ipheader->total_length);
  256. /* Go through the whole data segment after first fragment.*/
  257. for (offset = (header_length + frag_length); offset < total_length; offset += frag_length)
  258. {
  259. fnet_netbuf_t *nb_tmp;
  260. nb = fnet_netbuf_new(header_length, FNET_FALSE); /* Allocate a new header.*/
  261. if(nb == 0)
  262. {
  263. error++;
  264. goto FRAG_END;
  265. }
  266. fnet_memcpy(nb->data_ptr, ipheader, (unsigned int)header_length); /* Copy IP header.*/
  267. new_ipheader = nb->data_ptr;
  268. new_header_length = sizeof(fnet_ip_header_t);
  269. FNET_IP_HEADER_SET_HEADER_LENGTH(new_ipheader, new_header_length >> 2);
  270. new_ipheader->flags_fragment_offset = fnet_htons((unsigned short)((offset - header_length) >> 3));
  271. if(offset + frag_length >= total_length)
  272. frag_length = (int)(total_length - offset);
  273. else
  274. new_ipheader->flags_fragment_offset |= FNET_HTONS(FNET_IP_MF);
  275. /* Copy the data from the original packet into the fragment.*/
  276. if((nb_tmp = fnet_netbuf_copy(nb_prev, offset, frag_length, 0)) == 0)
  277. {
  278. error++;
  279. fnet_netbuf_free_chain(nb);
  280. goto FRAG_END;
  281. }
  282. nb = fnet_netbuf_concat(nb, nb_tmp);
  283. new_ipheader->total_length = fnet_htons((unsigned short)nb->total_length);
  284. *nb_next_ptr = nb;
  285. nb_next_ptr = &nb->next_chain;
  286. }
  287. /* Update the first fragment.*/
  288. nb = nb_prev;
  289. fnet_netbuf_trim(&nb, header_length + first_frag_length - fnet_ntohs(ipheader->total_length));
  290. ipheader->total_length = fnet_htons((unsigned short)nb->total_length);
  291. ipheader->flags_fragment_offset |= FNET_HTONS(FNET_IP_MF);
  292. FRAG_END:
  293. for (nb = nb_prev; nb; nb = nb_prev) /* Send each fragment.*/
  294. {
  295. nb_prev = nb->next_chain;
  296. nb->next_chain = 0;
  297. if(error == 0)
  298. {
  299. fnet_ip_trace("TX", nb->data_ptr); /* Print IP header. */
  300. fnet_ip_netif_output(netif, dest_ip, nb, do_not_route);
  301. }
  302. else
  303. fnet_netbuf_free_chain(nb);
  304. }
  305. #else
  306. error_code = FNET_ERR_MSGSIZE; /* Discard datagram.*/
  307. goto DROP;
  308. #endif /* FNET_CFG_IP4_FRAGMENTATION */
  309. }
  310. else
  311. {
  312. fnet_ip_netif_output(netif, dest_ip, nb, do_not_route);
  313. }
  314. return (FNET_OK);
  315. DROP:
  316. fnet_netbuf_free_chain(nb); /* Discard datagram */
  317. return (error_code);
  318. }
  319. /************************************************************************
  320. * NAME: fnet_ip_netif_output
  321. *
  322. * DESCRIPTION:
  323. *************************************************************************/
  324. static void fnet_ip_netif_output(struct fnet_netif *netif, fnet_ip4_addr_t dest_ip_addr, fnet_netbuf_t* nb, int do_not_route)
  325. {
  326. fnet_ip_header_t *ipheader = (fnet_ip_header_t *)nb->data_ptr;
  327. /* IPv4 Header Checksum*/
  328. ipheader->checksum = 0;
  329. #if FNET_CFG_CPU_ETH_HW_TX_IP_CHECKSUM
  330. if(netif->features & FNET_NETIF_FEATURE_HW_TX_IP_CHECKSUM)
  331. nb->flags |= FNET_NETBUF_FLAG_HW_IP_CHECKSUM;
  332. else
  333. #endif
  334. ipheader->checksum = fnet_checksum(nb, FNET_IP_HEADER_GET_HEADER_LENGTH(ipheader) << 2); /* IP checksum*/
  335. if( /* Datagrams sent to a broadcast address */
  336. (fnet_ip_addr_is_broadcast (dest_ip_addr, netif)
  337. /* Datagrams sent to a multicast address. */
  338. ||FNET_IP4_ADDR_IS_MULTICAST(dest_ip_addr)) )
  339. {
  340. #if FNET_CFG_LOOPBACK && (FNET_CFG_LOOPBACK_MULTICAST || FNET_CFG_LOOPBACK_BROADCAST)
  341. fnet_netbuf_t* nb_loop;
  342. if((netif != FNET_LOOP_IF) /* Avoid double send to the loopback interface.*/
  343. {
  344. /* Datagrams sent to a broadcast/multicast address are copied to the loopback interface.*/
  345. if((nb_loop=fnet_netbuf_copy(nb, 0, FNET_NETBUF_COPYALL, FNET_TRUE))!=0)
  346. {
  347. fnet_loop_output_ip4(netif, dest_ip_addr, nb_loop);
  348. }
  349. }
  350. #endif /* FNET_CFG_LOOPBACK && (FNET_CFG_LOOPBACK_MULTICAST || FNET_CFG_LOOPBACK_BROADCAST) */
  351. }
  352. else
  353. {
  354. if(!((do_not_route) || ((dest_ip_addr & netif->ip4_addr.subnetmask) == (netif->ip4_addr.address & netif->ip4_addr.subnetmask))))
  355. {
  356. /* Use the default router as the address to send.*/
  357. dest_ip_addr = netif->ip4_addr.gateway;
  358. }
  359. }
  360. /* Send to Interface.*/
  361. netif->api->output_ip4(netif, dest_ip_addr, nb);
  362. }
  363. /************************************************************************
  364. * NAME: fnet_ip_set_socket_addr
  365. *
  366. * DESCRIPTION: Prepare sockets addreses for upper protocol.
  367. *************************************************************************/
  368. void fnet_ip_set_socket_addr(fnet_ip_header_t *ip_hdr, struct sockaddr *src_addr, struct sockaddr *dest_addr )
  369. {
  370. fnet_memset_zero(src_addr, sizeof(struct sockaddr));
  371. src_addr->sa_family = AF_INET;
  372. ((struct sockaddr_in*)(src_addr))->sin_addr.s_addr = ip_hdr->source_addr;
  373. fnet_memset_zero(dest_addr, sizeof(struct sockaddr));
  374. dest_addr->sa_family = AF_INET;
  375. ((struct sockaddr_in*)(dest_addr))->sin_addr.s_addr = ip_hdr->desination_addr;
  376. }
  377. /************************************************************************
  378. * NAME: fnet_ip_input
  379. *
  380. * DESCRIPTION: IP input function.
  381. *************************************************************************/
  382. void fnet_ip_input( fnet_netif_t *netif, fnet_netbuf_t *nb )
  383. {
  384. if(netif && nb)
  385. {
  386. if(fnet_ip_queue_append(&ip_queue, netif, nb) != FNET_OK)
  387. {
  388. fnet_netbuf_free_chain(nb);
  389. return;
  390. }
  391. /* Initiate S/W Interrupt*/
  392. fnet_event_raise(ip_event);
  393. }
  394. }
  395. /************************************************************************
  396. * NAME: fnet_ip_input_low
  397. *
  398. * DESCRIPTION: This function performs handling of incoming datagrams.
  399. *************************************************************************/
  400. static void fnet_ip_input_low( void *cookie )
  401. {
  402. fnet_ip_header_t *hdr;
  403. fnet_netbuf_t *ip4_nb;
  404. fnet_netbuf_t *tmp_nb;
  405. fnet_prot_if_t *protocol;
  406. fnet_netif_t *netif;
  407. fnet_netbuf_t *nb;
  408. fnet_ip4_addr_t destination_addr;
  409. unsigned long total_length;
  410. unsigned long header_length;
  411. struct sockaddr src_addr;
  412. struct sockaddr dest_addr;
  413. FNET_COMP_UNUSED_ARG(cookie);
  414. fnet_isr_lock();
  415. while((nb = fnet_ip_queue_read(&ip_queue, &netif)) != 0)
  416. {
  417. nb->next_chain = 0;
  418. /* The header must reside in contiguous area of memory. */
  419. if((tmp_nb = fnet_netbuf_pullup(nb, sizeof(fnet_ip_header_t))) == 0 )
  420. {
  421. fnet_netbuf_free_chain(nb);
  422. continue;
  423. }
  424. nb = tmp_nb;
  425. hdr = nb->data_ptr;
  426. destination_addr = hdr->desination_addr;
  427. total_length = fnet_ntohs(hdr->total_length);
  428. header_length = (unsigned long)FNET_IP_HEADER_GET_HEADER_LENGTH(hdr) << 2;
  429. fnet_ip_trace("RX", hdr); /* Print IP header. */
  430. if((nb->total_length >= total_length) /* Check the amount of data*/
  431. && (nb->total_length >= sizeof(fnet_ip_header_t))
  432. && (FNET_IP_HEADER_GET_VERSION(hdr) == 4) /* Check the IP Version*/
  433. && (header_length >= sizeof(fnet_ip_header_t)) /* Check the IP header length*/
  434. #if FNET_CFG_CPU_ETH_HW_TX_IP_CHECKSUM || FNET_CFG_CPU_ETH_HW_RX_IP_CHECKSUM
  435. && ((netif->features | FNET_NETIF_FEATURE_HW_RX_IP_CHECKSUM)
  436. || (nb->flags | FNET_NETBUF_FLAG_HW_IP_CHECKSUM)
  437. || (fnet_checksum(nb, (int)header_length) == 0) ) /* Checksum*/
  438. #else
  439. && (fnet_checksum(nb, (int)header_length) == 0) /* Checksum*/
  440. #endif
  441. && ((destination_addr == netif->ip4_addr.address) /* It is final destination*/
  442. || fnet_ip_addr_is_broadcast(destination_addr, netif)
  443. #if FNET_CFG_MULTICAST
  444. || (FNET_IP4_ADDR_IS_MULTICAST(destination_addr))
  445. #endif
  446. )
  447. )
  448. {
  449. if(nb->total_length > total_length)
  450. {
  451. /* Logical size and the physical size of the packet should be the same.*/
  452. fnet_netbuf_trim(&nb, (int)(total_length - nb->total_length));
  453. }
  454. /* Reassembly.*/
  455. if(hdr->flags_fragment_offset & ~FNET_HTONS(FNET_IP_DF)) /* the MF bit or fragment offset is nonzero.*/
  456. {
  457. #if FNET_CFG_IP4_FRAGMENTATION
  458. if((nb = fnet_ip_reassembly(&nb)) == 0)
  459. continue;
  460. hdr = nb->data_ptr;
  461. header_length = (unsigned long)FNET_IP_HEADER_GET_HEADER_LENGTH(hdr) << 2;
  462. #else
  463. fnet_netbuf_free_chain(nb);
  464. continue;
  465. #endif
  466. }
  467. #if FNET_CFG_CPU_ETH_HW_RX_PROTOCOL_CHECKSUM
  468. else
  469. {
  470. if((netif->features | FNET_NETIF_FEATURE_HW_RX_PROTOCOL_CHECKSUM) &&
  471. ((hdr->protocol == FNET_IP_PROTOCOL_ICMP) ||
  472. (hdr->protocol == FNET_IP_PROTOCOL_UDP) ||
  473. (hdr->protocol == FNET_IP_PROTOCOL_TCP)) )
  474. {
  475. nb->flags |= FNET_NETBUF_FLAG_HW_PROTOCOL_CHECKSUM;
  476. }
  477. }
  478. #endif
  479. if(nb->total_length > FNET_IP_MAX_PACKET)
  480. {
  481. fnet_netbuf_free_chain(nb); /* Discard datagram */
  482. continue;
  483. }
  484. ip4_nb = fnet_netbuf_copy(nb, 0, (int)(header_length + 8), 0);
  485. fnet_netbuf_trim(&nb, (int)header_length);
  486. /**************************************
  487. * Send to upper layers.
  488. **************************************/
  489. /* Prepare addreses for upper protocol.*/
  490. fnet_ip_set_socket_addr(hdr, &src_addr, &dest_addr );
  491. #if FNET_CFG_RAW
  492. /* RAW Sockets inpput.*/
  493. fnet_raw_input(netif, &src_addr, &dest_addr, nb, ip4_nb);
  494. #endif
  495. /* Find transport protocol.*/
  496. if((protocol = fnet_prot_find(AF_INET, SOCK_UNSPEC, hdr->protocol)) != FNET_NULL)
  497. {
  498. protocol->prot_input(netif, &src_addr, &dest_addr, nb, ip4_nb);
  499. /* After that nb may point to wrong place. Do not use it.*/
  500. }
  501. else
  502. /* No protocol found.*/
  503. {
  504. fnet_netbuf_free_chain(nb);
  505. fnet_icmp_error(netif, FNET_ICMP_UNREACHABLE, FNET_ICMP_UNREACHABLE_PROTOCOL, ip4_nb);
  506. }
  507. }
  508. else
  509. {
  510. fnet_netbuf_free_chain(nb);
  511. }
  512. } /* while end */
  513. fnet_isr_unlock();
  514. }
  515. /************************************************************************
  516. * NAME: fnet_ip_reassembly
  517. *
  518. * DESCRIPTION: This function attempts to assemble a complete datagram.
  519. *************************************************************************/
  520. #if FNET_CFG_IP4_FRAGMENTATION
  521. fnet_netbuf_t *fnet_ip_reassembly( fnet_netbuf_t ** nb_ptr )
  522. {
  523. fnet_ip_frag_list_t *frag_list_ptr;
  524. fnet_ip_frag_header_t *frag_ptr, *cur_frag_ptr;
  525. fnet_netbuf_t *nb = *nb_ptr;
  526. fnet_netbuf_t *tmp_nb;
  527. fnet_ip_header_t *iphdr;
  528. int i;
  529. int offset;
  530. unsigned long hdr_length;
  531. /* For this algorithm the all datagram must reside in contiguous area of memory.*/
  532. if((tmp_nb = fnet_netbuf_pullup(nb, (int)nb->total_length)) == 0)
  533. {
  534. goto DROP_FRAG;
  535. }
  536. *nb_ptr = tmp_nb;
  537. nb = tmp_nb;
  538. iphdr = nb->data_ptr;
  539. /* Liner search of the list to locate the appropriate datagram for the current fragment.*/
  540. for (frag_list_ptr = ip_frag_list_head; frag_list_ptr != 0; frag_list_ptr = frag_list_ptr->next)
  541. {
  542. if((frag_list_ptr->id == iphdr->id) && (frag_list_ptr->protocol == iphdr->protocol)
  543. && (frag_list_ptr->source_addr == iphdr->source_addr)
  544. && (frag_list_ptr->desination_addr == iphdr->desination_addr))
  545. break;
  546. }
  547. cur_frag_ptr = (fnet_ip_frag_header_t *)iphdr;
  548. /* Exclude the standard IP header and options.*/
  549. hdr_length = (unsigned long)FNET_IP_HEADER_GET_HEADER_LENGTH(iphdr) << 2;
  550. fnet_netbuf_trim(&nb, (int)hdr_length);
  551. cur_frag_ptr->total_length = (unsigned short)(fnet_ntohs(cur_frag_ptr->total_length) - hdr_length); /* Host endian.*/
  552. if(frag_list_ptr == 0) /* The first fragment of the new datagram.*/
  553. {
  554. if((frag_list_ptr = fnet_malloc_zero(sizeof(fnet_ip_frag_list_t))) == 0) /* Create list.*/
  555. goto DROP_FRAG;
  556. fnet_ip_frag_list_add(&ip_frag_list_head, frag_list_ptr);
  557. frag_list_ptr->ttl = FNET_IP_FRAG_TTL;
  558. frag_list_ptr->id = iphdr->id;
  559. frag_list_ptr->protocol = iphdr->protocol;
  560. frag_list_ptr->source_addr = iphdr->source_addr;
  561. frag_list_ptr->desination_addr = iphdr->desination_addr;
  562. frag_ptr = 0;
  563. if(iphdr->flags_fragment_offset & FNET_HTONS(FNET_IP_MF))
  564. cur_frag_ptr->mf |= 1;
  565. cur_frag_ptr->offset = (unsigned short)(fnet_ntohs(cur_frag_ptr->offset) << 3); /* Convert offset to bytes (Host endian).*/
  566. cur_frag_ptr->nb = nb;
  567. }
  568. else
  569. {
  570. if(iphdr->flags_fragment_offset & FNET_HTONS(FNET_IP_MF))
  571. cur_frag_ptr->mf |= 1;
  572. cur_frag_ptr->offset = (unsigned short)(fnet_ntohs(cur_frag_ptr->offset) << 3); /* Convert offset to bytes.*/
  573. cur_frag_ptr->nb = nb;
  574. /* Find position in reassembly list.*/
  575. frag_ptr = frag_list_ptr->frag_ptr;
  576. do
  577. {
  578. if(frag_ptr->offset > cur_frag_ptr->offset)
  579. break;
  580. frag_ptr = frag_ptr->next;
  581. }
  582. while (frag_ptr != frag_list_ptr->frag_ptr);
  583. /* Trims or discards icoming fragments.*/
  584. if(frag_ptr != frag_list_ptr->frag_ptr)
  585. {
  586. if((i = frag_ptr->prev->offset + frag_ptr->prev->total_length - cur_frag_ptr->prev->offset) != 0)
  587. {
  588. if(i > cur_frag_ptr->total_length)
  589. goto DROP_FRAG;
  590. fnet_netbuf_trim(&nb, i);
  591. cur_frag_ptr->total_length -= i;
  592. cur_frag_ptr->offset += i;
  593. }
  594. }
  595. /* Trims or discards existing fragments.*/
  596. while((frag_ptr != frag_list_ptr->frag_ptr)
  597. && ((cur_frag_ptr->offset + cur_frag_ptr->total_length) > frag_ptr->offset))
  598. {
  599. i = (cur_frag_ptr->offset + cur_frag_ptr->total_length) - frag_ptr->offset;
  600. if(i < frag_ptr->total_length)
  601. {
  602. frag_ptr->total_length -= i;
  603. frag_ptr->offset += i;
  604. fnet_netbuf_trim((fnet_netbuf_t **)&frag_ptr->nb, i);
  605. break;
  606. }
  607. frag_ptr = frag_ptr->next;
  608. fnet_netbuf_free_chain(frag_ptr->prev->nb);
  609. fnet_ip_frag_del((fnet_ip_frag_header_t **)&frag_list_ptr->frag_ptr, frag_ptr->prev);
  610. }
  611. }
  612. /* Insert fragment to the list.*/
  613. fnet_ip_frag_add((fnet_ip_frag_header_t **)(&frag_list_ptr->frag_ptr), cur_frag_ptr, frag_ptr->prev);
  614. offset = 0;
  615. frag_ptr = frag_list_ptr->frag_ptr;
  616. do
  617. {
  618. if(frag_ptr->offset != offset)
  619. goto NEXT_FRAG;
  620. offset += frag_ptr->total_length;
  621. frag_ptr = frag_ptr->next;
  622. } while (frag_ptr != frag_list_ptr->frag_ptr);
  623. if(frag_ptr->prev->mf & 1)
  624. goto NEXT_FRAG;
  625. /* Reconstruct datagram.*/
  626. frag_ptr = frag_list_ptr->frag_ptr;
  627. nb = frag_ptr->nb;
  628. frag_ptr = frag_ptr->next;
  629. while(frag_ptr != frag_list_ptr->frag_ptr)
  630. {
  631. nb = fnet_netbuf_concat(nb, frag_ptr->nb);
  632. frag_ptr = frag_ptr->next;
  633. }
  634. /* Reconstruct datagram header.*/
  635. iphdr = (fnet_ip_header_t *)frag_list_ptr->frag_ptr;
  636. nb->total_length += FNET_IP_HEADER_GET_HEADER_LENGTH(iphdr) << 2;
  637. nb->length += FNET_IP_HEADER_GET_HEADER_LENGTH(iphdr) << 2;
  638. nb->data_ptr = (unsigned char *)nb->data_ptr - (FNET_IP_HEADER_GET_HEADER_LENGTH(iphdr) << 2);
  639. iphdr->total_length = fnet_htons((unsigned short)nb->total_length);
  640. iphdr->source_addr = frag_list_ptr->source_addr;
  641. iphdr->desination_addr = frag_list_ptr->desination_addr;
  642. iphdr->protocol = frag_list_ptr->protocol;
  643. iphdr->tos &= ~1;
  644. fnet_ip_frag_list_del(&ip_frag_list_head, frag_list_ptr);
  645. fnet_free(frag_list_ptr);
  646. return (nb);
  647. DROP_FRAG:
  648. fnet_netbuf_free_chain(nb);
  649. NEXT_FRAG:
  650. return (FNET_NULL);
  651. }
  652. #endif /* FNET_CFG_IP4_FRAGMENTATION */
  653. /************************************************************************
  654. * NAME: fnet_ip_timer
  655. *
  656. * DESCRIPTION: IP timer function.
  657. *************************************************************************/
  658. #if FNET_CFG_IP4_FRAGMENTATION
  659. static void fnet_ip_timer(void *cookie)
  660. {
  661. fnet_ip_frag_list_t *frag_list_ptr;
  662. fnet_ip_frag_list_t *tmp_frag_list_ptr;
  663. FNET_COMP_UNUSED_ARG(cookie);
  664. fnet_isr_lock();
  665. frag_list_ptr = ip_frag_list_head;
  666. while(frag_list_ptr != 0)
  667. {
  668. frag_list_ptr->ttl--;
  669. if(frag_list_ptr->ttl == 0)
  670. {
  671. tmp_frag_list_ptr = frag_list_ptr->next;
  672. fnet_ip_frag_list_free(frag_list_ptr);
  673. frag_list_ptr = tmp_frag_list_ptr;
  674. }
  675. else
  676. frag_list_ptr = frag_list_ptr->next;
  677. }
  678. fnet_isr_unlock();
  679. }
  680. #endif
  681. /************************************************************************
  682. * NAME: fnet_ip_drain
  683. *
  684. * DESCRIPTION: This function tries to free not critical parts
  685. * of memory occupied by the IP module.
  686. *************************************************************************/
  687. void fnet_ip_drain( void )
  688. {
  689. fnet_isr_lock();
  690. #if FNET_CFG_IP4_FRAGMENTATION
  691. while(((volatile fnet_ip_frag_list_t *)ip_frag_list_head) != 0)
  692. {
  693. fnet_ip_frag_list_free(ip_frag_list_head);
  694. }
  695. #endif
  696. while(((volatile fnet_netbuf_t *)ip_queue.head) != 0)
  697. {
  698. fnet_netbuf_del_chain(&ip_queue.head, ip_queue.head);
  699. }
  700. ip_queue.count = 0;
  701. fnet_isr_unlock();
  702. }
  703. /************************************************************************
  704. * NAME: fnet_ip_frag_list_free
  705. *
  706. * DESCRIPTION: This function frees list of datagram fragments.
  707. *************************************************************************/
  708. #if FNET_CFG_IP4_FRAGMENTATION
  709. static void fnet_ip_frag_list_free( fnet_ip_frag_list_t *list )
  710. {
  711. fnet_netbuf_t *nb;
  712. fnet_isr_lock();
  713. if(list)
  714. {
  715. while((volatile fnet_ip_frag_header_t *)(list->frag_ptr) != 0)
  716. {
  717. nb = list->frag_ptr->nb;
  718. fnet_ip_frag_del((fnet_ip_frag_header_t **)(&list->frag_ptr), list->frag_ptr);
  719. fnet_netbuf_free_chain(nb);
  720. }
  721. fnet_ip_frag_list_del(&ip_frag_list_head, list);
  722. fnet_free(list);
  723. }
  724. fnet_isr_unlock();
  725. }
  726. #endif /* FNET_CFG_IP4_FRAGMENTATION */
  727. /************************************************************************
  728. * NAME: fnet_ip_frag_list_add
  729. *
  730. * DESCRIPTION: Adds frag list to the general frag list.
  731. *************************************************************************/
  732. #if FNET_CFG_IP4_FRAGMENTATION
  733. static void fnet_ip_frag_list_add( fnet_ip_frag_list_t ** head, fnet_ip_frag_list_t *fl )
  734. {
  735. fl->next = *head;
  736. if(fl->next != 0)
  737. fl->next->prev = fl;
  738. fl->prev = 0;
  739. *head = fl;
  740. }
  741. #endif /* FNET_CFG_IP4_FRAGMENTATION */
  742. /************************************************************************
  743. * NAME: fnet_ip_frag_list_del
  744. *
  745. * DESCRIPTION: Deletes frag list from the general frag list.
  746. *************************************************************************/
  747. #if FNET_CFG_IP4_FRAGMENTATION
  748. static void fnet_ip_frag_list_del( fnet_ip_frag_list_t ** head, fnet_ip_frag_list_t *fl )
  749. {
  750. if(fl->prev == 0)
  751. *head=fl->next;
  752. else
  753. fl->prev->next = fl->next;
  754. if(fl->next != 0)
  755. fl->next->prev = fl->prev;
  756. }
  757. #endif /* FNET_CFG_IP4_FRAGMENTATION */
  758. /************************************************************************
  759. * NAME: fnet_ip_frag_add
  760. *
  761. * DESCRIPTION: Adds frag to the frag list.
  762. *************************************************************************/
  763. #if FNET_CFG_IP4_FRAGMENTATION
  764. static void fnet_ip_frag_add( fnet_ip_frag_header_t ** head, fnet_ip_frag_header_t *frag,
  765. fnet_ip_frag_header_t *frag_prev )
  766. {
  767. if(frag_prev && ( *head))
  768. {
  769. frag->next = frag_prev->next;
  770. frag->prev = frag_prev;
  771. frag_prev->next->prev = frag;
  772. frag_prev->next = frag;
  773. if((*head)->offset > frag->offset)
  774. {
  775. *head = frag;
  776. }
  777. }
  778. else
  779. {
  780. frag->next = frag;
  781. frag->prev = frag;
  782. *head = frag;
  783. }
  784. }
  785. #endif /* FNET_CFG_IP4_FRAGMENTATION */
  786. /************************************************************************
  787. * NAME: fnet_ip_frag_del
  788. *
  789. * DESCRIPTION: Deletes frag from the frag list.
  790. *************************************************************************/
  791. #if FNET_CFG_IP4_FRAGMENTATION
  792. static void fnet_ip_frag_del( fnet_ip_frag_header_t ** head, fnet_ip_frag_header_t *frag )
  793. {
  794. if(frag->prev == frag)
  795. *head=0;
  796. else
  797. {
  798. frag->prev->next = frag->next;
  799. frag->next->prev = frag->prev;
  800. if(*head == frag)
  801. *head=frag->next;
  802. }
  803. }
  804. #endif /* FNET_CFG_IP4_FRAGMENTATION */
  805. #if FNET_CFG_MULTICAST
  806. /************************************************************************
  807. * NAME: fnet_ip_multicast_join
  808. *
  809. * DESCRIPTION: Join a multicast group. Returns pointer to the entry in
  810. * the multicast list, or FNET_NULL if any error;
  811. *************************************************************************/
  812. fnet_ip4_multicast_list_entry_t *fnet_ip_multicast_join( fnet_netif_t *netif, fnet_ip4_addr_t group_addr )
  813. {
  814. int i;
  815. fnet_ip4_multicast_list_entry_t *result = FNET_NULL;
  816. /* Find existing entry or free one.*/
  817. for(i=0; i < FNET_CFG_MULTICAST_MAX; i++)
  818. {
  819. if(fnet_ip_multicast_list[i].user_counter > 0)
  820. {
  821. if((fnet_ip_multicast_list[i].netif == netif) && (fnet_ip_multicast_list[i].group_addr == group_addr))
  822. {
  823. result = &fnet_ip_multicast_list[i];
  824. break; /* Found.*/
  825. }
  826. }
  827. else /* user_counter == 0.*/
  828. {
  829. result = &fnet_ip_multicast_list[i]; /* Save the last free.*/
  830. }
  831. }
  832. if(result)
  833. {
  834. result->user_counter++; /* Increment user counter.*/
  835. if(result->user_counter == 1) /* New entry.*/
  836. {
  837. result->group_addr = group_addr;
  838. result->netif = netif;
  839. /* Join HW interface. */
  840. fnet_netif_join_ip4_multicast ( (fnet_netif_desc_t) netif, group_addr );
  841. #if FNET_CFG_IGMP /* Send IGMP report.*/
  842. /*
  843. * When a host joins a new group, it should immediately transmit a
  844. * Report for that group.
  845. * //TBD To cover the possibility of the initial Report being lost or damaged, it is
  846. * recommended that it be repeated once or twice after short delays.
  847. */
  848. fnet_igmp_join(netif, group_addr );
  849. #endif /* FNET_CFG_IGMP */
  850. }
  851. }
  852. return result;
  853. }
  854. /************************************************************************
  855. * NAME: fnet_ip_multicast_leave_entry
  856. *
  857. * DESCRIPTION: Leave a multicast group.
  858. *************************************************************************/
  859. void fnet_ip_multicast_leave_entry( fnet_ip4_multicast_list_entry_t *multicastentry )
  860. {
  861. if(multicastentry)
  862. {
  863. multicastentry->user_counter--; /* Decrement user counter.*/
  864. if(multicastentry->user_counter == 0)
  865. {
  866. #if FNET_CFG_IGMP /* Send IGMP leave.*/
  867. /* Leave via IGMP */
  868. fnet_igmp_leave( multicastentry->netif, multicastentry->group_addr );
  869. #endif /* FNET_CFG_IGMP */
  870. /* Leave HW interface. */
  871. fnet_netif_leave_ip4_multicast ( (fnet_netif_desc_t) multicastentry->netif, multicastentry->group_addr );
  872. }
  873. }
  874. }
  875. #endif /* FNET_CFG_MULTICAST */
  876. /************************************************************************
  877. * NAME: fnet_ip_addr_is_broadcast
  878. *
  879. * DESCRIPTION: Is the address is broadcast?
  880. *************************************************************************/
  881. int fnet_ip_addr_is_broadcast( fnet_ip4_addr_t addr, fnet_netif_t *netif )
  882. {
  883. fnet_netif_ip4_addr_t *netif_addr;
  884. int result = FNET_FALSE;
  885. if(addr == INADDR_BROADCAST || addr == INADDR_ANY) /* Limited broadcast */
  886. {
  887. result = FNET_TRUE;
  888. }
  889. else if(netif == FNET_NULL)
  890. {
  891. fnet_os_mutex_lock();
  892. for (netif = fnet_netif_list; netif != 0; netif = netif->next)
  893. {
  894. netif_addr = &(netif->ip4_addr);
  895. if(addr == netif_addr->netbroadcast || /* Net-directed broadcast */
  896. addr == netif_addr->subnetbroadcast || /* Subnet-directed broadcast */
  897. addr == netif_addr->subnet)
  898. {
  899. result = FNET_TRUE;
  900. break;
  901. }
  902. }
  903. fnet_os_mutex_unlock();
  904. }
  905. else
  906. {
  907. netif_addr = &(netif->ip4_addr);
  908. if(addr == netif_addr->netbroadcast || /* Net-directed broadcast */
  909. addr == netif_addr->subnetbroadcast || /* Subnet-directed broadcast */
  910. addr == netif_addr->subnet)
  911. {
  912. result = FNET_TRUE;
  913. }
  914. }
  915. return result;
  916. }
  917. /* TBD ??? */
  918. /*Todo path MTU discovery feature
  919. *Todo get MTU from a routing table, depending on destination MTU*/
  920. unsigned long fnet_ip_maximum_packet( fnet_ip4_addr_t dest_ip )
  921. {
  922. unsigned int result;
  923. #if FNET_CFG_IP4_FRAGMENTATION == 0
  924. {
  925. fnet_netif_t *netif;
  926. if((netif = fnet_ip_route(dest_ip)) == 0) /* No route*/
  927. result = FNET_IP_MAX_PACKET;
  928. else
  929. result = netif->mtu;
  930. }
  931. #else
  932. FNET_COMP_UNUSED_ARG(dest_ip);
  933. result = FNET_IP_MAX_PACKET;
  934. #endif
  935. result = (result - (FNET_IP_MAX_OPTIONS + sizeof(fnet_ip_header_t))) & (~0x3L);
  936. return result;
  937. }
  938. /************************************************************************
  939. * NAME: fnet_ip4_getsockopt
  940. *
  941. * DESCRIPTION: This function retrieves the current value
  942. * of IPv4 socket option.
  943. *************************************************************************/
  944. static int fnet_ip4_getsockopt(fnet_socket_t *sock, int optname, char *optval, unsigned int *optlen )
  945. {
  946. int result = FNET_OK;
  947. switch(optname) /* Socket options processing. */
  948. {
  949. case IP_TOS: /* Get IP TOS for outgoing datagrams.*/
  950. if(*optlen < sizeof(int))
  951. {
  952. result = FNET_ERR_INVAL;
  953. break;
  954. }
  955. *((int*)optval) = sock->options.ip_opt.tos;
  956. *optlen = sizeof(int);
  957. break;
  958. case IP_TTL: /* Get IP TTL for outgoing datagrams.*/
  959. if(*optlen < sizeof(int))
  960. {
  961. result = FNET_ERR_INVAL;
  962. break;
  963. }
  964. *((int*)optval) = (char)sock->options.ip_opt.ttl;
  965. *optlen = sizeof(int);
  966. break;
  967. #if FNET_CFG_MULTICAST
  968. case IP_MULTICAST_TTL: /* Get IP TTL for outgoing datagrams.*/
  969. if(*optlen < sizeof(int))
  970. {
  971. result = FNET_ERR_INVAL;
  972. break;
  973. }
  974. *((int*)optval) = (char)sock->options.ip_opt.ttl_multicast;
  975. *optlen = sizeof(int);
  976. break;
  977. #endif /* FNET_CFG_MULTICAST */
  978. default:
  979. result = FNET_ERR_NOPROTOOPT; /* The option is unknown or unsupported.*/
  980. break;
  981. }
  982. return result;
  983. }
  984. /************************************************************************
  985. * NAME: fnet_ip4_setsockopt
  986. *
  987. * DESCRIPTION: This function sets the value of IPv4 socket option.
  988. *************************************************************************/
  989. static int fnet_ip4_setsockopt( fnet_socket_t *sock, int optname, char *optval, unsigned int optlen )
  990. {
  991. int result = FNET_OK;
  992. switch(optname) /* Socket options processing. */
  993. {
  994. /******************************/
  995. case IP_TOS: /* Set IP TOS for outgoing datagrams. */
  996. if(optlen != sizeof(int))
  997. {
  998. result = FNET_ERR_INVAL;
  999. break;
  1000. }
  1001. sock->options.ip_opt.tos = (unsigned char) (*((int *)(optval)));
  1002. break;
  1003. /******************************/
  1004. case IP_TTL: /* Set IP TTL for outgoing datagrams. */
  1005. if(optlen != sizeof(int))
  1006. {
  1007. result = FNET_ERR_INVAL;
  1008. break;
  1009. }
  1010. sock->options.ip_opt.ttl = (unsigned char) (*((int *)(optval)));
  1011. break;
  1012. #if FNET_CFG_MULTICAST
  1013. /******************************/
  1014. case IP_MULTICAST_TTL: /* Set IP TTL for outgoing Multicast datagrams. */
  1015. /* Validation.*/
  1016. if( (optlen != sizeof(int)) || !(sock->protocol_interface) || (sock->protocol_interface->type != SOCK_DGRAM ) )
  1017. {
  1018. result = FNET_ERR_INVAL;
  1019. break;
  1020. }
  1021. sock->options.ip_opt.ttl_multicast = (unsigned char) (*((int *)(optval)));
  1022. break;
  1023. /******************************/
  1024. case IP_ADD_MEMBERSHIP: /* Join the socket to the supplied multicast group on
  1025. * the specified interface. */
  1026. case IP_DROP_MEMBERSHIP: /* Drops membership to the given multicast group and interface.*/
  1027. {
  1028. int i;
  1029. fnet_ip4_multicast_list_entry_t **multicast_entry = FNET_NULL;
  1030. struct ip_mreq *mreq = (struct ip_mreq *)optval;
  1031. fnet_netif_t *netif;
  1032. if(mreq->imr_interface.s_addr == INADDR_ANY)
  1033. {
  1034. netif = (fnet_netif_t *)fnet_netif_get_default();
  1035. }
  1036. else
  1037. {
  1038. netif = (fnet_netif_t *)fnet_netif_get_by_ip4_addr(mreq->imr_interface.s_addr);
  1039. }
  1040. if((optlen != sizeof(struct ip_mreq)) /* Check size.*/
  1041. || (netif == FNET_NULL) /* Found IF.*/
  1042. || (!FNET_IP4_ADDR_IS_MULTICAST(mreq->imr_multiaddr.s_addr)) /* Check if the address is multicast.*/
  1043. || !(sock->protocol_interface) || (sock->protocol_interface->type != SOCK_DGRAM )
  1044. )
  1045. {
  1046. result = FNET_ERR_INVAL;
  1047. break;
  1048. }
  1049. /* Find the existing entry with same parameters.*/
  1050. for(i = 0; i < FNET_CFG_MULTICAST_SOCKET_MAX; i++)
  1051. {
  1052. if( (sock->ip4_multicast_entry[i] != FNET_NULL)
  1053. && (sock->ip4_multicast_entry[i]->netif == netif)
  1054. && (sock->ip4_multicast_entry[i]->group_addr == mreq->imr_multiaddr.s_addr) )
  1055. {
  1056. multicast_entry = &sock->ip4_multicast_entry[i];
  1057. break; /* Found.*/
  1058. }
  1059. }
  1060. /******************************/
  1061. if(optname == IP_ADD_MEMBERSHIP)
  1062. {
  1063. if(multicast_entry != FNET_NULL)
  1064. {
  1065. /* Already joined.*/
  1066. result = FNET_ERR_ADDRINUSE;
  1067. break;
  1068. }
  1069. /* Find free entry.*/
  1070. for(i = 0; i < FNET_CFG_MULTICAST_SOCKET_MAX; i++)
  1071. {
  1072. if(sock->ip4_multicast_entry[i] == FNET_NULL)
  1073. {
  1074. multicast_entry = &sock->ip4_multicast_entry[i];
  1075. break; /* Found.*/
  1076. }
  1077. }
  1078. if(multicast_entry != FNET_NULL)
  1079. {
  1080. *multicast_entry = fnet_ip_multicast_join( netif, mreq->imr_multiaddr.s_addr );
  1081. if(*multicast_entry == FNET_NULL)
  1082. {
  1083. result = FNET_ERR_ADDRINUSE;
  1084. break;
  1085. }
  1086. }
  1087. else
  1088. {
  1089. result = FNET_ERR_ADDRINUSE;
  1090. break;
  1091. }
  1092. }
  1093. /******************************/
  1094. else /* IP_DROP_MEMBERSHIP */
  1095. {
  1096. if(multicast_entry != FNET_NULL)
  1097. {
  1098. /* Leave the group.*/
  1099. fnet_ip_multicast_leave_entry(*multicast_entry);
  1100. *multicast_entry = FNET_NULL;
  1101. }
  1102. else
  1103. {
  1104. /* Join entry is not foud.*/
  1105. result = FNET_ERR_INVAL;
  1106. break;
  1107. }
  1108. }
  1109. }
  1110. break;
  1111. #endif /* FNET_CFG_MULTICAST */
  1112. /******************************/
  1113. default:
  1114. result = FNET_ERR_NOPROTOOPT; /* The option is unknown or unsupported. */
  1115. break;
  1116. }
  1117. return result;
  1118. }
  1119. /************************************************************************
  1120. * NAME: fnet_ip_trace
  1121. *
  1122. * DESCRIPTION: Prints an IP header. For debug needs only.
  1123. *************************************************************************/
  1124. #if FNET_CFG_DEBUG_TRACE_IP
  1125. void fnet_ip_trace(char *str,fnet_ip_header_t *ip_hdr)
  1126. {
  1127. char ip_str[FNET_IP4_ADDR_STR_SIZE];
  1128. fnet_printf(FNET_SERIAL_ESC_FG_GREEN"%s", str); /* Print app-specific header.*/
  1129. fnet_println("[IP header]"FNET_SERIAL_ESC_FG_BLACK);
  1130. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  1131. fnet_println("|(V) %2d |(HL)%2d |(TOS) 0x%02x |(L) %5u |",
  1132. FNET_IP_HEADER_GET_VERSION(ip_hdr),
  1133. FNET_IP_HEADER_GET_HEADER_LENGTH(ip_hdr),
  1134. ip_hdr->tos,
  1135. fnet_ntohs(ip_hdr->total_length));
  1136. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  1137. fnet_println("|(Id) %5u |(F)%u |(Offset) %4u |",
  1138. fnet_ntohs(ip_hdr->id),
  1139. fnet_ntohs(FNET_IP_HEADER_GET_FLAG(ip_hdr))>>15,
  1140. fnet_ntohs(FNET_IP_HEADER_GET_OFFSET(ip_hdr)));
  1141. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  1142. fnet_println("|(TTL) %3u |(Proto) "FNET_SERIAL_ESC_FG_BLUE"%3u"FNET_SERIAL_ESC_FG_BLACK" |(Cheksum) 0x%04x |",
  1143. ip_hdr->ttl,
  1144. ip_hdr->protocol,
  1145. fnet_ntohs(ip_hdr->checksum));
  1146. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  1147. fnet_println("|(Src) "FNET_SERIAL_ESC_FG_BLUE"%15s"FNET_SERIAL_ESC_FG_BLACK" |",
  1148. fnet_inet_ntoa(*(struct in_addr *)(&ip_hdr->source_addr), ip_str));
  1149. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  1150. fnet_println("|(Dest) "FNET_SERIAL_ESC_FG_BLUE"%15s"FNET_SERIAL_ESC_FG_BLACK" |",
  1151. fnet_inet_ntoa(*(struct in_addr *)(&ip_hdr->desination_addr), ip_str));
  1152. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  1153. }
  1154. #endif /* FNET_CFG_DEBUG_TRACE_IP */
  1155. #endif /* FNET_CFG_IP4 */
  1156. /************************************************************************
  1157. * NAME: fnet_ip_setsockopt
  1158. *
  1159. * DESCRIPTION: This function sets the value of IP socket option.
  1160. *************************************************************************/
  1161. int fnet_ip_setsockopt( fnet_socket_t *sock, int level, int optname, char *optval, unsigned int optlen )
  1162. {
  1163. int error;
  1164. if((optval) && (optlen))
  1165. {
  1166. #if FNET_CFG_IP4
  1167. if((level == IPPROTO_IP) && (sock->protocol_interface->family & AF_INET))
  1168. {
  1169. error = fnet_ip4_setsockopt(sock, optname, optval, optlen);
  1170. if(error != FNET_OK)
  1171. goto ERROR_SOCK;
  1172. }
  1173. else
  1174. #endif
  1175. #if FNET_CFG_IP6
  1176. if((level == IPPROTO_IPV6) && (sock->protocol_interface->family & AF_INET6))
  1177. {
  1178. error = fnet_ip6_setsockopt(sock, optname, optval, optlen);
  1179. if(error != FNET_OK)
  1180. goto ERROR_SOCK;
  1181. }
  1182. else
  1183. #endif
  1184. {
  1185. error = FNET_ERR_INVAL; /* Invalid argument.*/
  1186. goto ERROR_SOCK;
  1187. }
  1188. }
  1189. else
  1190. {
  1191. error = FNET_ERR

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