Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
2d966958
U
U-Boot.Mirror
项目概览
OS
/
U-Boot.Mirror
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
U-Boot.Mirror
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2d966958
编写于
10月 31, 2002
作者:
W
wdenk
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Initial revision
上级
fef08ee8
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
1111 addition
and
0 deletion
+1111
-0
include/net.h
include/net.h
+358
-0
net/net.c
net/net.c
+753
-0
未找到文件。
include/net.h
0 → 100644
浏览文件 @
2d966958
/*
* LiMon Monitor (LiMon) - Network.
*
* Copyright 1994 - 2000 Neil Russell.
* (See License)
*
*
* History
* 9/16/00 bor adapted to TQM823L/STK8xxL board, RARP/TFTP boot added
*/
#ifndef __NET_H__
#define __NET_H__
#if !defined(CONFIG_NET_MULTI) && defined(CONFIG_8xx)
#include <commproc.h>
#if defined(FEC_ENET) || defined(SCC_ENET)
#define CONFIG_NET_MULTI
#endif
#endif
#include <asm/byteorder.h>
/* for nton* / ntoh* stuff */
/*
* The number of receive packet buffers, and the required packet buffer
* alignment in memory.
*
*/
#define PKTBUFSRX 4
#define PKTALIGN 32
typedef
ulong
IPaddr_t
;
/*
* The current receive packet handler. Called with a pointer to the
* application packet, and a protocol type (PORT_BOOTPC or PORT_TFTP).
* All other packets are dealt with without calling the handler.
*/
typedef
void
rxhand_f
(
uchar
*
,
unsigned
,
unsigned
,
unsigned
);
/*
* A timeout handler. Called after time interval has expired.
*/
typedef
void
thand_f
(
void
);
#ifdef CONFIG_NET_MULTI
#define NAMESIZE 16
enum
eth_state_t
{
ETH_STATE_INIT
,
ETH_STATE_PASSIVE
,
ETH_STATE_ACTIVE
};
struct
eth_device
{
char
name
[
NAMESIZE
];
unsigned
char
enetaddr
[
6
];
int
iobase
;
int
state
;
int
(
*
init
)
(
struct
eth_device
*
,
bd_t
*
);
int
(
*
send
)
(
struct
eth_device
*
,
volatile
void
*
pachet
,
int
length
);
int
(
*
recv
)
(
struct
eth_device
*
);
void
(
*
halt
)
(
struct
eth_device
*
);
struct
eth_device
*
next
;
void
*
priv
;
};
extern
int
eth_initialize
(
bd_t
*
bis
);
/* Initialize network subsystem */
extern
int
eth_register
(
struct
eth_device
*
dev
);
/* Register network device */
extern
void
eth_try_another
(
int
first_restart
);
/* Change the device */
extern
struct
eth_device
*
eth_get_dev
(
void
);
/* get the current device MAC */
extern
void
eth_set_enetaddr
(
int
num
,
char
*
a
);
/* Set new MAC address */
#endif
extern
int
eth_init
(
bd_t
*
bis
);
/* Initialize the device */
extern
int
eth_send
(
volatile
void
*
packet
,
int
length
);
/* Send a packet */
extern
int
eth_rx
(
void
);
/* Check for received packets */
extern
void
eth_halt
(
void
);
/* stop SCC */
/**********************************************************************/
/*
* Protocol headers.
*/
/*
* Ethernet header
*/
typedef
struct
{
uchar
et_dest
[
6
];
/* Destination node */
uchar
et_src
[
6
];
/* Source node */
ushort
et_protlen
;
/* Protocol or length */
uchar
et_dsap
;
/* 802 DSAP */
uchar
et_ssap
;
/* 802 SSAP */
uchar
et_ctl
;
/* 802 control */
uchar
et_snap1
;
/* SNAP */
uchar
et_snap2
;
uchar
et_snap3
;
ushort
et_prot
;
/* 802 protocol */
}
Ethernet_t
;
#define ETHER_HDR_SIZE 14
/* Ethernet header size */
#define E802_HDR_SIZE 22
/* 802 ethernet header size */
#define PROT_IP 0x0800
/* IP protocol */
#define PROT_ARP 0x0806
/* IP ARP protocol */
#define PROT_RARP 0x8035
/* IP ARP protocol */
#define IPPROTO_ICMP 1
/* Internet Control Message Protocol */
#define IPPROTO_UDP 17
/* User Datagram Protocol */
/*
* Internet Protocol (IP) header.
*/
typedef
struct
{
uchar
ip_hl_v
;
/* header length and version */
uchar
ip_tos
;
/* type of service */
ushort
ip_len
;
/* total length */
ushort
ip_id
;
/* identification */
ushort
ip_off
;
/* fragment offset field */
uchar
ip_ttl
;
/* time to live */
uchar
ip_p
;
/* protocol */
ushort
ip_sum
;
/* checksum */
IPaddr_t
ip_src
;
/* Source IP address */
IPaddr_t
ip_dst
;
/* Destination IP address */
ushort
udp_src
;
/* UDP source port */
ushort
udp_dst
;
/* UDP destination port */
ushort
udp_len
;
/* Length of UDP packet */
ushort
udp_xsum
;
/* Checksum */
}
IP_t
;
#define IP_HDR_SIZE_NO_UDP (sizeof (IP_t) - 8)
#define IP_HDR_SIZE (sizeof (IP_t))
/*
* Address Resolution Protocol (ARP) header.
*/
typedef
struct
{
ushort
ar_hrd
;
/* Format of hardware address */
# define ARP_ETHER 1
/* Ethernet hardware address */
ushort
ar_pro
;
/* Format of protocol address */
uchar
ar_hln
;
/* Length of hardware address */
uchar
ar_pln
;
/* Length of protocol address */
ushort
ar_op
;
/* Operation */
# define ARPOP_REQUEST 1
/* Request to resolve address */
# define ARPOP_REPLY 2
/* Response to previous request */
# define RARPOP_REQUEST 3
/* Request to resolve address */
# define RARPOP_REPLY 4
/* Response to previous request */
/*
* The remaining fields are variable in size, according to
* the sizes above, and are defined as appropriate for
* specific hardware/protocol combinations.
*/
uchar
ar_data
[
0
];
#if 0
uchar ar_sha[]; /* Sender hardware address */
uchar ar_spa[]; /* Sender protocol address */
uchar ar_tha[]; /* Target hardware address */
uchar ar_tpa[]; /* Target protocol address */
#endif /* 0 */
}
ARP_t
;
#define ARP_HDR_SIZE (8+20)
/* Size assuming ethernet */
/*
* ICMP stuff (just enough to handle (host) redirect messages)
*/
#define ICMP_REDIRECT 5
/* Redirect (change route) */
/* Codes for REDIRECT. */
#define ICMP_REDIR_NET 0
/* Redirect Net */
#define ICMP_REDIR_HOST 1
/* Redirect Host */
typedef
struct
icmphdr
{
uchar
type
;
uchar
code
;
ushort
checksum
;
union
{
struct
{
ushort
id
;
ushort
sequence
;
}
echo
;
ulong
gateway
;
struct
{
ushort
__unused
;
ushort
mtu
;
}
frag
;
}
un
;
}
ICMP_t
;
/*
* Maximum packet size; used to allocate packet storage.
* TFTP packets can be 524 bytes + IP header + ethernet header.
* Lets be conservative, and go for 38 * 16. (Must also be
* a multiple of 32 bytes).
*/
/*
* AS.HARNOIS : Better to set PKTSIZE to maximum size because
* traffic type is not always controlled
* maximum packet size = 1518
* maximum packet size and multiple of 32 bytes = 1536
*/
#define PKTSIZE 1518
#define PKTSIZE_ALIGN 1536
/*#define PKTSIZE 608*/
/*
* Maximum receive ring size; that is, the number of packets
* we can buffer before overflow happens. Basically, this just
* needs to be enough to prevent a packet being discarded while
* we are processing the previous one.
*/
#define RINGSZ 4
#define RINGSZ_LOG2 2
/**********************************************************************/
/*
* Globals.
*
* Note:
*
* All variables of type IPaddr_t are stored in NETWORK byte order
* (big endian).
*/
/* net.c */
/** BOOTP EXTENTIONS **/
extern
IPaddr_t
NetOurGatewayIP
;
/* Our gateway IP addresse */
extern
IPaddr_t
NetOurSubnetMask
;
/* Our subnet mask (0 = unknown)*/
extern
IPaddr_t
NetOurDNSIP
;
/* Our Domain Name Server (0 = unknown)*/
extern
char
NetOurNISDomain
[
32
];
/* Our NIS domain */
extern
char
NetOurHostName
[
32
];
/* Our hostname */
extern
char
NetOurRootPath
[
64
];
/* Our root path */
extern
ushort
NetBootFileSize
;
/* Our boot file size in blocks */
/** END OF BOOTP EXTENTIONS **/
extern
ulong
NetBootFileXferSize
;
/* size of bootfile in bytes */
extern
uchar
NetOurEther
[
6
];
/* Our ethernet address */
extern
uchar
NetServerEther
[
6
];
/* Boot server enet address */
extern
IPaddr_t
NetOurIP
;
/* Our IP addr (0 = unknown) */
extern
IPaddr_t
NetServerIP
;
/* Server IP addr (0 = unknown) */
extern
volatile
uchar
*
NetTxPacket
;
/* THE transmit packet */
extern
volatile
uchar
*
NetRxPackets
[
PKTBUFSRX
];
/* Receive packets */
extern
volatile
uchar
*
NetRxPkt
;
/* Current receive packet */
extern
int
NetRxPktLen
;
/* Current rx packet length */
extern
unsigned
NetIPID
;
/* IP ID (counting) */
extern
uchar
NetBcastAddr
[
6
];
/* Ethernet boardcast address */
extern
int
NetState
;
/* Network loop state */
#define NETLOOP_CONTINUE 1
#define NETLOOP_RESTART 2
#define NETLOOP_SUCCESS 3
#define NETLOOP_FAIL 4
#ifdef CONFIG_NET_MULTI
extern
int
NetRestartWrap
;
/* Tried all network devices */
#endif
typedef
enum
{
BOOTP
,
RARP
,
ARP
,
TFTP
,
DHCP
}
proto_t
;
/* from net/net.c */
extern
char
BootFile
[
128
];
/* Boot File name */
/* Initialize the network adapter */
extern
int
NetLoop
(
proto_t
);
/* Shutdown adapters and cleanup */
extern
void
NetStop
(
void
);
/* Load failed. Start again. */
extern
void
NetStartAgain
(
void
);
/* Set ethernet header */
extern
void
NetSetEther
(
volatile
uchar
*
,
uchar
*
,
uint
);
/* Set IP header */
extern
void
NetSetIP
(
volatile
uchar
*
,
IPaddr_t
,
int
,
int
,
int
);
/* Checksum */
extern
int
NetCksumOk
(
uchar
*
,
int
);
/* Return true if cksum OK */
extern
uint
NetCksum
(
uchar
*
,
int
);
/* Calculate the checksum */
/* Set callbacks */
extern
void
NetSetHandler
(
rxhand_f
*
);
/* Set RX packet handler */
extern
void
NetSetTimeout
(
int
,
thand_f
*
);
/* Set timeout handler */
/* Transmit "NetTxPacket" */
extern
void
NetSendPacket
(
volatile
uchar
*
,
int
);
/* Processes a received packet */
extern
void
NetReceive
(
volatile
uchar
*
,
int
);
/* Print an IP address on the console */
extern
void
print_IPaddr
(
IPaddr_t
);
/*
* The following functions are a bit ugly, but necessary to deal with
* alignment restrictions on ARM.
*
* We're using inline functions, which had the smallest memory
* footprint in our tests.
*/
/* return IP *in network byteorder* */
static
inline
IPaddr_t
NetReadIP
(
void
*
from
)
{
IPaddr_t
ip
;
memcpy
((
void
*
)
&
ip
,
from
,
sizeof
(
ip
));
return
ip
;
}
/* return ulong *in network byteorder* */
static
inline
ulong
NetReadLong
(
ulong
*
from
)
{
ulong
l
;
memcpy
((
void
*
)
&
l
,
(
void
*
)
from
,
sizeof
(
l
));
return
l
;
}
/* write IP *in network byteorder* */
static
inline
void
NetWriteIP
(
void
*
to
,
IPaddr_t
ip
)
{
memcpy
(
to
,
(
void
*
)
&
ip
,
sizeof
(
ip
));
}
/* copy IP */
static
inline
void
NetCopyIP
(
void
*
to
,
void
*
from
)
{
memcpy
(
to
,
from
,
sizeof
(
IPaddr_t
));
}
/* copy ulong */
static
inline
void
NetCopyLong
(
ulong
*
to
,
ulong
*
from
)
{
memcpy
((
void
*
)
to
,
(
void
*
)
from
,
sizeof
(
ulong
));
}
/* Convert an IP address to a string */
extern
void
ip_to_string
(
IPaddr_t
x
,
char
*
s
);
/* read an IP address from a environment variable */
extern
IPaddr_t
getenv_IPaddr
(
char
*
);
/* copy a filename (allow for "..." notation, limit length) */
extern
void
copy_filename
(
uchar
*
dst
,
uchar
*
src
,
int
size
);
/**********************************************************************/
#endif
/* __NET_H__ */
net/net.c
0 → 100644
浏览文件 @
2d966958
/*
* 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:
*
* Prerequisites: - own ethernet address
* We want: - IP, Netmask, ServerIP, Gateway IP
* - bootfilename, lease time
* Next step: - TFTP
*
* 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
*/
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <net.h>
#include "bootp.h"
#include "tftp.h"
#include "rarp.h"
#include "arp.h"
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if 0
#define ET_DEBUG
#endif
/** BOOTP EXTENTIONS **/
IPaddr_t
NetOurSubnetMask
=
0
;
/* Our subnet mask (0=unknown) */
IPaddr_t
NetOurGatewayIP
=
0
;
/* Our gateways IP address */
IPaddr_t
NetOurDNSIP
=
0
;
/* Our DNS IP address */
char
NetOurNISDomain
[
32
]
=
{
0
,};
/* Our NIS domain */
char
NetOurHostName
[
32
]
=
{
0
,};
/* Our hostname */
char
NetOurRootPath
[
64
]
=
{
0
,};
/* Our bootpath */
ushort
NetBootFileSize
=
0
;
/* Our bootfile size in blocks */
/** END OF BOOTP EXTENTIONS **/
ulong
NetBootFileXferSize
;
/* The actual transferred size of the bootfile (in bytes) */
uchar
NetOurEther
[
6
];
/* Our ethernet address */
uchar
NetServerEther
[
6
]
=
/* Boot server enet address */
{
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
};
IPaddr_t
NetOurIP
;
/* Our IP addr (0 = unknown) */
IPaddr_t
NetServerIP
;
/* Our IP addr (0 = unknown) */
volatile
uchar
*
NetRxPkt
;
/* Current receive packet */
int
NetRxPktLen
;
/* Current rx packet length */
unsigned
NetIPID
;
/* IP packet ID */
uchar
NetBcastAddr
[
6
]
=
/* Ethernet bcast address */
{
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
};
int
NetState
;
/* Network loop state */
#ifdef CONFIG_NET_MULTI
int
NetRestartWrap
=
0
;
/* Tried all network devices */
static
int
NetRestarted
=
0
;
/* Network loop restarted */
static
int
NetDevExists
=
0
;
/* At least one device configured */
#endif
char
BootFile
[
128
];
/* Boot File name */
volatile
uchar
PktBuf
[(
PKTBUFSRX
+
1
)
*
PKTSIZE_ALIGN
+
PKTALIGN
];
volatile
uchar
*
NetRxPackets
[
PKTBUFSRX
];
/* Receive packets */
static
rxhand_f
*
packetHandler
;
/* Current RX packet handler */
static
thand_f
*
timeHandler
;
/* Current timeout handler */
static
ulong
timeValue
;
/* Current timeout value */
volatile
uchar
*
NetTxPacket
=
0
;
/* THE transmit packet */
static
int
net_check_prereq
(
proto_t
protocol
);
/**********************************************************************/
/*
* Main network processing loop.
*/
int
NetLoop
(
proto_t
protocol
)
{
DECLARE_GLOBAL_DATA_PTR
;
bd_t
*
bd
=
gd
->
bd
;
#ifdef CONFIG_NET_MULTI
NetRestarted
=
0
;
NetDevExists
=
0
;
#endif
if
(
!
NetTxPacket
)
{
int
i
;
/*
* Setup packet buffers, aligned correctly.
*/
NetTxPacket
=
&
PktBuf
[
0
]
+
(
PKTALIGN
-
1
);
NetTxPacket
-=
(
ulong
)
NetTxPacket
%
PKTALIGN
;
for
(
i
=
0
;
i
<
PKTBUFSRX
;
i
++
)
{
NetRxPackets
[
i
]
=
NetTxPacket
+
(
i
+
1
)
*
PKTSIZE_ALIGN
;
}
}
eth_halt
();
eth_init
(
bd
);
restart:
#ifdef CONFIG_NET_MULTI
memcpy
(
NetOurEther
,
eth_get_dev
()
->
enetaddr
,
6
);
#else
memcpy
(
NetOurEther
,
bd
->
bi_enetaddr
,
6
);
#endif
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.
*/
switch
(
protocol
)
{
case
TFTP
:
NetCopyIP
(
&
NetOurIP
,
&
bd
->
bi_ip_addr
);
NetServerIP
=
getenv_IPaddr
(
"serverip"
);
NetOurGatewayIP
=
getenv_IPaddr
(
"gatewayip"
);
NetOurSubnetMask
=
getenv_IPaddr
(
"netmask"
);
break
;
case
BOOTP
:
case
RARP
:
/*
* initialize our IP addr to 0 in order to accept ANY
* IP addr assigned to us by the BOOTP / RARP server
*/
NetOurIP
=
0
;
NetServerIP
=
0
;
break
;
default:
break
;
}
switch
(
net_check_prereq
(
protocol
))
{
case
1
:
/* network not configured */
return
0
;
#ifdef CONFIG_NET_MULTI
case
2
:
/* network device not configured */
break
;
#endif
/* CONFIG_NET_MULTI */
case
0
:
#ifdef CONFIG_NET_MULTI
NetDevExists
=
1
;
#endif
switch
(
protocol
)
{
case
TFTP
:
/* always use ARP to get server ethernet address */
ArpTry
=
0
;
ArpRequest
();
break
;
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
case
DHCP
:
/* Start with a clean slate... */
NetOurIP
=
0
;
NetServerIP
=
0
;
DhcpRequest
();
/* Basically same as BOOTP */
break
;
#endif
/* CFG_CMD_DHCP */
case
BOOTP
:
BootpTry
=
0
;
BootpRequest
();
break
;
case
RARP
:
RarpTry
=
0
;
RarpRequest
();
break
;
default:
break
;
}
NetBootFileXferSize
=
0
;
break
;
}
/*
* Main packet reception loop. Loop receiving packets until
* someone sets `NetQuit'.
*/
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.
*/
eth_rx
();
/*
* Abort if ctrl-c was pressed.
*/
if
(
ctrlc
())
{
eth_halt
();
printf
(
"
\n
Abort
\n
"
);
return
0
;
}
/*
* Check for a timeout, and run the timeout handler
* if we have one.
*/
if
(
timeHandler
&&
(
get_timer
(
0
)
>
timeValue
))
{
thand_f
*
x
;
x
=
timeHandler
;
timeHandler
=
(
thand_f
*
)
0
;
(
*
x
)();
}
switch
(
NetState
)
{
case
NETLOOP_RESTART
:
#ifdef CONFIG_NET_MULTI
NetRestarted
=
1
;
#endif
goto
restart
;
case
NETLOOP_SUCCESS
:
if
(
NetBootFileXferSize
>
0
)
{
char
buf
[
10
];
printf
(
"Bytes transferred = %ld (%lx hex)
\n
"
,
NetBootFileXferSize
,
NetBootFileXferSize
);
sprintf
(
buf
,
"%lx"
,
NetBootFileXferSize
);
setenv
(
"filesize"
,
buf
);
}
eth_halt
();
return
NetBootFileXferSize
;
case
NETLOOP_FAIL
:
return
0
;
}
}
}
/**********************************************************************/
static
void
startAgainTimeout
(
void
)
{
NetState
=
NETLOOP_RESTART
;
}
static
void
startAgainHandler
(
uchar
*
pkt
,
unsigned
dest
,
unsigned
src
,
unsigned
len
)
{
/* Totally ignore the packet */
}
void
NetStartAgain
(
void
)
{
#ifndef CONFIG_NET_MULTI
NetSetTimeout
(
10
*
CFG_HZ
,
startAgainTimeout
);
NetSetHandler
(
startAgainHandler
);
#else
DECLARE_GLOBAL_DATA_PTR
;
eth_halt
();
eth_try_another
(
!
NetRestarted
);
eth_init
(
gd
->
bd
);
if
(
NetRestartWrap
)
{
NetRestartWrap
=
0
;
if
(
NetDevExists
)
{
NetSetTimeout
(
10
*
CFG_HZ
,
startAgainTimeout
);
NetSetHandler
(
startAgainHandler
);
}
else
{
NetState
=
NETLOOP_FAIL
;
}
}
else
{
NetState
=
NETLOOP_RESTART
;
}
#endif
}
/**********************************************************************/
/*
* Miscelaneous bits.
*/
void
NetSetHandler
(
rxhand_f
*
f
)
{
packetHandler
=
f
;
}
void
NetSetTimeout
(
int
iv
,
thand_f
*
f
)
{
if
(
iv
==
0
)
{
timeHandler
=
(
thand_f
*
)
0
;
}
else
{
timeHandler
=
f
;
timeValue
=
get_timer
(
0
)
+
iv
;
}
}
void
NetSendPacket
(
volatile
uchar
*
pkt
,
int
len
)
{
(
void
)
eth_send
(
pkt
,
len
);
}
void
NetReceive
(
volatile
uchar
*
pkt
,
int
len
)
{
Ethernet_t
*
et
;
IP_t
*
ip
;
ARP_t
*
arp
;
IPaddr_t
tmp
;
int
x
;
NetRxPkt
=
pkt
;
NetRxPktLen
=
len
;
et
=
(
Ethernet_t
*
)
pkt
;
x
=
ntohs
(
et
->
et_protlen
);
if
(
x
<
1514
)
{
/*
* Got a 802 packet. Check the other protocol field.
*/
x
=
ntohs
(
et
->
et_prot
);
ip
=
(
IP_t
*
)(
pkt
+
E802_HDR_SIZE
);
len
-=
E802_HDR_SIZE
;
}
else
{
ip
=
(
IP_t
*
)(
pkt
+
ETHER_HDR_SIZE
);
len
-=
ETHER_HDR_SIZE
;
}
#ifdef ET_DEBUG
printf
(
"Receive from protocol 0x%x
\n
"
,
x
);
#endif
switch
(
x
)
{
case
PROT_ARP
:
/*
* We have to deal with two types of ARP packets:
* - 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
*/
#ifdef ET_DEBUG
printf
(
"Got ARP
\n
"
);
#endif
arp
=
(
ARP_t
*
)
ip
;
if
(
len
<
ARP_HDR_SIZE
)
{
printf
(
"bad length %d < %d
\n
"
,
len
,
ARP_HDR_SIZE
);
return
;
}
if
(
ntohs
(
arp
->
ar_hrd
)
!=
ARP_ETHER
)
{
return
;
}
if
(
ntohs
(
arp
->
ar_pro
)
!=
PROT_IP
)
{
return
;
}
if
(
arp
->
ar_hln
!=
6
)
{
return
;
}
if
(
arp
->
ar_pln
!=
4
)
{
return
;
}
if
(
NetOurIP
==
0
)
{
return
;
}
if
(
NetReadIP
(
&
arp
->
ar_data
[
16
])
!=
NetOurIP
)
{
return
;
}
switch
(
ntohs
(
arp
->
ar_op
))
{
case
ARPOP_REQUEST
:
/* reply with our IP address */
#ifdef ET_DEBUG
printf
(
"Got ARP REQUEST, return our IP
\n
"
);
#endif
NetSetEther
((
uchar
*
)
et
,
et
->
et_src
,
PROT_ARP
);
arp
->
ar_op
=
htons
(
ARPOP_REPLY
);
memcpy
(
&
arp
->
ar_data
[
10
],
&
arp
->
ar_data
[
0
],
6
);
NetCopyIP
(
&
arp
->
ar_data
[
16
],
&
arp
->
ar_data
[
6
]);
memcpy
(
&
arp
->
ar_data
[
0
],
NetOurEther
,
6
);
NetCopyIP
(
&
arp
->
ar_data
[
6
],
&
NetOurIP
);
NetSendPacket
((
uchar
*
)
et
,((
uchar
*
)
arp
-
pkt
)
+
ARP_HDR_SIZE
);
return
;
case
ARPOP_REPLY
:
/* set TFTP server eth addr */
#ifdef ET_DEBUG
printf
(
"Got ARP REPLY, set server/gtwy eth addr
\n
"
);
#endif
memcpy
(
NetServerEther
,
&
arp
->
ar_data
[
0
],
6
);
(
*
packetHandler
)(
0
,
0
,
0
,
0
);
/* start TFTP */
return
;
default:
#ifdef ET_DEBUG
printf
(
"Unexpected ARP opcode 0x%x
\n
"
,
ntohs
(
arp
->
ar_op
));
#endif
return
;
}
case
PROT_RARP
:
#ifdef ET_DEBUG
printf
(
"Got RARP
\n
"
);
#endif
arp
=
(
ARP_t
*
)
ip
;
if
(
len
<
ARP_HDR_SIZE
)
{
printf
(
"bad length %d < %d
\n
"
,
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
))
{
printf
(
"invalid RARP header
\n
"
);
}
else
{
NetCopyIP
(
&
NetOurIP
,
&
arp
->
ar_data
[
16
]);
NetCopyIP
(
&
NetServerIP
,
&
arp
->
ar_data
[
6
]);
memcpy
(
NetServerEther
,
&
arp
->
ar_data
[
0
],
6
);
(
*
packetHandler
)(
0
,
0
,
0
,
0
);
}
break
;
case
PROT_IP
:
#ifdef ET_DEBUG
printf
(
"Got IP
\n
"
);
#endif
if
(
len
<
IP_HDR_SIZE
)
{
debug
(
"len bad %d < %d
\n
"
,
len
,
IP_HDR_SIZE
);
return
;
}
if
(
len
<
ntohs
(
ip
->
ip_len
))
{
printf
(
"len bad %d < %d
\n
"
,
len
,
ntohs
(
ip
->
ip_len
));
return
;
}
len
=
ntohs
(
ip
->
ip_len
);
#ifdef ET_DEBUG
printf
(
"len=%d, v=%02x
\n
"
,
len
,
ip
->
ip_hl_v
&
0xff
);
#endif
if
((
ip
->
ip_hl_v
&
0xf0
)
!=
0x40
)
{
return
;
}
if
(
ip
->
ip_off
&
htons
(
0x1fff
))
{
/* Can't deal w/ fragments */
return
;
}
if
(
!
NetCksumOk
((
uchar
*
)
ip
,
IP_HDR_SIZE_NO_UDP
/
2
))
{
printf
(
"checksum bad
\n
"
);
return
;
}
tmp
=
NetReadIP
(
&
ip
->
ip_dst
);
if
(
NetOurIP
&&
tmp
!=
NetOurIP
&&
tmp
!=
0xFFFFFFFF
)
{
return
;
}
/*
* watch for ICMP host redirects
*
* 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 :-)
*
* 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.
*/
if
(
ip
->
ip_p
==
IPPROTO_ICMP
)
{
ICMP_t
*
icmph
=
(
ICMP_t
*
)
&
(
ip
->
udp_src
);
if
(
icmph
->
type
!=
ICMP_REDIRECT
)
return
;
if
(
icmph
->
code
!=
ICMP_REDIR_HOST
)
return
;
puts
(
" ICMP Host Redirect to "
);
print_IPaddr
(
icmph
->
un
.
gateway
);
putc
(
' '
);
}
else
if
(
ip
->
ip_p
!=
IPPROTO_UDP
)
{
/* Only UDP packets */
return
;
}
/*
* IP header OK. Pass the packet to the current handler.
*/
(
*
packetHandler
)((
uchar
*
)
ip
+
IP_HDR_SIZE
,
ntohs
(
ip
->
udp_dst
),
ntohs
(
ip
->
udp_src
),
ntohs
(
ip
->
udp_len
)
-
8
);
break
;
}
}
/**********************************************************************/
static
int
net_check_prereq
(
proto_t
protocol
)
{
switch
(
protocol
)
{
case
ARP
:
/* nothing to do */
break
;
case
TFTP
:
if
(
NetServerIP
==
0
)
{
puts
(
"*** ERROR: `serverip' not set
\n
"
);
return
(
1
);
}
if
(
NetOurIP
==
0
)
{
puts
(
"*** ERROR: `ipaddr' not set
\n
"
);
return
(
1
);
}
/* Fall through */
case
DHCP
:
case
RARP
:
case
BOOTP
:
if
(
memcmp
(
NetOurEther
,
"
\0\0\0\0\0\0
"
,
6
)
==
0
)
{
#ifdef CONFIG_NET_MULTI
extern
int
eth_get_dev_index
(
void
);
int
num
=
eth_get_dev_index
();
switch
(
num
)
{
case
-
1
:
puts
(
"*** ERROR: No ethernet found.
\n
"
);
return
(
1
);
case
0
:
puts
(
"*** ERROR: `ethaddr' not set
\n
"
);
break
;
default:
printf
(
"*** ERROR: `eth%daddr' not set
\n
"
,
num
);
break
;
}
NetStartAgain
();
return
(
2
);
#else
puts
(
"*** ERROR: `ethaddr' not set
\n
"
);
return
(
1
);
#endif
}
/* Fall through */
}
return
(
0
);
/* OK */
}
/**********************************************************************/
int
NetCksumOk
(
uchar
*
ptr
,
int
len
)
{
return
!
((
NetCksum
(
ptr
,
len
)
+
1
)
&
0xfffe
);
}
unsigned
NetCksum
(
uchar
*
ptr
,
int
len
)
{
ulong
xsum
;
xsum
=
0
;
while
(
len
--
>
0
)
xsum
+=
*
((
ushort
*
)
ptr
)
++
;
xsum
=
(
xsum
&
0xffff
)
+
(
xsum
>>
16
);
xsum
=
(
xsum
&
0xffff
)
+
(
xsum
>>
16
);
return
(
xsum
&
0xffff
);
}
void
NetSetEther
(
volatile
uchar
*
xet
,
uchar
*
addr
,
uint
prot
)
{
Ethernet_t
*
et
=
(
Ethernet_t
*
)
xet
;
memcpy
(
et
->
et_dest
,
addr
,
6
);
memcpy
(
et
->
et_src
,
NetOurEther
,
6
);
et
->
et_protlen
=
htons
(
prot
);
}
void
NetSetIP
(
volatile
uchar
*
xip
,
IPaddr_t
dest
,
int
dport
,
int
sport
,
int
len
)
{
volatile
IP_t
*
ip
=
(
IP_t
*
)
xip
;
/*
* 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.
(need to set no fragment bit - XXX)
*/
ip
->
ip_hl_v
=
0x45
;
/* IP_HDR_SIZE / 4 (not including UDP) */
ip
->
ip_tos
=
0
;
ip
->
ip_len
=
htons
(
IP_HDR_SIZE
+
len
);
ip
->
ip_id
=
htons
(
NetIPID
++
);
ip
->
ip_off
=
htons
(
0x4000
);
/* No fragmentation */
ip
->
ip_ttl
=
255
;
ip
->
ip_p
=
17
;
/* UDP */
ip
->
ip_sum
=
0
;
NetCopyIP
((
void
*
)
&
ip
->
ip_src
,
&
NetOurIP
);
/* already in network byte order */
NetCopyIP
((
void
*
)
&
ip
->
ip_dst
,
&
dest
);
/* - "" - */
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
);
}
void
copy_filename
(
uchar
*
dst
,
uchar
*
src
,
int
size
)
{
if
(
*
src
&&
(
*
src
==
'"'
))
{
++
src
;
--
size
;
}
while
((
--
size
>
0
)
&&
*
src
&&
(
*
src
!=
'"'
))
{
*
dst
++
=
*
src
++
;
}
*
dst
=
'\0'
;
}
#endif
/* CFG_CMD_NET */
void
ip_to_string
(
IPaddr_t
x
,
char
*
s
)
{
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
)
);
}
void
print_IPaddr
(
IPaddr_t
x
)
{
char
tmp
[
16
];
ip_to_string
(
x
,
tmp
);
puts
(
tmp
);
}
IPaddr_t
getenv_IPaddr
(
char
*
var
)
{
IPaddr_t
addr
;
char
*
s
,
*
e
;
int
i
;
s
=
getenv
(
var
);
for
(
addr
=
0
,
i
=
0
;
i
<
4
;
++
i
)
{
ulong
val
=
s
?
simple_strtoul
(
s
,
&
e
,
10
)
:
0
;
addr
<<=
8
;
addr
|=
(
val
&
0xFF
);
if
(
s
)
{
s
=
(
*
e
)
?
e
+
1
:
e
;
}
}
return
(
htonl
(
addr
));
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录