10f74e101Schristos /*- 20f74e101Schristos * Copyright (c) 2003, 2004 David Young. All rights reserved. 30f74e101Schristos * 40f74e101Schristos * Redistribution and use in source and binary forms, with or without 50f74e101Schristos * modification, are permitted provided that the following conditions 60f74e101Schristos * are met: 70f74e101Schristos * 1. Redistributions of source code must retain the above copyright 80f74e101Schristos * notice, this list of conditions and the following disclaimer. 90f74e101Schristos * 2. Redistributions in binary form must reproduce the above copyright 100f74e101Schristos * notice, this list of conditions and the following disclaimer in the 110f74e101Schristos * documentation and/or other materials provided with the distribution. 120f74e101Schristos * 130f74e101Schristos * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY 140f74e101Schristos * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 150f74e101Schristos * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 160f74e101Schristos * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID 170f74e101Schristos * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 180f74e101Schristos * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 190f74e101Schristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 200f74e101Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 210f74e101Schristos * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 220f74e101Schristos * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 230f74e101Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 240f74e101Schristos * OF SUCH DAMAGE. 250f74e101Schristos */ 260f74e101Schristos 27fdccd7e4Schristos #include <sys/cdefs.h> 28fdccd7e4Schristos #ifndef lint 29*26ba0b50Schristos __RCSID("$NetBSD: cpack.c,v 1.8 2024/09/02 16:15:30 christos Exp $"); 30fdccd7e4Schristos #endif 31fdccd7e4Schristos 32c74ad251Schristos #include <config.h> 330f74e101Schristos 340f74e101Schristos #include <stdlib.h> 350f74e101Schristos #include <string.h> 36c74ad251Schristos #include "netdissect-stdinc.h" 370f74e101Schristos 38c74ad251Schristos #include "netdissect.h" 390f74e101Schristos #include "extract.h" 400f74e101Schristos 41c74ad251Schristos #include "cpack.h" 42c74ad251Schristos 43fdccd7e4Schristos const uint8_t * 44c74ad251Schristos nd_cpack_next_boundary(const uint8_t *buf, const uint8_t *p, size_t alignment) 450f74e101Schristos { 460f74e101Schristos size_t misalignment = (size_t)(p - buf) % alignment; 470f74e101Schristos 480f74e101Schristos if (misalignment == 0) 490f74e101Schristos return p; 500f74e101Schristos 510f74e101Schristos return p + (alignment - misalignment); 520f74e101Schristos } 530f74e101Schristos 540f74e101Schristos /* Advance to the next wordsize boundary. Return NULL if fewer than 550f74e101Schristos * wordsize bytes remain in the buffer after the boundary. Otherwise, 560f74e101Schristos * return a pointer to the boundary. 570f74e101Schristos */ 58fdccd7e4Schristos const uint8_t * 59c74ad251Schristos nd_cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize) 600f74e101Schristos { 61fdccd7e4Schristos const uint8_t *next; 620f74e101Schristos 630f74e101Schristos /* Ensure alignment. */ 64c74ad251Schristos next = nd_cpack_next_boundary(cs->c_buf, cs->c_next, wordsize); 650f74e101Schristos 660f74e101Schristos /* Too little space for wordsize bytes? */ 670f74e101Schristos if (next - cs->c_buf + wordsize > cs->c_len) 680f74e101Schristos return NULL; 690f74e101Schristos 700f74e101Schristos return next; 710f74e101Schristos } 720f74e101Schristos 73870189d2Schristos /* Advance by N bytes without returning them. */ 74870189d2Schristos int 75c74ad251Schristos nd_cpack_advance(struct cpack_state *cs, const size_t toskip) 76870189d2Schristos { 77870189d2Schristos /* No space left? */ 78870189d2Schristos if (cs->c_next - cs->c_buf + toskip > cs->c_len) 79870189d2Schristos return -1; 80870189d2Schristos cs->c_next += toskip; 81870189d2Schristos return 0; 82870189d2Schristos } 83870189d2Schristos 840f74e101Schristos int 85c74ad251Schristos nd_cpack_init(struct cpack_state *cs, const uint8_t *buf, size_t buflen) 860f74e101Schristos { 870f74e101Schristos memset(cs, 0, sizeof(*cs)); 880f74e101Schristos 890f74e101Schristos cs->c_buf = buf; 900f74e101Schristos cs->c_len = buflen; 910f74e101Schristos cs->c_next = cs->c_buf; 920f74e101Schristos 930f74e101Schristos return 0; 940f74e101Schristos } 950f74e101Schristos 960f74e101Schristos /* Unpack a 64-bit unsigned integer. */ 970f74e101Schristos int 98c74ad251Schristos nd_cpack_uint64(netdissect_options *ndo, struct cpack_state *cs, uint64_t *u) 990f74e101Schristos { 100fdccd7e4Schristos const uint8_t *next; 1010f74e101Schristos 102c74ad251Schristos if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1030f74e101Schristos return -1; 1040f74e101Schristos 105c74ad251Schristos *u = GET_LE_U_8(next); 1060f74e101Schristos 107b3a00663Schristos /* Move pointer past the uint64_t. */ 1080f74e101Schristos cs->c_next = next + sizeof(*u); 1090f74e101Schristos return 0; 1100f74e101Schristos } 1110f74e101Schristos 112c74ad251Schristos /* Unpack a 64-bit signed integer. */ 1130f74e101Schristos int 114c74ad251Schristos nd_cpack_int64(netdissect_options *ndo, struct cpack_state *cs, int64_t *u) 1150f74e101Schristos { 116fdccd7e4Schristos const uint8_t *next; 1170f74e101Schristos 118c74ad251Schristos if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1190f74e101Schristos return -1; 1200f74e101Schristos 121c74ad251Schristos *u = GET_LE_S_8(next); 122c74ad251Schristos 123c74ad251Schristos /* Move pointer past the int64_t. */ 124c74ad251Schristos cs->c_next = next + sizeof(*u); 125c74ad251Schristos return 0; 126c74ad251Schristos } 127c74ad251Schristos 128c74ad251Schristos /* Unpack a 32-bit unsigned integer. */ 129c74ad251Schristos int 130c74ad251Schristos nd_cpack_uint32(netdissect_options *ndo, struct cpack_state *cs, uint32_t *u) 131c74ad251Schristos { 132c74ad251Schristos const uint8_t *next; 133c74ad251Schristos 134c74ad251Schristos if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 135c74ad251Schristos return -1; 136c74ad251Schristos 137c74ad251Schristos *u = GET_LE_U_4(next); 1380f74e101Schristos 139b3a00663Schristos /* Move pointer past the uint32_t. */ 1400f74e101Schristos cs->c_next = next + sizeof(*u); 1410f74e101Schristos return 0; 1420f74e101Schristos } 1430f74e101Schristos 144c74ad251Schristos /* Unpack a 32-bit signed integer. */ 1450f74e101Schristos int 146c74ad251Schristos nd_cpack_int32(netdissect_options *ndo, struct cpack_state *cs, int32_t *u) 1470f74e101Schristos { 148fdccd7e4Schristos const uint8_t *next; 1490f74e101Schristos 150c74ad251Schristos if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1510f74e101Schristos return -1; 1520f74e101Schristos 153c74ad251Schristos *u = GET_LE_S_4(next); 154c74ad251Schristos 155c74ad251Schristos /* Move pointer past the int32_t. */ 156c74ad251Schristos cs->c_next = next + sizeof(*u); 157c74ad251Schristos return 0; 158c74ad251Schristos } 159c74ad251Schristos 160c74ad251Schristos /* Unpack a 16-bit unsigned integer. */ 161c74ad251Schristos int 162c74ad251Schristos nd_cpack_uint16(netdissect_options *ndo, struct cpack_state *cs, uint16_t *u) 163c74ad251Schristos { 164c74ad251Schristos const uint8_t *next; 165c74ad251Schristos 166c74ad251Schristos if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 167c74ad251Schristos return -1; 168c74ad251Schristos 169c74ad251Schristos *u = GET_LE_U_2(next); 1700f74e101Schristos 171b3a00663Schristos /* Move pointer past the uint16_t. */ 1720f74e101Schristos cs->c_next = next + sizeof(*u); 1730f74e101Schristos return 0; 1740f74e101Schristos } 1750f74e101Schristos 176c74ad251Schristos /* Unpack a 16-bit signed integer. */ 177c74ad251Schristos int 178c74ad251Schristos nd_cpack_int16(netdissect_options *ndo, struct cpack_state *cs, int16_t *u) 179c74ad251Schristos { 180c74ad251Schristos const uint8_t *next; 181c74ad251Schristos 182c74ad251Schristos if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 183c74ad251Schristos return -1; 184c74ad251Schristos 185c74ad251Schristos *u = GET_LE_S_2(next); 186c74ad251Schristos 187c74ad251Schristos /* Move pointer past the int16_t. */ 188c74ad251Schristos cs->c_next = next + sizeof(*u); 189c74ad251Schristos return 0; 190c74ad251Schristos } 191c74ad251Schristos 1920f74e101Schristos /* Unpack an 8-bit unsigned integer. */ 1930f74e101Schristos int 194c74ad251Schristos nd_cpack_uint8(netdissect_options *ndo, struct cpack_state *cs, uint8_t *u) 1950f74e101Schristos { 1960f74e101Schristos /* No space left? */ 1970f74e101Schristos if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 1980f74e101Schristos return -1; 1990f74e101Schristos 200c74ad251Schristos *u = GET_U_1(cs->c_next); 2010f74e101Schristos 202b3a00663Schristos /* Move pointer past the uint8_t. */ 2030f74e101Schristos cs->c_next++; 2040f74e101Schristos return 0; 2050f74e101Schristos } 206c74ad251Schristos 207c74ad251Schristos /* Unpack an 8-bit signed integer. */ 208c74ad251Schristos int 209c74ad251Schristos nd_cpack_int8(netdissect_options *ndo, struct cpack_state *cs, int8_t *u) 210c74ad251Schristos { 211c74ad251Schristos /* No space left? */ 212c74ad251Schristos if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 213c74ad251Schristos return -1; 214c74ad251Schristos 215c74ad251Schristos *u = GET_S_1(cs->c_next); 216c74ad251Schristos 217c74ad251Schristos /* Move pointer past the int8_t. */ 218c74ad251Schristos cs->c_next++; 219c74ad251Schristos return 0; 220c74ad251Schristos } 221