Blame view

net/net.c 44.9 KB
2d966958c   wdenk   Initial revision
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  /*
   *	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
   */
  
  /*
   * General Desription:
   *
   * The user interface supports commands for BOOTP, RARP, and TFTP.
   * Also, we support ARP internally. Depending on available data,
   * these interact as follows:
   *
   * BOOTP:
   *
   *	Prerequisites:	- own ethernet address
   *	We want:	- own IP address
   *			- TFTP server IP address
   *			- name of bootfile
   *	Next step:	ARP
   *
   * RARP:
   *
   *	Prerequisites:	- own ethernet address
   *	We want:	- own IP address
   *			- TFTP server IP address
   *	Next step:	ARP
   *
   * ARP:
   *
   *	Prerequisites:	- own ethernet address
   *			- own IP address
   *			- TFTP server IP address
   *	We want:	- TFTP server ethernet address
   *	Next step:	TFTP
   *
   * DHCP:
   *
b2f508075   Wolfgang Denk   Minor code cleanup
43
44
45
46
   *     Prerequisites:	- own ethernet address
   *     We want:		- IP, Netmask, ServerIP, Gateway IP
   *			- bootfilename, lease time
   *     Next step:	- TFTP
2d966958c   wdenk   Initial revision
47
48
49
50
51
52
53
54
55
56
57
   *
   * TFTP:
   *
   *	Prerequisites:	- own ethernet address
   *			- own IP address
   *			- TFTP server IP address
   *			- TFTP server ethernet address
   *			- name of bootfile (if unknown, we use a default name
   *			  derived from our own IP address)
   *	We want:	- load the boot file
   *	Next step:	none
cbd8a35c6   wdenk   * Patch by Masami...
58
59
60
61
62
63
64
65
66
   *
   * NFS:
   *
   *	Prerequisites:	- own ethernet address
   *			- own IP address
   *			- name of bootfile (if unknown, we use a default name
   *			  derived from our own IP address)
   *	We want:	- load the boot file
   *	Next step:	none
ea287debe   wdenk   * Patch by Masami...
67
68
69
   *
   * SNTP:
   *
b2f508075   Wolfgang Denk   Minor code cleanup
70
   *	Prerequisites:	- own ethernet address
ea287debe   wdenk   * Patch by Masami...
71
72
73
   *			- own IP address
   *	We want:	- network time
   *	Next step:	none
2d966958c   wdenk   Initial revision
74
75
76
77
78
79
80
81
82
   */
  
  
  #include <common.h>
  #include <watchdog.h>
  #include <command.h>
  #include <net.h>
  #include "bootp.h"
  #include "tftp.h"
bf6cb247a   Peter Tyser   rarp: Condtionall...
83
  #ifdef CONFIG_CMD_RARP
2d966958c   wdenk   Initial revision
84
  #include "rarp.h"
bf6cb247a   Peter Tyser   rarp: Condtionall...
85
  #endif
cbd8a35c6   wdenk   * Patch by Masami...
86
  #include "nfs.h"
fc3e2165e   wdenk   * Patch by Sangmo...
87
88
89
90
  #ifdef CONFIG_STATUS_LED
  #include <status_led.h>
  #include <miiphy.h>
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
91
  #if defined(CONFIG_CMD_SNTP)
ea287debe   wdenk   * Patch by Masami...
92
93
  #include "sntp.h"
  #endif
561858ee7   Peter Tyser   Update U-Boot's b...
94
95
96
  #if defined(CONFIG_CDP_VERSION)
  #include <timestamp.h>
  #endif
1a32bf418   Robin Getz   Add DNS support
97
98
99
  #if defined(CONFIG_CMD_DNS)
  #include "dns.h"
  #endif
2d966958c   wdenk   Initial revision
100

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
101
  DECLARE_GLOBAL_DATA_PTR;
40cb90ee2   Guennadi Liakhovetski   net: make ARP tim...
102
  #ifndef	CONFIG_ARP_TIMEOUT
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
103
104
  /* Milliseconds before trying ARP again */
  # define ARP_TIMEOUT		5000UL
40cb90ee2   Guennadi Liakhovetski   net: make ARP tim...
105
  #else
49f3bdbba   Bartlomiej Sieka   net: express the ...
106
  # define ARP_TIMEOUT		CONFIG_ARP_TIMEOUT
40cb90ee2   Guennadi Liakhovetski   net: make ARP tim...
107
  #endif
73a8b27c5   wdenk   * Add support for...
108
  #ifndef	CONFIG_NET_RETRY_COUNT
40cb90ee2   Guennadi Liakhovetski   net: make ARP tim...
109
  # define ARP_TIMEOUT_COUNT	5	/* # of timeouts before giving up  */
73a8b27c5   wdenk   * Add support for...
110
  #else
40cb90ee2   Guennadi Liakhovetski   net: make ARP tim...
111
  # define ARP_TIMEOUT_COUNT	CONFIG_NET_RETRY_COUNT
73a8b27c5   wdenk   * Add support for...
112
  #endif
2d966958c   wdenk   Initial revision
113
  /** BOOTP EXTENTIONS **/
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
114
  /* Our subnet mask (0=unknown) */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
115
  IPaddr_t	NetOurSubnetMask;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
116
  /* Our gateways IP address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
117
  IPaddr_t	NetOurGatewayIP;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
118
  /* Our DNS IP address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
119
  IPaddr_t	NetOurDNSIP;
1fe80d79c   Jon Loeliger   Finally retire cm...
120
  #if defined(CONFIG_BOOTP_DNS2)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
121
  /* Our 2nd DNS IP address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
122
  IPaddr_t	NetOurDNS2IP;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
123
124
  #endif
  /* Our NIS domain */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
125
  char		NetOurNISDomain[32] = {0,};
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
126
  /* Our hostname */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
127
  char		NetOurHostName[32] = {0,};
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
128
  /* Our bootpath */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
129
  char		NetOurRootPath[64] = {0,};
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
130
  /* Our bootfile size in blocks */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
131
  ushort		NetBootFileSize;
2d966958c   wdenk   Initial revision
132

53a5c424b   David Updegraff   multicast tftp: R...
133
134
135
  #ifdef CONFIG_MCAST_TFTP	/* Multicast TFTP */
  IPaddr_t Mcast_addr;
  #endif
2d966958c   wdenk   Initial revision
136
  /** END OF BOOTP EXTENTIONS **/
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
137
138
139
140
141
  /* The actual transferred size of the bootfile (in bytes) */
  ulong		NetBootFileXferSize;
  /* Our ethernet address */
  uchar		NetOurEther[6];
  /* Boot server enet address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
142
  uchar		NetServerEther[6];
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
143
144
145
146
147
148
149
150
151
152
153
  /* Our IP addr (0 = unknown) */
  IPaddr_t	NetOurIP;
  /* Server IP addr (0 = unknown) */
  IPaddr_t	NetServerIP;
  /* Current receive packet */
  volatile uchar *NetRxPacket;
  /* Current rx packet length */
  int		NetRxPacketLen;
  /* IP packet ID */
  unsigned	NetIPID;
  /* Ethernet bcast address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
154
155
  uchar		NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  uchar		NetEtherNullAddr[6];
f85b60710   Rafal Jaworowski   Introduce new eth...
156
157
158
  #ifdef CONFIG_API
  void		(*push_packet)(volatile void *, int len) = 0;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
159
  #if defined(CONFIG_CMD_CDP)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
160
  /* Ethernet bcast address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
161
  uchar		NetCDPAddr[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };
a3d991bd0   wdenk   Patches by Pantel...
162
  #endif
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
163
164
  /* Network loop state */
  int		NetState;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
165
  /* Tried all network devices */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
166
  int		NetRestartWrap;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
167
  /* Network loop restarted */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
168
  static int	NetRestarted;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
169
  /* At least one device configured */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
170
  static int	NetDevExists;
2d966958c   wdenk   Initial revision
171

6e5923851   wdenk   * Cleanup, minor ...
172
  /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
173
174
175
176
  /* default is without VLAN */
  ushort		NetOurVLAN = 0xFFFF;
  /* ditto */
  ushort		NetOurNativeVLAN = 0xFFFF;
a3d991bd0   wdenk   Patches by Pantel...
177

3e38e429f   Luca Ceresoli   net/net.c: cosmet...
178
179
  /* Boot File name */
  char		BootFile[128];
2d966958c   wdenk   Initial revision
180

643d1ab23   Jon Loeliger   net/: Remove obso...
181
  #if defined(CONFIG_CMD_PING)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
182
183
  /* the ip address to ping */
  IPaddr_t	NetPingIP;
73a8b27c5   wdenk   * Add support for...
184
185
186
  
  static void PingStart(void);
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
187
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
188
189
  static void CDPStart(void);
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
190
  #if defined(CONFIG_CMD_SNTP)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
191
192
193
  /* NTP server IP address */
  IPaddr_t	NetNtpServerIP;
  /* offset time from UTC */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
194
  int		NetTimeOffset;
ea287debe   wdenk   * Patch by Masami...
195
  #endif
68ceb29e7   wdenk   Add support for c...
196
197
198
199
  #ifdef CONFIG_NETCONSOLE
  void NcStart(void);
  int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
  #endif
2d966958c   wdenk   Initial revision
200
  volatile uchar	PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
201
202
  /* Receive packet */
  volatile uchar *NetRxPackets[PKTBUFSRX];
2d966958c   wdenk   Initial revision
203

3e38e429f   Luca Ceresoli   net/net.c: cosmet...
204
205
  /* Current RX packet handler */
  static rxhand_f *packetHandler;
39bccd21d   Simon Glass   net: Hide more co...
206
  #ifdef CONFIG_CMD_TFTPPUT
4793ee652   Simon Glass   net: tftpput: Add...
207
  static rxhand_icmp_f *packet_icmp_handler;	/* Current ICMP rx handler */
39bccd21d   Simon Glass   net: Hide more co...
208
  #endif
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
209
210
211
212
213
214
215
  /* Current timeout handler */
  static thand_f *timeHandler;
  /* Time base value */
  static ulong	timeStart;
  /* Current timeout value */
  static ulong	timeDelta;
  /* THE transmit packet */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
216
  volatile uchar *NetTxPacket;
2d966958c   wdenk   Initial revision
217

e4bf0c5cf   Simon Glass   net: tftpput: Ren...
218
  static int net_check_prereq(enum proto_t protocol);
2d966958c   wdenk   Initial revision
219

67b96e87d   Remy Bohmer   Repair the 'netre...
220
  static int NetTryCount;
2d966958c   wdenk   Initial revision
221
  /**********************************************************************/
73a8b27c5   wdenk   * Add support for...
222
223
224
  
  IPaddr_t	NetArpWaitPacketIP;
  IPaddr_t	NetArpWaitReplyIP;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
225
226
227
228
  /* MAC address of waiting packet's destination */
  uchar	       *NetArpWaitPacketMAC;
  /* THE transmit packet */
  uchar	       *NetArpWaitTxPacket;
73a8b27c5   wdenk   * Add support for...
229
  int		NetArpWaitTxPacketSize;
53677ef18   Wolfgang Denk   Big white-space c...
230
  uchar		NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
73a8b27c5   wdenk   * Add support for...
231
232
  ulong		NetArpWaitTimerStart;
  int		NetArpWaitTry;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
233
  void ArpRequest(void)
