1*05b00f60SXin Li /*-
2*05b00f60SXin Li * Copyright (c) 2003, 2004 David Young. All rights reserved.
3*05b00f60SXin Li *
4*05b00f60SXin Li * Redistribution and use in source and binary forms, with or without
5*05b00f60SXin Li * modification, are permitted provided that the following conditions
6*05b00f60SXin Li * are met:
7*05b00f60SXin Li * 1. Redistributions of source code must retain the above copyright
8*05b00f60SXin Li * notice, this list of conditions and the following disclaimer.
9*05b00f60SXin Li * 2. Redistributions in binary form must reproduce the above copyright
10*05b00f60SXin Li * notice, this list of conditions and the following disclaimer in the
11*05b00f60SXin Li * documentation and/or other materials provided with the distribution.
12*05b00f60SXin Li * 3. The name of David Young may not be used to endorse or promote
13*05b00f60SXin Li * products derived from this software without specific prior
14*05b00f60SXin Li * written permission.
15*05b00f60SXin Li *
16*05b00f60SXin Li * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
17*05b00f60SXin Li * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18*05b00f60SXin Li * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19*05b00f60SXin Li * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
20*05b00f60SXin Li * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21*05b00f60SXin Li * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22*05b00f60SXin Li * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23*05b00f60SXin Li * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24*05b00f60SXin Li * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25*05b00f60SXin Li * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*05b00f60SXin Li * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27*05b00f60SXin Li * OF SUCH DAMAGE.
28*05b00f60SXin Li */
29*05b00f60SXin Li
30*05b00f60SXin Li #ifdef HAVE_CONFIG_H
31*05b00f60SXin Li #include <config.h>
32*05b00f60SXin Li #endif
33*05b00f60SXin Li
34*05b00f60SXin Li #include <stdlib.h>
35*05b00f60SXin Li #include <string.h>
36*05b00f60SXin Li #include "netdissect-stdinc.h"
37*05b00f60SXin Li
38*05b00f60SXin Li #include "netdissect.h"
39*05b00f60SXin Li #include "extract.h"
40*05b00f60SXin Li
41*05b00f60SXin Li #include "cpack.h"
42*05b00f60SXin Li
43*05b00f60SXin Li const uint8_t *
nd_cpack_next_boundary(const uint8_t * buf,const uint8_t * p,size_t alignment)44*05b00f60SXin Li nd_cpack_next_boundary(const uint8_t *buf, const uint8_t *p, size_t alignment)
45*05b00f60SXin Li {
46*05b00f60SXin Li size_t misalignment = (size_t)(p - buf) % alignment;
47*05b00f60SXin Li
48*05b00f60SXin Li if (misalignment == 0)
49*05b00f60SXin Li return p;
50*05b00f60SXin Li
51*05b00f60SXin Li return p + (alignment - misalignment);
52*05b00f60SXin Li }
53*05b00f60SXin Li
54*05b00f60SXin Li /* Advance to the next wordsize boundary. Return NULL if fewer than
55*05b00f60SXin Li * wordsize bytes remain in the buffer after the boundary. Otherwise,
56*05b00f60SXin Li * return a pointer to the boundary.
57*05b00f60SXin Li */
58*05b00f60SXin Li const uint8_t *
nd_cpack_align_and_reserve(struct cpack_state * cs,size_t wordsize)59*05b00f60SXin Li nd_cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize)
60*05b00f60SXin Li {
61*05b00f60SXin Li const uint8_t *next;
62*05b00f60SXin Li
63*05b00f60SXin Li /* Ensure alignment. */
64*05b00f60SXin Li next = nd_cpack_next_boundary(cs->c_buf, cs->c_next, wordsize);
65*05b00f60SXin Li
66*05b00f60SXin Li /* Too little space for wordsize bytes? */
67*05b00f60SXin Li if (next - cs->c_buf + wordsize > cs->c_len)
68*05b00f60SXin Li return NULL;
69*05b00f60SXin Li
70*05b00f60SXin Li return next;
71*05b00f60SXin Li }
72*05b00f60SXin Li
73*05b00f60SXin Li /* Advance by N bytes without returning them. */
74*05b00f60SXin Li int
nd_cpack_advance(struct cpack_state * cs,const size_t toskip)75*05b00f60SXin Li nd_cpack_advance(struct cpack_state *cs, const size_t toskip)
76*05b00f60SXin Li {
77*05b00f60SXin Li /* No space left? */
78*05b00f60SXin Li if (cs->c_next - cs->c_buf + toskip > cs->c_len)
79*05b00f60SXin Li return -1;
80*05b00f60SXin Li cs->c_next += toskip;
81*05b00f60SXin Li return 0;
82*05b00f60SXin Li }
83*05b00f60SXin Li
84*05b00f60SXin Li int
nd_cpack_init(struct cpack_state * cs,const uint8_t * buf,size_t buflen)85*05b00f60SXin Li nd_cpack_init(struct cpack_state *cs, const uint8_t *buf, size_t buflen)
86*05b00f60SXin Li {
87*05b00f60SXin Li memset(cs, 0, sizeof(*cs));
88*05b00f60SXin Li
89*05b00f60SXin Li cs->c_buf = buf;
90*05b00f60SXin Li cs->c_len = buflen;
91*05b00f60SXin Li cs->c_next = cs->c_buf;
92*05b00f60SXin Li
93*05b00f60SXin Li return 0;
94*05b00f60SXin Li }
95*05b00f60SXin Li
96*05b00f60SXin Li /* Unpack a 64-bit unsigned integer. */
97*05b00f60SXin Li int
nd_cpack_uint64(netdissect_options * ndo,struct cpack_state * cs,uint64_t * u)98*05b00f60SXin Li nd_cpack_uint64(netdissect_options *ndo, struct cpack_state *cs, uint64_t *u)
99*05b00f60SXin Li {
100*05b00f60SXin Li const uint8_t *next;
101*05b00f60SXin Li
102*05b00f60SXin Li if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
103*05b00f60SXin Li return -1;
104*05b00f60SXin Li
105*05b00f60SXin Li *u = GET_LE_U_8(next);
106*05b00f60SXin Li
107*05b00f60SXin Li /* Move pointer past the uint64_t. */
108*05b00f60SXin Li cs->c_next = next + sizeof(*u);
109*05b00f60SXin Li return 0;
110*05b00f60SXin Li }
111*05b00f60SXin Li
112*05b00f60SXin Li /* Unpack a 64-bit signed integer. */
113*05b00f60SXin Li int
nd_cpack_int64(netdissect_options * ndo,struct cpack_state * cs,int64_t * u)114*05b00f60SXin Li nd_cpack_int64(netdissect_options *ndo, struct cpack_state *cs, int64_t *u)
115*05b00f60SXin Li {
116*05b00f60SXin Li const uint8_t *next;
117*05b00f60SXin Li
118*05b00f60SXin Li if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
119*05b00f60SXin Li return -1;
120*05b00f60SXin Li
121*05b00f60SXin Li *u = GET_LE_S_8(next);
122*05b00f60SXin Li
123*05b00f60SXin Li /* Move pointer past the int64_t. */
124*05b00f60SXin Li cs->c_next = next + sizeof(*u);
125*05b00f60SXin Li return 0;
126*05b00f60SXin Li }
127*05b00f60SXin Li
128*05b00f60SXin Li /* Unpack a 32-bit unsigned integer. */
129*05b00f60SXin Li int
nd_cpack_uint32(netdissect_options * ndo,struct cpack_state * cs,uint32_t * u)130*05b00f60SXin Li nd_cpack_uint32(netdissect_options *ndo, struct cpack_state *cs, uint32_t *u)
131*05b00f60SXin Li {
132*05b00f60SXin Li const uint8_t *next;
133*05b00f60SXin Li
134*05b00f60SXin Li if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
135*05b00f60SXin Li return -1;
136*05b00f60SXin Li
137*05b00f60SXin Li *u = GET_LE_U_4(next);
138*05b00f60SXin Li
139*05b00f60SXin Li /* Move pointer past the uint32_t. */
140*05b00f60SXin Li cs->c_next = next + sizeof(*u);
141*05b00f60SXin Li return 0;
142*05b00f60SXin Li }
143*05b00f60SXin Li
144*05b00f60SXin Li /* Unpack a 32-bit signed integer. */
145*05b00f60SXin Li int
nd_cpack_int32(netdissect_options * ndo,struct cpack_state * cs,int32_t * u)146*05b00f60SXin Li nd_cpack_int32(netdissect_options *ndo, struct cpack_state *cs, int32_t *u)
147*05b00f60SXin Li {
148*05b00f60SXin Li const uint8_t *next;
149*05b00f60SXin Li
150*05b00f60SXin Li if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
151*05b00f60SXin Li return -1;
152*05b00f60SXin Li
153*05b00f60SXin Li *u = GET_LE_S_4(next);
154*05b00f60SXin Li
155*05b00f60SXin Li /* Move pointer past the int32_t. */
156*05b00f60SXin Li cs->c_next = next + sizeof(*u);
157*05b00f60SXin Li return 0;
158*05b00f60SXin Li }
159*05b00f60SXin Li
160*05b00f60SXin Li /* Unpack a 16-bit unsigned integer. */
161*05b00f60SXin Li int
nd_cpack_uint16(netdissect_options * ndo,struct cpack_state * cs,uint16_t * u)162*05b00f60SXin Li nd_cpack_uint16(netdissect_options *ndo, struct cpack_state *cs, uint16_t *u)
163*05b00f60SXin Li {
164*05b00f60SXin Li const uint8_t *next;
165*05b00f60SXin Li
166*05b00f60SXin Li if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
167*05b00f60SXin Li return -1;
168*05b00f60SXin Li
169*05b00f60SXin Li *u = GET_LE_U_2(next);
170*05b00f60SXin Li
171*05b00f60SXin Li /* Move pointer past the uint16_t. */
172*05b00f60SXin Li cs->c_next = next + sizeof(*u);
173*05b00f60SXin Li return 0;
174*05b00f60SXin Li }
175*05b00f60SXin Li
176*05b00f60SXin Li /* Unpack a 16-bit signed integer. */
177*05b00f60SXin Li int
nd_cpack_int16(netdissect_options * ndo,struct cpack_state * cs,int16_t * u)178*05b00f60SXin Li nd_cpack_int16(netdissect_options *ndo, struct cpack_state *cs, int16_t *u)
179*05b00f60SXin Li {
180*05b00f60SXin Li const uint8_t *next;
181*05b00f60SXin Li
182*05b00f60SXin Li if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
183*05b00f60SXin Li return -1;
184*05b00f60SXin Li
185*05b00f60SXin Li *u = GET_LE_S_2(next);
186*05b00f60SXin Li
187*05b00f60SXin Li /* Move pointer past the int16_t. */
188*05b00f60SXin Li cs->c_next = next + sizeof(*u);
189*05b00f60SXin Li return 0;
190*05b00f60SXin Li }
191*05b00f60SXin Li
192*05b00f60SXin Li /* Unpack an 8-bit unsigned integer. */
193*05b00f60SXin Li int
nd_cpack_uint8(netdissect_options * ndo,struct cpack_state * cs,uint8_t * u)194*05b00f60SXin Li nd_cpack_uint8(netdissect_options *ndo, struct cpack_state *cs, uint8_t *u)
195*05b00f60SXin Li {
196*05b00f60SXin Li /* No space left? */
197*05b00f60SXin Li if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
198*05b00f60SXin Li return -1;
199*05b00f60SXin Li
200*05b00f60SXin Li *u = GET_U_1(cs->c_next);
201*05b00f60SXin Li
202*05b00f60SXin Li /* Move pointer past the uint8_t. */
203*05b00f60SXin Li cs->c_next++;
204*05b00f60SXin Li return 0;
205*05b00f60SXin Li }
206*05b00f60SXin Li
207*05b00f60SXin Li /* Unpack an 8-bit signed integer. */
208*05b00f60SXin Li int
nd_cpack_int8(netdissect_options * ndo,struct cpack_state * cs,int8_t * u)209*05b00f60SXin Li nd_cpack_int8(netdissect_options *ndo, struct cpack_state *cs, int8_t *u)
210*05b00f60SXin Li {
211*05b00f60SXin Li /* No space left? */
212*05b00f60SXin Li if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
213*05b00f60SXin Li return -1;
214*05b00f60SXin Li
215*05b00f60SXin Li *u = GET_S_1(cs->c_next);
216*05b00f60SXin Li
217*05b00f60SXin Li /* Move pointer past the int8_t. */
218*05b00f60SXin Li cs->c_next++;
219*05b00f60SXin Li return 0;
220*05b00f60SXin Li }
221