搜索
bottom↓
回复: 1

嵌入式TCP/IP学习笔记-ARP协议【恢复】

[复制链接]

出0入0汤圆

发表于 2008-12-17 11:24:38 | 显示全部楼层 |阅读模式
ARP.C 

//========================================================================== 

//  嵌入式 TCP/IP 协议栈 MSC51 专用版 

// ARP.C 

//  作     者:南开大学-李章林 

//  注     释:李清林 

//  日     期:2008 年3 月 

//  声     明:英文注释由作者李章林添加,中文注释由■李清林■添加。 

//        转载时请保留上述信息。 

//  成都理工学院/应用数字系/应用数字专业 

//========================================================================== 

#include "..\GloblDef\GloblDef.h" 

#include "..\TCPIP\TCPIPmem.h" 

#include "..\TCPIP\IP.h" 

#include "..\Netif\etherif.h" 

#include "..\Netif\ARP.h" 

#include "..\TCPIP\Netif.h" 

 

//  本机以太网网卡物理地址 

BYTE DT_XDATA EtherAddrAny[ETHER_ADDR_LEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; 

// ARP  高速缓存表 

struct SARPEntry DT_XDATA ARPTable[ARP_ENTRY_MAX_NUM]; 

 

//========================================================================== 

//  嵌入式 TCP/IP 协议栈 MSC51 专用版 

//  作     者:南开大学-李章林 

//  注     释:李清林 

//  日     期:2008 年3 月 

//  声     明:英文注释由作者李章林添加,中文注释由■李清林■添加。 

//        转载时请保留上述信息。 

//  成都理工学院/应用数字系/应用数字专业 

//--------------------------------------------------------------- 

//  程序名称:ARPInit= ARP  高速缓存表初始化子程序 

//  入口参数: 

//        无 

//  出口参数: 

//      无 

//========================================================================== 

void ARPInit() REENTRANT_MUL 

{ 

  BYTE i; 

 

  /* set every unit in arp tabel invalid */ 

  // ARP  高速缓存表每个表项的生存时间初始化为零 

  for (i = 0; i < ARP_ENTRY_MAX_NUM; i++) 

    ARPTable.time = 0; ARP.C 

} 

 

//========================================================================== 

//  嵌入式 TCP/IP 协议栈 MSC51 专用版 

//  作     者:南开大学-李章林 

//  注     释:李清林 

//  日     期:2008 年3 月 

//  声     明:英文注释由作者李章林添加,中文注释由■李清林■添加。 

//        转载时请保留上述信息。 

//  成都理工学院/应用数字系/应用数字专业 

//--------------------------------------------------------------- 

//  程序名称:ARPQuery= ARP  发送请求子程序 

//  功    能:填写数据链路层首部和 ARP 数据报文内容 

//       (1).以太网数据链路层首部的目的网卡物理地址由本机填写????????????? 

//       (2).以太网数据链路层首部的源网卡物理地址由网络接口设备填写??????? 

//       (3).ARP 报文接收端以太网物理地址由本机填写???????????????????????? 

//        (4).ARP 报文发送端以太网物理地址由网络接口设备填写???????????????? 

//       (5).ARP 报文接收端 IP 地址由入口参数填写???????????????????????????? 

//       (6).ARP 报文发送端 IP 地址由网络接口设备填写???????????????????????? 

//  入口参数: 

//       *NetIf=网络接口设备指针 

//     DestIP=目的IP 地址 

//  出口参数: 

//     SMemHead=缓存控制块指针 

//========================================================================== 

struct SMemHead DT_XDATA * ARPQuery(struct SNetIf DT_XDATA *NetIf, 

                  IP_ADDR DestIP) REENTRANT_SIG 

{ 

  struct SMemHead DT_XDATA *MemHead;       //   缓存控制块指针 

  struct SEtherHead DT_XDATA *EtherHead;    //  数据链路层报文首部指针 

  struct SARPPacket DT_XDATA *ARPPacket;    //  ARP 数据报文指针 

 

  //  缓存池申请内存空间(准备填充 ARP 数据报文以及以太网数据链路层首部) 

  if ((MemHead = MemAllocate(sizeof(struct SARPPacket) + 

      sizeof(struct SEtherHead))) == NULL) 

    return NULL;             //  分配失败,返回 NULL 

  //  以太网数据链路层报文首部指针指向申请到的缓存控制块(数据区域) 

  EtherHead = (struct SEtherHead DT_XDATA *)(MemHead->pStart); 

  // ARP 数据报文指针指向申请空间 ARP  数据报文存放位置 

  ARPPacket = (struct SARPPacket DT_XDATA *)(MemHead->pStart + 

      sizeof(struct SEtherHead)); 

//----------------------------------------------------------------- 

//   填写以太网数据链路层首部 

//----------------------------------------------------------------- 

  //  填写以太网数据链路层首部的.DestAddr 域(以太网目的网卡地址) ARP.C 

  MemCopy(EtherHead->DestAddr,EtherAddrAny,ETHER_ADDR_LEN); 

  //  填写以太网数据链路层首部的.ScrAddr 域(以太网源网卡地址) 

  //  网络接口设备指针中获取以太网源网卡地址 

  MemCopy(EtherHead->ScrAddr , 

  ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN); 

  //  填写以太网数据链路层首部的.type 域(以太网帧类型=ARP 数据包[0x0806]) 

  EtherHead->type = htons(ETHER_TYPE_ARP); 

//---------------------------------------------------------------------------- 

//   填写 ARP 数据报文首部 

//---------------------------------------------------------------------------- 

  //  填写 ARP  数据报文硬件地址长度=6(因为网卡地址=48 位) 

  ARPPacket->HardWareAddrLen  = ARP_HARDWARE_ADDR_LEN_ETHER; 

  //  填写 ARP  数据报文硬件类型=0x0001  代表以太网 

  ARPPacket->HardwareType    = htons(ARP_HARDWARE_TYPE_ETHER); 

  //  填写 ARP  数据报文协议长度=4 (因为 IP 地址=32 位) 

  ARPPacket->ProtocolAddrLen  = ARP_PROTOCOL_ADDR_LEN_IP; 

  //  填写 ARP  数据报文协议类型=0x0800  代表网际协议 

  ARPPacket->ProtocolType    = htons(ARP_PROTOCOL_TYPE_IP); 

  //  填写 ARP  数据报文操作码=0x0001(ARP 请求) 

  ARPPacket->type        = htons(ARP_TYPE_ARP_REQUEST); 

//---------------------------------------------------------------------------- 

//   填写 ARP 数据报文内容 

//---------------------------------------------------------------------------- 

  //  填写 ARP 数据报文接收端 IP 地址(入口参数获取) 

  ARPPacket->IPDestAddr  = DestIP; 

  //  填写 ARP 数据报文发送端 IP 地址(网络接口设备指针获取) 

  ARPPacket->IPScrAddr = NetIf->IPAddr; 

  //  填写 ARP 数据报文接收端以太网物理地址 

  MemCopy(ARPPacket->EtherDestAddr,EtherAddrAny,ETHER_ADDR_LEN); 

  //  填写 ARP 数据报文发送端以太网物理地址(网络接口设备指针获取) 

  MemCopy(ARPPacket->EtherScrAddr,  

  ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN); 

  return MemHead; 

} 

 

//========================================================================== 

// deel with a input arp packet. if send a reply is needed return 

// this replay packet, oterhwise return NULL 

//  嵌入式 TCP/IP 协议栈 MSC51 专用版 

//  作     者:南开大学-李章林 

//  注     释:李清林 

//  日     期:2008 年3 月 

//  声     明:英文注释由作者李章林添加,中文注释由■李清林■添加。 

//        转载时请保留上述信息。 

//  成都理工学院/应用数字系/应用数字专业 ARP.C 

//--------------------------------------------------------------- 

//  程序名称:ARPInput=ARP 接收子程序 

//  入口参数: 

//      MemHead:缓存控制块指针 

//       *NetIf=网络接口设备指针 

//  出口参数: 

//     MemHead:  缓存控制块指针 

//========================================================================== 

struct SMemHead DT_XDATA *ARPInput(struct SMemHead DT_XDATA *MemHead, 

     struct SNetIf DT_XDATA *NetIf) REENTRANT_MUL 

{ 

  struct SEtherHead DT_XDATA *EtherHead;  //  以太网数据链路层报文首部指针 

  struct SARPPacket DT_XDATA *ARPPacket;  // ARP 数据报文指针 

 

  //  以太网数据链路层首部指针指向缓存控制块 

  EtherHead = (struct SEtherHead DT_XDATA *)(MemHead->pStart); 

  // ARP 数据报文指针指向缓存控制块 ARP 数据报文位置 

  ARPPacket = (struct SARPPacket DT_XDATA *)(MemHead->pStart + 

        sizeof(struct SEtherHead)); 

  switch(ntohs(ARPPacket->type))  //  检查 ARP 数据报文类型 

  { 

    case ARP_TYPE_ARP_REQUEST:  // ARP 请求报文 

//---------------------------------------------------------------------------- 

//  如果 ARP 报文中的目的 IP 地址=网络接口设备中的 IP 地址 

//---------------------------------------------------------------------------- 

      if (ARPPacket->IPDestAddr == NetIf->IPAddr) 

      { 

        // send arp replay , fill Ether head 

//---------------------------------------------------------------------------- 

//   发送 ARP 应答报文,填写以太网数据链路层首部 

//---------------------------------------------------------------------------- 

        //  填写链路层首部的.DestAddr 域(以太网目的网卡物理地址) 

        MemCopy(EtherHead->DestAddr,ARPPacket->EtherScrAddr,  

            ETHER_ADDR_LEN); 

        //  填写链路层首部的.ScrAddr 域(以太网源网卡物理地址) 

        //  网络接口设备中获取源网卡物理地址 

        MemCopy(EtherHead->ScrAddr,  

          ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr, 

          ETHER_ADDR_LEN); 

        //  填写链路层首部的.type 域(以太网帧类型=ARP 数据包[0x0806]) 

        EtherHead->type = htons(ETHER_TYPE_ARP); 

//---------------------------------------------------------------------------- 

//   发送 ARP 应答报文,填写 ARP 报文 

//---------------------------------------------------------------------------- 

/* copy source part to dest part.include Ether addr and Ip addr */ ARP.C 

        //  填写 ARP 应答报文接收端网卡物理地址和接收端 IP 地址 

        //  =ARP 请求报文的发送端网卡物理地址和发送端 IP 地址 

        MemCopy(ARPPacket->EtherDestAddr,ARPPacket->EtherScrAddr,  

          (sizeof(IP_ADDR) + ETHER_ADDR_LEN)); 

        /* fill source part. include Ether addr and Ip addr*/ 

        //  填写 ARP 应答报文发送端 IP 地址=网络接口设备的 IP 地址 

        ARPPacket->IPScrAddr = NetIf->IPAddr; 

        //  填写 ARP 应答报文发送端网卡物理地址 

        //  =网络接口设备的网卡物理地址 

        MemCopy(ARPPacket->EtherScrAddr,  

          ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr, 

          ETHER_ADDR_LEN); 

        /* arp type */ 

        //  填写 ARP 应答报文的操作码=ARP 应答 

        ARPPacket->type = htons(ARP_TYPE_ARP_REPLY); 

        return MemHead; 

      } 

      break; 

    case ARP_TYPE_ARP_REPLY:    // ARP 应答报文 

      /* add to arp table */ 

      ARPAddEntry(ARPPacket);  //  添加网卡物理地址到高速缓存表 

      break; 

  } 

/* for any case except ARP_TYPE_ARP_REQUEST for this IP,  

arp packet is released */ 

  MemFree(MemHead);               //   释放缓冲控制块 

  /* no packet need send */ 

  return NULL; 

} 

 

//========================================================================== 

/* add a entry to arp table */ 

//  嵌入式 TCP/IP 协议栈 MSC51 专用版 

//  作     者:南开大学-李章林 

//  注     释:李清林 

//  日     期:2008 年3 月 

//  声     明:英文注释由作者李章林添加,中文注释由■李清林■添加。 

//        转载时请保留上述信息。 

//  成都理工学院/应用数字系/应用数字专业 

//--------------------------------------------------------------- 

//  程序名称:ARPAddEntry=ARP 高速缓存表添加网卡物理地址子程序 

//  入口参数: 

//       ARPPacket= ARP 报文指针 

//  出口参数: 

//      无 ARP.C 

//========================================================================== 

void ARPAddEntry(struct SARPPacket DT_XDATA *ARPPacket) REENTRANT_MUL 

{ 

  BYTE i; 

  WORD MinTime;    //  最小生存时间 

  BYTE iToReplace; /* index of entry going to be replace */ 

 

  //  高速缓存表查找一个空白表项 

  for (i = 0; i < ARP_ENTRY_MAX_NUM ; i++) 

  { 

    if (ARPTable.time == 0)    //  如果找到空白项 

    { 

      iToReplace = i;           //  记录下索引号 

      break; 

    } 

  } 

  if (i == ARP_ENTRY_MAX_NUM)     //  如果未找到空白项 

  {                //  寻找生存时间最老的一个表项 

    MinTime = ARP_ENTRY_TIME_OUT; 

    iToReplace = 0; 

    for (i = 0 ; i < ARP_ENTRY_MAX_NUM ; i++) 

    { 

      if (MinTime> ARPTable.time) 

      { 

        MinTime = ARPTable.time;  //    找到生存时间最老的表项 

        iToReplace = i;        //  记录下索引号 

      } 

    } 

  } 

  /* replace the entry */ 

  //  填写网卡物理地址=ARP 报文指针->源网卡源物理地址 

  MemCopy(ARPTable[iToReplace].EtherAddr,ARPPacket->EtherScrAddr,ETHER_ADDR_LEN); 

  //  填写 IP 地址=ARP 报文指针->源 IP 地址 

  ARPTable[iToReplace].IPAddr = ARPPacket->IPScrAddr; 

  /* start timer */ 

  //  填写生存时间=0xFFFF 

  ARPTable[iToReplace].time = ARP_ENTRY_TIME_OUT; 

} 

 

//========================================================================== 

/* find IPAddr in arptable copy it to EtherAddr. if can't find return false*/ 

//  嵌入式 TCP/IP 协议栈 MSC51 专用版 

//  作     者:南开大学-李章林 

//  注     释:李清林 

//  日     期:2008 年3 月 ARP.C 

//  声      明:英文注释由作者李章林添加,中文注释由■李清林■添加。 

//        转载时请保留上述信息。 

//  成都理工学院/应用数字系/应用数字专业 

//--------------------------------------------------------------- 

//  程序名称:ARPFind=高速缓存表查找子程序 

//  功     能:ARP  高速缓存表查找 IP 地址对应的网卡物理地址 

//  入口参数: 

//     IPAddr=  待查找 IP 地址 

//  出口参数: 

//     EtherAddr[]=IPAddr 地址相对应的以太网网卡物理地址 

//========================================================================== 

BOOL ARPFind(BYTE EtherAddr[],IP_ADDR IPAddr) REENTRANT_SIG 

{ 

  BYTE i; 

 

  for (i = 0 ; i < ARP_ENTRY_MAX_NUM ; i++) 

  { 

    if (ARPTable.time != 0)    //  如果当前表项的生存时间有效 

    { 

      if (ARPTable.IPAddr == IPAddr)  //  如果找到规定的 IP 地址 

      {  //   高速缓存表当前表项的网卡物理地址拷贝到数组 

        MemCopy(EtherAddr,ARPTable.EtherAddr,ETHER_ADDR_LEN); 

        return (TRUE); 

      } 

    } 

  } 

  return (FALSE);          //  未找到入口参数规定的 IP 地址 

} 

 

 

//========================================================================== 

//  嵌入式 TCP/IP 协议栈 MSC51 专用版 

//  作     者:南开大学-李章林 

//  注     释:李清林 

//  日     期:2008 年3 月 

//  声     明:英文注释由作者李章林添加,中文注释由■李清林■添加。 

//        转载时请保留上述信息。 

//  成都理工学院/应用数字系/应用数字专业 

//--------------------------------------------------------------- 

//  程序名称:ARPTimer=ARP  定时器化子程序 

//  功     能:每隔一定的时间将高速缓存表表项的生存时间递减 

//  入口参数: 

//        无 

//  出口参数: 

//      无 ARP.C 

//========================================================================== 

void ARPTimer() REENTRANT_MUL 

{ 

  BYTE i; 

 

  for (i = 0 ; i < ARP_ENTRY_MAX_NUM ; i++) 

  { 

    if (ARPTable.time != 0) //  如果当前表项生存时间不为零 

    { 

      ARPTable.time--;     //  当前表项的生存时间递减 

    } 

  } 

} 

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
头像被屏蔽

出0入0汤圆

发表于 2010-2-14 21:20:55 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 17:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表