Diff for /embedaddon/quagga/lib/vty.c between versions 1.1.1.2 and 1.1.1.4

version 1.1.1.2, 2012/10/09 09:22:28 version 1.1.1.4, 2016/11/02 10:09:10
Line 38 Line 38
 #include "network.h"  #include "network.h"
   
 #include <arpa/telnet.h>  #include <arpa/telnet.h>
   #include <termios.h>
   
 /* Vty events */  /* Vty events */
 enum event   enum event 
Line 57  static void vty_event (enum event, int, struct vty *); Line 58  static void vty_event (enum event, int, struct vty *);
   
 /* Extern host structure from command.c */  /* Extern host structure from command.c */
 extern struct host host;  extern struct host host;
 /* Vector which store each vty structure. */  /* Vector which store each vty structure. */
 static vector vtyvec;  static vector vtyvec;
   
Line 71  static char *vty_accesslist_name = NULL; Line 72  static char *vty_accesslist_name = NULL;
 static char *vty_ipv6_accesslist_name = NULL;  static char *vty_ipv6_accesslist_name = NULL;
   
 /* VTY server thread. */  /* VTY server thread. */
vector Vvty_serv_thread;static vector Vvty_serv_thread;
   
 /* Current directory. */  /* Current directory. */
 char *vty_cwd = NULL;  char *vty_cwd = NULL;
Line 89  static u_char restricted_mode = 0; Line 90  static u_char restricted_mode = 0;
 /* Integrated configuration file path */  /* Integrated configuration file path */
 char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;  char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
   
 /* VTY standard output function. */  /* VTY standard output function. */
 int  int
 vty_out (struct vty *vty, const char *format, ...)  vty_out (struct vty *vty, const char *format, ...)