73a8b27c5   wdenk   * Add support for...
234
  {
73a8b27c5   wdenk   * Add support for...
235
  	volatile uchar *pkt;
6e5923851   wdenk   * Cleanup, minor ...
236
  	ARP_t *arp;
73a8b27c5   wdenk   * Add support for...
237

0ebf04c60   Robin Getz   minor debug clean...
238
239
  	debug("ARP broadcast %d
  ", NetArpWaitTry);
73a8b27c5   wdenk   * Add support for...
240
  	pkt = NetTxPacket;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
241
  	pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
73a8b27c5   wdenk   * Add support for...
242

6e5923851   wdenk   * Cleanup, minor ...
243
  	arp = (ARP_t *) pkt;
73a8b27c5   wdenk   * Add support for...
244

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
245
246
  	arp->ar_hrd = htons(ARP_ETHER);
  	arp->ar_pro = htons(PROT_IP);
73a8b27c5   wdenk   * Add support for...
247
248
  	arp->ar_hln = 6;
  	arp->ar_pln = 4;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
249
  	arp->ar_op = htons(ARPOP_REQUEST);
73a8b27c5   wdenk   * Add support for...
250

3e38e429f   Luca Ceresoli   net/net.c: cosmet...
251
  	/* source ET addr */
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
252
  	memcpy(&arp->ar_data[0], NetOurEther, 6);
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
253
  	/* source IP addr */
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
254
  	NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
ed1ada712   Simon Glass   net: Change for l...
255
256
  	/* dest ET addr = 0 */
  	memset(&arp->ar_data[10], '\0', 6);
6e5923851   wdenk   * Cleanup, minor ...
257
258
259
  	if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
  	    (NetOurIP & NetOurSubnetMask)) {
  		if (NetOurGatewayIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
260
261
  			puts("## Warning: gatewayip needed but not set
  ");
d509b8121   Wolfgang Denk   Fix behaviour if ...
262
263
264
  			NetArpWaitReplyIP = NetArpWaitPacketIP;
  		} else {
  			NetArpWaitReplyIP = NetOurGatewayIP;
6e5923851   wdenk   * Cleanup, minor ...
265
  		}
6e5923851   wdenk   * Cleanup, minor ...
266
267
268
  	} else {
  		NetArpWaitReplyIP = NetArpWaitPacketIP;
  	}
73a8b27c5   wdenk   * Add support for...
269

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
270
271
  	NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP);
  	(void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
73a8b27c5   wdenk   * Add support for...
272
273
274
275
276
277
278
279
280
281
282
283
  }
  
  void ArpTimeoutCheck(void)
  {
  	ulong t;
  
  	if (!NetArpWaitPacketIP)
  		return;
  
  	t = get_timer(0);
  
  	/* check for arp timeout */
49f3bdbba   Bartlomiej Sieka   net: express the ...
284
  	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
73a8b27c5   wdenk   * Add support for...
285
286
287
  		NetArpWaitTry++;
  
  		if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
288
289
290
  			puts("
  ARP Retry count exceeded; starting again
  ");
73a8b27c5   wdenk   * Add support for...
291
292
293
294
295
296
297
298
  			NetArpWaitTry = 0;
  			NetStartAgain();
  		} else {
  			NetArpWaitTimerStart = t;
  			ArpRequest();
  		}
  	}
  }
e4a3d57dc   Simon Glass   net: Export auto_...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  /*
   * Check if autoload is enabled. If so, use either NFS or TFTP to download
   * the boot file.
   */
  void net_auto_load(void)
  {
  	const char *s = getenv("autoload");
  
  	if (s != NULL) {
  		if (*s == 'n') {
  			/*
  			 * Just use BOOTP/RARP to configure system;
  			 * Do not use TFTP to load the bootfile.
  			 */
  			NetState = NETLOOP_SUCCESS;
  			return;
  		}
  #if defined(CONFIG_CMD_NFS)
  		if (strcmp(s, "NFS") == 0) {
  			/*
  			 * Use NFS to load the bootfile.
  			 */
  			NfsStart();
  			return;
  		}
  #endif
  	}
  	TftpStart(TFTPGET);
  }
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
328
  static void NetInitLoop(enum proto_t protocol)
2f70c49e5   Heiko Schocher   netloop: speed up...
329
  {
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
330
  	static int env_changed_id;
2f70c49e5   Heiko Schocher   netloop: speed up...
331
  	bd_t *bd = gd->bd;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
332
  	int env_id = get_env_id();
2f70c49e5   Heiko Schocher   netloop: speed up...
333
334
  
  	/* update only when the environment has changed */
3c172c4fd   Michael Zaidman   NetLoop initializ...
335
  	if (env_changed_id != env_id) {
23a70bf9c   Enric Balletbo i Serra   net/net.c: Update...
336
337
  		NetOurIP = getenv_IPaddr("ipaddr");
  		NetCopyIP(&bd->bi_ip_addr, &NetOurIP);
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
338
339
340
  		NetOurGatewayIP = getenv_IPaddr("gatewayip");
  		NetOurSubnetMask = getenv_IPaddr("netmask");
  		NetServerIP = getenv_IPaddr("serverip");
2f70c49e5   Heiko Schocher   netloop: speed up...
341
  		NetOurNativeVLAN = getenv_VLAN("nvlan");
3c172c4fd   Michael Zaidman   NetLoop initializ...
342
  		NetOurVLAN = getenv_VLAN("vlan");
1a32bf418   Robin Getz   Add DNS support
343
344
345
  #if defined(CONFIG_CMD_DNS)
  		NetOurDNSIP = getenv_IPaddr("dnsip");
  #endif
3c172c4fd   Michael Zaidman   NetLoop initializ...
346
  		env_changed_id = env_id;
2f70c49e5   Heiko Schocher   netloop: speed up...
347
  	}
3c172c4fd   Michael Zaidman   NetLoop initializ...
348

da95427ce   Heiko Schocher   netloop: updates ...
349
  	return;
2f70c49e5   Heiko Schocher   netloop: speed up...
350
  }
73a8b27c5   wdenk   * Add support for...
351
  /**********************************************************************/
2d966958c   wdenk   Initial revision
352
353
354
  /*
   *	Main network processing loop.
   */
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
355
  int NetLoop(enum proto_t protocol)
2d966958c   wdenk   Initial revision
356
  {
2d966958c   wdenk   Initial revision
357
  	bd_t *bd = gd->bd;
4793ee652   Simon Glass   net: tftpput: Add...
358
  	int ret = -1;
2d966958c   wdenk   Initial revision
359

2d966958c   wdenk   Initial revision
360
361
  	NetRestarted = 0;
  	NetDevExists = 0;
2d966958c   wdenk   Initial revision
362

73a8b27c5   wdenk   * Add support for...
363
364
365
366
367
368
369
  	/* XXX problem with bss workaround */
  	NetArpWaitPacketMAC = NULL;
  	NetArpWaitTxPacket = NULL;
  	NetArpWaitPacketIP = 0;
  	NetArpWaitReplyIP = 0;
  	NetArpWaitTxPacket = NULL;
  	NetTxPacket = NULL;
67b96e87d   Remy Bohmer   Repair the 'netre...
370
  	NetTryCount = 1;
73a8b27c5   wdenk   * Add support for...
371

2d966958c   wdenk   Initial revision
372
373
  	if (!NetTxPacket) {
  		int	i;
2d966958c   wdenk   Initial revision
374
375
376
377
378
  		/*
  		 *	Setup packet buffers, aligned correctly.
  		 */
  		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
  		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
379
  		for (i = 0; i < PKTBUFSRX; i++)
2d966958c   wdenk   Initial revision
380
  			NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
73a8b27c5   wdenk   * Add support for...
381
382
383
384
385
386
  	}
  
  	if (!NetArpWaitTxPacket) {
  		NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
  		NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
  		NetArpWaitTxPacketSize = 0;
2d966958c   wdenk   Initial revision
387
  	}
573f14fe4   Simon Glass   bootstage: Plumb ...
388
  	bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
2d966958c   wdenk   Initial revision
389
  	eth_halt();
a3d991bd0   wdenk   Patches by Pantel...
390
  	eth_set_current();
b1bf6f2c9   wdenk   * Patch by Richar...
391
392
  	if (eth_init(bd) < 0) {
  		eth_halt();
92895de97   Luca Ceresoli   net/net.c: cosmet...
393
  		return -1;
b1bf6f2c9   wdenk   * Patch by Richar...
394
  	}
2d966958c   wdenk   Initial revision
395
396
  
  restart:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
397
  	memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
2d966958c   wdenk   Initial revision
398
399
400
401
402
403
404
405
  
  	NetState = NETLOOP_CONTINUE;
  
  	/*
  	 *	Start the ball rolling with the given start function.  From
  	 *	here on, this code is a state machine driven by received
  	 *	packets and timer events.
  	 */
2f70c49e5   Heiko Schocher   netloop: speed up...
406
  	NetInitLoop(protocol);
2d966958c   wdenk   Initial revision
407

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
408
  	switch (net_check_prereq(protocol)) {
2d966958c   wdenk   Initial revision
409
410
  	case 1:
  		/* network not configured */
b1bf6f2c9   wdenk   * Patch by Richar...
411
  		eth_halt();
92895de97   Luca Ceresoli   net/net.c: cosmet...
412
  		return -1;
2d966958c   wdenk   Initial revision
413

2d966958c   wdenk   Initial revision
414
415
416
  	case 2:
  		/* network device not configured */
  		break;
2d966958c   wdenk   Initial revision
417
418
  
  	case 0:
2d966958c   wdenk   Initial revision
419
  		NetDevExists = 1;
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
420
  		NetBootFileXferSize = 0;
2d966958c   wdenk   Initial revision
421
  		switch (protocol) {
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
422
  		case TFTPGET:
1fb7cd498   Simon Glass   net: tftpput: imp...
423
424
425
  #ifdef CONFIG_CMD_TFTPPUT
  		case TFTPPUT:
  #endif
2d966958c   wdenk   Initial revision
426
  			/* always use ARP to get server ethernet address */
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
427
  			TftpStart(protocol);
2d966958c   wdenk   Initial revision
428
  			break;
7a83af07a   Luca Ceresoli   TFTP: add tftpsrv...
429
430
431
432
433
  #ifdef CONFIG_CMD_TFTPSRV
  		case TFTPSRV:
  			TftpStartServer();
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
434
  #if defined(CONFIG_CMD_DHCP)
2d966958c   wdenk   Initial revision
435
  		case DHCP:
d407bf52b   wdenk   * Patch by Philip...
436
  			BootpTry = 0;
09133f858   Michael Zaidman   DHCP regression o...
437
  			NetOurIP = 0;
2d966958c   wdenk   Initial revision
438
439
  			DhcpRequest();		/* Basically same as BOOTP */
  			break;
610f2e9c2   Jon Loeliger   net/: Remove ling...
440
  #endif
2d966958c   wdenk   Initial revision
441
442
443
  
  		case BOOTP:
  			BootpTry = 0;
09133f858   Michael Zaidman   DHCP regression o...
444
  			NetOurIP = 0;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
445
  			BootpRequest();
2d966958c   wdenk   Initial revision
446
  			break;
bf6cb247a   Peter Tyser   rarp: Condtionall...
447
  #if defined(CONFIG_CMD_RARP)
2d966958c   wdenk   Initial revision
448
449
  		case RARP:
  			RarpTry = 0;
09133f858   Michael Zaidman   DHCP regression o...
450
  			NetOurIP = 0;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
451
  			RarpRequest();
2d966958c   wdenk   Initial revision
452
  			break;
bf6cb247a   Peter Tyser   rarp: Condtionall...
453
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
454
  #if defined(CONFIG_CMD_PING)
73a8b27c5   wdenk   * Add support for...
455
456
457
458
  		case PING:
  			PingStart();
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
459
  #if defined(CONFIG_CMD_NFS)
cbd8a35c6   wdenk   * Patch by Masami...
460
461
462
463
  		case NFS:
  			NfsStart();
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
464
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
465
466
467
468
  		case CDP:
  			CDPStart();
  			break;
  #endif
68ceb29e7   wdenk   Add support for c...
469
470
471
472
473
  #ifdef CONFIG_NETCONSOLE
  		case NETCONS:
  			NcStart();
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
474
  #if defined(CONFIG_CMD_SNTP)
ea287debe   wdenk   * Patch by Masami...
475
476
477
478
  		case SNTP:
  			SntpStart();
  			break;
  #endif
1a32bf418   Robin Getz   Add DNS support
479
480
481
482
483
  #if defined(CONFIG_CMD_DNS)
  		case DNS:
  			DnsStart();
  			break;
  #endif
2d966958c   wdenk   Initial revision
484
485
486
  		default:
  			break;
  		}
2d966958c   wdenk   Initial revision
487
488
  		break;
  	}
643d1ab23   Jon Loeliger   net/: Remove obso...
489
  #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
490
491
492
  #if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
  	defined(CONFIG_STATUS_LED)			&& \
  	defined(STATUS_LED_RED)
fc3e2165e   wdenk   * Patch by Sangmo...
493
  	/*
42d1f0394   wdenk   * Patches by Xian...
494
  	 * Echo the inverted link state to the fault LED.
fc3e2165e   wdenk   * Patch by Sangmo...
495
  	 */
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
496
  	if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
497
  		status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
498
  	else
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
499
  		status_led_set(STATUS_LED_RED, STATUS_LED_ON);
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
500
  #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
fc3e2165e   wdenk   * Patch by Sangmo...
501
  #endif /* CONFIG_MII, ... */
2d966958c   wdenk   Initial revision
502
503
504
  
  	/*
  	 *	Main packet reception loop.  Loop receiving packets until
59acc296d   wdenk   Minor cleanup
505
  	 *	someone sets `NetState' to a state that terminates.
2d966958c   wdenk   Initial revision
506
507
508
509
510
511
512
513
514
515
516
517
518
  	 */
  	for (;;) {
  		WATCHDOG_RESET();
  #ifdef CONFIG_SHOW_ACTIVITY
  		{
  			extern void show_activity(int arg);
  			show_activity(1);
  		}
  #endif
  		/*
  		 *	Check the ethernet for a new packet.  The ethernet
  		 *	receive routine will process it.
  		 */
40cb90ee2   Guennadi Liakhovetski   net: make ARP tim...
519
  		eth_rx();
2d966958c   wdenk   Initial revision
520
521
522
523
524
  
  		/*
  		 *	Abort if ctrl-c was pressed.
  		 */
  		if (ctrlc()) {
8bde7f776   wdenk   * Code cleanup:
525
  			eth_halt();
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
526
527
528
  			puts("
  Abort
  ");
4793ee652   Simon Glass   net: tftpput: Add...
529
  			goto done;
2d966958c   wdenk   Initial revision
530
  		}
73a8b27c5   wdenk   * Add support for...
531
  		ArpTimeoutCheck();
2d966958c   wdenk   Initial revision
532
533
534
535
536
  
  		/*
  		 *	Check for a timeout, and run the timeout handler
  		 *	if we have one.
  		 */
e0ac62d79   wdenk   * Make Ethernet a...
537
  		if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
2d966958c   wdenk   Initial revision
538
  			thand_f *x;
643d1ab23   Jon Loeliger   net/: Remove obso...
539
  #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
540
541
542
  #if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
  	defined(CONFIG_STATUS_LED)			&& \
  	defined(STATUS_LED_RED)
fc3e2165e   wdenk   * Patch by Sangmo...
543
  			/*
42d1f0394   wdenk   * Patches by Xian...
544
  			 * Echo the inverted link state to the fault LED.
fc3e2165e   wdenk   * Patch by Sangmo...
545
  			 */
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
546
  			if (miiphy_link(eth_get_dev()->name,
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
547
  				       CONFIG_SYS_FAULT_MII_ADDR)) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
548
  				status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
fc3e2165e   wdenk   * Patch by Sangmo...
549
  			} else {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
550
  				status_led_set(STATUS_LED_RED, STATUS_LED_ON);
fc3e2165e   wdenk   * Patch by Sangmo...
551
  			}
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
552
  #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
fc3e2165e   wdenk   * Patch by Sangmo...
553
  #endif /* CONFIG_MII, ... */
2d966958c   wdenk   Initial revision
554
555
556
557
558
559
560
561
562
  			x = timeHandler;
  			timeHandler = (thand_f *)0;
  			(*x)();
  		}
  
  
  		switch (NetState) {
  
  		case NETLOOP_RESTART:
2d966958c   wdenk   Initial revision
563
  			NetRestarted = 1;
2d966958c   wdenk   Initial revision
564
565
566
567
  			goto restart;
  
  		case NETLOOP_SUCCESS:
  			if (NetBootFileXferSize > 0) {
f34024d4a   Wolfgang Denk   Fix memory corrup...
568
  				char buf[20];
2d966958c   wdenk   Initial revision
569
570
571
572
  				printf("Bytes transferred = %ld (%lx hex)
  ",
  					NetBootFileXferSize,
  					NetBootFileXferSize);
f34024d4a   Wolfgang Denk   Fix memory corrup...
573
  				sprintf(buf, "%lX", NetBootFileXferSize);
2d966958c   wdenk   Initial revision
574
  				setenv("filesize", buf);
a3d991bd0   wdenk   Patches by Pantel...
575
576
577
  
  				sprintf(buf, "%lX", (unsigned long)load_addr);
  				setenv("fileaddr", buf);
2d966958c   wdenk   Initial revision
578
579
  			}
  			eth_halt();
4793ee652   Simon Glass   net: tftpput: Add...
580
581
  			ret = NetBootFileXferSize;
  			goto done;
2d966958c   wdenk   Initial revision
582
583
  
  		case NETLOOP_FAIL:
4793ee652   Simon Glass   net: tftpput: Add...
584
  			goto done;
2d966958c   wdenk   Initial revision
585
586
  		}
  	}
