Annotation of qemu/roms/ipxe/src/net/udp/tftp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2006 Michael Brown <[email protected]>.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: FILE_LICENCE ( GPL2_OR_LATER );
                     20: 
                     21: #include <stdint.h>
                     22: #include <stdlib.h>
                     23: #include <stdio.h>
                     24: #include <string.h>
                     25: #include <strings.h>
                     26: #include <byteswap.h>
                     27: #include <errno.h>
                     28: #include <assert.h>
                     29: #include <ipxe/refcnt.h>
                     30: #include <ipxe/iobuf.h>
                     31: #include <ipxe/xfer.h>
                     32: #include <ipxe/open.h>
                     33: #include <ipxe/uri.h>
                     34: #include <ipxe/tcpip.h>
                     35: #include <ipxe/retry.h>
                     36: #include <ipxe/features.h>
                     37: #include <ipxe/bitmap.h>
                     38: #include <ipxe/settings.h>
                     39: #include <ipxe/dhcp.h>
                     40: #include <ipxe/uri.h>
                     41: #include <ipxe/tftp.h>
                     42: 
                     43: /** @file
                     44:  *
                     45:  * TFTP protocol
                     46:  *
                     47:  */
                     48: 
                     49: FEATURE ( FEATURE_PROTOCOL, "TFTP", DHCP_EB_FEATURE_TFTP, 1 );
                     50: 
                     51: /* TFTP-specific error codes */
                     52: #define EINVAL_BLKSIZE         __einfo_error ( EINFO_EINVAL_BLKSIZE )
                     53: #define EINFO_EINVAL_BLKSIZE __einfo_uniqify \
                     54:        ( EINFO_EINVAL, 0x01, "Invalid blksize" )
                     55: #define EINVAL_TSIZE __einfo_error ( EINFO_EINVAL_TSIZE )
                     56: #define EINFO_EINVAL_TSIZE __einfo_uniqify \
                     57:        ( EINFO_EINVAL, 0x02, "Invalid tsize" )
                     58: #define EINVAL_MC_NO_PORT __einfo_error ( EINFO_EINVAL_MC_NO_PORT )
                     59: #define EINFO_EINVAL_MC_NO_PORT __einfo_uniqify \
                     60:        ( EINFO_EINVAL, 0x03, "Missing multicast port" )
                     61: #define EINVAL_MC_NO_MC __einfo_error ( EINFO_EINVAL_MC_NO_MC )
                     62: #define EINFO_EINVAL_MC_NO_MC __einfo_uniqify \
                     63:        ( EINFO_EINVAL, 0x04, "Missing multicast mc" )
                     64: #define EINVAL_MC_INVALID_MC __einfo_error ( EINFO_EINVAL_MC_INVALID_MC )
                     65: #define EINFO_EINVAL_MC_INVALID_MC __einfo_uniqify \
                     66:        ( EINFO_EINVAL, 0x05, "Missing multicast IP" )
                     67: #define EINVAL_MC_INVALID_IP __einfo_error ( EINFO_EINVAL_MC_INVALID_IP )
                     68: #define EINFO_EINVAL_MC_INVALID_IP __einfo_uniqify \
                     69:        ( EINFO_EINVAL, 0x06, "Invalid multicast IP" )
                     70: #define EINVAL_MC_INVALID_PORT __einfo_error ( EINFO_EINVAL_MC_INVALID_PORT )
                     71: #define EINFO_EINVAL_MC_INVALID_PORT __einfo_uniqify \
                     72:        ( EINFO_EINVAL, 0x07, "Invalid multicast port" )
                     73: 
                     74: /**
                     75:  * A TFTP request
                     76:  *
                     77:  * This data structure holds the state for an ongoing TFTP transfer.
                     78:  */
                     79: struct tftp_request {
                     80:        /** Reference count */
                     81:        struct refcnt refcnt;
                     82:        /** Data transfer interface */
                     83:        struct interface xfer;
                     84: 
                     85:        /** URI being fetched */
                     86:        struct uri *uri;
                     87:        /** Transport layer interface */
                     88:        struct interface socket;
                     89:        /** Multicast transport layer interface */
                     90:        struct interface mc_socket;
                     91: 
                     92:        /** Data block size
                     93:         *
                     94:         * This is the "blksize" option negotiated with the TFTP
                     95:         * server.  (If the TFTP server does not support TFTP options,
                     96:         * this will default to 512).
                     97:         */
                     98:        unsigned int blksize;
                     99:        /** File size
                    100:         *
                    101:         * This is the value returned in the "tsize" option from the
                    102:         * TFTP server.  If the TFTP server does not support the
                    103:         * "tsize" option, this value will be zero.
                    104:         */
                    105:        unsigned long tsize;
                    106:        
                    107:        /** Server port
                    108:         *
                    109:         * This is the port to which RRQ packets are sent.
                    110:         */
                    111:        unsigned int port;
                    112:        /** Peer address
                    113:         *
                    114:         * The peer address is determined by the first response
                    115:         * received to the TFTP RRQ.
                    116:         */
                    117:        struct sockaddr_tcpip peer;
                    118:        /** Request flags */
                    119:        unsigned int flags;
                    120:        /** MTFTP timeout count */
                    121:        unsigned int mtftp_timeouts;
                    122: 
                    123:        /** Block bitmap */
                    124:        struct bitmap bitmap;
                    125:        /** Maximum known length
                    126:         *
                    127:         * We don't always know the file length in advance.  In
                    128:         * particular, if the TFTP server doesn't support the tsize
                    129:         * option, or we are using MTFTP, then we don't know the file
                    130:         * length until we see the end-of-file block (which, in the
                    131:         * case of MTFTP, may not be the last block we see).
                    132:         *
                    133:         * This value is updated whenever we obtain information about
                    134:         * the file length.
                    135:         */
                    136:        size_t filesize;
                    137:        /** Retransmission timer */
                    138:        struct retry_timer timer;
                    139: };
                    140: 
                    141: /** TFTP request flags */
                    142: enum {
                    143:        /** Send ACK packets */
                    144:        TFTP_FL_SEND_ACK = 0x0001,
                    145:        /** Request blksize and tsize options */
                    146:        TFTP_FL_RRQ_SIZES = 0x0002,
                    147:        /** Request multicast option */
                    148:        TFTP_FL_RRQ_MULTICAST = 0x0004,
                    149:        /** Perform MTFTP recovery on timeout */
                    150:        TFTP_FL_MTFTP_RECOVERY = 0x0008,
                    151:        /** Only get filesize and then abort the transfer */
                    152:        TFTP_FL_SIZEONLY = 0x0010,
                    153: };
                    154: 
                    155: /** Maximum number of MTFTP open requests before falling back to TFTP */
                    156: #define MTFTP_MAX_TIMEOUTS 3
                    157: 
                    158: /**
                    159:  * Free TFTP request
                    160:  *
                    161:  * @v refcnt           Reference counter
                    162:  */
                    163: static void tftp_free ( struct refcnt *refcnt ) {
                    164:        struct tftp_request *tftp =
                    165:                container_of ( refcnt, struct tftp_request, refcnt );
                    166: 
                    167:        uri_put ( tftp->uri );
                    168:        bitmap_free ( &tftp->bitmap );
                    169:        free ( tftp );
                    170: }
                    171: 
                    172: /**
                    173:  * Mark TFTP request as complete
                    174:  *
                    175:  * @v tftp             TFTP connection
                    176:  * @v rc               Return status code
                    177:  */
                    178: static void tftp_done ( struct tftp_request *tftp, int rc ) {
                    179: 
                    180:        DBGC ( tftp, "TFTP %p finished with status %d (%s)\n",
                    181:               tftp, rc, strerror ( rc ) );
                    182: 
                    183:        /* Stop the retry timer */
                    184:        stop_timer ( &tftp->timer );
                    185: 
                    186:        /* Close all data transfer interfaces */
                    187:        intf_shutdown ( &tftp->socket, rc );
                    188:        intf_shutdown ( &tftp->mc_socket, rc );
                    189:        intf_shutdown ( &tftp->xfer, rc );
                    190: }
                    191: 
                    192: /**
                    193:  * Reopen TFTP socket
                    194:  *
                    195:  * @v tftp             TFTP connection
                    196:  * @ret rc             Return status code
                    197:  */
                    198: static int tftp_reopen ( struct tftp_request *tftp ) {
                    199:        struct sockaddr_tcpip server;
                    200:        int rc;
                    201: 
                    202:        /* Close socket */
                    203:        intf_restart ( &tftp->socket, 0 );
                    204: 
                    205:        /* Disable ACK sending. */
                    206:        tftp->flags &= ~TFTP_FL_SEND_ACK;
                    207: 
                    208:        /* Reset peer address */
                    209:        memset ( &tftp->peer, 0, sizeof ( tftp->peer ) );
                    210: 
                    211:        /* Open socket */
                    212:        memset ( &server, 0, sizeof ( server ) );
                    213:        server.st_port = htons ( tftp->port );
                    214:        if ( ( rc = xfer_open_named_socket ( &tftp->socket, SOCK_DGRAM,
                    215:                                             ( struct sockaddr * ) &server,
                    216:                                             tftp->uri->host, NULL ) ) != 0 ) {
                    217:                DBGC ( tftp, "TFTP %p could not open socket: %s\n",
                    218:                       tftp, strerror ( rc ) );
                    219:                return rc;
                    220:        }
                    221: 
                    222:        return 0;
                    223: }
                    224: 
                    225: /**
                    226:  * Reopen TFTP multicast socket
                    227:  *
                    228:  * @v tftp             TFTP connection
                    229:  * @v local            Local socket address
                    230:  * @ret rc             Return status code
                    231:  */
                    232: static int tftp_reopen_mc ( struct tftp_request *tftp,
                    233:                            struct sockaddr *local ) {
                    234:        int rc;
                    235: 
                    236:        /* Close multicast socket */
                    237:        intf_restart ( &tftp->mc_socket, 0 );
                    238: 
                    239:        /* Open multicast socket.  We never send via this socket, so
                    240:         * use the local address as the peer address (since the peer
                    241:         * address cannot be NULL).
                    242:         */
                    243:        if ( ( rc = xfer_open_socket ( &tftp->mc_socket, SOCK_DGRAM,
                    244:                                       local, local ) ) != 0 ) {
                    245:                DBGC ( tftp, "TFTP %p could not open multicast "
                    246:                       "socket: %s\n", tftp, strerror ( rc ) );
                    247:                return rc;
                    248:        }
                    249: 
                    250:        return 0;
                    251: }
                    252: 
                    253: /**
                    254:  * Presize TFTP receive buffers and block bitmap
                    255:  *
                    256:  * @v tftp             TFTP connection
                    257:  * @v filesize         Known minimum file size
                    258:  * @ret rc             Return status code
                    259:  */
                    260: static int tftp_presize ( struct tftp_request *tftp, size_t filesize ) {
                    261:        unsigned int num_blocks;
                    262:        int rc;
                    263: 
                    264:        /* Do nothing if we are already large enough */
                    265:        if ( filesize <= tftp->filesize )
                    266:                return 0;
                    267: 
                    268:        /* Record filesize */
                    269:        tftp->filesize = filesize;
                    270: 
                    271:        /* Notify recipient of file size */
                    272:        xfer_seek ( &tftp->xfer, filesize );
                    273:        xfer_seek ( &tftp->xfer, 0 );
                    274: 
                    275:        /* Calculate expected number of blocks.  Note that files whose
                    276:         * length is an exact multiple of the blocksize will have a
                    277:         * trailing zero-length block, which must be included.
                    278:         */
                    279:        num_blocks = ( ( filesize / tftp->blksize ) + 1 );
                    280:        if ( ( rc = bitmap_resize ( &tftp->bitmap, num_blocks ) ) != 0 ) {
                    281:                DBGC ( tftp, "TFTP %p could not resize bitmap to %d blocks: "
                    282:                       "%s\n", tftp, num_blocks, strerror ( rc ) );
                    283:                return rc;
                    284:        }
                    285: 
                    286:        return 0;
                    287: }
                    288: 
                    289: /**
                    290:  * TFTP requested blocksize
                    291:  *
                    292:  * This is treated as a global configuration parameter.
                    293:  */
                    294: static unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE;
                    295: 
                    296: /**
                    297:  * Set TFTP request blocksize
                    298:  *
                    299:  * @v blksize          Requested block size
                    300:  */
                    301: void tftp_set_request_blksize ( unsigned int blksize ) {
                    302:        if ( blksize < TFTP_DEFAULT_BLKSIZE )
                    303:                blksize = TFTP_DEFAULT_BLKSIZE;
                    304:        tftp_request_blksize = blksize;
                    305: }
                    306: 
                    307: /**
                    308:  * MTFTP multicast receive address
                    309:  *
                    310:  * This is treated as a global configuration parameter.
                    311:  */
                    312: static struct sockaddr_in tftp_mtftp_socket = {
                    313:        .sin_family = AF_INET,
                    314:        .sin_addr.s_addr = htonl ( 0xefff0101 ),
                    315:        .sin_port = htons ( 3001 ),
                    316: };
                    317: 
                    318: /**
                    319:  * Set MTFTP multicast address
                    320:  *
                    321:  * @v address          Multicast IPv4 address
                    322:  */
                    323: void tftp_set_mtftp_address ( struct in_addr address ) {
                    324:        tftp_mtftp_socket.sin_addr = address;
                    325: }
                    326: 
                    327: /**
                    328:  * Set MTFTP multicast port
                    329:  *
                    330:  * @v port             Multicast port
                    331:  */
                    332: void tftp_set_mtftp_port ( unsigned int port ) {
                    333:        tftp_mtftp_socket.sin_port = htons ( port );
                    334: }
                    335: 
                    336: /**
                    337:  * Transmit RRQ
                    338:  *
                    339:  * @v tftp             TFTP connection
                    340:  * @ret rc             Return status code
                    341:  */
                    342: static int tftp_send_rrq ( struct tftp_request *tftp ) {
                    343:        struct tftp_rrq *rrq;
                    344:        const char *path;
                    345:        size_t len;
                    346:        struct io_buffer *iobuf;
                    347: 
                    348:        /* Strip initial '/' if present.  If we were opened via the
                    349:         * URI interface, then there will be an initial '/', since a
                    350:         * full tftp:// URI provides no way to specify a non-absolute
                    351:         * path.  However, many TFTP servers (particularly Windows
                    352:         * TFTP servers) complain about having an initial '/', and it
                    353:         * violates user expectations to have a '/' silently added to
                    354:         * the DHCP-specified filename.
                    355:         */
                    356:        path = tftp->uri->path;
                    357:        if ( *path == '/' )
                    358:                path++;
                    359: 
                    360:        DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path );
                    361: 
                    362:        /* Allocate buffer */
                    363:        len = ( sizeof ( *rrq ) + strlen ( path ) + 1 /* NUL */
                    364:                + 5 + 1 /* "octet" + NUL */
                    365:                + 7 + 1 + 5 + 1 /* "blksize" + NUL + ddddd + NUL */
                    366:                + 5 + 1 + 1 + 1 /* "tsize" + NUL + "0" + NUL */ 
                    367:                + 9 + 1 + 1 /* "multicast" + NUL + NUL */ );
                    368:        iobuf = xfer_alloc_iob ( &tftp->socket, len );
                    369:        if ( ! iobuf )
                    370:                return -ENOMEM;
                    371: 
                    372:        /* Build request */
                    373:        rrq = iob_put ( iobuf, sizeof ( *rrq ) );
                    374:        rrq->opcode = htons ( TFTP_RRQ );
                    375:        iob_put ( iobuf, snprintf ( iobuf->tail, iob_tailroom ( iobuf ),
                    376:                                    "%s%coctet", path, 0 ) + 1 );
                    377:        if ( tftp->flags & TFTP_FL_RRQ_SIZES ) {
                    378:                iob_put ( iobuf, snprintf ( iobuf->tail,
                    379:                                            iob_tailroom ( iobuf ),
                    380:                                            "blksize%c%d%ctsize%c0", 0,
                    381:                                            tftp_request_blksize, 0, 0 ) + 1 );
                    382:        }
                    383:        if ( tftp->flags & TFTP_FL_RRQ_MULTICAST ) {
                    384:                iob_put ( iobuf, snprintf ( iobuf->tail,
                    385:                                            iob_tailroom ( iobuf ),
                    386:                                            "multicast%c", 0 ) + 1 );
                    387:        }
                    388: 
                    389:        /* RRQ always goes to the address specified in the initial
                    390:         * xfer_open() call
                    391:         */
                    392:        return xfer_deliver_iob ( &tftp->socket, iobuf );
                    393: }
                    394: 
                    395: /**
                    396:  * Transmit ACK
                    397:  *
                    398:  * @v tftp             TFTP connection
                    399:  * @ret rc             Return status code
                    400:  */
                    401: static int tftp_send_ack ( struct tftp_request *tftp ) {
                    402:        struct tftp_ack *ack;
                    403:        struct io_buffer *iobuf;
                    404:        struct xfer_metadata meta = {
                    405:                .dest = ( struct sockaddr * ) &tftp->peer,
                    406:        };
                    407:        unsigned int block;
                    408: 
                    409:        /* Determine next required block number */
                    410:        block = bitmap_first_gap ( &tftp->bitmap );
                    411:        DBGC2 ( tftp, "TFTP %p sending ACK for block %d\n", tftp, block );
                    412: 
                    413:        /* Allocate buffer */
                    414:        iobuf = xfer_alloc_iob ( &tftp->socket, sizeof ( *ack ) );
                    415:        if ( ! iobuf )
                    416:                return -ENOMEM;
                    417: 
                    418:        /* Build ACK */
                    419:        ack = iob_put ( iobuf, sizeof ( *ack ) );
                    420:        ack->opcode = htons ( TFTP_ACK );
                    421:        ack->block = htons ( block );
                    422: 
                    423:        /* ACK always goes to the peer recorded from the RRQ response */
                    424:        return xfer_deliver ( &tftp->socket, iobuf, &meta );
                    425: }
                    426: 
                    427: /**
                    428:  * Transmit ERROR (Abort)
                    429:  *
                    430:  * @v tftp             TFTP connection
                    431:  * @v errcode          TFTP error code
                    432:  * @v errmsg           Error message string
                    433:  * @ret rc             Return status code
                    434:  */
                    435: static int tftp_send_error ( struct tftp_request *tftp, int errcode,
                    436:                             const char *errmsg ) {
                    437:        struct tftp_error *err;
                    438:        struct io_buffer *iobuf;
                    439:        struct xfer_metadata meta = {
                    440:                .dest = ( struct sockaddr * ) &tftp->peer,
                    441:        };
                    442:        size_t msglen;
                    443: 
                    444:        DBGC2 ( tftp, "TFTP %p sending ERROR %d: %s\n", tftp, errcode,
                    445:                errmsg );
                    446: 
                    447:        /* Allocate buffer */
                    448:        msglen = sizeof ( *err ) + strlen ( errmsg ) + 1 /* NUL */;
                    449:        iobuf = xfer_alloc_iob ( &tftp->socket, msglen );
                    450:        if ( ! iobuf )
                    451:                return -ENOMEM;
                    452: 
                    453:        /* Build ERROR */
                    454:        err = iob_put ( iobuf, msglen );
                    455:        err->opcode = htons ( TFTP_ERROR );
                    456:        err->errcode = htons ( errcode );
                    457:        strcpy ( err->errmsg, errmsg );
                    458: 
                    459:        /* ERR always goes to the peer recorded from the RRQ response */
                    460:        return xfer_deliver ( &tftp->socket, iobuf, &meta );
                    461: }
                    462: 
                    463: /**
                    464:  * Transmit next relevant packet
                    465:  *
                    466:  * @v tftp             TFTP connection
                    467:  * @ret rc             Return status code
                    468:  */
                    469: static int tftp_send_packet ( struct tftp_request *tftp ) {
                    470: 
                    471:        /* Update retransmission timer.  While name resolution takes place the
                    472:         * window is zero.  Avoid unnecessary delay after name resolution
                    473:         * completes by retrying immediately.
                    474:         */
                    475:        stop_timer ( &tftp->timer );
                    476:        if ( xfer_window ( &tftp->socket ) ) {
                    477:                start_timer ( &tftp->timer );
                    478:        } else {
                    479:                start_timer_nodelay ( &tftp->timer );
                    480:        }
                    481: 
                    482:        /* Send RRQ or ACK as appropriate */
                    483:        if ( ! tftp->peer.st_family ) {
                    484:                return tftp_send_rrq ( tftp );
                    485:        } else {
                    486:                if ( tftp->flags & TFTP_FL_SEND_ACK ) {
                    487:                        return tftp_send_ack ( tftp );
                    488:                } else {
                    489:                        return 0;
                    490:                }
                    491:        }
                    492: }
                    493: 
                    494: /**
                    495:  * Handle TFTP retransmission timer expiry
                    496:  *
                    497:  * @v timer            Retry timer
                    498:  * @v fail             Failure indicator
                    499:  */
                    500: static void tftp_timer_expired ( struct retry_timer *timer, int fail ) {
                    501:        struct tftp_request *tftp =
                    502:                container_of ( timer, struct tftp_request, timer );
                    503:        int rc;
                    504: 
                    505:        /* If we are doing MTFTP, attempt the various recovery strategies */
                    506:        if ( tftp->flags & TFTP_FL_MTFTP_RECOVERY ) {
                    507:                if ( tftp->peer.st_family ) {
                    508:                        /* If we have received any response from the server,
                    509:                         * try resending the RRQ to restart the download.
                    510:                         */
                    511:                        DBGC ( tftp, "TFTP %p attempting reopen\n", tftp );
                    512:                        if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
                    513:                                goto err;
                    514:                } else {
                    515:                        /* Fall back to plain TFTP after several attempts */
                    516:                        tftp->mtftp_timeouts++;
                    517:                        DBGC ( tftp, "TFTP %p timeout %d waiting for MTFTP "
                    518:                               "open\n", tftp, tftp->mtftp_timeouts );
                    519: 
                    520:                        if ( tftp->mtftp_timeouts > MTFTP_MAX_TIMEOUTS ) {
                    521:                                DBGC ( tftp, "TFTP %p falling back to plain "
                    522:                                       "TFTP\n", tftp );
                    523:                                tftp->flags = TFTP_FL_RRQ_SIZES;
                    524: 
                    525:                                /* Close multicast socket */
                    526:                                intf_restart ( &tftp->mc_socket, 0 );
                    527: 
                    528:                                /* Reset retry timer */
                    529:                                start_timer_nodelay ( &tftp->timer );
                    530: 
                    531:                                /* The blocksize may change: discard
                    532:                                 * the block bitmap
                    533:                                 */
                    534:                                bitmap_free ( &tftp->bitmap );
                    535:                                memset ( &tftp->bitmap, 0,
                    536:                                         sizeof ( tftp->bitmap ) );
                    537: 
                    538:                                /* Reopen on standard TFTP port */
                    539:                                tftp->port = TFTP_PORT;
                    540:                                if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
                    541:                                        goto err;
                    542:                        }
                    543:                }
                    544:        } else {
                    545:                /* Not doing MTFTP (or have fallen back to plain
                    546:                 * TFTP); fail as per normal.
                    547:                 */
                    548:                if ( fail ) {
                    549:                        rc = -ETIMEDOUT;
                    550:                        goto err;
                    551:                }
                    552:        }
                    553:        tftp_send_packet ( tftp );
                    554:        return;
                    555: 
                    556:  err:
                    557:        tftp_done ( tftp, rc );
                    558: }
                    559: 
                    560: /**
                    561:  * Process TFTP "blksize" option
                    562:  *
                    563:  * @v tftp             TFTP connection
                    564:  * @v value            Option value
                    565:  * @ret rc             Return status code
                    566:  */
                    567: static int tftp_process_blksize ( struct tftp_request *tftp,
                    568:                                  const char *value ) {
                    569:        char *end;
                    570: 
                    571:        tftp->blksize = strtoul ( value, &end, 10 );
                    572:        if ( *end ) {
                    573:                DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
                    574:                       tftp, value );
                    575:                return -EINVAL_BLKSIZE;
                    576:        }
                    577:        DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
                    578: 
                    579:        return 0;
                    580: }
                    581: 
                    582: /**
                    583:  * Process TFTP "tsize" option
                    584:  *
                    585:  * @v tftp             TFTP connection
                    586:  * @v value            Option value
                    587:  * @ret rc             Return status code
                    588:  */
                    589: static int tftp_process_tsize ( struct tftp_request *tftp,
                    590:                                const char *value ) {
                    591:        char *end;
                    592: 
                    593:        tftp->tsize = strtoul ( value, &end, 10 );
                    594:        if ( *end ) {
                    595:                DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
                    596:                       tftp, value );
                    597:                return -EINVAL_TSIZE;
                    598:        }
                    599:        DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
                    600: 
                    601:        return 0;
                    602: }
                    603: 
                    604: /**
                    605:  * Process TFTP "multicast" option
                    606:  *
                    607:  * @v tftp             TFTP connection
                    608:  * @v value            Option value
                    609:  * @ret rc             Return status code
                    610:  */
                    611: static int tftp_process_multicast ( struct tftp_request *tftp,
                    612:                                    const char *value ) {
                    613:        union {
                    614:                struct sockaddr sa;
                    615:                struct sockaddr_in sin;
                    616:        } socket;
                    617:        char buf[ strlen ( value ) + 1 ];
                    618:        char *addr;
                    619:        char *port;
                    620:        char *port_end;
                    621:        char *mc;
                    622:        char *mc_end;
                    623:        int rc;
                    624: 
                    625:        /* Split value into "addr,port,mc" fields */
                    626:        memcpy ( buf, value, sizeof ( buf ) );
                    627:        addr = buf;
                    628:        port = strchr ( addr, ',' );
                    629:        if ( ! port ) {
                    630:                DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp );
                    631:                return -EINVAL_MC_NO_PORT;
                    632:        }
                    633:        *(port++) = '\0';
                    634:        mc = strchr ( port, ',' );
                    635:        if ( ! mc ) {
                    636:                DBGC ( tftp, "TFTP %p multicast missing mc\n", tftp );
                    637:                return -EINVAL_MC_NO_MC;
                    638:        }
                    639:        *(mc++) = '\0';
                    640: 
                    641:        /* Parse parameters */
                    642:        if ( strtoul ( mc, &mc_end, 0 ) == 0 )
                    643:                tftp->flags &= ~TFTP_FL_SEND_ACK;
                    644:        if ( *mc_end ) {
                    645:                DBGC ( tftp, "TFTP %p multicast invalid mc %s\n", tftp, mc );
                    646:                return -EINVAL_MC_INVALID_MC;
                    647:        }
                    648:        DBGC ( tftp, "TFTP %p is%s the master client\n",
                    649:               tftp, ( ( tftp->flags & TFTP_FL_SEND_ACK ) ? "" : " not" ) );
                    650:        if ( *addr && *port ) {
                    651:                socket.sin.sin_family = AF_INET;
                    652:                if ( inet_aton ( addr, &socket.sin.sin_addr ) == 0 ) {
                    653:                        DBGC ( tftp, "TFTP %p multicast invalid IP address "
                    654:                               "%s\n", tftp, addr );
                    655:                        return -EINVAL_MC_INVALID_IP;
                    656:                }
                    657:                DBGC ( tftp, "TFTP %p multicast IP address %s\n",
                    658:                       tftp, inet_ntoa ( socket.sin.sin_addr ) );
                    659:                socket.sin.sin_port = htons ( strtoul ( port, &port_end, 0 ) );
                    660:                if ( *port_end ) {
                    661:                        DBGC ( tftp, "TFTP %p multicast invalid port %s\n",
                    662:                               tftp, port );
                    663:                        return -EINVAL_MC_INVALID_PORT;
                    664:                }
                    665:                DBGC ( tftp, "TFTP %p multicast port %d\n",
                    666:                       tftp, ntohs ( socket.sin.sin_port ) );
                    667:                if ( ( rc = tftp_reopen_mc ( tftp, &socket.sa ) ) != 0 )
                    668:                        return rc;
                    669:        }
                    670: 
                    671:        return 0;
                    672: }
                    673: 
                    674: /** A TFTP option */
                    675: struct tftp_option {
                    676:        /** Option name */
                    677:        const char *name;
                    678:        /** Option processor
                    679:         *
                    680:         * @v tftp      TFTP connection
                    681:         * @v value     Option value
                    682:         * @ret rc      Return status code
                    683:         */
                    684:        int ( * process ) ( struct tftp_request *tftp, const char *value );
                    685: };
                    686: 
                    687: /** Recognised TFTP options */
                    688: static struct tftp_option tftp_options[] = {
                    689:        { "blksize", tftp_process_blksize },
                    690:        { "tsize", tftp_process_tsize },
                    691:        { "multicast", tftp_process_multicast },
                    692:        { NULL, NULL }
                    693: };
                    694: 
                    695: /**
                    696:  * Process TFTP option
                    697:  *
                    698:  * @v tftp             TFTP connection
                    699:  * @v name             Option name
                    700:  * @v value            Option value
                    701:  * @ret rc             Return status code
                    702:  */
                    703: static int tftp_process_option ( struct tftp_request *tftp,
                    704:                                 const char *name, const char *value ) {
                    705:        struct tftp_option *option;
                    706: 
                    707:        for ( option = tftp_options ; option->name ; option++ ) {
                    708:                if ( strcasecmp ( name, option->name ) == 0 )
                    709:                        return option->process ( tftp, value );
                    710:        }
                    711: 
                    712:        DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
                    713:               tftp, name, value );
                    714: 
                    715:        /* Unknown options should be silently ignored */
                    716:        return 0;
                    717: }
                    718: 
                    719: /**
                    720:  * Receive OACK
                    721:  *
                    722:  * @v tftp             TFTP connection
                    723:  * @v buf              Temporary data buffer
                    724:  * @v len              Length of temporary data buffer
                    725:  * @ret rc             Return status code
                    726:  */
                    727: static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
                    728:        struct tftp_oack *oack = buf;
                    729:        char *end = buf + len;
                    730:        char *name;
                    731:        char *value;
                    732:        char *next;
                    733:        int rc = 0;
                    734: 
                    735:        /* Sanity check */
                    736:        if ( len < sizeof ( *oack ) ) {
                    737:                DBGC ( tftp, "TFTP %p received underlength OACK packet "
                    738:                       "length %zd\n", tftp, len );
                    739:                rc = -EINVAL;
                    740:                goto done;
                    741:        }
                    742: 
                    743:        /* Process each option in turn */
                    744:        for ( name = oack->data ; name < end ; name = next ) {
                    745: 
                    746:                /* Parse option name and value
                    747:                 *
                    748:                 * We treat parsing errors as non-fatal, because there
                    749:                 * exists at least one TFTP server (IBM Tivoli PXE
                    750:                 * Server 5.1.0.3) that has been observed to send
                    751:                 * malformed OACKs containing trailing garbage bytes.
                    752:                 */
                    753:                value = ( name + strnlen ( name, ( end - name ) ) + 1 );
                    754:                if ( value > end ) {
                    755:                        DBGC ( tftp, "TFTP %p received OACK with malformed "
                    756:                               "option name:\n", tftp );
                    757:                        DBGC_HD ( tftp, oack, len );
                    758:                        break;
                    759:                }
                    760:                if ( value == end ) {
                    761:                        DBGC ( tftp, "TFTP %p received OACK missing value "
                    762:                               "for option \"%s\"\n", tftp, name );
                    763:                        DBGC_HD ( tftp, oack, len );
                    764:                        break;
                    765:                }
                    766:                next = ( value + strnlen ( value, ( end - value ) ) + 1 );
                    767:                if ( next > end ) {
                    768:                        DBGC ( tftp, "TFTP %p received OACK with malformed "
                    769:                               "value for option \"%s\":\n", tftp, name );
                    770:                        DBGC_HD ( tftp, oack, len );
                    771:                        break;
                    772:                }
                    773: 
                    774:                /* Process option */
                    775:                if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
                    776:                        goto done;
                    777:        }
                    778: 
                    779:        /* Process tsize information, if available */
                    780:        if ( tftp->tsize ) {
                    781:                if ( ( rc = tftp_presize ( tftp, tftp->tsize ) ) != 0 )
                    782:                        goto done;
                    783:        }
                    784: 
                    785:        /* Abort request if only trying to determine file size */
                    786:        if ( tftp->flags & TFTP_FL_SIZEONLY ) {
                    787:                rc = 0;
                    788:                tftp_send_error ( tftp, 0, "TFTP Aborted" );
                    789:                tftp_done ( tftp, rc );
                    790:                return rc;
                    791:        }
                    792: 
                    793:        /* Request next data block */
                    794:        tftp_send_packet ( tftp );
                    795: 
                    796:  done:
                    797:        if ( rc )
                    798:                tftp_done ( tftp, rc );
                    799:        return rc;
                    800: }
                    801: 
                    802: /**
                    803:  * Receive DATA
                    804:  *
                    805:  * @v tftp             TFTP connection
                    806:  * @v iobuf            I/O buffer
                    807:  * @ret rc             Return status code
                    808:  *
                    809:  * Takes ownership of I/O buffer.
                    810:  */
                    811: static int tftp_rx_data ( struct tftp_request *tftp,
                    812:                          struct io_buffer *iobuf ) {
                    813:        struct tftp_data *data = iobuf->data;
                    814:        struct xfer_metadata meta;
                    815:        unsigned int block;
                    816:        off_t offset;
                    817:        size_t data_len;
                    818:        int rc;
                    819: 
                    820:        if ( tftp->flags & TFTP_FL_SIZEONLY ) {
                    821:                /* If we get here then server doesn't support SIZE option */
                    822:                rc = -ENOTSUP;
                    823:                tftp_send_error ( tftp, 0, "TFTP Aborted" );
                    824:                goto done;
                    825:        }
                    826: 
                    827:        /* Sanity check */
                    828:        if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
                    829:                DBGC ( tftp, "TFTP %p received underlength DATA packet "
                    830:                       "length %zd\n", tftp, iob_len ( iobuf ) );
                    831:                rc = -EINVAL;
                    832:                goto done;
                    833:        }
                    834: 
                    835:        /* Calculate block number */
                    836:        block = ( ( bitmap_first_gap ( &tftp->bitmap ) + 1 ) & ~0xffff );
                    837:        if ( data->block == 0 && block == 0 ) {
                    838:                DBGC ( tftp, "TFTP %p received data block 0\n", tftp );
                    839:                rc = -EINVAL;
                    840:                goto done;
                    841:        }
                    842:        block += ( ntohs ( data->block ) - 1 );
                    843: 
                    844:        /* Extract data */
                    845:        offset = ( block * tftp->blksize );
                    846:        iob_pull ( iobuf, sizeof ( *data ) );
                    847:        data_len = iob_len ( iobuf );
                    848:        if ( data_len > tftp->blksize ) {
                    849:                DBGC ( tftp, "TFTP %p received overlength DATA packet "
                    850:                       "length %zd\n", tftp, data_len );
                    851:                rc = -EINVAL;
                    852:                goto done;
                    853:        }
                    854: 
                    855:        /* Deliver data */
                    856:        memset ( &meta, 0, sizeof ( meta ) );
                    857:        meta.flags = XFER_FL_ABS_OFFSET;
                    858:        meta.offset = offset;
                    859:        if ( ( rc = xfer_deliver ( &tftp->xfer, iob_disown ( iobuf ),
                    860:                                   &meta ) ) != 0 ) {
                    861:                DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
                    862:                       tftp, strerror ( rc ) );
                    863:                goto done;
                    864:        }
                    865: 
                    866:        /* Ensure block bitmap is ready */
                    867:        if ( ( rc = tftp_presize ( tftp, ( offset + data_len ) ) ) != 0 )
                    868:                goto done;
                    869: 
                    870:        /* Mark block as received */
                    871:        bitmap_set ( &tftp->bitmap, block );
                    872: 
                    873:        /* Acknowledge block */
                    874:        tftp_send_packet ( tftp );
                    875: 
                    876:        /* If all blocks have been received, finish. */
                    877:        if ( bitmap_full ( &tftp->bitmap ) )
                    878:                tftp_done ( tftp, 0 );
                    879: 
                    880:  done:
                    881:        free_iob ( iobuf );
                    882:        if ( rc )
                    883:                tftp_done ( tftp, rc );
                    884:        return rc;
                    885: }
                    886: 
                    887: /**
                    888:  * Convert TFTP error code to return status code
                    889:  *
                    890:  * @v errcode          TFTP error code
                    891:  * @ret rc             Return status code
                    892:  */
                    893: static int tftp_errcode_to_rc ( unsigned int errcode ) {
                    894:        switch ( errcode ) {
                    895:        case TFTP_ERR_FILE_NOT_FOUND:   return -ENOENT;
                    896:        case TFTP_ERR_ACCESS_DENIED:    return -EACCES;
                    897:        case TFTP_ERR_ILLEGAL_OP:       return -ENOTTY;
                    898:        default:                        return -ENOTSUP;
                    899:        }
                    900: }
                    901: 
                    902: /**
                    903:  * Receive ERROR
                    904:  *
                    905:  * @v tftp             TFTP connection
                    906:  * @v buf              Temporary data buffer
                    907:  * @v len              Length of temporary data buffer
                    908:  * @ret rc             Return status code
                    909:  */
                    910: static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
                    911:        struct tftp_error *error = buf;
                    912:        int rc;
                    913: 
                    914:        /* Sanity check */
                    915:        if ( len < sizeof ( *error ) ) {
                    916:                DBGC ( tftp, "TFTP %p received underlength ERROR packet "
                    917:                       "length %zd\n", tftp, len );
                    918:                return -EINVAL;
                    919:        }
                    920: 
                    921:        DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
                    922:               "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
                    923:        
                    924:        /* Determine final operation result */
                    925:        rc = tftp_errcode_to_rc ( ntohs ( error->errcode ) );
                    926: 
                    927:        /* Close TFTP request */
                    928:        tftp_done ( tftp, rc );
                    929: 
                    930:        return 0;
                    931: }
                    932: 
                    933: /**
                    934:  * Receive new data
                    935:  *
                    936:  * @v tftp             TFTP connection
                    937:  * @v iobuf            I/O buffer
                    938:  * @v meta             Transfer metadata
                    939:  * @ret rc             Return status code
                    940:  */
                    941: static int tftp_rx ( struct tftp_request *tftp,
                    942:                     struct io_buffer *iobuf,
                    943:                     struct xfer_metadata *meta ) {
                    944:        struct sockaddr_tcpip *st_src;
                    945:        struct tftp_common *common = iobuf->data;
                    946:        size_t len = iob_len ( iobuf );
                    947:        int rc = -EINVAL;
                    948:        
                    949:        /* Sanity checks */
                    950:        if ( len < sizeof ( *common ) ) {
                    951:                DBGC ( tftp, "TFTP %p received underlength packet length "
                    952:                       "%zd\n", tftp, len );
                    953:                goto done;
                    954:        }
                    955:        if ( ! meta->src ) {
                    956:                DBGC ( tftp, "TFTP %p received packet without source port\n",
                    957:                       tftp );
                    958:                goto done;
                    959:        }
                    960: 
                    961:        /* Filter by TID.  Set TID on first response received */
                    962:        st_src = ( struct sockaddr_tcpip * ) meta->src;
                    963:        if ( ! tftp->peer.st_family ) {
                    964:                memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
                    965:                DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
                    966:                       ntohs ( tftp->peer.st_port ) );
                    967:        } else if ( memcmp ( &tftp->peer, st_src,
                    968:                             sizeof ( tftp->peer ) ) != 0 ) {
                    969:                DBGC ( tftp, "TFTP %p received packet from wrong source (got "
                    970:                       "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
                    971:                       ntohs ( tftp->peer.st_port ) );
                    972:                goto done;
                    973:        }
                    974: 
                    975:        switch ( common->opcode ) {
                    976:        case htons ( TFTP_OACK ):
                    977:                rc = tftp_rx_oack ( tftp, iobuf->data, len );
                    978:                break;
                    979:        case htons ( TFTP_DATA ):
                    980:                rc = tftp_rx_data ( tftp, iob_disown ( iobuf ) );
                    981:                break;
                    982:        case htons ( TFTP_ERROR ):
                    983:                rc = tftp_rx_error ( tftp, iobuf->data, len );
                    984:                break;
                    985:        default:
                    986:                DBGC ( tftp, "TFTP %p received strange packet type %d\n",
                    987:                       tftp, ntohs ( common->opcode ) );
                    988:                break;
                    989:        };
                    990: 
                    991:  done:
                    992:        free_iob ( iobuf );
                    993:        return rc;
                    994: }
                    995: 
                    996: /**
                    997:  * Receive new data via socket
                    998:  *
                    999:  * @v tftp             TFTP connection
                   1000:  * @v iobuf            I/O buffer
                   1001:  * @v meta             Transfer metadata
                   1002:  * @ret rc             Return status code
                   1003:  */
                   1004: static int tftp_socket_deliver ( struct tftp_request *tftp,
                   1005:                                 struct io_buffer *iobuf,
                   1006:                                 struct xfer_metadata *meta ) {
                   1007: 
                   1008:        /* Enable sending ACKs when we receive a unicast packet.  This
                   1009:         * covers three cases:
                   1010:         *
                   1011:         * 1. Standard TFTP; we should always send ACKs, and will
                   1012:         *    always receive a unicast packet before we need to send the
                   1013:         *    first ACK.
                   1014:         *
                   1015:         * 2. RFC2090 multicast TFTP; the only unicast packets we will
                   1016:          *    receive are the OACKs; enable sending ACKs here (before
                   1017:          *    processing the OACK) and disable it when processing the
                   1018:          *    multicast option if we are not the master client.
                   1019:         *
                   1020:         * 3. MTFTP; receiving a unicast datagram indicates that we
                   1021:         *    are the "master client" and should send ACKs.
                   1022:         */
                   1023:        tftp->flags |= TFTP_FL_SEND_ACK;
                   1024: 
                   1025:        return tftp_rx ( tftp, iobuf, meta );
                   1026: }
                   1027: 
                   1028: /** TFTP socket operations */
                   1029: static struct interface_operation tftp_socket_operations[] = {
                   1030:        INTF_OP ( xfer_deliver, struct tftp_request *, tftp_socket_deliver ),
                   1031: };
                   1032: 
                   1033: /** TFTP socket interface descriptor */
                   1034: static struct interface_descriptor tftp_socket_desc =
                   1035:        INTF_DESC ( struct tftp_request, socket, tftp_socket_operations );
                   1036: 
                   1037: /** TFTP multicast socket operations */
                   1038: static struct interface_operation tftp_mc_socket_operations[] = {
                   1039:        INTF_OP ( xfer_deliver, struct tftp_request *, tftp_rx ),
                   1040: };
                   1041: 
                   1042: /** TFTP multicast socket interface descriptor */
                   1043: static struct interface_descriptor tftp_mc_socket_desc =
                   1044:        INTF_DESC ( struct tftp_request, mc_socket, tftp_mc_socket_operations );
                   1045: 
                   1046: /**
                   1047:  * Check flow control window
                   1048:  *
                   1049:  * @v tftp             TFTP connection
                   1050:  * @ret len            Length of window
                   1051:  */
                   1052: static size_t tftp_xfer_window ( struct tftp_request *tftp ) {
                   1053: 
                   1054:        /* We abuse this data-xfer method to convey the blocksize to
                   1055:         * the caller.  This really should be done using some kind of
                   1056:         * stat() method, but we don't yet have the facility to do
                   1057:         * that.
                   1058:         */
                   1059:        return tftp->blksize;
                   1060: }
                   1061: 
                   1062: /** TFTP data transfer interface operations */
                   1063: static struct interface_operation tftp_xfer_operations[] = {
                   1064:        INTF_OP ( xfer_window, struct tftp_request *, tftp_xfer_window ),
                   1065:        INTF_OP ( intf_close, struct tftp_request *, tftp_done ),
                   1066: };
                   1067: 
                   1068: /** TFTP data transfer interface descriptor */
                   1069: static struct interface_descriptor tftp_xfer_desc =
                   1070:        INTF_DESC ( struct tftp_request, xfer, tftp_xfer_operations );
                   1071: 
                   1072: /**
                   1073:  * Initiate TFTP/TFTM/MTFTP download
                   1074:  *
                   1075:  * @v xfer             Data transfer interface
                   1076:  * @v uri              Uniform Resource Identifier
                   1077:  * @ret rc             Return status code
                   1078:  */
                   1079: static int tftp_core_open ( struct interface *xfer, struct uri *uri,
                   1080:                            unsigned int default_port,
                   1081:                            struct sockaddr *multicast,
                   1082:                            unsigned int flags ) {
                   1083:        struct tftp_request *tftp;
                   1084:        int rc;
                   1085: 
                   1086:        /* Sanity checks */
                   1087:        if ( ! uri->host )
                   1088:                return -EINVAL;
                   1089:        if ( ! uri->path )
                   1090:                return -EINVAL;
                   1091: 
                   1092:        /* Allocate and populate TFTP structure */
                   1093:        tftp = zalloc ( sizeof ( *tftp ) );
                   1094:        if ( ! tftp )
                   1095:                return -ENOMEM;
                   1096:        ref_init ( &tftp->refcnt, tftp_free );
                   1097:        intf_init ( &tftp->xfer, &tftp_xfer_desc, &tftp->refcnt );
                   1098:        intf_init ( &tftp->socket, &tftp_socket_desc, &tftp->refcnt );
                   1099:        intf_init ( &tftp->mc_socket, &tftp_mc_socket_desc, &tftp->refcnt );
                   1100:        timer_init ( &tftp->timer, tftp_timer_expired, &tftp->refcnt );
                   1101:        tftp->uri = uri_get ( uri );
                   1102:        tftp->blksize = TFTP_DEFAULT_BLKSIZE;
                   1103:        tftp->flags = flags;
                   1104: 
                   1105:        /* Open socket */
                   1106:        tftp->port = uri_port ( tftp->uri, default_port );
                   1107:        if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
                   1108:                goto err;
                   1109: 
                   1110:        /* Open multicast socket */
                   1111:        if ( multicast ) {
                   1112:                if ( ( rc = tftp_reopen_mc ( tftp, multicast ) ) != 0 )
                   1113:                        goto err;
                   1114:        }
                   1115: 
                   1116:        /* Start timer to initiate RRQ */
                   1117:        start_timer_nodelay ( &tftp->timer );
                   1118: 
                   1119:        /* Attach to parent interface, mortalise self, and return */
                   1120:        intf_plug_plug ( &tftp->xfer, xfer );
                   1121:        ref_put ( &tftp->refcnt );
                   1122:        return 0;
                   1123: 
                   1124:  err:
                   1125:        DBGC ( tftp, "TFTP %p could not create request: %s\n",
                   1126:               tftp, strerror ( rc ) );
                   1127:        tftp_done ( tftp, rc );
                   1128:        ref_put ( &tftp->refcnt );
                   1129:        return rc;
                   1130: }
                   1131: 
                   1132: /**
                   1133:  * Initiate TFTP download
                   1134:  *
                   1135:  * @v xfer             Data transfer interface
                   1136:  * @v uri              Uniform Resource Identifier
                   1137:  * @ret rc             Return status code
                   1138:  */
                   1139: static int tftp_open ( struct interface *xfer, struct uri *uri ) {
                   1140:        return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
                   1141:                                TFTP_FL_RRQ_SIZES );
                   1142: 
                   1143: }
                   1144: 
                   1145: /** TFTP URI opener */
                   1146: struct uri_opener tftp_uri_opener __uri_opener = {
                   1147:        .scheme = "tftp",
                   1148:        .open   = tftp_open,
                   1149: };
                   1150: 
                   1151: /**
                   1152:  * Initiate TFTP-size request
                   1153:  *
                   1154:  * @v xfer             Data transfer interface
                   1155:  * @v uri              Uniform Resource Identifier
                   1156:  * @ret rc             Return status code
                   1157:  */
                   1158: static int tftpsize_open ( struct interface *xfer, struct uri *uri ) {
                   1159:        return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
                   1160:                                ( TFTP_FL_RRQ_SIZES |
                   1161:                                  TFTP_FL_SIZEONLY ) );
                   1162: 
                   1163: }
                   1164: 
                   1165: /** TFTP URI opener */
                   1166: struct uri_opener tftpsize_uri_opener __uri_opener = {
                   1167:        .scheme = "tftpsize",
                   1168:        .open   = tftpsize_open,
                   1169: };
                   1170: 
                   1171: /**
                   1172:  * Initiate TFTM download
                   1173:  *
                   1174:  * @v xfer             Data transfer interface
                   1175:  * @v uri              Uniform Resource Identifier
                   1176:  * @ret rc             Return status code
                   1177:  */
                   1178: static int tftm_open ( struct interface *xfer, struct uri *uri ) {
                   1179:        return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
                   1180:                                ( TFTP_FL_RRQ_SIZES |
                   1181:                                  TFTP_FL_RRQ_MULTICAST ) );
                   1182: 
                   1183: }
                   1184: 
                   1185: /** TFTM URI opener */
                   1186: struct uri_opener tftm_uri_opener __uri_opener = {
                   1187:        .scheme = "tftm",
                   1188:        .open   = tftm_open,
                   1189: };
                   1190: 
                   1191: /**
                   1192:  * Initiate MTFTP download
                   1193:  *
                   1194:  * @v xfer             Data transfer interface
                   1195:  * @v uri              Uniform Resource Identifier
                   1196:  * @ret rc             Return status code
                   1197:  */
                   1198: static int mtftp_open ( struct interface *xfer, struct uri *uri ) {
                   1199:        return tftp_core_open ( xfer, uri, MTFTP_PORT,
                   1200:                                ( struct sockaddr * ) &tftp_mtftp_socket,
                   1201:                                TFTP_FL_MTFTP_RECOVERY );
                   1202: }
                   1203: 
                   1204: /** MTFTP URI opener */
                   1205: struct uri_opener mtftp_uri_opener __uri_opener = {
                   1206:        .scheme = "mtftp",
                   1207:        .open   = mtftp_open,
                   1208: };
                   1209: 
                   1210: /******************************************************************************
                   1211:  *
                   1212:  * Settings
                   1213:  *
                   1214:  ******************************************************************************
                   1215:  */
                   1216: 
                   1217: /** TFTP server setting */
                   1218: struct setting next_server_setting __setting ( SETTING_BOOT ) = {
                   1219:        .name = "next-server",
                   1220:        .description = "TFTP server",
                   1221:        .tag = DHCP_EB_SIADDR,
                   1222:        .type = &setting_type_ipv4,
                   1223: };
                   1224: 
                   1225: /**
                   1226:  * Apply TFTP configuration settings
                   1227:  *
                   1228:  * @ret rc             Return status code
                   1229:  */
                   1230: static int tftp_apply_settings ( void ) {
                   1231:        static struct in_addr tftp_server = { 0 };
                   1232:        struct in_addr last_tftp_server;
                   1233:        char uri_string[32];
                   1234:        struct uri *uri;
                   1235: 
                   1236:        /* Retrieve TFTP server setting */
                   1237:        last_tftp_server = tftp_server;
                   1238:        fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
                   1239: 
                   1240:        /* If TFTP server setting has changed, set the current working
                   1241:         * URI to match.  Do it only when the TFTP server has changed
                   1242:         * to try to minimise surprises to the user, who probably
                   1243:         * won't expect the CWURI to change just because they updated
                   1244:         * an unrelated setting and triggered all the settings
                   1245:         * applicators.
                   1246:         */
                   1247:        if ( tftp_server.s_addr != last_tftp_server.s_addr ) {
                   1248:                if ( tftp_server.s_addr ) {
                   1249:                        snprintf ( uri_string, sizeof ( uri_string ),
                   1250:                                   "tftp://%s/", inet_ntoa ( tftp_server ) );
                   1251:                        uri = parse_uri ( uri_string );
                   1252:                        if ( ! uri )
                   1253:                                return -ENOMEM;
                   1254:                } else {
                   1255:                        uri = NULL;
                   1256:                }
                   1257:                churi ( uri );
                   1258:                uri_put ( uri );
                   1259:        }
                   1260: 
                   1261:        return 0;
                   1262: }
                   1263: 
                   1264: /** TFTP settings applicator */
                   1265: struct settings_applicator tftp_settings_applicator __settings_applicator = {
                   1266:        .apply = tftp_apply_settings,
                   1267: };

unix.superglobalmegacorp.com

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