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