summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/rthdr.c
diff options
context:
space:
mode:
authoritojun <>1999-12-11 08:09:11 +0000
committeritojun <>1999-12-11 08:09:11 +0000
commit4e33952cfed470971b26120bf2844b19653363e0 (patch)
treec03dcd27791457615cdb6435c89123a9594523de /src/lib/libc/net/rthdr.c
parent4f28b045b71f2e358d99dada79f93e6b020cd078 (diff)
downloadopenbsd-4e33952cfed470971b26120bf2844b19653363e0.tar.gz
openbsd-4e33952cfed470971b26120bf2844b19653363e0.tar.bz2
openbsd-4e33952cfed470971b26120bf2844b19653363e0.zip
add inet6_option_* and inet6_rthdr_*.
increase shlib minor.
Diffstat (limited to 'src/lib/libc/net/rthdr.c')
-rw-r--r--src/lib/libc/net/rthdr.c298
1 files changed, 298 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..2dff59668e
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,298 @@
1/* $OpenBSD: rthdr.c,v 1.1 1999/12/11 08:09:11 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 - 1)
51 + sizeof(struct ip6_rthdr0)));
52 default:
53#ifdef DEBUG
54 fprintf(stderr, "inet6_rthdr_space: unknown type(%d)\n", type);
55#endif
56 return(0);
57 }
58}
59
60struct cmsghdr *
61inet6_rthdr_init(bp, type)
62 void *bp;
63 int type;
64{
65 register struct cmsghdr *ch = (struct cmsghdr *)bp;
66 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(ch + 1);
67
68 ch->cmsg_level = IPPROTO_IPV6;
69 ch->cmsg_type = IPV6_RTHDR;
70
71 switch(type) {
72 case IPV6_RTHDR_TYPE_0:
73 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0) - sizeof(struct in6_addr));
74 bzero(rthdr, sizeof(struct ip6_rthdr0));
75 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
76 return(ch);
77 default:
78#ifdef DEBUG
79 fprintf(stderr, "inet6_rthdr_init: unknown type(%d)\n", type);
80#endif
81 return(NULL);
82 }
83}
84
85int
86inet6_rthdr_add(cmsg, addr, flags)
87 struct cmsghdr *cmsg;
88 const struct in6_addr *addr;
89 u_int flags;
90{
91 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
92
93 switch(rthdr->ip6r_type) {
94 case IPV6_RTHDR_TYPE_0:
95 {
96 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
97 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
98#ifdef DEBUG
99 fprintf(stderr, "inet6_rthdr_add: unsupported flag(%d)\n", flags);
100#endif
101 return(-1);
102 }
103 if (rt0->ip6r0_segleft == 23) {
104#ifdef DEBUG
105 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
106#endif
107 return(-1);
108 }
109 if (flags == IPV6_RTHDR_STRICT) {
110 int c, b;
111 c = rt0->ip6r0_segleft / 8;
112 b = rt0->ip6r0_segleft % 8;
113 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
114 }
115 rt0->ip6r0_segleft++;
116 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
117 sizeof(struct in6_addr));
118 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
119 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
120 break;
121 }
122 default:
123#ifdef DEBUG
124 fprintf(stderr, "inet6_rthdr_add: unknown type(%d)\n",
125 rthdr->ip6r_type);
126#endif
127 return(-1);
128 }
129
130 return(0);
131}
132
133int
134inet6_rthdr_lasthop(cmsg, flags)
135 struct cmsghdr *cmsg;
136 unsigned int flags;
137{
138 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
139
140 switch(rthdr->ip6r_type) {
141 case IPV6_RTHDR_TYPE_0:
142 {
143 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
144 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
145#ifdef DEBUG
146 fprintf(stderr, "inet6_rthdr_lasthop: unsupported flag(%d)\n", flags);
147#endif
148 return(-1);
149 }
150 if (rt0->ip6r0_segleft > 23) {
151#ifdef DEBUG
152 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
153#endif
154 return(-1);
155 }
156 if (flags == IPV6_RTHDR_STRICT) {
157 int c, b;
158 c = rt0->ip6r0_segleft / 8;
159 b = rt0->ip6r0_segleft % 8;
160 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
161 }
162 break;
163 }
164 default:
165#ifdef DEBUG
166 fprintf(stderr, "inet6_rthdr_lasthop: unknown type(%d)\n",
167 rthdr->ip6r_type);
168#endif
169 return(-1);
170 }
171
172 return(0);
173}
174
175#if 0
176int
177inet6_rthdr_reverse(in, out)
178 const struct cmsghdr *in;
179 struct cmsghdr *out;
180{
181#ifdef DEBUG
182 fprintf(stderr, "inet6_rthdr_reverse: not implemented yet\n");
183#endif
184 return -1;
185}
186#endif
187
188int
189inet6_rthdr_segments(cmsg)
190 const struct cmsghdr *cmsg;
191{
192 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
193
194 switch(rthdr->ip6r_type) {
195 case IPV6_RTHDR_TYPE_0:
196 {
197 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
198
199 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
200#ifdef DEBUG
201 fprintf(stderr, "inet6_rthdr_segments: invalid size(%d)\n",
202 rt0->ip6r0_len);
203#endif
204 return -1;
205 }
206
207 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
208 }
209
210 default:
211#ifdef DEBUG
212 fprintf(stderr, "inet6_rthdr_segments: unknown type(%d)\n",
213 rthdr->ip6r_type);
214#endif
215 return -1;
216 }
217}
218
219struct in6_addr *
220inet6_rthdr_getaddr(cmsg, index)
221 struct cmsghdr *cmsg;
222 int index;
223{
224 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
225
226 switch(rthdr->ip6r_type) {
227 case IPV6_RTHDR_TYPE_0:
228 {
229 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
230 int naddr;
231
232 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
233#ifdef DEBUG
234 fprintf(stderr, "inet6_rthdr_getaddr: invalid size(%d)\n",
235 rt0->ip6r0_len);
236#endif
237 return NULL;
238 }
239 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
240 if (index <= 0 || naddr < index) {
241#ifdef DEBUG
242 fprintf(stderr, "inet6_rthdr_getaddr: invalid index(%d)\n", index);
243#endif
244 return NULL;
245 }
246 return &rt0->ip6r0_addr[index - 1];
247 }
248
249 default:
250#ifdef DEBUG
251 fprintf(stderr, "inet6_rthdr_getaddr: unknown type(%d)\n",
252 rthdr->ip6r_type);
253#endif
254 return NULL;
255 }
256}
257
258int
259inet6_rthdr_getflags(cmsg, index)
260 const struct cmsghdr *cmsg;
261 int index;
262{
263 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
264
265 switch(rthdr->ip6r_type) {
266 case IPV6_RTHDR_TYPE_0:
267 {
268 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
269 int naddr;
270
271 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
272#ifdef DEBUG
273 fprintf(stderr, "inet6_rthdr_getflags: invalid size(%d)\n",
274 rt0->ip6r0_len);
275#endif
276 return -1;
277 }
278 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
279 if (index < 0 || naddr < index) {
280#ifdef DEBUG
281 fprintf(stderr, "inet6_rthdr_getflags: invalid index(%d)\n", index);
282#endif
283 return -1;
284 }
285 if (rt0->ip6r0_slmap[index / 8] & (0x80 >> (index % 8)))
286 return IPV6_RTHDR_STRICT;
287 else
288 return IPV6_RTHDR_LOOSE;
289 }
290
291 default:
292#ifdef DEBUG
293 fprintf(stderr, "inet6_rthdr_getflags: unknown type(%d)\n",
294 rthdr->ip6r_type);
295#endif
296 return -1;
297 }
298}