2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netinet/ip6.h>
43 inet6_rthdr_space(type, seg)
47 case IPV6_RTHDR_TYPE_0:
48 if (seg < 1 || seg > 23)
50 return(CMSG_SPACE(sizeof(struct in6_addr) * (seg - 1)
51 + sizeof(struct ip6_rthdr0)));
54 fprintf(stderr, "inet6_rthdr_space: unknown type(%d)\n", type);
61 inet6_rthdr_init(bp, type)
65 register struct cmsghdr *ch = (struct cmsghdr *)bp;
66 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(ch + 1);
68 ch->cmsg_level = IPPROTO_IPV6;
69 ch->cmsg_type = IPV6_RTHDR;
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;
79 fprintf(stderr, "inet6_rthdr_init: unknown type(%d)\n", type);
86 inet6_rthdr_add(cmsg, addr, flags)
88 const struct in6_addr *addr;
91 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
93 switch(rthdr->ip6r_type) {
94 case IPV6_RTHDR_TYPE_0:
96 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
97 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
99 fprintf(stderr, "inet6_rthdr_add: unsupported flag(%d)\n", flags);
103 if (rt0->ip6r0_segleft == 23) {
105 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
109 if (flags == IPV6_RTHDR_STRICT) {
111 c = rt0->ip6r0_segleft / 8;
112 b = rt0->ip6r0_segleft % 8;
113 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
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);
124 fprintf(stderr, "inet6_rthdr_add: unknown type(%d)\n",
134 inet6_rthdr_lasthop(cmsg, flags)
135 struct cmsghdr *cmsg;
138 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
140 switch(rthdr->ip6r_type) {
141 case IPV6_RTHDR_TYPE_0:
143 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
144 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
146 fprintf(stderr, "inet6_rthdr_lasthop: unsupported flag(%d)\n", flags);
150 if (rt0->ip6r0_segleft > 23) {
152 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
156 if (flags == IPV6_RTHDR_STRICT) {
158 c = rt0->ip6r0_segleft / 8;
159 b = rt0->ip6r0_segleft % 8;
160 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
166 fprintf(stderr, "inet6_rthdr_lasthop: unknown type(%d)\n",
177 inet6_rthdr_reverse(in, out)
178 const struct cmsghdr *in;
182 fprintf(stderr, "inet6_rthdr_reverse: not implemented yet\n");
189 inet6_rthdr_segments(cmsg)
190 const struct cmsghdr *cmsg;
192 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
194 switch(rthdr->ip6r_type) {
195 case IPV6_RTHDR_TYPE_0:
197 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
199 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
201 fprintf(stderr, "inet6_rthdr_segments: invalid size(%d)\n",
207 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
212 fprintf(stderr, "inet6_rthdr_segments: unknown type(%d)\n",
220 inet6_rthdr_getaddr(cmsg, index)
221 struct cmsghdr *cmsg;
224 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
226 switch(rthdr->ip6r_type) {
227 case IPV6_RTHDR_TYPE_0:
229 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
232 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
234 fprintf(stderr, "inet6_rthdr_getaddr: invalid size(%d)\n",
239 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
240 if (index <= 0 || naddr < index) {
242 fprintf(stderr, "inet6_rthdr_getaddr: invalid index(%d)\n", index);
246 return &rt0->ip6r0_addr[index - 1];
251 fprintf(stderr, "inet6_rthdr_getaddr: unknown type(%d)\n",
259 inet6_rthdr_getflags(cmsg, index)
260 const struct cmsghdr *cmsg;
263 register struct ip6_rthdr *rthdr = (struct ip6_rthdr *)(cmsg + 1);
265 switch(rthdr->ip6r_type) {
266 case IPV6_RTHDR_TYPE_0:
268 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
271 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
273 fprintf(stderr, "inet6_rthdr_getflags: invalid size(%d)\n",
278 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
279 if (index < 0 || naddr < index) {
281 fprintf(stderr, "inet6_rthdr_getflags: invalid index(%d)\n", index);
285 if (rt0->ip6r0_slmap[index / 8] & (0x80 >> (index % 8)))
286 return IPV6_RTHDR_STRICT;
288 return IPV6_RTHDR_LOOSE;
293 fprintf(stderr, "inet6_rthdr_getflags: unknown type(%d)\n",