Blame view

net/net.c 33.2 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
  /*
   *	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
   *
d22c338e0   Joe Hershberger   net: Add link-loc...
26
27
28
29
30
31
   * LINK_LOCAL:
   *
   *	Prerequisites:	- own ethernet address
   *	We want:	- own IP address
   *	Next step:	ARP
   *
2d966958c   wdenk   Initial revision
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
   * 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
49
50
51
52
   *     Prerequisites:	- own ethernet address
   *     We want:		- IP, Netmask, ServerIP, Gateway IP
   *			- bootfilename, lease time
   *     Next step:	- TFTP
2d966958c   wdenk   Initial revision
53
54
55
56
57
58
59
60
61
62
63
   *
   * 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...
64
65
66
67
68
69
70
71
72
   *
   * 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...
73
74
75
   *
   * SNTP:
   *
b2f508075   Wolfgang Denk   Minor code cleanup
76
   *	Prerequisites:	- own ethernet address
ea287debe   wdenk   * Patch by Masami...
77
78
79
   *			- own IP address
   *	We want:	- network time
   *	Next step:	none
2d966958c   wdenk   Initial revision
80
81
82
83
   */
  
  
  #include <common.h>
2d966958c   wdenk   Initial revision
84
  #include <command.h>
a9f51c9b4   Joe Hershberger   env: Add a bootfi...
85
  #include <environment.h>
2d966958c   wdenk   Initial revision
86
  #include <net.h>
4545f4e6d   Joe Hershberger   net: cosmetic: Al...
87
  #if defined(CONFIG_STATUS_LED)
fc3e2165e   wdenk   * Patch by Sangmo...
88
  #include <miiphy.h>
4545f4e6d   Joe Hershberger   net: cosmetic: Al...
89
  #include <status_led.h>
fc3e2165e   wdenk   * Patch by Sangmo...
90
  #endif
4545f4e6d   Joe Hershberger   net: cosmetic: Al...
91
92
93
94
  #include <watchdog.h>
  #include <linux/compiler.h>
  #include "arp.h"
  #include "bootp.h"
f575ae1f7   Joe Hershberger   net: Move CDP out...
95
  #include "cdp.h"
1a32bf418   Robin Getz   Add DNS support
96
97
98
  #if defined(CONFIG_CMD_DNS)
  #include "dns.h"
  #endif
d22c338e0   Joe Hershberger   net: Add link-loc...
99
  #include "link_local.h"
4545f4e6d   Joe Hershberger   net: cosmetic: Al...
100
  #include "nfs.h"
a36b12f95   Joe Hershberger   net: Move PING ou...
101
  #include "ping.h"
4545f4e6d   Joe Hershberger   net: cosmetic: Al...
102
103
104
105
106
  #include "rarp.h"
  #if defined(CONFIG_CMD_SNTP)
  #include "sntp.h"
  #endif
  #include "tftp.h"
2d966958c   wdenk   Initial revision
107

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
108
  DECLARE_GLOBAL_DATA_PTR;
2d966958c   wdenk   Initial revision
109
  /** BOOTP EXTENTIONS **/
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
110
  /* Our subnet mask (0=unknown) */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
111
  IPaddr_t	NetOurSubnetMask;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
112
  /* Our gateways IP address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
113
  IPaddr_t	NetOurGatewayIP;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
114
  /* Our DNS IP address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
115
  IPaddr_t	NetOurDNSIP;
1fe80d79c   Jon Loeliger   Finally retire cm...
116
  #if defined(CONFIG_BOOTP_DNS2)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
117
  /* Our 2nd DNS IP address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
118
  IPaddr_t	NetOurDNS2IP;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
119
120
  #endif
  /* Our NIS domain */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
121
  char		NetOurNISDomain[32] = {0,};
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
122
  /* Our hostname */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
123
  char		NetOurHostName[32] = {0,};
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
124
  /* Our bootpath */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
125
  char		NetOurRootPath[64] = {0,};
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
126
  /* Our bootfile size in blocks */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
127
  ushort		NetBootFileSize;
2d966958c   wdenk   Initial revision
128

53a5c424b   David Updegraff   multicast tftp: R...
129
130
131
  #ifdef CONFIG_MCAST_TFTP	/* Multicast TFTP */
  IPaddr_t Mcast_addr;
  #endif
2d966958c   wdenk   Initial revision
132
  /** END OF BOOTP EXTENTIONS **/
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
133
134
135
136
137
  /* 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...
138
  uchar		NetServerEther[6];
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
139
140
141
142
143
  /* Our IP addr (0 = unknown) */
  IPaddr_t	NetOurIP;
  /* Server IP addr (0 = unknown) */
  IPaddr_t	NetServerIP;
  /* Current receive packet */
db288a960   Joe Hershberger   net: Remove volat...
144
  uchar *NetRxPacket;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
145
146
147
148
149
  /* Current rx packet length */
  int		NetRxPacketLen;
  /* IP packet ID */
  unsigned	NetIPID;
  /* Ethernet bcast address */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
150
151
  uchar		NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  uchar		NetEtherNullAddr[6];
f85b60710   Rafal Jaworowski   Introduce new eth...
152
  #ifdef CONFIG_API
db288a960   Joe Hershberger   net: Remove volat...
153
  void		(*push_packet)(void *, int len) = 0;
f85b60710   Rafal Jaworowski   Introduce new eth...
154
  #endif
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
155
  /* Network loop state */
22f6e99d5   Joe Hershberger   net: Refactor to ...
156
  enum net_loop_state net_state;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
157
  /* Tried all network devices */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
158
  int		NetRestartWrap;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
159
  /* Network loop restarted */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
160
  static int	NetRestarted;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
161
  /* At least one device configured */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
162
  static int	NetDevExists;
2d966958c   wdenk   Initial revision
163

6e5923851   wdenk   * Cleanup, minor ...
164
  /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
165
166
167
168
  /* default is without VLAN */
  ushort		NetOurVLAN = 0xFFFF;
  /* ditto */
  ushort		NetOurNativeVLAN = 0xFFFF;
a3d991bd0   wdenk   Patches by Pantel...
169

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

643d1ab23   Jon Loeliger   net/: Remove obso...
173
  #if defined(CONFIG_CMD_SNTP)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
174
175
176
  /* NTP server IP address */
  IPaddr_t	NetNtpServerIP;
  /* offset time from UTC */
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
177
  int		NetTimeOffset;
ea287debe   wdenk   * Patch by Masami...
178
  #endif
063705908   Kim Phillips   net/: sparse fixes
179
  static uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
2d966958c   wdenk   Initial revision
180

3e38e429f   Luca Ceresoli   net/net.c: cosmet...
181
  /* Receive packet */
db288a960   Joe Hershberger   net: Remove volat...
182
  uchar *NetRxPackets[PKTBUFSRX];
2d966958c   wdenk   Initial revision
183

ece223b52   Joe Hershberger   net: Refactor to ...
184
185
186
187
  /* Current UDP RX packet handler */
  static rxhand_f *udp_packet_handler;
  /* Current ARP RX packet handler */
  static rxhand_f *arp_packet_handler;
39bccd21d   Simon Glass   net: Hide more co...
188
  #ifdef CONFIG_CMD_TFTPPUT
ece223b52   Joe Hershberger   net: Refactor to ...
189
190
  /* Current ICMP rx handler */
  static rxhand_icmp_f *packet_icmp_handler;
39bccd21d   Simon Glass   net: Hide more co...
191
  #endif
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
192
193
194
195
196
197
198
  /* Current timeout handler */
  static thand_f *timeHandler;
  /* Time base value */
  static ulong	timeStart;
  /* Current timeout value */
  static ulong	timeDelta;
  /* THE transmit packet */
db288a960   Joe Hershberger   net: Remove volat...
199
  uchar *NetTxPacket;
2d966958c   wdenk   Initial revision
200

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

67b96e87d   Remy Bohmer   Repair the 'netre...
203
  static int NetTryCount;
b63056d6a   Jim Lin   NET: Add net_busy...
204
  int __maybe_unused net_busy_flag;
2d966958c   wdenk   Initial revision
205
  /**********************************************************************/
73a8b27c5   wdenk   * Add support for...
206

a9f51c9b4   Joe Hershberger   env: Add a bootfi...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  static int on_bootfile(const char *name, const char *value, enum env_op op,
  	int flags)
  {
  	switch (op) {
  	case env_op_create:
  	case env_op_overwrite:
  		copy_filename(BootFile, value, sizeof(BootFile));
  		break;
  	default:
  		break;
  	}
  
  	return 0;
  }
  U_BOOT_ENV_CALLBACK(bootfile, on_bootfile);
