diff options
Diffstat (limited to 'FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/NetworkInterface_WinPCap.c')
-rw-r--r-- | FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/NetworkInterface_WinPCap.c | 272 |
1 files changed, 252 insertions, 20 deletions
diff --git a/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/NetworkInterface_WinPCap.c b/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/NetworkInterface_WinPCap.c index d27976a14..fe4b12f5e 100644 --- a/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/NetworkInterface_WinPCap.c +++ b/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/NetworkInterface_WinPCap.c @@ -39,6 +39,9 @@ #include "FreeRTOS_IP.h" #include "FreeRTOS_IP_Private.h" #include "NetworkBufferManagement.h" +#if defined( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 ) + #include "FreeRTOS_Routing.h" +#endif /* Thread-safe circular buffers are being used to pass data to and from the PCAP * access functions. */ @@ -150,9 +153,31 @@ static StreamBuffer_t * xRecvBuffer = NULL; /* Logs the number of WinPCAP send failures, for viewing in the debugger only. */ static volatile uint32_t ulWinPCAPSendFailures = 0; +#if defined( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 ) +/* + * A pointer to the network interface is needed later when receiving packets. + */ + static NetworkInterface_t * pxMyInterface; + + extern NetworkEndPoint_t * pxGetEndpoint( BaseType_t xIPType ); + + static BaseType_t xWinPcap_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); + static BaseType_t xWinPcap_NetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ); + static BaseType_t xWinPcap_GetPhyLinkStatus( NetworkInterface_t * pxInterface ); + + NetworkInterface_t * pxWinPcap_FillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ); +#endif + /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceInitialise( void ) +#if defined( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 ) + static BaseType_t xWinPcap_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) +#else + BaseType_t xNetworkInterfaceInitialise( void ) +#endif { BaseType_t xReturn = pdFALSE; pcap_if_t * pxAllNetworkInterfaces; @@ -257,8 +282,14 @@ static size_t prvStreamBufferAdd( StreamBuffer_t * pxBuffer, /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, - BaseType_t bReleaseAfterSend ) +#if defined( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 ) + static BaseType_t xWinPcap_NetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ) +#else + BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ) +#endif { size_t xSpace; @@ -298,6 +329,51 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkB } /*-----------------------------------------------------------*/ +#if defined( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 ) + + static BaseType_t xWinPcap_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) + { + BaseType_t xResult = pdFALSE; + + ( void ) pxInterface; + + if( pxOpenedInterfaceHandle != NULL ) + { + xResult = pdTRUE; + } + + return xResult; + } + + /*-----------------------------------------------------------*/ + + NetworkInterface_t * pxWinPcap_FillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) + { + static char pcName[ 17 ]; + + /* This function pxWinPcap_FillInterfaceDescriptor() adds a network-interface. + * Make sure that the object pointed to by 'pxInterface' + * is declared static or global, and that it will continue to exist. */ + + pxMyInterface = pxInterface; + + snprintf( pcName, sizeof( pcName ), "eth%ld", xEMACIndex ); + + memset( pxInterface, '\0', sizeof( *pxInterface ) ); + pxInterface->pcName = pcName; /* Just for logging, debugging. */ + pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has only meaning for the driver functions. */ + pxInterface->pfInitialise = xWinPcap_NetworkInterfaceInitialise; + pxInterface->pfOutput = xWinPcap_NetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = xWinPcap_GetPhyLinkStatus; + + FreeRTOS_AddNetworkInterface( pxInterface ); + + return pxInterface; + } +#endif +/*-----------------------------------------------------------*/ + static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ) { pcap_if_t * pxAllNetworkInterfaces = NULL, * xInterface; @@ -321,7 +397,7 @@ static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ) { /* Print out the list of network interfaces. The first in the list * is interface '1', not interface '0'. */ - for(xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next) + for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next ) { /* The descriptions of the devices can be full of spaces, clean them * a little. printf() can only be used here because the network is not @@ -416,7 +492,7 @@ static void prvOpenSelectedNetworkInterface( pcap_if_t * pxAllNetworkInterfaces /* Walk the list of devices until the selected device is located. */ pxInterface = pxAllNetworkInterfaces; - for(x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++) + for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ ) { pxInterface = pxInterface->next; } @@ -592,26 +668,69 @@ DWORD WINAPI prvWinPcapSendThread( void * pvParam ) } /*-----------------------------------------------------------*/ -static BaseType_t xPacketBouncedBack( const uint8_t * pucBuffer ) -{ - EthernetHeader_t * pxEtherHeader; - BaseType_t xResult; - - pxEtherHeader = ( EthernetHeader_t * ) pucBuffer; +#if defined ( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 ) - /* Sometimes, packets are bounced back by the driver and we need not process them. Check - * whether this packet is one such packet. */ - if( memcmp( ipLOCAL_MAC_ADDRESS, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + static BaseType_t xPacketBouncedBack( const uint8_t * pucBuffer ) { - xResult = pdTRUE; + static BaseType_t xHasWarned = pdFALSE; + EthernetHeader_t * pxEtherHeader; + NetworkEndPoint_t * pxEndPoint; + BaseType_t xResult = pdFALSE; + + pxEtherHeader = ( EthernetHeader_t * ) pucBuffer; + + /* Sometimes, packets are bounced back by the driver and we need not process them. Check + * whether this packet is one such packet. */ + for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL ); + pxEndPoint != NULL; + pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) ) + { + if( memcmp( pxEndPoint->xMACAddress.ucBytes, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + { + if( xHasWarned == pdFALSE ) + { + xHasWarned = pdTRUE; + FreeRTOS_printf( ( "Bounced back by WinPCAP interface: %02x:%02x:%02x:%02x:%02x:%02x\n", + pxEndPoint->xMACAddress.ucBytes[ 0 ], + pxEndPoint->xMACAddress.ucBytes[ 1 ], + pxEndPoint->xMACAddress.ucBytes[ 2 ], + pxEndPoint->xMACAddress.ucBytes[ 3 ], + pxEndPoint->xMACAddress.ucBytes[ 4 ], + pxEndPoint->xMACAddress.ucBytes[ 5 ] ) ); + } + + xResult = pdTRUE; + break; + } + } + + return xResult; } - else + +#else + + static BaseType_t xPacketBouncedBack( const uint8_t * pucBuffer ) { - xResult = pdFALSE; + EthernetHeader_t * pxEtherHeader; + BaseType_t xResult = pdFALSE; + + pxEtherHeader = ( EthernetHeader_t * ) pucBuffer; + + /* Sometimes, packets are bounced back by the driver and we need not process them. Check + * whether this packet is one such packet. */ + if( memcmp( ipLOCAL_MAC_ADDRESS, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + { + xResult = pdTRUE; + } + else + { + xResult = pdFALSE; + } + + return xResult; } - return xResult; -} +#endif /*-----------------------------------------------------------*/ static void prvInterruptSimulatorTask( void * pvParameters ) @@ -684,6 +803,117 @@ static void prvInterruptSimulatorTask( void * pvParameters ) if( pxNetworkBuffer != NULL ) { xRxEvent.pvData = ( void * ) pxNetworkBuffer; + #if defined ( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 ) + pxNetworkBuffer->pxInterface = pxMyInterface; + pxNetworkBuffer->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxNetworkBuffer->pucEthernetBuffer ); + + { + char pcDescription[ 129 ] = "unknown"; + const EthernetHeader_t * pxEthernetHeader = ( ( const EthernetHeader_t * ) pxNetworkBuffer->pucEthernetBuffer ); + uint8_t ucType = ipTYPE_IPv4; + + switch( pxEthernetHeader->usFrameType ) + { + case ipARP_FRAME_TYPE: + { + const ProtocolPacket_t * pxPacket = ( ( const ProtocolPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); + snprintf( pcDescription, sizeof pcDescription, "ARP frame for %xip", + FreeRTOS_ntohl( pxPacket->xARPPacket.xARPHeader.ulTargetProtocolAddress ) ); + } + break; + + case ipPROTOCOL_ICMP: + snprintf( pcDescription, sizeof pcDescription, "ICMP frame" ); + break; + + case ipIPv4_FRAME_TYPE: + { + const IPPacket_t * pxIPPacket; + uint8_t ucProtocol; + pxIPPacket = ( const IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; + ucProtocol = pxIPPacket->xIPHeader.ucProtocol; + + if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP ) + { + const ProtocolHeaders_t * pxProtocolHeaders = ( ( const ProtocolHeaders_t * ) + &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizePacket( pxNetworkBuffer ) ] ) ); + uint32_t ulLocalIP, ulRemoteIP; + uint16_t usLocalPort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usDestinationPort ); + uint16_t usRemotePort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usSourcePort ); + const IPHeader_t * pxIPHeader; + pxIPHeader = ( ( const IPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) ); + ulLocalIP = FreeRTOS_htonl( pxIPHeader->ulDestinationIPAddress ); + ulRemoteIP = FreeRTOS_htonl( pxIPHeader->ulSourceIPAddress ); + + snprintf( pcDescription, sizeof pcDescription, "TCP v4 packet %xip port%u to %xip: port %u", + ulRemoteIP, usRemotePort, ulLocalIP, usLocalPort ); + } + else if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) + { + snprintf( pcDescription, sizeof pcDescription, "UDP v4 packet" ); + const UDPPacket_t * pxUDPPacket = ( ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); + + if( pxUDPPacket->xIPHeader.ulSourceIPAddress == 0x642c6276U ) + { + FreeRTOS_printf( ( "Received UDP packet from %xip\n", + ( unsigned ) ( FreeRTOS_htonl( pxUDPPacket->xIPHeader.ulSourceIPAddress ) ) ) ); + } + } + else + { + snprintf( pcDescription, sizeof pcDescription, "v4 packet protocol %02X", ucProtocol ); + } + } + break; + + case ipIPv6_FRAME_TYPE: + { + const IPHeader_IPv6_t * pxIPHeader_IPv6; + uint8_t ucProtocol; + + ucType = ipTYPE_IPv6; + pxIPHeader_IPv6 = ( const IPHeader_IPv6_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ); + + ucProtocol = pxIPHeader_IPv6->ucNextHeader; + + if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP ) + { + snprintf( pcDescription, sizeof pcDescription, "TCP v6 packet" ); + } + else if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) + { + snprintf( pcDescription, sizeof pcDescription, "UDP v6 packet" ); + } + else if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP_IPv6 ) + { + snprintf( pcDescription, sizeof pcDescription, "ICMP v6 packet" ); + } + else + { + snprintf( pcDescription, sizeof pcDescription, "v6 packet protocol %02X", ucProtocol ); + } + } + break; + + default: + snprintf( pcDescription, sizeof pcDescription, "Unknown frame %04x", pxEthernetHeader->usFrameType ); + break; + } + + if( pxNetworkBuffer->pxEndPoint == NULL ) + { + pxNetworkBuffer->pxEndPoint = pxGetEndpoint( ucType ); + + if( strncasecmp( "ARP", pcDescription, 3 ) != 0 ) + { + FreeRTOS_printf( ( "No end-point for \"%s\". Using 0x%p type IPv%d\n", + pcDescription, + pxNetworkBuffer->pxEndPoint, + ucType == ipTYPE_IPv6 ? 6 : 4 ) ); + } + } + } + #endif /* Data was received and stored. Send a message to * the IP task to let it know. */ @@ -757,6 +987,7 @@ static const char * prvRemoveSpaces( char * pcBuffer, return pcBuffer; } +/*-----------------------------------------------------------*/ #define BUFFER_SIZE ( ipTOTAL_ETHERNET_FRAME_SIZE + ipBUFFER_PADDING ) #define BUFFER_SIZE_ROUNDED_UP ( ( BUFFER_SIZE + 7 ) & ~0x07UL ) @@ -778,7 +1009,7 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB } else { - for(uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; uxIndex++) + for( uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; uxIndex++ ) { size_t uxOffset = uxIndex * BUFFER_SIZE_ROUNDED_UP; NetworkBufferDescriptor_t ** ppDescriptor; @@ -795,3 +1026,4 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB } } } +/*-----------------------------------------------------------*/ |