wpabuf.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Dynamic data buffer 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "trace.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpabuf.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WPABUF_MAGIC 0x51a974e3 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf_trace { 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int magic; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf) 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (struct wpabuf_trace *) 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((const u8 *) buf - sizeof(struct wpabuf_trace)); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpabuf_overflow(const struct wpabuf *buf, size_t len) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf_trace *trace = wpabuf_get_trace(buf); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trace->magic != WPABUF_MAGIC) { 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace->magic); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu", 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, (unsigned long) buf->size, (unsigned long) buf->used, 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_show("wpabuf overflow"); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort(); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpabuf_resize(struct wpabuf **_buf, size_t add_len) 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf = *_buf; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf_trace *trace; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *_buf = wpabuf_alloc(add_len); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return *_buf == NULL ? -1 : 0; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace = wpabuf_get_trace(buf); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trace->magic != WPABUF_MAGIC) { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace->magic); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_show("wpabuf_resize invalid magic"); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort(); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf->used + add_len > buf->size) { 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *nbuf; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf->ext_data) { 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nbuf = os_realloc(buf->ext_data, buf->used + add_len); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nbuf == NULL) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nbuf + buf->used, 0, add_len); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->ext_data = nbuf; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) + 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpabuf) + 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->used + add_len); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nbuf == NULL) 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace = (struct wpabuf_trace *) nbuf; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (struct wpabuf *) (trace + 1); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nbuf + sizeof(struct wpabuf_trace) + 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpabuf) + buf->used, 0, 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_len); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE */ 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nbuf = os_realloc(buf, sizeof(struct wpabuf) + 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->used + add_len); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nbuf == NULL) 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (struct wpabuf *) nbuf; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0, 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_len); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *_buf = buf; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->size = buf->used + add_len; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpabuf_alloc - Allocate a wpabuf of the given size 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length for the allocated buffer 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Buffer to the allocated wpabuf or %NULL on failure 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpabuf_alloc(size_t len) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpabuf) + len); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trace == NULL) 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace->magic = WPABUF_MAGIC; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (struct wpabuf *) (trace + 1); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE */ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->size = len; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len) 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpabuf)); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trace == NULL) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace->magic = WPABUF_MAGIC; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (struct wpabuf *) (trace + 1); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE */ 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf)); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->size = len; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->used = len; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->ext_data = data; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpabuf_alloc_copy(const void *data, size_t len) 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf = wpabuf_alloc(len); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, data, len); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpabuf_dup(const struct wpabuf *src) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src)); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src)); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpabuf_free - Free a wpabuf 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: wpabuf buffer 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpabuf_free(struct wpabuf *buf) 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf_trace *trace; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace = wpabuf_get_trace(buf); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trace->magic != WPABUF_MAGIC) { 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x", 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trace->magic); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_show("wpabuf_free magic mismatch"); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort(); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf->ext_data); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(trace); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE */ 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf->ext_data); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * wpabuf_put(struct wpabuf *buf, size_t len) 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->used += len; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf->used > buf->size) { 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_overflow(buf, len); 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tmp; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpabuf_concat - Concatenate two buffers into a newly allocated one 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @a: First buffer 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @b: Second buffer 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: wpabuf with concatenated a + b data or %NULL on failure 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Both buffers a and b will be freed regardless of the return value. Input 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * buffers can be %NULL which is interpreted as an empty buffer. 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b) 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *n = NULL; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = 0; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (b == NULL) 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return a; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a) 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += wpabuf_len(a); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (b) 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += wpabuf_len(b); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt n = wpabuf_alloc(len); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (n) { 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(n, a); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (b) 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(n, b); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(a); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(b); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return n; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer to be padded 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length for the padded buffer 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: wpabuf padded to len octets or %NULL on failure 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If buf is longer than len octets or of same size, it will be returned as-is. 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * by the source data. The source buffer will be freed on error, i.e., caller 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will only be responsible on freeing the returned buffer. If buf is %NULL, 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * %NULL will be returned. 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len) 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ret; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t blen; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blen = wpabuf_len(buf); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blen >= len) 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpabuf_alloc(len); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(wpabuf_put(ret, len - blen), 0, len - blen); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(ret, buf); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpabuf_printf(struct wpabuf *buf, char *fmt, ...) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_list ap; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_start(ap, fmt); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = vsnprintf(tmp, buf->size - buf->used, fmt, ap); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_end(ap); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0 || (size_t) res >= buf->size - buf->used) 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_overflow(buf, res); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf->used += res; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 305