net.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  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. /*
  11. * General Desription:
  12. *
  13. * The user interface supports commands for BOOTP, RARP, and TFTP.
  14. * Also, we support ARP internally. Depending on available data,
  15. * these interact as follows:
  16. *
  17. * BOOTP:
  18. *
  19. * Prerequisites: - own ethernet address
  20. * We want: - own IP address
  21. * - TFTP server IP address
  22. * - name of bootfile
  23. * Next step: ARP
  24. *
  25. * RARP:
  26. *
  27. * Prerequisites: - own ethernet address
  28. * We want: - own IP address
  29. * - TFTP server IP address
  30. * Next step: ARP
  31. *
  32. * ARP:
  33. *
  34. * Prerequisites: - own ethernet address
  35. * - own IP address
  36. * - TFTP server IP address
  37. * We want: - TFTP server ethernet address
  38. * Next step: TFTP
  39. *
  40. * DHCP:
  41. *
  42. * Prerequisites: - own ethernet address
  43. * We want: - IP, Netmask, ServerIP, Gateway IP
  44. * - bootfilename, lease time
  45. * Next step: - TFTP
  46. *
  47. * TFTP:
  48. *
  49. * Prerequisites: - own ethernet address
  50. * - own IP address
  51. * - TFTP server IP address
  52. * - TFTP server ethernet address
  53. * - name of bootfile (if unknown, we use a default name
  54. * derived from our own IP address)
  55. * We want: - load the boot file
  56. * Next step: none
  57. */
  58. #include <common.h>
  59. #include <watchdog.h>
  60. #include <command.h>
  61. #include <net.h>
  62. #include "bootp.h"
  63. #include "tftp.h"
  64. #include "rarp.h"
  65. #include "arp.h"
  66. #if (CONFIG_COMMANDS & CFG_CMD_NET)
  67. #if 0
  68. #define ET_DEBUG
  69. #endif
  70. /** BOOTP EXTENTIONS **/
  71. IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */
  72. IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */
  73. IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */
  74. char NetOurNISDomain[32]={0,}; /* Our NIS domain */
  75. char NetOurHostName[32]={0,}; /* Our hostname */
  76. char NetOurRootPath[64]={0,}; /* Our bootpath */
  77. ushort NetBootFileSize=0; /* Our bootfile size in blocks */
  78. /** END OF BOOTP EXTENTIONS **/
  79. ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */
  80. uchar NetOurEther[6]; /* Our ethernet address */
  81. uchar NetServerEther[6] = /* Boot server enet address */
  82. { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  83. IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
  84. IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */
  85. volatile uchar *NetRxPkt; /* Current receive packet */
  86. int NetRxPktLen; /* Current rx packet length */
  87. unsigned NetIPID; /* IP packet ID */
  88. uchar NetBcastAddr[6] = /* Ethernet bcast address */
  89. { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  90. int NetState; /* Network loop state */
  91. #ifdef CONFIG_NET_MULTI
  92. int NetRestartWrap = 0; /* Tried all network devices */
  93. static int NetRestarted = 0; /* Network loop restarted */
  94. static int NetDevExists = 0; /* At least one device configured */
  95. #endif
  96. char BootFile[128]; /* Boot File name */
  97. volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
  98. volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */
  99. static rxhand_f *packetHandler; /* Current RX packet handler */
  100. static thand_f *timeHandler; /* Current timeout handler */
  101. static ulong timeValue; /* Current timeout value */
  102. volatile uchar *NetTxPacket = 0; /* THE transmit packet */
  103. static int net_check_prereq (proto_t protocol);
  104. /**********************************************************************/
  105. /*
  106. * Main network processing loop.
  107. */
  108. int
  109. NetLoop(proto_t protocol)
  110. {
  111. DECLARE_GLOBAL_DATA_PTR;
  112. bd_t *bd = gd->bd;
  113. #ifdef CONFIG_NET_MULTI
  114. NetRestarted = 0;
  115. NetDevExists = 0;
  116. #endif
  117. if (!NetTxPacket) {
  118. int i;
  119. /*
  120. * Setup packet buffers, aligned correctly.
  121. */
  122. NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
  123. NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
  124. for (i = 0; i < PKTBUFSRX; i++) {
  125. NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
  126. }
  127. }
  128. eth_halt();
  129. eth_init(bd);
  130. restart:
  131. #ifdef CONFIG_NET_MULTI
  132. memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
  133. #else
  134. memcpy (NetOurEther, bd->bi_enetaddr, 6);
  135. #endif
  136. NetState = NETLOOP_CONTINUE;
  137. /*
  138. * Start the ball rolling with the given start function. From
  139. * here on, this code is a state machine driven by received
  140. * packets and timer events.
  141. */
  142. switch (protocol) {
  143. case TFTP:
  144. NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
  145. NetServerIP = getenv_IPaddr ("serverip");
  146. NetOurGatewayIP = getenv_IPaddr ("gatewayip");
  147. NetOurSubnetMask= getenv_IPaddr ("netmask");
  148. break;
  149. case BOOTP:
  150. case RARP:
  151. /*
  152. * initialize our IP addr to 0 in order to accept ANY
  153. * IP addr assigned to us by the BOOTP / RARP server
  154. */
  155. NetOurIP = 0;
  156. NetServerIP = 0;
  157. break;
  158. default:
  159. break;
  160. }
  161. switch (net_check_prereq (protocol)) {
  162. case 1:
  163. /* network not configured */
  164. return (-1);
  165. #ifdef CONFIG_NET_MULTI
  166. case 2:
  167. /* network device not configured */
  168. break;
  169. #endif /* CONFIG_NET_MULTI */
  170. case 0:
  171. #ifdef CONFIG_NET_MULTI
  172. NetDevExists = 1;
  173. #endif
  174. switch (protocol) {
  175. case TFTP:
  176. /* always use ARP to get server ethernet address */
  177. ArpTry = 0;
  178. ArpRequest ();
  179. break;
  180. #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
  181. case DHCP:
  182. /* Start with a clean slate... */
  183. NetOurIP = 0;
  184. NetServerIP = 0;
  185. DhcpRequest(); /* Basically same as BOOTP */
  186. break;
  187. #endif /* CFG_CMD_DHCP */
  188. case BOOTP:
  189. BootpTry = 0;
  190. BootpRequest ();
  191. break;
  192. case RARP:
  193. RarpTry = 0;
  194. RarpRequest ();
  195. break;
  196. default:
  197. break;
  198. }
  199. NetBootFileXferSize = 0;
  200. break;
  201. }
  202. /*
  203. * Main packet reception loop. Loop receiving packets until
  204. * someone sets `NetQuit'.
  205. */
  206. for (;;) {
  207. WATCHDOG_RESET();
  208. #ifdef CONFIG_SHOW_ACTIVITY
  209. {
  210. extern void show_activity(int arg);
  211. show_activity(1);
  212. }
  213. #endif
  214. /*
  215. * Check the ethernet for a new packet. The ethernet
  216. * receive routine will process it.
  217. */
  218. eth_rx();
  219. /*
  220. * Abort if ctrl-c was pressed.
  221. */
  222. if (ctrlc()) {
  223. eth_halt();
  224. printf("\nAbort\n");
  225. return (-1);
  226. }
  227. /*
  228. * Check for a timeout, and run the timeout handler
  229. * if we have one.
  230. */
  231. if (timeHandler && (get_timer(0) > timeValue)) {
  232. thand_f *x;
  233. x = timeHandler;
  234. timeHandler = (thand_f *)0;
  235. (*x)();
  236. }
  237. switch (NetState) {
  238. case NETLOOP_RESTART:
  239. #ifdef CONFIG_NET_MULTI
  240. NetRestarted = 1;
  241. #endif
  242. goto restart;
  243. case NETLOOP_SUCCESS:
  244. if (NetBootFileXferSize > 0) {
  245. char buf[10];
  246. printf("Bytes transferred = %ld (%lx hex)\n",
  247. NetBootFileXferSize,
  248. NetBootFileXferSize);
  249. sprintf(buf, "%lx", NetBootFileXferSize);
  250. setenv("filesize", buf);
  251. }
  252. eth_halt();
  253. return NetBootFileXferSize;
  254. case NETLOOP_FAIL:
  255. return (-1);
  256. }
  257. }
  258. }
  259. /**********************************************************************/
  260. static void
  261. startAgainTimeout(void)
  262. {
  263. NetState = NETLOOP_RESTART;
  264. }
  265. static void
  266. startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
  267. {
  268. /* Totally ignore the packet */
  269. }
  270. void
  271. NetStartAgain(void)
  272. {
  273. #ifndef CONFIG_NET_MULTI
  274. NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
  275. NetSetHandler(startAgainHandler);
  276. #else
  277. DECLARE_GLOBAL_DATA_PTR;
  278. eth_halt();
  279. eth_try_another(!NetRestarted);
  280. eth_init(gd->bd);
  281. if (NetRestartWrap)
  282. {
  283. NetRestartWrap = 0;
  284. if (NetDevExists)
  285. {
  286. NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
  287. NetSetHandler(startAgainHandler);
  288. }
  289. else
  290. {
  291. NetState = NETLOOP_FAIL;
  292. }
  293. }
  294. else
  295. {
  296. NetState = NETLOOP_RESTART;
  297. }
  298. #endif
  299. }
  300. /**********************************************************************/
  301. /*
  302. * Miscelaneous bits.
  303. */
  304. void
  305. NetSetHandler(rxhand_f * f)
  306. {
  307. packetHandler = f;
  308. }
  309. void
  310. NetSetTimeout(int iv, thand_f * f)
  311. {
  312. if (iv == 0) {
  313. timeHandler = (thand_f *)0;
  314. } else {
  315. timeHandler = f;
  316. timeValue = get_timer(0) + iv;
  317. }
  318. }
  319. void
  320. NetSendPacket(volatile uchar * pkt, int len)
  321. {
  322. (void) eth_send(pkt, len);
  323. }
  324. void
  325. NetReceive(volatile uchar * pkt, int len)
  326. {
  327. Ethernet_t *et;
  328. IP_t *ip;
  329. ARP_t *arp;
  330. IPaddr_t tmp;
  331. int x;
  332. NetRxPkt = pkt;
  333. NetRxPktLen = len;
  334. et = (Ethernet_t *)pkt;
  335. x = ntohs(et->et_protlen);
  336. if (x < 1514) {
  337. /*
  338. * Got a 802 packet. Check the other protocol field.
  339. */
  340. x = ntohs(et->et_prot);
  341. ip = (IP_t *)(pkt + E802_HDR_SIZE);
  342. len -= E802_HDR_SIZE;
  343. } else {
  344. ip = (IP_t *)(pkt + ETHER_HDR_SIZE);
  345. len -= ETHER_HDR_SIZE;
  346. }
  347. #ifdef ET_DEBUG
  348. printf("Receive from protocol 0x%x\n", x);
  349. #endif
  350. switch (x) {
  351. case PROT_ARP:
  352. /*
  353. * We have to deal with two types of ARP packets:
  354. * - REQUEST packets will be answered by sending our
  355. * IP address - if we know it.
  356. * - REPLY packates are expected only after we asked
  357. * for the TFTP server's or the gateway's ethernet
  358. * address; so if we receive such a packet, we set
  359. * the server ethernet address
  360. */
  361. #ifdef ET_DEBUG
  362. printf("Got ARP\n");
  363. #endif
  364. arp = (ARP_t *)ip;
  365. if (len < ARP_HDR_SIZE) {
  366. printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
  367. return;
  368. }
  369. if (ntohs(arp->ar_hrd) != ARP_ETHER) {
  370. return;
  371. }
  372. if (ntohs(arp->ar_pro) != PROT_IP) {
  373. return;
  374. }
  375. if (arp->ar_hln != 6) {
  376. return;
  377. }
  378. if (arp->ar_pln != 4) {
  379. return;
  380. }
  381. if (NetOurIP == 0) {
  382. return;
  383. }
  384. if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
  385. return;
  386. }
  387. switch (ntohs(arp->ar_op)) {
  388. case ARPOP_REQUEST: /* reply with our IP address */
  389. #ifdef ET_DEBUG
  390. printf("Got ARP REQUEST, return our IP\n");
  391. #endif
  392. NetSetEther((uchar *)et, et->et_src, PROT_ARP);
  393. arp->ar_op = htons(ARPOP_REPLY);
  394. memcpy (&arp->ar_data[10], &arp->ar_data[0], 6);
  395. NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
  396. memcpy (&arp->ar_data[ 0], NetOurEther, 6);
  397. NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
  398. NetSendPacket((uchar *)et,((uchar *)arp-pkt)+ARP_HDR_SIZE);
  399. return;
  400. case ARPOP_REPLY: /* set TFTP server eth addr */
  401. #ifdef ET_DEBUG
  402. printf("Got ARP REPLY, set server/gtwy eth addr\n");
  403. #endif
  404. memcpy (NetServerEther, &arp->ar_data[0], 6);
  405. (*packetHandler)(0,0,0,0); /* start TFTP */
  406. return;
  407. default:
  408. #ifdef ET_DEBUG
  409. printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
  410. #endif
  411. return;
  412. }
  413. case PROT_RARP:
  414. #ifdef ET_DEBUG
  415. printf("Got RARP\n");
  416. #endif
  417. arp = (ARP_t *)ip;
  418. if (len < ARP_HDR_SIZE) {
  419. printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
  420. return;
  421. }
  422. if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
  423. (ntohs(arp->ar_hrd) != ARP_ETHER) ||
  424. (ntohs(arp->ar_pro) != PROT_IP) ||
  425. (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
  426. printf("invalid RARP header\n");
  427. } else {
  428. NetCopyIP(&NetOurIP, &arp->ar_data[16]);
  429. NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
  430. memcpy (NetServerEther, &arp->ar_data[ 0], 6);
  431. (*packetHandler)(0,0,0,0);
  432. }
  433. break;
  434. case PROT_IP:
  435. #ifdef ET_DEBUG
  436. printf("Got IP\n");
  437. #endif
  438. if (len < IP_HDR_SIZE) {
  439. debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
  440. return;
  441. }
  442. if (len < ntohs(ip->ip_len)) {
  443. printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
  444. return;
  445. }
  446. len = ntohs(ip->ip_len);
  447. #ifdef ET_DEBUG
  448. printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
  449. #endif
  450. if ((ip->ip_hl_v & 0xf0) != 0x40) {
  451. return;
  452. }
  453. if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
  454. return;
  455. }
  456. if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
  457. printf("checksum bad\n");
  458. return;
  459. }
  460. tmp = NetReadIP(&ip->ip_dst);
  461. if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
  462. return;
  463. }
  464. /*
  465. * watch for ICMP host redirects
  466. *
  467. * There is no real handler code (yet). We just watch
  468. * for ICMP host redirect messages. In case anybody
  469. * sees these messages: please contact me
  470. * (wd@denx.de), or - even better - send me the
  471. * necessary fixes :-)
  472. *
  473. * Note: in all cases where I have seen this so far
  474. * it was a problem with the router configuration,
  475. * for instance when a router was configured in the
  476. * BOOTP reply, but the TFTP server was on the same
  477. * subnet. So this is probably a warning that your
  478. * configuration might be wrong. But I'm not really
  479. * sure if there aren't any other situations.
  480. */
  481. if (ip->ip_p == IPPROTO_ICMP) {
  482. ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
  483. if (icmph->type != ICMP_REDIRECT)
  484. return;
  485. if (icmph->code != ICMP_REDIR_HOST)
  486. return;
  487. puts (" ICMP Host Redirect to ");
  488. print_IPaddr(icmph->un.gateway);
  489. putc(' ');
  490. } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
  491. return;
  492. }
  493. /*
  494. * IP header OK. Pass the packet to the current handler.
  495. */
  496. (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
  497. ntohs(ip->udp_dst),
  498. ntohs(ip->udp_src),
  499. ntohs(ip->udp_len) - 8);
  500. break;
  501. }
  502. }
  503. /**********************************************************************/
  504. static int net_check_prereq (proto_t protocol)
  505. {
  506. switch (protocol) {
  507. case ARP: /* nothing to do */
  508. break;
  509. case TFTP:
  510. if (NetServerIP == 0) {
  511. puts ("*** ERROR: `serverip' not set\n");
  512. return (1);
  513. }
  514. if (NetOurIP == 0) {
  515. puts ("*** ERROR: `ipaddr' not set\n");
  516. return (1);
  517. }
  518. /* Fall through */
  519. case DHCP:
  520. case RARP:
  521. case BOOTP:
  522. if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
  523. #ifdef CONFIG_NET_MULTI
  524. extern int eth_get_dev_index (void);
  525. int num = eth_get_dev_index();
  526. switch (num) {
  527. case -1:
  528. puts ("*** ERROR: No ethernet found.\n");
  529. return (1);
  530. case 0:
  531. puts ("*** ERROR: `ethaddr' not set\n");
  532. break;
  533. default:
  534. printf ("*** ERROR: `eth%daddr' not set\n",
  535. num);
  536. break;
  537. }
  538. NetStartAgain ();
  539. return (2);
  540. #else
  541. puts ("*** ERROR: `ethaddr' not set\n");
  542. return (1);
  543. #endif
  544. }
  545. /* Fall through */
  546. }
  547. return (0); /* OK */
  548. }
  549. /**********************************************************************/
  550. int
  551. NetCksumOk(uchar * ptr, int len)
  552. {
  553. return !((NetCksum(ptr, len) + 1) & 0xfffe);
  554. }
  555. unsigned
  556. NetCksum(uchar * ptr, int len)
  557. {
  558. ulong xsum;
  559. xsum = 0;
  560. while (len-- > 0)
  561. xsum += *((ushort *)ptr)++;
  562. xsum = (xsum & 0xffff) + (xsum >> 16);
  563. xsum = (xsum & 0xffff) + (xsum >> 16);
  564. return (xsum & 0xffff);
  565. }
  566. void
  567. NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
  568. {
  569. Ethernet_t *et = (Ethernet_t *)xet;
  570. memcpy (et->et_dest, addr, 6);
  571. memcpy (et->et_src, NetOurEther, 6);
  572. et->et_protlen = htons(prot);
  573. }
  574. void
  575. NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
  576. {
  577. volatile IP_t *ip = (IP_t *)xip;
  578. /*
  579. * If the data is an odd number of bytes, zero the
  580. * byte after the last byte so that the checksum
  581. * will work.
  582. */
  583. if (len & 1)
  584. xip[IP_HDR_SIZE + len] = 0;
  585. /*
  586. * Construct an IP and UDP header.
  587. (need to set no fragment bit - XXX)
  588. */
  589. ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
  590. ip->ip_tos = 0;
  591. ip->ip_len = htons(IP_HDR_SIZE + len);
  592. ip->ip_id = htons(NetIPID++);
  593. ip->ip_off = htons(0x4000); /* No fragmentation */
  594. ip->ip_ttl = 255;
  595. ip->ip_p = 17; /* UDP */
  596. ip->ip_sum = 0;
  597. NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
  598. NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
  599. ip->udp_src = htons(sport);
  600. ip->udp_dst = htons(dport);
  601. ip->udp_len = htons(8 + len);
  602. ip->udp_xsum = 0;
  603. ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
  604. }
  605. void copy_filename (uchar *dst, uchar *src, int size)
  606. {
  607. if (*src && (*src == '"')) {
  608. ++src;
  609. --size;
  610. }
  611. while ((--size > 0) && *src && (*src != '"')) {
  612. *dst++ = *src++;
  613. }
  614. *dst = '\0';
  615. }
  616. #endif /* CFG_CMD_NET */
  617. void ip_to_string (IPaddr_t x, char *s)
  618. {
  619. x = ntohl(x);
  620. sprintf (s,"%d.%d.%d.%d",
  621. (int)((x >> 24) & 0xff),
  622. (int)((x >> 16) & 0xff),
  623. (int)((x >> 8) & 0xff),
  624. (int)((x >> 0) & 0xff)
  625. );
  626. }
  627. void print_IPaddr (IPaddr_t x)
  628. {
  629. char tmp[16];
  630. ip_to_string(x, tmp);
  631. puts(tmp);
  632. }
  633. IPaddr_t getenv_IPaddr (char *var)
  634. {
  635. IPaddr_t addr;
  636. char *s, *e;
  637. int i;
  638. s = getenv (var);
  639. for (addr=0, i=0; i<4; ++i) {
  640. ulong val = s ? simple_strtoul(s, &e, 10) : 0;
  641. addr <<= 8;
  642. addr |= (val & 0xFF);
  643. if (s) {
  644. s = (*e) ? e+1 : e;
  645. }
  646. }
  647. return (htonl(addr));
  648. }