Exemplo n.º 1
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;
}
Exemplo n.º 2
0
error_t ipv4JoinMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
{
    error_t error;
    uint_t i;
    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
    osMutexAcquire(interface->ipv4FilterMutex);

    //Loop through filter table entries
    for(i = 0; i < interface->ipv4FilterSize; i++)
    {
        //Check whether the table already contains the specified IPv4 address
        if(interface->ipv4Filter[i].addr == groupAddr)
        {
            //Increment the reference count
            interface->ipv4Filter[i].refCount++;
            //Release exclusive access to the IPv4 filter table
            osMutexRelease(interface->ipv4FilterMutex);
            //No error to report
            return NO_ERROR;
        }
    }

    //The IPv4 filter table is full ?
    if(i >= IPV4_FILTER_MAX_SIZE)
    {
        //Release exclusive access to the IPv4 filter table
        osMutexRelease(interface->ipv4FilterMutex);
        //A new entry cannot be added
        return ERROR_FAILURE;
    }

    //Map the multicast IPv4 address to a MAC-layer address
    ipv4MapMulticastAddrToMac(groupAddr, &macAddr);
    //Add the corresponding address to the MAC filter table
    error = ethAcceptMulticastAddr(interface, &macAddr);

    //Ensure the MAC filter table was successfully updated
    if(!error)
    {
        //Now we can safely add a new entry to the table
        interface->ipv4Filter[i].addr = groupAddr;
        //Initialize the reference count
        interface->ipv4Filter[i].refCount = 1;
        //Adjust the size of the IPv4 filter table
        interface->ipv4FilterSize++;

#if (IGMP_SUPPORT == ENABLED)
        //Report multicast group membership to the router
        igmpJoinGroup(interface, &interface->ipv4Filter[i]);
#endif
    }

    //Release exclusive access to the IPv4 filter table
    osMutexRelease(interface->ipv4FilterMutex);
    //Return status code
    return error;
}
Exemplo n.º 3
0
error_t ipv4SendPacket(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
                       uint16_t fragId, uint16_t fragOffset, ChunkedBuffer *buffer, size_t offset, uint8_t timeToLive)
{
    error_t error;
    size_t length;
    Ipv4Addr destIpAddr = 0;
    MacAddr destMacAddr;
    Ipv4Header *packet;

    //Is there enough space for the IPv4 header?
    if(offset < sizeof(Ipv4Header))
        return ERROR_INVALID_PARAMETER;

    //Make room for the header
    offset -= sizeof(Ipv4Header);
    //Calculate the size of the entire packet, including header and data
    length = chunkedBufferGetLength(buffer) - offset;

    //Point to the IPv4 header
    packet = chunkedBufferAt(buffer, offset);

    //Format IPv4 header
    packet->version = IPV4_VERSION;
    packet->headerLength = 5;
    packet->typeOfService = 0;
    packet->totalLength = htons(length);
    packet->identification = htons(fragId);
    packet->fragmentOffset = htons(fragOffset);
    packet->timeToLive = timeToLive;
    packet->protocol = pseudoHeader->protocol;
    packet->headerChecksum = 0;
    packet->srcAddr = pseudoHeader->srcAddr;
    packet->destAddr = pseudoHeader->destAddr;

    //Calculate IP header checksum
    packet->headerChecksum = ipCalcChecksumEx(buffer, offset, packet->headerLength * 4);

    //Ensure the source address is valid
    error = ipv4CheckSourceAddr(interface, pseudoHeader->srcAddr);
    //Invalid source address?
    if(error) return error;

    //Destination address is the unspecified address?
    if(pseudoHeader->destAddr == IPV4_UNSPECIFIED_ADDR)
    {
        //Destination address is not acceptable
        error = ERROR_INVALID_ADDRESS;
    }
    //Destination address is the loopback address?
    else if(pseudoHeader->destAddr == IPV4_LOOPBACK_ADDR)
    {
        //Not yet implemented...
        error = ERROR_NOT_IMPLEMENTED;
    }
    //Destination address is a broadcast address?
    else if(ipv4IsBroadcastAddr(interface, pseudoHeader->destAddr))
    {
        //Destination IPv4 address
        destIpAddr = pseudoHeader->destAddr;
        //Make use of the broadcast MAC address
        destMacAddr = MAC_BROADCAST_ADDR;
        //No error to report
        error = NO_ERROR;
    }
    //Destination address is a multicast address?
    else if(ipv4IsMulticastAddr(pseudoHeader->destAddr))
    {
        //Destination IPv4 address
        destIpAddr = pseudoHeader->destAddr;
        //Map IPv4 multicast address to MAC-layer multicast address
        error = ipv4MapMulticastAddrToMac(pseudoHeader->destAddr, &destMacAddr);
    }
    //Destination host is in the local subnet?
    else if(ipv4IsInLocalSubnet(interface, pseudoHeader->destAddr))
    {
        //Destination IPv4 address
        destIpAddr = pseudoHeader->destAddr;
        //Resolve host address before sending the packet
        error = arpResolve(interface, pseudoHeader->destAddr, &destMacAddr);
    }
    //Destination host is outside the local subnet?
    else
    {
        //Make sure the default gateway is properly set
        if(interface->ipv4Config.defaultGateway != IPV4_UNSPECIFIED_ADDR)
        {
            //Use the default gateway to forward the packet
            destIpAddr = interface->ipv4Config.defaultGateway;
            //Perform address resolution
            error = arpResolve(interface, interface->ipv4Config.defaultGateway, &destMacAddr);
        }
        else
        {
            //There is no route to the outside world...
            error = ERROR_NO_ROUTE;
        }
    }

    //Successful address resolution?
    if(!error)
    {
        //Debug message
        TRACE_INFO("Sending IPv4 packet (%u bytes)...\r\n", length);
        //Dump IP header contents for debugging purpose
        ipv4DumpHeader(packet);

        //Send Ethernet frame
        error = ethSendFrame(interface, &destMacAddr, buffer, offset, ETH_TYPE_IPV4);
    }
    //Address resolution is in progress?
    else if(error == ERROR_IN_PROGRESS)
    {
        //Debug message
        TRACE_INFO("Enqueuing IPv4 packet (%u bytes)...\r\n", length);
        //Dump IP header contents for debugging purpose
        ipv4DumpHeader(packet);

        //Enqueue packets waiting for address resolution
        error = arpEnqueuePacket(interface, destIpAddr, buffer, offset);
    }
    //Address resolution failed?
    else
    {
        //Debug message
        TRACE_WARNING("Cannot map IPv4 address to Ethernet address!\r\n");
    }

    //Return status code
    return error;
}