Example #1
0
static int vsock_stream_getsockopt(struct socket *sock,
				   int level, int optname,
				   char __user *optval,
				   int __user *optlen)
{
	int err;
	int len;
	struct sock *sk;
	struct vsock_sock *vsk;
	u64 val;

	if (level != AF_VSOCK)
		return -ENOPROTOOPT;

	err = get_user(len, optlen);
	if (err != 0)
		return err;

#define COPY_OUT(_v)                            \
	do {					\
		if (len < sizeof(_v))		\
			return -EINVAL;		\
						\
		len = sizeof(_v);		\
		if (copy_to_user(optval, &_v, len) != 0)	\
			return -EFAULT;				\
								\
	} while (0)

	err = 0;
	sk = sock->sk;
	vsk = vsock_sk(sk);

	switch (optname) {
	case SO_VM_SOCKETS_BUFFER_SIZE:
		val = transport->get_buffer_size(vsk);
		COPY_OUT(val);
		break;

	case SO_VM_SOCKETS_BUFFER_MAX_SIZE:
		val = transport->get_max_buffer_size(vsk);
		COPY_OUT(val);
		break;

	case SO_VM_SOCKETS_BUFFER_MIN_SIZE:
		val = transport->get_min_buffer_size(vsk);
		COPY_OUT(val);
		break;

	case SO_VM_SOCKETS_CONNECT_TIMEOUT: {
		struct timeval tv;
		tv.tv_sec = vsk->connect_timeout / HZ;
		tv.tv_usec =
		    (vsk->connect_timeout -
		     tv.tv_sec * HZ) * (1000000 / HZ);
		COPY_OUT(tv);
		break;
	}
	default:
		return -ENOPROTOOPT;
	}

	err = put_user(len, optlen);
	if (err != 0)
		return -EFAULT;

#undef COPY_OUT

	return 0;
}
Example #2
0
static int
dialog_create (pinentry_t pinentry, dialog_t dialog)
{
  int err = 0;
  int size_y;
  int size_x;
  int y;
  int x;
  int ypos;
  int xpos;
  int description_x = 0;
  int error_x = 0;
  CH *description = NULL;
  CH *error = NULL;
  CH *prompt = NULL;

  dialog->pinentry = pinentry;

#define COPY_OUT(what)							\
  do									\
    if (pinentry->what)							\
      {									\
        what = utf8_to_local (pinentry->lc_ctype, pinentry->what);	\
        if (!what)							\
	  {								\
	    err = 1;							\
            pinentry->specific_err = ASSUAN_Locale_Problem;             \
	    goto out;							\
	  }								\
      }									\
  while (0)

  COPY_OUT (description);
  COPY_OUT (error);
  COPY_OUT (prompt);

  /* There is no pinentry->default_notok.  Map it to
     pinentry->notok.  */
#define default_notok notok
#define MAKE_BUTTON(which,default)					\
  do									\
    {									\
      char *new = NULL;							\
      if (pinentry->default_##which || pinentry->which)			\
        {								\
	  int len;							\
	  char *msg;							\
	  int i, j;							\
									\
	  msg = pinentry->which;					\
	  if (! msg)							\
	    msg = pinentry->default_##which;				\
          len = strlen (msg);						\
									\
          new = malloc (len + 3);				       	\
	  if (!new)							\
	    {								\
	      err = 1;							\
              pinentry->specific_err = ASSUAN_Out_Of_Core;              \
	      goto out;							\
	    }								\
									\
	  new[0] = '<'; 						\
	  for (i = 0, j = 1; i < len; i ++, j ++)			\
	    {								\
	      if (msg[i] == '_')					\
		{							\
		  i ++;							\
		  if (msg[i] == 0)					\
		    /* _ at end of string.  */				\
		    break;						\
		}							\
	      new[j] = msg[i];						\
	    }								\
									\
	  new[j] = '>';							\
	  new[j + 1] = 0;						\
        }								\
      dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype,	\
					      new ? new : default);	\
      if (!dialog->which)						\
        {								\
	  err = 1;							\
          pinentry->specific_err = ASSUAN_Locale_Problem;               \
	  goto out;							\
	}								\
    }									\
  while (0)

  MAKE_BUTTON (ok, STRING_OK);
  if (!pinentry->one_button)
    MAKE_BUTTON (cancel, STRING_CANCEL);
  else
    dialog->cancel = NULL;
  if (!pinentry->one_button && pinentry->notok)
    MAKE_BUTTON (notok, STRING_NOTOK);
  else
    dialog->notok = NULL;

  getmaxyx (stdscr, size_y, size_x);

  /* Check if all required lines fit on the screen.  */
  y = 1;		/* Top frame.  */
  if (description)
    {
      CH *start = description;
      int len = 0;

      do
	{
	  collect_line (size_x - 4, &start, &len);
	  if (len > description_x)
	    description_x = len;
	  y++;
	}
      while (start[len - 1]);
      y++;
    }

  if (pinentry->pin)
    {
      if (error)
	{
	  CH *p = error;
	  int err_x = 0;

	  while (*p)
	    {
	      if (*(p++) == '\n')
		{
		  if (err_x > error_x)
		    error_x = err_x;
		  y++;
		  err_x = 0;
		}
	      else
		err_x++;
	    }
	  if (err_x > error_x)
	    error_x = err_x;
	  y += 2;	/* Error message.  */
	}
      y += 2;		/* Pin entry field.  */
    }
  y += 2;		/* OK/Cancel and bottom frame.  */

  if (y > size_y)
    {
      err = 1;
      pinentry->specific_err = ASSUAN_Too_Short;
      goto out;
    }

  /* Check if all required columns fit on the screen.  */
  x = 0;
  if (description)
    {
      int new_x = description_x;
      if (new_x > size_x - 4)
	new_x = size_x - 4;
      if (new_x > x)
	x = new_x;
    }
  if (pinentry->pin)
    {
#define MIN_PINENTRY_LENGTH 40
      int new_x;

      if (error)
	{
	  new_x = error_x;
	  if (new_x > size_x - 4)
	    new_x = size_x - 4;
	  if (new_x > x)
	    x = new_x;
	}

      new_x = MIN_PINENTRY_LENGTH;
      if (prompt)
	{
	  new_x += STRLEN (prompt) + 1;	/* One space after prompt.  */
	}
      if (new_x > size_x - 4)
	new_x = size_x - 4;
      if (new_x > x)
	x = new_x;
    }
  /* We position the buttons after the first, second and third fourth
     of the width.  Account for rounding.  */
  if (x < 3 * strlen (dialog->ok))
    x = 3 * strlen (dialog->ok);
  if (dialog->cancel)
    if (x < 3 * strlen (dialog->cancel))
      x = 3 * strlen (dialog->cancel);
  if (dialog->notok)
    if (x < 3 * strlen (dialog->notok))
      x = 3 * strlen (dialog->notok);

  /* Add the frame.  */
  x += 4;

  if (x > size_x)
    {
      err = 1;
      pinentry->specific_err = ASSUAN_Too_Short;
      goto out;
    }

  dialog->pos = DIALOG_POS_NONE;
  dialog->pin_max = pinentry->pin_len;
  dialog->pin_loc = 0;
  dialog->pin_len = 0;
  ypos = (size_y - y) / 2;
  xpos = (size_x - x) / 2;
  move (ypos, xpos);
  addch (ACS_ULCORNER);
  hline (0, x - 2);
  move (ypos, xpos + x - 1);
  addch (ACS_URCORNER);
  move (ypos + 1, xpos + x - 1);
  vline (0, y - 2);
  move (ypos + y - 1, xpos);
  addch (ACS_LLCORNER);
  hline (0, x - 2);
  move (ypos + y - 1, xpos + x - 1);
  addch (ACS_LRCORNER);
  ypos++;
  if (description)
    {
      CH *start = description;
      int len = 0;

      do
	{
	  int i;

	  move (ypos, xpos);
	  addch (ACS_VLINE);
	  addch (' ');
	  collect_line (size_x - 4, &start, &len);
	  for (i = 0; i < len - 1; i++)
	    {
	      ADDCH (start[i]);
	    }
	  if (start[len - 1] != NULLCH && start[len - 1] != NLCH)
	    ADDCH (start[len - 1]);
	  ypos++;
	}
      while (start[len - 1]);
      move (ypos, xpos);
      addch (ACS_VLINE);
      ypos++;
    }
  if (pinentry->pin)
    {
      int i;

      if (error)
	{
	  CH *p = error;
	  i = 0;

	  while (*p)
	    {
	      move (ypos, xpos);
	      addch (ACS_VLINE);
	      addch (' ');
	      if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
		{
		  attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
		  attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
		}
	      else
		standout ();
	      for (;*p && *p != NLCH; p++)
		if (i < x - 4)
		  {
		    i++;
		    ADDCH (*p);
		  }
	      if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
		{
		  attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
		  attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
		}
	      else
		standend ();
	      if (*p == '\n')
		p++;
	      i = 0;
	      ypos++;
	    }
	  move (ypos, xpos);
	  addch (ACS_VLINE);
	  ypos++;
	}

      move (ypos, xpos);
      addch (ACS_VLINE);
      addch (' ');

      dialog->pin_y = ypos;
      dialog->pin_x = xpos + 2;
      dialog->pin_size = x - 4;
      if (prompt)
	{
	  CH *p = prompt;
	  i = STRLEN (prompt);
	  if (i > x - 4 - MIN_PINENTRY_LENGTH)
	    i = x - 4 - MIN_PINENTRY_LENGTH;
	  dialog->pin_x += i + 1;
	  dialog->pin_size -= i + 1;
	  while (i-- > 0)
	    {
	      ADDCH (*(p++));
	    }
	  addch (' ');
	}
      for (i = 0; i < dialog->pin_size; i++)
	addch ('_');
      ypos++;
      move (ypos, xpos);
      addch (ACS_VLINE);
      ypos++;
    }
  move (ypos, xpos);
  addch (ACS_VLINE);

  if (dialog->cancel || dialog->notok)
    {
      dialog->ok_y = ypos;
      /* Calculating the left edge of the left button, rounding down.  */
      dialog->ok_x = xpos + 2 + ((x - 4) / 3 - strlen (dialog->ok)) / 2;
      move (dialog->ok_y, dialog->ok_x);
      addstr (dialog->ok);

      if (! pinentry->pin && dialog->notok)
	{
	  dialog->notok_y = ypos;
	  /* Calculating the left edge of the middle button, rounding up.  */
	  dialog->notok_x = xpos + x / 2 - strlen (dialog->notok) / 2;
	  move (dialog->notok_y, dialog->notok_x);
	  addstr (dialog->notok);
	}
      if (dialog->cancel)
	{
	  dialog->cancel_y = ypos;
	  /* Calculating the left edge of the right button, rounding up.  */
	  dialog->cancel_x = xpos + x - 2 - ((x - 4) / 3 + strlen (dialog->cancel)) / 2;
	  move (dialog->cancel_y, dialog->cancel_x);
	  addstr (dialog->cancel);
	}
    }
  else
    {
      dialog->ok_y = ypos;
      /* Calculating the left edge of the OK button, rounding down.  */
      dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2;
      move (dialog->ok_y, dialog->ok_x);
      addstr (dialog->ok);
    }

 out:
  if (description)
    free (description);
  if (error)
    free (error);
  if (prompt)
    free (prompt);
  return err;
}
Example #3
0
static int
dialog_create (pinentry_t pinentry, dialog_t dialog)
{
  int err = 0;
  int size_y;
  int size_x;
  int y;
  int x;
  int ypos;
  int xpos;
  int description_x = 0;
  int error_x = 0;
  char *description = NULL;
  char *error = NULL;
  char *prompt = NULL;

#define COPY_OUT(what)							\
  do									\
    if (pinentry->what)							\
      {									\
        what = pinentry_utf8_to_local (pinentry->lc_ctype,		\
				       pinentry->what);			\
        if (!what)							\
	  {								\
	    err = 1;							\
	    goto out;							\
	  }								\
      }									\
  while (0)
    
  COPY_OUT (description);
  COPY_OUT (error);
  COPY_OUT (prompt);

#define MAKE_BUTTON(which,default)					\
  do									\
    {									\
      char *new = NULL;							\
      if (pinentry->which)						\
        {								\
          int len = strlen (pinentry->which);				\
          new = malloc (len + 3);				       	\
	  if (!new)							\
	    {								\
	      err = 1;							\
	      goto out;							\
	    }								\
	  new[0] = '<';							\
	  memcpy (&new[1], pinentry->which, len);			\
          new[len + 1] = '>';						\
	  new[len + 2] = '\0';						\
        }								\
      dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype,	\
					      new ? new : default);	\
      if (!dialog->which)						\
        {								\
	  err = 1;							\
	  goto out;							\
	}								\
    }									\
  while (0)

  MAKE_BUTTON (ok, STRING_OK);
  if (!pinentry->one_button)
    MAKE_BUTTON (cancel, STRING_CANCEL);
  else
    dialog->cancel = NULL;

  getmaxyx (stdscr, size_y, size_x);

  /* Check if all required lines fit on the screen.  */
  y = 1;		/* Top frame.  */
  if (description)
    {
      char *start = description;
      int len = 0;

      do
	{
	  collect_line (size_x - 4, &start, &len);
	  if (len > description_x)
	    description_x = len;
	  y++;
	}
      while (start[len - 1]);
      y++;
    }
      
  if (pinentry->pin)
    {
      if (error)
	{
	  char *p = error;
	  int err_x = 0;

	  while (*p)
	    {
	      if (*(p++) == '\n')
		{
		  if (err_x > error_x)
		    error_x = err_x;
		  y++;
		  err_x = 0;
		}
	      else
		err_x++;
	    }
	  if (err_x > error_x)
	    error_x = err_x;
	  y += 2;	/* Error message.  */
	}
      y += 2;		/* Pin entry field.  */
    }
  y += 2;		/* OK/Cancel and bottom frame.  */
  
  if (y > size_y)
    {
      err = 1;
      goto out;
    }

  /* Check if all required columns fit on the screen.  */
  x = 0;
  if (description)
    {
      int new_x = description_x;
      if (new_x > size_x - 4)
	new_x = size_x - 4;
      if (new_x > x)
	x = new_x;
    }
  if (pinentry->pin)
    {
#define MIN_PINENTRY_LENGTH 40
      int new_x;

      if (error)
	{
	  new_x = error_x;
	  if (new_x > size_x - 4)
	    new_x = size_x - 4;
	  if (new_x > x)
	    x = new_x;
	}

      new_x = MIN_PINENTRY_LENGTH;
      if (prompt)
	new_x += strlen (prompt) + 1;	/* One space after prompt.  */
      if (new_x > size_x - 4)
	new_x = size_x - 4;
      if (new_x > x)
	x = new_x;
    }
  /* We position the buttons after the first and second third of the
     width.  Account for rounding.  */
  if (x < 2 * strlen (dialog->ok))
    x = 2 * strlen (dialog->ok);
  if (dialog->cancel)
    if (x < 2 * strlen (dialog->cancel))
      x = 2 * strlen (dialog->cancel);

  /* Add the frame.  */
  x += 4;

  if (x > size_x)
    {
      err = 1;
      goto out;
    }

  dialog->pos = DIALOG_POS_NONE;
  dialog->pin = pinentry->pin;
  dialog->pin_max = pinentry->pin_len;
  dialog->pin_loc = 0;
  dialog->pin_len = 0;
  ypos = (size_y - y) / 2;
  xpos = (size_x - x) / 2;
  move (ypos, xpos);
  addch (ACS_ULCORNER);
  hline (0, x - 2);
  move (ypos, xpos + x - 1);
  addch (ACS_URCORNER);
  move (ypos + 1, xpos + x - 1);
  vline (0, y - 2);
  move (ypos + y - 1, xpos);
  addch (ACS_LLCORNER);
  hline (0, x - 2);
  move (ypos + y - 1, xpos + x - 1);
  addch (ACS_LRCORNER);
  ypos++;
  if (description)
    {
      char *start = description;
      int len = 0;

      do
	{
	  int i;

	  move (ypos, xpos);
	  addch (ACS_VLINE);
	  addch (' ');
	  collect_line (size_x - 4, &start, &len);
	  for (i = 0; i < len - 1; i++)
	    addch ((unsigned char) start[i]);
	  if (start[len - 1] && start[len - 1] != '\n')
	    addch ((unsigned char) start[len - 1]);
	  ypos++;
	}
      while (start[len - 1]);
      move (ypos, xpos);
      addch (ACS_VLINE);
      ypos++;
    }
  if (pinentry->pin)
    {
      int i;

      if (error)
	{
	  char *p = error;
	  i = 0;

	  while (*p)
	    {
	      move (ypos, xpos);
	      addch (ACS_VLINE);
	      addch (' ');
	      if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
		{
		  attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
		  attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
		}
	      else
		standout ();
	      for (;*p && *p != '\n'; p++)
		if (i < x - 4)
		  {
		    i++;
		    addch ((unsigned char) *p);
		  }
	      if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
		{
		  attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
		  attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
		}
	      else
		standend ();
	      if (*p == '\n')
		p++;
	      i = 0;
	      ypos++;
	    }
	  move (ypos, xpos);
	  addch (ACS_VLINE);
	  ypos++;
	}

      move (ypos, xpos);
      addch (ACS_VLINE);
      addch (' ');

      dialog->pin_y = ypos;
      dialog->pin_x = xpos + 2;
      dialog->pin_size = x - 4;
      if (prompt)
	{
	  char *p = prompt;
	  i = strlen (prompt);
	  if (i > x - 4 - MIN_PINENTRY_LENGTH)
	    i = x - 4 - MIN_PINENTRY_LENGTH;
	  dialog->pin_x += i + 1;
	  dialog->pin_size -= i + 1;
	  while (i-- > 0)
	    addch ((unsigned char) *(p++));
	  addch (' ');
	}
      for (i = 0; i < dialog->pin_size; i++)
	addch ('_');
      ypos++;
      move (ypos, xpos);
      addch (ACS_VLINE);
      ypos++;
    }
  move (ypos, xpos);
  addch (ACS_VLINE);

  if (dialog->cancel)
    {
      dialog->ok_y = ypos;
      /* Calculating the left edge of the left button, rounding down.  */
      dialog->ok_x = xpos + 2 + ((x - 4) / 2 - strlen (dialog->ok)) / 2;
      move (dialog->ok_y, dialog->ok_x);
      addstr (dialog->ok);

      dialog->cancel_y = ypos;
      /* Calculating the left edge of the right button, rounding up.  */
      dialog->cancel_x = xpos + x - 2 - ((x - 4) / 2 + strlen (dialog->cancel)) / 2;
      move (dialog->cancel_y, dialog->cancel_x);
      addstr (dialog->cancel);
    }
  else
    {
      dialog->ok_y = ypos;
      /* Calculating the left edge of the OK button, rounding down.  */
      dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2;
      move (dialog->ok_y, dialog->ok_x);
      addstr (dialog->ok);
    }

 out:
  if (description)
    free (description);
  if (error)
    free (error);
  if (prompt)
    free (prompt);
  return err;
}
Example #4
0
/*
 * This is the ``callback function'' that is invoked by `sysctl_rtsock' in
 * order to copy data out.  On each invocation, we get a buffer containing:
 *
 *   + A `struct rt_msghdr'.  The `rtm_type' member of this structure should
 *     always be `RTM_GET'.
 *   + A set of zero or more `struct sockaddr's describing the addresses
 *     associated with the route.
 *
 * See the function `sysctl_rtsock' for further details.  Some of the code
 * below is modeled after code in the FreeBSD `route' utility; in FreeBSD, see
 * the file `/usr/src/sbin/route/route.c'.
 */
