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