Line 110  vty_out (struct vty *vty, const char *format, ...) Line 111  vty_out (struct vty *vty, const char *format, ...)
     {      {
       /* Try to write to initial buffer.  */        /* Try to write to initial buffer.  */
       va_start (args, format);        va_start (args, format);
      len = vsnprintf (buf, sizeof buf, format, args);      len = vsnprintf (buf, sizeof(buf), format, args);
       va_end (args);        va_end (args);
   
       /* Initial buffer is not enough.  */        /* Initial buffer is not enough.  */
Line 184  vty_log_out (struct vty *vty, const char *level, const Line 185  vty_log_out (struct vty *vty, const char *level, const
   buf[len++] = '\r';    buf[len++] = '\r';
   buf[len++] = '\n';    buf[len++] = '\n';
   
  if (write(vty->fd, buf, len) < 0)  if (write(vty->wfd, buf, len) < 0)
     {      {
       if (ERRNO_IO_RETRY(errno))        if (ERRNO_IO_RETRY(errno))
         /* Kernel buffer is full, probably too much debugging output, so just          /* Kernel buffer is full, probably too much debugging output, so just
Line 400  vty_command (struct vty *vty, char *buf) Line 401  vty_command (struct vty *vty, char *buf)
   int ret;    int ret;
   vector vline;    vector vline;
   const char *protocolname;    const char *protocolname;
     char *cp;
   
     /*
      * Log non empty command lines
      */
     cp = buf;
     if (cp != NULL)
       {
         /* Skip white spaces. */
         while (isspace ((int) *cp) && *cp != '\0')
           cp++;
       }
     if (cp != NULL && *cp != '\0')
       {
         unsigned i;
         char      vty_str[VTY_BUFSIZ];
         char        prompt_str[VTY_BUFSIZ];
   
         /* format the base vty info */
         snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address);
         if (vty)
           for (i = 0; i < vector_active (vtyvec); i++)
             if ((vty == vector_slot (vtyvec, i)))
               {
                 snprintf(vty_str, sizeof(vty_str), "vty[%d]@%s",
                                                    i, vty->address);
                 break;
               }
   
         /* format the prompt */
         snprintf(prompt_str, sizeof(prompt_str), cmd_prompt (vty->node), vty_str);
   
         /* now log the command */
         zlog(NULL, LOG_NOTICE, "%s%s", prompt_str, buf);
       }
   /* Split readline string up into the vector */    /* Split readline string up into the vector */
   vline = cmd_make_strvec (buf);    vline = cmd_make_strvec (buf);
   
Line 455  vty_command (struct vty *vty, char *buf) Line 490  vty_command (struct vty *vty, char *buf)
   
   return ret;    return ret;
 }  }
 static const char telnet_backward_char = 0x08;  static const char telnet_backward_char = 0x08;
 static const char telnet_space_char = ' ';  static const char telnet_space_char = ' ';
   
Line 702  vty_end_config (struct vty *vty) Line 737  vty_end_config (struct vty *vty)
     case BABEL_NODE:      case BABEL_NODE:
     case BGP_NODE:      case BGP_NODE:
     case BGP_VPNV4_NODE:      case BGP_VPNV4_NODE:
       case BGP_VPNV6_NODE:
       case BGP_ENCAP_NODE:
       case BGP_ENCAPV6_NODE:
     case BGP_IPV4_NODE:      case BGP_IPV4_NODE:
     case BGP_IPV4M_NODE:      case BGP_IPV4M_NODE:
     case BGP_IPV6_NODE:      case BGP_IPV6_NODE:
Line 713  vty_end_config (struct vty *vty) Line 751  vty_end_config (struct vty *vty)
     case KEYCHAIN_NODE:      case KEYCHAIN_NODE:
     case KEYCHAIN_KEY_NODE:      case KEYCHAIN_KEY_NODE:
     case MASC_NODE:      case MASC_NODE:
       case PIM_NODE:
     case VTY_NODE:      case VTY_NODE:
       vty_config_unlock (vty);        vty_config_unlock (vty);
       vty->node = ENABLE_NODE;        vty->node = ENABLE_NODE;
Line 869  vty_complete_command (struct vty *vty) Line 908  vty_complete_command (struct vty *vty)
   
   /* In case of 'help \t'. */    /* In case of 'help \t'. */
   if (isspace ((int) vty->buf[vty->length - 1]))    if (isspace ((int) vty->buf[vty->length - 1]))
    vector_set (vline, '\0');    vector_set (vline, NULL);
   
  matched = cmd_complete_command (vline, vty, &ret);  matched = cmd_complete_command_lib (vline, vty, &ret, 1);
       
   cmd_free_strvec (vline);    cmd_free_strvec (vline);
   
Line 931  vty_complete_command (struct vty *vty) Line 970  vty_complete_command (struct vty *vty)
   
 static void  static void
 vty_describe_fold (struct vty *vty, int cmd_width,  vty_describe_fold (struct vty *vty, int cmd_width,
                   unsigned int desc_width, struct desc *desc)                   unsigned int desc_width, struct cmd_token *token)
 {  {
   char *buf;    char *buf;
   const char *cmd, *p;    const char *cmd, *p;
   int pos;    int pos;
   
  cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd;  cmd = token->cmd[0] == '.' ? token->cmd + 1 : token->cmd;
   
   if (desc_width <= 0)    if (desc_width <= 0)
     {      {
      vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, desc->str, VTY_NEWLINE);      vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, token->desc, VTY_NEWLINE);
       return;        return;
     }      }
   
  buf = XCALLOC (MTYPE_TMP, strlen (desc->str) + 1);  buf = XCALLOC (MTYPE_TMP, strlen (token->desc) + 1);
   
  for (p = desc->str; strlen (p) > desc_width; p += pos + 1)  for (p = token->desc; strlen (p) > desc_width; p += pos + 1)
     {      {
       for (pos = desc_width; pos > 0; pos--)        for (pos = desc_width; pos > 0; pos--)
       if (*(p + pos) == ' ')        if (*(p + pos) == ' ')
Line 976  vty_describe_command (struct vty *vty) Line 1015  vty_describe_command (struct vty *vty)
   vector vline;    vector vline;
   vector describe;    vector describe;
   unsigned int i, width, desc_width;    unsigned int i, width, desc_width;
  struct desc *desc, *desc_cr = NULL;  struct cmd_token *token, *token_cr = NULL;
   
   vline = cmd_make_strvec (vty->buf);    vline = cmd_make_strvec (vty->buf);
   
Line 984  vty_describe_command (struct vty *vty) Line 1023  vty_describe_command (struct vty *vty)
   if (vline == NULL)    if (vline == NULL)
     {      {
       vline = vector_init (1);        vline = vector_init (1);
      vector_set (vline, '\0');      vector_set (vline, NULL);
     }      }
   else     else 
     if (isspace ((int) vty->buf[vty->length - 1]))      if (isspace ((int) vty->buf[vty->length - 1]))
      vector_set (vline, '\0');      vector_set (vline, NULL);
   
   describe = cmd_describe_command (vline, vty, &ret);    describe = cmd_describe_command (vline, vty, &ret);
   
Line 1010  vty_describe_command (struct vty *vty) Line 1049  vty_describe_command (struct vty *vty)
   /* Get width of command string. */    /* Get width of command string. */
   width = 0;    width = 0;
   for (i = 0; i < vector_active (describe); i++)    for (i = 0; i < vector_active (describe); i++)
    if ((desc = vector_slot (describe, i)) != NULL)    if ((token = vector_slot (describe, i)) != NULL)
       {        {
         unsigned int len;          unsigned int len;
   
        if (desc->cmd[0] == '\0')        if (token->cmd[0] == '\0')
           continue;            continue;
   
        len = strlen (desc->cmd);        len = strlen (token->cmd);
        if (desc->cmd[0] == '.')        if (token->cmd[0] == '.')
           len--;            len--;
   
         if (width < len)          if (width < len)
Line 1030  vty_describe_command (struct vty *vty) Line 1069  vty_describe_command (struct vty *vty)
   
   /* Print out description. */    /* Print out description. */
   for (i = 0; i < vector_active (describe); i++)    for (i = 0; i < vector_active (describe); i++)
    if ((desc = vector_slot (describe, i)) != NULL)    if ((token = vector_slot (describe, i)) != NULL)
       {        {
        if (desc->cmd[0] == '\0')        if (token->cmd[0] == '\0')
           continue;            continue;
                   
        if (strcmp (desc->cmd, command_cr) == 0)        if (strcmp (token->cmd, command_cr) == 0)
           {            {
            desc_cr = desc;            token_cr = token;
             continue;              continue;
           }            }
   
        if (!desc->str)        if (!token->desc)
           vty_out (vty, "  %-s%s",            vty_out (vty, "  %-s%s",
                   desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,                   token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
                    VTY_NEWLINE);                     VTY_NEWLINE);
        else if (desc_width >= strlen (desc->str))        else if (desc_width >= strlen (token->desc))
           vty_out (vty, "  %-*s  %s%s", width,            vty_out (vty, "  %-*s  %s%s", width,
                   desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,                   token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
                   desc->str, VTY_NEWLINE);                   token->desc, VTY_NEWLINE);
         else          else
          vty_describe_fold (vty, width, desc_width, desc);          vty_describe_fold (vty, width, desc_width, token);
   
 #if 0  #if 0
         vty_out (vty, "  %-*s %s%s", width          vty_out (vty, "  %-*s %s%s", width
Line 1059  vty_describe_command (struct vty *vty) Line 1098  vty_describe_command (struct vty *vty)
 #endif /* 0 */  #endif /* 0 */
       }        }
   
  if ((desc = desc_cr))  if ((token = token_cr))
     {      {
      if (!desc->str)      if (!token->desc)
         vty_out (vty, "  %-s%s",          vty_out (vty, "  %-s%s",
                 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,                 token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
                  VTY_NEWLINE);                   VTY_NEWLINE);
      else if (desc_width >= strlen (desc->str))      else if (desc_width >= strlen (token->desc))
         vty_out (vty, "  %-*s  %s%s", width,          vty_out (vty, "  %-*s  %s%s", width,
                 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,                 token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
                 desc->str, VTY_NEWLINE);                 token->desc, VTY_NEWLINE);
       else        else
        vty_describe_fold (vty, width, desc_width, desc);        vty_describe_fold (vty, width, desc_width, token);
     }      }
   
 out:  out:
Line 1117  vty_stop_input (struct vty *vty) Line 1156  vty_stop_input (struct vty *vty)
     case KEYCHAIN_NODE:      case KEYCHAIN_NODE:
     case KEYCHAIN_KEY_NODE:      case KEYCHAIN_KEY_NODE:
     case MASC_NODE:      case MASC_NODE:
       case PIM_NODE:
     case VTY_NODE:      case VTY_NODE:
       vty_config_unlock (vty);        vty_config_unlock (vty);
       vty->node = ENABLE_NODE;        vty->node = ENABLE_NODE;
Line 1361  vty_read (struct thread *thread) Line 1401  vty_read (struct thread *thread)
           vty->monitor = 0; /* disable monitoring to avoid infinite recursion */            vty->monitor = 0; /* disable monitoring to avoid infinite recursion */
           zlog_warn("%s: read error on vty client fd %d, closing: %s",            zlog_warn("%s: read error on vty client fd %d, closing: %s",
                     __func__, vty->fd, safe_strerror(errno));                      __func__, vty->fd, safe_strerror(errno));
             buffer_reset(vty->obuf);
         }          }
       buffer_reset(vty->obuf);  
       vty->status = VTY_CLOSE;        vty->status = VTY_CLOSE;
     }      }
   
Line 1540  vty_read (struct thread *thread) Line 1580  vty_read (struct thread *thread)
     vty_close (vty);      vty_close (vty);
   else    else
     {      {
      vty_event (VTY_WRITE, vty_sock, vty);      vty_event (VTY_WRITE, vty->wfd, vty);
       vty_event (VTY_READ, vty_sock, vty);        vty_event (VTY_READ, vty_sock, vty);
     }      }
   return 0;    return 0;
Line 1568  vty_flush (struct thread *thread) Line 1608  vty_flush (struct thread *thread)
   erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE));    erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE));
   
   /* N.B. if width is 0, that means we don't know the window size. */    /* N.B. if width is 0, that means we don't know the window size. */
  if ((vty->lines == 0) || (vty->width == 0))  if ((vty->lines == 0) || (vty->width == 0) || (vty->height == 0))
    flushrc = buffer_flush_available(vty->obuf, vty->fd);    flushrc = buffer_flush_available(vty->obuf, vty_sock);
   else if (vty->status == VTY_MORELINE)    else if (vty->status == VTY_MORELINE)
    flushrc = buffer_flush_window(vty->obuf, vty->fd, vty->width,    flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width,
                                   1, erase, 0);                                    1, erase, 0);
   else    else
    flushrc = buffer_flush_window(vty->obuf, vty->fd, vty->width,    flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width,
                                   vty->lines >= 0 ? vty->lines :                                    vty->lines >= 0 ? vty->lines :
                                                     vty->height,                                                      vty->height,
                                   erase, 0);                                    erase, 0);
