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*ee67461eSJoseph Mingrone #include <config.h> 311de50e9fSSam Leffler 321de50e9fSSam Leffler #include <stdlib.h> 331de50e9fSSam Leffler #include <string.h> 34*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 351de50e9fSSam Leffler 36*ee67461eSJoseph Mingrone #include "netdissect.h" 371de50e9fSSam Leffler #include "extract.h" 381de50e9fSSam Leffler 39*ee67461eSJoseph Mingrone #include "cpack.h" 40*ee67461eSJoseph Mingrone 413340d773SGleb Smirnoff const uint8_t * 42*ee67461eSJoseph Mingrone nd_cpack_next_boundary(const uint8_t *buf, const uint8_t *p, size_t alignment) 431de50e9fSSam Leffler { 441de50e9fSSam Leffler size_t misalignment = (size_t)(p - buf) % alignment; 451de50e9fSSam Leffler 461de50e9fSSam Leffler if (misalignment == 0) 471de50e9fSSam Leffler return p; 481de50e9fSSam Leffler 491de50e9fSSam Leffler return p + (alignment - misalignment); 501de50e9fSSam Leffler } 511de50e9fSSam Leffler 521de50e9fSSam Leffler /* Advance to the next wordsize boundary. Return NULL if fewer than 531de50e9fSSam Leffler * wordsize bytes remain in the buffer after the boundary. Otherwise, 541de50e9fSSam Leffler * return a pointer to the boundary. 551de50e9fSSam Leffler */ 563340d773SGleb Smirnoff const uint8_t * 57*ee67461eSJoseph Mingrone nd_cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize) 581de50e9fSSam Leffler { 593340d773SGleb Smirnoff const uint8_t *next; 601de50e9fSSam Leffler 611de50e9fSSam Leffler /* Ensure alignment. */ 62*ee67461eSJoseph Mingrone next = nd_cpack_next_boundary(cs->c_buf, cs->c_next, wordsize); 631de50e9fSSam Leffler 641de50e9fSSam Leffler /* Too little space for wordsize bytes? */ 651de50e9fSSam Leffler if (next - cs->c_buf + wordsize > cs->c_len) 661de50e9fSSam Leffler return NULL; 671de50e9fSSam Leffler 681de50e9fSSam Leffler return next; 691de50e9fSSam Leffler } 701de50e9fSSam Leffler 713c602fabSXin LI /* Advance by N bytes without returning them. */ 721de50e9fSSam Leffler int 73*ee67461eSJoseph Mingrone nd_cpack_advance(struct cpack_state *cs, const size_t toskip) 743c602fabSXin LI { 753c602fabSXin LI /* No space left? */ 763c602fabSXin LI if (cs->c_next - cs->c_buf + toskip > cs->c_len) 773c602fabSXin LI return -1; 783c602fabSXin LI cs->c_next += toskip; 793c602fabSXin LI return 0; 803c602fabSXin LI } 813c602fabSXin LI 823c602fabSXin LI int 83*ee67461eSJoseph Mingrone nd_cpack_init(struct cpack_state *cs, const uint8_t *buf, size_t buflen) 841de50e9fSSam Leffler { 851de50e9fSSam Leffler memset(cs, 0, sizeof(*cs)); 861de50e9fSSam Leffler 871de50e9fSSam Leffler cs->c_buf = buf; 881de50e9fSSam Leffler cs->c_len = buflen; 891de50e9fSSam Leffler cs->c_next = cs->c_buf; 901de50e9fSSam Leffler 911de50e9fSSam Leffler return 0; 921de50e9fSSam Leffler } 931de50e9fSSam Leffler 941de50e9fSSam Leffler /* Unpack a 64-bit unsigned integer. */ 951de50e9fSSam Leffler int 96*ee67461eSJoseph Mingrone nd_cpack_uint64(netdissect_options *ndo, struct cpack_state *cs, uint64_t *u) 971de50e9fSSam Leffler { 983340d773SGleb Smirnoff const uint8_t *next; 991de50e9fSSam Leffler 100*ee67461eSJoseph Mingrone if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1011de50e9fSSam Leffler return -1; 1021de50e9fSSam Leffler 103*ee67461eSJoseph Mingrone *u = GET_LE_U_8(next); 1041de50e9fSSam Leffler 1053c602fabSXin LI /* Move pointer past the uint64_t. */ 1061de50e9fSSam Leffler cs->c_next = next + sizeof(*u); 1071de50e9fSSam Leffler return 0; 1081de50e9fSSam Leffler } 1091de50e9fSSam Leffler 110*ee67461eSJoseph Mingrone /* Unpack a 64-bit signed integer. */ 1111de50e9fSSam Leffler int 112*ee67461eSJoseph Mingrone nd_cpack_int64(netdissect_options *ndo, struct cpack_state *cs, int64_t *u) 1131de50e9fSSam Leffler { 1143340d773SGleb Smirnoff const uint8_t *next; 1151de50e9fSSam Leffler 116*ee67461eSJoseph Mingrone if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1171de50e9fSSam Leffler return -1; 1181de50e9fSSam Leffler 119*ee67461eSJoseph Mingrone *u = GET_LE_S_8(next); 120*ee67461eSJoseph Mingrone 121*ee67461eSJoseph Mingrone /* Move pointer past the int64_t. */ 122*ee67461eSJoseph Mingrone cs->c_next = next + sizeof(*u); 123*ee67461eSJoseph Mingrone return 0; 124*ee67461eSJoseph Mingrone } 125*ee67461eSJoseph Mingrone 126*ee67461eSJoseph Mingrone /* Unpack a 32-bit unsigned integer. */ 127*ee67461eSJoseph Mingrone int 128*ee67461eSJoseph Mingrone nd_cpack_uint32(netdissect_options *ndo, struct cpack_state *cs, uint32_t *u) 129*ee67461eSJoseph Mingrone { 130*ee67461eSJoseph Mingrone const uint8_t *next; 131*ee67461eSJoseph Mingrone 132*ee67461eSJoseph Mingrone if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 133*ee67461eSJoseph Mingrone return -1; 134*ee67461eSJoseph Mingrone 135*ee67461eSJoseph Mingrone *u = GET_LE_U_4(next); 1361de50e9fSSam Leffler 1373c602fabSXin LI /* Move pointer past the uint32_t. */ 1381de50e9fSSam Leffler cs->c_next = next + sizeof(*u); 1391de50e9fSSam Leffler return 0; 1401de50e9fSSam Leffler } 1411de50e9fSSam Leffler 142*ee67461eSJoseph Mingrone /* Unpack a 32-bit signed integer. */ 1431de50e9fSSam Leffler int 144*ee67461eSJoseph Mingrone nd_cpack_int32(netdissect_options *ndo, struct cpack_state *cs, int32_t *u) 1451de50e9fSSam Leffler { 1463340d773SGleb Smirnoff const uint8_t *next; 1471de50e9fSSam Leffler 148*ee67461eSJoseph Mingrone if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 1491de50e9fSSam Leffler return -1; 1501de50e9fSSam Leffler 151*ee67461eSJoseph Mingrone *u = GET_LE_S_4(next); 152*ee67461eSJoseph Mingrone 153*ee67461eSJoseph Mingrone /* Move pointer past the int32_t. */ 154*ee67461eSJoseph Mingrone cs->c_next = next + sizeof(*u); 155*ee67461eSJoseph Mingrone return 0; 156*ee67461eSJoseph Mingrone } 157*ee67461eSJoseph Mingrone 158*ee67461eSJoseph Mingrone /* Unpack a 16-bit unsigned integer. */ 159*ee67461eSJoseph Mingrone int 160*ee67461eSJoseph Mingrone nd_cpack_uint16(netdissect_options *ndo, struct cpack_state *cs, uint16_t *u) 161*ee67461eSJoseph Mingrone { 162*ee67461eSJoseph Mingrone const uint8_t *next; 163*ee67461eSJoseph Mingrone 164*ee67461eSJoseph Mingrone if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 165*ee67461eSJoseph Mingrone return -1; 166*ee67461eSJoseph Mingrone 167*ee67461eSJoseph Mingrone *u = GET_LE_U_2(next); 1681de50e9fSSam Leffler 1693c602fabSXin LI /* Move pointer past the uint16_t. */ 1701de50e9fSSam Leffler cs->c_next = next + sizeof(*u); 1711de50e9fSSam Leffler return 0; 1721de50e9fSSam Leffler } 1731de50e9fSSam Leffler 174*ee67461eSJoseph Mingrone /* Unpack a 16-bit signed integer. */ 175*ee67461eSJoseph Mingrone int 176*ee67461eSJoseph Mingrone nd_cpack_int16(netdissect_options *ndo, struct cpack_state *cs, int16_t *u) 177*ee67461eSJoseph Mingrone { 178*ee67461eSJoseph Mingrone const uint8_t *next; 179*ee67461eSJoseph Mingrone 180*ee67461eSJoseph Mingrone if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 181*ee67461eSJoseph Mingrone return -1; 182*ee67461eSJoseph Mingrone 183*ee67461eSJoseph Mingrone *u = GET_LE_S_2(next); 184*ee67461eSJoseph Mingrone 185*ee67461eSJoseph Mingrone /* Move pointer past the int16_t. */ 186*ee67461eSJoseph Mingrone cs->c_next = next + sizeof(*u); 187*ee67461eSJoseph Mingrone return 0; 188*ee67461eSJoseph Mingrone } 189*ee67461eSJoseph Mingrone 1901de50e9fSSam Leffler /* Unpack an 8-bit unsigned integer. */ 1911de50e9fSSam Leffler int 192*ee67461eSJoseph Mingrone nd_cpack_uint8(netdissect_options *ndo, struct cpack_state *cs, uint8_t *u) 1931de50e9fSSam Leffler { 1941de50e9fSSam Leffler /* No space left? */ 1951de50e9fSSam Leffler if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 1961de50e9fSSam Leffler return -1; 1971de50e9fSSam Leffler 198*ee67461eSJoseph Mingrone *u = GET_U_1(cs->c_next); 1991de50e9fSSam Leffler 2003c602fabSXin LI /* Move pointer past the uint8_t. */ 2011de50e9fSSam Leffler cs->c_next++; 2021de50e9fSSam Leffler return 0; 2031de50e9fSSam Leffler } 204*ee67461eSJoseph Mingrone 205*ee67461eSJoseph Mingrone /* Unpack an 8-bit signed integer. */ 206*ee67461eSJoseph Mingrone int 207*ee67461eSJoseph Mingrone nd_cpack_int8(netdissect_options *ndo, struct cpack_state *cs, int8_t *u) 208*ee67461eSJoseph Mingrone { 209*ee67461eSJoseph Mingrone /* No space left? */ 210*ee67461eSJoseph Mingrone if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 211*ee67461eSJoseph Mingrone return -1; 212*ee67461eSJoseph Mingrone 213*ee67461eSJoseph Mingrone *u = GET_S_1(cs->c_next); 214*ee67461eSJoseph Mingrone 215*ee67461eSJoseph Mingrone /* Move pointer past the int8_t. */ 216*ee67461eSJoseph Mingrone cs->c_next++; 217*ee67461eSJoseph Mingrone return 0; 218*ee67461eSJoseph Mingrone } 219