summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-08-20 17:47:49 +0000
committerEric Andersen <andersen@codepoet.org>2001-08-20 17:47:49 +0000
commit76fa8ea7903bd730b4b6157960647a7b8451983b (patch)
treebe4599fd8f405c1ad27f3bdc25bf2943026bb2ce
parentbac490fe533e16a6f24735f18ed9427e5d4ed8f0 (diff)
downloadbusybox-w32-76fa8ea7903bd730b4b6157960647a7b8451983b.tar.gz
busybox-w32-76fa8ea7903bd730b4b6157960647a7b8451983b.tar.bz2
busybox-w32-76fa8ea7903bd730b4b6157960647a7b8451983b.zip
Apply Glenn's tftp rewrite
-rw-r--r--networking/tftp.c243
-rw-r--r--tftp.c243
2 files changed, 212 insertions, 274 deletions
diff --git a/networking/tftp.c b/networking/tftp.c
index bb75c88ec..999b5d706 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -47,37 +47,6 @@
47 47
48//#define BB_FEATURE_TFTP_DEBUG 48//#define BB_FEATURE_TFTP_DEBUG
49 49
50/* we don't need #ifdefs with these constants and optimization... */
51
52#ifdef BB_FEATURE_TFTP_GET
53#define BB_TFTP_GET (1 << 0)
54#else
55#define BB_TFTP_GET 0
56#endif
57
58#ifdef BB_FEATURE_TFTP_PUT
59#define BB_TFTP_PUT (1 << 1)
60#else
61#define BB_TFTP_PUT 0
62#endif
63
64#ifdef BB_FEATURE_TFTP_DEBUG
65#define BB_TFTP_DEBUG 1
66#else
67#define BB_TFTP_DEBUG 0
68#endif
69
70#define BB_TFTP_NO_RETRIES 5
71#define BB_TFTP_TIMEOUT 5 /* seconds */
72
73#define RRQ 1 /* read request */
74#define WRQ 2 /* write request */
75#define DATA 3 /* data packet */
76#define ACK 4 /* acknowledgement */
77#define ERROR 5 /* error code */
78
79#define BUFSIZE (512+4)
80
81static const char *tftp_error_msg[] = { 50static const char *tftp_error_msg[] = {
82 "Undefined error", 51 "Undefined error",
83 "File not found", 52 "File not found",
@@ -89,24 +58,32 @@ static const char *tftp_error_msg[] = {
89 "No such user" 58 "No such user"
90}; 59};
91 60
92static inline int tftp(int cmd, struct hostent *host, 61const int tftp_cmd_get = 1;
93 char *serverfile, int localfd, int port) 62const int tftp_cmd_put = 2;
63
64static inline int tftp(const int cmd, const struct hostent *host,
65 const char *serverfile, int localfd, const int port, int tftp_bufsize)
94{ 66{
67 const int cmd_get = cmd & tftp_cmd_get;
68 const int cmd_put = cmd & tftp_cmd_put;
69 const int bb_tftp_num_retries = 5;
70
95 struct sockaddr_in sa; 71 struct sockaddr_in sa;
96 int socketfd;
97 struct timeval tv;
98 fd_set rfds;
99 struct sockaddr_in from; 72 struct sockaddr_in from;
73 struct timeval tv;
100 socklen_t fromlen; 74 socklen_t fromlen;
75 fd_set rfds;
101 char *cp; 76 char *cp;
102 unsigned short tmp; 77 unsigned short tmp;
103 int len, opcode, finished; 78 int socketfd;
104 int timeout, block_nr; 79 int len;
105 80 int opcode = 0;
106 RESERVE_BB_BUFFER(buf, BUFSIZE); 81 int finished = 0;
82 int timeout = bb_tftp_num_retries;
83 int block_nr = 1;
84 RESERVE_BB_BUFFER(buf, tftp_bufsize + 4); // Why 4 ?
107 85
108 opcode = finished = timeout = 0; 86 tftp_bufsize += 4;
109 block_nr = 1;
110 87
111 if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 88 if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
112 perror_msg("socket"); 89 perror_msg("socket");
@@ -125,12 +102,12 @@ static inline int tftp(int cmd, struct hostent *host,
125 102
126 /* build opcode */ 103 /* build opcode */
127 104
128 if (cmd & BB_TFTP_GET) { 105 if (cmd_get) {
129 opcode = RRQ; 106 opcode = 1; // read request = 1
130 } 107 }
131 108
132 if (cmd & BB_TFTP_PUT) { 109 if (cmd_put) {
133 opcode = WRQ; 110 opcode = 2; // write request = 2
134 } 111 }
135 112
136 while (1) { 113 while (1) {
@@ -147,16 +124,17 @@ static inline int tftp(int cmd, struct hostent *host,
147 124
148 /* add filename and mode */ 125 /* add filename and mode */
149 126
150 if ((BB_TFTP_GET && (opcode == RRQ)) || 127 if ((cmd_get && (opcode == 1)) || // read request = 1
151 (BB_TFTP_PUT && (opcode == WRQ))) { 128 (cmd_put && (opcode == 2))) { // write request = 2
152 129
153 while (cp != &buf[BUFSIZE - 1]) { 130 /* what is this trying to do ? */
131 while (cp != &buf[tftp_bufsize - 1]) {
154 if ((*cp = *serverfile++) == '\0') 132 if ((*cp = *serverfile++) == '\0')
155 break; 133 break;
156 cp++; 134 cp++;
157 } 135 }
158 136 /* and this ? */
159 if ((*cp != '\0') || (&buf[BUFSIZE - 1] - cp) < 7) { 137 if ((*cp != '\0') || (&buf[tftp_bufsize - 1] - cp) < 7) {
160 error_msg("too long server-filename"); 138 error_msg("too long server-filename");
161 break; 139 break;
162 } 140 }
@@ -167,8 +145,8 @@ static inline int tftp(int cmd, struct hostent *host,
167 145
168 /* add ack and data */ 146 /* add ack and data */
169 147
170 if ((BB_TFTP_GET && (opcode == ACK)) || 148 if ((cmd_get && (opcode == 4)) || // acknowledgement = 4
171 (BB_TFTP_PUT && (opcode == DATA))) { 149 (cmd_put && (opcode == 3))) { // data packet == 3
172 150
173 *((unsigned short *) cp) = htons(block_nr); 151 *((unsigned short *) cp) = htons(block_nr);
174 152
@@ -176,15 +154,15 @@ static inline int tftp(int cmd, struct hostent *host,
176 154
177 block_nr++; 155 block_nr++;
178 156
179 if (BB_TFTP_PUT && (opcode == DATA)) { 157 if (cmd_put && (opcode == 3)) { // data packet == 3
180 len = read(localfd, cp, BUFSIZE - 4); 158 len = read(localfd, cp, tftp_bufsize - 4);
181 159
182 if (len < 0) { 160 if (len < 0) {
183 perror_msg("read"); 161 perror_msg("read");
184 break; 162 break;
185 } 163 }
186 164
187 if (len != (BUFSIZE - 4)) { 165 if (len != (tftp_bufsize - 4)) {
188 finished++; 166 finished++;
189 } 167 }
190 168
@@ -202,16 +180,14 @@ static inline int tftp(int cmd, struct hostent *host,
202 180
203 len = cp - buf; 181 len = cp - buf;
204 182
205 if (BB_TFTP_DEBUG) { 183#ifdef BB_FEATURE_TFTP_DEBUG
206 printf("sending %u bytes\n", len); 184 printf("sending %u bytes\n", len);
207 185 for (cp = buf; cp < &buf[len]; cp++)
208 for (cp = buf; cp < &buf[len]; cp++) 186 printf("%02x ", *cp);
209 printf("%02x ", *cp); 187 printf("\n");
210 printf("\n"); 188#endif
211 }
212
213 if (sendto(socketfd, buf, len, 0, 189 if (sendto(socketfd, buf, len, 0,
214 (struct sockaddr *) &sa, sizeof(sa)) < 0) { 190 (struct sockaddr *) &sa, sizeof(sa)) < 0) {
215 perror_msg("send"); 191 perror_msg("send");
216 len = -1; 192 len = -1;
217 break; 193 break;
@@ -224,7 +200,7 @@ static inline int tftp(int cmd, struct hostent *host,
224 memset(&from, 0, sizeof(from)); 200 memset(&from, 0, sizeof(from));
225 fromlen = sizeof(from); 201 fromlen = sizeof(from);
226 202
227 tv.tv_sec = BB_TFTP_TIMEOUT; 203 tv.tv_sec = 5; // BB_TFPT_TIMEOUT = 5
228 tv.tv_usec = 0; 204 tv.tv_usec = 0;
229 205
230 FD_ZERO(&rfds); 206 FD_ZERO(&rfds);
@@ -232,9 +208,8 @@ static inline int tftp(int cmd, struct hostent *host,
232 208
233 switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) { 209 switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) {
234 case 1: 210 case 1:
235 len = recvfrom(socketfd, buf, 211 len = recvfrom(socketfd, buf, tftp_bufsize, 0,
236 BUFSIZE, 0, 212 (struct sockaddr *) &from, &fromlen);
237 (struct sockaddr *) &from, &fromlen);
238 213
239 if (len < 0) { 214 if (len < 0) {
240 perror_msg("recvfrom"); 215 perror_msg("recvfrom");
@@ -245,28 +220,23 @@ static inline int tftp(int cmd, struct hostent *host,
245 220
246 if (sa.sin_port == htons(port)) { 221 if (sa.sin_port == htons(port)) {
247 sa.sin_port = from.sin_port; 222 sa.sin_port = from.sin_port;
248 break;
249 } 223 }
250
251 if (sa.sin_port == from.sin_port) { 224 if (sa.sin_port == from.sin_port) {
252 break; 225 break;
253 } 226 }
254 227
255 /* fall-through for bad packets! */ 228 /* fall-through for bad packets! */
256 /* discard the packet - treat as timeout */ 229 /* discard the packet - treat as timeout */
230 timeout = bb_tftp_num_retries;
257 231
258 case 0: 232 case 0:
259 error_msg("timeout"); 233 error_msg("timeout");
260 234
261 if (!timeout) { 235 if (timeout == 0) {
262 timeout = BB_TFTP_NO_RETRIES;
263 } else {
264 timeout--;
265 }
266
267 if (!timeout) {
268 len = -1; 236 len = -1;
269 error_msg("last timeout"); 237 error_msg("last timeout");
238 } else {
239 timeout--;
270 } 240 }
271 break; 241 break;
272 242
@@ -287,11 +257,11 @@ static inline int tftp(int cmd, struct hostent *host,
287 opcode = ntohs(*((unsigned short *) buf)); 257 opcode = ntohs(*((unsigned short *) buf));
288 tmp = ntohs(*((unsigned short *) &buf[2])); 258 tmp = ntohs(*((unsigned short *) &buf[2]));
289 259
290 if (BB_TFTP_DEBUG) { 260#ifdef BB_FEATURE_TFTP_DEBUG
291 printf("received %d bytes: %04x %04x\n", len, opcode, tmp); 261 printf("received %d bytes: %04x %04x\n", len, opcode, tmp);
292 } 262#endif
293 263
294 if (BB_TFTP_GET && (opcode == DATA)) { 264 if (cmd_get && (opcode == 3)) { // data packet == 3
295 265
296 if (tmp == block_nr) { 266 if (tmp == block_nr) {
297 len = write(localfd, &buf[4], len - 4); 267 len = write(localfd, &buf[4], len - 4);
@@ -301,33 +271,33 @@ static inline int tftp(int cmd, struct hostent *host,
301 break; 271 break;
302 } 272 }
303 273
304 if (len != (BUFSIZE - 4)) { 274 if (len != (tftp_bufsize - 4)) {
305 finished++; 275 finished++;
306 } 276 }
307 277
308 opcode = ACK; 278 opcode = 4; // acknowledgement = 4
309 continue; 279 continue;
310 } 280 }
311 } 281 }
312 282
313 if (BB_TFTP_PUT && (opcode == ACK)) { 283 if (cmd_put && (opcode == 4)) { // acknowledgement = 4
314 284
315 if (tmp == (block_nr - 1)) { 285 if (tmp == (block_nr - 1)) {
316 if (finished) { 286 if (finished) {
317 break; 287 break;
318 } 288 }
319 289
320 opcode = DATA; 290 opcode = 3; // data packet == 3
321 continue; 291 continue;
322 } 292 }
323 } 293 }
324 294
325 if (opcode == ERROR) { 295 if (opcode == 5) { // error code == 5
326 char *msg = NULL; 296 char *msg = NULL;
327 297
328 if (buf[4] != '\0') { 298 if (buf[4] != '\0') {
329 msg = &buf[4]; 299 msg = &buf[4];
330 buf[BUFSIZE - 1] = '\0'; 300 buf[tftp_bufsize - 1] = '\0';
331 } else if (tmp < (sizeof(tftp_error_msg) / sizeof(char *))) { 301 } else if (tmp < (sizeof(tftp_error_msg) / sizeof(char *))) {
332 msg = (char *) tftp_error_msg[tmp]; 302 msg = (char *) tftp_error_msg[tmp];
333 } 303 }
@@ -347,68 +317,67 @@ static inline int tftp(int cmd, struct hostent *host,
347 317
348int tftp_main(int argc, char **argv) 318int tftp_main(int argc, char **argv)
349{ 319{
350 char *cp, *s; 320 struct hostent *host = NULL;
351 char *serverstr; 321 char *localfile = NULL;
352 struct hostent *host; 322 char *remotefile = NULL;
353 char *serverfile; 323 int port = 69;
354 char *localfile; 324 int cmd = 0;
355 int cmd, flags, fd, bad; 325 int fd = -1;
356 326 int flags = 0;
357 host = (void *) serverstr = serverfile = localfile = NULL; 327 int opt;
358 flags = cmd = 0; 328 int result;
359 bad = 1; 329 int blocksize = 512;
360 330
361 if (argc > 3) { 331 while ((opt = getopt(argc, argv, "b:gpl:r:")) != -1) {
362 if (BB_TFTP_GET && (strcmp(argv[1], "get") == 0)) { 332 switch (opt) {
363 cmd = BB_TFTP_GET; 333 case 'b':
334 blocksize = atoi(optarg);
335 break;
336#ifdef BB_FEATURE_TFTP_GET
337 case 'g':
338 cmd = tftp_cmd_get;
364 flags = O_WRONLY | O_CREAT; 339 flags = O_WRONLY | O_CREAT;
365 serverstr = argv[2]; 340 break;
366 localfile = argv[3]; 341#endif
367 } 342#ifdef BB_FEATURE_TFTP_PUT
368 343 case 'p':
369 if (BB_TFTP_PUT && (strcmp(argv[1], "put") == 0)) { 344 cmd = tftp_cmd_put;
370 cmd = BB_TFTP_PUT;
371 flags = O_RDONLY; 345 flags = O_RDONLY;
372 localfile = argv[2]; 346 break;
373 serverstr = argv[3]; 347#endif
348 case 'l':
349 localfile = xstrdup(optarg);
350 break;
351 case 'r':
352 remotefile = xstrdup(optarg);
353 break;
374 } 354 }
375
376 } 355 }
377 356
378 if (!(cmd & (BB_TFTP_GET | BB_TFTP_PUT))) { 357 if ((cmd == 0) || (optind == argc)) {
379 show_usage(); 358 show_usage();
380 } 359 }
381 360
382 for (cp = serverstr; *cp != '\0'; cp++) 361 fd = open(localfile, flags, 0644);
383 if (*cp == ':') 362 if (fd < 0) {
384 break; 363 perror_msg_and_die("local file");
385
386 if (*cp == ':') {
387
388 serverfile = cp + 1;
389
390 s = xstrdup(serverstr);
391 s[cp - serverstr] = '\0';
392
393 host = xgethostbyname(s);
394
395 free(s);
396 } 364 }
397 365
398 if (BB_TFTP_DEBUG) { 366 host = xgethostbyname(argv[optind]);
399 printf("using server \"%s\", serverfile \"%s\","
400 "localfile \"%s\".\n",
401 inet_ntoa(*((struct in_addr *) host->h_addr)),
402 serverfile, localfile);
403 }
404 367
405 if ((fd = open(localfile, flags, 0644)) < 0) { 368 if (optind + 2 == argc) {
406 perror_msg_and_die("local file"); 369 port = atoi(argv[optind + 1]);
407 } 370 }
408 371
409 flags = tftp(cmd, host, serverfile, fd, 69); 372#ifdef BB_FEATURE_TFTP_DEBUG
373 printf("using server \"%s\", serverfile \"%s\","
374 "localfile \"%s\".\n",
375 inet_ntoa(*((struct in_addr *) host->h_addr)),
376 remotefile, localfile);
377#endif
410 378
379 result = tftp(cmd, host, remotefile, fd, port, blocksize);
411 close(fd); 380 close(fd);
412 381
413 return flags; 382 return(result);
414} 383} \ No newline at end of file
diff --git a/tftp.c b/tftp.c
index bb75c88ec..999b5d706 100644
--- a/tftp.c
+++ b/tftp.c
@@ -47,37 +47,6 @@
47 47
48//#define BB_FEATURE_TFTP_DEBUG 48//#define BB_FEATURE_TFTP_DEBUG
49 49
50/* we don't need #ifdefs with these constants and optimization... */
51
52#ifdef BB_FEATURE_TFTP_GET
53#define BB_TFTP_GET (1 << 0)
54#else
55#define BB_TFTP_GET 0
56#endif
57
58#ifdef BB_FEATURE_TFTP_PUT
59#define BB_TFTP_PUT (1 << 1)
60#else
61#define BB_TFTP_PUT 0
62#endif
63
64#ifdef BB_FEATURE_TFTP_DEBUG
65#define BB_TFTP_DEBUG 1
66#else
67#define BB_TFTP_DEBUG 0
68#endif
69
70#define BB_TFTP_NO_RETRIES 5
71#define BB_TFTP_TIMEOUT 5 /* seconds */
72
73#define RRQ 1 /* read request */
74#define WRQ 2 /* write request */
75#define DATA 3 /* data packet */
76#define ACK 4 /* acknowledgement */
77#define ERROR 5 /* error code */
78
79#define BUFSIZE (512+4)
80
81static const char *tftp_error_msg[] = { 50static const char *tftp_error_msg[] = {
82 "Undefined error", 51 "Undefined error",
83 "File not found", 52 "File not found",
@@ -89,24 +58,32 @@ static const char *tftp_error_msg[] = {
89 "No such user" 58 "No such user"
90}; 59};
91 60
92static inline int tftp(int cmd, struct hostent *host, 61const int tftp_cmd_get = 1;
93 char *serverfile, int localfd, int port) 62const int tftp_cmd_put = 2;
63
64static inline int tftp(const int cmd, const struct hostent *host,
65 const char *serverfile, int localfd, const int port, int tftp_bufsize)
94{ 66{
67 const int cmd_get = cmd & tftp_cmd_get;
68 const int cmd_put = cmd & tftp_cmd_put;
69 const int bb_tftp_num_retries = 5;
70
95 struct sockaddr_in sa; 71 struct sockaddr_in sa;
96 int socketfd;
97 struct timeval tv;
98 fd_set rfds;
99 struct sockaddr_in from; 72 struct sockaddr_in from;
73 struct timeval tv;
100 socklen_t fromlen; 74 socklen_t fromlen;
75 fd_set rfds;
101 char *cp; 76 char *cp;
102 unsigned short tmp; 77 unsigned short tmp;
103 int len, opcode, finished; 78 int socketfd;
104 int timeout, block_nr; 79 int len;
105 80 int opcode = 0;
106 RESERVE_BB_BUFFER(buf, BUFSIZE); 81 int finished = 0;
82 int timeout = bb_tftp_num_retries;
83 int block_nr = 1;
84 RESERVE_BB_BUFFER(buf, tftp_bufsize + 4); // Why 4 ?
107 85
108 opcode = finished = timeout = 0; 86 tftp_bufsize += 4;
109 block_nr = 1;
110 87
111 if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 88 if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
112 perror_msg("socket"); 89 perror_msg("socket");
@@ -125,12 +102,12 @@ static inline int tftp(int cmd, struct hostent *host,
125 102
126 /* build opcode */ 103 /* build opcode */
127 104
128 if (cmd & BB_TFTP_GET) { 105 if (cmd_get) {
129 opcode = RRQ; 106 opcode = 1; // read request = 1
130 } 107 }
131 108
132 if (cmd & BB_TFTP_PUT) { 109 if (cmd_put) {
133 opcode = WRQ; 110 opcode = 2; // write request = 2
134 } 111 }
135 112
136 while (1) { 113 while (1) {
@@ -147,16 +124,17 @@ static inline int tftp(int cmd, struct hostent *host,
147 124
148 /* add filename and mode */ 125 /* add filename and mode */
149 126
150 if ((BB_TFTP_GET && (opcode == RRQ)) || 127 if ((cmd_get && (opcode == 1)) || // read request = 1
151 (BB_TFTP_PUT && (opcode == WRQ))) { 128 (cmd_put && (opcode == 2))) { // write request = 2
152 129
153 while (cp != &buf[BUFSIZE - 1]) { 130 /* what is this trying to do ? */
131 while (cp != &buf[tftp_bufsize - 1]) {
154 if ((*cp = *serverfile++) == '\0') 132 if ((*cp = *serverfile++) == '\0')
155 break; 133 break;
156 cp++; 134 cp++;
157 } 135 }
158 136 /* and this ? */
159 if ((*cp != '\0') || (&buf[BUFSIZE - 1] - cp) < 7) { 137 if ((*cp != '\0') || (&buf[tftp_bufsize - 1] - cp) < 7) {
160 error_msg("too long server-filename"); 138 error_msg("too long server-filename");
161 break; 139 break;
162 } 140 }
@@ -167,8 +145,8 @@ static inline int tftp(int cmd, struct hostent *host,
167 145
168 /* add ack and data */ 146 /* add ack and data */
169 147
170 if ((BB_TFTP_GET && (opcode == ACK)) || 148 if ((cmd_get && (opcode == 4)) || // acknowledgement = 4
171 (BB_TFTP_PUT && (opcode == DATA))) { 149 (cmd_put && (opcode == 3))) { // data packet == 3
172 150
173 *((unsigned short *) cp) = htons(block_nr); 151 *((unsigned short *) cp) = htons(block_nr);
174 152
@@ -176,15 +154,15 @@ static inline int tftp(int cmd, struct hostent *host,
176 154
177 block_nr++; 155 block_nr++;
178 156
179 if (BB_TFTP_PUT && (opcode == DATA)) { 157 if (cmd_put && (opcode == 3)) { // data packet == 3
180 len = read(localfd, cp, BUFSIZE - 4); 158 len = read(localfd, cp, tftp_bufsize - 4);
181 159
182 if (len < 0) { 160 if (len < 0) {
183 perror_msg("read"); 161 perror_msg("read");
184 break; 162 break;
185 } 163 }
186 164
187 if (len != (BUFSIZE - 4)) { 165 if (len != (tftp_bufsize - 4)) {
188 finished++; 166 finished++;
189 } 167 }
190 168
@@ -202,16 +180,14 @@ static inline int tftp(int cmd, struct hostent *host,
202 180
203 len = cp - buf; 181 len = cp - buf;
204 182
205 if (BB_TFTP_DEBUG) { 183#ifdef BB_FEATURE_TFTP_DEBUG
206 printf("sending %u bytes\n", len); 184 printf("sending %u bytes\n", len);
207 185 for (cp = buf; cp < &buf[len]; cp++)
208 for (cp = buf; cp < &buf[len]; cp++) 186 printf("%02x ", *cp);
209 printf("%02x ", *cp); 187 printf("\n");
210 printf("\n"); 188#endif
211 }
212
213 if (sendto(socketfd, buf, len, 0, 189 if (sendto(socketfd, buf, len, 0,
214 (struct sockaddr *) &sa, sizeof(sa)) < 0) { 190 (struct sockaddr *) &sa, sizeof(sa)) < 0) {
215 perror_msg("send"); 191 perror_msg("send");
216 len = -1; 192 len = -1;
217 break; 193 break;
@@ -224,7 +200,7 @@ static inline int tftp(int cmd, struct hostent *host,
224 memset(&from, 0, sizeof(from)); 200 memset(&from, 0, sizeof(from));
225 fromlen = sizeof(from); 201 fromlen = sizeof(from);
226 202
227 tv.tv_sec = BB_TFTP_TIMEOUT; 203 tv.tv_sec = 5; // BB_TFPT_TIMEOUT = 5
228 tv.tv_usec = 0; 204 tv.tv_usec = 0;
229 205
230 FD_ZERO(&rfds); 206 FD_ZERO(&rfds);
@@ -232,9 +208,8 @@ static inline int tftp(int cmd, struct hostent *host,
232 208
233 switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) { 209 switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) {
234 case 1: 210 case 1:
235 len = recvfrom(socketfd, buf, 211 len = recvfrom(socketfd, buf, tftp_bufsize, 0,
236 BUFSIZE, 0, 212 (struct sockaddr *) &from, &fromlen);
237 (struct sockaddr *) &from, &fromlen);
238 213
239 if (len < 0) { 214 if (len < 0) {
240 perror_msg("recvfrom"); 215 perror_msg("recvfrom");
@@ -245,28 +220,23 @@ static inline int tftp(int cmd, struct hostent *host,
245 220
246 if (sa.sin_port == htons(port)) { 221 if (sa.sin_port == htons(port)) {
247 sa.sin_port = from.sin_port; 222 sa.sin_port = from.sin_port;
248 break;
249 } 223 }
250
251 if (sa.sin_port == from.sin_port) { 224 if (sa.sin_port == from.sin_port) {
252 break; 225 break;
253 } 226 }
254 227
255 /* fall-through for bad packets! */ 228 /* fall-through for bad packets! */
256 /* discard the packet - treat as timeout */ 229 /* discard the packet - treat as timeout */
230 timeout = bb_tftp_num_retries;
257 231
258 case 0: 232 case 0:
259 error_msg("timeout"); 233 error_msg("timeout");
260 234
261 if (!timeout) { 235 if (timeout == 0) {
262 timeout = BB_TFTP_NO_RETRIES;
263 } else {
264 timeout--;
265 }
266
267 if (!timeout) {
268 len = -1; 236 len = -1;
269 error_msg("last timeout"); 237 error_msg("last timeout");
238 } else {
239 timeout--;
270 } 240 }
271 break; 241 break;
272 242
@@ -287,11 +257,11 @@ static inline int tftp(int cmd, struct hostent *host,
287 opcode = ntohs(*((unsigned short *) buf)); 257 opcode = ntohs(*((unsigned short *) buf));
288 tmp = ntohs(*((unsigned short *) &buf[2])); 258 tmp = ntohs(*((unsigned short *) &buf[2]));
289 259
290 if (BB_TFTP_DEBUG) { 260#ifdef BB_FEATURE_TFTP_DEBUG
291 printf("received %d bytes: %04x %04x\n", len, opcode, tmp); 261 printf("received %d bytes: %04x %04x\n", len, opcode, tmp);
292 } 262#endif
293 263
294 if (BB_TFTP_GET && (opcode == DATA)) { 264 if (cmd_get && (opcode == 3)) { // data packet == 3
295 265
296 if (tmp == block_nr) { 266 if (tmp == block_nr) {
297 len = write(localfd, &buf[4], len - 4); 267 len = write(localfd, &buf[4], len - 4);
@@ -301,33 +271,33 @@ static inline int tftp(int cmd, struct hostent *host,
301 break; 271 break;
302 } 272 }
303 273
304 if (len != (BUFSIZE - 4)) { 274 if (len != (tftp_bufsize - 4)) {
305 finished++; 275 finished++;
306 } 276 }
307 277
308 opcode = ACK; 278 opcode = 4; // acknowledgement = 4
309 continue; 279 continue;
310 } 280 }
311 } 281 }
312 282
313 if (BB_TFTP_PUT && (opcode == ACK)) { 283 if (cmd_put && (opcode == 4)) { // acknowledgement = 4
314 284
315 if (tmp == (block_nr - 1)) { 285 if (tmp == (block_nr - 1)) {
316 if (finished) { 286 if (finished) {
317 break; 287 break;
318 } 288 }
319 289
320 opcode = DATA; 290 opcode = 3; // data packet == 3
321 continue; 291 continue;
322 } 292 }
323 } 293 }
324 294
325 if (opcode == ERROR) { 295 if (opcode == 5) { // error code == 5
326 char *msg = NULL; 296 char *msg = NULL;
327 297
328 if (buf[4] != '\0') { 298 if (buf[4] != '\0') {
329 msg = &buf[4]; 299 msg = &buf[4];
330 buf[BUFSIZE - 1] = '\0'; 300 buf[tftp_bufsize - 1] = '\0';
331 } else if (tmp < (sizeof(tftp_error_msg) / sizeof(char *))) { 301 } else if (tmp < (sizeof(tftp_error_msg) / sizeof(char *))) {
332 msg = (char *) tftp_error_msg[tmp]; 302 msg = (char *) tftp_error_msg[tmp];
333 } 303 }
@@ -347,68 +317,67 @@ static inline int tftp(int cmd, struct hostent *host,
347 317
348int tftp_main(int argc, char **argv) 318int tftp_main(int argc, char **argv)
349{ 319{
350 char *cp, *s; 320 struct hostent *host = NULL;
351 char *serverstr; 321 char *localfile = NULL;
352 struct hostent *host; 322 char *remotefile = NULL;
353 char *serverfile; 323 int port = 69;
354 char *localfile; 324 int cmd = 0;
355 int cmd, flags, fd, bad; 325 int fd = -1;
356 326 int flags = 0;
357 host = (void *) serverstr = serverfile = localfile = NULL; 327 int opt;
358 flags = cmd = 0; 328 int result;
359 bad = 1; 329 int blocksize = 512;
360 330
361 if (argc > 3) { 331 while ((opt = getopt(argc, argv, "b:gpl:r:")) != -1) {
362 if (BB_TFTP_GET && (strcmp(argv[1], "get") == 0)) { 332 switch (opt) {
363 cmd = BB_TFTP_GET; 333 case 'b':
334 blocksize = atoi(optarg);
335 break;
336#ifdef BB_FEATURE_TFTP_GET
337 case 'g':
338 cmd = tftp_cmd_get;
364 flags = O_WRONLY | O_CREAT; 339 flags = O_WRONLY | O_CREAT;
365 serverstr = argv[2]; 340 break;
366 localfile = argv[3]; 341#endif
367 } 342#ifdef BB_FEATURE_TFTP_PUT
368 343 case 'p':
369 if (BB_TFTP_PUT && (strcmp(argv[1], "put") == 0)) { 344 cmd = tftp_cmd_put;
370 cmd = BB_TFTP_PUT;
371 flags = O_RDONLY; 345 flags = O_RDONLY;
372 localfile = argv[2]; 346 break;
373 serverstr = argv[3]; 347#endif
348 case 'l':
349 localfile = xstrdup(optarg);
350 break;
351 case 'r':
352 remotefile = xstrdup(optarg);
353 break;
374 } 354 }
375
376 } 355 }
377 356
378 if (!(cmd & (BB_TFTP_GET | BB_TFTP_PUT))) { 357 if ((cmd == 0) || (optind == argc)) {
379 show_usage(); 358 show_usage();
380 } 359 }
381 360
382 for (cp = serverstr; *cp != '\0'; cp++) 361 fd = open(localfile, flags, 0644);
383 if (*cp == ':') 362 if (fd < 0) {
384 break; 363 perror_msg_and_die("local file");
385
386 if (*cp == ':') {
387
388 serverfile = cp + 1;
389
390 s = xstrdup(serverstr);
391 s[cp - serverstr] = '\0';
392
393 host = xgethostbyname(s);
394
395 free(s);
396 } 364 }
397 365
398 if (BB_TFTP_DEBUG) { 366 host = xgethostbyname(argv[optind]);
399 printf("using server \"%s\", serverfile \"%s\","
400 "localfile \"%s\".\n",
401 inet_ntoa(*((struct in_addr *) host->h_addr)),
402 serverfile, localfile);
403 }
404 367
405 if ((fd = open(localfile, flags, 0644)) < 0) { 368 if (optind + 2 == argc) {
406 perror_msg_and_die("local file"); 369 port = atoi(argv[optind + 1]);
407 } 370 }
408 371
409 flags = tftp(cmd, host, serverfile, fd, 69); 372#ifdef BB_FEATURE_TFTP_DEBUG
373 printf("using server \"%s\", serverfile \"%s\","
374 "localfile \"%s\".\n",
375 inet_ntoa(*((struct in_addr *) host->h_addr)),
376 remotefile, localfile);
377#endif
410 378
379 result = tftp(cmd, host, remotefile, fd, port, blocksize);
411 close(fd); 380 close(fd);
412 381
413 return flags; 382 return(result);
414} 383} \ No newline at end of file