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 1422976643 Lines: 104 128 81.2 %
Date: 2015-02-03 Functions: 12 13 92.3 %

          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      159170 : static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf)
      23             : {
      24      159170 :         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       28381 : int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
      48             : {
      49       28381 :         struct wpabuf *buf = *_buf;
      50             : #ifdef WPA_TRACE
      51             :         struct wpabuf_trace *trace;
      52             : #endif /* WPA_TRACE */
      53             : 
      54       28381 :         if (buf == NULL) {
      55       10598 :                 *_buf = wpabuf_alloc(add_len);
      56       10598 :                 return *_buf == NULL ? -1 : 0;
      57             :         }
      58             : 
      59             : #ifdef WPA_TRACE
      60       17783 :         trace = wpabuf_get_trace(buf);
      61       17783 :         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       17783 :         if (buf->used + add_len > buf->size) {
      70             :                 unsigned char *nbuf;
      71       13776 :                 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       13776 :                         nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) +
      80             :                                           sizeof(struct wpabuf) +
      81       13776 :                                           buf->used + add_len);
      82       13776 :                         if (nbuf == NULL)
      83           1 :                                 return -1;
      84       13775 :                         trace = (struct wpabuf_trace *) nbuf;
      85       13775 :                         buf = (struct wpabuf *) (trace + 1);
      86       13775 :                         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       13775 :                         buf->buf = (u8 *) (buf + 1);
      99       13775 :                         *_buf = buf;
     100             :                 }
     101       13775 :                 buf->size = buf->used + add_len;
     102             :         }
     103             : 
     104       17782 :         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      141274 : struct wpabuf * wpabuf_alloc(size_t len)
     114             : {
     115             : #ifdef WPA_TRACE
     116      141274 :         struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
     117             :                                                sizeof(struct wpabuf) + len);
     118             :         struct wpabuf *buf;
     119      141274 :         if (trace == NULL)
     120          27 :                 return NULL;
     121      141247 :         trace->magic = WPABUF_MAGIC;
     122      141247 :         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      141247 :         buf->size = len;
     130      141247 :         buf->buf = (u8 *) (buf + 1);
     131      141247 :         return buf;
     132             : }
     133             : 
     134             : 
     135         141 : struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len)
     136             : {
     137             : #ifdef WPA_TRACE
     138         141 :         struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
     139             :                                                sizeof(struct wpabuf));
     140             :         struct wpabuf *buf;
     141         141 :         if (trace == NULL)
     142           1 :                 return NULL;
     143         140 :         trace->magic = WPABUF_MAGIC;
     144         140 :         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         140 :         buf->size = len;
     152         140 :         buf->used = len;
     153         140 :         buf->buf = data;
     154         140 :         buf->flags |= WPABUF_FLAG_EXT_DATA;
     155             : 
     156         140 :         return buf;
     157             : }
     158             : 
     159             : 
     160       20594 : struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len)
     161             : {
     162       20594 :         struct wpabuf *buf = wpabuf_alloc(len);
     163       20594 :         if (buf)
     164       20587 :                 wpabuf_put_data(buf, data, len);
     165       20594 :         return buf;
     166             : }
     167             : 
     168             : 
     169       27174 : struct wpabuf * wpabuf_dup(const struct wpabuf *src)
     170             : {
     171       27174 :         struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src));
     172       27174 :         if (buf)
     173       27168 :                 wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src));
     174       27174 :         return buf;
     175             : }
     176             : 
     177             : 
     178             : /**
     179             :  * wpabuf_free - Free a wpabuf
     180             :  * @buf: wpabuf buffer
     181             :  */
     182      358914 : void wpabuf_free(struct wpabuf *buf)
     183             : {
     184             : #ifdef WPA_TRACE
     185             :         struct wpabuf_trace *trace;
     186      358914 :         if (buf == NULL)
     187      576441 :                 return;
     188      141387 :         trace = wpabuf_get_trace(buf);
     189      141387 :         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      141387 :         if (buf->flags & WPABUF_FLAG_EXT_DATA)
     196         140 :                 os_free(buf->buf);
     197      141387 :         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          18 : void wpabuf_clear_free(struct wpabuf *buf)
     209             : {
     210          18 :         if (buf) {
     211           0 :                 os_memset(wpabuf_mhead(buf), 0, wpabuf_len(buf));
     212           0 :                 wpabuf_free(buf);
     213             :         }
     214          18 : }
     215             : 
     216             : 
     217     1004391 : void * wpabuf_put(struct wpabuf *buf, size_t len)
     218             : {
     219     1004391 :         void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
     220     1004391 :         buf->used += len;
     221     1004391 :         if (buf->used > buf->size) {
     222           0 :                 wpabuf_overflow(buf, len);
     223             :         }
     224     1004391 :         return tmp;
     225             : }
     226             : 
     227             : 
     228             : /**
     229             :  * wpabuf_concat - Concatenate two buffers into a newly allocated one
     230             :  * @a: First buffer
     231             :  * @b: Second buffer
     232             :  * Returns: wpabuf with concatenated a + b data or %NULL on failure
     233             :  *
     234             :  * Both buffers a and b will be freed regardless of the return value. Input
     235             :  * buffers can be %NULL which is interpreted as an empty buffer.
     236             :  */
     237         163 : struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
     238             : {
     239         163 :         struct wpabuf *n = NULL;
     240         163 :         size_t len = 0;
     241             : 
     242         163 :         if (b == NULL)
     243           0 :                 return a;
     244             : 
     245         163 :         if (a)
     246          77 :                 len += wpabuf_len(a);
     247         163 :         if (b)
     248         163 :                 len += wpabuf_len(b);
     249             : 
     250         163 :         n = wpabuf_alloc(len);
     251         163 :         if (n) {
     252         163 :                 if (a)
     253          77 :                         wpabuf_put_buf(n, a);
     254         163 :                 if (b)
     255         163 :                         wpabuf_put_buf(n, b);
     256             :         }
     257             : 
     258         163 :         wpabuf_free(a);
     259         163 :         wpabuf_free(b);
     260             : 
     261         163 :         return n;
     262             : }
     263             : 
     264             : 
     265             : /**
     266             :  * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length
     267             :  * @buf: Buffer to be padded
     268             :  * @len: Length for the padded buffer
     269             :  * Returns: wpabuf padded to len octets or %NULL on failure
     270             :  *
     271             :  * If buf is longer than len octets or of same size, it will be returned as-is.
     272             :  * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed
     273             :  * by the source data. The source buffer will be freed on error, i.e., caller
     274             :  * will only be responsible on freeing the returned buffer. If buf is %NULL,
     275             :  * %NULL will be returned.
     276             :  */
     277        1057 : struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len)
     278             : {
     279             :         struct wpabuf *ret;
     280             :         size_t blen;
     281             : 
     282        1057 :         if (buf == NULL)
     283           0 :                 return NULL;
     284             : 
     285        1057 :         blen = wpabuf_len(buf);
     286        1057 :         if (blen >= len)
     287        1052 :                 return buf;
     288             : 
     289           5 :         ret = wpabuf_alloc(len);
     290           5 :         if (ret) {
     291           5 :                 os_memset(wpabuf_put(ret, len - blen), 0, len - blen);
     292           5 :                 wpabuf_put_buf(ret, buf);
     293             :         }
     294           5 :         wpabuf_free(buf);
     295             : 
     296           5 :         return ret;
     297             : }
     298             : 
     299             : 
     300       39844 : void wpabuf_printf(struct wpabuf *buf, char *fmt, ...)
     301             : {
     302             :         va_list ap;
     303       39844 :         void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
     304             :         int res;
     305             : 
     306       39844 :         va_start(ap, fmt);
     307       39844 :         res = vsnprintf(tmp, buf->size - buf->used, fmt, ap);
     308       39844 :         va_end(ap);
     309       39844 :         if (res < 0 || (size_t) res >= buf->size - buf->used)
     310           0 :                 wpabuf_overflow(buf, res);
     311       39844 :         buf->used += res;
     312       39844 : }

Generated by: LCOV version 1.10