Back to index

glibc  2.9
Functions
inet6_opt.c File Reference
#include <string.h>
#include <netinet/in.h>
#include <netinet/ip6.h>

Go to the source code of this file.

Functions

int inet6_opt_init (void *extbuf, socklen_t extlen)
static void add_padding (uint8_t *extbuf, int offset, int npad)
int inet6_opt_append (void *extbuf, socklen_t extlen, int offset, uint8_t type, socklen_t len, uint8_t align, void **databufp)
int inet6_opt_finish (void *extbuf, socklen_t extlen, int offset)
int inet6_opt_set_val (void *databuf, int offset, void *val, socklen_t vallen)
int inet6_opt_next (void *extbuf, socklen_t extlen, int offset, uint8_t *typep, socklen_t *lenp, void **databufp)
int inet6_opt_find (void *extbuf, socklen_t extlen, int offset, uint8_t type, socklen_t *lenp, void **databufp)
int inet6_opt_get_val (void *databuf, int offset, void *val, socklen_t vallen)

Function Documentation

static void add_padding ( uint8_t extbuf,
int  offset,
int  npad 
) [static]

Definition at line 54 of file inet6_opt.c.

{
  if (npad == 1)
    extbuf[offset] = IP6OPT_PAD1;
  else if (npad > 0)
    {
      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);
    }
}

Here is the caller graph for this function:

int inet6_opt_append ( void *  extbuf,
socklen_t  extlen,
int  offset,
uint8_t  type,
socklen_t  len,
uint8_t  align,
void **  databufp 
)

Definition at line 81 of file inet6_opt.c.

{
  /* 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);

  if (extbuf != NULL)
    {
      /* Now we can check whether the buffer is large enough.  */
      if (data_offset + npad + len > extlen)
       return -1;

      add_padding (extbuf, offset, npad);

      offset += npad;

      /* Now prepare the option itself.  */
      struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset);

      opt->ip6o_type = type;
      opt->ip6o_len = len;

      *databufp = opt + 1;
    }
  else
    offset += npad;

  return offset + sizeof (struct ip6_opt) + len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int inet6_opt_find ( void *  extbuf,
socklen_t  extlen,
int  offset,
uint8_t  type,
socklen_t lenp,
void **  databufp 
)

Definition at line 230 of file inet6_opt.c.

{
  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;
}
int inet6_opt_finish ( void *  extbuf,
socklen_t  extlen,
int  offset 
)

Definition at line 141 of file inet6_opt.c.

{
  /* Check minimum offset.  */
  if (offset < sizeof (struct ip6_hbh))
    return -1;

  /* Required padding at the end.  */
  int npad = (8 - (offset & 7)) & 7;

  if (extbuf != NULL)
    {
      /* Make sure the buffer is large enough.  */
      if (offset + npad > extlen)
       return -1;

      add_padding (extbuf, offset, npad);
    }

  return offset + npad;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int inet6_opt_get_val ( void *  databuf,
int  offset,
void *  val,
socklen_t  vallen 
)

Definition at line 277 of file inet6_opt.c.

{
  memcpy (val, (uint8_t *) databuf + offset, vallen);

  return offset + vallen;
}

Here is the caller graph for this function:

int inet6_opt_init ( void *  extbuf,
socklen_t  extlen 
)

Definition at line 33 of file inet6_opt.c.

{
  if (extbuf != NULL)
    {
      if (extlen <= 0 || (extlen % 8) != 0 || extlen > 256 * 8)
       return -1;

      /* Fill in the length in units of 8 octets.  */
      struct ip6_hbh *extp = (struct ip6_hbh *) extbuf;

      /* RFC 2460 requires that the header extension length is the
        length of the option header in 8-byte units, not including
        the first 8 bytes.  Hence we have to subtract one.  */
      extp->ip6h_len = extlen / 8 - 1;
    }

  return sizeof (struct ip6_hbh);
}

Here is the caller graph for this function:

int inet6_opt_next ( void *  extbuf,
socklen_t  extlen,
int  offset,
uint8_t typep,
socklen_t lenp,
void **  databufp 
)

Definition at line 188 of file inet6_opt.c.

{
  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;
}

Here is the caller graph for this function:

int inet6_opt_set_val ( void *  databuf,
int  offset,
void *  val,
socklen_t  vallen 
)

Definition at line 171 of file inet6_opt.c.

{
  memcpy ((uint8_t *) databuf + offset, val, vallen);

  return offset + vallen;
}

Here is the caller graph for this function: