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

Annotation of src/usr.bin/ssh/buffer.c, Revision 1.33

1.33    ! djm         1: /* $OpenBSD: buffer.c,v 1.32 2010/02/09 03:56:28 djm Exp $ */
1.1       deraadt     2: /*
1.3       deraadt     3:  * Author: Tatu Ylonen <ylo@cs.hut.fi>
                      4:  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
                      5:  *                    All rights reserved
                      6:  * Functions for manipulating fifo buffers (that can grow if needed).
1.6       markus      7:  *
1.8       deraadt     8:  * As far as I am concerned, the code I have written for this software
                      9:  * can be used freely for any purpose.  Any derived versions of this
                     10:  * software must be clearly marked as such, and if the derived work is
                     11:  * incompatible with the protocol description in the RFC file, it must be
                     12:  * called by a name other than "ssh" or "Secure Shell".
1.3       deraadt    13:  */
1.1       deraadt    14:
1.29      stevesk    15: #include <sys/param.h>
1.28      stevesk    16:
1.30      stevesk    17: #include <stdio.h>
1.28      stevesk    18: #include <string.h>
1.31      deraadt    19: #include <stdarg.h>
1.1       deraadt    20:
                     21: #include "xmalloc.h"
                     22: #include "buffer.h"
1.10      markus     23: #include "log.h"
1.1       deraadt    24:
1.27      djm        25: #define        BUFFER_MAX_CHUNK        0x100000
                     26: #define        BUFFER_MAX_LEN          0xa00000
                     27: #define        BUFFER_ALLOCSZ          0x008000
                     28:
1.1       deraadt    29: /* Initializes the buffer structure. */
                     30:
1.6       markus     31: void
1.2       markus     32: buffer_init(Buffer *buffer)
1.1       deraadt    33: {
1.18      markus     34:        const u_int len = 4096;
                     35:
                     36:        buffer->alloc = 0;
                     37:        buffer->buf = xmalloc(len);
                     38:        buffer->alloc = len;
1.2       markus     39:        buffer->offset = 0;
                     40:        buffer->end = 0;
1.1       deraadt    41: }
                     42:
                     43: /* Frees any memory used for the buffer. */
                     44:
1.6       markus     45: void
1.2       markus     46: buffer_free(Buffer *buffer)
1.1       deraadt    47: {
1.18      markus     48:        if (buffer->alloc > 0) {
                     49:                memset(buffer->buf, 0, buffer->alloc);
1.19      markus     50:                buffer->alloc = 0;
1.33    ! djm        51:                free(buffer->buf);
1.18      markus     52:        }
1.1       deraadt    53: }
                     54:
1.4       markus     55: /*
                     56:  * Clears any data from the buffer, making it empty.  This does not actually
                     57:  * zero the memory.
                     58:  */
1.1       deraadt    59:
1.6       markus     60: void
1.2       markus     61: buffer_clear(Buffer *buffer)
1.1       deraadt    62: {
1.2       markus     63:        buffer->offset = 0;
                     64:        buffer->end = 0;
1.1       deraadt    65: }
                     66:
                     67: /* Appends data to the buffer, expanding it if necessary. */
                     68:
1.6       markus     69: void
1.14      stevesk    70: buffer_append(Buffer *buffer, const void *data, u_int len)
1.1       deraadt    71: {
1.14      stevesk    72:        void *p;
                     73:        p = buffer_append_space(buffer, len);
                     74:        memcpy(p, data, len);
1.1       deraadt    75: }
                     76:
1.27      djm        77: static int
                     78: buffer_compact(Buffer *buffer)
                     79: {
                     80:        /*
                     81:         * If the buffer is quite empty, but all data is at the end, move the
                     82:         * data to the beginning.
                     83:         */
                     84:        if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {
                     85:                memmove(buffer->buf, buffer->buf + buffer->offset,
                     86:                        buffer->end - buffer->offset);
                     87:                buffer->end -= buffer->offset;
                     88:                buffer->offset = 0;
                     89:                return (1);
                     90:        }
                     91:        return (0);
                     92: }
                     93:
1.4       markus     94: /*
                     95:  * Appends space to the buffer, expanding the buffer if necessary. This does
                     96:  * not actually copy the data into the buffer, but instead returns a pointer
                     97:  * to the allocated region.
                     98:  */
1.1       deraadt    99:
1.14      stevesk   100: void *
                    101: buffer_append_space(Buffer *buffer, u_int len)
