Example #1
0
error_t udpInvokeRxCallback(NetInterface *interface, const IpPseudoHeader *pseudoHeader,
                            const UdpHeader *header, const NetBuffer *buffer, size_t offset)
{
    uint_t i;
    void *params;
    UdpRxCallbackDesc *entry;

    //This flag tells whether a matching entry has been found
    bool_t found = FALSE;

    //Acquire exclusive access to the callback table
    osAcquireMutex(&udpCallbackMutex);

    //Loop through the table
    for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
    {
        //Point to the current entry
        entry = &udpCallbackTable[i];

        //Check whether the entry is currently in used
        if(entry->callback != NULL)
        {
            //Bound to a particular interface?
            if(entry->interface == NULL || entry->interface == interface)
            {
                //Does the specified port number match the current entry?
                if(entry->port == ntohs(header->destPort))
                {
                    //Retrieve callback parameters
                    params = entry->params;

                    //Release mutex to prevent any deadlock
                    if(params == NULL)
                        osReleaseMutex(&udpCallbackMutex);

                    //Invoke user callback function
                    entry->callback(interface, pseudoHeader,
                                    header, buffer, offset, params);

                    //Acquire mutex
                    if(params == NULL)
                        osAcquireMutex(&udpCallbackMutex);

                    //A matching entry was found
                    found = TRUE;
                }
            }
        }
    }

    //Release exclusive access to the callback table
    osReleaseMutex(&udpCallbackMutex);

    //Return status code
    return found ? NO_ERROR : ERROR_PORT_UNREACHABLE;
}
Example #2
0
error_t ipv4LeaveMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
{
   uint_t i;
   uint_t j;
   MacAddr macAddr;

   //Ensure the specified IPv4 address is a multicast address
   if(!ipv4IsMulticastAddr(groupAddr))
      return ERROR_INVALID_ADDRESS;

   //Acquire exclusive access to the IPv4 filter table
   osAcquireMutex(&interface->ipv4FilterMutex);

   //Loop through filter table entries
   for(i = 0; i < interface->ipv4FilterSize; i++)
   {
      //Specified IPv4 address found?
      if(interface->ipv4Filter[i].addr == groupAddr)
      {
         //Decrement the reference count
         interface->ipv4Filter[i].refCount--;

         //Remove the entry if the reference count drops to zero
         if(interface->ipv4Filter[i].refCount < 1)
         {
#if (IGMP_SUPPORT == ENABLED)
            //Report group membership termination
            igmpLeaveGroup(interface, &interface->ipv4Filter[i]);
#endif
            //Map the multicast IPv4 address to a MAC-layer address
            ipv4MapMulticastAddrToMac(groupAddr, &macAddr);

#if (ETH_SUPPORT == ENABLED)
            //Drop the corresponding address from the MAC filter table
            ethDropMulticastAddr(interface, &macAddr);
#endif
            //Adjust the size of the IPv4 filter table
            interface->ipv4FilterSize--;

            //Remove the corresponding entry
            for(j = i; j < interface->ipv4FilterSize; j++)
               interface->ipv4Filter[j] = interface->ipv4Filter[j + 1];
         }

         //Release exclusive access to the IPv4 filter table
         osReleaseMutex(&interface->ipv4FilterMutex);
         //No error to report
         return NO_ERROR;
      }
   }

   //Release exclusive access to the IPv4 filter table
   osReleaseMutex(&interface->ipv4FilterMutex);
   //The specified IPv4 address does not exist
   return ERROR_FAILURE;
}
Example #3
0
void dnsFlushCache(NetInterface *interface)
{
   uint_t i;
   DnsCacheEntry *entry;

   //Acquire exclusive access to the DNS cache
   osAcquireMutex(&dnsCacheMutex);

   //Go through DNS cache
   for(i = 0; i < DNS_CACHE_SIZE; i++)
   {
      //Point to the current entry
      entry = &dnsCache[i];

      //Check whether the entry is currently in used
      if(entry->state != DNS_STATE_NONE)
      {
         //Delete DNS entries only for the given network interface
         if(entry->interface == interface)
            dnsDeleteEntry(entry);
      }
   }

   //Release exclusive access to the DNS cache
   osReleaseMutex(&dnsCacheMutex);
}
Example #4
0
error_t socketListen(Socket *socket, uint_t backlog)
{
#if (TCP_SUPPORT == ENABLED)
   error_t error;

   //Make sure the socket handle is valid
   if(!socket)
      return ERROR_INVALID_PARAMETER;
   //This function shall be used with connection-oriented socket types
   if(socket->type != SOCKET_TYPE_STREAM)
      return ERROR_INVALID_SOCKET;

   //Enter critical section
   osAcquireMutex(&socketMutex);
   //Start listening for an incoming connection
   error = tcpListen(socket, backlog);
   //Leave critical section
   osReleaseMutex(&socketMutex);

   //Return status code
   return error;
#else
   return ERROR_NOT_IMPLEMENTED;
#endif
}
Example #5
0
error_t socketShutdown(Socket *socket, uint_t how)
{
#if (TCP_SUPPORT == ENABLED)
   error_t error;

   //Make sure the socket handle is valid
   if(!socket)
      return ERROR_INVALID_PARAMETER;
   //Make sure the socket type is correct
   if(socket->type != SOCKET_TYPE_STREAM)
      return ERROR_INVALID_SOCKET;
   //Check flags
   if((how != SOCKET_SD_SEND) && (how != SOCKET_SD_RECEIVE) && (how != SOCKET_SD_BOTH))
      return ERROR_INVALID_PARAMETER;

   //Enter critical section
   osAcquireMutex(&socketMutex);
   //Graceful shutdown
   error = tcpShutdown(socket, how);
   //Leave critical section
   osReleaseMutex(&socketMutex);

   //Return status code
   return error;
#else
   return ERROR_NOT_IMPLEMENTED;
#endif
}
Example #6
0
error_t udpReceiveDatagram(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort,
   IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
{
   SocketQueueItem *queueItem;

   //The receive queue is empty?
   if(!socket->receiveQueue)
   {
      //Set the events the application is interested in
      socket->eventMask = SOCKET_EVENT_RX_READY;
      //Reset the event object
      osResetEvent(&socket->event);
      //Leave critical section
      osReleaseMutex(&socketMutex);
      //Wait until an event is triggered
      osWaitForEvent(&socket->event, socket->timeout);
      //Enter critical section
      osAcquireMutex(&socketMutex);
   }

   //Check whether the read operation timed out
   if(!socket->receiveQueue)
   {
      //No data can be read
      *received = 0;
      //Report a timeout error
      return ERROR_TIMEOUT;
   }

   //Point to the first item in the receive queue
   queueItem = socket->receiveQueue;
   //Copy data to user buffer
   *received = chunkedBufferRead(data, queueItem->buffer, queueItem->offset, size);

   //Save the source IP address
   if(srcIpAddr)
      *srcIpAddr = queueItem->srcIpAddr;
   //Save the source port number
   if(srcPort)
      *srcPort = queueItem->srcPort;
   //Save the destination IP address
   if(destIpAddr)
      *destIpAddr = queueItem->destIpAddr;

   //If the SOCKET_FLAG_PEEK flag is set, the data is copied
   //into the buffer but is not removed from the input queue
   if(!(flags & SOCKET_FLAG_PEEK))
   {
      //Remove the item from the receive queue
      socket->receiveQueue = queueItem->next;
      //Deallocate memory buffer
      chunkedBufferFree(queueItem->buffer);
   }

   //Update the state of events
   udpUpdateEvents(socket);

   //Successful read operation
   return NO_ERROR;
}
Example #7
0
void ipv6FragTick(NetInterface *interface)
{
   error_t error;
   uint_t i;
   systime_t time;
   Ipv6HoleDesc *hole;

   //Acquire exclusive access to the reassembly queue
   osAcquireMutex(&interface->ipv6FragQueueMutex);

   //Get current time
   time = osGetSystemTime();

   //Loop through the reassembly queue
   for(i = 0; i < IPV6_MAX_FRAG_DATAGRAMS; i++)
   {
      //Point to the current entry in the reassembly queue
      Ipv6FragDesc *frag = &interface->ipv6FragQueue[i];

      //Make sure the entry is currently in use
      if(frag->buffer.chunkCount > 0)
      {
         //If the timer runs out, the partially-reassembled datagram must be
         //discarded and ICMPv6 Time Exceeded message sent to the source host
         if((time - frag->timestamp) >= IPV6_FRAG_TIME_TO_LIVE)
         {
            //Debug message
            TRACE_INFO("IPv6 fragment reassembly timeout...\r\n");
            //Dump IP header contents for debugging purpose
            ipv6DumpHeader(frag->buffer.chunk[0].address);

            //Point to the first hole descriptor
            hole = ipv6FindHole(frag, frag->firstHole);

            //Make sure the fragment zero has been received
            //before sending an ICMPv6 message
            if(hole != NULL && hole->first > 0)
            {
               //Fix the size of the reconstructed datagram
               error = chunkedBufferSetLength((ChunkedBuffer *) &frag->buffer,
                  frag->unfragPartLength + hole->first);

               //Check status code
               if(!error)
               {
                  //Send an ICMPv6 Time Exceeded message
                  icmpv6SendErrorMessage(interface, ICMPV6_TYPE_TIME_EXCEEDED,
                     ICMPV6_CODE_REASSEMBLY_TIME_EXCEEDED, 0, (ChunkedBuffer *) &frag->buffer);
               }
            }

            //Drop the partially reconstructed datagram
            chunkedBufferSetLength((ChunkedBuffer *) &frag->buffer, 0);
         }
      }
   }

   //Release exclusive access to the reassembly queue
   osReleaseMutex(&interface->ipv6FragQueueMutex);
}
Example #8
0
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort,
   const void *data, size_t length, size_t *written, uint_t flags)
{
   error_t error;

   //No data has been transmitted yet
   if(written)
      *written = 0;

   //Make sure the socket handle is valid
   if(!socket)
      return ERROR_INVALID_PARAMETER;

#if (TCP_SUPPORT == ENABLED)
   //Connection-oriented socket?
   if(socket->type == SOCKET_TYPE_STREAM)
   {
      //Enter critical section
      osAcquireMutex(&socketMutex);
      //For connection-oriented sockets, target address is ignored
      error = tcpSend(socket, data, length, written, flags);
      //Leave critical section
      osReleaseMutex(&socketMutex);
   }
   else
#endif
#if (UDP_SUPPORT == ENABLED)
   //Connectionless socket?
   if(socket->type == SOCKET_TYPE_DGRAM)
   {
      //Send UDP datagram
      error = udpSendDatagram(socket, destIpAddr,
         destPort, data, length, written);
   }
   else
#endif
#if (RAW_SOCKET_SUPPORT == ENABLED)
   //Raw socket?
   if(socket->type == SOCKET_TYPE_RAW_IP)
   {
      //Send a raw IP packet
      error = rawSocketSendIpPacket(socket, destIpAddr, data, length, written);
   }
   else if(socket->type == SOCKET_TYPE_RAW_ETH)
   {
      //Send a raw Ethernet packet
      error = rawSocketSendEthPacket(socket, data, length, written);
   }
   else
#endif
   //Socket type not supported...
   {
      //Invalid socket type
      error = ERROR_INVALID_SOCKET;
   }

   //Return status code
   return error;
}
Example #9
0
void slaacLinkChangeEvent(SlaacContext *context)
{
   //Enter critical section
   osAcquireMutex(&context->mutex);

   //Reinitialize state machine
   context->state = SLAAC_STATE_INIT;

   //Leave critical section
   osReleaseMutex(&context->mutex);
}
Example #10
0
error_t rawSocketReceiveEthPacket(Socket *socket,
   void *data, size_t size, size_t *received, uint_t flags)
{
   SocketQueueItem *queueItem;

   //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
   if(!(flags & SOCKET_FLAG_DONT_WAIT))
   {
      //The receive queue is empty?
      if(!socket->receiveQueue)
      {
         //Set the events the application is interested in
         socket->eventMask = SOCKET_EVENT_RX_READY;
         //Reset the event object
         osResetEvent(&socket->event);
         //Leave critical section
         osReleaseMutex(&socketMutex);
         //Wait until an event is triggered
         osWaitForEvent(&socket->event, socket->timeout);
         //Enter critical section
         osAcquireMutex(&socketMutex);
      }
   }

   //Check whether the read operation timed out
   if(!socket->receiveQueue)
   {
      //No data can be read
      *received = 0;
      //Report a timeout error
      return ERROR_TIMEOUT;
   }

   //Point to the first item in the receive queue
   queueItem = socket->receiveQueue;
   //Copy data to user buffer
   *received = netBufferRead(data, queueItem->buffer, queueItem->offset, size);

   //If the SOCKET_FLAG_PEEK flag is set, the data is copied
   //into the buffer but is not removed from the input queue
   if(!(flags & SOCKET_FLAG_PEEK))
   {
      //Remove the item from the receive queue
      socket->receiveQueue = queueItem->next;
      //Deallocate memory buffer
      netBufferFree(queueItem->buffer);
   }

   //Update the state of events
   rawSocketUpdateEvents(socket);

   //Successful read operation
   return NO_ERROR;
}
Example #11
0
error_t ipv4CheckDestAddr(NetInterface *interface, Ipv4Addr ipAddr)
{
   uint_t i;

   //Filter out any invalid addresses
   error_t error = ERROR_INVALID_ADDRESS;

   //Broadcast address?
   if(ipv4IsBroadcastAddr(interface, ipAddr))
   {
      //Always accept broadcast address
      error = NO_ERROR;
   }
   //Multicast address?
   else if(ipv4IsMulticastAddr(ipAddr))
   {
      //Acquire exclusive access to the IPv4 filter table
      osAcquireMutex(&interface->ipv4FilterMutex);

      //Loop through the IPv4 filter table
      for(i = 0; i < interface->ipv4FilterSize; i++)
      {
         //Check whether the destination IPv4 address matches
         //a relevant multicast address
         if(interface->ipv4Filter[i].addr == ipAddr)
         {
            //The multicast address is acceptable
            error = NO_ERROR;
            //Stop immediately
            break;
         }
      }

      //Release exclusive access to the IPv4 filter table
      osReleaseMutex(&interface->ipv4FilterMutex);
   }
   //Unicast address?
   else
   {
      //The destination address matches the host address?
      if(interface->ipv4Config.addrState != IPV4_ADDR_STATE_INVALID &&
         interface->ipv4Config.addr == ipAddr)
      {
         //The destination address is acceptable
         error = NO_ERROR;
      }
   }

   //Return status code
   return error;
}
Example #12
0
TcpState tcpGetState(Socket *socket)
{
   TcpState state;

   //Enter critical section
   osAcquireMutex(&socketMutex);
   //Get TCP FSM current state
   state = socket->state;
   //Leave critical section
   osReleaseMutex(&socketMutex);

   //Return current state
   return state;
}
Example #13
0
error_t slaacStop(SlaacContext *context)
{
   //Enter critical section
   osAcquireMutex(&context->mutex);

   //Suspend SLAAC operation
   context->running = FALSE;
   //Reinitialize state machine
   context->state = SLAAC_STATE_INIT;

   //Leave critical section
   osReleaseMutex(&context->mutex);

   //Successful processing
   return NO_ERROR;
}
Example #14
0
error_t socketUnregisterEvents(Socket *socket)
{
   //Make sure the socket handle is valid
   if(!socket)
      return ERROR_INVALID_PARAMETER;

   //Enter critical section
   osAcquireMutex(&socketMutex);

   //Unsuscribe socket events
   socket->userEvent = NULL;

   //Leave critical section
   osReleaseMutex(&socketMutex);
   //Successful processing
   return NO_ERROR;
}
Example #15
0
error_t socketRegisterEvents(Socket *socket, OsEvent *event, uint_t eventMask)
{
   //Make sure the socket handle is valid
   if(!socket)
      return ERROR_INVALID_PARAMETER;

   //Enter critical section
   osAcquireMutex(&socketMutex);

   //An user event may have been previously registered...
   if(socket->userEvent != NULL)
      socket->eventMask |= eventMask;
   else
      socket->eventMask = eventMask;

   //Suscribe to get notified of events
   socket->userEvent = event;

#if (TCP_SUPPORT == ENABLED)
   //Handle TCP specific events
   if(socket->type == SOCKET_TYPE_STREAM)
   {
      tcpUpdateEvents(socket);
   }
#endif
#if (UDP_SUPPORT == ENABLED)
   //Handle UDP specific events
   if(socket->type == SOCKET_TYPE_DGRAM)
   {
      udpUpdateEvents(socket);
   }
#endif
#if (RAW_SOCKET_SUPPORT == ENABLED)
   //Handle events that are specific to raw sockets
   if(socket->type == SOCKET_TYPE_RAW_IP ||
      socket->type == SOCKET_TYPE_RAW_ETH)
   {
      rawSocketUpdateEvents(socket);
   }
#endif

   //Leave critical section
   osReleaseMutex(&socketMutex);
   //Successful processing
   return NO_ERROR;
}
Example #16
0
void ipv6FlushFragQueue(NetInterface *interface)
{
   uint_t i;

   //Acquire exclusive access to the reassembly queue
   osAcquireMutex(&interface->ipv6FragQueueMutex);

   //Loop through the reassembly queue
   for(i = 0; i < IPV6_MAX_FRAG_DATAGRAMS; i++)
   {
      //Drop any partially reconstructed datagram
      chunkedBufferSetLength((ChunkedBuffer *) &interface->ipv6FragQueue[i].buffer, 0);
   }

   //Release exclusive access to the reassembly queue
   osReleaseMutex(&interface->ipv6FragQueueMutex);
}
Example #17
0
void socketClose(Socket *socket)
{
   //Make sure the socket handle is valid
   if(!socket) return;

   //Enter critical section
   osAcquireMutex(&socketMutex);

#if (TCP_SUPPORT == ENABLED)
   //Connection-oriented socket?
   if(socket->type == SOCKET_TYPE_STREAM)
   {
      //Abort the current TCP connection
      tcpAbort(socket);
   }
#endif
#if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED)
   //Connectionless socket or raw socket?
   if(socket->type == SOCKET_TYPE_DGRAM ||
      socket->type == SOCKET_TYPE_RAW_IP ||
      socket->type == SOCKET_TYPE_RAW_ETH)
   {
      //Point to the first item in the receive queue
      SocketQueueItem *queueItem = socket->receiveQueue;

      //Purge the receive queue
      while(queueItem)
      {
         //Keep track of the next item in the queue
         SocketQueueItem *nextQueueItem = queueItem->next;
         //Free previously allocated memory
         memPoolFree(queueItem);
         //Point to the next item
         queueItem = nextQueueItem;
      }

      //Mark the socket as closed
      socket->type = SOCKET_TYPE_UNUSED;
   }
#endif

   //Leave critical section
   osReleaseMutex(&socketMutex);
}
Example #18
0
error_t socketGetEvents(Socket *socket, uint_t *eventFlags)
{
   //Make sure the socket handle is valid
   if(!socket)
   {
      //Always return a valid value
      *eventFlags = 0;
      //Report an error
      return ERROR_INVALID_PARAMETER;
   }

   //Enter critical section
   osAcquireMutex(&socketMutex);

   //Read event flags for the specified socket
   *eventFlags = socket->eventFlags;

   //Leave critical section
   osReleaseMutex(&socketMutex);
   //Successful processing
   return NO_ERROR;
}
Example #19
0
error_t udpAttachRxCallback(NetInterface *interface,
                            uint16_t port, UdpRxCallback callback, void *params)
{
    uint_t i;
    UdpRxCallbackDesc *entry;

    //Acquire exclusive access to the callback table
    osAcquireMutex(&udpCallbackMutex);

    //Loop through the table
    for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
    {
        //Point to the current entry
        entry = &udpCallbackTable[i];

        //Check whether the entry is currently in used
        if(entry->callback == NULL)
        {
            //Create a new entry
            entry->interface = interface;
            entry->port = port;
            entry->callback = callback;
            entry->params = params;
            //We are done
            break;
        }
    }

    //Release exclusive access to the callback table
    osReleaseMutex(&udpCallbackMutex);

    //Failed to attach the specified user callback?
    if(i >= UDP_CALLBACK_TABLE_SIZE)
        return ERROR_OUT_OF_RESOURCES;

    //Successful processing
    return NO_ERROR;
}
Example #20
0
void ndpFlushCache(NetInterface *interface)
{
   uint_t i;
   NdpCacheEntry *entry;

   //Acquire exclusive access to Neighbor cache
   osAcquireMutex(&interface->ndpCacheMutex);

   //Loop through Neighbor cache entries
   for(i = 0; i < NDP_CACHE_SIZE; i++)
   {
      //Point to the current entry
      entry = &interface->ndpCache[i];

      //Drop packets that are waiting for address resolution
      ndpFlushQueuedPackets(interface, entry);
      //Release Neighbor cache entry
      entry->state = NDP_STATE_NONE;
   }

   //Release exclusive access to Neighbor cache
   osReleaseMutex(&interface->ndpCacheMutex);
}
Example #21
0
error_t udpDetachRxCallback(NetInterface *interface, uint16_t port)
{
    uint_t i;
    UdpRxCallbackDesc *entry;

    //This flag tells whether an entry has been found
    bool_t found = FALSE;

    //Acquire exclusive access to the callback table
    osAcquireMutex(&udpCallbackMutex);

    //Loop through the table
    for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
    {
        //Point to the current entry
        entry = &udpCallbackTable[i];

        //Check whether the entry is currently in used
        if(entry->callback != NULL)
        {
            //Does the specified port number match the current entry?
            if(entry->port == port && entry->interface == interface)
            {
                //Unregister user callback
                entry->callback = NULL;
                //A matching entry was found
                found = TRUE;
            }
        }
    }

    //Release exclusive access to the callback table
    osReleaseMutex(&udpCallbackMutex);

    //Check whether the specified callback has been successfully unregistered
    return found ? NO_ERROR : ERROR_FAILURE;
}
Example #22
0
error_t udpProcessDatagram(NetInterface *interface,
                           IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
{
    error_t error;
    uint_t i;
    size_t length;
    UdpHeader *header;
    Socket *socket;
    SocketQueueItem *queueItem;
    NetBuffer *p;

    //Retrieve the length of the UDP datagram
    length = netBufferGetLength(buffer) - offset;

    //Ensure the UDP header is valid
    if(length < sizeof(UdpHeader))
    {
        //Debug message
        TRACE_WARNING("UDP datagram length is invalid!\r\n");
        //Report an error
        return ERROR_INVALID_HEADER;
    }

    //Point to the UDP header
    header = netBufferAt(buffer, offset);
    //Sanity check
    if(!header) return ERROR_FAILURE;

    //Debug message
    TRACE_INFO("UDP datagram received (%" PRIuSIZE " bytes)...\r\n", length);
    //Dump UDP header contents for debugging purpose
    udpDumpHeader(header);

    //When UDP runs over IPv6, the checksum is mandatory
    if(header->checksum || pseudoHeader->length == sizeof(Ipv6PseudoHeader))
    {
        //Verify UDP checksum
        if(ipCalcUpperLayerChecksumEx(pseudoHeader->data,
                                      pseudoHeader->length, buffer, offset, length) != 0xFFFF)
        {
            //Debug message
            TRACE_WARNING("Wrong UDP header checksum!\r\n");
            //Report an error
            return ERROR_WRONG_CHECKSUM;
        }
    }

    //Enter critical section
    osAcquireMutex(&socketMutex);

    //Loop through opened sockets
    for(i = 0; i < SOCKET_MAX_COUNT; i++)
    {
        //Point to the current socket
        socket = socketTable + i;

        //UDP socket found?
        if(socket->type != SOCKET_TYPE_DGRAM)
            continue;
        //Check whether the socket is bound to a particular interface
        if(socket->interface && socket->interface != interface)
            continue;
        //Check destination port number
        if(socket->localPort != ntohs(header->destPort))
            continue;
        //Source port number filtering
        if(socket->remotePort && socket->remotePort != ntohs(header->srcPort))
            continue;

#if (IPV4_SUPPORT == ENABLED)
        //An IPv4 packet was received?
        if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
        {
            //Destination IP address filtering
            if(socket->localIpAddr.length)
            {
                //An IPv4 address is expected
                if(socket->localIpAddr.length != sizeof(Ipv4Addr))
                    continue;
                //Filter out non-matching addresses
                if(socket->localIpAddr.ipv4Addr != pseudoHeader->ipv4Data.destAddr)
                    continue;
            }
            //Source IP address filtering
            if(socket->remoteIpAddr.length)
            {
                //An IPv4 address is expected
                if(socket->remoteIpAddr.length != sizeof(Ipv4Addr))
                    continue;
                //Filter out non-matching addresses
                if(socket->remoteIpAddr.ipv4Addr != pseudoHeader->ipv4Data.srcAddr)
                    continue;
            }
        }
        else
#endif
#if (IPV6_SUPPORT == ENABLED)
            //An IPv6 packet was received?
            if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
            {
                //Destination IP address filtering
                if(socket->localIpAddr.length)
                {
                    //An IPv6 address is expected
                    if(socket->localIpAddr.length != sizeof(Ipv6Addr))
                        continue;
                    //Filter out non-matching addresses
                    if(!ipv6CompAddr(&socket->localIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.destAddr))
                        continue;
                }
                //Source IP address filtering
                if(socket->remoteIpAddr.length)
                {
                    //An IPv6 address is expected
                    if(socket->remoteIpAddr.length != sizeof(Ipv6Addr))
                        continue;
                    //Filter out non-matching addresses
                    if(!ipv6CompAddr(&socket->remoteIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.srcAddr))
                        continue;
                }
            }
            else
#endif
                //An invalid packet was received?
            {
                //This should never occur...
                continue;
            }

        //The current socket meets all the criteria
        break;
    }

    //Point to the payload
    offset += sizeof(UdpHeader);
    length -= sizeof(UdpHeader);

    //No matching socket found?
    if(i >= SOCKET_MAX_COUNT)
    {
        //Leave critical section
        osReleaseMutex(&socketMutex);
        //Invoke user callback, if any
        error = udpInvokeRxCallback(interface, pseudoHeader, header, buffer, offset);
        //Return status code
        return error;
    }

    //Empty receive queue?
    if(!socket->receiveQueue)
    {
        //Allocate a memory buffer to hold the data and the associated descriptor
        p = netBufferAlloc(sizeof(SocketQueueItem) + length);

        //Successful memory allocation?
        if(p != NULL)
        {
            //Point to the newly created item
            queueItem = netBufferAt(p, 0);
            queueItem->buffer = p;
            //Add the newly created item to the queue
            socket->receiveQueue = queueItem;
        }
        else
        {
            //Memory allocation failed
            queueItem = NULL;
        }
    }
    else
    {
        //Point to the very first item
        queueItem = socket->receiveQueue;
        //Reach the last item in the receive queue
        for(i = 1; queueItem->next; i++)
            queueItem = queueItem->next;

        //Make sure the receive queue is not full
        if(i >= UDP_RX_QUEUE_SIZE)
        {
            //Leave critical section
            osReleaseMutex(&socketMutex);
            //Notify the calling function that the queue is full
            return ERROR_RECEIVE_QUEUE_FULL;
        }

        //Allocate a memory buffer to hold the data and the associated descriptor
        p = netBufferAlloc(sizeof(SocketQueueItem) + length);

        //Successful memory allocation?
        if(p != NULL)
        {
            //Add the newly created item to the queue
            queueItem->next = netBufferAt(p, 0);
            //Point to the newly created item
            queueItem = queueItem->next;
            queueItem->buffer = p;
        }
        else
        {
            //Memory allocation failed
            queueItem = NULL;
        }
    }

    //Failed to allocate memory?
    if(!queueItem)
    {
        //Leave critical section
        osReleaseMutex(&socketMutex);
        //Return error code
        return ERROR_OUT_OF_MEMORY;
    }

    //Initialize next field
    queueItem->next = NULL;
    //Record the source port number
    queueItem->srcPort = ntohs(header->srcPort);

#if (IPV4_SUPPORT == ENABLED)
    //IPv4 remote address?
    if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
    {
        //Save the source IPv4 address
        queueItem->srcIpAddr.length = sizeof(Ipv4Addr);
        queueItem->srcIpAddr.ipv4Addr = pseudoHeader->ipv4Data.srcAddr;
        //Save the destination IPv4 address
        queueItem->destIpAddr.length = sizeof(Ipv4Addr);
        queueItem->destIpAddr.ipv4Addr = pseudoHeader->ipv4Data.destAddr;
    }
#endif
#if (IPV6_SUPPORT == ENABLED)
    //IPv6 remote address?
    if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
    {
        //Save the source IPv6 address
        queueItem->srcIpAddr.length = sizeof(Ipv6Addr);
        queueItem->srcIpAddr.ipv6Addr = pseudoHeader->ipv6Data.srcAddr;
        //Save the destination IPv6 address
        queueItem->destIpAddr.length = sizeof(Ipv6Addr);
        queueItem->destIpAddr.ipv6Addr = pseudoHeader->ipv6Data.destAddr;
    }
#endif

    //Offset to the payload
    queueItem->offset = sizeof(SocketQueueItem);
    //Copy the payload
    netBufferCopy(queueItem->buffer, queueItem->offset, buffer, offset, length);

    //Notify user that data is available
    udpUpdateEvents(socket);

    //Leave critical section
    osReleaseMutex(&socketMutex);
    //Successful processing
    return NO_ERROR;
}
Example #23
0
void ndpProcessNeighborAdv(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
   const ChunkedBuffer *buffer, size_t offset, uint8_t hopLimit)
{
   size_t length;
   NdpNeighborAdvMessage *message;
   NdpLinkLayerAddrOption *option;
   NdpCacheEntry *entry;

   //Retrieve the length of the message
   length = chunkedBufferGetLength(buffer) - offset;

   //Check the length of the Neighbor Advertisement message
   if(length < sizeof(NdpNeighborAdvMessage))
      return;

   //Point to the beginning of the message
   message = chunkedBufferAt(buffer, offset);
   //Sanity check
   if(!message) return;

   //Debug message
   TRACE_INFO("Neighbor Advertisement message received (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump message contents for debugging purpose
   ndpDumpNeighborAdvMessage(message);

   //The IPv6 Hop Limit field must have a value of 255 to ensure
   //that the packet has not been forwarded by a router
   if(hopLimit != NDP_HOP_LIMIT)
      return;

   //ICMPv6 Code must be 0
   if(message->code)
      return;

   //Check whether the target address is tentative or matches
   //a unicast address assigned to the interface
   if(ipv6CompAddr(&message->targetAddr, &interface->ipv6Config.linkLocalAddr) &&
      interface->ipv6Config.linkLocalAddrState != IPV6_ADDR_STATE_INVALID)
   {
      //Debug message
      TRACE_WARNING("The address %s is a duplicate!\r\n",
         ipv6AddrToString(&interface->ipv6Config.linkLocalAddr, NULL));

      //The address is a duplicate and should not be used
      interface->ipv6Config.linkLocalAddrDup = TRUE;
      //Exit immediately
      return;
   }
   else if(ipv6CompAddr(&message->targetAddr, &interface->ipv6Config.globalAddr) &&
      interface->ipv6Config.globalAddrState != IPV6_ADDR_STATE_INVALID)
   {
      //Debug message
      TRACE_WARNING("The address %s is a duplicate!\r\n",
         ipv6AddrToString(&interface->ipv6Config.globalAddr, NULL));

      //The address is a duplicate and should not be used
      interface->ipv6Config.globalAddrDup = TRUE;
      //Exit immediately
      return;
   }

   //The target address must not be a multicast address
   if(ipv6IsMulticastAddr(&message->targetAddr))
   {
      //Debug message
      TRACE_WARNING("Target address must not be a multicast address!\r\n");
      //Exit immediately
      return;
   }

   //If the destination address is a multicast address
   //then the Solicited flag must be zero
   if(ipv6IsMulticastAddr(&pseudoHeader->destAddr) && message->s)
   {
      //Debug message
      TRACE_WARNING("Solicited flag must be zero!\r\n");
      //Exit immediately
      return;
   }

   //Calculate the length of the Options field
   length -= sizeof(NdpNeighborSolMessage);
   //Search for the Target Link-Layer Address option
   option = ndpGetOption(message->options, length, NDP_OPT_TARGET_LINK_LAYER_ADDR);

   //Source Link-Layer Address option found?
   if(option && option->length == 1)
   {
      //Debug message
      TRACE_DEBUG("  Target Link-Layer Address = %s\r\n",
         macAddrToString(&option->linkLayerAddr, NULL));

      //Acquire exclusive access to Neighbor cache
      osAcquireMutex(&interface->ndpCacheMutex);

      //Search the Neighbor cache for the specified target address
      entry = ndpFindEntry(interface, &message->targetAddr);

      //If no entry exists, the advertisement should be silently discarded
      if(entry)
      {
         //INCOMPLETE state?
         if(entry->state == NDP_STATE_INCOMPLETE)
         {
            //Record link-layer address
            entry->macAddr = option->linkLayerAddr;
            //Send all the packets that are pending for transmission
            ndpSendQueuedPackets(interface, entry);
            //Save current time
            entry->timestamp = osGetSystemTime();

            //Solicited flag is set?
            if(message->s)
            {
               //Computing the random ReachableTime value
               entry->timeout = NDP_REACHABLE_TIME;
               //Switch to the REACHABLE state
               entry->state = NDP_STATE_REACHABLE;
            }
            //Solicited flag is cleared?
            else
            {
               //Enter the STALE state
               entry->state = NDP_STATE_STALE;
            }
         }
         //REACHABLE, STALE, DELAY or PROBE state?
         else
         {
            //Solicited flag is set and Override flag is cleared?
            if(message->s && !message->o)
            {
               //Same link-layer address than cached?
               if(macCompAddr(&entry->macAddr, &option->linkLayerAddr))
               {
                  //Save current time
                  entry->timestamp = osGetSystemTime();
                  //Computing the random ReachableTime value
                  entry->timeout = NDP_REACHABLE_TIME;
                  //Switch to the REACHABLE state
                  entry->state = NDP_STATE_REACHABLE;
               }
               //Different link-layer address than cached?
               else
               {
                  //REACHABLE state?
                  if(entry->state == NDP_STATE_REACHABLE)
                  {
                     //Save current time
                     entry->timestamp = osGetSystemTime();
                     //Enter the STALE state
                     entry->state = NDP_STATE_STALE;
                  }
               }
            }
            //Both Solicited and Override flags are set?
            else if(message->s && message->o)
            {
               //Record link-layer address (if different)
               entry->macAddr = option->linkLayerAddr;
               //Save current time
               entry->timestamp = osGetSystemTime();
               //Computing the random ReachableTime value
               entry->timeout = NDP_REACHABLE_TIME;
               //Switch to the REACHABLE state
               entry->state = NDP_STATE_REACHABLE;
            }
            //Solicited flag is cleared and Override flag is set?
            else if(!message->s && message->o)
            {
               //Different link-layer address than cached?
               if(!macCompAddr(&entry->macAddr, &option->linkLayerAddr))
               {
                  //Record link-layer address
                  entry->macAddr = option->linkLayerAddr;
                  //Save current time
                  entry->timestamp = osGetSystemTime();
                  //Enter the STALE state
                  entry->state = NDP_STATE_STALE;
               }
            }
         }
      }
   }
   //Source Link-Layer Address option not found?
   else
   {
      //Update content of IsRouter flag
   }

   //Release exclusive access to Neighbor cache
   osReleaseMutex(&interface->ndpCacheMutex);
}
Example #24
0
void ndpProcessNeighborSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
   const ChunkedBuffer *buffer, size_t offset, uint8_t hopLimit)
{
   size_t length;
   NdpNeighborSolMessage *message;
   NdpLinkLayerAddrOption *option;
   NdpCacheEntry *entry;

   //Retrieve the length of the message
   length = chunkedBufferGetLength(buffer) - offset;

   //Check the length of the Neighbor Solicitation message
   if(length < sizeof(NdpNeighborSolMessage))
      return;

   //Point to the beginning of the message
   message = chunkedBufferAt(buffer, offset);
   //Sanity check
   if(!message) return;

   //Debug message
   TRACE_INFO("Neighbor Solicitation message received (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump message contents for debugging purpose
   ndpDumpNeighborSolMessage(message);

   //The IPv6 Hop Limit field must have a value of 255 to ensure
   //that the packet has not been forwarded by a router
   if(hopLimit != NDP_HOP_LIMIT)
      return;

   //ICMPv6 Code must be 0
   if(message->code)
      return;

   //The target address must a valid unicast address assigned to the interface
   //or a tentative address on which DAD is being performed
   if(ipv6CompAddr(&message->targetAddr, &interface->ipv6Config.linkLocalAddr))
   {
      //Check whether the target address is tentative
      if(interface->ipv6Config.linkLocalAddrState == IPV6_ADDR_STATE_TENTATIVE)
      {
         //If the source address of the Neighbor Solicitation is the unspecified
         //address, the solicitation is from a node performing Duplicate Address
         //Detection
         if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
         {
            //Debug message
            TRACE_WARNING("The tentative address %s is a duplicate!\r\n",
               ipv6AddrToString(&interface->ipv6Config.linkLocalAddr, NULL));

            //The tentative address is a duplicate and should not be used
            interface->ipv6Config.linkLocalAddrDup = TRUE;
         }

         //In all cases, a node must not respond to a Neighbor Solicitation
         //for a tentative address
         return;
      }
   }
   else if(ipv6CompAddr(&message->targetAddr, &interface->ipv6Config.globalAddr))
   {
      //Check whether the target address is tentative
      if(interface->ipv6Config.globalAddrState == IPV6_ADDR_STATE_TENTATIVE)
      {
         //If the source address of the Neighbor Solicitation is the unspecified
         //address, the solicitation is from a node performing Duplicate Address
         //Detection
         if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
         {
            //Debug message
            TRACE_WARNING("The tentative address %s is a duplicate!\r\n",
               ipv6AddrToString(&interface->ipv6Config.globalAddr, NULL));

            //The tentative address is a duplicate and should not be used
            interface->ipv6Config.globalAddrDup = TRUE;
         }

         //In all cases, a node must not respond to a Neighbor Solicitation
         //for a tentative address
         return;
      }
   }
   else
   {
      //Debug message
      TRACE_WARNING("Wrong target address!\r\n");
      //Exit immediately
      return;
   }

   //If the IP source address is the unspecified address, the IP
   //destination address must be a solicited-node multicast address
   if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR) &&
      !ipv6IsSolicitedNodeAddr(&pseudoHeader->destAddr))
   {
      //Debug message
      TRACE_WARNING("Destination address must be a solicited-node address!\r\n");
      //Exit immediately
      return;
   }

   //Calculate the length of the Options field
   length -= sizeof(NdpNeighborSolMessage);
   //Search for the Source Link-Layer Address option
   option = ndpGetOption(message->options, length, NDP_OPT_SOURCE_LINK_LAYER_ADDR);

   //Source Link-Layer Address option found?
   if(option && option->length == 1)
   {
      //Debug message
      TRACE_DEBUG("  Source Link-Layer Address = %s\r\n",
         macAddrToString(&option->linkLayerAddr, NULL));

      //If the Source Address is not the unspecified address, then the Neighbor
      //cache should be updated for the IP source address of the solicitation
      if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
         return;

      //Acquire exclusive access to Neighbor cache
      osAcquireMutex(&interface->ndpCacheMutex);

      //Search the Neighbor cache for the source address of the solicitation
      entry = ndpFindEntry(interface, &pseudoHeader->srcAddr);

      //No matching entry has been found?
      if(!entry)
      {
         //Create an entry
         entry = ndpCreateEntry(interface);

         //Neighbor cache entry successfully created?
         if(entry)
         {
            //Record the IPv6 and the corresponding MAC address
            entry->ipAddr = pseudoHeader->srcAddr;
            entry->macAddr = option->linkLayerAddr;
            //Save current time
            entry->timestamp = osGetSystemTime();
            //Enter the STALE state
            entry->state = NDP_STATE_STALE;
         }
      }
      else
      {
         //INCOMPLETE state?
         if(entry->state == NDP_STATE_INCOMPLETE)
         {
            //Record link-layer address
            entry->macAddr = option->linkLayerAddr;
            //Send all the packets that are pending for transmission
            ndpSendQueuedPackets(interface, entry);
            //Save current time
            entry->timestamp = osGetSystemTime();
            //Enter the STALE state
            entry->state = NDP_STATE_STALE;
         }
         //REACHABLE, STALE, DELAY or PROBE state?
         else
         {
            //Different link-layer address than cached?
            if(!macCompAddr(&entry->macAddr, &option->linkLayerAddr))
            {
               //Update link-layer address
               entry->macAddr = option->linkLayerAddr;
               //Save current time
               entry->timestamp = osGetSystemTime();
               //Enter the STALE state
               entry->state = NDP_STATE_STALE;
            }
         }
      }

      //Release exclusive access to Neighbor cache
      osReleaseMutex(&interface->ndpCacheMutex);
   }
   //Source Link-Layer Address option not found?
   else
   {
      //This option must be included in multicast solicitations
      if(ipv6IsMulticastAddr(&pseudoHeader->destAddr))
      {
         //Debug message
         TRACE_WARNING("The Source Link-Layer Address must be included!\r\n");
         //Exit immediately
         return;
      }
   }

   //After any updates to the Neighbor cache, the node sends a Neighbor
   //Advertisement response as described in RFC 4861 7.2.4
   ndpSendNeighborAdv(interface, &message->targetAddr, &pseudoHeader->srcAddr);
}
Example #25
0
void ndpTick(NetInterface *interface)
{
   uint_t i;
   systime_t time;
   NdpCacheEntry *entry;

   //Get current time
   time = osGetSystemTime();

   //Acquire exclusive access to Neighbor cache
   osAcquireMutex(&interface->ndpCacheMutex);

   //Go through Neighbor cache
   for(i = 0; i < NDP_CACHE_SIZE; i++)
   {
      //Point to the current entry
      entry = &interface->ndpCache[i];

      //INCOMPLETE state?
      if(entry->state == NDP_STATE_INCOMPLETE)
      {
         //The Neighbor Solicitation timed out?
         if((time - entry->timestamp) >= entry->timeout)
         {
            //Increment retransmission counter
            entry->retransmitCount++;

            //Check whether the maximum number of retransmissions has been exceeded
            if(entry->retransmitCount < NDP_MAX_MULTICAST_SOLICIT)
            {
               //Retransmit a multicast Neighbor Solicitation message
               ndpSendNeighborSol(interface, &entry->ipAddr);

               //Save the time at which the message was sent
               entry->timestamp = time;
               //Set timeout value
               entry->timeout = NDP_RETRANS_TIMER;
            }
            else
            {
               //Drop packets that are waiting for address resolution
               ndpFlushQueuedPackets(interface, entry);
               //The entry should be deleted since address resolution has failed
               entry->state = NDP_STATE_NONE;
            }
         }
      }
      //REACHABLE state?
      else if(entry->state == NDP_STATE_REACHABLE)
      {
         //Periodically time out Neighbor cache entries
         if((time - entry->timestamp) >= entry->timeout)
         {
            //Save current time
            entry->timestamp = osGetSystemTime();
            //Enter STALE state
            entry->state = NDP_STATE_STALE;
         }
      }
      //DELAY state?
      else if(entry->state == NDP_STATE_DELAY)
      {
         //Wait for the specified delay before sending the first probe
         if((time - entry->timestamp) >= entry->timeout)
         {
            //Send a unicast Neighbor Solicitation message
            ndpSendNeighborSol(interface, &entry->ipAddr);

            //Save the time at which the message was sent
            entry->timestamp = time;
            //Set timeout value
            entry->timeout = NDP_RETRANS_TIMER;
            //Switch to the PROBE state
            entry->state = NDP_STATE_PROBE;
         }
      }
      //PROBE state?
      else if(entry->state == NDP_STATE_PROBE)
      {
         //The request timed out?
         if((time - entry->timestamp) >= entry->timeout)
         {
            //Increment retransmission counter
            entry->retransmitCount++;

            //Check whether the maximum number of retransmissions has been exceeded
            if(entry->retransmitCount < NDP_MAX_UNICAST_SOLICIT)
            {
               //Send a unicast Neighbor Solicitation message
               ndpSendNeighborSol(interface, &entry->ipAddr);

               //Save the time at which the packet was sent
               entry->timestamp = time;
               //Set timeout value
               entry->timeout = NDP_RETRANS_TIMER;
            }
            else
            {
               //The entry should be deleted since the host is not reachable anymore
               entry->state = NDP_STATE_NONE;
            }
         }
      }
   }

   //Release exclusive access to Neighbor cache
   osReleaseMutex(&interface->ndpCacheMutex);
}
Example #26
0
error_t ndpEnqueuePacket(NetInterface *interface,
   const Ipv6Addr *ipAddr, ChunkedBuffer *buffer, size_t offset)
{
   error_t error;
   uint_t i;
   size_t length;
   NdpCacheEntry *entry;

   //Retrieve the length of the multi-part buffer
   length = chunkedBufferGetLength(buffer);

   //Acquire exclusive access to Neighbor cache
   osAcquireMutex(&interface->ndpCacheMutex);

   //Search the Neighbor cache for the specified Ipv6 address
   entry = ndpFindEntry(interface, ipAddr);

   //No matching entry in Neighbor cache?
   if(!entry)
   {
      //Release exclusive access to Neighbor cache
      osReleaseMutex(&interface->ndpCacheMutex);
      //Report an error to the calling function
      return ERROR_FAILURE;
   }

   //Check current state
   if(entry->state == NDP_STATE_INCOMPLETE)
   {
      //Check whether the packet queue is full
      if(entry->queueSize >= NDP_MAX_PENDING_PACKETS)
      {
         //When the queue overflows, the new arrival should replace the oldest entry
         chunkedBufferFree(entry->queue[0].buffer);

         //Make room for the new packet
         for(i = 1; i < NDP_MAX_PENDING_PACKETS; i++)
            entry->queue[i - 1] = entry->queue[i];

         //Adjust the number of pending packets
         entry->queueSize--;
      }

      //Index of the entry to be filled in
      i = entry->queueSize;
      //Allocate a memory buffer to store the packet
      entry->queue[i].buffer = chunkedBufferAlloc(length);

      //Failed to allocate memory?
      if(!entry->queue[i].buffer)
      {
         //Release exclusive access to Neighbor cache
         osReleaseMutex(&interface->ndpCacheMutex);
         //Report an error to the calling function
         return ERROR_OUT_OF_MEMORY;
      }

      //Copy packet contents
      chunkedBufferCopy(entry->queue[i].buffer, 0, buffer, 0, length);
      //Offset to the first byte of the IPv6 header
      entry->queue[i].offset = offset;

      //Increment the number of queued packets
      entry->queueSize++;
      //The packet was successfully enqueued
      error = NO_ERROR;
   }
   else
   {
      //Send immediately the packet since the address is already resolved
      error = ethSendFrame(interface, &entry->macAddr, buffer, offset, ETH_TYPE_IPV6);
   }

   //Release exclusive access to Neighbor cache
   osReleaseMutex(&interface->ndpCacheMutex);
   //Return status code
   return error;
}
Example #27
0
error_t ndpResolve(NetInterface *interface, const Ipv6Addr *ipAddr, MacAddr *macAddr)
{
   NdpCacheEntry *entry;

   //Acquire exclusive access to Neighbor cache
   osAcquireMutex(&interface->ndpCacheMutex);

   //Search the ndpCacheMutex cache for the specified IPv6 address
   entry = ndpFindEntry(interface, ipAddr);

   //Check whether a matching entry has been found
   if(entry)
   {
      //Check the state of the Neighbor cache entry
      if(entry->state == NDP_STATE_INCOMPLETE)
      {
         //Release exclusive access to Neighbor cache
         osReleaseMutex(&interface->ndpCacheMutex);
         //The address resolution is already in progress
         return ERROR_IN_PROGRESS;
      }
      else if(entry->state == NDP_STATE_STALE)
      {
         //Copy the MAC address associated with the specified IPv6 address
         *macAddr = entry->macAddr;

         //Start delay timer
         entry->timestamp = osGetSystemTime();
         //Delay before sending the first probe
         entry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
         //Switch to the DELAY state
         entry->state = NDP_STATE_DELAY;

         //Release exclusive access to Neighbor cache
         osReleaseMutex(&interface->ndpCacheMutex);
         //Successful address resolution
         return NO_ERROR;
      }
      else
      {
         //Copy the MAC address associated with the specified IPv6 address
         *macAddr = entry->macAddr;

         //Release exclusive access to Neighbor cache
         osReleaseMutex(&interface->ndpCacheMutex);
         //Successful address resolution
         return NO_ERROR;
      }
   }

   //If no entry exists, then create a new one
   entry = ndpCreateEntry(interface);

   //Any error to report?
   if(!entry)
   {
      //Release exclusive access to Neighbor cache
      osReleaseMutex(&interface->ndpCacheMutex);
      //Report an error to the calling function
      return ERROR_OUT_OF_RESOURCES;
   }

   //Record the IPv6 address whose MAC address is unknown
   entry->ipAddr = *ipAddr;
   entry->macAddr = MAC_UNSPECIFIED_ADDR;

   //Reset retransmission counter
   entry->retransmitCount = 0;
   //No packet are pending in the transmit queue
   entry->queueSize = 0;

   //Send a multicast Neighbor Solicitation message
   ndpSendNeighborSol(interface, ipAddr);

   //Save the time at which the message was sent
   entry->timestamp = osGetSystemTime();
   //Set timeout value
   entry->timeout = NDP_RETRANS_TIMER;
   //Enter INCOMPLETE state
   entry->state = NDP_STATE_INCOMPLETE;

   //Release exclusive access to Neighbor cache
   osReleaseMutex(&interface->ndpCacheMutex);

   //The address resolution is in progress
   return ERROR_IN_PROGRESS;
}
Example #28
0
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
{
   error_t error;

   //Check input parameters
   if(!socket || !remoteIpAddr)
      return ERROR_INVALID_PARAMETER;

#if (TCP_SUPPORT == ENABLED)
   //Connection-oriented socket?
   if(socket->type == SOCKET_TYPE_STREAM)
   {
      //Save port number and IP address of the remote host
      socket->remoteIpAddr = *remoteIpAddr;
      socket->remotePort = remotePort;

      //Select the source address and the relevant network interface
      //to use when establishing the connection
      error = ipSelectSourceAddr(&socket->interface,
         &socket->remoteIpAddr, &socket->localIpAddr);
      //Any error to report?
      if(error) return error;

      //Make sure the source address is valid
      if(ipIsUnspecifiedAddr(&socket->localIpAddr))
         return ERROR_NOT_CONFIGURED;

      //Enter critical section
      osAcquireMutex(&socketMutex);
      //Establish TCP connection
      error = tcpConnect(socket);
      //Leave critical section
      osReleaseMutex(&socketMutex);
   }
   else
#endif
   //Connectionless socket?
   if(socket->type == SOCKET_TYPE_DGRAM)
   {
      //Save port number and IP address of the remote host
      socket->remoteIpAddr = *remoteIpAddr;
      socket->remotePort = remotePort;
      //No error to report
      error = NO_ERROR;
   }
   //Raw socket?
   else if(socket->type == SOCKET_TYPE_RAW_IP)
   {
      //Save the IP address of the remote host
      socket->remoteIpAddr = *remoteIpAddr;
      //No error to report
      error = NO_ERROR;
   }
   //Socket type not supported...
   else
   {
      //Invalid socket type
      error = ERROR_INVALID_SOCKET;
   }

   //Return status code
   return error;
}
Example #29
0
void mib2Unlock(void)
{
   //Leave critical section
   osReleaseMutex(&mib2Mutex);
}
Example #30
0
error_t socketReceiveEx(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort,
   IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
{
   error_t error;

   //Make sure the socket handle is valid
   if(!socket)
      return ERROR_INVALID_PARAMETER;

   //Enter critical section
   osAcquireMutex(&socketMutex);

#if (TCP_SUPPORT == ENABLED)
   //Connection-oriented socket?
   if(socket->type == SOCKET_TYPE_STREAM)
   {
      //Receive data
      error = tcpReceive(socket, data, size, received, flags);

      //Output parameters
      if(srcIpAddr)
         *srcIpAddr = socket->remoteIpAddr;
      if(srcPort)
         *srcPort = socket->remotePort;
      if(destIpAddr)
         *destIpAddr = socket->localIpAddr;
   }
   else
#endif
#if (UDP_SUPPORT == ENABLED)
   //Connectionless socket?
   if(socket->type == SOCKET_TYPE_DGRAM)
   {
      //Receive UDP datagram
      error = udpReceiveDatagram(socket, srcIpAddr,
         srcPort, destIpAddr, data, size, received, flags);
   }
   else
#endif
#if (RAW_SOCKET_SUPPORT == ENABLED)
   //Raw socket?
   if(socket->type == SOCKET_TYPE_RAW_IP)
   {
      //Receive a raw IP packet
      error = rawSocketReceiveIpPacket(socket,
         srcIpAddr, destIpAddr, data, size, received, flags);
   }
   else if(socket->type == SOCKET_TYPE_RAW_ETH)
   {
      //Receive a raw Ethernet packet
      error = rawSocketReceiveEthPacket(socket, data, size, received, flags);
   }
   else
#endif
   //Socket type not supported...
   {
      //No data can be read
      *received = 0;
      //Invalid socket type
      error = ERROR_INVALID_SOCKET;
   }

   //Leave critical section
   osReleaseMutex(&socketMutex);
   //Return status code
   return error;
}