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