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

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
1.1.1.2 ! root      559:                            && block > 1) {
1.1       root      560:                                send_ack(block, port_number);
1.1.1.2 ! root      561:                        }
        !           562:                        else if (port_number == -1 && block == 0
        !           563:                                 && (tftp_err->no_packets&3) == 3) {
        !           564:                                printf("\nRepeating TFTP read request...\n");
        !           565:                                send_rrq();
        !           566:                        }
1.1       root      567:                        tftp_err->no_packets++;
                    568:                        set_timer(TICKS_SEC);
                    569:                }
                    570: 
                    571:                /* handle received packets */
                    572:                receive_ether();
                    573: 
                    574:                /* bad_tftp_packets are counted whenever we receive a TFTP packet
                    575:                        * which was not expected; if this gets larger than 'retries'
                    576:                        * we just exit */
                    577:                if (tftp_err->bad_tftp_packets > retries) {
                    578:                        tftp_errno = -40;
                    579:                        break;
                    580:                }
                    581: 
                    582:                /* no_packets counts the times we have returned from receive_ether()
                    583:                        * without any packet received; if this gets larger than 'retries'
                    584:                        * we also just exit */
                    585:                if (tftp_err->no_packets > retries) {
                    586:                        tftp_errno = -41;
                    587:                        break;
                    588:                }
                    589:        }
                    590: 
                    591:        // Setting buffer to NULL disables handling of received TFTP packets.
                    592:        buffer = NULL;
                    593: 
                    594:        if (tftp_errno)
                    595:                return tftp_errno;
                    596: 
                    597:        print_progress(-1, received_len);
                    598:        printf("\n");
                    599:        if (lost_packets)
                    600:                printf("Lost ACK packets: %d\n", lost_packets);
                    601:                
                    602:        return received_len;
                    603: }

unix.superglobalmegacorp.com

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