4793ee652   Simon Glass   net: tftpput: Add...
587
588
  
  done:
39bccd21d   Simon Glass   net: Hide more co...
589
  #ifdef CONFIG_CMD_TFTPPUT
4793ee652   Simon Glass   net: tftpput: Add...
590
591
592
  	/* Clear out the handlers */
  	NetSetHandler(NULL);
  	net_set_icmp_handler(NULL);
39bccd21d   Simon Glass   net: Hide more co...
593
  #endif
4793ee652   Simon Glass   net: tftpput: Add...
594
  	return ret;
2d966958c   wdenk   Initial revision
595
596
597
598
599
600
601
602
603
604
605
  }
  
  /**********************************************************************/
  
  static void
  startAgainTimeout(void)
  {
  	NetState = NETLOOP_RESTART;
  }
  
  static void
03eb129f8   Luca Ceresoli   NET: pass source ...
606
607
  startAgainHandler(uchar *pkt, unsigned dest, IPaddr_t sip,
  		  unsigned src, unsigned len)
2d966958c   wdenk   Initial revision
608
609
610
  {
  	/* Totally ignore the packet */
  }
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
611
  void NetStartAgain(void)
2d966958c   wdenk   Initial revision
612
  {
6e5923851   wdenk   * Cleanup, minor ...
613
  	char *nretry;
67b96e87d   Remy Bohmer   Repair the 'netre...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
  	int retry_forever = 0;
  	unsigned long retrycnt = 0;
  
  	nretry = getenv("netretry");
  	if (nretry) {
  		if (!strcmp(nretry, "yes"))
  			retry_forever = 1;
  		else if (!strcmp(nretry, "no"))
  			retrycnt = 0;
  		else if (!strcmp(nretry, "once"))
  			retrycnt = 1;
  		else
  			retrycnt = simple_strtoul(nretry, NULL, 0);
  	} else
  		retry_forever = 1;
  
  	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
  		eth_halt();
a3d991bd0   wdenk   Patches by Pantel...
632
633
634
  		NetState = NETLOOP_FAIL;
  		return;
  	}
67b96e87d   Remy Bohmer   Repair the 'netre...
635
636
  
  	NetTryCount++;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
637
  	eth_halt();
8b0c5c127   Matthias Fuchs   net: Add CONFIG_N...
638
  #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
639
  	eth_try_another(!NetRestarted);
8b0c5c127   Matthias Fuchs   net: Add CONFIG_N...
640
  #endif
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
641
  	eth_init(gd->bd);
6e5923851   wdenk   * Cleanup, minor ...
642
  	if (NetRestartWrap) {
2d966958c   wdenk   Initial revision
643
  		NetRestartWrap = 0;
67b96e87d   Remy Bohmer   Repair the 'netre...
644
  		if (NetDevExists) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
645
646
  			NetSetTimeout(10000UL, startAgainTimeout);
  			NetSetHandler(startAgainHandler);
6e5923851   wdenk   * Cleanup, minor ...
647
  		} else {
2d966958c   wdenk   Initial revision
648
649
  			NetState = NETLOOP_FAIL;
  		}
6e5923851   wdenk   * Cleanup, minor ...
650
  	} else {
2d966958c   wdenk   Initial revision
651
652
  		NetState = NETLOOP_RESTART;
  	}
2d966958c   wdenk   Initial revision
653
654
655
656
657
658
659
660
  }
  
  /**********************************************************************/
  /*
   *	Miscelaneous bits.
   */
  
  void
6b147d113   Luca Ceresoli   net/net.c: cosmet...
661
  NetSetHandler(rxhand_f *f)
2d966958c   wdenk   Initial revision
662
663
664
  {
  	packetHandler = f;
  }
39bccd21d   Simon Glass   net: Hide more co...
665
  #ifdef CONFIG_CMD_TFTPPUT
4793ee652   Simon Glass   net: tftpput: Add...
666
667
668
669
  void net_set_icmp_handler(rxhand_icmp_f *f)
  {
  	packet_icmp_handler = f;
  }
39bccd21d   Simon Glass   net: Hide more co...
670
  #endif
2d966958c   wdenk   Initial revision
671
672
  
  void
6b147d113   Luca Ceresoli   net/net.c: cosmet...
673
  NetSetTimeout(ulong iv, thand_f *f)
2d966958c   wdenk   Initial revision
674
675
676
677
678
  {
  	if (iv == 0) {
  		timeHandler = (thand_f *)0;
  	} else {
  		timeHandler = f;
e0ac62d79   wdenk   * Make Ethernet a...
679
680
  		timeStart = get_timer(0);
  		timeDelta = iv;
2d966958c   wdenk   Initial revision
681
682
683
684
685
  	}
  }
  
  
  void
6b147d113   Luca Ceresoli   net/net.c: cosmet...
686
  NetSendPacket(volatile uchar *pkt, int len)
2d966958c   wdenk   Initial revision
687
688
689
  {
  	(void) eth_send(pkt, len);
  }
73a8b27c5   wdenk   * Add support for...
690
691
692
  int
  NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
  {
a3d991bd0   wdenk   Patches by Pantel...
693
  	uchar *pkt;
73a8b27c5   wdenk   * Add support for...
694
695
696
697
698
699
700
  	/* convert to new style broadcast */
  	if (dest == 0)
  		dest = 0xFFFFFFFF;
  
  	/* if broadcast, make the ether address a broadcast and don't do ARP */
  	if (dest == 0xFFFFFFFF)
  		ether = NetBcastAddr;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
701
702
703
704
  	/*
  	 * if MAC address was not discovered yet, save the packet and do
  	 * an ARP request
  	 */
73a8b27c5   wdenk   * Add support for...
705
  	if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
ea45cb0ad   Matthias Weisser   net: Make sure IP...
706
707
  		debug("sending ARP for %08x
  ", dest);
0ebf04c60   Robin Getz   minor debug clean...
708

73a8b27c5   wdenk   * Add support for...
709
710
  		NetArpWaitPacketIP = dest;
  		NetArpWaitPacketMAC = ether;
a3d991bd0   wdenk   Patches by Pantel...
711
712
  
  		pkt = NetArpWaitTxPacket;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
713
  		pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);
a3d991bd0   wdenk   Patches by Pantel...
714

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
715
  		NetSetIP(pkt, dest, dport, sport, len);
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
716
717
  		memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket +
  		       (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
73a8b27c5   wdenk   * Add support for...
718
719
  
  		/* size of the waiting packet */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
720
721
  		NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) +
  			IP_HDR_SIZE + len;
73a8b27c5   wdenk   * Add support for...
722
723
724
725
726
727
728
  
  		/* and do the ARP request */
  		NetArpWaitTry = 1;
  		NetArpWaitTimerStart = get_timer(0);
  		ArpRequest();
  		return 1;	/* waiting */
  	}
