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 1443382998 Lines: 112 128 87.5 %
Date: 2015-09-27 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             : } __attribute__((aligned(8)));
      21             : 
      22      227116 : static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf)
      23             : {
      24      227116 :         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       47151 : int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
      48             : {
      49       47151 :         struct wpabuf *buf = *_buf;
      50             : #ifdef WPA_TRACE
      51             :         struct wpabuf_trace *trace;
      52             : #endif /* WPA_TRACE */
      53             : 
      54       47151 :         if (buf == NULL) {
      55       17661 :                 *_buf = wpabuf_alloc(add_len);
      56       17661 :                 return *_buf == NULL ? -1 : 0;
      57             :         }
      58             : 
      59             : #ifdef WPA_TRACE
      60       29490 :         trace = wpabuf_get_trace(buf);
      61       29490 :         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       29490 :         if (buf->used + add_len > buf->size) {
      70             :                 unsigned char *nbuf;
      71       23178 :                 if (buf->flags & WPABUF_FLAG_EXT_DATA) {
      72           1 :                         nbuf = os_realloc(buf->buf, buf->used + add_len);
      73           1 :                         if (nbuf == NULL)
      74           0 :                                 return -1;
      75           1 :                         os_memset(nbuf + buf->used, 0, add_len);
      76           1 :                         buf->buf = nbuf;
      77             :                 } else {
      78             : #ifdef WPA_TRACE
      79       23177 :                         nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) +
      80             :                                           sizeof(struct wpabuf) +
      81       23177 :                                           buf->used + add_len);
      82       23177 :                         if (nbuf == NULL)
      83           8 :                                 return -1;
      84       23169 :                         trace = (struct wpabuf_trace *) nbuf;
      85       23169 :                         buf = (struct wpabuf *) (trace + 1);
      86       23169 :                         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       23169 :                         buf->buf = (u8 *) (buf + 1);
      99       23169 :                         *_buf = buf;
     100             :                 }
     101       23170 :                 buf->size = buf->used + add_len;
     102             :         }
     103             : 
     104       29482 :         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      197369 : struct wpabuf * wpabuf_alloc(size_t len)
     114             : {
     115             : #ifdef WPA_TRACE
     116      197369 :         struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
     117             :                                                sizeof(struct wpabuf) + len);
     118             :         struct wpabuf *buf;
     119      197369 :         if (trace == NULL)
     120         113 :                 return NULL;
     121      197256 :         trace->magic = WPABUF_MAGIC;
     122      197256 :         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      197256 :         buf->size = len;
     130      197256 :         buf->buf = (u8 *) (buf + 1);
     131      197256 :         return buf;
     132             : }
     133             : 
     134             : 
     135         372 : struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len)
     136             : {
     137             : #ifdef WPA_TRACE
     138         372 :         struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
     139             :                                                sizeof(struct wpabuf));
     140             :         struct wpabuf *buf;
     141         372 :         if (trace == NULL)
     142           2 :                 return NULL;
     143         370 :         trace->magic = WPABUF_MAGIC;
     144         370 :         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         370 :         buf->size = len;
     152         370 :         buf->used = len;
     153         370 :         buf->buf = data;
     154         370 :         buf->flags |= WPABUF_FLAG_EXT_DATA;
     155             : 
     156         370 :         return buf;
     157             : }
     158             : 
     159             : 
     160       25668 : struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len)
     161             : {
     162       25668 :         struct wpabuf *buf = wpabuf_alloc(len);
     163       25668 :         if (buf)
     164       25660 :                 wpabuf_put_data(buf, data, len);
     165       25668 :         return buf;
     166             : }
     167             : 
     168             : 
     169       34371 : struct wpabuf * wpabuf_dup(const struct wpabuf *src)
     170             : {
     171       34371 :         struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src));
     172       34371 :         if (buf)
     173       34359 :                 wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src));
     174       34371 :         return buf;
     175             : }
     176             : 
     177             : 
     178             : /**
     179             :  * wpabuf_free - Free a wpabuf
     180             :  * @buf: wpabuf buffer
     181             :  */
     182      536340 : void wpabuf_free(struct wpabuf *buf)
     183             : {
     184             : #ifdef WPA_TRACE
     185             :         struct wpabuf_trace *trace;
     186      536340 :         if (buf == NULL)
     187      875054 :                 return;
     188      197626 :         trace = wpabuf_get_trace(buf);
     189      197626 :         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      197626 :         if (buf->flags & WPABUF_FLAG_EXT_DATA)
     196         370 :                 os_free(buf->buf);
     197      197626 :         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          36 : void wpabuf_clear_free(struct wpabuf *buf)
     209             : {
     210          36 :         if (buf) {
     211           3 :                 os_memset(wpabuf_mhead(buf), 0, wpabuf_len(buf));
     212           3 :                 wpabuf_free(buf);
     213             :         }
     214          36 : }
     215             : 
     216             : 
     217     1381856 : void * wpabuf_put(struct wpabuf *buf, size_t len)
     218             : {
     219     1381856 :         void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
     220     1381856 :         buf->used += len;
     221     1381856 :         if (buf->used > buf->size) {
     222           0 :                 wpabuf_overflow(buf, len);
     223             :         }
     224     1381856 :         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         173 : struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
     238             : {
     239         173 :         struct wpabuf *n = NULL;
     240         173 :         size_t len = 0;
     241             : 
     242         173 :         if (b == NULL)
     243           1 :                 return a;
     244             : 
     245         172 :         if (a)
     246          81 :                 len += wpabuf_len(a);
     247         172 :         if (b)
     248         172 :                 len += wpabuf_len(b);
     249             : 
     250         172 :         n = wpabuf_alloc(len);
     251         172 :         if (n) {
     252         172 :                 if (a)
     253          81 :                         wpabuf_put_buf(n, a);
     254         172 :                 if (b)
     255         172 :                         wpabuf_put_buf(n, b);
     256             :         }
     257             : 
     258         172 :         wpabuf_free(a);
     259         172 :         wpabuf_free(b);
     260             : 
     261         172 :         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        1612 : struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len)
     278             : {
     279             :         struct wpabuf *ret;
     280             :         size_t blen;
     281             : 
     282        1612 :         if (buf == NULL)
     283           4 :                 return NULL;
     284             : 
     285        1608 :         blen = wpabuf_len(buf);
     286        1608 :         if (blen >= len)
     287        1601 :                 return buf;
     288             : 
     289           7 :         ret = wpabuf_alloc(len);
     290           7 :         if (ret) {
     291           7 :                 os_memset(wpabuf_put(ret, len - blen), 0, len - blen);
     292           7 :                 wpabuf_put_buf(ret, buf);
     293             :         }
     294           7 :         wpabuf_free(buf);
     295             : 
     296           7 :         return ret;
     297             : }
     298             : 
     299             : 
     300       61952 : void wpabuf_printf(struct wpabuf *buf, char *fmt, ...)
     301             : {
     302             :         va_list ap;
     303       61952 :         void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
     304             :         int res;
     305             : 
     306       61952 :         va_start(ap, fmt);
     307       61952 :         res = vsnprintf(tmp, buf->size - buf->used, fmt, ap);
     308       61952 :         va_end(ap);
     309       61952 :         if (res < 0 || (size_t) res >= buf->size - buf->used)
     310           0 :                 wpabuf_overflow(buf, res);
     311       61952 :         buf->used += res;
     312       61952 : }

Generated by: LCOV version 1.10