xref: /aosp_15_r20/external/tcpdump/cpack.c (revision 05b00f6010a2396e3db2409989fc67270046269f)
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