]> git.proxmox.com Git - mirror_frr.git/blob - mgmtd/mgmt_be_server.c
1fcc6bd6a1efa972eb6f9f5209cbb899bde2974b
[mirror_frr.git] / mgmtd / mgmt_be_server.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * MGMTD Backend Server
4 *
5 * Copyright (C) 2021 Vmware, Inc.
6 * Pushpasis Sarkar <spushpasis@vmware.com>
7 */
8
9 #include <zebra.h>
10 #include "network.h"
11 #include "libfrr.h"
12 #include "mgmtd/mgmt.h"
13 #include "mgmtd/mgmt_be_server.h"
14 #include "mgmtd/mgmt_be_adapter.h"
15
16 #ifdef REDIRECT_DEBUG_TO_STDERR
17 #define MGMTD_BE_SRVR_DBG(fmt, ...) \
18 fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
19 #define MGMTD_BE_SRVR_ERR(fmt, ...) \
20 fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
21 #else /* REDIRECT_DEBUG_TO_STDERR */
22 #define MGMTD_BE_SRVR_DBG(fmt, ...) \
23 do { \
24 if (mgmt_debug_be) \
25 zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
26 } while (0)
27 #define MGMTD_BE_SRVR_ERR(fmt, ...) \
28 zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
29 #endif /* REDIRECT_DEBUG_TO_STDERR */
30
31 static int mgmt_be_listen_fd = -1;
32 static struct thread_master *mgmt_be_listen_tm;
33 static struct event *mgmt_be_listen_ev;
34 static void mgmt_be_server_register_event(enum mgmt_be_event event);
35
36 static void mgmt_be_conn_accept(struct event *thread)
37 {
38 int client_conn_fd;
39 union sockunion su;
40
41 if (mgmt_be_listen_fd < 0)
42 return;
43
44 /* We continue hearing server listen socket. */
45 mgmt_be_server_register_event(MGMTD_BE_SERVER);
46
47 memset(&su, 0, sizeof(union sockunion));
48
49 /* We can handle IPv4 or IPv6 socket. */
50 client_conn_fd = sockunion_accept(mgmt_be_listen_fd, &su);
51 if (client_conn_fd < 0) {
52 MGMTD_BE_SRVR_ERR(
53 "Failed to accept MGMTD Backend client connection : %s",
54 safe_strerror(errno));
55 return;
56 }
57 set_nonblocking(client_conn_fd);
58 set_cloexec(client_conn_fd);
59
60 MGMTD_BE_SRVR_DBG("Got a new MGMTD Backend connection");
61
62 mgmt_be_create_adapter(client_conn_fd, &su);
63 }
64
65 static void mgmt_be_server_register_event(enum mgmt_be_event event)
66 {
67 if (event == MGMTD_BE_SERVER) {
68 thread_add_read(mgmt_be_listen_tm, mgmt_be_conn_accept,
69 NULL, mgmt_be_listen_fd,
70 &mgmt_be_listen_ev);
71 assert(mgmt_be_listen_ev);
72 } else {
73 assert(!"mgmt_be_server_post_event() called incorrectly");
74 }
75 }
76
77 static void mgmt_be_server_start(const char *hostname)
78 {
79 int ret;
80 int sock;
81 struct sockaddr_un addr;
82 mode_t old_mask;
83
84 /* Set umask */
85 old_mask = umask(0077);
86
87 sock = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
88 if (sock < 0) {
89 MGMTD_BE_SRVR_ERR("Failed to create server socket: %s",
90 safe_strerror(errno));
91 goto mgmt_be_server_start_failed;
92 }
93
94 addr.sun_family = AF_UNIX,
95 strlcpy(addr.sun_path, MGMTD_BE_SERVER_PATH, sizeof(addr.sun_path));
96 unlink(addr.sun_path);
97 ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
98 if (ret < 0) {
99 MGMTD_BE_SRVR_ERR(
100 "Failed to bind server socket to '%s'. Err: %s",
101 addr.sun_path, safe_strerror(errno));
102 goto mgmt_be_server_start_failed;
103 }
104
105 ret = listen(sock, MGMTD_BE_MAX_CONN);
106 if (ret < 0) {
107 MGMTD_BE_SRVR_ERR("Failed to listen on server socket: %s",
108 safe_strerror(errno));
109 goto mgmt_be_server_start_failed;
110 }
111
112 /* Restore umask */
113 umask(old_mask);
114
115 mgmt_be_listen_fd = sock;
116 mgmt_be_server_register_event(MGMTD_BE_SERVER);
117
118 MGMTD_BE_SRVR_DBG("Started MGMTD Backend Server!");
119 return;
120
121 mgmt_be_server_start_failed:
122 if (sock)
123 close(sock);
124
125 mgmt_be_listen_fd = -1;
126 exit(-1);
127 }
128
129 int mgmt_be_server_init(struct thread_master *master)
130 {
131 if (mgmt_be_listen_tm) {
132 MGMTD_BE_SRVR_DBG("MGMTD Backend Server already running!");
133 return 0;
134 }
135
136 mgmt_be_listen_tm = master;
137
138 mgmt_be_server_start("localhost");
139
140 return 0;
141 }
142
143 void mgmt_be_server_destroy(void)
144 {
145 if (mgmt_be_listen_tm) {
146 MGMTD_BE_SRVR_DBG("Closing MGMTD Backend Server!");
147
148 if (mgmt_be_listen_ev) {
149 THREAD_OFF(mgmt_be_listen_ev);
150 mgmt_be_listen_ev = NULL;
151 }
152
153 if (mgmt_be_listen_fd >= 0) {
154 close(mgmt_be_listen_fd);
155 mgmt_be_listen_fd = -1;
156 }
157
158 mgmt_be_listen_tm = NULL;
159 }
160 }