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