summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoritojun <>2006-12-09 01:12:28 +0000
committeritojun <>2006-12-09 01:12:28 +0000
commit4a3ae6fed825c2b6e0f6f3e8985a59c12fced6fa (patch)
tree7f8ed06527d0944b778d808c1929e52070bfc74d
parent5cdcbef9e2b8e7df629a9a6a32f24581308e0c27 (diff)
downloadopenbsd-4a3ae6fed825c2b6e0f6f3e8985a59c12fced6fa.tar.gz
openbsd-4a3ae6fed825c2b6e0f6f3e8985a59c12fced6fa.tar.bz2
openbsd-4a3ae6fed825c2b6e0f6f3e8985a59c12fced6fa.zip
switch IPv6 advanced API from RFC2292 to RFC3542 (2292 is superseded by 3542).
the kernel still handles RFC2292 set/getsockopts, so that compiled binary has no trouble running. userland sees RFC3542 symbols only on header file so new code has to use RFC3542 API. bump libc shlib minor for function additions. tested on i386/amd64 by jmc, i386 by brad. checked by deraadt.
-rw-r--r--src/lib/libc/net/Makefile.inc14
-rw-r--r--src/lib/libc/net/inet6_opt_init.3336
-rw-r--r--src/lib/libc/net/inet6_option_space.37
-rw-r--r--src/lib/libc/net/inet6_rth_space.3220
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.37
-rw-r--r--src/lib/libc/net/ip6opt.c227
-rw-r--r--src/lib/libc/net/rthdr.c165
7 files changed, 971 insertions, 5 deletions
diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc
index db2738f868..39d441a96a 100644
--- a/src/lib/libc/net/Makefile.inc
+++ b/src/lib/libc/net/Makefile.inc
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile.inc,v 1.42 2005/10/02 14:48:48 jmc Exp $ 1# $OpenBSD: Makefile.inc,v 1.43 2006/12/09 01:12:28 itojun Exp $
2 2
3# net sources 3# net sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net
@@ -31,6 +31,7 @@ MAN+= byteorder.3 ethers.3 gai_strerror.3 getaddrinfo.3 gethostbyname.3 \
31 getifaddrs.3 getnameinfo.3 getnetent.3 getprotoent.3 \ 31 getifaddrs.3 getnameinfo.3 getnetent.3 getprotoent.3 \
32 getrrsetbyname.3 getservent.3 if_indextoname.3 inet.3 \ 32 getrrsetbyname.3 getservent.3 if_indextoname.3 inet.3 \
33 inet_net.3 inet6_option_space.3 inet6_rthdr_space.3 \ 33 inet_net.3 inet6_option_space.3 inet6_rthdr_space.3 \
34 inet6_opt_init.3 inet6_rth_space.3 \
34 ipx.3 link_addr.3 net_addrcmp.3 \ 35 ipx.3 link_addr.3 net_addrcmp.3 \
35 rcmd.3 rcmdsh.3 resolver.3 36 rcmd.3 rcmdsh.3 resolver.3
36 37
@@ -88,3 +89,14 @@ MLINKS+=inet6_rthdr_space.3 inet6_rthdr_init.3 \
88 inet6_rthdr_space.3 inet6_rthdr_segments.3 \ 89 inet6_rthdr_space.3 inet6_rthdr_segments.3 \
89 inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \ 90 inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \
90 inet6_rthdr_space.3 inet6_rthdr_getflags.3 91 inet6_rthdr_space.3 inet6_rthdr_getflags.3
92MLINKS+=inet6_opt_init.3 inet6_opt_append.3 \
93 inet6_opt_init.3 inet6_opt_finish.3 \
94 inet6_opt_init.3 inet6_opt_set_val.3 \
95 inet6_opt_init.3 inet6_opt_next.3 \
96 inet6_opt_init.3 inet6_opt_find.3 \
97 inet6_opt_init.3 inet6_opt_get_val.3
98MLINKS+=inet6_rth_space.3 inet6_rth_init.3 \
99 inet6_rth_space.3 inet6_rth_add.3 \
100 inet6_rth_space.3 inet6_rth_reverse.3 \
101 inet6_rth_space.3 inet6_rth_segments.3 \
102 inet6_rth_space.3 inet6_rth_getaddr.3 \
diff --git a/src/lib/libc/net/inet6_opt_init.3 b/src/lib/libc/net/inet6_opt_init.3
new file mode 100644
index 0000000000..a97eb0f28b
--- /dev/null
+++ b/src/lib/libc/net/inet6_opt_init.3
@@ -0,0 +1,336 @@
1.\" $OpenBSD: inet6_opt_init.3,v 1.1 2006/12/09 01:12:28 itojun Exp $
2.\" $KAME: inet6_opt_init.3,v 1.7 2004/12/27 05:08:23 itojun Exp $
3.\"
4.\" Copyright (C) 2004 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.Dd December 23, 2004
32.Dt INET6_OPT_INIT 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_opt_init ,
37.Nm inet6_opt_append ,
38.Nm inet6_opt_finish ,
39.Nm inet6_opt_set_val ,
40.Nm inet6_opt_next ,
41.Nm inet6_opt_find ,
42.Nm inet6_opt_get_val
43.Nd IPv6 Hop-by-Hop and Destination Options manipulation
44.\"
45.Sh SYNOPSIS
46.In netinet/in.h
47.Ft "int"
48.Fn inet6_opt_init "void *extbuf" "socklen_t extlen"
49.Ft "int"
50.Fn inet6_opt_append "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t type" "socklen_t len" "u_int8_t align" "void **databufp"
51.Ft "int"
52.Fn inet6_opt_finish "void *extbuf" "socklen_t extlen" "int offset"
53.Ft "int"
54.Fn inet6_opt_set_val "void *databuf" "int offset" "void *val" "socklen_t vallen"
55.Ft "int"
56.Fn inet6_opt_next "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t *typep" "socklen_t *lenp" "void **databufp"
57.Ft "int"
58.Fn inet6_opt_find "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t type" "socklen_t *lenp" "void **databufp"
59.Ft "int"
60.Fn inet6_opt_get_val "void *databuf" "socklen_t offset" "void *val" "socklen_t vallen"
61.\"
62.Sh DESCRIPTION
63Building and parsing the Hop-by-Hop and Destination options is
64complicated.
65The advanced sockets API defines a set of functions to
66help applications create and manipulate Hop-by-Hope and Destination
67options.
68.\"This man page describes the functions specified in
69.\"IETF Draft RFC3542 while the
70.\".Xr inet6_options_space 3
71.\"man page documents the functions defined in RFC 2292.
72.\"It is expected
73.\"that this set of functions will supersede those in RFC 2292 but for
74.\"the time being both APIs are retained.
75These functions use the
76formatting rules specified in Appendix B in RFC2460, i.e., that the
77largest field is placed last in the option.
78The function prototypes
79for these functions are all contained in the header file
80.Aq netinet/in.h .
81.\"
82.Ss inet6_opt_init
83The
84.Fn inet6_opt_init
85function
86returns the number of bytes needed for an empty
87extension header, one without any options.
88If the
89.Va extbuf
90argument points to a valid section of memory
91then the
92.Fn inet6_opt_init
93function also initializes the extension header's length field.
94When attempting to initialize an extension buffer passed in the
95.Va extbuf argument
96.Fa extlen
97must be a positive multiple of 8 or else the function fails and
98returns \-1 to the caller.
99.\"
100.Ss inet6_opt_append
101The
102.Fn inet6_opt_append
103function can perform to different jobs.
104When a valid
105.Fa extbuf
106argument is supplied it appends an option to the extension buffer and
107returns the updated total length as well as a pointer to the newly
108created option in
109.Fa databufp .
110If the value
111of
112.Fa extbuf
113is
114.Dv NULL
115then the
116.Fn inet6_opt_append function only reports what the total length would
117be if the option were actually appended.
118The
119.Fa len
120and
121.Fa align
122arguments specify the length of the option and the required data
123alignment which must be used when appending the option.
124The
125.Fa offset
126argument should be the length returned by the
127.Fn inet6_opt_init
128function or a previous call to
129.Fn inet6_opt_append .
130.Pp
131The
132.Fa type
133argument is the 8-bit option type.
134.Pp
135After
136.Fn inet6_opt_append
137has been called, the application can use the buffer pointed to by
138.Fa databufp
139directly, or use
140.Fn inet6_opt_set_val
141to specify the data to be contained in the option.
142.Pp
143Option types of
144.Li 0
145and
146.Li 1
147are reserved for the
148.Li Pad1
149and
150.Li PadN
151options.
152All other values from 2 through 255 may be used by applications.
153.Pp
154The length of the option data is contained in an 8-bit value and so
155may contain any value from 0 through 255.
156.Pp
157The
158.Fa align
159parameter must have a value of 1, 2, 4, or 8 and cannot exceed the
160value of
161.Fa len .
162The alignment values represent no alignment, 16 bit, 32 bit and 64 bit
163alignments respectively.
164.\"
165.Ss inet6_opt_finish
166The
167.Fn inet6_opt_finish
168calculates the final padding necessary to make the extension header a
169multiple of 8 bytes, as required by the IPv6 extension header
170specification, and returns the extension header's updated total
171length.
172The
173.Fa offset
174argument should be the length returned by
175.Fn inet6_opt_init
176or
177.Fn inet6_opt_append .
178When
179.Fa extbuf
180is not
181.Dv NULL
182the function also sets up the appropriate padding bytes by inserting a
183Pad1 or PadN option of the proper length.
184.Pp
185If the extension header is too small to contain the proper padding
186then an error of \-1 is returned to the caller.
187.\"
188.Ss inet6_opt_set_val
189The
190.Fn inet6_opt_set_val
191function inserts data items of various sizes into the data portion of
192the option.
193The
194.Fa databuf
195argument is a pointer to memory that was returned by the
196.Fn inet6_opt_append
197call and the
198.Fa offset argument specifies where the option should be placed in the
199data buffer.
200The
201.Fa val
202argument points to an area of memory containing the data to be
203inserted into the extension header, and the
204.Fa vallen
205argument indicates how much data to copy.
206.Pp
207The caller should ensure that each field is aligned on its natural
208boundaries as described in Appendix B of RFC2460.
209.Pp
210The function returns the offset for the next field which is calculated as
211.Fa offset
212+
213.Fa vallen
214and is used when composing options with multiple fields.
215.\"
216.Ss inet6_opt_next
217The
218.Fn inet6_opt_next
219function parses received extension headers.
220The
221.Fa extbuf
222and
223.Fa extlen
224arguments specify the location and length of the extension header
225being parsed.
226The
227.Fa offset
228argument should either be zero, for the first option, or the length value
229returned by a previous call to
230.Fn inet6_opt_next
231or
232.Fn inet6_opt_find .
233The return value specifies the position where to continue scanning the
234extension buffer.
235The option is returned in the arguments
236.Fa typep , lenp ,
237and
238.Fa databufp .
239.Fa typep, lenp,
240and
241.Fa databufp
242point to the 8-bit option type, the 8-bit option length and the option
243data respectively.
244This function does not return any PAD1 or PADN options.
245When an error occurs or there are no more options the return
246value is \-1.
247.\"
248.Ss inet6_opt_find
249The
250.Fn inet6_opt_find
251function searches the extension buffer for a particular option type,
252passed in through the
253.Fa type
254argument.
255If the option is found then the
256.Fa lenp
257and
258.Fa databufp
259arguments are updated to point to the option's length and data
260respectively.
261.Fa extbuf
262and
263.Fa extlen
264must point to a valid extension buffer and give its length.
265The
266.Fa offset
267argument can be used to search from a location anywhere in the
268extension header.
269.Ss inet6_opt_get_val
270The
271.Fn inet6_opt_get_val
272function extracts data items of various sizes in the data portion of
273the option.
274The
275.Fa databuf
276is a pointer returned by the
277.Fn inet6_opt_next
278or
279.Fn inet6_opt_find
280functions.
281The
282.Fa val
283argument points where the data will be extracted.
284The
285.Fa offset
286argument specifies from where in the data portion of the option the
287value should be extracted; the first byte of option data is specified
288by an offset of zero.
289.Pp
290It is expected that each field is aligned on its natural boundaries as
291described in Appendix B of RFC2460.
292.Pp
293The function returns the offset for the next field
294by calculating
295.Fa offset
296+
297.Fa vallen
298which can be used when extracting option content with multiple fields.
299Robust receivers must verify alignment before calling this function.
300.\"
301.Sh DIAGNOSTICS
302All the functions return
303\-1
304on an error.
305.\"
306.Sh EXAMPLES
307RFC3542 gives comprehensive examples in Section 23.
308.Pp
309KAME also provides examples in the
310.Pa advapitest
311directory of its kit.
312.\"
313.Sh SEE ALSO
314.Rs
315.%A W. Stevens
316.%A M. Thomas
317.%A E. Nordmark
318.%A T. Jinmei
319.%T "Advanced Sockets API for IPv6"
320.%N RFC3542
321.%D October 2002
322.Re
323.Rs
324.%A S. Deering
325.%A R. Hinden
326.%T "Internet Protocol, Version 6 (IPv6) Specification"
327.%N RFC2460
328.%D December 1998
329.Re
330.Sh HISTORY
331The implementation first appeared in KAME advanced networking kit.
332.Sh STANDARDS
333The functions are documented in
334.Dq Advanced Sockets API for IPv6
335.Pq RFC3542 .
336.\"
diff --git a/src/lib/libc/net/inet6_option_space.3 b/src/lib/libc/net/inet6_option_space.3
index 5beec487ac..956cf9d815 100644
--- a/src/lib/libc/net/inet6_option_space.3
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -1,4 +1,4 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.18 2005/01/11 17:45:41 jaredy Exp $ 1.\" $OpenBSD: inet6_option_space.3,v 1.19 2006/12/09 01:12:28 itojun Exp $
2.\" $KAME: inet6_option_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $ 2.\" $KAME: inet6_option_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
3.\" 3.\"
4.\" Copyright (C) 2004 WIDE Project. 4.\" Copyright (C) 2004 WIDE Project.
@@ -70,6 +70,11 @@ All of the prototypes
70for the option functions are defined in the 70for the option functions are defined in the
71.Aq Pa netinet/in.h 71.Aq Pa netinet/in.h
72header file. 72header file.
73.Pp
74RFC 2292 was superseded by RFC 3542.
75Functions described in this document were deprecated.
76See
77.Xr inet6_opt_init 3 .
73.\" 78.\"
74.Ss inet6_option_space 79.Ss inet6_option_space
75In order to determine the amount of space necessary to hold any option 80In order to determine the amount of space necessary to hold any option
diff --git a/src/lib/libc/net/inet6_rth_space.3 b/src/lib/libc/net/inet6_rth_space.3
new file mode 100644
index 0000000000..ab593b202a
--- /dev/null
+++ b/src/lib/libc/net/inet6_rth_space.3
@@ -0,0 +1,220 @@
1.\" $OpenBSD: inet6_rth_space.3,v 1.1 2006/12/09 01:12:28 itojun Exp $
2.\" $KAME: inet6_rth_space.3,v 1.7 2005/01/05 03:00:44 itojun Exp $
3.\"
4.\" Copyright (C) 2004 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.Dd December 24, 2004
32.Dt INET6_RTH_SPACE 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_rth_space ,
37.Nm inet6_rth_init ,
38.Nm inet6_rth_add ,
39.Nm inet6_rth_reverse ,
40.Nm inet6_rth_segments ,
41.Nm inet6_rth_getaddr
42.Nd IPv6 Routing Header Options manipulation
43.\"
44.Sh SYNOPSIS
45.In netinet/in.h
46.Ft socklen_t
47.Fn inet6_rth_space "int" "int"
48.Ft "void *"
49.Fn inet6_rth_init "void *" "socklen_t" "int" "int"
50.Ft int
51.Fn inet6_rth_add "void *" "const struct in6_addr *"
52.Ft int
53.Fn inet6_rth_reverse "const void *" "void *"
54.Ft int
55.Fn inet6_rth_segments "const void *"
56.Ft "struct in6_addr *"
57.Fn inet6_rth_getaddr "const void *" "int"
58.\"
59.Sh DESCRIPTION
60The IPv6 Advanced API, RFC 3542, defines the functions that an
61application calls to build and examine IPv6 Routing headers.
62Routing headers are used to perform source routing in IPv6 networks.
63The RFC uses the word
64.Dq segments
65to describe addresses and that is the term used here as well.
66All of the functions are defined in the header file
67.Aq netinet/in.h .
68The functions described in this manual page all operate
69on routing header structures which are defined in
70.Aq netinet/ip6.h
71but which should not need to be modified outside the use of this API.
72The size and shape of the route header structures may change, so using
73the APIs is a more portable, long term, solution.
74.Pp
75The functions in the API are split into two groups, those that build a
76routing header and those that parse a received routing header.
77We will describe the builder functions followed by the parser functions.
78.Ss inet6_rth_space
79The
80.Fn inet6_rth_space
81function returns the number of bytes required to hold a Routing Header
82of the type, specified in the
83.Fa type
84argument and containing the number of addresses specified in the
85.Fa segments
86argumment.
87When the type is
88.Dv IPV6_RTHDR_TYPE_0
89the number of segments must be from 0 through 127.
90The return value from this function is the number of bytes required to
91store the routing header.
92If the value 0 is returned then either the
93route header type was not recognized or another error occurred.
94.Ss inet6_rth_init
95The
96.Fn inet6_rth_init
97function initializes the pre-allocated buffer pointed to by
98.Fa bp
99to contain a routing header of the specified type.
100The
101.Fa bp_len
102argument is used to verify that the buffer is large enough.
103The caller must allocate the buffer pointed to by bp.
104The necessary buffer size should be determined by calling
105.Fn inet6_rth_space
106described in the previous sections.
107.Pp
108The
109.Fn inet6_rth_init
110function returns a pointer to
111.Fa bp
112on success and
113.Dv NULL
114when there is an error.
115.Ss inet6_rth_add
116The
117.Fn inet6_rth_add
118function adds the IPv6 address pointed to by
119.Fa addr
120to the end of the routing header being constructed.
121.Pp
122A successful addition results in the function returning 0, otherwise
123\-1 is returned.
124.Ss inet6_rth_reverse
125The
126.Fn inet6_rth_reverse
127function takes a routing header, pointed to by the
128argument
129.Fa in ,
130and writes a new routing header into the argument pointed to by
131.Fa out .
132The routing header at that sends datagrams along the reverse of that
133route.
134Both arguments are allowed to point to the same buffer meaning
135that the reversal can occur in place.
136.Pp
137The return value of the function is 0 on success, or \-1 when
138there is an error.
139.\"
140.Pp
141The next set of functions operate on a routing header that the
142application wants to parse.
143In the usual case such a routing header
144is received from the network, although these functions can also be
145used with routing headers that the application itself created.
146.Ss inet6_rth_segments
147The
148.Fn inet6_rth_segments
149function returns the number of segments contained in the
150routing header pointed to by
151.Fa bp .
152The return value is the number of segments contained in the routing
153header, or \-1 if an error occurred.
154It is not an error for 0 to be
155returned as a routing header may contain 0 segments.
156.\"
157.Ss inet6_rth_getaddr
158The
159.Fn inet6_rth_getaddr
160function is used to retrieve a single address from a routing header.
161The
162.Fa index
163is the location in the routing header from which the application wants
164to retrieve an address.
165The
166.Fa index
167parameter must have a value between 0 and one less than the number of
168segments present in the routing header.
169The
170.Fn inet6_rth_segments
171function, described in the last section, should be used to determine
172the total number of segments in the routing header.
173The
174.Fn inet6_rth_getaddr
175function returns a pointer to an IPv6 address on success or
176.Dv NULL
177when an error has occurred.
178.\"
179.Sh DIAGNOSTICS
180The
181.Fn inet6_rth_space
182and
183.Fn inet6_rth_getaddr
184functions return 0 on errors.
185.Pp
186The
187.Fn inet6_rthdr_init
188function returns
189.Dv NULL
190on error.
191The
192.Fn inet6_rth_add
193and
194.Fn inet6_rth_reverse
195functions return 0 on success, or \-1 upon an error.
196.\"
197.Sh EXAMPLES
198RFC 3542 gives extensive examples in Section 21, Appendix B.
199.Pp
200KAME also provides examples in the advapitest directory of its kit.
201.\"
202.Sh SEE ALSO
203.Rs
204.%A W. Stevens
205.%A M. Thomas
206.%A E. Nordmark
207.%A T. Jinmei
208.%T "Advanced Sockets API for IPv6"
209.%N RFC 3542
210.%D May 2003
211.Re
212.Rs
213.%A S. Deering
214.%A R. Hinden
215.%T "Internet Protocol, Version 6 (IPv6) Specification"
216.%N RFC2460
217.%D December 1998
218.Re
219.Sh HISTORY
220The implementation first appeared in KAME advanced networking kit.
diff --git a/src/lib/libc/net/inet6_rthdr_space.3 b/src/lib/libc/net/inet6_rthdr_space.3
index 7c00c42e42..4a0d22843d 100644
--- a/src/lib/libc/net/inet6_rthdr_space.3
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -1,4 +1,4 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.17 2005/01/11 17:45:41 jaredy Exp $ 1.\" $OpenBSD: inet6_rthdr_space.3,v 1.18 2006/12/09 01:12:28 itojun Exp $
2.\" $KAME: inet6_rthdr_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $ 2.\" $KAME: inet6_rthdr_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
3.\" 3.\"
4.\" Copyright (C) 2004 WIDE Project. 4.\" Copyright (C) 2004 WIDE Project.
@@ -88,6 +88,11 @@ Please note that RFC 2292 uses the term
88instead of the term 88instead of the term
89.Dq addresses 89.Dq addresses
90but they are considered equivalent for this manual page. 90but they are considered equivalent for this manual page.
91.Pp
92RFC 2292 was superseded by RFC 3542.
93Functions described in this document were deprecated.
94See
95.Xr inet6_rth_space 3 .
91.\" 96.\"
92.Ss inet6_rthdr_space 97.Ss inet6_rthdr_space
93The 98The
diff --git a/src/lib/libc/net/ip6opt.c b/src/lib/libc/net/ip6opt.c
index d3d68a54bf..b215f9ac3e 100644
--- a/src/lib/libc/net/ip6opt.c
+++ b/src/lib/libc/net/ip6opt.c
@@ -1,4 +1,5 @@
1/* $OpenBSD: ip6opt.c,v 1.3 2006/12/08 21:32:59 itojun Exp $ */ 1/* $OpenBSD: ip6opt.c,v 1.4 2006/12/09 01:12:28 itojun Exp $ */
2/* $KAME: ip6opt.c,v 1.18 2005/06/15 07:11:35 keiichi Exp $ */
2 3
3/* 4/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -103,8 +104,10 @@ inet6_option_append(struct cmsghdr *cmsg, const u_int8_t *typep, int multx,
103 return (-1); 104 return (-1);
104 if (plusy < 0 || plusy > 7) 105 if (plusy < 0 || plusy > 7)
105 return (-1); 106 return (-1);
107#if 0
106 if (typep[0] > 255) 108 if (typep[0] > 255)
107 return (-1); 109 return (-1);
110#endif
108 111
109 /* 112 /*
110 * If this is the first option, allocate space for the 113 * If this is the first option, allocate space for the
@@ -369,3 +372,225 @@ inet6_insert_padopt(u_char *p, int len)
369 return; 372 return;
370 } 373 }
371} 374}
375
376/*
377 * The following functions are defined in RFC3542, which is a successor
378 * of RFC2292.
379 */
380
381int
382inet6_opt_init(void *extbuf, socklen_t extlen)
383{
384 struct ip6_ext *ext = (struct ip6_ext *)extbuf;
385
386 if (extlen < 0 || (extlen % 8))
387 return (-1);
388
389 if (ext) {
390 if (extlen == 0)
391 return (-1);
392 ext->ip6e_len = (extlen >> 3) - 1;
393 }
394
395 return (2); /* sizeof the next and the length fields */
396}
397
398int
399inet6_opt_append(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
400 socklen_t len, u_int8_t align, void **databufp)
401{
402 int currentlen = offset, padlen = 0;
403
404 /*
405 * The option type must have a value from 2 to 255, inclusive.
406 * (0 and 1 are reserved for the Pad1 and PadN options, respectively.)
407 */
408#if 0 /* always false */
409 if (type < 2 || type > 255)
410#else
411 if (type < 2)
412#endif
413 return (-1);
414
415 /*
416 * The option data length must have a value between 0 and 255,
417 * inclusive, and is the length of the option data that follows.
418 */
419 if (len < 0 || len > 255)
420 return (-1);
421
422 /*
423 * The align parameter must have a value of 1, 2, 4, or 8.
424 * The align value can not exceed the value of len.
425 */
426 if (align != 1 && align != 2 && align != 4 && align != 8)
427 return (-1);
428 if (align > len)
429 return (-1);
430
431 /* Calculate the padding length. */
432 currentlen += 2 + len; /* 2 means "type + len" */
433 if (currentlen % align)
434 padlen = align - (currentlen % align);
435
436 /* The option must fit in the extension header buffer. */
437 currentlen += padlen;
438 if (extlen && /* XXX: right? */
439 currentlen > extlen)
440 return (-1);
441
442 if (extbuf) {
443 u_int8_t *optp = (u_int8_t *)extbuf + offset;
444
445 if (padlen == 1) {
446 /* insert a Pad1 option */
447 *optp = IP6OPT_PAD1;
448 optp++;
449 } else if (padlen > 0) {
450 /* insert a PadN option for alignment */
451 *optp++ = IP6OPT_PADN;
452 *optp++ = padlen - 2;
453 memset(optp, 0, padlen - 2);
454 optp += (padlen - 2);
455 }
456
457 *optp++ = type;
458 *optp++ = len;
459
460 *databufp = optp;
461 }
462
463 return (currentlen);
464}
465
466int
467inet6_opt_finish(void *extbuf, socklen_t extlen, int offset)
468{
469 int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;;
470
471 if (extbuf) {
472 u_int8_t *padp;
473 int padlen = updatelen - offset;
474
475 if (updatelen > extlen)
476 return (-1);
477
478 padp = (u_int8_t *)extbuf + offset;
479 if (padlen == 1)
480 *padp = IP6OPT_PAD1;
481 else if (padlen > 0) {
482 *padp++ = IP6OPT_PADN;
483 *padp++ = (padlen - 2);
484 memset(padp, 0, padlen - 2);
485 }
486 }
487
488 return (updatelen);
489}
490
491int
492inet6_opt_set_val(void *databuf, int offset, void *val, socklen_t vallen)
493{
494
495 memcpy((u_int8_t *)databuf + offset, val, vallen);
496 return (offset + vallen);
497}
498
499int
500inet6_opt_next(void *extbuf, socklen_t extlen, int offset, u_int8_t *typep,
501 socklen_t *lenp, void **databufp)
502{
503 u_int8_t *optp, *lim;
504 int optlen;
505
506 /* Validate extlen. XXX: is the variable really necessary?? */
507 if (extlen == 0 || (extlen % 8))
508 return (-1);
509 lim = (u_int8_t *)extbuf + extlen;
510
511 /*
512 * If this is the first time this function called for this options
513 * header, simply return the 1st option.
514 * Otherwise, search the option list for the next option.
515 */
516 if (offset == 0)
517 optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
518 else
519 optp = (u_int8_t *)extbuf + offset;
520
521 /* Find the next option skipping any padding options. */
522 while (optp < lim) {
523 switch(*optp) {
524 case IP6OPT_PAD1:
525 optp++;
526 break;
527 case IP6OPT_PADN:
528 if ((optlen = ip6optlen(optp, lim)) == 0)
529 goto optend;
530 optp += optlen;
531 break;
532 default: /* found */
533 if ((optlen = ip6optlen(optp, lim)) == 0)
534 goto optend;
535 *typep = *optp;
536 *lenp = optlen - 2;
537 *databufp = optp + 2;
538 return (optp + optlen - (u_int8_t *)extbuf);
539 }
540 }
541
542 optend:
543 *databufp = NULL; /* for safety */
544 return (-1);
545}
546
547int
548inet6_opt_find(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
549 socklen_t *lenp, void **databufp)
550{
551 u_int8_t *optp, *lim;
552 int optlen;
553
554 /* Validate extlen. XXX: is the variable really necessary?? */
555 if (extlen == 0 || (extlen % 8))
556 return (-1);
557 lim = (u_int8_t *)extbuf + extlen;
558
559 /*
560 * If this is the first time this function called for this options
561 * header, simply return the 1st option.
562 * Otherwise, search the option list for the next option.
563 */
564 if (offset == 0)
565 optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
566 else
567 optp = (u_int8_t *)extbuf + offset;
568
569 /* Find the specified option */
570 while (optp < lim) {
571 if ((optlen = ip6optlen(optp, lim)) == 0)
572 goto optend;
573
574 if (*optp == type) { /* found */
575 *lenp = optlen - 2;
576 *databufp = optp + 2;
577 return (optp + optlen - (u_int8_t *)extbuf);
578 }
579
580 optp += optlen;
581 }
582
583 optend:
584 *databufp = NULL; /* for safety */
585 return (-1);
586}
587
588int
589inet6_opt_get_val(void *databuf, int offset, void *val, socklen_t vallen)
590{
591
592 /* we can't assume alignment here */
593 memcpy(val, (u_int8_t *)databuf + offset, vallen);
594
595 return (offset + vallen);
596}
diff --git a/src/lib/libc/net/rthdr.c b/src/lib/libc/net/rthdr.c
index 36ac5a3554..d10334e027 100644
--- a/src/lib/libc/net/rthdr.c
+++ b/src/lib/libc/net/rthdr.c
@@ -1,4 +1,5 @@
1/* $OpenBSD: rthdr.c,v 1.7 2005/03/25 13:24:12 otto Exp $ */ 1/* $OpenBSD: rthdr.c,v 1.8 2006/12/09 01:12:28 itojun Exp $ */
2/* $KAME: rthdr.c,v 1.22 2006/02/09 08:18:58 keiichi Exp $ */
2 3
3/* 4/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -39,6 +40,10 @@
39#include <string.h> 40#include <string.h>
40#include <stdio.h> 41#include <stdio.h>
41 42
43/*
44 * RFC2292 API
45 */
46
42size_t 47size_t
43inet6_rthdr_space(int type, int seg) 48inet6_rthdr_space(int type, int seg)
44{ 49{
@@ -213,3 +218,161 @@ inet6_rthdr_getflags(const struct cmsghdr *cmsg, int index)
213 return (-1); 218 return (-1);
214 } 219 }
215} 220}
221
222/*
223 * RFC3542 (2292bis) API
224 */
225
226socklen_t
227inet6_rth_space(int type, int segments)
228{
229 switch (type) {
230 case IPV6_RTHDR_TYPE_0:
231 return (((segments * 2) + 1) << 3);
232 default:
233 return (0); /* type not suppported */
234 }
235}
236
237void *
238inet6_rth_init(void *bp, socklen_t bp_len, int type, int segments)
239{
240 struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
241 struct ip6_rthdr0 *rth0;
242
243 switch (type) {
244 case IPV6_RTHDR_TYPE_0:
245 /* length validation */
246 if (bp_len < inet6_rth_space(IPV6_RTHDR_TYPE_0, segments))
247 return (NULL);
248
249 memset(bp, 0, bp_len);
250 rth0 = (struct ip6_rthdr0 *)rth;
251 rth0->ip6r0_len = segments * 2;
252 rth0->ip6r0_type = IPV6_RTHDR_TYPE_0;
253 rth0->ip6r0_segleft = 0;
254 rth0->ip6r0_reserved = 0;
255 break;
256 default:
257 return (NULL); /* type not supported */
258 }
259
260 return (bp);
261}
262
263int
264inet6_rth_add(void *bp, const struct in6_addr *addr)
265{
266 struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
267 struct ip6_rthdr0 *rth0;
268 struct in6_addr *nextaddr;
269
270 switch (rth->ip6r_type) {
271 case IPV6_RTHDR_TYPE_0:
272 rth0 = (struct ip6_rthdr0 *)rth;
273 nextaddr = (struct in6_addr *)(rth0 + 1) + rth0->ip6r0_segleft;
274 *nextaddr = *addr;
275 rth0->ip6r0_segleft++;
276 break;
277 default:
278 return (-1); /* type not supported */
279 }
280
281 return (0);
282}
283
284int
285inet6_rth_reverse(const void *in, void *out)
286{
287 struct ip6_rthdr *rth_in = (struct ip6_rthdr *)in;
288 struct ip6_rthdr0 *rth0_in, *rth0_out;
289 int i, segments;
290
291 switch (rth_in->ip6r_type) {
292 case IPV6_RTHDR_TYPE_0:
293 rth0_in = (struct ip6_rthdr0 *)in;
294 rth0_out = (struct ip6_rthdr0 *)out;
295
296 /* parameter validation XXX too paranoid? */
297 if (rth0_in->ip6r0_len % 2)
298 return (-1);
299 segments = rth0_in->ip6r0_len / 2;
300
301 /* we can't use memcpy here, since in and out may overlap */
302 memmove((void *)rth0_out, (void *)rth0_in,
303 ((rth0_in->ip6r0_len) + 1) << 3);
304 rth0_out->ip6r0_segleft = segments;
305
306 /* reverse the addresses */
307 for (i = 0; i < segments / 2; i++) {
308 struct in6_addr addr_tmp, *addr1, *addr2;
309
310 addr1 = (struct in6_addr *)(rth0_out + 1) + i;
311 addr2 = (struct in6_addr *)(rth0_out + 1) +
312 (segments - i - 1);
313 addr_tmp = *addr1;
314 *addr1 = *addr2;
315 *addr2 = addr_tmp;
316 }
317
318 break;
319 default:
320 return (-1); /* type not supported */
321 }
322
323 return (0);
324}
325
326int
327inet6_rth_segments(const void *bp)
328{
329 struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
330 struct ip6_rthdr0 *rh0;
331 int addrs;
332
333 switch (rh->ip6r_type) {
334 case IPV6_RTHDR_TYPE_0:
335 rh0 = (struct ip6_rthdr0 *)bp;
336
337 /*
338 * Validation for a type-0 routing header.
339 * Is this too strict?
340 */
341 if ((rh0->ip6r0_len % 2) != 0 ||
342 (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
343 return (-1);
344
345 return (addrs);
346 default:
347 return (-1); /* unknown type */
348 }
349}
350
351struct in6_addr *
352inet6_rth_getaddr(const void *bp, int idx)
353{
354 struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
355 struct ip6_rthdr0 *rh0;
356 int addrs;
357
358 switch (rh->ip6r_type) {
359 case IPV6_RTHDR_TYPE_0:
360 rh0 = (struct ip6_rthdr0 *)bp;
361
362 /*
363 * Validation for a type-0 routing header.
364 * Is this too strict?
365 */
366 if ((rh0->ip6r0_len % 2) != 0 ||
367 (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
368 return (NULL);
369
370 if (idx < 0 || addrs <= idx)
371 return (NULL);
372
373 return (((struct in6_addr *)(rh0 + 1)) + idx);
374 default:
375 return (NULL); /* unknown type */
376 break;
377 }
378}