annotate packages/net/tcpip/current/src/lib/tftp_server.c @ 115:6ed91473a1cd ecos-sw-2000-08-21

Merge from eCos master repository on 2000-08-21-22:40:54-BST
author jlarmour
date Fri, 25 Aug 2000 17:32:38 +0000
parents 02ea4320376c
children 0c2b7be0d798
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
1 //==========================================================================
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
2 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
3 // lib/tftp_server.c
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
4 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
5 // TFTP server support
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
6 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
7 //==========================================================================
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
8 //####COPYRIGHTBEGIN####
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
9 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
10 // -------------------------------------------
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
11 // The contents of this file are subject to the Red Hat eCos Public License
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
12 // Version 1.1 (the "License"); you may not use this file except in
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
13 // compliance with the License. You may obtain a copy of the License at
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
14 // http://www.redhat.com/
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
15 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
16 // Software distributed under the License is distributed on an "AS IS"
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
18 // License for the specific language governing rights and limitations under
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
19 // the License.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
20 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
21 // The Original Code is eCos - Embedded Configurable Operating System,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
22 // released September 30, 1998.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
23 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
24 // The Initial Developer of the Original Code is Red Hat.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
25 // Portions created by Red Hat are
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
27 // All Rights Reserved.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
28 // -------------------------------------------
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
29 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
30 //####COPYRIGHTEND####
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
31 //####BSDCOPYRIGHTBEGIN####
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
32 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
33 // -------------------------------------------
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
34 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
35 // Portions of this software may have been derived from OpenBSD or other sources,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
36 // and are covered by the appropriate copyright disclaimers included herein.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
37 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
38 // -------------------------------------------
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
39 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
40 //####BSDCOPYRIGHTEND####
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
41 //==========================================================================
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
42 //#####DESCRIPTIONBEGIN####
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
43 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
44 // Author(s): gthomas
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
45 // Contributors: gthomas, hmt, andrew.lunn@ascom.ch (Andrew Lunn)
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
46 // Date: 2000-04-06
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
47 // Purpose:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
48 // Description:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
49 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
50 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
51 //####DESCRIPTIONEND####
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
52 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
53 //==========================================================================
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
54
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
55 // TFTP server support
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
56
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
57 #include <network.h> // Basic networking support
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
58 #include <arpa/tftp.h> // TFTP protocol definitions
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
59 #include <tftp_support.h> // TFTPD structures
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
60 #include <cyg/kernel/kapi.h>
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
61 #include <stdlib.h> // For malloc
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
62
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
63 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+(3*(SEGSIZE+sizeof(struct tftphdr))))
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
64 static char *TFTP_tag = "TFTPD";
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
65 struct tftp_server {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
66 char *tag;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
67 char stack[STACK_SIZE];
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
68 cyg_thread thread_data;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
69 cyg_handle_t thread_handle;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
70 int port;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
71 struct tftpd_fileops *ops;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
72 };
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
73
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
74 static char * errmsg[] = {
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
75 "Undefined error code",
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
76 "File not found",
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
77 "Access violation",
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
78 "Disk full or allocation exceeded",
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
79 "Illegal TFTP operation",
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
80 "Unknown transfer ID",
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
81 "File already exists",
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
82 "No such user"
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
83 };
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
84
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
85
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
86 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
87 // Receive a file from the client
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
88 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
89 static void
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
90 tftpd_write_file(struct tftp_server *server,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
91 struct tftphdr *hdr,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
92 struct sockaddr_in *from_addr, int from_len)
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
93 {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
94 char data_out[SEGSIZE+sizeof(struct tftphdr)];
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
95 char data_in[SEGSIZE+sizeof(struct tftphdr)];
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
96 struct tftphdr *reply = (struct tftphdr *)data_out;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
97 struct tftphdr *response = (struct tftphdr *)data_in;
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
98 int fd, block, len, ok, closed, data_len, s;
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
99 struct timeval timeout;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
100 fd_set fds;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
101 int total_timeouts = 0;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
102 struct sockaddr_in client_addr, local_addr;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
103 int client_len;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
104
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
105 s = socket(AF_INET, SOCK_DGRAM, 0);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
106 if (s < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
107 diag_printf("TFTPD: can't open socket for 'write_file'\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
108 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
109 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
110 memset((char *)&local_addr, 0, sizeof(local_addr));
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
111 local_addr.sin_family = AF_INET;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
112 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
113 local_addr.sin_port = htons(INADDR_ANY);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
114 if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
115 // Problem setting up my end
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
116 diag_printf("TFTPD: can't bind to reply port for 'write_file'\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
117 close(s);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
118 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
119 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
120 if ((fd = (server->ops->open)(hdr->th_stuff, O_WRONLY)) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
121 reply->th_opcode = htons(ERROR);
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
122 reply->th_code = htons(TFTP_ENOTFOUND);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
123 strcpy(reply->th_msg, errmsg[TFTP_ENOTFOUND]);
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
124 sendto(s, reply, 4+strlen(reply->th_msg)+1, 0,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
125 (struct sockaddr *)from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
126 close(s);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
127 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
128 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
129 // Send ACK telling client he can send data
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
130 reply->th_opcode = htons(ACK);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
131 reply->th_block = 0;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
132 sendto(s, reply, 4, 0, (struct sockaddr *)from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
133 block = 1;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
134 ok = true;
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
135 closed = false;
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
136 while (ok) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
137 timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
138 timeout.tv_usec = 0;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
139 FD_ZERO(&fds);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
140 FD_SET(s, &fds);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
141 if (select(s+1, &fds, 0, 0, &timeout) <= 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
142 if (++total_timeouts > TFTP_TIMEOUT_MAX) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
143 ok = false;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
144 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
145 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
146 // Try resending last ACK
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
147 sendto(s, reply, 4, 0, (struct sockaddr *)from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
148 } else {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
149 // Some data has arrived
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
150 data_len = sizeof(data_in);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
151 client_len = sizeof(client_addr);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
152 if ((data_len = recvfrom(s, data_in, data_len, 0,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
153 (struct sockaddr *)&client_addr, &client_len)) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
154 // What happened?
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
155 diag_printf("Can't read client data!\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
156 ok = false;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
157 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
158 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
159 if (ntohs(response->th_opcode) == DATA) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
160 if (ntohs(response->th_block) == block) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
161 // Good data - write to file
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
162 len = (server->ops->write)(fd, response->th_data, data_len-4);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
163 if (len < (data_len-4)) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
164 // File is "full"
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
165 reply->th_opcode = htons(ERROR);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
166 reply->th_code = htons(TFTP_ENOSPACE);
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
167 strcpy(reply->th_msg, errmsg[TFTP_ENOSPACE]);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
168 sendto(s, reply, 4+strlen(reply->th_msg)+1, 0,
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
169 (struct sockaddr *)from_addr, from_len);
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
170 ok = false; // Give up
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
171 } else {
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
172 if (data_len < (SEGSIZE+4)) {
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
173 // End of file
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
174 closed = true;
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
175 ok = false;
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
176 if ((server->ops->close)(fd) == -1) {
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
177 reply->th_opcode = htons(ERROR);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
178 reply->th_code = htons(TFTP_EACCESS);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
179 strcpy(reply->th_msg, errmsg[TFTP_EACCESS]);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
180 sendto(s, reply, 4+strlen(reply->th_msg)+1, 0,
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
181 (struct sockaddr *)from_addr, from_len);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
182 } else {
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
183 reply->th_opcode = htons(ACK);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
184 reply->th_block = htons(block++);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
185 sendto(s, reply, 4, 0,
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
186 (struct sockaddr *)from_addr, from_len);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
187 }
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
188 } else {
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
189 reply->th_opcode = htons(ACK);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
190 reply->th_block = htons(block++);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
191 sendto(s, reply, 4, 0,
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
192 (struct sockaddr *)from_addr, from_len);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
193 }
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
194 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
195 } else {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
196 // Something is wrong - tell client last good block
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
197 sendto(s, reply, 4, 0, (struct sockaddr *)from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
198 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
199 } else {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
200 // Client has sent something bogus - bag out!
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
201 reply->th_opcode = htons(ERROR);
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
202 reply->th_code = htons(TFTP_EBADOP);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
203 strcpy(reply->th_msg, errmsg[TFTP_EBADOP]);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
204 sendto(s, reply, 4+strlen(reply->th_msg)+1, 0,
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
205 (struct sockaddr *)from_addr, from_len);
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
206 ok = false;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
207 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
208 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
209 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
210 close(s);
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
211 if (!closed) {
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
212 (server->ops->close)(fd);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
213 }
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
214 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
215
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
216 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
217 // Send a file to the client
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
218 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
219 static void
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
220 tftpd_read_file(struct tftp_server *server,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
221 struct tftphdr *hdr,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
222 struct sockaddr_in *from_addr, int from_len)
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
223 {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
224 char data_out[SEGSIZE+sizeof(struct tftphdr)];
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
225 char data_in[SEGSIZE+sizeof(struct tftphdr)];
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
226 struct tftphdr *reply = (struct tftphdr *)data_out;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
227 struct tftphdr *response = (struct tftphdr *)data_in;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
228 int fd, block, len, tries, ok, data_len, s;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
229 struct timeval timeout;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
230 fd_set fds;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
231 int total_timeouts = 0;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
232 struct sockaddr_in client_addr, local_addr;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
233 int client_len;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
234
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
235 s = socket(AF_INET, SOCK_DGRAM, 0);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
236 if (s < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
237 diag_printf("TFTPD: can't open socket for 'read_file'\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
238 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
239 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
240 memset((char *)&local_addr, 0, sizeof(local_addr));
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
241 local_addr.sin_family = AF_INET;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
242 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
243 local_addr.sin_port = htons(INADDR_ANY);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
244 if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
245 // Problem setting up my end
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
246 diag_printf("TFTPD: can't bind to reply port for 'read_file'\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
247 close(s);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
248 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
249 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
250 if ((fd = (server->ops->open)(hdr->th_stuff, O_RDONLY)) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
251 reply->th_opcode = htons(ERROR);
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
252 reply->th_code = htons(TFTP_ENOTFOUND);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
253 strcpy(reply->th_msg, errmsg[TFTP_ENOTFOUND]);
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
254 sendto(s, reply, 4+strlen(reply->th_msg)+1, 0,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
255 (struct sockaddr *)from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
256 close(s);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
257 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
258 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
259 block = 0;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
260 ok = true;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
261 while (ok) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
262 // Read next chunk of file
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
263 len = (server->ops->read)(fd, reply->th_data, SEGSIZE);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
264 reply->th_block = htons(++block);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
265 reply->th_opcode = htons(DATA);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
266 for (tries = 0; tries < TFTP_RETRIES_MAX; tries++) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
267 if (sendto(s, reply, 4+len, 0, (struct sockaddr *)from_addr, from_len) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
268 // Something went wrong with the network!
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
269 ok = false;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
270 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
271 }
112
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
272 repeat_select:
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
273 timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
274 timeout.tv_usec = 0;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
275 FD_ZERO(&fds);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
276 FD_SET(s, &fds);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
277 if (select(s+1, &fds, 0, 0, &timeout) <= 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
278 if (++total_timeouts > TFTP_TIMEOUT_MAX) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
279 ok = false;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
280 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
281 }
112
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
282 continue; // retry the send, using up one retry.
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
283 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
284 data_len = sizeof(data_in);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
285 client_len = sizeof(client_addr);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
286 if ((data_len = recvfrom(s, data_in, data_len, 0,
112
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
287 (struct sockaddr *)&client_addr,
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
288 &client_len)) < 0) {
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
289 // What happened? Maybe someone lied to us...
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
290 continue; // retry the send, using up one retry.
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
291 }
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
292 if ((ntohs(response->th_opcode) == ACK) &&
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
293 (ntohs(response->th_block) < block)) {
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
294 // Then it is a repeat ACK for an old block; listen again,
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
295 // but do not repeat sending the current block, and do not
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
296 // use up a retry count.
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
297 goto repeat_select;
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
298 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
299 if ((ntohs(response->th_opcode) == ACK) &&
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
300 (ntohs(response->th_block) == block)) {
112
02ea4320376c Merge from eCos master repository on 2000-07-21-21:01:39-BST
jlarmour
parents: 97
diff changeset
301 // Happy! Break out of the retries loop.
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
302 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
303 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
304 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
305 if (len < SEGSIZE) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
306 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
307 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
308 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
309 close(s);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
310 (server->ops->close)(fd);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
311 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
312
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
313 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
314 // Actual TFTP server
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
315 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
316 static void
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
317 tftpd_server(cyg_addrword_t p)
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
318 {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
319 struct tftp_server *server = (struct tftp_server *)p;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
320 int s;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
321 int data_len, recv_len, from_len;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
322 struct sockaddr_in local_addr, from_addr;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
323 struct servent *server_info;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
324 char data[SEGSIZE+sizeof(struct tftphdr)];
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
325 struct tftphdr *hdr = (struct tftphdr *)data;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
326
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
327 #ifndef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
328 // Otherwise routine printfs fail the test - interrupts disabled too long.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
329 diag_printf("TFTPD: %x, port: %d\n", p, server->port);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
330 #endif
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
331
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
332 // Set up port
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
333 if (server->port == 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
334 server_info = getservbyname("tftp", "udp");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
335 if (server_info == (struct servent *)0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
336 diag_printf("TFTPD: can't get TFTP service information\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
337 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
338 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
339 server->port = server_info->s_port;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
340 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
341
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
342 // Create socket
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
343 s = socket(AF_INET, SOCK_DGRAM, 0);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
344 if (s < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
345 diag_printf("TFTPD: can't open socket\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
346 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
347 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
348 memset((char *)&local_addr, 0, sizeof(local_addr));
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
349 local_addr.sin_family = AF_INET;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
350 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
351 local_addr.sin_port = htons(server->port);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
352 if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
353 // Problem setting up my end
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
354 diag_printf("TFTPD: can't bind to service port\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
355 close(s);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
356 return;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
357 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
358
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
359 while (true) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
360 recv_len = sizeof(data);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
361 from_len = sizeof(from_addr);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
362 if ((data_len = recvfrom(s, hdr, recv_len, 0,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
363 (struct sockaddr *)&from_addr, &from_len)) < 0) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
364 diag_printf("TFTPD: can't read request\n");
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
365 } else {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
366 #ifndef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
367 diag_printf("TFTPD: received %x from %s:%d\n",
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
368 ntohs(hdr->th_opcode), inet_ntoa(from_addr.sin_addr), from_addr.sin_port);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
369 #endif
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
370 switch (ntohs(hdr->th_opcode)) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
371 case WRQ:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
372 tftpd_write_file(server, hdr, &from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
373 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
374 case RRQ:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
375 tftpd_read_file(server, hdr, &from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
376 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
377 case ACK:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
378 case DATA:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
379 case ERROR:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
380 // Ignore
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
381 break;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
382 default:
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
383 diag_printf("TFTPD: bogus request %x from %s:%d\n",
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
384 ntohs(hdr->th_opcode), inet_ntoa(from_addr.sin_addr), from_addr.sin_port);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
385 hdr->th_opcode = htons(ERROR);
115
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
386 hdr->th_code = htons(TFTP_EBADOP);
6ed91473a1cd Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents: 112
diff changeset
387 strcpy(hdr->th_msg, errmsg[TFTP_EBADOP]);;
97
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
388 sendto(s, hdr, 4+strlen(hdr->th_msg)+1, 0,
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
389 (struct sockaddr *)&from_addr, from_len);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
390 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
391 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
392 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
393 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
394
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
395 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
396 // This function is used to create a new server [thread] which supports
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
397 // the TFTP protocol on the given port. A server 'id' will be returned
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
398 // which can later be used to destroy the server.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
399 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
400 // Note: all [memory] resources for the server thread will be allocated
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
401 // dynamically. If there are insufficient resources, an error will be
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
402 // returned.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
403 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
404 int
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
405 tftpd_start(int port, struct tftpd_fileops *ops)
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
406 {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
407 struct tftp_server *server;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
408 if ((server = malloc(sizeof(struct tftp_server)))) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
409 server->tag = TFTP_tag;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
410 server->port = port;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
411 server->ops = ops;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
412 cyg_thread_create(CYGPKG_NET_TFTPD_THREAD_PRIORITY, // Priority
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
413 tftpd_server, // entry
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
414 (cyg_addrword_t)server, // entry parameter
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
415 "TFTP server", // Name
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
416 &server->stack[0], // Stack
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
417 STACK_SIZE, // Size
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
418 &server->thread_handle, // Handle
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
419 &server->thread_data // Thread data structure
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
420 );
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
421 cyg_thread_resume(server->thread_handle); // Start it
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
422
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
423 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
424 return (int)server;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
425 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
426
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
427 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
428 // Destroy a TFTP server, using a previously created server 'id'.
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
429 //
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
430 int
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
431 tftpd_stop(int p)
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
432 {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
433 struct tftp_server *server = (struct tftp_server *)p;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
434 // Simple sanity check
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
435 if (server->tag == TFTP_tag) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
436 cyg_thread_kill(server->thread_handle);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
437 cyg_thread_set_priority(server->thread_handle, 0);
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
438 cyg_thread_delay(1); // Make sure it gets to die...
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
439 if (cyg_thread_delete(server->thread_handle)) {
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
440 // Success shutting down the thread
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
441 free(server); // Give up memory
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
442 return 1;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
443 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
444 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
445 return 0;
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
446 }
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
447
ced4577552cd Merge from eCos master repository on 2000-06-06-08:44:00-BST
jlarmour
parents:
diff changeset
448 // EOF tftp_server.c