--- /dev/null
+/*\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/* WinPCap includes. */\r
+#include "pcap.h"\r
+#include "remote-ext.h"\r
+\r
+/* uIP includes. */\r
+#include "net/uip.h"\r
+#include "net/uip_arp.h"\r
+#include "net/clock-arch.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+\r
+/*\r
+ * Query the computer the simulation is being executed on to find the network\r
+ * interfaces it has installed.\r
+ */\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );\r
+\r
+/*\r
+ * Open the network interface. The number of the interface to be opened is set\r
+ * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+ */\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );\r
+\r
+/*\r
+ * Configure the capture filter to allow blocking reads, and to filter out\r
+ * packets that are not of interest to this demo.\r
+ */\r
+static void prvConfigureCaptureBehaviour( void );\r
+\r
+pcap_t *pxOpenedInterfaceHandle = NULL;\r
+LARGE_INTEGER freq, sys_start_time;\r
+\r
+#define archNUM_BUFFERS 5\r
+#define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )\r
+\r
+static void prvInterruptSimulator( void *pvParameters );\r
+\r
+static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];\r
+static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];\r
+\r
+static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };\r
+static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;\r
+\r
+unsigned char *uip_buf = NULL;\r
+char cErrorBuffer[PCAP_ERRBUF_SIZE];\r
+\r
+void vNetifTx( void )\r
+{\r
+ pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
+ pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxNetifRx( void )\r
+{\r
+UBaseType_t xDataLen;\r
+unsigned char *pucTemp;\r
+\r
+ /* Check there is really data available. */\r
+ xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];\r
+ if( xDataLen != 0L )\r
+ {\r
+\r
+ /* The buffer pointed to by uip_buf is going to change. Remember which\r
+ buffer uip_buf is currently pointing to. */\r
+ pucTemp = uip_buf;\r
+\r
+ /* Point uip_buf at the next buffer that contains data. */\r
+ uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];\r
+\r
+ /* The buffer pointed to by \r
+ pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by\r
+ uip_buf, but the buffer uip_buf was pointing to on entry to this\r
+ function is free. Set \r
+ pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free \r
+ buffer. */\r
+ pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;\r
+ lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;\r
+\r
+ ucNextBufferToProcess++;\r
+ if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )\r
+ {\r
+ ucNextBufferToProcess = 0L;\r
+ }\r
+ }\r
+\r
+ return xDataLen;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetifInit( void )\r
+{\r
+BaseType_t x;\r
+pcap_if_t *pxAllNetworkInterfaces;\r
+\r
+ /* Allocate a free buffer to each buffer pointer. */\r
+ for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )\r
+ {\r
+ pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );\r
+ }\r
+\r
+ /* Start with uip_buf pointing to a buffer that is not referenced from the\r
+ pucEthernetBufferPointers[] array. */\r
+ uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );\r
+\r
+ /* Query the computer the simulation is being executed on to find the \r
+ network interfaces it has installed. */\r
+ pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();\r
+ \r
+ /* Open the network interface. The number of the interface to be opened is \r
+ set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+ Calling this function will set the pxOpenedInterfaceHandle variable. If,\r
+ after calling this function, pxOpenedInterfaceHandle is equal to NULL, then\r
+ the interface could not be opened. */\r
+ if( pxAllNetworkInterfaces != NULL )\r
+ {\r
+ prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );\r
+ }\r
+ \r
+\r
+ return x;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
+{ \r
+pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
+long lInterfaceNumber = 1;\r
+\r
+ if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
+ {\r
+ printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );\r
+ pxAllNetworkInterfaces = NULL;\r
+ }\r
+\r
+ if( pxAllNetworkInterfaces != NULL )\r
+ {\r
+ /* Print out the list of network interfaces. The first in the list\r
+ is interface '1', not interface '0'. */\r
+ for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )\r
+ {\r
+ printf( "%d. %s", lInterfaceNumber, xInterface->name );\r
+ \r
+ if( xInterface->description != NULL )\r
+ {\r
+ printf( " (%s)\r\n", xInterface->description );\r
+ }\r
+ else\r
+ {\r
+ printf( " (No description available)\r\n") ;\r
+ }\r
+ \r
+ lInterfaceNumber++;\r
+ }\r
+ }\r
+\r
+ if( lInterfaceNumber == 1 )\r
+ {\r
+ /* The interface number was never incremented, so the above for() loop\r
+ did not execute meaning no interfaces were found. */\r
+ printf( " \r\nNo network interfaces were found.\r\n" );\r
+ pxAllNetworkInterfaces = NULL;\r
+ }\r
+\r
+ printf( "\r\nThe interface that will be opened is set by configNETWORK_INTERFACE_TO_USE which should be defined in FreeRTOSConfig.h\r\n" );\r
+ printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );\r
+ \r
+ if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )\r
+ {\r
+ printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );\r
+ \r
+ if( pxAllNetworkInterfaces != NULL )\r
+ {\r
+ /* Free the device list, as no devices are going to be opened. */\r
+ pcap_freealldevs( pxAllNetworkInterfaces );\r
+ pxAllNetworkInterfaces = NULL;\r
+ }\r
+ }\r
+\r
+ return pxAllNetworkInterfaces;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
+{\r
+pcap_if_t *xInterface;\r
+long x;\r
+\r
+ /* Walk the list of devices until the selected device is located. */\r
+ xInterface = pxAllNetworkInterfaces;\r
+ for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )\r
+ {\r
+ xInterface = xInterface->next;\r
+ }\r
+\r
+ /* Open the selected interface. */\r
+ pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */\r
+ UIP_CONF_BUFFER_SIZE, /* The size of the packet to capture. */\r
+ PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscious mode as the MAC and \r
+ IP address is going to be "simulated", and \r
+ not be the real MAC and IP address. This allows\r
+ trafic to the simulated IP address to be routed\r
+ to uIP, and trafic to the real IP address to be\r
+ routed to the Windows TCP/IP stack. */\r
+ 0xfffffffL, /* The read time out. This is going to block\r
+ until data is available. */\r
+ NULL, /* No authentication is required as this is\r
+ not a remote capture session. */\r
+ cErrorBuffer \r
+ );\r
+ \r
+ if ( pxOpenedInterfaceHandle == NULL )\r
+ {\r
+ printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );\r
+ }\r
+ else\r
+ {\r
+ /* Configure the capture filter to allow blocking reads, and to filter \r
+ out packets that are not of interest to this demo. */\r
+ prvConfigureCaptureBehaviour();\r
+ }\r
+\r
+ /* The device list is no longer required. */\r
+ pcap_freealldevs( pxAllNetworkInterfaces );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvConfigureCaptureBehaviour( void )\r
+{\r
+struct bpf_program xFilterCode;\r
+const long lMinBytesToCopy = 10L, lBlocking = 0L;\r
+unsigned long ulNetMask;\r
+\r
+ /* Unblock a read as soon as anything is received. */\r
+ pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );\r
+\r
+ /* Allow blocking. */\r
+ pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );\r
+\r
+ /* Set up a filter so only the packets of interest are passed to the uIP\r
+ stack. cErrorBuffer is used for convenience to create the string. Don't\r
+ confuse this with an error message. */\r
+ sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
+\r
+ ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;\r
+\r
+ if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )\r
+ {\r
+ printf("\r\nThe packet filter string is invalid\r\n" );\r
+ }\r
+ else\r
+ { \r
+ if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
+ {\r
+ printf( "\r\nAn error occurred setting the packet filter.\r\n" );\r
+ }\r
+ }\r
+\r
+ /* Create a task that simulates an interrupt in a real system. This will\r
+ block waiting for packets, then send a message to the uIP task when data\r
+ is available. */\r
+ xTaskCreate( prvInterruptSimulator, ( signed char * ) "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInterruptSimulator( void *pvParameters )\r
+{\r
+static struct pcap_pkthdr *pxHeader;\r
+const unsigned char *pucPacketData;\r
+extern QueueHandle_t xEMACEventQueue;\r
+const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
+long lResult;\r
+\r
+ /* Just to kill the compiler warning. */\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* Get the next packet. */\r
+ lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );\r
+ if( lResult )\r
+ {\r
+ /* Is the next buffer into which data should be placed free? */\r
+ if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )\r
+ {\r
+ /* Copy the data from the captured packet into the buffer. */\r
+ memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );\r
+\r
+ /* Note the amount of data that was copied. */\r
+ lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;\r
+\r
+ /* Move onto the next buffer, wrapping around if necessary. */\r
+ ucNextBufferToFill++;\r
+ if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )\r
+ {\r
+ ucNextBufferToFill = 0U;\r
+ }\r
+\r
+ /* Data was received and stored. Send a message to the uIP task\r
+ to let it know. */\r
+ xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );\r
+ }\r
+ }\r
+ }\r
+}\r
+\r