11de50e9fSSam Leffler /*- 21de50e9fSSam Leffler * Copyright (c) 2003, 2004 David Young. All rights reserved. 31de50e9fSSam Leffler * 41de50e9fSSam Leffler * Redistribution and use in source and binary forms, with or without 51de50e9fSSam Leffler * modification, are permitted provided that the following conditions 61de50e9fSSam Leffler * are met: 71de50e9fSSam Leffler * 1. Redistributions of source code must retain the above copyright 81de50e9fSSam Leffler * notice, this list of conditions and the following disclaimer. 91de50e9fSSam Leffler * 2. Redistributions in binary form must reproduce the above copyright 101de50e9fSSam Leffler * notice, this list of conditions and the following disclaimer in the 111de50e9fSSam Leffler * documentation and/or other materials provided with the distribution. 121de50e9fSSam Leffler * 3. The name of David Young may not be used to endorse or promote 131de50e9fSSam Leffler * products derived from this software without specific prior 141de50e9fSSam Leffler * written permission. 151de50e9fSSam Leffler * 161de50e9fSSam Leffler * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY 171de50e9fSSam Leffler * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 181de50e9fSSam Leffler * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 191de50e9fSSam Leffler * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID 201de50e9fSSam Leffler * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 211de50e9fSSam Leffler * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 221de50e9fSSam Leffler * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231de50e9fSSam Leffler * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 241de50e9fSSam Leffler * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 251de50e9fSSam Leffler * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261de50e9fSSam Leffler * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 271de50e9fSSam Leffler * OF SUCH DAMAGE. 281de50e9fSSam Leffler */ 291de50e9fSSam Leffler 30*3c602fabSXin LI #define NETDISSECT_REWORKED 311de50e9fSSam Leffler #ifdef HAVE_CONFIG_H 321de50e9fSSam Leffler #include "config.h" 331de50e9fSSam Leffler #endif 341de50e9fSSam Leffler 351de50e9fSSam Leffler #include <stdlib.h> 361de50e9fSSam Leffler #include <string.h> 371de50e9fSSam Leffler #include <tcpdump-stdinc.h> 381de50e9fSSam Leffler 391de50e9fSSam Leffler #include "cpack.h" 401de50e9fSSam Leffler #include "extract.h" 411de50e9fSSam Leffler 42*3c602fabSXin LI uint8_t * 43*3c602fabSXin LI cpack_next_boundary(uint8_t *buf, uint8_t *p, size_t alignment) 441de50e9fSSam Leffler { 451de50e9fSSam Leffler size_t misalignment = (size_t)(p - buf) % alignment; 461de50e9fSSam Leffler 471de50e9fSSam Leffler if (misalignment == 0) 481de50e9fSSam Leffler return p; 491de50e9fSSam Leffler 501de50e9fSSam Leffler return p + (alignment - misalignment); 511de50e9fSSam Leffler } 521de50e9fSSam Leffler 531de50e9fSSam Leffler /* Advance to the next wordsize boundary. Return NULL if fewer than 541de50e9fSSam Leffler * wordsize bytes remain in the buffer after the boundary. Otherwise, 551de50e9fSSam Leffler * return a pointer to the boundary. 561de50e9fSSam Leffler */ 57*3c602fabSXin LI uint8_t * 581de50e9fSSam Leffler cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize) 591de50e9fSSam Leffler { 60*3c602fabSXin LI uint8_t *next; 611de50e9fSSam Leffler 621de50e9fSSam Leffler /* Ensure alignment. */ 631de50e9fSSam Leffler next = cpack_next_boundary(cs->c_buf, cs->c_next, wordsize); 641de50e9fSSam Leffler 651de50e9fSSam Leffler /* Too little space for wordsize bytes? */ 661de50e9fSSam Leffler if (next - cs->c_buf + wordsize > cs->c_len) 671de50e9fSSam Leffler return NULL; 681de50e9fSSam Leffler 691de50e9fSSam Leffler return next; 701de50e9fSSam Leffler } 711de50e9fSSam Leffler 72*3c602fabSXin LI /* Advance by N bytes without returning them. */ 731de50e9fSSam Leffler int 74*3c602fabSXin LI cpack_advance(struct cpack_state *cs, const size_t toskip) 75*3c602fabSXin LI { 76*3c602fabSXin LI /* No space left? */ 77*3c602fabSXin LI if (cs->c_next - cs->c_buf + toskip > cs->c_len) 78*3c602fabSXin LI return -1; 79*3c602fabSXin LI cs->c_next += toskip; 80*3c602fabSXin LI return 0; 81*3c602fabSXin LI } 82*3c602fabSXin LI 83*3c602fabSXin LI int 84*3c602fabSXin LI cpack_init(struct cpack_state *cs, uint8_t *buf, size_t buflen) 851de50e9fSSam Leffler { 861de50e9fSSam Leffler memset(cs, 0, sizeof(*cs)); 871de50e9fSSam Leffler 881de50e9fSSam Leffler cs->c_buf = buf; 891de50e9fSSam Leffler cs->c_len = buflen; 901de50e9fSSam Leffler cs->c_next = cs->c_buf; 911de50e9fSSam Leffler 921de50e9fSSam Leffler return 0; 931de50e9fSSam Leffler } 941de50e9fSSam Leffler 951de50e9fSSam Leffler /* Unpack a 64-bit unsigned integer. */ 961de50e9fSSam Leffler int 97*3c602fabSXin LI cpack_uint64(struct cpack_state *cs, uint64_t *u) 981de50e9fSSam Leffler { 99*3c602fabSXin LI uint8_t *next; 1001de50e9fSSam Leffler 1011de50e9fSSam Leffler if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1021de50e9fSSam Leffler return -1; 1031de50e9fSSam Leffler 1041de50e9fSSam Leffler *u = EXTRACT_LE_64BITS(next); 1051de50e9fSSam Leffler 106*3c602fabSXin LI /* Move pointer past the uint64_t. */ 1071de50e9fSSam Leffler cs->c_next = next + sizeof(*u); 1081de50e9fSSam Leffler return 0; 1091de50e9fSSam Leffler } 1101de50e9fSSam Leffler 1111de50e9fSSam Leffler /* Unpack a 32-bit unsigned integer. */ 1121de50e9fSSam Leffler int 113*3c602fabSXin LI cpack_uint32(struct cpack_state *cs, uint32_t *u) 1141de50e9fSSam Leffler { 115*3c602fabSXin LI uint8_t *next; 1161de50e9fSSam Leffler 1171de50e9fSSam Leffler if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1181de50e9fSSam Leffler return -1; 1191de50e9fSSam Leffler 1201de50e9fSSam Leffler *u = EXTRACT_LE_32BITS(next); 1211de50e9fSSam Leffler 122*3c602fabSXin LI /* Move pointer past the uint32_t. */ 1231de50e9fSSam Leffler cs->c_next = next + sizeof(*u); 1241de50e9fSSam Leffler return 0; 1251de50e9fSSam Leffler } 1261de50e9fSSam Leffler 1271de50e9fSSam Leffler /* Unpack a 16-bit unsigned integer. */ 1281de50e9fSSam Leffler int 129*3c602fabSXin LI cpack_uint16(struct cpack_state *cs, uint16_t *u) 1301de50e9fSSam Leffler { 131*3c602fabSXin LI uint8_t *next; 1321de50e9fSSam Leffler 1331de50e9fSSam Leffler if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1341de50e9fSSam Leffler return -1; 1351de50e9fSSam Leffler 1361de50e9fSSam Leffler *u = EXTRACT_LE_16BITS(next); 1371de50e9fSSam Leffler 138*3c602fabSXin LI /* Move pointer past the uint16_t. */ 1391de50e9fSSam Leffler cs->c_next = next + sizeof(*u); 1401de50e9fSSam Leffler return 0; 1411de50e9fSSam Leffler } 1421de50e9fSSam Leffler 1431de50e9fSSam Leffler /* Unpack an 8-bit unsigned integer. */ 1441de50e9fSSam Leffler int 145*3c602fabSXin LI cpack_uint8(struct cpack_state *cs, uint8_t *u) 1461de50e9fSSam Leffler { 1471de50e9fSSam Leffler /* No space left? */ 1481de50e9fSSam Leffler if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 1491de50e9fSSam Leffler return -1; 1501de50e9fSSam Leffler 1511de50e9fSSam Leffler *u = *cs->c_next; 1521de50e9fSSam Leffler 153*3c602fabSXin LI /* Move pointer past the uint8_t. */ 1541de50e9fSSam Leffler cs->c_next++; 1551de50e9fSSam Leffler return 0; 1561de50e9fSSam Leffler } 157