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

1.2     ! misho       1: /*************************************************************************
        !             2:  * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
        !             3:  *  by Michael Pounov <misho@aitbg.com>
        !             4:  *
        !             5:  * $Author: misho $
        !             6:  * $Id: upd.c,v 1.1.2.10 2011/06/08 09:15:32 misho Exp $
        !             7:  *
        !             8:  *************************************************************************/
        !             9: #include "global.h"
        !            10: #include "upd.h"
        !            11: 
        !            12: 
        !            13: int Kill;
        !            14: 
        !            15: 
        !            16: static inline int ChkImg(const char *csImg, char *psDir)
        !            17: {
        !            18:        int res = 0;
        !            19: 
        !            20:        getcwd(psDir, MAXPATHLEN);
        !            21:        if (access(csImg, R_OK) == -1) {
        !            22:                printf("Error:: Unable to find new image %s #%d - %s\n", 
        !            23:                                csImg, errno, strerror(errno));
        !            24:                res = -1;
        !            25:        } else {
        !            26:                strlcat(psDir, "/", MAXPATHLEN);
        !            27:                strlcat(psDir, csImg, MAXPATHLEN);
        !            28:        }
        !            29: 
        !            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: 
        !            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);
        !            53:        return 0;
        !            54: }
        !            55: 
        !            56: int Install(const char *csImg, const char *psDir)
        !            57: {
        !            58:        int src, dst, len;
        !            59:        u_char buf[BUFSIZ];
        !            60:        char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
        !            61:        struct stat ss, ds;
        !            62: 
        !            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;
        !           130: }
        !           131: 
        !           132: int Rollback(const char *csImg)
        !           133: {
        !           134:        int src, dst, len;
        !           135:        u_char buf[BUFSIZ];
        !           136:        char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
        !           137:        struct stat ss, ds;
        !           138: 
        !           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));
        !           175:                return -1;
        !           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:        }
        !           184: 
        !           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;
        !           205: 
        !           206:        return 0;
        !           207: }
        !           208: 
        !           209: int tFTP(const char *csImg, const char *psDir)
        !           210: {
        !           211:        int src, dst, len;
        !           212:        u_char buf[BUFSIZ];
        !           213:        char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
        !           214:        struct stat ss, ds;
        !           215: 
        !           216:        if (ChkImg(csImg, szDir) == -1)
        !           217:                return -1;
        !           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:        }
        !           226: 
        !           227:        VERB(3) printf("tFTP procedure for %s to %s\n", szDir, psDir);
        !           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);
        !           265: 
        !           266:                        len = -1;
        !           267:                        break;
        !           268:                }
        !           269: 
        !           270:        close(src);
        !           271:        close(dst);
        !           272: 
        !           273:        if (!len) {
        !           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:        }
        !           277:        return len;
        !           278: }
        !           279: 
        !           280: int Backup(const char *csImg)
        !           281: {
        !           282:        int src, dst, len;
        !           283:        u_char buf[BUFSIZ];
        !           284:        char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
        !           285: 
        !           286:        if (ChkImg(csImg, szDir) == -1)
        !           287:                return -1;
        !           288: 
        !           289:        getcwd(szFile, MAXPATHLEN);
        !           290:        strlcat(szFile, "/", MAXPATHLEN);
        !           291:        strlcat(szFile, FIRMWARE_BAK, MAXPATHLEN);
        !           292:        VERB(3) printf("Backup procedure for %s\n", szDir);
        !           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);
        !           316: 
        !           317:                        len = -1;
        !           318:                        break;
        !           319:                }
        !           320: 
        !           321:        close(src);
        !           322:        close(dst);
        !           323: 
        !           324:        if (!len) {
        !           325:                syslog(LOG_NOTICE, "Backup image %s", csImg);
        !           326:                VERB(1) printf("Backup image %s\n", csImg);
        !           327:        }
        !           328:        return len;
        !           329: }
        !           330: 
        !           331: int Clean(const char *csImg)
        !           332: {
        !           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:        }
        !           348: 
        !           349:        syslog(LOG_NOTICE, "Clean backup for image %s", csImg);
        !           350:        VERB(1) printf("Clean backup for image %s\n", csImg);
        !           351:        return 0;
        !           352: }
        !           353: 
        !           354: // ----------------------------------
        !           355: 
        !           356: static void Signal(int sig)
        !           357: {
        !           358:        int stat;
        !           359: 
        !           360:        switch (sig) {
        !           361:                case SIGHUP:
        !           362:                        VERB(5) printf("Info(5):: Signal arrived #%d\n", sig);
        !           363:                        break;
        !           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: 
        !           374: int Daemonize(struct sockaddr_in sin, const char *csTFTP)
        !           375: {
        !           376:        int s, n = 1;
        !           377:        pid_t pid;
        !           378:        fd_set rfd;
        !           379:        u_short seq = 0xffff;
        !           380:        int clilen, len, f, retry;
        !           381:        struct sockaddr_in cli, rcv;
        !           382:        struct sigaction sa;
        !           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 };
        !           387: 
        !           388:        VERB(3) printf("Daemonize procedure for %s:%d to %s\n", 
        !           389:                        inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), csTFTP);
        !           390: 
        !           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);
        !           396:        sigaction(SIGHUP, &sa, NULL);
        !           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: 
        !           428:                                memset(buf, 0, TFTP_BUF);
        !           429:                                clilen = sizeof cli;
        !           430:                                len = recvfrom(s, buf, TFTP_BUF, 0, (struct sockaddr*) &cli, 
        !           431:                                                (socklen_t*) &clilen);
        !           432:                                if (len == -1) {
        !           433:                                        VERB(5) printf("Error:: in recvfrom #%d - %s\n", 
        !           434:                                                        errno, strerror(errno));
        !           435:                                        continue;
        !           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:                                                        snprintf(tftp->th_data, STRSIZ, "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:                                                                snprintf(tftp->th_data, STRSIZ, "Error:: in transfer #%d", 
        !           545:                                                                                seq);
        !           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:                                                        }
        !           592:                                                        snprintf(tftp->th_data, STRSIZ, "Error:: in file %s", 
        !           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);
        !           657:                                                                snprintf(tftp->th_data, STRSIZ, "Error:: in transfer #%d", 
        !           658:                                                                                seq);
        !           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:                                }
        !           675:                        }
        !           676: 
        !           677:                        break;
        !           678:        }
        !           679: 
        !           680: 
        !           681:        close(s);
        !           682:        return 0;
        !           683: }

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