Exemplo n.º 1
0
/*-----------------------------------------------------------------------------
 * Method: void checkCachedPackets(struct sr_instance* sr, int cachedArp)
 *
 * searches our packet cache for a matching ip in arpCache[cachedArp]. if we 
 * find a match, we forward the packet. if we do not find a match we need an
 * arp cache entry for it. make sure we have been waiting at least 3 seconds
 * before we send the src icmp unreachable packets. this does not drop the 
 * packet, it just looks every 3rd second to see if we have a response. every
 * time we look, we try to increment the arp counter
 *---------------------------------------------------------------------------*/
void checkCachedPackets(struct sr_instance* sr, int cachedArp)
{
    int i, arpMatch;
    for (i = 0; i < PACKET_CACHE_SIZE; i++) {
        if (packetCache[i].len > 0) {
            // if we have a packet waiting
            if (packetCache[i].arps <= 5) {
                // and we have not sent 5 arps for this packet yet
                if ((arpMatch = arpSearchCache(packetCache[i].tip)) > -1) {
                    // and we have an arp match for our packet's next hop
                    forwardPacket(sr, (uint8_t*)&packetCache[i].packet, packetCache[i].len,
                            // send it along
                            packetCache[i].nexthop->interface, arpReturnEntryMac(arpMatch));
                    packetCache[i].len = 0;
                } else {
                    /* wait three seconds between each arp request */
                    if ((int)(difftime(time(NULL), packetCache[i].timeCached))%3 < 1) {
                        arpSendRequest(sr, sr_get_interface(sr, packetCache[i].nexthop->interface),
                                packetCache[i].nexthop->gw.s_addr);
                        packetCache[i].arps++;
                    }
                }
            } else {
                /* then */
                icmpSendUnreachable(sr, (uint8_t*)&packetCache[i].packet, packetCache[i].len,
                        packetCache[i].nexthop->interface, ICMP_HOST_UNREACHABLE);
                packetCache[i].len = 0;
            }
        }
    }
}
Exemplo n.º 2
0
/*-----------------------------------------------------------------------------
 * Method: void cachePacket(struct sr_instance* sr, uint8_t* packet,
 *                              unsigned int len, struct sr_rt* rtptr)
 *
 * sends a request for the hwaddr of the ipaddr we have, stores our packet
 * until we have an arp entry that matches the ip, then sends the packet
 *---------------------------------------------------------------------------*/
void cachePacket(
        struct sr_instance* sr,
        uint8_t* packet,
        unsigned int len,
        struct sr_rt* rtptr)
{
    struct ip* ipHdr = (struct ip*)(packet+14);
    int i;

    /* request arp for the unidentified packet */
    arpSendRequest(sr, sr_get_interface(sr, rtptr->interface), rtptr->gw.s_addr);

    /* look through packet cache for the first empty entry */
    for (i = 0; i < PACKET_CACHE_SIZE; i++) {
        if (packetCache[i].len == 0) 
            break;
    }

    /* copy packet data to cache */
    memcpy(&packetCache[i].packet, packet, len);
    packetCache[i].nexthop = rtptr;
    packetCache[i].tip = ipHdr->ip_dst.s_addr;
    packetCache[i].len = len;
    packetCache[i].arps = 1;
    packetCache[i].timeCached = time(NULL);

