⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netarp.c

📁 uC/IP Release Notes These release notes for uC/IP are divided into the following sections
💻 C
📖 第 1 页 / 共 2 页
字号:
    // This search for the oldest one is done here, and not in the first for loop 
    // since I wanted to keep the normal succesfull lookup as fast as possible.
    
    // **** Find oldest entry
    for (traverse = 0; traverse < ARP_ENTRIES; traverse++) {
      switch (arpEntries[traverse].state) {
        case ARP_PENDING:
        case ARP_RESOLVED:
          if (arpEntries[traverse].expire < oldestAge) {
            oldestAge = arpEntries[traverse].expire;
            oldest = traverse;
          }
          break;
      }
    }

    // **** IF we didn't find any oldest THEN RETURN NULL
    if (oldest == -1) return NULL;

    // Set traverse to oldest
    traverse = oldest;

    // ***** Remove oldest from ARP cache table
    arpRemove(traverse);

    // We have a "free" arp entry, clear it
    memset(&arpEntries[traverse], 0, sizeof(arpEntry));

    // Update ARP allocated statistics
    arpStats.alloc--;
  }

  // Update ARP allocated statistics
  arpStats.alloc++;
  // Update max. ARP allocated statistics
  if (arpStats.alloc > arpStats.maxAlloc) 
    arpStats.maxAlloc = arpStats.alloc;

  // **** Fill in new ARP entry
  // Fill in new infos...
  arpEntries[traverse].ip = ip;
  // Allow an ARP request to be sent now
  arpEntries[traverse].expire = time(NULL) + mySetup.arpExpire;
  // Since this is a new entry, we assume this ip is to be resolved
  arpEntries[traverse].state = ARP_PENDING;
  // Just in case, no packet queued
  arpEntries[traverse].packet = NULL;
  // Get index
  index = arpEntries[traverse].ip & (ARP_TABLE_SIZE - 1);
  // **** Insert new entry in ARP cache table
  arpEntries[traverse].next = arpTable[index];
  arpTable[index] = &arpEntries[traverse];

//  arpEntries[traverse].next = arpTable[arpEntries[traverse].ip & (ARP_TABLE_SIZE - 1)];
//  arpTable[arpEntries[traverse].ip & (ARP_TABLE_SIZE - 1)] = &arpEntries[traverse];

  TRACE("uCIP: ARP Alloc ADDED NEW IP %d.%d.%d.%d\n", 
      (ip >> 24) & 0xFF,
      (ip >> 16) & 0xFF,
      (ip >> 8)  & 0xFF,
      (ip)       & 0xFF );

  // **** RETURN ARP cache entry allocated
  return &arpEntries[traverse];
}


////////////////////////////////////////////////////////////////////////////////
// Search the ARP cache for given IP, create if not found and specified.
//
static arpEntry *arpLookup(u_long ip, int create)
{
  arpEntry *entry;

  // **** Get first arpEntry
  entry = arpTable[ip & (ARP_TABLE_SIZE - 1)];
  
  // Traverse chain
  while (entry) {
    // Did we find the ip we wanted
    if (entry->ip == ip)
      // Yes, return it
      return entry;

    // **** Go to next entry in chain
    entry = entry->next;
  }

  // We didn't find the ip
  // **** IF we should create a new entry THEN
  if (create)
    // **** RETURN new entry created
    return arpAlloc(ip);

  // **** RETURN no entry found or allocated
  return NULL;
}


int arpRequest(u_long ip)
{
  NBuf* pNBuf;
  int len;
  arpPacket arp;

  // **** Build arp request packet
  // Fill ethernet header
  memset(arp.ether.dst, 0xFF, sizeof(arp.ether.dst));
  memcpy(arp.ether.src, mySetup.hardwareAddr, sizeof(arp.ether.src));
  arp.ether.protocol = htons(ETHERTYPE_ARP);

  // Fill arp header
  arp.hwType    = htons(1);            // HW TYPE IS ETHER
  arp.hwLength  = 6;                   // 6 bytes long hardware address
  arp.prType    = htons(ETHERTYPE_IP); // TYPE IS IP
  arp.prLength  = 4;                   // 4 bytes IP adresses
  arp.operation = htons(ARP_REQUEST);  // ARP request
  arp.senderIp  = mySetup.localAddr;
  memcpy(arp.senderHw, mySetup.hardwareAddr, sizeof(arp.senderHw));
  arp.targetIp  = htonl(ip);

  // Create NBuf with ARP request
  nGET(pNBuf);
  // If not packet is allocated return FALSE
  if (!pNBuf) {
    // Update stat
    arpStats.nbufError++;
    return FALSE;
  }

  // Append prepared ARP Request
  nAPPEND(pNBuf, (void*)&arp, sizeof(arp), len);
  if (len != sizeof(arp)) {
    nFree(pNBuf);
    return FALSE;
  }

  // Send ARP request
  etherSend(pNBuf);

  // **** RETURN ARP request packet sent
  return TRUE;
}


