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