📄 vty.c
字号:
break; case CONTROL('K'): vty_kill_line (vty); break; case CONTROL('N'): vty_next_line (vty); break; case CONTROL('P'): vty_previous_line (vty); break; case CONTROL('T'): vty_transpose_chars (vty); break; case CONTROL('U'): vty_kill_line_from_beginning (vty); break; case CONTROL('W'): vty_backward_kill_word (vty); break; case CONTROL('Z'): vty_end_config (vty); break; case '\n': case '\r': vty_out (vty, "%s", VTY_NEWLINE); vty_execute (vty); break; case '\t': vty_complete_command (vty); break; case '?': if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) vty_self_insert (vty, buf[i]); else vty_describe_command (vty); break; case '\033': if (i + 1 < nbytes && buf[i + 1] == '[') { vty->escape = VTY_ESCAPE; i++; } else vty->escape = VTY_PRE_ESCAPE; break; default: if (buf[i] > 31 && buf[i] < 127) vty_self_insert (vty, buf[i]); break; } } /* Check status. */ if (vty->status == VTY_CLOSE) vty_close (vty); else { vty_event (VTY_WRITE, vty_sock, vty); vty_event (VTY_READ, vty_sock, vty); } return 0;}/* Flush buffer to the vty. */static intvty_flush (struct thread *thread){ int erase; int dont_more; int vty_sock = THREAD_FD (thread); struct vty *vty = THREAD_ARG (thread); vty->t_write = NULL; /* Tempolary disable read thread. */ if (vty->lines == 0) if (vty->t_read) { thread_cancel (vty->t_read); vty->t_read = NULL; } /* Function execution continue. */ if (vty->status == VTY_START || vty->status == VTY_CONTINUE) { if (vty->status == VTY_CONTINUE) erase = 1; else erase = 0; if (vty->output_func == NULL) dont_more = 1; else dont_more = 0; if (vty->lines == 0) { erase = 0; dont_more = 1; } buffer_flush_vty_all (vty->obuf, vty->fd, erase, dont_more); if (vty->status == VTY_CLOSE) { vty_close (vty); return 0; } if (vty->output_func == NULL) { vty->status = VTY_NORMAL; vty_prompt (vty); vty_event (VTY_WRITE, vty_sock, vty); } else vty->status = VTY_MORE; if (vty->lines == 0) { if (vty->output_func == NULL) vty_event (VTY_READ, vty_sock, vty); else { if (vty->output_func) (*vty->output_func) (vty, 0); vty_event (VTY_WRITE, vty_sock, vty); } } } else { if (vty->status == VTY_MORE || vty->status == VTY_MORELINE) erase = 1; else erase = 0; if (vty->lines == 0) buffer_flush_window (vty->obuf, vty->fd, vty->width, 25, 0, 1); else if (vty->status == VTY_MORELINE) buffer_flush_window (vty->obuf, vty->fd, vty->width, 1, erase, 0); else buffer_flush_window (vty->obuf, vty->fd, vty->width, vty->lines >= 0 ? vty->lines : vty->height, erase, 0); if (buffer_empty (vty->obuf)) { if (vty->status == VTY_CLOSE) vty_close (vty); else { vty->status = VTY_NORMAL; if (vty->lines == 0) vty_event (VTY_READ, vty_sock, vty); } } else { vty->status = VTY_MORE; if (vty->lines == 0) vty_event (VTY_WRITE, vty_sock, vty); } } return 0;}/* Create new vty structure. */struct vty *vty_create (int vty_sock, union sockunion *su){ struct vty *vty; /* Allocate new vty structure and set up default values. */ vty = vty_new (); vty->fd = vty_sock; vty->type = VTY_TERM; vty->address = sockunion_su2str (su); if (no_password_check) { if (host.advanced) vty->node = ENABLE_NODE; else vty->node = VIEW_NODE; } else vty->node = AUTH_NODE; vty->fail = 0; vty->cp = 0; vty_clear_buf (vty); vty->length = 0; memset (vty->hist, 0, sizeof (vty->hist)); vty->hp = 0; vty->hindex = 0; vector_set_index (vtyvec, vty_sock, vty); vty->status = VTY_NORMAL; vty->v_timeout = vty_timeout_val; if (host.lines >= 0) vty->lines = host.lines; else vty->lines = -1; vty->iac = 0; vty->iac_sb_in_progress = 0; vty->sb_buffer = buffer_new (1024); if (! no_password_check) { /* Vty is not available if password isn't set. */ if (host.password == NULL && host.password_encrypt == NULL) { vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE); vty->status = VTY_CLOSE; vty_close (vty); return NULL; } } /* Say hello to the world. */ vty_hello (vty); if (! no_password_check) vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); /* Setting up terminal. */ vty_will_echo (vty); vty_will_suppress_go_ahead (vty); vty_dont_linemode (vty); vty_do_window_size (vty); /* vty_dont_lflow_ahead (vty); */ vty_prompt (vty); /* Add read/write thread. */ vty_event (VTY_WRITE, vty_sock, vty); vty_event (VTY_READ, vty_sock, vty); return vty;}/* Accept connection from the network. */static intvty_accept (struct thread *thread){ int vty_sock; struct vty *vty; union sockunion su; int ret; unsigned int on; int accept_sock; struct prefix *p = NULL; struct access_list *acl = NULL; accept_sock = THREAD_FD (thread); /* We continue hearing vty socket. */ vty_event (VTY_SERV, accept_sock, NULL); memset (&su, 0, sizeof (union sockunion)); /* We can handle IPv4 or IPv6 socket. */ vty_sock = sockunion_accept (accept_sock, &su); if (vty_sock < 0) { zlog_warn ("can't accept vty socket : %s", strerror (errno)); return -1; } p = sockunion2hostprefix (&su); /* VTY's accesslist apply. */ if (p->family == AF_INET && vty_accesslist_name) { if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) && (access_list_apply (acl, p) == FILTER_DENY)) { char *buf; zlog (NULL, LOG_INFO, "Vty connection refused from %s", (buf = sockunion_su2str (&su))); free (buf); close (vty_sock); /* continue accepting connections */ vty_event (VTY_SERV, accept_sock, NULL); prefix_free (p); return 0; } }#ifdef HAVE_IPV6 /* VTY's ipv6 accesslist apply. */ if (p->family == AF_INET6 && vty_ipv6_accesslist_name) { if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) && (access_list_apply (acl, p) == FILTER_DENY)) { char *buf; zlog (NULL, LOG_INFO, "Vty connection refused from %s", (buf = sockunion_su2str (&su))); free (buf); close (vty_sock); /* continue accepting connections */ vty_event (VTY_SERV, accept_sock, NULL); prefix_free (p); return 0; } }#endif /* HAVE_IPV6 */ prefix_free (p); on = 1; ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof (on)); if (ret < 0) zlog (NULL, LOG_INFO, "can't set sockopt to vty_sock : %s", strerror (errno)); vty = vty_create (vty_sock, &su); return 0;}#if defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO)voidvty_serv_sock_addrinfo (const char *hostname, unsigned short port){ int ret; struct addrinfo req; struct addrinfo *ainfo; struct addrinfo *ainfo_save; int sock; char port_str[BUFSIZ]; memset (&req, 0, sizeof (struct addrinfo)); req.ai_flags = AI_PASSIVE; req.ai_family = AF_UNSPEC; req.ai_socktype = SOCK_STREAM; sprintf (port_str, "%d", port); port_str[sizeof (port_str) - 1] = '\0'; ret = getaddrinfo (hostname, port_str, &req, &ainfo); if (ret != 0) { fprintf (stderr, "getaddrinfo failed: %s\n", gai_strerror (ret)); exit (1); } ainfo_save = ainfo; do { if (ainfo->ai_family != AF_INET#ifdef HAVE_IPV6 && ainfo->ai_family != AF_INET6#endif /* HAVE_IPV6 */ ) continue; sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol); if (sock < 0) continue; sockopt_reuseaddr (sock); sockopt_reuseport (sock); ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen); if (ret < 0) { close (sock); /* Avoid sd leak. */ continue; } ret = listen (sock, 3); if (ret < 0) { close (sock); /* Avoid sd leak. */ continue; } vty_event (VTY_SERV, sock, NULL); } while ((ainfo = ainfo->ai_next) != NULL); freeaddrinfo (ainfo_save);}#endif /* ! (defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO)) *//* Make vty server socket. */voidvty_serv_sock_family (unsigned short port, int family){ int ret; union sockunion su; int accept_sock; memset (&su, 0, sizeof (union sockunion)); su.sa.sa_family = family; /* Make new socket. */ accept_sock = sockunion_stream_socket (&su); if (accept_sock < 0) return; /* This is server, so reuse address. */ sockopt_reuseaddr (accept_sock); sockopt_reuseport (accept_sock); /* Bind socket to universal address and given port. */ ret = sockunion_bind (accept_sock, &su, port, NULL); if (ret < 0) { close (accept_sock); /* Avoid sd leak. */ return; } /* Listen socket under queue 3. */ ret = listen (accept_sock, 3); if (ret < 0) { zlog (NULL, LOG_WARNING, "can't listen socket"); close (accept_sock); /* Avoid sd leak. */ return; } /* Add vty server event. */ vty_event (VTY_SERV, accept_sock, NULL);}#ifdef VTYSH/* For sockaddr_un. */#include <sys/un.h>/* VTY shell UNIX domain socket. */voidvty_serv_un (char *path){ int ret; int sock, len; struct sockaddr_un serv; mode_t old_mask; /* First of all, unlink existing socket */ unlink (path); /* Set umask */ old_mask = umask (0077); /* Make UNIX domain socket. */ sock = socket (AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { perror ("sock"); return; } /* Make server socket. */ memset (&serv, 0, sizeof (struct sockaddr_un)); serv.sun_family = AF_UNIX; strncpy (serv.sun_path, path, strlen (path));#ifdef HAVE_SUN_LEN len = serv.sun_len = SUN_LEN(&serv);#else len = sizeof (serv.sun_family) + strlen (serv.sun_path);#endif /* HAVE_SUN_LEN */ ret = bind (sock, (struct sockaddr *) &serv, len); if (ret < 0) { perror ("bind"); close (sock); /* Avoid sd leak. */ return; } ret = listen (sock, 5); if (ret < 0) { perror ("listen"); close (sock); /* Avoid sd leak. */ return; } umask (old_mask); vty_event (VTYSH_SERV, sock, NULL);}/* #define VTYSH_DEBUG 1 */static intvtysh_accept (struct thread *thread){ int accept_sock; int sock; int client_len; struct sockaddr_un client; struct vty *vty; accept_sock = THREAD_FD (thread); vty_event (VTYSH_SERV, accept_sock, NULL); memset (&client, 0, sizeof (struct sockaddr_un)); client_len = sizeof (struct sockaddr_un); sock = accept (accept_sock, (struct sockaddr *) &client, &client_len); if (sock < 0) { zlog_warn ("can't accept vty socket : %s", strerror (errno)); return -1; }#ifdef VTYSH_DEBUG printf ("VTY shell accept\n");#endif /* VTYSH_DEBUG */ vty = vty_new (); vty->fd = sock; vty->type = VTY_SHELL_SERV; vty->node = VIEW_NODE; vty_event (VTYSH_READ, sock, vty); return 0;}static intvtysh_read (struct thread *thread){ int ret; int sock; int nbytes; struct vty *vty; unsigned char buf[VTY_READ_BUFSIZ]; u_char header[4] = {0, 0, 0, 0}; sock = THREAD_FD (thread); vty = THREAD_ARG (thread); vty->t_read = NULL; nbytes = read (sock, buf, VTY_READ_BUFSIZ); if (nbytes <= 0) { vty_close (vty);#ifdef VTYSH_DEBUG printf ("close vtysh\n");#endif /* VTYSH_DEBUG */ return 0; }#ifdef VTYSH_DEBUG printf ("line: %s\n", buf);#endif /* VTYSH_DEBUG */ vty_ensure (vty, nbytes); memcpy (vty->buf, buf, nbytes); /* Pass this line to parser. */ ret = vty_execute (vty); vty_clear_buf (vty); /* Return result. */#ifdef VTYSH_DEBUG printf ("result: %d\n", ret); printf ("vtysh node: %d\n", vty->node);#endif /* VTYSH_DEBUG */ header[3] = ret; write (vty->fd, header, 4); vty_event (VTYSH_READ, sock, vty); return 0;}#endif /* VTYSH *//* Determine address family to bind. */voidvty_serv_sock (const char *hostname, unsigned short port, char *path){ /* If port is set to 0, do not listen on TCP/IP at all! */ if (port) {#if defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO) vty_serv_sock_addrinfo (hostname, port);#else /* ! (defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO)) */ vty_serv_sock_family (port, AF_INET);#endif /* HAVE_IPV6 */ }#ifdef VTYSH vty_serv_un (path);#endif /* VTYSH */}/* Close vty interface. */voidvty_close (struct vty *vty){ int i; /* Cancel threads.*/ if (vty->t_read) thread_cancel (vty->t_read); if (vty->t_write) thread_cancel (vty->t_write); if (vty->t_timeout) thread_cancel (vty->t_timeout); if (vty->t_output) thread_cancel (vty->t_output); /* Flush buffer. */ if (! buffer_empty (vty->obuf)) buffer_flush_all (vty->obuf, vty->fd); /* Free input buffer. */ buffer_free (vty->obuf); /* Free SB buffer. */ if (vty->sb_buffer) buffer_free (vty->sb_buffer); /* Free command history. */ for (i = 0; i < VTY_MAXHIST; i++) if (vty->hist[i]) XFREE (MTYPE_VTY_HIST, vty->hist[i]); /* Unset vector. */ vector_unset (vtyvec, vty->fd); /* Close socket. */ if (vty->fd > 0) close (vty->fd); if (vty->address) XFREE (0, vty->address); if (vty->buf) XFREE (MTYPE_VTY, vty->buf); /* Check configure. */ vty_config_unlock (vty); /* OK free vty. */ XFREE (MTYPE_VTY, vty);}/* When time out occur output message then close connection. */static intvty_timeout (struct thread *thread){ struct vty *vty; vty = THREAD_ARG (thread); vty->t_timeout = NULL; vty->v_timeout = 0; /* Clear buffer*/ buffer_reset (vty->obuf); vty_out (vty, "%sVty connection is timed out.%s", VTY_NEWLINE, VTY_NEWLINE); /* Close connection. */ vty->status = VTY_CLOSE; vty_close (vty); return 0;}/* Read up configuration file from file_name. */static voidvty_read_file (FILE *confp){ int ret; struct vty *vty; vty = vty_new (); vty->fd = 0; /* stdout */ vty->type = VTY_TERM; vty->node = CONFIG_NODE; /* Execute configuration file */ ret = config_from_file (vty, confp); if (ret != CMD_SUCCESS) { switch (ret) { case CMD_ERR_AMBIGUOUS: fprintf (stderr, "Ambiguous command.\n"); break; case CMD_ERR_NO_MATCH: fprintf (stderr, "There is no such command.\n"); break; } fprintf (stderr, "Error occured during reading below line.\n%s\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -