/src/suricata7/src/util-print.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2010 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | /** |
19 | | * \file |
20 | | * |
21 | | * \author Victor Julien <victor@inliniac.net> |
22 | | * |
23 | | * Print utility functions |
24 | | */ |
25 | | |
26 | | #include "suricata-common.h" |
27 | | #include "util-print.h" |
28 | | #include "util-error.h" |
29 | | #include "util-debug.h" |
30 | | #include "util-validate.h" |
31 | | #include "rust.h" |
32 | | |
33 | | /** |
34 | | * \brief print a buffer as hex on a single line |
35 | | * |
36 | | * Prints in the format "00 AA BB" |
37 | | * |
38 | | * \param nbuf buffer into which the output is written |
39 | | * \param offset of where to start writing into the buffer |
40 | | * \param max_size the size of the output buffer |
41 | | * \param buf buffer to print from |
42 | | * \param buflen length of the input buffer |
43 | | */ |
44 | | void PrintBufferRawLineHex(char *nbuf, int *offset, int max_size, const uint8_t *buf, uint32_t buflen) |
45 | 1.15k | { |
46 | 1.15k | uint32_t u = 0; |
47 | | |
48 | 36.2k | for (u = 0; u < buflen; u++) { |
49 | 35.0k | PrintBufferData(nbuf, offset, max_size, "%02X ", buf[u]); |
50 | 35.0k | } |
51 | 1.15k | } |
52 | | |
53 | | /** |
54 | | * \brief print a buffer as hex on a single line into retbuf buffer |
55 | | * |
56 | | * Prints in the format "00 AA BB" |
57 | | * |
58 | | * \param retbuf pointer to the buffer which will have the result |
59 | | * \param rebuflen length of the buffer |
60 | | * \param buf buffer to print from |
61 | | * \param buflen length of the input buffer |
62 | | */ |
63 | | void PrintRawLineHexBuf(char *retbuf, uint32_t retbuflen, const uint8_t *buf, uint32_t buflen) |
64 | 0 | { |
65 | 0 | uint32_t offset = 0; |
66 | 0 | uint32_t u = 0; |
67 | |
|
68 | 0 | for (u = 0; u < buflen; u++) { |
69 | 0 | PrintBufferData(retbuf, &offset, retbuflen, "%02X ", buf[u]); |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | void PrintRawJsonFp(FILE *fp, uint8_t *buf, uint32_t buflen) |
74 | 0 | { |
75 | 0 | #define BUFFER_LENGTH 2048 |
76 | 0 | char nbuf[BUFFER_LENGTH] = ""; |
77 | 0 | uint32_t offset = 0; |
78 | 0 | uint32_t u = 0; |
79 | |
|
80 | 0 | for (u = 0; u < buflen; u++) { |
81 | 0 | if (buf[u] == '\\' || buf[u] == '/' || buf[u] == '\"') { |
82 | 0 | PrintBufferData(nbuf, &offset, BUFFER_LENGTH, |
83 | 0 | "\\%c", buf[u]); |
84 | 0 | } else if (isprint(buf[u])) { |
85 | 0 | PrintBufferData(nbuf, &offset, BUFFER_LENGTH, |
86 | 0 | "%c", buf[u]); |
87 | 0 | } else { |
88 | 0 | PrintBufferData(nbuf, &offset, BUFFER_LENGTH, |
89 | 0 | "\\\\x%02X", buf[u]); |
90 | 0 | } |
91 | 0 | } |
92 | 0 | fprintf(fp, "%s", nbuf); |
93 | 0 | } |
94 | | |
95 | | void PrintRawUriFp(FILE *fp, uint8_t *buf, uint32_t buflen) |
96 | 0 | { |
97 | 0 | #define BUFFER_LENGTH 2048 |
98 | 0 | char nbuf[BUFFER_LENGTH] = ""; |
99 | 0 | uint32_t offset = 0; |
100 | 0 | uint32_t u = 0; |
101 | |
|
102 | 0 | for (u = 0; u < buflen; u++) { |
103 | 0 | if (isprint(buf[u]) && buf[u] != '\"') { |
104 | 0 | if (buf[u] == '\\') { |
105 | 0 | PrintBufferData(nbuf, &offset, BUFFER_LENGTH, |
106 | 0 | "\\\\"); |
107 | 0 | } else { |
108 | 0 | PrintBufferData(nbuf, &offset, BUFFER_LENGTH, |
109 | 0 | "%c", buf[u]); |
110 | 0 | } |
111 | 0 | } else { |
112 | 0 | PrintBufferData(nbuf, &offset, BUFFER_LENGTH, |
113 | 0 | "\\x%02X", buf[u]); |
114 | 0 | } |
115 | 0 | } |
116 | |
|
117 | 0 | fprintf(fp, "%s", nbuf); |
118 | 0 | } |
119 | | |
120 | | void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, |
121 | | uint8_t *buf, uint32_t buflen) |
122 | 195k | { |
123 | 195k | uint32_t u = 0; |
124 | | |
125 | 10.4M | for (u = 0; u < buflen; u++) { |
126 | 10.2M | if (isprint(buf[u]) && buf[u] != '\"') { |
127 | 5.26M | if (buf[u] == '\\') { |
128 | 19.0k | PrintBufferData(retbuf, offset, retbuflen, |
129 | 19.0k | "\\\\"); |
130 | 5.24M | } else { |
131 | 5.24M | PrintBufferData(retbuf, offset, retbuflen, |
132 | 5.24M | "%c", buf[u]); |
133 | 5.24M | } |
134 | 5.26M | } else { |
135 | 5.03M | PrintBufferData(retbuf, offset, retbuflen, |
136 | 5.03M | "\\x%02X", buf[u]); |
137 | 5.03M | } |
138 | 10.2M | } |
139 | | |
140 | 195k | return; |
141 | 195k | } |
142 | | |
143 | | void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen) |
144 | 0 | { |
145 | 0 | int ch = 0; |
146 | 0 | uint32_t u = 0; |
147 | |
|
148 | 0 | if (buf == NULL) { |
149 | 0 | fprintf(fp, " (null)\n"); |
150 | 0 | return; |
151 | 0 | } |
152 | 0 | for (u = 0; u < buflen; u+=16) { |
153 | 0 | fprintf(fp ," %04X ", u); |
154 | 0 | for (ch = 0; (u+ch) < buflen && ch < 16; ch++) { |
155 | 0 | fprintf(fp, "%02X ", (uint8_t)buf[u+ch]); |
156 | |
|
157 | 0 | if (ch == 7) fprintf(fp, " "); |
158 | 0 | } |
159 | 0 | if (ch == 16) fprintf(fp, " "); |
160 | 0 | else if (ch < 8) { |
161 | 0 | int spaces = (16 - ch) * 3 + 2 + 1; |
162 | 0 | int s = 0; |
163 | 0 | for ( ; s < spaces; s++) fprintf(fp, " "); |
164 | 0 | } else if(ch < 16) { |
165 | 0 | int spaces = (16 - ch) * 3 + 2; |
166 | 0 | int s = 0; |
167 | 0 | for ( ; s < spaces; s++) fprintf(fp, " "); |
168 | 0 | } |
169 | |
|
170 | 0 | for (ch = 0; (u+ch) < buflen && ch < 16; ch++) { |
171 | 0 | fprintf(fp, "%c", isprint((uint8_t)buf[u+ch]) ? (uint8_t)buf[u+ch] : '.'); |
172 | |
|
173 | 0 | if (ch == 7) fprintf(fp, " "); |
174 | 0 | if (ch == 15) fprintf(fp, "\n"); |
175 | 0 | } |
176 | 0 | } |
177 | 0 | if (ch != 16) |
178 | 0 | fprintf(fp, "\n"); |
179 | 0 | } |
180 | | |
181 | | void PrintRawDataToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, |
182 | | const uint8_t *src_buf, uint32_t src_buf_len) |
183 | 0 | { |
184 | 0 | int ch = 0; |
185 | 0 | uint32_t u = 0; |
186 | |
|
187 | 0 | for (u = 0; u < src_buf_len; u+=16) { |
188 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, |
189 | 0 | " %04X ", u); |
190 | 0 | for (ch = 0; (u + ch) < src_buf_len && ch < 16; ch++) { |
191 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, |
192 | 0 | "%02X ", (uint8_t)src_buf[u + ch]); |
193 | |
|
194 | 0 | if (ch == 7) { |
195 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, |
196 | 0 | " "); |
197 | 0 | } |
198 | 0 | } |
199 | 0 | if (ch == 16) { |
200 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, " "); |
201 | 0 | } else if (ch < 8) { |
202 | 0 | int spaces = (16 - ch) * 3 + 2 + 1; |
203 | 0 | int s = 0; |
204 | 0 | for ( ; s < spaces; s++) |
205 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, " "); |
206 | 0 | } else if(ch < 16) { |
207 | 0 | int spaces = (16 - ch) * 3 + 2; |
208 | 0 | int s = 0; |
209 | 0 | for ( ; s < spaces; s++) |
210 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, " "); |
211 | 0 | } |
212 | |
|
213 | 0 | for (ch = 0; (u+ch) < src_buf_len && ch < 16; ch++) { |
214 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, |
215 | 0 | "%c", |
216 | 0 | isprint((uint8_t)src_buf[u + ch]) ? (uint8_t)src_buf[u + ch] : '.'); |
217 | |
|
218 | 0 | if (ch == 7) |
219 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, " "); |
220 | 0 | if (ch == 15) |
221 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, "\n"); |
222 | 0 | } |
223 | 0 | } |
224 | 0 | if (ch != 16) |
225 | 0 | PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, "\n"); |
226 | |
|
227 | 0 | return; |
228 | 0 | } |
229 | | |
230 | | void PrintStringsToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, |
231 | | const uint8_t *src_buf, const uint32_t src_buf_len) |
232 | 0 | { |
233 | 0 | uint32_t ch = 0; |
234 | 0 | for (ch = 0; ch < src_buf_len && *dst_buf_offset_ptr < dst_buf_size; |
235 | 0 | ch++, (*dst_buf_offset_ptr)++) { |
236 | 0 | if (isprint((uint8_t)src_buf[ch]) || src_buf[ch] == '\n' || src_buf[ch] == '\r') { |
237 | 0 | dst_buf[*dst_buf_offset_ptr] = src_buf[ch]; |
238 | 0 | } else { |
239 | 0 | dst_buf[*dst_buf_offset_ptr] = '.'; |
240 | 0 | } |
241 | 0 | } |
242 | 0 | dst_buf[dst_buf_size - 1] = 0; |
243 | |
|
244 | 0 | return; |
245 | 0 | } |
246 | | |
247 | | #ifndef s6_addr16 |
248 | | # define s6_addr16 __u6_addr.__u6_addr16 |
249 | | #endif |
250 | | |
251 | | static const char *PrintInetIPv6(const void *src, char *dst, socklen_t size) |
252 | 5.23M | { |
253 | 5.23M | int i; |
254 | 5.23M | char s_part[6]; |
255 | 5.23M | uint16_t x[8]; |
256 | 5.23M | memcpy(&x, src, 16); |
257 | | |
258 | | /* current IPv6 format is fixed size */ |
259 | 5.23M | if (size < 8 * 5) { |
260 | 0 | SCLogWarning("Too small buffer to write IPv6 address"); |
261 | 0 | return NULL; |
262 | 0 | } |
263 | 5.23M | memset(dst, 0, size); |
264 | 47.0M | for(i = 0; i < 8; i++) { |
265 | 41.8M | snprintf(s_part, sizeof(s_part), "%04x:", htons(x[i])); |
266 | 41.8M | strlcat(dst, s_part, size); |
267 | 41.8M | } |
268 | | /* suppress last ':' */ |
269 | 5.23M | dst[strlen(dst) - 1] = 0; |
270 | | |
271 | 5.23M | return dst; |
272 | 5.23M | } |
273 | | |
274 | | const char *PrintInet(int af, const void *src, char *dst, socklen_t size) |
275 | 25.8M | { |
276 | 25.8M | switch (af) { |
277 | 20.6M | case AF_INET: |
278 | | #if defined(OS_WIN32) && NTDDI_VERSION >= NTDDI_VISTA |
279 | | { |
280 | | // because Windows has to provide a non-conformant inet_ntop, of |
281 | | // course! |
282 | | struct in_addr _src; |
283 | | memcpy(&_src, src, sizeof(struct in_addr)); |
284 | | return inet_ntop(af, &_src, dst, size); |
285 | | } |
286 | | #else |
287 | 20.6M | return inet_ntop(af, src, dst, size); |
288 | 0 | #endif |
289 | 5.23M | case AF_INET6: |
290 | | /* Format IPv6 without deleting zeroes */ |
291 | 5.23M | return PrintInetIPv6(src, dst, size); |
292 | 0 | default: |
293 | 0 | SCLogError("Unsupported protocol: %d", af); |
294 | 25.8M | } |
295 | 0 | return NULL; |
296 | 25.8M | } |
297 | | |
298 | | void PrintHexString(char *str, size_t size, uint8_t *buf, size_t buf_len) |
299 | 167k | { |
300 | 167k | DEBUG_VALIDATE_BUG_ON(size < 2 * buf_len); |
301 | 167k | rs_to_hex((uint8_t *)str, size, buf, buf_len); |
302 | 167k | } |