GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ldpd/util.c Lines: 0 154 0.0 %
Date: 2017-11-07 Branches: 0 176 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: util.c,v 1.4 2016/05/23 18:58:48 renato Exp $ */
2
3
/*
4
 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
5
 * Copyright (c) 2012 Alexander Bluhm <bluhm@openbsd.org>
6
 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
#include <sys/types.h>
23
#include <string.h>
24
25
#include "ldpd.h"
26
#include "log.h"
27
28
uint8_t
29
mask2prefixlen(in_addr_t ina)
30
{
31
	if (ina == 0)
32
		return (0);
33
	else
34
		return (33 - ffs(ntohl(ina)));
35
}
36
37
uint8_t
38
mask2prefixlen6(struct sockaddr_in6 *sa_in6)
39
{
40
	uint8_t	l = 0, *ap, *ep;
41
42
	/*
43
	 * sin6_len is the size of the sockaddr so substract the offset of
44
	 * the possibly truncated sin6_addr struct.
45
	 */
46
	ap = (uint8_t *)&sa_in6->sin6_addr;
47
	ep = (uint8_t *)sa_in6 + sa_in6->sin6_len;
48
	for (; ap < ep; ap++) {
49
		/* this "beauty" is adopted from sbin/route/show.c ... */
50
		switch (*ap) {
51
		case 0xff:
52
			l += 8;
53
			break;
54
		case 0xfe:
55
			l += 7;
56
			return (l);
57
		case 0xfc:
58
			l += 6;
59
			return (l);
60
		case 0xf8:
61
			l += 5;
62
			return (l);
63
		case 0xf0:
64
			l += 4;
65
			return (l);
66
		case 0xe0:
67
			l += 3;
68
			return (l);
69
		case 0xc0:
70
			l += 2;
71
			return (l);
72
		case 0x80:
73
			l += 1;
74
			return (l);
75
		case 0x00:
76
			return (l);
77
		default:
78
			fatalx("non contiguous inet6 netmask");
79
		}
80
	}
81
82
	return (l);
83
}
84
85
in_addr_t
86
prefixlen2mask(uint8_t prefixlen)
87
{
88
	if (prefixlen == 0)
89
		return (0);
90
91
	return (htonl(0xffffffff << (32 - prefixlen)));
92
}
93
94
struct in6_addr *
95
prefixlen2mask6(uint8_t prefixlen)
96
{
97
	static struct in6_addr	mask;
98
	int			i;
99
100
	memset(&mask, 0, sizeof(mask));
101
	for (i = 0; i < prefixlen / 8; i++)
102
		mask.s6_addr[i] = 0xff;
103
	i = prefixlen % 8;
104
	if (i)
105
		mask.s6_addr[prefixlen / 8] = 0xff00 >> i;
106
107
	return (&mask);
108
}
109
110
void
111
ldp_applymask(int af, union ldpd_addr *dest, const union ldpd_addr *src,
112
    int prefixlen)
113
{
114
	struct in6_addr	mask;
115
	int		i;
116
117
	switch (af) {
118
	case AF_INET:
119
		dest->v4.s_addr = src->v4.s_addr & prefixlen2mask(prefixlen);
120
		break;
121
	case AF_INET6:
122
		memset(&mask, 0, sizeof(mask));
123
		for (i = 0; i < prefixlen / 8; i++)
124
			mask.s6_addr[i] = 0xff;
125
		i = prefixlen % 8;
126
		if (i)
127
			mask.s6_addr[prefixlen / 8] = 0xff00 >> i;
128
129
		for (i = 0; i < 16; i++)
130
			dest->v6.s6_addr[i] = src->v6.s6_addr[i] &
131
			    mask.s6_addr[i];
132
		break;
133
	default:
134
		fatalx("ldp_applymask: unknown af");
135
	}
136
}
137
138
int
139
ldp_addrcmp(int af, const union ldpd_addr *a, const union ldpd_addr *b)
140
{
141
	switch (af) {
142
	case AF_INET:
143
		if (a->v4.s_addr == b->v4.s_addr)
144
			return (0);
145
		return ((ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr)) ? 1 : -1);
146
	case AF_INET6:
147
		return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr)));
148
	default:
149
		fatalx("ldp_addrcmp: unknown af");
150
	}
151
}
152
153
int
154
ldp_addrisset(int af, const union ldpd_addr *addr)
155
{
156
	switch (af) {
157
	case AF_UNSPEC:
158
		return (0);
159
	case AF_INET:
160
		if (addr->v4.s_addr != INADDR_ANY)
161
			return (1);
162
		break;
163
	case AF_INET6:
164
		if (!IN6_IS_ADDR_UNSPECIFIED(&addr->v6))
165
			return (1);
166
		break;
167
	default:
168
		fatalx("ldp_addrisset: unknown af");
169
	}
170
171
	return (0);
172
}
173
174
int
175
ldp_prefixcmp(int af, const union ldpd_addr *a, const union ldpd_addr *b,
176
    uint8_t prefixlen)
177
{
178
	in_addr_t	mask, aa, ba;
179
	int		i;
180
	uint8_t		m;
181
182
	switch (af) {
183
	case AF_INET:
184
		if (prefixlen == 0)
185
			return (0);
186
		if (prefixlen > 32)
187
			fatalx("ldp_prefixcmp: bad IPv4 prefixlen");
188
		mask = htonl(prefixlen2mask(prefixlen));
189
		aa = htonl(a->v4.s_addr) & mask;
190
		ba = htonl(b->v4.s_addr) & mask;
191
		return (aa - ba);
192
	case AF_INET6:
193
		if (prefixlen == 0)
194
			return (0);
195
		if (prefixlen > 128)
196
			fatalx("ldp_prefixcmp: bad IPv6 prefixlen");
197
		for (i = 0; i < prefixlen / 8; i++)
198
			if (a->v6.s6_addr[i] != b->v6.s6_addr[i])
199
				return (a->v6.s6_addr[i] - b->v6.s6_addr[i]);
200
		i = prefixlen % 8;
201
		if (i) {
202
			m = 0xff00 >> i;
203
			if ((a->v6.s6_addr[prefixlen / 8] & m) !=
204
			    (b->v6.s6_addr[prefixlen / 8] & m))
205
				return ((a->v6.s6_addr[prefixlen / 8] & m) -
206
				    (b->v6.s6_addr[prefixlen / 8] & m));
207
		}
208
		return (0);
209
	default:
210
		fatalx("ldp_prefixcmp: unknown af");
211
	}
212
	return (-1);
213
}
214
215
int
216
bad_addr_v4(struct in_addr addr)
217
{
218
	uint32_t	 a = ntohl(addr.s_addr);
219
220
	if (((a >> IN_CLASSA_NSHIFT) == 0) ||
221
	    ((a >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) ||
222
	    IN_MULTICAST(a) || IN_BADCLASS(a))
223
		return (1);
224
225
	return (0);
226
}
227
228
int
229
bad_addr_v6(struct in6_addr *addr)
230
{
231
	if (IN6_IS_ADDR_UNSPECIFIED(addr) ||
232
	    IN6_IS_ADDR_LOOPBACK(addr) ||
233
	    IN6_IS_ADDR_MULTICAST(addr) ||
234
	    IN6_IS_ADDR_SITELOCAL(addr) ||
235
	    IN6_IS_ADDR_V4MAPPED(addr) ||
236
	    IN6_IS_ADDR_V4COMPAT(addr))
237
		return (1);
238
239
	return (0);
240
}
241
242
int
243
bad_addr(int af, union ldpd_addr *addr)
244
{
245
	switch (af) {
246
	case AF_INET:
247
		return (bad_addr_v4(addr->v4));
248
	case AF_INET6:
249
		return (bad_addr_v6(&addr->v6));
250
	default:
251
		fatalx("bad_addr: unknown af");
252
	}
253
}
254
255
void
256
embedscope(struct sockaddr_in6 *sin6)
257
{
258
	uint16_t	 tmp16;
259
260
	if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr)) {
261
		memcpy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16));
