GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/switchd/util.c Lines: 0 171 0.0 %
Date: 2017-11-13 Branches: 0 114 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: util.c,v 1.6 2017/01/09 14:49:22 reyk Exp $	*/
2
3
/*
4
 * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/socket.h>
21
#include <sys/un.h>
22
23
#include <net/if.h>
24
#include <net/if_arp.h>
25
#include <netinet/in.h>
26
#include <netinet/if_ether.h>
27
#include <netinet/tcp.h>
28
29
#include <unistd.h>
30
#include <netdb.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <fcntl.h>
34
#include <string.h>
35
#include <errno.h>
36
#include <event.h>
37
38
#include "switchd.h"
39
40
void
41
socket_set_blockmode(int fd, enum blockmodes bm)
42
{
43
	int	flags;
44
45
	if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
46
		fatal("fcntl F_GETFL");
47
48
	if (bm == BM_NONBLOCK)
49
		flags |= O_NONBLOCK;
50
	else
51
		flags &= ~O_NONBLOCK;
52
53
	if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
54
		fatal("fcntl F_SETFL");
55
}
56
57
int
58
accept4_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
59
    int flags, int reserve, volatile int *counter)
60
{
61
	int	 fd;
62
63
	if (getdtablecount() + reserve + *counter >= getdtablesize()) {
64
		errno = EMFILE;
65
		return (-1);
66
	}
67
68
	if ((fd = accept4(sockfd, addr, addrlen, flags)) != -1) {
69
		(*counter)++;
70
		DPRINTF("%s: inflight incremented, now %d",__func__, *counter);
71
	}
72
73
	return (fd);
74
}
75
76
in_port_t
77
socket_getport(struct sockaddr_storage *ss)
78
{
79
	switch (ss->ss_family) {
80
	case AF_INET:
81
		return (ntohs(((struct sockaddr_in *)ss)->sin_port));
82
	case AF_INET6:
83
		return (ntohs(((struct sockaddr_in6 *)ss)->sin6_port));
84
	default:
85
		return (0);
86
	}
87
88
	/* NOTREACHED */
89
	return (0);
