]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/WinPCap/arch.c
b55a38ffea0dffe2a41d976a01ba266afb042d0d
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator / WinPCap / arch.c
1 /*\r
2     FreeRTOS V7.4.1 - Copyright (C) 2013 Real Time Engineers Ltd.\r
3 \r
4     FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME.  PLEASE VISIT\r
5     http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
10      *    Complete, revised, and edited pdf reference manuals are also       *\r
11      *    available.                                                         *\r
12      *                                                                       *\r
13      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
14      *    ensuring you get running as quickly as possible and with an        *\r
15      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
16      *    the FreeRTOS project to continue with its mission of providing     *\r
17      *    professional grade, cross platform, de facto standard solutions    *\r
18      *    for microcontrollers - completely free of charge!                  *\r
19      *                                                                       *\r
20      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
21      *                                                                       *\r
22      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
23      *                                                                       *\r
24     ***************************************************************************\r
25 \r
26 \r
27     This file is part of the FreeRTOS distribution.\r
28 \r
29     FreeRTOS is free software; you can redistribute it and/or modify it under\r
30     the terms of the GNU General Public License (version 2) as published by the\r
31     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
32 \r
33     >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to\r
34     distribute a combined work that includes FreeRTOS without being obliged to\r
35     provide the source code for proprietary components outside of the FreeRTOS\r
36     kernel.\r
37 \r
38     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
39     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
40     FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
41     details. You should have received a copy of the GNU General Public License\r
42     and the FreeRTOS license exception along with FreeRTOS; if not it can be\r
43     viewed here: http://www.freertos.org/a00114.html and also obtained by\r
44     writing to Real Time Engineers Ltd., contact details for whom are available\r
45     on the FreeRTOS WEB site.\r
46 \r
47     1 tab == 4 spaces!\r
48 \r
49     ***************************************************************************\r
50      *                                                                       *\r
51      *    Having a problem?  Start by reading the FAQ "My application does   *\r
52      *    not run, what could be wrong?"                                     *\r
53      *                                                                       *\r
54      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
55      *                                                                       *\r
56     ***************************************************************************\r
57 \r
58 \r
59     http://www.FreeRTOS.org - Documentation, books, training, latest versions, \r
60     license and Real Time Engineers Ltd. contact details.\r
61 \r
62     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
63     including FreeRTOS+Trace - an indispensable productivity tool, and our new\r
64     fully thread aware and reentrant UDP/IP stack.\r
65 \r
66     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High \r
67     Integrity Systems, who sell the code with commercial support, \r
68     indemnification and middleware, under the OpenRTOS brand.\r
69     \r
70     http://www.SafeRTOS.com - High Integrity Systems also provide a safety \r
71     engineered and independently SIL3 certified version for use in safety and \r
72     mission critical applications that require provable dependability.\r
73 */\r
74 \r
75 /* WinPCap includes. */\r
76 #include "pcap.h"\r
77 #include "remote-ext.h"\r
78 \r
79 /* uIP includes. */\r
80 #include "net/uip.h"\r
81 #include "net/uip_arp.h"\r
82 #include "net/clock-arch.h"\r
83 \r
84 /* FreeRTOS includes. */\r
85 #include "FreeRTOS.h"\r
86 #include "task.h"\r
87 #include "queue.h"\r
88 \r
89 /*\r
90  * Query the computer the simulation is being executed on to find the network\r
91  * interfaces it has installed.\r
92  */\r
93 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );\r
94 \r
95 /*\r
96  * Open the network interface.  The number of the interface to be opened is set\r
97  * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
98  */\r
99 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );\r
100 \r
101 /*\r
102  * Configure the capture filter to allow blocking reads, and to filter out\r
103  * packets that are not of interest to this demo.\r
104  */\r
105 static void prvConfigureCaptureBehaviour( void );\r
106 \r
107 pcap_t *pxOpenedInterfaceHandle = NULL;\r
108 LARGE_INTEGER freq, sys_start_time;\r
109 \r
110 #define archNUM_BUFFERS 5\r
111 #define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )\r
112 \r
113 static void prvInterruptSimulator( void *pvParameters );\r
114 \r
115 static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];\r
116 static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];\r
117 \r
118 static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };\r
119 static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;\r
120 \r
121 unsigned char *uip_buf = NULL;\r
122 char cErrorBuffer[PCAP_ERRBUF_SIZE];\r
123 \r
124 void vNetifTx( void )\r
125 {\r
126         pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
127         pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
128 }\r
129 /*-----------------------------------------------------------*/\r
130 \r
131 unsigned portBASE_TYPE uxNetifRx( void )\r
132 {\r
133 unsigned portBASE_TYPE xDataLen;\r
134 unsigned char *pucTemp;\r
135 \r
136         /* Check there is really data available. */\r
137         xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];\r
138         if( xDataLen != 0L )\r
139         {\r
140 \r
141                 /* The buffer pointed to by uip_buf is going to change.  Remember which\r
142                 buffer uip_buf is currently pointing to. */\r
143                 pucTemp = uip_buf;\r
144 \r
145                 /* Point uip_buf at the next buffer that contains data. */\r
146                 uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];\r
147 \r
148                 /* The buffer pointed to by \r
149                 pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by\r
150                 uip_buf, but the buffer uip_buf was pointing to on entry to this\r
151                 function is free.  Set \r
152                 pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free \r
153                 buffer. */\r
154                 pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;\r
155                 lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;\r
156 \r
157                 ucNextBufferToProcess++;\r
158                 if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )\r
159                 {\r
160                         ucNextBufferToProcess = 0L;\r
161                 }\r
162         }\r
163 \r
164         return xDataLen;\r
165 }\r
166 /*-----------------------------------------------------------*/\r
167 \r
168 portBASE_TYPE xNetifInit( void )\r
169 {\r
170 portBASE_TYPE x;\r
171 pcap_if_t *pxAllNetworkInterfaces;\r
172 \r
173         /* Allocate a free buffer to each buffer pointer. */\r
174         for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )\r
175         {\r
176                 pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );\r
177         }\r
178 \r
179         /* Start with uip_buf pointing to a buffer that is not referenced from the\r
180         pucEthernetBufferPointers[] array. */\r
181         uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );\r
182 \r
183         /* Query the computer the simulation is being executed on to find the \r
184         network interfaces it has installed. */\r
185         pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();\r
186         \r
187         /* Open the network interface.  The number of the interface to be opened is \r
188         set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
189         Calling this function will set the pxOpenedInterfaceHandle variable.  If,\r
190         after calling this function, pxOpenedInterfaceHandle is equal to NULL, then\r
191         the interface could not be opened. */\r
192         if( pxAllNetworkInterfaces != NULL )\r
193         {\r
194                 prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );\r
195         }\r
196         \r
197 \r
198         return x;\r
199 }\r
200 /*-----------------------------------------------------------*/\r
201 \r
202 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
203 {    \r
204 pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
205 long lInterfaceNumber = 1;\r
206 \r
207     if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
208     {\r
209         printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );\r
210         pxAllNetworkInterfaces = NULL;\r
211     }\r
212 \r
213         if( pxAllNetworkInterfaces != NULL )\r
214         {\r
215                 /* Print out the list of network interfaces.  The first in the list\r
216                 is interface '1', not interface '0'. */\r
217                 for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )\r
218                 {\r
219                         printf( "%d. %s", lInterfaceNumber, xInterface->name );\r
220                         \r
221                         if( xInterface->description != NULL )\r
222                         {\r
223                                 printf( " (%s)\r\n", xInterface->description );\r
224                         }\r
225                         else\r
226                         {\r
227                                 printf( " (No description available)\r\n") ;\r
228                         }\r
229                         \r
230                         lInterfaceNumber++;\r
231                 }\r
232         }\r
233 \r
234     if( lInterfaceNumber == 1 )\r
235     {\r
236                 /* The interface number was never incremented, so the above for() loop\r
237                 did not execute meaning no interfaces were found. */\r
238         printf( " \r\nNo network interfaces were found.\r\n" );\r
239         pxAllNetworkInterfaces = NULL;\r
240     }\r
241 \r
242         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
243         printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );\r
244         \r
245     if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )\r
246     {\r
247         printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );\r
248                 \r
249                 if( pxAllNetworkInterfaces != NULL )\r
250                 {\r
251                         /* Free the device list, as no devices are going to be opened. */\r
252                         pcap_freealldevs( pxAllNetworkInterfaces );\r
253                         pxAllNetworkInterfaces = NULL;\r
254                 }\r
255     }\r
256 \r
257         return pxAllNetworkInterfaces;\r
258 }\r
259 /*-----------------------------------------------------------*/\r
260 \r
261 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
262 {\r
263 pcap_if_t *xInterface;\r
264 long x;\r
265 \r
266     /* Walk the list of devices until the selected device is located. */\r
267         xInterface = pxAllNetworkInterfaces;\r
268     for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )\r
269         {\r
270                 xInterface = xInterface->next;\r
271         }\r
272 \r
273     /* Open the selected interface. */\r
274         pxOpenedInterfaceHandle = pcap_open(    xInterface->name,               /* The name of the selected interface. */\r
275                                                                                         UIP_CONF_BUFFER_SIZE,           /* The size of the packet to capture. */\r
276                                                                                         PCAP_OPENFLAG_PROMISCUOUS,      /* Open in promiscious mode as the MAC and \r
277                                                                                                                                                 IP address is going to be "simulated", and \r
278                                                                                                                                                 not be the real MAC and IP address.  This allows\r
279                                                                                                                                                 trafic to the simulated IP address to be routed\r
280                                                                                                                                                 to uIP, and trafic to the real IP address to be\r
281                                                                                                                                                 routed to the Windows TCP/IP stack. */\r
282                                                                                         0xfffffffL,                     /* The read time out.  This is going to block\r
283                                                                                                                                                 until data is available. */\r
284                                                                                         NULL,                                   /* No authentication is required as this is\r
285                                                                                                                                                 not a remote capture session. */\r
286                                                                                         cErrorBuffer            \r
287                                                                            );\r
288                                                                            \r
289     if ( pxOpenedInterfaceHandle == NULL )\r
290     {\r
291         printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );\r
292     }\r
293         else\r
294         {\r
295                 /* Configure the capture filter to allow blocking reads, and to filter \r
296                 out packets that are not of interest to this demo. */\r
297                 prvConfigureCaptureBehaviour();\r
298         }\r
299 \r
300         /* The device list is no longer required. */\r
301         pcap_freealldevs( pxAllNetworkInterfaces );\r
302 }\r
303 /*-----------------------------------------------------------*/\r
304 \r
305 static void prvConfigureCaptureBehaviour( void )\r
306 {\r
307 struct bpf_program xFilterCode;\r
308 const long lMinBytesToCopy = 10L, lBlocking = 0L;\r
309 unsigned long ulNetMask;\r
310 \r
311         /* Unblock a read as soon as anything is received. */\r
312         pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );\r
313 \r
314         /* Allow blocking. */\r
315         pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );\r
316 \r
317         /* Set up a filter so only the packets of interest are passed to the uIP\r
318         stack.  cErrorBuffer is used for convenience to create the string.  Don't\r
319         confuse this with an error message. */\r
320         sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
321 \r
322         ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;\r
323 \r
324         if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )\r
325     {\r
326         printf("\r\nThe packet filter string is invalid\r\n" );\r
327     }\r
328         else\r
329         {    \r
330                 if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
331                 {\r
332                         printf( "\r\nAn error occurred setting the packet filter.\r\n" );\r
333                 }\r
334         }\r
335 \r
336         /* Create a task that simulates an interrupt in a real system.  This will\r
337         block waiting for packets, then send a message to the uIP task when data\r
338         is available. */\r
339         xTaskCreate( prvInterruptSimulator, ( signed char * ) "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );\r
340 }\r
341 /*-----------------------------------------------------------*/\r
342 \r
343 static void prvInterruptSimulator( void *pvParameters )\r
344 {\r
345 static struct pcap_pkthdr *pxHeader;\r
346 const unsigned char *pucPacketData;\r
347 extern xQueueHandle xEMACEventQueue;\r
348 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
349 long lResult;\r
350 \r
351         /* Just to kill the compiler warning. */\r
352         ( void ) pvParameters;\r
353 \r
354         for( ;; )\r
355         {\r
356                 /* Get the next packet. */\r
357                 lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );\r
358                 if( lResult )\r
359                 {\r
360                         /* Is the next buffer into which data should be placed free? */\r
361                         if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )\r
362                         {\r
363                                 /* Copy the data from the captured packet into the buffer. */\r
364                                 memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );\r
365 \r
366                                 /* Note the amount of data that was copied. */\r
367                                 lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;\r
368 \r
369                                 /* Move onto the next buffer, wrapping around if necessary. */\r
370                                 ucNextBufferToFill++;\r
371                                 if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )\r
372                                 {\r
373                                         ucNextBufferToFill = 0U;\r
374                                 }\r
375 \r
376                                 /* Data was received and stored.  Send a message to the uIP task\r
377                                 to let it know. */\r
378                                 xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );\r
379                         }\r
380                 }\r
381         }\r
382 }\r
383 \r