262
		if (tmp16 != 0) {
263
			log_warnx("%s: address %s already has embeded scope %u",
264
			    __func__, log_sockaddr(sin6), ntohs(tmp16));
265
		}
266
		tmp16 = htons(sin6->sin6_scope_id);
267
		memcpy(&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof(tmp16));
268
		sin6->sin6_scope_id = 0;
269
	}
270
}
271
272
void
273
recoverscope(struct sockaddr_in6 *sin6)
274
{
275
	uint16_t	 tmp16;
276
277
	if (sin6->sin6_scope_id != 0)
278
		log_warnx("%s: address %s already has scope id %u",
279
		    __func__, log_sockaddr(sin6), sin6->sin6_scope_id);
280
281
	if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr)) {
282
		memcpy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16));
283
		sin6->sin6_scope_id = ntohs(tmp16);
284
		sin6->sin6_addr.s6_addr[2] = 0;
285
		sin6->sin6_addr.s6_addr[3] = 0;
286
	}
287
}
288
289
void
290
addscope(struct sockaddr_in6 *sin6, uint32_t id)
291
{
292
	if (sin6->sin6_scope_id != 0)
293
		log_warnx("%s: address %s already has scope id %u", __func__,
294
		    log_sockaddr(sin6), sin6->sin6_scope_id);
295
296
	if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr))
297
		sin6->sin6_scope_id = id;
298
}
299
300
void
301
clearscope(struct in6_addr *in6)
302
{
303
	if (IN6_IS_SCOPE_EMBED(in6)) {
304
		in6->s6_addr[2] = 0;
305
		in6->s6_addr[3] = 0;
306
	}
307
}
308
309
struct sockaddr *
310
addr2sa(int af, union ldpd_addr *addr, uint16_t port)
311
{
312
	static struct sockaddr_storage	 ss;
313
	struct sockaddr_in		*sa_in = (struct sockaddr_in *)&ss;
314
	struct sockaddr_in6		*sa_in6 = (struct sockaddr_in6 *)&ss;
315
316
	memset(&ss, 0, sizeof(ss));
317
	switch (af) {
318
	case AF_INET:
319
		sa_in->sin_family = AF_INET;
320
		sa_in->sin_len = sizeof(struct sockaddr_in);
321
		sa_in->sin_addr = addr->v4;
322
		sa_in->sin_port = htons(port);
323
		break;
324
	case AF_INET6:
325
		sa_in6->sin6_family = AF_INET6;
326
		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
327
		sa_in6->sin6_addr = addr->v6;
328
		sa_in6->sin6_port = htons(port);
329
		break;
330
	default:
331
		fatalx("addr2sa: unknown af");
332
	}
333
334
	return ((struct sockaddr *)&ss);
335
}
336
337
void
338
sa2addr(struct sockaddr *sa, int *af, union ldpd_addr *addr)
339
{
340
	struct sockaddr_in		*sa_in = (struct sockaddr_in *)sa;
341
	struct sockaddr_in6		*sa_in6 = (struct sockaddr_in6 *)sa;
342
343
	memset(addr, 0, sizeof(*addr));
344
	switch (sa->sa_family) {
345
	case AF_INET:
346
		*af = AF_INET;
347
		addr->v4 = sa_in->sin_addr;
348
		break;
349
	case AF_INET6:
350
		*af = AF_INET6;
351
		addr->v6 = sa_in6->sin6_addr;
352
		break;
353
	default:
354
		fatalx("sa2addr: unknown af");
355
	}
356
}