LCOV - code coverage report
Current view: top level - src/utils - wpabuf.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 98 123 79.7 %
Date: 2014-05-28 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /*
       2             :  * Dynamic data buffer
       3             :  * Copyright (c) 2007-2012, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "trace.h"
      13             : #include "wpabuf.h"
      14             : 
      15             : #ifdef WPA_TRACE
      16             : #define WPABUF_MAGIC 0x51a974e3
      17             : 
      18             : struct wpabuf_trace {
      19             :         unsigned int magic;
      20             : };
      21             : 
      22       93568 : static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf)
      23             : {
      24       93568 :         return (struct wpabuf_trace *)
      25             :                 ((const u8 *) buf - sizeof(struct wpabuf_trace));
      26             : }
      27             : #endif /* WPA_TRACE */
      28             : 
      29             : 
      30           0 : static void wpabuf_overflow(const struct wpabuf *buf, size_t len)
      31             : {
      32             : #ifdef WPA_TRACE
      33           0 :         struct wpabuf_trace *trace = wpabuf_get_trace(buf);
      34           0 :         if (trace->magic != WPABUF_MAGIC) {
      35           0 :                 wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x",
      36             :                            trace->magic);
      37             :         }
      38             : #endif /* WPA_TRACE */
      39           0 :         wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu",
      40             :                    buf, (unsigned long) buf->size, (unsigned long) buf->used,
      41             :                    (unsigned long) len);
      42           0 :         wpa_trace_show("wpabuf overflow");
      43           0 :         abort();
      44             : }
      45             : 
      46             : 
      47       16728 : int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
      48             : {
      49       16728 :         struct wpabuf *buf = *_buf;
      50             : #ifdef WPA_TRACE
      51             :         struct wpabuf_trace *trace;
      52             : #endif /* WPA_TRACE */
      53             : 
      54       16728 :         if (buf == NULL) {
      55        6477 :                 *_buf = wpabuf_alloc(add_len);
      56        6477 :                 return *_buf == NULL ? -1 : 0;
      57             :         }
      58             : 
      59             : #ifdef WPA_TRACE
      60       10251 :         trace = wpabuf_get_trace(buf);
      61       10251 :         if (trace->magic != WPABUF_MAGIC) {
      62           0 :                 wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x",
      63             :                            trace->magic);
      64           0 :                 wpa_trace_show("wpabuf_resize invalid magic");
      65           0 :                 abort();
      66             :         }
      67             : #endif /* WPA_TRACE */
      68             : 
      69       10251 :         if (buf->used + add_len > buf->size) {
      70             :                 unsigned char *nbuf;
      71        8908 :                 if (buf->flags & WPABUF_FLAG_EXT_DATA) {
      72           0 :                         nbuf = os_realloc(buf->buf, buf->used + add_len);
      73           0 :                         if (nbuf == NULL)
      74           0 :                                 return -1;
      75           0 :                         os_memset(nbuf + buf->used, 0, add_len);
      76           0 :                         buf->buf = nbuf;
      77             :                 } else {
      78             : #ifdef WPA_TRACE
      79        8908 :                         nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) +
      80             :                                           sizeof(struct wpabuf) +
      81        8908 :                                           buf->used + add_len);
      82        8908 :                         if (nbuf == NULL)
      83           0 :                                 return -1;
      84        8908 :                         trace = (struct wpabuf_trace *) nbuf;
      85        8908 :                         buf = (struct wpabuf *) (trace + 1);
      86        8908 :                         os_memset(nbuf + sizeof(struct wpabuf_trace) +
      87             :                                   sizeof(struct wpabuf) + buf->used, 0,
      88             :                                   add_len);
      89             : #else /* WPA_TRACE */
      90             :                         nbuf = os_realloc(buf, sizeof(struct wpabuf) +
      91             :                                           buf->used + add_len);
      92             :                         if (nbuf == NULL)
      93             :                                 return -1;
      94             :                         buf = (struct wpabuf *) nbuf;
      95             :                         os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0,
      96             :                                   add_len);
      97             : #endif /* WPA_TRACE */
      98        8908 :                         buf->buf = (u8 *) (buf + 1);
      99        8908 :                         *_buf = buf;
     100             :                 }
     101        8908 :                 buf->size = buf->used + add_len;
     102             :         }
     103             : 
     104       10251 :         return 0;
     105             : }
     106             : 
     107             : 
     108             : /**
     109             :  * wpabuf_alloc - Allocate a wpabuf of the given size
     110             :  * @len: Length for the allocated buffer
     111             :  * Returns: Buffer to the allocated wpabuf or %NULL on failure
     112             :  */
     113       83196 : struct wpabuf * wpabuf_alloc(size_t len)
     114             : {
     115             : #ifdef WPA_TRACE
     116       83196 :         struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
     117             :                                                sizeof(struct wpabuf) + len);
     118             :         struct wpabuf *buf;
     119       83196 :         if (trace == NULL)
     120           0 :                 return NULL;
     121       83196 :         trace->magic = WPABUF_MAGIC;
     122       83196 :         buf = (struct wpabuf *) (trace + 1);
     123             : #else /* WPA_TRACE */
     124             :         struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len);
     125             :         if (buf == NULL)
     126             :                 return NULL;
     127             : #endif /* WPA_TRACE */
     128             : 
     129       83196 :         buf->size = len;
     130       83196 :         buf->buf = (u8 *) (buf + 1);
     131       83196 :         return buf;
     132             : }
     133             : 
     134             : 
     135         121 : struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len)
     136             : {
     137             : #ifdef WPA_TRACE
     138         121 :         struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
     139             :                                                sizeof(struct wpabuf));
     140             :         struct wpabuf *buf;
     141         121 :         if (trace == NULL)
     142           0 :                 return NULL;
     143         121 :         trace->magic = WPABUF_MAGIC;
     144         121 :         buf = (struct wpabuf *) (trace + 1);
     145             : #else /* WPA_TRACE */
     146             :         struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf));
     147             :         if (buf == NULL)
     148             :                 return NULL;
     149             : #endif /* WPA_TRACE */
     150             : 
     151         121 :         buf->size = len;
     152         121 :         buf->used = len;
     153         121 :         buf->buf = data;
     154         121 :         buf->flags |= WPABUF_FLAG_EXT_DATA;
     155             : 
     156         121 :         return buf;
     157             : }
     158             : 
     159             : 
     160       10956 : struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len)
     161             : {
     162       10956 :         struct wpabuf *buf = wpabuf_alloc(len);
     163       10956 :         if (buf)
     164       10956 :                 wpabuf_put_data(buf, data, len);
     165       10956 :         return buf;
     166             : }
     167             : 
     168             : 
     169       15772 : struct wpabuf * wpabuf_dup(const struct wpabuf *src)
     170             : {
     171       15772 :         struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src));
     172       15772 :         if (buf)
     173       15772 :                 wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src));
     174       15772 :         return buf;
     175             : }
     176             : 
     177             : 
     178             : /**
     179             :  * wpabuf_free - Free a wpabuf
     180             :  * @buf: wpabuf buffer
     181             :  */
     182      181505 : void wpabuf_free(struct wpabuf *buf)
     183             : {
     184             : #ifdef WPA_TRACE
     185             :         struct wpabuf_trace *trace;
     186      181505 :         if (buf == NULL)
     187      279693 :                 return;
     188       83317 :         trace = wpabuf_get_trace(buf);
     189       83317 :         if (trace->magic != WPABUF_MAGIC) {
     190           0 :                 wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x",
     191             :                            trace->magic);
     192           0 :                 wpa_trace_show("wpabuf_free magic mismatch");
     193           0 :                 abort();
     194             :         }
     195       83317 :         if (buf->flags & WPABUF_FLAG_EXT_DATA)
     196         121 :                 os_free(buf->buf);
     197       83317 :         os_free(trace);
     198             : #else /* WPA_TRACE */
     199             :         if (buf == NULL)
     200             :                 return;
     201             :         if (buf->flags & WPABUF_FLAG_EXT_DATA)
     202             :                 os_free(buf->buf);
     203             :         os_free(buf);
     204             : #endif /* WPA_TRACE */
     205             : }
     206             : 
     207             : 
     208      608527 : void * wpabuf_put(struct wpabuf *buf, size_t len)
     209             : {
     210      608527 :         void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
     211      608527 :         buf->used += len;
     212      608527 :         if (buf->used > buf->size) {
     213           0 :                 wpabuf_overflow(buf, len);
     214             :         }
     215      608527 :         return tmp;
     216             : }
     217             : 
     218             : 
     219             : /**
     220             :  * wpabuf_concat - Concatenate two buffers into a newly allocated one
     221             :  * @a: First buffer
     222             :  * @b: Second buffer
     223             :  * Returns: wpabuf with concatenated a + b data or %NULL on failure
     224             :  *
     225             :  * Both buffers a and b will be freed regardless of the return value. Input
     226             :  * buffers can be %NULL which is interpreted as an empty buffer.
     227             :  */
     228         118 : struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
     229             : {
     230         118 :         struct wpabuf *n = NULL;
     231         118 :         size_t len = 0;
     232             : 
     233         118 :         if (b == NULL)
     234           0 :                 return a;
     235             : 
     236         118 :         if (a)
     237          43 :                 len += wpabuf_len(a);
     238         118 :         if (b)
     239         118 :                 len += wpabuf_len(b);
     240             : 
     241         118 :         n = wpabuf_alloc(len);
     242         118 :         if (n) {
     243         118 :                 if (a)
     244          43 :                         wpabuf_put_buf(n, a);
     245         118 :                 if (b)
     246         118 :                         wpabuf_put_buf(n, b);
     247             :         }
     248             : 
     249         118 :         wpabuf_free(a);
     250         118 :         wpabuf_free(b);
     251             : 
     252         118 :         return n;
     253             : }
     254             : 
     255             : 
     256             : /**
     257             :  * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length
     258             :  * @buf: Buffer to be padded
     259             :  * @len: Length for the padded buffer
     260             :  * Returns: wpabuf padded to len octets or %NULL on failure
     261             :  *
     262             :  * If buf is longer than len octets or of same size, it will be returned as-is.
     263             :  * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed
     264             :  * by the source data. The source buffer will be freed on error, i.e., caller
     265             :  * will only be responsible on freeing the returned buffer. If buf is %NULL,
     266             :  * %NULL will be returned.
     267             :  */
     268         743 : struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len)
     269             : {
     270             :         struct wpabuf *ret;
     271             :         size_t blen;
     272             : 
     273         743 :         if (buf == NULL)
     274           0 :                 return NULL;
     275             : 
     276         743 :         blen = wpabuf_len(buf);
     277         743 :         if (blen >= len)
     278         739 :                 return buf;
     279             : 
     280           4 :         ret = wpabuf_alloc(len);
     281           4 :         if (ret) {
     282           4 :                 os_memset(wpabuf_put(ret, len - blen), 0, len - blen);
     283           4 :                 wpabuf_put_buf(ret, buf);
     284             :         }
     285           4 :         wpabuf_free(buf);
     286             : 
     287           4 :         return ret;
     288             : }
     289             : 
     290             : 
     291        5108 : void wpabuf_printf(struct wpabuf *buf, char *fmt, ...)
     292             : {
     293             :         va_list ap;
     294        5108 :         void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
     295             :         int res;
     296             : 
     297        5108 :         va_start(ap, fmt);
     298        5108 :         res = vsnprintf(tmp, buf->size - buf->used, fmt, ap);
     299        5108 :         va_end(ap);
     300        5108 :         if (res < 0 || (size_t) res >= buf->size - buf->used)
     301           0 :                 wpabuf_overflow(buf, res);
     302        5108 :         buf->used += res;
     303        5108 : }

Generated by: LCOV version 1.10