Line 1608  vty_flush (struct thread *thread) Line 1648  vty_flush (struct thread *thread)
   return 0;    return 0;
 }  }
   
/* Create new vty structure. *//* allocate and initialise vty */
 static struct vty *  static struct vty *
vty_create (int vty_sock, union sockunion *su)vty_new_init (int vty_sock)
 {  {
   struct vty *vty;    struct vty *vty;
   
   /* Allocate new vty structure and set up default values. */  
   vty = vty_new ();    vty = vty_new ();
   vty->fd = vty_sock;    vty->fd = vty_sock;
     vty->wfd = vty_sock;
   vty->type = VTY_TERM;    vty->type = VTY_TERM;
  vty->address = sockunion_su2str (su);  vty->node = AUTH_NODE;
  if (no_password_check) 
    { 
      if (restricted_mode) 
        vty->node = RESTRICTED_NODE; 
      else if (host.advanced) 
        vty->node = ENABLE_NODE; 
      else 
        vty->node = VIEW_NODE; 
    } 
  else 
    vty->node = AUTH_NODE; 
   vty->fail = 0;    vty->fail = 0;
   vty->cp = 0;    vty->cp = 0;
   vty_clear_buf (vty);    vty_clear_buf (vty);
Line 1639  vty_create (int vty_sock, union sockunion *su) Line 1668  vty_create (int vty_sock, union sockunion *su)
   vty->hindex = 0;    vty->hindex = 0;
   vector_set_index (vtyvec, vty_sock, vty);    vector_set_index (vtyvec, vty_sock, vty);
   vty->status = VTY_NORMAL;    vty->status = VTY_NORMAL;
  vty->v_timeout = vty_timeout_val;  vty->lines = -1;
  if (host.lines >= 0) 
    vty->lines = host.lines; 
  else 
    vty->lines = -1; 
   vty->iac = 0;    vty->iac = 0;
   vty->iac_sb_in_progress = 0;    vty->iac_sb_in_progress = 0;
   vty->sb_len = 0;    vty->sb_len = 0;
   
     return vty;
   }
   
   /* Create new vty structure. */
   static struct vty *
   vty_create (int vty_sock, union sockunion *su)
   {
     char buf[SU_ADDRSTRLEN];
     struct vty *vty;
   
     sockunion2str(su, buf, SU_ADDRSTRLEN);
   
     /* Allocate new vty structure and set up default values. */
     vty = vty_new_init (vty_sock);
   
     /* configurable parameters not part of basic init */
     vty->v_timeout = vty_timeout_val;
     strcpy (vty->address, buf);
     if (no_password_check)
       {
         if (restricted_mode)
           vty->node = RESTRICTED_NODE;
         else if (host.advanced)
           vty->node = ENABLE_NODE;
         else
           vty->node = VIEW_NODE;
       }
     if (host.lines >= 0)
       vty->lines = host.lines;
   
   if (! no_password_check)    if (! no_password_check)
     {      {
       /* Vty is not available if password isn't set. */        /* Vty is not available if password isn't set. */
Line 1682  vty_create (int vty_sock, union sockunion *su) Line 1737  vty_create (int vty_sock, union sockunion *su)
   return vty;    return vty;
 }  }
   
   /* create vty for stdio */
   static struct termios stdio_orig_termios;
   static struct vty *stdio_vty = NULL;
   static void (*stdio_vty_atclose)(void);
   
   static void
   vty_stdio_reset (void)
   {
     if (stdio_vty)
       {
         tcsetattr (0, TCSANOW, &stdio_orig_termios);
         stdio_vty = NULL;
   
         if (stdio_vty_atclose)
           stdio_vty_atclose ();
         stdio_vty_atclose = NULL;
       }
   }
   
   struct vty *
   vty_stdio (void (*atclose)())
   {
     struct vty *vty;
     struct termios termios;
   
     /* refuse creating two vtys on stdio */
     if (stdio_vty)
       return NULL;
   
     vty = stdio_vty = vty_new_init (0);
     stdio_vty_atclose = atclose;
     vty->wfd = 1;
   
     /* always have stdio vty in a known _unchangeable_ state, don't want config
      * to have any effect here to make sure scripting this works as intended */
     vty->node = ENABLE_NODE;
     vty->v_timeout = 0;
     strcpy (vty->address, "console");
   
     if (!tcgetattr (0, &stdio_orig_termios))
       {
         termios = stdio_orig_termios;
         termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
                              | INLCR | IGNCR | ICRNL | IXON);
         termios.c_oflag &= ~OPOST;
         termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
         termios.c_cflag &= ~(CSIZE | PARENB);
         termios.c_cflag |= CS8;
         tcsetattr (0, TCSANOW, &termios);
       }
   
     vty_prompt (vty);
   
     /* Add read/write thread. */
     vty_event (VTY_WRITE, 1, vty);
     vty_event (VTY_READ, 0, vty);
   
     return vty;
   }
   
 /* Accept connection from the network. */  /* Accept connection from the network. */
 static int  static int
 vty_accept (struct thread *thread)  vty_accept (struct thread *thread)
Line 1691  vty_accept (struct thread *thread) Line 1806  vty_accept (struct thread *thread)
   int ret;    int ret;
   unsigned int on;    unsigned int on;
   int accept_sock;    int accept_sock;
  struct prefix *p = NULL;  struct prefix p;
   struct access_list *acl = NULL;    struct access_list *acl = NULL;
  char *bufp;  char buf[SU_ADDRSTRLEN];
   
   accept_sock = THREAD_FD (thread);    accept_sock = THREAD_FD (thread);
   
Line 1711  vty_accept (struct thread *thread) Line 1826  vty_accept (struct thread *thread)
     }      }
   set_nonblocking(vty_sock);    set_nonblocking(vty_sock);
   
  p = sockunion2hostprefix (&su);  sockunion2hostprefix (&su, &p);
   
   /* VTY's accesslist apply. */    /* VTY's accesslist apply. */
  if (p->family == AF_INET && vty_accesslist_name)  if (p.family == AF_INET && vty_accesslist_name)
     {      {
       if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) &&        if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) &&
          (access_list_apply (acl, p) == FILTER_DENY))          (access_list_apply (acl, &p) == FILTER_DENY))
         {          {
           char *buf;  
           zlog (NULL, LOG_INFO, "Vty connection refused from %s",            zlog (NULL, LOG_INFO, "Vty connection refused from %s",
                (buf = sockunion_su2str (&su)));                sockunion2str (&su, buf, SU_ADDRSTRLEN));
          free (buf); 
           close (vty_sock);            close (vty_sock);
                       
           /* continue accepting connections */            /* continue accepting connections */
           vty_event (VTY_SERV, accept_sock, NULL);            vty_event (VTY_SERV, accept_sock, NULL);
                       
           prefix_free (p);  
   
           return 0;            return 0;
         }          }
     }      }
   
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   /* VTY's ipv6 accesslist apply. */    /* VTY's ipv6 accesslist apply. */
  if (p->family == AF_INET6 && vty_ipv6_accesslist_name)  if (p.family == AF_INET6 && vty_ipv6_accesslist_name)
     {      {
       if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) &&        if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) &&
          (access_list_apply (acl, p) == FILTER_DENY))          (access_list_apply (acl, &p) == FILTER_DENY))
         {          {
           char *buf;  
           zlog (NULL, LOG_INFO, "Vty connection refused from %s",            zlog (NULL, LOG_INFO, "Vty connection refused from %s",
                (buf = sockunion_su2str (&su)));                sockunion2str (&su, buf, SU_ADDRSTRLEN));
          free (buf); 
           close (vty_sock);            close (vty_sock);
                       
           /* continue accepting connections */            /* continue accepting connections */
           vty_event (VTY_SERV, accept_sock, NULL);            vty_event (VTY_SERV, accept_sock, NULL);
                       
           prefix_free (p);  
   
           return 0;            return 0;
         }          }
     }      }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
       
   prefix_free (p);  
   
   on = 1;    on = 1;
   ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY,     ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY, 
                     (char *) &on, sizeof (on));                      (char *) &on, sizeof (on));