ea45cb0ad   Matthias Weisser   net: Make sure IP...
729
730
  	debug("sending UDP to %08x/%pM
  ", dest, ether);
73a8b27c5   wdenk   * Add support for...
731

a3d991bd0   wdenk   Patches by Pantel...
732
  	pkt = (uchar *)NetTxPacket;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
733
734
  	pkt += NetSetEther(pkt, ether, PROT_IP);
  	NetSetIP(pkt, dest, dport, sport, len);
a3d991bd0   wdenk   Patches by Pantel...
735
  	(void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
73a8b27c5   wdenk   * Add support for...
736

6e5923851   wdenk   * Cleanup, minor ...
737
  	return 0;	/* transmitted */
73a8b27c5   wdenk   * Add support for...
738
  }
643d1ab23   Jon Loeliger   net/: Remove obso...
739
  #if defined(CONFIG_CMD_PING)
73a8b27c5   wdenk   * Add support for...
740
741
742
743
744
745
746
  static ushort PingSeqNo;
  
  int PingSend(void)
  {
  	static uchar mac[6];
  	volatile IP_t *ip;
  	volatile ushort *s;
a3d991bd0   wdenk   Patches by Pantel...
747
  	uchar *pkt;
73a8b27c5   wdenk   * Add support for...
748
749
750
751
  
  	/* XXX always send arp request */
  
  	memcpy(mac, NetEtherNullAddr, 6);
ea45cb0ad   Matthias Weisser   net: Make sure IP...
752
753
  	debug("sending ARP for %08x
  ", NetPingIP);
73a8b27c5   wdenk   * Add support for...
754
755
756
  
  	NetArpWaitPacketIP = NetPingIP;
  	NetArpWaitPacketMAC = mac;
a3d991bd0   wdenk   Patches by Pantel...
757
758
  	pkt = NetArpWaitTxPacket;
  	pkt += NetSetEther(pkt, mac, PROT_IP);
73a8b27c5   wdenk   * Add support for...
759

a3d991bd0   wdenk   Patches by Pantel...
760
  	ip = (volatile IP_t *)pkt;
73a8b27c5   wdenk   * Add support for...
761
762
  
  	/*
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
763
764
  	 * Construct an IP and ICMP header.
  	 * (need to set no fragment bit - XXX)
73a8b27c5   wdenk   * Add support for...
765
  	 */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
766
767
  	/* IP_HDR_SIZE / 4 (not including UDP) */
  	ip->ip_hl_v  = 0x45;
73a8b27c5   wdenk   * Add support for...
768
769
770
  	ip->ip_tos   = 0;
  	ip->ip_len   = htons(IP_HDR_SIZE_NO_UDP + 8);
  	ip->ip_id    = htons(NetIPID++);
e0c07b868   Peter Tyser   net: Define IP fl...
771
  	ip->ip_off   = htons(IP_FLAGS_DFRAG);	/* Don't fragment */
73a8b27c5   wdenk   * Add support for...
772
773
774
  	ip->ip_ttl   = 255;
  	ip->ip_p     = 0x01;		/* ICMP */
  	ip->ip_sum   = 0;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
775
  	/* already in network byte order */
6b147d113   Luca Ceresoli   net/net.c: cosmet...
776
  	NetCopyIP((void *)&ip->ip_src, &NetOurIP);
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
777
  	/* - "" - */
6b147d113   Luca Ceresoli   net/net.c: cosmet...
778
  	NetCopyIP((void *)&ip->ip_dst, &NetPingIP);
73a8b27c5   wdenk   * Add support for...
779
780
781
782
783
  	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 */
53677ef18   Wolfgang Denk   Big white-space c...
784
  	s[2] = 0;			/* identifier */
73a8b27c5   wdenk   * Add support for...
785
786
787
788
  	s[3] = htons(PingSeqNo++);	/* sequence number */
  	s[1] = ~NetCksum((uchar *)s, 8/2);
  
  	/* size of the waiting packet */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
789
790
  	NetArpWaitTxPacketSize =
  		(pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
73a8b27c5   wdenk   * Add support for...
791
792
793
794
795
796
797
798
799
  
  	/* and do the ARP request */
  	NetArpWaitTry = 1;
  	NetArpWaitTimerStart = get_timer(0);
  	ArpRequest();
  	return 1;	/* waiting */
  }
  
  static void
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
800
  PingTimeout(void)
73a8b27c5   wdenk   * Add support for...
801
802
803
804
  {
  	eth_halt();
  	NetState = NETLOOP_FAIL;	/* we did not get the reply */
  }
2d966958c   wdenk   Initial revision
805

73a8b27c5   wdenk   * Add support for...
806
  static void
03eb129f8   Luca Ceresoli   NET: pass source ...
807
808
  PingHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
  	    unsigned len)
73a8b27c5   wdenk   * Add support for...
809
  {
03eb129f8   Luca Ceresoli   NET: pass source ...
810
  	if (sip != NetPingIP)
73a8b27c5   wdenk   * Add support for...
811
812
813
814
815
816
817
  		return;
  
  	NetState = NETLOOP_SUCCESS;
  }
  
  static void PingStart(void)
  {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
818
819
  	printf("Using %s device
  ", eth_get_name());
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
820
821
  	NetSetTimeout(10000UL, PingTimeout);
  	NetSetHandler(PingHandler);
73a8b27c5   wdenk   * Add support for...
822
823
824
  
  	PingSend();
  }
610f2e9c2   Jon Loeliger   net/: Remove ling...
825
  #endif
2d966958c   wdenk   Initial revision
826

643d1ab23   Jon Loeliger   net/: Remove obso...
827
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
828
829
830
831
832
833
834
835
836
837
838
839
840
841
  
  #define CDP_DEVICE_ID_TLV		0x0001
  #define CDP_ADDRESS_TLV			0x0002
  #define CDP_PORT_ID_TLV			0x0003
  #define CDP_CAPABILITIES_TLV		0x0004
  #define CDP_VERSION_TLV			0x0005
  #define CDP_PLATFORM_TLV		0x0006
  #define CDP_NATIVE_VLAN_TLV		0x000a
  #define CDP_APPLIANCE_VLAN_TLV		0x000e
  #define CDP_TRIGGER_TLV			0x000f
  #define CDP_POWER_CONSUMPTION_TLV	0x0010
  #define CDP_SYSNAME_TLV			0x0014
  #define CDP_SYSOBJECT_TLV		0x0015
  #define CDP_MANAGEMENT_ADDRESS_TLV	0x0016
49f3bdbba   Bartlomiej Sieka   net: express the ...
842
  #define CDP_TIMEOUT			250UL	/* one packet every 250ms */
a3d991bd0   wdenk   Patches by Pantel...
843
844
845
846
847
848
  
  static int CDPSeq;
  static int CDPOK;
  
  ushort CDPNativeVLAN;
  ushort CDPApplianceVLAN;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
849
850
  static const uchar CDP_SNAP_hdr[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20,
  				       0x00 };
a3d991bd0   wdenk   Patches by Pantel...
851
852
853
854
855
856
857
  
  static ushort CDP_compute_csum(const uchar *buff, ushort len)
  {
  	ushort csum;
  	int     odd;
  	ulong   result = 0;
  	ushort  leftover;
77ddac948   Wolfgang Denk   Cleanup for GCC-4.x
858
  	ushort *p;
a3d991bd0   wdenk   Patches by Pantel...
859
860
861
862
863
864
865
866
867
  
  	if (len > 0) {
  		odd = 1 & (ulong)buff;
  		if (odd) {
  			result = *buff << 8;
  			len--;
  			buff++;
  		}
  		while (len > 1) {
77ddac948   Wolfgang Denk   Cleanup for GCC-4.x
868
869
870
  			p = (ushort *)buff;
  			result += *p++;
  			buff = (uchar *)p;
a3d991bd0   wdenk   Patches by Pantel...
871
872
873
874
875
876
  			if (result & 0x80000000)
  				result = (result & 0xFFFF) + (result >> 16);
  			len -= 2;
  		}
  		if (len) {
  			leftover = (signed short)(*(const signed char *)buff);
3ada834e3   Wolfgang Denk   Add explanation f...
877
878
879
880
  			/* CISCO SUCKS big time! (and blows too):
  			 * CDP uses the IP checksum algorithm with a twist;
  			 * for the last byte it *sign* extends and sums.
  			 */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
881
882
  			result = (result & 0xffff0000) |
  				 ((result + leftover) & 0x0000ffff);
a3d991bd0   wdenk   Patches by Pantel...
883
884
885
886
887
  		}
  		while (result >> 16)
  			result = (result & 0xFFFF) + (result >> 16);
  
  		if (odd)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
888
889
  			result = ((result >> 8) & 0xff) |
  				 ((result & 0xff) << 8);
a3d991bd0   wdenk   Patches by Pantel...
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
  	}
  
  	/* add up 16-bit and 17-bit words for 17+c bits */
  	result = (result & 0xffff) + (result >> 16);
  	/* add up 16-bit and 2-bit for 16+c bit */
  	result = (result & 0xffff) + (result >> 16);
  	/* add up carry.. */
  	result = (result & 0xffff) + (result >> 16);
  
  	/* negate */
  	csum = ~(ushort)result;
  
  	/* run time endian detection */
  	if (csum != htons(csum))	/* little endian */
  		csum = htons(csum);
  
  	return csum;
  }
  
  int CDPSendTrigger(void)
  {
  	volatile uchar *pkt;
  	volatile ushort *s;
  	volatile ushort *cp;
  	Ethernet_t *et;
a3d991bd0   wdenk   Patches by Pantel...
915
916
  	int len;
  	ushort chksum;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
917
918
  #if	defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID)   || \
  	defined(CONFIG_CDP_VERSION)   || defined(CONFIG_CDP_PLATFORM)
6e5923851   wdenk   * Cleanup, minor ...
919
920
  	char buf[32];
  #endif
a3d991bd0   wdenk   Patches by Pantel...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
  
  	pkt = NetTxPacket;
  	et = (Ethernet_t *)pkt;
  
  	/* NOTE: trigger sent not on any VLAN */
  
  	/* form ethernet header */
  	memcpy(et->et_dest, NetCDPAddr, 6);
  	memcpy(et->et_src, NetOurEther, 6);
  
  	pkt += ETHER_HDR_SIZE;
  
  	/* SNAP header */
  	memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr));
  	pkt += sizeof(CDP_SNAP_hdr);
  
  	/* CDP header */
  	*pkt++ = 0x02;				/* CDP version 2 */
  	*pkt++ = 180;				/* TTL */
  	s = (volatile ushort *)pkt;
  	cp = s;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
942
943
  	/* checksum (0 for later calculation) */
  	*s++ = htons(0);
a3d991bd0   wdenk   Patches by Pantel...
944
945
946
947
948
  
  	/* CDP fields */
  #ifdef CONFIG_CDP_DEVICE_ID
  	*s++ = htons(CDP_DEVICE_ID_TLV);
  	*s++ = htons(CONFIG_CDP_DEVICE_ID);
95823ca07   Mike Frysinger   net: get mac addr...
949
  	sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%pm", NetOurEther);
a3d991bd0   wdenk   Patches by Pantel...
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
  	memcpy((uchar *)s, buf, 16);
  	s += 16 / 2;
  #endif
  
  #ifdef CONFIG_CDP_PORT_ID
  	*s++ = htons(CDP_PORT_ID_TLV);
  	memset(buf, 0, sizeof(buf));
  	sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index());
  	len = strlen(buf);
  	if (len & 1)	/* make it even */
  		len++;
  	*s++ = htons(len + 4);
  	memcpy((uchar *)s, buf, len);
  	s += len / 2;
  #endif
  
  #ifdef CONFIG_CDP_CAPABILITIES
  	*s++ = htons(CDP_CAPABILITIES_TLV);
  	*s++ = htons(8);
  	*(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES);
  	s += 2;
  #endif
  
  #ifdef CONFIG_CDP_VERSION
  	*s++ = htons(CDP_VERSION_TLV);
  	memset(buf, 0, sizeof(buf));
  	strcpy(buf, CONFIG_CDP_VERSION);
  	len = strlen(buf);
  	if (len & 1)	/* make it even */
  		len++;
  	*s++ = htons(len + 4);
  	memcpy((uchar *)s, buf, len);
  	s += len / 2;
  #endif
  
  #ifdef CONFIG_CDP_PLATFORM
  	*s++ = htons(CDP_PLATFORM_TLV);
  	memset(buf, 0, sizeof(buf));
  	strcpy(buf, CONFIG_CDP_PLATFORM);
  	len = strlen(buf);
  	if (len & 1)	/* make it even */
  		len++;
  	*s++ = htons(len + 4);
  	memcpy((uchar *)s, buf, len);
  	s += len / 2;
  #endif
  
  #ifdef CONFIG_CDP_TRIGGER
  	*s++ = htons(CDP_TRIGGER_TLV);
  	*s++ = htons(8);
  	*(ulong *)s = htonl(CONFIG_CDP_TRIGGER);
  	s += 2;
  #endif
  
  #ifdef CONFIG_CDP_POWER_CONSUMPTION
  	*s++ = htons(CDP_POWER_CONSUMPTION_TLV);
  	*s++ = htons(6);
  	*s++ = htons(CONFIG_CDP_POWER_CONSUMPTION);
  #endif
  
  	/* length of ethernet packet */
  	len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE);
  	et->et_protlen = htons(len);
  
  	len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr);
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1015
1016
  	chksum = CDP_compute_csum((uchar *)NetTxPacket + len,
  				  (uchar *)s - (NetTxPacket + len));
