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