static int
get_one_ipforward(
	struct sysctl_req *	req,
	const void *		buf,
	size_t			buf_size)
{
	get_ipforward_env_t *	env = (get_ipforward_env_t *) req;
	struct rt_msghdr *	rtm = (struct rt_msghdr *) buf;
	
	struct rt_addrinfo	rtinfo;
	struct sockaddr_in *	sin;
	
	oskit_mib_in_addr_t	dest;
	oskit_mib_in_addr_t	mask;
	/* oskit_s32_t		policy; */
	oskit_mib_in_addr_t	next_hop;
	oskit_s32_t		if_index;
	oskit_u32_t		type;
	oskit_u32_t		proto;
	/* oskit_s32_t		age; */
	oskit_s32_t		next_hop_as;
	oskit_s32_t		metric1;
	oskit_s32_t		metric2;
	oskit_s32_t		metric3;
	oskit_s32_t		metric4;
	oskit_s32_t		metric5;
	
	/*********************************************************************/
	
	if (rtm->rtm_version != RTM_VERSION) {
		/* A message we don't understand?  This should never happen. */
		assert(!"Received an unknown type of message.");
		goto done;
	}
	if (rtm->rtm_type != RTM_GET) {
		/* A message we don't understand?  This should never happen. */
		assert(!"Received an unknown type of message.");
		goto done;
	}
	
	/*
	 * Figure out what the socket addresses mean; i.e., assign them to the
	 * appropriate elements of the `rtinfo.rti_info' array.
	 */
	rtinfo.rti_addrs = rtm->rtm_addrs;
	rt_xaddrs(((char *) (rtm + 1)),
		  ((char *) rtm) + rtm->rtm_msglen,
		  &rtinfo);
	
	/* From `rtinfo', decode the fields of our table row. */
	sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_DST];
	if (!sin)
		/* No destination address?! */
		goto done;
	dest = sin->sin_addr.s_addr;
	
	sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_NETMASK];
	if (!sin)
		/* No network mask?! */
		goto done;
	mask = sin->sin_addr.s_addr;
	
	/*
	 * XXX --- RFC 1354 says that this should be an encoding of the IP TOS.
	 * I don't understand how I'm supposed to determine that for a route.
	 * The TOS is associated with a particular socket, not a route, right?
	 */
	/* policy = ...; */
	
	if (rtm->rtm_flags & RTF_LOCAL) {
		next_hop = INADDR_ANY; /* See RFC 1354. */
	} else {
		sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_GATEWAY];
		if (!sin)
			/* No next hop address?! */
			goto done;
		
		switch (sin->sin_family) {
		case AF_INET:
			next_hop = sin->sin_addr.s_addr;
			break;
		case AF_LINK:
			/*
			 * The gateway address is a link-layer address.  This
			 * means that we're talking about one of our own
			 * interfaces.
			 *
			 * RFC 1213 says (for `ipRouteNextHop'): ``In the case
			 * of a route bound to an interface which is realized
			 * via a broadcast media, the value of this field is
			 * the agent's IP address on that interface.''
			 *
			 * RFC 1354 says (for `ipForwardNextHop'): ``On remote
			 * routes, the address of the next system en route;
			 * Otherwise, 0.0.0.0.''
			 *
			 * We follow RFC 1354 because we *are* implementing the
			 * `ipForwardTable' after all.  Plus, we don't have our
			 * IP address on the interface handy at this point.
			 * (`dest' isn't it.  `dest' has had the subnet mask
			 * applied to it, so it's missing parts of our addr.)
			 */
#if 1
			next_hop = INADDR_ANY;
#else
			sdl = (struct sockaddr_dl *) sin;
			switch (sdl->sdl_type) {
			case IFT_ETHER:
			/* List other broadcast media here. */
				next_hop = /* Our IP address.  Not `dest'. */;
				break;
			default:
				next_hop = INADDR_ANY;
				break;
			}
#endif
			break;
		default:
			assert(!"Received an unrecognized kind of next-hop");
			next_hop = INADDR_ANY;
			break;
		}
	}
	
	if_index = rtm->rtm_index;
	type = ((rtm->rtm_flags & RTF_GATEWAY) ?
		OSKIT_MIB_IP_FORWARD_TYPE_REMOTE :
		OSKIT_MIB_IP_FORWARD_TYPE_LOCAL);
	
	proto = ((rtm->rtm_flags & RTF_LOCAL) ?
		 OSKIT_MIB_IP_FORWARD_PROTO_LOCAL :
		 (rtm->rtm_flags & RTF_DYNAMIC) ?
		 OSKIT_MIB_IP_FORWARD_PROTO_ICMP :
		 (rtm->rtm_flags & RTF_STATIC) ?
		 OSKIT_MIB_IP_FORWARD_PROTO_NETMGMT :
		 OSKIT_MIB_IP_FORWARD_PROTO_OTHER
		 );
	
	/* XXX --- I don't believe that route age is stored anywhere. */
	/* age = ...; */
	
	next_hop_as = 0; /* See IETF RFC 1354. */
	
	/*
	 * XXX --- I don't really understand the semantics of these values;
	 * e.g., are they supposed to have well-defined meanings?  I've just
	 * picked the most interesting set of metrics from our route info.
	 */
	metric1 = (rtm->rtm_flags & RTF_UP);	/* Is this route usable? */
	metric2 = rtm->rtm_rmx.rmx_hopcount;	/* Max hops expected. */
	metric3 = rtm->rtm_rmx.rmx_sendpipe;	/* Out delay-b'width product */
	metric4 = rtm->rtm_rmx.rmx_rtt;		/* Estimated round trip time */
	metric5 = rtm->rtm_rmx.rmx_rttvar;	/* Estimated RTT variance. */
	
	/*********************************************************************/
	
	/*
	 * Process the entry.
	 */
	if (ipforward_match(dest, mask, /* policy, */ next_hop,
			    if_index, type, proto, /* age, */ next_hop_as,
			    metric1, metric2, metric3, metric4, metric5,
			    env->args.matching)) {
		if (env->args.start_row > 0) {
			/* Skip this row. */
			env->args.start_row--;
		} else if (env->args.want_rows > 0) {
			/* Accumulate this row. */
#define COPY_OUT(slot_type, slot_name)				\
	oskit_mib_##slot_type##_set(				\
		&(env->args.table->ip_forward_##slot_name),	\
		slot_name)
#define CLEAR_OUT(slot_type, slot_name)				\
	oskit_mib_##slot_type##_clear(				\
		&(env->args.table->ip_forward_##slot_name))
			COPY_OUT(mib_in_addr,	dest);
			COPY_OUT(mib_in_addr,	mask);
			CLEAR_OUT(s32,		policy);	/* XXX */
			COPY_OUT(mib_in_addr,	next_hop);
			COPY_OUT(s32,		if_index);
			COPY_OUT(u32,		type);
			COPY_OUT(u32,		proto);
			CLEAR_OUT(s32,		age);		/* XXX */
			COPY_OUT(s32,		next_hop_as);
			COPY_OUT(s32,		metric1);
			COPY_OUT(s32,		metric2);
			COPY_OUT(s32,		metric3);
			COPY_OUT(s32,		metric4);
			COPY_OUT(s32,		metric5);
#undef COPY_OUT
			(*env->args.out_rows)++;
			env->args.table++;
			env->args.want_rows--;
			
		} else {
			/* Indicate that the table filled up. */
			*env->args.more_rows = 1;
		}
	}
	
 done:
	/* Indicate to the `sysctl_rtsock' function that no error occurred. */
	return 0;
}
Example #5
0
/*
 * This is the ``callback function'' that is invoked by `sysctl_rtsock' in
 * order to copy data out.  See the comments before `get_one_ipaddr' for
 * general information about the data we receive on each callback.
 */
