8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libsocket / inet / inet6_rthdr.c
blob4134f8a196e1f0b6d81a592c879dc8a0a9c5aab7
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2003 Sun Microsystems, Inc.
24 * All rights reserved. Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This code is conformant to revision 7 of 2292bis. Some of these functions
31 * were provided (named inet6_rthdr_) in a very similar form in RFC 2292.
32 * The RFC 2292 variants are not supported.
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <netinet/ip6.h>
43 #include <unistd.h>
44 #include <errno.h>
46 #define MAX_RTHDR0_SEGMENTS 127
49 * Return amount of space needed to hold N segments for the specified
50 * routing type. Does NOT include space for cmsghdr.
52 socklen_t
53 inet6_rth_space(int type, int segments)
55 if (type != IPV6_RTHDR_TYPE_0 || segments < 0 ||
56 segments > MAX_RTHDR0_SEGMENTS)
57 return (0);
59 return (sizeof (struct ip6_rthdr0) +
60 segments * sizeof (struct in6_addr));
64 * Initializes rthdr structure. Verifies the segments against the length of
65 * the buffer.
66 * Note that a routing header can only hold 127 segments since the length field
67 * in the header is just a byte.
69 void *
70 inet6_rth_init(void *bp, socklen_t bp_len, int type, int segments)
72 struct ip6_rthdr0 *rthdr;
74 if (type != IPV6_RTHDR_TYPE_0 || segments < 0 ||
75 segments > MAX_RTHDR0_SEGMENTS)
76 return (NULL);
78 if (bp_len < sizeof (struct ip6_rthdr0) +
79 segments * sizeof (struct in6_addr))
80 return (NULL);
82 rthdr = (struct ip6_rthdr0 *)bp;
83 rthdr->ip6r0_nxt = 0;
84 rthdr->ip6r0_len = (segments * 2);
85 rthdr->ip6r0_type = type;
86 rthdr->ip6r0_segleft = 0; /* Incremented by rthdr_add */
87 *(uint32_t *)&rthdr->ip6r0_reserved = 0;
88 return (bp);
92 * Add one more address to the routing header. Fails when there is no more
93 * room.
95 int
96 inet6_rth_add(void *bp, const struct in6_addr *addr)
98 struct ip6_rthdr0 *rthdr;
99 struct in6_addr *addrs;
101 rthdr = (struct ip6_rthdr0 *)bp;
102 if ((rthdr->ip6r0_segleft + 1) * 2 > rthdr->ip6r0_len) {
103 /* Not room for one more */
104 return (-1);
106 addrs = (struct in6_addr *)((char *)rthdr + sizeof (*rthdr));
107 addrs[rthdr->ip6r0_segleft++] = *addr;
108 return (0);
112 * Reverse a source route. Both arguments can point to the same buffer.
115 inet6_rth_reverse(const void *in, void *out)
117 struct ip6_rthdr0 *rtin, *rtout;
118 int i, segments;
119 struct in6_addr tmp;
120 struct in6_addr *rtout_addrs;
121 struct in6_addr *rtin_addrs;
123 rtin = (struct ip6_rthdr0 *)in;
124 rtout = (struct ip6_rthdr0 *)out;
126 if (rtout->ip6r0_type != 0 || rtin->ip6r0_type != 0 ||
127 rtout->ip6r0_len > MAX_RTHDR0_SEGMENTS * 2 ||
128 rtin->ip6r0_len > MAX_RTHDR0_SEGMENTS * 2 ||
129 rtout->ip6r0_len != rtin->ip6r0_len)
130 return (-1);
132 segments = rtin->ip6r0_len / 2;
133 rtout_addrs = (struct in6_addr *)((char *)rtout + sizeof (*rtout));
134 rtin_addrs = (struct in6_addr *)((char *)rtin + sizeof (*rtin));
135 for (i = 0; i < (segments + 1)/2; i++) {
136 tmp = rtin_addrs[i];
137 rtout_addrs[i] = rtin_addrs[segments - 1 - i];
138 rtout_addrs[segments - 1 - i] = tmp;
140 rtout->ip6r0_segleft = segments;
141 return (0);
145 * Return the number of segments in the routing header.
148 inet6_rth_segments(const void *bp)
150 struct ip6_rthdr0 *rthdr;
152 rthdr = (struct ip6_rthdr0 *)bp;
153 if (rthdr->ip6r0_type == 0) {
154 if (rthdr->ip6r0_len > MAX_RTHDR0_SEGMENTS * 2) {
155 return (-1);
156 } else {
157 return (rthdr->ip6r0_len / 2);
159 } else {
160 return (-1);
165 * Return a pointer to an element in the source route.
166 * This uses the C convention for index [0, size-1].
168 struct in6_addr *
169 inet6_rth_getaddr(const void *bp, int index)
171 struct ip6_rthdr0 *rthdr;
172 struct in6_addr *rv;
174 rthdr = (struct ip6_rthdr0 *)bp;
175 if (index >= rthdr->ip6r0_len/2 || index < 0)
176 return (NULL);
178 rv = (struct in6_addr *)((char *)rthdr + sizeof (*rthdr));
179 return (&rv[index]);