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