arp.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copied from Linux Monitor (LiMon) - Networking.
  3. *
  4. * Copyright 1994 - 2000 Neil Russell.
  5. * (See License)
  6. * Copyright 2000 Roland Borde
  7. * Copyright 2000 Paolo Scaffardi
  8. * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
  9. */
  10. #include <common.h>
  11. #include "arp.h"
  12. #ifndef CONFIG_ARP_TIMEOUT
  13. /* Milliseconds before trying ARP again */
  14. # define ARP_TIMEOUT 5000UL
  15. #else
  16. # define ARP_TIMEOUT CONFIG_ARP_TIMEOUT
  17. #endif
  18. #ifndef CONFIG_NET_RETRY_COUNT
  19. # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
  20. #else
  21. # define ARP_TIMEOUT_COUNT CONFIG_NET_RETRY_COUNT
  22. #endif
  23. IPaddr_t NetArpWaitPacketIP;
  24. IPaddr_t NetArpWaitReplyIP;
  25. /* MAC address of waiting packet's destination */
  26. uchar *NetArpWaitPacketMAC;
  27. /* THE transmit packet */
  28. uchar *NetArpWaitTxPacket;
  29. int NetArpWaitTxPacketSize;
  30. uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
  31. ulong NetArpWaitTimerStart;
  32. int NetArpWaitTry;
  33. void ArpInit(void)
  34. {
  35. /* XXX problem with bss workaround */
  36. NetArpWaitPacketMAC = NULL;
  37. NetArpWaitPacketIP = 0;
  38. NetArpWaitReplyIP = 0;
  39. NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
  40. NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
  41. NetArpWaitTxPacketSize = 0;
  42. }
  43. void ArpRequest(void)
  44. {
  45. uchar *pkt;
  46. ARP_t *arp;
  47. debug("ARP broadcast %d\n", NetArpWaitTry);
  48. pkt = NetTxPacket;
  49. pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
  50. arp = (ARP_t *) pkt;
  51. arp->ar_hrd = htons(ARP_ETHER);
  52. arp->ar_pro = htons(PROT_IP);
  53. arp->ar_hln = 6;
  54. arp->ar_pln = 4;
  55. arp->ar_op = htons(ARPOP_REQUEST);
  56. /* source ET addr */
  57. memcpy(&arp->ar_data[0], NetOurEther, 6);
  58. /* source IP addr */
  59. NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
  60. /* dest ET addr = 0 */
  61. memset(&arp->ar_data[10], '\0', 6);
  62. if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
  63. (NetOurIP & NetOurSubnetMask)) {
  64. if (NetOurGatewayIP == 0) {
  65. puts("## Warning: gatewayip needed but not set\n");
  66. NetArpWaitReplyIP = NetArpWaitPacketIP;
  67. } else {
  68. NetArpWaitReplyIP = NetOurGatewayIP;
  69. }
  70. } else {
  71. NetArpWaitReplyIP = NetArpWaitPacketIP;
  72. }
  73. NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP);
  74. (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
  75. }
  76. void ArpTimeoutCheck(void)
  77. {
  78. ulong t;
  79. if (!NetArpWaitPacketIP)
  80. return;
  81. t = get_timer(0);
  82. /* check for arp timeout */
  83. if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
  84. NetArpWaitTry++;
  85. if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
  86. puts("\nARP Retry count exceeded; starting again\n");
  87. NetArpWaitTry = 0;
  88. NetStartAgain();
  89. } else {
  90. NetArpWaitTimerStart = t;
  91. ArpRequest();
  92. }
  93. }
  94. }
  95. void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
  96. {
  97. ARP_t *arp;
  98. IPaddr_t tmp;
  99. uchar *pkt;
  100. /*
  101. * We have to deal with two types of ARP packets:
  102. * - REQUEST packets will be answered by sending our
  103. * IP address - if we know it.
  104. * - REPLY packates are expected only after we asked
  105. * for the TFTP server's or the gateway's ethernet
  106. * address; so if we receive such a packet, we set
  107. * the server ethernet address
  108. */
  109. debug("Got ARP\n");
  110. arp = (ARP_t *)ip;
  111. if (len < ARP_HDR_SIZE) {
  112. printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
  113. return;
  114. }
  115. if (ntohs(arp->ar_hrd) != ARP_ETHER)
  116. return;
  117. if (ntohs(arp->ar_pro) != PROT_IP)
  118. return;
  119. if (arp->ar_hln != 6)
  120. return;
  121. if (arp->ar_pln != 4)
  122. return;
  123. if (NetOurIP == 0)
  124. return;
  125. if (NetReadIP(&arp->ar_data[16]) != NetOurIP)
  126. return;
  127. switch (ntohs(arp->ar_op)) {
  128. case ARPOP_REQUEST:
  129. /* reply with our IP address */
  130. debug("Got ARP REQUEST, return our IP\n");
  131. pkt = (uchar *)et;
  132. pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
  133. arp->ar_op = htons(ARPOP_REPLY);
  134. memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
  135. NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
  136. memcpy(&arp->ar_data[0], NetOurEther, 6);
  137. NetCopyIP(&arp->ar_data[6], &NetOurIP);
  138. (void) eth_send((uchar *)et,
  139. (pkt - (uchar *)et) + ARP_HDR_SIZE);
  140. return;
  141. case ARPOP_REPLY: /* arp reply */
  142. /* are we waiting for a reply */
  143. if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
  144. break;
  145. #ifdef CONFIG_KEEP_SERVERADDR
  146. if (NetServerIP == NetArpWaitPacketIP) {
  147. char buf[20];
  148. sprintf(buf, "%pM", arp->ar_data);
  149. setenv("serveraddr", buf);
  150. }
  151. #endif
  152. tmp = NetReadIP(&arp->ar_data[6]);
  153. /* matched waiting packet's address */
  154. if (tmp == NetArpWaitReplyIP) {
  155. debug("Got ARP REPLY, set eth addr (%pM)\n",
  156. arp->ar_data);
  157. /* save address for later use */
  158. memcpy(NetArpWaitPacketMAC,
  159. &arp->ar_data[0], 6);
  160. #ifdef CONFIG_NETCONSOLE
  161. NetGetHandler()(0, 0, 0, 0, 0);
  162. #endif
  163. /* modify header, and transmit it */
  164. memcpy(((struct ethernet_hdr *)NetArpWaitTxPacket)->
  165. et_dest, NetArpWaitPacketMAC, 6);
  166. (void) eth_send(NetArpWaitTxPacket,
  167. NetArpWaitTxPacketSize);
  168. /* no arp request pending now */
  169. NetArpWaitPacketIP = 0;
  170. NetArpWaitTxPacketSize = 0;
  171. NetArpWaitPacketMAC = NULL;
  172. }
  173. return;
  174. default:
  175. debug("Unexpected ARP opcode 0x%x\n",
  176. ntohs(arp->ar_op));
  177. return;
  178. }
  179. }