xref: /openbsd-src/usr.sbin/tcpdump/util.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: util.c,v 1.25 2009/10/27 23:59:57 deraadt 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 #include <sys/types.h>
25 #include <sys/time.h>
26 #include <sys/file.h>
27 #include <sys/limits.h>
28 #include <sys/stat.h>
29 
30 #include <ctype.h>
31 #include <err.h>
32 #include <errno.h>
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36 #include <pcap.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #ifdef TIME_WITH_SYS_TIME
42 #include <time.h>
43 #endif
44 #include <unistd.h>
45 
46 #include "interface.h"
47 #include "privsep.h"
48 /*
49  * Print out a filename (or other ascii string).
50  * If ep is NULL, assume no truncation check is needed.
51  * Return true if truncated.
52  */
53 int
54 fn_print(register const u_char *s, register const u_char *ep)
55 {
56 	register int ret;
57 	register u_char c;
58 
59 	ret = 1;			/* assume truncated */
60 	while (ep == NULL || s < ep) {
61 		c = *s++;
62 		if (c == '\0') {
63 			ret = 0;
64 			break;
65 		}
66 		if (!isascii(c)) {
67 			c = toascii(c);
68 			putchar('M');
69 			putchar('-');
70 		}
71 		if (!isprint(c)) {
72 			c ^= 0x40;	/* DEL to ?, others to alpha */
73 			putchar('^');
74 		}
75 		putchar(c);
76 	}
77 	return(ret);
78 }
79 
80 /*
81  * Print out a counted filename (or other ascii string).
82  * If ep is NULL, assume no truncation check is needed.
83  * Return true if truncated.
84  */
85 int
86 fn_printn(register const u_char *s, register u_int n,
87 	  register const u_char *ep)
88 {
89 	register int ret;
90 	register u_char c;
91 
92 	ret = 1;			/* assume truncated */
93 	while (ep == NULL || s < ep) {
94 		if (n-- <= 0) {
95 			ret = 0;
96 			break;
97 		}
98 		c = *s++;
99 		if (!isascii(c)) {
100 			c = toascii(c);
101 			putchar('M');
102 			putchar('-');
103 		}
104 		if (!isprint(c)) {
105 			c ^= 0x40;	/* DEL to ?, others to alpha */
106 			putchar('^');
107 		}
108 		putchar(c);
109 	}
110 	return(ret);
111 }
112 
113 /*
114  * Print the timestamp
115  */
116 void
117 ts_print(register const struct bpf_timeval *tvp)
118 {
119 	register int s;
120 #define TSBUFLEN 32
121 	static char buf[TSBUFLEN];
122 	static struct bpf_timeval last;
123 	struct timeval diff;
124 	time_t t;
125 
126 	if (Iflag && device)
127 		(void)printf("%s ", device);
128 	switch(tflag){
129 	case 0:
130 		break;
131 	case -1:
132 		/* Unix timeval style */
133 		(void)printf("%u.%06u ",
134 		    (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec);
135 		break;
136 	case -2:
137 		t=tvp->tv_sec;
138 		strftime(buf, TSBUFLEN, "%b %d %T", priv_localtime(&t));
139 		printf("%s.%06u ", buf, (u_int32_t)tvp->tv_usec);
140 		break;
141 	case -3:
142 	case -4:
143 		/* time since first/last frame */
144 		timersub(tvp, &last, &diff);
145 		(void)printf("%u.%06u ",
146 		    (u_int32_t)diff.tv_sec, (u_int32_t)diff.tv_usec);
147 		if (tflag == -3 || (last.tv_sec == 0 && last.tv_usec == 0))
148 			last = *tvp;
149 		break;
150 	default:
151 		/* Default */
152 		s = (tvp->tv_sec + thiszone) % 86400;
153 		(void)printf("%02d:%02d:%02d.%06u ",
154 		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
155 		break;
156 	}
157 }
158 
159 /*
160  * Print a relative number of seconds (e.g. hold time, prune timer)
161  * in the form 5m1s.  This does no truncation, so 32230861 seconds
162  * is represented as 1y1w1d1h1m1s.
163  */
164 void
165 relts_print(int secs)
166 {
167 	static char *lengths[] = {"y", "w", "d", "h", "m", "s"};
168 	static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
169 	char **l = lengths;
170 	int *s = seconds;
171 
172 	if (secs <= 0) {
173 		(void)printf("0s");
174 		return;
175 	}
176 	while (secs > 0) {
177 		if (secs >= *s) {
178 			(void)printf("%d%s", secs / *s, *l);
179 			secs -= (secs / *s) * *s;
180 		}
181 		s++;
182 		l++;
183 	}
184 }
185 
186 /*
187  * Convert a token value to a string; use "fmt" if not found.
188  */
189 const char *
190 tok2str(register const struct tok *lp, register const char *fmt,
191 	register int v)
192 {
193 	static char buf[128];
194 
195 	while (lp->s != NULL) {
196 		if (lp->v == v)
197 			return (lp->s);
198 		++lp;
199 	}
200 	if (fmt == NULL)
201 		fmt = "#%d";
202 	(void)snprintf(buf, sizeof(buf), fmt, v);
203 	return (buf);
204 }
205 
206 
207 /* VARARGS */
208 __dead void
209 error(const char *fmt, ...)
210 {
211 	va_list ap;
212 
213 	(void)fprintf(stderr, "%s: ", program_name);
214 	va_start(ap, fmt);
215 	(void)vfprintf(stderr, fmt, ap);
216 	va_end(ap);
217 	(void)fputc('\n', stderr);
218 	exit(1);
219 	/* NOTREACHED */
220 }
221 
222 /* VARARGS */
223 void
224 warning(const char *fmt, ...)
225 {
226 	va_list ap;
227 
228 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
229 	va_start(ap, fmt);
230 	(void)vfprintf(stderr, fmt, ap);
231 	va_end(ap);
232 	(void)fputc('\n', stderr);
233 }
234 
235 
236 /*
237  * Copy arg vector into a new buffer, concatenating arguments with spaces.
238  */
239 char *
240 copy_argv(char * const *argv)
241 {
242 	size_t len = 0, n;
243 	char *buf;
244 
245 	if (argv == NULL)
246 		return (NULL);
247 
248 	for (n = 0; argv[n]; n++)
249 		len += strlen(argv[n])+1;
250 	if (len == 0)
251 		return (NULL);
252 
253 	buf = malloc(len);
254 	if (buf == NULL)
255 		return (NULL);
256 
257 	strlcpy(buf, argv[0], len);
258 	for (n = 1; argv[n]; n++) {
259 		strlcat(buf, " ", len);
260 		strlcat(buf, argv[n], len);
261 	}
262 	return (buf);
263 }
264 
265 char *
266 read_infile(char *fname)
267 {
268 	struct stat	 buf;
269 	int		 fd;
270 	ssize_t		 cc;
271 	size_t		 bs;
272 	char		*cp;
273 
274 	fd = open(fname, O_RDONLY);
275 	if (fd < 0)
276 		error("can't open %s: %s", fname, pcap_strerror(errno));
277 
278 	if (fstat(fd, &buf) < 0)
279 		error("can't stat %s: %s", fname, pcap_strerror(errno));
280 
281 	if (buf.st_size >= SSIZE_MAX)
282 		error("file too long");
283 
284 	bs = buf.st_size;
285 	cp = malloc(bs + 1);
286 	if (cp == NULL)
287 		err(1, NULL);
288 	cc = read(fd, cp, bs);
289 	if (cc == -1)
290 		error("read %s: %s", fname, pcap_strerror(errno));
291 	if (cc != bs)
292 		error("short read %s (%ld != %lu)", fname, (long)cc,
293 		    (unsigned long)bs);
294 	cp[bs] = '\0';
295 	close(fd);
296 
297 	return (cp);
298 }
299 
300 void
301 safeputs(const char *s)
302 {
303 	while (*s) {
304 		safeputchar(*s);
305 		s++;
306 	}
307 }
308 
309 void
310 safeputchar(int c)
311 {
312 	unsigned char ch;
313 
314 	ch = (unsigned char)(c & 0xff);
315 	if (c < 0x80 && isprint(c))
316 		printf("%c", c & 0xff);
317 	else
318 		printf("\\%03o", c & 0xff);
319 }
320 
321 /*
322  * Print a value a la the %b format of the kernel's printf
323  * (from sbin/ifconfig/ifconfig.c)
324  */
325 void
326 printb(char *s, unsigned short v, char *bits)
327 {
328 	int i, any = 0;
329 	char c;
330 
331 	if (bits && *bits == 8)
332 		printf("%s=%o", s, v);
333 	else
334 		printf("%s=%x", s, v);
335 
336 	if (bits) {
337 		bits++;
338 		putchar('<');
339 		while ((i = *bits++)) {
340 			if (v & (1 << (i-1))) {
341 				if (any)
342 					putchar(',');
343 				any = 1;
344 				for (; (c = *bits) > 32; bits++)
345 					putchar(c);
346 			} else
347 				for (; *bits > 32; bits++)
348 					;
349 		}
350 		putchar('>');
351 	}
352 }
353