Annotation of qemu/roms/SLOF/clients/net-snk/app/netlib/tftp.c, revision 1.1

1.1     ! root        1: /******************************************************************************
        !             2:  * Copyright (c) 2004, 2008 IBM Corporation
        !             3:  * All rights reserved.
        !             4:  * This program and the accompanying materials
        !             5:  * are made available under the terms of the BSD License
        !             6:  * which accompanies this distribution, and is available at
        !             7:  * http://www.opensource.org/licenses/bsd-license.php
        !             8:  *
        !             9:  * Contributors:
        !            10:  *     IBM Corporation - initial implementation
        !            11:  *****************************************************************************/
        !            12: 
        !            13: #include <tftp.h>
        !            14: #include <stdio.h>
        !            15: #include <stdlib.h>
        !            16: #include <string.h>
        !            17: #include <time.h>
        !            18: #include <sys/socket.h>
        !            19: 
        !            20: #include <ethernet.h>
        !            21: #include <ipv4.h>
        !            22: //#include <ipv6.h>
        !            23: #include <udp.h>
        !            24: 
        !            25: //#define __DEBUG__
        !            26: 
        !            27: #define MAX_BLOCKSIZE 1428
        !            28: #define BUFFER_LEN 2048
        !            29: #define ACK_BUFFER_LEN 256
        !            30: #define READ_BUFFER_LEN 256
        !            31: 
        !            32: #define ENOTFOUND 1
        !            33: #define EACCESS   2
        !            34: #define EBADOP    4
        !            35: #define EBADID    5
        !            36: #define ENOUSER   7
        !            37: //#define EUNDEF 0
        !            38: //#define ENOSPACE 3
        !            39: //#define EEXISTS 6
        !            40: 
        !            41: #define RRQ   1
        !            42: #define WRQ   2
        !            43: #define DATA  3
        !            44: #define ACK   4
        !            45: #define ERROR 5
        !            46: #define OACK  6
        !            47: 
        !            48: /* Local variables */
        !            49: static unsigned char  *buffer = NULL;
        !            50: static unsigned short block = 0;
        !            51: static unsigned short blocksize;
        !            52: static char blocksize_str[6];    /* Blocksize string for read request */
        !            53: static int received_len = 0;
        !            54: static int retries = 0;
        !            55: static int huge_load;
        !            56: static int len;
        !            57: static int tftp_finished = 0;
        !            58: static int lost_packets = 0;
        !            59: static int tftp_errno = 0; 
        !            60: static int ip_version = 0; 
        !            61: static short port_number = -1;
        !            62: static tftp_err_t *tftp_err;
        !            63: static filename_ip_t  *fn_ip;
        !            64: 
        !            65: /**
        !            66:  * dump_package - Prints a package.
        !            67:  *
        !            68:  * @package: package which is to print
        !            69:  * @len:     length of the package
        !            70:  */
        !            71: #ifdef __DEBUG__
        !            72: 
        !            73: static void
        !            74: dump_package(unsigned char *buffer, unsigned int len)
        !            75: {
        !            76:        int i;
        !            77: 
        !            78:        for (i = 1; i <= len; i++) {
        !            79:                printf("%02x%02x ", buffer[i - 1], buffer[i]);
        !            80:                i++;
        !            81:                if ((i % 16) == 0)
        !            82:                        printf("\n");
        !            83:        }
        !            84:        printf("\n");
        !            85: }
        !            86: #endif
        !            87: 
        !            88: /**
        !            89:  * send_rrq - Sends a read request package.
        !            90:  */
        !            91: static void
        !            92: send_rrq(void)
        !            93: {
        !            94:        int ip_len = 0;
        !            95:        //int ip6_payload_len    = 0;
        !            96:        unsigned short udp_len = 0;
        !            97:        unsigned char mode[] = "octet";
        !            98:        unsigned char packet[READ_BUFFER_LEN];
        !            99:        char *ptr            = NULL;
        !           100:        struct iphdr *ip     = NULL;
        !           101:        //struct ip6hdr *ip6   = NULL;
        !           102:        struct udphdr *udph  = NULL;
        !           103:        struct tftphdr *tftp = NULL;
        !           104: 
        !           105:        memset(packet, 0, READ_BUFFER_LEN);
        !           106: 
        !           107:        if (4 == ip_version) {
        !           108:                ip = (struct iphdr *) packet;
        !           109:                udph = (struct udphdr *) (ip + 1);
        !           110:                ip_len = sizeof(struct iphdr) + sizeof(struct udphdr)
        !           111:                        + strlen((char *) fn_ip->filename) + strlen((char *) mode) + 4
        !           112:                        + strlen("blksize") + strlen(blocksize_str) + 2;
        !           113:                fill_iphdr ((uint8_t *) ip, ip_len, IPTYPE_UDP, 0,
        !           114:                            fn_ip->server_ip);
        !           115:        }
        !           116: /*
        !           117:        else if (6 == ip_version) {
        !           118:                ip6 = (struct ip6hdr *) packet;
        !           119:                udph = (struct udphdr *) (ip6 + 1);
        !           120:                ip6_payload_len = sizeof(struct udphdr)
        !           121:                        + strlen((char *) fn_ip->filename) + strlen((char *) mode) + 4
        !           122:                        + strlen("blksize") + strlen(blocksize_str) + 2;
        !           123:                ip_len = sizeof(struct ip6hdr) + ip6_payload_len;
        !           124:                fill_ip6hdr ((uint8_t *) ip6, ip6_payload_len, IPTYPE_UDP, get_ipv6_address(),
        !           125:                             &(fn_ip->server_ip6)); 
        !           126: 
        !           127:        }
        !           128: */
        !           129:        udp_len = htons(sizeof(struct udphdr)
        !           130:                              + strlen((char *) fn_ip->filename) + strlen((char *) mode) + 4
        !           131:                              + strlen("blksize") + strlen(blocksize_str) + 2);
        !           132:        fill_udphdr ((uint8_t *) udph, udp_len, htons(2001), htons(69));
        !           133: 
        !           134:        tftp = (struct tftphdr *) (udph + 1);
        !           135:        tftp->th_opcode = htons(RRQ);
        !           136: 
        !           137:        ptr = (char *) &tftp->th_data;
        !           138:        memcpy(ptr, fn_ip->filename, strlen((char *) fn_ip->filename) + 1);
        !           139: 
        !           140:        ptr += strlen((char *) fn_ip->filename) + 1;
        !           141:        memcpy(ptr, mode, strlen((char *) mode) + 1);
        !           142: 
        !           143:        ptr += strlen((char *) mode) + 1;
        !           144:        memcpy(ptr, "blksize", strlen("blksize") + 1);
        !           145: 
        !           146:        ptr += strlen("blksize") + 1;
        !           147:        memcpy(ptr, blocksize_str, strlen(blocksize_str) + 1);
        !           148: 
        !           149:        send_ip (packet, ip_len);
        !           150: 
        !           151: #ifdef __DEBUG__
        !           152:        printf("tftp RRQ with %d bytes transmitted.\n", ip_len);
        !           153: #endif
        !           154:        return;
        !           155: }
        !           156: 
        !           157: /**
        !           158:  * send_ack - Sends a acknowlege package.
        !           159:  *
        !           160:  * @blckno: block number
        !           161:  * @dport:  UDP destination port
        !           162:  */
        !           163: static void
        !           164: send_ack(int blckno, unsigned short dport)
        !           165: {
        !           166:        int ip_len             = 0;
        !           167:        //int ip6_payload_len    = 0;
        !           168:        unsigned short udp_len = 0;
        !           169:        unsigned char packet[ACK_BUFFER_LEN];
        !           170:        struct iphdr *ip     = NULL;
        !           171:        //struct ip6hdr *ip6   = NULL;
        !           172:        struct udphdr *udph  = NULL;
        !           173:        struct tftphdr *tftp = NULL;
        !           174: 
        !           175:        memset(packet, 0, ACK_BUFFER_LEN);
        !           176: 
        !           177:        if (4 == ip_version) {
        !           178:                ip = (struct iphdr *) packet;
        !           179:                udph = (struct udphdr *) (ip + 1);
        !           180:                ip_len = sizeof(struct iphdr) + sizeof(struct udphdr) + 4;
        !           181:                fill_iphdr ((uint8_t *) ip, ip_len, IPTYPE_UDP, 0,
        !           182:                            fn_ip->server_ip);
        !           183:        }
        !           184: /*
        !           185:        else if (6 == ip_version) {
        !           186:                ip6 = (struct ip6hdr *) packet;
        !           187:                udph = (struct udphdr *) (ip6 + 1);
        !           188:                ip6_payload_len = sizeof(struct udphdr) + 4;
        !           189:                ip_len = sizeof(struct ethhdr) + sizeof(struct ip6hdr) +
        !           190:                         ip6_payload_len;
        !           191:                fill_ip6hdr ((uint8_t *) ip6, ip6_payload_len, IPTYPE_UDP, get_ipv6_address(),
        !           192:                             &(fn_ip->server_ip6));
        !           193:        }
        !           194: */
        !           195:        udp_len = htons(sizeof(struct udphdr) + 4);
        !           196:        fill_udphdr ((uint8_t *) udph, udp_len, htons(2001), htons(dport));
        !           197: 
        !           198:        tftp = (struct tftphdr *) (udph + 1);
        !           199:        tftp->th_opcode = htons(ACK);
        !           200:        tftp->th_data = htons(blckno);
        !           201: 
        !           202:        send_ip(packet, ip_len);
        !           203: 
        !           204: #ifdef __DEBUG__
        !           205:        printf("tftp ACK %d bytes transmitted.\n", ip_len);
        !           206: #endif
        !           207: 
        !           208:        return;
        !           209: }
        !           210: 
        !           211: /**
        !           212:  * send_error - Sends an error package.
        !           213:  *
        !           214:  * @error_code:  Used sub code for error packet
        !           215:  * @dport:       UDP destination port
        !           216:  */
        !           217: static void
        !           218: send_error(int error_code, unsigned short dport)
        !           219: {
        !           220:        int ip_len             = 0;
        !           221:        //int ip6_payload_len    = 0;
        !           222:        unsigned short udp_len = 0;
        !           223:        unsigned char packet[256];
        !           224:        //struct ip6hdr *ip6   = NULL;
        !           225:        struct iphdr *ip     = NULL;
        !           226:        struct udphdr *udph  = NULL;
        !           227:        struct tftphdr *tftp = NULL;
        !           228: 
        !           229:        memset(packet, 0, 256);
        !           230: 
        !           231:        if (4 == ip_version) {
        !           232:                ip = (struct iphdr *) packet;
        !           233:                udph = (struct udphdr *) (ip + 1);
        !           234:                ip_len = sizeof(struct iphdr) + sizeof(struct udphdr) + 5;
        !           235:                fill_iphdr ((uint8_t *) ip, ip_len, IPTYPE_UDP, 0,
        !           236:                            fn_ip->server_ip);
        !           237:        }
        !           238: /*
        !           239:        else if (6 == ip_version) {
        !           240:                ip6 = (struct ip6hdr *) packet;
        !           241:                udph = (struct udphdr *) (ip6 + 1);
        !           242:                ip6_payload_len = sizeof(struct udphdr) + 5;
        !           243:                ip_len = sizeof(struct ethhdr) + sizeof(struct ip6hdr) +
        !           244:                         ip6_payload_len; 
        !           245:                fill_ip6hdr ((uint8_t *) ip6, ip6_payload_len, IPTYPE_UDP, get_ipv6_address(),
        !           246:                            &(fn_ip->server_ip6));
        !           247:        }
        !           248: */
        !           249:        udp_len = htons(sizeof(struct udphdr) + 5);
        !           250:        fill_udphdr ((uint8_t *) udph, udp_len, htons(2001), htons(dport));
        !           251: 
        !           252:        tftp = (struct tftphdr *) (udph + 1);
        !           253:        tftp->th_opcode = htons(ERROR);
        !           254:        tftp->th_data = htons(error_code);
        !           255:        ((char *) &tftp->th_data)[2] = 0;
        !           256: 
        !           257:        send_ip(packet, ip_len);
        !           258: 
        !           259: #ifdef __DEBUG__
        !           260:        printf("tftp ERROR %d bytes transmitted.\n", ip_len);
        !           261: #endif
        !           262: 
        !           263:        return;
        !           264: }
        !           265: 
        !           266: static void
        !           267: print_progress(int urgent, int received_bytes)
        !           268: {
        !           269:        static unsigned int i = 1;
        !           270:        static int first = -1;
        !           271:        static int last_bytes = 0;
        !           272:        char buffer[100];
        !           273:        char *ptr;
        !           274: 
        !           275:        // 1MB steps or 0x400 times or urgent 
        !           276:        if(((received_bytes - last_bytes) >> 20) > 0
        !           277:        || (i & 0x3FF) == 0 || urgent) {
        !           278:                if(!first) {
        !           279:                        sprintf(buffer, "%d KBytes", (last_bytes >> 10));
        !           280:                        for(ptr = buffer; *ptr != 0; ++ptr)
        !           281:                                *ptr = '\b';
        !           282:                        printf(buffer);
        !           283:                }
        !           284:                printf("%d KBytes", (received_bytes >> 10));
        !           285:                i = 1;
        !           286:                first = 0;
        !           287:                last_bytes = received_bytes;
        !           288:        }
        !           289:        ++i;
        !           290: }
        !           291: 
        !           292: /**
        !           293:  * get_blksize tries to extract the blksize from the OACK package
        !           294:  * the TFTP returned. From RFC 1782
        !           295:  * The OACK packet has the following format:
        !           296:  *
        !           297:  *   +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
        !           298:  *   |  opc  |  opt1  | 0 | value1 | 0 |  optN  | 0 | valueN | 0 |
        !           299:  *   +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
        !           300:  *
        !           301:  * @param buffer  the network packet
        !           302:  * @param len  the length of the network packet
        !           303:  * @return  the blocksize the server supports or 0 for error
        !           304:  */
        !           305: static int
        !           306: get_blksize(unsigned char *buffer, unsigned int len)
        !           307: {
        !           308:        unsigned char *orig = buffer;
        !           309:        /* skip all headers until tftp has been reached */
        !           310:        buffer += sizeof(struct udphdr);
        !           311:        /* skip opc */
        !           312:        buffer += 2;
        !           313:        while (buffer < orig + len) {
        !           314:                if (!memcmp(buffer, "blksize", strlen("blksize") + 1))
        !           315:                        return (unsigned short) strtoul((char *) (buffer +
        !           316:                                                        strlen("blksize") + 1),
        !           317:                                                        (char **) NULL, 10);
        !           318:                else {
        !           319:                        /* skip the option name */
        !           320:                        buffer = (unsigned char *) strchr((char *) buffer, 0);
        !           321:                        if (!buffer)
        !           322:                                return 0;
        !           323:                        buffer++;
        !           324:                        /* skip the option value */
        !           325:                        buffer = (unsigned char *) strchr((char *) buffer, 0);
        !           326:                        if (!buffer)
        !           327:                                return 0;
        !           328:                        buffer++;
        !           329:                }
        !           330:        }
        !           331:        return 0;
        !           332: }
        !           333: 
        !           334: /**
        !           335:  * Handle incoming tftp packets after read request was sent 
        !           336:  *
        !           337:  * this function also prints out some status characters
        !           338:  * \|-/ for each packet received
        !           339:  * A for an arp packet
        !           340:  * I for an ICMP packet
        !           341:  * #+* for different unexpected TFTP packets (not very good)
        !           342:  *
        !           343:  * @param packet points to the UDP header of the packet 
        !           344:  * @param len    the length of the network packet
        !           345:  * @return       ZERO if packet was handled successfully
        !           346:  *               ERRORCODE if error occurred 
        !           347:  */
        !           348: int32_t
        !           349: handle_tftp(uint8_t *packet, int32_t packetsize) 
        !           350: {
        !           351:        struct udphdr *udph;
        !           352:        struct tftphdr *tftp;
        !           353: 
        !           354:        /* buffer is only set if we are handling TFTP */
        !           355:        if (buffer == NULL )
        !           356:                return 0;
        !           357: 
        !           358: #ifndef __DEBUG__
        !           359:        print_progress(0, received_len);
        !           360: #endif
        !           361:        udph = (struct udphdr *) packet;
        !           362:        tftp = (struct tftphdr *) ((void *) udph + sizeof(struct udphdr));
        !           363:        set_timer(TICKS_SEC);
        !           364: 
        !           365: #ifdef __DEBUG__
        !           366:        dump_package(packet, packetsize);
        !           367: #endif
        !           368: 
        !           369:        port_number = udph->uh_sport;
        !           370:        if (tftp->th_opcode == htons(OACK)) {
        !           371:                /* an OACK means that the server answers our blocksize request */
        !           372:                blocksize = get_blksize(packet, packetsize);
        !           373:                if (!blocksize || blocksize > MAX_BLOCKSIZE) {
        !           374:                        send_error(8, port_number);
        !           375:                        tftp_errno = -8;
        !           376:                        goto error;
        !           377:                }
        !           378:                send_ack(0, port_number);
        !           379:        } else if (tftp->th_opcode == htons(ACK)) {
        !           380:                /* an ACK means that the server did not answers
        !           381:                 * our blocksize request, therefore we will set the blocksize
        !           382:                 * to the default value of 512 */
        !           383:                blocksize = 512;
        !           384:                send_ack(0, port_number);
        !           385:        } else if ((unsigned char) tftp->th_opcode == ERROR) {
        !           386: #ifdef __DEBUG__
        !           387:                printf("tftp->th_opcode : %x\n", tftp->th_opcode);
        !           388:                printf("tftp->th_data   : %x\n", tftp->th_data);
        !           389: #endif
        !           390:                switch ( (uint8_t) tftp->th_data) {
        !           391:                case ENOTFOUND:
        !           392:                        tftp_errno = -3;        // ERROR: file not found
        !           393:                        break;
        !           394:                case EACCESS:
        !           395:                        tftp_errno = -4;        // ERROR: access violation
        !           396:                        break;
        !           397:                case EBADOP:
        !           398:                        tftp_errno = -5;        // ERROR: illegal TFTP operation
        !           399:                        break;
        !           400:                case EBADID:
        !           401:                        tftp_errno = -6;        // ERROR: unknown transfer ID
        !           402:                        break;
        !           403:                case ENOUSER:
        !           404:                        tftp_errno = -7;        // ERROR: no such user
        !           405:                        break;
        !           406:                default:        
        !           407:                        tftp_errno = -1;        // ERROR: unknown error
        !           408:                }
        !           409:                goto error;
        !           410:        } else if (tftp->th_opcode == DATA) {
        !           411:                /* DATA PACKAGE */
        !           412:                if (block + 1 == tftp->th_data) {
        !           413:                        ++block;
        !           414:                }
        !           415:                else if( block == 0xffff && huge_load != 0
        !           416:                     &&  (tftp->th_data == 0 || tftp->th_data == 1) ) {
        !           417:                        block = tftp->th_data;
        !           418:                }
        !           419:                else if (tftp->th_data == block) {
        !           420: #ifdef __DEBUG__
        !           421:                        printf
        !           422:                            ("\nTFTP: Received block %x, expected block was %x\n",
        !           423:                             tftp->th_data, block + 1);
        !           424:                        printf("\b+ ");
        !           425: #endif
        !           426:                        send_ack(tftp->th_data, port_number);
        !           427:                        lost_packets++;
        !           428:                        tftp_err->bad_tftp_packets++;
        !           429:                        return 0;
        !           430:                } else if (tftp->th_data < block) {
        !           431: #ifdef __DEBUG__
        !           432:                        printf
        !           433:                            ("\nTFTP: Received block %x, expected block was %x\n",
        !           434:                             tftp->th_data, block + 1);
        !           435:                        printf("\b* ");
        !           436: #endif
        !           437:                        /* This means that an old data packet appears (again);
        !           438:                         * this happens sometimes if we don't answer fast enough
        !           439:                         * and a timeout is generated on the server side;
        !           440:                         * as we already have this packet we just ignore it */
        !           441:                        tftp_err->bad_tftp_packets++;
        !           442:                        return 0;
        !           443:                } else {
        !           444:                        tftp_err->blocks_missed = block + 1;
        !           445:                        tftp_err->blocks_received = tftp->th_data;
        !           446:                        tftp_errno = -42;
        !           447:                        goto error;
        !           448:                }
        !           449:                tftp_err->bad_tftp_packets = 0;
        !           450:                /* check if our buffer is large enough */
        !           451:                if (received_len + udph->uh_ulen - 12 > len) {
        !           452:                        tftp_errno = -2;
        !           453:                        goto error;
        !           454:                }
        !           455:                memcpy(buffer + received_len, &tftp->th_data + 1,
        !           456:                       udph->uh_ulen - 12);
        !           457:                send_ack(tftp->th_data, port_number);
        !           458:                received_len += udph->uh_ulen - 12;
        !           459:                /* Last packet reached if the payload of the UDP packet
        !           460:                 * is smaller than blocksize + 12
        !           461:                 * 12 = UDP header (8) + 4 bytes TFTP payload */
        !           462:                if (udph->uh_ulen < blocksize + 12) {
        !           463:                        tftp_finished = 1;
        !           464:                        return 0;
        !           465:                }
        !           466:                /* 0xffff is the highest block number possible
        !           467:                 * see the TFTP RFCs */
        !           468: 
        !           469:                if (block >= 0xffff && huge_load == 0) {
        !           470:                        tftp_errno = -9;
        !           471:                        goto error;
        !           472:                }
        !           473:        } else {
        !           474: #ifdef __DEBUG__
        !           475:                printf("Unknown packet %x\n", tftp->th_opcode);
        !           476:                printf("\b# ");
        !           477: #endif
        !           478:                tftp_err->bad_tftp_packets++;
        !           479:                return 0;
        !           480:        }
        !           481: 
        !           482:        return 0;
        !           483: 
        !           484: error:
        !           485: #ifdef __DEBUG__
        !           486:        printf("\nTFTP errno: %d\n", tftp_errno);
        !           487: #endif
        !           488:        tftp_finished = 1;
        !           489:        return tftp_errno;
        !           490: }
        !           491: 
        !           492: /**
        !           493:  * TFTP: This function handles situation when "Destination unreachable"
        !           494:  *       ICMP-error occurs during sending TFTP-packet.
        !           495:  *
        !           496:  * @param  err_code   Error Code (e.g. "Host unreachable")
        !           497:  */
        !           498: void
        !           499: handle_tftp_dun(uint8_t err_code)
        !           500: {
        !           501:        tftp_errno = - err_code - 10;
        !           502:        tftp_finished = 1;
        !           503: }
        !           504: 
        !           505: /**
        !           506:  * TFTP: Interface function to load files via TFTP.
        !           507:  *
        !           508:  * @param  _fn_ip        contains the following configuration information:
        !           509:  *                       client IP, TFTP-server IP, filename to be loaded
        !           510:  * @param  _buffer       destination buffer for the file
        !           511:  * @param  _len          size of destination buffer
        !           512:  * @param  _retries      max number of retries
        !           513:  * @param  _tftp_err     contains info about TFTP-errors (e.g. lost packets)
        !           514:  * @param  _mode         NON ZERO - multicast, ZERO - unicast
        !           515:  * @param  _blocksize    blocksize for DATA-packets
        !           516:  * @return               ZERO - error condition occurs
        !           517:  *                       NON ZERO - size of received file
        !           518:  */
        !           519: int
        !           520: tftp(filename_ip_t * _fn_ip, unsigned char *_buffer, int _len,
        !           521:      unsigned int _retries, tftp_err_t * _tftp_err,
        !           522:      int32_t _mode, int32_t _blocksize, int _ip_version)
        !           523: {
        !           524:        retries     = _retries;
        !           525:        fn_ip       = _fn_ip;
        !           526:        len         = _len;
        !           527:        huge_load   = _mode;
        !           528:        ip_version  = _ip_version;
        !           529:        tftp_errno  = 0;
        !           530:        tftp_err    = _tftp_err;
        !           531:        tftp_err->bad_tftp_packets = 0;
        !           532:        tftp_err->no_packets = 0;
        !           533: 
        !           534:        /* Default blocksize must be 512 for TFTP servers
        !           535:         * which do not support the RRQ blocksize option */
        !           536:        blocksize = 512;
        !           537: 
        !           538:        /* Prefered blocksize - used as option for the read request */
        !           539:        if (_blocksize < 8)
        !           540:                _blocksize = 8;
        !           541:        else if (_blocksize > MAX_BLOCKSIZE)
        !           542:                _blocksize = MAX_BLOCKSIZE;
        !           543:        sprintf(blocksize_str, "%d", _blocksize);
        !           544: 
        !           545:        printf("  Receiving data:  ");
        !           546:        print_progress(-1, 0);
        !           547: 
        !           548:        // Setting buffer to a non-zero address enabled handling of received TFTP packets.
        !           549:        buffer = _buffer;
        !           550: 
        !           551:        set_timer(TICKS_SEC);
        !           552:        send_rrq();
        !           553: 
        !           554:        while (! tftp_finished) {
        !           555:                /* if timeout (no packet received) */
        !           556:                if(get_timer() <= 0) {
        !           557:                        /* the server doesn't seem to retry let's help out a bit */
        !           558:                        if (tftp_err->no_packets > 4 && port_number != -1
        !           559:                                && block > 1)
        !           560:                                send_ack(block, port_number);
        !           561:                        tftp_err->no_packets++;
        !           562:                        set_timer(TICKS_SEC);
        !           563:                }
        !           564: 
        !           565:                /* handle received packets */
        !           566:                receive_ether();
        !           567: 
        !           568:                /* bad_tftp_packets are counted whenever we receive a TFTP packet
        !           569:                        * which was not expected; if this gets larger than 'retries'
        !           570:                        * we just exit */
        !           571:                if (tftp_err->bad_tftp_packets > retries) {
        !           572:                        tftp_errno = -40;
        !           573:                        break;
        !           574:                }
        !           575: 
        !           576:                /* no_packets counts the times we have returned from receive_ether()
        !           577:                        * without any packet received; if this gets larger than 'retries'
        !           578:                        * we also just exit */
        !           579:                if (tftp_err->no_packets > retries) {
        !           580:                        tftp_errno = -41;
        !           581:                        break;
        !           582:                }
        !           583:        }
        !           584: 
        !           585:        // Setting buffer to NULL disables handling of received TFTP packets.
        !           586:        buffer = NULL;
        !           587: 
        !           588:        if (tftp_errno)
        !           589:                return tftp_errno;
        !           590: 
        !           591:        print_progress(-1, received_len);
        !           592:        printf("\n");
        !           593:        if (lost_packets)
        !           594:                printf("Lost ACK packets: %d\n", lost_packets);
        !           595:                
        !           596:        return received_len;
        !           597: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.