1 |
786 |
skrzyp |
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
|
6 |
|
|
|
7 |
|
|
|
8 |
|
|
|
9 |
|
|
|
10 |
|
|
|
11 |
|
|
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
|
15 |
|
|
|
16 |
|
|
|
17 |
|
|
|
18 |
|
|
|
19 |
|
|
|
20 |
|
|
|
21 |
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
|
|
TCP/IP Stack Support for eCos
|
32 |
|
|
|
33 |
|
|
|
34 |
|
|
The Common Networking for eCos package
|
35 |
|
|
provides support for a complete TCP/IP networking stack.
|
36 |
|
|
The design allows for the actual stack to be modular and at the
|
37 |
|
|
current time two different implementations, one based on OpenBSD
|
38 |
|
|
from 2000 and a new version based on FreeBSD, are available.
|
39 |
|
|
The particulars of each stack implementation are presented in
|
40 |
|
|
separate sections following this top-level discussion.
|
41 |
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
Ethernet Driver Design
|
45 |
|
|
Currently, the networking stack only supports ethernet based
|
46 |
|
|
networking.
|
47 |
|
|
The network drivers use a two-layer design. One layer is
|
48 |
|
|
hardware independent and contains all the stack specific code.
|
49 |
|
|
The other layer is platform dependent and communicates with the
|
50 |
|
|
hardware independent layer via a very simple API. In this way,
|
51 |
|
|
hardware device drivers can actually be used with other stacks,
|
52 |
|
|
if the same API can be provided by that stack. We designed the
|
53 |
|
|
drivers this way to encourage the development of other stacks in
|
54 |
|
|
eCos while allowing re-use of the actual hardware specific code.
|
55 |
|
|
More comprehensive documentation of the ethernet device driver and
|
56 |
|
|
the associated API can be found in the generic ethernet device driver
|
57 |
|
|
documentation
|
58 |
|
|
|
59 |
|
|
The driver and API is the same as the minimal debug stack used by
|
60 |
|
|
the RedBoot application. See the RedBoot documentation
|
61 |
|
|
for further
|
62 |
|
|
information.
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
Sample Code
|
66 |
|
|
Many examples using the networking support are provided.
|
67 |
|
|
These are arranged as eCos test programs, primarily for use in verifying
|
68 |
|
|
the package, but they can also serve as useful frameworks for program
|
69 |
|
|
design. We have taken a
|
70 |
|
|
KISS
|
71 |
|
|
approach to building programs which
|
72 |
|
|
use the network. A single include file
|
73 |
|
|
<network.h> is
|
74 |
|
|
all that is required to access the stack. A complete, annotated
|
75 |
|
|
test program can be found at
|
76 |
|
|
net/common/VERSION/tests/ftp_test.c,
|
77 |
|
|
with its associated files.
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
Configuring IP Addresses
|
81 |
|
|
Each interface (“eth0” and “eth1”)
|
82 |
|
|
has independent configuration of its setup. Each can be set up
|
83 |
|
|
manually (in which case you must write code to do this), or by using
|
84 |
|
|
BOOTP/DHCP,
|
85 |
|
|
or explicitly, with configured values. If additional
|
86 |
|
|
interfaces are added, these must be configured manually.
|
87 |
|
|
The configurable values are:
|
88 |
|
|
|
89 |
|
|
IP address
|
90 |
|
|
netmask
|
91 |
|
|
broadcast address
|
92 |
|
|
gateway/router
|
93 |
|
|
server address.
|
94 |
|
|
|
95 |
|
|
Server address is the DHCP server if applicable, but in addition,
|
96 |
|
|
many test cases use it as “the machine to talk to” in
|
97 |
|
|
whatever manner the test exercises the protocol stack.
|
98 |
|
|
The initialization is invoked by calling the C routine
|
99 |
|
|
|
100 |
|
|
void init_all_network_interfaces(void);
|
101 |
|
|
|
102 |
|
|
|
103 |
|
|
|
104 |
|
|
Additionally, if the system is configured to support IPv6 then each
|
105 |
|
|
interface may have an address assigned which is a composite of a 64 bit
|
106 |
|
|
prefix and the 32 bit IPv4 address for that interface.
|
107 |
|
|
The prefix is controlled by the CDL setting
|
108 |
|
|
CYGHWR_NET_DRIVER_ETH0_IPV6_PREFIX for “eth0”, etc.
|
109 |
|
|
This is a CDL booldata type, allowing this address to be suppressed if
|
110 |
|
|
not desired.
|
111 |
|
|
|
112 |
|
|
|
113 |
|
|
Alternatively, the system can configure its IPv6 address using
|
114 |
|
|
router solicitation. When the CDL option
|
115 |
|
|
CYGOPT_NET_IPV6_ROUTING_THREAD is enabled,
|
116 |
|
|
init_all_network_interface will start a thread which sends out router solicit messages, process router advertisements and thus configure an IPv6 address to the interface.
|
117 |
|
|
|
118 |
|
|
|
119 |
|
|
Refer to the test cases,
|
120 |
|
|
…/packages/net/common/VERSION/tests/ftp_test.c
|
121 |
|
|
for example usage, and the source files in
|
122 |
|
|
…/packages/net/common/VERSION/src/bootp_support.c
|
123 |
|
|
and
|
124 |
|
|
network_support.c
|
125 |
|
|
to see what that call does.
|
126 |
|
|
This assumes that the MAC address (also known as
|
127 |
|
|
ESA or Ethernet Station Address)
|
128 |
|
|
is already defined in the
|
129 |
|
|
serial EEPROM or however the particular target implements this;
|
130 |
|
|
support for setting the MAC address is hardware dependent.
|
131 |
|
|
DHCP support is active by default, and there are configuration
|
132 |
|
|
options to control it. Firstly, in the top level of the
|
133 |
|
|
“Networking” configuration
|
134 |
|
|
tree, “Use full DHCP instead of BOOTP” enables
|
135 |
|
|
DHCP, and it contains an option to have the system provide a thread
|
136 |
|
|
to renew DHCP leases and manage lease expiry. Secondly, the individual
|
137 |
|
|
interfaces “eth0” and “eth1” each
|
138 |
|
|
have new options within the “Use BOOTP/DHCP to
|
139 |
|
|
initialize ‘ethX’” to
|
140 |
|
|
select whether to use DHCP rather than BOOTP.
|
141 |
|
|
|
142 |
|
|
Note that you are completely at liberty to ignore this startup code and its
|
143 |
|
|
configuration in building your application.
|
144 |
|
|
init_all_network_interfaces()
|
145 |
|
|
is provided for three main purposes:
|
146 |
|
|
|
147 |
|
|
For use by Red Hat's own test programs.
|
148 |
|
|
As an easy “get you going” utility for
|
149 |
|
|
newcomers to eCos.
|
150 |
|
|
As readable example code from which further development
|
151 |
|
|
might start.
|
152 |
|
|
|
153 |
|
|
|
154 |
|
|
If your application has different requirements for bringing up
|
155 |
|
|
available network interfaces, setting up routes, determining IP addresses
|
156 |
|
|
and the like from the defaults that the example code provides, you can
|
157 |
|
|
write your own initialization code to use whatever sequence of
|
158 |
|
|
ioctl() function
|
159 |
|
|
calls carries out the desired setup. Analogously, in larger systems,
|
160 |
|
|
a sequence of “ifconfig&rdquo invocations is used; these mostly
|
161 |
|
|
map to ioctl() calls to manipulate the state of
|
162 |
|
|
the interface in question.
|
163 |
|
|
|
164 |
|
|
|
165 |
|
|
|
166 |
|
|
Tests and Demonstrations
|
167 |
|
|
|
168 |
|
|
Loopback tests
|
169 |
|
|
By default, only tests which can execute on any target
|
170 |
|
|
will be built. These therefore do not actually use external
|
171 |
|
|
network interfaces (though they may configure and initialize
|
172 |
|
|
them) but are limited to testing via the loopback
|
173 |
|
|
interface.
|
174 |
|
|
ping_lo_test - ping test of the loopback address
|
175 |
|
|
tcp_lo_select - simple test of select with TCP via loopback
|
176 |
|
|
tcp_lo_test - trivial TCP test via loopback
|
177 |
|
|
udp_lo_test - trivial UDP test via loopback
|
178 |
|
|
multi_lo_select - test of multiple select() calls simultaneously
|
179 |
|
|
|
180 |
|
|
|
181 |
|
|
Building the Network Tests
|
182 |
|
|
To build further network tests, ensure that the configuration
|
183 |
|
|
option CYGPKG_NET_BUILD_TESTS is set in your build
|
184 |
|
|
and then make the tests in the usual way. Alternatively
|
185 |
|
|
(with that option set) use
|
186 |
|
|
make -C net/common/VERSION/ tests
|
187 |
|
|
after building the eCos library, if you wish to build
|
188 |
|
|
only
|
189 |
|
|
the network tests.
|
190 |
|
|
This should give test executables in
|
191 |
|
|
install/tests/net/common/VERSION/tests
|
192 |
|
|
including
|
193 |
|
|
the following:
|
194 |
|
|
socket_test - trivial test of socket creation API
|
195 |
|
|
mbuf_test - trivial test of mbuf allocation API
|
196 |
|
|
ftp_test - simple FTP test, connects to “server”
|
197 |
|
|
ping_test - pings “server” and non-existent host to test timeout
|
198 |
|
|
dhcp_test - ping test, but also relinquishes and
|
199 |
|
|
reacquires DHCP leases periodically
|
200 |
|
|
flood - a flood ping test; use with care
|
201 |
|
|
tcp_echo - data forwarding program for performance test
|
202 |
|
|
nc_test_master - network characterization master
|
203 |
|
|
nc_test_slave - network characterization slave
|
204 |
|
|
server_test - a very simple server example
|
205 |
|
|
tftp_client_test - performs a tftp get and put from/to “server”
|
206 |
|
|
tftp_server_test - runs a tftp server for a short while
|
207 |
|
|
set_mac_address - set MAC address(es) of interfaces in NVRAM
|
208 |
|
|
bridge - contributed network bridge code
|
209 |
|
|
nc6_test_master - IPv4/IPv6 network characterization master
|
210 |
|
|
nc6_test_slave - IPv4/IPv6 network characterization slave
|
211 |
|
|
ga_server_test - a very simple IPv4/IPv6 server example
|
212 |
|
|
|
213 |
|
|
|
214 |
|
|
|
215 |
|
|
Standalone Tests
|
216 |
|
|
socket_test - trivial test of socket creation API
|
217 |
|
|
mbuf_test - trivial test of mbuf allocation API
|
218 |
|
|
These two do not communicate over the net; they just perform
|
219 |
|
|
simple API tests then exit.
|
220 |
|
|
ftp_test - simple FTP test, connects to “server”
|
221 |
|
|
This test initializes the interface(s) then connects to the
|
222 |
|
|
FTP server on the “server” machine for for each
|
223 |
|
|
active interface in turn, confirms that the connection was successful,
|
224 |
|
|
disconnects and exits. This tests interworking with the server.
|
225 |
|
|
ping_test - pings “server” and non-existent host to test timeout
|
226 |
|
|
This test initializes the interface(s) then pings the server
|
227 |
|
|
machine in the standard way, then pings address “32 up” from
|
228 |
|
|
the server in the expectation that there is no machine there. This
|
229 |
|
|
confirms that the successful ping is not a false positive, and tests
|
230 |
|
|
the receive timeout. If there is such a machine, of course the
|
231 |
|
|
2nd set of pings succeeds, confirming that we can talk to a machine
|
232 |
|
|
not previously mentioned by configuration or by bootp. It then does
|
233 |
|
|
the same thing on the other interface, eth1.
|
234 |
|
|
|
235 |
|
|
If IPv6 is enabled, the program will also ping to the address it
|
236 |
|
|
last received a router advertisement from. Also a ping will be made to
|
237 |
|
|
that address plus 32, in a similar way the the IPv4 case.
|
238 |
|
|
|
239 |
|
|
dhcp_test - ping test, but also manipulates DHCP leases
|
240 |
|
|
This test is very similar to the ping test, but in addition,
|
241 |
|
|
provided the network package is not configured to do this automatically,
|
242 |
|
|
it manually relinquishes and reclaims DHCP leases for all available
|
243 |
|
|
interfaces. This tests the external API to DHCP. See section below
|
244 |
|
|
describing this.
|
245 |
|
|
flood - a flood ping test; use with care
|
246 |
|
|
This test performs pings on all interfaces as quickly as possible,
|
247 |
|
|
and only prints status information periodically. Flood pinging is
|
248 |
|
|
bad for network performance; so do not use this test on general
|
249 |
|
|
purpose networks unless protected by a switch.
|
250 |
|
|
|
251 |
|
|
|
252 |
|
|
Performance Test
|
253 |
|
|
tcp_echo - data forwarding program for performance test
|
254 |
|
|
tcp_echo is one
|
255 |
|
|
part of the standard performance test we use. The other parts are
|
256 |
|
|
host programs tcp_source and tcp_sink.
|
257 |
|
|
To make these (under your HOST system) cd to the tests source directory in
|
258 |
|
|
the eCos repository and type “make -f make.host” -
|
259 |
|
|
this should build tcp_source and tcp_sink.
|
260 |
|
|
The host program “tcp_source” sends
|
261 |
|
|
data to the target. On the target, “tcp_echo” sends
|
262 |
|
|
it onwards to “tcp_sink” running
|
263 |
|
|
on your host. So the target must receive and send on all the data that tcp_source sends
|
264 |
|
|
it; the time taken for this is measured and the data rate is calculated.
|
265 |
|
|
To invoke the test, first start tcp_echo on
|
266 |
|
|
the target board and wait for it to become quiescent - it will report
|
267 |
|
|
work to calibrate a CPU load which can be used to simulate real
|
268 |
|
|
operating conditions for the stack.
|
269 |
|
|
Then on your host machine, in one terminal window, invoke tcp_sink giving
|
270 |
|
|
it the IP address (or hostname) of one interface of the target board.
|
271 |
|
|
For example “tcp_sink 10.130.39.66”.
|
272 |
|
|
tcp_echo on the target
|
273 |
|
|
will print something like “SINK connection
|
274 |
|
|
from 10.130.39.13:1143” when tcp_sink is
|
275 |
|
|
correctly invoked.
|
276 |
|
|
Next, in another host terminal window, invoke tcp_source,
|
277 |
|
|
giving it the IP address (or hostname) of an interface of the target
|
278 |
|
|
board, and optionally a background load to apply to the target while
|
279 |
|
|
the test runs. For example, “tcp_source
|
280 |
|
|
194.130.39.66” to run the test with no
|
281 |
|
|
additional target CPU load, or “tcp_source
|
282 |
|
|
194.130.39.66 85” to load it up to 85% used.
|
283 |
|
|
The target load must be a multiple of 5. tcp_echo on
|
284 |
|
|
the target will print something like “SOURCE
|
285 |
|
|
connection from 194.130.39.13:1144” when
|
286 |
|
|
tcp_source is correctly invoked.
|
287 |
|
|
You can connect tcp_sink to one target interface
|
288 |
|
|
and tcp_source to another, or both to the same interface.
|
289 |
|
|
Similarly, you can run tcp_sink and tcp_source on
|
290 |
|
|
the same host machine or different ones. TCP/IP and ARP
|
291 |
|
|
look after them finding one another, as intended.
|
292 |
|
|
nc_test_master - network characterization master
|
293 |
|
|
nc_test_slave - network characterization slave
|
294 |
|
|
These tests talk to each other to measure network performance.
|
295 |
|
|
They can each run on either a test target or a host computer
|
296 |
|
|
given some customization to your local environment. As provided, nc_test_slave must
|
297 |
|
|
run on the test target, and nc_test_master must
|
298 |
|
|
be run on a host computer, and be given the test target's
|
299 |
|
|
IP address or hostname.
|
300 |
|
|
The tests print network performance for various packet sizes
|
301 |
|
|
over UDP and TCP, versus various additional CPU loads on the target.
|
302 |
|
|
|
303 |
|
|
The programs nc6_test_slave
|
304 |
|
|
nc6_test_master
|
305 |
|
|
are additional forms which support both IPv4 and IPv6 addressing.
|
306 |
|
|
|
307 |
|
|
|
308 |
|
|
|
309 |
|
|
Interactive Tests
|
310 |
|
|
server_test - a very simple server example
|
311 |
|
|
This test simply awaits a connection on port 7734 and after
|
312 |
|
|
accepting a connection, gets a packet (with a timeout of a few seconds)
|
313 |
|
|
and prints it.
|
314 |
|
|
The connection is then closed. We then loop to await the next
|
315 |
|
|
connection, and so on. To use it, telnet to the target on port 7734
|
316 |
|
|
then type something (quickly!)
|
317 |
|
|
% telnet 172.16.19.171 7734
|
318 |
|
|
Hello target board
|
319 |
|
|
and the test program will print something like:
|
320 |
|
|
connection from 172.16.19.13:3369
|
321 |
|
|
buf = "Hello target board"
|
322 |
|
|
|
323 |
|
|
ga_server_test - another very simple server example
|
324 |
|
|
This is a variation on the ga_server_test test
|
325 |
|
|
with the difference being that it uses the getaddrinfo
|
326 |
|
|
function to set up its addresses. On a system with IPv6 enabled, it will
|
327 |
|
|
listen on port 7734 for a TCP connection via either IPv4 or IPv6.
|
328 |
|
|
|
329 |
|
|
|
330 |
|
|
tftp_client_test - performs a tftp get and put from/to “server”
|
331 |
|
|
This is only partially interactive. You need to set things
|
332 |
|
|
up on the “server” in order for this to work,
|
333 |
|
|
and you will need to look at the server afterwards to confirm that all
|
334 |
|
|
was well.
|
335 |
|
|
For each interface in turn, this test attempts to read by
|
336 |
|
|
tftp from the server, a file called
|
337 |
|
|
tftp_get
|
338 |
|
|
and
|
339 |
|
|
prints the status and contents it read (if any). It then writes
|
340 |
|
|
the same data to a file called
|
341 |
|
|
tftp_put
|
342 |
|
|
on
|
343 |
|
|
the same server.
|
344 |
|
|
In order for this to succeed, both files must already exist.
|
345 |
|
|
The TFTP protocol does not require that a WRQ request _create_ a
|
346 |
|
|
file, just that it can write it. The TFTP server on Linux certainly
|
347 |
|
|
will only allow writes to an existing file, given the appropriate
|
348 |
|
|
permission. Thus, you need to have these files in place, with proper permission,
|
349 |
|
|
before running the test.
|
350 |
|
|
The conventional place for the tftp server to operate in LINUX
|
351 |
|
|
is /tftpboot/; you will likely need root privileges
|
352 |
|
|
to create files there. The data contents of
|
353 |
|
|
tftp_get
|
354 |
|
|
can
|
355 |
|
|
be anything you like, but anything very large will waste lots of
|
356 |
|
|
time printing it on the test’s stdout, and anything above
|
357 |
|
|
32kB will cause a buffer overflow and unpredictable failure.
|
358 |
|
|
Creating an empty tftp_put file (eg. by copying /dev/null
|
359 |
|
|
to it) is neatest. So before the test you should have something
|
360 |
|
|
like:
|
361 |
|
|
-rw-rw-rw- 1 root 1076 May 1 11:39 tftp_get
|
362 |
|
|
-rw-rw-rw- 1 root 0 May 1 15:52 tftp_put
|
363 |
|
|
note that both files have public permissions wide open. After
|
364 |
|
|
running the test,
|
365 |
|
|
tftp_put
|
366 |
|
|
should
|
367 |
|
|
be a copy of
|
368 |
|
|
tftp_get.
|
369 |
|
|
-rw-rw-rw- 1 root 1076 May 1 11:39 tftp_get
|
370 |
|
|
-rw-rw-rw- 1 root 1076 May 1 15:52 tftp_put
|
371 |
|
|
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
If the configuration contains IPv6 support, the test program
|
375 |
|
|
will also use IPv6. It will attempt to put/get the files listed above
|
376 |
|
|
from the address it last received a routers solicit from.
|
377 |
|
|
|
378 |
|
|
tftp_server_test - runs a tftp server for a short while
|
379 |
|
|
This test is truly interactive, in that you can use a standard
|
380 |
|
|
tftp application to get and put files from the server, during the
|
381 |
|
|
5 minutes that it runs. The dummy filesystem which underlies the
|
382 |
|
|
server initially contains one file, called “uu” which contains
|
383 |
|
|
part of a familiar text and some padding. It also accommodates
|
384 |
|
|
creation of 3 further files of up to 1Mb in size and names of up
|
385 |
|
|
to 256 bytes. Exceeding these limits will cause a buffer overflow
|
386 |
|
|
and unpredictable failure.
|
387 |
|
|
The dummy filesystem is an implementation of the generic API
|
388 |
|
|
which allows a true filesystem to be attached to the tftp server
|
389 |
|
|
in the network stack.
|
390 |
|
|
We have been testing the tftp server by running the test on
|
391 |
|
|
the target board, then using two different host computers connecting
|
392 |
|
|
to the different target interfaces, putting a file from each, getting
|
393 |
|
|
the “uu” file, and getting the file from the other computer.
|
394 |
|
|
This verifies that data is preserved during the transfer as well
|
395 |
|
|
as interworking with standard tftp applications.
|
396 |
|
|
|
397 |
|
|
|
398 |
|
|
Maintenance Tools
|
399 |
|
|
set_mac_address - set MAC address(es) of interfaces in NVRAM
|
400 |
|
|
This program makes an example ioctl() call
|
401 |
|
|
SIOCSIFHWADDR
|
402 |
|
|
“Socket IO Set InterFace HardWare ADDRess”
|
403 |
|
|
to set the MAC address on targets
|
404 |
|
|
where this is supported and enabled in the configuration. You must
|
405 |
|
|
edit the source to choose a MAC address and further edit it to allow
|
406 |
|
|
this very dangerous operation. Not all ethernet drivers support
|
407 |
|
|
this operation, because most ethernet hardware does not support
|
408 |
|
|
it — or it comes pre-set from the factory.
|
409 |
|
|
Do not use this program.
|
410 |
|
|
|
411 |
|
|
|
412 |
|
|
|
413 |
|
|
Support Features
|
414 |
|
|
|
415 |
|
|
TFTP
|
416 |
|
|
The TFTP client and server are described in
|
417 |
|
|
tftp_support.h;
|
418 |
|
|
|
419 |
|
|
The TFTP client has and new and an older, deprecated, API. The
|
420 |
|
|
new API works for both IPv4 and IPv6 where as the deprecated API is
|
421 |
|
|
IPv4 only.
|
422 |
|
|
|
423 |
|
|
|
424 |
|
|
The new API is as follows:
|
425 |
|
|
|
426 |
|
|
int tftp_client_get(const char * const filename,
|
427 |
|
|
const char * const server,
|
428 |
|
|
const int port,
|
429 |
|
|
char *buf,
|
430 |
|
|
int len,
|
431 |
|
|
const int mode,
|
432 |
|
|
int * const err);
|
433 |
|
|
|
434 |
|
|
int tftp_client_put(const char * const filename,
|
435 |
|
|
const char * const server,
|
436 |
|
|
const int port,
|
437 |
|
|
const char *buf,
|
438 |
|
|
int len,
|
439 |
|
|
const int mode,
|
440 |
|
|
int *const err);
|
441 |
|
|
|
442 |
|
|
Currently server can only be a numeric IPv4 or
|
443 |
|
|
IPv6 address. The resolver is currently not used, but it is planned to
|
444 |
|
|
add this feature (patches welcome). If port is zero
|
445 |
|
|
the client connects to the default TFTP port on the server. Otherwise
|
446 |
|
|
the specified port is used.
|
447 |
|
|
|
448 |
|
|
|
449 |
|
|
The deprecated API is:
|
450 |
|
|
|
451 |
|
|
int tftp_get(const char * const filename,
|
452 |
|
|
const struct sockaddr_in * const server,
|
453 |
|
|
char * buf,
|
454 |
|
|
int len,
|
455 |
|
|
const int mode,
|
456 |
|
|
int * const error);
|
457 |
|
|
|
458 |
|
|
int tftp_put(const char * const filename,
|
459 |
|
|
const struct sockaddr_in * const server,
|
460 |
|
|
const char * buffer,
|
461 |
|
|
int len,
|
462 |
|
|
const int mode,
|
463 |
|
|
int * const err);
|
464 |
|
|
|
465 |
|
|
|
466 |
|
|
|
467 |
|
|
The server should contain the address of the
|
468 |
|
|
server to contact. If the sin_port member of the
|
469 |
|
|
structure is zero the default TFTP port is used. Otherwise the
|
470 |
|
|
specified port is used.
|
471 |
|
|
|
472 |
|
|
|
473 |
|
|
Both API's report errors in the same way. The functions return a value
|
474 |
|
|
of -1 and *err will be set to one of the
|
475 |
|
|
following values:
|
476 |
|
|
|
477 |
|
|
|
478 |
|
|
#define TFTP_ENOTFOUND 1 /* file not found */
|
479 |
|
|
#define TFTP_EACCESS 2 /* access violation */
|
480 |
|
|
#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */
|
481 |
|
|
#define TFTP_EBADOP 4 /* illegal TFTP operation */
|
482 |
|
|
#define TFTP_EBADID 5 /* unknown transfer ID */
|
483 |
|
|
#define TFTP_EEXISTS 6 /* file already exists */
|
484 |
|
|
#define TFTP_ENOUSER 7 /* no such user */
|
485 |
|
|
#define TFTP_TIMEOUT 8 /* operation timed out */
|
486 |
|
|
#define TFTP_NETERR 9 /* some sort of network error */
|
487 |
|
|
#define TFTP_INVALID 10 /* invalid parameter */
|
488 |
|
|
#define TFTP_PROTOCOL 11 /* protocol violation */
|
489 |
|
|
#define TFTP_TOOLARGE 12 /* file is larger than buffer */
|
490 |
|
|
|
491 |
|
|
If there are no errors the return value is the number of bytes
|
492 |
|
|
transfered.
|
493 |
|
|
|
494 |
|
|
|
495 |
|
|
The server is more complex. It requires a filesystem implementation
|
496 |
|
|
to be supplied by the user, and attached to the tftp server by means
|
497 |
|
|
of a vector of function pointers:
|
498 |
|
|
struct tftpd_fileops {
|
499 |
|
|
int (*open)(const char *, int);
|
500 |
|
|
int (*close)(int);
|
501 |
|
|
int (*write)(int, const void *, int);
|
502 |
|
|
int (*read)(int, void *, int);
|
503 |
|
|
};
|
504 |
|
|
These functions have the obvious semantics. The structure
|
505 |
|
|
describing the filesystem is an argument to the tftpd_start:
|
506 |
|
|
|
507 |
|
|
int tftp_start(int port,
|
508 |
|
|
struct tftpd_fileops *ops);
|
509 |
|
|
|
510 |
|
|
|
511 |
|
|
The first argument is the port to use for the server. If this
|
512 |
|
|
port number is zero, the default TFTP port number will be used. The
|
513 |
|
|
return value from tftpd_start is a handle which
|
514 |
|
|
can be passed to tftpd_stop. This will kill the
|
515 |
|
|
tftpd thread. Note that this is not a clean shutdown. The thread will
|
516 |
|
|
simply be killed. tftpd_stop will attempt to
|
517 |
|
|
close the sockets the thread was listening on and free some of its
|
518 |
|
|
allocated memory. But if the thread was actively transferreing data at
|
519 |
|
|
the time tftpd_stop is called, it is quite likely
|
520 |
|
|
some memory and a socket will be leaked. Use this function with
|
521 |
|
|
caution (or implement a clean shutdown and please contribute the code
|
522 |
|
|
back :-).
|
523 |
|
|
|
524 |
|
|
|
525 |
|
|
There are two CDL configuration options that control how many
|
526 |
|
|
servers on how many different ports tftp can be
|
527 |
|
|
started. CYGSEM_NET_TFTPD_MULTITHREADED, when enabled, allows multiple
|
528 |
|
|
tftpd threads to operate on the same port number. With only one
|
529 |
|
|
thread, while the thread is active transferring data, new requests for
|
530 |
|
|
transfers will not be served until the active transfer is
|
531 |
|
|
complete. When multiple threads are started on the same port, multiple
|
532 |
|
|
transfers can take place simultaneous, up to the number of threads
|
533 |
|
|
started. However a semaphore is required to synchronise the
|
534 |
|
|
threads. This semaphore is required per port. The CDL option
|
535 |
|
|
CYGNUM_NET_TFTPD_MULTITHREADED_PORTS controls how many different port
|
536 |
|
|
numbers multithreaded servers can service.
|
537 |
|
|
|
538 |
|
|
If CYGSEM_NET_TFTPD_MULTITHREADED is not enabled, only one
|
539 |
|
|
thread may be run per port number. But this removes the need for a
|
540 |
|
|
semaphore and so CYGNUM_NET_TFTPD_MULTITHREADED_PORTS is not required
|
541 |
|
|
and unlimited number of ports can be used.
|
542 |
|
|
|
543 |
|
|
It should be noted that the TFTPD does not perform any form of
|
544 |
|
|
file locking. When multiple servers are active, it is assumed the
|
545 |
|
|
underlying filesystem will refuse to open the same file multiple
|
546 |
|
|
times, operate correctly with simultaneous read/writes to the same
|
547 |
|
|
file, or if you are unlucky, corrupt itself beyond all repair.
|
548 |
|
|
|
549 |
|
|
When IPv6 is enabled the tftpd thread will listen for requests
|
550 |
|
|
from both IPv4 and IPv6 addresses.
|
551 |
|
|
|
552 |
|
|
As discussed in the description of the tftp_server_test
|
553 |
|
|
above, an example filesystem is provided in
|
554 |
|
|
net/common/VERSION/src/tftp_dummy_file.c
|
555 |
|
|
for
|
556 |
|
|
use by the tftp server test. The dummy filesystem is not a supported
|
557 |
|
|
part of the network stack, it exists purely for demonstration purposes.
|
558 |
|
|
|
559 |
|
|
|
560 |
|
|
DHCP
|
561 |
|
|
This API publishes a routine to maintain DHCP state, and a
|
562 |
|
|
semaphore that is signalled when a lease requires attention: this
|
563 |
|
|
is your clue to call the aforementioned routine.
|
564 |
|
|
The intent with this API is that a simple DHCP client thread,
|
565 |
|
|
which maintains the state of the interfaces, can go as follows:
|
566 |
|
|
(after init_all_network_interfaces() is
|
567 |
|
|
called from elsewhere)
|
568 |
|
|
while ( 1 ) {
|
569 |
|
|
while ( 1 ) {
|
570 |
|
|
cyg_semaphore_wait( &dhcp_needs_attention );
|
571 |
|
|
if ( ! dhcp_bind() ) // a lease expired
|
572 |
|
|
break; // If we need to re-bind
|
573 |
|
|
}
|
574 |
|
|
dhcp_halt(); // tear everything down
|
575 |
|
|
init_all_network_interfaces(); // re-initialize
|
576 |
|
|
}
|
577 |
|
|
and if the application does not want to suffer the overhead
|
578 |
|
|
of a separate thread and its stack for this, this functionality
|
579 |
|
|
can be placed in the app’s server loop in an obvious fashion.
|
580 |
|
|
That is the goal of breaking out these internal elements. For example,
|
581 |
|
|
some server might be arranged to poll DHCP from time to time like
|
582 |
|
|
this:
|
583 |
|
|
while ( 1 ) {
|
584 |
|
|
init_all_network_interfaces();
|
585 |
|
|
open-my-listen-sockets();
|
586 |
|
|
while ( 1 ) {
|
587 |
|
|
serve-one-request();
|
588 |
|
|
// sleeps if no connections, but not forever;
|
589 |
|
|
// so this loop is polled a few times a minute...
|
590 |
|
|
if ( cyg_semaphore_trywait( &dhcp_needs_attention )) {
|
591 |
|
|
if ( ! dhcp_bind() ) {
|
592 |
|
|
close-my-listen-sockets();
|
593 |
|
|
dhcp_halt();
|
594 |
|
|
break;
|
595 |
|
|
}
|
596 |
|
|
}
|
597 |
|
|
}
|
598 |
|
|
}
|
599 |
|
|
If the configuration option CYGOPT_NET_DHCP_DHCP_THREAD
|
600 |
|
|
is defined, then eCos provides a thread as described initially.
|
601 |
|
|
Independent of this option, initialization of the interfaces still
|
602 |
|
|
occurs in init_all_network_interfaces() and
|
603 |
|
|
your startup code can call that. It will start the DHCP management
|
604 |
|
|
thread if configured. If a lease fails to be renewed, the management
|
605 |
|
|
thread will shut down all interfaces and attempt to initialize all
|
606 |
|
|
the interfaces again from scratch. This may cause chaos in the
|
607 |
|
|
app, which is why managing the DHCP state in an application aware
|
608 |
|
|
thread is actually better, just far less convenient for testing.
|
609 |
|
|
|
610 |
|
|
If the configuration option CYGOPT_NET_DHCP_OPTION_HOST_NAME
|
611 |
|
|
is defined, then the TAG_HOST_NAME DHCP option will be included
|
612 |
|
|
in any DHCP lease requests. The text for the hostname is set by
|
613 |
|
|
calling dhcp_set_hostname(). Any DHCP lease requests
|
614 |
|
|
made prior to calling dhcp_set_hostname() will not
|
615 |
|
|
include the TAG_HOST_NAME DHCP option. The configuration option
|
616 |
|
|
CYGNUM_NET_DHCP_OPTION_HOST_NAME_LEN controls the maximum length allowed
|
617 |
|
|
for the hostname. This permits the hostname text to be determined at
|
618 |
|
|
run-time. Setting the hostname to the empty string will have the effect
|
619 |
|
|
of disabling the TAG_HOST_NAME DHCP option.
|
620 |
|
|
If the configuration option CYGOPT_NET_DHCP_OPTION_DHCP_CLIENTID_MAC
|
621 |
|
|
is defined, then the TAG_DHCP_CLIENTID DHCP option will be included
|
622 |
|
|
in any DHCP lease requests. The client ID used will be the current
|
623 |
|
|
MAC address of the network interface.
|
624 |
|
|
|
625 |
|
|
The option CYGOPT_NET_DHCP_PARM_REQ_LIST_ADDITIONAL allows
|
626 |
|
|
additional DHCP options to be added to the request sent to the DHCP
|
627 |
|
|
server. This option should be set to a comma separated list of options.
|
628 |
|
|
|
629 |
|
|
|
630 |
|
|
The option CYGOPT_NET_DHCP_PARM_REQ_LIST_REPLACE is similar to
|
631 |
|
|
CYGOPT_NET_DHCP_PARM_REQ_LIST_ADDITIONAL but in this case it
|
632 |
|
|
completely replaces the default list of options with the configured
|
633 |
|
|
set of comma separated options.
|
634 |
|
|
|
635 |
|
|
|
636 |
|
|
&net-common-tcpip-manpages-sgml;
|
637 |
|
|
|