vxworks 对于arp的处理.doc_第1页
vxworks 对于arp的处理.doc_第2页
vxworks 对于arp的处理.doc_第3页
vxworks 对于arp的处理.doc_第4页
vxworks 对于arp的处理.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

vxworks 对于arp的处理默认分类 2010-05-22 23:54:15 阅读144 评论0 字号:大中小订阅 虽然是vxworks2.0.2版本中的,但是与老土的BSD代码基本一样,事实上,最新的ip协议栈的代码上虽然加上不少新鲜的功能,但是其主体也依旧一样.ifnet也就是协议栈中的接口的概念,跟arp相关处理的最重要的三个成员是: if_ioctl 用于接口上的ioctl命令; if_resolve 用于进行地址解析的函数; if_output 用于在接口上发送数据包;在ipAttach时,这三个值都进行了初始化: pIfp-if_ioctl = (FUNCPTR) ipIoctl; pIfp-if_output = ipOutput; pIfp-if_resolve = muxAddrResFuncGet(mib2Tbl.ifType, 0x800);其中if_resolve的值,实际上就是arpresolve函数.in_ifaddrin_ifaddr是ifaddr的一种特殊形式,即ipv4版本的的ifaddr.当我们给接口配置ip地址时,实际上要生成一个in_ifaddr结构体,并与ifnet相关联.那么它与arp最相关的内容实际上是在ifaddr结构体中,它们是: ifa_rtrequest 这是一个处理arp相关的函数,在后面我们就会解释到它的用处. ia_ifp 与地址相关联的接口.sockaddr_dl数据链路层地址,它的作用就是保存MAC地址,其中与ARP处理相关的内容包括: sdl_len 长度,如果为0,表示mac信息无效,否则就是有效.这点很重要 sdl_data 如果有效,保存有mac信息.llinfo_arp它就是arp控制结构,整个系统中的llinfo_arp通过一个双向链表连接起来,链表头就是全局变量llinfo_arp.(C语言中,总是喜欢将全局变量定义成结构体的名字).其中现在我们关心的内容包括 la_rt 指向相关的rtentry,关于rtentry,后面马上就要讲到了. la_hold 持有的数据,在arp处理中会使用到,现在只知道它是要通过接口发送的数据包; la_asked 计数,用于统计在接收到arp回应前,发出了多少arp请求.rtentry路由表项,每一条路由都由一个rtentry表示,与arp相关的内容包括 rt_ifp 与路由相关联的接口; rt_ifa 与路由相关的接口地址; rt_genmask 用于clone路由时使用; rt_llinfo 指向arp控制结构 rt_gateway 表示下一跳信息,可能保存mac地址. rt_expire arp超时处理使用,如果为0,表示永久有效(用于静态配置的mac).routeroute数据结构主要用于路由处理,它包括两个成员: ro_rt 路由引用的rtentry ro_dst 目的地址数据的发送过程ip_outputip协议栈发送数据总是以int ip_output(m0, opt, ro, flags, imo)struct mbuf *m0;struct mbuf *opt;struct route *ro;int flags;struct ip_moptions *imo;函数调用开发的,对于其中一些特殊情况的处理我们就不会加以描述,我们只对普通情况说明.m0表示要发送的数据,而ro就是发送的路由.ip_output在进行了一大堆的事情之后,就会调用(*ifp-if_output)(ifp, m, (struct sockaddr *)dst, ro-ro_rt);发送数据,其中ifp就是根据路由或者什么的,找到的要outgoing接口.前面我们说过,ipAttach时,就已经指定了if_output为ipOutput函数:int ipOutput ( register struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, struct rtentry *rt0 )上面的几个参数比较明显 ifp为发送数据要使用的接口 m0是要发送的数据; dst是目的地址; rt0是使用的路由;在ipOutput中与arp相关的最重要的一环,就是下面的switch-case语句:switch (dst-sa_family) case AF_INET: if (ifp-if_resolve != NULL) if (!ifp-if_resolve(ac, rt, m, dst, edst) return (0); /* if not yet resolved */ /* If broadcasting on a simplex interface, loopback a copy */ if (m-m_flags & M_BCAST) & (ifp-if_flags & IFF_SIMPLEX) mcopy = m_copy(m, 0, (int)M_COPYALL); off = m-m_pkthdr.len - m-m_len; etype = ETHERTYPE_IP; break; case AF_UNSPEC:当 dst-sa_family为AF_UNSPEC时,说明dst中保存着对方的MAC地址信息,会导致构造二层帧头,然后放到接口的发送队列中. 而接口最终会把它发送出去.但是如果dst是一个ip地址(由AF_INET表示),则情况就不一样了.它首先调用ifp-if_resolve 函数.if_resolve函数的作用就是进行ip地址到MAC地址的映射,如果if_resolve能够直接返回对应的mac地址,则调用返回之后,edst就保存着目的mac,随后就可以构造二层报头,入发送队列(跟AF_UNSPEC时的情况一样),否则就直接返回.由于ipAttach时将if_resolve初始成arpresolve,所以我们还是看看arpresolve:int arpresolve(ac, rt, m, dst, desten)register struct arpcom *ac;register struct rtentry *rt;struct mbuf *m;register struct sockaddr *dst;register u_char *desten;前面说过,arpresolve的功能就是进行目的ip地址到mac地址的转换映射;目的地址由参数dst指定,如果arpresolve能够完成映射,则目的mac填写在desten中.这是由下面的代码段完成的sdl = SDL(rt-rt_gateway);if (rt-rt_expire = 0 | rt-rt_expire tickGet() & sdl-sdl_family = AF_LINK & sdl-sdl_alen != 0) bcopy(LLADDR(sdl), (char *)desten, sdl-sdl_alen);return 1;上面的意思是说,如果当前的arp信息有效,则直接返回mac信息.这个函数中,还处理一些NOARP的处理(对于NOARP的,自己搞定一个mac出来).if (la-la_hold) m_freem(la-la_hold);la-la_hold = m;上面的这段代码说,将要发送的数据保存在la_hold中,从上面可以看出,arp只保存最后一次请求时的数据.同时也说明了,如果arp无效,则要发送的数据是保存在arp控制信息中的,在后面的分析中,我们可以看到,在处理arp回应时,这个被保存的数据,会被协议栈发送.再接着看代码:if (rt-rt_expire) rt-rt_flags &= RTF_REJECT; if (la-la_asked = 0 | (tickGet () - rt-rt_expire = arpRxmitTicks) rt-rt_expire = tickGet(); if (la-la_asked+ sin_addr); else rt-rt_flags |= RTF_REJECT; rt-rt_expire += (sysClkRateGet() * arpt_down); la-la_asked = 0; 上面代码有三个主要功能: 清除RTF_REJECT标志,RTF_REJECT标志用于控制发送arp信息的频度,后面会有专门的讲解. 如果当前发送的arp请求次数小于arp_maxtries(5次),则调用arpshowhas发送arp请求; 否则,设置RTF_REJECT,以抑制ARP请求的发送,并将抑制时间定为20秒;arpwhohas实际调用arprequest,以请求ARP信息: static void arprequest(ac, sip, tip, enaddr)register struct arpcom *ac;register u_long *sip, *tip;register u_char *enaddr;arpwhohas首先构造一个报文,然后调用接口的发送函数:bcopy(caddr_t)etherbroadcastaddr, (caddr_t)eh-ether_dhost, sizeof(eh-ether_dhost);sa.sa_family = AF_UNSPEC; sa.sa_len = sizeof(sa);(*ac-ac_if.if_output)(&ac-ac_if, m, &sa, (struct rtentry *)0);我们可以看到目的mac在这写成了广播地址(全1),而sa.sa_family设置为AF_UNSPEC,这与我们前面描述的ipOutput是一致的(由前面的描述我们知道,这里调用的函数if_output实际上就是ipOutput).我们也知道,这次调用由于给的目的地址参数sa_family为AF_UNSPEC,所以会导致直接把要发送的数据放到接口发送队列,而不会再调用if_resolve造成死循环.arp的输入处理现在,该看看另外一个分支了,arp输入处理,arp的输入由arpintr驱动,它调用in_arpinput以处理跟ip相碰的arp报文:la = arplookup(isaddr.s_addr, itaddr.s_addr = myaddr.s_addr, 0); if (la & (rt = la-la_rt) & (sdl = SDL(rt-rt_gateway) if (sdl-sdl_alen & bcmp(caddr_t)ea-arp_sha, LLADDR(sdl), sdl-sdl_alen)logMsg(arp info overwritten for %08x by %sn, (int) ntohl(isaddr.s_addr), (int) ether_sprintf(ea-arp_sha),0,0,0,0);bcopy(caddr_t)ea-arp_sha, LLADDR(sdl), sdl-sdl_alen = sizeof(ea-arp_sha);if (rt-rt_expire)rt-rt_expire = tickGet() + (sysClkRateGet() * arpt_keep);rt-rt_flags &= RTF_REJECT;la-la_asked = 0;if (la-la_hold) (*ac-ac_if.if_output)(&ac-ac_if, la-la_hold,rt_key(rt), rt);la-la_hold = 0;首先,in_arpinput会调用arplookup,以检查发送者是不是在我们当前的arp缓存中(如果我们在前面发送了arp请求,那么就应该存在一个无效的arp项,如果是对方主请求,那么说明对方想与我们通讯,也需要检查对方在不在的).arplookup传入的第二个参数,表示在不存在arp项的时候,是不是要建立.那么什么时候建立呢?由于arp请求是广播发送的,所以我们可能接收到请求的目的ip不是我们自己的ip地址,在这种情况下,只需要更新arp信息(时标,以防止老化),只有请求是针对我自己的情况下(因为对方可能要与我通讯了,我马上就要使用对方的mac地址了),才会创建新的 arp项.如果arplookup查找出来一个有效的arp项,说明arp要被覆盖了,这也是我们看到arp info overwritten for 0xXXXXXXXX by xxxx n这条信息的原因.arp下面的处理,就是复制目的mac,然后 设置rt_expire,将老化时间设置为20分钟. 设置la_asked为0; 调用if_output发送la_hold.这与我们前面说过的,arp输入处理时,发送保存的数据是一致的.这一次由于系统中arp项的存在,会导致ipPutput调用arpresolve时返回1(有效mac),从而能够正常发送数据.arp的老化arp的老化由arptimer完成,arptimer每分钟运行一次,它处理全局链表llinfo_arp,将老化的arp设置为无效.if (rt-rt_expire & rt-rt_expire la_prev); /* timer has expired; clear */ 我们看到老化操作是在arptfree完成的. if (rt-rt_refcnt 0 & (sdl = SDL(rt-rt_gateway) & sdl-sdl_family = AF_LINK) sdl-sdl_alen = 0;la-la_asked = 0;rt-rt_flags &= RTF_REJECT;return;rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt), 0, (struct rtentry *)0);从上面的代码中可以看出,在rt_refcnt大于0的情况下,仅仅将mac信息标志为无效(sdl_len=0),否则调用rtrequest删除相应的arp表项. arp表项的建立从前面我们大概知道了整个arp表项,但是我们还没有知道arp在内存中到底是什么.其实我们所谓的arp,就是主机直接路由,它通过clone接口子网路由产生.所以这一次,我们从arp的前生今世开始讲.接口网络路由的建立当我们给接口增加/删除地址的时候,都会影响路由表,通过设置地址/掩码,也就确定一个可以直达的网络,如 ifAddrAdd(mottsec2,10.0.0.8,10.0.255.255,0xffff0000).这个函数调用经过一系列的传递之后,会调用到in_control,然后调用到in_ifinit,它里面有这样一段代码:if (ifp-if_ioctl & (error = (*ifp-if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia) splx(s);ia-ia_addr = oldaddr;return (error);因为if_ioctl就是ipIoctl,所以来看看,它作了些什么事情: switch (cmd)case SIOCSIFADDR: for (pIa = in_ifaddr; pIa; pIa = pIa-ia_next) if (pIa-ia_ifp = (struct ifnet *)ifp) & (pIa-ia_addr.sin_addr.s_addr = dt_saddr) break; pIa-ia_ifa.ifa_rtrequest = arp_rtrequest; pIa-ia_ifa.ifa_flags |= RTF_CLONING; ifp-ac_ipaddr = IA_SIN (data)-sin_addr; arpwhohas (ifp, &IA_SIN (data)-sin_addr); break;其它的不管,其中对我们arp影响最大的两项,就是将ifa_rtrequest设置为arp_rtrequest,并置上了RTF_CLONING标志.incontrol最后会调用rtinit,并由rtinit调用rtrequest将接

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论