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