00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016
00017 #include "common.h"
00018 #include "trace.h"
00019 #include "wpabuf.h"
00020
00021 #ifdef WPA_TRACE
00022 #define WPABUF_MAGIC 0x51a974e3
00023
00024 struct wpabuf_trace {
00025 unsigned int magic;
00026 };
00027
00028 static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf)
00029 {
00030 return (struct wpabuf_trace *)
00031 ((const u8 *) buf - sizeof(struct wpabuf_trace));
00032 }
00033 #endif
00034
00035
00036 static void wpabuf_overflow(const struct wpabuf *buf, size_t len)
00037 {
00038 #ifdef WPA_TRACE
00039 struct wpabuf_trace *trace = wpabuf_get_trace(buf);
00040 if (trace->magic != WPABUF_MAGIC) {
00041 wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x",
00042 trace->magic);
00043 }
00044 #endif
00045 wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu",
00046 buf, (unsigned long) buf->size, (unsigned long) buf->used,
00047 (unsigned long) len);
00048 wpa_trace_show("wpabuf overflow");
00049 abort();
00050 }
00051
00052
00053 int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
00054 {
00055 struct wpabuf *buf = *_buf;
00056 #ifdef WPA_TRACE
00057 struct wpabuf_trace *trace;
00058 #endif
00059
00060 if (buf == NULL) {
00061 *_buf = wpabuf_alloc(add_len);
00062 return *_buf == NULL ? -1 : 0;
00063 }
00064
00065 #ifdef WPA_TRACE
00066 trace = wpabuf_get_trace(buf);
00067 if (trace->magic != WPABUF_MAGIC) {
00068 wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x",
00069 trace->magic);
00070 wpa_trace_show("wpabuf_resize invalid magic");
00071 abort();
00072 }
00073 #endif
00074
00075 if (buf->used + add_len > buf->size) {
00076 unsigned char *nbuf;
00077 if (buf->ext_data) {
00078 nbuf = os_realloc(buf->ext_data, buf->used + add_len);
00079 if (nbuf == NULL)
00080 return -1;
00081 os_memset(nbuf + buf->used, 0, add_len);
00082 buf->ext_data = nbuf;
00083 } else {
00084 #ifdef WPA_TRACE
00085 nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) +
00086 sizeof(struct wpabuf) +
00087 buf->used + add_len);
00088 if (nbuf == NULL)
00089 return -1;
00090 trace = (struct wpabuf_trace *) nbuf;
00091 buf = (struct wpabuf *) (trace + 1);
00092 os_memset(nbuf + sizeof(struct wpabuf_trace) +
00093 sizeof(struct wpabuf) + buf->used, 0,
00094 add_len);
00095 #else
00096 nbuf = os_realloc(buf, sizeof(struct wpabuf) +
00097 buf->used + add_len);
00098 if (nbuf == NULL)
00099 return -1;
00100 buf = (struct wpabuf *) nbuf;
00101 os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0,
00102 add_len);
00103 #endif
00104 *_buf = buf;
00105 }
00106 buf->size = buf->used + add_len;
00107 }
00108
00109 return 0;
00110 }
00111
00112
00118 struct wpabuf * wpabuf_alloc(size_t len)
00119 {
00120 #ifdef WPA_TRACE
00121 struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
00122 sizeof(struct wpabuf) + len);
00123 struct wpabuf *buf;
00124 if (trace == NULL)
00125 return NULL;
00126 trace->magic = WPABUF_MAGIC;
00127 buf = (struct wpabuf *) (trace + 1);
00128 #else
00129 struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len);
00130 if (buf == NULL)
00131 return NULL;
00132 #endif
00133
00134 buf->size = len;
00135 return buf;
00136 }
00137
00138
00139 struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len)
00140 {
00141 #ifdef WPA_TRACE
00142 struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
00143 sizeof(struct wpabuf));
00144 struct wpabuf *buf;
00145 if (trace == NULL)
00146 return NULL;
00147 trace->magic = WPABUF_MAGIC;
00148 buf = (struct wpabuf *) (trace + 1);
00149 #else
00150 struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf));
00151 if (buf == NULL)
00152 return NULL;
00153 #endif
00154
00155 buf->size = len;
00156 buf->used = len;
00157 buf->ext_data = data;
00158
00159 return buf;
00160 }
00161
00162
00163 struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len)
00164 {
00165 struct wpabuf *buf = wpabuf_alloc(len);
00166 if (buf)
00167 wpabuf_put_data(buf, data, len);
00168 return buf;
00169 }
00170
00171
00172 struct wpabuf * wpabuf_dup(const struct wpabuf *src)
00173 {
00174 struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src));
00175 if (buf)
00176 wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src));
00177 return buf;
00178 }
00179
00180
00185 void wpabuf_free(struct wpabuf *buf)
00186 {
00187 #ifdef WPA_TRACE
00188 struct wpabuf_trace *trace;
00189 if (buf == NULL)
00190 return;
00191 trace = wpabuf_get_trace(buf);
00192 if (trace->magic != WPABUF_MAGIC) {
00193 wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x",
00194 trace->magic);
00195 wpa_trace_show("wpabuf_free magic mismatch");
00196 abort();
00197 }
00198 os_free(buf->ext_data);
00199 os_free(trace);
00200 #else
00201 if (buf == NULL)
00202 return;
00203 os_free(buf->ext_data);
00204 os_free(buf);
00205 #endif
00206 }
00207
00208
00209 void * wpabuf_put(struct wpabuf *buf, size_t len)
00210 {
00211 void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
00212 buf->used += len;
00213 if (buf->used > buf->size) {
00214 wpabuf_overflow(buf, len);
00215 }
00216 return tmp;
00217 }
00218
00219
00229 struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
00230 {
00231 struct wpabuf *n = NULL;
00232 size_t len = 0;
00233
00234 if (b == NULL)
00235 return a;
00236
00237 if (a)
00238 len += wpabuf_len(a);
00239 if (b)
00240 len += wpabuf_len(b);
00241
00242 n = wpabuf_alloc(len);
00243 if (n) {
00244 if (a)
00245 wpabuf_put_buf(n, a);
00246 if (b)
00247 wpabuf_put_buf(n, b);
00248 }
00249
00250 wpabuf_free(a);
00251 wpabuf_free(b);
00252
00253 return n;
00254 }
00255
00256
00269 struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len)
00270 {
00271 struct wpabuf *ret;
00272 size_t blen;
00273
00274 if (buf == NULL)
00275 return NULL;
00276
00277 blen = wpabuf_len(buf);
00278 if (blen >= len)
00279 return buf;
00280
00281 ret = wpabuf_alloc(len);
00282 if (ret) {
00283 os_memset(wpabuf_put(ret, len - blen), 0, len - blen);
00284 wpabuf_put_buf(ret, buf);
00285 }
00286 wpabuf_free(buf);
00287
00288 return ret;
00289 }
00290
00291
00292 void wpabuf_printf(struct wpabuf *buf, char *fmt, ...)
00293 {
00294 va_list ap;
00295 void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
00296 int res;
00297
00298 va_start(ap, fmt);
00299 res = vsnprintf(tmp, buf->size - buf->used, fmt, ap);
00300 va_end(ap);
00301 if (res < 0 || (size_t) res >= buf->size - buf->used)
00302 wpabuf_overflow(buf, res);
00303 buf->used += res;
00304 }