arp.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:9k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Address Resolution Protocol (ARP) functions. Sits between IP and
  2.  * Level 2, mapping IP to Level 2 addresses for all outgoing datagrams.
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  */
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "timer.h"
  8. #include "iface.h"
  9. #include "enet.h"
  10. #include "ax25.h"
  11. #include "icmp.h"
  12. #include "ip.h"
  13. #include "arp.h"
  14. #include "icmp.h"
  15. static void arp_output(struct iface *iface,enum arp_hwtype hardware,int32 target);
  16. /* Hash table headers */
  17. struct arp_tab *Arp_tab[HASHMOD];
  18. struct arp_stat Arp_stat;
  19. /* Resolve an IP address to a hardware address; if not found,
  20.  * initiate query and return NULL.  If an address is returned, the
  21.  * interface driver may send the packet; if NULL is returned,
  22.  * res_arp() will have saved the packet on its pending queue,
  23.  * so no further action (like freeing the packet) is necessary.
  24.  */
  25. uint8 *
  26. res_arp(
  27. struct iface *iface, /* Pointer to interface block */
  28. enum arp_hwtype hardware, /* Hardware type */
  29. int32 target, /* Target IP address */
  30. struct mbuf **bpp /* IP datagram to be queued if unresolved */
  31. ){
  32. register struct arp_tab *arp;
  33. struct ip ip;
  34. if((arp = arp_lookup(hardware,target)) != NULL && arp->state == ARP_VALID)
  35. return arp->hw_addr;
  36. if(arp != NULL){
  37. /* Earlier packets are already pending, kick this one back
  38.  * as a source quench
  39.  */
  40. ntohip(&ip,bpp);
  41. icmp_output(&ip,*bpp,ICMP_QUENCH,0,NULL);
  42. free_p(bpp);
  43. } else {
  44. /* Create an entry and put the datagram on the
  45.  * queue pending an answer
  46.  */
  47. arp = arp_add(target,hardware,NULL,0);
  48. enqueue(&arp->pending,bpp);
  49. arp_output(iface,hardware,target);
  50. }
  51. return NULL;
  52. }
  53. /* Handle incoming ARP packets. This is almost a direct implementation of
  54.  * the algorithm on page 5 of RFC 826, except for:
  55.  * 1. Outgoing datagrams to unresolved addresses are kept on a queue
  56.  *    pending a reply to our ARP request.
  57.  * 2. The names of the fields in the ARP packet were made more mnemonic.
  58.  * 3. Requests for IP addresses listed in our table as "published" are
  59.  *    responded to, even if the address is not our own.
  60.  */
  61. void
  62. arp_input(
  63. struct iface *iface,
  64. struct mbuf **bpp
  65. ){
  66. struct arp arp;
  67. struct arp_tab *ap;
  68. struct arp_type *at;
  69. int i;
  70. Arp_stat.recv++;
  71. if(ntoharp(&arp,bpp) == -1) /* Convert into host format */
  72. return;
  73. if(arp.hardware >= NHWTYPES){
  74. /* Unknown hardware type, ignore */
  75. Arp_stat.badtype++;
  76. return;
  77. }
  78. at = &Arp_type[arp.hardware];
  79. if(arp.protocol != at->iptype){
  80. /* Unsupported protocol type, ignore */
  81. Arp_stat.badtype++;
  82. return;
  83. }
  84. if(arp.hwalen > MAXHWALEN || arp.pralen != sizeof(int32)){
  85. /* Incorrect protocol addr length (different hw addr lengths
  86.  * are OK since AX.25 addresses can be of variable length)
  87.  */
  88. Arp_stat.badlen++;
  89. return;
  90. }
  91. if(memcmp(arp.shwaddr,at->bdcst,at->hwalen) == 0){
  92. /* This guy is trying to say he's got the broadcast address! */
  93. Arp_stat.badaddr++;
  94. return;
  95. }
  96. /* If this guy is already in the table, update its entry
  97.  * unless it's a manual entry (noted by the lack of a timer)
  98.  */
  99. ap = NULL; /* ap plays the role of merge_flag in the spec */
  100. if((ap = arp_lookup(arp.hardware,arp.sprotaddr)) != NULL
  101.  && dur_timer(&ap->timer) != 0){
  102. ap = arp_add(arp.sprotaddr,arp.hardware,arp.shwaddr,0);
  103. }
  104. /* See if we're the address they're looking for */
  105. if(ismyaddr(arp.tprotaddr) != NULL){
  106. if(ap == NULL) /* Only if not already in the table */
  107. arp_add(arp.sprotaddr,arp.hardware,arp.shwaddr,0);
  108. if(arp.opcode == ARP_REQUEST){
  109. /* Swap sender's and target's (us) hardware and protocol
  110.  * fields, and send the packet back as a reply
  111.  */
  112. memcpy(arp.thwaddr,arp.shwaddr,(uint16)arp.hwalen);
  113. /* Mark the end of the sender's AX.25 address
  114.  * in case he didn't
  115.  */
  116. if(arp.hardware == ARP_AX25)
  117. arp.thwaddr[arp.hwalen-1] |= E;
  118. memcpy(arp.shwaddr,iface->hwaddr,at->hwalen);
  119. arp.tprotaddr = arp.sprotaddr;
  120. arp.sprotaddr = iface->addr;
  121. arp.opcode = ARP_REPLY;
  122. if((*bpp = htonarp(&arp)) == NULL)
  123. return;
  124. if(iface->forw != NULL)
  125. (*iface->forw->output)(iface->forw,
  126.  arp.thwaddr,iface->forw->hwaddr,at->arptype,bpp);
  127. else 
  128. (*iface->output)(iface,arp.thwaddr,
  129.  iface->hwaddr,at->arptype,bpp);
  130. Arp_stat.inreq++;
  131. } else {
  132. Arp_stat.replies++;
  133. }
  134. } else if(arp.opcode == ARP_REQUEST
  135.  && (ap = arp_lookup(arp.hardware,arp.tprotaddr)) != NULL
  136.  && ap->pub){
  137. /* Otherwise, respond if the guy he's looking for is
  138.  * published in our table.
  139.  */
  140. memcpy(arp.thwaddr,arp.shwaddr,(uint16)arp.hwalen);
  141. memcpy(arp.shwaddr,ap->hw_addr,at->hwalen);
  142. arp.tprotaddr = arp.sprotaddr;
  143. arp.sprotaddr = ap->ip_addr;
  144. arp.opcode = ARP_REPLY;
  145. if((*bpp = htonarp(&arp)) == NULL)
  146. return;
  147. if(iface->forw != NULL)
  148. (*iface->forw->output)(iface->forw,
  149.  arp.thwaddr,iface->forw->hwaddr,at->arptype,bpp);
  150. else 
  151. (*iface->output)(iface,arp.thwaddr,
  152.  iface->hwaddr,at->arptype,bpp);
  153. Arp_stat.inreq++;
  154. } else if(arp.opcode == REVARP_REQUEST){
  155. for(i=0;i<HASHMOD;i++)
  156. for(ap = Arp_tab[i];ap != NULL;ap = ap->next)
  157. if(memcmp(ap->hw_addr,arp.thwaddr,at->hwalen) == 0)
  158. goto found;
  159. found: if(ap != NULL && ap->pub){
  160. memcpy(arp.shwaddr,iface->hwaddr,at->hwalen);
  161. arp.tprotaddr = ap->ip_addr;
  162. arp.sprotaddr = iface->addr;
  163. arp.opcode = REVARP_REPLY;
  164. if((*bpp = htonarp(&arp)) == NULL)
  165. return;
  166. if(iface->forw != NULL)
  167. (*iface->forw->output)(iface->forw,
  168.  arp.thwaddr,iface->forw->hwaddr,REVARP_TYPE,bpp);
  169. else 
  170. (*iface->output)(iface,arp.thwaddr,
  171.  iface->hwaddr,REVARP_TYPE,bpp);
  172. Arp_stat.inreq++;
  173. }
  174. }
  175. }
  176. /* Add an IP-addr / hardware-addr pair to the ARP table */
  177. struct arp_tab *
  178. arp_add(ipaddr,hardware,hw_addr,pub)
  179. int32 ipaddr; /* IP address, host order */
  180. enum arp_hwtype hardware; /* Hardware type */
  181. uint8 *hw_addr; /* Hardware address, if known; NULL otherwise */
  182. int pub; /* Publish this entry? */
  183. {
  184. struct mbuf *bp;
  185. register struct arp_tab *ap;
  186. struct arp_type *at;
  187. unsigned hashval;
  188. if(hardware >=NHWTYPES)
  189. return NULL; /* Invalid hardware type */
  190. at = &Arp_type[hardware];
  191. if((ap = arp_lookup(hardware,ipaddr)) == NULL){
  192. /* New entry */
  193. ap = (struct arp_tab *)callocw(1,sizeof(struct arp_tab));
  194. ap->hw_addr = mallocw(at->hwalen);
  195. ap->timer.func = arp_drop;
  196. ap->timer.arg = ap;
  197. ap->hardware = hardware;
  198. ap->ip_addr = ipaddr;
  199. /* Put on head of hash chain */
  200. hashval = hash_ip(ipaddr);
  201. ap->prev = NULL;
  202. ap->next = Arp_tab[hashval];
  203. Arp_tab[hashval] = ap;
  204. if(ap->next != NULL){
  205. ap->next->prev = ap;
  206. }
  207. }
  208. if(hw_addr == NULL){
  209. /* Await response */
  210. ap->state = ARP_PENDING;
  211. set_timer(&ap->timer,Arp_type[hardware].pendtime * 1000L);
  212. } else {
  213. /* Response has come in, update entry and run through queue */
  214. ap->state = ARP_VALID;
  215. set_timer(&ap->timer,ARPLIFE*1000L);
  216. memcpy(ap->hw_addr,hw_addr,at->hwalen);
  217. ap->pub = pub;
  218. while((bp = dequeue(&ap->pending)) != NULL)
  219. ip_route(NULL,&bp,0);
  220. }
  221. start_timer(&ap->timer);
  222. return ap;
  223. }
  224. /* Remove an entry from the ARP table */
  225. void
  226. arp_drop(p)
  227. void *p;
  228. {
  229. register struct arp_tab *ap;
  230. ap = (struct arp_tab *)p;
  231. if(ap == NULL)
  232. return;
  233. stop_timer(&ap->timer); /* Shouldn't be necessary */
  234. if(ap->next != NULL)
  235. ap->next->prev = ap->prev;
  236. if(ap->prev != NULL)
  237. ap->prev->next = ap->next;
  238. else
  239. Arp_tab[hash_ip(ap->ip_addr)] = ap->next;
  240. free_q(&ap->pending);
  241. free(ap->hw_addr);
  242. free(ap);
  243. }
  244. /* Look up the given IP address in the ARP table */
  245. struct arp_tab *
  246. arp_lookup(hardware,ipaddr)
  247. enum arp_hwtype hardware;
  248. int32 ipaddr;
  249. {
  250. register struct arp_tab *ap;
  251. for(ap = Arp_tab[hash_ip(ipaddr)]; ap != NULL; ap = ap->next){
  252. if(ap->ip_addr == ipaddr && ap->hardware == hardware)
  253. break;
  254. }
  255. return ap;
  256. }
  257. /* Send an ARP request to resolve IP address target_ip */
  258. static void
  259. arp_output(iface,hardware,target)
  260. struct iface *iface;
  261. enum arp_hwtype hardware;
  262. int32 target;
  263. {
  264. struct arp arp;
  265. struct mbuf *bp;
  266. struct arp_type *at;
  267. at = &Arp_type[hardware];
  268. if(iface->output == NULL)
  269. return;
  270. arp.hardware = hardware;
  271. arp.protocol = at->iptype;
  272. arp.hwalen = at->hwalen;
  273. arp.pralen = sizeof(int32);
  274. arp.opcode = ARP_REQUEST;
  275. memcpy(arp.shwaddr,iface->hwaddr,at->hwalen);
  276. arp.sprotaddr = iface->addr;
  277. memset(arp.thwaddr,0,at->hwalen);
  278. arp.tprotaddr = target;
  279. if((bp = htonarp(&arp)) == NULL)
  280. return;
  281. (*iface->output)(iface,at->bdcst,
  282. iface->hwaddr,at->arptype,&bp);
  283. Arp_stat.outreq++;
  284. }