Annotation of embedtools/src/upd.c, revision 1.1.2.9

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 $
        !             6:  * $Id: dpatch.c,v 1.1.2.1 2010/03/24 16:43:01 misho Exp $
        !             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:                                                        }
                    476:                                                        sprintf(tftp->th_data, "Error:: in file %s", 
                    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);
                    544:                                                                sprintf(tftp->th_data, "Error:: in transfer #%d", seq);
                    545:                                                                sendto(s, buf, strlen(tftp->th_data) + 4, 0, 
                    546:                                                                                (struct sockaddr*) &cli, sizeof cli);
                    547:                                                                retry--;
                    548:                                                        }
                    549:                                                }
                    550:                                                if (!retry) {
                    551:                                                        close(f);
                    552:                                                        unlink(szFName);
                    553:                                                        syslog(LOG_ERR, "Error:: transfer aborted - timeout!");
                    554:                                                }
                    555: 
                    556:                                                break;
                    557:                                        case RRQ:
                    558:                                                len -= 2;
                    559:                                                pos += 2;
                    560:                                                strlcpy(szFName, (char*) pos, MAX_STR);
                    561:                                                VERB(5) printf("Info(5):: Get filename %s\n", szFName);
                    562:                                                len -= strlen((char*) pos) + 1;
                    563:                                                pos += strlen((char*) pos) + 1;
                    564:                                                VERB(5) printf("Info(5):: Get mode %s len=%d\n", pos, len);
                    565:                                                if (strncmp((char*) pos, "octet", len)) {
                    566:                                                        memset(buf, 0, TFTP_BUF);
                    567:                                                        tftp->th_opcode = htons(ERROR);
                    568:                                                        tftp->th_code = htons(EBADOP);
                    569:                                                        strncpy(tftp->th_data, "Error:: mode not supported", 27);
                    570:                                                        sendto(s, buf, 31, 0, (struct sockaddr*) &cli, sizeof cli);
                    571:                                                        continue;
                    572:                                                }
                    573:                                                VERB(2) printf("Info(2):: Send file %s to %s\n", 
                    574:                                                                szFName, inet_ntoa(cli.sin_addr));
                    575: 
                    576:                                                f = open(szFName, O_RDONLY);
                    577:                                                if (f == -1) {
                    578:                                                        memset(buf, 0, TFTP_BUF);
                    579:                                                        tftp->th_opcode = htons(ERROR);
                    580:                                                        switch (errno) {
                    581:                                                                case EACCES:
                    582:                                                                case EPERM:
                    583:                                                                        tftp->th_code = htons(EACCESS);
                    584:                                                                        break;
                    585:                                                                case ENOENT:
                    586:                                                                        tftp->th_code = htons(ENOTFOUND);
                    587:                                                                        break;
                    588:                                                                default:
                    589:                                                                        tftp->th_code = htons(ENOSPACE);
                    590:                                                        }
                    591:                                                        sprintf(tftp->th_data, "Error:: in file %s", 
                    592:                                                                        strerror(errno));
                    593:                                                        sendto(s, buf, strlen(tftp->th_data) + 4, 0, 
                    594:                                                                        (struct sockaddr*) &cli, sizeof cli);
                    595:                                                        continue;
                    596:                                                } else
                    597:                                                        seq = 1;
                    598: 
                    599:                                                for (retry = TFTP_RETRY; retry;) {
                    600:                                                        tftp->th_opcode = htons(DATA);
                    601:                                                        tftp->th_block = htons(seq);
                    602:                                                        if ((len = read(f, tftp->th_data, SEGSIZE)) == -1) {
                    603:                                                                syslog(LOG_ERR, "Error:: Can`t read from file %s\n", 
                    604:                                                                                szFName);
                    605:                                                                close(f);
                    606:                                                                break;
                    607:                                                        } else
                    608:                                                                sendto(s, buf, len + 4, 0, 
                    609:                                                                                (struct sockaddr*) &cli, sizeof cli);
                    610: 
                    611:                                                        FD_ZERO(&rfd);
                    612:                                                        FD_SET(s, &rfd);
                    613:                                                        if (select(s + 1, &rfd, NULL, NULL, &tv) < 1) {
                    614:                                                                retry--;
                    615:                                                                continue;
                    616:                                                        }
                    617:                                                        memset(buf, 0, TFTP_BUF);
                    618:                                                        clilen = sizeof sin;
                    619:                                                        if (recvfrom(s, buf, TFTP_BUF, 0, (struct sockaddr*) &rcv, 
                    620:                                                                                (socklen_t*) &clilen) == -1) {
                    621:                                                                VERB(5) printf("Error:: in recvfrom #%d - %s\n", 
                    622:                                                                                errno, strerror(errno));
                    623:                                                                retry--;
                    624:                                                                continue;
                    625:                                                        } else
                    626:                                                                if (cli.sin_addr.s_addr != rcv.sin_addr.s_addr)
                    627:                                                                        continue;
                    628: 
                    629:                                                        VERB(5) printf("Info(5):: received opcode=%d block=%d seq=%d\n", 
                    630:                                                                        ntohs(tftp->th_opcode), ntohs(tftp->th_block), seq);
                    631:                                                        if (ERROR == ntohs(tftp->th_opcode)) {
                    632:                                                                syslog(LOG_ERR, "Error:: in tftp sending #%d - %s", 
                    633:                                                                                tftp->th_code, tftp->th_data);
                    634:                                                                if (lseek(f, len * -1, SEEK_CUR) == -1) {
                    635:                                                                        syslog(LOG_ERR, "Error:: revert sending #%d - %s", 
                    636:                                                                                        errno, strerror(errno));
                    637:                                                                        close(f);
                    638:                                                                        break;
                    639:                                                                }
                    640:                                                                retry--;
                    641:                                                                continue;
                    642:                                                        }
                    643:                                                        if (ACK == ntohs(tftp->th_opcode) && 
                    644:                                                                        seq == ntohs(tftp->th_block)) {
                    645:                                                                seq++;
                    646:                                                                if (SEGSIZE > len) {
                    647:                                                                        close(f);
                    648:                                                                        syslog(LOG_INFO, "TFTP transfer complete to %s", 
                    649:                                                                                        szFName);
                    650:                                                                        break;
                    651:                                                                }
                    652:                                                        } else {
                    653:                                                                memset(buf, 0, TFTP_BUF);
                    654:                                                                tftp->th_opcode = htons(ERROR);
                    655:                                                                tftp->th_code = htons(EBADID);
                    656:                                                                sprintf(tftp->th_data, "Error:: in transfer #%d", seq);
                    657:                                                                sendto(s, buf, strlen(tftp->th_data) + 4, 0, 
                    658:                                                                                (struct sockaddr*) &cli, sizeof cli);
                    659:                                                                retry--;
                    660:                                                        }
                    661:                                                }
                    662:                                                if (!retry) {
                    663:                                                        close(f);
                    664:                                                        syslog(LOG_ERR, "Error:: transfer aborted - timeout!");
                    665:                                                }
                    666: 
                    667:                                                break;
                    668:                                        case DATA:
                    669:                                                if (seq == 0xffff)
                    670:                                                        VERB(5) printf("Error:: not specified operation!\n");
                    671:                                                break;
                    672:                                }
1.1.2.7   misho     673:                        }
                    674: 
                    675:                        break;
                    676:        }
                    677: 
                    678: 
                    679:        close(s);
1.1.2.6   misho     680:        return 0;
                    681: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>