a3d991bd0   wdenk   Patches by Pantel...
1017
1018
1019
1020
1021
1022
1023
1024
1025
  	if (chksum == 0)
  		chksum = 0xFFFF;
  	*cp = htons(chksum);
  
  	(void) eth_send(NetTxPacket, (uchar *)s - NetTxPacket);
  	return 0;
  }
  
  static void
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1026
  CDPTimeout(void)
a3d991bd0   wdenk   Patches by Pantel...
1027
1028
1029
1030
  {
  	CDPSeq++;
  
  	if (CDPSeq < 3) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1031
  		NetSetTimeout(CDP_TIMEOUT, CDPTimeout);
a3d991bd0   wdenk   Patches by Pantel...
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
  		CDPSendTrigger();
  		return;
  	}
  
  	/* if not OK try again */
  	if (!CDPOK)
  		NetStartAgain();
  	else
  		NetState = NETLOOP_SUCCESS;
  }
  
  static void
03eb129f8   Luca Ceresoli   NET: pass source ...
1044
1045
  CDPDummyHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
  		unsigned len)
a3d991bd0   wdenk   Patches by Pantel...
1046
1047
1048
1049
1050
  {
  	/* nothing */
  }
  
  static void
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1051
  CDPHandler(const uchar *pkt, unsigned len)
a3d991bd0   wdenk   Patches by Pantel...
1052
1053
1054
1055
  {
  	const uchar *t;
  	const ushort *ss;
  	ushort type, tlen;
a3d991bd0   wdenk   Patches by Pantel...
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
  	ushort vlan, nvlan;
  
  	/* minimum size? */
  	if (len < sizeof(CDP_SNAP_hdr) + 4)
  		goto pkt_short;
  
  	/* check for valid CDP SNAP header */
  	if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0)
  		return;
  
  	pkt += sizeof(CDP_SNAP_hdr);
  	len -= sizeof(CDP_SNAP_hdr);
  
  	/* Version of CDP protocol must be >= 2 and TTL != 0 */
  	if (pkt[0] < 0x02 || pkt[1] == 0)
  		return;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1072
1073
1074
1075
  	/*
  	 * if version is greater than 0x02 maybe we'll have a problem;
  	 * output a warning
  	 */
a3d991bd0   wdenk   Patches by Pantel...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
  	if (pkt[0] != 0x02)
  		printf("** WARNING: CDP packet received with a protocol version %d > 2
  ",
  				pkt[0] & 0xff);
  
  	if (CDP_compute_csum(pkt, len) != 0)
  		return;
  
  	pkt += 4;
  	len -= 4;
  
  	vlan = htons(-1);
  	nvlan = htons(-1);
  	while (len > 0) {
  		if (len < 4)
  			goto pkt_short;
  
  		ss = (const ushort *)pkt;
  		type = ntohs(ss[0]);
  		tlen = ntohs(ss[1]);
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1096
  		if (tlen > len)
a3d991bd0   wdenk   Patches by Pantel...
1097
  			goto pkt_short;
a3d991bd0   wdenk   Patches by Pantel...
1098
1099
1100
1101
1102
1103
1104
1105
  
  		pkt += tlen;
  		len -= tlen;
  
  		ss += 2;	/* point ss to the data of the TLV */
  		tlen -= 4;
  
  		switch (type) {
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
  		case CDP_DEVICE_ID_TLV:
  			break;
  		case CDP_ADDRESS_TLV:
  			break;
  		case CDP_PORT_ID_TLV:
  			break;
  		case CDP_CAPABILITIES_TLV:
  			break;
  		case CDP_VERSION_TLV:
  			break;
  		case CDP_PLATFORM_TLV:
  			break;
  		case CDP_NATIVE_VLAN_TLV:
  			nvlan = *ss;
  			break;
  		case CDP_APPLIANCE_VLAN_TLV:
  			t = (const uchar *)ss;
  			while (tlen > 0) {
  				if (tlen < 3)
  					goto pkt_short;
a3d991bd0   wdenk   Patches by Pantel...
1126

c819abeef   Luca Ceresoli   net/net.c: cosmet...
1127
  				ss = (const ushort *)(t + 1);
a3d991bd0   wdenk   Patches by Pantel...
1128
1129
  
  #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
5c10419ce   Wolfgang Denk   net/net.c: Fix GC...
1130
  				if (t[0] == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1131
  					vlan = *ss;
a3d991bd0   wdenk   Patches by Pantel...
1132
  #else
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1133
1134
  				/* XXX will this work; dunno */
  				vlan = ntohs(*ss);
a3d991bd0   wdenk   Patches by Pantel...
1135
  #endif
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
  				t += 3; tlen -= 3;
  			}
  			break;
  		case CDP_TRIGGER_TLV:
  			break;
  		case CDP_POWER_CONSUMPTION_TLV:
  			break;
  		case CDP_SYSNAME_TLV:
  			break;
  		case CDP_SYSOBJECT_TLV:
  			break;
  		case CDP_MANAGEMENT_ADDRESS_TLV:
  			break;
a3d991bd0   wdenk   Patches by Pantel...
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  		}
  	}
  
  	CDPApplianceVLAN = vlan;
  	CDPNativeVLAN = nvlan;
  
  	CDPOK = 1;
  	return;
  
   pkt_short:
  	printf("** CDP packet is too short
  ");
  	return;
  }
  
  static void CDPStart(void)
  {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1166
1167
  	printf("Using %s device
  ", eth_get_name());
a3d991bd0   wdenk   Patches by Pantel...
1168
1169
1170
1171
1172
  	CDPSeq = 0;
  	CDPOK = 0;
  
  	CDPNativeVLAN = htons(-1);
  	CDPApplianceVLAN = htons(-1);
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1173
1174
  	NetSetTimeout(CDP_TIMEOUT, CDPTimeout);
  	NetSetHandler(CDPDummyHandler);
a3d991bd0   wdenk   Patches by Pantel...
1175
1176
1177
  
  	CDPSendTrigger();
  }
610f2e9c2   Jon Loeliger   net/: Remove ling...
1178
  #endif
a3d991bd0   wdenk   Patches by Pantel...
1179

5cfaa4e54   Alessandro Rubini   net: defragment I...
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  #ifdef CONFIG_IP_DEFRAG
  /*
   * This function collects fragments in a single packet, according
   * to the algorithm in RFC815. It returns NULL or the pointer to
   * a complete packet, in static storage
   */
  #ifndef CONFIG_NET_MAXDEFRAG
  #define CONFIG_NET_MAXDEFRAG 16384
  #endif
  /*
   * MAXDEFRAG, above, is chosen in the config file and  is real data
   * so we need to add the NFS overhead, which is more than TFTP.
   * To use sizeof in the internal unnamed structures, we need a real
   * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately).
   * The compiler doesn't complain nor allocates the actual structure
   */
  static struct rpc_t rpc_specimen;
  #define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply))
  
  #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE_NO_UDP)
  
  /*
   * this is the packet being assembled, either data or frag control.
   * Fragments go by 8 bytes, so this union must be 8 bytes long
   */
  struct hole {
  	/* first_byte is address of this structure */
  	u16 last_byte;	/* last byte in this hole + 1 (begin of next hole) */
  	u16 next_hole;	/* index of next (in 8-b blocks), 0 == none */
  	u16 prev_hole;	/* index of prev, 0 == none */
  	u16 unused;
  };
  
  static IP_t *__NetDefragment(IP_t *ip, int *lenp)
  {
  	static uchar pkt_buff[IP_PKTSIZE] __attribute__((aligned(PKTALIGN)));
  	static u16 first_hole, total_len;
  	struct hole *payload, *thisfrag, *h, *newh;
  	IP_t *localip = (IP_t *)pkt_buff;
  	uchar *indata = (uchar *)ip;
  	int offset8, start, len, done = 0;
  	u16 ip_off = ntohs(ip->ip_off);
  
  	/* payload starts after IP header, this fragment is in there */
  	payload = (struct hole *)(pkt_buff + IP_HDR_SIZE_NO_UDP);
  	offset8 =  (ip_off & IP_OFFS);
  	thisfrag = payload + offset8;
  	start = offset8 * 8;
  	len = ntohs(ip->ip_len) - IP_HDR_SIZE_NO_UDP;
  
  	if (start + len > IP_MAXUDP) /* fragment extends too far */
  		return NULL;
  
  	if (!total_len || localip->ip_id != ip->ip_id) {
  		/* new (or different) packet, reset structs */
  		total_len = 0xffff;
  		payload[0].last_byte = ~0;
  		payload[0].next_hole = 0;
  		payload[0].prev_hole = 0;
  		first_hole = 0;
  		/* any IP header will work, copy the first we received */
  		memcpy(localip, ip, IP_HDR_SIZE_NO_UDP);
  	}
  
  	/*
  	 * What follows is the reassembly algorithm. We use the payload
  	 * array as a linked list of hole descriptors, as each hole starts
  	 * at a multiple of 8 bytes. However, last byte can be whatever value,
  	 * so it is represented as byte count, not as 8-byte blocks.
  	 */
  
  	h = payload + first_hole;
  	while (h->last_byte < start) {
  		if (!h->next_hole) {
  			/* no hole that far away */
  			return NULL;
  		}
  		h = payload + h->next_hole;
  	}
e397e59e8   Fillod Stephane   ip/defrag: fix pr...
1259
1260
  	/* last fragment may be 1..7 bytes, the "+7" forces acceptance */
  	if (offset8 + ((len + 7) / 8) <= h - payload) {
5cfaa4e54   Alessandro Rubini   net: defragment I...
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
  		/* no overlap with holes (dup fragment?) */
  		return NULL;
  	}
  
  	if (!(ip_off & IP_FLAGS_MFRAG)) {
  		/* no more fragmentss: truncate this (last) hole */
  		total_len = start + len;
  		h->last_byte = start + len;
  	}
  
  	/*
  	 * There is some overlap: fix the hole list. This code doesn't
  	 * deal with a fragment that overlaps with two different holes
  	 * (thus being a superset of a previously-received fragment).
  	 */
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1276
  	if ((h >= thisfrag) && (h->last_byte <= start + len)) {
5cfaa4e54   Alessandro Rubini   net: defragment I...
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
  		/* complete overlap with hole: remove hole */
  		if (!h->prev_hole && !h->next_hole) {
  			/* last remaining hole */
  			done = 1;
  		} else if (!h->prev_hole) {
  			/* first hole */
  			first_hole = h->next_hole;
  			payload[h->next_hole].prev_hole = 0;
  		} else if (!h->next_hole) {
  			/* last hole */
  			payload[h->prev_hole].next_hole = 0;
  		} else {
  			/* in the middle of the list */
  			payload[h->next_hole].prev_hole = h->prev_hole;
  			payload[h->prev_hole].next_hole = h->next_hole;
  		}
  
  	} else if (h->last_byte <= start + len) {
  		/* overlaps with final part of the hole: shorten this hole */
  		h->last_byte = start;
  
  	} else if (h >= thisfrag) {
  		/* overlaps with initial part of the hole: move this hole */
  		newh = thisfrag + (len / 8);
  		*newh = *h;
  		h = newh;
  		if (h->next_hole)
  			payload[h->next_hole].prev_hole = (h - payload);
  		if (h->prev_hole)
  			payload[h->prev_hole].next_hole = (h - payload);
  		else
  			first_hole = (h - payload);
  
  	} else {
  		/* fragment sits in the middle: split the hole */
  		newh = thisfrag + (len / 8);
  		*newh = *h;
  		h->last_byte = start;
  		h->next_hole = (newh - payload);
  		newh->prev_hole = (h - payload);
  		if (newh->next_hole)
  			payload[newh->next_hole].prev_hole = (newh - payload);
  	}
  
  	/* finally copy this fragment and possibly return whole packet */
  	memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE_NO_UDP, len);
  	if (!done)
  		return NULL;
  
  	localip->ip_len = htons(total_len);
  	*lenp = total_len + IP_HDR_SIZE_NO_UDP;
  	return localip;
  }
  
  static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
  {
  	u16 ip_off = ntohs(ip->ip_off);
  	if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
  		return ip; /* not a fragment */
  	return __NetDefragment(ip, lenp);
  }
  
  #else /* !CONFIG_IP_DEFRAG */
  
  static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
  {
  	u16 ip_off = ntohs(ip->ip_off);
  	if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
  		return ip; /* not a fragment */
  	return NULL;
  }
  #endif
a3d991bd0   wdenk   Patches by Pantel...
1349

8f79bb17a   Simon Glass   net: tftpput: Mov...
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
  /**
   * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
   * drop others.
   *
   * @parma ip	IP packet containing the ICMP
   */
  static void receive_icmp(IP_t *ip, int len, IPaddr_t src_ip, Ethernet_t *et)
  {
  	ICMP_t *icmph = (ICMP_t *)&ip->udp_src;
  
  	switch (icmph->type) {
  	case ICMP_REDIRECT:
  		if (icmph->code != ICMP_REDIR_HOST)
  			return;
  		printf(" ICMP Host Redirect to %pI4 ",
  			&icmph->un.gateway);
  		break;
  #if defined(CONFIG_CMD_PING)
  	case ICMP_ECHO_REPLY:
  		/*
  			* IP header OK.  Pass the packet to the
  			* current handler.
  			*/
  		/*
  		 * XXX point to ip packet - should this use
  		 * packet_icmp_handler?
  		 */
  		(*packetHandler)((uchar *)ip, 0, src_ip, 0, 0);
  		break;
  	case ICMP_ECHO_REQUEST:
  		debug("Got ICMP ECHO REQUEST, return %d bytes
  ",
  			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);
  		break;
  #endif
  	default:
39bccd21d   Simon Glass   net: Hide more co...
1403
  #ifdef CONFIG_CMD_TFTPPUT
4793ee652   Simon Glass   net: tftpput: Add...
1404
1405
1406
1407
  		if (packet_icmp_handler)
  			packet_icmp_handler(icmph->type, icmph->code,
  				ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src),
  				icmph->un.data, ntohs(ip->udp_len));
39bccd21d   Simon Glass   net: Hide more co...
1408
  #endif
8f79bb17a   Simon Glass   net: tftpput: Mov...
1409
1410
1411
  		break;
  	}
  }