1.1       deraadt   102: {
1.17      deraadt   103:        u_int newlen;
1.14      stevesk   104:        void *p;
                    105:
1.23      markus    106:        if (len > BUFFER_MAX_CHUNK)
1.16      markus    107:                fatal("buffer_append_space: len %u not supported", len);
                    108:
1.2       markus    109:        /* If the buffer is empty, start using it from the beginning. */
                    110:        if (buffer->offset == buffer->end) {
                    111:                buffer->offset = 0;
                    112:                buffer->end = 0;
                    113:        }
                    114: restart:
                    115:        /* If there is enough space to store all data, store it now. */
                    116:        if (buffer->end + len < buffer->alloc) {
1.14      stevesk   117:                p = buffer->buf + buffer->end;
1.2       markus    118:                buffer->end += len;
1.14      stevesk   119:                return p;
1.2       markus    120:        }
1.27      djm       121:
                    122:        /* Compact data back to the start of the buffer if necessary */
                    123:        if (buffer_compact(buffer))
1.2       markus    124:                goto restart;
1.27      djm       125:
1.2       markus    126:        /* Increase the size of the buffer and retry. */
1.27      djm       127:        newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
1.23      markus    128:        if (newlen > BUFFER_MAX_LEN)
1.16      markus    129:                fatal("buffer_append_space: alloc %u not supported",
1.17      deraadt   130:                    newlen);
1.25      djm       131:        buffer->buf = xrealloc(buffer->buf, 1, newlen);
1.17      deraadt   132:        buffer->alloc = newlen;
1.2       markus    133:        goto restart;
1.14      stevesk   134:        /* NOTREACHED */
1.27      djm       135: }
                    136:
                    137: /*
                    138:  * Check whether an allocation of 'len' will fit in the buffer
                    139:  * This must follow the same math as buffer_append_space
                    140:  */
                    141: int
                    142: buffer_check_alloc(Buffer *buffer, u_int len)
                    143: {
                    144:        if (buffer->offset == buffer->end) {
                    145:                buffer->offset = 0;
                    146:                buffer->end = 0;
                    147:        }
                    148:  restart:
                    149:        if (buffer->end + len < buffer->alloc)
                    150:                return (1);
                    151:        if (buffer_compact(buffer))
                    152:                goto restart;
                    153:        if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
                    154:                return (1);
                    155:        return (0);
1.1       deraadt   156: }
                    157:
                    158: /* Returns the number of bytes of data in the buffer. */
                    159:
1.9       markus    160: u_int
1.32      djm       161: buffer_len(const Buffer *buffer)
1.1       deraadt   162: {
1.2       markus    163:        return buffer->end - buffer->offset;
1.1       deraadt   164: }
                    165:
                    166: /* Gets data from the beginning of the buffer. */
                    167:
1.22      djm       168: int
                    169: buffer_get_ret(Buffer *buffer, void *buf, u_int len)
1.1       deraadt   170: {
1.22      djm       171:        if (len > buffer->end - buffer->offset) {
                    172:                error("buffer_get_ret: trying to get more bytes %d than in buffer %d",
1.11      markus    173:                    len, buffer->end - buffer->offset);
1.22      djm       174:                return (-1);
                    175:        }
1.2       markus    176:        memcpy(buf, buffer->buf + buffer->offset, len);
                    177:        buffer->offset += len;
1.22      djm       178:        return (0);
                    179: }
                    180:
                    181: void
                    182: buffer_get(Buffer *buffer, void *buf, u_int len)
                    183: {
                    184:        if (buffer_get_ret(buffer, buf, len) == -1)
                    185:                fatal("buffer_get: buffer error");
1.1       deraadt   186: }
                    187:
                    188: /* Consumes the given number of bytes from the beginning of the buffer. */
                    189:
1.22      djm       190: int
                    191: buffer_consume_ret(Buffer *buffer, u_int bytes)
                    192: {
                    193:        if (bytes > buffer->end - buffer->offset) {
                    194:                error("buffer_consume_ret: trying to get more bytes than in buffer");
                    195:                return (-1);
                    196:        }
                    197:        buffer->offset += bytes;
                    198:        return (0);
                    199: }
                    200:
1.6       markus    201: void
1.9       markus    202: buffer_consume(Buffer *buffer, u_int bytes)
1.1       deraadt   203: {
1.22      djm       204:        if (buffer_consume_ret(buffer, bytes) == -1)
                    205:                fatal("buffer_consume: buffer error");
1.2       markus    206: }
1.1       deraadt   207:
                    208: /* Consumes the given number of bytes from the end of the buffer. */
                    209:
1.22      djm       210: int
                    211: buffer_consume_end_ret(Buffer *buffer, u_int bytes)
                    212: {
                    213:        if (bytes > buffer->end - buffer->offset)
                    214:                return (-1);
                    215:        buffer->end -= bytes;
                    216:        return (0);
                    217: }
                    218:
1.6       markus    219: void
1.9       markus    220: buffer_consume_end(Buffer *buffer, u_int bytes)
1.1       deraadt   221: {
1.22      djm       222:        if (buffer_consume_end_ret(buffer, bytes) == -1)
1.5       markus    223:                fatal("buffer_consume_end: trying to get more bytes than in buffer");
1.2       markus    224: }
1.1       deraadt   225:
                    226: /* Returns a pointer to the first used byte in the buffer. */
                    227:
1.14      stevesk   228: void *
1.32      djm       229: buffer_ptr(const Buffer *buffer)
1.1       deraadt   230: {
1.2       markus    231:        return buffer->buf + buffer->offset;
1.1       deraadt   232: }
                    233:
                    234: /* Dumps the contents of the buffer to stderr. */
                    235:
1.6       markus    236: void
1.32      djm       237: buffer_dump(const Buffer *buffer)
1.1       deraadt   238: {
1.20      markus    239:        u_int i;
1.15      stevesk   240:        u_char *ucp = buffer->buf;
1.2       markus    241:
1.13      markus    242:        for (i = buffer->offset; i < buffer->end; i++) {
                    243:                fprintf(stderr, "%02x", ucp[i]);
                    244:                if ((i-buffer->offset)%16==15)
                    245:                        fprintf(stderr, "\r\n");
                    246:                else if ((i-buffer->offset)%2==1)
                    247:                        fprintf(stderr, " ");
                    248:        }
1.12      markus    249:        fprintf(stderr, "\r\n");
1.1       deraadt   250: }