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