xref: /openbsd-src/usr.sbin/tcpdump/util.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: util.c,v 1.24 2008/09/19 08:52:16 mpf Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Id: util.c,v 1.24 2008/09/19 08:52:16 mpf Exp $ (LBL)";
27 #endif
28 
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <sys/file.h>
32 #include <sys/limits.h>
33 #include <sys/stat.h>
34 
35 #include <ctype.h>
36 #include <err.h>
37 #include <errno.h>
38 #ifdef HAVE_FCNTL_H
39 #include <fcntl.h>
40 #endif
41 #include <pcap.h>
42 #include <stdio.h>
43 #include <stdarg.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #ifdef TIME_WITH_SYS_TIME
47 #include <time.h>
48 #endif
49 #include <unistd.h>
50 
51 #include "interface.h"
52 #include "privsep.h"
53 /*
54  * Print out a filename (or other ascii string).
55  * If ep is NULL, assume no truncation check is needed.
56  * Return true if truncated.
57  */
58 int
59 fn_print(register const u_char *s, register const u_char *ep)
60 {
61 	register int ret;
62 	register u_char c;
63 
64 	ret = 1;			/* assume truncated */
65 	while (ep == NULL || s < ep) {
66 		c = *s++;
67 		if (c == '\0') {
68 			ret = 0;
69 			break;
70 		}
71 		if (!isascii(c)) {
72 			c = toascii(c);
73 			putchar('M');
74 			putchar('-');
75 		}
76 		if (!isprint(c)) {
77 			c ^= 0x40;	/* DEL to ?, others to alpha */
78 			putchar('^');
79 		}
80 		putchar(c);
81 	}
82 	return(ret);
83 }
84 
85 /*
86  * Print out a counted filename (or other ascii string).
87  * If ep is NULL, assume no truncation check is needed.
88  * Return true if truncated.
89  */
90 int
91 fn_printn(register const u_char *s, register u_int n,
92 	  register const u_char *ep)
93 {
94 	register int ret;
95 	register u_char c;
96 
97 	ret = 1;			/* assume truncated */
98 	while (ep == NULL || s < ep) {
99 		if (n-- <= 0) {
100 			ret = 0;
101 			break;
102 		}
103 		c = *s++;
104 		if (!isascii(c)) {
105 			c = toascii(c);
106 			putchar('M');
107 			putchar('-');
108 		}
109 		if (!isprint(c)) {
110 			c ^= 0x40;	/* DEL to ?, others to alpha */
111 			putchar('^');
112 		}
113 		putchar(c);
114 	}
115 	return(ret);
116 }
117 
118 /*
119  * Print the timestamp
120  */
121 void
122 ts_print(register const struct bpf_timeval *tvp)
123 {
124 	register int s;
125 #define TSBUFLEN 32
126 	static char buf[TSBUFLEN];
127 	static struct bpf_timeval last;
128 	struct timeval diff;
129 	time_t t;
130 
131 	if (Iflag && device)
132 		(void)printf("%s ", device);
133 	switch(tflag){
134 	case 0:
135 		break;
136 	case -1:
137 		/* Unix timeval style */
138 		(void)printf("%u.%06u ",
139 		    (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec);
140 		break;
141 	case -2:
142 		t=tvp->tv_sec;
143 		strftime(buf, TSBUFLEN, "%b %d %T", priv_localtime(&t));
144 		printf("%s.%06u ", buf, (u_int32_t)tvp->tv_usec);
145 		break;
146 	case -3:
147 	case -4:
148 		/* time since first/last frame */
149 		timersub(tvp, &last, &diff);
150 		(void)printf("%u.%06u ",
151 		    (u_int32_t)diff.tv_sec, (u_int32_t)diff.tv_usec);
152 		if (tflag == -3 || (last.tv_sec == 0 && last.tv_usec == 0))
153 			last = *tvp;
154 		break;
155 	default:
156 		/* Default */
157 		s = (tvp->tv_sec + thiszone) % 86400;
158 		(void)printf("%02d:%02d:%02d.%06u ",
159 		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)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 char *lengths[] = {"y", "w", "d", "h", "m", "s"};
173 	static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
174 	char **l = lengths;
175 	int *s = seconds;
176 
177 	if (secs <= 0) {
178 		(void)printf("0s");
179 		return;
180 	}
181 	while (secs > 0) {
182 		if (secs >= *s) {
183 			(void)printf("%d%s", secs / *s, *l);
184 			secs -= (secs / *s) * *s;
185 		}
186 		s++;
187 		l++;
188 	}
189 }
190 
191 /*
192  * Convert a token value to a string; use "fmt" if not found.
193  */
194 const char *
195 tok2str(register const struct tok *lp, register const char *fmt,
196 	register int v)
197 {
198 	static char buf[128];
199 
200 	while (lp->s != NULL) {
201 		if (lp->v == v)
202 			return (lp->s);
203 		++lp;
204 	}
205 	if (fmt == NULL)
206 		fmt = "#%d";
207 	(void)snprintf(buf, sizeof(buf), fmt, v);
208 	return (buf);
209 }
210 
211 
212 /* VARARGS */
213 __dead void
214 error(const char *fmt, ...)
215 {
216 	va_list ap;
217 
218 	(void)fprintf(stderr, "%s: ", program_name);
219 	va_start(ap, fmt);
220 	(void)vfprintf(stderr, fmt, ap);
221 	va_end(ap);
222 	(void)fputc('\n', stderr);
223 	exit(1);
224 	/* NOTREACHED */
225 }
226 
227 /* VARARGS */
228 void
229 warning(const char *fmt, ...)
230 {
231 	va_list ap;
232 
233 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
234 	va_start(ap, fmt);
235 	(void)vfprintf(stderr, fmt, ap);
236 	va_end(ap);
237 	(void)fputc('\n', stderr);
238 }
239 
240 
241 /*
242  * Copy arg vector into a new buffer, concatenating arguments with spaces.
243  */
244 char *
245 copy_argv(char * const *argv)
246 {
247 	size_t len = 0, n;
248 	char *buf;
249 
250 	if (argv == NULL)
251 		return (NULL);
252 
253 	for (n = 0; argv[n]; n++)
254 		len += strlen(argv[n])+1;
255 	if (len == 0)
256 		return (NULL);
257 
258 	buf = malloc(len);
259 	if (buf == NULL)
260 		return (NULL);
261 
262 	strlcpy(buf, argv[0], len);
263 	for (n = 1; argv[n]; n++) {
264 		strlcat(buf, " ", len);
265 		strlcat(buf, argv[n], len);
266 	}
267 	return (buf);
268 }
269 
270 char *
271 read_infile(char *fname)
272 {
273 	struct stat	 buf;
274 	int		 fd;
275 	ssize_t		 cc;
276 	size_t		 bs;
277 	char		*cp;
278 
279 	fd = open(fname, O_RDONLY);
280 	if (fd < 0)
281 		error("can't open %s: %s", fname, pcap_strerror(errno));
282 
283 	if (fstat(fd, &buf) < 0)
284 		error("can't stat %s: %s", fname, pcap_strerror(errno));
285 
286 	if (buf.st_size >= SSIZE_MAX)
287 		error("file too long");
288 
289 	bs = buf.st_size;
290 	cp = malloc(bs + 1);
291 	if (cp == NULL)
292 		err(1, NULL);
293 	cc = read(fd, cp, bs);
294 	if (cc == -1)
295 		error("read %s: %s", fname, pcap_strerror(errno));
296 	if (cc != bs)
297 		error("short read %s (%ld != %lu)", fname, (long)cc,
298 		    (unsigned long)bs);
299 	cp[bs] = '\0';
300 	close(fd);
301 
302 	return (cp);
303 }
304 
305 void
306 safeputs(const char *s)
307 {
308 	while (*s) {
309 		safeputchar(*s);
310 		s++;
311 	}
312 }
313 
314 void
315 safeputchar(int c)
316 {
317 	unsigned char ch;
318 
319 	ch = (unsigned char)(c & 0xff);
320 	if (c < 0x80 && isprint(c))
321 		printf("%c", c & 0xff);
322 	else
323 		printf("\\%03o", c & 0xff);
324 }
325 
326 /*
327  * Print a value a la the %b format of the kernel's printf
328  * (from sbin/ifconfig/ifconfig.c)
329  */
330 void
331 printb(char *s, unsigned short v, char *bits)
332 {
333 	int i, any = 0;
334 	char c;
335 
336 	if (bits && *bits == 8)
337 		printf("%s=%o", s, v);
338 	else
339 		printf("%s=%x", s, v);
340 
341 	if (bits) {
342 		bits++;
343 		putchar('<');
344 		while ((i = *bits++)) {
345 			if (v & (1 << (i-1))) {
346 				if (any)
347 					putchar(',');
348 				any = 1;
349 				for (; (c = *bits) > 32; bits++)
350 					putchar(c);
351 			} else
352 				for (; *bits > 32; bits++)
353 					;
354 		}
355 		putchar('>');
356 	}
357 }
358