summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/rthdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/rthdr.c')
-rw-r--r--src/lib/libc/net/rthdr.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/lib/libc/net/rthdr.c b/src/lib/libc/net/rthdr.c
new file mode 100644
index 0000000000..36ac5a3554
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,215 @@
1/* $OpenBSD: rthdr.c,v 1.7 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
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
42size_t
43inet6_rthdr_space(int type, int seg)
44{
45 switch (type) {
46 case IPV6_RTHDR_TYPE_0:
47 if (seg < 1 || seg > 23)
48 return (0);
49 return (CMSG_SPACE(sizeof(struct in6_addr) * seg +
50 sizeof(struct ip6_rthdr0)));
51 default:
52 return (0);
53 }
54}
55
56struct cmsghdr *
57inet6_rthdr_init(void *bp, int type)
58{
59 struct cmsghdr *ch = (struct cmsghdr *)bp;
60 struct ip6_rthdr *rthdr;
61
62 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
63
64 ch->cmsg_level = IPPROTO_IPV6;
65 ch->cmsg_type = IPV6_RTHDR;
66
67 switch (type) {
68 case IPV6_RTHDR_TYPE_0:
69 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0));
70 bzero(rthdr, sizeof(struct ip6_rthdr0));
71 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
72 return (ch);
73 default:
74 return (NULL);
75 }
76}
77
78int
79inet6_rthdr_add(struct cmsghdr *cmsg, const struct in6_addr *addr, u_int flags)
80{
81 struct ip6_rthdr *rthdr;
82
83 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
84
85 switch (rthdr->ip6r_type) {
86 case IPV6_RTHDR_TYPE_0:
87 {
88 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
89 if (flags != IPV6_RTHDR_LOOSE)
90 return (-1);
91 if (rt0->ip6r0_segleft == 23)
92 return (-1);
93 rt0->ip6r0_segleft++;
94 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
95 sizeof(struct in6_addr));
96 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
97 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
98 break;
99 }
100 default:
101 return (-1);
102 }
103
104 return (0);
105}
106
107int
108inet6_rthdr_lasthop(struct cmsghdr *cmsg, unsigned int flags)
109{
110 struct ip6_rthdr *rthdr;
111
112 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
113
114 switch (rthdr->ip6r_type) {
115 case IPV6_RTHDR_TYPE_0:
116 {
117 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
118 if (flags != IPV6_RTHDR_LOOSE)
119 return (-1);
120 if (rt0->ip6r0_segleft > 23)
121 return (-1);
122 break;
123 }
124 default:
125 return (-1);
126 }
127
128 return (0);
129}
130
131#if 0
132int
133inet6_rthdr_reverse(in, out)
134 const struct cmsghdr *in;
135 struct cmsghdr *out;
136{
137
138 return (-1);
139}
140#endif
141
142int
143inet6_rthdr_segments(const struct cmsghdr *cmsg)
144{
145 struct ip6_rthdr *rthdr;
146
147 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
148
149 switch (rthdr->ip6r_type) {
150 case IPV6_RTHDR_TYPE_0:
151 {
152 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
153
154 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
155 return (-1);
156
157 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
158 }
159
160 default:
161 return (-1);
162 }
163}
164
165struct in6_addr *
166inet6_rthdr_getaddr(struct cmsghdr *cmsg, int index)
167{
168 struct ip6_rthdr *rthdr;
169
170 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
171
172 switch (rthdr->ip6r_type) {
173 case IPV6_RTHDR_TYPE_0:
174 {
175 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
176 int naddr;
177
178 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
179 return NULL;
180 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
181 if (index <= 0 || naddr < index)
182 return NULL;
183 return ((struct in6_addr *)(rt0 + 1)) + index;
184 }
185
186 default:
187 return NULL;
188 }
189}
190
191int
192inet6_rthdr_getflags(const struct cmsghdr *cmsg, int index)
193{
194 struct ip6_rthdr *rthdr;
195
196 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
197
198 switch (rthdr->ip6r_type) {
199 case IPV6_RTHDR_TYPE_0:
200 {
201 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
202 int naddr;
203
204 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
205 return (-1);
206 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
207 if (index < 0 || naddr < index)
208 return (-1);
209 return IPV6_RTHDR_LOOSE;
210 }
211
212 default:
213 return (-1);
214 }
215}