1411677aeSAaron LI /*
2411677aeSAaron LI * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3411677aeSAaron LI * The Regents of the University of California. All rights reserved.
4411677aeSAaron LI *
5411677aeSAaron LI * Redistribution and use in source and binary forms, with or without
6411677aeSAaron LI * modification, are permitted provided that: (1) source code distributions
7411677aeSAaron LI * retain the above copyright notice and this paragraph in its entirety, (2)
8411677aeSAaron LI * distributions including binary code include the above copyright notice and
9411677aeSAaron LI * this paragraph in its entirety in the documentation or other materials
10411677aeSAaron LI * provided with the distribution, and (3) all advertising materials mentioning
11411677aeSAaron LI * features or use of this software display the following acknowledgement:
12411677aeSAaron LI * ``This product includes software developed by the University of California,
13411677aeSAaron LI * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14411677aeSAaron LI * the University nor the names of its contributors may be used to endorse
15411677aeSAaron LI * or promote products derived from this software without specific prior
16411677aeSAaron LI * written permission.
17411677aeSAaron LI * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18411677aeSAaron LI * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19411677aeSAaron LI * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20411677aeSAaron LI */
21411677aeSAaron LI
22411677aeSAaron LI /*
23411677aeSAaron LI * txtproto_print() derived from original code by Hannes Gredler
24411677aeSAaron LI * (hannes@gredler.at):
25411677aeSAaron LI *
26411677aeSAaron LI * Redistribution and use in source and binary forms, with or without
27411677aeSAaron LI * modification, are permitted provided that: (1) source code
28411677aeSAaron LI * distributions retain the above copyright notice and this paragraph
29411677aeSAaron LI * in its entirety, and (2) distributions including binary code include
30411677aeSAaron LI * the above copyright notice and this paragraph in its entirety in
31411677aeSAaron LI * the documentation or other materials provided with the distribution.
32411677aeSAaron LI * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
33411677aeSAaron LI * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
34411677aeSAaron LI * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35411677aeSAaron LI * FOR A PARTICULAR PURPOSE.
36411677aeSAaron LI */
37411677aeSAaron LI
38411677aeSAaron LI #ifdef HAVE_CONFIG_H
39*ed775ee7SAntonio Huete Jimenez #include <config.h>
40411677aeSAaron LI #endif
41411677aeSAaron LI
42*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
43411677aeSAaron LI
44411677aeSAaron LI #include <sys/stat.h>
45411677aeSAaron LI
46411677aeSAaron LI #ifdef HAVE_FCNTL_H
47411677aeSAaron LI #include <fcntl.h>
48411677aeSAaron LI #endif
49411677aeSAaron LI #include <stdio.h>
50411677aeSAaron LI #include <stdarg.h>
51411677aeSAaron LI #include <stdlib.h>
52411677aeSAaron LI #include <string.h>
53411677aeSAaron LI
54*ed775ee7SAntonio Huete Jimenez #include "netdissect-ctype.h"
55*ed775ee7SAntonio Huete Jimenez
56411677aeSAaron LI #include "netdissect.h"
57*ed775ee7SAntonio Huete Jimenez #include "extract.h"
58411677aeSAaron LI #include "ascii_strcasecmp.h"
59411677aeSAaron LI #include "timeval-operations.h"
60411677aeSAaron LI
61411677aeSAaron LI #define TOKBUFSIZE 128
62411677aeSAaron LI
63*ed775ee7SAntonio Huete Jimenez enum date_flag { WITHOUT_DATE = 0, WITH_DATE = 1 };
64*ed775ee7SAntonio Huete Jimenez enum time_flag { UTC_TIME = 0, LOCAL_TIME = 1 };
65*ed775ee7SAntonio Huete Jimenez
66411677aeSAaron LI /*
67411677aeSAaron LI * Print out a character, filtering out the non-printable ones
68411677aeSAaron LI */
69411677aeSAaron LI void
fn_print_char(netdissect_options * ndo,u_char c)70411677aeSAaron LI fn_print_char(netdissect_options *ndo, u_char c)
71411677aeSAaron LI {
72411677aeSAaron LI if (!ND_ISASCII(c)) {
73411677aeSAaron LI c = ND_TOASCII(c);
74*ed775ee7SAntonio Huete Jimenez ND_PRINT("M-");
75411677aeSAaron LI }
76*ed775ee7SAntonio Huete Jimenez if (!ND_ASCII_ISPRINT(c)) {
77411677aeSAaron LI c ^= 0x40; /* DEL to ?, others to alpha */
78*ed775ee7SAntonio Huete Jimenez ND_PRINT("^");
79411677aeSAaron LI }
80*ed775ee7SAntonio Huete Jimenez ND_PRINT("%c", c);
81411677aeSAaron LI }
82411677aeSAaron LI
83411677aeSAaron LI /*
84*ed775ee7SAntonio Huete Jimenez * Print a null-terminated string, filtering out non-printable characters.
85*ed775ee7SAntonio Huete Jimenez * DON'T USE IT with a pointer on the packet buffer because there is no
86*ed775ee7SAntonio Huete Jimenez * truncation check. For this use, see the nd_printX() functions below.
87411677aeSAaron LI */
88*ed775ee7SAntonio Huete Jimenez void
fn_print_str(netdissect_options * ndo,const u_char * s)89*ed775ee7SAntonio Huete Jimenez fn_print_str(netdissect_options *ndo, const u_char *s)
90411677aeSAaron LI {
91*ed775ee7SAntonio Huete Jimenez while (*s != '\0') {
92*ed775ee7SAntonio Huete Jimenez fn_print_char(ndo, *s);
93*ed775ee7SAntonio Huete Jimenez s++;
94411677aeSAaron LI }
95411677aeSAaron LI }
96411677aeSAaron LI
97411677aeSAaron LI /*
98*ed775ee7SAntonio Huete Jimenez * Print out a null-terminated filename (or other ASCII string) from
99411677aeSAaron LI * a fixed-length field in the packet buffer, or from what remains of
100411677aeSAaron LI * the packet.
101411677aeSAaron LI *
102411677aeSAaron LI * n is the length of the fixed-length field, or the number of bytes
103411677aeSAaron LI * remaining in the packet based on its on-the-network length.
104411677aeSAaron LI *
105411677aeSAaron LI * If ep is non-null, it should point just past the last captured byte
106411677aeSAaron LI * of the packet, e.g. ndo->ndo_snapend. If ep is NULL, we assume no
107411677aeSAaron LI * truncation check, other than the checks of the field length/remaining
108411677aeSAaron LI * packet data length, is needed.
109411677aeSAaron LI *
110411677aeSAaron LI * Return the number of bytes of string processed, including the
111411677aeSAaron LI * terminating null, if not truncated; as the terminating null is
112411677aeSAaron LI * included in the count, and as there must be a terminating null,
113411677aeSAaron LI * this will always be non-zero. Return 0 if truncated.
114411677aeSAaron LI */
115411677aeSAaron LI u_int
nd_printztn(netdissect_options * ndo,const u_char * s,u_int n,const u_char * ep)116*ed775ee7SAntonio Huete Jimenez nd_printztn(netdissect_options *ndo,
117*ed775ee7SAntonio Huete Jimenez const u_char *s, u_int n, const u_char *ep)
118411677aeSAaron LI {
119*ed775ee7SAntonio Huete Jimenez u_int bytes;
120*ed775ee7SAntonio Huete Jimenez u_char c;
121411677aeSAaron LI
122411677aeSAaron LI bytes = 0;
123411677aeSAaron LI for (;;) {
124411677aeSAaron LI if (n == 0 || (ep != NULL && s >= ep)) {
125411677aeSAaron LI /*
126411677aeSAaron LI * Truncated. This includes "no null before we
127411677aeSAaron LI * got to the end of the fixed-length buffer or
128411677aeSAaron LI * the end of the packet".
129411677aeSAaron LI *
130411677aeSAaron LI * XXX - BOOTP says "null-terminated", which
131411677aeSAaron LI * means the maximum length of the string, in
132411677aeSAaron LI * bytes, is 1 less than the size of the buffer,
133411677aeSAaron LI * as there must always be a terminating null.
134411677aeSAaron LI */
135411677aeSAaron LI bytes = 0;
136411677aeSAaron LI break;
137411677aeSAaron LI }
138411677aeSAaron LI
139*ed775ee7SAntonio Huete Jimenez c = GET_U_1(s);
140*ed775ee7SAntonio Huete Jimenez s++;
141411677aeSAaron LI bytes++;
142411677aeSAaron LI n--;
143411677aeSAaron LI if (c == '\0') {
144411677aeSAaron LI /* End of string */
145411677aeSAaron LI break;
146411677aeSAaron LI }
147*ed775ee7SAntonio Huete Jimenez fn_print_char(ndo, c);
148411677aeSAaron LI }
149411677aeSAaron LI return(bytes);
150411677aeSAaron LI }
151411677aeSAaron LI
152411677aeSAaron LI /*
153*ed775ee7SAntonio Huete Jimenez * Print out a counted filename (or other ASCII string), part of
154*ed775ee7SAntonio Huete Jimenez * the packet buffer.
155411677aeSAaron LI * If ep is NULL, assume no truncation check is needed.
156411677aeSAaron LI * Return true if truncated.
157411677aeSAaron LI * Stop at ep (if given) or after n bytes, whichever is first.
158411677aeSAaron LI */
159411677aeSAaron LI int
nd_printn(netdissect_options * ndo,const u_char * s,u_int n,const u_char * ep)160*ed775ee7SAntonio Huete Jimenez nd_printn(netdissect_options *ndo,
161*ed775ee7SAntonio Huete Jimenez const u_char *s, u_int n, const u_char *ep)
162411677aeSAaron LI {
163*ed775ee7SAntonio Huete Jimenez u_char c;
164411677aeSAaron LI
165411677aeSAaron LI while (n > 0 && (ep == NULL || s < ep)) {
166411677aeSAaron LI n--;
167*ed775ee7SAntonio Huete Jimenez c = GET_U_1(s);
168*ed775ee7SAntonio Huete Jimenez s++;
169*ed775ee7SAntonio Huete Jimenez fn_print_char(ndo, c);
170411677aeSAaron LI }
171411677aeSAaron LI return (n == 0) ? 0 : 1;
172411677aeSAaron LI }
173411677aeSAaron LI
174411677aeSAaron LI /*
175*ed775ee7SAntonio Huete Jimenez * Print a null-padded filename (or other ASCII string), part of
176*ed775ee7SAntonio Huete Jimenez * the packet buffer, filtering out non-printable characters.
177*ed775ee7SAntonio Huete Jimenez * Stop if truncated (via GET_U_1/longjmp) or after n bytes or before
178*ed775ee7SAntonio Huete Jimenez * the null char, whichever occurs first.
179*ed775ee7SAntonio Huete Jimenez * The suffix comes from: j:longJmp, n:after N bytes, p:null-Padded.
180411677aeSAaron LI */
181*ed775ee7SAntonio Huete Jimenez void
nd_printjnp(netdissect_options * ndo,const u_char * s,u_int n)182*ed775ee7SAntonio Huete Jimenez nd_printjnp(netdissect_options *ndo, const u_char *s, u_int n)
183411677aeSAaron LI {
184*ed775ee7SAntonio Huete Jimenez u_char c;
185411677aeSAaron LI
186*ed775ee7SAntonio Huete Jimenez while (n > 0) {
187*ed775ee7SAntonio Huete Jimenez c = GET_U_1(s);
188*ed775ee7SAntonio Huete Jimenez if (c == '\0')
189*ed775ee7SAntonio Huete Jimenez break;
190*ed775ee7SAntonio Huete Jimenez fn_print_char(ndo, c);
191411677aeSAaron LI n--;
192*ed775ee7SAntonio Huete Jimenez s++;
193411677aeSAaron LI }
194411677aeSAaron LI }
195411677aeSAaron LI
196411677aeSAaron LI /*
197*ed775ee7SAntonio Huete Jimenez * Print the timestamp .FRAC part (Microseconds/nanoseconds)
198411677aeSAaron LI */
199*ed775ee7SAntonio Huete Jimenez static void
ts_frac_print(netdissect_options * ndo,long usec)200*ed775ee7SAntonio Huete Jimenez ts_frac_print(netdissect_options *ndo, long usec)
201411677aeSAaron LI {
202411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
203411677aeSAaron LI switch (ndo->ndo_tstamp_precision) {
204411677aeSAaron LI
205411677aeSAaron LI case PCAP_TSTAMP_PRECISION_MICRO:
206*ed775ee7SAntonio Huete Jimenez ND_PRINT(".%06u", (unsigned)usec);
207411677aeSAaron LI break;
208411677aeSAaron LI
209411677aeSAaron LI case PCAP_TSTAMP_PRECISION_NANO:
210*ed775ee7SAntonio Huete Jimenez ND_PRINT(".%09u", (unsigned)usec);
211411677aeSAaron LI break;
212411677aeSAaron LI
213411677aeSAaron LI default:
214*ed775ee7SAntonio Huete Jimenez ND_PRINT(".{unknown}");
215411677aeSAaron LI break;
216411677aeSAaron LI }
217411677aeSAaron LI #else
218*ed775ee7SAntonio Huete Jimenez ND_PRINT(".%06u", (unsigned)usec);
219411677aeSAaron LI #endif
220411677aeSAaron LI }
221411677aeSAaron LI
222411677aeSAaron LI /*
223*ed775ee7SAntonio Huete Jimenez * Print the timestamp as [YY:MM:DD] HH:MM:SS.FRAC.
224*ed775ee7SAntonio Huete Jimenez * if time_flag == LOCAL_TIME print local time else UTC/GMT time
225*ed775ee7SAntonio Huete Jimenez * if date_flag == WITH_DATE print YY:MM:DD before HH:MM:SS.FRAC
226411677aeSAaron LI */
227*ed775ee7SAntonio Huete Jimenez static void
ts_date_hmsfrac_print(netdissect_options * ndo,long sec,long usec,enum date_flag date_flag,enum time_flag time_flag)228*ed775ee7SAntonio Huete Jimenez ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec,
229*ed775ee7SAntonio Huete Jimenez enum date_flag date_flag, enum time_flag time_flag)
230411677aeSAaron LI {
231*ed775ee7SAntonio Huete Jimenez time_t Time = sec;
232*ed775ee7SAntonio Huete Jimenez struct tm *tm;
233*ed775ee7SAntonio Huete Jimenez char timestr[32];
234411677aeSAaron LI
235*ed775ee7SAntonio Huete Jimenez if ((unsigned)sec & 0x80000000) {
236*ed775ee7SAntonio Huete Jimenez ND_PRINT("[Error converting time]");
237*ed775ee7SAntonio Huete Jimenez return;
238411677aeSAaron LI }
239411677aeSAaron LI
240*ed775ee7SAntonio Huete Jimenez if (time_flag == LOCAL_TIME)
241*ed775ee7SAntonio Huete Jimenez tm = localtime(&Time);
242*ed775ee7SAntonio Huete Jimenez else
243*ed775ee7SAntonio Huete Jimenez tm = gmtime(&Time);
244411677aeSAaron LI
245*ed775ee7SAntonio Huete Jimenez if (!tm) {
246*ed775ee7SAntonio Huete Jimenez ND_PRINT("[Error converting time]");
247*ed775ee7SAntonio Huete Jimenez return;
248*ed775ee7SAntonio Huete Jimenez }
249*ed775ee7SAntonio Huete Jimenez if (date_flag == WITH_DATE)
250*ed775ee7SAntonio Huete Jimenez strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
251*ed775ee7SAntonio Huete Jimenez else
252*ed775ee7SAntonio Huete Jimenez strftime(timestr, sizeof(timestr), "%H:%M:%S", tm);
253*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s", timestr);
254*ed775ee7SAntonio Huete Jimenez
255*ed775ee7SAntonio Huete Jimenez ts_frac_print(ndo, usec);
256*ed775ee7SAntonio Huete Jimenez }
257*ed775ee7SAntonio Huete Jimenez
258*ed775ee7SAntonio Huete Jimenez /*
259*ed775ee7SAntonio Huete Jimenez * Print the timestamp - Unix timeval style, as SECS.FRAC.
260*ed775ee7SAntonio Huete Jimenez */
261*ed775ee7SAntonio Huete Jimenez static void
ts_unix_print(netdissect_options * ndo,long sec,long usec)262*ed775ee7SAntonio Huete Jimenez ts_unix_print(netdissect_options *ndo, long sec, long usec)
263*ed775ee7SAntonio Huete Jimenez {
264*ed775ee7SAntonio Huete Jimenez if ((unsigned)sec & 0x80000000) {
265*ed775ee7SAntonio Huete Jimenez ND_PRINT("[Error converting time]");
266*ed775ee7SAntonio Huete Jimenez return;
267*ed775ee7SAntonio Huete Jimenez }
268*ed775ee7SAntonio Huete Jimenez
269*ed775ee7SAntonio Huete Jimenez ND_PRINT("%u", (unsigned)sec);
270*ed775ee7SAntonio Huete Jimenez ts_frac_print(ndo, usec);
271411677aeSAaron LI }
272411677aeSAaron LI
273411677aeSAaron LI /*
274411677aeSAaron LI * Print the timestamp
275411677aeSAaron LI */
276411677aeSAaron LI void
ts_print(netdissect_options * ndo,const struct timeval * tvp)277411677aeSAaron LI ts_print(netdissect_options *ndo,
278*ed775ee7SAntonio Huete Jimenez const struct timeval *tvp)
279411677aeSAaron LI {
280411677aeSAaron LI static struct timeval tv_ref;
281411677aeSAaron LI struct timeval tv_result;
282411677aeSAaron LI int negative_offset;
283411677aeSAaron LI int nano_prec;
284411677aeSAaron LI
285411677aeSAaron LI switch (ndo->ndo_tflag) {
286411677aeSAaron LI
287411677aeSAaron LI case 0: /* Default */
288*ed775ee7SAntonio Huete Jimenez ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
289*ed775ee7SAntonio Huete Jimenez WITHOUT_DATE, LOCAL_TIME);
290*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ");
291411677aeSAaron LI break;
292411677aeSAaron LI
293411677aeSAaron LI case 1: /* No time stamp */
294411677aeSAaron LI break;
295411677aeSAaron LI
296411677aeSAaron LI case 2: /* Unix timeval style */
297*ed775ee7SAntonio Huete Jimenez ts_unix_print(ndo, tvp->tv_sec, tvp->tv_usec);
298*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ");
299411677aeSAaron LI break;
300411677aeSAaron LI
301411677aeSAaron LI case 3: /* Microseconds/nanoseconds since previous packet */
302411677aeSAaron LI case 5: /* Microseconds/nanoseconds since first packet */
303411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
304411677aeSAaron LI switch (ndo->ndo_tstamp_precision) {
305411677aeSAaron LI case PCAP_TSTAMP_PRECISION_MICRO:
306411677aeSAaron LI nano_prec = 0;
307411677aeSAaron LI break;
308411677aeSAaron LI case PCAP_TSTAMP_PRECISION_NANO:
309411677aeSAaron LI nano_prec = 1;
310411677aeSAaron LI break;
311411677aeSAaron LI default:
312411677aeSAaron LI nano_prec = 0;
313411677aeSAaron LI break;
314411677aeSAaron LI }
315411677aeSAaron LI #else
316411677aeSAaron LI nano_prec = 0;
317411677aeSAaron LI #endif
318411677aeSAaron LI if (!(netdissect_timevalisset(&tv_ref)))
319411677aeSAaron LI tv_ref = *tvp; /* set timestamp for first packet */
320411677aeSAaron LI
321411677aeSAaron LI negative_offset = netdissect_timevalcmp(tvp, &tv_ref, <);
322411677aeSAaron LI if (negative_offset)
323411677aeSAaron LI netdissect_timevalsub(&tv_ref, tvp, &tv_result, nano_prec);
324411677aeSAaron LI else
325411677aeSAaron LI netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
326411677aeSAaron LI
327*ed775ee7SAntonio Huete Jimenez ND_PRINT((negative_offset ? "-" : " "));
328*ed775ee7SAntonio Huete Jimenez ts_date_hmsfrac_print(ndo, tv_result.tv_sec, tv_result.tv_usec,
329*ed775ee7SAntonio Huete Jimenez WITHOUT_DATE, UTC_TIME);
330*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ");
331411677aeSAaron LI
332411677aeSAaron LI if (ndo->ndo_tflag == 3)
333411677aeSAaron LI tv_ref = *tvp; /* set timestamp for previous packet */
334411677aeSAaron LI break;
335411677aeSAaron LI
336*ed775ee7SAntonio Huete Jimenez case 4: /* Date + Default */
337*ed775ee7SAntonio Huete Jimenez ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
338*ed775ee7SAntonio Huete Jimenez WITH_DATE, LOCAL_TIME);
339*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ");
340411677aeSAaron LI break;
341411677aeSAaron LI }
342411677aeSAaron LI }
343411677aeSAaron LI
344411677aeSAaron LI /*
345411677aeSAaron LI * Print an unsigned relative number of seconds (e.g. hold time, prune timer)
346411677aeSAaron LI * in the form 5m1s. This does no truncation, so 32230861 seconds
347411677aeSAaron LI * is represented as 1y1w1d1h1m1s.
348411677aeSAaron LI */
349411677aeSAaron LI void
unsigned_relts_print(netdissect_options * ndo,uint32_t secs)350411677aeSAaron LI unsigned_relts_print(netdissect_options *ndo,
351411677aeSAaron LI uint32_t secs)
352411677aeSAaron LI {
353411677aeSAaron LI static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
354411677aeSAaron LI static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
355411677aeSAaron LI const char **l = lengths;
356411677aeSAaron LI const u_int *s = seconds;
357411677aeSAaron LI
358411677aeSAaron LI if (secs == 0) {
359*ed775ee7SAntonio Huete Jimenez ND_PRINT("0s");
360411677aeSAaron LI return;
361411677aeSAaron LI }
362411677aeSAaron LI while (secs > 0) {
363411677aeSAaron LI if (secs >= *s) {
364*ed775ee7SAntonio Huete Jimenez ND_PRINT("%u%s", secs / *s, *l);
365411677aeSAaron LI secs -= (secs / *s) * *s;
366411677aeSAaron LI }
367411677aeSAaron LI s++;
368411677aeSAaron LI l++;
369411677aeSAaron LI }
370411677aeSAaron LI }
371411677aeSAaron LI
372411677aeSAaron LI /*
373411677aeSAaron LI * Print a signed relative number of seconds (e.g. hold time, prune timer)
374411677aeSAaron LI * in the form 5m1s. This does no truncation, so 32230861 seconds
375411677aeSAaron LI * is represented as 1y1w1d1h1m1s.
376411677aeSAaron LI */
377411677aeSAaron LI void
signed_relts_print(netdissect_options * ndo,int32_t secs)378411677aeSAaron LI signed_relts_print(netdissect_options *ndo,
379411677aeSAaron LI int32_t secs)
380411677aeSAaron LI {
381411677aeSAaron LI if (secs < 0) {
382*ed775ee7SAntonio Huete Jimenez ND_PRINT("-");
383411677aeSAaron LI if (secs == INT32_MIN) {
384411677aeSAaron LI /*
385411677aeSAaron LI * -2^31; you can't fit its absolute value into
386411677aeSAaron LI * a 32-bit signed integer.
387411677aeSAaron LI *
388411677aeSAaron LI * Just directly pass said absolute value to
389411677aeSAaron LI * unsigned_relts_print() directly.
390411677aeSAaron LI *
391411677aeSAaron LI * (XXX - does ISO C guarantee that -(-2^n),
392411677aeSAaron LI * when calculated and cast to an n-bit unsigned
393411677aeSAaron LI * integer type, will have the value 2^n?)
394411677aeSAaron LI */
395411677aeSAaron LI unsigned_relts_print(ndo, 2147483648U);
396411677aeSAaron LI } else {
397411677aeSAaron LI /*
398411677aeSAaron LI * We now know -secs will fit into an int32_t;
399411677aeSAaron LI * negate it and pass that to unsigned_relts_print().
400411677aeSAaron LI */
401411677aeSAaron LI unsigned_relts_print(ndo, -secs);
402411677aeSAaron LI }
403411677aeSAaron LI return;
404411677aeSAaron LI }
405411677aeSAaron LI unsigned_relts_print(ndo, secs);
406411677aeSAaron LI }
407411677aeSAaron LI
408*ed775ee7SAntonio Huete Jimenez /* Print the truncated string */
nd_print_trunc(netdissect_options * ndo)409*ed775ee7SAntonio Huete Jimenez void nd_print_trunc(netdissect_options *ndo)
410*ed775ee7SAntonio Huete Jimenez {
411*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|%s]", ndo->ndo_protocol);
412*ed775ee7SAntonio Huete Jimenez }
413*ed775ee7SAntonio Huete Jimenez
414*ed775ee7SAntonio Huete Jimenez /* Print the protocol name */
nd_print_protocol(netdissect_options * ndo)415*ed775ee7SAntonio Huete Jimenez void nd_print_protocol(netdissect_options *ndo)
416*ed775ee7SAntonio Huete Jimenez {
417*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s", ndo->ndo_protocol);
418*ed775ee7SAntonio Huete Jimenez }
419*ed775ee7SAntonio Huete Jimenez
420*ed775ee7SAntonio Huete Jimenez /* Print the protocol name in caps (uppercases) */
nd_print_protocol_caps(netdissect_options * ndo)421*ed775ee7SAntonio Huete Jimenez void nd_print_protocol_caps(netdissect_options *ndo)
422*ed775ee7SAntonio Huete Jimenez {
423*ed775ee7SAntonio Huete Jimenez const char *p;
424*ed775ee7SAntonio Huete Jimenez for (p = ndo->ndo_protocol; *p != '\0'; p++)
425*ed775ee7SAntonio Huete Jimenez ND_PRINT("%c", ND_ASCII_TOUPPER(*p));
426*ed775ee7SAntonio Huete Jimenez }
427*ed775ee7SAntonio Huete Jimenez
428*ed775ee7SAntonio Huete Jimenez /* Print the invalid string */
nd_print_invalid(netdissect_options * ndo)429*ed775ee7SAntonio Huete Jimenez void nd_print_invalid(netdissect_options *ndo)
430*ed775ee7SAntonio Huete Jimenez {
431*ed775ee7SAntonio Huete Jimenez ND_PRINT(" (invalid)");
432*ed775ee7SAntonio Huete Jimenez }
433*ed775ee7SAntonio Huete Jimenez
434411677aeSAaron LI /*
435411677aeSAaron LI * this is a generic routine for printing unknown data;
436411677aeSAaron LI * we pass on the linefeed plus indentation string to
437411677aeSAaron LI * get a proper output - returns 0 on error
438411677aeSAaron LI */
439411677aeSAaron LI
440411677aeSAaron LI int
print_unknown_data(netdissect_options * ndo,const u_char * cp,const char * ident,u_int len)441*ed775ee7SAntonio Huete Jimenez print_unknown_data(netdissect_options *ndo, const u_char *cp,
442*ed775ee7SAntonio Huete Jimenez const char *ident, u_int len)
443411677aeSAaron LI {
444*ed775ee7SAntonio Huete Jimenez u_int len_to_print;
445*ed775ee7SAntonio Huete Jimenez
446*ed775ee7SAntonio Huete Jimenez len_to_print = len;
447*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_LEN(cp, 0)) {
448*ed775ee7SAntonio Huete Jimenez ND_PRINT("%sDissector error: print_unknown_data called with pointer past end of packet",
449*ed775ee7SAntonio Huete Jimenez ident);
450411677aeSAaron LI return(0);
451411677aeSAaron LI }
452*ed775ee7SAntonio Huete Jimenez if (ND_BYTES_AVAILABLE_AFTER(cp) < len_to_print)
453*ed775ee7SAntonio Huete Jimenez len_to_print = ND_BYTES_AVAILABLE_AFTER(cp);
454*ed775ee7SAntonio Huete Jimenez hex_print(ndo, ident, cp, len_to_print);
455411677aeSAaron LI return(1); /* everything is ok */
456411677aeSAaron LI }
457411677aeSAaron LI
458411677aeSAaron LI /*
459411677aeSAaron LI * Convert a token value to a string; use "fmt" if not found.
460411677aeSAaron LI */
461411677aeSAaron LI const char *
tok2strbuf(const struct tok * lp,const char * fmt,u_int v,char * buf,size_t bufsize)462*ed775ee7SAntonio Huete Jimenez tok2strbuf(const struct tok *lp, const char *fmt,
463*ed775ee7SAntonio Huete Jimenez u_int v, char *buf, size_t bufsize)
464411677aeSAaron LI {
465411677aeSAaron LI if (lp != NULL) {
466411677aeSAaron LI while (lp->s != NULL) {
467411677aeSAaron LI if (lp->v == v)
468411677aeSAaron LI return (lp->s);
469411677aeSAaron LI ++lp;
470411677aeSAaron LI }
471411677aeSAaron LI }
472411677aeSAaron LI if (fmt == NULL)
473411677aeSAaron LI fmt = "#%d";
474411677aeSAaron LI
475411677aeSAaron LI (void)snprintf(buf, bufsize, fmt, v);
476411677aeSAaron LI return (const char *)buf;
477411677aeSAaron LI }
478411677aeSAaron LI
479411677aeSAaron LI /*
480411677aeSAaron LI * Convert a token value to a string; use "fmt" if not found.
481*ed775ee7SAntonio Huete Jimenez * Uses tok2strbuf() on one of four local static buffers of size TOKBUFSIZE
482*ed775ee7SAntonio Huete Jimenez * in round-robin fashion.
483411677aeSAaron LI */
484411677aeSAaron LI const char *
tok2str(const struct tok * lp,const char * fmt,u_int v)485*ed775ee7SAntonio Huete Jimenez tok2str(const struct tok *lp, const char *fmt,
486*ed775ee7SAntonio Huete Jimenez u_int v)
487411677aeSAaron LI {
488411677aeSAaron LI static char buf[4][TOKBUFSIZE];
489411677aeSAaron LI static int idx = 0;
490411677aeSAaron LI char *ret;
491411677aeSAaron LI
492411677aeSAaron LI ret = buf[idx];
493411677aeSAaron LI idx = (idx+1) & 3;
494411677aeSAaron LI return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
495411677aeSAaron LI }
496411677aeSAaron LI
497411677aeSAaron LI /*
498411677aeSAaron LI * Convert a bit token value to a string; use "fmt" if not found.
499*ed775ee7SAntonio Huete Jimenez * this is useful for parsing bitfields, the output strings are separated
500411677aeSAaron LI * if the s field is positive.
501*ed775ee7SAntonio Huete Jimenez *
502*ed775ee7SAntonio Huete Jimenez * A token matches iff it has one or more bits set and every bit that is set
503*ed775ee7SAntonio Huete Jimenez * in the token is set in v. Consequently, a 0 token never matches.
504411677aeSAaron LI */
505411677aeSAaron LI static char *
bittok2str_internal(const struct tok * lp,const char * fmt,u_int v,const char * sep)506*ed775ee7SAntonio Huete Jimenez bittok2str_internal(const struct tok *lp, const char *fmt,
507*ed775ee7SAntonio Huete Jimenez u_int v, const char *sep)
508411677aeSAaron LI {
509411677aeSAaron LI static char buf[1024+1]; /* our string buffer */
510411677aeSAaron LI char *bufp = buf;
511411677aeSAaron LI size_t space_left = sizeof(buf), string_size;
512411677aeSAaron LI const char * sepstr = "";
513411677aeSAaron LI
514411677aeSAaron LI while (lp != NULL && lp->s != NULL) {
515*ed775ee7SAntonio Huete Jimenez if (lp->v && (v & lp->v) == lp->v) {
516411677aeSAaron LI /* ok we have found something */
517411677aeSAaron LI if (space_left <= 1)
518411677aeSAaron LI return (buf); /* only enough room left for NUL, if that */
519411677aeSAaron LI string_size = strlcpy(bufp, sepstr, space_left);
520411677aeSAaron LI if (string_size >= space_left)
521411677aeSAaron LI return (buf); /* we ran out of room */
522411677aeSAaron LI bufp += string_size;
523411677aeSAaron LI space_left -= string_size;
524411677aeSAaron LI if (space_left <= 1)
525411677aeSAaron LI return (buf); /* only enough room left for NUL, if that */
526411677aeSAaron LI string_size = strlcpy(bufp, lp->s, space_left);
527411677aeSAaron LI if (string_size >= space_left)
528411677aeSAaron LI return (buf); /* we ran out of room */
529411677aeSAaron LI bufp += string_size;
530411677aeSAaron LI space_left -= string_size;
531411677aeSAaron LI sepstr = sep;
532411677aeSAaron LI }
533411677aeSAaron LI lp++;
534411677aeSAaron LI }
535411677aeSAaron LI
536411677aeSAaron LI if (bufp == buf)
537411677aeSAaron LI /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
538411677aeSAaron LI (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v);
539411677aeSAaron LI return (buf);
540411677aeSAaron LI }
541411677aeSAaron LI
542411677aeSAaron LI /*
543411677aeSAaron LI * Convert a bit token value to a string; use "fmt" if not found.
544*ed775ee7SAntonio Huete Jimenez * this is useful for parsing bitfields, the output strings are not separated.
545411677aeSAaron LI */
546411677aeSAaron LI char *
bittok2str_nosep(const struct tok * lp,const char * fmt,u_int v)547*ed775ee7SAntonio Huete Jimenez bittok2str_nosep(const struct tok *lp, const char *fmt,
548*ed775ee7SAntonio Huete Jimenez u_int v)
549411677aeSAaron LI {
550411677aeSAaron LI return (bittok2str_internal(lp, fmt, v, ""));
551411677aeSAaron LI }
552411677aeSAaron LI
553411677aeSAaron LI /*
554411677aeSAaron LI * Convert a bit token value to a string; use "fmt" if not found.
555*ed775ee7SAntonio Huete Jimenez * this is useful for parsing bitfields, the output strings are comma separated.
556411677aeSAaron LI */
557411677aeSAaron LI char *
bittok2str(const struct tok * lp,const char * fmt,u_int v)558*ed775ee7SAntonio Huete Jimenez bittok2str(const struct tok *lp, const char *fmt,
559*ed775ee7SAntonio Huete Jimenez u_int v)
560411677aeSAaron LI {
561411677aeSAaron LI return (bittok2str_internal(lp, fmt, v, ", "));
562411677aeSAaron LI }
563411677aeSAaron LI
564411677aeSAaron LI /*
565411677aeSAaron LI * Convert a value to a string using an array; the macro
566411677aeSAaron LI * tok2strary() in <netdissect.h> is the public interface to
567411677aeSAaron LI * this function and ensures that the second argument is
568411677aeSAaron LI * correct for bounds-checking.
569411677aeSAaron LI */
570411677aeSAaron LI const char *
tok2strary_internal(const char ** lp,int n,const char * fmt,int v)571*ed775ee7SAntonio Huete Jimenez tok2strary_internal(const char **lp, int n, const char *fmt,
572*ed775ee7SAntonio Huete Jimenez int v)
573411677aeSAaron LI {
574411677aeSAaron LI static char buf[TOKBUFSIZE];
575411677aeSAaron LI
576411677aeSAaron LI if (v >= 0 && v < n && lp[v] != NULL)
577411677aeSAaron LI return lp[v];
578411677aeSAaron LI if (fmt == NULL)
579411677aeSAaron LI fmt = "#%d";
580411677aeSAaron LI (void)snprintf(buf, sizeof(buf), fmt, v);
581411677aeSAaron LI return (buf);
582411677aeSAaron LI }
583411677aeSAaron LI
584*ed775ee7SAntonio Huete Jimenez const struct tok *
uint2tokary_internal(const struct uint_tokary dict[],const size_t size,const u_int val)585*ed775ee7SAntonio Huete Jimenez uint2tokary_internal(const struct uint_tokary dict[], const size_t size,
586*ed775ee7SAntonio Huete Jimenez const u_int val)
587*ed775ee7SAntonio Huete Jimenez {
588*ed775ee7SAntonio Huete Jimenez size_t i;
589*ed775ee7SAntonio Huete Jimenez /* Try a direct lookup before the full scan. */
590*ed775ee7SAntonio Huete Jimenez if (val < size && dict[val].uintval == val)
591*ed775ee7SAntonio Huete Jimenez return dict[val].tokary; /* OK if NULL */
592*ed775ee7SAntonio Huete Jimenez for (i = 0; i < size; i++)
593*ed775ee7SAntonio Huete Jimenez if (dict[i].uintval == val)
594*ed775ee7SAntonio Huete Jimenez return dict[i].tokary; /* OK if NULL */
595*ed775ee7SAntonio Huete Jimenez return NULL;
596*ed775ee7SAntonio Huete Jimenez }
597*ed775ee7SAntonio Huete Jimenez
598411677aeSAaron LI /*
599411677aeSAaron LI * Convert a 32-bit netmask to prefixlen if possible
600411677aeSAaron LI * the function returns the prefix-len; if plen == -1
601411677aeSAaron LI * then conversion was not possible;
602411677aeSAaron LI */
603411677aeSAaron LI
604411677aeSAaron LI int
mask2plen(uint32_t mask)605411677aeSAaron LI mask2plen(uint32_t mask)
606411677aeSAaron LI {
607411677aeSAaron LI uint32_t bitmasks[33] = {
608411677aeSAaron LI 0x00000000,
609411677aeSAaron LI 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
610411677aeSAaron LI 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
611411677aeSAaron LI 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
612411677aeSAaron LI 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
613411677aeSAaron LI 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
614411677aeSAaron LI 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
615411677aeSAaron LI 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
616411677aeSAaron LI 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
617411677aeSAaron LI };
618411677aeSAaron LI int prefix_len = 32;
619411677aeSAaron LI
620411677aeSAaron LI /* let's see if we can transform the mask into a prefixlen */
621411677aeSAaron LI while (prefix_len >= 0) {
622411677aeSAaron LI if (bitmasks[prefix_len] == mask)
623411677aeSAaron LI break;
624411677aeSAaron LI prefix_len--;
625411677aeSAaron LI }
626411677aeSAaron LI return (prefix_len);
627411677aeSAaron LI }
628411677aeSAaron LI
629411677aeSAaron LI int
mask62plen(const u_char * mask)630411677aeSAaron LI mask62plen(const u_char *mask)
631411677aeSAaron LI {
632411677aeSAaron LI u_char bitmasks[9] = {
633411677aeSAaron LI 0x00,
634411677aeSAaron LI 0x80, 0xc0, 0xe0, 0xf0,
635411677aeSAaron LI 0xf8, 0xfc, 0xfe, 0xff
636411677aeSAaron LI };
637411677aeSAaron LI int byte;
638411677aeSAaron LI int cidr_len = 0;
639411677aeSAaron LI
640411677aeSAaron LI for (byte = 0; byte < 16; byte++) {
641411677aeSAaron LI u_int bits;
642411677aeSAaron LI
643411677aeSAaron LI for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) {
644411677aeSAaron LI if (mask[byte] == bitmasks[bits]) {
645411677aeSAaron LI cidr_len += bits;
646411677aeSAaron LI break;
647411677aeSAaron LI }
648411677aeSAaron LI }
649411677aeSAaron LI
650411677aeSAaron LI if (mask[byte] != 0xff)
651411677aeSAaron LI break;
652411677aeSAaron LI }
653411677aeSAaron LI return (cidr_len);
654411677aeSAaron LI }
655411677aeSAaron LI
656411677aeSAaron LI /*
657411677aeSAaron LI * Routine to print out information for text-based protocols such as FTP,
658411677aeSAaron LI * HTTP, SMTP, RTSP, SIP, ....
659411677aeSAaron LI */
660411677aeSAaron LI #define MAX_TOKEN 128
661411677aeSAaron LI
662411677aeSAaron LI /*
663411677aeSAaron LI * Fetch a token from a packet, starting at the specified index,
664411677aeSAaron LI * and return the length of the token.
665411677aeSAaron LI *
666411677aeSAaron LI * Returns 0 on error; yes, this is indistinguishable from an empty
667411677aeSAaron LI * token, but an "empty token" isn't a valid token - it just means
668411677aeSAaron LI * either a space character at the beginning of the line (this
669411677aeSAaron LI * includes a blank line) or no more tokens remaining on the line.
670411677aeSAaron LI */
671411677aeSAaron LI static int
fetch_token(netdissect_options * ndo,const u_char * pptr,u_int idx,u_int len,u_char * tbuf,size_t tbuflen)672411677aeSAaron LI fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
673411677aeSAaron LI u_char *tbuf, size_t tbuflen)
674411677aeSAaron LI {
675411677aeSAaron LI size_t toklen = 0;
676*ed775ee7SAntonio Huete Jimenez u_char c;
677411677aeSAaron LI
678411677aeSAaron LI for (; idx < len; idx++) {
679*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_1(pptr + idx)) {
680411677aeSAaron LI /* ran past end of captured data */
681411677aeSAaron LI return (0);
682411677aeSAaron LI }
683*ed775ee7SAntonio Huete Jimenez c = GET_U_1(pptr + idx);
684*ed775ee7SAntonio Huete Jimenez if (!ND_ISASCII(c)) {
685411677aeSAaron LI /* not an ASCII character */
686411677aeSAaron LI return (0);
687411677aeSAaron LI }
688*ed775ee7SAntonio Huete Jimenez if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
689411677aeSAaron LI /* end of token */
690411677aeSAaron LI break;
691411677aeSAaron LI }
692*ed775ee7SAntonio Huete Jimenez if (!ND_ASCII_ISPRINT(c)) {
693411677aeSAaron LI /* not part of a command token or response code */
694411677aeSAaron LI return (0);
695411677aeSAaron LI }
696411677aeSAaron LI if (toklen + 2 > tbuflen) {
697411677aeSAaron LI /* no room for this character and terminating '\0' */
698411677aeSAaron LI return (0);
699411677aeSAaron LI }
700*ed775ee7SAntonio Huete Jimenez tbuf[toklen] = c;
701411677aeSAaron LI toklen++;
702411677aeSAaron LI }
703411677aeSAaron LI if (toklen == 0) {
704411677aeSAaron LI /* no token */
705411677aeSAaron LI return (0);
706411677aeSAaron LI }
707411677aeSAaron LI tbuf[toklen] = '\0';
708411677aeSAaron LI
709411677aeSAaron LI /*
710411677aeSAaron LI * Skip past any white space after the token, until we see
711411677aeSAaron LI * an end-of-line (CR or LF).
712411677aeSAaron LI */
713411677aeSAaron LI for (; idx < len; idx++) {
714*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_1(pptr + idx)) {
715411677aeSAaron LI /* ran past end of captured data */
716411677aeSAaron LI break;
717411677aeSAaron LI }
718*ed775ee7SAntonio Huete Jimenez c = GET_U_1(pptr + idx);
719*ed775ee7SAntonio Huete Jimenez if (c == '\r' || c == '\n') {
720411677aeSAaron LI /* end of line */
721411677aeSAaron LI break;
722411677aeSAaron LI }
723*ed775ee7SAntonio Huete Jimenez if (!ND_ASCII_ISPRINT(c)) {
724411677aeSAaron LI /* not a printable ASCII character */
725411677aeSAaron LI break;
726411677aeSAaron LI }
727*ed775ee7SAntonio Huete Jimenez if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
728411677aeSAaron LI /* beginning of next token */
729411677aeSAaron LI break;
730411677aeSAaron LI }
731411677aeSAaron LI }
732411677aeSAaron LI return (idx);
733411677aeSAaron LI }
734411677aeSAaron LI
735411677aeSAaron LI /*
736411677aeSAaron LI * Scan a buffer looking for a line ending - LF or CR-LF.
737411677aeSAaron LI * Return the index of the character after the line ending or 0 if
738411677aeSAaron LI * we encounter a non-ASCII or non-printable character or don't find
739411677aeSAaron LI * the line ending.
740411677aeSAaron LI */
741411677aeSAaron LI static u_int
print_txt_line(netdissect_options * ndo,const char * prefix,const u_char * pptr,u_int idx,u_int len)742*ed775ee7SAntonio Huete Jimenez print_txt_line(netdissect_options *ndo, const char *prefix,
743*ed775ee7SAntonio Huete Jimenez const u_char *pptr, u_int idx, u_int len)
744411677aeSAaron LI {
745411677aeSAaron LI u_int startidx;
746411677aeSAaron LI u_int linelen;
747*ed775ee7SAntonio Huete Jimenez u_char c;
748411677aeSAaron LI
749411677aeSAaron LI startidx = idx;
750411677aeSAaron LI while (idx < len) {
751*ed775ee7SAntonio Huete Jimenez c = GET_U_1(pptr + idx);
752*ed775ee7SAntonio Huete Jimenez if (c == '\n') {
753411677aeSAaron LI /*
754411677aeSAaron LI * LF without CR; end of line.
755411677aeSAaron LI * Skip the LF and print the line, with the
756411677aeSAaron LI * exception of the LF.
757411677aeSAaron LI */
758411677aeSAaron LI linelen = idx - startidx;
759411677aeSAaron LI idx++;
760411677aeSAaron LI goto print;
761*ed775ee7SAntonio Huete Jimenez } else if (c == '\r') {
762411677aeSAaron LI /* CR - any LF? */
763411677aeSAaron LI if ((idx+1) >= len) {
764411677aeSAaron LI /* not in this packet */
765411677aeSAaron LI return (0);
766411677aeSAaron LI }
767*ed775ee7SAntonio Huete Jimenez if (GET_U_1(pptr + idx + 1) == '\n') {
768411677aeSAaron LI /*
769411677aeSAaron LI * CR-LF; end of line.
770411677aeSAaron LI * Skip the CR-LF and print the line, with
771411677aeSAaron LI * the exception of the CR-LF.
772411677aeSAaron LI */
773411677aeSAaron LI linelen = idx - startidx;
774411677aeSAaron LI idx += 2;
775411677aeSAaron LI goto print;
776411677aeSAaron LI }
777411677aeSAaron LI
778411677aeSAaron LI /*
779411677aeSAaron LI * CR followed by something else; treat this
780411677aeSAaron LI * as if it were binary data, and don't print
781411677aeSAaron LI * it.
782411677aeSAaron LI */
783411677aeSAaron LI return (0);
784*ed775ee7SAntonio Huete Jimenez } else if (!ND_ASCII_ISPRINT(c) && c != '\t') {
785411677aeSAaron LI /*
786411677aeSAaron LI * Not a printable ASCII character and not a tab;
787411677aeSAaron LI * treat this as if it were binary data, and
788411677aeSAaron LI * don't print it.
789411677aeSAaron LI */
790411677aeSAaron LI return (0);
791411677aeSAaron LI }
792411677aeSAaron LI idx++;
793411677aeSAaron LI }
794411677aeSAaron LI
795411677aeSAaron LI /*
796411677aeSAaron LI * All printable ASCII, but no line ending after that point
797411677aeSAaron LI * in the buffer; treat this as if it were truncated.
798411677aeSAaron LI */
799411677aeSAaron LI linelen = idx - startidx;
800*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
801*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
802411677aeSAaron LI return (0);
803411677aeSAaron LI
804411677aeSAaron LI print:
805*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
806411677aeSAaron LI return (idx);
807411677aeSAaron LI }
808411677aeSAaron LI
809*ed775ee7SAntonio Huete Jimenez /* Assign needed before calling txtproto_print(): ndo->ndo_protocol = "proto" */
810411677aeSAaron LI void
txtproto_print(netdissect_options * ndo,const u_char * pptr,u_int len,const char ** cmds,u_int flags)811411677aeSAaron LI txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
812*ed775ee7SAntonio Huete Jimenez const char **cmds, u_int flags)
813411677aeSAaron LI {
814411677aeSAaron LI u_int idx, eol;
815411677aeSAaron LI u_char token[MAX_TOKEN+1];
816411677aeSAaron LI const char *cmd;
817*ed775ee7SAntonio Huete Jimenez int print_this = 0;
818411677aeSAaron LI
819411677aeSAaron LI if (cmds != NULL) {
820411677aeSAaron LI /*
821411677aeSAaron LI * This protocol has more than just request and
822411677aeSAaron LI * response lines; see whether this looks like a
823*ed775ee7SAntonio Huete Jimenez * request or response and, if so, print it and,
824*ed775ee7SAntonio Huete Jimenez * in verbose mode, print everything after it.
825*ed775ee7SAntonio Huete Jimenez *
826*ed775ee7SAntonio Huete Jimenez * This is for HTTP-like protocols, where we
827*ed775ee7SAntonio Huete Jimenez * want to print requests and responses, but
828*ed775ee7SAntonio Huete Jimenez * don't want to print continuations of request
829*ed775ee7SAntonio Huete Jimenez * or response bodies in packets that don't
830*ed775ee7SAntonio Huete Jimenez * contain the request or response line.
831411677aeSAaron LI */
832411677aeSAaron LI idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
833411677aeSAaron LI if (idx != 0) {
834411677aeSAaron LI /* Is this a valid request name? */
835411677aeSAaron LI while ((cmd = *cmds++) != NULL) {
836411677aeSAaron LI if (ascii_strcasecmp((const char *)token, cmd) == 0) {
837411677aeSAaron LI /* Yes. */
838*ed775ee7SAntonio Huete Jimenez print_this = 1;
839411677aeSAaron LI break;
840411677aeSAaron LI }
841411677aeSAaron LI }
842411677aeSAaron LI
843411677aeSAaron LI /*
844411677aeSAaron LI * No - is this a valid response code (3 digits)?
845411677aeSAaron LI *
846411677aeSAaron LI * Is this token the response code, or is the next
847411677aeSAaron LI * token the response code?
848411677aeSAaron LI */
849411677aeSAaron LI if (flags & RESP_CODE_SECOND_TOKEN) {
850411677aeSAaron LI /*
851411677aeSAaron LI * Next token - get it.
852411677aeSAaron LI */
853411677aeSAaron LI idx = fetch_token(ndo, pptr, idx, len, token,
854411677aeSAaron LI sizeof(token));
855411677aeSAaron LI }
856411677aeSAaron LI if (idx != 0) {
857*ed775ee7SAntonio Huete Jimenez if (ND_ASCII_ISDIGIT(token[0]) && ND_ASCII_ISDIGIT(token[1]) &&
858*ed775ee7SAntonio Huete Jimenez ND_ASCII_ISDIGIT(token[2]) && token[3] == '\0') {
859411677aeSAaron LI /* Yes. */
860*ed775ee7SAntonio Huete Jimenez print_this = 1;
861411677aeSAaron LI }
862411677aeSAaron LI }
863411677aeSAaron LI }
864411677aeSAaron LI } else {
865411677aeSAaron LI /*
866*ed775ee7SAntonio Huete Jimenez * Either:
867*ed775ee7SAntonio Huete Jimenez *
868*ed775ee7SAntonio Huete Jimenez * 1) This protocol has only request and response lines
869*ed775ee7SAntonio Huete Jimenez * (e.g., FTP, where all the data goes over a different
870*ed775ee7SAntonio Huete Jimenez * connection); assume the payload is a request or
871*ed775ee7SAntonio Huete Jimenez * response.
872*ed775ee7SAntonio Huete Jimenez *
873*ed775ee7SAntonio Huete Jimenez * or
874*ed775ee7SAntonio Huete Jimenez *
875*ed775ee7SAntonio Huete Jimenez * 2) This protocol is just text, so that we should
876*ed775ee7SAntonio Huete Jimenez * always, at minimum, print the first line and,
877*ed775ee7SAntonio Huete Jimenez * in verbose mode, print all lines.
878411677aeSAaron LI */
879*ed775ee7SAntonio Huete Jimenez print_this = 1;
880411677aeSAaron LI }
881411677aeSAaron LI
882*ed775ee7SAntonio Huete Jimenez nd_print_protocol_caps(ndo);
883411677aeSAaron LI
884*ed775ee7SAntonio Huete Jimenez if (print_this) {
885411677aeSAaron LI /*
886411677aeSAaron LI * In non-verbose mode, just print the protocol, followed
887*ed775ee7SAntonio Huete Jimenez * by the first line.
888411677aeSAaron LI *
889411677aeSAaron LI * In verbose mode, print lines as text until we run out
890411677aeSAaron LI * of characters or see something that's not a
891411677aeSAaron LI * printable-ASCII line.
892411677aeSAaron LI */
893411677aeSAaron LI if (ndo->ndo_vflag) {
894411677aeSAaron LI /*
895411677aeSAaron LI * We're going to print all the text lines in the
896411677aeSAaron LI * request or response; just print the length
897411677aeSAaron LI * on the first line of the output.
898411677aeSAaron LI */
899*ed775ee7SAntonio Huete Jimenez ND_PRINT(", length: %u", len);
900411677aeSAaron LI for (idx = 0;
901*ed775ee7SAntonio Huete Jimenez idx < len && (eol = print_txt_line(ndo, "\n\t", pptr, idx, len)) != 0;
902411677aeSAaron LI idx = eol)
903411677aeSAaron LI ;
904411677aeSAaron LI } else {
905411677aeSAaron LI /*
906411677aeSAaron LI * Just print the first text line.
907411677aeSAaron LI */
908*ed775ee7SAntonio Huete Jimenez print_txt_line(ndo, ": ", pptr, 0, len);
909411677aeSAaron LI }
910411677aeSAaron LI }
911411677aeSAaron LI }
912411677aeSAaron LI
913*ed775ee7SAntonio Huete Jimenez #if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
914*ed775ee7SAntonio Huete Jimenez (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
915*ed775ee7SAntonio Huete Jimenez (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
916*ed775ee7SAntonio Huete Jimenez (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
917*ed775ee7SAntonio Huete Jimenez (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \
918*ed775ee7SAntonio Huete Jimenez defined(__vax__)
919411677aeSAaron LI /*
920*ed775ee7SAntonio Huete Jimenez * The procesor natively handles unaligned loads, so just use memcpy()
921*ed775ee7SAntonio Huete Jimenez * and memcmp(), to enable those optimizations.
922*ed775ee7SAntonio Huete Jimenez *
923*ed775ee7SAntonio Huete Jimenez * XXX - are those all the x86 tests we need?
924*ed775ee7SAntonio Huete Jimenez * XXX - do we need to worry about ARMv1 through ARMv5, which didn't
925*ed775ee7SAntonio Huete Jimenez * support unaligned loads, and, if so, do we need to worry about all
926*ed775ee7SAntonio Huete Jimenez * of them, or just some of them, e.g. ARMv5?
927*ed775ee7SAntonio Huete Jimenez * XXX - are those the only 68k tests we need not to generated
928*ed775ee7SAntonio Huete Jimenez * unaligned accesses if the target is the 68000 or 68010?
929*ed775ee7SAntonio Huete Jimenez * XXX - are there any tests we don't need, because some definitions are for
930*ed775ee7SAntonio Huete Jimenez * compilers that also predefine the GCC symbols?
931*ed775ee7SAntonio Huete Jimenez * XXX - do we need to test for both 32-bit and 64-bit versions of those
932*ed775ee7SAntonio Huete Jimenez * architectures in all cases?
933*ed775ee7SAntonio Huete Jimenez */
934*ed775ee7SAntonio Huete Jimenez #else
935*ed775ee7SAntonio Huete Jimenez /*
936*ed775ee7SAntonio Huete Jimenez * The processor doesn't natively handle unaligned loads,
937*ed775ee7SAntonio Huete Jimenez * and the compiler might "helpfully" optimize memcpy()
938*ed775ee7SAntonio Huete Jimenez * and memcmp(), when handed pointers that would normally
939*ed775ee7SAntonio Huete Jimenez * be properly aligned, into sequences that assume proper
940*ed775ee7SAntonio Huete Jimenez * alignment.
941*ed775ee7SAntonio Huete Jimenez *
942*ed775ee7SAntonio Huete Jimenez * Do copies and compares of possibly-unaligned data by
943*ed775ee7SAntonio Huete Jimenez * calling routines that wrap memcpy() and memcmp(), to
944*ed775ee7SAntonio Huete Jimenez * prevent that optimization.
945411677aeSAaron LI */
946411677aeSAaron LI void
unaligned_memcpy(void * p,const void * q,size_t l)947411677aeSAaron LI unaligned_memcpy(void *p, const void *q, size_t l)
948411677aeSAaron LI {
949411677aeSAaron LI memcpy(p, q, l);
950411677aeSAaron LI }
951411677aeSAaron LI
952411677aeSAaron LI /* As with memcpy(), so with memcmp(). */
953411677aeSAaron LI int
unaligned_memcmp(const void * p,const void * q,size_t l)954411677aeSAaron LI unaligned_memcmp(const void *p, const void *q, size_t l)
955411677aeSAaron LI {
956411677aeSAaron LI return (memcmp(p, q, l));
957411677aeSAaron LI }
958411677aeSAaron LI #endif
959411677aeSAaron LI
960