xref: /rk3399_rockchip-uboot/net/ping.c (revision 00f33268ab02984a5fa8b3783b6096d4ce6c48c7)
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 	int eth_hdr_size;
46 
47 	/* XXX always send arp request */
48 
49 	memcpy(mac, NetEtherNullAddr, 6);
50 
51 	debug("sending ARP for %pI4\n", &NetPingIP);
52 
53 	NetArpWaitPacketIP = NetPingIP;
54 	NetArpWaitPacketMAC = mac;
55 
56 	pkt = NetArpWaitTxPacket;
57 	eth_hdr_size = NetSetEther(pkt, mac, PROT_IP);
58 	pkt += eth_hdr_size;
59 
60 	set_icmp_header(pkt, NetPingIP);
61 
62 	/* size of the waiting packet */
63 	NetArpWaitTxPacketSize = eth_hdr_size + IP_ICMP_HDR_SIZE;
64 
65 	/* and do the ARP request */
66 	NetArpWaitTry = 1;
67 	NetArpWaitTimerStart = get_timer(0);
68 	ArpRequest();
69 	return 1;	/* waiting */
70 }
71 
72 static void ping_timeout(void)
73 {
74 	eth_halt();
75 	NetState = NETLOOP_FAIL;	/* we did not get the reply */
76 }
77 
78 static void ping_handler(uchar *pkt, unsigned dest, IPaddr_t sip,
79 	    unsigned src, unsigned len)
80 {
81 	if (sip != NetPingIP)
82 		return;
83 
84 	NetState = NETLOOP_SUCCESS;
85 }
86 
87 void ping_start(void)
88 {
89 	printf("Using %s device\n", eth_get_name());
90 	NetSetTimeout(10000UL, ping_timeout);
91 	NetSetHandler(ping_handler);
92 
93 	ping_send();
94 }
95 
96 void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
97 {
98 	struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
99 	IPaddr_t src_ip;
100 
101 	switch (icmph->type) {
102 	case ICMP_ECHO_REPLY:
103 		/*
104 		 * IP header OK.  Pass the packet to the
105 		 * current handler.
106 		 */
107 		/* XXX point to ip packet */
108 		src_ip = NetReadIP((void *)&ip->ip_src);
109 		NetGetHandler()((uchar *)ip, 0, src_ip, 0, 0);
110 		return;
111 	case ICMP_ECHO_REQUEST:
112 		debug("Got ICMP ECHO REQUEST, return "
113 			"%d bytes\n", ETHER_HDR_SIZE + len);
114 
115 		memcpy(&et->et_dest[0], &et->et_src[0], 6);
116 		memcpy(&et->et_src[0], NetOurEther, 6);
117 
118 		ip->ip_sum = 0;
119 		ip->ip_off = 0;
120 		NetCopyIP((void *)&ip->ip_dst, &ip->ip_src);
121 		NetCopyIP((void *)&ip->ip_src, &NetOurIP);
122 		ip->ip_sum = ~NetCksum((uchar *)ip,
123 				       IP_HDR_SIZE >> 1);
124 
125 		icmph->type = ICMP_ECHO_REPLY;
126 		icmph->checksum = 0;
127 		icmph->checksum = ~NetCksum((uchar *)icmph,
128 			(len - IP_HDR_SIZE) >> 1);
129 		(void) eth_send((uchar *)et,
130 				ETHER_HDR_SIZE + len);
131 		return;
132 /*	default:
133 		return;*/
134 	}
135 }
136