Project

General

Profile

Bug #653 ยป rfc3542-opt-and-rth.patch

hasso, 05/25/2007 06:28 AM

View differences:

lib/libc/net/ip6opt.c Wed May 23 21:42:13 2007 +0300 โ†’ lib/libc/net/ip6opt.c Fri May 25 06:12:44 2007 +0300
return;
}
}
/*
* The following functions are defined in RFC3542, which is a successor
* of RFC2292.
*/
int
inet6_opt_init(void *extbuf, socklen_t extlen)
{
struct ip6_ext *ext = (struct ip6_ext *)extbuf;
if (extlen < 0 || (extlen % 8))
return (-1);
if (ext) {
if (extlen == 0)
return (-1);
ext->ip6e_len = (extlen >> 3) - 1;
}
return (2); /* sizeof the next and the length fields */
}
int
inet6_opt_append(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
socklen_t len, u_int8_t align, void **databufp)
{
int currentlen = offset, padlen = 0;
/*
* The option type must have a value from 2 to 255, inclusive.
* (0 and 1 are reserved for the Pad1 and PadN options, respectively.)
*/
#if 0 /* always false */
if (type < 2 || type > 255)
#else
if (type < 2)
#endif
return (-1);
/*
* The option data length must have a value between 0 and 255,
* inclusive, and is the length of the option data that follows.
*/
if (len < 0 || len > 255)
return (-1);
/*
* The align parameter must have a value of 1, 2, 4, or 8.
* The align value can not exceed the value of len.
*/
if (align != 1 && align != 2 && align != 4 && align != 8)
return (-1);
if (align > len)
return (-1);
/* Calculate the padding length. */
currentlen += 2 + len; /* 2 means "type + len" */
if (currentlen % align)
padlen = align - (currentlen % align);
/* The option must fit in the extension header buffer. */
currentlen += padlen;
if (extlen && /* XXX: right? */
currentlen > extlen)
return (-1);
if (extbuf) {
u_int8_t *optp = (u_int8_t *)extbuf + offset;
if (padlen == 1) {
/* insert a Pad1 option */
*optp = IP6OPT_PAD1;
optp++;
} else if (padlen > 0) {
/* insert a PadN option for alignment */
*optp++ = IP6OPT_PADN;
*optp++ = padlen - 2;
memset(optp, 0, padlen - 2);
optp += (padlen - 2);
}
*optp++ = type;
*optp++ = len;
*databufp = optp;
}
return (currentlen);
}
int
inet6_opt_finish(void *extbuf, socklen_t extlen, int offset)
{
int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;;
if (extbuf) {
u_int8_t *padp;
int padlen = updatelen - offset;
if (updatelen > extlen)
return (-1);
padp = (u_int8_t *)extbuf + offset;
if (padlen == 1)
*padp = IP6OPT_PAD1;
else if (padlen > 0) {
*padp++ = IP6OPT_PADN;
*padp++ = (padlen - 2);
memset(padp, 0, padlen - 2);
}
}
return (updatelen);
}
int
inet6_opt_set_val(void *databuf, int offset, void *val, socklen_t vallen)
{
memcpy((u_int8_t *)databuf + offset, val, vallen);
return (offset + vallen);
}
int
inet6_opt_next(void *extbuf, socklen_t extlen, int offset, u_int8_t *typep,
socklen_t *lenp, void **databufp)
{
u_int8_t *optp, *lim;
int optlen;
/* Validate extlen. XXX: is the variable really necessary?? */
if (extlen == 0 || (extlen % 8))
return (-1);
lim = (u_int8_t *)extbuf + extlen;
/*
* If this is the first time this function called for this options
* header, simply return the 1st option.
* Otherwise, search the option list for the next option.
*/
if (offset == 0)
optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
else
optp = (u_int8_t *)extbuf + offset;
/* Find the next option skipping any padding options. */
while (optp < lim) {
switch(*optp) {
case IP6OPT_PAD1:
optp++;
break;
case IP6OPT_PADN:
if ((optlen = ip6optlen(optp, lim)) == 0)
goto optend;
optp += optlen;
break;
default: /* found */
if ((optlen = ip6optlen(optp, lim)) == 0)
goto optend;
*typep = *optp;
*lenp = optlen - 2;
*databufp = optp + 2;
return (optp + optlen - (u_int8_t *)extbuf);
}
}
optend:
*databufp = NULL; /* for safety */
return (-1);
}
int
inet6_opt_find(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
socklen_t *lenp, void **databufp)
{
u_int8_t *optp, *lim;
int optlen;
/* Validate extlen. XXX: is the variable really necessary?? */
if (extlen == 0 || (extlen % 8))
return (-1);
lim = (u_int8_t *)extbuf + extlen;
/*
* If this is the first time this function called for this options
* header, simply return the 1st option.
* Otherwise, search the option list for the next option.
*/
if (offset == 0)
optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
else
optp = (u_int8_t *)extbuf + offset;
/* Find the specified option */
while (optp < lim) {
if ((optlen = ip6optlen(optp, lim)) == 0)
goto optend;
if (*optp == type) { /* found */
*lenp = optlen - 2;
*databufp = optp + 2;
return (optp + optlen - (u_int8_t *)extbuf);
}
optp += optlen;
}
optend:
*databufp = NULL; /* for safety */
return (-1);
}
int
inet6_opt_get_val(void *databuf, int offset, void *val, socklen_t vallen)
{
/* we can't assume alignment here */
memcpy(val, (u_int8_t *)databuf + offset, vallen);
return (offset + vallen);
}
lib/libc/net/rthdr.c Wed May 23 21:42:13 2007 +0300 โ†’ lib/libc/net/rthdr.c Fri May 25 06:12:44 2007 +0300
return -1;
}
}
/*
* RFC3542 (2292bis) API
*/
socklen_t
inet6_rth_space(int type __unused, int segments __unused)
{
return (0); /* type not suppported */
}
void *
inet6_rth_init(void *bp __unused, socklen_t bp_len __unused, int type __unused,
int segments __unused)
{
return (NULL); /* type not supported */
}
int
inet6_rth_add(void *bp __unused, const struct in6_addr *addr __unused)
{
return (-1); /* type not supported */
}
int
inet6_rth_reverse(const void *in __unused, void *out __unused)
{
return (-1); /* type not supported */
}
int
inet6_rth_segments(const void *bp __unused)
{
return (-1); /* type not supported */
}
struct in6_addr *
inet6_rth_getaddr(const void *bp __unused, int idx __unused)
{
return (NULL); /* type not supported */
}
sys/netinet6/in6.h Wed May 23 21:42:13 2007 +0300 โ†’ sys/netinet6/in6.h Fri May 25 06:12:44 2007 +0300
*/
#define __KAME__
#define __KAME_VERSION "20010528/FreeBSD"
#ifndef _SOCKLEN_T_DECLARED
#define _SOCKLEN_T_DECLARED
typedef __socklen_t socklen_t;
#endif
/*
* Local port number conventions:
......
int inet6_option_next (const struct cmsghdr *, uint8_t **);
int inet6_option_space (int);
int inet6_opt_append (void *, size_t, int, uint8_t, size_t, uint8_t, void **);
int inet6_opt_find (void *, size_t, int, uint8_t, size_t *, void **);
int inet6_opt_finish (void *, size_t, int);
int inet6_opt_get_val (void *, size_t, void *, int);
int inet6_opt_init (void *, size_t);
int inet6_opt_next (void *, size_t, int, uint8_t *, size_t *, void **);
int inet6_opt_set_val (void *, size_t, void *, int);
int inet6_opt_append (void *, socklen_t, int, uint8_t, size_t, uint8_t, void **);
int inet6_opt_find (void *, socklen_t, int, uint8_t, size_t *, void **);
int inet6_opt_finish (void *, socklen_t, int);
int inet6_opt_get_val (void *, int, void *, socklen_t);
int inet6_opt_init (void *, socklen_t);
int inet6_opt_next (void *, socklen_t, int, uint8_t *, socklen_t *, void **);
int inet6_opt_set_val (void *, int, void *, socklen_t);
int inet6_rth_add (void *, const struct in6_addr *);
struct in6_addr *inet6_rth_getaddr (const void *, int);
void *inet6_rth_init (void *, int, int, int);
void *inet6_rth_init (void *, socklen_t, int, int);
int inet6_rth_reverse (const void *, void *);
int inet6_rth_segments (const void *);
size_t inet6_rth_space (int, int);
socklen_t inet6_rth_space (int, int);
int inet6_rthdr_add (struct cmsghdr *, const struct in6_addr *,
unsigned int);
    (1-1/1)