[BACK]Return to tftpsubs.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tftp

Annotation of src/usr.bin/tftp/tftpsubs.c, Revision 1.15

1.15    ! gsoares     1: /*     $OpenBSD: tftpsubs.c,v 1.14 2009/10/27 23:59:44 deraadt Exp $   */
1.1       deraadt     2: /*     $NetBSD: tftpsubs.c,v 1.3 1994/12/08 09:51:31 jtc Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1983, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.6       millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
1.10      mglocker   33: /*
                     34:  * Simple minded read-ahead/write-behind subroutines for tftp user and
                     35:  * server.  Written originally with multiple buffers in mind, but current
                     36:  * implementation has two buffer logic wired in.
                     37:  *
                     38:  * Todo:  add some sort of final error check so when the write-buffer
                     39:  * is finally flushed, the caller can detect if the disk filled up
                     40:  * (or had an i/o error) and return a nak to the other side.
                     41:  *
                     42:  *                     Jim Guyton 10/85
1.1       deraadt    43:  */
                     44:
                     45: #include <sys/types.h>
                     46: #include <sys/socket.h>
                     47: #include <sys/ioctl.h>
1.10      mglocker   48:
1.1       deraadt    49: #include <netinet/in.h>
                     50: #include <arpa/tftp.h>
                     51:
                     52: #include <stdio.h>
                     53: #include <unistd.h>
                     54:
                     55: #include "tftpsubs.h"
                     56:
1.10      mglocker   57:                                        /* values for bf.counter */
                     58: #define BF_ALLOC       -3              /* alloc'd but not yet filled */
                     59: #define BF_FREE                -2              /* free */
                     60: /* [-1 .. SEGSIZE] = size of data in the data buffer */
                     61:
                     62: static struct tftphdr  *rw_init(int);
1.1       deraadt    63:
                     64: struct bf {
1.11      mglocker   65:        int     counter;                /* size of data in buffer, or flag */
                     66:        char    buf[SEGSIZE_MAX + 4];   /* room for data packet */
1.1       deraadt    67: } bfs[2];
                     68:
1.10      mglocker   69: static int     nextone;        /* index of next buffer to use */
                     70: static int     current;        /* index of buffer in use */
1.1       deraadt    71:                                /* control flags for crlf conversions */
1.10      mglocker   72: int            newline = 0;    /* fillbuf: in middle of newline expansion */
                     73: int            prevchar = -1;  /* putbuf: previous char (cr check) */
1.1       deraadt    74:
1.7       deraadt    75: struct tftphdr *
                     76: w_init(void)
                     77: {
1.10      mglocker   78:        return (rw_init(0));    /* write-behind */
1.7       deraadt    79: }
                     80:
                     81: struct tftphdr *
                     82: r_init(void)
                     83: {
1.10      mglocker   84:        return (rw_init(1));    /* read-ahead */
1.7       deraadt    85: }
1.1       deraadt    86:
1.10      mglocker   87: /*
                     88:  * Init for either read-ahead or write-behind.
                     89:  * Zero for write-behind, one for read-head.
                     90:  */
1.1       deraadt    91: static struct tftphdr *
1.7       deraadt    92: rw_init(int x)
1.1       deraadt    93: {
1.10      mglocker   94:        newline = 0;                    /* init crlf flag */
1.1       deraadt    95:        prevchar = -1;
1.12      mglocker   96:        bfs[0].counter = BF_ALLOC;      /* pass out the first buffer */
1.1       deraadt    97:        current = 0;
                     98:        bfs[1].counter = BF_FREE;
1.10      mglocker   99:        nextone = x;                    /* ahead or behind? */
                    100:
                    101:        return ((struct tftphdr *)bfs[0].buf);
1.1       deraadt   102: }
                    103:
1.10      mglocker  104: /*
                    105:  * Have emptied current buffer by sending to net and getting ack.
                    106:  * Free it and return next buffer filled with data.
1.1       deraadt   107:  */
                    108: int
