annotate packages/net/common/current/src/tftp_server.c @ 957:db3e0a2fda2f

2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch> * src/network_support.c (init_loopback_interface): Close the socket when things go wrong otherwise we leak sockets. * src/tftp_server.c (tftpd_server): Added support for IPv6 as well as IPv4. Extended the multithreading support so that it works correctly when there are multiple servers on multiple ports. * doc/tcpip.sgml: Documentation for the changes made to the tftp server. 2003-04-10 Andrew Lunn <andrew.lunn@ascom.ch> * src/network_support.c (init_all_network_interfaces): Wait upto 4 seconds for a router solicit message to be received. Once we have received the message we know we have a valid IPv6 address. * src/tftp_client.c: Added support for IPv6. This requires two new functions, tftp_client_{get|put} which are protocol version independent. * tests/tftp_client_test.c (tftp_test): Added tests which use IPv6 addresses. 2003-04-07 Andrew Lunn <andrew.lunn@ascom.ch> * src/getaddrinfo.c (getaddrinfo): Correctly deal with node when its not NULL. Its OK for the address to not parse for an address family when AF_UNSPEC is passed in hints. Also get the socktype correct when wildcarding for services that use UDP. * tests/addr_test.c: Added more test cases which test IP addresses in number format as node. 2003-04-05 Andrew Lunn <andrew.lunn@ascom.ch> * cdl/net.cdl: Added addr_tests to the HW tests. * tests/addr_test.c (net_test): void function not int. * tests/ping_test.c (net_test): Added IPv6 ping test. This pings the router which answers our router solicit message. * src/ipv6_routing_thread.c (cyg_rs): Print out the router advertisement message. Cleaned up the debug messages so they can be disabled. * src/ipv6_routing_thread.c (cyg_net_get_ipv6_advrouter): New function to return the address of the router. * include/network.h: Added prototype for above and ipv6_start_routing_thread which did not have a prototype. * src/ipv6_routing_thread.c (cyg_rs): Only wait 2 seconds before sending the first solicit request rather than 10. * src/dhcp_prot.c (do_dhcp_down_net): clear the if_laddrreq before using it. If the request fails finish the IPv4 code rather than returning,. 2003-04-02 Andrew Lunn <andrew.lunn@ascom.ch> * tests/ping_lo_test.c: Added IPv6 ping test. * src/getproto.c: Added the protocol ipv6-icmp.
author asl
date Wed, 23 Apr 2003 08:52:08 +0000
parents 7c34839e7e97
children 16d247bb9c70
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
1 //==========================================================================
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
2 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
3 // lib/tftp_server.c
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
4 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
5 // TFTP server support
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
6 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
7 //==========================================================================
490
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
8 //####ECOSGPLCOPYRIGHTBEGIN####
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
9 // -------------------------------------------
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
10 // This file is part of eCos, the Embedded Configurable Operating System.
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
12 // Copyright (C) 2003 Andrew Lunn
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
13 //
490
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
14 // eCos is free software; you can redistribute it and/or modify it under
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
15 // the terms of the GNU General Public License as published by the Free
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
16 // Software Foundation; either version 2 or (at your option) any later version.
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
17 //
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
21 // for more details.
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
22 //
490
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
23 // You should have received a copy of the GNU General Public License along
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
26 //
490
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
27 // As a special exception, if other files instantiate templates or use macros
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
28 // or inline functions from this file, or you compile this file and link it
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
29 // with other works to produce a work based on this file, this file does not
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
30 // by itself cause the resulting work to be covered by the GNU General Public
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
31 // License. However the source code for this file must still be made available
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
32 // in accordance with section (3) of the GNU General Public License.
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
33 //
490
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
34 // This exception does not invalidate any other reasons why a work based on
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
35 // this file might be covered by the GNU General Public License.
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
36 //
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
38 // at http://sources.redhat.com/ecos/ecos-license/
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
39 // -------------------------------------------
7c34839e7e97 * src/bootp_support.c: Fix licence which should always have been
jlarmour
parents: 270
diff changeset
40 //####ECOSGPLCOPYRIGHTEND####
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
41 //==========================================================================
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
42 //#####DESCRIPTIONBEGIN####
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
43 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
44 // Author(s): gthomas
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
45 // Contributors: gthomas, hmt, andrew.lunn@ascom.ch (Andrew Lunn)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
46 // Date: 2000-04-06
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
47 // Purpose:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
48 // Description:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
49 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
50 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
51 //####DESCRIPTIONEND####
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
52 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
53 //==========================================================================
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
54
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
55 // TFTP server support
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
56
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
57 #include <network.h> // Basic networking support
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
58 #include <arpa/tftp.h> // TFTP protocol definitions
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
59 #include <tftp_support.h> // TFTPD structures
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
60 #include <cyg/kernel/kapi.h>
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
61 #include <stdlib.h> // For malloc
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
62
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
63 #define nCYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
64 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
65
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
66 struct subinfo {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
67 int rx;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
68 int rx_repeat;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
69 int rx_skip;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
70 int send;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
71 int resend;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
72 };
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
73
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
74 struct info {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
75 struct subinfo ack, data;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
76 int err_send;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
77 int total_transactions;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
78 };
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
79
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
80
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
81 static struct info tftp_server_instrument = {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
82 { 0,0,0,0,0 },
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
83 { 0,0,0,0,0 },
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
84 0, 0,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
85 };
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
86
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
87 #endif // CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
88
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
89 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
90 struct tftpd_sem {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
91 int port;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
92 cyg_sem_t sem;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
93 };
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
94
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
95 static struct tftpd_sem tftpd_sems[CYGNUM_NET_TFTPD_MULTITHREADED_PORTS];
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
96 #endif //CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
97
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
98 #define STACK_SIZE (((CYGNUM_HAL_STACK_SIZE_TYPICAL+(3*(SEGSIZE+sizeof(struct tftphdr)))) + CYGARC_ALIGNMENT-1) & ~(CYGARC_ALIGNMENT-1))
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
99 static char *TFTP_tag = "TFTPD";
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
100 #define CYGNUM_NET_MAX_INET_PROTOS 2
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
101 struct tftp_server {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
102 char *tag;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
103 char stack[STACK_SIZE];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
104 cyg_thread thread_data;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
105 cyg_handle_t thread_handle;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
106 int port;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
107 struct tftpd_fileops *ops;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
108 int s[CYGNUM_NET_MAX_INET_PROTOS], num_s;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
109 struct addrinfo *res;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
110 };
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
111
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
112 static char * errmsg[] = {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
113 "Undefined error code", // 0 nothing defined
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
114 "File not found", // 1 TFTP_ENOTFOUND
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
115 "Access violation", // 2 TFTP_EACCESS
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
116 "Disk full or allocation exceeded", // 3 TFTP_ENOSPACE
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
117 "Illegal TFTP operation", // 4 TFTP_EBADOP
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
118 "Unknown transfer ID", // 5 TFTP_EBADID
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
119 "File already exists", // 6 TFTP_EEXISTS
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
120 "No such user", // 7 TFTP_ENOUSER
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
121 };
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
122
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
123 // Little helper function to set the port number in an address
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
124 static void set_port(struct sockaddr * address, int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
125
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
126 switch (address->sa_family) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
127 case AF_INET:{
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
128 struct sockaddr_in *addr = (struct sockaddr_in *)address;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
129 addr->sin_port = ntohs(port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
130 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
131 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
132 #ifdef CYGPKG_NET_INET6
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
133 case AF_INET6:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
134 {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
135 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)address;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
136 addr->sin6_port = ntohs(port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
137 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
138 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
139 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
140 default:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
141 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
142 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
143 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
144
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
145 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
146
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
147 // Allocate a semaphore for a given port number if one is not already
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
148 // allocated.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
149 static void sem_alloc(int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
150 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
151
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
152 CYG_ASSERT(port != 0, "Invalid port number");
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
153
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
154 cyg_scheduler_lock(); // Avoid race with other tftpd's
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
155 for (i=0; i < CYGNUM_NET_TFTPD_MULTITHREADED_PORTS; i++) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
156 if (tftpd_sems[i].port == port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
157 cyg_scheduler_unlock();
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
158 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
159 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
160 if (tftpd_sems[i].port == 0) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
161 tftpd_sems[i].port = port;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
162 cyg_semaphore_init(&tftpd_sems[i].sem,1);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
163 cyg_scheduler_unlock();
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
164 return ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
165 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
166 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
167 cyg_scheduler_unlock();
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
168 diag_printf("TFTPD: Unable to allocate a semaphore for port %d\n",port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
169 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
170
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
171 // Wait on the semaphore for a given port number.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
172 static void sem_wait(int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
173 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
174 CYG_ASSERT(port != 0, "Invalid port number");
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
175
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
176 for (i=0; i < CYGNUM_NET_TFTPD_MULTITHREADED_PORTS; i++) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
177 if (tftpd_sems[i].port == port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
178 cyg_semaphore_wait(&tftpd_sems[i].sem);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
179 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
180 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
181 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
182 diag_printf("TFTPD: No semaphore for port %d\n",port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
183 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
184
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
185 // Release the semaphore for a given port number.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
186 static void sem_post(int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
187 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
188 CYG_ASSERT(port != 0, "Invalid port number");
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
189
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
190 for (i=0; i < CYGNUM_NET_TFTPD_MULTITHREADED_PORTS; i++) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
191 if (tftpd_sems[i].port == port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
192 cyg_semaphore_post(&tftpd_sems[i].sem);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
193 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
194 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
195 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
196 diag_printf("TFTPD: No semaphore for port %d\n",port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
197 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
198 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
199
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
200 /* Send an error packet to the client */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
201 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
202 tftpd_send_error(int s, struct tftphdr * reply, int err,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
203 struct sockaddr *from_addr, int from_len)
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
204 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
205 CYG_ASSERT( 0 <= err, "err underflow" );
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
206 CYG_ASSERT( sizeof(errmsg)/sizeof(errmsg[0]) > err, "err overflow" );
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
207
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
208 reply->th_opcode = htons(ERROR);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
209 reply->th_code = htons(err);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
210 if ( (0 > err) || (sizeof(errmsg)/sizeof(errmsg[0]) <= err) )
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
211 err = 0; // Do not copy a random string from hyperspace
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
212 strcpy(reply->th_msg, errmsg[err]);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
213 sendto(s, reply, 4+strlen(reply->th_msg)+1, 0,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
214 from_addr, from_len);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
215 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
216
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
217 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
218 // Receive a file from the client
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
219 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
220 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
221 tftpd_write_file(struct tftp_server *server,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
222 struct tftphdr *hdr,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
223 struct sockaddr *from_addr, int from_len)
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
224 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
225 char data_out[SEGSIZE+sizeof(struct tftphdr)];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
226 char data_in[SEGSIZE+sizeof(struct tftphdr)];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
227 struct tftphdr *reply = (struct tftphdr *)data_out;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
228 struct tftphdr *response = (struct tftphdr *)data_in;
270
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
229 int fd, len, ok, tries, closed, data_len, s;
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
230 unsigned short block;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
231 struct timeval timeout;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
232 fd_set fds;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
233 int total_timeouts = 0;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
234 struct sockaddr client_addr;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
235 struct addrinfo hints;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
236 struct addrinfo *res;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
237 int client_len;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
238 int error;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
239
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
240 memset(&hints,0,sizeof(hints));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
241 hints.ai_family = from_addr->sa_family;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
242 hints.ai_flags = AI_PASSIVE;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
243
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
244 error = getaddrinfo(NULL,"tftp",&hints, &res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
245 if (0 != error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
246 diag_printf("TFTPD: can't get a suitable local address: %s\n",
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
247 gai_strerror(error));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
248 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
249 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
250 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
251 if (s < 0) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
252 diag_printf("TFTPD: can't open socket for 'write_file'\n");
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
253 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
254 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
255 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
256
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
257 // We want the stack to pick a free local port number
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
258 set_port(res->ai_addr,0);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
259
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
260 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
261 // Problem setting up my end
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
262 diag_printf("TFTPD: can't bind to reply port for 'write_file'\n");
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
263 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
264 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
265 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
266 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
267 if ((fd = (server->ops->open)(hdr->th_stuff, O_WRONLY)) < 0) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
268 tftpd_send_error(s,reply,TFTP_ENOTFOUND,from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
269 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
270 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
271 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
272 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
273 ok = true;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
274 closed = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
275 block = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
276 while (ok) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
277 // Send ACK telling client he can send data
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
278 reply->th_opcode = htons(ACK);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
279 reply->th_block = htons(block++); // postincrement
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
280 for (tries = 0; tries < TFTP_RETRIES_MAX; tries++) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
281 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
282 tftp_server_instrument.ack.send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
283 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
284 sendto(s, reply, 4, 0, from_addr, from_len);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
285 repeat_select:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
286 timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
287 timeout.tv_usec = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
288 FD_ZERO(&fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
289 FD_SET(s, &fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
290 if (select(s+1, &fds, 0, 0, &timeout) <= 0) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
291 if (++total_timeouts > TFTP_TIMEOUT_MAX) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
292 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
293 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
294 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
295 tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
296 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
297 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
298 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
299 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
300 tftp_server_instrument.ack.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
301 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
302 continue; // retry the send, using up one retry.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
303 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
304 // Some data has arrived
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
305 data_len = sizeof(data_in);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
306 client_len = sizeof(client_addr);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
307 if ((data_len = recvfrom(s, data_in, data_len, 0,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
308 &client_addr, &client_len)) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
309 // What happened? No data here!
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
310 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
311 tftp_server_instrument.ack.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
312 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
313 continue; // retry the send, using up one retry.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
314 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
315 if (ntohs(response->th_opcode) == DATA &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
316 ntohs(response->th_block) < block) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
317 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
318 tftp_server_instrument.data.rx_repeat++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
319 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
320 // Then it is repeat DATA with an old block; listen again,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
321 // but do not repeat sending the current ack, and do not
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
322 // use up a retry count. (we do re-send the ack if
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
323 // subsequently we time out)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
324 goto repeat_select;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
325 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
326 if (ntohs(response->th_opcode) == DATA &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
327 ntohs(response->th_block) == block) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
328 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
329 tftp_server_instrument.data.rx++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
330 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
331 // Good data - write to file
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
332 len = (server->ops->write)(fd, response->th_data, data_len-4);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
333 if (len < (data_len-4)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
334 // File is "full"
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
335 tftpd_send_error(s,reply,TFTP_ENOSPACE,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
336 from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
337 ok = false; // Give up
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
338 break; // out of the retries loop
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
339 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
340 if (data_len < (SEGSIZE+4)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
341 // End of file
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
342 closed = true;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
343 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
344 if ((server->ops->close)(fd) == -1) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
345 tftpd_send_error(s,reply,TFTP_EACCESS,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
346 from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
347 break; // out of the retries loop
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
348 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
349 // Exception to the loop structure: we must ACK the last
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
350 // packet, the one that implied EOF:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
351 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
352 tftp_server_instrument.ack.send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
353 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
354 reply->th_opcode = htons(ACK);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
355 reply->th_block = htons(block++); // postincrement
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
356 sendto(s, reply, 4, 0, from_addr, from_len);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
357 break; // out of the retries loop
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
358 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
359 // Happy! Break out of the retries loop.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
360 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
361 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
362 // Otherwise, we got something we do not understand! So repeat
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
363 // sending the current ACK, and use up a retry count.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
364 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
365 if ( (ntohs(response->th_opcode) == DATA) )
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
366 tftp_server_instrument.data.rx_skip++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
367 tftp_server_instrument.ack.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
368 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
369 } // End of the retries loop.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
370 if (TFTP_RETRIES_MAX <= tries) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
371 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
372 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
373 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
374 tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
375 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
376 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
377 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
378 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
379 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
380 if (!closed) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
381 (server->ops->close)(fd);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
382 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
383 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
384
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
385 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
386 // Send a file to the client
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
387 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
388 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
389 tftpd_read_file(struct tftp_server *server,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
390 struct tftphdr *hdr,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
391 struct sockaddr *from_addr, int from_len)
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
392 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
393 char data_out[SEGSIZE+sizeof(struct tftphdr)];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
394 char data_in[SEGSIZE+sizeof(struct tftphdr)];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
395 struct tftphdr *reply = (struct tftphdr *)data_out;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
396 struct tftphdr *response = (struct tftphdr *)data_in;
270
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
397 int fd, len, tries, ok, data_len, s;
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
398 unsigned short block;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
399 struct timeval timeout;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
400 fd_set fds;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
401 int total_timeouts = 0;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
402 struct sockaddr client_addr;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
403 struct addrinfo hints;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
404 struct addrinfo *res;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
405 int client_len;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
406 int error;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
407
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
408 memset(&hints,0,sizeof(hints));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
409 hints.ai_family = from_addr->sa_family;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
410 hints.ai_flags = AI_PASSIVE;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
411
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
412 error = getaddrinfo(NULL,"tftp",&hints, &res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
413 if (0 != error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
414 diag_printf("TFTPD: can't get a suitable local address: %s\n",
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
415 gai_strerror(error));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
416 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
417 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
418 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
419 if (s < 0) {
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
420 diag_printf("TFTPD: can't open socket for 'write_file'\n");
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
421 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
422 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
423 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
424
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
425 // We want the stack to pick a free local port number
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
426 set_port(res->ai_addr,0);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
427
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
428 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
429 // Problem setting up my end
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
430 diag_printf("TFTPD: can't bind to reply port for 'write_file'\n");
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
431 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
432 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
433 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
434 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
435
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
436 if ((fd = (server->ops->open)(hdr->th_stuff, O_WRONLY)) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
437 tftpd_send_error(s,reply,TFTP_ENOTFOUND,from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
438 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
439 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
440 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
441 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
442 block = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
443 ok = true;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
444 while (ok) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
445 // Read next chunk of file
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
446 len = (server->ops->read)(fd, reply->th_data, SEGSIZE);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
447 reply->th_block = htons(++block); // preincrement
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
448 reply->th_opcode = htons(DATA);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
449 for (tries = 0; tries < TFTP_RETRIES_MAX; tries++) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
450 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
451 tftp_server_instrument.data.send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
452 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
453 if (sendto(s, reply, 4+len, 0,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
454 from_addr, from_len) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
455 // Something went wrong with the network!
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
456 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
457 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
458 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
459 repeat_select:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
460 timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
461 timeout.tv_usec = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
462 FD_ZERO(&fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
463 FD_SET(s, &fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
464 if (select(s+1, &fds, 0, 0, &timeout) <= 0) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
465 if (++total_timeouts > TFTP_TIMEOUT_MAX) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
466 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
467 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
468 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
469 tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
470 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
471 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
472 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
473 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
474 tftp_server_instrument.data.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
475 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
476 continue; // retry the send, using up one retry.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
477 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
478 data_len = sizeof(data_in);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
479 client_len = sizeof(client_addr);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
480 if ((data_len = recvfrom(s, data_in, data_len, 0,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
481 &client_addr,
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
482 &client_len)) < 0) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
483 // What happened? Maybe someone lied to us...
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
484 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
485 tftp_server_instrument.data.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
486 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
487 continue; // retry the send, using up one retry.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
488 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
489 if ((ntohs(response->th_opcode) == ACK) &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
490 (ntohs(response->th_block) < block)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
491 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
492 tftp_server_instrument.ack.rx_repeat++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
493 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
494 // Then it is a repeat ACK for an old block; listen again,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
495 // but do not repeat sending the current block, and do not
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
496 // use up a retry count. (we do re-send the data if
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
497 // subsequently we time out)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
498 goto repeat_select;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
499 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
500 if ((ntohs(response->th_opcode) == ACK) &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
501 (ntohs(response->th_block) == block)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
502 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
503 tftp_server_instrument.ack.rx++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
504 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
505 // Happy! Break out of the retries loop.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
506 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
507 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
508 // Otherwise, we got something we do not understand! So repeat
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
509 // sending the current block, and use up a retry count.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
510 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
511 if ( (ntohs(response->th_opcode) == ACK) )
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
512 tftp_server_instrument.ack.rx_skip++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
513 tftp_server_instrument.data.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
514 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
515 } // End of the retries loop.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
516 if (TFTP_RETRIES_MAX <= tries) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
517 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
518 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
519 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
520 tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
521 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
522 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
523 if (len < SEGSIZE) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
524 break; // That's end of file then.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
525 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
526 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
527 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
528 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
529 (server->ops->close)(fd);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
530 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
531
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
532 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
533 // Actual TFTP server
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
534 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
535
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
536 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
537 tftpd_server(cyg_addrword_t p)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
538 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
539 struct tftp_server *server = (struct tftp_server *)p;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
540 int max_s = 0;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
541 int data_len, recv_len, from_len;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
542 struct sockaddr from_addr;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
543 char data[SEGSIZE+sizeof(struct tftphdr)];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
544 struct tftphdr *hdr = (struct tftphdr *)data;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
545 struct addrinfo hints;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
546 struct addrinfo *ai;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
547 fd_set readfds;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
548 char name[64];
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
549 int error;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
550 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
551 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
552 struct info o = tftp_server_instrument;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
553 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
554
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
555 #ifndef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
556 // Otherwise routine printfs fail the test - interrupts disabled too long.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
557 diag_printf("TFTPD [%x]: port %d\n", p, server->port);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
558 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
559
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
560 memset(&hints,0,sizeof(hints));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
561 hints.ai_family = PF_UNSPEC;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
562 hints.ai_flags = AI_PASSIVE;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
563
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
564 error = getaddrinfo(NULL,"tftp",&hints, &server->res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
565 if (0 != error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
566 diag_printf("TFTPD [%p] : can't get a local server address to bind to: %s\n",
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
567 p, gai_strerror(error));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
568 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
569 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
570
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
571 // If the port is 0, we need to use the default TFTP port. Extrace
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
572 // the port number from one of the addresses returned by
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
573 // getaddrinfo.
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
574 if (server->port == 0) {
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
575 switch (server->res->ai_family) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
576 case AF_INET:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
577 {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
578 struct sockaddr_in *addr = (struct sockaddr_in *)server->res->ai_addr;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
579 server->port = ntohs(addr->sin_port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
580 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
581 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
582 #ifdef CYGPKG_NET_INET6
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
583 case AF_INET6:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
584 {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
585 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)server->res->ai_addr;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
586 server->port = ntohs(addr->sin6_port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
587 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
588 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
589 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
590 default:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
591 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
592 }
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
593 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
594
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
595 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
596 sem_alloc(server->port);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
597 while (true) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
598 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
599 // Iterate over the addresses and create a local port to listen for requests
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
600 ai = server->res;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
601 memset(server->s,0,sizeof(server->s));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
602 server->num_s = 0;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
603 while (ai && (server->num_s < CYGNUM_NET_MAX_INET_PROTOS)) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
604 server->s[server->num_s] = socket(ai->ai_family,
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
605 ai->ai_socktype,
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
606 ai->ai_protocol);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
607 if (server->s[server->num_s] < 0 ) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
608 diag_printf("TFTPD [%x]: can't open socket\n", p);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
609 freeaddrinfo(server->res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
610 server->res = NULL;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
611 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
612 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
613
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
614 set_port(ai->ai_addr, server->port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
615
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
616 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
617 sem_wait(server->port);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
618 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
619 if (bind(server->s[server->num_s],ai->ai_addr, ai->ai_addrlen) < 0) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
620 // Problem setting up my end
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
621 diag_printf("TFTPD [%x]: can't bind to server port\n",p);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
622 close(server->s[server->num_s]);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
623 server->s[server->num_s] = 0;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
624 ai = ai->ai_next;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
625 continue;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
626 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
627 // We need to know the highest socket number for select.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
628 if (server->s[server->num_s] > max_s)
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
629 max_s = server->s[server->num_s];
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
630 server->num_s++;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
631 ai = ai->ai_next;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
632 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
633
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
634 #ifndef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
635 while (true) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
636 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
637 FD_ZERO(&readfds);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
638 for (i=0; i < CYGNUM_NET_MAX_INET_PROTOS; i++) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
639 if (server->s[i]) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
640 FD_SET(server->s[i],&readfds);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
641 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
642 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
643 error = select(max_s+1,&readfds,NULL,NULL,NULL);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
644 if ( -1 == error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
645 diag_printf("TFTPD [%x]: error in select\n",p);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
646 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
647 for (i=0; i < CYGNUM_NET_MAX_INET_PROTOS; i++) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
648 if (server->s[i] && FD_ISSET(server->s[i],&readfds)) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
649 recv_len = sizeof(data);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
650 from_len = sizeof(from_addr);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
651 data_len = recvfrom(server->s[i], hdr, recv_len, 0,
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
652 &from_addr, &from_len);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
653 if ( data_len < 0) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
654 diag_printf("TFTPD [%x]: can't read request\n", p);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
655 } else {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
656 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
657 // Close the socket and post on the semaphore some
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
658 // another thread can start listening for requests. This
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
659 // is not quite right. select could of returned with more than
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
660 // one socket with data to read. Here we only deal with one of them
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
661 for (i=0; i < CYGNUM_NET_MAX_INET_PROTOS; i++) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
662 if (server->s[i]) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
663 close (server->s[i]);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
664 server->s[i] = 0;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
665 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
666 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
667 sem_post(server->port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
668 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
669 #ifndef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
670 getnameinfo(&from_addr,sizeof(from_addr), name, sizeof(name),0,0,0);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
671 diag_printf("TFTPD [%x]: received %x from %s\n", p,
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
672 ntohs(hdr->th_opcode), name);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
673 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
674 switch (ntohs(hdr->th_opcode)) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
675 case WRQ:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
676 tftpd_write_file(server, hdr, &from_addr, from_len);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
677 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
678 case RRQ:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
679 tftpd_read_file(server, hdr, &from_addr, from_len);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
680 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
681 case ACK:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
682 case DATA:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
683 case ERROR:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
684 // Ignore
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
685 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
686 default:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
687 getnameinfo(&from_addr,sizeof(from_addr), name, sizeof(name),0,0,0);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
688 diag_printf("TFTPD [%x]: bogus request %x from %s\n", p,
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
689 ntohs(hdr->th_opcode),
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
690 name);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
691 tftpd_send_error(server->s[i],hdr,TFTP_EBADOP,&from_addr,from_len);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
692 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
693
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
694 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
695 tftp_server_instrument.total_transactions++;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
696
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
697 o.data.rx -= tftp_server_instrument.data.rx ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
698 o.data.rx_repeat -= tftp_server_instrument.data.rx_repeat;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
699 o.data.rx_skip -= tftp_server_instrument.data.rx_skip ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
700 o.data.send -= tftp_server_instrument.data.send ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
701 o.data.resend -= tftp_server_instrument.data.resend ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
702
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
703 o.ack.rx -= tftp_server_instrument.ack.rx ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
704 o.ack.rx_repeat -= tftp_server_instrument.ack.rx_repeat ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
705 o.ack.rx_skip -= tftp_server_instrument.ack.rx_skip ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
706 o.ack.send -= tftp_server_instrument.ack.send ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
707 o.ack.resend -= tftp_server_instrument.ack.resend ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
708
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
709 o.err_send -= tftp_server_instrument.err_send ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
710
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
711 #ifndef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
712 if ( o.data.rx ) diag_printf( "data rx %4d\n", -o.data.rx );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
713 if ( o.data.rx_repeat ) diag_printf( "data rx_repeat%4d\n", -o.data.rx_repeat );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
714 if ( o.data.rx_skip ) diag_printf( "data rx_skip %4d\n", -o.data.rx_skip );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
715 if ( o.data.send ) diag_printf( "data send %4d\n", -o.data.send );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
716 if ( o.data.resend ) diag_printf( "data resend %4d\n", -o.data.resend );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
717
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
718 if ( o.ack.rx ) diag_printf( " ack rx %4d\n", -o.ack.rx );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
719 if ( o.ack.rx_repeat ) diag_printf( " ack rx_repeat%4d\n", -o.ack.rx_repeat );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
720 if ( o.ack.rx_skip ) diag_printf( " ack rx_skip %4d\n", -o.ack.rx_skip );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
721 if ( o.ack.send ) diag_printf( " ack send %4d\n", -o.ack.send );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
722 if ( o.ack.resend ) diag_printf( " ack resend %4d\n", -o.ack.resend );
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
723
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
724 if ( o.err_send ) diag_printf( "*error sends %4d\n", -o.err_send );
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
725 #endif // CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
726 #endif // CYGOPT_NET_TFTP_SERVER_INSTRUMENT
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
727 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
728 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
729 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
730 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
731 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
732 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
733 // The following looks a little strange, but it keeps emacs's
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
734 // auto indention happy.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
735 #ifndef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
736 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
737 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
738 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
739 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
740 #endif
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
741 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
742
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
743
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
744 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
745 // This function is used to create a new server [thread] which supports
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
746 // the TFTP protocol on the given port. A server 'id' will be returned
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
747 // which can later be used to destroy the server.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
748 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
749 // Note: all [memory] resources for the server thread will be allocated
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
750 // dynamically. If there are insufficient resources, an error will be
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
751 // returned.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
752 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
753 int
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
754 tftpd_start(int port, struct tftpd_fileops *ops)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
755 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
756 struct tftp_server *server;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
757 #ifdef CYGSEM_TFTP_SERVER_MULTITHREADED
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
758 static char init = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
759 if ( 0 == init ) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
760 init++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
761 cyg_semaphore_init( &tftp_server_sem, 0 );
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
762 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
763 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
764
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
765 if ((server = malloc(sizeof(struct tftp_server)))) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
766 server->tag = TFTP_tag;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
767 server->port = port;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
768 server->ops = ops;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
769 cyg_thread_create(CYGPKG_NET_TFTPD_THREAD_PRIORITY, // Priority
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
770 tftpd_server, // entry
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
771 (cyg_addrword_t)server, // entry parameter
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
772 "TFTP server", // Name
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
773 &server->stack[0], // Stack
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
774 STACK_SIZE, // Size
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
775 &server->thread_handle, // Handle
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
776 &server->thread_data // Thread data structure
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
777 );
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
778 cyg_thread_resume(server->thread_handle); // Start it
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
779
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
780 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
781 return (int)server;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
782 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
783
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
784 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
785 // Destroy a TFTP server, using a previously created server 'id'.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
786 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
787 int
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
788 tftpd_stop(int p)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
789 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
790 struct tftp_server *server = (struct tftp_server *)p;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
791 // Simple sanity check
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
792 if (server->tag == TFTP_tag) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
793 cyg_thread_kill(server->thread_handle);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
794 cyg_thread_set_priority(server->thread_handle, 0);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
795 cyg_thread_delay(1); // Make sure it gets to die...
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
796 if (cyg_thread_delete(server->thread_handle)) {
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
797 // Success shutting down the thread. Close all its sockets.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
798 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
799 for (i = 0 ; i < CYGNUM_NET_MAX_INET_PROTOS; i++) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
800 if (server->s[i]) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
801 close (server->s[i]);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
802 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
803 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
804 freeaddrinfo(server->res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
805 free(server); // Give up memory
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
806 return 1;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
807 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
808 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
809 return 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
810 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
811
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
812 // EOF tftp_server.c