e4a3d57dc   Simon Glass   net: Export auto_...
222
223
224
225
226
227
  /*
   * Check if autoload is enabled. If so, use either NFS or TFTP to download
   * the boot file.
   */
  void net_auto_load(void)
  {
ec8a252cd   Joe Hershberger   env: Use getenv_y...
228
  #if defined(CONFIG_CMD_NFS)
e4a3d57dc   Simon Glass   net: Export auto_...
229
  	const char *s = getenv("autoload");
ec8a252cd   Joe Hershberger   env: Use getenv_y...
230
231
232
233
234
235
236
  	if (s != NULL && strcmp(s, "NFS") == 0) {
  		/*
  		 * Use NFS to load the bootfile.
  		 */
  		NfsStart();
  		return;
  	}
e4a3d57dc   Simon Glass   net: Export auto_...
237
  #endif
ec8a252cd   Joe Hershberger   env: Use getenv_y...
238
239
240
241
242
243
244
  	if (getenv_yesno("autoload") == 0) {
  		/*
  		 * Just use BOOTP/RARP to configure system;
  		 * Do not use TFTP to load the bootfile.
  		 */
  		net_set_state(NETLOOP_SUCCESS);
  		return;
e4a3d57dc   Simon Glass   net: Export auto_...
245
246
247
  	}
  	TftpStart(TFTPGET);
  }
cb1c99112   Joe Hershberger   net: Remove unuse...
248
  static void NetInitLoop(void)
2f70c49e5   Heiko Schocher   netloop: speed up...
249
  {
c586ce6e0   Luca Ceresoli   net/net.c: cosmet...
250
  	static int env_changed_id;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
251
  	int env_id = get_env_id();
2f70c49e5   Heiko Schocher   netloop: speed up...
252
253
  
  	/* update only when the environment has changed */
3c172c4fd   Michael Zaidman   NetLoop initializ...
254
  	if (env_changed_id != env_id) {
23a70bf9c   Enric Balletbo i Serra   net/net.c: Update...
255
  		NetOurIP = getenv_IPaddr("ipaddr");
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
256
257
258
  		NetOurGatewayIP = getenv_IPaddr("gatewayip");
  		NetOurSubnetMask = getenv_IPaddr("netmask");
  		NetServerIP = getenv_IPaddr("serverip");
2f70c49e5   Heiko Schocher   netloop: speed up...
259
  		NetOurNativeVLAN = getenv_VLAN("nvlan");
3c172c4fd   Michael Zaidman   NetLoop initializ...
260
  		NetOurVLAN = getenv_VLAN("vlan");
1a32bf418   Robin Getz   Add DNS support
261
262
263
  #if defined(CONFIG_CMD_DNS)
  		NetOurDNSIP = getenv_IPaddr("dnsip");
  #endif
3c172c4fd   Michael Zaidman   NetLoop initializ...
264
  		env_changed_id = env_id;
2f70c49e5   Heiko Schocher   netloop: speed up...
265
  	}
7315cfd9e   Jim Lin   NET: Fix system h...
266
267
  	if (eth_get_dev())
  		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
3c172c4fd   Michael Zaidman   NetLoop initializ...
268

da95427ce   Heiko Schocher   netloop: updates ...
269
  	return;
2f70c49e5   Heiko Schocher   netloop: speed up...
270
  }
ece223b52   Joe Hershberger   net: Refactor to ...
271
272
273
274
275
276
277
278
279
280
281
  static void net_clear_handlers(void)
  {
  	net_set_udp_handler(NULL);
  	net_set_arp_handler(NULL);
  	NetSetTimeout(0, NULL);
  }
  
  static void net_cleanup_loop(void)
  {
  	net_clear_handlers();
  }
46c495d52   Joe Hershberger   net: Fix net buff...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  void net_init(void)
  {
  	static int first_call = 1;
  
  	if (first_call) {
  		/*
  		 *	Setup packet buffers, aligned correctly.
  		 */
  		int i;
  
  		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
  		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
  		for (i = 0; i < PKTBUFSRX; i++)
  			NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
  
  		ArpInit();
  		net_clear_handlers();
  
  		/* Only need to setup buffer pointers once. */
  		first_call = 0;
  	}
  
  	NetInitLoop();
  }
73a8b27c5   wdenk   * Add support for...
306
  /**********************************************************************/
2d966958c   wdenk   Initial revision
307
308
309
  /*
   *	Main network processing loop.
   */
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
310
  int NetLoop(enum proto_t protocol)
