]>
Commit | Line | Data |
---|---|---|
a36b12f9 JH |
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, [email protected] | |
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 int ping_send(void) | |
20 | { | |
21 | static uchar mac[6]; | |
594c26f8 | 22 | struct ip_udp_hdr *ip; |
a36b12f9 JH |
23 | ushort *s; |
24 | uchar *pkt; | |
25 | ||
26 | /* XXX always send arp request */ | |
27 | ||
28 | memcpy(mac, NetEtherNullAddr, 6); | |
29 | ||
30 | debug("sending ARP for %pI4\n", &NetPingIP); | |
31 | ||
32 | NetArpWaitPacketIP = NetPingIP; | |
33 | NetArpWaitPacketMAC = mac; | |
34 | ||
35 | pkt = NetArpWaitTxPacket; | |
36 | pkt += NetSetEther(pkt, mac, PROT_IP); | |
37 | ||
594c26f8 | 38 | ip = (struct ip_udp_hdr *)pkt; |
a36b12f9 JH |
39 | |
40 | /* | |
41 | * Construct an IP and ICMP header. | |
42 | * (need to set no fragment bit - XXX) | |
43 | */ | |
44 | /* IP_HDR_SIZE / 4 (not including UDP) */ | |
45 | ip->ip_hl_v = 0x45; | |
46 | ip->ip_tos = 0; | |
c5c59df0 | 47 | ip->ip_len = htons(IP_HDR_SIZE + 8); |
a36b12f9 JH |
48 | ip->ip_id = htons(NetIPID++); |
49 | ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ | |
50 | ip->ip_ttl = 255; | |
51 | ip->ip_p = 0x01; /* ICMP */ | |
52 | ip->ip_sum = 0; | |
53 | /* already in network byte order */ | |
54 | NetCopyIP((void *)&ip->ip_src, &NetOurIP); | |
55 | /* - "" - */ | |
56 | NetCopyIP((void *)&ip->ip_dst, &NetPingIP); | |
c5c59df0 | 57 | ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE / 2); |
a36b12f9 JH |
58 | |
59 | s = &ip->udp_src; /* XXX ICMP starts here */ | |
60 | s[0] = htons(0x0800); /* echo-request, code */ | |
61 | s[1] = 0; /* checksum */ | |
62 | s[2] = 0; /* identifier */ | |
63 | s[3] = htons(PingSeqNo++); /* sequence number */ | |
64 | s[1] = ~NetCksum((uchar *)s, 8/2); | |
65 | ||
66 | /* size of the waiting packet */ | |
67 | NetArpWaitTxPacketSize = | |
c5c59df0 | 68 | (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + 8; |
a36b12f9 JH |
69 | |
70 | /* and do the ARP request */ | |
71 | NetArpWaitTry = 1; | |
72 | NetArpWaitTimerStart = get_timer(0); | |
73 | ArpRequest(); | |
74 | return 1; /* waiting */ | |
75 | } | |
76 | ||
77 | static void ping_timeout(void) | |
78 | { | |
79 | eth_halt(); | |
80 | NetState = NETLOOP_FAIL; /* we did not get the reply */ | |
81 | } | |
82 | ||
83 | static void ping_handler(uchar *pkt, unsigned dest, IPaddr_t sip, | |
84 | unsigned src, unsigned len) | |
85 | { | |
86 | if (sip != NetPingIP) | |
87 | return; | |
88 | ||
89 | NetState = NETLOOP_SUCCESS; | |
90 | } | |
91 | ||
92 | void ping_start(void) | |
93 | { | |
94 | printf("Using %s device\n", eth_get_name()); | |
95 | NetSetTimeout(10000UL, ping_timeout); | |
96 | NetSetHandler(ping_handler); | |
97 | ||
98 | ping_send(); | |
99 | } | |
100 | ||
cb487f56 | 101 | void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) |
a36b12f9 JH |
102 | { |
103 | ICMP_t *icmph = (ICMP_t *)&(ip->udp_src); | |
104 | IPaddr_t src_ip; | |
105 | ||
106 | switch (icmph->type) { | |
107 | case ICMP_ECHO_REPLY: | |
108 | /* | |
109 | * IP header OK. Pass the packet to the | |
110 | * current handler. | |
111 | */ | |
112 | /* XXX point to ip packet */ | |
113 | src_ip = NetReadIP((void *)&ip->ip_src); | |
114 | NetGetHandler()((uchar *)ip, 0, src_ip, 0, 0); | |
115 | return; | |
116 | case ICMP_ECHO_REQUEST: | |
117 | debug("Got ICMP ECHO REQUEST, return " | |
118 | "%d bytes\n", ETHER_HDR_SIZE + len); | |
119 | ||
120 | memcpy(&et->et_dest[0], &et->et_src[0], 6); | |
121 | memcpy(&et->et_src[0], NetOurEther, 6); | |
122 | ||
123 | ip->ip_sum = 0; | |
124 | ip->ip_off = 0; | |
125 | NetCopyIP((void *)&ip->ip_dst, &ip->ip_src); | |
126 | NetCopyIP((void *)&ip->ip_src, &NetOurIP); | |
127 | ip->ip_sum = ~NetCksum((uchar *)ip, | |
c5c59df0 | 128 | IP_HDR_SIZE >> 1); |
a36b12f9 JH |
129 | |
130 | icmph->type = ICMP_ECHO_REPLY; | |
131 | icmph->checksum = 0; | |
132 | icmph->checksum = ~NetCksum((uchar *)icmph, | |
c5c59df0 | 133 | (len - IP_HDR_SIZE) >> 1); |
a36b12f9 JH |
134 | (void) eth_send((uchar *)et, |
135 | ETHER_HDR_SIZE + len); | |
136 | return; | |
137 | /* default: | |
138 | return;*/ | |
139 | } | |
140 | } |