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.c228
1 files changed, 228 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..366ca9e6ba
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,228 @@
1/* $OpenBSD: rthdr.c,v 1.6 2003/06/11 02:54:02 itojun 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(type, seg)
44 int type, seg;
45{
46 switch (type) {
47 case IPV6_RTHDR_TYPE_0:
48 if (seg < 1 || seg > 23)
49 return (0);
50 return (CMSG_SPACE(sizeof(struct in6_addr) * seg +
51 sizeof(struct ip6_rthdr0)));
52 default:
53 return (0);
54 }
55}
56
57struct cmsghdr *
58inet6_rthdr_init(bp, type)
59 void *bp;
60 int type;
61{
62 struct cmsghdr *ch = (struct cmsghdr *)bp;
63 struct ip6_rthdr *rthdr;
64
65 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
66
67 ch->cmsg_level = IPPROTO_IPV6;
68 ch->cmsg_type = IPV6_RTHDR;
69
70 switch (type) {
71 case IPV6_RTHDR_TYPE_0:
72 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0));
73 bzero(rthdr, sizeof(struct ip6_rthdr0));
74 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
75 return (ch);
76 default:
77 return (NULL);
78 }
79}
80
81int
82inet6_rthdr_add(cmsg, addr, flags)
83 struct cmsghdr *cmsg;
84 const struct in6_addr *addr;
85 u_int flags;
86{
87 struct ip6_rthdr *rthdr;
88
89 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
90
91 switch (rthdr->ip6r_type) {
92 case IPV6_RTHDR_TYPE_0:
93 {
94 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
95 if (flags != IPV6_RTHDR_LOOSE)
96 return (-1);
97 if (rt0->ip6r0_segleft == 23)
98 return (-1);
99 rt0->ip6r0_segleft++;
100 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
101 sizeof(struct in6_addr));
102 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
103 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
104 break;
105 }
106 default:
107 return (-1);
108 }
109
110 return (0);
111}
112
113int
114inet6_rthdr_lasthop(cmsg, flags)
115 struct cmsghdr *cmsg;
116 unsigned int flags;
117{
118 struct ip6_rthdr *rthdr;
119
120 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
121
122 switch (rthdr->ip6r_type) {
123 case IPV6_RTHDR_TYPE_0:
124 {
125 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
126 if (flags != IPV6_RTHDR_LOOSE)
127 return (-1);
128 if (rt0->ip6r0_segleft > 23)
129 return (-1);
130 break;
131 }
132 default:
133 return (-1);
134 }
135
136 return (0);
137}
138
139#if 0
140int
141inet6_rthdr_reverse(in, out)
142 const struct cmsghdr *in;
143 struct cmsghdr *out;
144{
145
146 return (-1);
147}
148#endif
149
150int
151inet6_rthdr_segments(cmsg)
152 const struct cmsghdr *cmsg;
153{
154 struct ip6_rthdr *rthdr;
155
156 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
157
158 switch (rthdr->ip6r_type) {
159 case IPV6_RTHDR_TYPE_0:
160 {
161 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
162
163 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
164 return (-1);
165
166 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
167 }
168
169 default:
170 return (-1);
171 }
172}
173
174struct in6_addr *
175inet6_rthdr_getaddr(cmsg, index)
176 struct cmsghdr *cmsg;
177 int index;
178{
179 struct ip6_rthdr *rthdr;
180
181 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
182
183 switch (rthdr->ip6r_type) {
184 case IPV6_RTHDR_TYPE_0:
185 {
186 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
187 int naddr;
188
189 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
190 return NULL;
191 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
192 if (index <= 0 || naddr < index)
193 return NULL;
194 return ((struct in6_addr *)(rt0 + 1)) + index;
195 }
196
197 default:
198 return NULL;
199 }
200}
201
202int
203inet6_rthdr_getflags(cmsg, index)
204 const struct cmsghdr *cmsg;
205 int index;
206{
207 struct ip6_rthdr *rthdr;
208
209 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
210
211 switch (rthdr->ip6r_type) {
212 case IPV6_RTHDR_TYPE_0:
213 {
214 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
215 int naddr;
216
217 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
218 return (-1);
219 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
220 if (index < 0 || naddr < index)
221 return (-1);
222 return IPV6_RTHDR_LOOSE;
223 }
224
225 default:
226 return (-1);
227 }
228}