2d966958c   wdenk   Initial revision
1412
  void
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1413
  NetReceive(volatile uchar *inpkt, int len)
2d966958c   wdenk   Initial revision
1414
1415
1416
1417
1418
  {
  	Ethernet_t *et;
  	IP_t	*ip;
  	ARP_t	*arp;
  	IPaddr_t tmp;
03eb129f8   Luca Ceresoli   NET: pass source ...
1419
  	IPaddr_t src_ip;
2d966958c   wdenk   Initial revision
1420
  	int	x;
a3d991bd0   wdenk   Patches by Pantel...
1421
  	uchar *pkt;
643d1ab23   Jon Loeliger   net/: Remove obso...
1422
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
1423
1424
1425
  	int iscdp;
  #endif
  	ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
0ebf04c60   Robin Getz   minor debug clean...
1426
1427
  	debug("packet received
  ");
2d966958c   wdenk   Initial revision
1428

d9bec9f42   Mike Frysinger   net: rename NetRx...
1429
1430
  	NetRxPacket = inpkt;
  	NetRxPacketLen = len;
a3d991bd0   wdenk   Patches by Pantel...
1431
1432
1433
1434
1435
  	et = (Ethernet_t *)inpkt;
  
  	/* too small packet? */
  	if (len < ETHER_HDR_SIZE)
  		return;
f85b60710   Rafal Jaworowski   Introduce new eth...
1436
1437
1438
1439
1440
1441
  #ifdef CONFIG_API
  	if (push_packet) {
  		(*push_packet)(inpkt, len);
  		return;
  	}
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
1442
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
  	/* keep track if packet is CDP */
  	iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0;
  #endif
  
  	myvlanid = ntohs(NetOurVLAN);
  	if (myvlanid == (ushort)-1)
  		myvlanid = VLAN_NONE;
  	mynvlanid = ntohs(NetOurNativeVLAN);
  	if (mynvlanid == (ushort)-1)
  		mynvlanid = VLAN_NONE;
2d966958c   wdenk   Initial revision
1453
1454
  
  	x = ntohs(et->et_protlen);
0ebf04c60   Robin Getz   minor debug clean...
1455
1456
  	debug("packet received
  ");
a3d991bd0   wdenk   Patches by Pantel...
1457

2d966958c   wdenk   Initial revision
1458
1459
1460
1461
1462
  	if (x < 1514) {
  		/*
  		 *	Got a 802 packet.  Check the other protocol field.
  		 */
  		x = ntohs(et->et_prot);
a3d991bd0   wdenk   Patches by Pantel...
1463
1464
  
  		ip = (IP_t *)(inpkt + E802_HDR_SIZE);
2d966958c   wdenk   Initial revision
1465
  		len -= E802_HDR_SIZE;
a3d991bd0   wdenk   Patches by Pantel...
1466
1467
1468
  
  	} else if (x != PROT_VLAN) {	/* normal packet */
  		ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
2d966958c   wdenk   Initial revision
1469
  		len -= ETHER_HDR_SIZE;
a3d991bd0   wdenk   Patches by Pantel...
1470
1471
1472
  
  	} else {			/* VLAN packet */
  		VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
0ebf04c60   Robin Getz   minor debug clean...
1473
1474
  		debug("VLAN packet received
  ");
a3d991bd0   wdenk   Patches by Pantel...
1475
1476
1477
1478
1479
1480
  		/* too small packet? */
  		if (len < VLAN_ETHER_HDR_SIZE)
  			return;
  
  		/* if no VLAN active */
  		if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
643d1ab23   Jon Loeliger   net/: Remove obso...
1481
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
  				&& iscdp == 0
  #endif
  				)
  			return;
  
  		cti = ntohs(vet->vet_tag);
  		vlanid = cti & VLAN_IDMASK;
  		x = ntohs(vet->vet_type);
  
  		ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
  		len -= VLAN_ETHER_HDR_SIZE;
2d966958c   wdenk   Initial revision
1493
  	}
0ebf04c60   Robin Getz   minor debug clean...
1494
1495
  	debug("Receive from protocol 0x%x
  ", x);
2d966958c   wdenk   Initial revision
1496

643d1ab23   Jon Loeliger   net/: Remove obso...
1497
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
  	if (iscdp) {
  		CDPHandler((uchar *)ip, len);
  		return;
  	}
  #endif
  
  	if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
  		if (vlanid == VLAN_NONE)
  			vlanid = (mynvlanid & VLAN_IDMASK);
  		/* not matched? */
  		if (vlanid != (myvlanid & VLAN_IDMASK))
  			return;
  	}
2d966958c   wdenk   Initial revision
1511
1512
1513
1514
1515
  	switch (x) {
  
  	case PROT_ARP:
  		/*
  		 * We have to deal with two types of ARP packets:
8bde7f776   wdenk   * Code cleanup:
1516
1517
1518
1519
1520
1521
  		 * - REQUEST packets will be answered by sending  our
  		 *   IP address - if we know it.
  		 * - REPLY packates are expected only after we asked
  		 *   for the TFTP server's or the gateway's ethernet
  		 *   address; so if we receive such a packet, we set
  		 *   the server ethernet address
2d966958c   wdenk   Initial revision
1522
  		 */
0ebf04c60   Robin Getz   minor debug clean...
1523
1524
  		debug("Got ARP
  ");
2d966958c   wdenk   Initial revision
1525
1526
1527
1528
1529
1530
  		arp = (ARP_t *)ip;
  		if (len < ARP_HDR_SIZE) {
  			printf("bad length %d < %d
  ", len, ARP_HDR_SIZE);
  			return;
  		}
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1531
  		if (ntohs(arp->ar_hrd) != ARP_ETHER)
2d966958c   wdenk   Initial revision
1532
  			return;
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1533
  		if (ntohs(arp->ar_pro) != PROT_IP)
2d966958c   wdenk   Initial revision
1534
  			return;
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1535
  		if (arp->ar_hln != 6)
2d966958c   wdenk   Initial revision
1536
  			return;
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1537
  		if (arp->ar_pln != 4)
2d966958c   wdenk   Initial revision
1538
  			return;
2d966958c   wdenk   Initial revision
1539

d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1540
  		if (NetOurIP == 0)
2d966958c   wdenk   Initial revision
1541
  			return;
2d966958c   wdenk   Initial revision
1542

d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1543
  		if (NetReadIP(&arp->ar_data[16]) != NetOurIP)
2d966958c   wdenk   Initial revision
1544
  			return;
2d966958c   wdenk   Initial revision
1545
1546
  
  		switch (ntohs(arp->ar_op)) {
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1547
1548
  		case ARPOP_REQUEST:
  			/* reply with our IP address */
0ebf04c60   Robin Getz   minor debug clean...
1549
1550
  			debug("Got ARP REQUEST, return our IP
  ");
a3d991bd0   wdenk   Patches by Pantel...
1551
1552
  			pkt = (uchar *)et;
  			pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
2d966958c   wdenk   Initial revision
1553
  			arp->ar_op = htons(ARPOP_REPLY);
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1554
  			memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
2d966958c   wdenk   Initial revision
1555
  			NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1556
1557
  			memcpy(&arp->ar_data[0], NetOurEther, 6);
  			NetCopyIP(&arp->ar_data[6], &NetOurIP);
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1558
1559
  			(void) eth_send((uchar *)et,
  					(pkt - (uchar *)et) + ARP_HDR_SIZE);
2d966958c   wdenk   Initial revision
1560
  			return;
73a8b27c5   wdenk   * Add support for...
1561
1562
1563
1564
1565
  
  		case ARPOP_REPLY:		/* arp reply */
  			/* are we waiting for a reply */
  			if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
  				break;
97cfe8616   Robin Getz   Save server's MAC...
1566
1567
1568
1569
1570
1571
1572
1573
  
  #ifdef CONFIG_KEEP_SERVERADDR
  			if (NetServerIP == NetArpWaitPacketIP) {
  				char buf[20];
  				sprintf(buf, "%pM", arp->ar_data);
  				setenv("serveraddr", buf);
  			}
  #endif
0ebf04c60   Robin Getz   minor debug clean...
1574
1575
  			debug("Got ARP REPLY, set server/gtwy eth addr (%pM)
  ",
95823ca07   Mike Frysinger   net: get mac addr...
1576
  				arp->ar_data);
73a8b27c5   wdenk   * Add support for...
1577
1578
1579
1580
1581
  
  			tmp = NetReadIP(&arp->ar_data[6]);
  
  			/* matched waiting packet's address */
  			if (tmp == NetArpWaitReplyIP) {
0ebf04c60   Robin Getz   minor debug clean...
1582
1583
  				debug("Got it
  ");
73a8b27c5   wdenk   * Add support for...
1584
  				/* save address for later use */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1585
1586
  				memcpy(NetArpWaitPacketMAC,
  				       &arp->ar_data[0], 6);
73a8b27c5   wdenk   * Add support for...
1587

68ceb29e7   wdenk   Add support for c...
1588
  #ifdef CONFIG_NETCONSOLE
03eb129f8   Luca Ceresoli   NET: pass source ...
1589
  				(*packetHandler)(0, 0, 0, 0, 0);
68ceb29e7   wdenk   Add support for c...
1590
  #endif
73a8b27c5   wdenk   * Add support for...
1591
1592
  				/* modify header, and transmit it */
  				memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1593
1594
  				(void) eth_send(NetArpWaitTxPacket,
  						NetArpWaitTxPacketSize);
73a8b27c5   wdenk   * Add support for...
1595
1596
1597
1598
1599
1600
1601
  
  				/* no arp request pending now */
  				NetArpWaitPacketIP = 0;
  				NetArpWaitTxPacketSize = 0;
  				NetArpWaitPacketMAC = NULL;
  
  			}
2d966958c   wdenk   Initial revision
1602
1603
  			return;
  		default:
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1604
1605
1606
  			debug("Unexpected ARP opcode 0x%x
  ",
  			      ntohs(arp->ar_op));
2d966958c   wdenk   Initial revision
1607
1608
  			return;
  		}
289f932c5   wdenk   * Some Cleanup.
1609
  		break;
2d966958c   wdenk   Initial revision
1610

bf6cb247a   Peter Tyser   rarp: Condtionall...
1611
  #ifdef CONFIG_CMD_RARP
2d966958c   wdenk   Initial revision
1612
  	case PROT_RARP:
0ebf04c60   Robin Getz   minor debug clean...
1613
1614
  		debug("Got RARP
  ");
2d966958c   wdenk   Initial revision
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
  		arp = (ARP_t *)ip;
  		if (len < ARP_HDR_SIZE) {
  			printf("bad length %d < %d
  ", len, ARP_HDR_SIZE);
  			return;
  		}
  
  		if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
  			(ntohs(arp->ar_hrd) != ARP_ETHER)   ||
  			(ntohs(arp->ar_pro) != PROT_IP)     ||
  			(arp->ar_hln != 6) || (arp->ar_pln != 4)) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1626
1627
  			puts("invalid RARP header
  ");
2d966958c   wdenk   Initial revision
1628
  		} else {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1629
  			NetCopyIP(&NetOurIP, &arp->ar_data[16]);
3d3befa75   wdenk   * Patch by Philip...
1630
  			if (NetServerIP == 0)
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1631
1632
  				NetCopyIP(&NetServerIP, &arp->ar_data[6]);
  			memcpy(NetServerEther, &arp->ar_data[0], 6);
2d966958c   wdenk   Initial revision
1633

03eb129f8   Luca Ceresoli   NET: pass source ...
1634
  			(*packetHandler)(0, 0, 0, 0, 0);
2d966958c   wdenk   Initial revision
1635
1636
  		}
  		break;
bf6cb247a   Peter Tyser   rarp: Condtionall...
1637
  #endif
2d966958c   wdenk   Initial revision
1638
  	case PROT_IP:
0ebf04c60   Robin Getz   minor debug clean...
1639
1640
  		debug("Got IP
  ");
5cfaa4e54   Alessandro Rubini   net: defragment I...
1641
  		/* Before we start poking the header, make sure it is there */
2d966958c   wdenk   Initial revision
1642
  		if (len < IP_HDR_SIZE) {
0ebf04c60   Robin Getz   minor debug clean...
1643
1644
  			debug("len bad %d < %lu
  ", len, (ulong)IP_HDR_SIZE);
2d966958c   wdenk   Initial revision
1645
1646
  			return;
  		}
5cfaa4e54   Alessandro Rubini   net: defragment I...
1647
  		/* Check the packet length */
2d966958c   wdenk   Initial revision
1648
1649
1650
1651
1652
1653
  		if (len < ntohs(ip->ip_len)) {
  			printf("len bad %d < %d
  ", len, ntohs(ip->ip_len));
  			return;
  		}
  		len = ntohs(ip->ip_len);
0ebf04c60   Robin Getz   minor debug clean...
1654
1655
  		debug("len=%d, v=%02x
  ", len, ip->ip_hl_v & 0xff);
5cfaa4e54   Alessandro Rubini   net: defragment I...
1656
  		/* Can't deal with anything except IPv4 */
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1657
  		if ((ip->ip_hl_v & 0xf0) != 0x40)
2d966958c   wdenk   Initial revision
1658
  			return;
5cfaa4e54   Alessandro Rubini   net: defragment I...
1659
  		/* Can't deal with IP options (headers != 20 bytes) */
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1660
  		if ((ip->ip_hl_v & 0x0f) > 0x05)
6b52cfe16   Remy Bohmer   Get rid of annoyi...
1661
  			return;
5cfaa4e54   Alessandro Rubini   net: defragment I...
1662
  		/* Check the Checksum of the header */
2d966958c   wdenk   Initial revision
1663
  		if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1664
1665
  			puts("checksum bad
  ");
2d966958c   wdenk   Initial revision
1666
1667
  			return;
  		}
5cfaa4e54   Alessandro Rubini   net: defragment I...
1668
  		/* If it is not for us, ignore it */
2d966958c   wdenk   Initial revision
1669
1670
  		tmp = NetReadIP(&ip->ip_dst);
  		if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
53a5c424b   David Updegraff   multicast tftp: R...
1671
  #ifdef CONFIG_MCAST_TFTP
85eb5caf6   Wolfgang Denk   Coding style clea...
1672
  			if (Mcast_addr != tmp)
53a5c424b   David Updegraff   multicast tftp: R...
1673
  #endif
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1674
  				return;
2d966958c   wdenk   Initial revision
1675
  		}
03eb129f8   Luca Ceresoli   NET: pass source ...
1676
1677
  		/* Read source IP address for later use */
  		src_ip = NetReadIP(&ip->ip_src);
2d966958c   wdenk   Initial revision
1678
  		/*
5cfaa4e54   Alessandro Rubini   net: defragment I...
1679
1680
1681
1682
  		 * The function returns the unchanged packet if it's not
  		 * a fragment, and either the complete packet or NULL if
  		 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
  		 */
ccb9ebefb   Luca Ceresoli   net/net.c: cosmet...
1683
1684
  		ip = NetDefragment(ip, &len);
  		if (!ip)
5cfaa4e54   Alessandro Rubini   net: defragment I...
1685
1686
  			return;
  		/*
2d966958c   wdenk   Initial revision
1687
1688
  		 * watch for ICMP host redirects
  		 *
8bde7f776   wdenk   * Code cleanup:
1689
1690
1691
1692
1693
  		 * There is no real handler code (yet). We just watch
  		 * for ICMP host redirect messages. In case anybody
  		 * sees these messages: please contact me
  		 * (wd@denx.de), or - even better - send me the
  		 * necessary fixes :-)
2d966958c   wdenk   Initial revision
1694
  		 *
8bde7f776   wdenk   * Code cleanup:
1695
1696
1697
1698
1699
1700
1701
  		 * Note: in all cases where I have seen this so far
  		 * it was a problem with the router configuration,
  		 * for instance when a router was configured in the
  		 * BOOTP reply, but the TFTP server was on the same
  		 * subnet. So this is probably a warning that your
  		 * configuration might be wrong. But I'm not really
  		 * sure if there aren't any other situations.
4793ee652   Simon Glass   net: tftpput: Add...
1702
1703
1704
1705
  		 *
  		 * Simon Glass <sjg@chromium.org>: We get an ICMP when
  		 * we send a tftp packet to a dead connection, or when
  		 * there is no server at the other end.
2d966958c   wdenk   Initial revision
1706
1707
  		 */
  		if (ip->ip_p == IPPROTO_ICMP) {
8f79bb17a   Simon Glass   net: tftpput: Mov...
1708
1709
  			receive_icmp(ip, len, src_ip, et);
  			return;
2d966958c   wdenk   Initial revision
1710
1711
1712
  		} else if (ip->ip_p != IPPROTO_UDP) {	/* Only UDP packets */
  			return;
  		}
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1713
1714
  #ifdef CONFIG_UDP_CHECKSUM
  		if (ip->udp_xsum != 0) {
b2f508075   Wolfgang Denk   Minor code cleanup
1715
  			ulong   xsum;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
  			ushort *sumptr;
  			ushort  sumlen;
  
  			xsum  = ip->ip_p;
  			xsum += (ntohs(ip->udp_len));
  			xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
  			xsum += (ntohl(ip->ip_src) >>  0) & 0x0000ffff;
  			xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
  			xsum += (ntohl(ip->ip_dst) >>  0) & 0x0000ffff;
  
  			sumlen = ntohs(ip->udp_len);
  			sumptr = (ushort *) &(ip->udp_src);
  
  			while (sumlen > 1) {
b2f508075   Wolfgang Denk   Minor code cleanup
1730
  				ushort sumdata;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1731
1732
1733
1734
1735
1736
  
  				sumdata = *sumptr++;
  				xsum += ntohs(sumdata);
  				sumlen -= 2;
  			}
  			if (sumlen > 0) {
b2f508075   Wolfgang Denk   Minor code cleanup
1737
  				ushort sumdata;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1738
1739
  
  				sumdata = *(unsigned char *) sumptr;
b2f508075   Wolfgang Denk   Minor code cleanup
1740
  				sumdata = (sumdata << 8) & 0xff00;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1741
1742
1743
  				xsum += sumdata;
  			}
  			while ((xsum >> 16) != 0) {
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1744
1745
  				xsum = (xsum & 0x0000ffff) +
  				       ((xsum >> 16) & 0x0000ffff);
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1746
1747
  			}
  			if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
9b55a2536   Wolfgang Denk   Fix some more pri...
1748
1749
1750
  				printf(" UDP wrong checksum %08lx %08x
  ",
  					xsum, ntohs(ip->udp_xsum));
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1751
1752
1753
1754
  				return;
  			}
  		}
  #endif
53a5c424b   David Updegraff   multicast tftp: R...
1755

68ceb29e7   wdenk   Add support for c...
1756
  #ifdef CONFIG_NETCONSOLE
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1757
  		nc_input_packet((uchar *)ip + IP_HDR_SIZE,
68ceb29e7   wdenk   Add support for c...
1758
1759
1760
1761
  						ntohs(ip->udp_dst),
  						ntohs(ip->udp_src),
  						ntohs(ip->udp_len) - 8);
  #endif
2d966958c   wdenk   Initial revision
1762
1763
1764
  		/*
  		 *	IP header OK.  Pass the packet to the current handler.
  		 */
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1765
  		(*packetHandler)((uchar *)ip + IP_HDR_SIZE,
2d966958c   wdenk   Initial revision
1766
  						ntohs(ip->udp_dst),
03eb129f8   Luca Ceresoli   NET: pass source ...
1767
  						src_ip,
2d966958c   wdenk   Initial revision
1768
1769
  						ntohs(ip->udp_src),
  						ntohs(ip->udp_len) - 8);
2d966958c   wdenk   Initial revision
1770
1771
1772
1773
1774
1775
  		break;
  	}
  }
  
  
  /**********************************************************************/
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
1776
  static int net_check_prereq(enum proto_t protocol)
2d966958c   wdenk   Initial revision
1777
1778
  {
  	switch (protocol) {
6e5923851   wdenk   * Cleanup, minor ...
1779
  		/* Fall through */
643d1ab23   Jon Loeliger   net/: Remove obso...
1780
  #if defined(CONFIG_CMD_PING)
73a8b27c5   wdenk   * Add support for...
1781
  	case PING:
6e5923851   wdenk   * Cleanup, minor ...
1782
  		if (NetPingIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1783
1784
  			puts("*** ERROR: ping address not given
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1785
  			return 1;
6e5923851   wdenk   * Cleanup, minor ...
1786
1787
  		}
  		goto common;
73a8b27c5   wdenk   * Add support for...
1788
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
1789
  #if defined(CONFIG_CMD_SNTP)
ea287debe   wdenk   * Patch by Masami...
1790
1791
  	case SNTP:
  		if (NetNtpServerIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1792
1793
  			puts("*** ERROR: NTP server address not given
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1794
  			return 1;
ea287debe   wdenk   * Patch by Masami...
1795
1796
1797
  		}
  		goto common;
  #endif
1a32bf418   Robin Getz   Add DNS support
1798
1799
1800
1801
1802
1803
1804
1805
1806
  #if defined(CONFIG_CMD_DNS)
  	case DNS:
  		if (NetOurDNSIP == 0) {
  			puts("*** ERROR: DNS server address not given
  ");
  			return 1;
  		}
  		goto common;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
1807
  #if defined(CONFIG_CMD_NFS)
cbd8a35c6   wdenk   * Patch by Masami...
1808
1809
  	case NFS:
  #endif
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
1810
  	case TFTPGET:
1fb7cd498   Simon Glass   net: tftpput: imp...
1811
  	case TFTPPUT:
6e5923851   wdenk   * Cleanup, minor ...
1812
  		if (NetServerIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1813
1814
  			puts("*** ERROR: `serverip' not set
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1815
  			return 1;
6e5923851   wdenk   * Cleanup, minor ...
1816
  		}
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1817
1818
1819
  #if	defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
  	defined(CONFIG_CMD_DNS)
  common:
73a8b27c5   wdenk   * Add support for...
1820
  #endif
8b6bbe104   Simon Guinot   netconsole: remov...
1821
  		/* Fall through */
73a8b27c5   wdenk   * Add support for...
1822

8b6bbe104   Simon Guinot   netconsole: remov...
1823
  	case NETCONS:
7a83af07a   Luca Ceresoli   TFTP: add tftpsrv...
1824
  	case TFTPSRV:
6e5923851   wdenk   * Cleanup, minor ...
1825
  		if (NetOurIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1826
1827
  			puts("*** ERROR: `ipaddr' not set
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1828
  			return 1;
6e5923851   wdenk   * Cleanup, minor ...
1829
1830
  		}
  		/* Fall through */
2d966958c   wdenk   Initial revision
1831

bf6cb247a   Peter Tyser   rarp: Condtionall...
1832
  #ifdef CONFIG_CMD_RARP
2d966958c   wdenk   Initial revision
1833
  	case RARP:
bf6cb247a   Peter Tyser   rarp: Condtionall...
1834
  #endif
2d966958c   wdenk   Initial revision
1835
  	case BOOTP:
a3d991bd0   wdenk   Patches by Pantel...
1836
  	case CDP:
bf6cb247a   Peter Tyser   rarp: Condtionall...
1837
  	case DHCP:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1838
  		if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1839
1840
  			extern int eth_get_dev_index(void);
  			int num = eth_get_dev_index();
2d966958c   wdenk   Initial revision
1841

6e5923851   wdenk   * Cleanup, minor ...
1842
1843
  			switch (num) {
  			case -1:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1844
1845
  				puts("*** ERROR: No ethernet found.
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1846
  				return 1;
6e5923851   wdenk   * Cleanup, minor ...
1847
  			case 0:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1848
1849
  				puts("*** ERROR: `ethaddr' not set
  ");
2d966958c   wdenk   Initial revision
1850
  				break;
6e5923851   wdenk   * Cleanup, minor ...
1851
  			default:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1852
1853
  				printf("*** ERROR: `eth%daddr' not set
  ",
2d966958c   wdenk   Initial revision
1854
1855
  					num);
  				break;
6e5923851   wdenk   * Cleanup, minor ...
1856
  			}
2d966958c   wdenk   Initial revision
1857

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1858
  			NetStartAgain();
92895de97   Luca Ceresoli   net/net.c: cosmet...
1859
  			return 2;
6e5923851   wdenk   * Cleanup, minor ...
1860
1861
1862
  		}
  		/* Fall through */
  	default:
92895de97   Luca Ceresoli   net/net.c: cosmet...
1863
  		return 0;
2d966958c   wdenk   Initial revision
1864
  	}
92895de97   Luca Ceresoli   net/net.c: cosmet...
1865
  	return 0;		/* OK */
2d966958c   wdenk   Initial revision
1866
1867
1868
1869
  }
  /**********************************************************************/
  
  int
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1870
  NetCksumOk(uchar *ptr, int len)
2d966958c   wdenk   Initial revision
1871
1872
1873
1874
1875
1876
  {
  	return !((NetCksum(ptr, len) + 1) & 0xfffe);
  }
  
  
  unsigned
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1877
  NetCksum(uchar *ptr, int len)
2d966958c   wdenk   Initial revision
1878
1879
  {
  	ulong	xsum;
9d2a873bd   Stefan Roese   Add I2C support t...
1880
  	ushort *p = (ushort *)ptr;
2d966958c   wdenk   Initial revision
1881
1882
1883
  
  	xsum = 0;
  	while (len-- > 0)
7bc5ee078   Wolfgang Denk   Prepare U-Boot fo...
1884
  		xsum += *p++;
2d966958c   wdenk   Initial revision
1885
1886
  	xsum = (xsum & 0xffff) + (xsum >> 16);
  	xsum = (xsum & 0xffff) + (xsum >> 16);
92895de97   Luca Ceresoli   net/net.c: cosmet...
1887
  	return xsum & 0xffff;
2d966958c   wdenk   Initial revision
1888
  }
a3d991bd0   wdenk   Patches by Pantel...
1889
1890
1891
1892
  int
  NetEthHdrSize(void)
  {
  	ushort myvlanid;
2d966958c   wdenk   Initial revision
1893

a3d991bd0   wdenk   Patches by Pantel...
1894
1895
1896
  	myvlanid = ntohs(NetOurVLAN);
  	if (myvlanid == (ushort)-1)
  		myvlanid = VLAN_NONE;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1897
1898
  	return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE :
  		VLAN_ETHER_HDR_SIZE;
a3d991bd0   wdenk   Patches by Pantel...
1899
1900
1901
  }
  
  int
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1902
  NetSetEther(volatile uchar *xet, uchar * addr, uint prot)
2d966958c   wdenk   Initial revision
1903
1904
  {
  	Ethernet_t *et = (Ethernet_t *)xet;
a3d991bd0   wdenk   Patches by Pantel...
1905
1906
1907
1908
1909
  	ushort myvlanid;
  
  	myvlanid = ntohs(NetOurVLAN);
  	if (myvlanid == (ushort)-1)
  		myvlanid = VLAN_NONE;
2d966958c   wdenk   Initial revision
1910

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1911
1912
  	memcpy(et->et_dest, addr, 6);
  	memcpy(et->et_src, NetOurEther, 6);
a3d991bd0   wdenk   Patches by Pantel...
1913
  	if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1914
  		et->et_protlen = htons(prot);
a3d991bd0   wdenk   Patches by Pantel...
1915
1916
1917
  		return ETHER_HDR_SIZE;
  	} else {
  		VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
2d966958c   wdenk   Initial revision
1918

a3d991bd0   wdenk   Patches by Pantel...
1919
1920
1921
1922
1923
1924
  		vet->vet_vlan_type = htons(PROT_VLAN);
  		vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
  		vet->vet_type = htons(prot);
  		return VLAN_ETHER_HDR_SIZE;
  	}
  }
2d966958c   wdenk   Initial revision
1925
1926
  
  void
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1927
  NetSetIP(volatile uchar *xip, IPaddr_t dest, int dport, int sport, int len)
2d966958c   wdenk   Initial revision
1928
  {
af8626e0c   Olav Morken   Fix IP alignment ...
1929
  	IP_t *ip = (IP_t *)xip;
2d966958c   wdenk   Initial revision
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
  
  	/*
  	 *	If the data is an odd number of bytes, zero the
  	 *	byte after the last byte so that the checksum
  	 *	will work.
  	 */
  	if (len & 1)
  		xip[IP_HDR_SIZE + len] = 0;
  
  	/*
  	 *	Construct an IP and UDP header.
6e5923851   wdenk   * Cleanup, minor ...
1941
  	 *	(need to set no fragment bit - XXX)
2d966958c   wdenk   Initial revision
1942
  	 */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1943
1944
  	/* IP_HDR_SIZE / 4 (not including UDP) */
  	ip->ip_hl_v  = 0x45;
2d966958c   wdenk   Initial revision
1945
1946
1947
  	ip->ip_tos   = 0;
  	ip->ip_len   = htons(IP_HDR_SIZE + len);
  	ip->ip_id    = htons(NetIPID++);
e0c07b868   Peter Tyser   net: Define IP fl...
1948
  	ip->ip_off   = htons(IP_FLAGS_DFRAG);	/* Don't fragment */
2d966958c   wdenk   Initial revision
1949
1950
1951
  	ip->ip_ttl   = 255;
  	ip->ip_p     = 17;		/* UDP */
  	ip->ip_sum   = 0;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1952
  	/* already in network byte order */
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1953
  	NetCopyIP((void *)&ip->ip_src, &NetOurIP);
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1954
  	/* - "" - */
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1955
  	NetCopyIP((void *)&ip->ip_dst, &dest);
2d966958c   wdenk   Initial revision
1956
1957
1958
1959
1960
1961
  	ip->udp_src  = htons(sport);
  	ip->udp_dst  = htons(dport);
  	ip->udp_len  = htons(8 + len);
  	ip->udp_xsum = 0;
  	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
  }
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1962
  void copy_filename(char *dst, const char *src, int size)
2d966958c   wdenk   Initial revision
1963
1964
1965
1966
1967
  {
  	if (*src && (*src == '"')) {
  		++src;
  		--size;
  	}
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1968
  	while ((--size > 0) && *src && (*src != '"'))
2d966958c   wdenk   Initial revision
1969
  		*dst++ = *src++;
2d966958c   wdenk   Initial revision
1970
1971
  	*dst = '\0';
  }
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1972
1973
1974
  #if	defined(CONFIG_CMD_NFS)		|| \
  	defined(CONFIG_CMD_SNTP)	|| \
  	defined(CONFIG_CMD_DNS)
1a32bf418   Robin Getz   Add DNS support
1975
  /*
9739946cc   Robin Getz   ./net/net.c - mak...
1976
1977
1978
   * make port a little random (1024-17407)
   * This keeps the math somewhat trivial to compute, and seems to work with
   * all supported protocols/clients/servers
1a32bf418   Robin Getz   Add DNS support
1979
1980
1981
   */
  unsigned int random_port(void)
  {
9739946cc   Robin Getz   ./net/net.c - mak...
1982
  	return 1024 + (get_timer(0) % 0x4000);
1a32bf418   Robin Getz   Add DNS support
1983
1984
  }
  #endif
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1985
  void ip_to_string(IPaddr_t x, char *s)
2d966958c   wdenk   Initial revision
1986
  {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1987
1988
1989
1990
1991
  	x = ntohl(x);
  	sprintf(s, "%d.%d.%d.%d",
  		(int) ((x >> 24) & 0xff),
  		(int) ((x >> 16) & 0xff),
  		(int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
6e5923851   wdenk   * Cleanup, minor ...
1992
  	);
2d966958c   wdenk   Initial revision
1993
  }
a3d991bd0   wdenk   Patches by Pantel...
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
  void VLAN_to_string(ushort x, char *s)
  {
  	x = ntohs(x);
  
  	if (x == (ushort)-1)
  		x = VLAN_NONE;
  
  	if (x == VLAN_NONE)
  		strcpy(s, "none");
  	else
  		sprintf(s, "%d", x & VLAN_IDMASK);
  }
2e3ef6e4e   Mike Frysinger   string_to_VLAN: c...
2006
  ushort string_to_VLAN(const char *s)
a3d991bd0   wdenk   Patches by Pantel...
2007
2008
2009
2010
  {
  	ushort id;
  
  	if (s == NULL)
b9711de10   wdenk   * Patch by John K...
2011
  		return htons(VLAN_NONE);
a3d991bd0   wdenk   Patches by Pantel...
2012
2013
2014
2015
2016
  
  	if (*s < '0' || *s > '9')
  		id = VLAN_NONE;
  	else
  		id = (ushort)simple_strtoul(s, NULL, 10);
b9711de10   wdenk   * Patch by John K...
2017
  	return htons(id);
a3d991bd0   wdenk   Patches by Pantel...
2018
  }
a3d991bd0   wdenk   Patches by Pantel...
2019
2020
  ushort getenv_VLAN(char *var)
  {
92895de97   Luca Ceresoli   net/net.c: cosmet...
2021
  	return string_to_VLAN(getenv(var));
a3d991bd0   wdenk   Patches by Pantel...
2022
  }