2d966958c   wdenk   Initial revision
311
  {
2d966958c   wdenk   Initial revision
312
  	bd_t *bd = gd->bd;
4793ee652   Simon Glass   net: tftpput: Add...
313
  	int ret = -1;
2d966958c   wdenk   Initial revision
314

2d966958c   wdenk   Initial revision
315
316
  	NetRestarted = 0;
  	NetDevExists = 0;
67b96e87d   Remy Bohmer   Repair the 'netre...
317
  	NetTryCount = 1;
4ef8d53ca   Joe Hershberger   net: Allow filter...
318
319
  	debug_cond(DEBUG_INT_STATE, "--- NetLoop Entry
  ");
73a8b27c5   wdenk   * Add support for...
320

573f14fe4   Simon Glass   bootstage: Plumb ...
321
  	bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
46c495d52   Joe Hershberger   net: Fix net buff...
322
  	net_init();
f8be7d659   Joe Hershberger   net: Improve the ...
323
  	if (eth_is_on_demand_init() || protocol != NETCONS) {
b1bf6f2c9   wdenk   * Patch by Richar...
324
  		eth_halt();
f8be7d659   Joe Hershberger   net: Improve the ...
325
326
327
328
329
330
331
  		eth_set_current();
  		if (eth_init(bd) < 0) {
  			eth_halt();
  			return -1;
  		}
  	} else
  		eth_init_state_only(bd);
2d966958c   wdenk   Initial revision
332
333
  
  restart:
b63056d6a   Jim Lin   NET: Add net_busy...
334
335
336
  #ifdef CONFIG_USB_KEYBOARD
  	net_busy_flag = 0;
  #endif
22f6e99d5   Joe Hershberger   net: Refactor to ...
337
  	net_set_state(NETLOOP_CONTINUE);
2d966958c   wdenk   Initial revision
338
339
340
341
342
343
  
  	/*
  	 *	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.
  	 */
4ef8d53ca   Joe Hershberger   net: Allow filter...
344
345
  	debug_cond(DEBUG_INT_STATE, "--- NetLoop Init
  ");
cb1c99112   Joe Hershberger   net: Remove unuse...
346
  	NetInitLoop();
2d966958c   wdenk   Initial revision
347

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
348
  	switch (net_check_prereq(protocol)) {
2d966958c   wdenk   Initial revision
349
350
  	case 1:
  		/* network not configured */
b1bf6f2c9   wdenk   * Patch by Richar...
351
  		eth_halt();
92895de97   Luca Ceresoli   net/net.c: cosmet...
352
  		return -1;
2d966958c   wdenk   Initial revision
353

2d966958c   wdenk   Initial revision
354
355
356
  	case 2:
  		/* network device not configured */
  		break;
2d966958c   wdenk   Initial revision
357
358
  
  	case 0:
2d966958c   wdenk   Initial revision
359
  		NetDevExists = 1;
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
360
  		NetBootFileXferSize = 0;
2d966958c   wdenk   Initial revision
361
  		switch (protocol) {
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
362
  		case TFTPGET:
1fb7cd498   Simon Glass   net: tftpput: imp...
363
364
365
  #ifdef CONFIG_CMD_TFTPPUT
  		case TFTPPUT:
  #endif
2d966958c   wdenk   Initial revision
366
  			/* always use ARP to get server ethernet address */
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
367
  			TftpStart(protocol);
2d966958c   wdenk   Initial revision
368
  			break;
7a83af07a   Luca Ceresoli   TFTP: add tftpsrv...
369
370
371
372
373
  #ifdef CONFIG_CMD_TFTPSRV
  		case TFTPSRV:
  			TftpStartServer();
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
374
  #if defined(CONFIG_CMD_DHCP)
2d966958c   wdenk   Initial revision
375
  		case DHCP:
d407bf52b   wdenk   * Patch by Philip...
376
  			BootpTry = 0;
09133f858   Michael Zaidman   DHCP regression o...
377
  			NetOurIP = 0;
2d966958c   wdenk   Initial revision
378
379
  			DhcpRequest();		/* Basically same as BOOTP */
  			break;
610f2e9c2   Jon Loeliger   net/: Remove ling...
380
  #endif
2d966958c   wdenk   Initial revision
381
382
383
  
  		case BOOTP:
  			BootpTry = 0;
09133f858   Michael Zaidman   DHCP regression o...
384
  			NetOurIP = 0;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
385
  			BootpRequest();
2d966958c   wdenk   Initial revision
386
  			break;
bf6cb247a   Peter Tyser   rarp: Condtionall...
387
  #if defined(CONFIG_CMD_RARP)
2d966958c   wdenk   Initial revision
388
389
  		case RARP:
  			RarpTry = 0;
09133f858   Michael Zaidman   DHCP regression o...
390
  			NetOurIP = 0;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
391
  			RarpRequest();
2d966958c   wdenk   Initial revision
392
  			break;
bf6cb247a   Peter Tyser   rarp: Condtionall...
393
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
394
  #if defined(CONFIG_CMD_PING)
73a8b27c5   wdenk   * Add support for...
395
  		case PING:
a36b12f95   Joe Hershberger   net: Move PING ou...
396
  			ping_start();
73a8b27c5   wdenk   * Add support for...
397
398
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
399
  #if defined(CONFIG_CMD_NFS)
cbd8a35c6   wdenk   * Patch by Masami...
400
401
402
403
  		case NFS:
  			NfsStart();
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
404
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
405
406
407
408
  		case CDP:
  			CDPStart();
  			break;
  #endif
68ceb29e7   wdenk   Add support for c...
409
410
411
412
413
  #ifdef CONFIG_NETCONSOLE
  		case NETCONS:
  			NcStart();
  			break;
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
414
  #if defined(CONFIG_CMD_SNTP)
ea287debe   wdenk   * Patch by Masami...
415
416
417
418
  		case SNTP:
  			SntpStart();
  			break;
  #endif
1a32bf418   Robin Getz   Add DNS support
419
420
421
422
423
  #if defined(CONFIG_CMD_DNS)
  		case DNS:
  			DnsStart();
  			break;
  #endif
d22c338e0   Joe Hershberger   net: Add link-loc...
424
425
426
427
428
  #if defined(CONFIG_CMD_LINK_LOCAL)
  		case LINKLOCAL:
  			link_local_start();
  			break;
  #endif
2d966958c   wdenk   Initial revision
429
430
431
  		default:
  			break;
  		}
2d966958c   wdenk   Initial revision
432
433
  		break;
  	}
643d1ab23   Jon Loeliger   net/: Remove obso...
434
  #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
435
436
437
  #if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
  	defined(CONFIG_STATUS_LED)			&& \
  	defined(STATUS_LED_RED)
fc3e2165e   wdenk   * Patch by Sangmo...
438
  	/*
42d1f0394   wdenk   * Patches by Xian...
439
  	 * Echo the inverted link state to the fault LED.
fc3e2165e   wdenk   * Patch by Sangmo...
440
  	 */
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
441
  	if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
442
  		status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
443
  	else
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
444
  		status_led_set(STATUS_LED_RED, STATUS_LED_ON);
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
445
  #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
fc3e2165e   wdenk   * Patch by Sangmo...
446
  #endif /* CONFIG_MII, ... */
b63056d6a   Jim Lin   NET: Add net_busy...
447
448
449
  #ifdef CONFIG_USB_KEYBOARD
  	net_busy_flag = 1;
  #endif
2d966958c   wdenk   Initial revision
450
451
452
  
  	/*
  	 *	Main packet reception loop.  Loop receiving packets until
22f6e99d5   Joe Hershberger   net: Refactor to ...
453
  	 *	someone sets `net_state' to a state that terminates.
2d966958c   wdenk   Initial revision
454
455
456
457
  	 */
  	for (;;) {
  		WATCHDOG_RESET();
  #ifdef CONFIG_SHOW_ACTIVITY
48522bb50   Joe Hershberger   net: cosmetic: ne...
458
  		show_activity(1);
2d966958c   wdenk   Initial revision
459
460
461
462
463
  #endif
  		/*
  		 *	Check the ethernet for a new packet.  The ethernet
  		 *	receive routine will process it.
  		 */
40cb90ee2   Guennadi Liakhovetski   net: make ARP tim...
464
  		eth_rx();
2d966958c   wdenk   Initial revision
465
466
467
468
469
  
  		/*
  		 *	Abort if ctrl-c was pressed.
  		 */
  		if (ctrlc()) {
e94070c44   Joe Hershberger   net: Don't copy e...
470
471
  			/* cancel any ARP that may not have completed */
  			NetArpWaitPacketIP = 0;
ece223b52   Joe Hershberger   net: Refactor to ...
472
  			net_cleanup_loop();
8bde7f776   wdenk   * Code cleanup:
473
  			eth_halt();
f8be7d659   Joe Hershberger   net: Improve the ...
474
475
  			/* Invalidate the last protocol */
  			eth_set_last_protocol(BOOTP);
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
476
477
478
  			puts("
  Abort
  ");
4ef8d53ca   Joe Hershberger   net: Allow filter...
479
480
481
482
  			/* include a debug print as well incase the debug
  			   messages are directed to stderr */
  			debug_cond(DEBUG_INT_STATE, "--- NetLoop Abort!
  ");
4793ee652   Simon Glass   net: tftpput: Add...
483
  			goto done;
2d966958c   wdenk   Initial revision
484
  		}
73a8b27c5   wdenk   * Add support for...
485
  		ArpTimeoutCheck();
2d966958c   wdenk   Initial revision
486
487
488
489
490
  
  		/*
  		 *	Check for a timeout, and run the timeout handler
  		 *	if we have one.
  		 */
e0ac62d79   wdenk   * Make Ethernet a...
491
  		if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
2d966958c   wdenk   Initial revision
492
  			thand_f *x;
643d1ab23   Jon Loeliger   net/: Remove obso...
493
  #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
494
495
496
  #if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
  	defined(CONFIG_STATUS_LED)			&& \
  	defined(STATUS_LED_RED)
fc3e2165e   wdenk   * Patch by Sangmo...
497
  			/*
42d1f0394   wdenk   * Patches by Xian...
498
  			 * Echo the inverted link state to the fault LED.
fc3e2165e   wdenk   * Patch by Sangmo...
499
  			 */
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
500
  			if (miiphy_link(eth_get_dev()->name,
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
501
  				       CONFIG_SYS_FAULT_MII_ADDR)) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
502
  				status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
fc3e2165e   wdenk   * Patch by Sangmo...
503
  			} else {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
504
  				status_led_set(STATUS_LED_RED, STATUS_LED_ON);
fc3e2165e   wdenk   * Patch by Sangmo...
505
  			}
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
506
  #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
fc3e2165e   wdenk   * Patch by Sangmo...
507
  #endif /* CONFIG_MII, ... */
4ef8d53ca   Joe Hershberger   net: Allow filter...
508
509
  			debug_cond(DEBUG_INT_STATE, "--- NetLoop timeout
  ");
2d966958c   wdenk   Initial revision
510
511
512
513
  			x = timeHandler;
  			timeHandler = (thand_f *)0;
  			(*x)();
  		}
22f6e99d5   Joe Hershberger   net: Refactor to ...
514
  		switch (net_state) {
2d966958c   wdenk   Initial revision
515
516
  
  		case NETLOOP_RESTART:
2d966958c   wdenk   Initial revision
517
  			NetRestarted = 1;
2d966958c   wdenk   Initial revision
518
519
520
  			goto restart;
  
  		case NETLOOP_SUCCESS:
ece223b52   Joe Hershberger   net: Refactor to ...
521
  			net_cleanup_loop();
2d966958c   wdenk   Initial revision
522
  			if (NetBootFileXferSize > 0) {
2d966958c   wdenk   Initial revision
523
524
525
526
  				printf("Bytes transferred = %ld (%lx hex)
  ",
  					NetBootFileXferSize,
  					NetBootFileXferSize);
978226da5   Simon Glass   net: Use new nume...
527
528
  				setenv_hex("filesize", NetBootFileXferSize);
  				setenv_hex("fileaddr", load_addr);
2d966958c   wdenk   Initial revision
529
  			}
f8be7d659   Joe Hershberger   net: Improve the ...
530
531
532
533
534
535
  			if (protocol != NETCONS)
  				eth_halt();
  			else
  				eth_halt_state_only();
  
  			eth_set_last_protocol(protocol);
4793ee652   Simon Glass   net: tftpput: Add...
536
  			ret = NetBootFileXferSize;
4ef8d53ca   Joe Hershberger   net: Allow filter...
537
538
  			debug_cond(DEBUG_INT_STATE, "--- NetLoop Success!
  ");
4793ee652   Simon Glass   net: tftpput: Add...
539
  			goto done;
2d966958c   wdenk   Initial revision
540
541
  
  		case NETLOOP_FAIL:
ece223b52   Joe Hershberger   net: Refactor to ...
542
  			net_cleanup_loop();
f8be7d659   Joe Hershberger   net: Improve the ...
543
544
  			/* Invalidate the last protocol */
  			eth_set_last_protocol(BOOTP);
4ef8d53ca   Joe Hershberger   net: Allow filter...
545
546
  			debug_cond(DEBUG_INT_STATE, "--- NetLoop Fail!
  ");
4793ee652   Simon Glass   net: tftpput: Add...
547
  			goto done;
22f6e99d5   Joe Hershberger   net: Refactor to ...
548
549
550
  
  		case NETLOOP_CONTINUE:
  			continue;
2d966958c   wdenk   Initial revision
551
552
  		}
  	}
4793ee652   Simon Glass   net: tftpput: Add...
553
554
  
  done:
b63056d6a   Jim Lin   NET: Add net_busy...
555
556
557
  #ifdef CONFIG_USB_KEYBOARD
  	net_busy_flag = 0;
  #endif
39bccd21d   Simon Glass   net: Hide more co...
558
  #ifdef CONFIG_CMD_TFTPPUT
4793ee652   Simon Glass   net: tftpput: Add...
559
  	/* Clear out the handlers */
ece223b52   Joe Hershberger   net: Refactor to ...
560
  	net_set_udp_handler(NULL);
4793ee652   Simon Glass   net: tftpput: Add...
561
  	net_set_icmp_handler(NULL);
39bccd21d   Simon Glass   net: Hide more co...
562
  #endif
4793ee652   Simon Glass   net: tftpput: Add...
563
  	return ret;
2d966958c   wdenk   Initial revision
564
565
566
567
568
569
570
  }
  
  /**********************************************************************/
  
  static void
  startAgainTimeout(void)
  {
22f6e99d5   Joe Hershberger   net: Refactor to ...
571
  	net_set_state(NETLOOP_RESTART);
2d966958c   wdenk   Initial revision
572
  }
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
573
  void NetStartAgain(void)
2d966958c   wdenk   Initial revision
574
  {
6e5923851   wdenk   * Cleanup, minor ...
575
  	char *nretry;
67b96e87d   Remy Bohmer   Repair the 'netre...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  	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();
22f6e99d5   Joe Hershberger   net: Refactor to ...
594
  		net_set_state(NETLOOP_FAIL);
a3d991bd0   wdenk   Patches by Pantel...
595
596
  		return;
  	}
67b96e87d   Remy Bohmer   Repair the 'netre...
597
598
  
  	NetTryCount++;
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
599
  	eth_halt();
8b0c5c127   Matthias Fuchs   net: Add CONFIG_N...
600
  #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
601
  	eth_try_another(!NetRestarted);
8b0c5c127   Matthias Fuchs   net: Add CONFIG_N...
602
  #endif
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
603
  	eth_init(gd->bd);
6e5923851   wdenk   * Cleanup, minor ...
604
  	if (NetRestartWrap) {
2d966958c   wdenk   Initial revision
605
  		NetRestartWrap = 0;
67b96e87d   Remy Bohmer   Repair the 'netre...
606
  		if (NetDevExists) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
607
  			NetSetTimeout(10000UL, startAgainTimeout);
ece223b52   Joe Hershberger   net: Refactor to ...
608
  			net_set_udp_handler(NULL);
6e5923851   wdenk   * Cleanup, minor ...
609
  		} else {
22f6e99d5   Joe Hershberger   net: Refactor to ...
610
  			net_set_state(NETLOOP_FAIL);
2d966958c   wdenk   Initial revision
611
  		}
6e5923851   wdenk   * Cleanup, minor ...
612
  	} else {
22f6e99d5   Joe Hershberger   net: Refactor to ...
613
  		net_set_state(NETLOOP_RESTART);
2d966958c   wdenk   Initial revision
614
  	}
2d966958c   wdenk   Initial revision
615
616
617
618
619
620
  }
  
  /**********************************************************************/
  /*
   *	Miscelaneous bits.
   */
ece223b52   Joe Hershberger   net: Refactor to ...
621
622
623
  static void dummy_handler(uchar *pkt, unsigned dport,
  			IPaddr_t sip, unsigned sport,
  			unsigned len)
d280d3f43   Joe Hershberger   net: Move ARP out...
624
  {
d280d3f43   Joe Hershberger   net: Move ARP out...
625
  }
ece223b52   Joe Hershberger   net: Refactor to ...
626
627
628
629
  rxhand_f *net_get_udp_handler(void)
  {
  	return udp_packet_handler;
  }
d280d3f43   Joe Hershberger   net: Move ARP out...
630

ece223b52   Joe Hershberger   net: Refactor to ...
631
632
  void net_set_udp_handler(rxhand_f *f)
  {
4ef8d53ca   Joe Hershberger   net: Allow filter...
633
634
  	debug_cond(DEBUG_INT_STATE, "--- NetLoop UDP handler set (%p)
  ", f);
ece223b52   Joe Hershberger   net: Refactor to ...
635
636
637
638
639
640
641
  	if (f == NULL)
  		udp_packet_handler = dummy_handler;
  	else
  		udp_packet_handler = f;
  }
  
  rxhand_f *net_get_arp_handler(void)
2d966958c   wdenk   Initial revision
642
  {
ece223b52   Joe Hershberger   net: Refactor to ...
643
644
645
646
647
  	return arp_packet_handler;
  }
  
  void net_set_arp_handler(rxhand_f *f)
  {
4ef8d53ca   Joe Hershberger   net: Allow filter...
648
649
  	debug_cond(DEBUG_INT_STATE, "--- NetLoop ARP handler set (%p)
  ", f);
ece223b52   Joe Hershberger   net: Refactor to ...
650
651
652
653
  	if (f == NULL)
  		arp_packet_handler = dummy_handler;
  	else
  		arp_packet_handler = f;
2d966958c   wdenk   Initial revision
654
  }
39bccd21d   Simon Glass   net: Hide more co...
655
  #ifdef CONFIG_CMD_TFTPPUT
4793ee652   Simon Glass   net: tftpput: Add...
656
657
658
659
  void net_set_icmp_handler(rxhand_icmp_f *f)
  {
  	packet_icmp_handler = f;
  }
39bccd21d   Simon Glass   net: Hide more co...
660
  #endif
2d966958c   wdenk   Initial revision
661
662
  
  void
6b147d113   Luca Ceresoli   net/net.c: cosmet...
663
  NetSetTimeout(ulong iv, thand_f *f)
2d966958c   wdenk   Initial revision
664
665
  {
  	if (iv == 0) {
4ef8d53ca   Joe Hershberger   net: Allow filter...
666
667
668
  		debug_cond(DEBUG_INT_STATE,
  			"--- NetLoop timeout handler cancelled
  ");
2d966958c   wdenk   Initial revision
669
670
  		timeHandler = (thand_f *)0;
  	} else {
4ef8d53ca   Joe Hershberger   net: Allow filter...
671
672
673
  		debug_cond(DEBUG_INT_STATE,
  			"--- NetLoop timeout handler set (%p)
  ", f);
2d966958c   wdenk   Initial revision
674
  		timeHandler = f;
e0ac62d79   wdenk   * Make Ethernet a...
675
  		timeStart = get_timer(0);
1389f98fc   Tetsuyuki Kobayashi   net: bugfix: NetS...
676
  		timeDelta = iv * CONFIG_SYS_HZ / 1000;
2d966958c   wdenk   Initial revision
677
678
  	}
  }
206d07fd7   Joe Hershberger   net: cosmetic: Re...
679
680
  int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport,
  		int payload_len)
73a8b27c5   wdenk   * Add support for...
681
  {
a3d991bd0   wdenk   Patches by Pantel...
682
  	uchar *pkt;
9214637a5   Joe Hershberger   net: Refactor Net...
683
684
  	int eth_hdr_size;
  	int pkt_hdr_size;
a3d991bd0   wdenk   Patches by Pantel...
685

46c495d52   Joe Hershberger   net: Fix net buff...
686
687
688
689
  	/* make sure the NetTxPacket is initialized (NetInit() was called) */
  	assert(NetTxPacket != NULL);
  	if (NetTxPacket == NULL)
  		return -1;
73a8b27c5   wdenk   * Add support for...
690
691
692
693
694
695
696
  	/* 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;
e94070c44   Joe Hershberger   net: Don't copy e...
697
  	pkt = (uchar *)NetTxPacket;
9214637a5   Joe Hershberger   net: Refactor Net...
698
699
700
701
702
  
  	eth_hdr_size = NetSetEther(pkt, ether, PROT_IP);
  	pkt += eth_hdr_size;
  	net_set_udp_header(pkt, dest, dport, sport, payload_len);
  	pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE;
73a8b27c5   wdenk   * Add support for...
703

e94070c44   Joe Hershberger   net: Don't copy e...
704
705
  	/* if MAC address was not discovered yet, do an ARP request */
  	if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
4ef8d53ca   Joe Hershberger   net: Allow filter...
706
707
  		debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4
  ", &dest);
0ebf04c60   Robin Getz   minor debug clean...
708

9214637a5   Joe Hershberger   net: Refactor Net...
709
  		/* save the ip and eth addr for the packet to send after arp */
73a8b27c5   wdenk   * Add support for...
710
711
  		NetArpWaitPacketIP = dest;
  		NetArpWaitPacketMAC = ether;
a3d991bd0   wdenk   Patches by Pantel...
712

73a8b27c5   wdenk   * Add support for...
713
  		/* size of the waiting packet */
9214637a5   Joe Hershberger   net: Refactor Net...
714
  		NetArpWaitTxPacketSize = pkt_hdr_size + payload_len;
73a8b27c5   wdenk   * Add support for...
715
716
717
718
719
720
  
  		/* and do the ARP request */
  		NetArpWaitTry = 1;
  		NetArpWaitTimerStart = get_timer(0);
  		ArpRequest();
  		return 1;	/* waiting */
9214637a5   Joe Hershberger   net: Refactor Net...
721
  	} else {
4ef8d53ca   Joe Hershberger   net: Allow filter...
722
723
724
  		debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM
  ",
  			&dest, ether);
adf5d93e4   Joe Hershberger   net: Refactor to ...
725
  		NetSendPacket(NetTxPacket, pkt_hdr_size + payload_len);
9214637a5   Joe Hershberger   net: Refactor Net...
726
  		return 0;	/* transmitted */
73a8b27c5   wdenk   * Add support for...
727
  	}
73a8b27c5   wdenk   * Add support for...
728
  }
5cfaa4e54   Alessandro Rubini   net: defragment I...
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  #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))
c5c59df04   Joe Hershberger   net: cosmetic: Sp...
747
  #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE)
5cfaa4e54   Alessandro Rubini   net: defragment I...
748
749
750
751
752
753
754
755
756
757
758
759
  
  /*
   * 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;
  };
594c26f8a   Joe Hershberger   net: cosmetic: Un...
760
  static struct ip_udp_hdr *__NetDefragment(struct ip_udp_hdr *ip, int *lenp)
5cfaa4e54   Alessandro Rubini   net: defragment I...
761
  {
48522bb50   Joe Hershberger   net: cosmetic: ne...
762
  	static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN);
5cfaa4e54   Alessandro Rubini   net: defragment I...
763
764
  	static u16 first_hole, total_len;
  	struct hole *payload, *thisfrag, *h, *newh;
594c26f8a   Joe Hershberger   net: cosmetic: Un...
765
  	struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff;
5cfaa4e54   Alessandro Rubini   net: defragment I...
766
767
768
769
770
  	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 */
c5c59df04   Joe Hershberger   net: cosmetic: Sp...
771
  	payload = (struct hole *)(pkt_buff + IP_HDR_SIZE);
5cfaa4e54   Alessandro Rubini   net: defragment I...
772
773
774
  	offset8 =  (ip_off & IP_OFFS);
  	thisfrag = payload + offset8;
  	start = offset8 * 8;
c5c59df04   Joe Hershberger   net: cosmetic: Sp...
775
  	len = ntohs(ip->ip_len) - IP_HDR_SIZE;
5cfaa4e54   Alessandro Rubini   net: defragment I...
776
777
778
779
780
781
782
783
784
785
786
787
  
  	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 */
c5c59df04   Joe Hershberger   net: cosmetic: Sp...
788
  		memcpy(localip, ip, IP_HDR_SIZE);
5cfaa4e54   Alessandro Rubini   net: defragment I...
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  	}
  
  	/*
  	 * 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...
806
807
  	/* last fragment may be 1..7 bytes, the "+7" forces acceptance */
  	if (offset8 + ((len + 7) / 8) <= h - payload) {
5cfaa4e54   Alessandro Rubini   net: defragment I...
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  		/* 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...
823
  	if ((h >= thisfrag) && (h->last_byte <= start + len)) {
5cfaa4e54   Alessandro Rubini   net: defragment I...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  		/* 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 */
c5c59df04   Joe Hershberger   net: cosmetic: Sp...
869
  	memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len);
5cfaa4e54   Alessandro Rubini   net: defragment I...
870
871
872
873
  	if (!done)
  		return NULL;
  
  	localip->ip_len = htons(total_len);
c5c59df04   Joe Hershberger   net: cosmetic: Sp...
874
  	*lenp = total_len + IP_HDR_SIZE;
5cfaa4e54   Alessandro Rubini   net: defragment I...
875
876
  	return localip;
  }
594c26f8a   Joe Hershberger   net: cosmetic: Un...
877
  static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp)
5cfaa4e54   Alessandro Rubini   net: defragment I...
878
879
880
881
882
883
884
885
  {
  	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 */
594c26f8a   Joe Hershberger   net: cosmetic: Un...
886
  static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp)
5cfaa4e54   Alessandro Rubini   net: defragment I...
887
888
889
890
891
892
893
  {
  	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...
894

8f79bb17a   Simon Glass   net: tftpput: Mov...
895
896
897
898
899
900
  /**
   * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
   * drop others.
   *
   * @parma ip	IP packet containing the ICMP
   */
594c26f8a   Joe Hershberger   net: cosmetic: Un...
901
  static void receive_icmp(struct ip_udp_hdr *ip, int len,
cb487f566   Joe Hershberger   net: cosmetic: Un...
902
  			IPaddr_t src_ip, struct ethernet_hdr *et)
8f79bb17a   Simon Glass   net: tftpput: Mov...
903
  {
e0a630795   Joe Hershberger   net: cosmetic: Un...
904
  	struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
8f79bb17a   Simon Glass   net: tftpput: Mov...
905
906
907
908
909
910
911
912
  
  	switch (icmph->type) {
  	case ICMP_REDIRECT:
  		if (icmph->code != ICMP_REDIR_HOST)
  			return;
  		printf(" ICMP Host Redirect to %pI4 ",
  			&icmph->un.gateway);
  		break;
a36b12f95   Joe Hershberger   net: Move PING ou...
913
  	default:
8f79bb17a   Simon Glass   net: tftpput: Mov...
914
  #if defined(CONFIG_CMD_PING)
a36b12f95   Joe Hershberger   net: Move PING ou...
915
  		ping_receive(et, ip, len);
8f79bb17a   Simon Glass   net: tftpput: Mov...
916
  #endif
39bccd21d   Simon Glass   net: Hide more co...
917
  #ifdef CONFIG_CMD_TFTPPUT
4793ee652   Simon Glass   net: tftpput: Add...
918
919
920
921
  		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...
922
  #endif
8f79bb17a   Simon Glass   net: tftpput: Mov...
923
924
925
  		break;
  	}
  }
2d966958c   wdenk   Initial revision
926
  void
db288a960   Joe Hershberger   net: Remove volat...
927
  NetReceive(uchar *inpkt, int len)
2d966958c   wdenk   Initial revision
928
  {
cb487f566   Joe Hershberger   net: cosmetic: Un...
929
  	struct ethernet_hdr *et;
594c26f8a   Joe Hershberger   net: cosmetic: Un...
930
  	struct ip_udp_hdr *ip;
8d353eb86   Joe Hershberger   net: cosmetic: Re...
931
  	IPaddr_t dst_ip;
03eb129f8   Luca Ceresoli   NET: pass source ...
932
  	IPaddr_t src_ip;
8d353eb86   Joe Hershberger   net: cosmetic: Re...
933
  	int eth_proto;
643d1ab23   Jon Loeliger   net/: Remove obso...
934
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
935
936
937
  	int iscdp;
  #endif
  	ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
4ef8d53ca   Joe Hershberger   net: Allow filter...
938
939
  	debug_cond(DEBUG_NET_PKT, "packet received
  ");
2d966958c   wdenk   Initial revision
940

d9bec9f42   Mike Frysinger   net: rename NetRx...
941
942
  	NetRxPacket = inpkt;
  	NetRxPacketLen = len;
cb487f566   Joe Hershberger   net: cosmetic: Un...
943
  	et = (struct ethernet_hdr *)inpkt;
a3d991bd0   wdenk   Patches by Pantel...
944
945
946
947
  
  	/* too small packet? */
  	if (len < ETHER_HDR_SIZE)
  		return;
f85b60710   Rafal Jaworowski   Introduce new eth...
948
949
950
951
952
953
  #ifdef CONFIG_API
  	if (push_packet) {
  		(*push_packet)(inpkt, len);
  		return;
  	}
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
954
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
955
  	/* keep track if packet is CDP */
173518832   Joe Hershberger   net: Encapsulate ...
956
  	iscdp = is_cdp_packet(et->et_dest);
a3d991bd0   wdenk   Patches by Pantel...
957
958
959
960
961
962
963
964
  #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
965

8d353eb86   Joe Hershberger   net: cosmetic: Re...
966
  	eth_proto = ntohs(et->et_protlen);
2d966958c   wdenk   Initial revision
967

8d353eb86   Joe Hershberger   net: cosmetic: Re...
968
  	if (eth_proto < 1514) {
cb487f566   Joe Hershberger   net: cosmetic: Un...
969
  		struct e802_hdr *et802 = (struct e802_hdr *)et;
2d966958c   wdenk   Initial revision
970
  		/*
da5ebe2c9   Joe Hershberger   net: cosmetic: Ad...
971
972
  		 *	Got a 802.2 packet.  Check the other protocol field.
  		 *	XXX VLAN over 802.2+SNAP not implemented!
2d966958c   wdenk   Initial revision
973
  		 */
8d353eb86   Joe Hershberger   net: cosmetic: Re...
974
  		eth_proto = ntohs(et802->et_prot);
a3d991bd0   wdenk   Patches by Pantel...
975

594c26f8a   Joe Hershberger   net: cosmetic: Un...
976
  		ip = (struct ip_udp_hdr *)(inpkt + E802_HDR_SIZE);
2d966958c   wdenk   Initial revision
977
  		len -= E802_HDR_SIZE;
a3d991bd0   wdenk   Patches by Pantel...
978

8d353eb86   Joe Hershberger   net: cosmetic: Re...
979
  	} else if (eth_proto != PROT_VLAN) {	/* normal packet */
594c26f8a   Joe Hershberger   net: cosmetic: Un...
980
  		ip = (struct ip_udp_hdr *)(inpkt + ETHER_HDR_SIZE);
2d966958c   wdenk   Initial revision
981
  		len -= ETHER_HDR_SIZE;
a3d991bd0   wdenk   Patches by Pantel...
982
983
  
  	} else {			/* VLAN packet */
c68cca35b   Joe Hershberger   net: cosmetic: Un...
984
985
  		struct vlan_ethernet_hdr *vet =
  			(struct vlan_ethernet_hdr *)et;
a3d991bd0   wdenk   Patches by Pantel...
986

4ef8d53ca   Joe Hershberger   net: Allow filter...
987
988
  		debug_cond(DEBUG_NET_PKT, "VLAN packet received
  ");
0ebf04c60   Robin Getz   minor debug clean...
989

a3d991bd0   wdenk   Patches by Pantel...
990
991
992
993
994
995
  		/* 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...
996
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
997
998
999
1000
1001
1002
1003
  				&& iscdp == 0
  #endif
  				)
  			return;
  
  		cti = ntohs(vet->vet_tag);
  		vlanid = cti & VLAN_IDMASK;
8d353eb86   Joe Hershberger   net: cosmetic: Re...
1004
  		eth_proto = ntohs(vet->vet_type);
a3d991bd0   wdenk   Patches by Pantel...
1005

594c26f8a   Joe Hershberger   net: cosmetic: Un...
1006
  		ip = (struct ip_udp_hdr *)(inpkt + VLAN_ETHER_HDR_SIZE);
a3d991bd0   wdenk   Patches by Pantel...
1007
  		len -= VLAN_ETHER_HDR_SIZE;
2d966958c   wdenk   Initial revision
1008
  	}
4ef8d53ca   Joe Hershberger   net: Allow filter...
1009
1010
  	debug_cond(DEBUG_NET_PKT, "Receive from protocol 0x%x
  ", eth_proto);
2d966958c   wdenk   Initial revision
1011

643d1ab23   Jon Loeliger   net/: Remove obso...
1012
  #if defined(CONFIG_CMD_CDP)
a3d991bd0   wdenk   Patches by Pantel...
1013
  	if (iscdp) {
0b4c5ff4a   Joe Hershberger   net: cosmetic: Re...
1014
  		cdp_receive((uchar *)ip, len);
a3d991bd0   wdenk   Patches by Pantel...
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
  		return;
  	}
  #endif
  
  	if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
  		if (vlanid == VLAN_NONE)
  			vlanid = (mynvlanid & VLAN_IDMASK);
  		/* not matched? */
  		if (vlanid != (myvlanid & VLAN_IDMASK))
  			return;
  	}
8d353eb86   Joe Hershberger   net: cosmetic: Re...
1026
  	switch (eth_proto) {
2d966958c   wdenk   Initial revision
1027
1028
  
  	case PROT_ARP:
d280d3f43   Joe Hershberger   net: Move ARP out...
1029
  		ArpReceive(et, ip, len);
289f932c5   wdenk   * Some Cleanup.
1030
  		break;
2d966958c   wdenk   Initial revision
1031

bf6cb247a   Peter Tyser   rarp: Condtionall...
1032
  #ifdef CONFIG_CMD_RARP
2d966958c   wdenk   Initial revision
1033
  	case PROT_RARP:
8b9c53221   Joe Hershberger   net: Move RARP re...
1034
  		rarp_receive(ip, len);
2d966958c   wdenk   Initial revision
1035
  		break;
bf6cb247a   Peter Tyser   rarp: Condtionall...
1036
  #endif
2d966958c   wdenk   Initial revision
1037
  	case PROT_IP:
4ef8d53ca   Joe Hershberger   net: Allow filter...
1038
1039
  		debug_cond(DEBUG_NET_PKT, "Got IP
  ");
5cfaa4e54   Alessandro Rubini   net: defragment I...
1040
  		/* Before we start poking the header, make sure it is there */
594c26f8a   Joe Hershberger   net: cosmetic: Un...
1041
1042
1043
1044
  		if (len < IP_UDP_HDR_SIZE) {
  			debug("len bad %d < %lu
  ", len,
  				(ulong)IP_UDP_HDR_SIZE);
2d966958c   wdenk   Initial revision
1045
1046
  			return;
  		}
5cfaa4e54   Alessandro Rubini   net: defragment I...
1047
  		/* Check the packet length */
2d966958c   wdenk   Initial revision
1048
  		if (len < ntohs(ip->ip_len)) {
4ef8d53ca   Joe Hershberger   net: Allow filter...
1049
1050
  			debug("len bad %d < %d
  ", len, ntohs(ip->ip_len));
2d966958c   wdenk   Initial revision
1051
1052
1053
  			return;
  		}
  		len = ntohs(ip->ip_len);
4ef8d53ca   Joe Hershberger   net: Allow filter...
1054
1055
1056
  		debug_cond(DEBUG_NET_PKT, "len=%d, v=%02x
  ",
  			len, ip->ip_hl_v & 0xff);
0ebf04c60   Robin Getz   minor debug clean...
1057

5cfaa4e54   Alessandro Rubini   net: defragment I...
1058
  		/* Can't deal with anything except IPv4 */
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1059
  		if ((ip->ip_hl_v & 0xf0) != 0x40)
2d966958c   wdenk   Initial revision
1060
  			return;
5cfaa4e54   Alessandro Rubini   net: defragment I...
1061
  		/* Can't deal with IP options (headers != 20 bytes) */
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1062
  		if ((ip->ip_hl_v & 0x0f) > 0x05)
6b52cfe16   Remy Bohmer   Get rid of annoyi...
1063
  			return;
5cfaa4e54   Alessandro Rubini   net: defragment I...
1064
  		/* Check the Checksum of the header */
c5c59df04   Joe Hershberger   net: cosmetic: Sp...
1065
  		if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE / 2)) {
4ef8d53ca   Joe Hershberger   net: Allow filter...
1066
1067
  			debug("checksum bad
  ");
2d966958c   wdenk   Initial revision
1068
1069
  			return;
  		}
5cfaa4e54   Alessandro Rubini   net: defragment I...
1070
  		/* If it is not for us, ignore it */
8d353eb86   Joe Hershberger   net: cosmetic: Re...
1071
1072
  		dst_ip = NetReadIP(&ip->ip_dst);
  		if (NetOurIP && dst_ip != NetOurIP && dst_ip != 0xFFFFFFFF) {
53a5c424b   David Updegraff   multicast tftp: R...
1073
  #ifdef CONFIG_MCAST_TFTP
8d353eb86   Joe Hershberger   net: cosmetic: Re...
1074
  			if (Mcast_addr != dst_ip)
53a5c424b   David Updegraff   multicast tftp: R...
1075
  #endif
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1076
  				return;
2d966958c   wdenk   Initial revision
1077
  		}
03eb129f8   Luca Ceresoli   NET: pass source ...
1078
1079
  		/* Read source IP address for later use */
  		src_ip = NetReadIP(&ip->ip_src);
2d966958c   wdenk   Initial revision
1080
  		/*
5cfaa4e54   Alessandro Rubini   net: defragment I...
1081
1082
1083
1084
  		 * 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...
1085
1086
  		ip = NetDefragment(ip, &len);
  		if (!ip)
5cfaa4e54   Alessandro Rubini   net: defragment I...
1087
1088
  			return;
  		/*
2d966958c   wdenk   Initial revision
1089
1090
  		 * watch for ICMP host redirects
  		 *
8bde7f776   wdenk   * Code cleanup:
1091
1092
1093
1094
1095
  		 * 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
1096
  		 *
8bde7f776   wdenk   * Code cleanup:
1097
1098
1099
1100
1101
1102
1103
  		 * 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...
1104
1105
1106
1107
  		 *
  		 * 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
1108
1109
  		 */
  		if (ip->ip_p == IPPROTO_ICMP) {
8f79bb17a   Simon Glass   net: tftpput: Mov...
1110
1111
  			receive_icmp(ip, len, src_ip, et);
  			return;
2d966958c   wdenk   Initial revision
1112
1113
1114
  		} else if (ip->ip_p != IPPROTO_UDP) {	/* Only UDP packets */
  			return;
  		}
4ef8d53ca   Joe Hershberger   net: Allow filter...
1115
1116
1117
1118
  		debug_cond(DEBUG_DEV_PKT,
  			"received UDP (to=%pI4, from=%pI4, len=%d)
  ",
  			&dst_ip, &src_ip, len);
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1119
1120
  #ifdef CONFIG_UDP_CHECKSUM
  		if (ip->udp_xsum != 0) {
b2f508075   Wolfgang Denk   Minor code cleanup
1121
  			ulong   xsum;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
  			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
1136
  				ushort sumdata;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1137
1138
1139
1140
1141
1142
  
  				sumdata = *sumptr++;
  				xsum += ntohs(sumdata);
  				sumlen -= 2;
  			}
  			if (sumlen > 0) {
b2f508075   Wolfgang Denk   Minor code cleanup
1143
  				ushort sumdata;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1144
1145
  
  				sumdata = *(unsigned char *) sumptr;
b2f508075   Wolfgang Denk   Minor code cleanup
1146
  				sumdata = (sumdata << 8) & 0xff00;
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1147
1148
1149
  				xsum += sumdata;
  			}
  			while ((xsum >> 16) != 0) {
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1150
1151
  				xsum = (xsum & 0x0000ffff) +
  				       ((xsum >> 16) & 0x0000ffff);
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1152
1153
  			}
  			if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
9b55a2536   Wolfgang Denk   Fix some more pri...
1154
1155
1156
  				printf(" UDP wrong checksum %08lx %08x
  ",
  					xsum, ntohs(ip->udp_xsum));
8534bf9ac   Stefan Roese   Add UPD-Checksum ...
1157
1158
1159
1160
  				return;
  			}
  		}
  #endif
53a5c424b   David Updegraff   multicast tftp: R...
1161

68ceb29e7   wdenk   Add support for c...
1162
  #ifdef CONFIG_NETCONSOLE
594c26f8a   Joe Hershberger   net: cosmetic: Un...
1163
  		nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE,
8cab08e80   Joe Hershberger   net: fix netconso...
1164
  					src_ip,
594c26f8a   Joe Hershberger   net: cosmetic: Un...
1165
1166
1167
  					ntohs(ip->udp_dst),
  					ntohs(ip->udp_src),
  					ntohs(ip->udp_len) - UDP_HDR_SIZE);
68ceb29e7   wdenk   Add support for c...
1168
  #endif
2d966958c   wdenk   Initial revision
1169
1170
1171
  		/*
  		 *	IP header OK.  Pass the packet to the current handler.
  		 */
ece223b52   Joe Hershberger   net: Refactor to ...
1172
1173
1174
1175
1176
  		(*udp_packet_handler)((uchar *)ip + IP_UDP_HDR_SIZE,
  				ntohs(ip->udp_dst),
  				src_ip,
  				ntohs(ip->udp_src),
  				ntohs(ip->udp_len) - UDP_HDR_SIZE);
2d966958c   wdenk   Initial revision
1177
1178
1179
1180
1181
1182
  		break;
  	}
  }
  
  
  /**********************************************************************/
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
1183
  static int net_check_prereq(enum proto_t protocol)
2d966958c   wdenk   Initial revision
1184
1185
  {
  	switch (protocol) {
6e5923851   wdenk   * Cleanup, minor ...
1186
  		/* Fall through */
643d1ab23   Jon Loeliger   net/: Remove obso...
1187
  #if defined(CONFIG_CMD_PING)
73a8b27c5   wdenk   * Add support for...
1188
  	case PING:
6e5923851   wdenk   * Cleanup, minor ...
1189
  		if (NetPingIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1190
1191
  			puts("*** ERROR: ping address not given
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1192
  			return 1;
6e5923851   wdenk   * Cleanup, minor ...
1193
1194
  		}
  		goto common;
73a8b27c5   wdenk   * Add support for...
1195
  #endif
643d1ab23   Jon Loeliger   net/: Remove obso...
1196
  #if defined(CONFIG_CMD_SNTP)
ea287debe   wdenk   * Patch by Masami...
1197
1198
  	case SNTP:
  		if (NetNtpServerIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1199
1200
  			puts("*** ERROR: NTP server address not given
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1201
  			return 1;
ea287debe   wdenk   * Patch by Masami...
1202
1203
1204
  		}
  		goto common;
  #endif
1a32bf418   Robin Getz   Add DNS support
1205
1206
1207
1208
1209
1210
1211
1212
1213
  #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...
1214
  #if defined(CONFIG_CMD_NFS)
cbd8a35c6   wdenk   * Patch by Masami...
1215
1216
  	case NFS:
  #endif
e4bf0c5cf   Simon Glass   net: tftpput: Ren...
1217
  	case TFTPGET:
1fb7cd498   Simon Glass   net: tftpput: imp...
1218
  	case TFTPPUT:
6e5923851   wdenk   * Cleanup, minor ...
1219
  		if (NetServerIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1220
1221
  			puts("*** ERROR: `serverip' not set
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1222
  			return 1;
6e5923851   wdenk   * Cleanup, minor ...
1223
  		}
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1224
1225
1226
  #if	defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
  	defined(CONFIG_CMD_DNS)
  common:
73a8b27c5   wdenk   * Add support for...
1227
  #endif
8b6bbe104   Simon Guinot   netconsole: remov...
1228
  		/* Fall through */
73a8b27c5   wdenk   * Add support for...
1229

8b6bbe104   Simon Guinot   netconsole: remov...
1230
  	case NETCONS:
7a83af07a   Luca Ceresoli   TFTP: add tftpsrv...
1231
  	case TFTPSRV:
6e5923851   wdenk   * Cleanup, minor ...
1232
  		if (NetOurIP == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1233
1234
  			puts("*** ERROR: `ipaddr' not set
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1235
  			return 1;
6e5923851   wdenk   * Cleanup, minor ...
1236
1237
  		}
  		/* Fall through */
2d966958c   wdenk   Initial revision
1238

bf6cb247a   Peter Tyser   rarp: Condtionall...
1239
  #ifdef CONFIG_CMD_RARP
2d966958c   wdenk   Initial revision
1240
  	case RARP:
bf6cb247a   Peter Tyser   rarp: Condtionall...
1241
  #endif
2d966958c   wdenk   Initial revision
1242
  	case BOOTP:
a3d991bd0   wdenk   Patches by Pantel...
1243
  	case CDP:
bf6cb247a   Peter Tyser   rarp: Condtionall...
1244
  	case DHCP:
d22c338e0   Joe Hershberger   net: Add link-loc...
1245
  	case LINKLOCAL:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1246
  		if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1247
  			int num = eth_get_dev_index();
2d966958c   wdenk   Initial revision
1248

6e5923851   wdenk   * Cleanup, minor ...
1249
1250
  			switch (num) {
  			case -1:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1251
1252
  				puts("*** ERROR: No ethernet found.
  ");
92895de97   Luca Ceresoli   net/net.c: cosmet...
1253
  				return 1;
6e5923851   wdenk   * Cleanup, minor ...
1254
  			case 0:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1255
1256
  				puts("*** ERROR: `ethaddr' not set
  ");
2d966958c   wdenk   Initial revision
1257
  				break;
6e5923851   wdenk   * Cleanup, minor ...
1258
  			default:
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1259
1260
  				printf("*** ERROR: `eth%daddr' not set
  ",
2d966958c   wdenk   Initial revision
1261
1262
  					num);
  				break;
6e5923851   wdenk   * Cleanup, minor ...
1263
  			}
2d966958c   wdenk   Initial revision
1264

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1265
  			NetStartAgain();
92895de97   Luca Ceresoli   net/net.c: cosmet...
1266
  			return 2;
6e5923851   wdenk   * Cleanup, minor ...
1267
1268
1269
  		}
  		/* Fall through */
  	default:
92895de97   Luca Ceresoli   net/net.c: cosmet...
1270
  		return 0;
2d966958c   wdenk   Initial revision
1271
  	}
92895de97   Luca Ceresoli   net/net.c: cosmet...
1272
  	return 0;		/* OK */
2d966958c   wdenk   Initial revision
1273
1274
1275
1276
  }
  /**********************************************************************/
  
  int
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1277
  NetCksumOk(uchar *ptr, int len)
2d966958c   wdenk   Initial revision
1278
1279
1280
1281
1282
1283
  {
  	return !((NetCksum(ptr, len) + 1) & 0xfffe);
  }
  
  
  unsigned
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1284
  NetCksum(uchar *ptr, int len)
2d966958c   wdenk   Initial revision
1285
1286
  {
  	ulong	xsum;
9d2a873bd   Stefan Roese   Add I2C support t...
1287
  	ushort *p = (ushort *)ptr;
2d966958c   wdenk   Initial revision
1288
1289
1290
  
  	xsum = 0;
  	while (len-- > 0)
7bc5ee078   Wolfgang Denk   Prepare U-Boot fo...
1291
  		xsum += *p++;
2d966958c   wdenk   Initial revision
1292
1293
  	xsum = (xsum & 0xffff) + (xsum >> 16);
  	xsum = (xsum & 0xffff) + (xsum >> 16);
92895de97   Luca Ceresoli   net/net.c: cosmet...
1294
  	return xsum & 0xffff;
2d966958c   wdenk   Initial revision
1295
  }
a3d991bd0   wdenk   Patches by Pantel...
1296
1297
1298
1299
  int
  NetEthHdrSize(void)
  {
  	ushort myvlanid;
2d966958c   wdenk   Initial revision
1300

a3d991bd0   wdenk   Patches by Pantel...
1301
1302
1303
  	myvlanid = ntohs(NetOurVLAN);
  	if (myvlanid == (ushort)-1)
  		myvlanid = VLAN_NONE;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1304
1305
  	return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE :
  		VLAN_ETHER_HDR_SIZE;
a3d991bd0   wdenk   Patches by Pantel...
1306
1307
1308
  }
  
  int
db288a960   Joe Hershberger   net: Remove volat...
1309
  NetSetEther(uchar *xet, uchar * addr, uint prot)
2d966958c   wdenk   Initial revision
1310
  {
cb487f566   Joe Hershberger   net: cosmetic: Un...
1311
  	struct ethernet_hdr *et = (struct ethernet_hdr *)xet;
a3d991bd0   wdenk   Patches by Pantel...
1312
1313
1314
1315
1316
  	ushort myvlanid;
  
  	myvlanid = ntohs(NetOurVLAN);
  	if (myvlanid == (ushort)-1)
  		myvlanid = VLAN_NONE;
2d966958c   wdenk   Initial revision
1317

4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1318
1319
  	memcpy(et->et_dest, addr, 6);
  	memcpy(et->et_src, NetOurEther, 6);
a3d991bd0   wdenk   Patches by Pantel...
1320
  	if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
c819abeef   Luca Ceresoli   net/net.c: cosmet...
1321
  		et->et_protlen = htons(prot);
a3d991bd0   wdenk   Patches by Pantel...
1322
1323
  		return ETHER_HDR_SIZE;
  	} else {
c68cca35b   Joe Hershberger   net: cosmetic: Un...
1324
1325
  		struct vlan_ethernet_hdr *vet =
  			(struct vlan_ethernet_hdr *)xet;
2d966958c   wdenk   Initial revision
1326

a3d991bd0   wdenk   Patches by Pantel...
1327
1328
1329
1330
1331
1332
  		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
1333

e71110158   Joe Hershberger   net: Add net_upda...
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
  int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot)
  {
  	ushort protlen;
  
  	memcpy(et->et_dest, addr, 6);
  	memcpy(et->et_src, NetOurEther, 6);
  	protlen = ntohs(et->et_protlen);
  	if (protlen == PROT_VLAN) {
  		struct vlan_ethernet_hdr *vet =
  			(struct vlan_ethernet_hdr *)et;
  		vet->vet_type = htons(prot);
  		return VLAN_ETHER_HDR_SIZE;
  	} else if (protlen > 1514) {
  		et->et_protlen = htons(prot);
  		return ETHER_HDR_SIZE;
  	} else {
  		/* 802.2 + SNAP */
  		struct e802_hdr *et802 = (struct e802_hdr *)et;
  		et802->et_prot = htons(prot);
  		return E802_HDR_SIZE;
  	}
  }
4b11c9166   Joe Hershberger   net: Refactor IP,...
1356
  void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source)
2d966958c   wdenk   Initial revision
1357
  {
4b11c9166   Joe Hershberger   net: Refactor IP,...
1358
  	struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
2d966958c   wdenk   Initial revision
1359
1360
  
  	/*
4b11c9166   Joe Hershberger   net: Refactor IP,...
1361
  	 *	Construct an IP header.
2d966958c   wdenk   Initial revision
1362
  	 */
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1363
1364
  	/* IP_HDR_SIZE / 4 (not including UDP) */
  	ip->ip_hl_v  = 0x45;
2d966958c   wdenk   Initial revision
1365
  	ip->ip_tos   = 0;
4b11c9166   Joe Hershberger   net: Refactor IP,...
1366
  	ip->ip_len   = htons(IP_HDR_SIZE);
2d966958c   wdenk   Initial revision
1367
  	ip->ip_id    = htons(NetIPID++);
e0c07b868   Peter Tyser   net: Define IP fl...
1368
  	ip->ip_off   = htons(IP_FLAGS_DFRAG);	/* Don't fragment */
2d966958c   wdenk   Initial revision
1369
  	ip->ip_ttl   = 255;
2d966958c   wdenk   Initial revision
1370
  	ip->ip_sum   = 0;
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1371
  	/* already in network byte order */
4b11c9166   Joe Hershberger   net: Refactor IP,...
1372
1373
  	NetCopyIP((void *)&ip->ip_src, &source);
  	/* already in network byte order */
6b147d113   Luca Ceresoli   net/net.c: cosmet...
1374
  	NetCopyIP((void *)&ip->ip_dst, &dest);
4b11c9166   Joe Hershberger   net: Refactor IP,...
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
  }
  
  void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport, int sport,
  			int len)
  {
  	struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
  
  	/*
  	 *	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)
  		pkt[IP_UDP_HDR_SIZE + len] = 0;
  
  	net_set_ip_header(pkt, dest, NetOurIP);
  	ip->ip_len   = htons(IP_UDP_HDR_SIZE + len);
  	ip->ip_p     = IPPROTO_UDP;
  	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1);
2d966958c   wdenk   Initial revision
1394
1395
  	ip->udp_src  = htons(sport);
  	ip->udp_dst  = htons(dport);
594c26f8a   Joe Hershberger   net: cosmetic: Un...
1396
  	ip->udp_len  = htons(UDP_HDR_SIZE + len);
2d966958c   wdenk   Initial revision
1397
  	ip->udp_xsum = 0;
2d966958c   wdenk   Initial revision
1398
  }
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1399
  void copy_filename(char *dst, const char *src, int size)
2d966958c   wdenk   Initial revision
1400
1401
1402
1403
1404
  {
  	if (*src && (*src == '"')) {
  		++src;
  		--size;
  	}
d3c65b015   Luca Ceresoli   net/net.c: cosmet...
1405
  	while ((--size > 0) && *src && (*src != '"'))
2d966958c   wdenk   Initial revision
1406
  		*dst++ = *src++;
2d966958c   wdenk   Initial revision
1407
1408
  	*dst = '\0';
  }
3e38e429f   Luca Ceresoli   net/net.c: cosmet...
1409
1410
1411
  #if	defined(CONFIG_CMD_NFS)		|| \
  	defined(CONFIG_CMD_SNTP)	|| \
  	defined(CONFIG_CMD_DNS)
1a32bf418   Robin Getz   Add DNS support
1412
  /*
9739946cc   Robin Getz   ./net/net.c - mak...
1413
1414
1415
   * 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
1416
1417
1418
   */
  unsigned int random_port(void)
  {
9739946cc   Robin Getz   ./net/net.c - mak...
1419
  	return 1024 + (get_timer(0) % 0x4000);
1a32bf418   Robin Getz   Add DNS support
1420
1421
  }
  #endif
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1422
  void ip_to_string(IPaddr_t x, char *s)
2d966958c   wdenk   Initial revision
1423
  {
4f63acd06   Luca Ceresoli   net/net.c: cosmet...
1424
1425
1426
1427
1428
  	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 ...
1429
  	);
2d966958c   wdenk   Initial revision
1430
  }
a3d991bd0   wdenk   Patches by Pantel...
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
  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...
1443
  ushort string_to_VLAN(const char *s)
a3d991bd0   wdenk   Patches by Pantel...
1444
1445
1446
1447
  {
  	ushort id;
  
  	if (s == NULL)
b9711de10   wdenk   * Patch by John K...
1448
  		return htons(VLAN_NONE);
a3d991bd0   wdenk   Patches by Pantel...
1449
1450
1451
1452
1453
  
  	if (*s < '0' || *s > '9')
  		id = VLAN_NONE;
  	else
  		id = (ushort)simple_strtoul(s, NULL, 10);
b9711de10   wdenk   * Patch by John K...
1454
  	return htons(id);
a3d991bd0   wdenk   Patches by Pantel...
1455
  }
a3d991bd0   wdenk   Patches by Pantel...
1456
1457
  ushort getenv_VLAN(char *var)
  {
92895de97   Luca Ceresoli   net/net.c: cosmet...
1458
  	return string_to_VLAN(getenv(var));
a3d991bd0   wdenk   Patches by Pantel...
1459
  }