diff options
| author | Joe Hershberger <joe.hershberger@ni.com> | 2012-05-23 07:58:02 +0000 | 
|---|---|---|
| committer | Joe Hershberger <joe.hershberger@ni.com> | 2012-05-23 14:19:23 -0500 | 
| commit | a36b12f95a29647a06b5459198684fc142482020 (patch) | |
| tree | 6ad5427d06340b799b3e69d8f698e6fdbaaee7ef /net/ping.c | |
| parent | d280d3f430a4056e7baf66dc4be705dc8cc9bd37 (diff) | |
| download | olio-uboot-2014.01-a36b12f95a29647a06b5459198684fc142482020.tar.xz olio-uboot-2014.01-a36b12f95a29647a06b5459198684fc142482020.zip | |
net: Move PING out of net.c
Separate this functionality out of the net.c behemoth
Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Acked-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'net/ping.c')
| -rw-r--r-- | net/ping.c | 140 | 
1 files changed, 140 insertions, 0 deletions
| diff --git a/net/ping.c b/net/ping.c new file mode 100644 index 000000000..0e5b1dab7 --- /dev/null +++ b/net/ping.c @@ -0,0 +1,140 @@ +/* + *	Copied from Linux Monitor (LiMon) - Networking. + * + *	Copyright 1994 - 2000 Neil Russell. + *	(See License) + *	Copyright 2000 Roland Borde + *	Copyright 2000 Paolo Scaffardi + *	Copyright 2000-2002 Wolfgang Denk, wd@denx.de + */ + +#include "ping.h" +#include "arp.h" + +static ushort PingSeqNo; + +/* The ip address to ping */ +IPaddr_t NetPingIP; + +static int ping_send(void) +{ +	static uchar mac[6]; +	IP_t *ip; +	ushort *s; +	uchar *pkt; + +	/* XXX always send arp request */ + +	memcpy(mac, NetEtherNullAddr, 6); + +	debug("sending ARP for %pI4\n", &NetPingIP); + +	NetArpWaitPacketIP = NetPingIP; +	NetArpWaitPacketMAC = mac; + +	pkt = NetArpWaitTxPacket; +	pkt += NetSetEther(pkt, mac, PROT_IP); + +	ip = (IP_t *)pkt; + +	/* +	 * Construct an IP and ICMP header. +	 * (need to set no fragment bit - XXX) +	 */ +	/* IP_HDR_SIZE / 4 (not including UDP) */ +	ip->ip_hl_v  = 0x45; +	ip->ip_tos   = 0; +	ip->ip_len   = htons(IP_HDR_SIZE_NO_UDP + 8); +	ip->ip_id    = htons(NetIPID++); +	ip->ip_off   = htons(IP_FLAGS_DFRAG);	/* Don't fragment */ +	ip->ip_ttl   = 255; +	ip->ip_p     = 0x01;		/* ICMP */ +	ip->ip_sum   = 0; +	/* already in network byte order */ +	NetCopyIP((void *)&ip->ip_src, &NetOurIP); +	/* - "" - */ +	NetCopyIP((void *)&ip->ip_dst, &NetPingIP); +	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); + +	s = &ip->udp_src;		/* XXX ICMP starts here */ +	s[0] = htons(0x0800);		/* echo-request, code */ +	s[1] = 0;			/* checksum */ +	s[2] = 0;			/* identifier */ +	s[3] = htons(PingSeqNo++);	/* sequence number */ +	s[1] = ~NetCksum((uchar *)s, 8/2); + +	/* size of the waiting packet */ +	NetArpWaitTxPacketSize = +		(pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8; + +	/* and do the ARP request */ +	NetArpWaitTry = 1; +	NetArpWaitTimerStart = get_timer(0); +	ArpRequest(); +	return 1;	/* waiting */ +} + +static void ping_timeout(void) +{ +	eth_halt(); +	NetState = NETLOOP_FAIL;	/* we did not get the reply */ +} + +static void ping_handler(uchar *pkt, unsigned dest, IPaddr_t sip, +	    unsigned src, unsigned len) +{ +	if (sip != NetPingIP) +		return; + +	NetState = NETLOOP_SUCCESS; +} + +void ping_start(void) +{ +	printf("Using %s device\n", eth_get_name()); +	NetSetTimeout(10000UL, ping_timeout); +	NetSetHandler(ping_handler); + +	ping_send(); +} + +void ping_receive(Ethernet_t *et, IP_t *ip, int len) +{ +	ICMP_t *icmph = (ICMP_t *)&(ip->udp_src); +	IPaddr_t src_ip; + +	switch (icmph->type) { +	case ICMP_ECHO_REPLY: +		/* +		 * IP header OK.  Pass the packet to the +		 * current handler. +		 */ +		/* XXX point to ip packet */ +		src_ip = NetReadIP((void *)&ip->ip_src); +		NetGetHandler()((uchar *)ip, 0, src_ip, 0, 0); +		return; +	case ICMP_ECHO_REQUEST: +		debug("Got ICMP ECHO REQUEST, return " +			"%d bytes\n", ETHER_HDR_SIZE + len); + +		memcpy(&et->et_dest[0], &et->et_src[0], 6); +		memcpy(&et->et_src[0], NetOurEther, 6); + +		ip->ip_sum = 0; +		ip->ip_off = 0; +		NetCopyIP((void *)&ip->ip_dst, &ip->ip_src); +		NetCopyIP((void *)&ip->ip_src, &NetOurIP); +		ip->ip_sum = ~NetCksum((uchar *)ip, +				       IP_HDR_SIZE_NO_UDP >> 1); + +		icmph->type = ICMP_ECHO_REPLY; +		icmph->checksum = 0; +		icmph->checksum = ~NetCksum((uchar *)icmph, +			(len - IP_HDR_SIZE_NO_UDP) >> 1); +		(void) eth_send((uchar *)et, +				ETHER_HDR_SIZE + len); +		return; +/*	default: +		return;*/ +	} +} |