1 /* $KAME: rthdr.c,v 1.8 2001/08/20 02:32:40 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
31 * $FreeBSD: src/lib/libc/net/rthdr.c,v 1.2.2.1 2002/04/28 05:40:24 suz Exp $
32 * $DragonFly: src/lib/libcr/net/Attic/rthdr.c,v 1.2 2003/06/17 04:26:44 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <netinet/ip6.h>
46 inet6_rthdr_space(type, seg)
50 case IPV6_RTHDR_TYPE_0:
51 if (seg < 1 || seg > 23)
53 return(CMSG_SPACE(sizeof(struct in6_addr) * (seg - 1)
54 + sizeof(struct ip6_rthdr0)));
57 fprintf(stderr, "inet6_rthdr_space: unknown type(%d)\n", type);
64 inet6_rthdr_init(bp, type)
68 register struct cmsghdr *ch = (struct cmsghdr *)bp;
69 register struct ip6_rthdr *rthdr;
71 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
73 ch->cmsg_level = IPPROTO_IPV6;
74 ch->cmsg_type = IPV6_RTHDR;
77 case IPV6_RTHDR_TYPE_0:
78 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0) - sizeof(struct in6_addr));
79 bzero(rthdr, sizeof(struct ip6_rthdr0));
80 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
84 fprintf(stderr, "inet6_rthdr_init: unknown type(%d)\n", type);
91 inet6_rthdr_add(cmsg, addr, flags)
93 const struct in6_addr *addr;
96 register struct ip6_rthdr *rthdr;
98 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
100 switch(rthdr->ip6r_type) {
101 case IPV6_RTHDR_TYPE_0:
103 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
104 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
106 fprintf(stderr, "inet6_rthdr_add: unsupported flag(%d)\n", flags);
110 if (rt0->ip6r0_segleft == 23) {
112 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
116 if (flags == IPV6_RTHDR_STRICT) {
118 c = rt0->ip6r0_segleft / 8;
119 b = rt0->ip6r0_segleft % 8;
120 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
122 rt0->ip6r0_segleft++;
123 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
124 sizeof(struct in6_addr));
125 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
126 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
131 fprintf(stderr, "inet6_rthdr_add: unknown type(%d)\n",
141 inet6_rthdr_lasthop(cmsg, flags)
142 struct cmsghdr *cmsg;
145 register struct ip6_rthdr *rthdr;
147 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
149 switch(rthdr->ip6r_type) {
150 case IPV6_RTHDR_TYPE_0:
152 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
153 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
155 fprintf(stderr, "inet6_rthdr_lasthop: unsupported flag(%d)\n", flags);
159 if (rt0->ip6r0_segleft > 23) {
161 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
165 if (flags == IPV6_RTHDR_STRICT) {
167 c = rt0->ip6r0_segleft / 8;
168 b = rt0->ip6r0_segleft % 8;
169 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
175 fprintf(stderr, "inet6_rthdr_lasthop: unknown type(%d)\n",
186 inet6_rthdr_reverse(in, out)
187 const struct cmsghdr *in;
191 fprintf(stderr, "inet6_rthdr_reverse: not implemented yet\n");
198 inet6_rthdr_segments(cmsg)
199 const struct cmsghdr *cmsg;
201 register struct ip6_rthdr *rthdr;
203 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
205 switch(rthdr->ip6r_type) {
206 case IPV6_RTHDR_TYPE_0:
208 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
210 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
212 fprintf(stderr, "inet6_rthdr_segments: invalid size(%d)\n",
218 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
223 fprintf(stderr, "inet6_rthdr_segments: unknown type(%d)\n",
231 inet6_rthdr_getaddr(cmsg, idx)
232 struct cmsghdr *cmsg;
235 register struct ip6_rthdr *rthdr;
237 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
239 switch(rthdr->ip6r_type) {
240 case IPV6_RTHDR_TYPE_0:
242 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
245 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
247 fprintf(stderr, "inet6_rthdr_getaddr: invalid size(%d)\n",
252 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
253 if (idx <= 0 || naddr < idx) {
255 fprintf(stderr, "inet6_rthdr_getaddr: invalid idx(%d)\n", idx);
259 return &rt0->ip6r0_addr[idx - 1];
264 fprintf(stderr, "inet6_rthdr_getaddr: unknown type(%d)\n",
272 inet6_rthdr_getflags(cmsg, idx)
273 const struct cmsghdr *cmsg;
276 register struct ip6_rthdr *rthdr;
278 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
280 switch(rthdr->ip6r_type) {
281 case IPV6_RTHDR_TYPE_0:
283 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
286 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
288 fprintf(stderr, "inet6_rthdr_getflags: invalid size(%d)\n",
293 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
294 if (idx < 0 || naddr < idx) {
296 fprintf(stderr, "inet6_rthdr_getflags: invalid idx(%d)\n", idx);
300 if (rt0->ip6r0_slmap[idx / 8] & (0x80 >> (idx % 8)))
301 return IPV6_RTHDR_STRICT;
303 return IPV6_RTHDR_LOOSE;
308 fprintf(stderr, "inet6_rthdr_getflags: unknown type(%d)\n",