static int
get_one_ipnettomedia(
	struct sysctl_req *	req,
	const void *		buf,
	size_t			buf_size)
{
	get_ipnettomedia_env_t *	env = (get_ipnettomedia_env_t *) req;
	struct ifa_msghdr *		ifam = (struct ifa_msghdr *) buf;
	
	struct rt_addrinfo	rtinfo;
	struct sockaddr_in *	sin;
	
	oskit_u32_t		if_index;
	/* oskit_mib_string_t	phys_address; --- not needed. */
	oskit_mib_in_addr_t	net_address;
	oskit_u32_t		type;
	
	/*********************************************************************/
	
	/*
	 * We get physical addresses from `RTM_IFINFO' messages, and we get IP
	 * addresses from subsequent `RTM_NEWADDR' messages.  Note that there
	 * may be more than one IP address per interface.
	 *
	 */
	if (ifam->ifam_type == RTM_IFINFO) {
		struct if_msghdr *	ifm = (struct if_msghdr *) buf;
		struct sockaddr_dl *	sdl = (struct sockaddr_dl *) (ifm+1);
		
		extract_phys_address(sdl, env);
		
		DEBUG_SET_STATE((env->state = SEEN_IFINFO));
		goto done;
	}
	
	if (ifam->ifam_type != RTM_NEWADDR) {
		assert(!"Received an unknown type of message.");
		goto done;
	}
	
	DEBUG_CHECK_STATE((env->state == SEEN_IFINFO));
	
	/*********************************************************************/
	
	/* If we don't have a valid physical address, bail early. */
	if (!env->phys_address.str)
		goto done;
	
	/*
	 * Figure out what the socket addresses mean; i.e., assign them to the
	 * appropriate elements of the `rtinfo.rti_info' array.
	 */
	rtinfo.rti_addrs = ifam->ifam_addrs;
	rt_xaddrs(((char *) (ifam + 1)),
		  ((char *) ifam) + ifam->ifam_msglen,
		  &rtinfo);
	
	/*
	 * From `env->phys_address' and `rtinfo', decode the fields of our
	 * table row.
	 */
	if_index = ifam->ifam_index;
	
	/* phys_address = env->phys_address; --- why bother? */
	
	sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_IFA];
	if (!sin)
		/* No interface address?! */
		goto done;
	net_address = sin->sin_addr.s_addr;
	
	/*
	 * XXX --- Perhaps this isn't right, but I'm not sure what is.  The
	 * UCD-SNMP code returns `static' for permanent ARP cache entries and
	 * `dynamic' for others.  But that doesn't seem right: what exactly is
	 * dynamic about a host's own IP-->Ethernet mappings?
	 */
	type = OSKIT_MIB_IP_NET_TO_MEDIA_TYPE_STATIC;
	
	/*********************************************************************/
	
	/*
	 * Process the entry.
	 */
	if (ipnettomedia_match(if_index, env->phys_address, net_address, type,
			       env->args.matching)) {
		if (env->args.start_row > 0) {
			/* Skip this row. */
			env->args.start_row--;
		} else if (env->args.want_rows > 0) {
			/* Accumulate this row. */
#define COPY_OUT(slot_type, slot_name)					\
	oskit_mib_##slot_type##_set(					\
		&(env->args.table->ip_net_to_media_##slot_name),	\
		slot_name)
			COPY_OUT(u32, if_index);
			copy_out_str(&(env->args.table->
				       ip_net_to_media_phys_address),
				     &(env->phys_address));
			COPY_OUT(mib_in_addr, net_address);
			COPY_OUT(u32, type);
#undef COPY_OUT
			(*env->args.out_rows)++;
			env->args.table++;
			env->args.want_rows--;
			
		} else {
			/* Indicate that the table filled up. */
			*env->args.more_rows = 1;
		}
	}
	
 done:
	/* Indicate to the `sysctl_rtsock' function that no error occurred. */
	return 0;
}
Example #6
0
/*
 * This is the ``callback function'' that is invoked by `sysctl_rtsock' in
 * order to copy data out.  The data that is given to us is as follows:
 *
 *   + First, we are called with a buffer containing a `struct if_msghdr', with
 *     the type member set to `RTM_IFINFO'.  This signals the start of a group
 *     of callbacks about a particular interface.  The `if_msghdr' is followed
 *     by zero of more `struct sockaddr_dl's (in the same buffer).
 *
 *   + Subsequent callbacks will receive a `struct ifa_msghdr' (with its type
 *     member set to `RTM_NEWADDR') followed immediatley by zero or more
 *     `struct sockaddr_in's.  This describes a particular group of (IP)
 *     addresses for an interface.
 *
 * These callbacks are performed one for each interface.  I.e., for each
 * interface, we will receive a `RTM_IFINFO' callback followed by zero or more
 * `RTM_NEWADDR' callbacks.
 *
 * See the function `sysctl_rtsock' for further details.  Some of the code
 * below is modeled after code in the FreeBSD `ifconfig' utility; in FreeBSD,
 * see the file `/usr/src/sbin/ifconfig/ifconfig.c'.
 */