90
}
91
92
int
93
socket_setport(struct sockaddr_storage *ss, in_port_t port)
94
{
95
	switch (ss->ss_family) {
96
	case AF_INET:
97
		((struct sockaddr_in *)ss)->sin_port = ntohs(port);
98
		return (0);
99
	case AF_INET6:
100
		((struct sockaddr_in6 *)ss)->sin6_port = ntohs(port);
101
		return (0);
102
	default:
103
		return (-1);
104
	}
105
106
	/* NOTREACHED */
107
	return (-1);
108
}
109
110
int
111
sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
112
{
113
	struct sockaddr_in	*a4, *b4;
114
	struct sockaddr_in6	*a6, *b6;
115
	struct sockaddr_un	*au, *bu;
116
	uint32_t		 av[4], bv[4], mv[4];
117
118
	if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
119
		return (0);
120
	else if (a->sa_family > b->sa_family)
121
		return (1);
122
	else if (a->sa_family < b->sa_family)
123
		return (-1);
124
125
	if (prefixlen == -1)
126
		memset(&mv, 0xff, sizeof(mv));
127
128
	switch (a->sa_family) {
129
	case AF_INET:
130
		a4 = (struct sockaddr_in *)a;
131
		b4 = (struct sockaddr_in *)b;
132
133
		av[0] = a4->sin_addr.s_addr;
134
		bv[0] = b4->sin_addr.s_addr;
135
		if (prefixlen != -1)
136
			mv[0] = prefixlen2mask(prefixlen);
137
138
		if ((av[0] & mv[0]) > (bv[0] & mv[0]))
139
			return (1);
140
		if ((av[0] & mv[0]) < (bv[0] & mv[0]))
141
			return (-1);
142
		break;
143
	case AF_INET6:
144
		a6 = (struct sockaddr_in6 *)a;
145
		b6 = (struct sockaddr_in6 *)b;
146
147
		memcpy(&av, &a6->sin6_addr.s6_addr, 16);
148
		memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
149
		if (prefixlen != -1)
150
			prefixlen2mask6(prefixlen, mv);
151
152
		if ((av[3] & mv[3]) > (bv[3] & mv[3]))
153
			return (1);
154
		if ((av[3] & mv[3]) < (bv[3] & mv[3]))
155
			return (-1);
156
		if ((av[2] & mv[2]) > (bv[2] & mv[2]))
157
			return (1);
158
		if ((av[2] & mv[2]) < (bv[2] & mv[2]))
159
			return (-1);
160
		if ((av[1] & mv[1]) > (bv[1] & mv[1]))
161
			return (1);
162
		if ((av[1] & mv[1]) < (bv[1] & mv[1]))
163
			return (-1);
164
		if ((av[0] & mv[0]) > (bv[0] & mv[0]))
165
			return (1);
166
		if ((av[0] & mv[0]) < (bv[0] & mv[0]))
167
			return (-1);
168
		break;
169
	case AF_UNIX:
170
		au = (struct sockaddr_un *)a;
171
		bu = (struct sockaddr_un *)b;
172
		return (strcmp(au->sun_path, bu->sun_path));
173
	}
174
175
	return (0);
176
}
177
178
uint32_t
179
prefixlen2mask(uint8_t prefixlen)
180
{
181
	if (prefixlen == 0)
182
		return (0);
183
184
	if (prefixlen > 32)
185
		prefixlen = 32;
186
187
	return (htonl(0xffffffff << (32 - prefixlen)));
188
}
189
190
struct in6_addr *
191
prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
192
{
193
	static struct in6_addr  s6;
194
	int			i;
195
196
	if (prefixlen > 128)
197
		prefixlen = 128;
198
199
	bzero(&s6, sizeof(s6));
200
	for (i = 0; i < prefixlen / 8; i++)
201
		s6.s6_addr[i] = 0xff;
202
	i = prefixlen % 8;
203
	if (i)
204
		s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
205
206
	memcpy(mask, &s6, sizeof(s6));
207
208
	return (&s6);
209
}
210
211
const char *
212
print_ether(const uint8_t *ea)
213
{
214
	static char	 sbuf[SWITCHD_CYCLE_BUFFERS]
215
			    [ETHER_ADDR_LEN * 2 + 5 + 1];
216
	static int	 idx = 0;
217
	size_t		 len;
218
	char		*buf;
219
220
	buf = sbuf[idx];
221
	len = sizeof(sbuf[idx]);
222
	if (++idx >= SWITCHD_CYCLE_BUFFERS)
223
		idx = 0;
224
225
	snprintf(buf, len, "%02x:%02x:%02x:%02x:%02x:%02x",
226
	    ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
227
228
	return (buf);
229
}
230
231
const char *
232
print_host(struct sockaddr_storage *ss, char *buf, size_t len)
233
{
234
	static char	sbuf[SWITCHD_CYCLE_BUFFERS][NI_MAXHOST + 7];
235
	struct sockaddr_un *un;
236
	static int	idx = 0;
237
	char		pbuf[7];
238
	in_port_t	port;
239
240
	if (buf == NULL) {
241
		buf = sbuf[idx];
242
		len = sizeof(sbuf[idx]);
243
		if (++idx >= SWITCHD_CYCLE_BUFFERS)
244
			idx = 0;
245
	}
246
247
	if (ss->ss_family == AF_UNSPEC) {
248
		strlcpy(buf, "any", len);
249
		return (buf);
250
	} else if (ss->ss_family == AF_UNIX) {
251
		un = (struct sockaddr_un *)ss;
252
		strlcpy(buf, un->sun_path, len);
253
		return (buf);
254
	}
255
256
	if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
257
	    buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
258
		buf[0] = '\0';
259
		return (NULL);
260
	}
261
262
	if ((port = socket_getport(ss)) != 0) {
263
		snprintf(pbuf, sizeof(pbuf), ":%d", port);
264
		(void)strlcat(buf, pbuf, len);
265
	}
266
267
	return (buf);
268
}
269
270
const char *
271
print_map(unsigned int type, struct constmap *map)
272
{
273
	unsigned int		 i;
274
	static char		 buf[SWITCHD_CYCLE_BUFFERS][32];
275
	static int		 idx = 0;
276
	const char		*name = NULL;
277
278
	if (idx >= SWITCHD_CYCLE_BUFFERS)
279
		idx = 0;
280
	bzero(buf[idx], sizeof(buf[idx]));
281
282
	for (i = 0; map[i].cm_name != NULL; i++) {
283
		if (map[i].cm_type == type) {
284
			name = map[i].cm_name;
285
			break;
286
		}
287
	}
288
289
	if (name == NULL)
290
		snprintf(buf[idx], sizeof(buf[idx]), "<%u>", type);
291
	else
292
		strlcpy(buf[idx], name, sizeof(buf[idx]));
293
294
	return (buf[idx++]);
295
}
296
297
void
298
getmonotime(struct timeval *tv)
299
{
300
	struct timespec	 ts;
301
302
	if (clock_gettime(CLOCK_MONOTONIC, &ts))
303
		fatal("clock_gettime");
304
305
	TIMESPEC_TO_TIMEVAL(tv, &ts);
306
}
307
308
void
309
print_debug(const char *emsg, ...)
310
{
311
	va_list	 ap;
312
313
	if (log_getverbose() > 2) {
314
		va_start(ap, emsg);
315
		vfprintf(stderr, emsg, ap);
316
		va_end(ap);
317
	}
318
}
319
320
void
321
print_verbose(const char *emsg, ...)
322
{
323
	va_list	 ap;
324
325
	if (log_getverbose()) {
326
		va_start(ap, emsg);
327
		vfprintf(stderr, emsg, ap);
328
		va_end(ap);
329
	}
330
}
331
332
void
333
print_hex(uint8_t *buf, off_t offset, size_t length)
334
{
335
	unsigned int	 i;
336
337
	if (log_getverbose() < 3 || !length)
338
		return;
339
340
	for (i = 0; i < length; i++) {
341
		if (i && (i % 4) == 0) {
342
			if ((i % 32) == 0)
343
				print_debug("\n");
344
			else
345
				print_debug(" ");
346
		}
347
		print_debug("%02x", buf[offset + i]);
348
	}
349
	print_debug("\n");
350
}
351
352
int
353
parsehostport(const char *str, struct sockaddr *sa, socklen_t salen)
354
{
355
	char		 buf[NI_MAXHOST + NI_MAXSERV + 8], *servp, *nodep;
356
	struct addrinfo	 hints, *ai;
357
358
	if (strlcpy(buf, str, sizeof(buf)) >= sizeof(buf))
359
		return (-1);
360
361
	memset(&hints, 0, sizeof(hints));
362
	hints.ai_flags = 0;
363
	hints.ai_family = AF_UNSPEC;
364
	hints.ai_socktype = SOCK_STREAM;
365
	hints.ai_protocol = IPPROTO_TCP;
366
367
	if (buf[0] == '[' &&
368
	    (servp = strchr(buf, ']')) != NULL &&
369
	    (*(servp + 1) == '\0' || *(servp + 1) == ':')) {
370
		hints.ai_family = AF_INET6;
371
		hints.ai_flags = AI_NUMERICHOST;
372
		nodep = buf + 1;
373
		*servp++ = '\0';
374
	} else {
375
		nodep = buf;
376
		servp = strrchr(nodep, ':');
377
	}
378
	if (servp != NULL) {
379
		*servp = '\0';
380
		servp++;
381
	} else
382
		servp = NULL;
383
384
	if (getaddrinfo(nodep, servp, &hints, &ai) != 0)
385
		return (-1);
386
387
	if (salen < ai->ai_addrlen) {
388
		freeaddrinfo(ai);
389
		return (-1);
390
	}
391
	memset(sa, 0, salen);
392
	memcpy(sa, ai->ai_addr, ai->ai_addrlen);
393
394
	return (0);
395
}