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

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

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