[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.35

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