From 07bfff20c78f861cb0cca78e4d26b9c662d21248 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 25 May 2006 04:50:06 +0000 Subject: [PATCH] [BZ #2693] * inet/Makefile (routines): Add inet6_opt and inet6_rth. * inet/Versions (libc, GLIBC_2.5): Add inet6_opt_init, inet6_opt_append, inet6_opt_finish, inet6_opt_set_val, inet6_opt_next, inet6_opt_find, inet6_opt_get_val, inet6_rth_space, inet6_rth_init, inet6_rth_add, inet6_rth_reverse, inet6_rth_segments, and inet6_rth_getaddr. * inet/netinet/ip6.h (struct ip6_rthdr0): Make ip6r0_addr a flexible array. * inet/netinet/in.h (struct ip6_mtuinfo): Define. Mark inet6_option_* interfaces as deprecated. Declare inet6_opt_init, inet6_opt_append, inet6_opt_finish, inet6_opt_set_val, inet6_opt_next, inet6_opt_find, inet6_opt_get_val, inet6_rth_space, inet6_rth_init, inet6_rth_add, inet6_rth_reverse, inet6_rth_segments, and inet6_rth_getaddr. * inet/inet6_opt.c: New file. * inet/inet6_rth.c: New file. * inet/netinet/icmp6.h: Pretty printing. --- ChangeLog | 20 ++++ NEWS | 7 +- inet/Makefile | 4 +- inet/Versions | 6 + inet/inet6_opt.c | 278 +++++++++++++++++++++++++++++++++++++++++++ inet/inet6_rth.c | 192 ++++++++++++++++++++++++++++++ inet/netinet/icmp6.h | 30 ++--- inet/netinet/in.h | 61 ++++++++-- inet/netinet/ip6.h | 21 ++-- 9 files changed, 580 insertions(+), 39 deletions(-) create mode 100644 inet/inet6_opt.c create mode 100644 inet/inet6_rth.c diff --git a/ChangeLog b/ChangeLog index 9fc6dc445b..f0555f09e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ 2006-05-24 Ulrich Drepper + [BZ #2693] + * inet/Makefile (routines): Add inet6_opt and inet6_rth. + * inet/Versions (libc, GLIBC_2.5): Add inet6_opt_init, + inet6_opt_append, inet6_opt_finish, inet6_opt_set_val, inet6_opt_next, + inet6_opt_find, inet6_opt_get_val, inet6_rth_space, inet6_rth_init, + inet6_rth_add, inet6_rth_reverse, inet6_rth_segments, + and inet6_rth_getaddr. + * inet/netinet/ip6.h (struct ip6_rthdr0): Make ip6r0_addr a flexible + array. + * inet/netinet/in.h (struct ip6_mtuinfo): Define. + Mark inet6_option_* interfaces as deprecated. + Declare inet6_opt_init, inet6_opt_append, inet6_opt_finish, + inet6_opt_set_val, inet6_opt_next, inet6_opt_find, inet6_opt_get_val, + inet6_rth_space, inet6_rth_init, inet6_rth_add, inet6_rth_reverse, + inet6_rth_segments, and inet6_rth_getaddr. + * inet/inet6_opt.c: New file. + * inet/inet6_rth.c: New file. + + * inet/netinet/icmp6.h: Pretty printing. + [BZ #2683] * elf/dl-addr.c (_dl_addr): Don't match undefined references. diff --git a/NEWS b/NEWS index 006aa2989f..edc576e096 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -GNU C Library NEWS -- history of user-visible changes. 2006-05-07 +GNU C Library NEWS -- history of user-visible changes. 2006-05-24 Copyright (C) 1992-2002,2003,2004,2005,2006 Free Software Foundation, Inc. See the end for copying conditions. @@ -23,11 +23,14 @@ Version 2.5 site might have problems with default behavior. Implemented by Ulrich Drepper. -* Iterating over entire database in NIS and NIS+ can be slow. With the +* Iterating over entire database in NIS can be slow. With the SETENT_BATCH_READ option in /etc/default/nss a system admin can decide to trade time for memory. The entire database will be read at once. Implemented by Ulrich Drepper. +* The interfaces introduced in RFC 3542 have been implemented by + Ulrich Drepper. + Version 2.4 diff --git a/inet/Makefile b/inet/Makefile index 0fdf9e33e4..075716fbeb 100644 --- a/inet/Makefile +++ b/inet/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1991-2002, 2003, 2004, 2006 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -47,7 +47,7 @@ routines := htonl htons \ getaliasent_r getaliasent getaliasname getaliasname_r \ in6_addr getnameinfo if_index ifaddrs inet6_option \ getipv4sourcefilter setipv4sourcefilter \ - getsourcefilter setsourcefilter + getsourcefilter setsourcefilter inet6_opt inet6_rth aux := check_pf ifreq diff --git a/inet/Versions b/inet/Versions index 2b7ec901ff..06507199a9 100644 --- a/inet/Versions +++ b/inet/Versions @@ -78,6 +78,12 @@ libc { getipv4sourcefilter; setipv4sourcefilter; getsourcefilter; setsourcefilter; } + GLIBC_2.5 { + inet6_opt_init; inet6_opt_append; inet6_opt_finish; inet6_opt_set_val; + inet6_opt_next; inet6_opt_find; inet6_opt_get_val; + inet6_rth_space; inet6_rth_init; inet6_rth_add; inet6_rth_reverse; + inet6_rth_segments; inet6_rth_getaddr; + } GLIBC_PRIVATE { # functions used in other libraries __internal_endnetgrent; __internal_getnetgrent_r; diff --git a/inet/inet6_opt.c b/inet/inet6_opt.c new file mode 100644 index 0000000000..bddb85182b --- /dev/null +++ b/inet/inet6_opt.c @@ -0,0 +1,278 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* RFC 3542, 10.1 + + This function returns the number of bytes needed for the empty + extension header i.e., without any options. If EXTBUF is not NULL it + also initializes the extension header to have the correct length + field. In that case if the EXTLEN value is not a positive (i.e., + non-zero) multiple of 8 the function fails and returns -1. */ +int +inet6_opt_init (void *extbuf, socklen_t extlen) +{ + if (extbuf != NULL) + { + if (extlen <= 0 || (extlen % 8) != 0) + return -1; + + /* Fill in the length in units of 8 octets. */ + struct ip6_hbh *extp = (struct ip6_hbh *) extbuf; + extp->ip6h_len = extlen / 8; + } + + return sizeof (struct ip6_hbh); +} + + +static void +add_padding (uint8_t *extbuf, int offset, int npad) +{ + if (npad == 1) + extbuf[offset] = IP6OPT_PAD1; + else + { + struct ip6_opt *pad_opt = (struct ip6_opt *) (extbuf + offset); + + pad_opt->ip6o_type = IP6OPT_PADN; + pad_opt->ip6o_len = npad - sizeof (struct ip6_opt); + /* Clear the memory used by the padding. */ + memset (pad_opt + 1, '\0', pad_opt->ip6o_len); + } +} + + + +/* RFC 3542, 10.2 + + This function returns the updated total length taking into account + adding an option with length 'len' and alignment 'align'. If + EXTBUF is not NULL then, in addition to returning the length, the + function inserts any needed pad option, initializes the option + (setting the type and length fields) and returns a pointer to the + location for the option content in databufp. If the option does + not fit in the extension header buffer the function returns -1. */ +int +inet6_opt_append (void *extbuf, socklen_t extlen, int offset, uint8_t type, + socklen_t len, uint8_t align, void **databufp) +{ + /* Check minimum offset. */ + if (offset < sizeof (struct ip6_hbh)) + return -1; + + /* One cannot add padding options. */ + if (type == IP6OPT_PAD1 || type == IP6OPT_PADN) + return -1; + + /* The option length must fit in one octet. */ + if (len > 255) + return -1; + + /* The alignment can only by 1, 2, 4, or 8 and must not exceed the + option length. */ + if (align == 0 || align > 8 || (align & (align - 1)) != 0 || align > len) + return -1; + + /* Determine the needed padding for alignment. Following the + current content of the buffer we have the is the IPv6 option type + and length, followed immediately by the data. The data has the + alignment constraints. Therefore padding must be inserted in the + form of padding options before the new option. */ + int data_offset = offset + sizeof (struct ip6_opt); + int npad = (align - data_offset % align) & (align - 1); + + /* Now we can check whether the buffer is large enough. */ + if (data_offset + npad + len > extlen) + return -1; + + if (npad != 0) + { + if (extbuf != NULL) + add_padding (extbuf, offset, npad); + + offset += npad; + } + + /* Now prepare the option itself. */ + if (extbuf != NULL) + { + struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset); + + opt->ip6o_type = type; + opt->ip6o_len = len; + + *databufp = opt + 1; + } + + return offset + sizeof (struct ip6_opt) + len; +} + + +/* RFC 3542, 10.3 + + This function returns the updated total length taking into account + the final padding of the extension header to make it a multiple of + 8 bytes. If EXTBUF is not NULL the function also initializes the + option by inserting a Pad1 or PadN option of the proper length. */ +int +inet6_opt_finish (void *extbuf, socklen_t extlen, int offset) +{ + /* Check minimum offset. */ + if (offset < sizeof (struct ip6_hbh)) + return -1; + + /* Required padding at the end. */ + int npad = (8 - (offset & 7)) & 7; + + /* Make sure the buffer is large enough. */ + if (offset + npad > extlen) + return -1; + + if (extbuf != NULL) + add_padding (extbuf, offset, npad); + + return offset + npad; +} + + +/* RFC 3542, 10.4 + + This function inserts data items of various sizes in the data + portion of the option. VAL should point to the data to be + inserted. OFFSET specifies where in the data portion of the option + the value should be inserted; the first byte after the option type + and length is accessed by specifying an offset of zero. */ +int +inet6_opt_set_val (void *databuf, int offset, void *val, socklen_t vallen) +{ + memcpy ((uint8_t *) databuf + offset, val, vallen); + + return offset + vallen; +} + + +/* RFC 3542, 10.5 + + This function parses received option extension headers returning + the next option. EXTBUF and EXTLEN specifies the extension header. + OFFSET should either be zero (for the first option) or the length + returned by a previous call to 'inet6_opt_next' or + 'inet6_opt_find'. It specifies the position where to continue + scanning the extension buffer. */ +int +inet6_opt_next (void *extbuf, socklen_t extlen, int offset, uint8_t *typep, + socklen_t *lenp, void **databufp) +{ + if (offset == 0) + offset = sizeof (struct ip6_hbh); + else if (offset < sizeof (struct ip6_hbh)) + return -1; + + while (offset < extlen) + { + struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset); + + if (opt->ip6o_type == IP6OPT_PAD1) + /* Single byte padding. */ + ++offset; + else if (opt->ip6o_type == IP6OPT_PADN) + offset += sizeof (struct ip6_opt) + opt->ip6o_len; + else + { + /* Check whether the option is valid. */ + offset += sizeof (struct ip6_opt) + opt->ip6o_len; + if (offset > extlen) + return -1; + + *typep = opt->ip6o_type; + *lenp = opt->ip6o_len; + *databufp = opt + 1; + return offset; + } + } + + return -1; +} + + +/* RFC 3542, 10.6 + + This function is similar to the previously described + 'inet6_opt_next' function, except this function lets the caller + specify the option type to be searched for, instead of always + returning the next option in the extension header. */ +int +inet6_opt_find (void *extbuf, socklen_t extlen, int offset, uint8_t type, + socklen_t *lenp, void **databufp) +{ + if (offset == 0) + offset = sizeof (struct ip6_hbh); + else if (offset < sizeof (struct ip6_hbh)) + return -1; + + while (offset < extlen) + { + struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset); + + if (opt->ip6o_type == IP6OPT_PAD1) + { + /* Single byte padding. */ + ++offset; + if (type == IP6OPT_PAD1) + { + *lenp = 0; + *databufp = (uint8_t *) extbuf + offset; + return offset; + } + } + else if (opt->ip6o_type != type) + offset += sizeof (struct ip6_opt) + opt->ip6o_len; + else + { + /* Check whether the option is valid. */ + offset += sizeof (struct ip6_opt) + opt->ip6o_len; + if (offset > extlen) + return -1; + + *lenp = opt->ip6o_len; + *databufp = opt + 1; + return offset; + } + } + + return -1; +} + + +/* RFC 3542, 10.7 + + This function extracts data items of various sizes in the data + portion of the option. */ +int +inet6_opt_get_val (void *databuf, int offset, void *val, socklen_t vallen) +{ + memcpy (val, (uint8_t *) databuf + offset, vallen); + + return offset + vallen; +} diff --git a/inet/inet6_rth.c b/inet/inet6_rth.c new file mode 100644 index 0000000000..15f8240909 --- /dev/null +++ b/inet/inet6_rth.c @@ -0,0 +1,192 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* RFC 3542, 7.1 + + This function returns the number of bytes required to hold a + Routing header of the specified type containing the specified + number of segments (addresses). For an IPv6 Type 0 Routing header, + the number of segments must be between 0 and 127, inclusive. */ +socklen_t +inet6_rth_space (int type, int segments) +{ + switch (type) + { + case IPV6_RTHDR_TYPE_0: + if (segments < 0 || segments > 127) + return 0; + + return sizeof (struct ip6_rthdr0) + segments * sizeof (struct in6_addr); + } + + return 0; +} + + +/* RFC 3542, 7.2 + + This function initializes the buffer pointed to by BP to contain a + Routing header of the specified type and sets ip6r_len based on the + segments parameter. */ +void * +inet6_rth_init (void *bp, socklen_t bp_len, int type, int segments) +{ + struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp; + + switch (type) + { + case IPV6_RTHDR_TYPE_0: + /* Make sure the parameters are valid and the buffer is large enough. */ + if (segments < 0 || segments > 127) + break; + + socklen_t len = (sizeof (struct ip6_rthdr0) + + segments * sizeof (struct in6_addr)); + if (len > bp_len) + break; + + /* Some implementations seem to initialize the whole memory area. */ + memset (bp, '\0', len); + + /* Length in units of 8 octets. */ + rthdr->ip6r_len = segments * sizeof (struct in6_addr) / 8; + rthdr->ip6r_type = IPV6_RTHDR_TYPE_0; + return bp; + } + + return NULL; +} + + +/* RFC 3542, 7.3 + + This function adds the IPv6 address pointed to by addr to the end of + the Routing header being constructed. */ +int +inet6_rth_add (void *bp, const struct in6_addr *addr) +{ + struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp; + + switch (rthdr->ip6r_type) + { + struct ip6_rthdr0 *rthdr0; + case IPV6_RTHDR_TYPE_0: + rthdr0 = (struct ip6_rthdr0 *) rthdr; + + memcpy (&rthdr0->ip6r0_addr[rthdr0->ip6r0_segleft++], + addr, sizeof (struct in6_addr)); + + return 0; + } + + return -1; +} + + +/* RFC 3542, 7.4 + + This function takes a Routing header extension header (pointed to by + the first argument) and writes a new Routing header that sends + datagrams along the reverse of that route. The function reverses the + order of the addresses and sets the segleft member in the new Routing + header to the number of segments. */ +int +inet6_rth_reverse (const void *in, void *out) +{ + struct ip6_rthdr *in_rthdr = (struct ip6_rthdr *) in; + + switch (in_rthdr->ip6r_type) + { + struct ip6_rthdr0 *in_rthdr0; + struct ip6_rthdr0 *out_rthdr0; + case IPV6_RTHDR_TYPE_0: + in_rthdr0 = (struct ip6_rthdr0 *) in; + out_rthdr0 = (struct ip6_rthdr0 *) out; + + /* Copy header, not the addresses. The memory regions can overlap. */ + memmove (out_rthdr0, in_rthdr0, sizeof (struct ip6_rthdr0)); + + int total = in_rthdr0->ip6r0_segleft * 8 / sizeof (struct in6_addr); + for (int i = 0; i < total / 2; ++i) + { + /* Remember, IN_RTHDR0 and OUT_RTHDR0 might overlap. */ + struct in6_addr temp = in_rthdr0->ip6r0_addr[i]; + out_rthdr0->ip6r0_addr[i] = in_rthdr0->ip6r0_addr[total - 1 - i]; + out_rthdr0->ip6r0_addr[total - 1 - i] = temp; + } + if (total % 2 != 0 && in != out) + out_rthdr0->ip6r0_addr[total / 2] = in_rthdr0->ip6r0_addr[total / 2]; + + return 0; + } + + return -1; +} + + +/* RFC 3542, 7.5 + + This function returns the number of segments (addresses) contained in + the Routing header described by BP. */ +int +inet6_rth_segments (const void *bp) +{ + struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp; + + switch (rthdr->ip6r_type) + { + case IPV6_RTHDR_TYPE_0: + + return rthdr->ip6r_len * 8 / sizeof (struct in6_addr); + } + + return -1; +} + + +/* RFC 3542, 7.6 + + This function returns a pointer to the IPv6 address specified by + index (which must have a value between 0 and one less than the + value returned by 'inet6_rth_segments') in the Routing header + described by BP. */ +struct in6_addr * +inet6_rth_getaddr (const void *bp, int index) +{ + struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp; + + switch (rthdr->ip6r_type) + { + struct ip6_rthdr0 *rthdr0; + case IPV6_RTHDR_TYPE_0: + rthdr0 = (struct ip6_rthdr0 *) rthdr; + + if (index >= rthdr0->ip6r0_len * 8 / sizeof (struct in6_addr)) + break; + + return &rthdr0->ip6r0_addr[index]; + } + + return NULL; +} diff --git a/inet/netinet/icmp6.h b/inet/netinet/icmp6.h index c5138a39c9..0cb1aa6a6c 100644 --- a/inet/netinet/icmp6.h +++ b/inet/netinet/icmp6.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,93,94,95,96,97,2000 Free Software Foundation, Inc. +/* Copyright (C) 1991-1997,2000,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -191,13 +191,13 @@ struct nd_opt_hdr /* Neighbor discovery option header */ /* followed by option specific data */ }; -#define ND_OPT_SOURCE_LINKADDR 1 -#define ND_OPT_TARGET_LINKADDR 2 -#define ND_OPT_PREFIX_INFORMATION 3 -#define ND_OPT_REDIRECTED_HEADER 4 -#define ND_OPT_MTU 5 -#define ND_OPT_RTR_ADV_INTERVAL 7 -#define ND_OPT_HOME_AGENT_INFO 8 +#define ND_OPT_SOURCE_LINKADDR 1 +#define ND_OPT_TARGET_LINKADDR 2 +#define ND_OPT_PREFIX_INFORMATION 3 +#define ND_OPT_REDIRECTED_HEADER 4 +#define ND_OPT_MTU 5 +#define ND_OPT_RTR_ADV_INTERVAL 7 +#define ND_OPT_HOME_AGENT_INFO 8 struct nd_opt_prefix_info /* prefix information */ { @@ -211,9 +211,9 @@ struct nd_opt_prefix_info /* prefix information */ struct in6_addr nd_opt_pi_prefix; }; -#define ND_OPT_PI_FLAG_ONLINK 0x80 -#define ND_OPT_PI_FLAG_AUTO 0x40 -#define ND_OPT_PI_FLAG_RADDR 0x20 +#define ND_OPT_PI_FLAG_ONLINK 0x80 +#define ND_OPT_PI_FLAG_AUTO 0x40 +#define ND_OPT_PI_FLAG_RADDR 0x20 struct nd_opt_rd_hdr /* redirected header */ { @@ -300,11 +300,11 @@ struct rr_pco_use /* use prefix part */ #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x10 #if BYTE_ORDER == BIG_ENDIAN -# define ICMP6_RR_PCOUSE_DECRVLTIME 0x80000000 -# define ICMP6_RR_PCOUSE_DECRPLTIME 0x40000000 +# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000 +# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000 #elif BYTE_ORDER == LITTLE_ENDIAN -# define ICMP6_RR_PCOUSE_DECRVLTIME 0x80 -# define ICMP6_RR_PCOUSE_DECRPLTIME 0x40 +# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80 +# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40 #endif struct rr_result /* router renumbering result message */ diff --git a/inet/netinet/in.h b/inet/netinet/in.h index 8898be3664..4fdc0fadf1 100644 --- a/inet/netinet/in.h +++ b/inet/netinet/in.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2001, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-2001, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -455,25 +455,66 @@ extern int bindresvport6 (int __sockfd, struct sockaddr_in6 *__sock_in) /* IPv6 packet information. */ struct in6_pktinfo { - struct in6_addr ipi6_addr; /* src/dst IPv6 address */ - unsigned int ipi6_ifindex; /* send/recv interface index */ + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ + }; + +/* IPv6 MTU information. */ +struct ip6_mtuinfo + { + struct sockaddr_in6 ip6m_addr; /* dst address including zone ID */ + uint32_t ip6m_mtu; /* path MTU in host byte order */ }; #ifdef __USE_GNU -/* Hop-by-Hop and Destination Options Processing. */ -extern int inet6_option_space (int __nbytes) __THROW; +/* Obsolete hop-by-hop and Destination Options Processing (RFC 2292). */ +extern int inet6_option_space (int __nbytes) + __THROW __attribute_deprecated__; extern int inet6_option_init (void *__bp, struct cmsghdr **__cmsgp, - int __type) __THROW; + int __type) __THROW __attribute_deprecated__; extern int inet6_option_append (struct cmsghdr *__cmsg, __const uint8_t *__typep, int __multx, - int __plusy) __THROW; + int __plusy) __THROW __attribute_deprecated__; extern uint8_t *inet6_option_alloc (struct cmsghdr *__cmsg, int __datalen, - int __multx, int __plusy) __THROW; + int __multx, int __plusy) + __THROW __attribute_deprecated__; extern int inet6_option_next (__const struct cmsghdr *__cmsg, - uint8_t **__tptrp) __THROW; + uint8_t **__tptrp) + __THROW __attribute_deprecated__; extern int inet6_option_find (__const struct cmsghdr *__cmsg, - uint8_t **__tptrp, int __type) __THROW; + uint8_t **__tptrp, int __type) + __THROW __attribute_deprecated__; + + +/* Hop-by-Hop and Destination Options Processing (RFC 3542). */ +extern int inet6_opt_init (void *__extbuf, socklen_t __extlen) __THROW; +extern int inet6_opt_append (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t __type, socklen_t __len, uint8_t __align, + void **__databufp) __THROW; +extern int inet6_opt_finish (void *__extbuf, socklen_t __extlen, int __offset) + __THROW; +extern int inet6_opt_set_val (void *__databuf, int __offset, void *__val, + socklen_t __vallen) __THROW; +extern int inet6_opt_next (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t *__typep, socklen_t *__lenp, + void **__databufp) __THROW; +extern int inet6_opt_find (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t __type, socklen_t *__lenp, + void **__databufp) __THROW; +extern int inet6_opt_get_val (void *__databuf, int __offset, void *__val, + socklen_t __vallen) __THROW; + + +/* Routing Header Option (RFC 3542). */ +extern socklen_t inet6_rth_space (int __type, int __segments) __THROW; +extern void *inet6_rth_init (void *__bp, socklen_t __bp_len, int __type, + int __segments) __THROW; +extern int inet6_rth_add (void *__bp, __const struct in6_addr *__addr) __THROW; +extern int inet6_rth_reverse (__const void *__in, void *__out) __THROW; +extern int inet6_rth_segments (__const void *__bp) __THROW; +extern struct in6_addr *inet6_rth_getaddr (__const void *__bp, int __index) + __THROW; /* Multicast source filter support. */ diff --git a/inet/netinet/ip6.h b/inet/netinet/ip6.h index 0ad62f8980..bef2af2f5a 100644 --- a/inet/netinet/ip6.h +++ b/inet/netinet/ip6.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-1997, 2001, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1991-1997, 2001, 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -89,7 +89,8 @@ struct ip6_rthdr0 uint8_t ip6r0_segleft; /* segments left */ uint8_t ip6r0_reserved; /* reserved field */ uint8_t ip6r0_slmap[3]; /* strict/loose bit map */ - struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */ + /* followed by up to 127 struct in6_addr */ + struct in6_addr ip6r0_addr[0]; }; /* Fragment header */ @@ -101,14 +102,14 @@ struct ip6_frag uint32_t ip6f_ident; /* identification */ }; -#if BYTE_ORDER == BIG_ENDIAN -#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */ -#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ -#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ +#if BYTE_ORDER == BIG_ENDIAN +# define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */ +# define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ +# define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ #else /* BYTE_ORDER == LITTLE_ENDIAN */ -#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */ -#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */ -#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */ +# define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */ +# define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */ +# define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */ #endif /* IPv6 options */ @@ -175,7 +176,7 @@ struct ip6_opt_router }; /* Router alert values (in network byte order) */ -#if BYTE_ORDER == BIG_ENDIAN +#if BYTE_ORDER == BIG_ENDIAN # define IP6_ALERT_MLD 0x0000 # define IP6_ALERT_RSVP 0x0001 # define IP6_ALERT_AN 0x0002