static int
get_one_ipaddr(
	struct sysctl_req *	req,
	const void *		buf,
	size_t			buf_size)
{
	get_ipaddr_env_t *	env = (get_ipaddr_env_t *) req;
	struct ifa_msghdr *	ifam = (struct ifa_msghdr *) buf;
	
	struct rt_addrinfo	rtinfo;
	struct sockaddr_in *	sin;
	
	oskit_mib_in_addr_t	addr;
	oskit_u32_t		if_index;
	oskit_mib_in_addr_t	net_mask;
	oskit_u32_t		bcast_addr;
	oskit_u16_t		reasm_max_size;
	
	/*********************************************************************/
	
	/*
	 * Mainly, we care about `RTM_NEWADDR' messages.  Each of these
	 * messages contains a `struct ifa_msghdr' followed by a set of socket
	 * addresses (`struct sockaddr_in's).
	 *
	 * We need `RTM_IFINFO' messages only to set our `env->ifinfo_flags'.
	 * One of these messages contains a `struct if_msghdr' (followed by a
	 * set of `struct sockaddr_dl's, which we don't care about here).
	 */
	if (ifam->ifam_type == RTM_IFINFO) {
		env->ifinfo_flags = ((struct if_msghdr *) buf)->ifm_flags;
		DEBUG_SET_STATE((env->state = SEEN_IFINFO));
		goto done;
	}
	
	if (ifam->ifam_type != RTM_NEWADDR) {
		assert(!"Received an unknown type of message.");
		goto done;
	}
	
	DEBUG_CHECK_STATE((env->state == SEEN_IFINFO));
	
	/*********************************************************************/
	
	/*
	 * Figure out what the socket addresses mean; i.e., assign them to the
	 * appropriate elements of the `rtinfo.rti_info' array.
	 */
	rtinfo.rti_addrs = ifam->ifam_addrs;
	rt_xaddrs(((char *) (ifam + 1)),
		  ((char *) ifam) + ifam->ifam_msglen,
		  &rtinfo);
	
	/*
	 * From `rtinfo', decode the fields of our table row.
	 */
	
	sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_IFA];
	if (!sin)
		/* No interface address?! */
		goto done;
	addr = sin->sin_addr.s_addr;
	
	if_index = ifam->ifam_index;
	
	sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_NETMASK];
	if (!sin)
		/* No network mask?! */
		goto done;
	net_mask = sin->sin_addr.s_addr;
	
	/* XXX --- Default `bcast_addr' to one. */
	bcast_addr = 1;
	/*
	 * For point-to-point links, `rti_info[RTAX_BRD]' holds the destination
	 * address.  So, one must check for the `IFF_BROADCAST' flag.
	 */
	if (env->ifinfo_flags & IFF_BROADCAST) {
		sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_BRD];
		if (sin)
			bcast_addr = (ntohl(sin->sin_addr.s_addr) & 1);
	}
	
	/*
	 * I'm pretty sure that the `reasm_max_size' is `IP_MAXPACKET' for all
	 * interfaces.
	 */
	reasm_max_size = IP_MAXPACKET;
	
	/*********************************************************************/
	
	/*
	 * Process the entry.
	 */
	if (ipaddr_match(addr, if_index, net_mask, bcast_addr, reasm_max_size,
			 env->args.matching)) {
		if (env->args.start_row > 0) {
			/* Skip this row. */
			env->args.start_row--;
		} else if (env->args.want_rows > 0) {
			/* Accumulate this row. */
#define COPY_OUT(slot_type, slot_name)				\
	oskit_mib_##slot_type##_set(				\
		&(env->args.table->ip_ad_ent_##slot_name),	\
		slot_name)
			COPY_OUT(mib_in_addr, addr);
			COPY_OUT(u32, if_index);
			COPY_OUT(mib_in_addr, net_mask);
			COPY_OUT(u32, bcast_addr);
			COPY_OUT(u16, reasm_max_size);
#undef COPY_OUT
			(*env->args.out_rows)++;
			env->args.table++;
			env->args.want_rows--;
			
		} else {
			/* Indicate that the table filled up. */
			*env->args.more_rows = 1;
		}
	}
	
 done:
	/* Indicate to the `sysctl_rtsock' function that no error occurred. */
	return 0;
}