xref: /rk3399_rockchip-uboot/net/ping.c (revision 4b11c9166b86ccc5f8f02fda01ded0f9e9760df0)
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 #include "ping.h"
12 #include "arp.h"
13 
14 static ushort PingSeqNo;
15 
16 /* The ip address to ping */
17 IPaddr_t NetPingIP;
18 
19 static void set_icmp_header(uchar *pkt, IPaddr_t dest)
20 {
21 	/*
22 	 *	Construct an IP and ICMP header.
23 	 */
24 	struct ip_hdr *ip = (struct ip_hdr *)pkt;
25 	struct icmp_hdr *icmp = (struct icmp_hdr *)(pkt + IP_HDR_SIZE);
26 
27 	net_set_ip_header(pkt, dest, NetOurIP);
28 
29 	ip->ip_len   = htons(IP_ICMP_HDR_SIZE);
30 	ip->ip_p     = IPPROTO_ICMP;
31 	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1);
32 
33 	icmp->type = ICMP_ECHO_REQUEST;
34 	icmp->code = 0;
35 	icmp->checksum = 0;
36 	icmp->un.echo.id = 0;
37 	icmp->un.echo.sequence = htons(PingSeqNo++);
38 	icmp->checksum = ~NetCksum((uchar *)icmp, ICMP_HDR_SIZE	>> 1);
39 }
40 
41 static int ping_send(void)
42 {
43 	static uchar mac[6];
44 	uchar *pkt;
45 
46 	/* XXX always send arp request */
47 
48 	memcpy(mac, NetEtherNullAddr, 6);
49 
50 	debug("sending ARP for %pI4\n", &NetPingIP);
51 
52 	NetArpWaitPacketIP = NetPingIP;
53 	NetArpWaitPacketMAC = mac;
54 
55 	pkt = NetArpWaitTxPacket;
56 	pkt += NetSetEther(pkt, mac, PROT_IP);
57 
58 	set_icmp_header(pkt, NetPingIP);
59 
60 	/* size of the waiting packet */
61 	NetArpWaitTxPacketSize =
62 		(pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + 8;
63 
64 	/* and do the ARP request */
65 	NetArpWaitTry = 1;
66 	NetArpWaitTimerStart = get_timer(0);
67 	ArpRequest();
68 	return 1;	/* waiting */
69 }
70 
71 static void ping_timeout(void)
72 {
73 	eth_halt();
74 	NetState = NETLOOP_FAIL;	/* we did not get the reply */
75 }
76 
77 static void ping_handler(uchar *pkt, unsigned dest, IPaddr_t sip,
78 	    unsigned src, unsigned len)
79 {
80 	if (sip != NetPingIP)
81 		return;
82 
83 	NetState = NETLOOP_SUCCESS;
84 }
85 
86 void ping_start(void)
87 {
88 	printf("Using %s device\n", eth_get_name());
89 	NetSetTimeout(10000UL, ping_timeout);
90 	NetSetHandler(ping_handler);
91 
92 	ping_send();
93 }
94 
95 void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
96 {
97 	struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
98 	IPaddr_t src_ip;
99 
100 	switch (icmph->type) {
101 	case ICMP_ECHO_REPLY:
102 		/*
103 		 * IP header OK.  Pass the packet to the
104 		 * current handler.
105 		 */
106 		/* XXX point to ip packet */
107 		src_ip = NetReadIP((void *)&ip->ip_src);
108 		NetGetHandler()((uchar *)ip, 0, src_ip, 0, 0);
109 		return;
110 	case ICMP_ECHO_REQUEST:
111 		debug("Got ICMP ECHO REQUEST, return "
112 			"%d bytes\n", ETHER_HDR_SIZE + len);
113 
114 		memcpy(&et->et_dest[0], &et->et_src[0], 6);
115 		memcpy(&et->et_src[0], NetOurEther, 6);
116 
117 		ip->ip_sum = 0;
118 		ip->ip_off = 0;
119 		NetCopyIP((void *)&ip->ip_dst, &ip->ip_src);
120 		NetCopyIP((void *)&ip->ip_src, &NetOurIP);
121 		ip->ip_sum = ~NetCksum((uchar *)ip,
122 				       IP_HDR_SIZE >> 1);
123 
124 		icmph->type = ICMP_ECHO_REPLY;
125 		icmph->checksum = 0;
126 		icmph->checksum = ~NetCksum((uchar *)icmph,
127 			(len - IP_HDR_SIZE) >> 1);
128 		(void) eth_send((uchar *)et,
129 				ETHER_HDR_SIZE + len);
130 		return;
131 /*	default:
132 		return;*/
133 	}
134 }
135