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

Diff for /src/usr.bin/ssh/Attic/buffer.c between version 1.35 and 1.36

version 1.35, 2014/02/02 03:44:31 version 1.36, 2014/04/30 05:29:56
Line 1 
Line 1 
 /* $OpenBSD$ */  /* $OpenBSD$ */
   
 /*  /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>   * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland  
  *                    All rights reserved  
  * Functions for manipulating fifo buffers (that can grow if needed).  
  *   *
  * As far as I am concerned, the code I have written for this software   * Permission to use, copy, modify, and distribute this software for any
  * can be used freely for any purpose.  Any derived versions of this   * purpose with or without fee is hereby granted, provided that the above
  * software must be clearly marked as such, and if the derived work is   * copyright notice and this permission notice appear in all copies.
  * incompatible with the protocol description in the RFC file, it must be   *
  * called by a name other than "ssh" or "Secure Shell".   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */   */
   
 #include <sys/param.h>  /* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
   
 #include <stdio.h>  #include <sys/types.h>
 #include <string.h>  
 #include <stdarg.h>  
 #include <stdlib.h>  
   
 #include "xmalloc.h"  
 #include "buffer.h"  #include "buffer.h"
 #include "log.h"  #include "log.h"
   #include "ssherr.h"
   
 #define BUFFER_MAX_CHUNK        0x100000  
 #define BUFFER_MAX_LEN          0xa00000  
 #define BUFFER_ALLOCSZ          0x008000  
   
 /* Initializes the buffer structure. */  
   
 void  void
 buffer_init(Buffer *buffer)  
 {  
         const u_int len = 4096;  
   
         buffer->alloc = 0;  
         buffer->buf = xmalloc(len);  
         buffer->alloc = len;  
         buffer->offset = 0;  
         buffer->end = 0;  
 }  
   
 /* Frees any memory used for the buffer. */  
   
 void  
 buffer_free(Buffer *buffer)  
 {  
         if (buffer->alloc > 0) {  
                 explicit_bzero(buffer->buf, buffer->alloc);  
                 buffer->alloc = 0;  
                 free(buffer->buf);  
         }  
 }  
   
 /*  
  * Clears any data from the buffer, making it empty.  This does not actually  
  * zero the memory.  
  */  
   
 void  
 buffer_clear(Buffer *buffer)  
 {  
         buffer->offset = 0;  
         buffer->end = 0;  
 }  
   
 /* Appends data to the buffer, expanding it if necessary. */  
   
 void  
 buffer_append(Buffer *buffer, const void *data, u_int len)  buffer_append(Buffer *buffer, const void *data, u_int len)
 {  {
         void *p;          int ret;
         p = buffer_append_space(buffer, len);  
         memcpy(p, data, len);  
 }  
   
 static int          if ((ret = sshbuf_put(buffer, data, len)) != 0)
 buffer_compact(Buffer *buffer)                  fatal("%s: %s", __func__, ssh_err(ret));
 {  
         /*  
          * If the buffer is quite empty, but all data is at the end, move the  
          * data to the beginning.  
          */  
         if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {  
                 memmove(buffer->buf, buffer->buf + buffer->offset,  
                         buffer->end - buffer->offset);  
                 buffer->end -= buffer->offset;  
                 buffer->offset = 0;  
                 return (1);  
         }  
         return (0);  
 }  }
   
 /*  
  * Appends space to the buffer, expanding the buffer if necessary. This does  
  * not actually copy the data into the buffer, but instead returns a pointer  
  * to the allocated region.  
  */  
   
 void *  void *
 buffer_append_space(Buffer *buffer, u_int len)  buffer_append_space(Buffer *buffer, u_int len)
 {  {
         u_int newlen;          int ret;
         void *p;          u_char *p;
   
         if (len > BUFFER_MAX_CHUNK)          if ((ret = sshbuf_reserve(buffer, len, &p)) != 0)
                 fatal("buffer_append_space: len %u not supported", len);                  fatal("%s: %s", __func__, ssh_err(ret));
           return p;
         /* If the buffer is empty, start using it from the beginning. */  
         if (buffer->offset == buffer->end) {  
                 buffer->offset = 0;  
                 buffer->end = 0;  
         }  
 restart:  
         /* If there is enough space to store all data, store it now. */  
         if (buffer->end + len < buffer->alloc) {  
                 p = buffer->buf + buffer->end;  
                 buffer->end += len;  
                 return p;  
         }  
   
         /* Compact data back to the start of the buffer if necessary */  
         if (buffer_compact(buffer))  
                 goto restart;  
   
         /* Increase the size of the buffer and retry. */  
         newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);  
         if (newlen > BUFFER_MAX_LEN)  
                 fatal("buffer_append_space: alloc %u not supported",  
                     newlen);  
         buffer->buf = xrealloc(buffer->buf, 1, newlen);  
         buffer->alloc = newlen;  
         goto restart;  
         /* NOTREACHED */  
 }  }
   
 /*  
  * Check whether an allocation of 'len' will fit in the buffer  
  * This must follow the same math as buffer_append_space  
  */  
 int  int
 buffer_check_alloc(Buffer *buffer, u_int len)  buffer_check_alloc(Buffer *buffer, u_int len)
 {  {
         if (buffer->offset == buffer->end) {          int ret = sshbuf_check_reserve(buffer, len);
                 buffer->offset = 0;  
                 buffer->end = 0;  
         }  
  restart:  
         if (buffer->end + len < buffer->alloc)  
                 return (1);  
         if (buffer_compact(buffer))  
                 goto restart;  
         if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)  
                 return (1);  
         return (0);  
 }  
   
 /* Returns the number of bytes of data in the buffer. */          if (ret == 0)
                   return 1;
 u_int          if (ret == SSH_ERR_NO_BUFFER_SPACE)
 buffer_len(const Buffer *buffer)                  return 0;
 {          fatal("%s: %s", __func__, ssh_err(ret));
         return buffer->end - buffer->offset;  
 }  }
   
 /* Gets data from the beginning of the buffer. */  
   
 int  int
 buffer_get_ret(Buffer *buffer, void *buf, u_int len)  buffer_get_ret(Buffer *buffer, void *buf, u_int len)
 {  {
         if (len > buffer->end - buffer->offset) {          int ret;
                 error("buffer_get_ret: trying to get more bytes %d than in buffer %d",  
                     len, buffer->end - buffer->offset);          if ((ret = sshbuf_get(buffer, buf, len)) != 0) {
                 return (-1);                  error("%s: %s", __func__, ssh_err(ret));
                   return -1;
         }          }
         memcpy(buf, buffer->buf + buffer->offset, len);          return 0;
         buffer->offset += len;  
         return (0);  
 }  }
   
 void  void
 buffer_get(Buffer *buffer, void *buf, u_int len)  buffer_get(Buffer *buffer, void *buf, u_int len)
 {  {
         if (buffer_get_ret(buffer, buf, len) == -1)          if (buffer_get_ret(buffer, buf, len) == -1)
                 fatal("buffer_get: buffer error");                  fatal("%s: buffer error", __func__);
 }  }
   
 /* Consumes the given number of bytes from the beginning of the buffer. */  
   
 int  int
 buffer_consume_ret(Buffer *buffer, u_int bytes)  buffer_consume_ret(Buffer *buffer, u_int bytes)
 {  {
         if (bytes > buffer->end - buffer->offset) {          int ret = sshbuf_consume(buffer, bytes);
                 error("buffer_consume_ret: trying to get more bytes than in buffer");  
                 return (-1);          if (ret == 0)
         }                  return 0;
         buffer->offset += bytes;          if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
         return (0);                  return -1;
           fatal("%s: %s", __func__, ssh_err(ret));
 }  }
   
 void  void
 buffer_consume(Buffer *buffer, u_int bytes)  buffer_consume(Buffer *buffer, u_int bytes)
 {  {
         if (buffer_consume_ret(buffer, bytes) == -1)          if (buffer_consume_ret(buffer, bytes) == -1)
                 fatal("buffer_consume: buffer error");                  fatal("%s: buffer error", __func__);
 }  }
   
 /* Consumes the given number of bytes from the end of the buffer. */  
   
 int  int
 buffer_consume_end_ret(Buffer *buffer, u_int bytes)  buffer_consume_end_ret(Buffer *buffer, u_int bytes)
 {  {
         if (bytes > buffer->end - buffer->offset)          int ret = sshbuf_consume_end(buffer, bytes);
                 return (-1);  
         buffer->end -= bytes;          if (ret == 0)
         return (0);                  return 0;
           if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
                   return -1;
           fatal("%s: %s", __func__, ssh_err(ret));
 }  }
   
 void  void
 buffer_consume_end(Buffer *buffer, u_int bytes)  buffer_consume_end(Buffer *buffer, u_int bytes)
 {  {
         if (buffer_consume_end_ret(buffer, bytes) == -1)          if (buffer_consume_end_ret(buffer, bytes) == -1)
                 fatal("buffer_consume_end: trying to get more bytes than in buffer");                  fatal("%s: buffer error", __func__);
 }  }
   
 /* Returns a pointer to the first used byte in the buffer. */  
   
 void *  
 buffer_ptr(const Buffer *buffer)  
 {  
         return buffer->buf + buffer->offset;  
 }  
   
 /* Dumps the contents of the buffer to stderr. */  
   
 void  
 buffer_dump(const Buffer *buffer)  
 {  
         u_int i;  
         u_char *ucp = buffer->buf;  
   
         for (i = buffer->offset; i < buffer->end; i++) {  
                 fprintf(stderr, "%02x", ucp[i]);  
                 if ((i-buffer->offset)%16==15)  
                         fprintf(stderr, "\r\n");  
                 else if ((i-buffer->offset)%2==1)  
                         fprintf(stderr, " ");  
         }  
         fprintf(stderr, "\r\n");  
 }  

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.36