blob: f09a537a48daed240a6ec1506353d631c01a2b9a [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 * main.c: Unix main routine
17 *
18 * Copyright (c) 2008 Eliot Dresselhaus
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining
21 * a copy of this software and associated documentation files (the
22 * "Software"), to deal in the Software without restriction, including
23 * without limitation the rights to use, copy, modify, merge, publish,
24 * distribute, sublicense, and/or sell copies of the Software, and to
25 * permit persons to whom the Software is furnished to do so, subject to
26 * the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be
29 * included in all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 */
39#include <vlib/vlib.h>
40#include <vlib/unix/unix.h>
41#include <vlib/unix/plugin.h>
42
Jing Peng4859d8d2022-03-04 17:43:50 -050043#include <limits.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070044#include <signal.h>
45#include <sys/ucontext.h>
46#include <syslog.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <fcntl.h>
Klement Sekerac8c44eb2017-03-02 11:13:30 +010050#include <sys/time.h>
51#include <sys/resource.h>
Damjan Mariona54230d2017-06-21 11:57:07 +020052#include <unistd.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070053
Chris Luke7afda3a2016-04-25 13:49:22 -040054/** Default CLI pager limit is not configured in startup.conf */
55#define UNIX_CLI_DEFAULT_PAGER_LIMIT 100000
56
57/** Default CLI history depth if not configured in startup.conf */
58#define UNIX_CLI_DEFAULT_HISTORY 50
59
Damjan Marion57d963f2017-07-20 19:17:06 +020060char *vlib_default_runtime_dir __attribute__ ((weak));
Damjan Marionc67787b2017-08-30 17:12:25 +020061char *vlib_default_runtime_dir = "vlib";
Chris Luke7afda3a2016-04-25 13:49:22 -040062
Ed Warnickecb9cada2015-12-08 15:45:58 -070063unix_main_t unix_main;
Damjan Marion56dd5432017-09-08 19:52:02 +020064clib_file_main_t file_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -070065
66static clib_error_t *
67unix_main_init (vlib_main_t * vm)
68{
Dave Barach9b8ffd92016-07-08 08:13:45 -040069 unix_main_t *um = &unix_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -070070 um->vlib_main = vm;
Dave Barachf8d50682019-05-14 18:01:44 -040071 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070072}
73
Dave Barachf8d50682019-05-14 18:01:44 -040074/* *INDENT-OFF* */
75VLIB_INIT_FUNCTION (unix_main_init) =
76{
77 .runs_before = VLIB_INITS ("unix_input_init"),
78};
79/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070080
Kingwel Xie497deaf2018-06-15 04:56:24 -040081static int
82unsetup_signal_handlers (int sig)
83{
84 struct sigaction sa;
85
86 sa.sa_handler = SIG_DFL;
87 sa.sa_flags = 0;
88 sigemptyset (&sa.sa_mask);
89 return sigaction (sig, &sa, 0);
90}
91
92
93/* allocate this buffer from mheap when setting up the signal handler.
94 dangerous to vec_resize it when crashing, mheap itself might have been
Paul Vinciguerrad29422c2019-10-27 14:00:53 -040095 corrupted already */
Kingwel Xie497deaf2018-06-15 04:56:24 -040096static u8 *syslog_msg = 0;
Dave Barach695eb932020-10-09 10:17:22 -040097int vlib_last_signum = 0;
98uword vlib_last_faulting_address = 0;
Kingwel Xie497deaf2018-06-15 04:56:24 -040099
Dave Barach9b8ffd92016-07-08 08:13:45 -0400100static void
101unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700102{
Dave Barach903651c2017-10-13 19:16:56 -0400103 uword fatal = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104
Dave Barach9e52ef62019-02-28 17:52:57 -0500105 /* These come in handy when looking at core files from optimized images */
Dave Barach695eb932020-10-09 10:17:22 -0400106 vlib_last_signum = signum;
107 vlib_last_faulting_address = (uword) si->si_addr;
Dave Barach9e52ef62019-02-28 17:52:57 -0500108
Kingwel Xie497deaf2018-06-15 04:56:24 -0400109 syslog_msg = format (syslog_msg, "received signal %U, PC %U",
110 format_signal, signum, format_ucontext_pc, uc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700111
112 if (signum == SIGSEGV)
Kingwel Xie497deaf2018-06-15 04:56:24 -0400113 syslog_msg = format (syslog_msg, ", faulting address %p", si->si_addr);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700114
115 switch (signum)
116 {
117 /* these (caught) signals cause the application to exit */
118 case SIGTERM:
Dave Barachd1e17d02019-03-21 18:01:48 -0400119 /*
120 * Ignore SIGTERM if it's sent before we're ready.
121 */
122 if (unix_main.vlib_main && unix_main.vlib_main->main_loop_exit_set)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400123 {
124 syslog (LOG_ERR | LOG_DAEMON, "received SIGTERM, exiting...");
Dave Barach903651c2017-10-13 19:16:56 -0400125 unix_main.vlib_main->main_loop_exit_now = 1;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400126 }
Dave Barachd1e17d02019-03-21 18:01:48 -0400127 else
128 syslog (LOG_ERR | LOG_DAEMON, "IGNORE early SIGTERM...");
Dave Barach903651c2017-10-13 19:16:56 -0400129 break;
Dave Barachb2a6e252016-07-27 10:00:58 -0400130 /* fall through */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700131 case SIGQUIT:
132 case SIGINT:
133 case SIGILL:
134 case SIGBUS:
135 case SIGSEGV:
136 case SIGHUP:
137 case SIGFPE:
Kingwel Xie497deaf2018-06-15 04:56:24 -0400138 case SIGABRT:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700139 fatal = 1;
140 break;
141
142 /* by default, print a message and continue */
143 default:
144 fatal = 0;
145 break;
146 }
147
148 /* Null terminate. */
Kingwel Xie497deaf2018-06-15 04:56:24 -0400149 vec_add1 (syslog_msg, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150
151 if (fatal)
152 {
Kingwel Xie497deaf2018-06-15 04:56:24 -0400153 syslog (LOG_ERR | LOG_DAEMON, "%s", syslog_msg);
154
155 /* Address of callers: outer first, inner last. */
156 uword callers[15];
157 uword n_callers = clib_backtrace (callers, ARRAY_LEN (callers), 0);
158 int i;
159 for (i = 0; i < n_callers; i++)
160 {
161 vec_reset_length (syslog_msg);
162
163 syslog_msg =
164 format (syslog_msg, "#%-2d 0x%016lx %U%c", i, callers[i],
165 format_clib_elf_symbol_with_address, callers[i], 0);
166
167 syslog (LOG_ERR | LOG_DAEMON, "%s", syslog_msg);
168 }
169
Paul Vinciguerrad29422c2019-10-27 14:00:53 -0400170 /* have to remove SIGABRT to avoid recursive - os_exit calling abort() */
Kingwel Xie497deaf2018-06-15 04:56:24 -0400171 unsetup_signal_handlers (SIGABRT);
172
Christian Hopps1da08192020-04-24 04:39:59 -0400173 /* os_exit(1) causes core generation, skip that for SIGINT, SIGHUP */
174 if (signum == SIGINT || signum == SIGHUP)
Christian E. Hopps10a8bda2019-09-27 13:52:50 -0400175 os_exit (0);
176 else
177 os_exit (1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700178 }
179 else
Kingwel Xie497deaf2018-06-15 04:56:24 -0400180 clib_warning ("%s", syslog_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181
Ed Warnickecb9cada2015-12-08 15:45:58 -0700182}
183
184static clib_error_t *
185setup_signal_handlers (unix_main_t * um)
186{
187 uword i;
188 struct sigaction sa;
189
Kingwel Xie497deaf2018-06-15 04:56:24 -0400190 /* give a big enough buffer for msg, most likely it can avoid vec_resize */
191 vec_alloc (syslog_msg, 2048);
192
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193 for (i = 1; i < 32; i++)
194 {
Dave Barachb7b92992018-10-17 10:38:51 -0400195 clib_memset (&sa, 0, sizeof (sa));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196 sa.sa_sigaction = (void *) unix_signal_handler;
197 sa.sa_flags = SA_SIGINFO;
198
199 switch (i)
200 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400201 /* these signals take the default action */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700202 case SIGKILL:
Vladislav Grishenko84862832022-03-21 02:21:42 +0500203 case SIGCONT:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204 case SIGSTOP:
Dave Barach9b8ffd92016-07-08 08:13:45 -0400205 case SIGUSR1:
206 case SIGUSR2:
Jieqiang Wang6f533d72020-01-20 13:43:38 +0800207 case SIGPROF:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700208 continue;
209
Dave Barach9b8ffd92016-07-08 08:13:45 -0400210 /* ignore SIGPIPE, SIGCHLD */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700211 case SIGPIPE:
212 case SIGCHLD:
213 sa.sa_sigaction = (void *) SIG_IGN;
214 break;
215
Dave Barach9b8ffd92016-07-08 08:13:45 -0400216 /* catch and handle all other signals */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700217 default:
218 break;
219 }
220
221 if (sigaction (i, &sa, 0) < 0)
222 return clib_error_return_unix (0, "sigaction %U", format_signal, i);
223 }
224
225 return 0;
226}
227
Dave Barach9b8ffd92016-07-08 08:13:45 -0400228static void
229unix_error_handler (void *arg, u8 * msg, int msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700230{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400231 unix_main_t *um = arg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700232
Ruslan Babayeve31820a2020-02-14 17:45:02 -0800233 /* Echo to stderr when interactive or syslog is disabled. */
234 if (um->flags & (UNIX_FLAG_INTERACTIVE | UNIX_FLAG_NOSYSLOG))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235 {
236 CLIB_UNUSED (int r) = write (2, msg, msg_len);
237 }
238 else
239 {
Jing Peng4859d8d2022-03-04 17:43:50 -0500240 syslog (LOG_ERR | LOG_DAEMON, "%.*s", msg_len, msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241 }
242}
243
Dave Barach9b8ffd92016-07-08 08:13:45 -0400244void
245vlib_unix_error_report (vlib_main_t * vm, clib_error_t * error)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700246{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400247 unix_main_t *um = &unix_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248
Dave Barach9b8ffd92016-07-08 08:13:45 -0400249 if (um->flags & UNIX_FLAG_INTERACTIVE || error == 0)
250 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700251
Dave Barach9b8ffd92016-07-08 08:13:45 -0400252 {
Jing Peng4859d8d2022-03-04 17:43:50 -0500253 u8 *msg = error->what;
254 u32 len = vec_len (msg);
255 int msg_len = (len > INT_MAX) ? INT_MAX : len;
256 syslog (LOG_ERR | LOG_DAEMON, "%.*s", msg_len, msg);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400257 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700258}
259
260static uword
261startup_config_process (vlib_main_t * vm,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400262 vlib_node_runtime_t * rt, vlib_frame_t * f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700263{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400264 unix_main_t *um = &unix_main;
Xiaoming Jiang4d830d22022-12-08 07:54:06 +0000265 unformat_input_t in;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700266
267 vlib_process_suspend (vm, 2.0);
268
269 while (um->unix_config_complete == 0)
270 vlib_process_suspend (vm, 0.1);
271
Xiaoming Jiang4d830d22022-12-08 07:54:06 +0000272 if (!um->startup_config_filename)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400273 {
Xiaoming Jiang4d830d22022-12-08 07:54:06 +0000274 return 0;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400275 }
Xiaoming Jiang4d830d22022-12-08 07:54:06 +0000276
277 unformat_init_vector (&in,
278 format (0, "exec %s", um->startup_config_filename));
279
280 vlib_cli_input (vm, &in, 0, 0);
281
282 unformat_free (&in);
283
Ed Warnickecb9cada2015-12-08 15:45:58 -0700284 return 0;
285}
286
Dave Barach9b8ffd92016-07-08 08:13:45 -0400287/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700288VLIB_REGISTER_NODE (startup_config_node,static) = {
289 .function = startup_config_process,
290 .type = VLIB_NODE_TYPE_PROCESS,
291 .name = "startup-config-process",
GordonNoonanb2dbb362019-12-04 15:16:40 +0000292 .process_log2_n_stack_bytes = 18,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700293};
Dave Barach9b8ffd92016-07-08 08:13:45 -0400294/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700295
296static clib_error_t *
297unix_config (vlib_main_t * vm, unformat_input_t * input)
298{
Damjan Marionfd8deb42021-03-06 12:26:28 +0100299 vlib_global_main_t *vgm = vlib_get_global_main ();
Dave Barach9b8ffd92016-07-08 08:13:45 -0400300 unix_main_t *um = &unix_main;
301 clib_error_t *error = 0;
Damjan Mariona54230d2017-06-21 11:57:07 +0200302 gid_t gid;
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400303 int pidfd = -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700304
Chris Luke7afda3a2016-04-25 13:49:22 -0400305 /* Defaults */
306 um->cli_pager_buffer_limit = UNIX_CLI_DEFAULT_PAGER_LIMIT;
307 um->cli_history_limit = UNIX_CLI_DEFAULT_HISTORY;
308
Ed Warnickecb9cada2015-12-08 15:45:58 -0700309 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
310 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400311 char *cli_prompt;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700312 if (unformat (input, "interactive"))
313 um->flags |= UNIX_FLAG_INTERACTIVE;
314 else if (unformat (input, "nodaemon"))
Dave Barach9b8ffd92016-07-08 08:13:45 -0400315 um->flags |= UNIX_FLAG_NODAEMON;
Ruslan Babayeve31820a2020-02-14 17:45:02 -0800316 else if (unformat (input, "nosyslog"))
317 um->flags |= UNIX_FLAG_NOSYSLOG;
Damjan Marion06d82262020-10-21 12:43:40 +0200318 else if (unformat (input, "nocolor"))
319 um->flags |= UNIX_FLAG_NOCOLOR;
320 else if (unformat (input, "nobanner"))
321 um->flags |= UNIX_FLAG_NOBANNER;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700322 else if (unformat (input, "cli-prompt %s", &cli_prompt))
323 vlib_unix_cli_set_prompt (cli_prompt);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400324 else
325 if (unformat (input, "cli-listen %s", &um->cli_listen_socket.config))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700326 ;
Damjan Marion57d963f2017-07-20 19:17:06 +0200327 else if (unformat (input, "runtime-dir %s", &um->runtime_dir))
328 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700329 else if (unformat (input, "cli-line-mode"))
Dave Barach9b8ffd92016-07-08 08:13:45 -0400330 um->cli_line_mode = 1;
Chris Luke572d8122016-04-25 13:49:07 -0400331 else if (unformat (input, "cli-no-banner"))
Dave Barach9b8ffd92016-07-08 08:13:45 -0400332 um->cli_no_banner = 1;
Chris Luke7afda3a2016-04-25 13:49:22 -0400333 else if (unformat (input, "cli-no-pager"))
Dave Barach9b8ffd92016-07-08 08:13:45 -0400334 um->cli_no_pager = 1;
Dave Barach85aa4902018-06-14 18:52:46 -0400335 else if (unformat (input, "poll-sleep-usec %d", &um->poll_sleep_usec))
336 ;
Chris Luke7afda3a2016-04-25 13:49:22 -0400337 else if (unformat (input, "cli-pager-buffer-limit %d",
Dave Barach9b8ffd92016-07-08 08:13:45 -0400338 &um->cli_pager_buffer_limit))
339 ;
340 else
341 if (unformat (input, "cli-history-limit %d", &um->cli_history_limit))
342 ;
Klement Sekerac8c44eb2017-03-02 11:13:30 +0100343 else if (unformat (input, "coredump-size"))
344 {
345 uword coredump_size = 0;
346 if (unformat (input, "unlimited"))
347 {
348 coredump_size = RLIM_INFINITY;
349 }
350 else
351 if (!unformat (input, "%U", unformat_memory_size, &coredump_size))
352 {
353 return clib_error_return (0,
354 "invalid coredump-size parameter `%U'",
355 format_unformat_error, input);
356 }
357 const struct rlimit new_limit = { coredump_size, coredump_size };
358 if (0 != setrlimit (RLIMIT_CORE, &new_limit))
359 {
360 clib_unix_warning ("prlimit() failed");
361 }
362 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363 else if (unformat (input, "full-coredump"))
Dave Barach9b8ffd92016-07-08 08:13:45 -0400364 {
365 int fd;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366
Dave Barach9b8ffd92016-07-08 08:13:45 -0400367 fd = open ("/proc/self/coredump_filter", O_WRONLY);
Dave Barachb2a6e252016-07-27 10:00:58 -0400368 if (fd >= 0)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400369 {
370 if (write (fd, "0x6f\n", 5) != 5)
371 clib_unix_warning ("coredump filter write failed!");
372 close (fd);
373 }
374 else
375 clib_unix_warning ("couldn't open /proc/self/coredump_filter");
376 }
377 else if (unformat (input, "startup-config %s",
378 &um->startup_config_filename))
379 ;
380 else if (unformat (input, "exec %s", &um->startup_config_filename))
381 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382 else if (unformat (input, "log %s", &um->log_filename))
Dave Barach9b8ffd92016-07-08 08:13:45 -0400383 {
384 um->log_fd = open ((char *) um->log_filename,
385 O_CREAT | O_WRONLY | O_APPEND, 0644);
386 if (um->log_fd < 0)
387 {
388 clib_warning ("couldn't open log '%s'\n", um->log_filename);
389 um->log_fd = 0;
390 }
391 else
392 {
393 u8 *lv = 0;
394 lv = format (0, "%U: ***** Start: PID %d *****\n",
Andreas Schultz972dc172020-05-15 11:50:07 +0200395 format_timeval, NULL /* current bat-format */,
396 0 /* current bat-time */, getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700397 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400398 int rv __attribute__ ((unused)) =
399 write (um->log_fd, lv, vec_len (lv));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400 }
Dave Barach9b8ffd92016-07-08 08:13:45 -0400401 vec_free (lv);
402 }
403 }
Damjan Mariona54230d2017-06-21 11:57:07 +0200404 else if (unformat (input, "gid %U", unformat_unix_gid, &gid))
405 {
406 if (setegid (gid) == -1)
407 return clib_error_return_unix (0, "setegid");
408 }
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400409 else if (unformat (input, "pidfile %s", &um->pidfile))
410 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700411 else
412 return clib_error_return (0, "unknown input `%U'",
413 format_unformat_error, input);
414 }
415
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400416 if (um->runtime_dir == 0)
417 {
418 uid_t uid = geteuid ();
419 if (uid == 00)
420 um->runtime_dir = format (0, "/run/%s%c",
421 vlib_default_runtime_dir, 0);
422 else
423 um->runtime_dir = format (0, "/run/user/%u/%s%c", uid,
424 vlib_default_runtime_dir, 0);
425 }
426
Ole Troand991a792019-08-19 14:51:45 +0200427 /* Ensure the runtime directory is created */
428 error = vlib_unix_recursive_mkdir ((char *) um->runtime_dir);
429 if (error)
430 return error;
431
Damjan Mariona254de42023-01-26 20:23:11 +0100432 if (chdir ((char *) um->runtime_dir) < 0)
433 return clib_error_return_unix (0, "chdir('%s')", um->runtime_dir);
434
Chris Lukeab7b8d92017-09-07 07:40:13 -0400435 error = setup_signal_handlers (um);
436 if (error)
437 return error;
438
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400439 if (um->pidfile)
440 {
441 if ((error = vlib_unix_validate_runtime_file (um,
442 (char *) um->pidfile,
443 &um->pidfile)))
444 return error;
445
446 if (((pidfd = open ((char *) um->pidfile,
447 O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0))
448 {
449 return clib_error_return_unix (0, "open");
450 }
451 }
452
Ruslan Babayeve31820a2020-02-14 17:45:02 -0800453 if (!(um->flags & (UNIX_FLAG_INTERACTIVE | UNIX_FLAG_NOSYSLOG)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700454 {
Damjan Marionfd8deb42021-03-06 12:26:28 +0100455 openlog (vgm->name, LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700456 clib_error_register_handler (unix_error_handler, um);
457
Dave Barach9b8ffd92016-07-08 08:13:45 -0400458 if (!(um->flags & UNIX_FLAG_NODAEMON) && daemon ( /* chdir to / */ 0,
459 /* stdin/stdout/stderr -> /dev/null */
460 0) < 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700461 clib_error_return (0, "daemon () fails");
462 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700463
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400464 if (pidfd >= 0)
Damjan Marionc67787b2017-08-30 17:12:25 +0200465 {
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400466 u8 *lv = format (0, "%d", getpid ());
467 if (write (pidfd, (char *) lv, vec_len (lv)) != vec_len (lv))
468 {
469 vec_free (lv);
470 close (pidfd);
471 return clib_error_return_unix (0, "write");
472 }
473 vec_free (lv);
474 close (pidfd);
Damjan Marionc67787b2017-08-30 17:12:25 +0200475 }
476
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400477 um->unix_config_complete = 1;
Damjan Marion57d963f2017-07-20 19:17:06 +0200478
Ed Warnickecb9cada2015-12-08 15:45:58 -0700479 return 0;
480}
481
482/* unix { ... } configuration. */
Chris Luke90f52bf2016-09-12 08:55:13 -0400483/*?
484 *
485 * @cfgcmd{interactive}
486 * Attach CLI to stdin/out and provide a debugging command line interface.
487 * Implies @c nodaemon.
488 *
489 * @cfgcmd{nodaemon}
490 * Do not fork or background the VPP process. Typically used when invoking
491 * VPP applications from a process monitor.
492 *
Ruslan Babayeve31820a2020-02-14 17:45:02 -0800493 * @cfgcmd{nosyslog}
494 * Do not send e.g. clib_warning(...) output to syslog. Used
495 * when invoking VPP applications from a process monitor which
496 * pipe stdout/stderr to a dedicated logger service.
497 *
Damjan Marion06d82262020-10-21 12:43:40 +0200498 * @cfgcmd{nocolor}
499 * Do not use colors in outputs.
500 * *
501 * @cfgcmd{nobanner}
502 * Do not display startup banner.
503 *
Chris Luke90f52bf2016-09-12 08:55:13 -0400504 * @cfgcmd{exec, &lt;filename&gt;}
505 * @par <code>startup-config &lt;filename&gt;</code>
506 * Read startup operational configuration from @c filename.
507 * The contents of the file will be performed as though entered at the CLI.
508 * The two keywords are aliases for the same function; if both are specified,
509 * only the last will have an effect.
510 *
511 * @cfgcmd{log, &lt;filename&gt;}
512 * Logs the startup configuration and all subsequent CLI commands in
513 * @c filename.
514 * Very useful in situations where folks don't remember or can't be bothered
515 * to include CLI commands in bug reports.
516 *
Pierre Pfister9a244bb2017-07-27 22:57:34 -0400517 * @cfgcmd{pidfile, &lt;filename&gt;}
518 * Writes the pid of the main thread in @c filename.
519 *
Chris Luke90f52bf2016-09-12 08:55:13 -0400520 * @cfgcmd{full-coredump}
521 * Ask the Linux kernel to dump all memory-mapped address regions, instead
522 * of just text+data+bss.
523 *
Damjan Marion57d963f2017-07-20 19:17:06 +0200524 * @cfgcmd{runtime-dir}
525 * Define directory where VPP is going to store all runtime files.
Paul Vinciguerrad54815c2019-04-11 06:32:19 -0700526 * Default is /run/vpp when running as root, /run/user/<UID>/vpp if running as
527 * an unprivileged user.
Damjan Marion57d963f2017-07-20 19:17:06 +0200528 *
Chris Luke90f52bf2016-09-12 08:55:13 -0400529 * @cfgcmd{cli-listen, &lt;address:port&gt;}
Paul Vinciguerrad54815c2019-04-11 06:32:19 -0700530 * Bind the CLI to listen at the address and port given. @c localhost
Chris Luke90f52bf2016-09-12 08:55:13 -0400531 * on TCP port @c 5002, given as <tt>cli-listen localhost:5002</tt>,
532 * is typical.
533 *
534 * @cfgcmd{cli-line-mode}
535 * Disable character-by-character I/O on stdin. Useful when combined with,
536 * for example, <tt>emacs M-x gud-gdb</tt>.
537 *
538 * @cfgcmd{cli-prompt, &lt;string&gt;}
539 * Configure the CLI prompt to be @c string.
540 *
541 * @cfgcmd{cli-history-limit, &lt;nn&gt;}
Paul Vinciguerrad54815c2019-04-11 06:32:19 -0700542 * Limit command history to @c nn lines. A value of @c 0
Chris Luke90f52bf2016-09-12 08:55:13 -0400543 * disables command history. Default value: @c 50
544 *
545 * @cfgcmd{cli-no-banner}
546 * Disable the login banner on stdin and Telnet connections.
547 *
548 * @cfgcmd{cli-no-pager}
549 * Disable the output pager.
550 *
551 * @cfgcmd{cli-pager-buffer-limit, &lt;nn&gt;}
552 * Limit pager buffer to @c nn lines of output.
553 * A value of @c 0 disables the pager. Default value: @c 100000
Paul Vinciguerrad54815c2019-04-11 06:32:19 -0700554 *
555 * @cfgcmd{gid, &lt;nn&gt;}
556 * Set the effective gid under which the vpp process is to run.
557 *
558 * @cfgcmd{poll-sleep-usec, &lt;nn&gt;}
559 * Set a fixed poll sleep interval between main loop polls.
Chris Luke90f52bf2016-09-12 08:55:13 -0400560?*/
Damjan Marion57d963f2017-07-20 19:17:06 +0200561VLIB_EARLY_CONFIG_FUNCTION (unix_config, "unix");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700562
563static clib_error_t *
564unix_exit (vlib_main_t * vm)
565{
566 /* Close syslog connection. */
567 closelog ();
568 return 0;
569}
570
571VLIB_MAIN_LOOP_EXIT_FUNCTION (unix_exit);
572
573u8 **vlib_thread_stacks;
574
Dave Barach9b8ffd92016-07-08 08:13:45 -0400575static uword
576thread0 (uword arg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700577{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400578 vlib_main_t *vm = (vlib_main_t *) arg;
Damjan Marion2e90b292022-04-04 18:48:11 +0200579 vlib_global_main_t *vgm = vlib_get_global_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580 unformat_input_t input;
581 int i;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400582
Damjan Marioncea46522020-05-21 16:47:05 +0200583 vlib_process_finish_switch_stack (vm);
584
Damjan Marion2e90b292022-04-04 18:48:11 +0200585 unformat_init_command_line (&input, (char **) vgm->argv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700586 i = vlib_main (vm, &input);
587 unformat_free (&input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700588
Dave Barach9b8ffd92016-07-08 08:13:45 -0400589 return i;
590}
591
Damjan Marion586afd72017-04-05 19:18:20 +0200592u8 *
593vlib_thread_stack_init (uword thread_index)
594{
Damjan Marionfc639ff2020-09-11 22:25:34 +0200595 void *stack;
Dave Barach2180bac2019-05-10 15:25:10 -0400596 ASSERT (thread_index < vec_len (vlib_thread_stacks));
Damjan Marionfc639ff2020-09-11 22:25:34 +0200597 stack = clib_mem_vm_map_stack (VLIB_THREAD_STACK_SIZE,
598 CLIB_MEM_PAGE_SZ_DEFAULT,
599 "thread stack: thread %u", thread_index);
Damjan Marion586afd72017-04-05 19:18:20 +0200600
Damjan Marionfc639ff2020-09-11 22:25:34 +0200601 if (stack == CLIB_MEM_VM_MAP_FAILED)
602 clib_panic ("failed to allocate thread %u stack", thread_index);
603
604 vlib_thread_stacks[thread_index] = stack;
605 return stack;
Damjan Marion586afd72017-04-05 19:18:20 +0200606}
607
Damjan Marion2e90b292022-04-04 18:48:11 +0200608#ifndef PATH_MAX
609#define PATH_MAX 4096
610#endif
611
Dave Barach9b8ffd92016-07-08 08:13:45 -0400612int
613vlib_unix_main (int argc, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700614{
Damjan Marionfd8deb42021-03-06 12:26:28 +0100615 vlib_global_main_t *vgm = vlib_get_global_main ();
Damjan Marion6ffb7c62021-03-26 13:06:13 +0100616 vlib_main_t *vm = vlib_get_first_main (); /* one and only time for this! */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700617 unformat_input_t input;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400618 clib_error_t *e;
Damjan Marion2e90b292022-04-04 18:48:11 +0200619 char buffer[PATH_MAX];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700620 int i;
621
Damjan Marionfd8deb42021-03-06 12:26:28 +0100622 vec_validate_aligned (vgm->vlib_mains, 0, CLIB_CACHE_LINE_BYTES);
623
Damjan Marion2e90b292022-04-04 18:48:11 +0200624 if ((i = readlink ("/proc/self/exe", buffer, sizeof (buffer) - 1)) > 0)
625 {
626 int j;
627 buffer[i] = 0;
628 vgm->exec_path = vec_new (char, i + 1);
629 clib_memcpy_fast (vgm->exec_path, buffer, i + 1);
630 for (j = i - 1; j > 0; j--)
631 if (buffer[j - 1] == '/')
632 break;
633 vgm->name = vec_new (char, i - j + 1);
634 clib_memcpy_fast (vgm->name, buffer + j, i - j + 1);
635 }
636 else
637 vgm->exec_path = vgm->name = argv[0];
638
639 vgm->argv = (u8 **) argv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700640
Dave Barach8dc954a2020-02-05 17:31:09 -0500641 clib_time_init (&vm->clib_time);
642
Dave Barachbc867c32020-11-25 10:07:09 -0500643 /* Turn on the event logger at the first possible moment */
Damjan Marionfd8deb42021-03-06 12:26:28 +0100644 vgm->configured_elog_ring_size = 128 << 10;
645 elog_init (vlib_get_elog_main (), vgm->configured_elog_ring_size);
Damjan Marionf553a2c2021-03-26 13:45:37 +0100646 elog_enable_disable (vlib_get_elog_main (), 1);
Dave Barachbc867c32020-11-25 10:07:09 -0500647
Damjan Marion2e90b292022-04-04 18:48:11 +0200648 unformat_init_command_line (&input, (char **) vgm->argv);
Damjan Marion3b46cba2017-01-23 21:13:45 +0100649 if ((e = vlib_plugin_config (vm, &input)))
650 {
651 clib_error_report (e);
652 return 1;
653 }
654 unformat_free (&input);
655
Ed Warnickecb9cada2015-12-08 15:45:58 -0700656 i = vlib_plugin_early_init (vm);
657 if (i)
658 return i;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400659
Damjan Marion2e90b292022-04-04 18:48:11 +0200660 unformat_init_command_line (&input, (char **) vgm->argv);
Damjan Marionfd8deb42021-03-06 12:26:28 +0100661 if (vgm->init_functions_called == 0)
662 vgm->init_functions_called = hash_create (0, /* value bytes */ 0);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400663 e = vlib_call_all_config_functions (vm, &input, 1 /* early */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700664 if (e != 0)
665 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400666 clib_error_report (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700667 return 1;
668 }
669 unformat_free (&input);
670
Kingwel Xie497deaf2018-06-15 04:56:24 -0400671 /* always load symbols, for signal handler and mheap memory get/put backtrace */
Damjan Marion2e90b292022-04-04 18:48:11 +0200672 clib_elf_main_init (vgm->exec_path);
Kingwel Xie497deaf2018-06-15 04:56:24 -0400673
Dave Barach2180bac2019-05-10 15:25:10 -0400674 vec_validate (vlib_thread_stacks, 0);
Damjan Marion586afd72017-04-05 19:18:20 +0200675 vlib_thread_stack_init (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700676
Damjan Marionf55f9b82017-05-10 21:06:28 +0200677 __os_thread_index = 0;
Keith Burns (alagalah)0bda0f42017-10-20 13:55:18 -0700678 vm->thread_index = 0;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400679
Damjan Marioncea46522020-05-21 16:47:05 +0200680 vlib_process_start_switch_stack (vm, 0);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400681 i = clib_calljmp (thread0, (uword) vm,
682 (void *) (vlib_thread_stacks[0] +
683 VLIB_THREAD_STACK_SIZE));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700684 return i;
685}
Dave Barach9b8ffd92016-07-08 08:13:45 -0400686
687/*
688 * fd.io coding-style-patch-verification: ON
689 *
690 * Local Variables:
691 * eval: (c-set-style "gnu")
692 * End:
693 */