    /* dump cache
    uint8_t* ptr = packetCache[i].packet;
    printf("\nnexthop: %s\n", inet_ntoa(packetCache[i].nexthop->gw));
    printf("tip: %8.8x\n", packetCache[i].tip);
    printf("len: %d\n", packetCache[i].len);
    printf("arps: %d\n", packetCache[i].arps);
    for (i = 0; i < len; i++)
        printf("%2.2x", *ptr++);
    printf("\n");
    */
}
Exemplo n.º 3
0
void arpTick(NetInterface *interface)
{
   uint_t i;
   time_t time;
   ArpCacheEntry *entry;

   //Get current time
   time = osGetTickCount();

   //Acquire exclusive access to ARP cache
   osMutexAcquire(interface->arpCacheMutex);

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

      //INCOMPLETE state?
      if(entry->state == ARP_STATE_INCOMPLETE)
      {
         //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 < ARP_MAX_REQUESTS)
            {
               //Retransmit ARP request
               arpSendRequest(interface, interface->ipv4Config.addr,
                  entry->ipAddr, &MAC_BROADCAST_ADDR);

               //Save the time at which the packet was sent
               entry->timestamp = time;
               //Set timeout value
               entry->timeout = ARP_REQUEST_TIMEOUT;
            }
            else
            {
               //Drop packets that are waiting for address resolution
               arpFlushQueuedPackets(interface, entry);
               //The entry should be deleted since address resolution has failed
               entry->state = ARP_STATE_NONE;
            }
         }
      }
      //REACHABLE state?
      else if(entry->state == ARP_STATE_REACHABLE)
      {
         //Periodically time out ARP cache entries
         if((time - entry->timestamp) >= entry->timeout)
         {
            //Save current time
            entry->timestamp = osGetTickCount();
            //Enter STALE state
            entry->state = ARP_STATE_STALE;
         }
      }
      //DELAY state?
      else if(entry->state == ARP_STATE_DELAY)
      {
         //Wait for the specified delay before sending the first probe
         if((time - entry->timestamp) >= entry->timeout)
         {
            //Send a point-to-point ARP request to the host
            arpSendRequest(interface, interface->ipv4Config.addr,
               entry->ipAddr, &entry->macAddr);

            //Save the time at which the packet was sent
            entry->timestamp = time;
            //Set timeout value
            entry->timeout = ARP_PROBE_TIMEOUT;
            //Switch to the PROBE state
            entry->state = ARP_STATE_PROBE;
         }
      }
      //PROBE state?
      else if(entry->state == ARP_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 < ARP_MAX_PROBES)
            {
               //Send a point-to-point ARP request to the host
               arpSendRequest(interface, interface->ipv4Config.addr,
                  entry->ipAddr, &entry->macAddr);

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

   //Release exclusive access to ARP cache
   osMutexRelease(interface->arpCacheMutex);
}
Exemplo n.º 4
0
error_t arpResolve(NetInterface *interface, Ipv4Addr ipAddr, MacAddr *macAddr)
{
   ArpCacheEntry *entry;

   //Acquire exclusive access to ARP cache
   osMutexAcquire(interface->arpCacheMutex);

   //Search the ARP cache for the specified IPv4 address
   entry = arpFindEntry(interface, ipAddr);

   //Check whether a matching entry has been found
   if(entry)
   {
      //Check the state of the ARP entry
      if(entry->state == ARP_STATE_INCOMPLETE)
      {
         //Release exclusive access to ARP cache
         osMutexRelease(interface->arpCacheMutex);
         //The address resolution is already in progress
         return ERROR_IN_PROGRESS;
      }
      else if(entry->state == ARP_STATE_STALE)
      {
         //Copy the MAC address associated with the specified IPv4 address
         *macAddr = entry->macAddr;

         //Start delay timer
         entry->timestamp = osGetTickCount();
         //Delay before sending the first probe
         entry->timeout = ARP_DELAY_FIRST_PROBE_TIME;
         //Switch to the DELAY state
         entry->state = ARP_STATE_DELAY;

         //Release exclusive access to ARP cache
         osMutexRelease(interface->arpCacheMutex);
         //Successful address resolution
         return NO_ERROR;
      }
      else
      {
         //Copy the MAC address associated with the specified IPv4 address
         *macAddr = entry->macAddr;

         //Release exclusive access to ARP cache
         osMutexRelease(interface->arpCacheMutex);
         //Successful address resolution
         return NO_ERROR;
      }
   }

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

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

   //Record the IPv4 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 an ARP request
   arpSendRequest(interface, interface->ipv4Config.addr,
      entry->ipAddr, &MAC_BROADCAST_ADDR);

   //Save the time at which the packet was sent
   entry->timestamp = osGetTickCount();
   //Set timeout value
   entry->timeout = ARP_REQUEST_TIMEOUT;
   //Enter INCOMPLETE state
   entry->state = ARP_STATE_INCOMPLETE;

   //Release exclusive access to ARP cache
   osMutexRelease(interface->arpCacheMutex);

   //The address resolution is in progress
   return ERROR_IN_PROGRESS;
}