141c99275SPeter Avalos /*-
241c99275SPeter Avalos * Copyright (c) 2003, 2004 David Young. All rights reserved.
341c99275SPeter Avalos *
441c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
541c99275SPeter Avalos * modification, are permitted provided that the following conditions
641c99275SPeter Avalos * are met:
741c99275SPeter Avalos * 1. Redistributions of source code must retain the above copyright
841c99275SPeter Avalos * notice, this list of conditions and the following disclaimer.
941c99275SPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
1041c99275SPeter Avalos * notice, this list of conditions and the following disclaimer in the
1141c99275SPeter Avalos * documentation and/or other materials provided with the distribution.
1241c99275SPeter Avalos * 3. The name of David Young may not be used to endorse or promote
1341c99275SPeter Avalos * products derived from this software without specific prior
1441c99275SPeter Avalos * written permission.
1541c99275SPeter Avalos *
1641c99275SPeter Avalos * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
1741c99275SPeter Avalos * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1841c99275SPeter Avalos * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
1941c99275SPeter Avalos * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
2041c99275SPeter Avalos * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2141c99275SPeter Avalos * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2241c99275SPeter Avalos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2341c99275SPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2441c99275SPeter Avalos * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2541c99275SPeter Avalos * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2641c99275SPeter Avalos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2741c99275SPeter Avalos * OF SUCH DAMAGE.
2841c99275SPeter Avalos */
2941c99275SPeter Avalos
3041c99275SPeter Avalos #ifdef HAVE_CONFIG_H
31*ed775ee7SAntonio Huete Jimenez #include <config.h>
3241c99275SPeter Avalos #endif
3341c99275SPeter Avalos
3441c99275SPeter Avalos #include <stdlib.h>
3541c99275SPeter Avalos #include <string.h>
36*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
3741c99275SPeter Avalos
38*ed775ee7SAntonio Huete Jimenez #include "netdissect.h"
3941c99275SPeter Avalos #include "extract.h"
4041c99275SPeter Avalos
41*ed775ee7SAntonio Huete Jimenez #include "cpack.h"
42*ed775ee7SAntonio Huete Jimenez
43411677aeSAaron LI const uint8_t *
nd_cpack_next_boundary(const uint8_t * buf,const uint8_t * p,size_t alignment)44*ed775ee7SAntonio Huete Jimenez nd_cpack_next_boundary(const uint8_t *buf, const uint8_t *p, size_t alignment)
4541c99275SPeter Avalos {
4641c99275SPeter Avalos size_t misalignment = (size_t)(p - buf) % alignment;
4741c99275SPeter Avalos
4841c99275SPeter Avalos if (misalignment == 0)
4941c99275SPeter Avalos return p;
5041c99275SPeter Avalos
5141c99275SPeter Avalos return p + (alignment - misalignment);
5241c99275SPeter Avalos }
5341c99275SPeter Avalos
5441c99275SPeter Avalos /* Advance to the next wordsize boundary. Return NULL if fewer than
5541c99275SPeter Avalos * wordsize bytes remain in the buffer after the boundary. Otherwise,
5641c99275SPeter Avalos * return a pointer to the boundary.
5741c99275SPeter Avalos */
58411677aeSAaron LI const uint8_t *
nd_cpack_align_and_reserve(struct cpack_state * cs,size_t wordsize)59*ed775ee7SAntonio Huete Jimenez nd_cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize)
6041c99275SPeter Avalos {
61411677aeSAaron LI const uint8_t *next;
6241c99275SPeter Avalos
6341c99275SPeter Avalos /* Ensure alignment. */
64*ed775ee7SAntonio Huete Jimenez next = nd_cpack_next_boundary(cs->c_buf, cs->c_next, wordsize);
6541c99275SPeter Avalos
6641c99275SPeter Avalos /* Too little space for wordsize bytes? */
6741c99275SPeter Avalos if (next - cs->c_buf + wordsize > cs->c_len)
6841c99275SPeter Avalos return NULL;
6941c99275SPeter Avalos
7041c99275SPeter Avalos return next;
7141c99275SPeter Avalos }
7241c99275SPeter Avalos
73411677aeSAaron LI /* Advance by N bytes without returning them. */
7441c99275SPeter Avalos int
nd_cpack_advance(struct cpack_state * cs,const size_t toskip)75*ed775ee7SAntonio Huete Jimenez nd_cpack_advance(struct cpack_state *cs, const size_t toskip)
76411677aeSAaron LI {
77411677aeSAaron LI /* No space left? */
78411677aeSAaron LI if (cs->c_next - cs->c_buf + toskip > cs->c_len)
79411677aeSAaron LI return -1;
80411677aeSAaron LI cs->c_next += toskip;
81411677aeSAaron LI return 0;
82411677aeSAaron LI }
83411677aeSAaron LI
84411677aeSAaron LI int
nd_cpack_init(struct cpack_state * cs,const uint8_t * buf,size_t buflen)85*ed775ee7SAntonio Huete Jimenez nd_cpack_init(struct cpack_state *cs, const uint8_t *buf, size_t buflen)
8641c99275SPeter Avalos {
8741c99275SPeter Avalos memset(cs, 0, sizeof(*cs));
8841c99275SPeter Avalos
8941c99275SPeter Avalos cs->c_buf = buf;
9041c99275SPeter Avalos cs->c_len = buflen;
9141c99275SPeter Avalos cs->c_next = cs->c_buf;
9241c99275SPeter Avalos
9341c99275SPeter Avalos return 0;
9441c99275SPeter Avalos }
9541c99275SPeter Avalos
9641c99275SPeter Avalos /* Unpack a 64-bit unsigned integer. */
9741c99275SPeter Avalos int
nd_cpack_uint64(netdissect_options * ndo,struct cpack_state * cs,uint64_t * u)98*ed775ee7SAntonio Huete Jimenez nd_cpack_uint64(netdissect_options *ndo, struct cpack_state *cs, uint64_t *u)
9941c99275SPeter Avalos {
100411677aeSAaron LI const uint8_t *next;
10141c99275SPeter Avalos
102*ed775ee7SAntonio Huete Jimenez if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
10341c99275SPeter Avalos return -1;
10441c99275SPeter Avalos
105*ed775ee7SAntonio Huete Jimenez *u = GET_LE_U_8(next);
10641c99275SPeter Avalos
107411677aeSAaron LI /* Move pointer past the uint64_t. */
10841c99275SPeter Avalos cs->c_next = next + sizeof(*u);
10941c99275SPeter Avalos return 0;
11041c99275SPeter Avalos }
11141c99275SPeter Avalos
112*ed775ee7SAntonio Huete Jimenez /* Unpack a 64-bit signed integer. */
11341c99275SPeter Avalos int
nd_cpack_int64(netdissect_options * ndo,struct cpack_state * cs,int64_t * u)114*ed775ee7SAntonio Huete Jimenez nd_cpack_int64(netdissect_options *ndo, struct cpack_state *cs, int64_t *u)
11541c99275SPeter Avalos {
116411677aeSAaron LI const uint8_t *next;
11741c99275SPeter Avalos
118*ed775ee7SAntonio Huete Jimenez if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
11941c99275SPeter Avalos return -1;
12041c99275SPeter Avalos
121*ed775ee7SAntonio Huete Jimenez *u = GET_LE_S_8(next);
122*ed775ee7SAntonio Huete Jimenez
123*ed775ee7SAntonio Huete Jimenez /* Move pointer past the int64_t. */
124*ed775ee7SAntonio Huete Jimenez cs->c_next = next + sizeof(*u);
125*ed775ee7SAntonio Huete Jimenez return 0;
126*ed775ee7SAntonio Huete Jimenez }
127*ed775ee7SAntonio Huete Jimenez
128*ed775ee7SAntonio Huete Jimenez /* Unpack a 32-bit unsigned integer. */
129*ed775ee7SAntonio Huete Jimenez int
nd_cpack_uint32(netdissect_options * ndo,struct cpack_state * cs,uint32_t * u)130*ed775ee7SAntonio Huete Jimenez nd_cpack_uint32(netdissect_options *ndo, struct cpack_state *cs, uint32_t *u)
131*ed775ee7SAntonio Huete Jimenez {
132*ed775ee7SAntonio Huete Jimenez const uint8_t *next;
133*ed775ee7SAntonio Huete Jimenez
134*ed775ee7SAntonio Huete Jimenez if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
135*ed775ee7SAntonio Huete Jimenez return -1;
136*ed775ee7SAntonio Huete Jimenez
137*ed775ee7SAntonio Huete Jimenez *u = GET_LE_U_4(next);
13841c99275SPeter Avalos
139411677aeSAaron LI /* Move pointer past the uint32_t. */
14041c99275SPeter Avalos cs->c_next = next + sizeof(*u);
14141c99275SPeter Avalos return 0;
14241c99275SPeter Avalos }
14341c99275SPeter Avalos
144*ed775ee7SAntonio Huete Jimenez /* Unpack a 32-bit signed integer. */
14541c99275SPeter Avalos int
nd_cpack_int32(netdissect_options * ndo,struct cpack_state * cs,int32_t * u)146*ed775ee7SAntonio Huete Jimenez nd_cpack_int32(netdissect_options *ndo, struct cpack_state *cs, int32_t *u)
14741c99275SPeter Avalos {
148411677aeSAaron LI const uint8_t *next;
14941c99275SPeter Avalos
150*ed775ee7SAntonio Huete Jimenez if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
15141c99275SPeter Avalos return -1;
15241c99275SPeter Avalos
153*ed775ee7SAntonio Huete Jimenez *u = GET_LE_S_4(next);
154*ed775ee7SAntonio Huete Jimenez
155*ed775ee7SAntonio Huete Jimenez /* Move pointer past the int32_t. */
156*ed775ee7SAntonio Huete Jimenez cs->c_next = next + sizeof(*u);
157*ed775ee7SAntonio Huete Jimenez return 0;
158*ed775ee7SAntonio Huete Jimenez }
159*ed775ee7SAntonio Huete Jimenez
160*ed775ee7SAntonio Huete Jimenez /* Unpack a 16-bit unsigned integer. */
161*ed775ee7SAntonio Huete Jimenez int
nd_cpack_uint16(netdissect_options * ndo,struct cpack_state * cs,uint16_t * u)162*ed775ee7SAntonio Huete Jimenez nd_cpack_uint16(netdissect_options *ndo, struct cpack_state *cs, uint16_t *u)
163*ed775ee7SAntonio Huete Jimenez {
164*ed775ee7SAntonio Huete Jimenez const uint8_t *next;
165*ed775ee7SAntonio Huete Jimenez
166*ed775ee7SAntonio Huete Jimenez if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
167*ed775ee7SAntonio Huete Jimenez return -1;
168*ed775ee7SAntonio Huete Jimenez
169*ed775ee7SAntonio Huete Jimenez *u = GET_LE_U_2(next);
17041c99275SPeter Avalos
171411677aeSAaron LI /* Move pointer past the uint16_t. */
17241c99275SPeter Avalos cs->c_next = next + sizeof(*u);
17341c99275SPeter Avalos return 0;
17441c99275SPeter Avalos }
17541c99275SPeter Avalos
176*ed775ee7SAntonio Huete Jimenez /* Unpack a 16-bit signed integer. */
177*ed775ee7SAntonio Huete Jimenez int
nd_cpack_int16(netdissect_options * ndo,struct cpack_state * cs,int16_t * u)178*ed775ee7SAntonio Huete Jimenez nd_cpack_int16(netdissect_options *ndo, struct cpack_state *cs, int16_t *u)
179*ed775ee7SAntonio Huete Jimenez {
180*ed775ee7SAntonio Huete Jimenez const uint8_t *next;
181*ed775ee7SAntonio Huete Jimenez
182*ed775ee7SAntonio Huete Jimenez if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
183*ed775ee7SAntonio Huete Jimenez return -1;
184*ed775ee7SAntonio Huete Jimenez
185*ed775ee7SAntonio Huete Jimenez *u = GET_LE_S_2(next);
186*ed775ee7SAntonio Huete Jimenez
187*ed775ee7SAntonio Huete Jimenez /* Move pointer past the int16_t. */
188*ed775ee7SAntonio Huete Jimenez cs->c_next = next + sizeof(*u);
189*ed775ee7SAntonio Huete Jimenez return 0;
190*ed775ee7SAntonio Huete Jimenez }
191*ed775ee7SAntonio Huete Jimenez
19241c99275SPeter Avalos /* Unpack an 8-bit unsigned integer. */
19341c99275SPeter Avalos int
nd_cpack_uint8(netdissect_options * ndo,struct cpack_state * cs,uint8_t * u)194*ed775ee7SAntonio Huete Jimenez nd_cpack_uint8(netdissect_options *ndo, struct cpack_state *cs, uint8_t *u)
19541c99275SPeter Avalos {
19641c99275SPeter Avalos /* No space left? */
19741c99275SPeter Avalos if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
19841c99275SPeter Avalos return -1;
19941c99275SPeter Avalos
200*ed775ee7SAntonio Huete Jimenez *u = GET_U_1(cs->c_next);
20141c99275SPeter Avalos
202411677aeSAaron LI /* Move pointer past the uint8_t. */
20341c99275SPeter Avalos cs->c_next++;
20441c99275SPeter Avalos return 0;
20541c99275SPeter Avalos }
206*ed775ee7SAntonio Huete Jimenez
207*ed775ee7SAntonio Huete Jimenez /* Unpack an 8-bit signed integer. */
208*ed775ee7SAntonio Huete Jimenez int
nd_cpack_int8(netdissect_options * ndo,struct cpack_state * cs,int8_t * u)209*ed775ee7SAntonio Huete Jimenez nd_cpack_int8(netdissect_options *ndo, struct cpack_state *cs, int8_t *u)
210*ed775ee7SAntonio Huete Jimenez {
211*ed775ee7SAntonio Huete Jimenez /* No space left? */
212*ed775ee7SAntonio Huete Jimenez if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
213*ed775ee7SAntonio Huete Jimenez return -1;
214*ed775ee7SAntonio Huete Jimenez
215*ed775ee7SAntonio Huete Jimenez *u = GET_S_1(cs->c_next);
216*ed775ee7SAntonio Huete Jimenez
217*ed775ee7SAntonio Huete Jimenez /* Move pointer past the int8_t. */
218*ed775ee7SAntonio Huete Jimenez cs->c_next++;
219*ed775ee7SAntonio Huete Jimenez return 0;
220*ed775ee7SAntonio Huete Jimenez }
221