GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/net/rthdr.c Lines: 0 60 0.0 %
Date: 2017-11-13 Branches: 0 30 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rthdr.c,v 1.12 2016/09/21 04:38:56 guenther Exp $	*/
2
/*	$KAME: rthdr.c,v 1.22 2006/02/09 08:18:58 keiichi Exp $	*/
3
4
/*
5
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the project nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
36
#include <netinet/in.h>
37
#include <netinet/ip6.h>
38
39
#include <string.h>
40
#include <stdio.h>
41
42
/*
43
 * RFC3542 (2292bis) API
44
 */
45
46
socklen_t
47
inet6_rth_space(int type, int segments)
48
{
49
	switch (type) {
50
	case IPV6_RTHDR_TYPE_0:
51
		return (((segments * 2) + 1) << 3);
52
	default:
53
		return (0);	/* type not suppported */
54
	}
55
}
56
DEF_WEAK(inet6_rth_space);
57
58
void *
59
inet6_rth_init(void *bp, socklen_t bp_len, int type, int segments)
60
{
61
	struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
62
	struct ip6_rthdr0 *rth0;
63
64
	switch (type) {
65
	case IPV6_RTHDR_TYPE_0:
66
		/* length validation */
67
		if (bp_len < inet6_rth_space(IPV6_RTHDR_TYPE_0, segments))
68
			return (NULL);
69
70
		memset(bp, 0, bp_len);
71
		rth0 = (struct ip6_rthdr0 *)rth;
72
		rth0->ip6r0_len = segments * 2;
73
		rth0->ip6r0_type = IPV6_RTHDR_TYPE_0;
74
		rth0->ip6r0_segleft = 0;
75
		rth0->ip6r0_reserved = 0;
76
		break;
77
	default:
78
		return (NULL);	/* type not supported */
79
	}
80
81
	return (bp);
82
}
83
84
int
85
inet6_rth_add(void *bp, const struct in6_addr *addr)
86
{
87
	struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
88
	struct ip6_rthdr0 *rth0;
89
	struct in6_addr *nextaddr;
90
91
	switch (rth->ip6r_type) {
92
	case IPV6_RTHDR_TYPE_0:
93
		rth0 = (struct ip6_rthdr0 *)rth;
94
		nextaddr = (struct in6_addr *)(rth0 + 1) + rth0->ip6r0_segleft;
95
		*nextaddr = *addr;
96
		rth0->ip6r0_segleft++;
97
		break;
98
	default:
99
		return (-1);	/* type not supported */
100
	}
101
102
	return (0);
103
}
104
105
int
106
inet6_rth_reverse(const void *in, void *out)
107
{
108
	struct ip6_rthdr *rth_in = (struct ip6_rthdr *)in;
109
	struct ip6_rthdr0 *rth0_in, *rth0_out;
110
	int i, segments;
111
112
	switch (rth_in->ip6r_type) {
113
	case IPV6_RTHDR_TYPE_0:
114
		rth0_in = (struct ip6_rthdr0 *)in;
115
		rth0_out = (struct ip6_rthdr0 *)out;
116
117
		/* parameter validation XXX too paranoid? */
118
		if (rth0_in->ip6r0_len % 2)
119
			return (-1);
120
		segments = rth0_in->ip6r0_len / 2;
121
122
		/* we can't use memcpy here, since in and out may overlap */
123
		memmove(rth0_out, rth0_in, ((rth0_in->ip6r0_len) + 1) << 3);
124
		rth0_out->ip6r0_segleft = segments;
125
126
		/* reverse the addresses */
127
		for (i = 0; i < segments / 2; i++) {
128
			struct in6_addr addr_tmp, *addr1, *addr2;
129
130
			addr1 = (struct in6_addr *)(rth0_out + 1) + i;
131
			addr2 = (struct in6_addr *)(rth0_out + 1) +
132
			    (segments - i - 1);
133
			addr_tmp = *addr1;
134
			*addr1 = *addr2;
135
			*addr2 = addr_tmp;
136
		}
137
138
		break;
139
	default:
140
		return (-1);	/* type not supported */
141
	}
142
143
	return (0);
144
}
145
146
int
147
inet6_rth_segments(const void *bp)
148
{
149
	struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
150
	struct ip6_rthdr0 *rh0;
151
	int addrs;
152
153
	switch (rh->ip6r_type) {
154
	case IPV6_RTHDR_TYPE_0:
155
		rh0 = (struct ip6_rthdr0 *)bp;
156
157
		/*
158
		 * Validation for a type-0 routing header.
159
		 * Is this too strict?
160
		 */
161
		if ((rh0->ip6r0_len % 2) != 0 ||
162
		    (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
163
			return (-1);
164
165
		return (addrs);
166
	default:
167
		return (-1);	/* unknown type */
168
	}
169
}
170
171
struct in6_addr *
172
inet6_rth_getaddr(const void *bp, int idx)
173
{
174
	struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
175
	struct ip6_rthdr0 *rh0;
176
	int addrs;
177
178
	switch (rh->ip6r_type) {
179
	case IPV6_RTHDR_TYPE_0:
180
		 rh0 = (struct ip6_rthdr0 *)bp;
181
182
		/*
183
		 * Validation for a type-0 routing header.
184
		 * Is this too strict?
185
		 */
186
		if ((rh0->ip6r0_len % 2) != 0 ||
187
		    (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
188
			return (NULL);
189
190
		if (idx < 0 || addrs <= idx)
191
			return (NULL);
192
193
		return (((struct in6_addr *)(rh0 + 1)) + idx);
194
	default:
195
		return (NULL);	/* unknown type */
196
		break;
197
	}
198
}