Merge pull request #8075 from opensourcerouting/assorted-20210212

lib: bunch of random small fixes
This commit is contained in:
Donald Sharp 2021-02-15 15:20:18 -05:00 committed by GitHub
commit a6d1b6a043
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 98 additions and 40 deletions

View File

@ -71,6 +71,7 @@ static char vtypath_default[512];
bool debug_memstats_at_exit = false; bool debug_memstats_at_exit = false;
static bool nodetach_term, nodetach_daemon; static bool nodetach_term, nodetach_daemon;
static uint64_t startup_fds;
static char comb_optstr[256]; static char comb_optstr[256];
static struct option comb_lo[64]; static struct option comb_lo[64];
@ -341,6 +342,28 @@ void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv)
strlcpy(frr_protonameinst, di->logname, sizeof(frr_protonameinst)); strlcpy(frr_protonameinst, di->logname, sizeof(frr_protonameinst));
di->cli_mode = FRR_CLI_CLASSIC; di->cli_mode = FRR_CLI_CLASSIC;
/* we may be starting with extra FDs open for whatever purpose,
* e.g. logging, some module, etc. Recording them here allows later
* checking whether an fd is valid for such extension purposes,
* without this we could end up e.g. logging to a BGP session fd.
*/
startup_fds = 0;
for (int i = 0; i < 64; i++) {
struct stat st;
if (fstat(i, &st))
continue;
if (S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode))
continue;
startup_fds |= UINT64_C(0x1) << (uint64_t)i;
}
}
bool frr_is_startup_fd(int fd)
{
return !!(startup_fds & (UINT64_C(0x1) << (uint64_t)fd));
} }
void frr_opt_add(const char *optstr, const struct option *longopts, void frr_opt_add(const char *optstr, const struct option *longopts,

View File

@ -138,7 +138,8 @@ extern __attribute__((__noreturn__)) void frr_help_exit(int status);
extern struct thread_master *frr_init(void); extern struct thread_master *frr_init(void);
extern const char *frr_get_progname(void); extern const char *frr_get_progname(void);
extern enum frr_cli_mode frr_get_cli_mode(void); extern enum frr_cli_mode frr_get_cli_mode(void);
uint32_t frr_get_fd_limit(void); extern uint32_t frr_get_fd_limit(void);
extern bool frr_is_startup_fd(int fd);
DECLARE_HOOK(frr_late_init, (struct thread_master * tm), (tm)) DECLARE_HOOK(frr_late_init, (struct thread_master * tm), (tm))
DECLARE_HOOK(frr_very_late_init, (struct thread_master * tm), (tm)) DECLARE_HOOK(frr_very_late_init, (struct thread_master * tm), (tm))

View File

@ -587,6 +587,8 @@ void zprivs_preinit(struct zebra_privs_t *zprivs)
} }
} }
struct zebra_privs_t *lib_privs;
void zprivs_init(struct zebra_privs_t *zprivs) void zprivs_init(struct zebra_privs_t *zprivs)
{ {
gid_t groups[NGROUPS_MAX] = {}; gid_t groups[NGROUPS_MAX] = {};
@ -598,6 +600,8 @@ void zprivs_init(struct zebra_privs_t *zprivs)
|| zprivs->cap_num_i)) || zprivs->cap_num_i))
return; return;
lib_privs = zprivs;
if (zprivs->user) { if (zprivs->user) {
ngroups = array_size(groups); ngroups = array_size(groups);
if (getgrouplist(zprivs->user, zprivs_state.zgid, groups, if (getgrouplist(zprivs->user, zprivs_state.zgid, groups,
@ -701,6 +705,8 @@ void zprivs_terminate(struct zebra_privs_t *zprivs)
{ {
struct zebra_privs_refs_t *refs; struct zebra_privs_refs_t *refs;
lib_privs = NULL;
if (!zprivs) { if (!zprivs) {
fprintf(stderr, "%s: no privs struct given, terminating", fprintf(stderr, "%s: no privs struct given, terminating",
__func__); __func__);

View File

@ -100,6 +100,8 @@ struct zprivs_ids_t {
gid_t gid_vty; /* vty gid */ gid_t gid_vty; /* vty gid */
}; };
extern struct zebra_privs_t *lib_privs;
/* initialise zebra privileges */ /* initialise zebra privileges */
extern void zprivs_preinit(struct zebra_privs_t *zprivs); extern void zprivs_preinit(struct zebra_privs_t *zprivs);
extern void zprivs_init(struct zebra_privs_t *zprivs); extern void zprivs_init(struct zebra_privs_t *zprivs);

104
lib/vty.c
View File

@ -73,7 +73,8 @@ enum event {
#endif /* VTYSH */ #endif /* VTYSH */
}; };
static void vty_event(enum event, int, struct vty *); static void vty_event_serv(enum event event, int sock);
static void vty_event(enum event, struct vty *);
/* Extern host structure from command.c */ /* Extern host structure from command.c */
extern struct host host; extern struct host host;
@ -1284,6 +1285,7 @@ static int vty_execute(struct vty *vty)
#define VTY_NORMAL 0 #define VTY_NORMAL 0
#define VTY_PRE_ESCAPE 1 #define VTY_PRE_ESCAPE 1
#define VTY_ESCAPE 2 #define VTY_ESCAPE 2
#define VTY_CR 3
/* Escape character command map. */ /* Escape character command map. */
static void vty_escape_map(unsigned char c, struct vty *vty) static void vty_escape_map(unsigned char c, struct vty *vty)
@ -1325,14 +1327,13 @@ static int vty_read(struct thread *thread)
int nbytes; int nbytes;
unsigned char buf[VTY_READ_BUFSIZ]; unsigned char buf[VTY_READ_BUFSIZ];
int vty_sock = THREAD_FD(thread);
struct vty *vty = THREAD_ARG(thread); struct vty *vty = THREAD_ARG(thread);
/* Read raw data from socket */ /* Read raw data from socket */
if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) { if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) {
if (nbytes < 0) { if (nbytes < 0) {
if (ERRNO_IO_RETRY(errno)) { if (ERRNO_IO_RETRY(errno)) {
vty_event(VTY_READ, vty_sock, vty); vty_event(VTY_READ, vty);
return 0; return 0;
} }
vty->monitor = 0; /* disable monitoring to avoid vty->monitor = 0; /* disable monitoring to avoid
@ -1423,6 +1424,17 @@ static int vty_read(struct thread *thread)
continue; continue;
} }
if (vty->escape == VTY_CR) {
/* if we get CR+NL, the NL results in an extra empty
* prompt line being printed without this; just drop
* the NL if it immediately follows CR.
*/
vty->escape = VTY_NORMAL;
if (buf[i] == '\n')
continue;
}
switch (buf[i]) { switch (buf[i]) {
case CONTROL('A'): case CONTROL('A'):
vty_beginning_of_line(vty); vty_beginning_of_line(vty);
@ -1467,9 +1479,12 @@ static int vty_read(struct thread *thread)
case CONTROL('Z'): case CONTROL('Z'):
vty_end_config(vty); vty_end_config(vty);
break; break;
case '\n':
case '\r': case '\r':
vty->escape = VTY_CR;
/* fallthru */
case '\n':
vty_out(vty, "\n"); vty_out(vty, "\n");
buffer_flush_available(vty->obuf, vty->wfd);
vty_execute(vty); vty_execute(vty);
break; break;
case '\t': case '\t':
@ -1500,8 +1515,8 @@ static int vty_read(struct thread *thread)
if (vty->status == VTY_CLOSE) if (vty->status == VTY_CLOSE)
vty_close(vty); vty_close(vty);
else { else {
vty_event(VTY_WRITE, vty->wfd, vty); vty_event(VTY_WRITE, vty);
vty_event(VTY_READ, vty_sock, vty); vty_event(VTY_READ, vty);
} }
return 0; return 0;
} }
@ -1511,7 +1526,6 @@ static int vty_flush(struct thread *thread)
{ {
int erase; int erase;
buffer_status_t flushrc; buffer_status_t flushrc;
int vty_sock = THREAD_FD(thread);
struct vty *vty = THREAD_ARG(thread); struct vty *vty = THREAD_ARG(thread);
/* Tempolary disable read thread. */ /* Tempolary disable read thread. */
@ -1523,20 +1537,20 @@ static int vty_flush(struct thread *thread)
/* 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) || (vty->height == 0)) if ((vty->lines == 0) || (vty->width == 0) || (vty->height == 0))
flushrc = buffer_flush_available(vty->obuf, vty_sock); flushrc = buffer_flush_available(vty->obuf, vty->wfd);
else if (vty->status == VTY_MORELINE) else if (vty->status == VTY_MORELINE)
flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, flushrc = buffer_flush_window(vty->obuf, vty->wfd, vty->width,
1, erase, 0); 1, erase, 0);
else else
flushrc = buffer_flush_window( flushrc = buffer_flush_window(
vty->obuf, vty_sock, vty->width, vty->obuf, vty->wfd, vty->width,
vty->lines >= 0 ? vty->lines : vty->height, erase, 0); vty->lines >= 0 ? vty->lines : vty->height, erase, 0);
switch (flushrc) { switch (flushrc) {
case BUFFER_ERROR: case BUFFER_ERROR:
vty->monitor = vty->monitor =
0; /* disable monitoring to avoid infinite recursion */ 0; /* disable monitoring to avoid infinite recursion */
zlog_info("buffer_flush failed on vty client fd %d, closing", zlog_info("buffer_flush failed on vty client fd %d/%d, closing",
vty->fd); vty->fd, vty->wfd);
buffer_reset(vty->lbuf); buffer_reset(vty->lbuf);
buffer_reset(vty->obuf); buffer_reset(vty->obuf);
vty_close(vty); vty_close(vty);
@ -1547,14 +1561,14 @@ static int vty_flush(struct thread *thread)
else { else {
vty->status = VTY_NORMAL; vty->status = VTY_NORMAL;
if (vty->lines == 0) if (vty->lines == 0)
vty_event(VTY_READ, vty_sock, vty); vty_event(VTY_READ, vty);
} }
break; break;
case BUFFER_PENDING: case BUFFER_PENDING:
/* There is more data waiting to be written. */ /* There is more data waiting to be written. */
vty->status = VTY_MORE; vty->status = VTY_MORE;
if (vty->lines == 0) if (vty->lines == 0)
vty_event(VTY_WRITE, vty_sock, vty); vty_event(VTY_WRITE, vty);
break; break;
} }
@ -1657,8 +1671,8 @@ static struct vty *vty_create(int vty_sock, union sockunion *su)
vty_prompt(vty); vty_prompt(vty);
/* Add read/write thread. */ /* Add read/write thread. */
vty_event(VTY_WRITE, vty_sock, vty); vty_event(VTY_WRITE, vty);
vty_event(VTY_READ, vty_sock, vty); vty_event(VTY_READ, vty);
return vty; return vty;
} }
@ -1714,7 +1728,6 @@ void vty_stdio_resume(void)
termios = stdio_orig_termios; termios = stdio_orig_termios;
termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
| IGNCR | ICRNL | IXON); | IGNCR | ICRNL | IXON);
termios.c_oflag &= ~OPOST;
termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN); termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
termios.c_cflag &= ~(CSIZE | PARENB); termios.c_cflag &= ~(CSIZE | PARENB);
termios.c_cflag |= CS8; termios.c_cflag |= CS8;
@ -1725,8 +1738,8 @@ void vty_stdio_resume(void)
vty_prompt(stdio_vty); vty_prompt(stdio_vty);
/* Add read/write thread. */ /* Add read/write thread. */
vty_event(VTY_WRITE, 1, stdio_vty); vty_event(VTY_WRITE, stdio_vty);
vty_event(VTY_READ, 0, stdio_vty); vty_event(VTY_READ, stdio_vty);
} }
void vty_stdio_close(void) void vty_stdio_close(void)
@ -1775,7 +1788,7 @@ static int vty_accept(struct thread *thread)
accept_sock = THREAD_FD(thread); accept_sock = THREAD_FD(thread);
/* We continue hearing vty socket. */ /* We continue hearing vty socket. */
vty_event(VTY_SERV, accept_sock, NULL); vty_event_serv(VTY_SERV, accept_sock);
memset(&su, 0, sizeof(union sockunion)); memset(&su, 0, sizeof(union sockunion));
@ -1805,7 +1818,7 @@ static int vty_accept(struct thread *thread)
close(vty_sock); close(vty_sock);
/* continue accepting connections */ /* continue accepting connections */
vty_event(VTY_SERV, accept_sock, NULL); vty_event_serv(VTY_SERV, accept_sock);
return 0; return 0;
} }
@ -1821,7 +1834,7 @@ static int vty_accept(struct thread *thread)
close(vty_sock); close(vty_sock);
/* continue accepting connections */ /* continue accepting connections */
vty_event(VTY_SERV, accept_sock, NULL); vty_event_serv(VTY_SERV, accept_sock);
return 0; return 0;
} }
@ -1894,7 +1907,7 @@ static void vty_serv_sock_addrinfo(const char *hostname, unsigned short port)
continue; continue;
} }
vty_event(VTY_SERV, sock, NULL); vty_event_serv(VTY_SERV, sock);
} while ((ainfo = ainfo->ai_next) != NULL); } while ((ainfo = ainfo->ai_next) != NULL);
freeaddrinfo(ainfo_save); freeaddrinfo(ainfo_save);
@ -1972,7 +1985,7 @@ static void vty_serv_un(const char *path)
} }
} }
vty_event(VTYSH_SERV, sock, NULL); vty_event_serv(VTYSH_SERV, sock);
} }
/* #define VTYSH_DEBUG 1 */ /* #define VTYSH_DEBUG 1 */
@ -1987,7 +2000,7 @@ static int vtysh_accept(struct thread *thread)
accept_sock = THREAD_FD(thread); accept_sock = THREAD_FD(thread);
vty_event(VTYSH_SERV, accept_sock, NULL); vty_event_serv(VTYSH_SERV, accept_sock);
memset(&client, 0, sizeof(struct sockaddr_un)); memset(&client, 0, sizeof(struct sockaddr_un));
client_len = sizeof(struct sockaddr_un); client_len = sizeof(struct sockaddr_un);
@ -2021,7 +2034,7 @@ static int vtysh_accept(struct thread *thread)
vty->type = VTY_SHELL_SERV; vty->type = VTY_SHELL_SERV;
vty->node = VIEW_NODE; vty->node = VIEW_NODE;
vty_event(VTYSH_READ, sock, vty); vty_event(VTYSH_READ, vty);
return 0; return 0;
} }
@ -2030,7 +2043,7 @@ static int vtysh_flush(struct vty *vty)
{ {
switch (buffer_flush_available(vty->obuf, vty->wfd)) { switch (buffer_flush_available(vty->obuf, vty->wfd)) {
case BUFFER_PENDING: case BUFFER_PENDING:
vty_event(VTYSH_WRITE, vty->wfd, vty); vty_event(VTYSH_WRITE, vty);
break; break;
case BUFFER_ERROR: case BUFFER_ERROR:
vty->monitor = vty->monitor =
@ -2063,7 +2076,7 @@ static int vtysh_read(struct thread *thread)
if ((nbytes = read(sock, buf, VTY_READ_BUFSIZ)) <= 0) { if ((nbytes = read(sock, buf, VTY_READ_BUFSIZ)) <= 0) {
if (nbytes < 0) { if (nbytes < 0) {
if (ERRNO_IO_RETRY(errno)) { if (ERRNO_IO_RETRY(errno)) {
vty_event(VTYSH_READ, sock, vty); vty_event(VTYSH_READ, vty);
return 0; return 0;
} }
vty->monitor = 0; /* disable monitoring to avoid vty->monitor = 0; /* disable monitoring to avoid
@ -2129,7 +2142,7 @@ static int vtysh_read(struct thread *thread)
if (vty->status == VTY_CLOSE) if (vty->status == VTY_CLOSE)
vty_close(vty); vty_close(vty);
else else
vty_event(VTYSH_READ, sock, vty); vty_event(VTYSH_READ, vty);
return 0; return 0;
} }
@ -2636,33 +2649,44 @@ int vty_config_node_exit(struct vty *vty)
/* Master of the threads. */ /* Master of the threads. */
static struct thread_master *vty_master; static struct thread_master *vty_master;
static void vty_event(enum event event, int sock, struct vty *vty) static void vty_event_serv(enum event event, int sock)
{ {
struct thread *vty_serv_thread = NULL; struct thread *vty_serv_thread = NULL;
switch (event) { switch (event) {
case VTY_SERV: case VTY_SERV:
vty_serv_thread = thread_add_read(vty_master, vty_accept, vty, vty_serv_thread = thread_add_read(vty_master, vty_accept,
sock, NULL); NULL, sock, NULL);
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:
vty_serv_thread = thread_add_read(vty_master, vtysh_accept, vty, vty_serv_thread = thread_add_read(vty_master, vtysh_accept,
sock, NULL); NULL, sock, NULL);
vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); vector_set_index(Vvty_serv_thread, sock, vty_serv_thread);
break; break;
#endif /* VTYSH */
default:
assert(!"vty_event_serv() called incorrectly");
}
}
static void vty_event(enum event event, struct vty *vty)
{
switch (event) {
#ifdef VTYSH
case VTYSH_READ: case VTYSH_READ:
thread_add_read(vty_master, vtysh_read, vty, sock, thread_add_read(vty_master, vtysh_read, vty, vty->fd,
&vty->t_read); &vty->t_read);
break; break;
case VTYSH_WRITE: case VTYSH_WRITE:
thread_add_write(vty_master, vtysh_write, vty, sock, thread_add_write(vty_master, vtysh_write, vty, vty->wfd,
&vty->t_write); &vty->t_write);
break; break;
#endif /* VTYSH */ #endif /* VTYSH */
case VTY_READ: case VTY_READ:
thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read); thread_add_read(vty_master, vty_read, vty, vty->fd,
&vty->t_read);
/* Time out treatment. */ /* Time out treatment. */
if (vty->v_timeout) { if (vty->v_timeout) {
@ -2672,7 +2696,7 @@ static void vty_event(enum event event, int sock, struct vty *vty)
} }
break; break;
case VTY_WRITE: case VTY_WRITE:
thread_add_write(vty_master, vty_flush, vty, sock, thread_add_write(vty_master, vty_flush, vty, vty->wfd,
&vty->t_write); &vty->t_write);
break; break;
case VTY_TIMEOUT_RESET: case VTY_TIMEOUT_RESET:
@ -2681,6 +2705,8 @@ static void vty_event(enum event event, int sock, struct vty *vty)
thread_add_timer(vty_master, vty_timeout, vty, thread_add_timer(vty_master, vty_timeout, vty,
vty->v_timeout, &vty->t_timeout); vty->v_timeout, &vty->t_timeout);
break; break;
default:
assert(!"vty_event() called incorrectly");
} }
} }
@ -2727,7 +2753,7 @@ static int exec_timeout(struct vty *vty, const char *min_str,
vty_timeout_val = timeout; vty_timeout_val = timeout;
vty->v_timeout = timeout; vty->v_timeout = timeout;
vty_event(VTY_TIMEOUT_RESET, 0, vty); vty_event(VTY_TIMEOUT_RESET, vty);
return CMD_SUCCESS; return CMD_SUCCESS;