Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pcap_driver.c Source File

pcap_driver.c

Go to the documentation of this file.
00001 /**
00002  * @file pcap_driver.c
00003  * @brief PCAP driver
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "core/net.h"
00034 #include "drivers/pcap_driver.h"
00035 #include "debug.h"
00036 
00037 //Undefine conflicting definitions
00038 #undef Socket
00039 #undef htons
00040 #undef htonl
00041 #undef ntohs
00042 #undef ntohl
00043 
00044 //PCAP dependencies
00045 #include <pcap.h>
00046 
00047 //Undefine conflicting definitions
00048 #undef interface
00049 
00050 
00051 /**
00052  * @brief Packet descriptor
00053  **/
00054 
00055 typedef struct
00056 {
00057    size_t length;
00058    uint8_t data[PCAP_DRIVER_MAX_PACKET_SIZE];
00059 } PcapDriverPacket;
00060 
00061 
00062 /**
00063  * @brief PCAP driver context
00064  **/
00065 
00066 typedef struct
00067 {
00068    pcap_t *handle;
00069    uint_t writeIndex;
00070    uint_t readIndex;
00071    PcapDriverPacket queue[PCAP_DRIVER_QUEUE_SIZE];
00072 } PcapDriverContext;
00073 
00074 
00075 /**
00076  * @brief PCAP driver
00077  **/
00078 
00079 const NicDriver pcapDriver =
00080 {
00081    NIC_TYPE_ETHERNET,
00082    ETH_MTU,
00083    pcapDriverInit,
00084    pcapDriverTick,
00085    pcapDriverEnableIrq,
00086    pcapDriverDisableIrq,
00087    pcapDriverEventHandler,
00088    pcapDriverSendPacket,
00089    pcapDriverSetMulticastFilter,
00090    NULL,
00091    NULL,
00092    NULL,
00093    TRUE,
00094    TRUE,
00095    TRUE,
00096    TRUE
00097 };
00098 
00099 
00100 /**
00101  * @brief PCAP driver initialization
00102  * @param[in] interface Underlying network interface
00103  * @return Error code
00104  **/
00105 
00106 error_t pcapDriverInit(NetInterface *interface)
00107 {
00108    int_t ret;
00109    uint_t i;
00110    uint_t j;
00111    pcap_if_t *device;
00112    pcap_if_t *deviceList;
00113    struct bpf_program filerCode;
00114    char_t filterExpr[256];
00115    char_t errorBuffer[PCAP_ERRBUF_SIZE];
00116    PcapDriverContext *context;
00117 #if (NET_RTOS_SUPPORT == ENABLED)
00118    OsTask *task;
00119 #endif
00120 
00121    //Debug message
00122    TRACE_INFO("Initializing PCAP driver...\r\n");
00123 
00124    //Allocate PCAP driver context
00125    context = (PcapDriverContext *) malloc(sizeof(PcapDriverContext));
00126 
00127    //Failed to allocate memory?
00128    if(context == NULL)
00129    {
00130       //Debug message
00131       printf("Failed to allocate context!\r\n");
00132 
00133       //Report an error
00134       return ERROR_FAILURE;
00135    }
00136 
00137    //Attach the PCAP driver context to the network interface
00138    *((PcapDriverContext **) interface->nicContext) = context;
00139    //Clear PCAP driver context
00140    memset(context, 0, sizeof(PcapDriverContext));
00141 
00142    //Find all the devices
00143    ret = pcap_findalldevs(&deviceList, errorBuffer);
00144 
00145    //Any error to report?
00146    if(ret != 0)
00147    {
00148       //Debug message
00149       printf("Failed to list devices!\r\n");
00150 
00151       //Clean up side effects
00152       free(context);
00153 
00154       //Report an error
00155       return ERROR_FAILURE;
00156    }
00157 
00158    //No network adapter found?
00159    if(deviceList == NULL)
00160    {
00161       //Debug message
00162       printf("No network adapter found!\r\n");
00163 
00164       //Clean up side effects
00165       free(context);
00166 
00167       //Exit immediately
00168       return ERROR_FAILURE;
00169    }
00170 
00171    //Network adapter selection
00172    while(1)
00173    {
00174       //Debug message
00175       printf("Network adapters:\r\n");
00176 
00177       //Point to the first device
00178       device = deviceList;
00179       i = 0;
00180 
00181       //Loop through the list of devices
00182       while(device != NULL)
00183       {
00184          //Index of the current network adapter
00185          printf("  %-2u", i + 1);
00186 
00187 #if !defined(_WIN32)
00188          //Display the name of the device
00189          if(device->name != NULL)
00190             printf(" %-8s", device->name);
00191 #endif
00192          //Description of the device
00193          if(device->description != NULL)
00194             printf(" %s\r\n", device->description);
00195          else
00196             printf(" -\r\n");
00197 
00198          //Next device
00199          device = device->next;
00200          i++;
00201       }
00202 
00203       //Display message
00204       printf("Select network adapter for %s interface (1-%u):", interface->name, i);
00205       //Get user choice
00206       scanf("%d", &j);
00207 
00208       //Valid selection?
00209       if(j >= 1 && j <= i)
00210          break;
00211    }
00212 
00213    //Point to the first device
00214    device = deviceList;
00215 
00216    //Point to the desired network adapter
00217    for(i = 1; i < j; i++)
00218       device = device->next;
00219 
00220    //Open the device
00221    context->handle = pcap_open_live(device->name, 65535,
00222       TRUE, PCAP_DRIVER_TIMEOUT, errorBuffer);
00223 
00224    //Failed to open device?
00225    if(context->handle == NULL)
00226    {
00227       //Debug message
00228       printf("Failed to open device!\r\n");
00229 
00230       //Clean up side effects
00231       pcap_freealldevs(deviceList);
00232       free(context);
00233 
00234       //Report an error
00235       return ERROR_FAILURE;
00236    }
00237 
00238    //Free the device list
00239    pcap_freealldevs(deviceList);
00240 
00241    //Filter expression
00242    sprintf(filterExpr, "!(ether src %02x:%02x:%02x:%02x:%02x:%02x) && "
00243       "((ether dst %02x:%02x:%02x:%02x:%02x:%02x) || (ether broadcast) || (ether multicast))",
00244       interface->macAddr.b[0], interface->macAddr.b[1], interface->macAddr.b[2],
00245       interface->macAddr.b[3], interface->macAddr.b[4], interface->macAddr.b[5],
00246       interface->macAddr.b[0], interface->macAddr.b[1], interface->macAddr.b[2],
00247       interface->macAddr.b[3], interface->macAddr.b[4], interface->macAddr.b[5]);
00248 
00249    //Compile the filter
00250    ret = pcap_compile(context->handle, &filerCode, filterExpr, 1, 0);
00251 
00252    //Failed to open device?
00253    if(ret != 0)
00254    {
00255       //Debug message
00256       printf("Failed to compile filter!\r\n");
00257 
00258       //Clean up side effects
00259       pcap_close(context->handle);
00260       free(context);
00261 
00262       //Report an error
00263       return ERROR_FAILURE;
00264    }
00265 
00266    //Set the filter
00267    ret = pcap_setfilter(context->handle, &filerCode);
00268 
00269    //Failed to open device?
00270    if(ret != 0)
00271    {
00272       //Debug message
00273       printf("Failed to set filter!\r\n");
00274 
00275       //Clean up side effects
00276       pcap_close(context->handle);
00277       free(context);
00278 
00279       //Report an error
00280       return ERROR_FAILURE;
00281    }
00282 
00283 #if (NET_RTOS_SUPPORT == ENABLED)
00284    //Create the receive task
00285    task = osCreateTask("PCAP", pcapDriverTask, interface, 0, 0);
00286 
00287    //Failed to create the task?
00288    if(task == OS_INVALID_HANDLE)
00289    {
00290       //Debug message
00291       printf("Failed to create task!\r\n");
00292 
00293       //Clean up side effects
00294       pcap_close(context->handle);
00295       free(context);
00296 
00297       //Report an error
00298       return ERROR_FAILURE;
00299    }
00300 #endif
00301 
00302    //Accept any packets from the upper layer
00303    osSetEvent(&interface->nicTxEvent);
00304 
00305    //Return status code
00306    return NO_ERROR;
00307 }
00308 
00309 
00310 /**
00311  * @brief PCAP timer handler
00312  *
00313  * This routine is periodically called by the TCP/IP stack to
00314  * handle periodic operations such as polling the link state
00315  *
00316  * @param[in] interface Underlying network interface
00317  **/
00318 
00319 void pcapDriverTick(NetInterface *interface)
00320 {
00321    //Not implemented
00322 }
00323 
00324 
00325 /**
00326  * @brief Enable interrupts
00327  * @param[in] interface Underlying network interface
00328  **/
00329 
00330 void pcapDriverEnableIrq(NetInterface *interface)
00331 {
00332    //Not implemented
00333 }
00334 
00335 
00336 /**
00337  * @brief Disable interrupts
00338  * @param[in] interface Underlying network interface
00339  **/
00340 
00341 void pcapDriverDisableIrq(NetInterface *interface)
00342 {
00343    //Not implemented
00344 }
00345 
00346 
00347 /**
00348  * @brief PCAP event handler
00349  * @param[in] interface Underlying network interface
00350  **/
00351 
00352 void pcapDriverEventHandler(NetInterface *interface)
00353 {
00354    uint_t n;
00355    PcapDriverContext *context;
00356 
00357    //Point to the PCAP driver context
00358    context = *((PcapDriverContext **) interface->nicContext);
00359 
00360    //Process all pending packets
00361    while(context->queue[context->readIndex].length > 0)
00362    {
00363       //Pass the packet to the upper layer
00364       nicProcessPacket(interface, context->queue[context->readIndex].data,
00365          context->queue[context->readIndex].length);
00366 
00367       //Compute the index of the next packet descriptor
00368       n = (context->readIndex + 1) % PCAP_DRIVER_QUEUE_SIZE;
00369 
00370       //Release the current packet
00371       context->queue[context->readIndex].length = 0;
00372       //Point to the next packet descriptor
00373       context->readIndex = n;
00374    }
00375 }
00376 
00377 
00378 /**
00379  * @brief Send a packet
00380  * @param[in] interface Underlying network interface
00381  * @param[in] buffer Multi-part buffer containing the data to send
00382  * @param[in] offset Offset to the first data byte
00383  * @return Error code
00384  **/
00385 
00386 error_t pcapDriverSendPacket(NetInterface *interface,
00387    const NetBuffer *buffer, size_t offset)
00388 {
00389    int_t ret;
00390    size_t length;
00391    PcapDriverContext *context;
00392    uint8_t temp[PCAP_DRIVER_MAX_PACKET_SIZE];
00393 
00394    //Point to the PCAP driver context
00395    context = *((PcapDriverContext **) interface->nicContext);
00396 
00397    //Retrieve the length of the packet
00398    length = netBufferGetLength(buffer) - offset;
00399 
00400    //Check the frame length
00401    if(length > PCAP_DRIVER_MAX_PACKET_SIZE)
00402    {
00403       //The transmitter can accept another packet
00404       osSetEvent(&interface->nicTxEvent);
00405       //Report an error
00406       return ERROR_INVALID_LENGTH;
00407    }
00408 
00409    //Copy the packet to the transmit buffer
00410    netBufferRead(temp, buffer, offset, length);
00411 
00412    //Send packet
00413    ret = pcap_sendpacket(context->handle, temp, length);
00414 
00415    //The transmitter can accept another packet
00416    osSetEvent(&interface->nicTxEvent);
00417 
00418    //Return status code
00419    if(ret < 0)
00420       return ERROR_FAILURE;
00421    else
00422      return NO_ERROR;
00423 }
00424 
00425 
00426 /**
00427  * @brief Configure multicast MAC address filtering
00428  * @param[in] interface Underlying network interface
00429  * @return Error code
00430  **/
00431 
00432 error_t pcapDriverSetMulticastFilter(NetInterface *interface)
00433 {
00434    //Not implemented
00435    return NO_ERROR;
00436 }
00437 
00438 
00439 /**
00440  * @brief PCAP receive task
00441  * @param[in] interface Underlying network interface
00442  **/
00443 
00444 void pcapDriverTask(NetInterface *interface)
00445 {
00446    int_t ret;
00447    uint_t n;
00448    uint_t length;
00449    const uint8_t *data;
00450    struct pcap_pkthdr *header;
00451    PcapDriverContext *context;
00452 
00453    //Point to the PCAP driver context
00454    context = *((PcapDriverContext **) interface->nicContext);
00455 
00456    //Process events
00457    while(1)
00458    {
00459       //Wait for an incoming packet
00460       ret = pcap_next_ex(context->handle, &header, &data);
00461 
00462       //Any packet received?
00463       if(ret > 0)
00464       {
00465          //Retrieve the length of the packet
00466          length = header->caplen;
00467 
00468          //Check the length of the received packet
00469          if(length > 0 && length < PCAP_DRIVER_MAX_PACKET_SIZE)
00470          {
00471             //Check whether the link is up
00472             if(interface->linkState)
00473             {
00474                //Compute the index of the next packet descriptor
00475                n = (context->writeIndex + 1) % PCAP_DRIVER_QUEUE_SIZE;
00476 
00477                //Ensure the receive queue is not full
00478                if(n != context->readIndex)
00479                {
00480                   //Copy the incoming packet
00481                   memcpy(context->queue[context->writeIndex].data, data, length);
00482                   //Save the length of the packet
00483                   context->queue[context->writeIndex].length = length;
00484 
00485                   //Point to the next packet descriptor
00486                   context->writeIndex = n;
00487 
00488                   //Set event flag
00489                   interface->nicEvent = TRUE;
00490                   //Notify the TCP/IP stack of the event
00491                   osSetEvent(&netEvent);
00492                }
00493             }
00494          }
00495       }
00496       else
00497       {
00498 #if (NET_RTOS_SUPPORT == DISABLED)
00499          //No packet has been received
00500          break;
00501 #endif
00502       }
00503    }
00504 }
00505