1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3*b636d99dSDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
4*b636d99dSDavid van Moolenbroek *
5*b636d99dSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*b636d99dSDavid van Moolenbroek * modification, are permitted provided that: (1) source code distributions
7*b636d99dSDavid van Moolenbroek * retain the above copyright notice and this paragraph in its entirety, (2)
8*b636d99dSDavid van Moolenbroek * distributions including binary code include the above copyright notice and
9*b636d99dSDavid van Moolenbroek * this paragraph in its entirety in the documentation or other materials
10*b636d99dSDavid van Moolenbroek * provided with the distribution, and (3) all advertising materials mentioning
11*b636d99dSDavid van Moolenbroek * features or use of this software display the following acknowledgement:
12*b636d99dSDavid van Moolenbroek * ``This product includes software developed by the University of California,
13*b636d99dSDavid van Moolenbroek * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*b636d99dSDavid van Moolenbroek * the University nor the names of its contributors may be used to endorse
15*b636d99dSDavid van Moolenbroek * or promote products derived from this software without specific prior
16*b636d99dSDavid van Moolenbroek * written permission.
17*b636d99dSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*b636d99dSDavid van Moolenbroek * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*b636d99dSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*b636d99dSDavid van Moolenbroek */
21*b636d99dSDavid van Moolenbroek
22*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
23*b636d99dSDavid van Moolenbroek #ifndef lint
24*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: util.c,v 1.5 2015/03/31 21:59:35 christos Exp $");
25*b636d99dSDavid van Moolenbroek #endif
26*b636d99dSDavid van Moolenbroek
27*b636d99dSDavid van Moolenbroek /*
28*b636d99dSDavid van Moolenbroek * txtproto_print() derived from original code by Hannes Gredler
29*b636d99dSDavid van Moolenbroek * (hannes@juniper.net):
30*b636d99dSDavid van Moolenbroek *
31*b636d99dSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
32*b636d99dSDavid van Moolenbroek * modification, are permitted provided that: (1) source code
33*b636d99dSDavid van Moolenbroek * distributions retain the above copyright notice and this paragraph
34*b636d99dSDavid van Moolenbroek * in its entirety, and (2) distributions including binary code include
35*b636d99dSDavid van Moolenbroek * the above copyright notice and this paragraph in its entirety in
36*b636d99dSDavid van Moolenbroek * the documentation or other materials provided with the distribution.
37*b636d99dSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
38*b636d99dSDavid van Moolenbroek * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
39*b636d99dSDavid van Moolenbroek * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
40*b636d99dSDavid van Moolenbroek * FOR A PARTICULAR PURPOSE.
41*b636d99dSDavid van Moolenbroek */
42*b636d99dSDavid van Moolenbroek
43*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
44*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
45*b636d99dSDavid van Moolenbroek #include "config.h"
46*b636d99dSDavid van Moolenbroek #endif
47*b636d99dSDavid van Moolenbroek
48*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
49*b636d99dSDavid van Moolenbroek
50*b636d99dSDavid van Moolenbroek #include <sys/stat.h>
51*b636d99dSDavid van Moolenbroek
52*b636d99dSDavid van Moolenbroek #ifdef HAVE_FCNTL_H
53*b636d99dSDavid van Moolenbroek #include <fcntl.h>
54*b636d99dSDavid van Moolenbroek #endif
55*b636d99dSDavid van Moolenbroek #include <stdio.h>
56*b636d99dSDavid van Moolenbroek #include <stdarg.h>
57*b636d99dSDavid van Moolenbroek #include <stdlib.h>
58*b636d99dSDavid van Moolenbroek #include <string.h>
59*b636d99dSDavid van Moolenbroek
60*b636d99dSDavid van Moolenbroek #include "interface.h"
61*b636d99dSDavid van Moolenbroek
62*b636d99dSDavid van Moolenbroek /*
63*b636d99dSDavid van Moolenbroek * Print out a null-terminated filename (or other ascii string).
64*b636d99dSDavid van Moolenbroek * If ep is NULL, assume no truncation check is needed.
65*b636d99dSDavid van Moolenbroek * Return true if truncated.
66*b636d99dSDavid van Moolenbroek */
67*b636d99dSDavid van Moolenbroek int
fn_print(netdissect_options * ndo,register const u_char * s,register const u_char * ep)68*b636d99dSDavid van Moolenbroek fn_print(netdissect_options *ndo,
69*b636d99dSDavid van Moolenbroek register const u_char *s, register const u_char *ep)
70*b636d99dSDavid van Moolenbroek {
71*b636d99dSDavid van Moolenbroek register int ret;
72*b636d99dSDavid van Moolenbroek register u_char c;
73*b636d99dSDavid van Moolenbroek
74*b636d99dSDavid van Moolenbroek ret = 1; /* assume truncated */
75*b636d99dSDavid van Moolenbroek while (ep == NULL || s < ep) {
76*b636d99dSDavid van Moolenbroek c = *s++;
77*b636d99dSDavid van Moolenbroek if (c == '\0') {
78*b636d99dSDavid van Moolenbroek ret = 0;
79*b636d99dSDavid van Moolenbroek break;
80*b636d99dSDavid van Moolenbroek }
81*b636d99dSDavid van Moolenbroek if (!ND_ISASCII(c)) {
82*b636d99dSDavid van Moolenbroek c = ND_TOASCII(c);
83*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "M-"));
84*b636d99dSDavid van Moolenbroek }
85*b636d99dSDavid van Moolenbroek if (!ND_ISPRINT(c)) {
86*b636d99dSDavid van Moolenbroek c ^= 0x40; /* DEL to ?, others to alpha */
87*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "^"));
88*b636d99dSDavid van Moolenbroek }
89*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%c", c));
90*b636d99dSDavid van Moolenbroek }
91*b636d99dSDavid van Moolenbroek return(ret);
92*b636d99dSDavid van Moolenbroek }
93*b636d99dSDavid van Moolenbroek
94*b636d99dSDavid van Moolenbroek /*
95*b636d99dSDavid van Moolenbroek * Print out a counted filename (or other ascii string).
96*b636d99dSDavid van Moolenbroek * If ep is NULL, assume no truncation check is needed.
97*b636d99dSDavid van Moolenbroek * Return true if truncated.
98*b636d99dSDavid van Moolenbroek */
99*b636d99dSDavid van Moolenbroek int
fn_printn(netdissect_options * ndo,register const u_char * s,register u_int n,register const u_char * ep)100*b636d99dSDavid van Moolenbroek fn_printn(netdissect_options *ndo,
101*b636d99dSDavid van Moolenbroek register const u_char *s, register u_int n, register const u_char *ep)
102*b636d99dSDavid van Moolenbroek {
103*b636d99dSDavid van Moolenbroek register u_char c;
104*b636d99dSDavid van Moolenbroek
105*b636d99dSDavid van Moolenbroek while (n > 0 && (ep == NULL || s < ep)) {
106*b636d99dSDavid van Moolenbroek n--;
107*b636d99dSDavid van Moolenbroek c = *s++;
108*b636d99dSDavid van Moolenbroek if (!ND_ISASCII(c)) {
109*b636d99dSDavid van Moolenbroek c = ND_TOASCII(c);
110*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "M-"));
111*b636d99dSDavid van Moolenbroek }
112*b636d99dSDavid van Moolenbroek if (!ND_ISPRINT(c)) {
113*b636d99dSDavid van Moolenbroek c ^= 0x40; /* DEL to ?, others to alpha */
114*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "^"));
115*b636d99dSDavid van Moolenbroek }
116*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%c", c));
117*b636d99dSDavid van Moolenbroek }
118*b636d99dSDavid van Moolenbroek return (n == 0) ? 0 : 1;
119*b636d99dSDavid van Moolenbroek }
120*b636d99dSDavid van Moolenbroek
121*b636d99dSDavid van Moolenbroek /*
122*b636d99dSDavid van Moolenbroek * Print out a null-padded filename (or other ascii string).
123*b636d99dSDavid van Moolenbroek * If ep is NULL, assume no truncation check is needed.
124*b636d99dSDavid van Moolenbroek * Return true if truncated.
125*b636d99dSDavid van Moolenbroek */
126*b636d99dSDavid van Moolenbroek int
fn_printzp(netdissect_options * ndo,register const u_char * s,register u_int n,register const u_char * ep)127*b636d99dSDavid van Moolenbroek fn_printzp(netdissect_options *ndo,
128*b636d99dSDavid van Moolenbroek register const u_char *s, register u_int n,
129*b636d99dSDavid van Moolenbroek register const u_char *ep)
130*b636d99dSDavid van Moolenbroek {
131*b636d99dSDavid van Moolenbroek register int ret;
132*b636d99dSDavid van Moolenbroek register u_char c;
133*b636d99dSDavid van Moolenbroek
134*b636d99dSDavid van Moolenbroek ret = 1; /* assume truncated */
135*b636d99dSDavid van Moolenbroek while (n > 0 && (ep == NULL || s < ep)) {
136*b636d99dSDavid van Moolenbroek n--;
137*b636d99dSDavid van Moolenbroek c = *s++;
138*b636d99dSDavid van Moolenbroek if (c == '\0') {
139*b636d99dSDavid van Moolenbroek ret = 0;
140*b636d99dSDavid van Moolenbroek break;
141*b636d99dSDavid van Moolenbroek }
142*b636d99dSDavid van Moolenbroek if (!ND_ISASCII(c)) {
143*b636d99dSDavid van Moolenbroek c = ND_TOASCII(c);
144*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "M-"));
145*b636d99dSDavid van Moolenbroek }
146*b636d99dSDavid van Moolenbroek if (!ND_ISPRINT(c)) {
147*b636d99dSDavid van Moolenbroek c ^= 0x40; /* DEL to ?, others to alpha */
148*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "^"));
149*b636d99dSDavid van Moolenbroek }
150*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%c", c));
151*b636d99dSDavid van Moolenbroek }
152*b636d99dSDavid van Moolenbroek return (n == 0) ? 0 : ret;
153*b636d99dSDavid van Moolenbroek }
154*b636d99dSDavid van Moolenbroek
155*b636d99dSDavid van Moolenbroek /*
156*b636d99dSDavid van Moolenbroek * Format the timestamp
157*b636d99dSDavid van Moolenbroek */
158*b636d99dSDavid van Moolenbroek static char *
ts_format(netdissect_options * ndo _U_,int sec,int usec)159*b636d99dSDavid van Moolenbroek ts_format(netdissect_options *ndo
160*b636d99dSDavid van Moolenbroek #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
161*b636d99dSDavid van Moolenbroek _U_
162*b636d99dSDavid van Moolenbroek #endif
163*b636d99dSDavid van Moolenbroek , int sec, int usec)
164*b636d99dSDavid van Moolenbroek {
165*b636d99dSDavid van Moolenbroek static char buf[sizeof("00:00:00.000000000")];
166*b636d99dSDavid van Moolenbroek const char *format;
167*b636d99dSDavid van Moolenbroek
168*b636d99dSDavid van Moolenbroek #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
169*b636d99dSDavid van Moolenbroek switch (ndo->ndo_tstamp_precision) {
170*b636d99dSDavid van Moolenbroek
171*b636d99dSDavid van Moolenbroek case PCAP_TSTAMP_PRECISION_MICRO:
172*b636d99dSDavid van Moolenbroek format = "%02d:%02d:%02d.%06u";
173*b636d99dSDavid van Moolenbroek break;
174*b636d99dSDavid van Moolenbroek
175*b636d99dSDavid van Moolenbroek case PCAP_TSTAMP_PRECISION_NANO:
176*b636d99dSDavid van Moolenbroek format = "%02d:%02d:%02d.%09u";
177*b636d99dSDavid van Moolenbroek break;
178*b636d99dSDavid van Moolenbroek
179*b636d99dSDavid van Moolenbroek default:
180*b636d99dSDavid van Moolenbroek format = "%02d:%02d:%02d.{unknown precision}";
181*b636d99dSDavid van Moolenbroek break;
182*b636d99dSDavid van Moolenbroek }
183*b636d99dSDavid van Moolenbroek #else
184*b636d99dSDavid van Moolenbroek format = "%02d:%02d:%02d.%06u";
185*b636d99dSDavid van Moolenbroek #endif
186*b636d99dSDavid van Moolenbroek
187*b636d99dSDavid van Moolenbroek snprintf(buf, sizeof(buf), format,
188*b636d99dSDavid van Moolenbroek sec / 3600, (sec % 3600) / 60, sec % 60, usec);
189*b636d99dSDavid van Moolenbroek
190*b636d99dSDavid van Moolenbroek return buf;
191*b636d99dSDavid van Moolenbroek }
192*b636d99dSDavid van Moolenbroek
193*b636d99dSDavid van Moolenbroek /*
194*b636d99dSDavid van Moolenbroek * Print the timestamp
195*b636d99dSDavid van Moolenbroek */
196*b636d99dSDavid van Moolenbroek void
ts_print(netdissect_options * ndo,register const struct timeval * tvp)197*b636d99dSDavid van Moolenbroek ts_print(netdissect_options *ndo,
198*b636d99dSDavid van Moolenbroek register const struct timeval *tvp)
199*b636d99dSDavid van Moolenbroek {
200*b636d99dSDavid van Moolenbroek register int s;
201*b636d99dSDavid van Moolenbroek struct tm *tm;
202*b636d99dSDavid van Moolenbroek time_t Time;
203*b636d99dSDavid van Moolenbroek static unsigned b_sec;
204*b636d99dSDavid van Moolenbroek static unsigned b_usec;
205*b636d99dSDavid van Moolenbroek int d_usec;
206*b636d99dSDavid van Moolenbroek int d_sec;
207*b636d99dSDavid van Moolenbroek
208*b636d99dSDavid van Moolenbroek switch (ndo->ndo_tflag) {
209*b636d99dSDavid van Moolenbroek
210*b636d99dSDavid van Moolenbroek case 0: /* Default */
211*b636d99dSDavid van Moolenbroek s = (tvp->tv_sec + thiszone) % 86400;
212*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec)));
213*b636d99dSDavid van Moolenbroek break;
214*b636d99dSDavid van Moolenbroek
215*b636d99dSDavid van Moolenbroek case 1: /* No time stamp */
216*b636d99dSDavid van Moolenbroek break;
217*b636d99dSDavid van Moolenbroek
218*b636d99dSDavid van Moolenbroek case 2: /* Unix timeval style */
219*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%u.%06u ",
220*b636d99dSDavid van Moolenbroek (unsigned)tvp->tv_sec,
221*b636d99dSDavid van Moolenbroek (unsigned)tvp->tv_usec));
222*b636d99dSDavid van Moolenbroek break;
223*b636d99dSDavid van Moolenbroek
224*b636d99dSDavid van Moolenbroek case 3: /* Microseconds since previous packet */
225*b636d99dSDavid van Moolenbroek case 5: /* Microseconds since first packet */
226*b636d99dSDavid van Moolenbroek if (b_sec == 0) {
227*b636d99dSDavid van Moolenbroek /* init timestamp for first packet */
228*b636d99dSDavid van Moolenbroek b_usec = tvp->tv_usec;
229*b636d99dSDavid van Moolenbroek b_sec = tvp->tv_sec;
230*b636d99dSDavid van Moolenbroek }
231*b636d99dSDavid van Moolenbroek
232*b636d99dSDavid van Moolenbroek d_usec = tvp->tv_usec - b_usec;
233*b636d99dSDavid van Moolenbroek d_sec = tvp->tv_sec - b_sec;
234*b636d99dSDavid van Moolenbroek
235*b636d99dSDavid van Moolenbroek while (d_usec < 0) {
236*b636d99dSDavid van Moolenbroek d_usec += 1000000;
237*b636d99dSDavid van Moolenbroek d_sec--;
238*b636d99dSDavid van Moolenbroek }
239*b636d99dSDavid van Moolenbroek
240*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec)));
241*b636d99dSDavid van Moolenbroek
242*b636d99dSDavid van Moolenbroek if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */
243*b636d99dSDavid van Moolenbroek b_sec = tvp->tv_sec;
244*b636d99dSDavid van Moolenbroek b_usec = tvp->tv_usec;
245*b636d99dSDavid van Moolenbroek }
246*b636d99dSDavid van Moolenbroek break;
247*b636d99dSDavid van Moolenbroek
248*b636d99dSDavid van Moolenbroek case 4: /* Default + Date*/
249*b636d99dSDavid van Moolenbroek s = (tvp->tv_sec + thiszone) % 86400;
250*b636d99dSDavid van Moolenbroek Time = (tvp->tv_sec + thiszone) - s;
251*b636d99dSDavid van Moolenbroek tm = gmtime (&Time);
252*b636d99dSDavid van Moolenbroek if (!tm)
253*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Date fail "));
254*b636d99dSDavid van Moolenbroek else
255*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%04d-%02d-%02d %s ",
256*b636d99dSDavid van Moolenbroek tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
257*b636d99dSDavid van Moolenbroek ts_format(ndo, s, tvp->tv_usec)));
258*b636d99dSDavid van Moolenbroek break;
259*b636d99dSDavid van Moolenbroek }
260*b636d99dSDavid van Moolenbroek }
261*b636d99dSDavid van Moolenbroek
262*b636d99dSDavid van Moolenbroek /*
263*b636d99dSDavid van Moolenbroek * Print a relative number of seconds (e.g. hold time, prune timer)
264*b636d99dSDavid van Moolenbroek * in the form 5m1s. This does no truncation, so 32230861 seconds
265*b636d99dSDavid van Moolenbroek * is represented as 1y1w1d1h1m1s.
266*b636d99dSDavid van Moolenbroek */
267*b636d99dSDavid van Moolenbroek void
relts_print(netdissect_options * ndo,int secs)268*b636d99dSDavid van Moolenbroek relts_print(netdissect_options *ndo,
269*b636d99dSDavid van Moolenbroek int secs)
270*b636d99dSDavid van Moolenbroek {
271*b636d99dSDavid van Moolenbroek static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
272*b636d99dSDavid van Moolenbroek static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
273*b636d99dSDavid van Moolenbroek const char **l = lengths;
274*b636d99dSDavid van Moolenbroek const int *s = seconds;
275*b636d99dSDavid van Moolenbroek
276*b636d99dSDavid van Moolenbroek if (secs == 0) {
277*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "0s"));
278*b636d99dSDavid van Moolenbroek return;
279*b636d99dSDavid van Moolenbroek }
280*b636d99dSDavid van Moolenbroek if (secs < 0) {
281*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "-"));
282*b636d99dSDavid van Moolenbroek secs = -secs;
283*b636d99dSDavid van Moolenbroek }
284*b636d99dSDavid van Moolenbroek while (secs > 0) {
285*b636d99dSDavid van Moolenbroek if (secs >= *s) {
286*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%d%s", secs / *s, *l));
287*b636d99dSDavid van Moolenbroek secs -= (secs / *s) * *s;
288*b636d99dSDavid van Moolenbroek }
289*b636d99dSDavid van Moolenbroek s++;
290*b636d99dSDavid van Moolenbroek l++;
291*b636d99dSDavid van Moolenbroek }
292*b636d99dSDavid van Moolenbroek }
293*b636d99dSDavid van Moolenbroek
294*b636d99dSDavid van Moolenbroek /*
295*b636d99dSDavid van Moolenbroek * this is a generic routine for printing unknown data;
296*b636d99dSDavid van Moolenbroek * we pass on the linefeed plus indentation string to
297*b636d99dSDavid van Moolenbroek * get a proper output - returns 0 on error
298*b636d99dSDavid van Moolenbroek */
299*b636d99dSDavid van Moolenbroek
300*b636d99dSDavid van Moolenbroek int
print_unknown_data(netdissect_options * ndo,const u_char * cp,const char * ident,int len)301*b636d99dSDavid van Moolenbroek print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len)
302*b636d99dSDavid van Moolenbroek {
303*b636d99dSDavid van Moolenbroek if (len < 0) {
304*b636d99dSDavid van Moolenbroek ND_PRINT((ndo,"%sDissector error: print_unknown_data called with negative length",
305*b636d99dSDavid van Moolenbroek ident));
306*b636d99dSDavid van Moolenbroek return(0);
307*b636d99dSDavid van Moolenbroek }
308*b636d99dSDavid van Moolenbroek if (ndo->ndo_snapend - cp < len)
309*b636d99dSDavid van Moolenbroek len = ndo->ndo_snapend - cp;
310*b636d99dSDavid van Moolenbroek if (len < 0) {
311*b636d99dSDavid van Moolenbroek ND_PRINT((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet",
312*b636d99dSDavid van Moolenbroek ident));
313*b636d99dSDavid van Moolenbroek return(0);
314*b636d99dSDavid van Moolenbroek }
315*b636d99dSDavid van Moolenbroek hex_print(ndo, ident,cp,len);
316*b636d99dSDavid van Moolenbroek return(1); /* everything is ok */
317*b636d99dSDavid van Moolenbroek }
318*b636d99dSDavid van Moolenbroek
319*b636d99dSDavid van Moolenbroek /*
320*b636d99dSDavid van Moolenbroek * Convert a token value to a string; use "fmt" if not found.
321*b636d99dSDavid van Moolenbroek */
322*b636d99dSDavid van Moolenbroek const char *
tok2strbuf(register const struct tok * lp,register const char * fmt,register u_int v,char * buf,size_t bufsize)323*b636d99dSDavid van Moolenbroek tok2strbuf(register const struct tok *lp, register const char *fmt,
324*b636d99dSDavid van Moolenbroek register u_int v, char *buf, size_t bufsize)
325*b636d99dSDavid van Moolenbroek {
326*b636d99dSDavid van Moolenbroek if (lp != NULL) {
327*b636d99dSDavid van Moolenbroek while (lp->s != NULL) {
328*b636d99dSDavid van Moolenbroek if (lp->v == v)
329*b636d99dSDavid van Moolenbroek return (lp->s);
330*b636d99dSDavid van Moolenbroek ++lp;
331*b636d99dSDavid van Moolenbroek }
332*b636d99dSDavid van Moolenbroek }
333*b636d99dSDavid van Moolenbroek if (fmt == NULL)
334*b636d99dSDavid van Moolenbroek fmt = "#%d";
335*b636d99dSDavid van Moolenbroek
336*b636d99dSDavid van Moolenbroek (void)snprintf(buf, bufsize, fmt, v);
337*b636d99dSDavid van Moolenbroek return (const char *)buf;
338*b636d99dSDavid van Moolenbroek }
339*b636d99dSDavid van Moolenbroek
340*b636d99dSDavid van Moolenbroek /*
341*b636d99dSDavid van Moolenbroek * Convert a token value to a string; use "fmt" if not found.
342*b636d99dSDavid van Moolenbroek */
343*b636d99dSDavid van Moolenbroek const char *
tok2str(register const struct tok * lp,register const char * fmt,register int v)344*b636d99dSDavid van Moolenbroek tok2str(register const struct tok *lp, register const char *fmt,
345*b636d99dSDavid van Moolenbroek register int v)
346*b636d99dSDavid van Moolenbroek {
347*b636d99dSDavid van Moolenbroek static char buf[4][128];
348*b636d99dSDavid van Moolenbroek static int idx = 0;
349*b636d99dSDavid van Moolenbroek char *ret;
350*b636d99dSDavid van Moolenbroek
351*b636d99dSDavid van Moolenbroek ret = buf[idx];
352*b636d99dSDavid van Moolenbroek idx = (idx+1) & 3;
353*b636d99dSDavid van Moolenbroek return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
354*b636d99dSDavid van Moolenbroek }
355*b636d99dSDavid van Moolenbroek
356*b636d99dSDavid van Moolenbroek /*
357*b636d99dSDavid van Moolenbroek * Convert a bit token value to a string; use "fmt" if not found.
358*b636d99dSDavid van Moolenbroek * this is useful for parsing bitfields, the output strings are seperated
359*b636d99dSDavid van Moolenbroek * if the s field is positive.
360*b636d99dSDavid van Moolenbroek */
361*b636d99dSDavid van Moolenbroek static char *
bittok2str_internal(register const struct tok * lp,register const char * fmt,register int v,register int sep)362*b636d99dSDavid van Moolenbroek bittok2str_internal(register const struct tok *lp, register const char *fmt,
363*b636d99dSDavid van Moolenbroek register int v, register int sep)
364*b636d99dSDavid van Moolenbroek {
365*b636d99dSDavid van Moolenbroek static char buf[256]; /* our stringbuffer */
366*b636d99dSDavid van Moolenbroek int buflen=0;
367*b636d99dSDavid van Moolenbroek register int rotbit; /* this is the bit we rotate through all bitpositions */
368*b636d99dSDavid van Moolenbroek register int tokval;
369*b636d99dSDavid van Moolenbroek const char * sepstr = "";
370*b636d99dSDavid van Moolenbroek
371*b636d99dSDavid van Moolenbroek while (lp != NULL && lp->s != NULL) {
372*b636d99dSDavid van Moolenbroek tokval=lp->v; /* load our first value */
373*b636d99dSDavid van Moolenbroek rotbit=1;
374*b636d99dSDavid van Moolenbroek while (rotbit != 0) {
375*b636d99dSDavid van Moolenbroek /*
376*b636d99dSDavid van Moolenbroek * lets AND the rotating bit with our token value
377*b636d99dSDavid van Moolenbroek * and see if we have got a match
378*b636d99dSDavid van Moolenbroek */
379*b636d99dSDavid van Moolenbroek if (tokval == (v&rotbit)) {
380*b636d99dSDavid van Moolenbroek /* ok we have found something */
381*b636d99dSDavid van Moolenbroek buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
382*b636d99dSDavid van Moolenbroek sepstr, lp->s);
383*b636d99dSDavid van Moolenbroek sepstr = sep ? ", " : "";
384*b636d99dSDavid van Moolenbroek break;
385*b636d99dSDavid van Moolenbroek }
386*b636d99dSDavid van Moolenbroek rotbit=rotbit<<1; /* no match - lets shift and try again */
387*b636d99dSDavid van Moolenbroek }
388*b636d99dSDavid van Moolenbroek lp++;
389*b636d99dSDavid van Moolenbroek }
390*b636d99dSDavid van Moolenbroek
391*b636d99dSDavid van Moolenbroek if (buflen == 0)
392*b636d99dSDavid van Moolenbroek /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
393*b636d99dSDavid van Moolenbroek (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%d" : fmt, v);
394*b636d99dSDavid van Moolenbroek return (buf);
395*b636d99dSDavid van Moolenbroek }
396*b636d99dSDavid van Moolenbroek
397*b636d99dSDavid van Moolenbroek /*
398*b636d99dSDavid van Moolenbroek * Convert a bit token value to a string; use "fmt" if not found.
399*b636d99dSDavid van Moolenbroek * this is useful for parsing bitfields, the output strings are not seperated.
400*b636d99dSDavid van Moolenbroek */
401*b636d99dSDavid van Moolenbroek char *
bittok2str_nosep(register const struct tok * lp,register const char * fmt,register int v)402*b636d99dSDavid van Moolenbroek bittok2str_nosep(register const struct tok *lp, register const char *fmt,
403*b636d99dSDavid van Moolenbroek register int v)
404*b636d99dSDavid van Moolenbroek {
405*b636d99dSDavid van Moolenbroek return (bittok2str_internal(lp, fmt, v, 0));
406*b636d99dSDavid van Moolenbroek }
407*b636d99dSDavid van Moolenbroek
408*b636d99dSDavid van Moolenbroek /*
409*b636d99dSDavid van Moolenbroek * Convert a bit token value to a string; use "fmt" if not found.
410*b636d99dSDavid van Moolenbroek * this is useful for parsing bitfields, the output strings are comma seperated.
411*b636d99dSDavid van Moolenbroek */
412*b636d99dSDavid van Moolenbroek char *
bittok2str(register const struct tok * lp,register const char * fmt,register int v)413*b636d99dSDavid van Moolenbroek bittok2str(register const struct tok *lp, register const char *fmt,
414*b636d99dSDavid van Moolenbroek register int v)
415*b636d99dSDavid van Moolenbroek {
416*b636d99dSDavid van Moolenbroek return (bittok2str_internal(lp, fmt, v, 1));
417*b636d99dSDavid van Moolenbroek }
418*b636d99dSDavid van Moolenbroek
419*b636d99dSDavid van Moolenbroek /*
420*b636d99dSDavid van Moolenbroek * Convert a value to a string using an array; the macro
421*b636d99dSDavid van Moolenbroek * tok2strary() in <interface.h> is the public interface to
422*b636d99dSDavid van Moolenbroek * this function and ensures that the second argument is
423*b636d99dSDavid van Moolenbroek * correct for bounds-checking.
424*b636d99dSDavid van Moolenbroek */
425*b636d99dSDavid van Moolenbroek const char *
tok2strary_internal(register const char ** lp,int n,register const char * fmt,register int v)426*b636d99dSDavid van Moolenbroek tok2strary_internal(register const char **lp, int n, register const char *fmt,
427*b636d99dSDavid van Moolenbroek register int v)
428*b636d99dSDavid van Moolenbroek {
429*b636d99dSDavid van Moolenbroek static char buf[128];
430*b636d99dSDavid van Moolenbroek
431*b636d99dSDavid van Moolenbroek if (v >= 0 && v < n && lp[v] != NULL)
432*b636d99dSDavid van Moolenbroek return lp[v];
433*b636d99dSDavid van Moolenbroek if (fmt == NULL)
434*b636d99dSDavid van Moolenbroek fmt = "#%d";
435*b636d99dSDavid van Moolenbroek (void)snprintf(buf, sizeof(buf), fmt, v);
436*b636d99dSDavid van Moolenbroek return (buf);
437*b636d99dSDavid van Moolenbroek }
438*b636d99dSDavid van Moolenbroek
439*b636d99dSDavid van Moolenbroek /*
440*b636d99dSDavid van Moolenbroek * Convert a 32-bit netmask to prefixlen if possible
441*b636d99dSDavid van Moolenbroek * the function returns the prefix-len; if plen == -1
442*b636d99dSDavid van Moolenbroek * then conversion was not possible;
443*b636d99dSDavid van Moolenbroek */
444*b636d99dSDavid van Moolenbroek
445*b636d99dSDavid van Moolenbroek int
mask2plen(uint32_t mask)446*b636d99dSDavid van Moolenbroek mask2plen(uint32_t mask)
447*b636d99dSDavid van Moolenbroek {
448*b636d99dSDavid van Moolenbroek uint32_t bitmasks[33] = {
449*b636d99dSDavid van Moolenbroek 0x00000000,
450*b636d99dSDavid van Moolenbroek 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
451*b636d99dSDavid van Moolenbroek 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
452*b636d99dSDavid van Moolenbroek 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
453*b636d99dSDavid van Moolenbroek 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
454*b636d99dSDavid van Moolenbroek 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
455*b636d99dSDavid van Moolenbroek 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
456*b636d99dSDavid van Moolenbroek 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
457*b636d99dSDavid van Moolenbroek 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
458*b636d99dSDavid van Moolenbroek };
459*b636d99dSDavid van Moolenbroek int prefix_len = 32;
460*b636d99dSDavid van Moolenbroek
461*b636d99dSDavid van Moolenbroek /* let's see if we can transform the mask into a prefixlen */
462*b636d99dSDavid van Moolenbroek while (prefix_len >= 0) {
463*b636d99dSDavid van Moolenbroek if (bitmasks[prefix_len] == mask)
464*b636d99dSDavid van Moolenbroek break;
465*b636d99dSDavid van Moolenbroek prefix_len--;
466*b636d99dSDavid van Moolenbroek }
467*b636d99dSDavid van Moolenbroek return (prefix_len);
468*b636d99dSDavid van Moolenbroek }
469*b636d99dSDavid van Moolenbroek
470*b636d99dSDavid van Moolenbroek #ifdef INET6
471*b636d99dSDavid van Moolenbroek int
mask62plen(const u_char * mask)472*b636d99dSDavid van Moolenbroek mask62plen(const u_char *mask)
473*b636d99dSDavid van Moolenbroek {
474*b636d99dSDavid van Moolenbroek u_char bitmasks[9] = {
475*b636d99dSDavid van Moolenbroek 0x00,
476*b636d99dSDavid van Moolenbroek 0x80, 0xc0, 0xe0, 0xf0,
477*b636d99dSDavid van Moolenbroek 0xf8, 0xfc, 0xfe, 0xff
478*b636d99dSDavid van Moolenbroek };
479*b636d99dSDavid van Moolenbroek int byte;
480*b636d99dSDavid van Moolenbroek int cidr_len = 0;
481*b636d99dSDavid van Moolenbroek
482*b636d99dSDavid van Moolenbroek for (byte = 0; byte < 16; byte++) {
483*b636d99dSDavid van Moolenbroek u_int bits;
484*b636d99dSDavid van Moolenbroek
485*b636d99dSDavid van Moolenbroek for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) {
486*b636d99dSDavid van Moolenbroek if (mask[byte] == bitmasks[bits]) {
487*b636d99dSDavid van Moolenbroek cidr_len += bits;
488*b636d99dSDavid van Moolenbroek break;
489*b636d99dSDavid van Moolenbroek }
490*b636d99dSDavid van Moolenbroek }
491*b636d99dSDavid van Moolenbroek
492*b636d99dSDavid van Moolenbroek if (mask[byte] != 0xff)
493*b636d99dSDavid van Moolenbroek break;
494*b636d99dSDavid van Moolenbroek }
495*b636d99dSDavid van Moolenbroek return (cidr_len);
496*b636d99dSDavid van Moolenbroek }
497*b636d99dSDavid van Moolenbroek #endif /* INET6 */
498*b636d99dSDavid van Moolenbroek
499*b636d99dSDavid van Moolenbroek /*
500*b636d99dSDavid van Moolenbroek * Routine to print out information for text-based protocols such as FTP,
501*b636d99dSDavid van Moolenbroek * HTTP, SMTP, RTSP, SIP, ....
502*b636d99dSDavid van Moolenbroek */
503*b636d99dSDavid van Moolenbroek #define MAX_TOKEN 128
504*b636d99dSDavid van Moolenbroek
505*b636d99dSDavid van Moolenbroek /*
506*b636d99dSDavid van Moolenbroek * Fetch a token from a packet, starting at the specified index,
507*b636d99dSDavid van Moolenbroek * and return the length of the token.
508*b636d99dSDavid van Moolenbroek *
509*b636d99dSDavid van Moolenbroek * Returns 0 on error; yes, this is indistinguishable from an empty
510*b636d99dSDavid van Moolenbroek * token, but an "empty token" isn't a valid token - it just means
511*b636d99dSDavid van Moolenbroek * either a space character at the beginning of the line (this
512*b636d99dSDavid van Moolenbroek * includes a blank line) or no more tokens remaining on the line.
513*b636d99dSDavid van Moolenbroek */
514*b636d99dSDavid van Moolenbroek static int
fetch_token(netdissect_options * ndo,const u_char * pptr,u_int idx,u_int len,u_char * tbuf,size_t tbuflen)515*b636d99dSDavid van Moolenbroek fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
516*b636d99dSDavid van Moolenbroek u_char *tbuf, size_t tbuflen)
517*b636d99dSDavid van Moolenbroek {
518*b636d99dSDavid van Moolenbroek size_t toklen = 0;
519*b636d99dSDavid van Moolenbroek
520*b636d99dSDavid van Moolenbroek for (; idx < len; idx++) {
521*b636d99dSDavid van Moolenbroek if (!ND_TTEST(*(pptr + idx))) {
522*b636d99dSDavid van Moolenbroek /* ran past end of captured data */
523*b636d99dSDavid van Moolenbroek return (0);
524*b636d99dSDavid van Moolenbroek }
525*b636d99dSDavid van Moolenbroek if (!isascii(*(pptr + idx))) {
526*b636d99dSDavid van Moolenbroek /* not an ASCII character */
527*b636d99dSDavid van Moolenbroek return (0);
528*b636d99dSDavid van Moolenbroek }
529*b636d99dSDavid van Moolenbroek if (isspace(*(pptr + idx))) {
530*b636d99dSDavid van Moolenbroek /* end of token */
531*b636d99dSDavid van Moolenbroek break;
532*b636d99dSDavid van Moolenbroek }
533*b636d99dSDavid van Moolenbroek if (!isprint(*(pptr + idx))) {
534*b636d99dSDavid van Moolenbroek /* not part of a command token or response code */
535*b636d99dSDavid van Moolenbroek return (0);
536*b636d99dSDavid van Moolenbroek }
537*b636d99dSDavid van Moolenbroek if (toklen + 2 > tbuflen) {
538*b636d99dSDavid van Moolenbroek /* no room for this character and terminating '\0' */
539*b636d99dSDavid van Moolenbroek return (0);
540*b636d99dSDavid van Moolenbroek }
541*b636d99dSDavid van Moolenbroek tbuf[toklen] = *(pptr + idx);
542*b636d99dSDavid van Moolenbroek toklen++;
543*b636d99dSDavid van Moolenbroek }
544*b636d99dSDavid van Moolenbroek if (toklen == 0) {
545*b636d99dSDavid van Moolenbroek /* no token */
546*b636d99dSDavid van Moolenbroek return (0);
547*b636d99dSDavid van Moolenbroek }
548*b636d99dSDavid van Moolenbroek tbuf[toklen] = '\0';
549*b636d99dSDavid van Moolenbroek
550*b636d99dSDavid van Moolenbroek /*
551*b636d99dSDavid van Moolenbroek * Skip past any white space after the token, until we see
552*b636d99dSDavid van Moolenbroek * an end-of-line (CR or LF).
553*b636d99dSDavid van Moolenbroek */
554*b636d99dSDavid van Moolenbroek for (; idx < len; idx++) {
555*b636d99dSDavid van Moolenbroek if (!ND_TTEST(*(pptr + idx))) {
556*b636d99dSDavid van Moolenbroek /* ran past end of captured data */
557*b636d99dSDavid van Moolenbroek break;
558*b636d99dSDavid van Moolenbroek }
559*b636d99dSDavid van Moolenbroek if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') {
560*b636d99dSDavid van Moolenbroek /* end of line */
561*b636d99dSDavid van Moolenbroek break;
562*b636d99dSDavid van Moolenbroek }
563*b636d99dSDavid van Moolenbroek if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) {
564*b636d99dSDavid van Moolenbroek /* not a printable ASCII character */
565*b636d99dSDavid van Moolenbroek break;
566*b636d99dSDavid van Moolenbroek }
567*b636d99dSDavid van Moolenbroek if (!isspace(*(pptr + idx))) {
568*b636d99dSDavid van Moolenbroek /* beginning of next token */
569*b636d99dSDavid van Moolenbroek break;
570*b636d99dSDavid van Moolenbroek }
571*b636d99dSDavid van Moolenbroek }
572*b636d99dSDavid van Moolenbroek return (idx);
573*b636d99dSDavid van Moolenbroek }
574*b636d99dSDavid van Moolenbroek
575*b636d99dSDavid van Moolenbroek /*
576*b636d99dSDavid van Moolenbroek * Scan a buffer looking for a line ending - LF or CR-LF.
577*b636d99dSDavid van Moolenbroek * Return the index of the character after the line ending or 0 if
578*b636d99dSDavid van Moolenbroek * we encounter a non-ASCII or non-printable character or don't find
579*b636d99dSDavid van Moolenbroek * the line ending.
580*b636d99dSDavid van Moolenbroek */
581*b636d99dSDavid van Moolenbroek static u_int
print_txt_line(netdissect_options * ndo,const char * protoname,const char * prefix,const u_char * pptr,u_int idx,u_int len)582*b636d99dSDavid van Moolenbroek print_txt_line(netdissect_options *ndo, const char *protoname,
583*b636d99dSDavid van Moolenbroek const char *prefix, const u_char *pptr, u_int idx, u_int len)
584*b636d99dSDavid van Moolenbroek {
585*b636d99dSDavid van Moolenbroek u_int startidx;
586*b636d99dSDavid van Moolenbroek u_int linelen;
587*b636d99dSDavid van Moolenbroek
588*b636d99dSDavid van Moolenbroek startidx = idx;
589*b636d99dSDavid van Moolenbroek while (idx < len) {
590*b636d99dSDavid van Moolenbroek ND_TCHECK(*(pptr+idx));
591*b636d99dSDavid van Moolenbroek if (*(pptr+idx) == '\n') {
592*b636d99dSDavid van Moolenbroek /*
593*b636d99dSDavid van Moolenbroek * LF without CR; end of line.
594*b636d99dSDavid van Moolenbroek * Skip the LF and print the line, with the
595*b636d99dSDavid van Moolenbroek * exception of the LF.
596*b636d99dSDavid van Moolenbroek */
597*b636d99dSDavid van Moolenbroek linelen = idx - startidx;
598*b636d99dSDavid van Moolenbroek idx++;
599*b636d99dSDavid van Moolenbroek goto print;
600*b636d99dSDavid van Moolenbroek } else if (*(pptr+idx) == '\r') {
601*b636d99dSDavid van Moolenbroek /* CR - any LF? */
602*b636d99dSDavid van Moolenbroek if ((idx+1) >= len) {
603*b636d99dSDavid van Moolenbroek /* not in this packet */
604*b636d99dSDavid van Moolenbroek return (0);
605*b636d99dSDavid van Moolenbroek }
606*b636d99dSDavid van Moolenbroek ND_TCHECK(*(pptr+idx+1));
607*b636d99dSDavid van Moolenbroek if (*(pptr+idx+1) == '\n') {
608*b636d99dSDavid van Moolenbroek /*
609*b636d99dSDavid van Moolenbroek * CR-LF; end of line.
610*b636d99dSDavid van Moolenbroek * Skip the CR-LF and print the line, with
611*b636d99dSDavid van Moolenbroek * the exception of the CR-LF.
612*b636d99dSDavid van Moolenbroek */
613*b636d99dSDavid van Moolenbroek linelen = idx - startidx;
614*b636d99dSDavid van Moolenbroek idx += 2;
615*b636d99dSDavid van Moolenbroek goto print;
616*b636d99dSDavid van Moolenbroek }
617*b636d99dSDavid van Moolenbroek
618*b636d99dSDavid van Moolenbroek /*
619*b636d99dSDavid van Moolenbroek * CR followed by something else; treat this
620*b636d99dSDavid van Moolenbroek * as if it were binary data, and don't print
621*b636d99dSDavid van Moolenbroek * it.
622*b636d99dSDavid van Moolenbroek */
623*b636d99dSDavid van Moolenbroek return (0);
624*b636d99dSDavid van Moolenbroek } else if (!isascii(*(pptr+idx)) ||
625*b636d99dSDavid van Moolenbroek (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) {
626*b636d99dSDavid van Moolenbroek /*
627*b636d99dSDavid van Moolenbroek * Not a printable ASCII character and not a tab;
628*b636d99dSDavid van Moolenbroek * treat this as if it were binary data, and
629*b636d99dSDavid van Moolenbroek * don't print it.
630*b636d99dSDavid van Moolenbroek */
631*b636d99dSDavid van Moolenbroek return (0);
632*b636d99dSDavid van Moolenbroek }
633*b636d99dSDavid van Moolenbroek idx++;
634*b636d99dSDavid van Moolenbroek }
635*b636d99dSDavid van Moolenbroek
636*b636d99dSDavid van Moolenbroek /*
637*b636d99dSDavid van Moolenbroek * All printable ASCII, but no line ending after that point
638*b636d99dSDavid van Moolenbroek * in the buffer; treat this as if it were truncated.
639*b636d99dSDavid van Moolenbroek */
640*b636d99dSDavid van Moolenbroek trunc:
641*b636d99dSDavid van Moolenbroek linelen = idx - startidx;
642*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx,
643*b636d99dSDavid van Moolenbroek protoname));
644*b636d99dSDavid van Moolenbroek return (0);
645*b636d99dSDavid van Moolenbroek
646*b636d99dSDavid van Moolenbroek print:
647*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx));
648*b636d99dSDavid van Moolenbroek return (idx);
649*b636d99dSDavid van Moolenbroek }
650*b636d99dSDavid van Moolenbroek
651*b636d99dSDavid van Moolenbroek void
txtproto_print(netdissect_options * ndo,const u_char * pptr,u_int len,const char * protoname,const char ** cmds,u_int flags)652*b636d99dSDavid van Moolenbroek txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
653*b636d99dSDavid van Moolenbroek const char *protoname, const char **cmds, u_int flags)
654*b636d99dSDavid van Moolenbroek {
655*b636d99dSDavid van Moolenbroek u_int idx, eol;
656*b636d99dSDavid van Moolenbroek u_char token[MAX_TOKEN+1];
657*b636d99dSDavid van Moolenbroek const char *cmd;
658*b636d99dSDavid van Moolenbroek int is_reqresp = 0;
659*b636d99dSDavid van Moolenbroek const char *pnp;
660*b636d99dSDavid van Moolenbroek
661*b636d99dSDavid van Moolenbroek if (cmds != NULL) {
662*b636d99dSDavid van Moolenbroek /*
663*b636d99dSDavid van Moolenbroek * This protocol has more than just request and
664*b636d99dSDavid van Moolenbroek * response lines; see whether this looks like a
665*b636d99dSDavid van Moolenbroek * request or response.
666*b636d99dSDavid van Moolenbroek */
667*b636d99dSDavid van Moolenbroek idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
668*b636d99dSDavid van Moolenbroek if (idx != 0) {
669*b636d99dSDavid van Moolenbroek /* Is this a valid request name? */
670*b636d99dSDavid van Moolenbroek while ((cmd = *cmds++) != NULL) {
671*b636d99dSDavid van Moolenbroek if (strcasecmp((const char *)token, cmd) == 0) {
672*b636d99dSDavid van Moolenbroek /* Yes. */
673*b636d99dSDavid van Moolenbroek is_reqresp = 1;
674*b636d99dSDavid van Moolenbroek break;
675*b636d99dSDavid van Moolenbroek }
676*b636d99dSDavid van Moolenbroek }
677*b636d99dSDavid van Moolenbroek
678*b636d99dSDavid van Moolenbroek /*
679*b636d99dSDavid van Moolenbroek * No - is this a valid response code (3 digits)?
680*b636d99dSDavid van Moolenbroek *
681*b636d99dSDavid van Moolenbroek * Is this token the response code, or is the next
682*b636d99dSDavid van Moolenbroek * token the response code?
683*b636d99dSDavid van Moolenbroek */
684*b636d99dSDavid van Moolenbroek if (flags & RESP_CODE_SECOND_TOKEN) {
685*b636d99dSDavid van Moolenbroek /*
686*b636d99dSDavid van Moolenbroek * Next token - get it.
687*b636d99dSDavid van Moolenbroek */
688*b636d99dSDavid van Moolenbroek idx = fetch_token(ndo, pptr, idx, len, token,
689*b636d99dSDavid van Moolenbroek sizeof(token));
690*b636d99dSDavid van Moolenbroek }
691*b636d99dSDavid van Moolenbroek if (idx != 0) {
692*b636d99dSDavid van Moolenbroek if (isdigit(token[0]) && isdigit(token[1]) &&
693*b636d99dSDavid van Moolenbroek isdigit(token[2]) && token[3] == '\0') {
694*b636d99dSDavid van Moolenbroek /* Yes. */
695*b636d99dSDavid van Moolenbroek is_reqresp = 1;
696*b636d99dSDavid van Moolenbroek }
697*b636d99dSDavid van Moolenbroek }
698*b636d99dSDavid van Moolenbroek }
699*b636d99dSDavid van Moolenbroek } else {
700*b636d99dSDavid van Moolenbroek /*
701*b636d99dSDavid van Moolenbroek * This protocol has only request and response lines
702*b636d99dSDavid van Moolenbroek * (e.g., FTP, where all the data goes over a
703*b636d99dSDavid van Moolenbroek * different connection); assume the payload is
704*b636d99dSDavid van Moolenbroek * a request or response.
705*b636d99dSDavid van Moolenbroek */
706*b636d99dSDavid van Moolenbroek is_reqresp = 1;
707*b636d99dSDavid van Moolenbroek }
708*b636d99dSDavid van Moolenbroek
709*b636d99dSDavid van Moolenbroek /* Capitalize the protocol name */
710*b636d99dSDavid van Moolenbroek for (pnp = protoname; *pnp != '\0'; pnp++)
711*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%c", toupper((unsigned char)*pnp)));
712*b636d99dSDavid van Moolenbroek
713*b636d99dSDavid van Moolenbroek if (is_reqresp) {
714*b636d99dSDavid van Moolenbroek /*
715*b636d99dSDavid van Moolenbroek * In non-verbose mode, just print the protocol, followed
716*b636d99dSDavid van Moolenbroek * by the first line as the request or response info.
717*b636d99dSDavid van Moolenbroek *
718*b636d99dSDavid van Moolenbroek * In verbose mode, print lines as text until we run out
719*b636d99dSDavid van Moolenbroek * of characters or see something that's not a
720*b636d99dSDavid van Moolenbroek * printable-ASCII line.
721*b636d99dSDavid van Moolenbroek */
722*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag) {
723*b636d99dSDavid van Moolenbroek /*
724*b636d99dSDavid van Moolenbroek * We're going to print all the text lines in the
725*b636d99dSDavid van Moolenbroek * request or response; just print the length
726*b636d99dSDavid van Moolenbroek * on the first line of the output.
727*b636d99dSDavid van Moolenbroek */
728*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", length: %u", len));
729*b636d99dSDavid van Moolenbroek for (idx = 0;
730*b636d99dSDavid van Moolenbroek idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0;
731*b636d99dSDavid van Moolenbroek idx = eol)
732*b636d99dSDavid van Moolenbroek ;
733*b636d99dSDavid van Moolenbroek } else {
734*b636d99dSDavid van Moolenbroek /*
735*b636d99dSDavid van Moolenbroek * Just print the first text line.
736*b636d99dSDavid van Moolenbroek */
737*b636d99dSDavid van Moolenbroek print_txt_line(ndo, protoname, ": ", pptr, 0, len);
738*b636d99dSDavid van Moolenbroek }
739*b636d99dSDavid van Moolenbroek }
740*b636d99dSDavid van Moolenbroek }
741*b636d99dSDavid van Moolenbroek
742*b636d99dSDavid van Moolenbroek /* VARARGS */
743*b636d99dSDavid van Moolenbroek void
error(const char * fmt,...)744*b636d99dSDavid van Moolenbroek error(const char *fmt, ...)
745*b636d99dSDavid van Moolenbroek {
746*b636d99dSDavid van Moolenbroek va_list ap;
747*b636d99dSDavid van Moolenbroek
748*b636d99dSDavid van Moolenbroek (void)fprintf(stderr, "%s: ", program_name);
749*b636d99dSDavid van Moolenbroek va_start(ap, fmt);
750*b636d99dSDavid van Moolenbroek (void)vfprintf(stderr, fmt, ap);
751*b636d99dSDavid van Moolenbroek va_end(ap);
752*b636d99dSDavid van Moolenbroek if (*fmt) {
753*b636d99dSDavid van Moolenbroek fmt += strlen(fmt);
754*b636d99dSDavid van Moolenbroek if (fmt[-1] != '\n')
755*b636d99dSDavid van Moolenbroek (void)fputc('\n', stderr);
756*b636d99dSDavid van Moolenbroek }
757*b636d99dSDavid van Moolenbroek exit(1);
758*b636d99dSDavid van Moolenbroek /* NOTREACHED */
759*b636d99dSDavid van Moolenbroek }
760*b636d99dSDavid van Moolenbroek
761*b636d99dSDavid van Moolenbroek /* VARARGS */
762*b636d99dSDavid van Moolenbroek void
warning(const char * fmt,...)763*b636d99dSDavid van Moolenbroek warning(const char *fmt, ...)
764*b636d99dSDavid van Moolenbroek {
765*b636d99dSDavid van Moolenbroek va_list ap;
766*b636d99dSDavid van Moolenbroek
767*b636d99dSDavid van Moolenbroek (void)fprintf(stderr, "%s: WARNING: ", program_name);
768*b636d99dSDavid van Moolenbroek va_start(ap, fmt);
769*b636d99dSDavid van Moolenbroek (void)vfprintf(stderr, fmt, ap);
770*b636d99dSDavid van Moolenbroek va_end(ap);
771*b636d99dSDavid van Moolenbroek if (*fmt) {
772*b636d99dSDavid van Moolenbroek fmt += strlen(fmt);
773*b636d99dSDavid van Moolenbroek if (fmt[-1] != '\n')
774*b636d99dSDavid van Moolenbroek (void)fputc('\n', stderr);
775*b636d99dSDavid van Moolenbroek }
776*b636d99dSDavid van Moolenbroek }
777*b636d99dSDavid van Moolenbroek
778*b636d99dSDavid van Moolenbroek /*
779*b636d99dSDavid van Moolenbroek * Copy arg vector into a new buffer, concatenating arguments with spaces.
780*b636d99dSDavid van Moolenbroek */
781*b636d99dSDavid van Moolenbroek char *
copy_argv(register char ** argv)782*b636d99dSDavid van Moolenbroek copy_argv(register char **argv)
783*b636d99dSDavid van Moolenbroek {
784*b636d99dSDavid van Moolenbroek register char **p;
785*b636d99dSDavid van Moolenbroek register u_int len = 0;
786*b636d99dSDavid van Moolenbroek char *buf;
787*b636d99dSDavid van Moolenbroek char *src, *dst;
788*b636d99dSDavid van Moolenbroek
789*b636d99dSDavid van Moolenbroek p = argv;
790*b636d99dSDavid van Moolenbroek if (*p == 0)
791*b636d99dSDavid van Moolenbroek return 0;
792*b636d99dSDavid van Moolenbroek
793*b636d99dSDavid van Moolenbroek while (*p)
794*b636d99dSDavid van Moolenbroek len += strlen(*p++) + 1;
795*b636d99dSDavid van Moolenbroek
796*b636d99dSDavid van Moolenbroek buf = (char *)malloc(len);
797*b636d99dSDavid van Moolenbroek if (buf == NULL)
798*b636d99dSDavid van Moolenbroek error("copy_argv: malloc");
799*b636d99dSDavid van Moolenbroek
800*b636d99dSDavid van Moolenbroek p = argv;
801*b636d99dSDavid van Moolenbroek dst = buf;
802*b636d99dSDavid van Moolenbroek while ((src = *p++) != NULL) {
803*b636d99dSDavid van Moolenbroek while ((*dst++ = *src++) != '\0')
804*b636d99dSDavid van Moolenbroek ;
805*b636d99dSDavid van Moolenbroek dst[-1] = ' ';
806*b636d99dSDavid van Moolenbroek }
807*b636d99dSDavid van Moolenbroek dst[-1] = '\0';
808*b636d99dSDavid van Moolenbroek
809*b636d99dSDavid van Moolenbroek return buf;
810*b636d99dSDavid van Moolenbroek }
811*b636d99dSDavid van Moolenbroek
812*b636d99dSDavid van Moolenbroek /*
813*b636d99dSDavid van Moolenbroek * On Windows, we need to open the file in binary mode, so that
814*b636d99dSDavid van Moolenbroek * we get all the bytes specified by the size we get from "fstat()".
815*b636d99dSDavid van Moolenbroek * On UNIX, that's not necessary. O_BINARY is defined on Windows;
816*b636d99dSDavid van Moolenbroek * we define it as 0 if it's not defined, so it does nothing.
817*b636d99dSDavid van Moolenbroek */
818*b636d99dSDavid van Moolenbroek #ifndef O_BINARY
819*b636d99dSDavid van Moolenbroek #define O_BINARY 0
820*b636d99dSDavid van Moolenbroek #endif
821*b636d99dSDavid van Moolenbroek
822*b636d99dSDavid van Moolenbroek char *
read_infile(char * fname)823*b636d99dSDavid van Moolenbroek read_infile(char *fname)
824*b636d99dSDavid van Moolenbroek {
825*b636d99dSDavid van Moolenbroek register int i, fd, cc;
826*b636d99dSDavid van Moolenbroek register char *cp;
827*b636d99dSDavid van Moolenbroek struct stat buf;
828*b636d99dSDavid van Moolenbroek
829*b636d99dSDavid van Moolenbroek fd = open(fname, O_RDONLY|O_BINARY);
830*b636d99dSDavid van Moolenbroek if (fd < 0)
831*b636d99dSDavid van Moolenbroek error("can't open %s: %s", fname, pcap_strerror(errno));
832*b636d99dSDavid van Moolenbroek
833*b636d99dSDavid van Moolenbroek if (fstat(fd, &buf) < 0)
834*b636d99dSDavid van Moolenbroek error("can't stat %s: %s", fname, pcap_strerror(errno));
835*b636d99dSDavid van Moolenbroek
836*b636d99dSDavid van Moolenbroek cp = malloc((u_int)buf.st_size + 1);
837*b636d99dSDavid van Moolenbroek if (cp == NULL)
838*b636d99dSDavid van Moolenbroek error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
839*b636d99dSDavid van Moolenbroek fname, pcap_strerror(errno));
840*b636d99dSDavid van Moolenbroek cc = read(fd, cp, (u_int)buf.st_size);
841*b636d99dSDavid van Moolenbroek if (cc < 0)
842*b636d99dSDavid van Moolenbroek error("read %s: %s", fname, pcap_strerror(errno));
843*b636d99dSDavid van Moolenbroek if (cc != buf.st_size)
844*b636d99dSDavid van Moolenbroek error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
845*b636d99dSDavid van Moolenbroek
846*b636d99dSDavid van Moolenbroek close(fd);
847*b636d99dSDavid van Moolenbroek /* replace "# comment" with spaces */
848*b636d99dSDavid van Moolenbroek for (i = 0; i < cc; i++) {
849*b636d99dSDavid van Moolenbroek if (cp[i] == '#')
850*b636d99dSDavid van Moolenbroek while (i < cc && cp[i] != '\n')
851*b636d99dSDavid van Moolenbroek cp[i++] = ' ';
852*b636d99dSDavid van Moolenbroek }
853*b636d99dSDavid van Moolenbroek cp[cc] = '\0';
854*b636d99dSDavid van Moolenbroek return (cp);
855*b636d99dSDavid van Moolenbroek }
856*b636d99dSDavid van Moolenbroek
857*b636d99dSDavid van Moolenbroek void
safeputs(netdissect_options * ndo,const u_char * s,const u_int maxlen)858*b636d99dSDavid van Moolenbroek safeputs(netdissect_options *ndo,
859*b636d99dSDavid van Moolenbroek const u_char *s, const u_int maxlen)
860*b636d99dSDavid van Moolenbroek {
861*b636d99dSDavid van Moolenbroek u_int idx = 0;
862*b636d99dSDavid van Moolenbroek
863*b636d99dSDavid van Moolenbroek while (*s && idx < maxlen) {
864*b636d99dSDavid van Moolenbroek safeputchar(ndo, *s);
865*b636d99dSDavid van Moolenbroek idx++;
866*b636d99dSDavid van Moolenbroek s++;
867*b636d99dSDavid van Moolenbroek }
868*b636d99dSDavid van Moolenbroek }
869*b636d99dSDavid van Moolenbroek
870*b636d99dSDavid van Moolenbroek void
safeputchar(netdissect_options * ndo,const u_char c)871*b636d99dSDavid van Moolenbroek safeputchar(netdissect_options *ndo,
872*b636d99dSDavid van Moolenbroek const u_char c)
873*b636d99dSDavid van Moolenbroek {
874*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c));
875*b636d99dSDavid van Moolenbroek }
876*b636d99dSDavid van Moolenbroek
877*b636d99dSDavid van Moolenbroek #ifdef LBL_ALIGN
878*b636d99dSDavid van Moolenbroek /*
879*b636d99dSDavid van Moolenbroek * Some compilers try to optimize memcpy(), using the alignment constraint
880*b636d99dSDavid van Moolenbroek * on the argument pointer type. by using this function, we try to avoid the
881*b636d99dSDavid van Moolenbroek * optimization.
882*b636d99dSDavid van Moolenbroek */
883*b636d99dSDavid van Moolenbroek void
unaligned_memcpy(void * p,const void * q,size_t l)884*b636d99dSDavid van Moolenbroek unaligned_memcpy(void *p, const void *q, size_t l)
885*b636d99dSDavid van Moolenbroek {
886*b636d99dSDavid van Moolenbroek memcpy(p, q, l);
887*b636d99dSDavid van Moolenbroek }
888*b636d99dSDavid van Moolenbroek
889*b636d99dSDavid van Moolenbroek /* As with memcpy(), so with memcmp(). */
890*b636d99dSDavid van Moolenbroek int
unaligned_memcmp(const void * p,const void * q,size_t l)891*b636d99dSDavid van Moolenbroek unaligned_memcmp(const void *p, const void *q, size_t l)
892*b636d99dSDavid van Moolenbroek {
893*b636d99dSDavid van Moolenbroek return (memcmp(p, q, l));
894*b636d99dSDavid van Moolenbroek }
895*b636d99dSDavid van Moolenbroek #endif
896