1.11      mglocker  109: readit(FILE *file, struct tftphdr **dpp, int convert, int segment_size)
1.1       deraadt   110: {
1.10      mglocker  111:        struct bf       *b;
                    112:
                    113:        bfs[current].counter = BF_FREE;         /* free old one */
                    114:        current = !current;                     /* "incr" current */
1.1       deraadt   115:
1.10      mglocker  116:        b = &bfs[current];                      /* look at new buffer */
                    117:        if (b->counter == BF_FREE)              /* if it's empty */
1.11      mglocker  118:                read_ahead(file, convert, segment_size);        /* fill it */
1.10      mglocker  119:        /* assert(b->counter != BF_FREE); */    /* check */
                    120:        *dpp = (struct tftphdr *)b->buf;        /* set caller's ptr */
1.1       deraadt   121:
1.10      mglocker  122:        return (b->counter);
1.1       deraadt   123: }
                    124:
                    125: /*
1.10      mglocker  126:  * Fill the input buffer, doing ascii conversions if requested.
                    127:  * Conversions are lf -> cr, lf and cr -> cr, nul.
1.1       deraadt   128:  */
                    129: void
1.11      mglocker  130: read_ahead(FILE *file, int convert, int segment_size)
1.1       deraadt   131: {
1.10      mglocker  132:        int              i;
                    133:        char            *p;
                    134:        int              c;
                    135:        struct bf       *b;
                    136:        struct tftphdr  *dp;
1.1       deraadt   137:
1.10      mglocker  138:        b = &bfs[nextone];                      /* look at "next" buffer */
                    139:        if (b->counter != BF_FREE)              /* nop if not free */
1.1       deraadt   140:                return;
1.10      mglocker  141:        nextone = !nextone;                     /* "incr" next buffer ptr */
1.1       deraadt   142:
                    143:        dp = (struct tftphdr *)b->buf;
                    144:
                    145:        if (convert == 0) {
1.11      mglocker  146:                b->counter = read(fileno(file), dp->th_data, segment_size);
1.1       deraadt   147:                return;
                    148:        }
                    149:
                    150:        p = dp->th_data;
1.11      mglocker  151:        for (i = 0; i < segment_size; i++) {
1.1       deraadt   152:                if (newline) {
                    153:                        if (prevchar == '\n')
1.10      mglocker  154:                                c = '\n';       /* lf to cr, lf */
1.9       deraadt   155:                        else
1.10      mglocker  156:                                c = '\0';       /* cr to cr, nul */
1.1       deraadt   157:                        newline = 0;
1.9       deraadt   158:                } else {
1.1       deraadt   159:                        c = getc(file);
1.10      mglocker  160:                        if (c == EOF)
                    161:                                break;
1.1       deraadt   162:                        if (c == '\n' || c == '\r') {
                    163:                                prevchar = c;
                    164:                                c = '\r';
                    165:                                newline = 1;
                    166:                        }
                    167:                }
                    168:               *p++ = c;
                    169:        }
                    170:        b->counter = (int)(p - dp->th_data);
                    171: }
                    172:
1.10      mglocker  173: /*
                    174:  * Update count associated with the buffer, get new buffer
                    175:  * from the queue.  Calls write_behind only if next buffer not
                    176:  * available.
1.1       deraadt   177:  */
                    178: int
