diff options
-rw-r--r-- | lib/libc/net/ip6opt.c | 309 | ||||
-rw-r--r-- | lib/libc/net/rthdr.c | 181 | ||||
-rw-r--r-- | sys/netinet6/in6.h | 21 |
3 files changed, 4 insertions, 507 deletions
diff --git a/lib/libc/net/ip6opt.c b/lib/libc/net/ip6opt.c index 7b4fdc4c4e6..d98e300cb62 100644 --- a/lib/libc/net/ip6opt.c +++ b/lib/libc/net/ip6opt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6opt.c,v 1.6 2014/02/17 21:05:39 stsp Exp $ */ +/* $OpenBSD: ip6opt.c,v 1.7 2014/06/13 15:41:06 chrisz Exp $ */ /* $KAME: ip6opt.c,v 1.18 2005/06/15 07:11:35 keiichi Exp $ */ /* @@ -41,296 +41,6 @@ #include <stdio.h> static int ip6optlen(u_int8_t *opt, u_int8_t *lim); -static void inet6_insert_padopt(u_char *p, int len); - -/* - * This function returns the number of bytes required to hold an option - * when it is stored as ancillary data, including the cmsghdr structure - * at the beginning, and any padding at the end (to make its size a - * multiple of 8 bytes). The argument is the size of the structure - * defining the option, which must include any pad bytes at the - * beginning (the value y in the alignment term "xn + y"), the type - * byte, the length byte, and the option data. - */ -int -inet6_option_space(int nbytes) -{ - nbytes += 2; /* we need space for nxt-hdr and length fields */ - return (CMSG_SPACE((nbytes + 7) & ~7)); -} - -/* - * This function is called once per ancillary data object that will - * contain either Hop-by-Hop or Destination options. It returns 0 on - * success or -1 on an error. - */ -int -inet6_option_init(void *bp, struct cmsghdr **cmsgp, int type) -{ - struct cmsghdr *ch = (struct cmsghdr *)bp; - - /* argument validation */ - if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS) - return (-1); - - ch->cmsg_level = IPPROTO_IPV6; - ch->cmsg_type = type; - ch->cmsg_len = CMSG_LEN(0); - - *cmsgp = ch; - return (0); -} - -/* - * This function appends a Hop-by-Hop option or a Destination option - * into an ancillary data object that has been initialized by - * inet6_option_init(). This function returns 0 if it succeeds or -1 on - * an error. - * multx is the value x in the alignment term "xn + y" described - * earlier. It must have a value of 1, 2, 4, or 8. - * plusy is the value y in the alignment term "xn + y" described - * earlier. It must have a value between 0 and 7, inclusive. - */ -int -inet6_option_append(struct cmsghdr *cmsg, const u_int8_t *typep, int multx, - int plusy) -{ - int padlen, optlen, off; - u_char *bp = (u_char *)cmsg + cmsg->cmsg_len; - struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg); - - /* argument validation */ - if (multx != 1 && multx != 2 && multx != 4 && multx != 8) - return (-1); - if (plusy < 0 || plusy > 7) - return (-1); -#if 0 - if (typep[0] > 255) - return (-1); -#endif - - /* - * If this is the first option, allocate space for the - * first 2 bytes(for next header and length fields) of - * the option header. - */ - if (bp == (u_char *)eh) { - bp += 2; - cmsg->cmsg_len += 2; - } - - /* calculate pad length before the option. */ - off = bp - (u_char *)eh; - padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) - - (off % multx); - padlen += plusy; - padlen %= multx; /* keep the pad as short as possible */ - /* insert padding */ - inet6_insert_padopt(bp, padlen); - cmsg->cmsg_len += padlen; - bp += padlen; - - /* copy the option */ - if (typep[0] == IP6OPT_PAD1) - optlen = 1; - else - optlen = typep[1] + 2; - memcpy(bp, typep, optlen); - bp += optlen; - cmsg->cmsg_len += optlen; - - /* calculate pad length after the option and insert the padding */ - off = bp - (u_char *)eh; - padlen = ((off + 7) & ~7) - off; - inet6_insert_padopt(bp, padlen); - bp += padlen; - cmsg->cmsg_len += padlen; - - /* update the length field of the ip6 option header */ - eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1; - - return (0); -} - -/* - * This function appends a Hop-by-Hop option or a Destination option - * into an ancillary data object that has been initialized by - * inet6_option_init(). This function returns a pointer to the 8-bit - * option type field that starts the option on success, or NULL on an - * error. - * The difference between this function and inet6_option_append() is - * that the latter copies the contents of a previously built option into - * the ancillary data object while the current function returns a - * pointer to the space in the data object where the option's TLV must - * then be built by the caller. - * - */ -u_int8_t * -inet6_option_alloc(struct cmsghdr *cmsg, int datalen, int multx, int plusy) -{ - int padlen, off; - u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len; - u_int8_t *retval; - struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg); - - /* argument validation */ - if (multx != 1 && multx != 2 && multx != 4 && multx != 8) - return (NULL); - if (plusy < 0 || plusy > 7) - return (NULL); - - /* - * If this is the first option, allocate space for the - * first 2 bytes(for next header and length fields) of - * the option header. - */ - if (bp == (u_char *)eh) { - bp += 2; - cmsg->cmsg_len += 2; - } - - /* calculate pad length before the option. */ - off = bp - (u_char *)eh; - padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) - - (off % multx); - padlen += plusy; - padlen %= multx; /* keep the pad as short as possible */ - /* insert padding */ - inet6_insert_padopt(bp, padlen); - cmsg->cmsg_len += padlen; - bp += padlen; - - /* keep space to store specified length of data */ - retval = bp; - bp += datalen; - cmsg->cmsg_len += datalen; - - /* calculate pad length after the option and insert the padding */ - off = bp - (u_char *)eh; - padlen = ((off + 7) & ~7) - off; - inet6_insert_padopt(bp, padlen); - bp += padlen; - cmsg->cmsg_len += padlen; - - /* update the length field of the ip6 option header */ - eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1; - - return (retval); -} - -/* - * This function processes the next Hop-by-Hop option or Destination - * option in an ancillary data object. If another option remains to be - * processed, the return value of the function is 0 and *tptrp points to - * the 8-bit option type field (which is followed by the 8-bit option - * data length, followed by the option data). If no more options remain - * to be processed, the return value is -1 and *tptrp is NULL. If an - * error occurs, the return value is -1 and *tptrp is not NULL. - * (RFC 2292, 6.3.5) - */ -int -inet6_option_next(const struct cmsghdr *cmsg, u_int8_t **tptrp) -{ - struct ip6_ext *ip6e; - int hdrlen, optlen; - u_int8_t *lim; - - if (cmsg->cmsg_level != IPPROTO_IPV6 || - (cmsg->cmsg_type != IPV6_HOPOPTS && - cmsg->cmsg_type != IPV6_DSTOPTS)) - return (-1); - - /* message length validation */ - if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext))) - return (-1); - ip6e = (struct ip6_ext *)CMSG_DATA(cmsg); - hdrlen = (ip6e->ip6e_len + 1) << 3; - if (cmsg->cmsg_len < CMSG_SPACE(hdrlen)) - return (-1); - - /* - * If the caller does not specify the starting point, - * simply return the 1st option. - * Otherwise, search the option list for the next option. - */ - lim = (u_int8_t *)ip6e + hdrlen; - if (*tptrp == NULL) - *tptrp = (u_int8_t *)(ip6e + 1); - else { - if ((optlen = ip6optlen(*tptrp, lim)) == 0) - return (-1); - - *tptrp = *tptrp + optlen; - } - if (*tptrp >= lim) { /* there is no option */ - *tptrp = NULL; - return (-1); - } - /* - * Finally, checks if the next option is safely stored in the - * cmsg data. - */ - if (ip6optlen(*tptrp, lim) == 0) - return (-1); - else - return (0); -} - -/* - * This function is similar to the inet6_option_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 - * ancillary data object. - * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think - * it's a typo. The variable should be type of u_int8_t **. - */ -int -inet6_option_find(const struct cmsghdr *cmsg, u_int8_t **tptrp, int type) -{ - struct ip6_ext *ip6e; - int hdrlen, optlen; - u_int8_t *optp, *lim; - - if (cmsg->cmsg_level != IPPROTO_IPV6 || - (cmsg->cmsg_type != IPV6_HOPOPTS && - cmsg->cmsg_type != IPV6_DSTOPTS)) - return (-1); - - /* message length validation */ - if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext))) - return (-1); - ip6e = (struct ip6_ext *)CMSG_DATA(cmsg); - hdrlen = (ip6e->ip6e_len + 1) << 3; - if (cmsg->cmsg_len < CMSG_SPACE(hdrlen)) - return (-1); - - /* - * If the caller does not specify the starting point, - * search from the beginning of the option list. - * Otherwise, search from *the next option* of the specified point. - */ - lim = (u_int8_t *)ip6e + hdrlen; - if (*tptrp == NULL) - *tptrp = (u_int8_t *)(ip6e + 1); - else { - if ((optlen = ip6optlen(*tptrp, lim)) == 0) - return (-1); - - *tptrp = *tptrp + optlen; - } - for (optp = *tptrp; optp < lim; optp += optlen) { - if (*optp == type) { - *tptrp = optp; - return (0); - } - if ((optlen = ip6optlen(optp, lim)) == 0) - return (-1); - } - - /* search failed */ - *tptrp = NULL; - return (-1); -} /* * Calculate the length of a given IPv6 option. Also checks @@ -356,23 +66,6 @@ ip6optlen(u_int8_t *opt, u_int8_t *lim) return (0); } -static void -inet6_insert_padopt(u_char *p, int len) -{ - switch(len) { - case 0: - return; - case 1: - p[0] = IP6OPT_PAD1; - return; - default: - p[0] = IP6OPT_PADN; - p[1] = len - 2; - memset(&p[2], 0, len - 2); - return; - } -} - /* * The following functions are defined in RFC3542, which is a successor * of RFC2292. diff --git a/lib/libc/net/rthdr.c b/lib/libc/net/rthdr.c index d10334e0277..9e917f1009a 100644 --- a/lib/libc/net/rthdr.c +++ b/lib/libc/net/rthdr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthdr.c,v 1.8 2006/12/09 01:12:28 itojun Exp $ */ +/* $OpenBSD: rthdr.c,v 1.9 2014/06/13 15:41:06 chrisz Exp $ */ /* $KAME: rthdr.c,v 1.22 2006/02/09 08:18:58 keiichi Exp $ */ /* @@ -41,185 +41,6 @@ #include <stdio.h> /* - * RFC2292 API - */ - -size_t -inet6_rthdr_space(int type, int seg) -{ - switch (type) { - case IPV6_RTHDR_TYPE_0: - if (seg < 1 || seg > 23) - return (0); - return (CMSG_SPACE(sizeof(struct in6_addr) * seg + - sizeof(struct ip6_rthdr0))); - default: - return (0); - } -} - -struct cmsghdr * -inet6_rthdr_init(void *bp, int type) -{ - struct cmsghdr *ch = (struct cmsghdr *)bp; - struct ip6_rthdr *rthdr; - - rthdr = (struct ip6_rthdr *)CMSG_DATA(ch); - - ch->cmsg_level = IPPROTO_IPV6; - ch->cmsg_type = IPV6_RTHDR; - - switch (type) { - case IPV6_RTHDR_TYPE_0: - ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0)); - bzero(rthdr, sizeof(struct ip6_rthdr0)); - rthdr->ip6r_type = IPV6_RTHDR_TYPE_0; - return (ch); - default: - return (NULL); - } -} - -int -inet6_rthdr_add(struct cmsghdr *cmsg, const struct in6_addr *addr, u_int flags) -{ - struct ip6_rthdr *rthdr; - - rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg); - - switch (rthdr->ip6r_type) { - case IPV6_RTHDR_TYPE_0: - { - struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr; - if (flags != IPV6_RTHDR_LOOSE) - return (-1); - if (rt0->ip6r0_segleft == 23) - return (-1); - rt0->ip6r0_segleft++; - bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3), - sizeof(struct in6_addr)); - rt0->ip6r0_len += sizeof(struct in6_addr) >> 3; - cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3); - break; - } - default: - return (-1); - } - - return (0); -} - -int -inet6_rthdr_lasthop(struct cmsghdr *cmsg, unsigned int flags) -{ - struct ip6_rthdr *rthdr; - - rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg); - - switch (rthdr->ip6r_type) { - case IPV6_RTHDR_TYPE_0: - { - struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr; - if (flags != IPV6_RTHDR_LOOSE) - return (-1); - if (rt0->ip6r0_segleft > 23) - return (-1); - break; - } - default: - return (-1); - } - - return (0); -} - -#if 0 -int -inet6_rthdr_reverse(in, out) - const struct cmsghdr *in; - struct cmsghdr *out; -{ - - return (-1); -} -#endif - -int -inet6_rthdr_segments(const struct cmsghdr *cmsg) -{ - struct ip6_rthdr *rthdr; - - rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg); - - switch (rthdr->ip6r_type) { - case IPV6_RTHDR_TYPE_0: - { - struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr; - - if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) - return (-1); - - return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr); - } - - default: - return (-1); - } -} - -struct in6_addr * -inet6_rthdr_getaddr(struct cmsghdr *cmsg, int index) -{ - struct ip6_rthdr *rthdr; - - rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg); - - switch (rthdr->ip6r_type) { - case IPV6_RTHDR_TYPE_0: - { - struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr; - int naddr; - - if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) - return NULL; - naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr); - if (index <= 0 || naddr < index) - return NULL; - return ((struct in6_addr *)(rt0 + 1)) + index; - } - - default: - return NULL; - } -} - -int -inet6_rthdr_getflags(const struct cmsghdr *cmsg, int index) -{ - struct ip6_rthdr *rthdr; - - rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg); - - switch (rthdr->ip6r_type) { - case IPV6_RTHDR_TYPE_0: - { - struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr; - int naddr; - - if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) - return (-1); - naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr); - if (index < 0 || naddr < index) - return (-1); - return IPV6_RTHDR_LOOSE; - } - - default: - return (-1); - } -} - -/* * RFC3542 (2292bis) API */ diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 78cd3e32a72..b9fe5d8c29b 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in6.h,v 1.71 2014/04/20 16:48:22 naddy Exp $ */ +/* $OpenBSD: in6.h,v 1.72 2014/06/13 15:41:06 chrisz Exp $ */ /* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */ /* @@ -381,7 +381,7 @@ struct ipv6_mreq { }; /* - * IPV6_PKTINFO: Packet information(RFC2292 sec 5) + * IPV6_PKTINFO: Packet information(RFC3542 sec 6) */ struct in6_pktinfo { struct in6_addr ipi6_addr; /* src/dst IPv6 address */ @@ -721,23 +721,6 @@ ifatoia6(struct ifaddr *ifa) __BEGIN_DECLS struct cmsghdr; -extern int inet6_option_space(int); -extern int inet6_option_init(void *, struct cmsghdr **, int); -extern int inet6_option_append(struct cmsghdr *, const u_int8_t *, - int, int); -extern u_int8_t *inet6_option_alloc(struct cmsghdr *, int, int, int); -extern int inet6_option_next(const struct cmsghdr *, u_int8_t **); -extern int inet6_option_find(const struct cmsghdr *, u_int8_t **, int); - -extern size_t inet6_rthdr_space(int, int); -extern struct cmsghdr *inet6_rthdr_init(void *, int); -extern int inet6_rthdr_add(struct cmsghdr *, const struct in6_addr *, - unsigned int); -extern int inet6_rthdr_lasthop(struct cmsghdr *, unsigned int); -extern int inet6_rthdr_segments(const struct cmsghdr *); -extern struct in6_addr *inet6_rthdr_getaddr(struct cmsghdr *, int); -extern int inet6_rthdr_getflags(const struct cmsghdr *, int); - extern int inet6_opt_init(void *, socklen_t); extern int inet6_opt_append(void *, socklen_t, int, u_int8_t, socklen_t, u_int8_t, void **); |