Line 1767  vty_accept (struct thread *thread) Line 1872  vty_accept (struct thread *thread)
           safe_strerror (errno));            safe_strerror (errno));
   
   zlog (NULL, LOG_INFO, "Vty connection from %s",    zlog (NULL, LOG_INFO, "Vty connection from %s",
    (bufp = sockunion_su2str (&su)));        sockunion2str (&su, buf, SU_ADDRSTRLEN));
  if (bufp) 
    XFREE (MTYPE_TMP, bufp); 
   
   vty_create (vty_sock, &su);    vty_create (vty_sock, &su);
   
   return 0;    return 0;
 }  }
   
#if defined(HAVE_IPV6) && !defined(NRL)#ifdef HAVE_IPV6
 static void  static void
 vty_serv_sock_addrinfo (const char *hostname, unsigned short port)  vty_serv_sock_addrinfo (const char *hostname, unsigned short port)
 {  {
Line 1841  vty_serv_sock_addrinfo (const char *hostname, unsigned Line 1944  vty_serv_sock_addrinfo (const char *hostname, unsigned
   
   freeaddrinfo (ainfo_save);    freeaddrinfo (ainfo_save);
 }  }
#else /* HAVE_IPV6 && ! NRL */#else /* HAVE_IPV6 */
   
 /* Make vty server socket. */  /* Make vty server socket. */
 static void  static void
Line 1859  vty_serv_sock_family (const char* addr, unsigned short Line 1962  vty_serv_sock_family (const char* addr, unsigned short
     {      {
       case AF_INET:        case AF_INET:
         naddr=&su.sin.sin_addr;          naddr=&su.sin.sin_addr;
           break;
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
       case AF_INET6:        case AF_INET6:
         naddr=&su.sin6.sin6_addr;          naddr=&su.sin6.sin6_addr;
           break;
 #endif    #endif  
     }      }
   
Line 1907  vty_serv_sock_family (const char* addr, unsigned short Line 2012  vty_serv_sock_family (const char* addr, unsigned short
   /* Add vty server event. */    /* Add vty server event. */
   vty_event (VTY_SERV, accept_sock, NULL);    vty_event (VTY_SERV, accept_sock, NULL);
 }  }
#endif /* HAVE_IPV6 && ! NRL */#endif /* HAVE_IPV6 */
   
 #ifdef VTYSH  #ifdef VTYSH
 /* For sockaddr_un. */  /* For sockaddr_un. */
Line 2021  vtysh_accept (struct thread *thread) Line 2126  vtysh_accept (struct thread *thread)
   
   vty = vty_new ();    vty = vty_new ();
   vty->fd = sock;    vty->fd = sock;
     vty->wfd = sock;
   vty->type = VTY_SHELL_SERV;    vty->type = VTY_SHELL_SERV;
   vty->node = VIEW_NODE;    vty->node = VIEW_NODE;
   
Line 2032  vtysh_accept (struct thread *thread) Line 2138  vtysh_accept (struct thread *thread)
 static int  static int
 vtysh_flush(struct vty *vty)  vtysh_flush(struct vty *vty)
 {  {
  switch (buffer_flush_available(vty->obuf, vty->fd))  switch (buffer_flush_available(vty->obuf, vty->wfd))
     {      {
     case BUFFER_PENDING:      case BUFFER_PENDING:
      vty_event(VTYSH_WRITE, vty->fd, vty);      vty_event(VTYSH_WRITE, vty->wfd, vty);
       break;        break;
     case BUFFER_ERROR:      case BUFFER_ERROR:
       vty->monitor = 0; /* disable monitoring to avoid infinite recursion */        vty->monitor = 0; /* disable monitoring to avoid infinite recursion */
Line 2142  vty_serv_sock (const char *addr, unsigned short port,  Line 2248  vty_serv_sock (const char *addr, unsigned short port, 
     {      {
   
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
 #ifdef NRL  
       vty_serv_sock_family (addr, port, AF_INET);  
       vty_serv_sock_family (addr, port, AF_INET6);  
 #else /* ! NRL */  
       vty_serv_sock_addrinfo (addr, port);        vty_serv_sock_addrinfo (addr, port);
 #endif /* NRL*/  
 #else /* ! HAVE_IPV6 */  #else /* ! HAVE_IPV6 */
       vty_serv_sock_family (addr,port, AF_INET);        vty_serv_sock_family (addr,port, AF_INET);
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
Line 2176  vty_close (struct vty *vty) Line 2277  vty_close (struct vty *vty)
     thread_cancel (vty->t_timeout);      thread_cancel (vty->t_timeout);
   
   /* Flush buffer. */    /* Flush buffer. */
  buffer_flush_all (vty->obuf, vty->fd);  buffer_flush_all (vty->obuf, vty->wfd);
   
   /* Free input buffer. */    /* Free input buffer. */
   buffer_free (vty->obuf);    buffer_free (vty->obuf);
Line 2192  vty_close (struct vty *vty) Line 2293  vty_close (struct vty *vty)
   /* Close socket. */    /* Close socket. */
   if (vty->fd > 0)    if (vty->fd > 0)
     close (vty->fd);      close (vty->fd);
     else
       vty_stdio_reset ();
   
   if (vty->address)  
     XFREE (MTYPE_TMP, vty->address);  
   if (vty->buf)    if (vty->buf)
     XFREE (MTYPE_VTY, vty->buf);      XFREE (MTYPE_VTY, vty->buf);
   
Line 2232  vty_read_file (FILE *confp) Line 2333  vty_read_file (FILE *confp)
 {  {
   int ret;    int ret;
   struct vty *vty;    struct vty *vty;
     unsigned int line_num = 0;
   
   vty = vty_new ();    vty = vty_new ();
  vty->fd = 0;                      /* stdout */  vty->wfd = dup(STDERR_FILENO); /* vty_close() will close this */
  vty->type = VTY_TERM;  if (vty->wfd < 0)
   {
     /* Fine, we couldn't make a new fd. vty_close doesn't close stdout. */
     vty->wfd = STDOUT_FILENO;
   }
   vty->fd = STDIN_FILENO;
   vty->type = VTY_FILE;
   vty->node = CONFIG_NODE;    vty->node = CONFIG_NODE;
       
   /* Execute configuration file */    /* Execute configuration file */
  ret = config_from_file (vty, confp);  ret = config_from_file (vty, confp, &line_num);
   
     /* Flush any previous errors before printing messages below */
     buffer_flush_all (vty->obuf, vty->fd);
   
   if ( !((ret == CMD_SUCCESS) || (ret == CMD_ERR_NOTHING_TODO)) )     if ( !((ret == CMD_SUCCESS) || (ret == CMD_ERR_NOTHING_TODO)) ) 
     {      {
       switch (ret)        switch (ret)
        {         {
          case CMD_ERR_AMBIGUOUS:           case CMD_ERR_AMBIGUOUS:
           fprintf (stderr, "Ambiguous command.\n");           fprintf (stderr, "*** Error reading config: Ambiguous command.\n");
            break;             break;
          case CMD_ERR_NO_MATCH:           case CMD_ERR_NO_MATCH:
           fprintf (stderr, "There is no such command.\n");           fprintf (stderr, "*** Error reading config: There is no such command.\n");
            break;             break;
        }         }
      fprintf (stderr, "Error occured during reading below line.\n%s\n",       fprintf (stderr, "*** Error occured processing line %u, below:\n%s\n",
               vty->buf);                       line_num, vty->buf);
       vty_close (vty);        vty_close (vty);
       exit (1);        exit (1);
     }      }
Line 2452  vty_log (const char *level, const char *proto_str, Line 2563  vty_log (const char *level, const char *proto_str,
   
 /* Async-signal-safe version of vty_log for fixed strings. */  /* Async-signal-safe version of vty_log for fixed strings. */
 void  void
vty_log_fixed (const char *buf, size_t len)vty_log_fixed (char *buf, size_t len)
 {  {
   unsigned int i;    unsigned int i;
   struct iovec iov[2];    struct iovec iov[2];
Line 2461  vty_log_fixed (const char *buf, size_t len) Line 2572  vty_log_fixed (const char *buf, size_t len)
   if (!vtyvec)    if (!vtyvec)
     return;      return;
       
  iov[0].iov_base = (void *)buf;  iov[0].iov_base = buf;
   iov[0].iov_len = len;    iov[0].iov_len = len;
   iov[1].iov_base = (void *)"\r\n";    iov[1].iov_base = (void *)"\r\n";
   iov[1].iov_len = 2;    iov[1].iov_len = 2;
Line 2472  vty_log_fixed (const char *buf, size_t len) Line 2583  vty_log_fixed (const char *buf, size_t len)
       if (((vty = vector_slot (vtyvec, i)) != NULL) && vty->monitor)        if (((vty = vector_slot (vtyvec, i)) != NULL) && vty->monitor)
         /* N.B. We don't care about the return code, since process is          /* N.B. We don't care about the return code, since process is
            most likely just about to die anyway. */             most likely just about to die anyway. */
        writev(vty->fd, iov, 2);        writev(vty->wfd, iov, 2);
     }      }
 }  }
   
Line 2497  vty_config_unlock (struct vty *vty) Line 2608  vty_config_unlock (struct vty *vty)
     }      }
   return vty->config;    return vty->config;
 }  }
 /* Master of the threads. */  /* Master of the threads. */
static struct thread_master *master;static struct thread_master *vty_master;
   
 static void  static void
 vty_event (enum event event, int sock, struct vty *vty)  vty_event (enum event event, int sock, struct vty *vty)
Line 2509  vty_event (enum event event, int sock, struct vty *vty Line 2620  vty_event (enum event event, int sock, struct vty *vty
   switch (event)    switch (event)
     {      {
     case VTY_SERV:      case VTY_SERV:
      vty_serv_thread = thread_add_read (master, vty_accept, vty, sock);      vty_serv_thread = thread_add_read (vty_master, vty_accept, vty, sock);
       vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);        vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
       break;        break;
 #ifdef VTYSH  #ifdef VTYSH
     case VTYSH_SERV:      case VTYSH_SERV:
      thread_add_read (master, vtysh_accept, vty, sock);      vty_serv_thread = thread_add_read (vty_master, vtysh_accept, vty, sock);
       vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
       break;        break;
     case VTYSH_READ:      case VTYSH_READ:
      vty->t_read = thread_add_read (master, vtysh_read, vty, sock);      vty->t_read = thread_add_read (vty_master, vtysh_read, vty, sock);
       break;        break;
     case VTYSH_WRITE:      case VTYSH_WRITE:
      vty->t_write = thread_add_write (master, vtysh_write, vty, sock);      vty->t_write = thread_add_write (vty_master, vtysh_write, vty, sock);
       break;        break;
 #endif /* VTYSH */  #endif /* VTYSH */
     case VTY_READ:      case VTY_READ:
      vty->t_read = thread_add_read (master, vty_read, vty, sock);      vty->t_read = thread_add_read (vty_master, vty_read, vty, sock);
   
       /* Time out treatment. */        /* Time out treatment. */
       if (vty->v_timeout)        if (vty->v_timeout)
Line 2532  vty_event (enum event event, int sock, struct vty *vty Line 2644  vty_event (enum event event, int sock, struct vty *vty
           if (vty->t_timeout)            if (vty->t_timeout)
             thread_cancel (vty->t_timeout);              thread_cancel (vty->t_timeout);
           vty->t_timeout =             vty->t_timeout = 
            thread_add_timer (master, vty_timeout, vty, vty->v_timeout);            thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout);
         }          }
       break;        break;
     case VTY_WRITE:      case VTY_WRITE:
       if (! vty->t_write)        if (! vty->t_write)
        vty->t_write = thread_add_write (master, vty_flush, vty, sock);        vty->t_write = thread_add_write (vty_master, vty_flush, vty, sock);
       break;        break;
     case VTY_TIMEOUT_RESET:      case VTY_TIMEOUT_RESET:
       if (vty->t_timeout)        if (vty->t_timeout)
Line 2548  vty_event (enum event event, int sock, struct vty *vty Line 2660  vty_event (enum event event, int sock, struct vty *vty
       if (vty->v_timeout)        if (vty->v_timeout)
         {          {
           vty->t_timeout =             vty->t_timeout = 
            thread_add_timer (master, vty_timeout, vty, vty->v_timeout);            thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout);
         }          }
       break;        break;
     }      }
 }  }
 DEFUN (config_who,  DEFUN (config_who,
        config_who_cmd,         config_who_cmd,
        "who",         "who",
Line 2960  vty_init (struct thread_master *master_thread) Line 3072  vty_init (struct thread_master *master_thread)
   
   vtyvec = vector_init (VECTOR_MIN_SIZE);    vtyvec = vector_init (VECTOR_MIN_SIZE);
   
  master = master_thread;  vty_master = master_thread;
 
   atexit (vty_stdio_reset);
   
   /* Initilize server thread vector. */    /* Initilize server thread vector. */
   Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE);    Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE);

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>