1.7       deraadt   179: writeit(FILE *file, struct tftphdr **dpp, int ct, int convert)
1.1       deraadt   180: {
1.10      mglocker  181:        bfs[current].counter = ct;              /* set size of data to write */
                    182:        current = !current;                     /* switch to other buffer */
                    183:        if (bfs[current].counter != BF_FREE)    /* if not free */
                    184:                /* flush it */
                    185:                (void)write_behind(file, convert);
                    186:        bfs[current].counter = BF_ALLOC;        /* mark as alloc'd */
1.1       deraadt   187:        *dpp =  (struct tftphdr *)bfs[current].buf;
1.10      mglocker  188:
                    189:        return (ct);                            /* this is a lie of course */
1.1       deraadt   190: }
                    191:
                    192: /*
                    193:  * Output a buffer to a file, converting from netascii if requested.
1.10      mglocker  194:  * CR, NUL -> CR and CR, LF -> LF.
1.1       deraadt   195:  * Note spec is undefined if we get CR as last byte of file or a
                    196:  * CR followed by anything else.  In this case we leave it alone.
1.10      mglocker  197:  */
1.1       deraadt   198: int
1.7       deraadt   199: write_behind(FILE *file, int convert)
1.1       deraadt   200: {
1.10      mglocker  201:        char            *buf;
                    202:        int              count;
                    203:        int              ct;
                    204:        char            *p;
                    205:        int              c; /* current character */
                    206:        struct bf       *b;
                    207:        struct tftphdr  *dp;
1.1       deraadt   208:
                    209:        b = &bfs[nextone];
1.10      mglocker  210:        if (b->counter < -1)            /* anything to flush? */
                    211:                return (0);             /* just nop if nothing to do */
1.1       deraadt   212:
1.10      mglocker  213:        count = b->counter;             /* remember byte count */
                    214:        b->counter = BF_FREE;           /* reset flag */
1.1       deraadt   215:        dp = (struct tftphdr *)b->buf;
1.10      mglocker  216:        nextone = !nextone;             /* incr for next time */
1.1       deraadt   217:        buf = dp->th_data;
                    218:
1.10      mglocker  219:        if (count <= 0)                 /* nak logic? */
                    220:                return (-1);
1.1       deraadt   221:
                    222:        if (convert == 0)
1.10      mglocker  223:                return (write(fileno(file), buf, count));
1.1       deraadt   224:
                    225:        p = buf;
                    226:        ct = count;
1.10      mglocker  227:        while (ct--) {                          /* loop over the buffer */
                    228:                c = *p++;                       /* pick up a character */
                    229:                if (prevchar == '\r') {         /* if prev char was cr */
                    230:                        if (c == '\n')          /* if have cr,lf then just */
                    231:                                /* smash lf on top of the cr */
1.13      tobias    232:                                fseek(file, -1, SEEK_CUR);
1.10      mglocker  233:                        else if (c == '\0')     /* if have cr,nul then */
                    234:                                goto skipit;    /* just skip over the putc */
                    235:                        /* FALLTHROUGH */
1.9       deraadt   236:                }
                    237:                putc(c, file);
1.1       deraadt   238: skipit:
1.9       deraadt   239:                prevchar = c;
1.1       deraadt   240:        }
1.10      mglocker  241:
                    242:        return (count);
1.1       deraadt   243: }
                    244:
1.10      mglocker  245: /*
                    246:  * When an error has occurred, it is possible that the two sides
1.1       deraadt   247:  * are out of synch.  Ie: that what I think is the other side's
                    248:  * response to packet N is really their response to packet N-1.
                    249:  *
                    250:  * So, to try to prevent that, we flush all the input queued up
                    251:  * for us on the network connection on our host.
                    252:  *
                    253:  * We return the number of packets we flushed (mostly for reporting
                    254:  * when trace is active).
                    255:  */
                    256: int
1.7       deraadt   257: synchnet(int f)
1.1       deraadt   258: {
1.10      mglocker  259:        int                     i, j = 0;
1.11      mglocker  260:        char                    rbuf[SEGSIZE_MIN];
1.15    ! gsoares   261:        struct sockaddr_storage from;
1.10      mglocker  262:        socklen_t               fromlen;
1.1       deraadt   263:
1.10      mglocker  264:        for (;;) {
                    265:                (void)ioctl(f, FIONREAD, &i);
1.1       deraadt   266:                if (i) {
                    267:                        j++;
1.10      mglocker  268:                        fromlen = sizeof(from);
                    269:                        (void)recvfrom(f, rbuf, sizeof(rbuf), 0,
1.9       deraadt   270:                            (struct sockaddr *)&from, &fromlen);
1.10      mglocker  271:                } else
                    272:                        return (j);
1.1       deraadt   273:        }
                    274: }