Commit 2ea9103924048637d28baf0f7b1dd410f6704c32
Committed by
Tom Rini
1 parent
04e2a13336
Exists in
v2017.01-smarct4x
and in
37 other branches
SPDX License cleanup for LiMon imported files
A number of network related files were imported from the LiMon project; these contain a somewhat unclear license statement: Copyright 1994 - 2000 Neil Russell. (See License) I analyzed the source code of LiMon v1.4.2 which was used for this import. It does not contain any "License" file, but the top level directory contains a file "COPYING", which turns out to be GPL v2 of June 1991. So it is legitimate to conclude that the LiMon derived files are also to be released under GPLv2. Mark them as such. Signed-off-by: Wolfgang Denk <wd@denx.de>
Showing 8 changed files with 8 additions and 1 deletions Inline Diff
include/net.h
1 | /* | 1 | /* |
2 | * LiMon Monitor (LiMon) - Network. | 2 | * LiMon Monitor (LiMon) - Network. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * | 6 | * SPDX-License-Identifier: GPL-2.0 |
7 | * | 7 | * |
8 | * History | 8 | * History |
9 | * 9/16/00 bor adapted to TQM823L/STK8xxL board, RARP/TFTP boot added | 9 | * 9/16/00 bor adapted to TQM823L/STK8xxL board, RARP/TFTP boot added |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef __NET_H__ | 12 | #ifndef __NET_H__ |
13 | #define __NET_H__ | 13 | #define __NET_H__ |
14 | 14 | ||
15 | #if defined(CONFIG_8xx) | 15 | #if defined(CONFIG_8xx) |
16 | #include <commproc.h> | 16 | #include <commproc.h> |
17 | #endif /* CONFIG_8xx */ | 17 | #endif /* CONFIG_8xx */ |
18 | 18 | ||
19 | #include <asm/cache.h> | 19 | #include <asm/cache.h> |
20 | #include <asm/byteorder.h> /* for nton* / ntoh* stuff */ | 20 | #include <asm/byteorder.h> /* for nton* / ntoh* stuff */ |
21 | 21 | ||
22 | #define DEBUG_LL_STATE 0 /* Link local state machine changes */ | 22 | #define DEBUG_LL_STATE 0 /* Link local state machine changes */ |
23 | #define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */ | 23 | #define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */ |
24 | #define DEBUG_NET_PKT 0 /* Packets on info on the network at large */ | 24 | #define DEBUG_NET_PKT 0 /* Packets on info on the network at large */ |
25 | #define DEBUG_INT_STATE 0 /* Internal network state changes */ | 25 | #define DEBUG_INT_STATE 0 /* Internal network state changes */ |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * The number of receive packet buffers, and the required packet buffer | 28 | * The number of receive packet buffers, and the required packet buffer |
29 | * alignment in memory. | 29 | * alignment in memory. |
30 | * | 30 | * |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #ifdef CONFIG_SYS_RX_ETH_BUFFER | 33 | #ifdef CONFIG_SYS_RX_ETH_BUFFER |
34 | # define PKTBUFSRX CONFIG_SYS_RX_ETH_BUFFER | 34 | # define PKTBUFSRX CONFIG_SYS_RX_ETH_BUFFER |
35 | #else | 35 | #else |
36 | # define PKTBUFSRX 4 | 36 | # define PKTBUFSRX 4 |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | #define PKTALIGN ARCH_DMA_MINALIGN | 39 | #define PKTALIGN ARCH_DMA_MINALIGN |
40 | 40 | ||
41 | /* IPv4 addresses are always 32 bits in size */ | 41 | /* IPv4 addresses are always 32 bits in size */ |
42 | typedef __be32 IPaddr_t; | 42 | typedef __be32 IPaddr_t; |
43 | 43 | ||
44 | 44 | ||
45 | /** | 45 | /** |
46 | * An incoming packet handler. | 46 | * An incoming packet handler. |
47 | * @param pkt pointer to the application packet | 47 | * @param pkt pointer to the application packet |
48 | * @param dport destination UDP port | 48 | * @param dport destination UDP port |
49 | * @param sip source IP address | 49 | * @param sip source IP address |
50 | * @param sport source UDP port | 50 | * @param sport source UDP port |
51 | * @param len packet length | 51 | * @param len packet length |
52 | */ | 52 | */ |
53 | typedef void rxhand_f(uchar *pkt, unsigned dport, | 53 | typedef void rxhand_f(uchar *pkt, unsigned dport, |
54 | IPaddr_t sip, unsigned sport, | 54 | IPaddr_t sip, unsigned sport, |
55 | unsigned len); | 55 | unsigned len); |
56 | 56 | ||
57 | /** | 57 | /** |
58 | * An incoming ICMP packet handler. | 58 | * An incoming ICMP packet handler. |
59 | * @param type ICMP type | 59 | * @param type ICMP type |
60 | * @param code ICMP code | 60 | * @param code ICMP code |
61 | * @param dport destination UDP port | 61 | * @param dport destination UDP port |
62 | * @param sip source IP address | 62 | * @param sip source IP address |
63 | * @param sport source UDP port | 63 | * @param sport source UDP port |
64 | * @param pkt pointer to the ICMP packet data | 64 | * @param pkt pointer to the ICMP packet data |
65 | * @param len packet length | 65 | * @param len packet length |
66 | */ | 66 | */ |
67 | typedef void rxhand_icmp_f(unsigned type, unsigned code, unsigned dport, | 67 | typedef void rxhand_icmp_f(unsigned type, unsigned code, unsigned dport, |
68 | IPaddr_t sip, unsigned sport, uchar *pkt, unsigned len); | 68 | IPaddr_t sip, unsigned sport, uchar *pkt, unsigned len); |
69 | 69 | ||
70 | /* | 70 | /* |
71 | * A timeout handler. Called after time interval has expired. | 71 | * A timeout handler. Called after time interval has expired. |
72 | */ | 72 | */ |
73 | typedef void thand_f(void); | 73 | typedef void thand_f(void); |
74 | 74 | ||
75 | enum eth_state_t { | 75 | enum eth_state_t { |
76 | ETH_STATE_INIT, | 76 | ETH_STATE_INIT, |
77 | ETH_STATE_PASSIVE, | 77 | ETH_STATE_PASSIVE, |
78 | ETH_STATE_ACTIVE | 78 | ETH_STATE_ACTIVE |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct eth_device { | 81 | struct eth_device { |
82 | char name[16]; | 82 | char name[16]; |
83 | unsigned char enetaddr[6]; | 83 | unsigned char enetaddr[6]; |
84 | int iobase; | 84 | int iobase; |
85 | int state; | 85 | int state; |
86 | 86 | ||
87 | int (*init) (struct eth_device *, bd_t *); | 87 | int (*init) (struct eth_device *, bd_t *); |
88 | int (*send) (struct eth_device *, void *packet, int length); | 88 | int (*send) (struct eth_device *, void *packet, int length); |
89 | int (*recv) (struct eth_device *); | 89 | int (*recv) (struct eth_device *); |
90 | void (*halt) (struct eth_device *); | 90 | void (*halt) (struct eth_device *); |
91 | #ifdef CONFIG_MCAST_TFTP | 91 | #ifdef CONFIG_MCAST_TFTP |
92 | int (*mcast) (struct eth_device *, const u8 *enetaddr, u8 set); | 92 | int (*mcast) (struct eth_device *, const u8 *enetaddr, u8 set); |
93 | #endif | 93 | #endif |
94 | int (*write_hwaddr) (struct eth_device *); | 94 | int (*write_hwaddr) (struct eth_device *); |
95 | struct eth_device *next; | 95 | struct eth_device *next; |
96 | int index; | 96 | int index; |
97 | void *priv; | 97 | void *priv; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | extern int eth_initialize(bd_t *bis); /* Initialize network subsystem */ | 100 | extern int eth_initialize(bd_t *bis); /* Initialize network subsystem */ |
101 | extern int eth_register(struct eth_device* dev);/* Register network device */ | 101 | extern int eth_register(struct eth_device* dev);/* Register network device */ |
102 | extern int eth_unregister(struct eth_device *dev);/* Remove network device */ | 102 | extern int eth_unregister(struct eth_device *dev);/* Remove network device */ |
103 | extern void eth_try_another(int first_restart); /* Change the device */ | 103 | extern void eth_try_another(int first_restart); /* Change the device */ |
104 | extern void eth_set_current(void); /* set nterface to ethcur var */ | 104 | extern void eth_set_current(void); /* set nterface to ethcur var */ |
105 | 105 | ||
106 | /* get the current device MAC */ | 106 | /* get the current device MAC */ |
107 | extern struct eth_device *eth_current; | 107 | extern struct eth_device *eth_current; |
108 | 108 | ||
109 | static inline __attribute__((always_inline)) | 109 | static inline __attribute__((always_inline)) |
110 | struct eth_device *eth_get_dev(void) | 110 | struct eth_device *eth_get_dev(void) |
111 | { | 111 | { |
112 | return eth_current; | 112 | return eth_current; |
113 | } | 113 | } |
114 | extern struct eth_device *eth_get_dev_by_name(const char *devname); | 114 | extern struct eth_device *eth_get_dev_by_name(const char *devname); |
115 | extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */ | 115 | extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */ |
116 | extern int eth_get_dev_index(void); /* get the device index */ | 116 | extern int eth_get_dev_index(void); /* get the device index */ |
117 | extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr); | 117 | extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr); |
118 | extern int eth_getenv_enetaddr(char *name, uchar *enetaddr); | 118 | extern int eth_getenv_enetaddr(char *name, uchar *enetaddr); |
119 | extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr); | 119 | extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr); |
120 | 120 | ||
121 | /* | 121 | /* |
122 | * Get the hardware address for an ethernet interface . | 122 | * Get the hardware address for an ethernet interface . |
123 | * Args: | 123 | * Args: |
124 | * base_name - base name for device (normally "eth") | 124 | * base_name - base name for device (normally "eth") |
125 | * index - device index number (0 for first) | 125 | * index - device index number (0 for first) |
126 | * enetaddr - returns 6 byte hardware address | 126 | * enetaddr - returns 6 byte hardware address |
127 | * Returns: | 127 | * Returns: |
128 | * Return true if the address is valid. | 128 | * Return true if the address is valid. |
129 | */ | 129 | */ |
130 | extern int eth_getenv_enetaddr_by_index(const char *base_name, int index, | 130 | extern int eth_getenv_enetaddr_by_index(const char *base_name, int index, |
131 | uchar *enetaddr); | 131 | uchar *enetaddr); |
132 | 132 | ||
133 | extern int usb_eth_initialize(bd_t *bi); | 133 | extern int usb_eth_initialize(bd_t *bi); |
134 | extern int eth_init(bd_t *bis); /* Initialize the device */ | 134 | extern int eth_init(bd_t *bis); /* Initialize the device */ |
135 | extern int eth_send(void *packet, int length); /* Send a packet */ | 135 | extern int eth_send(void *packet, int length); /* Send a packet */ |
136 | 136 | ||
137 | #ifdef CONFIG_API | 137 | #ifdef CONFIG_API |
138 | extern int eth_receive(void *packet, int length); /* Receive a packet*/ | 138 | extern int eth_receive(void *packet, int length); /* Receive a packet*/ |
139 | extern void (*push_packet)(void *packet, int length); | 139 | extern void (*push_packet)(void *packet, int length); |
140 | #endif | 140 | #endif |
141 | extern int eth_rx(void); /* Check for received packets */ | 141 | extern int eth_rx(void); /* Check for received packets */ |
142 | extern void eth_halt(void); /* stop SCC */ | 142 | extern void eth_halt(void); /* stop SCC */ |
143 | extern char *eth_get_name(void); /* get name of current device */ | 143 | extern char *eth_get_name(void); /* get name of current device */ |
144 | 144 | ||
145 | /* Set active state */ | 145 | /* Set active state */ |
146 | static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis) | 146 | static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis) |
147 | { | 147 | { |
148 | eth_get_dev()->state = ETH_STATE_ACTIVE; | 148 | eth_get_dev()->state = ETH_STATE_ACTIVE; |
149 | 149 | ||
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | /* Set passive state */ | 152 | /* Set passive state */ |
153 | static inline __attribute__((always_inline)) void eth_halt_state_only(void) | 153 | static inline __attribute__((always_inline)) void eth_halt_state_only(void) |
154 | { | 154 | { |
155 | eth_get_dev()->state = ETH_STATE_PASSIVE; | 155 | eth_get_dev()->state = ETH_STATE_PASSIVE; |
156 | } | 156 | } |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * Set the hardware address for an ethernet interface based on 'eth%daddr' | 159 | * Set the hardware address for an ethernet interface based on 'eth%daddr' |
160 | * environment variable (or just 'ethaddr' if eth_number is 0). | 160 | * environment variable (or just 'ethaddr' if eth_number is 0). |
161 | * Args: | 161 | * Args: |
162 | * base_name - base name for device (normally "eth") | 162 | * base_name - base name for device (normally "eth") |
163 | * eth_number - value of %d (0 for first device of this type) | 163 | * eth_number - value of %d (0 for first device of this type) |
164 | * Returns: | 164 | * Returns: |
165 | * 0 is success, non-zero is error status from driver. | 165 | * 0 is success, non-zero is error status from driver. |
166 | */ | 166 | */ |
167 | int eth_write_hwaddr(struct eth_device *dev, const char *base_name, | 167 | int eth_write_hwaddr(struct eth_device *dev, const char *base_name, |
168 | int eth_number); | 168 | int eth_number); |
169 | 169 | ||
170 | #ifdef CONFIG_MCAST_TFTP | 170 | #ifdef CONFIG_MCAST_TFTP |
171 | int eth_mcast_join(IPaddr_t mcast_addr, u8 join); | 171 | int eth_mcast_join(IPaddr_t mcast_addr, u8 join); |
172 | u32 ether_crc(size_t len, unsigned char const *p); | 172 | u32 ether_crc(size_t len, unsigned char const *p); |
173 | #endif | 173 | #endif |
174 | 174 | ||
175 | 175 | ||
176 | /**********************************************************************/ | 176 | /**********************************************************************/ |
177 | /* | 177 | /* |
178 | * Protocol headers. | 178 | * Protocol headers. |
179 | */ | 179 | */ |
180 | 180 | ||
181 | /* | 181 | /* |
182 | * Ethernet header | 182 | * Ethernet header |
183 | */ | 183 | */ |
184 | 184 | ||
185 | struct ethernet_hdr { | 185 | struct ethernet_hdr { |
186 | uchar et_dest[6]; /* Destination node */ | 186 | uchar et_dest[6]; /* Destination node */ |
187 | uchar et_src[6]; /* Source node */ | 187 | uchar et_src[6]; /* Source node */ |
188 | ushort et_protlen; /* Protocol or length */ | 188 | ushort et_protlen; /* Protocol or length */ |
189 | }; | 189 | }; |
190 | 190 | ||
191 | /* Ethernet header size */ | 191 | /* Ethernet header size */ |
192 | #define ETHER_HDR_SIZE (sizeof(struct ethernet_hdr)) | 192 | #define ETHER_HDR_SIZE (sizeof(struct ethernet_hdr)) |
193 | 193 | ||
194 | struct e802_hdr { | 194 | struct e802_hdr { |
195 | uchar et_dest[6]; /* Destination node */ | 195 | uchar et_dest[6]; /* Destination node */ |
196 | uchar et_src[6]; /* Source node */ | 196 | uchar et_src[6]; /* Source node */ |
197 | ushort et_protlen; /* Protocol or length */ | 197 | ushort et_protlen; /* Protocol or length */ |
198 | uchar et_dsap; /* 802 DSAP */ | 198 | uchar et_dsap; /* 802 DSAP */ |
199 | uchar et_ssap; /* 802 SSAP */ | 199 | uchar et_ssap; /* 802 SSAP */ |
200 | uchar et_ctl; /* 802 control */ | 200 | uchar et_ctl; /* 802 control */ |
201 | uchar et_snap1; /* SNAP */ | 201 | uchar et_snap1; /* SNAP */ |
202 | uchar et_snap2; | 202 | uchar et_snap2; |
203 | uchar et_snap3; | 203 | uchar et_snap3; |
204 | ushort et_prot; /* 802 protocol */ | 204 | ushort et_prot; /* 802 protocol */ |
205 | }; | 205 | }; |
206 | 206 | ||
207 | /* 802 + SNAP + ethernet header size */ | 207 | /* 802 + SNAP + ethernet header size */ |
208 | #define E802_HDR_SIZE (sizeof(struct e802_hdr)) | 208 | #define E802_HDR_SIZE (sizeof(struct e802_hdr)) |
209 | 209 | ||
210 | /* | 210 | /* |
211 | * Virtual LAN Ethernet header | 211 | * Virtual LAN Ethernet header |
212 | */ | 212 | */ |
213 | struct vlan_ethernet_hdr { | 213 | struct vlan_ethernet_hdr { |
214 | uchar vet_dest[6]; /* Destination node */ | 214 | uchar vet_dest[6]; /* Destination node */ |
215 | uchar vet_src[6]; /* Source node */ | 215 | uchar vet_src[6]; /* Source node */ |
216 | ushort vet_vlan_type; /* PROT_VLAN */ | 216 | ushort vet_vlan_type; /* PROT_VLAN */ |
217 | ushort vet_tag; /* TAG of VLAN */ | 217 | ushort vet_tag; /* TAG of VLAN */ |
218 | ushort vet_type; /* protocol type */ | 218 | ushort vet_type; /* protocol type */ |
219 | }; | 219 | }; |
220 | 220 | ||
221 | /* VLAN Ethernet header size */ | 221 | /* VLAN Ethernet header size */ |
222 | #define VLAN_ETHER_HDR_SIZE (sizeof(struct vlan_ethernet_hdr)) | 222 | #define VLAN_ETHER_HDR_SIZE (sizeof(struct vlan_ethernet_hdr)) |
223 | 223 | ||
224 | #define PROT_IP 0x0800 /* IP protocol */ | 224 | #define PROT_IP 0x0800 /* IP protocol */ |
225 | #define PROT_ARP 0x0806 /* IP ARP protocol */ | 225 | #define PROT_ARP 0x0806 /* IP ARP protocol */ |
226 | #define PROT_RARP 0x8035 /* IP ARP protocol */ | 226 | #define PROT_RARP 0x8035 /* IP ARP protocol */ |
227 | #define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */ | 227 | #define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */ |
228 | 228 | ||
229 | #define IPPROTO_ICMP 1 /* Internet Control Message Protocol */ | 229 | #define IPPROTO_ICMP 1 /* Internet Control Message Protocol */ |
230 | #define IPPROTO_UDP 17 /* User Datagram Protocol */ | 230 | #define IPPROTO_UDP 17 /* User Datagram Protocol */ |
231 | 231 | ||
232 | /* | 232 | /* |
233 | * Internet Protocol (IP) header. | 233 | * Internet Protocol (IP) header. |
234 | */ | 234 | */ |
235 | struct ip_hdr { | 235 | struct ip_hdr { |
236 | uchar ip_hl_v; /* header length and version */ | 236 | uchar ip_hl_v; /* header length and version */ |
237 | uchar ip_tos; /* type of service */ | 237 | uchar ip_tos; /* type of service */ |
238 | ushort ip_len; /* total length */ | 238 | ushort ip_len; /* total length */ |
239 | ushort ip_id; /* identification */ | 239 | ushort ip_id; /* identification */ |
240 | ushort ip_off; /* fragment offset field */ | 240 | ushort ip_off; /* fragment offset field */ |
241 | uchar ip_ttl; /* time to live */ | 241 | uchar ip_ttl; /* time to live */ |
242 | uchar ip_p; /* protocol */ | 242 | uchar ip_p; /* protocol */ |
243 | ushort ip_sum; /* checksum */ | 243 | ushort ip_sum; /* checksum */ |
244 | IPaddr_t ip_src; /* Source IP address */ | 244 | IPaddr_t ip_src; /* Source IP address */ |
245 | IPaddr_t ip_dst; /* Destination IP address */ | 245 | IPaddr_t ip_dst; /* Destination IP address */ |
246 | }; | 246 | }; |
247 | 247 | ||
248 | #define IP_OFFS 0x1fff /* ip offset *= 8 */ | 248 | #define IP_OFFS 0x1fff /* ip offset *= 8 */ |
249 | #define IP_FLAGS 0xe000 /* first 3 bits */ | 249 | #define IP_FLAGS 0xe000 /* first 3 bits */ |
250 | #define IP_FLAGS_RES 0x8000 /* reserved */ | 250 | #define IP_FLAGS_RES 0x8000 /* reserved */ |
251 | #define IP_FLAGS_DFRAG 0x4000 /* don't fragments */ | 251 | #define IP_FLAGS_DFRAG 0x4000 /* don't fragments */ |
252 | #define IP_FLAGS_MFRAG 0x2000 /* more fragments */ | 252 | #define IP_FLAGS_MFRAG 0x2000 /* more fragments */ |
253 | 253 | ||
254 | #define IP_HDR_SIZE (sizeof(struct ip_hdr)) | 254 | #define IP_HDR_SIZE (sizeof(struct ip_hdr)) |
255 | 255 | ||
256 | /* | 256 | /* |
257 | * Internet Protocol (IP) + UDP header. | 257 | * Internet Protocol (IP) + UDP header. |
258 | */ | 258 | */ |
259 | struct ip_udp_hdr { | 259 | struct ip_udp_hdr { |
260 | uchar ip_hl_v; /* header length and version */ | 260 | uchar ip_hl_v; /* header length and version */ |
261 | uchar ip_tos; /* type of service */ | 261 | uchar ip_tos; /* type of service */ |
262 | ushort ip_len; /* total length */ | 262 | ushort ip_len; /* total length */ |
263 | ushort ip_id; /* identification */ | 263 | ushort ip_id; /* identification */ |
264 | ushort ip_off; /* fragment offset field */ | 264 | ushort ip_off; /* fragment offset field */ |
265 | uchar ip_ttl; /* time to live */ | 265 | uchar ip_ttl; /* time to live */ |
266 | uchar ip_p; /* protocol */ | 266 | uchar ip_p; /* protocol */ |
267 | ushort ip_sum; /* checksum */ | 267 | ushort ip_sum; /* checksum */ |
268 | IPaddr_t ip_src; /* Source IP address */ | 268 | IPaddr_t ip_src; /* Source IP address */ |
269 | IPaddr_t ip_dst; /* Destination IP address */ | 269 | IPaddr_t ip_dst; /* Destination IP address */ |
270 | ushort udp_src; /* UDP source port */ | 270 | ushort udp_src; /* UDP source port */ |
271 | ushort udp_dst; /* UDP destination port */ | 271 | ushort udp_dst; /* UDP destination port */ |
272 | ushort udp_len; /* Length of UDP packet */ | 272 | ushort udp_len; /* Length of UDP packet */ |
273 | ushort udp_xsum; /* Checksum */ | 273 | ushort udp_xsum; /* Checksum */ |
274 | }; | 274 | }; |
275 | 275 | ||
276 | #define IP_UDP_HDR_SIZE (sizeof(struct ip_udp_hdr)) | 276 | #define IP_UDP_HDR_SIZE (sizeof(struct ip_udp_hdr)) |
277 | #define UDP_HDR_SIZE (IP_UDP_HDR_SIZE - IP_HDR_SIZE) | 277 | #define UDP_HDR_SIZE (IP_UDP_HDR_SIZE - IP_HDR_SIZE) |
278 | 278 | ||
279 | /* | 279 | /* |
280 | * Address Resolution Protocol (ARP) header. | 280 | * Address Resolution Protocol (ARP) header. |
281 | */ | 281 | */ |
282 | struct arp_hdr { | 282 | struct arp_hdr { |
283 | ushort ar_hrd; /* Format of hardware address */ | 283 | ushort ar_hrd; /* Format of hardware address */ |
284 | # define ARP_ETHER 1 /* Ethernet hardware address */ | 284 | # define ARP_ETHER 1 /* Ethernet hardware address */ |
285 | ushort ar_pro; /* Format of protocol address */ | 285 | ushort ar_pro; /* Format of protocol address */ |
286 | uchar ar_hln; /* Length of hardware address */ | 286 | uchar ar_hln; /* Length of hardware address */ |
287 | # define ARP_HLEN 6 | 287 | # define ARP_HLEN 6 |
288 | uchar ar_pln; /* Length of protocol address */ | 288 | uchar ar_pln; /* Length of protocol address */ |
289 | # define ARP_PLEN 4 | 289 | # define ARP_PLEN 4 |
290 | ushort ar_op; /* Operation */ | 290 | ushort ar_op; /* Operation */ |
291 | # define ARPOP_REQUEST 1 /* Request to resolve address */ | 291 | # define ARPOP_REQUEST 1 /* Request to resolve address */ |
292 | # define ARPOP_REPLY 2 /* Response to previous request */ | 292 | # define ARPOP_REPLY 2 /* Response to previous request */ |
293 | 293 | ||
294 | # define RARPOP_REQUEST 3 /* Request to resolve address */ | 294 | # define RARPOP_REQUEST 3 /* Request to resolve address */ |
295 | # define RARPOP_REPLY 4 /* Response to previous request */ | 295 | # define RARPOP_REPLY 4 /* Response to previous request */ |
296 | 296 | ||
297 | /* | 297 | /* |
298 | * The remaining fields are variable in size, according to | 298 | * The remaining fields are variable in size, according to |
299 | * the sizes above, and are defined as appropriate for | 299 | * the sizes above, and are defined as appropriate for |
300 | * specific hardware/protocol combinations. | 300 | * specific hardware/protocol combinations. |
301 | */ | 301 | */ |
302 | uchar ar_data[0]; | 302 | uchar ar_data[0]; |
303 | #define ar_sha ar_data[0] | 303 | #define ar_sha ar_data[0] |
304 | #define ar_spa ar_data[ARP_HLEN] | 304 | #define ar_spa ar_data[ARP_HLEN] |
305 | #define ar_tha ar_data[ARP_HLEN + ARP_PLEN] | 305 | #define ar_tha ar_data[ARP_HLEN + ARP_PLEN] |
306 | #define ar_tpa ar_data[ARP_HLEN + ARP_PLEN + ARP_HLEN] | 306 | #define ar_tpa ar_data[ARP_HLEN + ARP_PLEN + ARP_HLEN] |
307 | #if 0 | 307 | #if 0 |
308 | uchar ar_sha[]; /* Sender hardware address */ | 308 | uchar ar_sha[]; /* Sender hardware address */ |
309 | uchar ar_spa[]; /* Sender protocol address */ | 309 | uchar ar_spa[]; /* Sender protocol address */ |
310 | uchar ar_tha[]; /* Target hardware address */ | 310 | uchar ar_tha[]; /* Target hardware address */ |
311 | uchar ar_tpa[]; /* Target protocol address */ | 311 | uchar ar_tpa[]; /* Target protocol address */ |
312 | #endif /* 0 */ | 312 | #endif /* 0 */ |
313 | }; | 313 | }; |
314 | 314 | ||
315 | #define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */ | 315 | #define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */ |
316 | 316 | ||
317 | /* | 317 | /* |
318 | * ICMP stuff (just enough to handle (host) redirect messages) | 318 | * ICMP stuff (just enough to handle (host) redirect messages) |
319 | */ | 319 | */ |
320 | #define ICMP_ECHO_REPLY 0 /* Echo reply */ | 320 | #define ICMP_ECHO_REPLY 0 /* Echo reply */ |
321 | #define ICMP_NOT_REACH 3 /* Detination unreachable */ | 321 | #define ICMP_NOT_REACH 3 /* Detination unreachable */ |
322 | #define ICMP_REDIRECT 5 /* Redirect (change route) */ | 322 | #define ICMP_REDIRECT 5 /* Redirect (change route) */ |
323 | #define ICMP_ECHO_REQUEST 8 /* Echo request */ | 323 | #define ICMP_ECHO_REQUEST 8 /* Echo request */ |
324 | 324 | ||
325 | /* Codes for REDIRECT. */ | 325 | /* Codes for REDIRECT. */ |
326 | #define ICMP_REDIR_NET 0 /* Redirect Net */ | 326 | #define ICMP_REDIR_NET 0 /* Redirect Net */ |
327 | #define ICMP_REDIR_HOST 1 /* Redirect Host */ | 327 | #define ICMP_REDIR_HOST 1 /* Redirect Host */ |
328 | 328 | ||
329 | /* Codes for NOT_REACH */ | 329 | /* Codes for NOT_REACH */ |
330 | #define ICMP_NOT_REACH_PORT 3 /* Port unreachable */ | 330 | #define ICMP_NOT_REACH_PORT 3 /* Port unreachable */ |
331 | 331 | ||
332 | struct icmp_hdr { | 332 | struct icmp_hdr { |
333 | uchar type; | 333 | uchar type; |
334 | uchar code; | 334 | uchar code; |
335 | ushort checksum; | 335 | ushort checksum; |
336 | union { | 336 | union { |
337 | struct { | 337 | struct { |
338 | ushort id; | 338 | ushort id; |
339 | ushort sequence; | 339 | ushort sequence; |
340 | } echo; | 340 | } echo; |
341 | ulong gateway; | 341 | ulong gateway; |
342 | struct { | 342 | struct { |
343 | ushort unused; | 343 | ushort unused; |
344 | ushort mtu; | 344 | ushort mtu; |
345 | } frag; | 345 | } frag; |
346 | uchar data[0]; | 346 | uchar data[0]; |
347 | } un; | 347 | } un; |
348 | }; | 348 | }; |
349 | 349 | ||
350 | #define ICMP_HDR_SIZE (sizeof(struct icmp_hdr)) | 350 | #define ICMP_HDR_SIZE (sizeof(struct icmp_hdr)) |
351 | #define IP_ICMP_HDR_SIZE (IP_HDR_SIZE + ICMP_HDR_SIZE) | 351 | #define IP_ICMP_HDR_SIZE (IP_HDR_SIZE + ICMP_HDR_SIZE) |
352 | 352 | ||
353 | /* | 353 | /* |
354 | * Maximum packet size; used to allocate packet storage. | 354 | * Maximum packet size; used to allocate packet storage. |
355 | * TFTP packets can be 524 bytes + IP header + ethernet header. | 355 | * TFTP packets can be 524 bytes + IP header + ethernet header. |
356 | * Lets be conservative, and go for 38 * 16. (Must also be | 356 | * Lets be conservative, and go for 38 * 16. (Must also be |
357 | * a multiple of 32 bytes). | 357 | * a multiple of 32 bytes). |
358 | */ | 358 | */ |
359 | /* | 359 | /* |
360 | * AS.HARNOIS : Better to set PKTSIZE to maximum size because | 360 | * AS.HARNOIS : Better to set PKTSIZE to maximum size because |
361 | * traffic type is not always controlled | 361 | * traffic type is not always controlled |
362 | * maximum packet size = 1518 | 362 | * maximum packet size = 1518 |
363 | * maximum packet size and multiple of 32 bytes = 1536 | 363 | * maximum packet size and multiple of 32 bytes = 1536 |
364 | */ | 364 | */ |
365 | #define PKTSIZE 1518 | 365 | #define PKTSIZE 1518 |
366 | #define PKTSIZE_ALIGN 1536 | 366 | #define PKTSIZE_ALIGN 1536 |
367 | /*#define PKTSIZE 608*/ | 367 | /*#define PKTSIZE 608*/ |
368 | 368 | ||
369 | /* | 369 | /* |
370 | * Maximum receive ring size; that is, the number of packets | 370 | * Maximum receive ring size; that is, the number of packets |
371 | * we can buffer before overflow happens. Basically, this just | 371 | * we can buffer before overflow happens. Basically, this just |
372 | * needs to be enough to prevent a packet being discarded while | 372 | * needs to be enough to prevent a packet being discarded while |
373 | * we are processing the previous one. | 373 | * we are processing the previous one. |
374 | */ | 374 | */ |
375 | #define RINGSZ 4 | 375 | #define RINGSZ 4 |
376 | #define RINGSZ_LOG2 2 | 376 | #define RINGSZ_LOG2 2 |
377 | 377 | ||
378 | /**********************************************************************/ | 378 | /**********************************************************************/ |
379 | /* | 379 | /* |
380 | * Globals. | 380 | * Globals. |
381 | * | 381 | * |
382 | * Note: | 382 | * Note: |
383 | * | 383 | * |
384 | * All variables of type IPaddr_t are stored in NETWORK byte order | 384 | * All variables of type IPaddr_t are stored in NETWORK byte order |
385 | * (big endian). | 385 | * (big endian). |
386 | */ | 386 | */ |
387 | 387 | ||
388 | /* net.c */ | 388 | /* net.c */ |
389 | /** BOOTP EXTENTIONS **/ | 389 | /** BOOTP EXTENTIONS **/ |
390 | extern IPaddr_t NetOurGatewayIP; /* Our gateway IP address */ | 390 | extern IPaddr_t NetOurGatewayIP; /* Our gateway IP address */ |
391 | extern IPaddr_t NetOurSubnetMask; /* Our subnet mask (0 = unknown) */ | 391 | extern IPaddr_t NetOurSubnetMask; /* Our subnet mask (0 = unknown) */ |
392 | extern IPaddr_t NetOurDNSIP; /* Our Domain Name Server (0 = unknown) */ | 392 | extern IPaddr_t NetOurDNSIP; /* Our Domain Name Server (0 = unknown) */ |
393 | #if defined(CONFIG_BOOTP_DNS2) | 393 | #if defined(CONFIG_BOOTP_DNS2) |
394 | extern IPaddr_t NetOurDNS2IP; /* Our 2nd Domain Name Server (0 = unknown) */ | 394 | extern IPaddr_t NetOurDNS2IP; /* Our 2nd Domain Name Server (0 = unknown) */ |
395 | #endif | 395 | #endif |
396 | extern char NetOurNISDomain[32]; /* Our NIS domain */ | 396 | extern char NetOurNISDomain[32]; /* Our NIS domain */ |
397 | extern char NetOurHostName[32]; /* Our hostname */ | 397 | extern char NetOurHostName[32]; /* Our hostname */ |
398 | extern char NetOurRootPath[64]; /* Our root path */ | 398 | extern char NetOurRootPath[64]; /* Our root path */ |
399 | extern ushort NetBootFileSize; /* Our boot file size in blocks */ | 399 | extern ushort NetBootFileSize; /* Our boot file size in blocks */ |
400 | /** END OF BOOTP EXTENTIONS **/ | 400 | /** END OF BOOTP EXTENTIONS **/ |
401 | extern ulong NetBootFileXferSize; /* size of bootfile in bytes */ | 401 | extern ulong NetBootFileXferSize; /* size of bootfile in bytes */ |
402 | extern uchar NetOurEther[6]; /* Our ethernet address */ | 402 | extern uchar NetOurEther[6]; /* Our ethernet address */ |
403 | extern uchar NetServerEther[6]; /* Boot server enet address */ | 403 | extern uchar NetServerEther[6]; /* Boot server enet address */ |
404 | extern IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ | 404 | extern IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ |
405 | extern IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */ | 405 | extern IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */ |
406 | extern uchar *NetTxPacket; /* THE transmit packet */ | 406 | extern uchar *NetTxPacket; /* THE transmit packet */ |
407 | extern uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */ | 407 | extern uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */ |
408 | extern uchar *NetRxPacket; /* Current receive packet */ | 408 | extern uchar *NetRxPacket; /* Current receive packet */ |
409 | extern int NetRxPacketLen; /* Current rx packet length */ | 409 | extern int NetRxPacketLen; /* Current rx packet length */ |
410 | extern unsigned NetIPID; /* IP ID (counting) */ | 410 | extern unsigned NetIPID; /* IP ID (counting) */ |
411 | extern uchar NetBcastAddr[6]; /* Ethernet boardcast address */ | 411 | extern uchar NetBcastAddr[6]; /* Ethernet boardcast address */ |
412 | extern uchar NetEtherNullAddr[6]; | 412 | extern uchar NetEtherNullAddr[6]; |
413 | 413 | ||
414 | #define VLAN_NONE 4095 /* untagged */ | 414 | #define VLAN_NONE 4095 /* untagged */ |
415 | #define VLAN_IDMASK 0x0fff /* mask of valid vlan id */ | 415 | #define VLAN_IDMASK 0x0fff /* mask of valid vlan id */ |
416 | extern ushort NetOurVLAN; /* Our VLAN */ | 416 | extern ushort NetOurVLAN; /* Our VLAN */ |
417 | extern ushort NetOurNativeVLAN; /* Our Native VLAN */ | 417 | extern ushort NetOurNativeVLAN; /* Our Native VLAN */ |
418 | 418 | ||
419 | extern int NetRestartWrap; /* Tried all network devices */ | 419 | extern int NetRestartWrap; /* Tried all network devices */ |
420 | 420 | ||
421 | enum proto_t { | 421 | enum proto_t { |
422 | BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP, | 422 | BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP, |
423 | TFTPSRV, TFTPPUT, LINKLOCAL | 423 | TFTPSRV, TFTPPUT, LINKLOCAL |
424 | }; | 424 | }; |
425 | 425 | ||
426 | /* from net/net.c */ | 426 | /* from net/net.c */ |
427 | extern char BootFile[128]; /* Boot File name */ | 427 | extern char BootFile[128]; /* Boot File name */ |
428 | 428 | ||
429 | #if defined(CONFIG_CMD_DNS) | 429 | #if defined(CONFIG_CMD_DNS) |
430 | extern char *NetDNSResolve; /* The host to resolve */ | 430 | extern char *NetDNSResolve; /* The host to resolve */ |
431 | extern char *NetDNSenvvar; /* the env var to put the ip into */ | 431 | extern char *NetDNSenvvar; /* the env var to put the ip into */ |
432 | #endif | 432 | #endif |
433 | 433 | ||
434 | #if defined(CONFIG_CMD_PING) | 434 | #if defined(CONFIG_CMD_PING) |
435 | extern IPaddr_t NetPingIP; /* the ip address to ping */ | 435 | extern IPaddr_t NetPingIP; /* the ip address to ping */ |
436 | #endif | 436 | #endif |
437 | 437 | ||
438 | #if defined(CONFIG_CMD_CDP) | 438 | #if defined(CONFIG_CMD_CDP) |
439 | /* when CDP completes these hold the return values */ | 439 | /* when CDP completes these hold the return values */ |
440 | extern ushort CDPNativeVLAN; /* CDP returned native VLAN */ | 440 | extern ushort CDPNativeVLAN; /* CDP returned native VLAN */ |
441 | extern ushort CDPApplianceVLAN; /* CDP returned appliance VLAN */ | 441 | extern ushort CDPApplianceVLAN; /* CDP returned appliance VLAN */ |
442 | 442 | ||
443 | /* | 443 | /* |
444 | * Check for a CDP packet by examining the received MAC address field | 444 | * Check for a CDP packet by examining the received MAC address field |
445 | */ | 445 | */ |
446 | static inline int is_cdp_packet(const uchar *et_addr) | 446 | static inline int is_cdp_packet(const uchar *et_addr) |
447 | { | 447 | { |
448 | extern const uchar NetCDPAddr[6]; | 448 | extern const uchar NetCDPAddr[6]; |
449 | 449 | ||
450 | return memcmp(et_addr, NetCDPAddr, 6) == 0; | 450 | return memcmp(et_addr, NetCDPAddr, 6) == 0; |
451 | } | 451 | } |
452 | #endif | 452 | #endif |
453 | 453 | ||
454 | #if defined(CONFIG_CMD_SNTP) | 454 | #if defined(CONFIG_CMD_SNTP) |
455 | extern IPaddr_t NetNtpServerIP; /* the ip address to NTP */ | 455 | extern IPaddr_t NetNtpServerIP; /* the ip address to NTP */ |
456 | extern int NetTimeOffset; /* offset time from UTC */ | 456 | extern int NetTimeOffset; /* offset time from UTC */ |
457 | #endif | 457 | #endif |
458 | 458 | ||
459 | #if defined(CONFIG_MCAST_TFTP) | 459 | #if defined(CONFIG_MCAST_TFTP) |
460 | extern IPaddr_t Mcast_addr; | 460 | extern IPaddr_t Mcast_addr; |
461 | #endif | 461 | #endif |
462 | 462 | ||
463 | /* Initialize the network adapter */ | 463 | /* Initialize the network adapter */ |
464 | extern void net_init(void); | 464 | extern void net_init(void); |
465 | extern int NetLoop(enum proto_t); | 465 | extern int NetLoop(enum proto_t); |
466 | 466 | ||
467 | /* Shutdown adapters and cleanup */ | 467 | /* Shutdown adapters and cleanup */ |
468 | extern void NetStop(void); | 468 | extern void NetStop(void); |
469 | 469 | ||
470 | /* Load failed. Start again. */ | 470 | /* Load failed. Start again. */ |
471 | extern void NetStartAgain(void); | 471 | extern void NetStartAgain(void); |
472 | 472 | ||
473 | /* Get size of the ethernet header when we send */ | 473 | /* Get size of the ethernet header when we send */ |
474 | extern int NetEthHdrSize(void); | 474 | extern int NetEthHdrSize(void); |
475 | 475 | ||
476 | /* Set ethernet header; returns the size of the header */ | 476 | /* Set ethernet header; returns the size of the header */ |
477 | extern int NetSetEther(uchar *, uchar *, uint); | 477 | extern int NetSetEther(uchar *, uchar *, uint); |
478 | extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot); | 478 | extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot); |
479 | 479 | ||
480 | /* Set IP header */ | 480 | /* Set IP header */ |
481 | extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source); | 481 | extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source); |
482 | extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport, | 482 | extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport, |
483 | int sport, int len); | 483 | int sport, int len); |
484 | 484 | ||
485 | /* Checksum */ | 485 | /* Checksum */ |
486 | extern int NetCksumOk(uchar *, int); /* Return true if cksum OK */ | 486 | extern int NetCksumOk(uchar *, int); /* Return true if cksum OK */ |
487 | extern uint NetCksum(uchar *, int); /* Calculate the checksum */ | 487 | extern uint NetCksum(uchar *, int); /* Calculate the checksum */ |
488 | 488 | ||
489 | /* Callbacks */ | 489 | /* Callbacks */ |
490 | extern rxhand_f *net_get_udp_handler(void); /* Get UDP RX packet handler */ | 490 | extern rxhand_f *net_get_udp_handler(void); /* Get UDP RX packet handler */ |
491 | extern void net_set_udp_handler(rxhand_f *); /* Set UDP RX packet handler */ | 491 | extern void net_set_udp_handler(rxhand_f *); /* Set UDP RX packet handler */ |
492 | extern rxhand_f *net_get_arp_handler(void); /* Get ARP RX packet handler */ | 492 | extern rxhand_f *net_get_arp_handler(void); /* Get ARP RX packet handler */ |
493 | extern void net_set_arp_handler(rxhand_f *); /* Set ARP RX packet handler */ | 493 | extern void net_set_arp_handler(rxhand_f *); /* Set ARP RX packet handler */ |
494 | extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */ | 494 | extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */ |
495 | extern void NetSetTimeout(ulong, thand_f *);/* Set timeout handler */ | 495 | extern void NetSetTimeout(ulong, thand_f *);/* Set timeout handler */ |
496 | 496 | ||
497 | /* Network loop state */ | 497 | /* Network loop state */ |
498 | enum net_loop_state { | 498 | enum net_loop_state { |
499 | NETLOOP_CONTINUE, | 499 | NETLOOP_CONTINUE, |
500 | NETLOOP_RESTART, | 500 | NETLOOP_RESTART, |
501 | NETLOOP_SUCCESS, | 501 | NETLOOP_SUCCESS, |
502 | NETLOOP_FAIL | 502 | NETLOOP_FAIL |
503 | }; | 503 | }; |
504 | extern enum net_loop_state net_state; | 504 | extern enum net_loop_state net_state; |
505 | 505 | ||
506 | static inline void net_set_state(enum net_loop_state state) | 506 | static inline void net_set_state(enum net_loop_state state) |
507 | { | 507 | { |
508 | debug_cond(DEBUG_INT_STATE, "--- NetState set to %d\n", state); | 508 | debug_cond(DEBUG_INT_STATE, "--- NetState set to %d\n", state); |
509 | net_state = state; | 509 | net_state = state; |
510 | } | 510 | } |
511 | 511 | ||
512 | /* Transmit a packet */ | 512 | /* Transmit a packet */ |
513 | static inline void NetSendPacket(uchar *pkt, int len) | 513 | static inline void NetSendPacket(uchar *pkt, int len) |
514 | { | 514 | { |
515 | (void) eth_send(pkt, len); | 515 | (void) eth_send(pkt, len); |
516 | } | 516 | } |
517 | 517 | ||
518 | /* | 518 | /* |
519 | * Transmit "NetTxPacket" as UDP packet, performing ARP request if needed | 519 | * Transmit "NetTxPacket" as UDP packet, performing ARP request if needed |
520 | * (ether will be populated) | 520 | * (ether will be populated) |
521 | * | 521 | * |
522 | * @param ether Raw packet buffer | 522 | * @param ether Raw packet buffer |
523 | * @param dest IP address to send the datagram to | 523 | * @param dest IP address to send the datagram to |
524 | * @param dport Destination UDP port | 524 | * @param dport Destination UDP port |
525 | * @param sport Source UDP port | 525 | * @param sport Source UDP port |
526 | * @param payload_len Length of data after the UDP header | 526 | * @param payload_len Length of data after the UDP header |
527 | */ | 527 | */ |
528 | extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, | 528 | extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, |
529 | int sport, int payload_len); | 529 | int sport, int payload_len); |
530 | 530 | ||
531 | /* Processes a received packet */ | 531 | /* Processes a received packet */ |
532 | extern void NetReceive(uchar *, int); | 532 | extern void NetReceive(uchar *, int); |
533 | 533 | ||
534 | #ifdef CONFIG_NETCONSOLE | 534 | #ifdef CONFIG_NETCONSOLE |
535 | void NcStart(void); | 535 | void NcStart(void); |
536 | int nc_input_packet(uchar *pkt, IPaddr_t src_ip, unsigned dest_port, | 536 | int nc_input_packet(uchar *pkt, IPaddr_t src_ip, unsigned dest_port, |
537 | unsigned src_port, unsigned len); | 537 | unsigned src_port, unsigned len); |
538 | #endif | 538 | #endif |
539 | 539 | ||
540 | static inline __attribute__((always_inline)) int eth_is_on_demand_init(void) | 540 | static inline __attribute__((always_inline)) int eth_is_on_demand_init(void) |
541 | { | 541 | { |
542 | #ifdef CONFIG_NETCONSOLE | 542 | #ifdef CONFIG_NETCONSOLE |
543 | extern enum proto_t net_loop_last_protocol; | 543 | extern enum proto_t net_loop_last_protocol; |
544 | 544 | ||
545 | return net_loop_last_protocol != NETCONS; | 545 | return net_loop_last_protocol != NETCONS; |
546 | #else | 546 | #else |
547 | return 1; | 547 | return 1; |
548 | #endif | 548 | #endif |
549 | } | 549 | } |
550 | 550 | ||
551 | static inline void eth_set_last_protocol(int protocol) | 551 | static inline void eth_set_last_protocol(int protocol) |
552 | { | 552 | { |
553 | #ifdef CONFIG_NETCONSOLE | 553 | #ifdef CONFIG_NETCONSOLE |
554 | extern enum proto_t net_loop_last_protocol; | 554 | extern enum proto_t net_loop_last_protocol; |
555 | 555 | ||
556 | net_loop_last_protocol = protocol; | 556 | net_loop_last_protocol = protocol; |
557 | #endif | 557 | #endif |
558 | } | 558 | } |
559 | 559 | ||
560 | /* | 560 | /* |
561 | * Check if autoload is enabled. If so, use either NFS or TFTP to download | 561 | * Check if autoload is enabled. If so, use either NFS or TFTP to download |
562 | * the boot file. | 562 | * the boot file. |
563 | */ | 563 | */ |
564 | void net_auto_load(void); | 564 | void net_auto_load(void); |
565 | 565 | ||
566 | /* | 566 | /* |
567 | * The following functions are a bit ugly, but necessary to deal with | 567 | * The following functions are a bit ugly, but necessary to deal with |
568 | * alignment restrictions on ARM. | 568 | * alignment restrictions on ARM. |
569 | * | 569 | * |
570 | * We're using inline functions, which had the smallest memory | 570 | * We're using inline functions, which had the smallest memory |
571 | * footprint in our tests. | 571 | * footprint in our tests. |
572 | */ | 572 | */ |
573 | /* return IP *in network byteorder* */ | 573 | /* return IP *in network byteorder* */ |
574 | static inline IPaddr_t NetReadIP(void *from) | 574 | static inline IPaddr_t NetReadIP(void *from) |
575 | { | 575 | { |
576 | IPaddr_t ip; | 576 | IPaddr_t ip; |
577 | 577 | ||
578 | memcpy((void *)&ip, (void *)from, sizeof(ip)); | 578 | memcpy((void *)&ip, (void *)from, sizeof(ip)); |
579 | return ip; | 579 | return ip; |
580 | } | 580 | } |
581 | 581 | ||
582 | /* return ulong *in network byteorder* */ | 582 | /* return ulong *in network byteorder* */ |
583 | static inline ulong NetReadLong(ulong *from) | 583 | static inline ulong NetReadLong(ulong *from) |
584 | { | 584 | { |
585 | ulong l; | 585 | ulong l; |
586 | 586 | ||
587 | memcpy((void *)&l, (void *)from, sizeof(l)); | 587 | memcpy((void *)&l, (void *)from, sizeof(l)); |
588 | return l; | 588 | return l; |
589 | } | 589 | } |
590 | 590 | ||
591 | /* write IP *in network byteorder* */ | 591 | /* write IP *in network byteorder* */ |
592 | static inline void NetWriteIP(void *to, IPaddr_t ip) | 592 | static inline void NetWriteIP(void *to, IPaddr_t ip) |
593 | { | 593 | { |
594 | memcpy(to, (void *)&ip, sizeof(ip)); | 594 | memcpy(to, (void *)&ip, sizeof(ip)); |
595 | } | 595 | } |
596 | 596 | ||
597 | /* copy IP */ | 597 | /* copy IP */ |
598 | static inline void NetCopyIP(void *to, void *from) | 598 | static inline void NetCopyIP(void *to, void *from) |
599 | { | 599 | { |
600 | memcpy((void *)to, from, sizeof(IPaddr_t)); | 600 | memcpy((void *)to, from, sizeof(IPaddr_t)); |
601 | } | 601 | } |
602 | 602 | ||
603 | /* copy ulong */ | 603 | /* copy ulong */ |
604 | static inline void NetCopyLong(ulong *to, ulong *from) | 604 | static inline void NetCopyLong(ulong *to, ulong *from) |
605 | { | 605 | { |
606 | memcpy((void *)to, (void *)from, sizeof(ulong)); | 606 | memcpy((void *)to, (void *)from, sizeof(ulong)); |
607 | } | 607 | } |
608 | 608 | ||
609 | /** | 609 | /** |
610 | * is_zero_ether_addr - Determine if give Ethernet address is all zeros. | 610 | * is_zero_ether_addr - Determine if give Ethernet address is all zeros. |
611 | * @addr: Pointer to a six-byte array containing the Ethernet address | 611 | * @addr: Pointer to a six-byte array containing the Ethernet address |
612 | * | 612 | * |
613 | * Return true if the address is all zeroes. | 613 | * Return true if the address is all zeroes. |
614 | */ | 614 | */ |
615 | static inline int is_zero_ether_addr(const u8 *addr) | 615 | static inline int is_zero_ether_addr(const u8 *addr) |
616 | { | 616 | { |
617 | return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); | 617 | return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); |
618 | } | 618 | } |
619 | 619 | ||
620 | /** | 620 | /** |
621 | * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. | 621 | * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. |
622 | * @addr: Pointer to a six-byte array containing the Ethernet address | 622 | * @addr: Pointer to a six-byte array containing the Ethernet address |
623 | * | 623 | * |
624 | * Return true if the address is a multicast address. | 624 | * Return true if the address is a multicast address. |
625 | * By definition the broadcast address is also a multicast address. | 625 | * By definition the broadcast address is also a multicast address. |
626 | */ | 626 | */ |
627 | static inline int is_multicast_ether_addr(const u8 *addr) | 627 | static inline int is_multicast_ether_addr(const u8 *addr) |
628 | { | 628 | { |
629 | return 0x01 & addr[0]; | 629 | return 0x01 & addr[0]; |
630 | } | 630 | } |
631 | 631 | ||
632 | /* | 632 | /* |
633 | * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast | 633 | * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast |
634 | * @addr: Pointer to a six-byte array containing the Ethernet address | 634 | * @addr: Pointer to a six-byte array containing the Ethernet address |
635 | * | 635 | * |
636 | * Return true if the address is the broadcast address. | 636 | * Return true if the address is the broadcast address. |
637 | */ | 637 | */ |
638 | static inline int is_broadcast_ether_addr(const u8 *addr) | 638 | static inline int is_broadcast_ether_addr(const u8 *addr) |
639 | { | 639 | { |
640 | return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == | 640 | return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == |
641 | 0xff; | 641 | 0xff; |
642 | } | 642 | } |
643 | 643 | ||
644 | /* | 644 | /* |
645 | * is_valid_ether_addr - Determine if the given Ethernet address is valid | 645 | * is_valid_ether_addr - Determine if the given Ethernet address is valid |
646 | * @addr: Pointer to a six-byte array containing the Ethernet address | 646 | * @addr: Pointer to a six-byte array containing the Ethernet address |
647 | * | 647 | * |
648 | * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not | 648 | * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not |
649 | * a multicast address, and is not FF:FF:FF:FF:FF:FF. | 649 | * a multicast address, and is not FF:FF:FF:FF:FF:FF. |
650 | * | 650 | * |
651 | * Return true if the address is valid. | 651 | * Return true if the address is valid. |
652 | */ | 652 | */ |
653 | static inline int is_valid_ether_addr(const u8 *addr) | 653 | static inline int is_valid_ether_addr(const u8 *addr) |
654 | { | 654 | { |
655 | /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to | 655 | /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to |
656 | * explicitly check for it here. */ | 656 | * explicitly check for it here. */ |
657 | return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); | 657 | return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); |
658 | } | 658 | } |
659 | 659 | ||
660 | /** | 660 | /** |
661 | * eth_random_addr - Generate software assigned random Ethernet address | 661 | * eth_random_addr - Generate software assigned random Ethernet address |
662 | * @addr: Pointer to a six-byte array containing the Ethernet address | 662 | * @addr: Pointer to a six-byte array containing the Ethernet address |
663 | * | 663 | * |
664 | * Generate a random Ethernet address (MAC) that is not multicast | 664 | * Generate a random Ethernet address (MAC) that is not multicast |
665 | * and has the local assigned bit set. | 665 | * and has the local assigned bit set. |
666 | */ | 666 | */ |
667 | static inline void eth_random_addr(uchar *addr) | 667 | static inline void eth_random_addr(uchar *addr) |
668 | { | 668 | { |
669 | int i; | 669 | int i; |
670 | unsigned int seed = get_timer(0); | 670 | unsigned int seed = get_timer(0); |
671 | 671 | ||
672 | for (i = 0; i < 6; i++) | 672 | for (i = 0; i < 6; i++) |
673 | addr[i] = rand_r(&seed); | 673 | addr[i] = rand_r(&seed); |
674 | 674 | ||
675 | addr[0] &= 0xfe; /* clear multicast bit */ | 675 | addr[0] &= 0xfe; /* clear multicast bit */ |
676 | addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ | 676 | addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ |
677 | } | 677 | } |
678 | 678 | ||
679 | /* Convert an IP address to a string */ | 679 | /* Convert an IP address to a string */ |
680 | extern void ip_to_string(IPaddr_t x, char *s); | 680 | extern void ip_to_string(IPaddr_t x, char *s); |
681 | 681 | ||
682 | /* Convert a string to ip address */ | 682 | /* Convert a string to ip address */ |
683 | extern IPaddr_t string_to_ip(const char *s); | 683 | extern IPaddr_t string_to_ip(const char *s); |
684 | 684 | ||
685 | /* Convert a VLAN id to a string */ | 685 | /* Convert a VLAN id to a string */ |
686 | extern void VLAN_to_string(ushort x, char *s); | 686 | extern void VLAN_to_string(ushort x, char *s); |
687 | 687 | ||
688 | /* Convert a string to a vlan id */ | 688 | /* Convert a string to a vlan id */ |
689 | extern ushort string_to_VLAN(const char *s); | 689 | extern ushort string_to_VLAN(const char *s); |
690 | 690 | ||
691 | /* read a VLAN id from an environment variable */ | 691 | /* read a VLAN id from an environment variable */ |
692 | extern ushort getenv_VLAN(char *); | 692 | extern ushort getenv_VLAN(char *); |
693 | 693 | ||
694 | /* copy a filename (allow for "..." notation, limit length) */ | 694 | /* copy a filename (allow for "..." notation, limit length) */ |
695 | extern void copy_filename(char *dst, const char *src, int size); | 695 | extern void copy_filename(char *dst, const char *src, int size); |
696 | 696 | ||
697 | /* get a random source port */ | 697 | /* get a random source port */ |
698 | extern unsigned int random_port(void); | 698 | extern unsigned int random_port(void); |
699 | 699 | ||
700 | /* Update U-Boot over TFTP */ | 700 | /* Update U-Boot over TFTP */ |
701 | extern int update_tftp(ulong addr); | 701 | extern int update_tftp(ulong addr); |
702 | 702 | ||
703 | /**********************************************************************/ | 703 | /**********************************************************************/ |
704 | 704 | ||
705 | #endif /* __NET_H__ */ | 705 | #endif /* __NET_H__ */ |
706 | 706 |
net/arp.c
1 | /* | 1 | /* |
2 | * Copied from Linux Monitor (LiMon) - Networking. | 2 | * Copied from Linux Monitor (LiMon) - Networking. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * Copyright 2000 Roland Borde | 6 | * Copyright 2000 Roland Borde |
7 | * Copyright 2000 Paolo Scaffardi | 7 | * Copyright 2000 Paolo Scaffardi |
8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de | 8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de |
9 | * SPDX-License-Identifier: GPL-2.0 | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include <common.h> | 12 | #include <common.h> |
12 | 13 | ||
13 | #include "arp.h" | 14 | #include "arp.h" |
14 | 15 | ||
15 | #ifndef CONFIG_ARP_TIMEOUT | 16 | #ifndef CONFIG_ARP_TIMEOUT |
16 | /* Milliseconds before trying ARP again */ | 17 | /* Milliseconds before trying ARP again */ |
17 | # define ARP_TIMEOUT 5000UL | 18 | # define ARP_TIMEOUT 5000UL |
18 | #else | 19 | #else |
19 | # define ARP_TIMEOUT CONFIG_ARP_TIMEOUT | 20 | # define ARP_TIMEOUT CONFIG_ARP_TIMEOUT |
20 | #endif | 21 | #endif |
21 | 22 | ||
22 | 23 | ||
23 | #ifndef CONFIG_NET_RETRY_COUNT | 24 | #ifndef CONFIG_NET_RETRY_COUNT |
24 | # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ | 25 | # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ |
25 | #else | 26 | #else |
26 | # define ARP_TIMEOUT_COUNT CONFIG_NET_RETRY_COUNT | 27 | # define ARP_TIMEOUT_COUNT CONFIG_NET_RETRY_COUNT |
27 | #endif | 28 | #endif |
28 | 29 | ||
29 | IPaddr_t NetArpWaitPacketIP; | 30 | IPaddr_t NetArpWaitPacketIP; |
30 | static IPaddr_t NetArpWaitReplyIP; | 31 | static IPaddr_t NetArpWaitReplyIP; |
31 | /* MAC address of waiting packet's destination */ | 32 | /* MAC address of waiting packet's destination */ |
32 | uchar *NetArpWaitPacketMAC; | 33 | uchar *NetArpWaitPacketMAC; |
33 | int NetArpWaitTxPacketSize; | 34 | int NetArpWaitTxPacketSize; |
34 | ulong NetArpWaitTimerStart; | 35 | ulong NetArpWaitTimerStart; |
35 | int NetArpWaitTry; | 36 | int NetArpWaitTry; |
36 | 37 | ||
37 | static uchar *NetArpTxPacket; /* THE ARP transmit packet */ | 38 | static uchar *NetArpTxPacket; /* THE ARP transmit packet */ |
38 | static uchar NetArpPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; | 39 | static uchar NetArpPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; |
39 | 40 | ||
40 | void ArpInit(void) | 41 | void ArpInit(void) |
41 | { | 42 | { |
42 | /* XXX problem with bss workaround */ | 43 | /* XXX problem with bss workaround */ |
43 | NetArpWaitPacketMAC = NULL; | 44 | NetArpWaitPacketMAC = NULL; |
44 | NetArpWaitPacketIP = 0; | 45 | NetArpWaitPacketIP = 0; |
45 | NetArpWaitReplyIP = 0; | 46 | NetArpWaitReplyIP = 0; |
46 | NetArpWaitTxPacketSize = 0; | 47 | NetArpWaitTxPacketSize = 0; |
47 | NetArpTxPacket = &NetArpPacketBuf[0] + (PKTALIGN - 1); | 48 | NetArpTxPacket = &NetArpPacketBuf[0] + (PKTALIGN - 1); |
48 | NetArpTxPacket -= (ulong)NetArpTxPacket % PKTALIGN; | 49 | NetArpTxPacket -= (ulong)NetArpTxPacket % PKTALIGN; |
49 | } | 50 | } |
50 | 51 | ||
51 | void arp_raw_request(IPaddr_t sourceIP, const uchar *targetEther, | 52 | void arp_raw_request(IPaddr_t sourceIP, const uchar *targetEther, |
52 | IPaddr_t targetIP) | 53 | IPaddr_t targetIP) |
53 | { | 54 | { |
54 | uchar *pkt; | 55 | uchar *pkt; |
55 | struct arp_hdr *arp; | 56 | struct arp_hdr *arp; |
56 | int eth_hdr_size; | 57 | int eth_hdr_size; |
57 | 58 | ||
58 | debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", NetArpWaitTry); | 59 | debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", NetArpWaitTry); |
59 | 60 | ||
60 | pkt = NetArpTxPacket; | 61 | pkt = NetArpTxPacket; |
61 | 62 | ||
62 | eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_ARP); | 63 | eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_ARP); |
63 | pkt += eth_hdr_size; | 64 | pkt += eth_hdr_size; |
64 | 65 | ||
65 | arp = (struct arp_hdr *) pkt; | 66 | arp = (struct arp_hdr *) pkt; |
66 | 67 | ||
67 | arp->ar_hrd = htons(ARP_ETHER); | 68 | arp->ar_hrd = htons(ARP_ETHER); |
68 | arp->ar_pro = htons(PROT_IP); | 69 | arp->ar_pro = htons(PROT_IP); |
69 | arp->ar_hln = ARP_HLEN; | 70 | arp->ar_hln = ARP_HLEN; |
70 | arp->ar_pln = ARP_PLEN; | 71 | arp->ar_pln = ARP_PLEN; |
71 | arp->ar_op = htons(ARPOP_REQUEST); | 72 | arp->ar_op = htons(ARPOP_REQUEST); |
72 | 73 | ||
73 | memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); /* source ET addr */ | 74 | memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); /* source ET addr */ |
74 | NetWriteIP(&arp->ar_spa, sourceIP); /* source IP addr */ | 75 | NetWriteIP(&arp->ar_spa, sourceIP); /* source IP addr */ |
75 | memcpy(&arp->ar_tha, targetEther, ARP_HLEN); /* target ET addr */ | 76 | memcpy(&arp->ar_tha, targetEther, ARP_HLEN); /* target ET addr */ |
76 | NetWriteIP(&arp->ar_tpa, targetIP); /* target IP addr */ | 77 | NetWriteIP(&arp->ar_tpa, targetIP); /* target IP addr */ |
77 | 78 | ||
78 | NetSendPacket(NetArpTxPacket, eth_hdr_size + ARP_HDR_SIZE); | 79 | NetSendPacket(NetArpTxPacket, eth_hdr_size + ARP_HDR_SIZE); |
79 | } | 80 | } |
80 | 81 | ||
81 | void ArpRequest(void) | 82 | void ArpRequest(void) |
82 | { | 83 | { |
83 | if ((NetArpWaitPacketIP & NetOurSubnetMask) != | 84 | if ((NetArpWaitPacketIP & NetOurSubnetMask) != |
84 | (NetOurIP & NetOurSubnetMask)) { | 85 | (NetOurIP & NetOurSubnetMask)) { |
85 | if (NetOurGatewayIP == 0) { | 86 | if (NetOurGatewayIP == 0) { |
86 | puts("## Warning: gatewayip needed but not set\n"); | 87 | puts("## Warning: gatewayip needed but not set\n"); |
87 | NetArpWaitReplyIP = NetArpWaitPacketIP; | 88 | NetArpWaitReplyIP = NetArpWaitPacketIP; |
88 | } else { | 89 | } else { |
89 | NetArpWaitReplyIP = NetOurGatewayIP; | 90 | NetArpWaitReplyIP = NetOurGatewayIP; |
90 | } | 91 | } |
91 | } else { | 92 | } else { |
92 | NetArpWaitReplyIP = NetArpWaitPacketIP; | 93 | NetArpWaitReplyIP = NetArpWaitPacketIP; |
93 | } | 94 | } |
94 | 95 | ||
95 | arp_raw_request(NetOurIP, NetEtherNullAddr, NetArpWaitReplyIP); | 96 | arp_raw_request(NetOurIP, NetEtherNullAddr, NetArpWaitReplyIP); |
96 | } | 97 | } |
97 | 98 | ||
98 | void ArpTimeoutCheck(void) | 99 | void ArpTimeoutCheck(void) |
99 | { | 100 | { |
100 | ulong t; | 101 | ulong t; |
101 | 102 | ||
102 | if (!NetArpWaitPacketIP) | 103 | if (!NetArpWaitPacketIP) |
103 | return; | 104 | return; |
104 | 105 | ||
105 | t = get_timer(0); | 106 | t = get_timer(0); |
106 | 107 | ||
107 | /* check for arp timeout */ | 108 | /* check for arp timeout */ |
108 | if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) { | 109 | if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) { |
109 | NetArpWaitTry++; | 110 | NetArpWaitTry++; |
110 | 111 | ||
111 | if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { | 112 | if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { |
112 | puts("\nARP Retry count exceeded; starting again\n"); | 113 | puts("\nARP Retry count exceeded; starting again\n"); |
113 | NetArpWaitTry = 0; | 114 | NetArpWaitTry = 0; |
114 | NetStartAgain(); | 115 | NetStartAgain(); |
115 | } else { | 116 | } else { |
116 | NetArpWaitTimerStart = t; | 117 | NetArpWaitTimerStart = t; |
117 | ArpRequest(); | 118 | ArpRequest(); |
118 | } | 119 | } |
119 | } | 120 | } |
120 | } | 121 | } |
121 | 122 | ||
122 | void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) | 123 | void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) |
123 | { | 124 | { |
124 | struct arp_hdr *arp; | 125 | struct arp_hdr *arp; |
125 | IPaddr_t reply_ip_addr; | 126 | IPaddr_t reply_ip_addr; |
126 | uchar *pkt; | 127 | uchar *pkt; |
127 | int eth_hdr_size; | 128 | int eth_hdr_size; |
128 | 129 | ||
129 | /* | 130 | /* |
130 | * We have to deal with two types of ARP packets: | 131 | * We have to deal with two types of ARP packets: |
131 | * - REQUEST packets will be answered by sending our | 132 | * - REQUEST packets will be answered by sending our |
132 | * IP address - if we know it. | 133 | * IP address - if we know it. |
133 | * - REPLY packates are expected only after we asked | 134 | * - REPLY packates are expected only after we asked |
134 | * for the TFTP server's or the gateway's ethernet | 135 | * for the TFTP server's or the gateway's ethernet |
135 | * address; so if we receive such a packet, we set | 136 | * address; so if we receive such a packet, we set |
136 | * the server ethernet address | 137 | * the server ethernet address |
137 | */ | 138 | */ |
138 | debug_cond(DEBUG_NET_PKT, "Got ARP\n"); | 139 | debug_cond(DEBUG_NET_PKT, "Got ARP\n"); |
139 | 140 | ||
140 | arp = (struct arp_hdr *)ip; | 141 | arp = (struct arp_hdr *)ip; |
141 | if (len < ARP_HDR_SIZE) { | 142 | if (len < ARP_HDR_SIZE) { |
142 | printf("bad length %d < %d\n", len, ARP_HDR_SIZE); | 143 | printf("bad length %d < %d\n", len, ARP_HDR_SIZE); |
143 | return; | 144 | return; |
144 | } | 145 | } |
145 | if (ntohs(arp->ar_hrd) != ARP_ETHER) | 146 | if (ntohs(arp->ar_hrd) != ARP_ETHER) |
146 | return; | 147 | return; |
147 | if (ntohs(arp->ar_pro) != PROT_IP) | 148 | if (ntohs(arp->ar_pro) != PROT_IP) |
148 | return; | 149 | return; |
149 | if (arp->ar_hln != ARP_HLEN) | 150 | if (arp->ar_hln != ARP_HLEN) |
150 | return; | 151 | return; |
151 | if (arp->ar_pln != ARP_PLEN) | 152 | if (arp->ar_pln != ARP_PLEN) |
152 | return; | 153 | return; |
153 | 154 | ||
154 | if (NetOurIP == 0) | 155 | if (NetOurIP == 0) |
155 | return; | 156 | return; |
156 | 157 | ||
157 | if (NetReadIP(&arp->ar_tpa) != NetOurIP) | 158 | if (NetReadIP(&arp->ar_tpa) != NetOurIP) |
158 | return; | 159 | return; |
159 | 160 | ||
160 | switch (ntohs(arp->ar_op)) { | 161 | switch (ntohs(arp->ar_op)) { |
161 | case ARPOP_REQUEST: | 162 | case ARPOP_REQUEST: |
162 | /* reply with our IP address */ | 163 | /* reply with our IP address */ |
163 | debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n"); | 164 | debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n"); |
164 | pkt = (uchar *)et; | 165 | pkt = (uchar *)et; |
165 | eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP); | 166 | eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP); |
166 | pkt += eth_hdr_size; | 167 | pkt += eth_hdr_size; |
167 | arp->ar_op = htons(ARPOP_REPLY); | 168 | arp->ar_op = htons(ARPOP_REPLY); |
168 | memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN); | 169 | memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN); |
169 | NetCopyIP(&arp->ar_tpa, &arp->ar_spa); | 170 | NetCopyIP(&arp->ar_tpa, &arp->ar_spa); |
170 | memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); | 171 | memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); |
171 | NetCopyIP(&arp->ar_spa, &NetOurIP); | 172 | NetCopyIP(&arp->ar_spa, &NetOurIP); |
172 | 173 | ||
173 | #ifdef CONFIG_CMD_LINK_LOCAL | 174 | #ifdef CONFIG_CMD_LINK_LOCAL |
174 | /* | 175 | /* |
175 | * Work-around for brain-damaged Cisco equipment with | 176 | * Work-around for brain-damaged Cisco equipment with |
176 | * arp-proxy enabled. | 177 | * arp-proxy enabled. |
177 | * | 178 | * |
178 | * If the requesting IP is not on our subnet, wait 5ms to | 179 | * If the requesting IP is not on our subnet, wait 5ms to |
179 | * reply to ARP request so that our reply will overwrite | 180 | * reply to ARP request so that our reply will overwrite |
180 | * the arp-proxy's instead of the other way around. | 181 | * the arp-proxy's instead of the other way around. |
181 | */ | 182 | */ |
182 | if ((NetReadIP(&arp->ar_tpa) & NetOurSubnetMask) != | 183 | if ((NetReadIP(&arp->ar_tpa) & NetOurSubnetMask) != |
183 | (NetReadIP(&arp->ar_spa) & NetOurSubnetMask)) | 184 | (NetReadIP(&arp->ar_spa) & NetOurSubnetMask)) |
184 | udelay(5000); | 185 | udelay(5000); |
185 | #endif | 186 | #endif |
186 | NetSendPacket((uchar *)et, eth_hdr_size + ARP_HDR_SIZE); | 187 | NetSendPacket((uchar *)et, eth_hdr_size + ARP_HDR_SIZE); |
187 | return; | 188 | return; |
188 | 189 | ||
189 | case ARPOP_REPLY: /* arp reply */ | 190 | case ARPOP_REPLY: /* arp reply */ |
190 | /* are we waiting for a reply */ | 191 | /* are we waiting for a reply */ |
191 | if (!NetArpWaitPacketIP) | 192 | if (!NetArpWaitPacketIP) |
192 | break; | 193 | break; |
193 | 194 | ||
194 | #ifdef CONFIG_KEEP_SERVERADDR | 195 | #ifdef CONFIG_KEEP_SERVERADDR |
195 | if (NetServerIP == NetArpWaitPacketIP) { | 196 | if (NetServerIP == NetArpWaitPacketIP) { |
196 | char buf[20]; | 197 | char buf[20]; |
197 | sprintf(buf, "%pM", &arp->ar_sha); | 198 | sprintf(buf, "%pM", &arp->ar_sha); |
198 | setenv("serveraddr", buf); | 199 | setenv("serveraddr", buf); |
199 | } | 200 | } |
200 | #endif | 201 | #endif |
201 | 202 | ||
202 | reply_ip_addr = NetReadIP(&arp->ar_spa); | 203 | reply_ip_addr = NetReadIP(&arp->ar_spa); |
203 | 204 | ||
204 | /* matched waiting packet's address */ | 205 | /* matched waiting packet's address */ |
205 | if (reply_ip_addr == NetArpWaitReplyIP) { | 206 | if (reply_ip_addr == NetArpWaitReplyIP) { |
206 | debug_cond(DEBUG_DEV_PKT, | 207 | debug_cond(DEBUG_DEV_PKT, |
207 | "Got ARP REPLY, set eth addr (%pM)\n", | 208 | "Got ARP REPLY, set eth addr (%pM)\n", |
208 | arp->ar_data); | 209 | arp->ar_data); |
209 | 210 | ||
210 | /* save address for later use */ | 211 | /* save address for later use */ |
211 | if (NetArpWaitPacketMAC != NULL) | 212 | if (NetArpWaitPacketMAC != NULL) |
212 | memcpy(NetArpWaitPacketMAC, | 213 | memcpy(NetArpWaitPacketMAC, |
213 | &arp->ar_sha, ARP_HLEN); | 214 | &arp->ar_sha, ARP_HLEN); |
214 | 215 | ||
215 | net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr, | 216 | net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr, |
216 | 0, len); | 217 | 0, len); |
217 | 218 | ||
218 | /* set the mac address in the waiting packet's header | 219 | /* set the mac address in the waiting packet's header |
219 | and transmit it */ | 220 | and transmit it */ |
220 | memcpy(((struct ethernet_hdr *)NetTxPacket)->et_dest, | 221 | memcpy(((struct ethernet_hdr *)NetTxPacket)->et_dest, |
221 | &arp->ar_sha, ARP_HLEN); | 222 | &arp->ar_sha, ARP_HLEN); |
222 | NetSendPacket(NetTxPacket, NetArpWaitTxPacketSize); | 223 | NetSendPacket(NetTxPacket, NetArpWaitTxPacketSize); |
223 | 224 | ||
224 | /* no arp request pending now */ | 225 | /* no arp request pending now */ |
225 | NetArpWaitPacketIP = 0; | 226 | NetArpWaitPacketIP = 0; |
226 | NetArpWaitTxPacketSize = 0; | 227 | NetArpWaitTxPacketSize = 0; |
227 | NetArpWaitPacketMAC = NULL; | 228 | NetArpWaitPacketMAC = NULL; |
228 | 229 | ||
229 | } | 230 | } |
230 | return; | 231 | return; |
231 | default: | 232 | default: |
232 | debug("Unexpected ARP opcode 0x%x\n", | 233 | debug("Unexpected ARP opcode 0x%x\n", |
233 | ntohs(arp->ar_op)); | 234 | ntohs(arp->ar_op)); |
234 | return; | 235 | return; |
235 | } | 236 | } |
236 | } | 237 | } |
237 | 238 |
net/arp.h
1 | /* | 1 | /* |
2 | * Copied from Linux Monitor (LiMon) - Networking. | 2 | * Copied from Linux Monitor (LiMon) - Networking. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * Copyright 2000 Roland Borde | 6 | * Copyright 2000 Roland Borde |
7 | * Copyright 2000 Paolo Scaffardi | 7 | * Copyright 2000 Paolo Scaffardi |
8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de | 8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de |
9 | * SPDX-License-Identifier: GPL-2.0 | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | #ifndef __ARP_H__ | 12 | #ifndef __ARP_H__ |
12 | #define __ARP_H__ | 13 | #define __ARP_H__ |
13 | 14 | ||
14 | #include <common.h> | 15 | #include <common.h> |
15 | 16 | ||
16 | extern IPaddr_t NetArpWaitPacketIP; | 17 | extern IPaddr_t NetArpWaitPacketIP; |
17 | /* MAC address of waiting packet's destination */ | 18 | /* MAC address of waiting packet's destination */ |
18 | extern uchar *NetArpWaitPacketMAC; | 19 | extern uchar *NetArpWaitPacketMAC; |
19 | extern int NetArpWaitTxPacketSize; | 20 | extern int NetArpWaitTxPacketSize; |
20 | extern ulong NetArpWaitTimerStart; | 21 | extern ulong NetArpWaitTimerStart; |
21 | extern int NetArpWaitTry; | 22 | extern int NetArpWaitTry; |
22 | 23 | ||
23 | void ArpInit(void); | 24 | void ArpInit(void); |
24 | void ArpRequest(void); | 25 | void ArpRequest(void); |
25 | void arp_raw_request(IPaddr_t sourceIP, const uchar *targetEther, | 26 | void arp_raw_request(IPaddr_t sourceIP, const uchar *targetEther, |
26 | IPaddr_t targetIP); | 27 | IPaddr_t targetIP); |
27 | void ArpTimeoutCheck(void); | 28 | void ArpTimeoutCheck(void); |
28 | void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len); | 29 | void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len); |
29 | 30 | ||
30 | #endif /* __ARP_H__ */ | 31 | #endif /* __ARP_H__ */ |
31 | 32 |
net/cdp.c
1 | /* | 1 | /* |
2 | * Copied from Linux Monitor (LiMon) - Networking. | 2 | * Copied from Linux Monitor (LiMon) - Networking. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * Copyright 2000 Roland Borde | 6 | * Copyright 2000 Roland Borde |
7 | * Copyright 2000 Paolo Scaffardi | 7 | * Copyright 2000 Paolo Scaffardi |
8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de | 8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de |
9 | * SPDX-License-Identifier: GPL-2.0 | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include <common.h> | 12 | #include <common.h> |
12 | #include <net.h> | 13 | #include <net.h> |
13 | #if defined(CONFIG_CDP_VERSION) | 14 | #if defined(CONFIG_CDP_VERSION) |
14 | #include <timestamp.h> | 15 | #include <timestamp.h> |
15 | #endif | 16 | #endif |
16 | 17 | ||
17 | #include "cdp.h" | 18 | #include "cdp.h" |
18 | 19 | ||
19 | /* Ethernet bcast address */ | 20 | /* Ethernet bcast address */ |
20 | const uchar NetCDPAddr[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc }; | 21 | const uchar NetCDPAddr[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc }; |
21 | 22 | ||
22 | #define CDP_DEVICE_ID_TLV 0x0001 | 23 | #define CDP_DEVICE_ID_TLV 0x0001 |
23 | #define CDP_ADDRESS_TLV 0x0002 | 24 | #define CDP_ADDRESS_TLV 0x0002 |
24 | #define CDP_PORT_ID_TLV 0x0003 | 25 | #define CDP_PORT_ID_TLV 0x0003 |
25 | #define CDP_CAPABILITIES_TLV 0x0004 | 26 | #define CDP_CAPABILITIES_TLV 0x0004 |
26 | #define CDP_VERSION_TLV 0x0005 | 27 | #define CDP_VERSION_TLV 0x0005 |
27 | #define CDP_PLATFORM_TLV 0x0006 | 28 | #define CDP_PLATFORM_TLV 0x0006 |
28 | #define CDP_NATIVE_VLAN_TLV 0x000a | 29 | #define CDP_NATIVE_VLAN_TLV 0x000a |
29 | #define CDP_APPLIANCE_VLAN_TLV 0x000e | 30 | #define CDP_APPLIANCE_VLAN_TLV 0x000e |
30 | #define CDP_TRIGGER_TLV 0x000f | 31 | #define CDP_TRIGGER_TLV 0x000f |
31 | #define CDP_POWER_CONSUMPTION_TLV 0x0010 | 32 | #define CDP_POWER_CONSUMPTION_TLV 0x0010 |
32 | #define CDP_SYSNAME_TLV 0x0014 | 33 | #define CDP_SYSNAME_TLV 0x0014 |
33 | #define CDP_SYSOBJECT_TLV 0x0015 | 34 | #define CDP_SYSOBJECT_TLV 0x0015 |
34 | #define CDP_MANAGEMENT_ADDRESS_TLV 0x0016 | 35 | #define CDP_MANAGEMENT_ADDRESS_TLV 0x0016 |
35 | 36 | ||
36 | #define CDP_TIMEOUT 250UL /* one packet every 250ms */ | 37 | #define CDP_TIMEOUT 250UL /* one packet every 250ms */ |
37 | 38 | ||
38 | static int CDPSeq; | 39 | static int CDPSeq; |
39 | static int CDPOK; | 40 | static int CDPOK; |
40 | 41 | ||
41 | ushort CDPNativeVLAN; | 42 | ushort CDPNativeVLAN; |
42 | ushort CDPApplianceVLAN; | 43 | ushort CDPApplianceVLAN; |
43 | 44 | ||
44 | static const uchar CDP_SNAP_hdr[8] = { | 45 | static const uchar CDP_SNAP_hdr[8] = { |
45 | 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00 }; | 46 | 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00 }; |
46 | 47 | ||
47 | static ushort | 48 | static ushort |
48 | CDP_compute_csum(const uchar *buff, ushort len) | 49 | CDP_compute_csum(const uchar *buff, ushort len) |
49 | { | 50 | { |
50 | ushort csum; | 51 | ushort csum; |
51 | int odd; | 52 | int odd; |
52 | ulong result = 0; | 53 | ulong result = 0; |
53 | ushort leftover; | 54 | ushort leftover; |
54 | ushort *p; | 55 | ushort *p; |
55 | 56 | ||
56 | if (len > 0) { | 57 | if (len > 0) { |
57 | odd = 1 & (ulong)buff; | 58 | odd = 1 & (ulong)buff; |
58 | if (odd) { | 59 | if (odd) { |
59 | result = *buff << 8; | 60 | result = *buff << 8; |
60 | len--; | 61 | len--; |
61 | buff++; | 62 | buff++; |
62 | } | 63 | } |
63 | while (len > 1) { | 64 | while (len > 1) { |
64 | p = (ushort *)buff; | 65 | p = (ushort *)buff; |
65 | result += *p++; | 66 | result += *p++; |
66 | buff = (uchar *)p; | 67 | buff = (uchar *)p; |
67 | if (result & 0x80000000) | 68 | if (result & 0x80000000) |
68 | result = (result & 0xFFFF) + (result >> 16); | 69 | result = (result & 0xFFFF) + (result >> 16); |
69 | len -= 2; | 70 | len -= 2; |
70 | } | 71 | } |
71 | if (len) { | 72 | if (len) { |
72 | leftover = (signed short)(*(const signed char *)buff); | 73 | leftover = (signed short)(*(const signed char *)buff); |
73 | /* | 74 | /* |
74 | * CISCO SUCKS big time! (and blows too): | 75 | * CISCO SUCKS big time! (and blows too): |
75 | * CDP uses the IP checksum algorithm with a twist; | 76 | * CDP uses the IP checksum algorithm with a twist; |
76 | * for the last byte it *sign* extends and sums. | 77 | * for the last byte it *sign* extends and sums. |
77 | */ | 78 | */ |
78 | result = (result & 0xffff0000) | | 79 | result = (result & 0xffff0000) | |
79 | ((result + leftover) & 0x0000ffff); | 80 | ((result + leftover) & 0x0000ffff); |
80 | } | 81 | } |
81 | while (result >> 16) | 82 | while (result >> 16) |
82 | result = (result & 0xFFFF) + (result >> 16); | 83 | result = (result & 0xFFFF) + (result >> 16); |
83 | 84 | ||
84 | if (odd) | 85 | if (odd) |
85 | result = ((result >> 8) & 0xff) | | 86 | result = ((result >> 8) & 0xff) | |
86 | ((result & 0xff) << 8); | 87 | ((result & 0xff) << 8); |
87 | } | 88 | } |
88 | 89 | ||
89 | /* add up 16-bit and 17-bit words for 17+c bits */ | 90 | /* add up 16-bit and 17-bit words for 17+c bits */ |
90 | result = (result & 0xffff) + (result >> 16); | 91 | result = (result & 0xffff) + (result >> 16); |
91 | /* add up 16-bit and 2-bit for 16+c bit */ | 92 | /* add up 16-bit and 2-bit for 16+c bit */ |
92 | result = (result & 0xffff) + (result >> 16); | 93 | result = (result & 0xffff) + (result >> 16); |
93 | /* add up carry.. */ | 94 | /* add up carry.. */ |
94 | result = (result & 0xffff) + (result >> 16); | 95 | result = (result & 0xffff) + (result >> 16); |
95 | 96 | ||
96 | /* negate */ | 97 | /* negate */ |
97 | csum = ~(ushort)result; | 98 | csum = ~(ushort)result; |
98 | 99 | ||
99 | /* run time endian detection */ | 100 | /* run time endian detection */ |
100 | if (csum != htons(csum)) /* little endian */ | 101 | if (csum != htons(csum)) /* little endian */ |
101 | csum = htons(csum); | 102 | csum = htons(csum); |
102 | 103 | ||
103 | return csum; | 104 | return csum; |
104 | } | 105 | } |
105 | 106 | ||
106 | static int | 107 | static int |
107 | CDPSendTrigger(void) | 108 | CDPSendTrigger(void) |
108 | { | 109 | { |
109 | uchar *pkt; | 110 | uchar *pkt; |
110 | ushort *s; | 111 | ushort *s; |
111 | ushort *cp; | 112 | ushort *cp; |
112 | struct ethernet_hdr *et; | 113 | struct ethernet_hdr *et; |
113 | int len; | 114 | int len; |
114 | ushort chksum; | 115 | ushort chksum; |
115 | #if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID) || \ | 116 | #if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID) || \ |
116 | defined(CONFIG_CDP_VERSION) || defined(CONFIG_CDP_PLATFORM) | 117 | defined(CONFIG_CDP_VERSION) || defined(CONFIG_CDP_PLATFORM) |
117 | char buf[32]; | 118 | char buf[32]; |
118 | #endif | 119 | #endif |
119 | 120 | ||
120 | pkt = NetTxPacket; | 121 | pkt = NetTxPacket; |
121 | et = (struct ethernet_hdr *)pkt; | 122 | et = (struct ethernet_hdr *)pkt; |
122 | 123 | ||
123 | /* NOTE: trigger sent not on any VLAN */ | 124 | /* NOTE: trigger sent not on any VLAN */ |
124 | 125 | ||
125 | /* form ethernet header */ | 126 | /* form ethernet header */ |
126 | memcpy(et->et_dest, NetCDPAddr, 6); | 127 | memcpy(et->et_dest, NetCDPAddr, 6); |
127 | memcpy(et->et_src, NetOurEther, 6); | 128 | memcpy(et->et_src, NetOurEther, 6); |
128 | 129 | ||
129 | pkt += ETHER_HDR_SIZE; | 130 | pkt += ETHER_HDR_SIZE; |
130 | 131 | ||
131 | /* SNAP header */ | 132 | /* SNAP header */ |
132 | memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)); | 133 | memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)); |
133 | pkt += sizeof(CDP_SNAP_hdr); | 134 | pkt += sizeof(CDP_SNAP_hdr); |
134 | 135 | ||
135 | /* CDP header */ | 136 | /* CDP header */ |
136 | *pkt++ = 0x02; /* CDP version 2 */ | 137 | *pkt++ = 0x02; /* CDP version 2 */ |
137 | *pkt++ = 180; /* TTL */ | 138 | *pkt++ = 180; /* TTL */ |
138 | s = (ushort *)pkt; | 139 | s = (ushort *)pkt; |
139 | cp = s; | 140 | cp = s; |
140 | /* checksum (0 for later calculation) */ | 141 | /* checksum (0 for later calculation) */ |
141 | *s++ = htons(0); | 142 | *s++ = htons(0); |
142 | 143 | ||
143 | /* CDP fields */ | 144 | /* CDP fields */ |
144 | #ifdef CONFIG_CDP_DEVICE_ID | 145 | #ifdef CONFIG_CDP_DEVICE_ID |
145 | *s++ = htons(CDP_DEVICE_ID_TLV); | 146 | *s++ = htons(CDP_DEVICE_ID_TLV); |
146 | *s++ = htons(CONFIG_CDP_DEVICE_ID); | 147 | *s++ = htons(CONFIG_CDP_DEVICE_ID); |
147 | sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%pm", NetOurEther); | 148 | sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%pm", NetOurEther); |
148 | memcpy((uchar *)s, buf, 16); | 149 | memcpy((uchar *)s, buf, 16); |
149 | s += 16 / 2; | 150 | s += 16 / 2; |
150 | #endif | 151 | #endif |
151 | 152 | ||
152 | #ifdef CONFIG_CDP_PORT_ID | 153 | #ifdef CONFIG_CDP_PORT_ID |
153 | *s++ = htons(CDP_PORT_ID_TLV); | 154 | *s++ = htons(CDP_PORT_ID_TLV); |
154 | memset(buf, 0, sizeof(buf)); | 155 | memset(buf, 0, sizeof(buf)); |
155 | sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index()); | 156 | sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index()); |
156 | len = strlen(buf); | 157 | len = strlen(buf); |
157 | if (len & 1) /* make it even */ | 158 | if (len & 1) /* make it even */ |
158 | len++; | 159 | len++; |
159 | *s++ = htons(len + 4); | 160 | *s++ = htons(len + 4); |
160 | memcpy((uchar *)s, buf, len); | 161 | memcpy((uchar *)s, buf, len); |
161 | s += len / 2; | 162 | s += len / 2; |
162 | #endif | 163 | #endif |
163 | 164 | ||
164 | #ifdef CONFIG_CDP_CAPABILITIES | 165 | #ifdef CONFIG_CDP_CAPABILITIES |
165 | *s++ = htons(CDP_CAPABILITIES_TLV); | 166 | *s++ = htons(CDP_CAPABILITIES_TLV); |
166 | *s++ = htons(8); | 167 | *s++ = htons(8); |
167 | *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES); | 168 | *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES); |
168 | s += 2; | 169 | s += 2; |
169 | #endif | 170 | #endif |
170 | 171 | ||
171 | #ifdef CONFIG_CDP_VERSION | 172 | #ifdef CONFIG_CDP_VERSION |
172 | *s++ = htons(CDP_VERSION_TLV); | 173 | *s++ = htons(CDP_VERSION_TLV); |
173 | memset(buf, 0, sizeof(buf)); | 174 | memset(buf, 0, sizeof(buf)); |
174 | strcpy(buf, CONFIG_CDP_VERSION); | 175 | strcpy(buf, CONFIG_CDP_VERSION); |
175 | len = strlen(buf); | 176 | len = strlen(buf); |
176 | if (len & 1) /* make it even */ | 177 | if (len & 1) /* make it even */ |
177 | len++; | 178 | len++; |
178 | *s++ = htons(len + 4); | 179 | *s++ = htons(len + 4); |
179 | memcpy((uchar *)s, buf, len); | 180 | memcpy((uchar *)s, buf, len); |
180 | s += len / 2; | 181 | s += len / 2; |
181 | #endif | 182 | #endif |
182 | 183 | ||
183 | #ifdef CONFIG_CDP_PLATFORM | 184 | #ifdef CONFIG_CDP_PLATFORM |
184 | *s++ = htons(CDP_PLATFORM_TLV); | 185 | *s++ = htons(CDP_PLATFORM_TLV); |
185 | memset(buf, 0, sizeof(buf)); | 186 | memset(buf, 0, sizeof(buf)); |
186 | strcpy(buf, CONFIG_CDP_PLATFORM); | 187 | strcpy(buf, CONFIG_CDP_PLATFORM); |
187 | len = strlen(buf); | 188 | len = strlen(buf); |
188 | if (len & 1) /* make it even */ | 189 | if (len & 1) /* make it even */ |
189 | len++; | 190 | len++; |
190 | *s++ = htons(len + 4); | 191 | *s++ = htons(len + 4); |
191 | memcpy((uchar *)s, buf, len); | 192 | memcpy((uchar *)s, buf, len); |
192 | s += len / 2; | 193 | s += len / 2; |
193 | #endif | 194 | #endif |
194 | 195 | ||
195 | #ifdef CONFIG_CDP_TRIGGER | 196 | #ifdef CONFIG_CDP_TRIGGER |
196 | *s++ = htons(CDP_TRIGGER_TLV); | 197 | *s++ = htons(CDP_TRIGGER_TLV); |
197 | *s++ = htons(8); | 198 | *s++ = htons(8); |
198 | *(ulong *)s = htonl(CONFIG_CDP_TRIGGER); | 199 | *(ulong *)s = htonl(CONFIG_CDP_TRIGGER); |
199 | s += 2; | 200 | s += 2; |
200 | #endif | 201 | #endif |
201 | 202 | ||
202 | #ifdef CONFIG_CDP_POWER_CONSUMPTION | 203 | #ifdef CONFIG_CDP_POWER_CONSUMPTION |
203 | *s++ = htons(CDP_POWER_CONSUMPTION_TLV); | 204 | *s++ = htons(CDP_POWER_CONSUMPTION_TLV); |
204 | *s++ = htons(6); | 205 | *s++ = htons(6); |
205 | *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION); | 206 | *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION); |
206 | #endif | 207 | #endif |
207 | 208 | ||
208 | /* length of ethernet packet */ | 209 | /* length of ethernet packet */ |
209 | len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE); | 210 | len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE); |
210 | et->et_protlen = htons(len); | 211 | et->et_protlen = htons(len); |
211 | 212 | ||
212 | len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr); | 213 | len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr); |
213 | chksum = CDP_compute_csum((uchar *)NetTxPacket + len, | 214 | chksum = CDP_compute_csum((uchar *)NetTxPacket + len, |
214 | (uchar *)s - (NetTxPacket + len)); | 215 | (uchar *)s - (NetTxPacket + len)); |
215 | if (chksum == 0) | 216 | if (chksum == 0) |
216 | chksum = 0xFFFF; | 217 | chksum = 0xFFFF; |
217 | *cp = htons(chksum); | 218 | *cp = htons(chksum); |
218 | 219 | ||
219 | NetSendPacket(NetTxPacket, (uchar *)s - NetTxPacket); | 220 | NetSendPacket(NetTxPacket, (uchar *)s - NetTxPacket); |
220 | return 0; | 221 | return 0; |
221 | } | 222 | } |
222 | 223 | ||
223 | static void | 224 | static void |
224 | CDPTimeout(void) | 225 | CDPTimeout(void) |
225 | { | 226 | { |
226 | CDPSeq++; | 227 | CDPSeq++; |
227 | 228 | ||
228 | if (CDPSeq < 3) { | 229 | if (CDPSeq < 3) { |
229 | NetSetTimeout(CDP_TIMEOUT, CDPTimeout); | 230 | NetSetTimeout(CDP_TIMEOUT, CDPTimeout); |
230 | CDPSendTrigger(); | 231 | CDPSendTrigger(); |
231 | return; | 232 | return; |
232 | } | 233 | } |
233 | 234 | ||
234 | /* if not OK try again */ | 235 | /* if not OK try again */ |
235 | if (!CDPOK) | 236 | if (!CDPOK) |
236 | NetStartAgain(); | 237 | NetStartAgain(); |
237 | else | 238 | else |
238 | net_set_state(NETLOOP_SUCCESS); | 239 | net_set_state(NETLOOP_SUCCESS); |
239 | } | 240 | } |
240 | 241 | ||
241 | void cdp_receive(const uchar *pkt, unsigned len) | 242 | void cdp_receive(const uchar *pkt, unsigned len) |
242 | { | 243 | { |
243 | const uchar *t; | 244 | const uchar *t; |
244 | const ushort *ss; | 245 | const ushort *ss; |
245 | ushort type, tlen; | 246 | ushort type, tlen; |
246 | ushort vlan, nvlan; | 247 | ushort vlan, nvlan; |
247 | 248 | ||
248 | /* minimum size? */ | 249 | /* minimum size? */ |
249 | if (len < sizeof(CDP_SNAP_hdr) + 4) | 250 | if (len < sizeof(CDP_SNAP_hdr) + 4) |
250 | goto pkt_short; | 251 | goto pkt_short; |
251 | 252 | ||
252 | /* check for valid CDP SNAP header */ | 253 | /* check for valid CDP SNAP header */ |
253 | if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0) | 254 | if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0) |
254 | return; | 255 | return; |
255 | 256 | ||
256 | pkt += sizeof(CDP_SNAP_hdr); | 257 | pkt += sizeof(CDP_SNAP_hdr); |
257 | len -= sizeof(CDP_SNAP_hdr); | 258 | len -= sizeof(CDP_SNAP_hdr); |
258 | 259 | ||
259 | /* Version of CDP protocol must be >= 2 and TTL != 0 */ | 260 | /* Version of CDP protocol must be >= 2 and TTL != 0 */ |
260 | if (pkt[0] < 0x02 || pkt[1] == 0) | 261 | if (pkt[0] < 0x02 || pkt[1] == 0) |
261 | return; | 262 | return; |
262 | 263 | ||
263 | /* | 264 | /* |
264 | * if version is greater than 0x02 maybe we'll have a problem; | 265 | * if version is greater than 0x02 maybe we'll have a problem; |
265 | * output a warning | 266 | * output a warning |
266 | */ | 267 | */ |
267 | if (pkt[0] != 0x02) | 268 | if (pkt[0] != 0x02) |
268 | printf("**WARNING: CDP packet received with a protocol version " | 269 | printf("**WARNING: CDP packet received with a protocol version " |
269 | "%d > 2\n", pkt[0] & 0xff); | 270 | "%d > 2\n", pkt[0] & 0xff); |
270 | 271 | ||
271 | if (CDP_compute_csum(pkt, len) != 0) | 272 | if (CDP_compute_csum(pkt, len) != 0) |
272 | return; | 273 | return; |
273 | 274 | ||
274 | pkt += 4; | 275 | pkt += 4; |
275 | len -= 4; | 276 | len -= 4; |
276 | 277 | ||
277 | vlan = htons(-1); | 278 | vlan = htons(-1); |
278 | nvlan = htons(-1); | 279 | nvlan = htons(-1); |
279 | while (len > 0) { | 280 | while (len > 0) { |
280 | if (len < 4) | 281 | if (len < 4) |
281 | goto pkt_short; | 282 | goto pkt_short; |
282 | 283 | ||
283 | ss = (const ushort *)pkt; | 284 | ss = (const ushort *)pkt; |
284 | type = ntohs(ss[0]); | 285 | type = ntohs(ss[0]); |
285 | tlen = ntohs(ss[1]); | 286 | tlen = ntohs(ss[1]); |
286 | if (tlen > len) | 287 | if (tlen > len) |
287 | goto pkt_short; | 288 | goto pkt_short; |
288 | 289 | ||
289 | pkt += tlen; | 290 | pkt += tlen; |
290 | len -= tlen; | 291 | len -= tlen; |
291 | 292 | ||
292 | ss += 2; /* point ss to the data of the TLV */ | 293 | ss += 2; /* point ss to the data of the TLV */ |
293 | tlen -= 4; | 294 | tlen -= 4; |
294 | 295 | ||
295 | switch (type) { | 296 | switch (type) { |
296 | case CDP_DEVICE_ID_TLV: | 297 | case CDP_DEVICE_ID_TLV: |
297 | break; | 298 | break; |
298 | case CDP_ADDRESS_TLV: | 299 | case CDP_ADDRESS_TLV: |
299 | break; | 300 | break; |
300 | case CDP_PORT_ID_TLV: | 301 | case CDP_PORT_ID_TLV: |
301 | break; | 302 | break; |
302 | case CDP_CAPABILITIES_TLV: | 303 | case CDP_CAPABILITIES_TLV: |
303 | break; | 304 | break; |
304 | case CDP_VERSION_TLV: | 305 | case CDP_VERSION_TLV: |
305 | break; | 306 | break; |
306 | case CDP_PLATFORM_TLV: | 307 | case CDP_PLATFORM_TLV: |
307 | break; | 308 | break; |
308 | case CDP_NATIVE_VLAN_TLV: | 309 | case CDP_NATIVE_VLAN_TLV: |
309 | nvlan = *ss; | 310 | nvlan = *ss; |
310 | break; | 311 | break; |
311 | case CDP_APPLIANCE_VLAN_TLV: | 312 | case CDP_APPLIANCE_VLAN_TLV: |
312 | t = (const uchar *)ss; | 313 | t = (const uchar *)ss; |
313 | while (tlen > 0) { | 314 | while (tlen > 0) { |
314 | if (tlen < 3) | 315 | if (tlen < 3) |
315 | goto pkt_short; | 316 | goto pkt_short; |
316 | 317 | ||
317 | ss = (const ushort *)(t + 1); | 318 | ss = (const ushort *)(t + 1); |
318 | 319 | ||
319 | #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE | 320 | #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE |
320 | if (t[0] == CONFIG_CDP_APPLIANCE_VLAN_TYPE) | 321 | if (t[0] == CONFIG_CDP_APPLIANCE_VLAN_TYPE) |
321 | vlan = *ss; | 322 | vlan = *ss; |
322 | #else | 323 | #else |
323 | /* XXX will this work; dunno */ | 324 | /* XXX will this work; dunno */ |
324 | vlan = ntohs(*ss); | 325 | vlan = ntohs(*ss); |
325 | #endif | 326 | #endif |
326 | t += 3; tlen -= 3; | 327 | t += 3; tlen -= 3; |
327 | } | 328 | } |
328 | break; | 329 | break; |
329 | case CDP_TRIGGER_TLV: | 330 | case CDP_TRIGGER_TLV: |
330 | break; | 331 | break; |
331 | case CDP_POWER_CONSUMPTION_TLV: | 332 | case CDP_POWER_CONSUMPTION_TLV: |
332 | break; | 333 | break; |
333 | case CDP_SYSNAME_TLV: | 334 | case CDP_SYSNAME_TLV: |
334 | break; | 335 | break; |
335 | case CDP_SYSOBJECT_TLV: | 336 | case CDP_SYSOBJECT_TLV: |
336 | break; | 337 | break; |
337 | case CDP_MANAGEMENT_ADDRESS_TLV: | 338 | case CDP_MANAGEMENT_ADDRESS_TLV: |
338 | break; | 339 | break; |
339 | } | 340 | } |
340 | } | 341 | } |
341 | 342 | ||
342 | CDPApplianceVLAN = vlan; | 343 | CDPApplianceVLAN = vlan; |
343 | CDPNativeVLAN = nvlan; | 344 | CDPNativeVLAN = nvlan; |
344 | 345 | ||
345 | CDPOK = 1; | 346 | CDPOK = 1; |
346 | return; | 347 | return; |
347 | 348 | ||
348 | pkt_short: | 349 | pkt_short: |
349 | printf("** CDP packet is too short\n"); | 350 | printf("** CDP packet is too short\n"); |
350 | return; | 351 | return; |
351 | } | 352 | } |
352 | 353 | ||
353 | void | 354 | void |
354 | CDPStart(void) | 355 | CDPStart(void) |
355 | { | 356 | { |
356 | printf("Using %s device\n", eth_get_name()); | 357 | printf("Using %s device\n", eth_get_name()); |
357 | CDPSeq = 0; | 358 | CDPSeq = 0; |
358 | CDPOK = 0; | 359 | CDPOK = 0; |
359 | 360 | ||
360 | CDPNativeVLAN = htons(-1); | 361 | CDPNativeVLAN = htons(-1); |
361 | CDPApplianceVLAN = htons(-1); | 362 | CDPApplianceVLAN = htons(-1); |
362 | 363 | ||
363 | NetSetTimeout(CDP_TIMEOUT, CDPTimeout); | 364 | NetSetTimeout(CDP_TIMEOUT, CDPTimeout); |
364 | 365 | ||
365 | CDPSendTrigger(); | 366 | CDPSendTrigger(); |
366 | } | 367 | } |
367 | 368 |
net/cdp.h
1 | /* | 1 | /* |
2 | * Copied from Linux Monitor (LiMon) - Networking. | 2 | * Copied from Linux Monitor (LiMon) - Networking. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * Copyright 2000 Roland Borde | 6 | * Copyright 2000 Roland Borde |
7 | * Copyright 2000 Paolo Scaffardi | 7 | * Copyright 2000 Paolo Scaffardi |
8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de | 8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de |
9 | * SPDX-License-Identifier: GPL-2.0 | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | #if defined(CONFIG_CMD_CDP) | 12 | #if defined(CONFIG_CMD_CDP) |
12 | 13 | ||
13 | #ifndef __CDP_H__ | 14 | #ifndef __CDP_H__ |
14 | #define __CDP_H__ | 15 | #define __CDP_H__ |
15 | 16 | ||
16 | void CDPStart(void); | 17 | void CDPStart(void); |
17 | /* Process a received CDP packet */ | 18 | /* Process a received CDP packet */ |
18 | void cdp_receive(const uchar *pkt, unsigned len); | 19 | void cdp_receive(const uchar *pkt, unsigned len); |
19 | 20 | ||
20 | #endif /* __CDP_H__ */ | 21 | #endif /* __CDP_H__ */ |
21 | #endif | 22 | #endif |
22 | 23 |
net/net.c
1 | /* | 1 | /* |
2 | * Copied from Linux Monitor (LiMon) - Networking. | 2 | * Copied from Linux Monitor (LiMon) - Networking. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * Copyright 2000 Roland Borde | 6 | * Copyright 2000 Roland Borde |
7 | * Copyright 2000 Paolo Scaffardi | 7 | * Copyright 2000 Paolo Scaffardi |
8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de | 8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de |
9 | * SPDX-License-Identifier: GPL-2.0 | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | /* | 12 | /* |
12 | * General Desription: | 13 | * General Desription: |
13 | * | 14 | * |
14 | * The user interface supports commands for BOOTP, RARP, and TFTP. | 15 | * The user interface supports commands for BOOTP, RARP, and TFTP. |
15 | * Also, we support ARP internally. Depending on available data, | 16 | * Also, we support ARP internally. Depending on available data, |
16 | * these interact as follows: | 17 | * these interact as follows: |
17 | * | 18 | * |
18 | * BOOTP: | 19 | * BOOTP: |
19 | * | 20 | * |
20 | * Prerequisites: - own ethernet address | 21 | * Prerequisites: - own ethernet address |
21 | * We want: - own IP address | 22 | * We want: - own IP address |
22 | * - TFTP server IP address | 23 | * - TFTP server IP address |
23 | * - name of bootfile | 24 | * - name of bootfile |
24 | * Next step: ARP | 25 | * Next step: ARP |
25 | * | 26 | * |
26 | * LINK_LOCAL: | 27 | * LINK_LOCAL: |
27 | * | 28 | * |
28 | * Prerequisites: - own ethernet address | 29 | * Prerequisites: - own ethernet address |
29 | * We want: - own IP address | 30 | * We want: - own IP address |
30 | * Next step: ARP | 31 | * Next step: ARP |
31 | * | 32 | * |
32 | * RARP: | 33 | * RARP: |
33 | * | 34 | * |
34 | * Prerequisites: - own ethernet address | 35 | * Prerequisites: - own ethernet address |
35 | * We want: - own IP address | 36 | * We want: - own IP address |
36 | * - TFTP server IP address | 37 | * - TFTP server IP address |
37 | * Next step: ARP | 38 | * Next step: ARP |
38 | * | 39 | * |
39 | * ARP: | 40 | * ARP: |
40 | * | 41 | * |
41 | * Prerequisites: - own ethernet address | 42 | * Prerequisites: - own ethernet address |
42 | * - own IP address | 43 | * - own IP address |
43 | * - TFTP server IP address | 44 | * - TFTP server IP address |
44 | * We want: - TFTP server ethernet address | 45 | * We want: - TFTP server ethernet address |
45 | * Next step: TFTP | 46 | * Next step: TFTP |
46 | * | 47 | * |
47 | * DHCP: | 48 | * DHCP: |
48 | * | 49 | * |
49 | * Prerequisites: - own ethernet address | 50 | * Prerequisites: - own ethernet address |
50 | * We want: - IP, Netmask, ServerIP, Gateway IP | 51 | * We want: - IP, Netmask, ServerIP, Gateway IP |
51 | * - bootfilename, lease time | 52 | * - bootfilename, lease time |
52 | * Next step: - TFTP | 53 | * Next step: - TFTP |
53 | * | 54 | * |
54 | * TFTP: | 55 | * TFTP: |
55 | * | 56 | * |
56 | * Prerequisites: - own ethernet address | 57 | * Prerequisites: - own ethernet address |
57 | * - own IP address | 58 | * - own IP address |
58 | * - TFTP server IP address | 59 | * - TFTP server IP address |
59 | * - TFTP server ethernet address | 60 | * - TFTP server ethernet address |
60 | * - name of bootfile (if unknown, we use a default name | 61 | * - name of bootfile (if unknown, we use a default name |
61 | * derived from our own IP address) | 62 | * derived from our own IP address) |
62 | * We want: - load the boot file | 63 | * We want: - load the boot file |
63 | * Next step: none | 64 | * Next step: none |
64 | * | 65 | * |
65 | * NFS: | 66 | * NFS: |
66 | * | 67 | * |
67 | * Prerequisites: - own ethernet address | 68 | * Prerequisites: - own ethernet address |
68 | * - own IP address | 69 | * - own IP address |
69 | * - name of bootfile (if unknown, we use a default name | 70 | * - name of bootfile (if unknown, we use a default name |
70 | * derived from our own IP address) | 71 | * derived from our own IP address) |
71 | * We want: - load the boot file | 72 | * We want: - load the boot file |
72 | * Next step: none | 73 | * Next step: none |
73 | * | 74 | * |
74 | * SNTP: | 75 | * SNTP: |
75 | * | 76 | * |
76 | * Prerequisites: - own ethernet address | 77 | * Prerequisites: - own ethernet address |
77 | * - own IP address | 78 | * - own IP address |
78 | * We want: - network time | 79 | * We want: - network time |
79 | * Next step: none | 80 | * Next step: none |
80 | */ | 81 | */ |
81 | 82 | ||
82 | 83 | ||
83 | #include <common.h> | 84 | #include <common.h> |
84 | #include <command.h> | 85 | #include <command.h> |
85 | #include <environment.h> | 86 | #include <environment.h> |
86 | #include <net.h> | 87 | #include <net.h> |
87 | #if defined(CONFIG_STATUS_LED) | 88 | #if defined(CONFIG_STATUS_LED) |
88 | #include <miiphy.h> | 89 | #include <miiphy.h> |
89 | #include <status_led.h> | 90 | #include <status_led.h> |
90 | #endif | 91 | #endif |
91 | #include <watchdog.h> | 92 | #include <watchdog.h> |
92 | #include <linux/compiler.h> | 93 | #include <linux/compiler.h> |
93 | #include "arp.h" | 94 | #include "arp.h" |
94 | #include "bootp.h" | 95 | #include "bootp.h" |
95 | #include "cdp.h" | 96 | #include "cdp.h" |
96 | #if defined(CONFIG_CMD_DNS) | 97 | #if defined(CONFIG_CMD_DNS) |
97 | #include "dns.h" | 98 | #include "dns.h" |
98 | #endif | 99 | #endif |
99 | #include "link_local.h" | 100 | #include "link_local.h" |
100 | #include "nfs.h" | 101 | #include "nfs.h" |
101 | #include "ping.h" | 102 | #include "ping.h" |
102 | #include "rarp.h" | 103 | #include "rarp.h" |
103 | #if defined(CONFIG_CMD_SNTP) | 104 | #if defined(CONFIG_CMD_SNTP) |
104 | #include "sntp.h" | 105 | #include "sntp.h" |
105 | #endif | 106 | #endif |
106 | #include "tftp.h" | 107 | #include "tftp.h" |
107 | 108 | ||
108 | DECLARE_GLOBAL_DATA_PTR; | 109 | DECLARE_GLOBAL_DATA_PTR; |
109 | 110 | ||
110 | /** BOOTP EXTENTIONS **/ | 111 | /** BOOTP EXTENTIONS **/ |
111 | 112 | ||
112 | /* Our subnet mask (0=unknown) */ | 113 | /* Our subnet mask (0=unknown) */ |
113 | IPaddr_t NetOurSubnetMask; | 114 | IPaddr_t NetOurSubnetMask; |
114 | /* Our gateways IP address */ | 115 | /* Our gateways IP address */ |
115 | IPaddr_t NetOurGatewayIP; | 116 | IPaddr_t NetOurGatewayIP; |
116 | /* Our DNS IP address */ | 117 | /* Our DNS IP address */ |
117 | IPaddr_t NetOurDNSIP; | 118 | IPaddr_t NetOurDNSIP; |
118 | #if defined(CONFIG_BOOTP_DNS2) | 119 | #if defined(CONFIG_BOOTP_DNS2) |
119 | /* Our 2nd DNS IP address */ | 120 | /* Our 2nd DNS IP address */ |
120 | IPaddr_t NetOurDNS2IP; | 121 | IPaddr_t NetOurDNS2IP; |
121 | #endif | 122 | #endif |
122 | /* Our NIS domain */ | 123 | /* Our NIS domain */ |
123 | char NetOurNISDomain[32] = {0,}; | 124 | char NetOurNISDomain[32] = {0,}; |
124 | /* Our hostname */ | 125 | /* Our hostname */ |
125 | char NetOurHostName[32] = {0,}; | 126 | char NetOurHostName[32] = {0,}; |
126 | /* Our bootpath */ | 127 | /* Our bootpath */ |
127 | char NetOurRootPath[64] = {0,}; | 128 | char NetOurRootPath[64] = {0,}; |
128 | /* Our bootfile size in blocks */ | 129 | /* Our bootfile size in blocks */ |
129 | ushort NetBootFileSize; | 130 | ushort NetBootFileSize; |
130 | 131 | ||
131 | #ifdef CONFIG_MCAST_TFTP /* Multicast TFTP */ | 132 | #ifdef CONFIG_MCAST_TFTP /* Multicast TFTP */ |
132 | IPaddr_t Mcast_addr; | 133 | IPaddr_t Mcast_addr; |
133 | #endif | 134 | #endif |
134 | 135 | ||
135 | /** END OF BOOTP EXTENTIONS **/ | 136 | /** END OF BOOTP EXTENTIONS **/ |
136 | 137 | ||
137 | /* The actual transferred size of the bootfile (in bytes) */ | 138 | /* The actual transferred size of the bootfile (in bytes) */ |
138 | ulong NetBootFileXferSize; | 139 | ulong NetBootFileXferSize; |
139 | /* Our ethernet address */ | 140 | /* Our ethernet address */ |
140 | uchar NetOurEther[6]; | 141 | uchar NetOurEther[6]; |
141 | /* Boot server enet address */ | 142 | /* Boot server enet address */ |
142 | uchar NetServerEther[6]; | 143 | uchar NetServerEther[6]; |
143 | /* Our IP addr (0 = unknown) */ | 144 | /* Our IP addr (0 = unknown) */ |
144 | IPaddr_t NetOurIP; | 145 | IPaddr_t NetOurIP; |
145 | /* Server IP addr (0 = unknown) */ | 146 | /* Server IP addr (0 = unknown) */ |
146 | IPaddr_t NetServerIP; | 147 | IPaddr_t NetServerIP; |
147 | /* Current receive packet */ | 148 | /* Current receive packet */ |
148 | uchar *NetRxPacket; | 149 | uchar *NetRxPacket; |
149 | /* Current rx packet length */ | 150 | /* Current rx packet length */ |
150 | int NetRxPacketLen; | 151 | int NetRxPacketLen; |
151 | /* IP packet ID */ | 152 | /* IP packet ID */ |
152 | unsigned NetIPID; | 153 | unsigned NetIPID; |
153 | /* Ethernet bcast address */ | 154 | /* Ethernet bcast address */ |
154 | uchar NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 155 | uchar NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
155 | uchar NetEtherNullAddr[6]; | 156 | uchar NetEtherNullAddr[6]; |
156 | #ifdef CONFIG_API | 157 | #ifdef CONFIG_API |
157 | void (*push_packet)(void *, int len) = 0; | 158 | void (*push_packet)(void *, int len) = 0; |
158 | #endif | 159 | #endif |
159 | /* Network loop state */ | 160 | /* Network loop state */ |
160 | enum net_loop_state net_state; | 161 | enum net_loop_state net_state; |
161 | /* Tried all network devices */ | 162 | /* Tried all network devices */ |
162 | int NetRestartWrap; | 163 | int NetRestartWrap; |
163 | /* Network loop restarted */ | 164 | /* Network loop restarted */ |
164 | static int NetRestarted; | 165 | static int NetRestarted; |
165 | /* At least one device configured */ | 166 | /* At least one device configured */ |
166 | static int NetDevExists; | 167 | static int NetDevExists; |
167 | 168 | ||
168 | /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */ | 169 | /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */ |
169 | /* default is without VLAN */ | 170 | /* default is without VLAN */ |
170 | ushort NetOurVLAN = 0xFFFF; | 171 | ushort NetOurVLAN = 0xFFFF; |
171 | /* ditto */ | 172 | /* ditto */ |
172 | ushort NetOurNativeVLAN = 0xFFFF; | 173 | ushort NetOurNativeVLAN = 0xFFFF; |
173 | 174 | ||
174 | /* Boot File name */ | 175 | /* Boot File name */ |
175 | char BootFile[128]; | 176 | char BootFile[128]; |
176 | 177 | ||
177 | #if defined(CONFIG_CMD_SNTP) | 178 | #if defined(CONFIG_CMD_SNTP) |
178 | /* NTP server IP address */ | 179 | /* NTP server IP address */ |
179 | IPaddr_t NetNtpServerIP; | 180 | IPaddr_t NetNtpServerIP; |
180 | /* offset time from UTC */ | 181 | /* offset time from UTC */ |
181 | int NetTimeOffset; | 182 | int NetTimeOffset; |
182 | #endif | 183 | #endif |
183 | 184 | ||
184 | static uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; | 185 | static uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; |
185 | 186 | ||
186 | /* Receive packet */ | 187 | /* Receive packet */ |
187 | uchar *NetRxPackets[PKTBUFSRX]; | 188 | uchar *NetRxPackets[PKTBUFSRX]; |
188 | 189 | ||
189 | /* Current UDP RX packet handler */ | 190 | /* Current UDP RX packet handler */ |
190 | static rxhand_f *udp_packet_handler; | 191 | static rxhand_f *udp_packet_handler; |
191 | /* Current ARP RX packet handler */ | 192 | /* Current ARP RX packet handler */ |
192 | static rxhand_f *arp_packet_handler; | 193 | static rxhand_f *arp_packet_handler; |
193 | #ifdef CONFIG_CMD_TFTPPUT | 194 | #ifdef CONFIG_CMD_TFTPPUT |
194 | /* Current ICMP rx handler */ | 195 | /* Current ICMP rx handler */ |
195 | static rxhand_icmp_f *packet_icmp_handler; | 196 | static rxhand_icmp_f *packet_icmp_handler; |
196 | #endif | 197 | #endif |
197 | /* Current timeout handler */ | 198 | /* Current timeout handler */ |
198 | static thand_f *timeHandler; | 199 | static thand_f *timeHandler; |
199 | /* Time base value */ | 200 | /* Time base value */ |
200 | static ulong timeStart; | 201 | static ulong timeStart; |
201 | /* Current timeout value */ | 202 | /* Current timeout value */ |
202 | static ulong timeDelta; | 203 | static ulong timeDelta; |
203 | /* THE transmit packet */ | 204 | /* THE transmit packet */ |
204 | uchar *NetTxPacket; | 205 | uchar *NetTxPacket; |
205 | 206 | ||
206 | static int net_check_prereq(enum proto_t protocol); | 207 | static int net_check_prereq(enum proto_t protocol); |
207 | 208 | ||
208 | static int NetTryCount; | 209 | static int NetTryCount; |
209 | 210 | ||
210 | int __maybe_unused net_busy_flag; | 211 | int __maybe_unused net_busy_flag; |
211 | 212 | ||
212 | /**********************************************************************/ | 213 | /**********************************************************************/ |
213 | 214 | ||
214 | static int on_bootfile(const char *name, const char *value, enum env_op op, | 215 | static int on_bootfile(const char *name, const char *value, enum env_op op, |
215 | int flags) | 216 | int flags) |
216 | { | 217 | { |
217 | switch (op) { | 218 | switch (op) { |
218 | case env_op_create: | 219 | case env_op_create: |
219 | case env_op_overwrite: | 220 | case env_op_overwrite: |
220 | copy_filename(BootFile, value, sizeof(BootFile)); | 221 | copy_filename(BootFile, value, sizeof(BootFile)); |
221 | break; | 222 | break; |
222 | default: | 223 | default: |
223 | break; | 224 | break; |
224 | } | 225 | } |
225 | 226 | ||
226 | return 0; | 227 | return 0; |
227 | } | 228 | } |
228 | U_BOOT_ENV_CALLBACK(bootfile, on_bootfile); | 229 | U_BOOT_ENV_CALLBACK(bootfile, on_bootfile); |
229 | 230 | ||
230 | /* | 231 | /* |
231 | * Check if autoload is enabled. If so, use either NFS or TFTP to download | 232 | * Check if autoload is enabled. If so, use either NFS or TFTP to download |
232 | * the boot file. | 233 | * the boot file. |
233 | */ | 234 | */ |
234 | void net_auto_load(void) | 235 | void net_auto_load(void) |
235 | { | 236 | { |
236 | #if defined(CONFIG_CMD_NFS) | 237 | #if defined(CONFIG_CMD_NFS) |
237 | const char *s = getenv("autoload"); | 238 | const char *s = getenv("autoload"); |
238 | 239 | ||
239 | if (s != NULL && strcmp(s, "NFS") == 0) { | 240 | if (s != NULL && strcmp(s, "NFS") == 0) { |
240 | /* | 241 | /* |
241 | * Use NFS to load the bootfile. | 242 | * Use NFS to load the bootfile. |
242 | */ | 243 | */ |
243 | NfsStart(); | 244 | NfsStart(); |
244 | return; | 245 | return; |
245 | } | 246 | } |
246 | #endif | 247 | #endif |
247 | if (getenv_yesno("autoload") == 0) { | 248 | if (getenv_yesno("autoload") == 0) { |
248 | /* | 249 | /* |
249 | * Just use BOOTP/RARP to configure system; | 250 | * Just use BOOTP/RARP to configure system; |
250 | * Do not use TFTP to load the bootfile. | 251 | * Do not use TFTP to load the bootfile. |
251 | */ | 252 | */ |
252 | net_set_state(NETLOOP_SUCCESS); | 253 | net_set_state(NETLOOP_SUCCESS); |
253 | return; | 254 | return; |
254 | } | 255 | } |
255 | TftpStart(TFTPGET); | 256 | TftpStart(TFTPGET); |
256 | } | 257 | } |
257 | 258 | ||
258 | static void NetInitLoop(void) | 259 | static void NetInitLoop(void) |
259 | { | 260 | { |
260 | static int env_changed_id; | 261 | static int env_changed_id; |
261 | int env_id = get_env_id(); | 262 | int env_id = get_env_id(); |
262 | 263 | ||
263 | /* update only when the environment has changed */ | 264 | /* update only when the environment has changed */ |
264 | if (env_changed_id != env_id) { | 265 | if (env_changed_id != env_id) { |
265 | NetOurIP = getenv_IPaddr("ipaddr"); | 266 | NetOurIP = getenv_IPaddr("ipaddr"); |
266 | NetOurGatewayIP = getenv_IPaddr("gatewayip"); | 267 | NetOurGatewayIP = getenv_IPaddr("gatewayip"); |
267 | NetOurSubnetMask = getenv_IPaddr("netmask"); | 268 | NetOurSubnetMask = getenv_IPaddr("netmask"); |
268 | NetServerIP = getenv_IPaddr("serverip"); | 269 | NetServerIP = getenv_IPaddr("serverip"); |
269 | NetOurNativeVLAN = getenv_VLAN("nvlan"); | 270 | NetOurNativeVLAN = getenv_VLAN("nvlan"); |
270 | NetOurVLAN = getenv_VLAN("vlan"); | 271 | NetOurVLAN = getenv_VLAN("vlan"); |
271 | #if defined(CONFIG_CMD_DNS) | 272 | #if defined(CONFIG_CMD_DNS) |
272 | NetOurDNSIP = getenv_IPaddr("dnsip"); | 273 | NetOurDNSIP = getenv_IPaddr("dnsip"); |
273 | #endif | 274 | #endif |
274 | env_changed_id = env_id; | 275 | env_changed_id = env_id; |
275 | } | 276 | } |
276 | if (eth_get_dev()) | 277 | if (eth_get_dev()) |
277 | memcpy(NetOurEther, eth_get_dev()->enetaddr, 6); | 278 | memcpy(NetOurEther, eth_get_dev()->enetaddr, 6); |
278 | 279 | ||
279 | return; | 280 | return; |
280 | } | 281 | } |
281 | 282 | ||
282 | static void net_clear_handlers(void) | 283 | static void net_clear_handlers(void) |
283 | { | 284 | { |
284 | net_set_udp_handler(NULL); | 285 | net_set_udp_handler(NULL); |
285 | net_set_arp_handler(NULL); | 286 | net_set_arp_handler(NULL); |
286 | NetSetTimeout(0, NULL); | 287 | NetSetTimeout(0, NULL); |
287 | } | 288 | } |
288 | 289 | ||
289 | static void net_cleanup_loop(void) | 290 | static void net_cleanup_loop(void) |
290 | { | 291 | { |
291 | net_clear_handlers(); | 292 | net_clear_handlers(); |
292 | } | 293 | } |
293 | 294 | ||
294 | void net_init(void) | 295 | void net_init(void) |
295 | { | 296 | { |
296 | static int first_call = 1; | 297 | static int first_call = 1; |
297 | 298 | ||
298 | if (first_call) { | 299 | if (first_call) { |
299 | /* | 300 | /* |
300 | * Setup packet buffers, aligned correctly. | 301 | * Setup packet buffers, aligned correctly. |
301 | */ | 302 | */ |
302 | int i; | 303 | int i; |
303 | 304 | ||
304 | NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); | 305 | NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); |
305 | NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; | 306 | NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; |
306 | for (i = 0; i < PKTBUFSRX; i++) | 307 | for (i = 0; i < PKTBUFSRX; i++) |
307 | NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN; | 308 | NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN; |
308 | 309 | ||
309 | ArpInit(); | 310 | ArpInit(); |
310 | net_clear_handlers(); | 311 | net_clear_handlers(); |
311 | 312 | ||
312 | /* Only need to setup buffer pointers once. */ | 313 | /* Only need to setup buffer pointers once. */ |
313 | first_call = 0; | 314 | first_call = 0; |
314 | } | 315 | } |
315 | 316 | ||
316 | NetInitLoop(); | 317 | NetInitLoop(); |
317 | } | 318 | } |
318 | 319 | ||
319 | /**********************************************************************/ | 320 | /**********************************************************************/ |
320 | /* | 321 | /* |
321 | * Main network processing loop. | 322 | * Main network processing loop. |
322 | */ | 323 | */ |
323 | 324 | ||
324 | int NetLoop(enum proto_t protocol) | 325 | int NetLoop(enum proto_t protocol) |
325 | { | 326 | { |
326 | bd_t *bd = gd->bd; | 327 | bd_t *bd = gd->bd; |
327 | int ret = -1; | 328 | int ret = -1; |
328 | 329 | ||
329 | NetRestarted = 0; | 330 | NetRestarted = 0; |
330 | NetDevExists = 0; | 331 | NetDevExists = 0; |
331 | NetTryCount = 1; | 332 | NetTryCount = 1; |
332 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Entry\n"); | 333 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Entry\n"); |
333 | 334 | ||
334 | bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); | 335 | bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); |
335 | net_init(); | 336 | net_init(); |
336 | if (eth_is_on_demand_init() || protocol != NETCONS) { | 337 | if (eth_is_on_demand_init() || protocol != NETCONS) { |
337 | eth_halt(); | 338 | eth_halt(); |
338 | eth_set_current(); | 339 | eth_set_current(); |
339 | if (eth_init(bd) < 0) { | 340 | if (eth_init(bd) < 0) { |
340 | eth_halt(); | 341 | eth_halt(); |
341 | return -1; | 342 | return -1; |
342 | } | 343 | } |
343 | } else | 344 | } else |
344 | eth_init_state_only(bd); | 345 | eth_init_state_only(bd); |
345 | 346 | ||
346 | restart: | 347 | restart: |
347 | #ifdef CONFIG_USB_KEYBOARD | 348 | #ifdef CONFIG_USB_KEYBOARD |
348 | net_busy_flag = 0; | 349 | net_busy_flag = 0; |
349 | #endif | 350 | #endif |
350 | net_set_state(NETLOOP_CONTINUE); | 351 | net_set_state(NETLOOP_CONTINUE); |
351 | 352 | ||
352 | /* | 353 | /* |
353 | * Start the ball rolling with the given start function. From | 354 | * Start the ball rolling with the given start function. From |
354 | * here on, this code is a state machine driven by received | 355 | * here on, this code is a state machine driven by received |
355 | * packets and timer events. | 356 | * packets and timer events. |
356 | */ | 357 | */ |
357 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Init\n"); | 358 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Init\n"); |
358 | NetInitLoop(); | 359 | NetInitLoop(); |
359 | 360 | ||
360 | switch (net_check_prereq(protocol)) { | 361 | switch (net_check_prereq(protocol)) { |
361 | case 1: | 362 | case 1: |
362 | /* network not configured */ | 363 | /* network not configured */ |
363 | eth_halt(); | 364 | eth_halt(); |
364 | return -1; | 365 | return -1; |
365 | 366 | ||
366 | case 2: | 367 | case 2: |
367 | /* network device not configured */ | 368 | /* network device not configured */ |
368 | break; | 369 | break; |
369 | 370 | ||
370 | case 0: | 371 | case 0: |
371 | NetDevExists = 1; | 372 | NetDevExists = 1; |
372 | NetBootFileXferSize = 0; | 373 | NetBootFileXferSize = 0; |
373 | switch (protocol) { | 374 | switch (protocol) { |
374 | case TFTPGET: | 375 | case TFTPGET: |
375 | #ifdef CONFIG_CMD_TFTPPUT | 376 | #ifdef CONFIG_CMD_TFTPPUT |
376 | case TFTPPUT: | 377 | case TFTPPUT: |
377 | #endif | 378 | #endif |
378 | /* always use ARP to get server ethernet address */ | 379 | /* always use ARP to get server ethernet address */ |
379 | TftpStart(protocol); | 380 | TftpStart(protocol); |
380 | break; | 381 | break; |
381 | #ifdef CONFIG_CMD_TFTPSRV | 382 | #ifdef CONFIG_CMD_TFTPSRV |
382 | case TFTPSRV: | 383 | case TFTPSRV: |
383 | TftpStartServer(); | 384 | TftpStartServer(); |
384 | break; | 385 | break; |
385 | #endif | 386 | #endif |
386 | #if defined(CONFIG_CMD_DHCP) | 387 | #if defined(CONFIG_CMD_DHCP) |
387 | case DHCP: | 388 | case DHCP: |
388 | BootpReset(); | 389 | BootpReset(); |
389 | NetOurIP = 0; | 390 | NetOurIP = 0; |
390 | DhcpRequest(); /* Basically same as BOOTP */ | 391 | DhcpRequest(); /* Basically same as BOOTP */ |
391 | break; | 392 | break; |
392 | #endif | 393 | #endif |
393 | 394 | ||
394 | case BOOTP: | 395 | case BOOTP: |
395 | BootpReset(); | 396 | BootpReset(); |
396 | NetOurIP = 0; | 397 | NetOurIP = 0; |
397 | BootpRequest(); | 398 | BootpRequest(); |
398 | break; | 399 | break; |
399 | 400 | ||
400 | #if defined(CONFIG_CMD_RARP) | 401 | #if defined(CONFIG_CMD_RARP) |
401 | case RARP: | 402 | case RARP: |
402 | RarpTry = 0; | 403 | RarpTry = 0; |
403 | NetOurIP = 0; | 404 | NetOurIP = 0; |
404 | RarpRequest(); | 405 | RarpRequest(); |
405 | break; | 406 | break; |
406 | #endif | 407 | #endif |
407 | #if defined(CONFIG_CMD_PING) | 408 | #if defined(CONFIG_CMD_PING) |
408 | case PING: | 409 | case PING: |
409 | ping_start(); | 410 | ping_start(); |
410 | break; | 411 | break; |
411 | #endif | 412 | #endif |
412 | #if defined(CONFIG_CMD_NFS) | 413 | #if defined(CONFIG_CMD_NFS) |
413 | case NFS: | 414 | case NFS: |
414 | NfsStart(); | 415 | NfsStart(); |
415 | break; | 416 | break; |
416 | #endif | 417 | #endif |
417 | #if defined(CONFIG_CMD_CDP) | 418 | #if defined(CONFIG_CMD_CDP) |
418 | case CDP: | 419 | case CDP: |
419 | CDPStart(); | 420 | CDPStart(); |
420 | break; | 421 | break; |
421 | #endif | 422 | #endif |
422 | #if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD) | 423 | #if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD) |
423 | case NETCONS: | 424 | case NETCONS: |
424 | NcStart(); | 425 | NcStart(); |
425 | break; | 426 | break; |
426 | #endif | 427 | #endif |
427 | #if defined(CONFIG_CMD_SNTP) | 428 | #if defined(CONFIG_CMD_SNTP) |
428 | case SNTP: | 429 | case SNTP: |
429 | SntpStart(); | 430 | SntpStart(); |
430 | break; | 431 | break; |
431 | #endif | 432 | #endif |
432 | #if defined(CONFIG_CMD_DNS) | 433 | #if defined(CONFIG_CMD_DNS) |
433 | case DNS: | 434 | case DNS: |
434 | DnsStart(); | 435 | DnsStart(); |
435 | break; | 436 | break; |
436 | #endif | 437 | #endif |
437 | #if defined(CONFIG_CMD_LINK_LOCAL) | 438 | #if defined(CONFIG_CMD_LINK_LOCAL) |
438 | case LINKLOCAL: | 439 | case LINKLOCAL: |
439 | link_local_start(); | 440 | link_local_start(); |
440 | break; | 441 | break; |
441 | #endif | 442 | #endif |
442 | default: | 443 | default: |
443 | break; | 444 | break; |
444 | } | 445 | } |
445 | 446 | ||
446 | break; | 447 | break; |
447 | } | 448 | } |
448 | 449 | ||
449 | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) | 450 | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) |
450 | #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ | 451 | #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ |
451 | defined(CONFIG_STATUS_LED) && \ | 452 | defined(CONFIG_STATUS_LED) && \ |
452 | defined(STATUS_LED_RED) | 453 | defined(STATUS_LED_RED) |
453 | /* | 454 | /* |
454 | * Echo the inverted link state to the fault LED. | 455 | * Echo the inverted link state to the fault LED. |
455 | */ | 456 | */ |
456 | if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) | 457 | if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) |
457 | status_led_set(STATUS_LED_RED, STATUS_LED_OFF); | 458 | status_led_set(STATUS_LED_RED, STATUS_LED_OFF); |
458 | else | 459 | else |
459 | status_led_set(STATUS_LED_RED, STATUS_LED_ON); | 460 | status_led_set(STATUS_LED_RED, STATUS_LED_ON); |
460 | #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ | 461 | #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ |
461 | #endif /* CONFIG_MII, ... */ | 462 | #endif /* CONFIG_MII, ... */ |
462 | #ifdef CONFIG_USB_KEYBOARD | 463 | #ifdef CONFIG_USB_KEYBOARD |
463 | net_busy_flag = 1; | 464 | net_busy_flag = 1; |
464 | #endif | 465 | #endif |
465 | 466 | ||
466 | /* | 467 | /* |
467 | * Main packet reception loop. Loop receiving packets until | 468 | * Main packet reception loop. Loop receiving packets until |
468 | * someone sets `net_state' to a state that terminates. | 469 | * someone sets `net_state' to a state that terminates. |
469 | */ | 470 | */ |
470 | for (;;) { | 471 | for (;;) { |
471 | WATCHDOG_RESET(); | 472 | WATCHDOG_RESET(); |
472 | #ifdef CONFIG_SHOW_ACTIVITY | 473 | #ifdef CONFIG_SHOW_ACTIVITY |
473 | show_activity(1); | 474 | show_activity(1); |
474 | #endif | 475 | #endif |
475 | /* | 476 | /* |
476 | * Check the ethernet for a new packet. The ethernet | 477 | * Check the ethernet for a new packet. The ethernet |
477 | * receive routine will process it. | 478 | * receive routine will process it. |
478 | */ | 479 | */ |
479 | eth_rx(); | 480 | eth_rx(); |
480 | 481 | ||
481 | /* | 482 | /* |
482 | * Abort if ctrl-c was pressed. | 483 | * Abort if ctrl-c was pressed. |
483 | */ | 484 | */ |
484 | if (ctrlc()) { | 485 | if (ctrlc()) { |
485 | /* cancel any ARP that may not have completed */ | 486 | /* cancel any ARP that may not have completed */ |
486 | NetArpWaitPacketIP = 0; | 487 | NetArpWaitPacketIP = 0; |
487 | 488 | ||
488 | net_cleanup_loop(); | 489 | net_cleanup_loop(); |
489 | eth_halt(); | 490 | eth_halt(); |
490 | /* Invalidate the last protocol */ | 491 | /* Invalidate the last protocol */ |
491 | eth_set_last_protocol(BOOTP); | 492 | eth_set_last_protocol(BOOTP); |
492 | 493 | ||
493 | puts("\nAbort\n"); | 494 | puts("\nAbort\n"); |
494 | /* include a debug print as well incase the debug | 495 | /* include a debug print as well incase the debug |
495 | messages are directed to stderr */ | 496 | messages are directed to stderr */ |
496 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Abort!\n"); | 497 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Abort!\n"); |
497 | goto done; | 498 | goto done; |
498 | } | 499 | } |
499 | 500 | ||
500 | ArpTimeoutCheck(); | 501 | ArpTimeoutCheck(); |
501 | 502 | ||
502 | /* | 503 | /* |
503 | * Check for a timeout, and run the timeout handler | 504 | * Check for a timeout, and run the timeout handler |
504 | * if we have one. | 505 | * if we have one. |
505 | */ | 506 | */ |
506 | if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) { | 507 | if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) { |
507 | thand_f *x; | 508 | thand_f *x; |
508 | 509 | ||
509 | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) | 510 | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) |
510 | #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ | 511 | #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ |
511 | defined(CONFIG_STATUS_LED) && \ | 512 | defined(CONFIG_STATUS_LED) && \ |
512 | defined(STATUS_LED_RED) | 513 | defined(STATUS_LED_RED) |
513 | /* | 514 | /* |
514 | * Echo the inverted link state to the fault LED. | 515 | * Echo the inverted link state to the fault LED. |
515 | */ | 516 | */ |
516 | if (miiphy_link(eth_get_dev()->name, | 517 | if (miiphy_link(eth_get_dev()->name, |
517 | CONFIG_SYS_FAULT_MII_ADDR)) { | 518 | CONFIG_SYS_FAULT_MII_ADDR)) { |
518 | status_led_set(STATUS_LED_RED, STATUS_LED_OFF); | 519 | status_led_set(STATUS_LED_RED, STATUS_LED_OFF); |
519 | } else { | 520 | } else { |
520 | status_led_set(STATUS_LED_RED, STATUS_LED_ON); | 521 | status_led_set(STATUS_LED_RED, STATUS_LED_ON); |
521 | } | 522 | } |
522 | #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ | 523 | #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ |
523 | #endif /* CONFIG_MII, ... */ | 524 | #endif /* CONFIG_MII, ... */ |
524 | debug_cond(DEBUG_INT_STATE, "--- NetLoop timeout\n"); | 525 | debug_cond(DEBUG_INT_STATE, "--- NetLoop timeout\n"); |
525 | x = timeHandler; | 526 | x = timeHandler; |
526 | timeHandler = (thand_f *)0; | 527 | timeHandler = (thand_f *)0; |
527 | (*x)(); | 528 | (*x)(); |
528 | } | 529 | } |
529 | 530 | ||
530 | 531 | ||
531 | switch (net_state) { | 532 | switch (net_state) { |
532 | 533 | ||
533 | case NETLOOP_RESTART: | 534 | case NETLOOP_RESTART: |
534 | NetRestarted = 1; | 535 | NetRestarted = 1; |
535 | goto restart; | 536 | goto restart; |
536 | 537 | ||
537 | case NETLOOP_SUCCESS: | 538 | case NETLOOP_SUCCESS: |
538 | net_cleanup_loop(); | 539 | net_cleanup_loop(); |
539 | if (NetBootFileXferSize > 0) { | 540 | if (NetBootFileXferSize > 0) { |
540 | printf("Bytes transferred = %ld (%lx hex)\n", | 541 | printf("Bytes transferred = %ld (%lx hex)\n", |
541 | NetBootFileXferSize, | 542 | NetBootFileXferSize, |
542 | NetBootFileXferSize); | 543 | NetBootFileXferSize); |
543 | setenv_hex("filesize", NetBootFileXferSize); | 544 | setenv_hex("filesize", NetBootFileXferSize); |
544 | setenv_hex("fileaddr", load_addr); | 545 | setenv_hex("fileaddr", load_addr); |
545 | } | 546 | } |
546 | if (protocol != NETCONS) | 547 | if (protocol != NETCONS) |
547 | eth_halt(); | 548 | eth_halt(); |
548 | else | 549 | else |
549 | eth_halt_state_only(); | 550 | eth_halt_state_only(); |
550 | 551 | ||
551 | eth_set_last_protocol(protocol); | 552 | eth_set_last_protocol(protocol); |
552 | 553 | ||
553 | ret = NetBootFileXferSize; | 554 | ret = NetBootFileXferSize; |
554 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Success!\n"); | 555 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Success!\n"); |
555 | goto done; | 556 | goto done; |
556 | 557 | ||
557 | case NETLOOP_FAIL: | 558 | case NETLOOP_FAIL: |
558 | net_cleanup_loop(); | 559 | net_cleanup_loop(); |
559 | /* Invalidate the last protocol */ | 560 | /* Invalidate the last protocol */ |
560 | eth_set_last_protocol(BOOTP); | 561 | eth_set_last_protocol(BOOTP); |
561 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Fail!\n"); | 562 | debug_cond(DEBUG_INT_STATE, "--- NetLoop Fail!\n"); |
562 | goto done; | 563 | goto done; |
563 | 564 | ||
564 | case NETLOOP_CONTINUE: | 565 | case NETLOOP_CONTINUE: |
565 | continue; | 566 | continue; |
566 | } | 567 | } |
567 | } | 568 | } |
568 | 569 | ||
569 | done: | 570 | done: |
570 | #ifdef CONFIG_USB_KEYBOARD | 571 | #ifdef CONFIG_USB_KEYBOARD |
571 | net_busy_flag = 0; | 572 | net_busy_flag = 0; |
572 | #endif | 573 | #endif |
573 | #ifdef CONFIG_CMD_TFTPPUT | 574 | #ifdef CONFIG_CMD_TFTPPUT |
574 | /* Clear out the handlers */ | 575 | /* Clear out the handlers */ |
575 | net_set_udp_handler(NULL); | 576 | net_set_udp_handler(NULL); |
576 | net_set_icmp_handler(NULL); | 577 | net_set_icmp_handler(NULL); |
577 | #endif | 578 | #endif |
578 | return ret; | 579 | return ret; |
579 | } | 580 | } |
580 | 581 | ||
581 | /**********************************************************************/ | 582 | /**********************************************************************/ |
582 | 583 | ||
583 | static void | 584 | static void |
584 | startAgainTimeout(void) | 585 | startAgainTimeout(void) |
585 | { | 586 | { |
586 | net_set_state(NETLOOP_RESTART); | 587 | net_set_state(NETLOOP_RESTART); |
587 | } | 588 | } |
588 | 589 | ||
589 | void NetStartAgain(void) | 590 | void NetStartAgain(void) |
590 | { | 591 | { |
591 | char *nretry; | 592 | char *nretry; |
592 | int retry_forever = 0; | 593 | int retry_forever = 0; |
593 | unsigned long retrycnt = 0; | 594 | unsigned long retrycnt = 0; |
594 | 595 | ||
595 | nretry = getenv("netretry"); | 596 | nretry = getenv("netretry"); |
596 | if (nretry) { | 597 | if (nretry) { |
597 | if (!strcmp(nretry, "yes")) | 598 | if (!strcmp(nretry, "yes")) |
598 | retry_forever = 1; | 599 | retry_forever = 1; |
599 | else if (!strcmp(nretry, "no")) | 600 | else if (!strcmp(nretry, "no")) |
600 | retrycnt = 0; | 601 | retrycnt = 0; |
601 | else if (!strcmp(nretry, "once")) | 602 | else if (!strcmp(nretry, "once")) |
602 | retrycnt = 1; | 603 | retrycnt = 1; |
603 | else | 604 | else |
604 | retrycnt = simple_strtoul(nretry, NULL, 0); | 605 | retrycnt = simple_strtoul(nretry, NULL, 0); |
605 | } else | 606 | } else |
606 | retry_forever = 1; | 607 | retry_forever = 1; |
607 | 608 | ||
608 | if ((!retry_forever) && (NetTryCount >= retrycnt)) { | 609 | if ((!retry_forever) && (NetTryCount >= retrycnt)) { |
609 | eth_halt(); | 610 | eth_halt(); |
610 | net_set_state(NETLOOP_FAIL); | 611 | net_set_state(NETLOOP_FAIL); |
611 | return; | 612 | return; |
612 | } | 613 | } |
613 | 614 | ||
614 | NetTryCount++; | 615 | NetTryCount++; |
615 | 616 | ||
616 | eth_halt(); | 617 | eth_halt(); |
617 | #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER) | 618 | #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER) |
618 | eth_try_another(!NetRestarted); | 619 | eth_try_another(!NetRestarted); |
619 | #endif | 620 | #endif |
620 | eth_init(gd->bd); | 621 | eth_init(gd->bd); |
621 | if (NetRestartWrap) { | 622 | if (NetRestartWrap) { |
622 | NetRestartWrap = 0; | 623 | NetRestartWrap = 0; |
623 | if (NetDevExists) { | 624 | if (NetDevExists) { |
624 | NetSetTimeout(10000UL, startAgainTimeout); | 625 | NetSetTimeout(10000UL, startAgainTimeout); |
625 | net_set_udp_handler(NULL); | 626 | net_set_udp_handler(NULL); |
626 | } else { | 627 | } else { |
627 | net_set_state(NETLOOP_FAIL); | 628 | net_set_state(NETLOOP_FAIL); |
628 | } | 629 | } |
629 | } else { | 630 | } else { |
630 | net_set_state(NETLOOP_RESTART); | 631 | net_set_state(NETLOOP_RESTART); |
631 | } | 632 | } |
632 | } | 633 | } |
633 | 634 | ||
634 | /**********************************************************************/ | 635 | /**********************************************************************/ |
635 | /* | 636 | /* |
636 | * Miscelaneous bits. | 637 | * Miscelaneous bits. |
637 | */ | 638 | */ |
638 | 639 | ||
639 | static void dummy_handler(uchar *pkt, unsigned dport, | 640 | static void dummy_handler(uchar *pkt, unsigned dport, |
640 | IPaddr_t sip, unsigned sport, | 641 | IPaddr_t sip, unsigned sport, |
641 | unsigned len) | 642 | unsigned len) |
642 | { | 643 | { |
643 | } | 644 | } |
644 | 645 | ||
645 | rxhand_f *net_get_udp_handler(void) | 646 | rxhand_f *net_get_udp_handler(void) |
646 | { | 647 | { |
647 | return udp_packet_handler; | 648 | return udp_packet_handler; |
648 | } | 649 | } |
649 | 650 | ||
650 | void net_set_udp_handler(rxhand_f *f) | 651 | void net_set_udp_handler(rxhand_f *f) |
651 | { | 652 | { |
652 | debug_cond(DEBUG_INT_STATE, "--- NetLoop UDP handler set (%p)\n", f); | 653 | debug_cond(DEBUG_INT_STATE, "--- NetLoop UDP handler set (%p)\n", f); |
653 | if (f == NULL) | 654 | if (f == NULL) |
654 | udp_packet_handler = dummy_handler; | 655 | udp_packet_handler = dummy_handler; |
655 | else | 656 | else |
656 | udp_packet_handler = f; | 657 | udp_packet_handler = f; |
657 | } | 658 | } |
658 | 659 | ||
659 | rxhand_f *net_get_arp_handler(void) | 660 | rxhand_f *net_get_arp_handler(void) |
660 | { | 661 | { |
661 | return arp_packet_handler; | 662 | return arp_packet_handler; |
662 | } | 663 | } |
663 | 664 | ||
664 | void net_set_arp_handler(rxhand_f *f) | 665 | void net_set_arp_handler(rxhand_f *f) |
665 | { | 666 | { |
666 | debug_cond(DEBUG_INT_STATE, "--- NetLoop ARP handler set (%p)\n", f); | 667 | debug_cond(DEBUG_INT_STATE, "--- NetLoop ARP handler set (%p)\n", f); |
667 | if (f == NULL) | 668 | if (f == NULL) |
668 | arp_packet_handler = dummy_handler; | 669 | arp_packet_handler = dummy_handler; |
669 | else | 670 | else |
670 | arp_packet_handler = f; | 671 | arp_packet_handler = f; |
671 | } | 672 | } |
672 | 673 | ||
673 | #ifdef CONFIG_CMD_TFTPPUT | 674 | #ifdef CONFIG_CMD_TFTPPUT |
674 | void net_set_icmp_handler(rxhand_icmp_f *f) | 675 | void net_set_icmp_handler(rxhand_icmp_f *f) |
675 | { | 676 | { |
676 | packet_icmp_handler = f; | 677 | packet_icmp_handler = f; |
677 | } | 678 | } |
678 | #endif | 679 | #endif |
679 | 680 | ||
680 | void | 681 | void |
681 | NetSetTimeout(ulong iv, thand_f *f) | 682 | NetSetTimeout(ulong iv, thand_f *f) |
682 | { | 683 | { |
683 | if (iv == 0) { | 684 | if (iv == 0) { |
684 | debug_cond(DEBUG_INT_STATE, | 685 | debug_cond(DEBUG_INT_STATE, |
685 | "--- NetLoop timeout handler cancelled\n"); | 686 | "--- NetLoop timeout handler cancelled\n"); |
686 | timeHandler = (thand_f *)0; | 687 | timeHandler = (thand_f *)0; |
687 | } else { | 688 | } else { |
688 | debug_cond(DEBUG_INT_STATE, | 689 | debug_cond(DEBUG_INT_STATE, |
689 | "--- NetLoop timeout handler set (%p)\n", f); | 690 | "--- NetLoop timeout handler set (%p)\n", f); |
690 | timeHandler = f; | 691 | timeHandler = f; |
691 | timeStart = get_timer(0); | 692 | timeStart = get_timer(0); |
692 | timeDelta = iv * CONFIG_SYS_HZ / 1000; | 693 | timeDelta = iv * CONFIG_SYS_HZ / 1000; |
693 | } | 694 | } |
694 | } | 695 | } |
695 | 696 | ||
696 | int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, | 697 | int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, |
697 | int payload_len) | 698 | int payload_len) |
698 | { | 699 | { |
699 | uchar *pkt; | 700 | uchar *pkt; |
700 | int eth_hdr_size; | 701 | int eth_hdr_size; |
701 | int pkt_hdr_size; | 702 | int pkt_hdr_size; |
702 | 703 | ||
703 | /* make sure the NetTxPacket is initialized (NetInit() was called) */ | 704 | /* make sure the NetTxPacket is initialized (NetInit() was called) */ |
704 | assert(NetTxPacket != NULL); | 705 | assert(NetTxPacket != NULL); |
705 | if (NetTxPacket == NULL) | 706 | if (NetTxPacket == NULL) |
706 | return -1; | 707 | return -1; |
707 | 708 | ||
708 | /* convert to new style broadcast */ | 709 | /* convert to new style broadcast */ |
709 | if (dest == 0) | 710 | if (dest == 0) |
710 | dest = 0xFFFFFFFF; | 711 | dest = 0xFFFFFFFF; |
711 | 712 | ||
712 | /* if broadcast, make the ether address a broadcast and don't do ARP */ | 713 | /* if broadcast, make the ether address a broadcast and don't do ARP */ |
713 | if (dest == 0xFFFFFFFF) | 714 | if (dest == 0xFFFFFFFF) |
714 | ether = NetBcastAddr; | 715 | ether = NetBcastAddr; |
715 | 716 | ||
716 | pkt = (uchar *)NetTxPacket; | 717 | pkt = (uchar *)NetTxPacket; |
717 | 718 | ||
718 | eth_hdr_size = NetSetEther(pkt, ether, PROT_IP); | 719 | eth_hdr_size = NetSetEther(pkt, ether, PROT_IP); |
719 | pkt += eth_hdr_size; | 720 | pkt += eth_hdr_size; |
720 | net_set_udp_header(pkt, dest, dport, sport, payload_len); | 721 | net_set_udp_header(pkt, dest, dport, sport, payload_len); |
721 | pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; | 722 | pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; |
722 | 723 | ||
723 | /* if MAC address was not discovered yet, do an ARP request */ | 724 | /* if MAC address was not discovered yet, do an ARP request */ |
724 | if (memcmp(ether, NetEtherNullAddr, 6) == 0) { | 725 | if (memcmp(ether, NetEtherNullAddr, 6) == 0) { |
725 | debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &dest); | 726 | debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &dest); |
726 | 727 | ||
727 | /* save the ip and eth addr for the packet to send after arp */ | 728 | /* save the ip and eth addr for the packet to send after arp */ |
728 | NetArpWaitPacketIP = dest; | 729 | NetArpWaitPacketIP = dest; |
729 | NetArpWaitPacketMAC = ether; | 730 | NetArpWaitPacketMAC = ether; |
730 | 731 | ||
731 | /* size of the waiting packet */ | 732 | /* size of the waiting packet */ |
732 | NetArpWaitTxPacketSize = pkt_hdr_size + payload_len; | 733 | NetArpWaitTxPacketSize = pkt_hdr_size + payload_len; |
733 | 734 | ||
734 | /* and do the ARP request */ | 735 | /* and do the ARP request */ |
735 | NetArpWaitTry = 1; | 736 | NetArpWaitTry = 1; |
736 | NetArpWaitTimerStart = get_timer(0); | 737 | NetArpWaitTimerStart = get_timer(0); |
737 | ArpRequest(); | 738 | ArpRequest(); |
738 | return 1; /* waiting */ | 739 | return 1; /* waiting */ |
739 | } else { | 740 | } else { |
740 | debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM\n", | 741 | debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM\n", |
741 | &dest, ether); | 742 | &dest, ether); |
742 | NetSendPacket(NetTxPacket, pkt_hdr_size + payload_len); | 743 | NetSendPacket(NetTxPacket, pkt_hdr_size + payload_len); |
743 | return 0; /* transmitted */ | 744 | return 0; /* transmitted */ |
744 | } | 745 | } |
745 | } | 746 | } |
746 | 747 | ||
747 | #ifdef CONFIG_IP_DEFRAG | 748 | #ifdef CONFIG_IP_DEFRAG |
748 | /* | 749 | /* |
749 | * This function collects fragments in a single packet, according | 750 | * This function collects fragments in a single packet, according |
750 | * to the algorithm in RFC815. It returns NULL or the pointer to | 751 | * to the algorithm in RFC815. It returns NULL or the pointer to |
751 | * a complete packet, in static storage | 752 | * a complete packet, in static storage |
752 | */ | 753 | */ |
753 | #ifndef CONFIG_NET_MAXDEFRAG | 754 | #ifndef CONFIG_NET_MAXDEFRAG |
754 | #define CONFIG_NET_MAXDEFRAG 16384 | 755 | #define CONFIG_NET_MAXDEFRAG 16384 |
755 | #endif | 756 | #endif |
756 | /* | 757 | /* |
757 | * MAXDEFRAG, above, is chosen in the config file and is real data | 758 | * MAXDEFRAG, above, is chosen in the config file and is real data |
758 | * so we need to add the NFS overhead, which is more than TFTP. | 759 | * so we need to add the NFS overhead, which is more than TFTP. |
759 | * To use sizeof in the internal unnamed structures, we need a real | 760 | * To use sizeof in the internal unnamed structures, we need a real |
760 | * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately). | 761 | * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately). |
761 | * The compiler doesn't complain nor allocates the actual structure | 762 | * The compiler doesn't complain nor allocates the actual structure |
762 | */ | 763 | */ |
763 | static struct rpc_t rpc_specimen; | 764 | static struct rpc_t rpc_specimen; |
764 | #define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply)) | 765 | #define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply)) |
765 | 766 | ||
766 | #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE) | 767 | #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE) |
767 | 768 | ||
768 | /* | 769 | /* |
769 | * this is the packet being assembled, either data or frag control. | 770 | * this is the packet being assembled, either data or frag control. |
770 | * Fragments go by 8 bytes, so this union must be 8 bytes long | 771 | * Fragments go by 8 bytes, so this union must be 8 bytes long |
771 | */ | 772 | */ |
772 | struct hole { | 773 | struct hole { |
773 | /* first_byte is address of this structure */ | 774 | /* first_byte is address of this structure */ |
774 | u16 last_byte; /* last byte in this hole + 1 (begin of next hole) */ | 775 | u16 last_byte; /* last byte in this hole + 1 (begin of next hole) */ |
775 | u16 next_hole; /* index of next (in 8-b blocks), 0 == none */ | 776 | u16 next_hole; /* index of next (in 8-b blocks), 0 == none */ |
776 | u16 prev_hole; /* index of prev, 0 == none */ | 777 | u16 prev_hole; /* index of prev, 0 == none */ |
777 | u16 unused; | 778 | u16 unused; |
778 | }; | 779 | }; |
779 | 780 | ||
780 | static struct ip_udp_hdr *__NetDefragment(struct ip_udp_hdr *ip, int *lenp) | 781 | static struct ip_udp_hdr *__NetDefragment(struct ip_udp_hdr *ip, int *lenp) |
781 | { | 782 | { |
782 | static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN); | 783 | static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN); |
783 | static u16 first_hole, total_len; | 784 | static u16 first_hole, total_len; |
784 | struct hole *payload, *thisfrag, *h, *newh; | 785 | struct hole *payload, *thisfrag, *h, *newh; |
785 | struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff; | 786 | struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff; |
786 | uchar *indata = (uchar *)ip; | 787 | uchar *indata = (uchar *)ip; |
787 | int offset8, start, len, done = 0; | 788 | int offset8, start, len, done = 0; |
788 | u16 ip_off = ntohs(ip->ip_off); | 789 | u16 ip_off = ntohs(ip->ip_off); |
789 | 790 | ||
790 | /* payload starts after IP header, this fragment is in there */ | 791 | /* payload starts after IP header, this fragment is in there */ |
791 | payload = (struct hole *)(pkt_buff + IP_HDR_SIZE); | 792 | payload = (struct hole *)(pkt_buff + IP_HDR_SIZE); |
792 | offset8 = (ip_off & IP_OFFS); | 793 | offset8 = (ip_off & IP_OFFS); |
793 | thisfrag = payload + offset8; | 794 | thisfrag = payload + offset8; |
794 | start = offset8 * 8; | 795 | start = offset8 * 8; |
795 | len = ntohs(ip->ip_len) - IP_HDR_SIZE; | 796 | len = ntohs(ip->ip_len) - IP_HDR_SIZE; |
796 | 797 | ||
797 | if (start + len > IP_MAXUDP) /* fragment extends too far */ | 798 | if (start + len > IP_MAXUDP) /* fragment extends too far */ |
798 | return NULL; | 799 | return NULL; |
799 | 800 | ||
800 | if (!total_len || localip->ip_id != ip->ip_id) { | 801 | if (!total_len || localip->ip_id != ip->ip_id) { |
801 | /* new (or different) packet, reset structs */ | 802 | /* new (or different) packet, reset structs */ |
802 | total_len = 0xffff; | 803 | total_len = 0xffff; |
803 | payload[0].last_byte = ~0; | 804 | payload[0].last_byte = ~0; |
804 | payload[0].next_hole = 0; | 805 | payload[0].next_hole = 0; |
805 | payload[0].prev_hole = 0; | 806 | payload[0].prev_hole = 0; |
806 | first_hole = 0; | 807 | first_hole = 0; |
807 | /* any IP header will work, copy the first we received */ | 808 | /* any IP header will work, copy the first we received */ |
808 | memcpy(localip, ip, IP_HDR_SIZE); | 809 | memcpy(localip, ip, IP_HDR_SIZE); |
809 | } | 810 | } |
810 | 811 | ||
811 | /* | 812 | /* |
812 | * What follows is the reassembly algorithm. We use the payload | 813 | * What follows is the reassembly algorithm. We use the payload |
813 | * array as a linked list of hole descriptors, as each hole starts | 814 | * array as a linked list of hole descriptors, as each hole starts |
814 | * at a multiple of 8 bytes. However, last byte can be whatever value, | 815 | * at a multiple of 8 bytes. However, last byte can be whatever value, |
815 | * so it is represented as byte count, not as 8-byte blocks. | 816 | * so it is represented as byte count, not as 8-byte blocks. |
816 | */ | 817 | */ |
817 | 818 | ||
818 | h = payload + first_hole; | 819 | h = payload + first_hole; |
819 | while (h->last_byte < start) { | 820 | while (h->last_byte < start) { |
820 | if (!h->next_hole) { | 821 | if (!h->next_hole) { |
821 | /* no hole that far away */ | 822 | /* no hole that far away */ |
822 | return NULL; | 823 | return NULL; |
823 | } | 824 | } |
824 | h = payload + h->next_hole; | 825 | h = payload + h->next_hole; |
825 | } | 826 | } |
826 | 827 | ||
827 | /* last fragment may be 1..7 bytes, the "+7" forces acceptance */ | 828 | /* last fragment may be 1..7 bytes, the "+7" forces acceptance */ |
828 | if (offset8 + ((len + 7) / 8) <= h - payload) { | 829 | if (offset8 + ((len + 7) / 8) <= h - payload) { |
829 | /* no overlap with holes (dup fragment?) */ | 830 | /* no overlap with holes (dup fragment?) */ |
830 | return NULL; | 831 | return NULL; |
831 | } | 832 | } |
832 | 833 | ||
833 | if (!(ip_off & IP_FLAGS_MFRAG)) { | 834 | if (!(ip_off & IP_FLAGS_MFRAG)) { |
834 | /* no more fragmentss: truncate this (last) hole */ | 835 | /* no more fragmentss: truncate this (last) hole */ |
835 | total_len = start + len; | 836 | total_len = start + len; |
836 | h->last_byte = start + len; | 837 | h->last_byte = start + len; |
837 | } | 838 | } |
838 | 839 | ||
839 | /* | 840 | /* |
840 | * There is some overlap: fix the hole list. This code doesn't | 841 | * There is some overlap: fix the hole list. This code doesn't |
841 | * deal with a fragment that overlaps with two different holes | 842 | * deal with a fragment that overlaps with two different holes |
842 | * (thus being a superset of a previously-received fragment). | 843 | * (thus being a superset of a previously-received fragment). |
843 | */ | 844 | */ |
844 | 845 | ||
845 | if ((h >= thisfrag) && (h->last_byte <= start + len)) { | 846 | if ((h >= thisfrag) && (h->last_byte <= start + len)) { |
846 | /* complete overlap with hole: remove hole */ | 847 | /* complete overlap with hole: remove hole */ |
847 | if (!h->prev_hole && !h->next_hole) { | 848 | if (!h->prev_hole && !h->next_hole) { |
848 | /* last remaining hole */ | 849 | /* last remaining hole */ |
849 | done = 1; | 850 | done = 1; |
850 | } else if (!h->prev_hole) { | 851 | } else if (!h->prev_hole) { |
851 | /* first hole */ | 852 | /* first hole */ |
852 | first_hole = h->next_hole; | 853 | first_hole = h->next_hole; |
853 | payload[h->next_hole].prev_hole = 0; | 854 | payload[h->next_hole].prev_hole = 0; |
854 | } else if (!h->next_hole) { | 855 | } else if (!h->next_hole) { |
855 | /* last hole */ | 856 | /* last hole */ |
856 | payload[h->prev_hole].next_hole = 0; | 857 | payload[h->prev_hole].next_hole = 0; |
857 | } else { | 858 | } else { |
858 | /* in the middle of the list */ | 859 | /* in the middle of the list */ |
859 | payload[h->next_hole].prev_hole = h->prev_hole; | 860 | payload[h->next_hole].prev_hole = h->prev_hole; |
860 | payload[h->prev_hole].next_hole = h->next_hole; | 861 | payload[h->prev_hole].next_hole = h->next_hole; |
861 | } | 862 | } |
862 | 863 | ||
863 | } else if (h->last_byte <= start + len) { | 864 | } else if (h->last_byte <= start + len) { |
864 | /* overlaps with final part of the hole: shorten this hole */ | 865 | /* overlaps with final part of the hole: shorten this hole */ |
865 | h->last_byte = start; | 866 | h->last_byte = start; |
866 | 867 | ||
867 | } else if (h >= thisfrag) { | 868 | } else if (h >= thisfrag) { |
868 | /* overlaps with initial part of the hole: move this hole */ | 869 | /* overlaps with initial part of the hole: move this hole */ |
869 | newh = thisfrag + (len / 8); | 870 | newh = thisfrag + (len / 8); |
870 | *newh = *h; | 871 | *newh = *h; |
871 | h = newh; | 872 | h = newh; |
872 | if (h->next_hole) | 873 | if (h->next_hole) |
873 | payload[h->next_hole].prev_hole = (h - payload); | 874 | payload[h->next_hole].prev_hole = (h - payload); |
874 | if (h->prev_hole) | 875 | if (h->prev_hole) |
875 | payload[h->prev_hole].next_hole = (h - payload); | 876 | payload[h->prev_hole].next_hole = (h - payload); |
876 | else | 877 | else |
877 | first_hole = (h - payload); | 878 | first_hole = (h - payload); |
878 | 879 | ||
879 | } else { | 880 | } else { |
880 | /* fragment sits in the middle: split the hole */ | 881 | /* fragment sits in the middle: split the hole */ |
881 | newh = thisfrag + (len / 8); | 882 | newh = thisfrag + (len / 8); |
882 | *newh = *h; | 883 | *newh = *h; |
883 | h->last_byte = start; | 884 | h->last_byte = start; |
884 | h->next_hole = (newh - payload); | 885 | h->next_hole = (newh - payload); |
885 | newh->prev_hole = (h - payload); | 886 | newh->prev_hole = (h - payload); |
886 | if (newh->next_hole) | 887 | if (newh->next_hole) |
887 | payload[newh->next_hole].prev_hole = (newh - payload); | 888 | payload[newh->next_hole].prev_hole = (newh - payload); |
888 | } | 889 | } |
889 | 890 | ||
890 | /* finally copy this fragment and possibly return whole packet */ | 891 | /* finally copy this fragment and possibly return whole packet */ |
891 | memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len); | 892 | memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len); |
892 | if (!done) | 893 | if (!done) |
893 | return NULL; | 894 | return NULL; |
894 | 895 | ||
895 | localip->ip_len = htons(total_len); | 896 | localip->ip_len = htons(total_len); |
896 | *lenp = total_len + IP_HDR_SIZE; | 897 | *lenp = total_len + IP_HDR_SIZE; |
897 | return localip; | 898 | return localip; |
898 | } | 899 | } |
899 | 900 | ||
900 | static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp) | 901 | static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp) |
901 | { | 902 | { |
902 | u16 ip_off = ntohs(ip->ip_off); | 903 | u16 ip_off = ntohs(ip->ip_off); |
903 | if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG))) | 904 | if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG))) |
904 | return ip; /* not a fragment */ | 905 | return ip; /* not a fragment */ |
905 | return __NetDefragment(ip, lenp); | 906 | return __NetDefragment(ip, lenp); |
906 | } | 907 | } |
907 | 908 | ||
908 | #else /* !CONFIG_IP_DEFRAG */ | 909 | #else /* !CONFIG_IP_DEFRAG */ |
909 | 910 | ||
910 | static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp) | 911 | static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp) |
911 | { | 912 | { |
912 | u16 ip_off = ntohs(ip->ip_off); | 913 | u16 ip_off = ntohs(ip->ip_off); |
913 | if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG))) | 914 | if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG))) |
914 | return ip; /* not a fragment */ | 915 | return ip; /* not a fragment */ |
915 | return NULL; | 916 | return NULL; |
916 | } | 917 | } |
917 | #endif | 918 | #endif |
918 | 919 | ||
919 | /** | 920 | /** |
920 | * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently | 921 | * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently |
921 | * drop others. | 922 | * drop others. |
922 | * | 923 | * |
923 | * @parma ip IP packet containing the ICMP | 924 | * @parma ip IP packet containing the ICMP |
924 | */ | 925 | */ |
925 | static void receive_icmp(struct ip_udp_hdr *ip, int len, | 926 | static void receive_icmp(struct ip_udp_hdr *ip, int len, |
926 | IPaddr_t src_ip, struct ethernet_hdr *et) | 927 | IPaddr_t src_ip, struct ethernet_hdr *et) |
927 | { | 928 | { |
928 | struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src; | 929 | struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src; |
929 | 930 | ||
930 | switch (icmph->type) { | 931 | switch (icmph->type) { |
931 | case ICMP_REDIRECT: | 932 | case ICMP_REDIRECT: |
932 | if (icmph->code != ICMP_REDIR_HOST) | 933 | if (icmph->code != ICMP_REDIR_HOST) |
933 | return; | 934 | return; |
934 | printf(" ICMP Host Redirect to %pI4 ", | 935 | printf(" ICMP Host Redirect to %pI4 ", |
935 | &icmph->un.gateway); | 936 | &icmph->un.gateway); |
936 | break; | 937 | break; |
937 | default: | 938 | default: |
938 | #if defined(CONFIG_CMD_PING) | 939 | #if defined(CONFIG_CMD_PING) |
939 | ping_receive(et, ip, len); | 940 | ping_receive(et, ip, len); |
940 | #endif | 941 | #endif |
941 | #ifdef CONFIG_CMD_TFTPPUT | 942 | #ifdef CONFIG_CMD_TFTPPUT |
942 | if (packet_icmp_handler) | 943 | if (packet_icmp_handler) |
943 | packet_icmp_handler(icmph->type, icmph->code, | 944 | packet_icmp_handler(icmph->type, icmph->code, |
944 | ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src), | 945 | ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src), |
945 | icmph->un.data, ntohs(ip->udp_len)); | 946 | icmph->un.data, ntohs(ip->udp_len)); |
946 | #endif | 947 | #endif |
947 | break; | 948 | break; |
948 | } | 949 | } |
949 | } | 950 | } |
950 | 951 | ||
951 | void | 952 | void |
952 | NetReceive(uchar *inpkt, int len) | 953 | NetReceive(uchar *inpkt, int len) |
953 | { | 954 | { |
954 | struct ethernet_hdr *et; | 955 | struct ethernet_hdr *et; |
955 | struct ip_udp_hdr *ip; | 956 | struct ip_udp_hdr *ip; |
956 | IPaddr_t dst_ip; | 957 | IPaddr_t dst_ip; |
957 | IPaddr_t src_ip; | 958 | IPaddr_t src_ip; |
958 | int eth_proto; | 959 | int eth_proto; |
959 | #if defined(CONFIG_CMD_CDP) | 960 | #if defined(CONFIG_CMD_CDP) |
960 | int iscdp; | 961 | int iscdp; |
961 | #endif | 962 | #endif |
962 | ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid; | 963 | ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid; |
963 | 964 | ||
964 | debug_cond(DEBUG_NET_PKT, "packet received\n"); | 965 | debug_cond(DEBUG_NET_PKT, "packet received\n"); |
965 | 966 | ||
966 | NetRxPacket = inpkt; | 967 | NetRxPacket = inpkt; |
967 | NetRxPacketLen = len; | 968 | NetRxPacketLen = len; |
968 | et = (struct ethernet_hdr *)inpkt; | 969 | et = (struct ethernet_hdr *)inpkt; |
969 | 970 | ||
970 | /* too small packet? */ | 971 | /* too small packet? */ |
971 | if (len < ETHER_HDR_SIZE) | 972 | if (len < ETHER_HDR_SIZE) |
972 | return; | 973 | return; |
973 | 974 | ||
974 | #ifdef CONFIG_API | 975 | #ifdef CONFIG_API |
975 | if (push_packet) { | 976 | if (push_packet) { |
976 | (*push_packet)(inpkt, len); | 977 | (*push_packet)(inpkt, len); |
977 | return; | 978 | return; |
978 | } | 979 | } |
979 | #endif | 980 | #endif |
980 | 981 | ||
981 | #if defined(CONFIG_CMD_CDP) | 982 | #if defined(CONFIG_CMD_CDP) |
982 | /* keep track if packet is CDP */ | 983 | /* keep track if packet is CDP */ |
983 | iscdp = is_cdp_packet(et->et_dest); | 984 | iscdp = is_cdp_packet(et->et_dest); |
984 | #endif | 985 | #endif |
985 | 986 | ||
986 | myvlanid = ntohs(NetOurVLAN); | 987 | myvlanid = ntohs(NetOurVLAN); |
987 | if (myvlanid == (ushort)-1) | 988 | if (myvlanid == (ushort)-1) |
988 | myvlanid = VLAN_NONE; | 989 | myvlanid = VLAN_NONE; |
989 | mynvlanid = ntohs(NetOurNativeVLAN); | 990 | mynvlanid = ntohs(NetOurNativeVLAN); |
990 | if (mynvlanid == (ushort)-1) | 991 | if (mynvlanid == (ushort)-1) |
991 | mynvlanid = VLAN_NONE; | 992 | mynvlanid = VLAN_NONE; |
992 | 993 | ||
993 | eth_proto = ntohs(et->et_protlen); | 994 | eth_proto = ntohs(et->et_protlen); |
994 | 995 | ||
995 | if (eth_proto < 1514) { | 996 | if (eth_proto < 1514) { |
996 | struct e802_hdr *et802 = (struct e802_hdr *)et; | 997 | struct e802_hdr *et802 = (struct e802_hdr *)et; |
997 | /* | 998 | /* |
998 | * Got a 802.2 packet. Check the other protocol field. | 999 | * Got a 802.2 packet. Check the other protocol field. |
999 | * XXX VLAN over 802.2+SNAP not implemented! | 1000 | * XXX VLAN over 802.2+SNAP not implemented! |
1000 | */ | 1001 | */ |
1001 | eth_proto = ntohs(et802->et_prot); | 1002 | eth_proto = ntohs(et802->et_prot); |
1002 | 1003 | ||
1003 | ip = (struct ip_udp_hdr *)(inpkt + E802_HDR_SIZE); | 1004 | ip = (struct ip_udp_hdr *)(inpkt + E802_HDR_SIZE); |
1004 | len -= E802_HDR_SIZE; | 1005 | len -= E802_HDR_SIZE; |
1005 | 1006 | ||
1006 | } else if (eth_proto != PROT_VLAN) { /* normal packet */ | 1007 | } else if (eth_proto != PROT_VLAN) { /* normal packet */ |
1007 | ip = (struct ip_udp_hdr *)(inpkt + ETHER_HDR_SIZE); | 1008 | ip = (struct ip_udp_hdr *)(inpkt + ETHER_HDR_SIZE); |
1008 | len -= ETHER_HDR_SIZE; | 1009 | len -= ETHER_HDR_SIZE; |
1009 | 1010 | ||
1010 | } else { /* VLAN packet */ | 1011 | } else { /* VLAN packet */ |
1011 | struct vlan_ethernet_hdr *vet = | 1012 | struct vlan_ethernet_hdr *vet = |
1012 | (struct vlan_ethernet_hdr *)et; | 1013 | (struct vlan_ethernet_hdr *)et; |
1013 | 1014 | ||
1014 | debug_cond(DEBUG_NET_PKT, "VLAN packet received\n"); | 1015 | debug_cond(DEBUG_NET_PKT, "VLAN packet received\n"); |
1015 | 1016 | ||
1016 | /* too small packet? */ | 1017 | /* too small packet? */ |
1017 | if (len < VLAN_ETHER_HDR_SIZE) | 1018 | if (len < VLAN_ETHER_HDR_SIZE) |
1018 | return; | 1019 | return; |
1019 | 1020 | ||
1020 | /* if no VLAN active */ | 1021 | /* if no VLAN active */ |
1021 | if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE | 1022 | if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE |
1022 | #if defined(CONFIG_CMD_CDP) | 1023 | #if defined(CONFIG_CMD_CDP) |
1023 | && iscdp == 0 | 1024 | && iscdp == 0 |
1024 | #endif | 1025 | #endif |
1025 | ) | 1026 | ) |
1026 | return; | 1027 | return; |
1027 | 1028 | ||
1028 | cti = ntohs(vet->vet_tag); | 1029 | cti = ntohs(vet->vet_tag); |
1029 | vlanid = cti & VLAN_IDMASK; | 1030 | vlanid = cti & VLAN_IDMASK; |
1030 | eth_proto = ntohs(vet->vet_type); | 1031 | eth_proto = ntohs(vet->vet_type); |
1031 | 1032 | ||
1032 | ip = (struct ip_udp_hdr *)(inpkt + VLAN_ETHER_HDR_SIZE); | 1033 | ip = (struct ip_udp_hdr *)(inpkt + VLAN_ETHER_HDR_SIZE); |
1033 | len -= VLAN_ETHER_HDR_SIZE; | 1034 | len -= VLAN_ETHER_HDR_SIZE; |
1034 | } | 1035 | } |
1035 | 1036 | ||
1036 | debug_cond(DEBUG_NET_PKT, "Receive from protocol 0x%x\n", eth_proto); | 1037 | debug_cond(DEBUG_NET_PKT, "Receive from protocol 0x%x\n", eth_proto); |
1037 | 1038 | ||
1038 | #if defined(CONFIG_CMD_CDP) | 1039 | #if defined(CONFIG_CMD_CDP) |
1039 | if (iscdp) { | 1040 | if (iscdp) { |
1040 | cdp_receive((uchar *)ip, len); | 1041 | cdp_receive((uchar *)ip, len); |
1041 | return; | 1042 | return; |
1042 | } | 1043 | } |
1043 | #endif | 1044 | #endif |
1044 | 1045 | ||
1045 | if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) { | 1046 | if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) { |
1046 | if (vlanid == VLAN_NONE) | 1047 | if (vlanid == VLAN_NONE) |
1047 | vlanid = (mynvlanid & VLAN_IDMASK); | 1048 | vlanid = (mynvlanid & VLAN_IDMASK); |
1048 | /* not matched? */ | 1049 | /* not matched? */ |
1049 | if (vlanid != (myvlanid & VLAN_IDMASK)) | 1050 | if (vlanid != (myvlanid & VLAN_IDMASK)) |
1050 | return; | 1051 | return; |
1051 | } | 1052 | } |
1052 | 1053 | ||
1053 | switch (eth_proto) { | 1054 | switch (eth_proto) { |
1054 | 1055 | ||
1055 | case PROT_ARP: | 1056 | case PROT_ARP: |
1056 | ArpReceive(et, ip, len); | 1057 | ArpReceive(et, ip, len); |
1057 | break; | 1058 | break; |
1058 | 1059 | ||
1059 | #ifdef CONFIG_CMD_RARP | 1060 | #ifdef CONFIG_CMD_RARP |
1060 | case PROT_RARP: | 1061 | case PROT_RARP: |
1061 | rarp_receive(ip, len); | 1062 | rarp_receive(ip, len); |
1062 | break; | 1063 | break; |
1063 | #endif | 1064 | #endif |
1064 | case PROT_IP: | 1065 | case PROT_IP: |
1065 | debug_cond(DEBUG_NET_PKT, "Got IP\n"); | 1066 | debug_cond(DEBUG_NET_PKT, "Got IP\n"); |
1066 | /* Before we start poking the header, make sure it is there */ | 1067 | /* Before we start poking the header, make sure it is there */ |
1067 | if (len < IP_UDP_HDR_SIZE) { | 1068 | if (len < IP_UDP_HDR_SIZE) { |
1068 | debug("len bad %d < %lu\n", len, | 1069 | debug("len bad %d < %lu\n", len, |
1069 | (ulong)IP_UDP_HDR_SIZE); | 1070 | (ulong)IP_UDP_HDR_SIZE); |
1070 | return; | 1071 | return; |
1071 | } | 1072 | } |
1072 | /* Check the packet length */ | 1073 | /* Check the packet length */ |
1073 | if (len < ntohs(ip->ip_len)) { | 1074 | if (len < ntohs(ip->ip_len)) { |
1074 | debug("len bad %d < %d\n", len, ntohs(ip->ip_len)); | 1075 | debug("len bad %d < %d\n", len, ntohs(ip->ip_len)); |
1075 | return; | 1076 | return; |
1076 | } | 1077 | } |
1077 | len = ntohs(ip->ip_len); | 1078 | len = ntohs(ip->ip_len); |
1078 | debug_cond(DEBUG_NET_PKT, "len=%d, v=%02x\n", | 1079 | debug_cond(DEBUG_NET_PKT, "len=%d, v=%02x\n", |
1079 | len, ip->ip_hl_v & 0xff); | 1080 | len, ip->ip_hl_v & 0xff); |
1080 | 1081 | ||
1081 | /* Can't deal with anything except IPv4 */ | 1082 | /* Can't deal with anything except IPv4 */ |
1082 | if ((ip->ip_hl_v & 0xf0) != 0x40) | 1083 | if ((ip->ip_hl_v & 0xf0) != 0x40) |
1083 | return; | 1084 | return; |
1084 | /* Can't deal with IP options (headers != 20 bytes) */ | 1085 | /* Can't deal with IP options (headers != 20 bytes) */ |
1085 | if ((ip->ip_hl_v & 0x0f) > 0x05) | 1086 | if ((ip->ip_hl_v & 0x0f) > 0x05) |
1086 | return; | 1087 | return; |
1087 | /* Check the Checksum of the header */ | 1088 | /* Check the Checksum of the header */ |
1088 | if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE / 2)) { | 1089 | if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE / 2)) { |
1089 | debug("checksum bad\n"); | 1090 | debug("checksum bad\n"); |
1090 | return; | 1091 | return; |
1091 | } | 1092 | } |
1092 | /* If it is not for us, ignore it */ | 1093 | /* If it is not for us, ignore it */ |
1093 | dst_ip = NetReadIP(&ip->ip_dst); | 1094 | dst_ip = NetReadIP(&ip->ip_dst); |
1094 | if (NetOurIP && dst_ip != NetOurIP && dst_ip != 0xFFFFFFFF) { | 1095 | if (NetOurIP && dst_ip != NetOurIP && dst_ip != 0xFFFFFFFF) { |
1095 | #ifdef CONFIG_MCAST_TFTP | 1096 | #ifdef CONFIG_MCAST_TFTP |
1096 | if (Mcast_addr != dst_ip) | 1097 | if (Mcast_addr != dst_ip) |
1097 | #endif | 1098 | #endif |
1098 | return; | 1099 | return; |
1099 | } | 1100 | } |
1100 | /* Read source IP address for later use */ | 1101 | /* Read source IP address for later use */ |
1101 | src_ip = NetReadIP(&ip->ip_src); | 1102 | src_ip = NetReadIP(&ip->ip_src); |
1102 | /* | 1103 | /* |
1103 | * The function returns the unchanged packet if it's not | 1104 | * The function returns the unchanged packet if it's not |
1104 | * a fragment, and either the complete packet or NULL if | 1105 | * a fragment, and either the complete packet or NULL if |
1105 | * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL) | 1106 | * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL) |
1106 | */ | 1107 | */ |
1107 | ip = NetDefragment(ip, &len); | 1108 | ip = NetDefragment(ip, &len); |
1108 | if (!ip) | 1109 | if (!ip) |
1109 | return; | 1110 | return; |
1110 | /* | 1111 | /* |
1111 | * watch for ICMP host redirects | 1112 | * watch for ICMP host redirects |
1112 | * | 1113 | * |
1113 | * There is no real handler code (yet). We just watch | 1114 | * There is no real handler code (yet). We just watch |
1114 | * for ICMP host redirect messages. In case anybody | 1115 | * for ICMP host redirect messages. In case anybody |
1115 | * sees these messages: please contact me | 1116 | * sees these messages: please contact me |
1116 | * (wd@denx.de), or - even better - send me the | 1117 | * (wd@denx.de), or - even better - send me the |
1117 | * necessary fixes :-) | 1118 | * necessary fixes :-) |
1118 | * | 1119 | * |
1119 | * Note: in all cases where I have seen this so far | 1120 | * Note: in all cases where I have seen this so far |
1120 | * it was a problem with the router configuration, | 1121 | * it was a problem with the router configuration, |
1121 | * for instance when a router was configured in the | 1122 | * for instance when a router was configured in the |
1122 | * BOOTP reply, but the TFTP server was on the same | 1123 | * BOOTP reply, but the TFTP server was on the same |
1123 | * subnet. So this is probably a warning that your | 1124 | * subnet. So this is probably a warning that your |
1124 | * configuration might be wrong. But I'm not really | 1125 | * configuration might be wrong. But I'm not really |
1125 | * sure if there aren't any other situations. | 1126 | * sure if there aren't any other situations. |
1126 | * | 1127 | * |
1127 | * Simon Glass <sjg@chromium.org>: We get an ICMP when | 1128 | * Simon Glass <sjg@chromium.org>: We get an ICMP when |
1128 | * we send a tftp packet to a dead connection, or when | 1129 | * we send a tftp packet to a dead connection, or when |
1129 | * there is no server at the other end. | 1130 | * there is no server at the other end. |
1130 | */ | 1131 | */ |
1131 | if (ip->ip_p == IPPROTO_ICMP) { | 1132 | if (ip->ip_p == IPPROTO_ICMP) { |
1132 | receive_icmp(ip, len, src_ip, et); | 1133 | receive_icmp(ip, len, src_ip, et); |
1133 | return; | 1134 | return; |
1134 | } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */ | 1135 | } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */ |
1135 | return; | 1136 | return; |
1136 | } | 1137 | } |
1137 | 1138 | ||
1138 | debug_cond(DEBUG_DEV_PKT, | 1139 | debug_cond(DEBUG_DEV_PKT, |
1139 | "received UDP (to=%pI4, from=%pI4, len=%d)\n", | 1140 | "received UDP (to=%pI4, from=%pI4, len=%d)\n", |
1140 | &dst_ip, &src_ip, len); | 1141 | &dst_ip, &src_ip, len); |
1141 | 1142 | ||
1142 | #ifdef CONFIG_UDP_CHECKSUM | 1143 | #ifdef CONFIG_UDP_CHECKSUM |
1143 | if (ip->udp_xsum != 0) { | 1144 | if (ip->udp_xsum != 0) { |
1144 | ulong xsum; | 1145 | ulong xsum; |
1145 | ushort *sumptr; | 1146 | ushort *sumptr; |
1146 | ushort sumlen; | 1147 | ushort sumlen; |
1147 | 1148 | ||
1148 | xsum = ip->ip_p; | 1149 | xsum = ip->ip_p; |
1149 | xsum += (ntohs(ip->udp_len)); | 1150 | xsum += (ntohs(ip->udp_len)); |
1150 | xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff; | 1151 | xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff; |
1151 | xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff; | 1152 | xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff; |
1152 | xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff; | 1153 | xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff; |
1153 | xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff; | 1154 | xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff; |
1154 | 1155 | ||
1155 | sumlen = ntohs(ip->udp_len); | 1156 | sumlen = ntohs(ip->udp_len); |
1156 | sumptr = (ushort *) &(ip->udp_src); | 1157 | sumptr = (ushort *) &(ip->udp_src); |
1157 | 1158 | ||
1158 | while (sumlen > 1) { | 1159 | while (sumlen > 1) { |
1159 | ushort sumdata; | 1160 | ushort sumdata; |
1160 | 1161 | ||
1161 | sumdata = *sumptr++; | 1162 | sumdata = *sumptr++; |
1162 | xsum += ntohs(sumdata); | 1163 | xsum += ntohs(sumdata); |
1163 | sumlen -= 2; | 1164 | sumlen -= 2; |
1164 | } | 1165 | } |
1165 | if (sumlen > 0) { | 1166 | if (sumlen > 0) { |
1166 | ushort sumdata; | 1167 | ushort sumdata; |
1167 | 1168 | ||
1168 | sumdata = *(unsigned char *) sumptr; | 1169 | sumdata = *(unsigned char *) sumptr; |
1169 | sumdata = (sumdata << 8) & 0xff00; | 1170 | sumdata = (sumdata << 8) & 0xff00; |
1170 | xsum += sumdata; | 1171 | xsum += sumdata; |
1171 | } | 1172 | } |
1172 | while ((xsum >> 16) != 0) { | 1173 | while ((xsum >> 16) != 0) { |
1173 | xsum = (xsum & 0x0000ffff) + | 1174 | xsum = (xsum & 0x0000ffff) + |
1174 | ((xsum >> 16) & 0x0000ffff); | 1175 | ((xsum >> 16) & 0x0000ffff); |
1175 | } | 1176 | } |
1176 | if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) { | 1177 | if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) { |
1177 | printf(" UDP wrong checksum %08lx %08x\n", | 1178 | printf(" UDP wrong checksum %08lx %08x\n", |
1178 | xsum, ntohs(ip->udp_xsum)); | 1179 | xsum, ntohs(ip->udp_xsum)); |
1179 | return; | 1180 | return; |
1180 | } | 1181 | } |
1181 | } | 1182 | } |
1182 | #endif | 1183 | #endif |
1183 | 1184 | ||
1184 | 1185 | ||
1185 | #if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD) | 1186 | #if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD) |
1186 | nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE, | 1187 | nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE, |
1187 | src_ip, | 1188 | src_ip, |
1188 | ntohs(ip->udp_dst), | 1189 | ntohs(ip->udp_dst), |
1189 | ntohs(ip->udp_src), | 1190 | ntohs(ip->udp_src), |
1190 | ntohs(ip->udp_len) - UDP_HDR_SIZE); | 1191 | ntohs(ip->udp_len) - UDP_HDR_SIZE); |
1191 | #endif | 1192 | #endif |
1192 | /* | 1193 | /* |
1193 | * IP header OK. Pass the packet to the current handler. | 1194 | * IP header OK. Pass the packet to the current handler. |
1194 | */ | 1195 | */ |
1195 | (*udp_packet_handler)((uchar *)ip + IP_UDP_HDR_SIZE, | 1196 | (*udp_packet_handler)((uchar *)ip + IP_UDP_HDR_SIZE, |
1196 | ntohs(ip->udp_dst), | 1197 | ntohs(ip->udp_dst), |
1197 | src_ip, | 1198 | src_ip, |
1198 | ntohs(ip->udp_src), | 1199 | ntohs(ip->udp_src), |
1199 | ntohs(ip->udp_len) - UDP_HDR_SIZE); | 1200 | ntohs(ip->udp_len) - UDP_HDR_SIZE); |
1200 | break; | 1201 | break; |
1201 | } | 1202 | } |
1202 | } | 1203 | } |
1203 | 1204 | ||
1204 | 1205 | ||
1205 | /**********************************************************************/ | 1206 | /**********************************************************************/ |
1206 | 1207 | ||
1207 | static int net_check_prereq(enum proto_t protocol) | 1208 | static int net_check_prereq(enum proto_t protocol) |
1208 | { | 1209 | { |
1209 | switch (protocol) { | 1210 | switch (protocol) { |
1210 | /* Fall through */ | 1211 | /* Fall through */ |
1211 | #if defined(CONFIG_CMD_PING) | 1212 | #if defined(CONFIG_CMD_PING) |
1212 | case PING: | 1213 | case PING: |
1213 | if (NetPingIP == 0) { | 1214 | if (NetPingIP == 0) { |
1214 | puts("*** ERROR: ping address not given\n"); | 1215 | puts("*** ERROR: ping address not given\n"); |
1215 | return 1; | 1216 | return 1; |
1216 | } | 1217 | } |
1217 | goto common; | 1218 | goto common; |
1218 | #endif | 1219 | #endif |
1219 | #if defined(CONFIG_CMD_SNTP) | 1220 | #if defined(CONFIG_CMD_SNTP) |
1220 | case SNTP: | 1221 | case SNTP: |
1221 | if (NetNtpServerIP == 0) { | 1222 | if (NetNtpServerIP == 0) { |
1222 | puts("*** ERROR: NTP server address not given\n"); | 1223 | puts("*** ERROR: NTP server address not given\n"); |
1223 | return 1; | 1224 | return 1; |
1224 | } | 1225 | } |
1225 | goto common; | 1226 | goto common; |
1226 | #endif | 1227 | #endif |
1227 | #if defined(CONFIG_CMD_DNS) | 1228 | #if defined(CONFIG_CMD_DNS) |
1228 | case DNS: | 1229 | case DNS: |
1229 | if (NetOurDNSIP == 0) { | 1230 | if (NetOurDNSIP == 0) { |
1230 | puts("*** ERROR: DNS server address not given\n"); | 1231 | puts("*** ERROR: DNS server address not given\n"); |
1231 | return 1; | 1232 | return 1; |
1232 | } | 1233 | } |
1233 | goto common; | 1234 | goto common; |
1234 | #endif | 1235 | #endif |
1235 | #if defined(CONFIG_CMD_NFS) | 1236 | #if defined(CONFIG_CMD_NFS) |
1236 | case NFS: | 1237 | case NFS: |
1237 | #endif | 1238 | #endif |
1238 | case TFTPGET: | 1239 | case TFTPGET: |
1239 | case TFTPPUT: | 1240 | case TFTPPUT: |
1240 | if (NetServerIP == 0) { | 1241 | if (NetServerIP == 0) { |
1241 | puts("*** ERROR: `serverip' not set\n"); | 1242 | puts("*** ERROR: `serverip' not set\n"); |
1242 | return 1; | 1243 | return 1; |
1243 | } | 1244 | } |
1244 | #if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \ | 1245 | #if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \ |
1245 | defined(CONFIG_CMD_DNS) | 1246 | defined(CONFIG_CMD_DNS) |
1246 | common: | 1247 | common: |
1247 | #endif | 1248 | #endif |
1248 | /* Fall through */ | 1249 | /* Fall through */ |
1249 | 1250 | ||
1250 | case NETCONS: | 1251 | case NETCONS: |
1251 | case TFTPSRV: | 1252 | case TFTPSRV: |
1252 | if (NetOurIP == 0) { | 1253 | if (NetOurIP == 0) { |
1253 | puts("*** ERROR: `ipaddr' not set\n"); | 1254 | puts("*** ERROR: `ipaddr' not set\n"); |
1254 | return 1; | 1255 | return 1; |
1255 | } | 1256 | } |
1256 | /* Fall through */ | 1257 | /* Fall through */ |
1257 | 1258 | ||
1258 | #ifdef CONFIG_CMD_RARP | 1259 | #ifdef CONFIG_CMD_RARP |
1259 | case RARP: | 1260 | case RARP: |
1260 | #endif | 1261 | #endif |
1261 | case BOOTP: | 1262 | case BOOTP: |
1262 | case CDP: | 1263 | case CDP: |
1263 | case DHCP: | 1264 | case DHCP: |
1264 | case LINKLOCAL: | 1265 | case LINKLOCAL: |
1265 | if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) { | 1266 | if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) { |
1266 | int num = eth_get_dev_index(); | 1267 | int num = eth_get_dev_index(); |
1267 | 1268 | ||
1268 | switch (num) { | 1269 | switch (num) { |
1269 | case -1: | 1270 | case -1: |
1270 | puts("*** ERROR: No ethernet found.\n"); | 1271 | puts("*** ERROR: No ethernet found.\n"); |
1271 | return 1; | 1272 | return 1; |
1272 | case 0: | 1273 | case 0: |
1273 | puts("*** ERROR: `ethaddr' not set\n"); | 1274 | puts("*** ERROR: `ethaddr' not set\n"); |
1274 | break; | 1275 | break; |
1275 | default: | 1276 | default: |
1276 | printf("*** ERROR: `eth%daddr' not set\n", | 1277 | printf("*** ERROR: `eth%daddr' not set\n", |
1277 | num); | 1278 | num); |
1278 | break; | 1279 | break; |
1279 | } | 1280 | } |
1280 | 1281 | ||
1281 | NetStartAgain(); | 1282 | NetStartAgain(); |
1282 | return 2; | 1283 | return 2; |
1283 | } | 1284 | } |
1284 | /* Fall through */ | 1285 | /* Fall through */ |
1285 | default: | 1286 | default: |
1286 | return 0; | 1287 | return 0; |
1287 | } | 1288 | } |
1288 | return 0; /* OK */ | 1289 | return 0; /* OK */ |
1289 | } | 1290 | } |
1290 | /**********************************************************************/ | 1291 | /**********************************************************************/ |
1291 | 1292 | ||
1292 | int | 1293 | int |
1293 | NetCksumOk(uchar *ptr, int len) | 1294 | NetCksumOk(uchar *ptr, int len) |
1294 | { | 1295 | { |
1295 | return !((NetCksum(ptr, len) + 1) & 0xfffe); | 1296 | return !((NetCksum(ptr, len) + 1) & 0xfffe); |
1296 | } | 1297 | } |
1297 | 1298 | ||
1298 | 1299 | ||
1299 | unsigned | 1300 | unsigned |
1300 | NetCksum(uchar *ptr, int len) | 1301 | NetCksum(uchar *ptr, int len) |
1301 | { | 1302 | { |
1302 | ulong xsum; | 1303 | ulong xsum; |
1303 | ushort *p = (ushort *)ptr; | 1304 | ushort *p = (ushort *)ptr; |
1304 | 1305 | ||
1305 | xsum = 0; | 1306 | xsum = 0; |
1306 | while (len-- > 0) | 1307 | while (len-- > 0) |
1307 | xsum += *p++; | 1308 | xsum += *p++; |
1308 | xsum = (xsum & 0xffff) + (xsum >> 16); | 1309 | xsum = (xsum & 0xffff) + (xsum >> 16); |
1309 | xsum = (xsum & 0xffff) + (xsum >> 16); | 1310 | xsum = (xsum & 0xffff) + (xsum >> 16); |
1310 | return xsum & 0xffff; | 1311 | return xsum & 0xffff; |
1311 | } | 1312 | } |
1312 | 1313 | ||
1313 | int | 1314 | int |
1314 | NetEthHdrSize(void) | 1315 | NetEthHdrSize(void) |
1315 | { | 1316 | { |
1316 | ushort myvlanid; | 1317 | ushort myvlanid; |
1317 | 1318 | ||
1318 | myvlanid = ntohs(NetOurVLAN); | 1319 | myvlanid = ntohs(NetOurVLAN); |
1319 | if (myvlanid == (ushort)-1) | 1320 | if (myvlanid == (ushort)-1) |
1320 | myvlanid = VLAN_NONE; | 1321 | myvlanid = VLAN_NONE; |
1321 | 1322 | ||
1322 | return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : | 1323 | return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : |
1323 | VLAN_ETHER_HDR_SIZE; | 1324 | VLAN_ETHER_HDR_SIZE; |
1324 | } | 1325 | } |
1325 | 1326 | ||
1326 | int | 1327 | int |
1327 | NetSetEther(uchar *xet, uchar * addr, uint prot) | 1328 | NetSetEther(uchar *xet, uchar * addr, uint prot) |
1328 | { | 1329 | { |
1329 | struct ethernet_hdr *et = (struct ethernet_hdr *)xet; | 1330 | struct ethernet_hdr *et = (struct ethernet_hdr *)xet; |
1330 | ushort myvlanid; | 1331 | ushort myvlanid; |
1331 | 1332 | ||
1332 | myvlanid = ntohs(NetOurVLAN); | 1333 | myvlanid = ntohs(NetOurVLAN); |
1333 | if (myvlanid == (ushort)-1) | 1334 | if (myvlanid == (ushort)-1) |
1334 | myvlanid = VLAN_NONE; | 1335 | myvlanid = VLAN_NONE; |
1335 | 1336 | ||
1336 | memcpy(et->et_dest, addr, 6); | 1337 | memcpy(et->et_dest, addr, 6); |
1337 | memcpy(et->et_src, NetOurEther, 6); | 1338 | memcpy(et->et_src, NetOurEther, 6); |
1338 | if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) { | 1339 | if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) { |
1339 | et->et_protlen = htons(prot); | 1340 | et->et_protlen = htons(prot); |
1340 | return ETHER_HDR_SIZE; | 1341 | return ETHER_HDR_SIZE; |
1341 | } else { | 1342 | } else { |
1342 | struct vlan_ethernet_hdr *vet = | 1343 | struct vlan_ethernet_hdr *vet = |
1343 | (struct vlan_ethernet_hdr *)xet; | 1344 | (struct vlan_ethernet_hdr *)xet; |
1344 | 1345 | ||
1345 | vet->vet_vlan_type = htons(PROT_VLAN); | 1346 | vet->vet_vlan_type = htons(PROT_VLAN); |
1346 | vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK)); | 1347 | vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK)); |
1347 | vet->vet_type = htons(prot); | 1348 | vet->vet_type = htons(prot); |
1348 | return VLAN_ETHER_HDR_SIZE; | 1349 | return VLAN_ETHER_HDR_SIZE; |
1349 | } | 1350 | } |
1350 | } | 1351 | } |
1351 | 1352 | ||
1352 | int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot) | 1353 | int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot) |
1353 | { | 1354 | { |
1354 | ushort protlen; | 1355 | ushort protlen; |
1355 | 1356 | ||
1356 | memcpy(et->et_dest, addr, 6); | 1357 | memcpy(et->et_dest, addr, 6); |
1357 | memcpy(et->et_src, NetOurEther, 6); | 1358 | memcpy(et->et_src, NetOurEther, 6); |
1358 | protlen = ntohs(et->et_protlen); | 1359 | protlen = ntohs(et->et_protlen); |
1359 | if (protlen == PROT_VLAN) { | 1360 | if (protlen == PROT_VLAN) { |
1360 | struct vlan_ethernet_hdr *vet = | 1361 | struct vlan_ethernet_hdr *vet = |
1361 | (struct vlan_ethernet_hdr *)et; | 1362 | (struct vlan_ethernet_hdr *)et; |
1362 | vet->vet_type = htons(prot); | 1363 | vet->vet_type = htons(prot); |
1363 | return VLAN_ETHER_HDR_SIZE; | 1364 | return VLAN_ETHER_HDR_SIZE; |
1364 | } else if (protlen > 1514) { | 1365 | } else if (protlen > 1514) { |
1365 | et->et_protlen = htons(prot); | 1366 | et->et_protlen = htons(prot); |
1366 | return ETHER_HDR_SIZE; | 1367 | return ETHER_HDR_SIZE; |
1367 | } else { | 1368 | } else { |
1368 | /* 802.2 + SNAP */ | 1369 | /* 802.2 + SNAP */ |
1369 | struct e802_hdr *et802 = (struct e802_hdr *)et; | 1370 | struct e802_hdr *et802 = (struct e802_hdr *)et; |
1370 | et802->et_prot = htons(prot); | 1371 | et802->et_prot = htons(prot); |
1371 | return E802_HDR_SIZE; | 1372 | return E802_HDR_SIZE; |
1372 | } | 1373 | } |
1373 | } | 1374 | } |
1374 | 1375 | ||
1375 | void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source) | 1376 | void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source) |
1376 | { | 1377 | { |
1377 | struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt; | 1378 | struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt; |
1378 | 1379 | ||
1379 | /* | 1380 | /* |
1380 | * Construct an IP header. | 1381 | * Construct an IP header. |
1381 | */ | 1382 | */ |
1382 | /* IP_HDR_SIZE / 4 (not including UDP) */ | 1383 | /* IP_HDR_SIZE / 4 (not including UDP) */ |
1383 | ip->ip_hl_v = 0x45; | 1384 | ip->ip_hl_v = 0x45; |
1384 | ip->ip_tos = 0; | 1385 | ip->ip_tos = 0; |
1385 | ip->ip_len = htons(IP_HDR_SIZE); | 1386 | ip->ip_len = htons(IP_HDR_SIZE); |
1386 | ip->ip_id = htons(NetIPID++); | 1387 | ip->ip_id = htons(NetIPID++); |
1387 | ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ | 1388 | ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ |
1388 | ip->ip_ttl = 255; | 1389 | ip->ip_ttl = 255; |
1389 | ip->ip_sum = 0; | 1390 | ip->ip_sum = 0; |
1390 | /* already in network byte order */ | 1391 | /* already in network byte order */ |
1391 | NetCopyIP((void *)&ip->ip_src, &source); | 1392 | NetCopyIP((void *)&ip->ip_src, &source); |
1392 | /* already in network byte order */ | 1393 | /* already in network byte order */ |
1393 | NetCopyIP((void *)&ip->ip_dst, &dest); | 1394 | NetCopyIP((void *)&ip->ip_dst, &dest); |
1394 | } | 1395 | } |
1395 | 1396 | ||
1396 | void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport, int sport, | 1397 | void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport, int sport, |
1397 | int len) | 1398 | int len) |
1398 | { | 1399 | { |
1399 | struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt; | 1400 | struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt; |
1400 | 1401 | ||
1401 | /* | 1402 | /* |
1402 | * If the data is an odd number of bytes, zero the | 1403 | * If the data is an odd number of bytes, zero the |
1403 | * byte after the last byte so that the checksum | 1404 | * byte after the last byte so that the checksum |
1404 | * will work. | 1405 | * will work. |
1405 | */ | 1406 | */ |
1406 | if (len & 1) | 1407 | if (len & 1) |
1407 | pkt[IP_UDP_HDR_SIZE + len] = 0; | 1408 | pkt[IP_UDP_HDR_SIZE + len] = 0; |
1408 | 1409 | ||
1409 | net_set_ip_header(pkt, dest, NetOurIP); | 1410 | net_set_ip_header(pkt, dest, NetOurIP); |
1410 | ip->ip_len = htons(IP_UDP_HDR_SIZE + len); | 1411 | ip->ip_len = htons(IP_UDP_HDR_SIZE + len); |
1411 | ip->ip_p = IPPROTO_UDP; | 1412 | ip->ip_p = IPPROTO_UDP; |
1412 | ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1); | 1413 | ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1); |
1413 | 1414 | ||
1414 | ip->udp_src = htons(sport); | 1415 | ip->udp_src = htons(sport); |
1415 | ip->udp_dst = htons(dport); | 1416 | ip->udp_dst = htons(dport); |
1416 | ip->udp_len = htons(UDP_HDR_SIZE + len); | 1417 | ip->udp_len = htons(UDP_HDR_SIZE + len); |
1417 | ip->udp_xsum = 0; | 1418 | ip->udp_xsum = 0; |
1418 | } | 1419 | } |
1419 | 1420 | ||
1420 | void copy_filename(char *dst, const char *src, int size) | 1421 | void copy_filename(char *dst, const char *src, int size) |
1421 | { | 1422 | { |
1422 | if (*src && (*src == '"')) { | 1423 | if (*src && (*src == '"')) { |
1423 | ++src; | 1424 | ++src; |
1424 | --size; | 1425 | --size; |
1425 | } | 1426 | } |
1426 | 1427 | ||
1427 | while ((--size > 0) && *src && (*src != '"')) | 1428 | while ((--size > 0) && *src && (*src != '"')) |
1428 | *dst++ = *src++; | 1429 | *dst++ = *src++; |
1429 | *dst = '\0'; | 1430 | *dst = '\0'; |
1430 | } | 1431 | } |
1431 | 1432 | ||
1432 | #if defined(CONFIG_CMD_NFS) || \ | 1433 | #if defined(CONFIG_CMD_NFS) || \ |
1433 | defined(CONFIG_CMD_SNTP) || \ | 1434 | defined(CONFIG_CMD_SNTP) || \ |
1434 | defined(CONFIG_CMD_DNS) | 1435 | defined(CONFIG_CMD_DNS) |
1435 | /* | 1436 | /* |
1436 | * make port a little random (1024-17407) | 1437 | * make port a little random (1024-17407) |
1437 | * This keeps the math somewhat trivial to compute, and seems to work with | 1438 | * This keeps the math somewhat trivial to compute, and seems to work with |
1438 | * all supported protocols/clients/servers | 1439 | * all supported protocols/clients/servers |
1439 | */ | 1440 | */ |
1440 | unsigned int random_port(void) | 1441 | unsigned int random_port(void) |
1441 | { | 1442 | { |
1442 | return 1024 + (get_timer(0) % 0x4000); | 1443 | return 1024 + (get_timer(0) % 0x4000); |
1443 | } | 1444 | } |
1444 | #endif | 1445 | #endif |
1445 | 1446 | ||
1446 | void ip_to_string(IPaddr_t x, char *s) | 1447 | void ip_to_string(IPaddr_t x, char *s) |
1447 | { | 1448 | { |
1448 | x = ntohl(x); | 1449 | x = ntohl(x); |
1449 | sprintf(s, "%d.%d.%d.%d", | 1450 | sprintf(s, "%d.%d.%d.%d", |
1450 | (int) ((x >> 24) & 0xff), | 1451 | (int) ((x >> 24) & 0xff), |
1451 | (int) ((x >> 16) & 0xff), | 1452 | (int) ((x >> 16) & 0xff), |
1452 | (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff) | 1453 | (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff) |
1453 | ); | 1454 | ); |
1454 | } | 1455 | } |
1455 | 1456 | ||
1456 | void VLAN_to_string(ushort x, char *s) | 1457 | void VLAN_to_string(ushort x, char *s) |
1457 | { | 1458 | { |
1458 | x = ntohs(x); | 1459 | x = ntohs(x); |
1459 | 1460 | ||
1460 | if (x == (ushort)-1) | 1461 | if (x == (ushort)-1) |
1461 | x = VLAN_NONE; | 1462 | x = VLAN_NONE; |
1462 | 1463 | ||
1463 | if (x == VLAN_NONE) | 1464 | if (x == VLAN_NONE) |
1464 | strcpy(s, "none"); | 1465 | strcpy(s, "none"); |
1465 | else | 1466 | else |
1466 | sprintf(s, "%d", x & VLAN_IDMASK); | 1467 | sprintf(s, "%d", x & VLAN_IDMASK); |
1467 | } | 1468 | } |
1468 | 1469 | ||
1469 | ushort string_to_VLAN(const char *s) | 1470 | ushort string_to_VLAN(const char *s) |
1470 | { | 1471 | { |
1471 | ushort id; | 1472 | ushort id; |
1472 | 1473 | ||
1473 | if (s == NULL) | 1474 | if (s == NULL) |
1474 | return htons(VLAN_NONE); | 1475 | return htons(VLAN_NONE); |
1475 | 1476 | ||
1476 | if (*s < '0' || *s > '9') | 1477 | if (*s < '0' || *s > '9') |
1477 | id = VLAN_NONE; | 1478 | id = VLAN_NONE; |
1478 | else | 1479 | else |
1479 | id = (ushort)simple_strtoul(s, NULL, 10); | 1480 | id = (ushort)simple_strtoul(s, NULL, 10); |
1480 | 1481 | ||
1481 | return htons(id); | 1482 | return htons(id); |
1482 | } | 1483 | } |
1483 | 1484 | ||
1484 | ushort getenv_VLAN(char *var) | 1485 | ushort getenv_VLAN(char *var) |
1485 | { | 1486 | { |
1486 | return string_to_VLAN(getenv(var)); | 1487 | return string_to_VLAN(getenv(var)); |
1487 | } | 1488 | } |
1488 | 1489 |
net/ping.c
1 | /* | 1 | /* |
2 | * Copied from Linux Monitor (LiMon) - Networking. | 2 | * Copied from Linux Monitor (LiMon) - Networking. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * Copyright 2000 Roland Borde | 6 | * Copyright 2000 Roland Borde |
7 | * Copyright 2000 Paolo Scaffardi | 7 | * Copyright 2000 Paolo Scaffardi |
8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de | 8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de |
9 | * SPDX-License-Identifier: GPL-2.0 | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include "ping.h" | 12 | #include "ping.h" |
12 | #include "arp.h" | 13 | #include "arp.h" |
13 | 14 | ||
14 | static ushort PingSeqNo; | 15 | static ushort PingSeqNo; |
15 | 16 | ||
16 | /* The ip address to ping */ | 17 | /* The ip address to ping */ |
17 | IPaddr_t NetPingIP; | 18 | IPaddr_t NetPingIP; |
18 | 19 | ||
19 | static void set_icmp_header(uchar *pkt, IPaddr_t dest) | 20 | static void set_icmp_header(uchar *pkt, IPaddr_t dest) |
20 | { | 21 | { |
21 | /* | 22 | /* |
22 | * Construct an IP and ICMP header. | 23 | * Construct an IP and ICMP header. |
23 | */ | 24 | */ |
24 | struct ip_hdr *ip = (struct ip_hdr *)pkt; | 25 | struct ip_hdr *ip = (struct ip_hdr *)pkt; |
25 | struct icmp_hdr *icmp = (struct icmp_hdr *)(pkt + IP_HDR_SIZE); | 26 | struct icmp_hdr *icmp = (struct icmp_hdr *)(pkt + IP_HDR_SIZE); |
26 | 27 | ||
27 | net_set_ip_header(pkt, dest, NetOurIP); | 28 | net_set_ip_header(pkt, dest, NetOurIP); |
28 | 29 | ||
29 | ip->ip_len = htons(IP_ICMP_HDR_SIZE); | 30 | ip->ip_len = htons(IP_ICMP_HDR_SIZE); |
30 | ip->ip_p = IPPROTO_ICMP; | 31 | ip->ip_p = IPPROTO_ICMP; |
31 | ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1); | 32 | ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1); |
32 | 33 | ||
33 | icmp->type = ICMP_ECHO_REQUEST; | 34 | icmp->type = ICMP_ECHO_REQUEST; |
34 | icmp->code = 0; | 35 | icmp->code = 0; |
35 | icmp->checksum = 0; | 36 | icmp->checksum = 0; |
36 | icmp->un.echo.id = 0; | 37 | icmp->un.echo.id = 0; |
37 | icmp->un.echo.sequence = htons(PingSeqNo++); | 38 | icmp->un.echo.sequence = htons(PingSeqNo++); |
38 | icmp->checksum = ~NetCksum((uchar *)icmp, ICMP_HDR_SIZE >> 1); | 39 | icmp->checksum = ~NetCksum((uchar *)icmp, ICMP_HDR_SIZE >> 1); |
39 | } | 40 | } |
40 | 41 | ||
41 | static int ping_send(void) | 42 | static int ping_send(void) |
42 | { | 43 | { |
43 | uchar *pkt; | 44 | uchar *pkt; |
44 | int eth_hdr_size; | 45 | int eth_hdr_size; |
45 | 46 | ||
46 | /* XXX always send arp request */ | 47 | /* XXX always send arp request */ |
47 | 48 | ||
48 | debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &NetPingIP); | 49 | debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &NetPingIP); |
49 | 50 | ||
50 | NetArpWaitPacketIP = NetPingIP; | 51 | NetArpWaitPacketIP = NetPingIP; |
51 | 52 | ||
52 | eth_hdr_size = NetSetEther(NetTxPacket, NetEtherNullAddr, PROT_IP); | 53 | eth_hdr_size = NetSetEther(NetTxPacket, NetEtherNullAddr, PROT_IP); |
53 | pkt = (uchar *)NetTxPacket + eth_hdr_size; | 54 | pkt = (uchar *)NetTxPacket + eth_hdr_size; |
54 | 55 | ||
55 | set_icmp_header(pkt, NetPingIP); | 56 | set_icmp_header(pkt, NetPingIP); |
56 | 57 | ||
57 | /* size of the waiting packet */ | 58 | /* size of the waiting packet */ |
58 | NetArpWaitTxPacketSize = eth_hdr_size + IP_ICMP_HDR_SIZE; | 59 | NetArpWaitTxPacketSize = eth_hdr_size + IP_ICMP_HDR_SIZE; |
59 | 60 | ||
60 | /* and do the ARP request */ | 61 | /* and do the ARP request */ |
61 | NetArpWaitTry = 1; | 62 | NetArpWaitTry = 1; |
62 | NetArpWaitTimerStart = get_timer(0); | 63 | NetArpWaitTimerStart = get_timer(0); |
63 | ArpRequest(); | 64 | ArpRequest(); |
64 | return 1; /* waiting */ | 65 | return 1; /* waiting */ |
65 | } | 66 | } |
66 | 67 | ||
67 | static void ping_timeout(void) | 68 | static void ping_timeout(void) |
68 | { | 69 | { |
69 | eth_halt(); | 70 | eth_halt(); |
70 | net_set_state(NETLOOP_FAIL); /* we did not get the reply */ | 71 | net_set_state(NETLOOP_FAIL); /* we did not get the reply */ |
71 | } | 72 | } |
72 | 73 | ||
73 | void ping_start(void) | 74 | void ping_start(void) |
74 | { | 75 | { |
75 | printf("Using %s device\n", eth_get_name()); | 76 | printf("Using %s device\n", eth_get_name()); |
76 | NetSetTimeout(10000UL, ping_timeout); | 77 | NetSetTimeout(10000UL, ping_timeout); |
77 | 78 | ||
78 | ping_send(); | 79 | ping_send(); |
79 | } | 80 | } |
80 | 81 | ||
81 | void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) | 82 | void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) |
82 | { | 83 | { |
83 | struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src; | 84 | struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src; |
84 | IPaddr_t src_ip; | 85 | IPaddr_t src_ip; |
85 | int eth_hdr_size; | 86 | int eth_hdr_size; |
86 | 87 | ||
87 | switch (icmph->type) { | 88 | switch (icmph->type) { |
88 | case ICMP_ECHO_REPLY: | 89 | case ICMP_ECHO_REPLY: |
89 | src_ip = NetReadIP((void *)&ip->ip_src); | 90 | src_ip = NetReadIP((void *)&ip->ip_src); |
90 | if (src_ip == NetPingIP) | 91 | if (src_ip == NetPingIP) |
91 | net_set_state(NETLOOP_SUCCESS); | 92 | net_set_state(NETLOOP_SUCCESS); |
92 | return; | 93 | return; |
93 | case ICMP_ECHO_REQUEST: | 94 | case ICMP_ECHO_REQUEST: |
94 | eth_hdr_size = net_update_ether(et, et->et_src, PROT_IP); | 95 | eth_hdr_size = net_update_ether(et, et->et_src, PROT_IP); |
95 | 96 | ||
96 | debug_cond(DEBUG_DEV_PKT, "Got ICMP ECHO REQUEST, return " | 97 | debug_cond(DEBUG_DEV_PKT, "Got ICMP ECHO REQUEST, return " |
97 | "%d bytes\n", eth_hdr_size + len); | 98 | "%d bytes\n", eth_hdr_size + len); |
98 | 99 | ||
99 | ip->ip_sum = 0; | 100 | ip->ip_sum = 0; |
100 | ip->ip_off = 0; | 101 | ip->ip_off = 0; |
101 | NetCopyIP((void *)&ip->ip_dst, &ip->ip_src); | 102 | NetCopyIP((void *)&ip->ip_dst, &ip->ip_src); |
102 | NetCopyIP((void *)&ip->ip_src, &NetOurIP); | 103 | NetCopyIP((void *)&ip->ip_src, &NetOurIP); |
103 | ip->ip_sum = ~NetCksum((uchar *)ip, | 104 | ip->ip_sum = ~NetCksum((uchar *)ip, |
104 | IP_HDR_SIZE >> 1); | 105 | IP_HDR_SIZE >> 1); |
105 | 106 | ||
106 | icmph->type = ICMP_ECHO_REPLY; | 107 | icmph->type = ICMP_ECHO_REPLY; |
107 | icmph->checksum = 0; | 108 | icmph->checksum = 0; |
108 | icmph->checksum = ~NetCksum((uchar *)icmph, | 109 | icmph->checksum = ~NetCksum((uchar *)icmph, |
109 | (len - IP_HDR_SIZE) >> 1); | 110 | (len - IP_HDR_SIZE) >> 1); |
110 | NetSendPacket((uchar *)et, eth_hdr_size + len); | 111 | NetSendPacket((uchar *)et, eth_hdr_size + len); |
111 | return; | 112 | return; |
112 | /* default: | 113 | /* default: |
113 | return;*/ | 114 | return;*/ |
114 | } | 115 | } |
115 | } | 116 | } |
116 | 117 |
net/ping.h
1 | /* | 1 | /* |
2 | * Copied from Linux Monitor (LiMon) - Networking. | 2 | * Copied from Linux Monitor (LiMon) - Networking. |
3 | * | 3 | * |
4 | * Copyright 1994 - 2000 Neil Russell. | 4 | * Copyright 1994 - 2000 Neil Russell. |
5 | * (See License) | 5 | * (See License) |
6 | * Copyright 2000 Roland Borde | 6 | * Copyright 2000 Roland Borde |
7 | * Copyright 2000 Paolo Scaffardi | 7 | * Copyright 2000 Paolo Scaffardi |
8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de | 8 | * Copyright 2000-2002 Wolfgang Denk, wd@denx.de |
9 | * SPDX-License-Identifier: GPL-2.0 | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | #ifndef __PING_H__ | 12 | #ifndef __PING_H__ |
12 | #define __PING_H__ | 13 | #define __PING_H__ |
13 | 14 | ||
14 | #include <common.h> | 15 | #include <common.h> |
15 | #include <net.h> | 16 | #include <net.h> |
16 | 17 | ||
17 | /* | 18 | /* |
18 | * Initialize ping (beginning of netloop) | 19 | * Initialize ping (beginning of netloop) |
19 | */ | 20 | */ |
20 | void ping_start(void); | 21 | void ping_start(void); |
21 | 22 | ||
22 | /* | 23 | /* |
23 | * Deal with the receipt of a ping packet | 24 | * Deal with the receipt of a ping packet |
24 | * | 25 | * |
25 | * @param et Ethernet header in packet | 26 | * @param et Ethernet header in packet |
26 | * @param ip IP header in the same packet | 27 | * @param ip IP header in the same packet |
27 | * @param len Packet length | 28 | * @param len Packet length |
28 | */ | 29 | */ |
29 | void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len); | 30 | void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len); |
30 | 31 | ||
31 | #endif /* __PING_H__ */ | 32 | #endif /* __PING_H__ */ |
32 | 33 |