]>
Commit | Line | Data |
---|---|---|
ef43a632 CH |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * MGMTD Frontend 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_fe_server.h" | |
14 | #include "mgmtd/mgmt_fe_adapter.h" | |
15 | ||
ef43a632 | 16 | #define MGMTD_FE_SRVR_DBG(fmt, ...) \ |
cfa0facb | 17 | DEBUGD(&mgmt_debug_fe, "%s:" fmt, __func__, ##__VA_ARGS__) |
ef43a632 CH |
18 | #define MGMTD_FE_SRVR_ERR(fmt, ...) \ |
19 | zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) | |
ef43a632 | 20 | |
f82370b4 | 21 | static int mgmt_fe_listen_fd = -1; |
cd9d0537 | 22 | static struct event_loop *mgmt_fe_listen_tm; |
e6685141 | 23 | static struct event *mgmt_fe_listen_ev; |
ef43a632 CH |
24 | static void mgmt_fe_server_register_event(enum mgmt_fe_event event); |
25 | ||
e6685141 | 26 | static void mgmt_fe_conn_accept(struct event *thread) |
ef43a632 CH |
27 | { |
28 | int client_conn_fd; | |
29 | union sockunion su; | |
30 | ||
31 | if (mgmt_fe_listen_fd < 0) | |
32 | return; | |
33 | ||
34 | /* We continue hearing server listen socket. */ | |
35 | mgmt_fe_server_register_event(MGMTD_FE_SERVER); | |
36 | ||
37 | memset(&su, 0, sizeof(union sockunion)); | |
38 | ||
39 | /* We can handle IPv4 or IPv6 socket. */ | |
40 | client_conn_fd = sockunion_accept(mgmt_fe_listen_fd, &su); | |
41 | if (client_conn_fd < 0) { | |
42 | MGMTD_FE_SRVR_ERR( | |
43 | "Failed to accept MGMTD Frontend client connection : %s", | |
44 | safe_strerror(errno)); | |
45 | return; | |
46 | } | |
47 | set_nonblocking(client_conn_fd); | |
48 | set_cloexec(client_conn_fd); | |
49 | ||
50 | MGMTD_FE_SRVR_DBG("Got a new MGMTD Frontend connection"); | |
51 | ||
52 | mgmt_fe_create_adapter(client_conn_fd, &su); | |
53 | } | |
54 | ||
55 | static void mgmt_fe_server_register_event(enum mgmt_fe_event event) | |
56 | { | |
57 | if (event == MGMTD_FE_SERVER) { | |
907a2395 | 58 | event_add_read(mgmt_fe_listen_tm, mgmt_fe_conn_accept, |
ef43a632 CH |
59 | NULL, mgmt_fe_listen_fd, |
60 | &mgmt_fe_listen_ev); | |
61 | assert(mgmt_fe_listen_ev); | |
62 | } else { | |
63 | assert(!"mgmt_fe_server_post_event() called incorrectly"); | |
64 | } | |
65 | } | |
66 | ||
67 | static void mgmt_fe_server_start(const char *hostname) | |
68 | { | |
69 | int ret; | |
70 | int sock; | |
71 | struct sockaddr_un addr; | |
72 | mode_t old_mask; | |
73 | ||
74 | /* Set umask */ | |
75 | old_mask = umask(0077); | |
76 | ||
77 | sock = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC); | |
78 | if (sock < 0) { | |
79 | MGMTD_FE_SRVR_ERR("Failed to create server socket: %s", | |
80 | safe_strerror(errno)); | |
81 | goto mgmt_fe_server_start_failed; | |
82 | } | |
83 | ||
84 | addr.sun_family = AF_UNIX, | |
85 | strlcpy(addr.sun_path, MGMTD_FE_SERVER_PATH, sizeof(addr.sun_path)); | |
86 | unlink(addr.sun_path); | |
87 | ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); | |
88 | if (ret < 0) { | |
89 | MGMTD_FE_SRVR_ERR( | |
90 | "Failed to bind server socket to '%s'. Err: %s", | |
91 | addr.sun_path, safe_strerror(errno)); | |
92 | goto mgmt_fe_server_start_failed; | |
93 | } | |
94 | ||
95 | ret = listen(sock, MGMTD_FE_MAX_CONN); | |
96 | if (ret < 0) { | |
97 | MGMTD_FE_SRVR_ERR("Failed to listen on server socket: %s", | |
98 | safe_strerror(errno)); | |
99 | goto mgmt_fe_server_start_failed; | |
100 | } | |
101 | ||
102 | /* Restore umask */ | |
103 | umask(old_mask); | |
104 | ||
105 | mgmt_fe_listen_fd = sock; | |
106 | mgmt_fe_server_register_event(MGMTD_FE_SERVER); | |
107 | ||
108 | MGMTD_FE_SRVR_DBG("Started MGMTD Frontend Server!"); | |
109 | return; | |
110 | ||
111 | mgmt_fe_server_start_failed: | |
93d4e355 | 112 | if (sock > 0) |
ef43a632 CH |
113 | close(sock); |
114 | ||
115 | mgmt_fe_listen_fd = -1; | |
116 | exit(-1); | |
117 | } | |
118 | ||
cd9d0537 | 119 | int mgmt_fe_server_init(struct event_loop *master) |
ef43a632 CH |
120 | { |
121 | if (mgmt_fe_listen_tm) { | |
122 | MGMTD_FE_SRVR_DBG("MGMTD Frontend Server already running!"); | |
123 | return 0; | |
124 | } | |
125 | ||
126 | mgmt_fe_listen_tm = master; | |
127 | ||
128 | mgmt_fe_server_start("localhost"); | |
129 | ||
130 | return 0; | |
131 | } | |
132 | ||
133 | void mgmt_fe_server_destroy(void) | |
134 | { | |
135 | if (mgmt_fe_listen_tm) { | |
136 | MGMTD_FE_SRVR_DBG("Closing MGMTD Frontend Server!"); | |
137 | ||
138 | if (mgmt_fe_listen_ev) { | |
e16d030c | 139 | EVENT_OFF(mgmt_fe_listen_ev); |
ef43a632 CH |
140 | mgmt_fe_listen_ev = NULL; |
141 | } | |
142 | ||
143 | if (mgmt_fe_listen_fd >= 0) { | |
144 | close(mgmt_fe_listen_fd); | |
145 | mgmt_fe_listen_fd = -1; | |
146 | } | |
147 | ||
148 | mgmt_fe_listen_tm = NULL; | |
149 | } | |
150 | } |