////////////////////////////////////////////////////////////////////////////////
//
int arpResolve(u_long ip, u_char *hardware, NBuf* pNBuf)
{
  arpEntry *entry;

  // Should this packet be sent to the gateway ?
  if ((ip & mySetup.subnetMask) != mySetup.networkAddr) {
    // Yes, we have a destination outside our network
    // Since we only (currently) support one gateway send it there...

    // **** IF we have a gateway defined THEN
    // Do we have a gateway defined ?
    if (mySetup.gatewayAddr)
      // **** Find entry for gateway
      entry = arpLookup(mySetup.gatewayAddr, TRUE);
    else
      // **** No gateway is defined, indicate no entry found for gateway
      entry = NULL;
  } else {
    // **** ELSE Find entry for host on our network
    entry = arpLookup(ip, TRUE);
  }

  if (!entry) {
    // We didn't get an entry!
    if (pNBuf) nFreeChain(pNBuf);
    return FALSE;
  }

//  TRACE("uCIP: ARP Resolve LOOKUP IP OK %d.%d.%d.%d\n", 
//      ((entry)->ip >> 24) & 0xFF, ((entry)->ip >> 16) & 0xFF,
//      ((entry)->ip >> 8)  & 0xFF, ((entry)->ip)       & 0xFF);

  // Did we get a valid hardware address
  if ((entry->state == ARP_RESOLVED) || (entry->state == ARP_FIXED)) {
//    TRACE("uCIP: ARP Resolve IP IS RESOLVED OR FIXED\n"); 

    // Yes! Copy ethernet address
    memcpy(hardware, entry->hardware, sizeof(entry->hardware));
    // Update expire time
    entry->expire = time(NULL) + mySetup.arpExpire;
    return TRUE;
  }

  // No hardware address found, is IP being resolved ?
  if (entry->state == ARP_PENDING) {
    TRACE("uCIP: ARP Resolve IP IS PENDING\n"); 
    // Is it OK to send a new ARP request ?
    if ( entry->expire - mySetup.arpExpire <= time(NULL) ) {
      // Update expire time
      // Allow a new request to be sent after 1 second
      entry->expire = time(NULL) + mySetup.arpExpire + 1;

      TRACE("uCIP: ARP Resolve REQUEST FOR IP %d.%d.%d.%d\n", 
      ((entry)->ip >> 24) & 0xFF,
      ((entry)->ip >> 16) & 0xFF,
      ((entry)->ip >> 8)  & 0xFF,
      ((entry)->ip)       & 0xFF);

      // **** Send ARP request
      arpRequest(entry->ip);
    }

    // If a new packet is to be sent
    if (pNBuf) {
      // Free old queued packet (if any)
      if (entry->packet) nFreeChain(entry->packet);

      // Queue new packet
      entry->packet = pNBuf;
    }
    return FALSE;
  }

  // This is wrong should never get here
  // Cleanup...
  if (pNBuf) nFreeChain(pNBuf);

  // **** RETURN none found (FALSE)
  return FALSE;
}


////////////////////////////////////////////////////////////////////////////////
//
static void arpRemove(u_long index)
{
  arpEntry *entry, *lastEntry = NULL;

  // **** Get first arpEntry
  entry = arpTable[arpEntries[index].ip & (ARP_TABLE_SIZE - 1)];

  // **** IF this is the index we want removed THEN
  if (&arpEntries[index] == entry)
  {
    // **** Remove entry from chain
    arpTable[arpEntries[index].ip & (ARP_TABLE_SIZE - 1)] =
      arpTable[arpEntries[index].ip & (ARP_TABLE_SIZE - 1)]->next;
    entry = NULL;
  }
  else
  {
    // **** Go to next entry
    lastEntry = entry;
    entry = entry->next;
  }

  // **** WHILE entries in chain
  while (entry)
  {
  // **** IF this is the index we want removed THEN
    if (&arpEntries[index] == entry)
    {
      // **** Remove entry from chain
      lastEntry->next = lastEntry->next->next; 
      // **** RETURN
      return;
    }
    else
    {
      // **** Go to next entry
      lastEntry = entry;
      entry = entry->next; 
    }
  }
}

#pragma warning (pop)
////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -