annotate packages/net/common/current/src/tftp_server.c @ 1777:c16341b1bac6 default tip

* Added execute permissions to files missed in conversion from CVS
author alexs
date Mon, 12 Oct 2009 02:26:09 +0100
parents 42c0adb7b2fc
children
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
1621
26840b464238 * src/tftp_server.c: files are now created with the
jlarmour
parents: 1018
diff changeset
62 #include <fcntl.h>
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
63
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
64 #define nCYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
65 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
66
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
67 struct subinfo {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
68 int rx;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
69 int rx_repeat;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
70 int rx_skip;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
71 int send;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
72 int resend;
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
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
75 struct info {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
76 struct subinfo ack, data;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
77 int err_send;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
78 int total_transactions;
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
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
82 static struct info tftp_server_instrument = {
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,0,0,0 },
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
85 0, 0,
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
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
88 #endif // CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
89
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
90 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
91 struct tftpd_sem {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
92 int port;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
93 cyg_sem_t sem;
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
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
96 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
97 #endif //CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
98
1696
42c0adb7b2fc * src/tftp_server.c:
asl
parents: 1621
diff changeset
99 #define STACK_SIZE (((CYGPKG_NET_TFTPD_THREAD_STACK_SIZE) + CYGARC_ALIGNMENT-1) & ~(CYGARC_ALIGNMENT-1))
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
100 static char *TFTP_tag = "TFTPD";
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
101 #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
102 struct tftp_server {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
103 char *tag;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
104 char stack[STACK_SIZE];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
105 cyg_thread thread_data;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
106 cyg_handle_t thread_handle;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
107 int port;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
108 struct tftpd_fileops *ops;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
109 int s[CYGNUM_NET_MAX_INET_PROTOS], num_s;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
110 struct addrinfo *res;
208
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
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
113 static char * errmsg[] = {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
114 "Undefined error code", // 0 nothing defined
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
115 "File not found", // 1 TFTP_ENOTFOUND
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
116 "Access violation", // 2 TFTP_EACCESS
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
117 "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
118 "Illegal TFTP operation", // 4 TFTP_EBADOP
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
119 "Unknown transfer ID", // 5 TFTP_EBADID
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
120 "File already exists", // 6 TFTP_EEXISTS
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
121 "No such user", // 7 TFTP_ENOUSER
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
122 };
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
123
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
124 // 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
125 static void set_port(struct sockaddr * address, int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
126
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
127 switch (address->sa_family) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
128 case AF_INET:{
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
129 struct sockaddr_in *addr = (struct sockaddr_in *)address;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
130 addr->sin_port = ntohs(port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
131 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
132 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
133 #ifdef CYGPKG_NET_INET6
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
134 case AF_INET6:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
135 {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
136 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)address;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
137 addr->sin6_port = ntohs(port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
138 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
139 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
140 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
141 default:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
142 break;
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
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
146 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
147
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
148 // 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
149 // allocated.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
150 static void sem_alloc(int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
151 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
152
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
153 CYG_ASSERT(port != 0, "Invalid port number");
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
154
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
155 cyg_scheduler_lock(); // Avoid race with other tftpd's
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
156 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
157 if (tftpd_sems[i].port == port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
158 cyg_scheduler_unlock();
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
159 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
160 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
161 if (tftpd_sems[i].port == 0) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
162 tftpd_sems[i].port = port;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
163 cyg_semaphore_init(&tftpd_sems[i].sem,1);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
164 cyg_scheduler_unlock();
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
165 return ;
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 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
168 cyg_scheduler_unlock();
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
169 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
170 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
171
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
172 // Wait on the semaphore for a given port number.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
173 static void sem_wait(int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
174 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
175 CYG_ASSERT(port != 0, "Invalid port number");
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
176
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
177 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
178 if (tftpd_sems[i].port == port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
179 cyg_semaphore_wait(&tftpd_sems[i].sem);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
180 return;
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 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
183 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
184 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
185
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
186 // Release the semaphore for a given port number.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
187 static void sem_post(int port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
188 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
189 CYG_ASSERT(port != 0, "Invalid port number");
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
190
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
191 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
192 if (tftpd_sems[i].port == port) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
193 cyg_semaphore_post(&tftpd_sems[i].sem);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
194 return;
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 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
197 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
198 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
199 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
200
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
201 /* 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
202 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
203 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
204 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
205 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
206 CYG_ASSERT( 0 <= err, "err underflow" );
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
207 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
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
209 reply->th_opcode = htons(ERROR);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
210 reply->th_code = htons(err);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
211 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
212 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
213 strcpy(reply->th_msg, errmsg[err]);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
214 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
215 from_addr, from_len);
208
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 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
219 // Receive a file from the client
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
220 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
221 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
222 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
223 struct tftphdr *hdr,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
224 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
225 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
226 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
227 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
228 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
229 struct tftphdr *response = (struct tftphdr *)data_in;
270
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
230 int fd, len, ok, tries, closed, data_len, s;
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
231 unsigned short block;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
232 struct timeval timeout;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
233 fd_set fds;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
234 int total_timeouts = 0;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
235 struct sockaddr client_addr;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
236 struct addrinfo hints;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
237 struct addrinfo *res;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
238 int client_len;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
239 int error;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
240
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
241 memset(&hints,0,sizeof(hints));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
242 hints.ai_family = from_addr->sa_family;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
243 hints.ai_flags = AI_PASSIVE;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
244
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
245 error = getaddrinfo(NULL,"tftp",&hints, &res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
246 if (0 != error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
247 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
248 gai_strerror(error));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
249 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
250 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
251 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
252 if (s < 0) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
253 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
254 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
255 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
256 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
257
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
258 // 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
259 set_port(res->ai_addr,0);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
260
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
261 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
262 // Problem setting up my end
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
263 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
264 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
265 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
266 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
267 }
1621
26840b464238 * src/tftp_server.c: files are now created with the
jlarmour
parents: 1018
diff changeset
268 if ((fd = (server->ops->open)(hdr->th_stuff, O_WRONLY|O_TRUNC|O_CREAT)) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
269 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
270 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
271 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
272 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
273 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
274 ok = true;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
275 closed = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
276 block = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
277 while (ok) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
278 // 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
279 reply->th_opcode = htons(ACK);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
280 reply->th_block = htons(block++); // postincrement
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
281 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
282 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
283 tftp_server_instrument.ack.send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
284 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
285 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
286 repeat_select:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
287 timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
288 timeout.tv_usec = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
289 FD_ZERO(&fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
290 FD_SET(s, &fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
291 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
292 if (++total_timeouts > TFTP_TIMEOUT_MAX) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
293 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
294 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
295 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
296 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
297 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
298 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
299 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
300 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
301 tftp_server_instrument.ack.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
302 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
303 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
304 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
305 // Some data has arrived
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
306 data_len = sizeof(data_in);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
307 client_len = sizeof(client_addr);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
308 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
309 &client_addr, &client_len)) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
310 // What happened? No data here!
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
311 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
312 tftp_server_instrument.ack.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
313 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
314 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
315 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
316 if (ntohs(response->th_opcode) == DATA &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
317 ntohs(response->th_block) < block) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
318 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
319 tftp_server_instrument.data.rx_repeat++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
320 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
321 // 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
322 // 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
323 // 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
324 // subsequently we time out)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
325 goto repeat_select;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
326 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
327 if (ntohs(response->th_opcode) == DATA &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
328 ntohs(response->th_block) == block) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
329 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
330 tftp_server_instrument.data.rx++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
331 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
332 // Good data - write to file
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
333 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
334 if (len < (data_len-4)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
335 // File is "full"
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
336 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
337 from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
338 ok = false; // Give up
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
339 break; // out of the retries loop
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
340 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
341 if (data_len < (SEGSIZE+4)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
342 // End of file
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
343 closed = true;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
344 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
345 if ((server->ops->close)(fd) == -1) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
346 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
347 from_addr, from_len);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
348 break; // out of the retries loop
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
349 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
350 // 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
351 // packet, the one that implied EOF:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
352 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
353 tftp_server_instrument.ack.send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
354 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
355 reply->th_opcode = htons(ACK);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
356 reply->th_block = htons(block++); // postincrement
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
357 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
358 break; // out of the retries loop
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
359 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
360 // 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
361 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
362 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
363 // 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
364 // 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
365 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
366 if ( (ntohs(response->th_opcode) == DATA) )
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
367 tftp_server_instrument.data.rx_skip++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
368 tftp_server_instrument.ack.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
369 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
370 } // End of the retries loop.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
371 if (TFTP_RETRIES_MAX <= tries) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
372 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
373 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
374 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
375 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
376 ok = false;
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 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
379 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
380 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
381 if (!closed) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
382 (server->ops->close)(fd);
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 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
387 // Send a file to the client
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
388 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
389 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
390 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
391 struct tftphdr *hdr,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
392 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
393 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
394 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
395 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
396 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
397 struct tftphdr *response = (struct tftphdr *)data_in;
270
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
398 int fd, len, tries, ok, data_len, s;
42332443fea2 Fix TFTP for large (16MB+) files.
gthomas
parents: 208
diff changeset
399 unsigned short block;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
400 struct timeval timeout;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
401 fd_set fds;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
402 int total_timeouts = 0;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
403 struct sockaddr client_addr;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
404 struct addrinfo hints;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
405 struct addrinfo *res;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
406 int client_len;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
407 int error;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
408
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
409 memset(&hints,0,sizeof(hints));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
410 hints.ai_family = from_addr->sa_family;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
411 hints.ai_flags = AI_PASSIVE;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
412
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
413 error = getaddrinfo(NULL,"tftp",&hints, &res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
414 if (0 != error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
415 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
416 gai_strerror(error));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
417 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
418 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
419 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
420 if (s < 0) {
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
421 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
422 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
423 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
424 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
425
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
426 // 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
427 set_port(res->ai_addr,0);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
428
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
429 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
430 // Problem setting up my end
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
431 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
432 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
433 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
434 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
435 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
436
1018
3737492e03d1 * src/tftp_server.c (tftpd_read_file): Open the file for reading,
asl
parents: 1007
diff changeset
437 if ((fd = (server->ops->open)(hdr->th_stuff, O_RDONLY)) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
438 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
439 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
440 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
441 return;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
442 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
443 block = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
444 ok = true;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
445 while (ok) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
446 // Read next chunk of file
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
447 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
448 reply->th_block = htons(++block); // preincrement
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
449 reply->th_opcode = htons(DATA);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
450 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
451 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
452 tftp_server_instrument.data.send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
453 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
454 if (sendto(s, reply, 4+len, 0,
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
455 from_addr, from_len) < 0) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
456 // Something went wrong with the network!
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
457 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
458 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
459 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
460 repeat_select:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
461 timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
462 timeout.tv_usec = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
463 FD_ZERO(&fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
464 FD_SET(s, &fds);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
465 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
466 if (++total_timeouts > TFTP_TIMEOUT_MAX) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
467 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
468 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
469 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
470 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
471 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
472 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
473 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
474 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
475 tftp_server_instrument.data.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
476 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
477 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
478 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
479 data_len = sizeof(data_in);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
480 client_len = sizeof(client_addr);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
481 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
482 &client_addr,
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
483 &client_len)) < 0) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
484 // 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
485 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
486 tftp_server_instrument.data.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
487 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
488 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
489 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
490 if ((ntohs(response->th_opcode) == ACK) &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
491 (ntohs(response->th_block) < block)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
492 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
493 tftp_server_instrument.ack.rx_repeat++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
494 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
495 // 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
496 // 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
497 // 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
498 // subsequently we time out)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
499 goto repeat_select;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
500 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
501 if ((ntohs(response->th_opcode) == ACK) &&
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
502 (ntohs(response->th_block) == block)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
503 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
504 tftp_server_instrument.ack.rx++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
505 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
506 // 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
507 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
508 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
509 // 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
510 // 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
511 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
512 if ( (ntohs(response->th_opcode) == ACK) )
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
513 tftp_server_instrument.ack.rx_skip++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
514 tftp_server_instrument.data.resend++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
515 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
516 } // End of the retries loop.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
517 if (TFTP_RETRIES_MAX <= tries) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
518 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
519 tftp_server_instrument.err_send++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
520 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
521 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
522 ok = false;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
523 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
524 if (len < SEGSIZE) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
525 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
526 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
527 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
528 close(s);
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
529 freeaddrinfo(res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
530 (server->ops->close)(fd);
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 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
534 // Actual TFTP server
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
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
537 static void
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
538 tftpd_server(cyg_addrword_t p)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
539 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
540 struct tftp_server *server = (struct tftp_server *)p;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
541 int max_s = 0;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
542 int data_len, recv_len, from_len;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
543 struct sockaddr from_addr;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
544 char data[SEGSIZE+sizeof(struct tftphdr)];
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
545 struct tftphdr *hdr = (struct tftphdr *)data;
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
546 struct addrinfo hints;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
547 struct addrinfo *ai;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
548 fd_set readfds;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
549 char name[64];
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
550 int error;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
551 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
552 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
553 struct info o = tftp_server_instrument;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
554 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
555
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
556 #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
557 // 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
558 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
559 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
560
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
561 memset(&hints,0,sizeof(hints));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
562 hints.ai_family = PF_UNSPEC;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
563 hints.ai_flags = AI_PASSIVE;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
564
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
565 error = getaddrinfo(NULL,"tftp",&hints, &server->res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
566 if (0 != error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
567 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
568 p, gai_strerror(error));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
569 return;
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
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
572 // 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
573 // 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
574 // getaddrinfo.
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
575 if (server->port == 0) {
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
576 switch (server->res->ai_family) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
577 case AF_INET:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
578 {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
579 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
580 server->port = ntohs(addr->sin_port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
581 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
582 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
583 #ifdef CYGPKG_NET_INET6
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
584 case AF_INET6:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
585 {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
586 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
587 server->port = ntohs(addr->sin6_port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
588 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
589 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
590 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
591 default:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
592 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
593 }
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
594 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
595
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
596 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
597 sem_alloc(server->port);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
598 while (true) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
599 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
600 // 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
601 ai = server->res;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
602 memset(server->s,0,sizeof(server->s));
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
603 server->num_s = 0;
1007
16d247bb9c70 * src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents: 957
diff changeset
604 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
16d247bb9c70 * src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents: 957
diff changeset
605 sem_wait(server->port);
16d247bb9c70 * src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents: 957
diff changeset
606 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
607 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
608 server->s[server->num_s] = socket(ai->ai_family,
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
609 ai->ai_socktype,
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
610 ai->ai_protocol);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
611 if (server->s[server->num_s] < 0 ) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
612 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
613 freeaddrinfo(server->res);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
614 server->res = NULL;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
615 return;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
616 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
617
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
618 set_port(ai->ai_addr, server->port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
619
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
620 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
621 // Problem setting up my end
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
622 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
623 close(server->s[server->num_s]);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
624 server->s[server->num_s] = 0;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
625 ai = ai->ai_next;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
626 continue;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
627 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
628 // 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
629 if (server->s[server->num_s] > max_s)
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
630 max_s = server->s[server->num_s];
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
631 server->num_s++;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
632 ai = ai->ai_next;
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
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
635 #ifndef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
636 while (true) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
637 #endif
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
638 FD_ZERO(&readfds);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
639 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
640 if (server->s[i]) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
641 FD_SET(server->s[i],&readfds);
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 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
644 error = select(max_s+1,&readfds,NULL,NULL,NULL);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
645 if ( -1 == error) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
646 diag_printf("TFTPD [%x]: error in select\n",p);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
647 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
648 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
649 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
650 recv_len = sizeof(data);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
651 from_len = sizeof(from_addr);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
652 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
653 &from_addr, &from_len);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
654 if ( data_len < 0) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
655 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
656 } else {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
657 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
658 // Close the socket and post on the semaphore some
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
659 // another thread can start listening for requests. This
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
660 // 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
661 // 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
662 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
663 if (server->s[i]) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
664 close (server->s[i]);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
665 server->s[i] = 0;
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 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
668 sem_post(server->port);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
669 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
670 #ifndef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
671 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
672 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
673 ntohs(hdr->th_opcode), name);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
674 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
675 switch (ntohs(hdr->th_opcode)) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
676 case WRQ:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
677 tftpd_write_file(server, hdr, &from_addr, from_len);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
678 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
679 case RRQ:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
680 tftpd_read_file(server, hdr, &from_addr, from_len);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
681 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
682 case ACK:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
683 case DATA:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
684 case ERROR:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
685 // Ignore
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
686 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
687 default:
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
688 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
689 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
690 ntohs(hdr->th_opcode),
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
691 name);
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
692 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
693 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
694
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
695 #ifdef CYGOPT_NET_TFTP_SERVER_INSTRUMENT
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
696 tftp_server_instrument.total_transactions++;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
697
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
698 o.data.rx -= tftp_server_instrument.data.rx ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
699 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
700 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
701 o.data.send -= tftp_server_instrument.data.send ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
702 o.data.resend -= tftp_server_instrument.data.resend ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
703
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
704 o.ack.rx -= tftp_server_instrument.ack.rx ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
705 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
706 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
707 o.ack.send -= tftp_server_instrument.ack.send ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
708 o.ack.resend -= tftp_server_instrument.ack.resend ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
709
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
710 o.err_send -= tftp_server_instrument.err_send ;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
711
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
712 #ifndef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
713 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
714 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
715 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
716 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
717 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
718
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
719 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
720 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
721 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
722 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
723 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
724
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
725 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
726 #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
727 #endif // CYGOPT_NET_TFTP_SERVER_INSTRUMENT
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
728 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
729 break;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
730 #endif
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 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
734 // 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
735 // auto indention happy.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
736 #ifndef CYGSEM_NET_TFTPD_MULTITHREADED
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
737 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
738 #endif
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
739 #ifdef CYGSEM_NET_TFTPD_MULTITHREADED
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
740 }
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
741 #endif
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
742 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
743
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
744
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
745 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
746 // 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
747 // 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
748 // 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
749 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
750 // 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
751 // 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
752 // returned.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
753 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
754 int
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
755 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
756 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
757 struct tftp_server *server;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
758 #ifdef CYGSEM_TFTP_SERVER_MULTITHREADED
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
759 static char init = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
760 if ( 0 == init ) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
761 init++;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
762 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
763 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
764 #endif
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
765
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
766 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
767 server->tag = TFTP_tag;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
768 server->port = port;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
769 server->ops = ops;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
770 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
771 tftpd_server, // entry
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
772 (cyg_addrword_t)server, // entry parameter
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
773 "TFTP server", // Name
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
774 &server->stack[0], // Stack
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
775 STACK_SIZE, // Size
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
776 &server->thread_handle, // Handle
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
777 &server->thread_data // Thread data structure
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
778 );
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
779 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
780
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
781 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
782 return (int)server;
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 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
786 // 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
787 //
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
788 int
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
789 tftpd_stop(int p)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
790 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
791 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
792 // Simple sanity check
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
793 if (server->tag == TFTP_tag) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
794 cyg_thread_kill(server->thread_handle);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
795 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
796 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
797 if (cyg_thread_delete(server->thread_handle)) {
957
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
798 // Success shutting down the thread. Close all its sockets.
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
799 int i;
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
800 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
801 if (server->s[i]) {
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
802 close (server->s[i]);
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 }
db3e0a2fda2f 2003-04-12 Andrew Lunn <andrew.lunn@ascom.ch>
asl
parents: 490
diff changeset
805 freeaddrinfo(server->res);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
806 free(server); // Give up memory
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
807 return 1;
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 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
810 return 0;
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
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
813 // EOF tftp_server.c