GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ospf6ctl/../ospf6d/util.c Lines: 0 64 0.0 %
Date: 2017-11-13 Branches: 0 76 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: util.c,v 1.2 2012/10/22 07:28:49 bluhm Exp $ */
2
3
/*
4
 * Copyright (c) 2012 Alexander Bluhm <bluhm@openbsd.org>
5
 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
6
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#include <netinet/in.h>
22
#include <string.h>
23
24
#include "ospf6d.h"
25
#include "log.h"
26
27
#define IN6_IS_SCOPE_EMBED(a)   \
28
	((IN6_IS_ADDR_LINKLOCAL(a)) ||  \
29
	 (IN6_IS_ADDR_MC_LINKLOCAL(a)) || \
30
	 (IN6_IS_ADDR_MC_INTFACELOCAL(a)))
31
32
void
33
embedscope(struct sockaddr_in6 *sin6)
34
{
35
	u_int16_t	 tmp16;
36
37
	if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr)) {
38
		bcopy(&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof(tmp16));
39
		if (tmp16 != 0) {
40
			log_warnx("embedscope: address %s already has embeded "
41
			    "scope %u", log_sockaddr(sin6), ntohs(tmp16));
42
		}
43
		tmp16 = htons(sin6->sin6_scope_id);
44
		bcopy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16));
45
		sin6->sin6_scope_id = 0;
46
	}
47
}
48
49
void
50
recoverscope(struct sockaddr_in6 *sin6)
51
{
52
	u_int16_t	 tmp16;
53
54
	if (sin6->sin6_scope_id != 0) {
55
		log_warnx("recoverscope: address %s already has scope id %u",
56
		    log_sockaddr(sin6), sin6->sin6_scope_id);
57
	}
58
59
	if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr)) {
60
		bcopy(&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof(tmp16));
61
		sin6->sin6_scope_id = ntohs(tmp16);
62
		sin6->sin6_addr.s6_addr[2] = 0;
63
		sin6->sin6_addr.s6_addr[3] = 0;
64
	}
65
}
66
67
void
68
addscope(struct sockaddr_in6 *sin6, u_int32_t id)
69
{
70
	if (sin6->sin6_scope_id != 0) {
71
		log_warnx("addscope: address %s already has scope id %u",
72
		    log_sockaddr(sin6), sin6->sin6_scope_id);
73
	}
74
75
	if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr)) {
76
		sin6->sin6_scope_id = id;
77
	}
78
}
79
80
void
81
clearscope(struct in6_addr *in6)
82
{
83
	if (IN6_IS_SCOPE_EMBED(in6)) {
84
		in6->s6_addr[2] = 0;
85
		in6->s6_addr[3] = 0;
86
	}
87
}
88
89
#undef IN6_IS_SCOPE_EMBED
90
91
u_int8_t
92
mask2prefixlen(struct sockaddr_in6 *sa_in6)
93
{
94
	u_int8_t	l = 0, *ap, *ep;
95
96
	/*
97
	 * sin6_len is the size of the sockaddr so substract the offset of
98
	 * the possibly truncated sin6_addr struct.
99
	 */
100
	ap = (u_int8_t *)&sa_in6->sin6_addr;
101
	ep = (u_int8_t *)sa_in6 + sa_in6->sin6_len;
102
	for (; ap < ep; ap++) {
103
		/* this "beauty" is adopted from sbin/route/show.c ... */
104
		switch (*ap) {
105
		case 0xff:
106
			l += 8;
107
			break;
108
		case 0xfe:
109
			l += 7;
110
			return (l);
111
		case 0xfc:
112
			l += 6;
113
			return (l);
114
		case 0xf8:
115
			l += 5;
116
			return (l);
117
		case 0xf0:
118
			l += 4;
119
			return (l);
120
		case 0xe0:
121
			l += 3;
122
			return (l);
123
		case 0xc0:
124
			l += 2;
125
			return (l);
126
		case 0x80:
127
			l += 1;
128
			return (l);
129
		case 0x00:
130
			return (l);
131
		default:
132
			fatalx("non contiguous inet6 netmask");
133
		}
134
	}
135
136
	return (l);
137
}
138
139
struct in6_addr *
140
prefixlen2mask(u_int8_t prefixlen)
141
{
142
	static struct in6_addr	mask;
143
	int			i;
144
145
	bzero(&mask, sizeof(mask));
146
	for (i = 0; i < prefixlen / 8; i++)
147
		mask.s6_addr[i] = 0xff;
148
	i = prefixlen % 8;
149
	if (i)
150
		mask.s6_addr[prefixlen / 8] = 0xff00 >> i;
151
152
	return (&mask);
153
}
154
155
void
156
inet6applymask(struct in6_addr *dest, const struct in6_addr *src, int prefixlen)
157
{
158
	struct in6_addr	mask;
159
	int		i;
160
161
	bzero(&mask, sizeof(mask));
162
	for (i = 0; i < prefixlen / 8; i++)
163
		mask.s6_addr[i] = 0xff;
164
	i = prefixlen % 8;
165
	if (i)
166
		mask.s6_addr[prefixlen / 8] = 0xff00 >> i;
167
168
	for (i = 0; i < 16; i++)
169
		dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i];
170
}