]> The Tcpdump Group git mirrors - tcpdump/blob - util.c
don't pass on src & dst MAC adresses to the isoclns decoder as MAC adresses
[tcpdump] / util.c
1 /*
2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.85 2003-04-21 16:59:52 fenner Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <tcpdump-stdinc.h>
32
33 #include <sys/stat.h>
34
35 #include <errno.h>
36 #ifdef HAVE_FCNTL_H
37 #include <fcntl.h>
38 #endif
39 #include <pcap.h>
40 #include <stdio.h>
41 #include <stdarg.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "interface.h"
46
47 /*
48 * Print out a filename (or other ascii string).
49 * If ep is NULL, assume no truncation check is needed.
50 * Return true if truncated.
51 */
52 int
53 fn_print(register const u_char *s, register const u_char *ep)
54 {
55 register int ret;
56 register u_char c;
57
58 ret = 1; /* assume truncated */
59 while (ep == NULL || s < ep) {
60 c = *s++;
61 if (c == '\0') {
62 ret = 0;
63 break;
64 }
65 if (!isascii(c)) {
66 c = toascii(c);
67 putchar('M');
68 putchar('-');
69 }
70 if (!isprint(c)) {
71 c ^= 0x40; /* DEL to ?, others to alpha */
72 putchar('^');
73 }
74 putchar(c);
75 }
76 return(ret);
77 }
78
79 /*
80 * Print out a counted filename (or other ascii string).
81 * If ep is NULL, assume no truncation check is needed.
82 * Return true if truncated.
83 */
84 int
85 fn_printn(register const u_char *s, register u_int n,
86 register const u_char *ep)
87 {
88 register u_char c;
89
90 while (n > 0 && (ep == NULL || s < ep)) {
91 n--;
92 c = *s++;
93 if (!isascii(c)) {
94 c = toascii(c);
95 putchar('M');
96 putchar('-');
97 }
98 if (!isprint(c)) {
99 c ^= 0x40; /* DEL to ?, others to alpha */
100 putchar('^');
101 }
102 putchar(c);
103 }
104 return (n == 0) ? 0 : 1;
105 }
106
107 /*
108 * Print the timestamp
109 */
110 void
111 ts_print(register const struct timeval *tvp)
112 {
113 register int s;
114 struct tm *tm;
115 time_t Time;
116 static unsigned b_sec;
117 static unsigned b_usec;
118
119 switch(tflag) {
120 case 1: /* Default */
121 s = (tvp->tv_sec + thiszone) % 86400;
122 (void)printf("%02d:%02d:%02d.%06u ",
123 s / 3600, (s % 3600) / 60, s % 60,
124 (unsigned)tvp->tv_usec);
125 break;
126 case -1: /* Unix timeval style */
127 (void)printf("%u.%06u ",
128 (unsigned)tvp->tv_sec,
129 (unsigned)tvp->tv_usec);
130 break;
131 case -2:
132 if (b_sec == 0) {
133 printf("000000 ");
134 } else {
135 int d_usec = tvp->tv_usec - b_usec;
136 int d_sec = tvp->tv_sec - b_sec;
137
138 while (d_usec < 0) {
139 d_usec += 1000000;
140 d_sec--;
141 }
142 if (d_sec)
143 printf("%d. ", d_sec);
144 printf("%06d ", d_usec);
145 }
146 b_sec = tvp->tv_sec;
147 b_usec = tvp->tv_usec;
148 break;
149 case -3: /* Default + Date*/
150 s = (tvp->tv_sec + thiszone) % 86400;
151 Time = (tvp->tv_sec + thiszone) - s;
152 tm = gmtime (&Time);
153 if (!tm)
154 printf("Date fail ");
155 else
156 printf("%04d-%02d-%02d ",
157 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
158 printf("%02d:%02d:%02d.%06u ",
159 s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec);
160 break;
161 }
162 }
163
164 /*
165 * Print a relative number of seconds (e.g. hold time, prune timer)
166 * in the form 5m1s. This does no truncation, so 32230861 seconds
167 * is represented as 1y1w1d1h1m1s.
168 */
169 void
170 relts_print(int secs)
171 {
172 static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
173 static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
174 const char **l = lengths;
175 const int *s = seconds;
176
177 if (secs == 0) {
178 (void)printf("0s");
179 return;
180 }
181 if (secs < 0) {
182 (void)printf("-");
183 secs = -secs;
184 }
185 while (secs > 0) {
186 if (secs >= *s) {
187 (void)printf("%d%s", secs / *s, *l);
188 secs -= (secs / *s) * *s;
189 }
190 s++;
191 l++;
192 }
193 }
194
195 /*
196 * this is a generic routine for printing unknown data;
197 * we pass on the linefeed plus indentation string to
198 * get a proper output - returns 0 on error
199 */
200
201 int
202 print_unknown_data(const u_char *cp,const char *lf,int len)
203 {
204 int i;
205
206 if (len ==0)
207 return(0);
208
209 printf("%s0x0000: ",lf);
210 for(i=0;i<len;i++) {
211 if (!TTEST2(*(cp+i), 1)) {
212 printf("%spacket exceeded snapshot",lf);
213 return(0);
214 }
215 printf("%02x",*(cp+i));
216 if (i%2)
217 printf(" ");
218 if (i/16!=(i+1)/16) {
219 if (i<(len-1))
220 printf("%s0x%04x: ",lf,i);
221 }
222 }
223 return(1); /* everything is ok */
224 }
225
226 /*
227 * Convert a token value to a string; use "fmt" if not found.
228 */
229 const char *
230 tok2str(register const struct tok *lp, register const char *fmt,
231 register int v)
232 {
233 static char buf[128];
234
235 while (lp->s != NULL) {
236 if (lp->v == v)
237 return (lp->s);
238 ++lp;
239 }
240 if (fmt == NULL)
241 fmt = "#%d";
242 (void)snprintf(buf, sizeof(buf), fmt, v);
243 return (buf);
244 }
245
246 /*
247 * Convert a bit token value to a string; use "fmt" if not found.
248 * this is useful for parsing bitfields, the output strings are comma seperated
249 */
250 char *
251 bittok2str(register const struct tok *lp, register const char *fmt,
252 register int v)
253 {
254 static char buf[256]; /* our stringbuffer */
255 int buflen=0;
256 register int rotbit; /* this is the bit we rotate through all bitpositions */
257 register int tokval;
258
259 while (lp->s != NULL) {
260 tokval=lp->v; /* load our first value */
261 rotbit=1;
262 while (rotbit != 0) {
263 /*
264 * lets AND the rotating bit with our token value
265 * and see if we have got a match
266 */
267 if (tokval == (v&rotbit)) {
268 /* ok we have found something */
269 buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s, ",lp->s);
270 break;
271 }
272 rotbit=rotbit<<1; /* no match - lets shift and try again */
273 }
274 lp++;
275 }
276
277 if (buflen != 0) { /* did we find anything */
278 /* yep, set the the trailing zero 2 bytes before to eliminate the last comma & whitespace */
279 buf[buflen-2] = '\0';
280 return (buf);
281 }
282 else {
283 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
284 if (fmt == NULL)
285 fmt = "#%d";
286 (void)snprintf(buf, sizeof(buf), fmt, v);
287 return (buf);
288 }
289 }
290
291 /*
292 * Convert a value to a string using an array; the macro
293 * tok2strary() in <interface.h> is the public interface to
294 * this function and ensures that the second argument is
295 * correct for bounds-checking.
296 */
297 const char *
298 tok2strary_internal(register const char **lp, int n, register const char *fmt,
299 register int v)
300 {
301 static char buf[128];
302
303 if (v >= 0 && v < n && lp[v] != NULL)
304 return lp[v];
305 if (fmt == NULL)
306 fmt = "#%d";
307 (void)snprintf(buf, sizeof(buf), fmt, v);
308 return (buf);
309 }
310
311 /*
312 * Convert a 32-bit netmask to prefixlen if possible
313 * the function returns the prefix-len; if plen == -1
314 * then conversion was not possible;
315 */
316
317 int
318 mask2plen (u_int32_t mask)
319 {
320 u_int32_t bitmasks[33] = {
321 0x00000000,
322 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
323 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
324 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
325 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
326 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
327 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
328 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
329 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
330 };
331 int prefix_len = 33;
332
333 /* lets see if we can transform the mask into a prefixlen */
334 while (prefix_len >= 0) {
335 if (bitmasks[prefix_len] == mask)
336 break;
337 prefix_len--;
338 }
339 return (prefix_len);
340 }
341
342 /* VARARGS */
343 void
344 error(const char *fmt, ...)
345 {
346 va_list ap;
347
348 (void)fprintf(stderr, "%s: ", program_name);
349 va_start(ap, fmt);
350 (void)vfprintf(stderr, fmt, ap);
351 va_end(ap);
352 if (*fmt) {
353 fmt += strlen(fmt);
354 if (fmt[-1] != '\n')
355 (void)fputc('\n', stderr);
356 }
357 exit(1);
358 /* NOTREACHED */
359 }
360
361 /* VARARGS */
362 void
363 warning(const char *fmt, ...)
364 {
365 va_list ap;
366
367 (void)fprintf(stderr, "%s: WARNING: ", program_name);
368 va_start(ap, fmt);
369 (void)vfprintf(stderr, fmt, ap);
370 va_end(ap);
371 if (*fmt) {
372 fmt += strlen(fmt);
373 if (fmt[-1] != '\n')
374 (void)fputc('\n', stderr);
375 }
376 }
377
378 /*
379 * Copy arg vector into a new buffer, concatenating arguments with spaces.
380 */
381 char *
382 copy_argv(register char **argv)
383 {
384 register char **p;
385 register u_int len = 0;
386 char *buf;
387 char *src, *dst;
388
389 p = argv;
390 if (*p == 0)
391 return 0;
392
393 while (*p)
394 len += strlen(*p++) + 1;
395
396 buf = (char *)malloc(len);
397 if (buf == NULL)
398 error("copy_argv: malloc");
399
400 p = argv;
401 dst = buf;
402 while ((src = *p++) != NULL) {
403 while ((*dst++ = *src++) != '\0')
404 ;
405 dst[-1] = ' ';
406 }
407 dst[-1] = '\0';
408
409 return buf;
410 }
411
412 /*
413 * On Windows, we need to open the file in binary mode, so that
414 * we get all the bytes specified by the size we get from "fstat()".
415 * On UNIX, that's not necessary. O_BINARY is defined on Windows;
416 * we define it as 0 if it's not defined, so it does nothing.
417 */
418 #ifndef O_BINARY
419 #define O_BINARY 0
420 #endif
421
422 char *
423 read_infile(char *fname)
424 {
425 register int i, fd, cc;
426 register char *cp;
427 struct stat buf;
428
429 fd = open(fname, O_RDONLY|O_BINARY);
430 if (fd < 0)
431 error("can't open %s: %s", fname, pcap_strerror(errno));
432
433 if (fstat(fd, &buf) < 0)
434 error("can't stat %s: %s", fname, pcap_strerror(errno));
435
436 cp = malloc((u_int)buf.st_size + 1);
437 if (cp == NULL)
438 error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
439 fname, pcap_strerror(errno));
440 cc = read(fd, cp, (u_int)buf.st_size);
441 if (cc < 0)
442 error("read %s: %s", fname, pcap_strerror(errno));
443 if (cc != buf.st_size)
444 error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
445
446 close(fd);
447 /* replace "# comment" with spaces */
448 for (i = 0; i < cc; i++) {
449 if (cp[i] == '#')
450 while (i < cc && cp[i] != '\n')
451 cp[i++] = ' ';
452 }
453 cp[cc] = '\0';
454 return (cp);
455 }
456
457 void
458 safeputs(const char *s)
459 {
460 while (*s) {
461 safeputchar(*s);
462 s++;
463 }
464 }
465
466 void
467 safeputchar(int c)
468 {
469 unsigned char ch;
470
471 ch = (unsigned char)(c & 0xff);
472 if (ch < 0x80 && isprint(ch))
473 printf("%c", ch);
474 else
475 printf("\\%03o", ch);
476 }