Annotation of embedtools/src/upd.c, revision 1.2.2.1
1.2 misho 1: /*************************************************************************
2: * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
3: * by Michael Pounov <misho@aitbg.com>
4: *
5: * $Author: misho $
1.2.2.1 ! misho 6: * $Id: upd.c,v 1.2 2011/06/08 12:45:41 misho Exp $
1.2 misho 7: *
1.2.2.1 ! misho 8: *************************************************************************
! 9: The ELWIX and AITNET software is distributed under the following
! 10: terms:
! 11:
! 12: All of the documentation and software included in the ELWIX and AITNET
! 13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
! 14:
! 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
! 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
! 17:
! 18: Redistribution and use in source and binary forms, with or without
! 19: modification, are permitted provided that the following conditions
! 20: are met:
! 21: 1. Redistributions of source code must retain the above copyright
! 22: notice, this list of conditions and the following disclaimer.
! 23: 2. Redistributions in binary form must reproduce the above copyright
! 24: notice, this list of conditions and the following disclaimer in the
! 25: documentation and/or other materials provided with the distribution.
! 26: 3. All advertising materials mentioning features or use of this software
! 27: must display the following acknowledgement:
! 28: This product includes software developed by Michael Pounov <misho@elwix.org>
! 29: ELWIX - Embedded LightWeight unIX and its contributors.
! 30: 4. Neither the name of AITNET nor the names of its contributors
! 31: may be used to endorse or promote products derived from this software
! 32: without specific prior written permission.
! 33:
! 34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
! 35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 44: SUCH DAMAGE.
! 45: */
1.2 misho 46: #include "global.h"
47: #include "upd.h"
48:
49:
50: int Kill;
51:
52:
53: static inline int ChkImg(const char *csImg, char *psDir)
54: {
55: int res = 0;
56:
57: getcwd(psDir, MAXPATHLEN);
58: if (access(csImg, R_OK) == -1) {
59: printf("Error:: Unable to find new image %s #%d - %s\n",
60: csImg, errno, strerror(errno));
61: res = -1;
62: } else {
63: strlcat(psDir, "/", MAXPATHLEN);
64: strlcat(psDir, csImg, MAXPATHLEN);
65: }
66:
67: return res;
68: }
69:
70: // -------------------------------
71:
72: int Activate(const char *csImg)
73: {
74: char szDir[MAXPATHLEN];
75:
76: if (ChkImg(csImg, szDir) == -1)
77: return -1;
78:
79: VERB(3) printf("Activate procedure for %s\n", szDir);
80:
81: unlink(FIRMWARE_IMG);
82: if (symlink(szDir, FIRMWARE_IMG) == -1) {
83: printf("Error:: Unable to activate new image %s #%d - %s\n",
84: csImg, errno, strerror(errno));
85: return -2;
86: }
87:
88: syslog(LOG_NOTICE, "Activate new image %s", csImg);
89: VERB(1) printf("Activate new image %s\n", csImg);
90: return 0;
91: }
92:
93: int Install(const char *csImg, const char *psDir)
94: {
95: int src, dst, len;
96: u_char buf[BUFSIZ];
97: char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
98: struct stat ss, ds;
99:
100: strlcpy(szFile, psDir, MAXPATHLEN);
101: strlcat(szFile, "/", MAXPATHLEN);
102: strlcat(szFile, csImg, MAXPATHLEN);
103: if (access(szFile, R_OK) == -1) {
104: printf("Error:: Unable to find new image %s #%d - %s\n",
105: csImg, errno, strerror(errno));
106: return -1;
107: } else {
108: memset(&ss, 0, sizeof ss);
109: if (stat(szFile, &ss) == -1) {
110: printf("Error:: Unable to find new image %s #%d - %s\n",
111: csImg, errno, strerror(errno));
112: return -1;
113: }
114: }
115:
116: getcwd(szDir, MAXPATHLEN);
117: VERB(3) printf("Install procedure from %s to %s\n", szFile, szDir);
118: strlcat(szDir, "/", MAXPATHLEN);
119: strlcat(szDir, csImg, MAXPATHLEN);
120: memset(&ds, 0, sizeof ds);
121: if (stat(szDir, &ds) == -1 && ENOENT != errno) {
122: printf("Error:: Unable to stat target #%d - %s\n",
123: errno, strerror(errno));
124: return -1;
125: }
126:
127: if (ss.st_dev == ds.st_dev && ss.st_ino == ds.st_ino) {
128: printf("Error:: Unable to install into self ...\n");
129: return -1;
130: }
131:
132: dst = open(szDir, O_WRONLY | O_CREAT | O_TRUNC, 0644);
133: if (dst == -1) {
134: printf("Error:: in create image %s #%d - %s\n",
135: szDir, errno, strerror(errno));
136: return -1;
137: }
138: src = open(szFile, O_RDONLY);
139: if (src == -1) {
140: printf("Error:: in open image %s #%d - %s\n",
141: szFile, errno, strerror(errno));
142: close(dst);
143: unlink(szDir);
144: return -1;
145: }
146:
147: while ((len = read(src, buf, BUFSIZ)) > 0)
148: if (write(dst, buf, len) == -1) {
149: printf("Error:: in write image #%d - %s\n",
150: errno, strerror(errno));
151: close(src);
152: close(dst);
153: unlink(szDir);
154:
155: len = -1;
156: break;
157: }
158:
159: close(src);
160: close(dst);
161:
162: if (!len) {
163: syslog(LOG_NOTICE, "Install image %s to %s", csImg, szDir);
164: VERB(1) printf("Install image %s to %s\n", csImg, szDir);
165: }
166: return len;
167: }
168:
169: int Rollback(const char *csImg)
170: {
171: int src, dst, len;
172: u_char buf[BUFSIZ];
173: char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
174: struct stat ss, ds;
175:
176: getcwd(szFile, MAXPATHLEN);
177: strlcat(szFile, "/", MAXPATHLEN);
178: strlcat(szFile, FIRMWARE_BAK, MAXPATHLEN);
179: if (access(szFile, R_OK) == -1) {
180: printf("Error:: Unable to find backup image #%d - %s\n",
181: errno, strerror(errno));
182: return -1;
183: } else {
184: memset(&ss, 0, sizeof ss);
185: if (stat(szFile, &ss) == -1) {
186: printf("Error:: Unable to find backup image #%d - %s\n",
187: errno, strerror(errno));
188: return -1;
189: }
190: }
191:
192: getcwd(szDir, MAXPATHLEN);
193: strlcat(szDir, "/", MAXPATHLEN);
194: strlcat(szDir, csImg, MAXPATHLEN);
195: VERB(3) printf("Rollback procedure for image %s from backup!\n", csImg);
196: memset(&ds, 0, sizeof ds);
197: if (stat(szDir, &ds) == -1 && ENOENT != errno) {
198: printf("Error:: Unable to stat target #%d - %s\n",
199: errno, strerror(errno));
200: return -1;
201: }
202:
203: if (ss.st_dev == ds.st_dev && ss.st_ino == ds.st_ino) {
204: printf("Error:: Unable to rollback into self ...\n");
205: return -1;
206: }
207:
208: src = open(szFile, O_RDONLY);
209: if (src == -1) {
210: printf("Error:: in open backup %s #%d - %s\n",
211: szFile, errno, strerror(errno));
212: return -1;
213: }
214: dst = open(szDir, O_WRONLY | O_CREAT | O_TRUNC, 0644);
215: if (dst == -1) {
216: printf("Error:: in create image %s #%d - %s\n",
217: szDir, errno, strerror(errno));
218: close(src);
219: return -1;
220: }
221:
222: while ((len = read(src, buf, BUFSIZ)) > 0)
223: if (write(dst, buf, len) == -1) {
224: printf("Error:: in write image #%d - %s\n",
225: errno, strerror(errno));
226: close(dst);
227: close(src);
228: unlink(szDir);
229:
230: len = -1;
231: break;
232: }
233:
234: close(dst);
235: close(src);
236:
237: if (!len) {
238: syslog(LOG_NOTICE, "Rollback image %s to %s", csImg, szDir);
239: VERB(1) printf("Rollback image %s to %s\n", csImg, szDir);
240: }
241: return len;
242:
243: return 0;
244: }
245:
246: int tFTP(const char *csImg, const char *psDir)
247: {
248: int src, dst, len;
249: u_char buf[BUFSIZ];
250: char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
251: struct stat ss, ds;
252:
253: if (ChkImg(csImg, szDir) == -1)
254: return -1;
255: else {
256: memset(&ss, 0, sizeof ss);
257: if (stat(szDir, &ss) == -1) {
258: printf("Error:: Unable to find image %s #%d - %s\n",
259: szDir, errno, strerror(errno));
260: return -1;
261: }
262: }
263:
264: VERB(3) printf("tFTP procedure for %s to %s\n", szDir, psDir);
265: strlcpy(szFile, psDir, MAXPATHLEN);
266: strlcat(szFile, "/", MAXPATHLEN);
267: strlcat(szFile, csImg, MAXPATHLEN);
268: memset(&ds, 0, sizeof ds);
269: if (stat(szFile, &ds) == -1 && ENOENT != errno) {
270: printf("Error:: Unable to stat target %s #%d - %s\n",
271: szFile, errno, strerror(errno));
272: return -1;
273: }
274:
275: if (ss.st_dev == ds.st_dev && ss.st_ino == ds.st_ino) {
276: printf("Error:: Unable to copy into self ...\n");
277: return -1;
278: }
279:
280: dst = open(szFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
281: if (dst == -1) {
282: printf("Error:: in create backup %s #%d - %s\n",
283: szFile, errno, strerror(errno));
284: return -1;
285: }
286: src = open(szDir, O_RDONLY);
287: if (src == -1) {
288: printf("Error:: in open image %s #%d - %s\n",
289: szDir, errno, strerror(errno));
290: close(dst);
291: unlink(szFile);
292: return -1;
293: }
294:
295: while ((len = read(src, buf, BUFSIZ)) > 0)
296: if (write(dst, buf, len) == -1) {
297: printf("Error:: in write backup #%d - %s\n",
298: errno, strerror(errno));
299: close(src);
300: close(dst);
301: unlink(szFile);
302:
303: len = -1;
304: break;
305: }
306:
307: close(src);
308: close(dst);
309:
310: if (!len) {
311: syslog(LOG_NOTICE, "Export tFTP image %s to %s", csImg, psDir);
312: VERB(1) printf("Export tFTP image %s to %s\n", csImg, psDir);
313: }
314: return len;
315: }
316:
317: int Backup(const char *csImg)
318: {
319: int src, dst, len;
320: u_char buf[BUFSIZ];
321: char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
322:
323: if (ChkImg(csImg, szDir) == -1)
324: return -1;
325:
326: getcwd(szFile, MAXPATHLEN);
327: strlcat(szFile, "/", MAXPATHLEN);
328: strlcat(szFile, FIRMWARE_BAK, MAXPATHLEN);
329: VERB(3) printf("Backup procedure for %s\n", szDir);
330:
331: dst = open(szFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
332: if (dst == -1) {
333: printf("Error:: in create backup %s #%d - %s\n",
334: szFile, errno, strerror(errno));
335: return -1;
336: }
337: src = open(szDir, O_RDONLY);
338: if (src == -1) {
339: printf("Error:: in open image %s #%d - %s\n",
340: szDir, errno, strerror(errno));
341: close(dst);
342: unlink(szFile);
343: return -1;
344: }
345:
346: while ((len = read(src, buf, BUFSIZ)) > 0)
347: if (write(dst, buf, len) == -1) {
348: printf("Error:: in write backup #%d - %s\n",
349: errno, strerror(errno));
350: close(src);
351: close(dst);
352: unlink(szFile);
353:
354: len = -1;
355: break;
356: }
357:
358: close(src);
359: close(dst);
360:
361: if (!len) {
362: syslog(LOG_NOTICE, "Backup image %s", csImg);
363: VERB(1) printf("Backup image %s\n", csImg);
364: }
365: return len;
366: }
367:
368: int Clean(const char *csImg)
369: {
370: char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
371:
372: if (ChkImg(csImg, szDir) == -1)
373: return -1;
374:
375: getcwd(szFile, MAXPATHLEN);
376: strlcat(szFile, "/", MAXPATHLEN);
377: strlcat(szFile, FIRMWARE_BAK, MAXPATHLEN);
378:
379: VERB(3) printf("Clean procedure for %s\n", szDir);
380:
381: if (unlink(szFile) == -1) {
382: printf("Error:: in clean backup #%d - %s\n", errno, strerror(errno));
383: return -1;
384: }
385:
386: syslog(LOG_NOTICE, "Clean backup for image %s", csImg);
387: VERB(1) printf("Clean backup for image %s\n", csImg);
388: return 0;
389: }
390:
391: // ----------------------------------
392:
393: static void Signal(int sig)
394: {
395: int stat;
396:
397: switch (sig) {
398: case SIGHUP:
399: VERB(5) printf("Info(5):: Signal arrived #%d\n", sig);
400: break;
401: case SIGCHLD:
402: while (waitpid(-1, &stat, WNOHANG) > 0);
403: break;
404: case SIGTERM:
405: Kill = 1;
406: VERB(5) printf("Info(5):: Signal arrived #%d\n", sig);
407: break;
408: }
409: }
410:
411: int Daemonize(struct sockaddr_in sin, const char *csTFTP)
412: {
413: int s, n = 1;
414: pid_t pid;
415: fd_set rfd;
416: u_short seq = 0xffff;
417: int clilen, len, f, retry;
418: struct sockaddr_in cli, rcv;
419: struct sigaction sa;
420: u_char buf[TFTP_BUF], *pos;
421: char szFName[MAX_STR];
422: struct tftphdr *tftp = (struct tftphdr*) buf;
423: struct timeval tv = { TFTP_TIMEOUT, 0 };
424:
425: VERB(3) printf("Daemonize procedure for %s:%d to %s\n",
426: inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), csTFTP);
427:
428: memset(&sa, 0, sizeof sa);
429: sigemptyset(&sa.sa_mask);
430: sa.sa_handler = Signal;
431: sigaction(SIGCHLD, &sa, NULL);
432: sigaction(SIGTERM, &sa, NULL);
433: sigaction(SIGHUP, &sa, NULL);
434:
435: s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
436: if (s == -1) {
437: printf("Error:: in create socket #%d - %s\n", errno, strerror(errno));
438: return -1;
439: }
440: if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n) == -1) {
441: printf("Error:: in socket options #%d - %s\n", errno, strerror(errno));
442: close(s);
443: return -1;
444: }
445: if (bind(s, (struct sockaddr*) &sin, sizeof sin) == -1) {
446: printf("Error:: in bind #%d - %s\n", errno, strerror(errno));
447: close(s);
448: return -1;
449: }
450:
451: switch ((pid = fork())) {
452: case -1:
453: printf("Error:: in socket options #%d - %s\n", errno, strerror(errno));
454: close(s);
455: return -1;
456: case 0:
457: setsid();
458:
459: while (!Kill) {
460: FD_ZERO(&rfd);
461: FD_SET(s, &rfd);
462: if (select(s + 1, &rfd, NULL, NULL, NULL) == -1)
463: continue;
464:
465: memset(buf, 0, TFTP_BUF);
466: clilen = sizeof cli;
467: len = recvfrom(s, buf, TFTP_BUF, 0, (struct sockaddr*) &cli,
468: (socklen_t*) &clilen);
469: if (len == -1) {
470: VERB(5) printf("Error:: in recvfrom #%d - %s\n",
471: errno, strerror(errno));
472: continue;
473: }
474:
475: tftp = (struct tftphdr*) (pos = buf);
476: VERB(5) printf("Info(5):: Received packet from %s len %d with opcode=%hd\n",
477: inet_ntoa(cli.sin_addr), len, ntohs(tftp->th_opcode));
478: switch (ntohs(tftp->th_opcode)) {
479: case WRQ:
480: len -= 2;
481: pos += 2;
482: strlcpy(szFName, (char*) pos, MAX_STR);
483: VERB(5) printf("Info(5):: Get filename %s\n", szFName);
484: len -= strlen((char*) pos) + 1;
485: pos += strlen((char*) pos) + 1;
486: VERB(5) printf("Info(5):: Get mode %s len=%d\n", pos, len);
487: if (strncmp((char*) pos, "octet", len)) {
488: memset(buf, 0, TFTP_BUF);
489: tftp->th_opcode = htons(ERROR);
490: tftp->th_code = htons(EBADOP);
491: strncpy(tftp->th_data, "Error:: mode not supported", 27);
492: sendto(s, buf, 31, 0, (struct sockaddr*) &cli, sizeof cli);
493: continue;
494: }
495: VERB(2) printf("Info(2):: Receive file %s from %s\n",
496: szFName, inet_ntoa(cli.sin_addr));
497:
498: f = open(szFName, O_WRONLY | O_CREAT | O_EXCL, 0644);
499: if (f == -1) {
500: memset(buf, 0, TFTP_BUF);
501: tftp->th_opcode = htons(ERROR);
502: switch (errno) {
503: case EACCES:
504: case EPERM:
505: tftp->th_code = htons(EACCESS);
506: break;
507: case EEXIST:
508: tftp->th_code = htons(EEXISTS);
509: break;
510: default:
511: tftp->th_code = htons(ENOSPACE);
512: }
513: snprintf(tftp->th_data, STRSIZ, "Error:: in file %s",
514: strerror(errno));
515: sendto(s, buf, strlen(tftp->th_data) + 4, 0,
516: (struct sockaddr*) &cli, sizeof cli);
517: continue;
518: }
519:
520: memset(buf, 0, TFTP_BUF);
521: tftp->th_opcode = htons(ACK);
522: tftp->th_block = seq = 0;
523: sendto(s, tftp, 4, 0, (struct sockaddr*) &cli, sizeof cli);
524:
525: for (retry = TFTP_RETRY; retry;) {
526: FD_ZERO(&rfd);
527: FD_SET(s, &rfd);
528: if (select(s + 1, &rfd, NULL, NULL, &tv) < 1) {
529: retry--;
530: continue;
531: }
532: memset(buf, 0, TFTP_BUF);
533: clilen = sizeof sin;
534: if ((len = recvfrom(s, buf, TFTP_BUF, 0,
535: (struct sockaddr*) &rcv,
536: (socklen_t*) &clilen)) == -1) {
537: VERB(5) printf("Error:: in recvfrom #%d - %s\n",
538: errno, strerror(errno));
539: retry--;
540: continue;
541: } else
542: if (cli.sin_addr.s_addr != rcv.sin_addr.s_addr)
543: continue;
544:
545: VERB(5) printf("Info(5):: received opcode=%d block=%d seq=%d\n",
546: ntohs(tftp->th_opcode), ntohs(tftp->th_block), seq);
547: if (ERROR == ntohs(tftp->th_opcode)) {
548: syslog(LOG_ERR, "Error:: in tftp receiving #%d - %s",
549: tftp->th_code, tftp->th_data);
550: close(f);
551: unlink(szFName);
552: break;
553: }
554: if (DATA == ntohs(tftp->th_opcode) &&
555: ++seq == ntohs(tftp->th_block)) {
556: if (write(f, tftp->th_data, len - 4) == -1) {
557: syslog(LOG_ERR, "Error:: Can`t write to file %s\n",
558: szFName);
559: close(f);
560: unlink(szFName);
561: break;
562: }
563:
564: memset(buf, 0, TFTP_BUF);
565: tftp->th_opcode = htons(ACK);
566: tftp->th_block = htons(seq);
567: sendto(s, tftp, 4, 0, (struct sockaddr*) &rcv, sizeof rcv);
568: VERB(5) printf("Info(5):: Send ACK for %s block=%d\n",
569: inet_ntoa(cli.sin_addr), seq);
570:
571: if (SEGSIZE > len - 4) {
572: close(f);
573: syslog(LOG_INFO, "TFTP transfer complete to %s",
574: szFName);
575: break;
576: }
577: } else {
578: memset(buf, 0, TFTP_BUF);
579: tftp->th_opcode = htons(ERROR);
580: tftp->th_code = htons(EBADID);
581: snprintf(tftp->th_data, STRSIZ, "Error:: in transfer #%d",
582: seq);
583: sendto(s, buf, strlen(tftp->th_data) + 4, 0,
584: (struct sockaddr*) &cli, sizeof cli);
585: retry--;
586: }
587: }
588: if (!retry) {
589: close(f);
590: unlink(szFName);
591: syslog(LOG_ERR, "Error:: transfer aborted - timeout!");
592: }
593:
594: break;
595: case RRQ:
596: len -= 2;
597: pos += 2;
598: strlcpy(szFName, (char*) pos, MAX_STR);
599: VERB(5) printf("Info(5):: Get filename %s\n", szFName);
600: len -= strlen((char*) pos) + 1;
601: pos += strlen((char*) pos) + 1;
602: VERB(5) printf("Info(5):: Get mode %s len=%d\n", pos, len);
603: if (strncmp((char*) pos, "octet", len)) {
604: memset(buf, 0, TFTP_BUF);
605: tftp->th_opcode = htons(ERROR);
606: tftp->th_code = htons(EBADOP);
607: strncpy(tftp->th_data, "Error:: mode not supported", 27);
608: sendto(s, buf, 31, 0, (struct sockaddr*) &cli, sizeof cli);
609: continue;
610: }
611: VERB(2) printf("Info(2):: Send file %s to %s\n",
612: szFName, inet_ntoa(cli.sin_addr));
613:
614: f = open(szFName, O_RDONLY);
615: if (f == -1) {
616: memset(buf, 0, TFTP_BUF);
617: tftp->th_opcode = htons(ERROR);
618: switch (errno) {
619: case EACCES:
620: case EPERM:
621: tftp->th_code = htons(EACCESS);
622: break;
623: case ENOENT:
624: tftp->th_code = htons(ENOTFOUND);
625: break;
626: default:
627: tftp->th_code = htons(ENOSPACE);
628: }
629: snprintf(tftp->th_data, STRSIZ, "Error:: in file %s",
630: strerror(errno));
631: sendto(s, buf, strlen(tftp->th_data) + 4, 0,
632: (struct sockaddr*) &cli, sizeof cli);
633: continue;
634: } else
635: seq = 1;
636:
637: for (retry = TFTP_RETRY; retry;) {
638: tftp->th_opcode = htons(DATA);
639: tftp->th_block = htons(seq);
640: if ((len = read(f, tftp->th_data, SEGSIZE)) == -1) {
641: syslog(LOG_ERR, "Error:: Can`t read from file %s\n",
642: szFName);
643: close(f);
644: break;
645: } else
646: sendto(s, buf, len + 4, 0,
647: (struct sockaddr*) &cli, sizeof cli);
648:
649: FD_ZERO(&rfd);
650: FD_SET(s, &rfd);
651: if (select(s + 1, &rfd, NULL, NULL, &tv) < 1) {
652: retry--;
653: continue;
654: }
655: memset(buf, 0, TFTP_BUF);
656: clilen = sizeof sin;
657: if (recvfrom(s, buf, TFTP_BUF, 0, (struct sockaddr*) &rcv,
658: (socklen_t*) &clilen) == -1) {
659: VERB(5) printf("Error:: in recvfrom #%d - %s\n",
660: errno, strerror(errno));
661: retry--;
662: continue;
663: } else
664: if (cli.sin_addr.s_addr != rcv.sin_addr.s_addr)
665: continue;
666:
667: VERB(5) printf("Info(5):: received opcode=%d block=%d seq=%d\n",
668: ntohs(tftp->th_opcode), ntohs(tftp->th_block), seq);
669: if (ERROR == ntohs(tftp->th_opcode)) {
670: syslog(LOG_ERR, "Error:: in tftp sending #%d - %s",
671: tftp->th_code, tftp->th_data);
672: if (lseek(f, len * -1, SEEK_CUR) == -1) {
673: syslog(LOG_ERR, "Error:: revert sending #%d - %s",
674: errno, strerror(errno));
675: close(f);
676: break;
677: }
678: retry--;
679: continue;
680: }
681: if (ACK == ntohs(tftp->th_opcode) &&
682: seq == ntohs(tftp->th_block)) {
683: seq++;
684: if (SEGSIZE > len) {
685: close(f);
686: syslog(LOG_INFO, "TFTP transfer complete to %s",
687: szFName);
688: break;
689: }
690: } else {
691: memset(buf, 0, TFTP_BUF);
692: tftp->th_opcode = htons(ERROR);
693: tftp->th_code = htons(EBADID);
694: snprintf(tftp->th_data, STRSIZ, "Error:: in transfer #%d",
695: seq);
696: sendto(s, buf, strlen(tftp->th_data) + 4, 0,
697: (struct sockaddr*) &cli, sizeof cli);
698: retry--;
699: }
700: }
701: if (!retry) {
702: close(f);
703: syslog(LOG_ERR, "Error:: transfer aborted - timeout!");
704: }
705:
706: break;
707: case DATA:
708: if (seq == 0xffff)
709: VERB(5) printf("Error:: not specified operation!\n");
710: break;
711: }
712: }
713:
714: break;
715: }
716:
717:
718: close(s);
719: return 0;
720: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>