1 /****************************************************************************\ 2 * pack.h - definitions for lowest level un/pack functions. all functions 3 * utilize a Buf structure. Call init_buf, un/pack, and free_buf 4 ***************************************************************************** 5 * Copyright (C) 2002-2007 The Regents of the University of California. 6 * Copyright (C) 2008 Lawrence Livermore National Security. 7 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 8 * Written by Kevin Tew <tew1@llnl.gov>, Morris Jette <jette1@llnl.gov>, et. al. 9 * CODE-OCEC-09-009. All rights reserved. 10 * 11 * This file is part of Slurm, a resource management program. 12 * For details, see <https://slurm.schedmd.com/>. 13 * Please also read the included file: DISCLAIMER. 14 * 15 * Slurm is free software; you can redistribute it and/or modify it under 16 * the terms of the GNU General Public License as published by the Free 17 * Software Foundation; either version 2 of the License, or (at your option) 18 * any later version. 19 * 20 * In addition, as a special exception, the copyright holders give permission 21 * to link the code of portions of this program with the OpenSSL library under 22 * certain conditions as described in each individual source file, and 23 * distribute linked combinations including the two. You must obey the GNU 24 * General Public License in all respects for all of the code used other than 25 * OpenSSL. If you modify file(s) with this exception, you may extend this 26 * exception to your version of the file(s), but you are not obligated to do 27 * so. If you do not wish to do so, delete this exception statement from your 28 * version. If you delete this exception statement from all source files in 29 * the program, then also delete it here. 30 * 31 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY 32 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 33 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 34 * details. 35 * 36 * You should have received a copy of the GNU General Public License along 37 * with Slurm; if not, write to the Free Software Foundation, Inc., 38 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 39 \****************************************************************************/ 40 41 #ifndef _PACK_INCLUDED 42 #define _PACK_INCLUDED 43 44 #include <assert.h> 45 #include <inttypes.h> 46 #include <time.h> 47 #include <stdbool.h> 48 #include <string.h> 49 50 #include "src/common/bitstring.h" 51 52 #define BUF_MAGIC 0x42554545 53 #define BUF_SIZE (16 * 1024) 54 #define MAX_BUF_SIZE ((uint32_t) 0xffff0000) /* avoid going over 32-bits */ 55 #define REASONABLE_BUF_SIZE ((uint32_t) 0xbfff4000) /* three-quarters of max */ 56 #define FLOAT_MULT 1000000 57 58 /* If we unpack a buffer that contains bad data, we want to avoid a memory 59 * allocation error due to array or buffer sizes that are unreasonably large */ 60 #define MAX_PACK_ARRAY_LEN (128 * 1024) 61 #define MAX_PACK_MEM_LEN (1024 * 1024 * 1024) 62 63 typedef struct slurm_buf { 64 uint32_t magic; 65 char *head; 66 uint32_t size; 67 uint32_t processed; 68 bool mmaped; 69 } buf_t; 70 71 typedef struct slurm_buf * Buf; 72 73 #define get_buf_data(__buf) (__buf->head) 74 #define get_buf_offset(__buf) (__buf->processed) 75 #define set_buf_offset(__buf,__val) (__buf->processed = __val) 76 #define remaining_buf(__buf) (__buf->size - __buf->processed) 77 #define size_buf(__buf) (__buf->size) 78 79 Buf create_buf (char *data, uint32_t size); 80 Buf create_mmap_buf(char *file); 81 void free_buf(Buf my_buf); 82 Buf init_buf(uint32_t size); 83 void grow_buf (Buf my_buf, uint32_t size); 84 void *xfer_buf_data(Buf my_buf); 85 86 void pack_time(time_t val, Buf buffer); 87 int unpack_time(time_t *valp, Buf buffer); 88 89 void packfloat(float val, Buf buffer); 90 int unpackfloat(float *valp, Buf buffer); 91 92 void packdouble(double val, Buf buffer); 93 int unpackdouble(double *valp, Buf buffer); 94 95 void packlongdouble(long double val, Buf buffer); 96 int unpacklongdouble(long double *valp, Buf buffer); 97 98 void pack64(uint64_t val, Buf buffer); 99 int unpack64(uint64_t *valp, Buf buffer); 100 101 void pack32(uint32_t val, Buf buffer); 102 int unpack32(uint32_t *valp, Buf buffer); 103 104 void pack16(uint16_t val, Buf buffer); 105 int unpack16(uint16_t *valp, Buf buffer); 106 107 void pack8(uint8_t val, Buf buffer); 108 int unpack8(uint8_t *valp, Buf buffer); 109 110 void packbool(bool val, Buf buffer); 111 int unpackbool(bool *valp, Buf buffer); 112 113 void pack16_array(uint16_t *valp, uint32_t size_val, Buf buffer); 114 int unpack16_array(uint16_t **valp, uint32_t* size_val, Buf buffer); 115 116 void pack32_array(uint32_t *valp, uint32_t size_val, Buf buffer); 117 int unpack32_array(uint32_t **valp, uint32_t* size_val, Buf buffer); 118 119 void pack64_array(uint64_t *valp, uint32_t size_val, Buf buffer); 120 int unpack64_array(uint64_t **valp, uint32_t* size_val, Buf buffer); 121 122 void pack64_array_as_32(uint64_t * valp, uint32_t size_val, Buf buffer); 123 int unpack64_array_from_32(uint64_t ** valp, uint32_t * size_val, Buf buffer); 124 125 void packdouble_array(double *valp, uint32_t size_val, Buf buffer); 126 int unpackdouble_array(double **valp, uint32_t* size_val, Buf buffer); 127 128 void packlongdouble_array(long double *valp, uint32_t size_val, Buf buffer); 129 int unpacklongdouble_array(long double **valp, uint32_t* size_val, 130 Buf buffer); 131 132 void packmem(char *valp, uint32_t size_val, Buf buffer); 133 int unpackmem(char *valp, uint32_t *size_valp, Buf buffer); 134 int unpackmem_ptr(char **valp, uint32_t *size_valp, Buf buffer); 135 int unpackmem_xmalloc(char **valp, uint32_t *size_valp, Buf buffer); 136 int unpackmem_malloc(char **valp, uint32_t *size_valp, Buf buffer); 137 138 int unpackstr_xmalloc_escaped(char **valp, uint32_t *size_valp, Buf buffer); 139 int unpackstr_xmalloc_chooser(char **valp, uint32_t *size_valp, Buf buffer); 140 141 void packstr_array(char **valp, uint32_t size_val, Buf buffer); 142 int unpackstr_array(char ***valp, uint32_t* size_val, Buf buffer); 143 144 void packmem_array(char *valp, uint32_t size_val, Buf buffer); 145 int unpackmem_array(char *valp, uint32_t size_valp, Buf buffer); 146 147 #define safe_unpack_time(valp,buf) do { \ 148 assert(sizeof(*valp) == sizeof(time_t)); \ 149 assert(buf->magic == BUF_MAGIC); \ 150 if (unpack_time(valp,buf)) \ 151 goto unpack_error; \ 152 } while (0) 153 154 #define safe_unpackfloat(valp,buf) do { \ 155 assert(sizeof(*valp) == sizeof(float)); \ 156 assert(buf->magic == BUF_MAGIC); \ 157 if (unpackfloat(valp,buf)) \ 158 goto unpack_error; \ 159 } while (0) 160 161 #define safe_unpackdouble(valp,buf) do { \ 162 assert(sizeof(*valp) == sizeof(double)); \ 163 assert(buf->magic == BUF_MAGIC); \ 164 if (unpackdouble(valp,buf)) \ 165 goto unpack_error; \ 166 } while (0) 167 168 #define safe_unpacklongdouble(valp,buf) do { \ 169 assert(sizeof(*valp) == sizeof(long double)); \ 170 assert(buf->magic == BUF_MAGIC); \ 171 if (unpacklongdouble(valp,buf)) \ 172 goto unpack_error; \ 173 } while (0) 174 175 #define safe_unpack64(valp,buf) do { \ 176 assert(sizeof(*valp) == sizeof(uint64_t)); \ 177 assert(buf->magic == BUF_MAGIC); \ 178 if (unpack64(valp,buf)) \ 179 goto unpack_error; \ 180 } while (0) 181 182 #define safe_unpack32(valp,buf) do { \ 183 assert(sizeof(*valp) == sizeof(uint32_t)); \ 184 assert(buf->magic == BUF_MAGIC); \ 185 if (unpack32(valp,buf)) \ 186 goto unpack_error; \ 187 } while (0) 188 189 #define safe_unpack16(valp,buf) do { \ 190 assert(sizeof(*valp) == sizeof(uint16_t)); \ 191 assert(buf->magic == BUF_MAGIC); \ 192 if (unpack16(valp,buf)) \ 193 goto unpack_error; \ 194 } while (0) 195 196 #define safe_unpack8(valp,buf) do { \ 197 assert(sizeof(*valp) == sizeof(uint8_t)); \ 198 assert(buf->magic == BUF_MAGIC); \ 199 if (unpack8(valp,buf)) \ 200 goto unpack_error; \ 201 } while (0) 202 203 #define safe_unpackbool(valp,buf) do { \ 204 assert(sizeof(*valp) == sizeof(bool)); \ 205 assert(buf->magic == BUF_MAGIC); \ 206 if (unpackbool(valp,buf)) \ 207 goto unpack_error; \ 208 } while (0) 209 210 #define safe_unpack16_array(valp,size_valp,buf) do { \ 211 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 212 assert(buf->magic == BUF_MAGIC); \ 213 if (unpack16_array(valp,size_valp,buf)) \ 214 goto unpack_error; \ 215 } while (0) 216 217 #define safe_unpack32_array(valp,size_valp,buf) do { \ 218 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 219 assert(buf->magic == BUF_MAGIC); \ 220 if (unpack32_array(valp,size_valp,buf)) \ 221 goto unpack_error; \ 222 } while (0) 223 224 #define safe_unpack64_array(valp,size_valp,buf) do { \ 225 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 226 assert(buf->magic == BUF_MAGIC); \ 227 if (unpack64_array(valp,size_valp,buf)) \ 228 goto unpack_error; \ 229 } while (0) 230 231 #define safe_unpack64_array_from_32(valp,size_valp,buf) do { \ 232 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 233 assert(buf->magic == BUF_MAGIC); \ 234 if (unpack64_array_from_32(valp,size_valp,buf)) \ 235 goto unpack_error; \ 236 } while (0) 237 238 #define safe_unpackdouble_array(valp,size_valp,buf) do { \ 239 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 240 assert(buf->magic == BUF_MAGIC); \ 241 if (unpackdouble_array(valp,size_valp,buf)) \ 242 goto unpack_error; \ 243 } while (0) 244 245 #define safe_unpacklongdouble_array(valp,size_valp,buf) do { \ 246 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 247 assert(buf->magic == BUF_MAGIC); \ 248 if (unpacklongdouble_array(valp,size_valp,buf)) \ 249 goto unpack_error; \ 250 } while (0) 251 252 #define safe_unpackmem(valp,size_valp,buf) do { \ 253 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 254 assert(buf->magic == BUF_MAGIC); \ 255 if (unpackmem(valp,size_valp,buf)) \ 256 goto unpack_error; \ 257 } while (0) 258 259 #define safe_unpackmem_ptr(valp,size_valp,buf) do { \ 260 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 261 assert(buf->magic == BUF_MAGIC); \ 262 if (unpackmem_ptr(valp,size_valp,buf)) \ 263 goto unpack_error; \ 264 } while (0) 265 266 #define safe_unpackmem_xmalloc(valp,size_valp,buf) do { \ 267 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 268 assert(buf->magic == BUF_MAGIC); \ 269 if (unpackmem_xmalloc(valp,size_valp,buf)) \ 270 goto unpack_error; \ 271 } while (0) 272 273 #define safe_unpackmem_malloc(valp,size_valp,buf) do { \ 274 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 275 assert(buf->magic == BUF_MAGIC); \ 276 if (unpackmem_malloc(valp,size_valp,buf)) \ 277 goto unpack_error; \ 278 } while (0) 279 280 #define packstr(str,buf) do { \ 281 uint32_t _size = 0; \ 282 if((char *)str != NULL) \ 283 _size = (uint32_t)strlen(str)+1; \ 284 assert(_size == 0 || str != NULL); \ 285 assert(_size <= 0xffffffff); \ 286 assert(buf->magic == BUF_MAGIC); \ 287 packmem(str,(uint32_t)_size,buf); \ 288 } while (0) 289 290 #define packnull(buf) do { \ 291 assert(buf != NULL); \ 292 assert(buf->magic == BUF_MAGIC); \ 293 packmem(NULL, 0, buf); \ 294 } while (0) 295 296 #define pack_bit_str_hex(bitmap,buf) do { \ 297 assert(buf->magic == BUF_MAGIC); \ 298 if (bitmap) { \ 299 char *_tmp_str; \ 300 uint32_t _size; \ 301 _tmp_str = bit_fmt_hexmask(bitmap); \ 302 _size = bit_size(bitmap); \ 303 pack32(_size, buf); \ 304 _size = strlen(_tmp_str)+1; \ 305 packmem(_tmp_str,_size,buf); \ 306 xfree(_tmp_str); \ 307 } else \ 308 pack32(NO_VAL, buf); \ 309 } while (0) 310 311 #define unpack_bit_str_hex(bitmap,buf) do { \ 312 char *tmp_str = NULL; \ 313 uint32_t _size, _tmp_uint32; \ 314 assert(*bitmap == NULL); \ 315 assert(buf->magic == BUF_MAGIC); \ 316 safe_unpack32(&_size, buf); \ 317 if (_size != NO_VAL) { \ 318 safe_unpackstr_xmalloc(&tmp_str, &_tmp_uint32, buf); \ 319 if (_size) { \ 320 *bitmap = bit_alloc(_size); \ 321 if (bit_unfmt_hexmask(*bitmap, tmp_str)) { \ 322 FREE_NULL_BITMAP(*bitmap); \ 323 xfree(tmp_str); \ 324 goto unpack_error; \ 325 } \ 326 } else \ 327 *bitmap = NULL; \ 328 xfree(tmp_str); \ 329 } else \ 330 *bitmap = NULL; \ 331 } while (0) 332 333 /* note: this would be faster if collapsed into a single function 334 * rather than a combination of unpack_bit_str_hex and bitstr2inx */ 335 #define unpack_bit_str_hex_as_inx(inx, buf) do { \ 336 bitstr_t *b = NULL; \ 337 unpack_bit_str_hex(&b, buf); \ 338 *inx = bitstr2inx(b); \ 339 FREE_NULL_BITMAP(b); \ 340 } while (0) 341 342 #define unpackstr_malloc \ 343 unpackmem_malloc 344 345 #define unpackstr_xmalloc \ 346 unpackmem_xmalloc 347 348 #define safe_unpackstr_malloc \ 349 safe_unpackmem_malloc 350 351 #define safe_unpackstr_xmalloc(valp, size_valp, buf) do { \ 352 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 353 assert(buf->magic == BUF_MAGIC); \ 354 if (unpackstr_xmalloc_chooser(valp, size_valp, buf)) \ 355 goto unpack_error; \ 356 } while (0) 357 358 #define safe_unpackstr_array(valp,size_valp,buf) do { \ 359 assert(sizeof(*size_valp) == sizeof(uint32_t)); \ 360 assert(buf->magic == BUF_MAGIC); \ 361 if (unpackstr_array(valp,size_valp,buf)) \ 362 goto unpack_error; \ 363 } while (0) 364 365 #define safe_unpackmem_array(valp,size,buf) do { \ 366 assert(valp != NULL); \ 367 assert(sizeof(size) == sizeof(uint32_t)); \ 368 assert(buf->magic == BUF_MAGIC); \ 369 if (unpackmem_array(valp,size,buf)) \ 370 goto unpack_error; \ 371 } while (0) 372 373 #define safe_xcalloc(p, cnt, sz) do { \ 374 size_t _cnt = cnt; \ 375 size_t _sz = sz; \ 376 if (!_cnt || !_sz) \ 377 p = NULL; \ 378 else if (!(p = try_xcalloc(_cnt, _sz))) \ 379 goto unpack_error; \ 380 } while (0) 381 382 #define safe_xmalloc(p, sz) do { \ 383 size_t _sz = sz; \ 384 if (!_sz) \ 385 p = NULL; \ 386 else if (!(p = try_xmalloc(_sz))) \ 387 goto unpack_error; \ 388 } while (0) 389 390 #define FREE_NULL_BUFFER(_X) \ 391 do { \ 392 if (_X) free_buf (_X); \ 393 _X = NULL; \ 394 } while (0) 395 396 #endif /* _PACK_INCLUDED */ 397