$search
00001 /* 00002 * Dynamic data buffer 00003 * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 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 /* WPA_TRACE */ 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 /* WPA_TRACE */ 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 /* WPA_TRACE */ 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 /* WPA_TRACE */ 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 /* WPA_TRACE */ 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 /* WPA_TRACE */ 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 /* WPA_TRACE */ 00129 struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len); 00130 if (buf == NULL) 00131 return NULL; 00132 #endif /* WPA_TRACE */ 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 /* WPA_TRACE */ 00150 struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf)); 00151 if (buf == NULL) 00152 return NULL; 00153 #endif /* WPA_TRACE */ 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 /* WPA_TRACE */ 00201 if (buf == NULL) 00202 return; 00203 os_free(buf->ext_data); 00204 os_free(buf); 00205 #endif /* WPA_TRACE */ 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 }