1 /*****************************************************************************\
2  *  slurm_protocol_api.c - high-level slurm communication functions
3  *****************************************************************************
4  *  Copyright (C) 2002-2007 The Regents of the University of California.
5  *  Copyright (C) 2008-2010 Lawrence Livermore National Security.
6  *  Copyright (C) 2010-2015 SchedMD LLC.
7  *  Copyright (C) 2013      Intel, Inc.
8  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
9  *  Written by Kevin Tew <tew1@llnl.gov>, et. al.
10  *  CODE-OCEC-09-009. All rights reserved.
11  *
12  *  This file is part of Slurm, a resource management program.
13  *  For details, see <https://slurm.schedmd.com/>.
14  *  Please also read the included file: DISCLAIMER.
15  *
16  *  Slurm is free software; you can redistribute it and/or modify it under
17  *  the terms of the GNU General Public License as published by the Free
18  *  Software Foundation; either version 2 of the License, or (at your option)
19  *  any later version.
20  *
21  *  In addition, as a special exception, the copyright holders give permission
22  *  to link the code of portions of this program with the OpenSSL library under
23  *  certain conditions as described in each individual source file, and
24  *  distribute linked combinations including the two. You must obey the GNU
25  *  General Public License in all respects for all of the code used other than
26  *  OpenSSL. If you modify file(s) with this exception, you may extend this
27  *  exception to your version of the file(s), but you are not obligated to do
28  *  so. If you do not wish to do so, delete this exception statement from your
29  *  version.  If you delete this exception statement from all source files in
30  *  the program, then also delete it here.
31  *
32  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
33  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
35  *  details.
36  *
37  *  You should have received a copy of the GNU General Public License along
38  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
39  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
40 \*****************************************************************************/
41 
42 #include "config.h"
43 
44 /* GLOBAL INCLUDES */
45 
46 #include <ctype.h>
47 #include <errno.h>
48 #include <poll.h>
49 #include <pthread.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <sys/stat.h>
54 #include <sys/types.h>
55 #include <time.h>
56 #include <unistd.h>
57 
58 /* PROJECT INCLUDES */
59 #include "src/common/assoc_mgr.h"
60 #include "src/common/fd.h"
61 #include "src/common/forward.h"
62 #include "src/common/log.h"
63 #include "src/common/macros.h"
64 #include "src/common/msg_aggr.h"
65 #include "src/common/pack.h"
66 #include "src/common/read_config.h"
67 #include "src/common/slurm_accounting_storage.h"
68 #include "src/common/slurm_auth.h"
69 #include "src/common/slurm_protocol_interface.h"
70 #include "src/common/slurm_protocol_api.h"
71 #include "src/common/slurm_protocol_common.h"
72 #include "src/common/slurm_protocol_pack.h"
73 #include "src/common/slurm_route.h"
74 #include "src/common/strlcpy.h"
75 #include "src/common/xmalloc.h"
76 #include "src/common/xstring.h"
77 #include "src/slurmdbd/read_config.h"
78 
79 strong_alias(convert_num_unit2, slurm_convert_num_unit2);
80 strong_alias(convert_num_unit, slurm_convert_num_unit);
81 strong_alias(revert_num_unit, slurm_revert_num_unit);
82 strong_alias(get_convert_unit_val, slurm_get_convert_unit_val);
83 strong_alias(get_unit_type, slurm_get_unit_type);
84 
85 /* EXTERNAL VARIABLES */
86 
87 /* #DEFINES */
88 #define _DEBUG	0
89 
90 /* STATIC VARIABLES */
91 static int message_timeout = -1;
92 
93 /* STATIC FUNCTIONS */
94 static char *_global_auth_key(void);
95 static void  _remap_slurmctld_errno(void);
96 static int   _unpack_msg_uid(Buf buffer, uint16_t protocol_version);
97 static bool  _is_port_ok(int, uint16_t, bool);
98 
99 #if _DEBUG
100 static void _print_data(char *data, int len);
101 #endif
102 
103 /* define slurmdbd_conf here so we can treat its existence as a flag */
104 slurmdbd_conf_t *slurmdbd_conf = NULL;
105 
106 /**********************************************************************\
107  * protocol configuration functions
108 \**********************************************************************/
109 
110 /* Free memory space returned by _slurm_api_get_comm_config() */
_slurm_api_free_comm_config(slurm_protocol_config_t * proto_conf)111 static void _slurm_api_free_comm_config(slurm_protocol_config_t *proto_conf)
112 {
113 	if (proto_conf) {
114 		xfree(proto_conf->controller_addr);
115 		xfree(proto_conf);
116 	}
117 }
118 
119 /*
120  * Get communication data structure based upon configuration file
121  * RET communication information structure, call _slurm_api_free_comm_config
122  *	to release allocated memory
123  */
_slurm_api_get_comm_config(void)124 static slurm_protocol_config_t *_slurm_api_get_comm_config(void)
125 {
126 	slurm_protocol_config_t *proto_conf = NULL;
127 	slurm_addr_t controller_addr;
128 	slurm_ctl_conf_t *conf;
129 	int i;
130 
131 	conf = slurm_conf_lock();
132 
133 	if (!conf->control_cnt ||
134 	    !conf->control_addr || !conf->control_addr[0]) {
135 		error("Unable to establish controller machine");
136 		goto cleanup;
137 	}
138 	if (conf->slurmctld_port == 0) {
139 		error("Unable to establish controller port");
140 		goto cleanup;
141 	}
142 	if (conf->control_cnt == 0) {
143 		error("No slurmctld servers configured");
144 		goto cleanup;
145 	}
146 
147 	memset(&controller_addr, 0, sizeof(slurm_addr_t));
148 	slurm_set_addr(&controller_addr, conf->slurmctld_port,
149 		       conf->control_addr[0]);
150 	if (controller_addr.sin_port == 0) {
151 		error("Unable to establish control machine address");
152 		goto cleanup;
153 	}
154 
155 	proto_conf = xmalloc(sizeof(slurm_protocol_config_t));
156 	proto_conf->controller_addr = xcalloc(conf->control_cnt,
157 					      sizeof(slurm_addr_t));
158 	proto_conf->control_cnt = conf->control_cnt;
159 	memcpy(&proto_conf->controller_addr[0], &controller_addr,
160 	       sizeof(slurm_addr_t));
161 
162 	for (i = 1; i < proto_conf->control_cnt; i++) {
163 		if (conf->control_addr[i]) {
164 			slurm_set_addr(&proto_conf->controller_addr[i],
165 				       conf->slurmctld_port,
166 				       conf->control_addr[i]);
167 		}
168 	}
169 
170 	if (conf->slurmctld_addr) {
171 		proto_conf->vip_addr_set = true;
172 		slurm_set_addr(&proto_conf->vip_addr, conf->slurmctld_port,
173 			       conf->slurmctld_addr);
174 	}
175 
176 cleanup:
177 	slurm_conf_unlock();
178 	return proto_conf;
179 }
180 
181 /* slurm_api_clear_config
182  * execute this only at program termination to free all memory */
slurm_api_clear_config(void)183 void slurm_api_clear_config(void)
184 {
185 	slurm_conf_destroy();
186 }
187 
188 /* slurm_get_complete_wait
189  * RET CompleteWait value from slurm.conf
190  */
slurm_get_complete_wait(void)191 uint16_t slurm_get_complete_wait(void)
192 {
193 	uint16_t complete_wait = 0;
194 	slurm_ctl_conf_t *conf;
195 
196 	if (slurmdbd_conf) {
197 	} else {
198 		conf = slurm_conf_lock();
199 		complete_wait = conf->complete_wait;
200 		slurm_conf_unlock();
201 	}
202 	return complete_wait;
203 }
204 
205 /* slurm_get_cpu_freq_def
206  * RET CpuFreqDef value from slurm.conf
207  */
slurm_get_cpu_freq_def(void)208 uint32_t slurm_get_cpu_freq_def(void)
209 {
210 	uint32_t cpu_freq_def = 0;
211 	slurm_ctl_conf_t *conf;
212 
213 	if (slurmdbd_conf) {
214 	} else {
215 		conf = slurm_conf_lock();
216 		cpu_freq_def = conf->cpu_freq_def;
217 		slurm_conf_unlock();
218 	}
219 	return cpu_freq_def;
220 }
221 
222 /* slurm_get_cpu_freq_govs
223  * RET CpuFreqGovernors value from slurm.conf
224  */
slurm_get_cpu_freq_govs(void)225 uint32_t slurm_get_cpu_freq_govs(void)
226 {
227 	uint32_t cpu_freq_govs = 0;
228 	slurm_ctl_conf_t *conf;
229 
230 	if (slurmdbd_conf) {
231 	} else {
232 		conf = slurm_conf_lock();
233 		cpu_freq_govs = conf->cpu_freq_govs;
234 		slurm_conf_unlock();
235 	}
236 	return cpu_freq_govs;
237 }
238 
239 /* slurm_get_batch_start_timeout
240  * RET BatchStartTimeout value from slurm.conf
241  */
slurm_get_batch_start_timeout(void)242 uint16_t slurm_get_batch_start_timeout(void)
243 {
244 	uint16_t batch_start_timeout = 0;
245 	slurm_ctl_conf_t *conf;
246 
247 	if (slurmdbd_conf) {
248 	} else {
249 		conf = slurm_conf_lock();
250 		batch_start_timeout = conf->batch_start_timeout;
251 		slurm_conf_unlock();
252 	}
253 	return batch_start_timeout;
254 }
255 
256 /*
257  * slurm_get_control_cnt
258  * RET Count of SlurmctldHost records from slurm.conf
259  * (slurmctld server count, primary plus backups)
260  */
slurm_get_control_cnt(void)261 uint32_t slurm_get_control_cnt(void)
262 {
263 	uint32_t control_cnt = 0;
264 	slurm_ctl_conf_t *conf;
265 
266 	if (slurmdbd_conf) {
267 	} else {
268 		conf = slurm_conf_lock();
269 		control_cnt = conf->control_cnt;
270 		slurm_conf_unlock();
271 	}
272 	return control_cnt;
273 }
274 
275 /* slurm_get_suspend_timeout
276  * RET SuspendTimeout value from slurm.conf
277  */
slurm_get_suspend_timeout(void)278 uint16_t slurm_get_suspend_timeout(void)
279 {
280 	uint16_t suspend_timeout = 0;
281 	slurm_ctl_conf_t *conf;
282 
283 	if (slurmdbd_conf) {
284 	} else {
285 		conf = slurm_conf_lock();
286 		suspend_timeout = conf->suspend_timeout;
287 		slurm_conf_unlock();
288 	}
289 	return suspend_timeout;
290 }
291 
292 /* slurm_get_resume_timeout
293  * RET ResumeTimeout value from slurm.conf
294  */
slurm_get_resume_timeout(void)295 uint16_t slurm_get_resume_timeout(void)
296 {
297 	uint16_t resume_timeout = 0;
298 	slurm_ctl_conf_t *conf;
299 
300 	if (slurmdbd_conf) {
301 	} else {
302 		conf = slurm_conf_lock();
303 		resume_timeout = conf->resume_timeout;
304 		slurm_conf_unlock();
305 	}
306 	return resume_timeout;
307 }
308 
309 /* slurm_get_suspend_time
310  * RET SuspendTime value from slurm.conf
311  */
slurm_get_suspend_time(void)312 uint32_t slurm_get_suspend_time(void)
313 {
314 	uint32_t suspend_time = 0;
315 	slurm_ctl_conf_t *conf;
316 
317 	if (slurmdbd_conf) {
318 	} else {
319 		conf = slurm_conf_lock();
320 		suspend_time = conf->suspend_time;
321 		slurm_conf_unlock();
322 	}
323 	return suspend_time;
324 }
325 
326 /* slurm_get_def_mem_per_cpu
327  * RET DefMemPerCPU/Node value from slurm.conf
328  */
slurm_get_def_mem_per_cpu(void)329 uint64_t slurm_get_def_mem_per_cpu(void)
330 {
331 	uint64_t mem_per_cpu = 0;
332 	slurm_ctl_conf_t *conf;
333 
334 	if (slurmdbd_conf) {
335 	} else {
336 		conf = slurm_conf_lock();
337 		mem_per_cpu = conf->def_mem_per_cpu;
338 		slurm_conf_unlock();
339 	}
340 	return mem_per_cpu;
341 }
342 
343 /* slurm_get_kill_on_bad_exit
344  * RET KillOnBadExit value from slurm.conf
345  */
slurm_get_kill_on_bad_exit(void)346 uint16_t slurm_get_kill_on_bad_exit(void)
347 {
348 	uint16_t kill_on_bad_exit = 0;
349 	slurm_ctl_conf_t *conf;
350 
351 	if (slurmdbd_conf) {
352 	} else {
353 		conf = slurm_conf_lock();
354 		kill_on_bad_exit = conf->kill_on_bad_exit;
355 		slurm_conf_unlock();
356 	}
357 	return kill_on_bad_exit;
358 }
359 
360 /* slurm_get_prolog_flags
361  * RET PrologFlags value from slurm.conf
362  */
slurm_get_prolog_flags(void)363 uint32_t slurm_get_prolog_flags(void)
364 {
365 	uint32_t prolog_flags = 0;
366 	slurm_ctl_conf_t *conf;
367 
368 	if (slurmdbd_conf) {
369 	} else {
370 		conf = slurm_conf_lock();
371 		prolog_flags = conf->prolog_flags;
372 		slurm_conf_unlock();
373 	}
374 	return prolog_flags;
375 }
376 
377 /* slurm_get_debug_flags
378  * RET DebugFlags value from slurm.conf
379  */
slurm_get_debug_flags(void)380 uint64_t slurm_get_debug_flags(void)
381 {
382 	uint64_t debug_flags = 0;
383 	slurm_ctl_conf_t *conf;
384 
385 	if (slurmdbd_conf) {
386 		debug_flags = slurmdbd_conf->debug_flags;
387 	} else {
388 		conf = slurm_conf_lock();
389 		debug_flags = conf->debug_flags;
390 		slurm_conf_unlock();
391 	}
392 	return debug_flags;
393 }
394 
395 /* slurm_set_debug_flags
396  */
slurm_set_debug_flags(uint64_t debug_flags)397 void slurm_set_debug_flags(uint64_t debug_flags)
398 {
399 	slurm_ctl_conf_t *conf;
400 
401 	if (slurmdbd_conf) {
402 	} else {
403 		conf = slurm_conf_lock();
404 		conf->debug_flags = debug_flags;
405 		slurm_conf_unlock();
406 	}
407 }
408 
409 /* slurm_get_max_mem_per_cpu
410  * RET MaxMemPerCPU/Node value from slurm.conf
411  */
slurm_get_max_mem_per_cpu(void)412 uint64_t slurm_get_max_mem_per_cpu(void)
413 {
414 	uint64_t mem_per_cpu = 0;
415 	slurm_ctl_conf_t *conf;
416 
417 	if (slurmdbd_conf) {
418 	} else {
419 		conf = slurm_conf_lock();
420 		mem_per_cpu = conf->max_mem_per_cpu;
421 		slurm_conf_unlock();
422 	}
423 	return mem_per_cpu;
424 }
425 
426 /* slurm_get_epilog_msg_time
427  * RET EpilogMsgTime value from slurm.conf
428  */
slurm_get_epilog_msg_time(void)429 uint32_t slurm_get_epilog_msg_time(void)
430 {
431 	uint32_t epilog_msg_time = 0;
432 	slurm_ctl_conf_t *conf;
433 
434  	if (slurmdbd_conf) {
435 	} else {
436 		conf = slurm_conf_lock();
437 		epilog_msg_time = conf->epilog_msg_time;
438 		slurm_conf_unlock();
439 	}
440 	return epilog_msg_time;
441 }
442 
443 /* slurm_get_env_timeout
444  * return default timeout for srun/sbatch --get-user-env option
445  */
slurm_get_env_timeout(void)446 extern int slurm_get_env_timeout(void)
447 {
448 	int timeout = 0;
449 	slurm_ctl_conf_t *conf;
450 
451 	if (slurmdbd_conf) {
452 	} else {
453 		conf = slurm_conf_lock();
454 		timeout = conf->get_env_timeout;
455 		slurm_conf_unlock();
456 	}
457 	return timeout;
458 }
459 
460 /* slurm_get_max_array_size
461  * return MaxArraySize configuration parameter
462  */
slurm_get_max_array_size(void)463 extern uint32_t slurm_get_max_array_size(void)
464 {
465 	int max_array_size = 0;
466 	slurm_ctl_conf_t *conf;
467 
468 	if (slurmdbd_conf) {
469 	} else {
470 		conf = slurm_conf_lock();
471 		max_array_size = conf->max_array_sz;
472 		slurm_conf_unlock();
473 	}
474 	return max_array_size;
475 }
476 
477 
478 /* slurm_get_mpi_default
479  * get default mpi value from slurmctld_conf object
480  * RET char *   - mpi default value from slurm.conf,  MUST be xfreed by caller
481  */
slurm_get_mpi_default(void)482 char *slurm_get_mpi_default(void)
483 {
484 	char *mpi_default = NULL;
485 	slurm_ctl_conf_t *conf;
486 
487 	if (slurmdbd_conf) {
488 	} else {
489 		conf = slurm_conf_lock();
490 		mpi_default = xstrdup(conf->mpi_default);
491 		slurm_conf_unlock();
492 	}
493 	return mpi_default;
494 }
495 
496 /* slurm_get_mpi_params
497  * get mpi parameters value from slurmctld_conf object
498  * RET char *   - mpi default value from slurm.conf,  MUST be xfreed by caller
499  */
slurm_get_mpi_params(void)500 char *slurm_get_mpi_params(void)
501 {
502 	char *mpi_params = NULL;
503 	slurm_ctl_conf_t *conf;
504 
505 	if (slurmdbd_conf) {
506 	} else {
507 		conf = slurm_conf_lock();
508 		mpi_params = xstrdup(conf->mpi_params);
509 		slurm_conf_unlock();
510 	}
511 	return mpi_params;
512 }
513 
514 /* slurm_get_msg_aggr_params
515  * get message aggregation parameters value from slurmctld_conf object
516  * RET char *   - message aggregation value from slurm.conf,
517  * MUST be xfreed by caller
518  */
slurm_get_msg_aggr_params(void)519 char *slurm_get_msg_aggr_params(void)
520 {
521 	char *msg_aggr_params = NULL;
522 	slurm_ctl_conf_t *conf;
523 
524 	if (slurmdbd_conf) {
525 	} else {
526 		conf = slurm_conf_lock();
527 		msg_aggr_params = xstrdup(conf->msg_aggr_params);
528 		slurm_conf_unlock();
529 	}
530 	return msg_aggr_params;
531 }
532 
533 /* slurm_get_reboot_program
534  * RET char * - RebootProgram from slurm.conf, MUST be xfreed by caller
535  */
slurm_get_reboot_program(void)536 extern char *slurm_get_reboot_program(void)
537 {
538 	char *reboot_program = NULL;
539 	slurm_ctl_conf_t *conf;
540 
541 	if (slurmdbd_conf) {
542 	} else {
543 		conf = slurm_conf_lock();
544 		reboot_program = xstrdup(conf->reboot_program);
545 		slurm_conf_unlock();
546 	}
547 	return reboot_program;
548 }
549 
550 /* slurm_get_tcp_timeout
551  * get default tcp timeout value from slurmctld_conf object
552  */
slurm_get_tcp_timeout(void)553 uint16_t slurm_get_tcp_timeout(void)
554 {
555 	uint16_t tcp_timeout = 0;
556 	slurm_ctl_conf_t *conf;
557 
558  	if (slurmdbd_conf) {
559 		tcp_timeout = slurmdbd_conf->tcp_timeout;
560 	} else {
561 		conf = slurm_conf_lock();
562 		tcp_timeout = conf->tcp_timeout;
563 		slurm_conf_unlock();
564 	}
565 	return tcp_timeout;
566 }
567 
568 /* slurm_get_msg_timeout
569  * get default message timeout value from slurmctld_conf object
570  */
slurm_get_msg_timeout(void)571 uint16_t slurm_get_msg_timeout(void)
572 {
573 	uint16_t msg_timeout = 0;
574 	slurm_ctl_conf_t *conf;
575 
576  	if (slurmdbd_conf) {
577 		msg_timeout = slurmdbd_conf->msg_timeout;
578 	} else {
579 		conf = slurm_conf_lock();
580 		msg_timeout = conf->msg_timeout;
581 		slurm_conf_unlock();
582 #ifdef MEMORY_LEAK_DEBUG
583 		msg_timeout *= 4;
584 #endif
585 	}
586 	return msg_timeout;
587 }
588 
589 /* slurm_get_plugin_dir
590  * get plugin directory from slurmctld_conf object
591  * RET char *   - plugin directory, MUST be xfreed by caller
592  */
slurm_get_plugin_dir(void)593 char *slurm_get_plugin_dir(void)
594 {
595 	char *plugin_dir = NULL;
596 	slurm_ctl_conf_t *conf;
597 
598 	if (slurmdbd_conf) {
599 		plugin_dir = xstrdup(slurmdbd_conf->plugindir);
600 	} else {
601 		conf = slurm_conf_lock();
602 		plugin_dir = xstrdup(conf->plugindir);
603 		slurm_conf_unlock();
604 	}
605 	return plugin_dir;
606 }
607 
608 /* slurm_get_priority_decay_hl
609  * returns the priority decay half life in seconds from slurmctld_conf object
610  * RET uint32_t - decay_hl in secs.
611  */
slurm_get_priority_decay_hl(void)612 uint32_t slurm_get_priority_decay_hl(void)
613 {
614 	uint32_t priority_hl = NO_VAL;
615 	slurm_ctl_conf_t *conf;
616 
617 	if (slurmdbd_conf) {
618 	} else {
619 		conf = slurm_conf_lock();
620 		priority_hl = conf->priority_decay_hl;
621 		slurm_conf_unlock();
622 	}
623 
624 	return priority_hl;
625 }
626 
627 /* slurm_get_priority_calc_period
628  * returns the seconds between priority decay calculation from slurmctld_conf
629  * RET uint32_t - calc_period in secs.
630  */
slurm_get_priority_calc_period(void)631 uint32_t slurm_get_priority_calc_period(void)
632 {
633 	uint32_t calc_period = NO_VAL;
634 	slurm_ctl_conf_t *conf;
635 
636 	if (slurmdbd_conf) {
637 	} else {
638 		conf = slurm_conf_lock();
639 		calc_period = conf->priority_calc_period;
640 		slurm_conf_unlock();
641 	}
642 
643 	return calc_period;
644 }
645 
646 /* slurm_get_priority_favor_small
647  * returns weither or not we are favoring small jobs from slurmctld_conf object
648  * RET bool - true if favor small, false else.
649  */
slurm_get_priority_favor_small(void)650 bool slurm_get_priority_favor_small(void)
651 {
652 	bool factor = 0;
653 	slurm_ctl_conf_t *conf;
654 
655 	if (slurmdbd_conf) {
656 	} else {
657 		conf = slurm_conf_lock();
658 		factor = conf->priority_favor_small;
659 		slurm_conf_unlock();
660 	}
661 
662 	return factor;
663 }
664 
665 /* slurm_get_priority_flags
666  * returns the priority flags bitmap from slurmctld_conf object
667  * RET uint16_t - priority flags
668  */
slurm_get_priority_flags(void)669 uint16_t slurm_get_priority_flags(void)
670 {
671 	uint16_t flags = 0;
672 	slurm_ctl_conf_t *conf;
673 
674 	if (slurmdbd_conf) {
675 	} else {
676 		conf = slurm_conf_lock();
677 		flags = conf->priority_flags;
678 		slurm_conf_unlock();
679 	}
680 
681 	return flags;
682 }
683 
684 /* slurm_get_priority_max_age
685  * returns the priority age max in seconds from slurmctld_conf object
686  * RET uint32_t - age_max in secs.
687  */
slurm_get_priority_max_age(void)688 uint32_t slurm_get_priority_max_age(void)
689 {
690 	uint32_t age = NO_VAL;
691 	slurm_ctl_conf_t *conf;
692 
693 	if (slurmdbd_conf) {
694 	} else {
695 		conf = slurm_conf_lock();
696 		age = conf->priority_max_age;
697 		slurm_conf_unlock();
698 	}
699 
700 	return age;
701 }
702 
703 /* slurm_get_priority_params
704  * RET char * - Value of PriorityParameters, MUST be xfreed by caller */
slurm_get_priority_params(void)705 char *slurm_get_priority_params(void)
706 {
707 	char *params = 0;
708 	slurm_ctl_conf_t *conf;
709 
710  	if (slurmdbd_conf) {
711 	} else {
712 		conf = slurm_conf_lock();
713 		params = xstrdup(conf->priority_params);
714 		slurm_conf_unlock();
715 	}
716 	return params;
717 }
718 
719 /* slurm_get_priority_reset_period
720  * returns the priority usage reset period from slurmctld_conf object
721  * RET uint16_t - flag, see PRIORITY_RESET_* in slurm/slurm.h.
722  */
slurm_get_priority_reset_period(void)723 uint16_t slurm_get_priority_reset_period(void)
724 {
725 	uint16_t reset_period = (uint16_t) 0;
726 	slurm_ctl_conf_t *conf;
727 
728 	if (slurmdbd_conf) {
729 	} else {
730 		conf = slurm_conf_lock();
731 		reset_period = conf->priority_reset_period;
732 		slurm_conf_unlock();
733 	}
734 
735 	return reset_period;
736 }
737 
738 /* slurm_get_priority_site_factor_params
739  * returns the site_factor_params value from slurmctld_conf object
740  * RET char *    - site_factor_params, MUST be xfreed by caller
741  */
slurm_get_priority_site_factor_params(void)742 char *slurm_get_priority_site_factor_params(void)
743 {
744 	char *params = NULL;
745 	slurm_ctl_conf_t *conf;
746 
747 	if (slurmdbd_conf) {
748 	} else {
749 		conf = slurm_conf_lock();
750 		params = xstrdup(conf->site_factor_params);
751 		slurm_conf_unlock();
752 	}
753 
754 	return params;
755 }
756 
757 /* slurm_get_priority_site_factor_plugin
758  * returns the site_factor_plugin value from slurmctld_conf object
759  * RET char *    - site_factor_plugin, MUST be xfreed by caller
760  */
slurm_get_priority_site_factor_plugin(void)761 char *slurm_get_priority_site_factor_plugin(void)
762 {
763 	char *plugin = NULL;
764 	slurm_ctl_conf_t *conf;
765 
766 	if (slurmdbd_conf) {
767 	} else {
768 		conf = slurm_conf_lock();
769 		plugin = xstrdup(conf->site_factor_plugin);
770 		slurm_conf_unlock();
771 	}
772 
773 	return plugin;
774 }
775 
776 /* slurm_get_priority_type
777  * returns the priority type from slurmctld_conf object
778  * RET char *    - priority type, MUST be xfreed by caller
779  */
slurm_get_priority_type(void)780 char *slurm_get_priority_type(void)
781 {
782 	char *priority_type = NULL;
783 	slurm_ctl_conf_t *conf;
784 
785 	if (slurmdbd_conf) {
786 	} else {
787 		conf = slurm_conf_lock();
788 		priority_type = xstrdup(conf->priority_type);
789 		slurm_conf_unlock();
790 	}
791 
792 	return priority_type;
793 }
794 
795 /* slurm_get_priority_weight_age
796  * returns the priority weight for age from slurmctld_conf object
797  * RET uint32_t - factor weight.
798  */
slurm_get_priority_weight_age(void)799 uint32_t slurm_get_priority_weight_age(void)
800 {
801 	uint32_t factor = NO_VAL;
802 	slurm_ctl_conf_t *conf;
803 
804 	if (slurmdbd_conf) {
805 	} else {
806 		conf = slurm_conf_lock();
807 		factor = conf->priority_weight_age;
808 		slurm_conf_unlock();
809 	}
810 
811 	return factor;
812 }
813 
814 
815 /* slurm_get_priority_weight_assoc
816  * returns the priority weight for association from slurmctld_conf object
817  * RET uint32_t - factor weight.
818  */
slurm_get_priority_weight_assoc(void)819 uint32_t slurm_get_priority_weight_assoc(void)
820 {
821 	uint32_t factor = NO_VAL;
822 	slurm_ctl_conf_t *conf;
823 
824 	if (slurmdbd_conf) {
825 	} else {
826 		conf = slurm_conf_lock();
827 		factor = conf->priority_weight_assoc;
828 		slurm_conf_unlock();
829 	}
830 
831 	return factor;
832 }
833 
834 
835 /* slurm_get_priority_weight_fairshare
836  * returns the priority weight for fairshare from slurmctld_conf object
837  * RET uint32_t - factor weight.
838  */
slurm_get_priority_weight_fairshare(void)839 uint32_t slurm_get_priority_weight_fairshare(void)
840 {
841 	uint32_t factor = NO_VAL;
842 	slurm_ctl_conf_t *conf;
843 
844 	if (slurmdbd_conf) {
845 	} else {
846 		conf = slurm_conf_lock();
847 		factor = conf->priority_weight_fs;
848 		slurm_conf_unlock();
849 	}
850 
851 	return factor;
852 }
853 
854 /* slurm_get_fs_dampening_factor
855  * returns the dampening factor for fairshare from slurmctld_conf object
856  * RET uint32_t - factor.
857  */
slurm_get_fs_dampening_factor(void)858 uint16_t slurm_get_fs_dampening_factor(void)
859 {
860 	uint16_t factor = 1;
861 	slurm_ctl_conf_t *conf;
862 
863 	if (slurmdbd_conf) {
864 	} else {
865 		conf = slurm_conf_lock();
866 		factor = conf->fs_dampening_factor;
867 		slurm_conf_unlock();
868 	}
869 
870 	return factor;
871 }
872 
873 /* slurm_set_fs_dampening_factor
874  * set the dampening factor for fairshare from slurmctld_conf object
875  */
slurm_set_fs_dampening_factor(uint16_t factor)876 void slurm_set_fs_dampening_factor(uint16_t factor)
877 {
878 	slurm_ctl_conf_t *conf;
879 
880 	if (slurmdbd_conf) {
881 	} else {
882 		conf = slurm_conf_lock();
883 		conf->fs_dampening_factor = factor;
884 		slurm_conf_unlock();
885 	}
886 }
887 /* slurm_get_priority_weight_job_size
888  * returns the priority weight for job size from slurmctld_conf object
889  * RET uint32_t - factor weight.
890  */
slurm_get_priority_weight_job_size(void)891 uint32_t slurm_get_priority_weight_job_size(void)
892 {
893 	uint32_t factor = NO_VAL;
894 	slurm_ctl_conf_t *conf;
895 
896 	if (slurmdbd_conf) {
897 	} else {
898 		conf = slurm_conf_lock();
899 		factor = conf->priority_weight_js;
900 		slurm_conf_unlock();
901 	}
902 
903 	return factor;
904 }
905 
906 /* slurm_get_priority_weight_partition
907  * returns the priority weight for partitions from slurmctld_conf object
908  * RET uint32_t - factor weight.
909  */
slurm_get_priority_weight_partition(void)910 uint32_t slurm_get_priority_weight_partition(void)
911 {
912 	uint32_t factor = NO_VAL;
913 	slurm_ctl_conf_t *conf;
914 
915 	if (slurmdbd_conf) {
916 	} else {
917 		conf = slurm_conf_lock();
918 		factor = conf->priority_weight_part;
919 		slurm_conf_unlock();
920 	}
921 
922 	return factor;
923 }
924 
925 
926 /* slurm_get_priority_weight_qos
927  * returns the priority weight for QOS from slurmctld_conf object
928  * RET uint32_t - factor weight.
929  */
slurm_get_priority_weight_qos(void)930 uint32_t slurm_get_priority_weight_qos(void)
931 {
932 	uint32_t factor = NO_VAL;
933 	slurm_ctl_conf_t *conf;
934 
935 	if (slurmdbd_conf) {
936 	} else {
937 		conf = slurm_conf_lock();
938 		factor = conf->priority_weight_qos;
939 		slurm_conf_unlock();
940 	}
941 
942 	return factor;
943 }
944 
945 /* slurm_get_priority_weight_tres
946  * returns the priority weights for TRES' from slurmctld_conf object
947  * RET char * string of configured tres weights. MUST be xfreed by caller
948  */
slurm_get_priority_weight_tres(void)949 char *slurm_get_priority_weight_tres(void)
950 {
951 	char *weights = NULL;
952 	slurm_ctl_conf_t *conf;
953 
954 	if (slurmdbd_conf) {
955 	} else {
956 		conf = slurm_conf_lock();
957 		weights = xstrdup(conf->priority_weight_tres);
958 		slurm_conf_unlock();
959 	}
960 
961 	return weights;
962 }
963 
964 /* slurm_get_prep_plugins
965  * returns the PrEpPlugins from slurmctld_conf object
966  * RET char *    - PrEpPlugins, MUST be xfreed by caller
967  */
slurm_get_prep_plugins(void)968 char *slurm_get_prep_plugins(void)
969 {
970 	char *plugins = NULL;
971 	slurm_ctl_conf_t *conf;
972 
973 	if (slurmdbd_conf) {
974 	} else {
975 		conf = slurm_conf_lock();
976 		plugins = xstrdup(conf->prep_plugins);
977 		slurm_conf_unlock();
978 	}
979 
980 	return plugins;
981 }
982 
_get_tres_id(char * type,char * name)983 static int _get_tres_id(char *type, char *name)
984 {
985 	slurmdb_tres_rec_t tres_rec;
986 	memset(&tres_rec, 0, sizeof(slurmdb_tres_rec_t));
987 	tres_rec.type = type;
988 	tres_rec.name = name;
989 
990 	return assoc_mgr_find_tres_pos(&tres_rec, false);
991 }
992 
_tres_weight_item(double * weights,char * item_str)993 static int _tres_weight_item(double *weights, char *item_str)
994 {
995 	char *type = NULL, *value_str = NULL, *val_unit = NULL, *name = NULL;
996 	int tres_id;
997 	double weight_value = 0;
998 
999 	if (!item_str) {
1000 		error("TRES weight item is null");
1001 		return SLURM_ERROR;
1002 	}
1003 
1004 	type = strtok_r(item_str, "=", &value_str);
1005 	if (type == NULL) {
1006 		error("\"%s\" is an invalid TRES weight entry", item_str);
1007 		return SLURM_ERROR;
1008 	}
1009 	if (strchr(type, '/'))
1010 		type = strtok_r(type, "/", &name);
1011 
1012 	if (!value_str || !*value_str) {
1013 		error("\"%s\" is an invalid TRES weight entry", item_str);
1014 		return SLURM_ERROR;
1015 	}
1016 
1017 	if ((tres_id = _get_tres_id(type, name)) == -1) {
1018 		error("TRES weight '%s%s%s' is not a configured TRES type.",
1019 		      type, (name) ? ":" : "", (name) ? name : "");
1020 		return SLURM_ERROR;
1021 	}
1022 
1023 	errno = 0;
1024 	weight_value = strtod(value_str, &val_unit);
1025 	if (errno) {
1026 		error("Unable to convert %s value to double in %s",
1027 		      __func__, value_str);
1028 		return SLURM_ERROR;
1029 	}
1030 
1031 	if (val_unit && *val_unit) {
1032 		int base_unit = slurmdb_get_tres_base_unit(type);
1033 		int convert_val = get_convert_unit_val(base_unit, *val_unit);
1034 		if (convert_val == SLURM_ERROR)
1035 			return SLURM_ERROR;
1036 		if (convert_val > 0) {
1037 			weight_value /= convert_val;
1038 		}
1039 	}
1040 
1041 	weights[tres_id] = weight_value;
1042 
1043 	return SLURM_SUCCESS;
1044 }
1045 
1046 /* slurm_get_tres_weight_array
1047  * IN weights_str - string of tres and weights to be parsed.
1048  * IN tres_cnt - count of how many tres' are on the system (e.g.
1049  * 		slurmctld_tres_cnt).
1050  * IN fail - whether to fatal or not if there are parsing errors.
1051  * RET double* of tres weights.
1052  */
slurm_get_tres_weight_array(char * weights_str,int tres_cnt,bool fail)1053 double *slurm_get_tres_weight_array(char *weights_str, int tres_cnt, bool fail)
1054 {
1055 	double *weights;
1056 	char *tmp_str;
1057 	char *token, *last = NULL;
1058 
1059 	if (!weights_str || !*weights_str || !tres_cnt)
1060 		return NULL;
1061 
1062 	tmp_str = xstrdup(weights_str);
1063 	weights = xcalloc(tres_cnt, sizeof(double));
1064 
1065 	token = strtok_r(tmp_str, ",", &last);
1066 	while (token) {
1067 		if (_tres_weight_item(weights, token)) {
1068 			xfree(weights);
1069 			xfree(tmp_str);
1070 			if (fail)
1071 				fatal("failed to parse tres weights str '%s'",
1072 				      weights_str);
1073 			else
1074 				error("failed to parse tres weights str '%s'",
1075 				      weights_str);
1076 			return NULL;
1077 		}
1078 		token = strtok_r(NULL, ",", &last);
1079 	}
1080 	xfree(tmp_str);
1081 	return weights;
1082 }
1083 
1084 /* slurm_get_private_data
1085  * get private data from slurmctld_conf object
1086  */
slurm_get_private_data(void)1087 uint16_t slurm_get_private_data(void)
1088 {
1089 	uint16_t private_data = 0;
1090 	slurm_ctl_conf_t *conf;
1091 
1092 	if (slurmdbd_conf) {
1093 		private_data = slurmdbd_conf->private_data;
1094 	} else {
1095 		conf = slurm_conf_lock();
1096 		private_data = conf->private_data;
1097 		slurm_conf_unlock();
1098 	}
1099 	return private_data;
1100 }
1101 
1102 /* slurm_get_resume_fail_program
1103  * returns the ResumeFailProgram from slurmctld_conf object
1104  * RET char *    - ResumeFailProgram, MUST be xfreed by caller
1105  */
slurm_get_resume_fail_program(void)1106 char *slurm_get_resume_fail_program(void)
1107 {
1108 	char *resume_fail_program = NULL;
1109 	slurm_ctl_conf_t *conf;
1110 
1111 	if (slurmdbd_conf) {
1112 	} else {
1113 		conf = slurm_conf_lock();
1114 		resume_fail_program = xstrdup(conf->resume_fail_program);
1115 		slurm_conf_unlock();
1116 	}
1117 	return resume_fail_program;
1118 }
1119 
1120 /* slurm_get_resume_program
1121  * returns the ResumeProgram from slurmctld_conf object
1122  * RET char *    - ResumeProgram, MUST be xfreed by caller
1123  */
slurm_get_resume_program(void)1124 char *slurm_get_resume_program(void)
1125 {
1126 	char *resume_program = NULL;
1127 	slurm_ctl_conf_t *conf;
1128 
1129 	if (slurmdbd_conf) {
1130 	} else {
1131 		conf = slurm_conf_lock();
1132 		resume_program = xstrdup(conf->resume_program);
1133 		slurm_conf_unlock();
1134 	}
1135 	return resume_program;
1136 }
1137 
1138 /* slurm_get_state_save_location
1139  * get state_save_location from slurmctld_conf object from slurmctld_conf object
1140  * RET char *   - state_save_location directory, MUST be xfreed by caller
1141  */
slurm_get_state_save_location(void)1142 char *slurm_get_state_save_location(void)
1143 {
1144 	char *state_save_loc = NULL;
1145 	slurm_ctl_conf_t *conf;
1146 
1147 	if (slurmdbd_conf) {
1148 	} else {
1149 		conf = slurm_conf_lock();
1150 		state_save_loc = xstrdup(conf->state_save_location);
1151 		slurm_conf_unlock();
1152 	}
1153 	return state_save_loc;
1154 }
1155 
1156 /* slurm_get_stepd_loc
1157  * get path to the slurmstepd
1158  *      1. configure --sbindir concatenated with slurmstepd.
1159  *	2. configure --prefix concatenated with /sbin/slurmstepd.
1160  * RET char * - absolute path to the slurmstepd, MUST be xfreed by caller
1161  */
slurm_get_stepd_loc(void)1162 extern char *slurm_get_stepd_loc(void)
1163 {
1164 #ifdef SBINDIR
1165 	return xstrdup_printf("%s/slurmstepd", SBINDIR);
1166 #elif defined SLURM_PREFIX
1167 	return xstrdup_printf("%s/sbin/slurmstepd", SLURM_PREFIX);
1168 #endif
1169 }
1170 
1171 /* slurm_get_tmp_fs
1172  * returns the TmpFS configuration parameter from slurmctld_conf object
1173  * RET char *    - tmp_fs, MUST be xfreed by caller
1174  */
slurm_get_tmp_fs(char * node_name)1175 extern char *slurm_get_tmp_fs(char *node_name)
1176 {
1177 	char *tmp_fs = NULL;
1178 	slurm_ctl_conf_t *conf = NULL;
1179 
1180 	if (slurmdbd_conf) {
1181 	} else {
1182 		conf = slurm_conf_lock();
1183 		if (!node_name)
1184 			tmp_fs = xstrdup(conf->tmp_fs);
1185 		else
1186 			tmp_fs = slurm_conf_expand_slurmd_path(
1187 				conf->tmp_fs, node_name);
1188 		slurm_conf_unlock();
1189 	}
1190 	return tmp_fs;
1191 }
1192 
1193 /* slurm_get_auth_alt_types
1194  * returns the alternate authentication types from slurmctld_conf object
1195  * RET char *    - auth alternate types, MUST be xfreed by caller
1196  */
slurm_get_auth_alt_types(void)1197 char *slurm_get_auth_alt_types(void)
1198 {
1199 	char *auth_alt_types = NULL;
1200 	slurm_ctl_conf_t *conf = NULL;
1201 
1202 	if (slurmdbd_conf) {
1203 		auth_alt_types = xstrdup(slurmdbd_conf->auth_alt_types);
1204 	} else {
1205 		conf = slurm_conf_lock();
1206 		auth_alt_types = xstrdup(conf->authalttypes);
1207 		slurm_conf_unlock();
1208 	}
1209 	return auth_alt_types;
1210 }
1211 
1212 /* slurm_get_auth_type
1213  * returns the authentication type from slurmctld_conf object
1214  * RET char *    - auth type, MUST be xfreed by caller
1215  */
slurm_get_auth_type(void)1216 char *slurm_get_auth_type(void)
1217 {
1218 	char *auth_type = NULL;
1219 	slurm_ctl_conf_t *conf = NULL;
1220 
1221 	if (slurmdbd_conf) {
1222 		auth_type = xstrdup(slurmdbd_conf->auth_type);
1223 	} else {
1224 		conf = slurm_conf_lock();
1225 		auth_type = xstrdup(conf->authtype);
1226 		slurm_conf_unlock();
1227 	}
1228 	return auth_type;
1229 }
1230 
1231 /* slurm_get_bb_type
1232  * returns the BurstBufferType (bb_type) from slurmctld_conf object
1233  * RET char *    - BurstBufferType, MUST be xfreed by caller
1234  */
slurm_get_bb_type(void)1235 extern char *slurm_get_bb_type(void)
1236 {
1237 	char *bb_type = NULL;
1238 	slurm_ctl_conf_t *conf = NULL;
1239 
1240 	if (slurmdbd_conf) {
1241 	} else {
1242 		conf = slurm_conf_lock();
1243 		bb_type = xstrdup(conf->bb_type);
1244 		slurm_conf_unlock();
1245 	}
1246 	return bb_type;
1247 }
1248 
1249 /* slurm_get_cluster_name
1250  * returns the cluster name from slurmctld_conf object
1251  * RET char *    - cluster name,  MUST be xfreed by caller
1252  */
slurm_get_cluster_name(void)1253 char *slurm_get_cluster_name(void)
1254 {
1255 	char *name = NULL;
1256 	slurm_ctl_conf_t *conf;
1257 
1258 	if (slurmdbd_conf) {
1259 	} else {
1260 		conf = slurm_conf_lock();
1261 		name = xstrdup(conf->cluster_name);
1262 		slurm_conf_unlock();
1263 	}
1264 	return name;
1265 }
1266 
1267 /* slurm_get_comm_parameters
1268  * returns the value of comm_param in slurmctld_conf object
1269  * RET char *    - comm parameters, MUST be xfreed by caller
1270  */
slurm_get_comm_parameters(void)1271 extern char *slurm_get_comm_parameters(void)
1272 {
1273 	char *comm_params = NULL;
1274 	slurm_ctl_conf_t *conf;
1275 
1276 	if (slurmdbd_conf) {
1277 	} else {
1278 		conf = slurm_conf_lock();
1279 		comm_params = xstrdup(conf->comm_params);
1280 		slurm_conf_unlock();
1281 	}
1282 	return comm_params;
1283 }
1284 
1285 
1286 /* slurm_get_cred_type
1287  * returns the cred_type from slurmctld_conf object
1288  * RET char *    - cred type, MUST be xfreed by caller
1289  */
slurm_get_cred_type(void)1290 extern char *slurm_get_cred_type(void)
1291 {
1292 	char *cred_type = NULL;
1293 	slurm_ctl_conf_t *conf;
1294 
1295 	if (slurmdbd_conf) {
1296 	} else {
1297 		conf = slurm_conf_lock();
1298 		cred_type = xstrdup(conf->cred_type);
1299 		slurm_conf_unlock();
1300 	}
1301 	return cred_type;
1302 }
1303 
1304 /* slurm_get_power_parameters
1305  * returns the PowerParameters from slurmctld_conf object
1306  * RET char *    - PowerParameters, MUST be xfreed by caller
1307  */
slurm_get_power_parameters(void)1308 extern char *slurm_get_power_parameters(void)
1309 {
1310 	char *power_parameters = NULL;
1311 	slurm_ctl_conf_t *conf;
1312 
1313 	if (slurmdbd_conf) {
1314 	} else {
1315 		conf = slurm_conf_lock();
1316 		power_parameters = xstrdup(conf->power_parameters);
1317 		slurm_conf_unlock();
1318 	}
1319 	return power_parameters;
1320 }
1321 
1322 /* slurm_set_power_parameters
1323  * reset the PowerParameters object
1324  */
slurm_set_power_parameters(char * power_parameters)1325 extern void slurm_set_power_parameters(char *power_parameters)
1326 {
1327 	slurm_ctl_conf_t *conf;
1328 
1329 	if (slurmdbd_conf) {
1330 	} else {
1331 		conf = slurm_conf_lock();
1332 		xfree(conf->power_parameters);
1333 		conf->power_parameters = xstrdup(power_parameters);
1334 		slurm_conf_unlock();
1335 	}
1336 }
1337 
1338 /* slurm_get_power_plugin
1339  * returns the PowerPlugin from slurmctld_conf object
1340  * RET char *    - PowerPlugin, MUST be xfreed by caller
1341  */
slurm_get_power_plugin(void)1342 extern char *slurm_get_power_plugin(void)
1343 {
1344 	char *power_plugin = NULL;
1345 	slurm_ctl_conf_t *conf;
1346 
1347 	if (slurmdbd_conf) {
1348 	} else {
1349 		conf = slurm_conf_lock();
1350 		power_plugin = xstrdup(conf->power_plugin);
1351 		slurm_conf_unlock();
1352 	}
1353 	return power_plugin;
1354 }
1355 
1356 /* slurm_get_topology_param
1357  * returns the value of topology_param in slurmctld_conf object
1358  * RET char *    - topology parameters, MUST be xfreed by caller
1359  */
slurm_get_topology_param(void)1360 extern char * slurm_get_topology_param(void)
1361 {
1362 	char *topology_param = NULL;
1363 	slurm_ctl_conf_t *conf;
1364 
1365 	if (slurmdbd_conf) {
1366 	} else {
1367 		conf = slurm_conf_lock();
1368 		topology_param = xstrdup(conf->topology_param);
1369 		slurm_conf_unlock();
1370 	}
1371 	return topology_param;
1372 }
1373 
1374 /* slurm_get_topology_plugin
1375  * returns the value of topology_plugin in slurmctld_conf object
1376  * RET char *    - topology type, MUST be xfreed by caller
1377  */
slurm_get_topology_plugin(void)1378 extern char * slurm_get_topology_plugin(void)
1379 {
1380 	char *topology_plugin = NULL;
1381 	slurm_ctl_conf_t *conf;
1382 
1383 	if (slurmdbd_conf) {
1384 	} else {
1385 		conf = slurm_conf_lock();
1386 		topology_plugin = xstrdup(conf->topology_plugin);
1387 		slurm_conf_unlock();
1388 	}
1389 	return topology_plugin;
1390 }
1391 
1392 /* slurm_get_propagate_prio_process
1393  * return the PropagatePrioProcess flag from slurmctld_conf object
1394  */
slurm_get_propagate_prio_process(void)1395 extern uint16_t slurm_get_propagate_prio_process(void)
1396 {
1397 	uint16_t propagate_prio = 0;
1398 	slurm_ctl_conf_t *conf;
1399 
1400  	if (slurmdbd_conf) {
1401 	} else {
1402 		conf = slurm_conf_lock();
1403 		propagate_prio = conf->propagate_prio_process;
1404 		slurm_conf_unlock();
1405 	}
1406 	return propagate_prio;
1407 }
1408 
1409 /* slurm_get_route_plugin
1410  * returns the value of route_plugin in slurmctld_conf object
1411  * RET char *    - route type, MUST be xfreed by caller
1412  */
slurm_get_route_plugin(void)1413 extern char * slurm_get_route_plugin(void)
1414 {
1415 	char *route_plugin = NULL;
1416 	slurm_ctl_conf_t *conf;
1417 
1418 	if (slurmdbd_conf) {
1419 	} else {
1420 		conf = slurm_conf_lock();
1421 
1422 		route_plugin = xstrdup(conf->route_plugin);
1423 		slurm_conf_unlock();
1424 	}
1425 	return route_plugin;
1426 }
1427 
1428 /* slurm_get_track_wckey
1429  * returns the value of track_wckey in slurmctld_conf object
1430  */
slurm_get_track_wckey(void)1431 extern uint16_t slurm_get_track_wckey(void)
1432 {
1433 	uint16_t track_wckey = 0;
1434 	slurm_ctl_conf_t *conf;
1435 
1436 	if (slurmdbd_conf) {
1437 		track_wckey = slurmdbd_conf->track_wckey;
1438 	} else {
1439 		conf = slurm_conf_lock();
1440 		track_wckey = conf->conf_flags & CTL_CONF_WCKEY ? 1 : 0;
1441 		slurm_conf_unlock();
1442 	}
1443 	return track_wckey;
1444 }
1445 
1446 /* slurm_set_tree_width
1447  * sets the value of tree_width in slurmctld_conf object
1448  * RET 0 or error code
1449  */
slurm_set_tree_width(uint16_t tree_width)1450 extern int slurm_set_tree_width(uint16_t tree_width)
1451 {
1452 	slurm_ctl_conf_t *conf;
1453 
1454 	if (slurmdbd_conf) {
1455 	} else {
1456 		conf = slurm_conf_lock();
1457 		if (tree_width == 0) {
1458 			error("can't have span count of 0");
1459 			return SLURM_ERROR;
1460 		}
1461 		conf->tree_width = tree_width;
1462 		slurm_conf_unlock();
1463 	}
1464 	return 0;
1465 }
1466 /* slurm_get_tree_width
1467  * returns the value of tree_width in slurmctld_conf object
1468  */
slurm_get_tree_width(void)1469 extern uint16_t slurm_get_tree_width(void)
1470 {
1471 	/* initialize to 1 to silence later warnings
1472 	 * about potential division by zero */
1473 	uint16_t tree_width = 1;
1474 	slurm_ctl_conf_t *conf;
1475 
1476 	if (slurmdbd_conf) {
1477 	} else {
1478 		conf = slurm_conf_lock();
1479 		tree_width = conf->tree_width;
1480 		slurm_conf_unlock();
1481 	}
1482 	return tree_width;
1483 }
1484 
1485 /* slurm_get_vsize_factor
1486  * returns the value of vsize_factor in slurmctld_conf object
1487  */
slurm_get_vsize_factor(void)1488 extern uint16_t slurm_get_vsize_factor(void)
1489 {
1490 	uint16_t vsize_factor = 0;
1491 	slurm_ctl_conf_t *conf;
1492 
1493 	if (slurmdbd_conf) {
1494 	} else {
1495 		conf = slurm_conf_lock();
1496 		vsize_factor = conf->vsize_factor;
1497 		slurm_conf_unlock();
1498 	}
1499 	return vsize_factor;
1500 }
1501 
1502 /* slurm_set_auth_type
1503  * set the authentication type in slurmctld_conf object
1504  * used for security testing purposes
1505  * RET 0 or error code
1506  */
slurm_set_auth_type(char * auth_type)1507 extern int slurm_set_auth_type(char *auth_type)
1508 {
1509 	slurm_ctl_conf_t *conf;
1510 
1511 	if (slurmdbd_conf) {
1512 		xfree(slurmdbd_conf->auth_type);
1513 		slurmdbd_conf->auth_type = xstrdup(auth_type);
1514 	} else {
1515 		conf = slurm_conf_lock();
1516 		xfree(conf->authtype);
1517 		conf->authtype = xstrdup(auth_type);
1518 		slurm_conf_unlock();
1519 	}
1520 	return 0;
1521 }
1522 
1523 /* slurm_get_hash_val
1524  * get hash val of the slurm.conf from slurmctld_conf object from
1525  * slurmctld_conf object
1526  * RET uint32_t  - hash_val
1527  */
slurm_get_hash_val(void)1528 uint32_t slurm_get_hash_val(void)
1529 {
1530 	uint32_t hash_val;
1531 	slurm_ctl_conf_t *conf;
1532 
1533 	if (slurmdbd_conf) {
1534 		hash_val = NO_VAL;
1535 	} else {
1536 		conf = slurm_conf_lock();
1537 		hash_val = conf->hash_val;
1538 		slurm_conf_unlock();
1539 	}
1540 	return hash_val;
1541 }
1542 
1543 /* slurm_get_health_check_program
1544  * get health_check_program from slurmctld_conf object from
1545  * slurmctld_conf object
1546  * RET char *   - health_check_program, MUST be xfreed by caller
1547  */
slurm_get_health_check_program(void)1548 char *slurm_get_health_check_program(void)
1549 {
1550 	char *health_check_program = NULL;
1551 	slurm_ctl_conf_t *conf;
1552 
1553 	if (slurmdbd_conf) {
1554 	} else {
1555 		conf = slurm_conf_lock();
1556 		health_check_program = xstrdup(conf->health_check_program);
1557 		slurm_conf_unlock();
1558 	}
1559 	return health_check_program;
1560 }
1561 
1562 /* slurm_get_gres_plugins
1563  * get gres_plugins from slurmctld_conf object from
1564  * slurmctld_conf object
1565  * RET char *   - gres_plugins, MUST be xfreed by caller
1566  */
slurm_get_gres_plugins(void)1567 char *slurm_get_gres_plugins(void)
1568 {
1569 	char *gres_plugins = NULL;
1570 	slurm_ctl_conf_t *conf;
1571 
1572 	if (slurmdbd_conf) {
1573 	} else {
1574 		conf = slurm_conf_lock();
1575 		gres_plugins = xstrdup(conf->gres_plugins);
1576 		slurm_conf_unlock();
1577 	}
1578 	return gres_plugins;
1579 }
1580 
1581 /* slurm_get_job_submit_plugins
1582  * get job_submit_plugins from slurmctld_conf object from
1583  * slurmctld_conf object
1584  * RET char *   - job_submit_plugins, MUST be xfreed by caller
1585  */
slurm_get_job_submit_plugins(void)1586 char *slurm_get_job_submit_plugins(void)
1587 {
1588 	char *job_submit_plugins = NULL;
1589 	slurm_ctl_conf_t *conf;
1590 
1591 	if (slurmdbd_conf) {
1592 	} else {
1593 		conf = slurm_conf_lock();
1594 		job_submit_plugins = xstrdup(conf->job_submit_plugins);
1595 		slurm_conf_unlock();
1596 	}
1597 	return job_submit_plugins;
1598 }
1599 
1600 /* slurm_get_cli_filter_plugins
1601  * get cli_filter_plugins from slurmctld_conf object from
1602  * slurmctld_conf object
1603  * RET char *   - cli_filter_plugins, MUST be xfreed by caller
1604  */
slurm_get_cli_filter_plugins(void)1605 char *slurm_get_cli_filter_plugins(void)
1606 {
1607 	char *cli_filter_plugins = NULL;
1608 	slurm_ctl_conf_t *conf;
1609 
1610 	if (slurmdbd_conf) {
1611 	} else {
1612 		conf = slurm_conf_lock();
1613 		cli_filter_plugins = xstrdup(conf->cli_filter_plugins);
1614 		slurm_conf_unlock();
1615 	}
1616 	return cli_filter_plugins;
1617 }
1618 
1619 /* slurm_get_slurmctld_logfile
1620  * get slurmctld_logfile from slurmctld_conf object from slurmctld_conf object
1621  * RET char *   - slurmctld_logfile, MUST be xfreed by caller
1622  */
slurm_get_job_slurmctld_logfile(void)1623 char *slurm_get_job_slurmctld_logfile(void)
1624 {
1625 	char *slurmctld_logfile = NULL;
1626 	slurm_ctl_conf_t *conf;
1627 
1628 	if (slurmdbd_conf) {
1629 	} else {
1630 		conf = slurm_conf_lock();
1631 		slurmctld_logfile = xstrdup(conf->slurmctld_logfile);
1632 		slurm_conf_unlock();
1633 	}
1634 	return slurmctld_logfile;
1635 }
1636 
1637 /* slurm_get_node_features_plugins
1638  * get node_features_plugins from slurmctld_conf object
1639  * RET char *   - knl_plugins, MUST be xfreed by caller
1640  */
slurm_get_node_features_plugins(void)1641 char *slurm_get_node_features_plugins(void)
1642 {
1643 	char *knl_plugins = NULL;
1644 	slurm_ctl_conf_t *conf;
1645 
1646 	if (slurmdbd_conf) {
1647 	} else {
1648 		conf = slurm_conf_lock();
1649 		knl_plugins = xstrdup(conf->node_features_plugins);
1650 		slurm_conf_unlock();
1651 	}
1652 	return knl_plugins;
1653 }
1654 
1655 /* slurm_get_slurmctld_plugstack
1656  * get slurmctld_plugstack from slurmctld_conf object from
1657  * slurmctld_conf object
1658  * RET char *   - slurmctld_plugstack, MUST be xfreed by caller
1659  */
slurm_get_slurmctld_plugstack(void)1660 char *slurm_get_slurmctld_plugstack(void)
1661 {
1662 	char *slurmctld_plugstack = NULL;
1663 	slurm_ctl_conf_t *conf;
1664 
1665 	if (slurmdbd_conf) {
1666 	} else {
1667 		conf = slurm_conf_lock();
1668 		slurmctld_plugstack = xstrdup(conf->slurmctld_plugstack);
1669 		slurm_conf_unlock();
1670 	}
1671 	return slurmctld_plugstack;
1672 }
1673 
1674 /* slurm_get_slurmctld_timeout
1675  * get slurmctld_timeout from slurmctld_conf object from
1676  * slurmctld_conf object
1677  * RET uint16_t - slurmctld timeout in seconds
1678  */
slurm_get_slurmctld_timeout(void)1679 uint16_t slurm_get_slurmctld_timeout(void)
1680 {
1681 	uint16_t slurmctld_timeout = 0;
1682 	slurm_ctl_conf_t *conf;
1683 
1684 	if (slurmdbd_conf) {
1685 	} else {
1686 		conf = slurm_conf_lock();
1687 		slurmctld_timeout = conf->slurmctld_timeout;
1688 		slurm_conf_unlock();
1689 	}
1690 	return slurmctld_timeout;
1691 }
1692 
1693 /* slurm_get_accounting_storage_type
1694  * returns the accounting storage type from slurmctld_conf object
1695  * RET char *    - accounting storage type,  MUST be xfreed by caller
1696  */
slurm_get_accounting_storage_type(void)1697 char *slurm_get_accounting_storage_type(void)
1698 {
1699 	char *accounting_type;
1700 	slurm_ctl_conf_t *conf;
1701 
1702 	if (slurmdbd_conf) {
1703 		accounting_type = xstrdup(slurmdbd_conf->storage_type);
1704 	} else {
1705 		conf = slurm_conf_lock();
1706 		accounting_type = xstrdup(conf->accounting_storage_type);
1707 		slurm_conf_unlock();
1708 	}
1709 	return accounting_type;
1710 
1711 }
1712 
1713 /* slurm_get_accounting_storage_tres
1714  * returns the accounting storage tres from slurmctld_conf object
1715  * RET char *    - accounting storage tres,  MUST be xfreed by caller
1716  */
slurm_get_accounting_storage_tres(void)1717 char *slurm_get_accounting_storage_tres(void)
1718 {
1719 	char *accounting_tres;
1720 	slurm_ctl_conf_t *conf;
1721 
1722 	if (slurmdbd_conf) {
1723 		accounting_tres = NULL;
1724 	} else {
1725 		conf = slurm_conf_lock();
1726 		accounting_tres = xstrdup(conf->accounting_storage_tres);
1727 		slurm_conf_unlock();
1728 	}
1729 	return accounting_tres;
1730 
1731 }
1732 
1733 /* slurm_set_accounting_storage_tres
1734  * sets the value of accounting_storage_tres in slurmctld_conf object
1735  * RET 0 or error_code
1736  */
slurm_set_accounting_storage_tres(char * tres)1737 extern int slurm_set_accounting_storage_tres(char *tres)
1738 {
1739 	slurm_ctl_conf_t *conf;
1740 
1741 	if (slurmdbd_conf) {
1742 	} else {
1743 		conf = slurm_conf_lock();
1744 		xfree(conf->accounting_storage_tres);
1745 		conf->accounting_storage_tres = xstrdup(tres);
1746 		slurm_conf_unlock();
1747 	}
1748 	return 0;
1749 
1750 }
1751 
1752 /* slurm_get_accounting_storage_user
1753  * returns the storage user from slurmctld_conf object
1754  * RET char *    - storage user,  MUST be xfreed by caller
1755  */
slurm_get_accounting_storage_user(void)1756 char *slurm_get_accounting_storage_user(void)
1757 {
1758 	char *storage_user;
1759 	slurm_ctl_conf_t *conf;
1760 
1761 	if (slurmdbd_conf) {
1762 		storage_user = xstrdup(slurmdbd_conf->storage_user);
1763 	} else {
1764 		conf = slurm_conf_lock();
1765 		storage_user = xstrdup(conf->accounting_storage_user);
1766 		slurm_conf_unlock();
1767 	}
1768 	return storage_user;
1769 }
1770 
1771 /* slurm_set_accounting_storage_user
1772  * IN: char *user (name of file or database)
1773  * RET 0 or error code
1774  */
slurm_set_accounting_storage_user(char * user)1775 int slurm_set_accounting_storage_user(char *user)
1776 {
1777 	slurm_ctl_conf_t *conf;
1778 
1779 	if (slurmdbd_conf) {
1780 		xfree(slurmdbd_conf->storage_user);
1781 		slurmdbd_conf->storage_user = xstrdup(user);
1782 	} else {
1783 		conf = slurm_conf_lock();
1784 		xfree(conf->accounting_storage_user);
1785 		conf->accounting_storage_user = xstrdup(user);
1786 		slurm_conf_unlock();
1787 	}
1788 	return 0;
1789 }
1790 
1791 /* slurm_get_accounting_storage_backup_host
1792  * returns the storage backup host from slurmctld_conf object
1793  * RET char *    - storage backup host,  MUST be xfreed by caller
1794  */
slurm_get_accounting_storage_backup_host(void)1795 char *slurm_get_accounting_storage_backup_host(void)
1796 {
1797 	char *storage_host;
1798 	slurm_ctl_conf_t *conf;
1799 
1800 	if (slurmdbd_conf) {
1801 		storage_host = xstrdup(slurmdbd_conf->storage_backup_host);
1802 	} else {
1803 		conf = slurm_conf_lock();
1804 		storage_host = xstrdup(conf->accounting_storage_backup_host);
1805 		slurm_conf_unlock();
1806 	}
1807 	return storage_host;
1808 }
1809 
slurm_get_accounting_storage_ext_host(void)1810 char *slurm_get_accounting_storage_ext_host(void)
1811 {
1812 	char *ext_host = NULL;
1813 	slurm_ctl_conf_t *conf;
1814 
1815 	if (slurmdbd_conf) {
1816 	} else {
1817 		conf = slurm_conf_lock();
1818 		ext_host = xstrdup(conf->accounting_storage_ext_host);
1819 		slurm_conf_unlock();
1820 	}
1821 	return ext_host;
1822 }
1823 
1824 /* slurm_get_accounting_storage_host
1825  * returns the storage host from slurmctld_conf object
1826  * RET char *    - storage host,  MUST be xfreed by caller
1827  */
slurm_get_accounting_storage_host(void)1828 char *slurm_get_accounting_storage_host(void)
1829 {
1830 	char *storage_host;
1831 	slurm_ctl_conf_t *conf;
1832 
1833 	if (slurmdbd_conf) {
1834 		storage_host = xstrdup(slurmdbd_conf->storage_host);
1835 	} else {
1836 		conf = slurm_conf_lock();
1837 		storage_host = xstrdup(conf->accounting_storage_host);
1838 		slurm_conf_unlock();
1839 	}
1840 	return storage_host;
1841 }
1842 
1843 /* slurm_set_accounting_storage_host
1844  * IN: char *host (name of file or database)
1845  * RET 0 or error code
1846  */
slurm_set_accounting_storage_host(char * host)1847 int slurm_set_accounting_storage_host(char *host)
1848 {
1849 	slurm_ctl_conf_t *conf;
1850 
1851 	if (slurmdbd_conf) {
1852 		xfree(slurmdbd_conf->storage_host);
1853 		slurmdbd_conf->storage_host = xstrdup(host);
1854 	} else {
1855 		conf = slurm_conf_lock();
1856 		xfree(conf->accounting_storage_host);
1857 		conf->accounting_storage_host = xstrdup(host);
1858 		slurm_conf_unlock();
1859 	}
1860 	return 0;
1861 }
1862 
1863 /* slurm_get_accounting_storage_loc
1864  * returns the storage location from slurmctld_conf object
1865  * RET char *    - storage location,  MUST be xfreed by caller
1866  */
slurm_get_accounting_storage_loc(void)1867 char *slurm_get_accounting_storage_loc(void)
1868 {
1869 	char *storage_loc;
1870 	slurm_ctl_conf_t *conf;
1871 
1872 	if (slurmdbd_conf) {
1873 		storage_loc = xstrdup(slurmdbd_conf->storage_loc);
1874 	} else {
1875 		conf = slurm_conf_lock();
1876 		storage_loc = xstrdup(conf->accounting_storage_loc);
1877 		slurm_conf_unlock();
1878 	}
1879 	return storage_loc;
1880 }
1881 
1882 /* slurm_set_accounting_storage_loc
1883  * IN: char *loc (name of file or database)
1884  * RET 0 or error code
1885  */
slurm_set_accounting_storage_loc(char * loc)1886 int slurm_set_accounting_storage_loc(char *loc)
1887 {
1888 	slurm_ctl_conf_t *conf;
1889 
1890 	if (slurmdbd_conf) {
1891 		xfree(slurmdbd_conf->storage_loc);
1892 		slurmdbd_conf->storage_loc = xstrdup(loc);
1893 	} else {
1894 		conf = slurm_conf_lock();
1895 		xfree(conf->accounting_storage_loc);
1896 		conf->accounting_storage_loc = xstrdup(loc);
1897 		slurm_conf_unlock();
1898 	}
1899 	return 0;
1900 }
1901 
1902 /* slurm_get_accounting_storage_enforce
1903  * returns what level to enforce associations at
1904  */
slurm_get_accounting_storage_enforce(void)1905 uint16_t slurm_get_accounting_storage_enforce(void)
1906 {
1907 	uint16_t enforce = 0;
1908 	slurm_ctl_conf_t *conf;
1909 
1910 	if (slurmdbd_conf) {
1911 	} else {
1912 		conf = slurm_conf_lock();
1913 		enforce = conf->accounting_storage_enforce;
1914 		slurm_conf_unlock();
1915 	}
1916 	return enforce;
1917 
1918 }
1919 
1920 /* slurm_get_is_association_based_accounting
1921  * returns if we are doing accounting by associations
1922  */
slurm_get_is_association_based_accounting(void)1923 int slurm_get_is_association_based_accounting(void)
1924 {
1925 	int enforce = 0;
1926 	slurm_ctl_conf_t *conf;
1927 
1928 	if (slurmdbd_conf) {
1929 		return 1;
1930 	} else {
1931 		conf = slurm_conf_lock();
1932 		if (!xstrcasecmp(conf->accounting_storage_type,
1933 				 "accounting_storage/slurmdbd") ||
1934 		    !xstrcasecmp(conf->accounting_storage_type,
1935 				 "accounting_storage/mysql"))
1936 			enforce = 1;
1937 		slurm_conf_unlock();
1938 	}
1939 	return enforce;
1940 
1941 }
1942 
1943 /* slurm_get_accounting_storage_pass
1944  * returns the storage password from slurmctld_conf object
1945  * RET char *    - storage password,  MUST be xfreed by caller
1946  */
slurm_get_accounting_storage_pass(void)1947 char *slurm_get_accounting_storage_pass(void)
1948 {
1949 	char *storage_pass;
1950 	slurm_ctl_conf_t *conf;
1951 
1952 	if (slurmdbd_conf) {
1953 		storage_pass = xstrdup(slurmdbd_conf->storage_pass);
1954 	} else {
1955 		conf = slurm_conf_lock();
1956 		storage_pass = xstrdup(conf->accounting_storage_pass);
1957 		slurm_conf_unlock();
1958 	}
1959 	return storage_pass;
1960 }
1961 
1962 /* slurm_get_auth_info
1963  * returns the auth_info from slurmctld_conf object (AuthInfo parameter)
1964  * RET char * - AuthInfo value,  MUST be xfreed by caller
1965  */
slurm_get_auth_info(void)1966 extern char *slurm_get_auth_info(void)
1967 {
1968 	char *auth_info;
1969 	slurm_ctl_conf_t *conf;
1970 
1971 	if (slurmdbd_conf) {
1972 		auth_info = xstrdup(slurmdbd_conf->auth_info);
1973 	} else {
1974 		conf = slurm_conf_lock();
1975 		auth_info = xstrdup(conf->authinfo);
1976 		slurm_conf_unlock();
1977 	}
1978 
1979 	return auth_info;
1980 }
1981 
1982 /*
1983  * Convert AuthInfo to a socket path. Accepts two input formats:
1984  * 1) <path>		(Old format)
1985  * 2) socket=<path>[,]	(New format)
1986  * NOTE: Caller must xfree return value
1987  */
slurm_auth_opts_to_socket(char * opts)1988 extern char *slurm_auth_opts_to_socket(char *opts)
1989 {
1990 	char *socket = NULL, *sep, *tmp;
1991 
1992 	if (!opts)
1993 		return NULL;
1994 
1995 	tmp = strstr(opts, "socket=");
1996 	if (tmp) {
1997 		/* New format */
1998 		socket = xstrdup(tmp + 7);
1999 		sep = strchr(socket, ',');
2000 		if (sep)
2001 			sep[0] = '\0';
2002 	} else if (strchr(opts, '=')) {
2003 		/* New format, but socket not specified */
2004 		;
2005 	} else {
2006 		/* Old format */
2007 		socket = xstrdup(opts);
2008 	}
2009 
2010 	return socket;
2011 }
2012 
2013 /* slurm_get_sbcast_parameters
2014  * RET char * - SbcastParameters from slurm.conf,  MUST be xfreed by caller
2015  */
slurm_get_sbcast_parameters(void)2016 char *slurm_get_sbcast_parameters(void)
2017 {
2018 	char *sbcast_parameters = NULL;
2019 	slurm_ctl_conf_t *conf;
2020 
2021 	if (!slurmdbd_conf) {
2022 		conf = slurm_conf_lock();
2023 		sbcast_parameters = xstrdup(conf->sbcast_parameters);
2024 		slurm_conf_unlock();
2025 	}
2026 
2027 	return sbcast_parameters;
2028 }
2029 
2030 /* slurm_get_auth_ttl
2031  * returns the credential Time To Live option from the AuthInfo parameter
2032  * cache value in local buffer for best performance
2033  * RET int - Time To Live in seconds or 0 if not specified
2034  */
slurm_get_auth_ttl(void)2035 extern int slurm_get_auth_ttl(void)
2036 {
2037 	static int ttl = -1;
2038 	char *auth_info, *tmp;
2039 
2040 	if (ttl >= 0)
2041 		return ttl;
2042 
2043 	auth_info = slurm_get_auth_info();
2044 	if (!auth_info)
2045 		return 0;
2046 
2047 	tmp = strstr(auth_info, "ttl=");
2048 	if (tmp) {
2049 		ttl = atoi(tmp + 4);
2050 		if (ttl < 0)
2051 			ttl = 0;
2052 	} else {
2053 		ttl = 0;
2054 	}
2055 	xfree(auth_info);
2056 
2057 	return ttl;
2058 }
2059 
2060 /* _global_auth_key
2061  * returns the storage password from slurmctld_conf or slurmdbd_conf object
2062  * cache value in local buffer for best performance
2063  * RET char *    - storage password
2064  */
_global_auth_key(void)2065 static char *_global_auth_key(void)
2066 {
2067 	static bool loaded_storage_pass = false;
2068 	static char storage_pass[512] = "\0";
2069 	static char *storage_pass_ptr = NULL;
2070 
2071 	if (loaded_storage_pass)
2072 		return storage_pass_ptr;
2073 
2074 	if (slurmdbd_conf) {
2075 		if (slurmdbd_conf->auth_info) {
2076 			if (strlcpy(storage_pass, slurmdbd_conf->auth_info,
2077 				    sizeof(storage_pass))
2078 			    >= sizeof(storage_pass))
2079 				fatal("AuthInfo is too long");
2080 			storage_pass_ptr = storage_pass;
2081 		}
2082 	} else {
2083 		slurm_ctl_conf_t *conf = slurm_conf_lock();
2084 		if (conf->accounting_storage_pass) {
2085 			if (strlcpy(storage_pass, conf->accounting_storage_pass,
2086 				    sizeof(storage_pass))
2087 			    >= sizeof(storage_pass))
2088 				fatal("AccountingStoragePass is too long");
2089 			storage_pass_ptr = storage_pass;
2090 		}
2091 		slurm_conf_unlock();
2092 	}
2093 
2094 	loaded_storage_pass = true;
2095 	return storage_pass_ptr;
2096 }
2097 
2098 /* slurm_get_accounting_storage_port
2099  * returns the storage port from slurmctld_conf object
2100  * RET uint32_t   - storage port
2101  */
slurm_get_accounting_storage_port(void)2102 uint32_t slurm_get_accounting_storage_port(void)
2103 {
2104 	uint32_t storage_port;
2105 	slurm_ctl_conf_t *conf;
2106 
2107 	if (slurmdbd_conf) {
2108 		storage_port = slurmdbd_conf->storage_port;
2109 	} else {
2110 		conf = slurm_conf_lock();
2111 		storage_port = conf->accounting_storage_port;
2112 		slurm_conf_unlock();
2113 	}
2114 	return storage_port;
2115 
2116 }
2117 
2118 /* slurm_set_accounting_storage_port
2119  * sets the storage port in slurmctld_conf object
2120  * RET 0 or error code
2121  */
slurm_set_accounting_storage_port(uint32_t storage_port)2122 int slurm_set_accounting_storage_port(uint32_t storage_port)
2123 {
2124 	slurm_ctl_conf_t *conf;
2125 
2126 	if (slurmdbd_conf) {
2127 		slurmdbd_conf->storage_port = storage_port;
2128 	} else {
2129 		conf = slurm_conf_lock();
2130 		if (storage_port == 0) {
2131 			error("can't have storage port of 0");
2132 			return SLURM_ERROR;
2133 		}
2134 
2135 		conf->accounting_storage_port = storage_port;
2136 		slurm_conf_unlock();
2137 	}
2138 	return 0;
2139 }
2140 
2141 /*
2142  * slurm_get_dependency_params
2143  * RET dependency_params must be xfreed by caller
2144  */
slurm_get_dependency_params(void)2145 char *slurm_get_dependency_params(void)
2146 {
2147 	char *dependency_params = NULL;
2148 	slurm_ctl_conf_t *conf;
2149 
2150 	if (slurmdbd_conf) {
2151 	} else {
2152 		conf = slurm_conf_lock();
2153 		dependency_params = xstrdup(conf->dependency_params);
2154 		slurm_conf_unlock();
2155 	}
2156 	return dependency_params;
2157 }
2158 
2159 /* slurm_get_preempt_mode
2160  * returns the PreemptMode value from slurmctld_conf object
2161  * RET uint16_t   - PreemptMode value (See PREEMPT_MODE_* in slurm.h)
2162  */
slurm_get_preempt_mode(void)2163 uint16_t slurm_get_preempt_mode(void)
2164 {
2165 	uint16_t preempt_mode = 0;
2166 	slurm_ctl_conf_t *conf;
2167 
2168 	if (slurmdbd_conf) {
2169 	} else {
2170 		conf = slurm_conf_lock();
2171 		preempt_mode = conf->preempt_mode;
2172 		slurm_conf_unlock();
2173 	}
2174 	return preempt_mode;
2175 }
2176 
2177 /* slurm_get_jobacct_gather_type
2178  * returns the job accounting type from the slurmctld_conf object
2179  * RET char *    - job accounting type,  MUST be xfreed by caller
2180  */
slurm_get_jobacct_gather_type(void)2181 char *slurm_get_jobacct_gather_type(void)
2182 {
2183 	char *jobacct_type = NULL;
2184 	slurm_ctl_conf_t *conf;
2185 
2186 	if (slurmdbd_conf) {
2187 	} else {
2188 		conf = slurm_conf_lock();
2189 		jobacct_type = xstrdup(conf->job_acct_gather_type);
2190 		slurm_conf_unlock();
2191 	}
2192 	return jobacct_type;
2193 }
2194 
2195 /* slurm_get_jobacct_gather_params
2196  * returns the job accounting params from the slurmctld_conf object
2197  * RET char *    - job accounting params,  MUST be xfreed by caller
2198  */
slurm_get_jobacct_gather_params(void)2199 char *slurm_get_jobacct_gather_params(void)
2200 {
2201 	char *jobacct_params = NULL;
2202 	slurm_ctl_conf_t *conf;
2203 
2204 	if (slurmdbd_conf) {
2205 	} else {
2206 		conf = slurm_conf_lock();
2207 		jobacct_params = xstrdup(conf->job_acct_gather_params);
2208 		slurm_conf_unlock();
2209 	}
2210 	return jobacct_params;
2211 }
2212 
2213 /* slurm_get_job_acct_oom_kill
2214  * returns the job_acct_oom_kill setting from the slurmctld_conf object
2215  * which represents the value of the OverMemoryKill flag.
2216  * RET bool *    - job_acct_oom_kill parameter
2217  */
slurm_get_job_acct_oom_kill(void)2218 bool slurm_get_job_acct_oom_kill(void)
2219 {
2220         uint16_t enabled = 0;
2221 	slurm_ctl_conf_t *conf;
2222 
2223 	if (slurmdbd_conf) {
2224 	} else {
2225 		conf = slurm_conf_lock();
2226 		enabled = conf->job_acct_oom_kill;
2227 		slurm_conf_unlock();
2228 	}
2229 	return enabled;
2230 }
2231 
2232 /* slurm_get_jobacct_freq
2233  * returns the job accounting poll frequency from the slurmctld_conf object
2234  * RET int    - job accounting frequency
2235  */
slurm_get_jobacct_gather_freq(void)2236 char *slurm_get_jobacct_gather_freq(void)
2237 {
2238 	char *freq = NULL;
2239 	slurm_ctl_conf_t *conf;
2240 
2241 	if (slurmdbd_conf) {
2242 	} else {
2243 		conf = slurm_conf_lock();
2244 		freq = xstrdup(conf->job_acct_gather_freq);
2245 		slurm_conf_unlock();
2246 	}
2247 	return freq;
2248 }
2249 
2250 /* slurm_get_energy_accounting_type
2251  * get EnergyAccountingType from slurmctld_conf object
2252  * RET char *   - energy_accounting type, MUST be xfreed by caller
2253  */
slurm_get_acct_gather_energy_type(void)2254 char *slurm_get_acct_gather_energy_type(void)
2255 {
2256 	char *acct_gather_energy_type = NULL;
2257 	slurm_ctl_conf_t *conf;
2258 
2259 	if (slurmdbd_conf) {
2260 	} else {
2261 		conf = slurm_conf_lock();
2262 		acct_gather_energy_type =
2263 			xstrdup(conf->acct_gather_energy_type);
2264 		slurm_conf_unlock();
2265 	}
2266 	return acct_gather_energy_type;
2267 }
2268 
2269 /* slurm_get_profile_accounting_type
2270  * get ProfileAccountingType from slurmctld_conf object
2271  * RET char *   - profile_accounting type, MUST be xfreed by caller
2272  */
slurm_get_acct_gather_profile_type(void)2273 char *slurm_get_acct_gather_profile_type(void)
2274 {
2275 	char *acct_gather_profile_type = NULL;
2276 	slurm_ctl_conf_t *conf;
2277 
2278 	if (slurmdbd_conf) {
2279 	} else {
2280 		conf = slurm_conf_lock();
2281 		acct_gather_profile_type =
2282 			xstrdup(conf->acct_gather_profile_type);
2283 		slurm_conf_unlock();
2284 	}
2285 	return acct_gather_profile_type;
2286 }
2287 
2288 /* slurm_get_interconnect_accounting_type
2289  * get InterconnectAccountingType from slurmctld_conf object
2290  * RET char *   - interconnect_accounting type, MUST be xfreed by caller
2291  */
slurm_get_acct_gather_interconnect_type(void)2292 char *slurm_get_acct_gather_interconnect_type(void)
2293 {
2294 	char *acct_gather_interconnect_type = NULL;
2295 	slurm_ctl_conf_t *conf;
2296 
2297 	if (slurmdbd_conf) {
2298 	} else {
2299 		conf = slurm_conf_lock();
2300 		acct_gather_interconnect_type =
2301 			xstrdup(conf->acct_gather_interconnect_type);
2302 		slurm_conf_unlock();
2303 	}
2304 	return acct_gather_interconnect_type;
2305 }
2306 
2307 /* slurm_get_filesystem_accounting_type
2308  * get FilesystemAccountingType from slurmctld_conf object
2309  * RET char *   - filesystem_accounting type, MUST be xfreed by caller
2310  */
slurm_get_acct_gather_filesystem_type(void)2311 char *slurm_get_acct_gather_filesystem_type(void)
2312 {
2313 	char *acct_gather_filesystem_type = NULL;
2314 	slurm_ctl_conf_t *conf;
2315 
2316 	if (slurmdbd_conf) {
2317 	} else {
2318 		conf = slurm_conf_lock();
2319 		acct_gather_filesystem_type =
2320 			xstrdup(conf->acct_gather_filesystem_type);
2321 		slurm_conf_unlock();
2322 	}
2323 	return acct_gather_filesystem_type;
2324 }
2325 
2326 
slurm_get_acct_gather_node_freq(void)2327 extern uint16_t slurm_get_acct_gather_node_freq(void)
2328 {
2329 	uint16_t freq = 0;
2330 	slurm_ctl_conf_t *conf;
2331 
2332 	if (slurmdbd_conf) {
2333 	} else {
2334 		conf = slurm_conf_lock();
2335 		freq = conf->acct_gather_node_freq;
2336 		slurm_conf_unlock();
2337 	}
2338 	return freq;
2339 }
2340 
2341 /* slurm_get_ext_sensors_type
2342  * get ExtSensorsType from slurmctld_conf object
2343  * RET char *   - ext_sensors type, MUST be xfreed by caller
2344  */
slurm_get_ext_sensors_type(void)2345 char *slurm_get_ext_sensors_type(void)
2346 {
2347 	char *ext_sensors_type = NULL;
2348 	slurm_ctl_conf_t *conf;
2349 
2350 	if (slurmdbd_conf) {
2351 	} else {
2352 		conf = slurm_conf_lock();
2353 		ext_sensors_type =
2354 			xstrdup(conf->ext_sensors_type);
2355 		slurm_conf_unlock();
2356 	}
2357 	return ext_sensors_type;
2358 }
2359 
slurm_get_ext_sensors_freq(void)2360 extern uint16_t slurm_get_ext_sensors_freq(void)
2361 {
2362 	uint16_t freq = 0;
2363 	slurm_ctl_conf_t *conf;
2364 
2365 	if (slurmdbd_conf) {
2366 	} else {
2367 		conf = slurm_conf_lock();
2368 		freq = conf->ext_sensors_freq;
2369 		slurm_conf_unlock();
2370 	}
2371 	return freq;
2372 }
2373 
2374 /*
2375  * returns the configured GpuFreqDef value
2376  * RET char *    - GpuFreqDef value,  MUST be xfreed by caller
2377  */
slurm_get_gpu_freq_def(void)2378 char *slurm_get_gpu_freq_def(void)
2379 {
2380 	char *gpu_freq_def = NULL;
2381 	slurm_ctl_conf_t *conf;
2382 
2383 	if (slurmdbd_conf) {
2384 	} else {
2385 		conf = slurm_conf_lock();
2386 		gpu_freq_def = xstrdup(conf->gpu_freq_def);
2387 		slurm_conf_unlock();
2388 	}
2389 	return gpu_freq_def;
2390 }
2391 
2392 /*
2393  * slurm_get_jobcomp_type
2394  * returns the job completion logger type from slurmctld_conf object
2395  * RET char *    - job completion type,  MUST be xfreed by caller
2396  */
slurm_get_jobcomp_type(void)2397 char *slurm_get_jobcomp_type(void)
2398 {
2399 	char *jobcomp_type = NULL;
2400 	slurm_ctl_conf_t *conf;
2401 
2402 	if (slurmdbd_conf) {
2403 	} else {
2404 		conf = slurm_conf_lock();
2405 		jobcomp_type = xstrdup(conf->job_comp_type);
2406 		slurm_conf_unlock();
2407 	}
2408 	return jobcomp_type;
2409 }
2410 
2411 /* slurm_get_jobcomp_loc
2412  * returns the job completion loc from slurmctld_conf object
2413  * RET char *    - job completion location,  MUST be xfreed by caller
2414  */
slurm_get_jobcomp_loc(void)2415 char *slurm_get_jobcomp_loc(void)
2416 {
2417 	char *jobcomp_loc = 0;
2418 	slurm_ctl_conf_t *conf;
2419 
2420 	if (slurmdbd_conf) {
2421 	} else {
2422 		conf = slurm_conf_lock();
2423 		jobcomp_loc = xstrdup(conf->job_comp_loc);
2424 		slurm_conf_unlock();
2425 	}
2426 	return jobcomp_loc;
2427 }
2428 
2429 /* slurm_get_jobcomp_user
2430  * returns the storage user from slurmctld_conf object
2431  * RET char *    - storage user,  MUST be xfreed by caller
2432  */
slurm_get_jobcomp_user(void)2433 char *slurm_get_jobcomp_user(void)
2434 {
2435 	char *storage_user = NULL;
2436 	slurm_ctl_conf_t *conf;
2437 
2438 	if (slurmdbd_conf) {
2439 	} else {
2440 		conf = slurm_conf_lock();
2441 		storage_user = xstrdup(conf->job_comp_user);
2442 		slurm_conf_unlock();
2443 	}
2444 	return storage_user;
2445 }
2446 
2447 /* slurm_get_jobcomp_host
2448  * returns the storage host from slurmctld_conf object
2449  * RET char *    - storage host,  MUST be xfreed by caller
2450  */
slurm_get_jobcomp_host(void)2451 char *slurm_get_jobcomp_host(void)
2452 {
2453 	char *storage_host = NULL;
2454 	slurm_ctl_conf_t *conf;
2455 
2456 	if (slurmdbd_conf) {
2457 	} else {
2458 		conf = slurm_conf_lock();
2459 		storage_host = xstrdup(conf->job_comp_host);
2460 		slurm_conf_unlock();
2461 	}
2462 	return storage_host;
2463 }
2464 
slurm_get_jobcomp_params(void)2465 char *slurm_get_jobcomp_params(void)
2466 {
2467 	char *param = NULL;
2468 	slurm_ctl_conf_t *conf;
2469 
2470 	if (slurmdbd_conf) {
2471 	} else {
2472 		conf = slurm_conf_lock();
2473 		param = xstrdup(conf->job_comp_params);
2474 		slurm_conf_unlock();
2475 	}
2476 	return param;
2477 }
2478 
2479 /* slurm_get_jobcomp_pass
2480  * returns the storage password from slurmctld_conf object
2481  * RET char *    - storage password,  MUST be xfreed by caller
2482  */
slurm_get_jobcomp_pass(void)2483 char *slurm_get_jobcomp_pass(void)
2484 {
2485 	char *storage_pass = NULL;
2486 	slurm_ctl_conf_t *conf;
2487 
2488 	if (slurmdbd_conf) {
2489 	} else {
2490 		conf = slurm_conf_lock();
2491 		storage_pass = xstrdup(conf->job_comp_pass);
2492 		slurm_conf_unlock();
2493 	}
2494 	return storage_pass;
2495 }
2496 
2497 /* slurm_get_jobcomp_port
2498  * returns the storage port from slurmctld_conf object
2499  * RET uint32_t   - storage port
2500  */
slurm_get_jobcomp_port(void)2501 uint32_t slurm_get_jobcomp_port(void)
2502 {
2503 	uint32_t storage_port = 0;
2504 	slurm_ctl_conf_t *conf;
2505 
2506 	if (slurmdbd_conf) {
2507 	} else {
2508 		conf = slurm_conf_lock();
2509 		storage_port = conf->job_comp_port;
2510 		slurm_conf_unlock();
2511 	}
2512 	return storage_port;
2513 
2514 }
2515 
2516 /* slurm_set_jobcomp_port
2517  * sets the jobcomp port in slurmctld_conf object
2518  * RET 0 or error code
2519  */
slurm_set_jobcomp_port(uint32_t port)2520 int slurm_set_jobcomp_port(uint32_t port)
2521 {
2522 	slurm_ctl_conf_t *conf;
2523 
2524 	if (slurmdbd_conf) {
2525 	} else {
2526 		conf = slurm_conf_lock();
2527 		if (port == 0) {
2528 			error("can't have jobcomp port of 0");
2529 			return SLURM_ERROR;
2530 		}
2531 
2532 		conf->job_comp_port = port;
2533 		slurm_conf_unlock();
2534 	}
2535 	return 0;
2536 }
2537 
2538 /* slurm_get_keep_alive_time
2539  * returns keep_alive_time slurmctld_conf object
2540  * RET uint16_t	- keep_alive_time
2541  */
slurm_get_keep_alive_time(void)2542 uint16_t slurm_get_keep_alive_time(void)
2543 {
2544 	uint16_t keep_alive_time = NO_VAL16;
2545 	slurm_ctl_conf_t *conf;
2546 
2547 	if (slurmdbd_conf) {
2548 	} else {
2549 		conf = slurm_conf_lock();
2550 		keep_alive_time = conf->keep_alive_time;
2551 		slurm_conf_unlock();
2552 	}
2553 	return keep_alive_time;
2554 }
2555 
2556 
2557 /* slurm_get_kill_wait
2558  * returns kill_wait from slurmctld_conf object
2559  * RET uint16_t	- kill_wait
2560  */
slurm_get_kill_wait(void)2561 uint16_t slurm_get_kill_wait(void)
2562 {
2563 	uint16_t kill_wait = 0;
2564 	slurm_ctl_conf_t *conf;
2565 
2566 	if (slurmdbd_conf) {
2567 	} else {
2568 		conf = slurm_conf_lock();
2569 		kill_wait = conf->kill_wait;
2570 		slurm_conf_unlock();
2571 	}
2572 	return kill_wait;
2573 }
2574 
2575 /* slurm_get_launch_params
2576  * get launch_params from slurmctld_conf object
2577  * RET char *   - launch_params, MUST be xfreed by caller
2578  */
slurm_get_launch_params(void)2579 char *slurm_get_launch_params(void)
2580 {
2581 	char *launch_params = NULL;
2582 	slurm_ctl_conf_t *conf;
2583 
2584 	if (slurmdbd_conf) {
2585 	} else {
2586 		conf = slurm_conf_lock();
2587 		launch_params = xstrdup(conf->launch_params);
2588 		slurm_conf_unlock();
2589 	}
2590 	return launch_params;
2591 }
2592 
2593 /* slurm_get_launch_type
2594  * get launch_type from slurmctld_conf object
2595  * RET char *   - launch_type, MUST be xfreed by caller
2596  */
slurm_get_launch_type(void)2597 char *slurm_get_launch_type(void)
2598 {
2599 	char *launch_type = NULL;
2600 	slurm_ctl_conf_t *conf;
2601 
2602 	if (slurmdbd_conf) {
2603 	} else {
2604 		conf = slurm_conf_lock();
2605 		launch_type = xstrdup(conf->launch_type);
2606 		slurm_conf_unlock();
2607 	}
2608 	return launch_type;
2609 }
2610 
2611 /* slurm_set_launch_type
2612  * set launch_type in slurmctld_conf object
2613  * RET 0 or error code
2614  */
slurm_set_launch_type(char * launch_type)2615 int slurm_set_launch_type(char *launch_type)
2616 {
2617 	slurm_ctl_conf_t *conf;
2618 
2619 	if (slurmdbd_conf) {
2620 	} else {
2621 		conf = slurm_conf_lock();
2622 		xfree(conf->launch_type);
2623 		conf->launch_type = xstrdup(launch_type);
2624 		slurm_conf_unlock();
2625 	}
2626 	return 0;
2627 }
2628 
2629 /* slurm_get_mcs_plugin
2630  * RET mcs_plugin name, must be xfreed by caller */
slurm_get_mcs_plugin(void)2631 char *slurm_get_mcs_plugin(void)
2632 {
2633 	char *mcs_plugin = NULL;
2634 	slurm_ctl_conf_t *conf;
2635 
2636 	if (slurmdbd_conf) {
2637 	} else {
2638 		conf = slurm_conf_lock();
2639 		mcs_plugin = xstrdup(conf->mcs_plugin);
2640 		slurm_conf_unlock();
2641 	}
2642 	return mcs_plugin;
2643 }
2644 
2645 /* slurm_get_mcs_plugin_params
2646  * RET mcs_plugin_params name, must be xfreed by caller */
slurm_get_mcs_plugin_params(void)2647 char *slurm_get_mcs_plugin_params(void)
2648 {
2649 	char *mcs_plugin_params = NULL;
2650 	slurm_ctl_conf_t *conf;
2651 
2652 	if (slurmdbd_conf) {
2653 	} else {
2654 		conf = slurm_conf_lock();
2655 		mcs_plugin_params = xstrdup(conf->mcs_plugin_params);
2656 		slurm_conf_unlock();
2657 	}
2658 	return mcs_plugin_params;
2659 }
2660 
2661 /* slurm_get_preempt_type
2662  * get PreemptType from slurmctld_conf object
2663  * RET char *   - preempt type, MUST be xfreed by caller
2664  */
slurm_get_preempt_type(void)2665 char *slurm_get_preempt_type(void)
2666 {
2667 	char *preempt_type = NULL;
2668 	slurm_ctl_conf_t *conf;
2669 
2670 	if (slurmdbd_conf) {
2671 	} else {
2672 		conf = slurm_conf_lock();
2673 		preempt_type = xstrdup(conf->preempt_type);
2674 		slurm_conf_unlock();
2675 	}
2676 	return preempt_type;
2677 }
2678 
2679 /* slurm_get_proctrack_type
2680  * get ProctrackType from slurmctld_conf object
2681  * RET char *   - proctrack type, MUST be xfreed by caller
2682  */
slurm_get_proctrack_type(void)2683 char *slurm_get_proctrack_type(void)
2684 {
2685 	char *proctrack_type = NULL;
2686 	slurm_ctl_conf_t *conf;
2687 
2688 	if (slurmdbd_conf) {
2689 	} else {
2690 		conf = slurm_conf_lock();
2691 		proctrack_type = xstrdup(conf->proctrack_type);
2692 		slurm_conf_unlock();
2693 	}
2694 	return proctrack_type;
2695 }
2696 
2697 /* slurm_get_slurmd_port
2698  * returns slurmd port from slurmctld_conf object
2699  * RET uint16_t	- slurmd port
2700  */
slurm_get_slurmd_port(void)2701 uint16_t slurm_get_slurmd_port(void)
2702 {
2703 	uint16_t slurmd_port = 0;
2704 	slurm_ctl_conf_t *conf;
2705 
2706 	if (slurmdbd_conf) {
2707 	} else {
2708 		conf = slurm_conf_lock();
2709 		slurmd_port = conf->slurmd_port;
2710 		slurm_conf_unlock();
2711 	}
2712 	return slurmd_port;
2713 }
2714 
2715 /* slurm_get_slurm_user_id
2716  * returns slurm uid from slurmctld_conf object
2717  * RET uint32_t	- slurm user id
2718  */
slurm_get_slurm_user_id(void)2719 uint32_t slurm_get_slurm_user_id(void)
2720 {
2721 	uint32_t slurm_uid = 0;
2722 	slurm_ctl_conf_t *conf;
2723 
2724 	if (slurmdbd_conf) {
2725 		slurm_uid = slurmdbd_conf->slurm_user_id;
2726 	} else {
2727 		conf = slurm_conf_lock();
2728 		slurm_uid = conf->slurm_user_id;
2729 		slurm_conf_unlock();
2730 	}
2731 	return slurm_uid;
2732 }
2733 
2734 /* slurm_get_slurmd_user_id
2735  * returns slurmd uid from slurmctld_conf object
2736  * RET uint32_t	- slurmd user id
2737  */
slurm_get_slurmd_user_id(void)2738 uint32_t slurm_get_slurmd_user_id(void)
2739 {
2740 	uint32_t slurmd_uid = 0;
2741 	slurm_ctl_conf_t *conf;
2742 
2743 	if (slurmdbd_conf) {
2744 	} else {
2745 		conf = slurm_conf_lock();
2746 		slurmd_uid = conf->slurmd_user_id;
2747 		slurm_conf_unlock();
2748 	}
2749 	return slurmd_uid;
2750 }
2751 
2752 /*
2753  * slurm_get_slurmd_params
2754  * RET slurmd_params must be xfreed by caller
2755  */
slurm_get_slurmd_params(void)2756 char *slurm_get_slurmd_params(void)
2757 {
2758 	char *slurmd_params = NULL;
2759 	slurm_ctl_conf_t *conf;
2760 
2761 	if (slurmdbd_conf) {
2762 	} else {
2763 		conf = slurm_conf_lock();
2764 		slurmd_params = xstrdup(conf->slurmd_params);
2765 		slurm_conf_unlock();
2766 	}
2767 	return slurmd_params;
2768 }
2769 
2770 /*
2771  * slurm_get_slurmctld_params
2772  * RET slurmctld_params must be xfreed by caller
2773  */
slurm_get_slurmctld_params(void)2774 char *slurm_get_slurmctld_params(void)
2775 {
2776 	char *slurmctld_params = NULL;
2777 	slurm_ctl_conf_t *conf;
2778 
2779 	if (slurmdbd_conf) {
2780 	} else {
2781 		conf = slurm_conf_lock();
2782 		slurmctld_params = xstrdup(conf->slurmctld_params);
2783 		slurm_conf_unlock();
2784 	}
2785 	return slurmctld_params;
2786 }
2787 
2788 /* slurm_get_sched_params
2789  * RET char * - Value of SchedulerParameters, MUST be xfreed by caller */
slurm_get_sched_params(void)2790 extern char *slurm_get_sched_params(void)
2791 {
2792 	char *params = 0;
2793 	slurm_ctl_conf_t *conf;
2794 
2795  	if (slurmdbd_conf) {
2796 	} else {
2797 		conf = slurm_conf_lock();
2798 		params = xstrdup(conf->sched_params);
2799 		slurm_conf_unlock();
2800 	}
2801 	return params;
2802 }
2803 
2804 /* slurm_get_sched_type
2805  * get sched type from slurmctld_conf object
2806  * RET char *   - sched type, MUST be xfreed by caller
2807  */
slurm_get_sched_type(void)2808 char *slurm_get_sched_type(void)
2809 {
2810 	char *sched_type = NULL;
2811 	slurm_ctl_conf_t *conf;
2812 
2813 	if (slurmdbd_conf) {
2814 	} else {
2815 		conf = slurm_conf_lock();
2816 		sched_type = xstrdup(conf->schedtype);
2817 		slurm_conf_unlock();
2818 	}
2819 	return sched_type;
2820 }
2821 
2822 /* slurm_get_select_type
2823  * get select_type from slurmctld_conf object
2824  * RET char *   - select_type, MUST be xfreed by caller
2825  */
slurm_get_select_type(void)2826 char *slurm_get_select_type(void)
2827 {
2828 	char *select_type = NULL;
2829 	slurm_ctl_conf_t *conf;
2830 
2831 	if (slurmdbd_conf) {
2832 	} else {
2833 		conf = slurm_conf_lock();
2834 		select_type = xstrdup(conf->select_type);
2835 		slurm_conf_unlock();
2836 	}
2837 	return select_type;
2838 }
2839 
2840 /* slurm_get_select_type_param
2841  * get select_type_param from slurmctld_conf object
2842  * RET uint16_t   - select_type_param
2843  */
slurm_get_select_type_param(void)2844 uint16_t slurm_get_select_type_param(void)
2845 {
2846 	uint16_t select_type_param = 0;
2847 	slurm_ctl_conf_t *conf;
2848 
2849 	if (slurmdbd_conf) {
2850 	} else {
2851 		conf = slurm_conf_lock();
2852 		select_type_param = conf->select_type_param;
2853 		slurm_conf_unlock();
2854 	}
2855 	return select_type_param;
2856 }
2857 
2858 /* slurm_set_select_type_param
2859  * set select_type_param for slurmctld_conf object
2860  * IN uint16_t   - select_type_param
2861  */
slurm_set_select_type_param(uint16_t select_type_param)2862 void slurm_set_select_type_param(uint16_t select_type_param)
2863 {
2864 	slurm_ctl_conf_t *conf;
2865 
2866 	if (slurmdbd_conf) {
2867 	} else {
2868 		conf = slurm_conf_lock();
2869 		conf->select_type_param = select_type_param;
2870 		slurm_conf_unlock();
2871 	}
2872 }
2873 
2874 /** Return true if (remote) system runs Cray Aries */
is_cray_select_type(void)2875 bool is_cray_select_type(void)
2876 {
2877 	bool result = false;
2878 
2879 	if (slurmdbd_conf) {
2880 	} else {
2881 		slurm_ctl_conf_t *conf = slurm_conf_lock();
2882 		result = !xstrcasecmp(conf->select_type, "select/cray_aries");
2883 		slurm_conf_unlock();
2884 	}
2885 	return result;
2886 }
2887 
2888 /* slurm_get_switch_type
2889  * get switch type from slurmctld_conf object
2890  * RET char *   - switch type, MUST be xfreed by caller
2891  */
slurm_get_switch_type(void)2892 char *slurm_get_switch_type(void)
2893 {
2894 	char *switch_type = NULL;
2895 	slurm_ctl_conf_t *conf;
2896 
2897 	conf = slurm_conf_lock();
2898 	switch_type = xstrdup(conf->switch_type);
2899 	slurm_conf_unlock();
2900 	return switch_type;
2901 }
2902 
2903 /* slurm_get_wait_time
2904  * returns wait_time from slurmctld_conf object
2905  * RET uint16_t	- wait_time
2906  */
slurm_get_wait_time(void)2907 uint16_t slurm_get_wait_time(void)
2908 {
2909 	uint16_t wait_time = 0;
2910 	slurm_ctl_conf_t *conf;
2911 
2912 	if (slurmdbd_conf) {
2913 	} else {
2914 		conf = slurm_conf_lock();
2915 		wait_time = conf->wait_time;
2916 		slurm_conf_unlock();
2917 	}
2918 	return wait_time;
2919 }
2920 
2921 /* slurm_get_srun_prolog
2922  * return the name of the srun prolog program
2923  * RET char *   - name of prolog program, must be xfreed by caller
2924  */
slurm_get_srun_prolog(void)2925 char *slurm_get_srun_prolog(void)
2926 {
2927 	char *prolog = NULL;
2928 	slurm_ctl_conf_t *conf;
2929 
2930 	if (slurmdbd_conf) {
2931 	} else {
2932 		conf = slurm_conf_lock();
2933 		prolog = xstrdup(conf->srun_prolog);
2934 		slurm_conf_unlock();
2935 	}
2936 	return prolog;
2937 }
2938 
2939 /* slurm_get_srun_epilog
2940  * return the name of the srun epilog program
2941  * RET char *   - name of epilog program, must be xfreed by caller
2942  */
slurm_get_srun_epilog(void)2943 char *slurm_get_srun_epilog(void)
2944 {
2945 	char *epilog = NULL;
2946 	slurm_ctl_conf_t *conf;
2947 
2948 	if (slurmdbd_conf) {
2949 	} else {
2950 		conf = slurm_conf_lock();
2951 		epilog = xstrdup(conf->srun_epilog);
2952 		slurm_conf_unlock();
2953 	}
2954 	return epilog;
2955 }
2956 
2957 /* slurm_get_task_epilog
2958  * RET task_epilog name, must be xfreed by caller */
slurm_get_task_epilog(void)2959 char *slurm_get_task_epilog(void)
2960 {
2961 	char *task_epilog = NULL;
2962 	slurm_ctl_conf_t *conf;
2963 
2964 	if (slurmdbd_conf) {
2965 	} else {
2966 		conf = slurm_conf_lock();
2967 		task_epilog = xstrdup(conf->task_epilog);
2968 		slurm_conf_unlock();
2969 	}
2970 	return task_epilog;
2971 }
2972 
2973 /* slurm_get_task_prolog
2974  * RET task_prolog name, must be xfreed by caller */
slurm_get_task_prolog(void)2975 char *slurm_get_task_prolog(void)
2976 {
2977 	char *task_prolog = NULL;
2978 	slurm_ctl_conf_t *conf;
2979 
2980 	if (slurmdbd_conf) {
2981 	} else {
2982 		conf = slurm_conf_lock();
2983 		task_prolog = xstrdup(conf->task_prolog);
2984 		slurm_conf_unlock();
2985 	}
2986 	return task_prolog;
2987 }
2988 
2989 /*  slurm_get_srun_port_range()
2990  */
2991 uint16_t *
slurm_get_srun_port_range(void)2992 slurm_get_srun_port_range(void)
2993 {
2994 	uint16_t *ports = NULL;
2995 	slurm_ctl_conf_t *conf;
2996 
2997 	if (slurmdbd_conf) {
2998 	} else {
2999 		conf = slurm_conf_lock();
3000 		ports = conf->srun_port_range;
3001 		slurm_conf_unlock();
3002 	}
3003 	return ports;	/* CLANG false positive */
3004 }
3005 
3006 /* slurm_get_task_plugin
3007  * RET task_plugin name, must be xfreed by caller */
slurm_get_task_plugin(void)3008 char *slurm_get_task_plugin(void)
3009 {
3010 	char *task_plugin = NULL;
3011 	slurm_ctl_conf_t *conf;
3012 
3013 	conf = slurm_conf_lock();
3014 	task_plugin = xstrdup(conf->task_plugin);
3015 	slurm_conf_unlock();
3016 	return task_plugin;
3017 }
3018 
3019 /* slurm_get_task_plugin_param */
slurm_get_task_plugin_param(void)3020 uint32_t slurm_get_task_plugin_param(void)
3021 {
3022 	uint32_t task_plugin_param = 0;
3023 	slurm_ctl_conf_t *conf;
3024 
3025 	if (slurmdbd_conf) {
3026 	} else {
3027 		conf = slurm_conf_lock();
3028 		task_plugin_param = conf->task_plugin_param;
3029 		slurm_conf_unlock();
3030 	}
3031 	return task_plugin_param;
3032 }
3033 
3034 /* Get SchedulerTimeSlice (secs) */
slurm_get_time_slice(void)3035 uint16_t slurm_get_time_slice(void)
3036 {
3037 	uint16_t sched_time_slice = 0;
3038 	slurm_ctl_conf_t *conf;
3039 
3040 	if (slurmdbd_conf) {
3041 	} else {
3042 		conf = slurm_conf_lock();
3043 		sched_time_slice = conf->sched_time_slice;
3044 		slurm_conf_unlock();
3045 	}
3046 	return sched_time_slice;
3047 }
3048 
3049 /* slurm_get_core_spec_plugin
3050  * RET core_spec plugin name, must be xfreed by caller */
slurm_get_core_spec_plugin(void)3051 char *slurm_get_core_spec_plugin(void)
3052 {
3053 	char *core_spec_plugin = NULL;
3054 	slurm_ctl_conf_t *conf;
3055 
3056 	conf = slurm_conf_lock();
3057 	core_spec_plugin = xstrdup(conf->core_spec_plugin);
3058 	slurm_conf_unlock();
3059 	return core_spec_plugin;
3060 }
3061 
3062 /* slurm_get_job_container_plugin
3063  * RET job_container plugin name, must be xfreed by caller */
slurm_get_job_container_plugin(void)3064 char *slurm_get_job_container_plugin(void)
3065 {
3066 	char *job_container_plugin = NULL;
3067 	slurm_ctl_conf_t *conf;
3068 
3069 	conf = slurm_conf_lock();
3070 	job_container_plugin = xstrdup(conf->job_container_plugin);
3071 	slurm_conf_unlock();
3072 	return job_container_plugin;
3073 }
3074 
3075 /* slurm_get_slurmd_spooldir
3076  * RET slurmd_spooldir name, must be xfreed by caller */
slurm_get_slurmd_spooldir(char * node_name)3077 char *slurm_get_slurmd_spooldir(char *node_name)
3078 {
3079 	char *slurmd_spooldir = NULL;
3080 	slurm_ctl_conf_t *conf;
3081 
3082 	if (slurmdbd_conf) {
3083 	} else {
3084 		conf = slurm_conf_lock();
3085 		if (!node_name)
3086 			slurmd_spooldir = xstrdup(conf->slurmd_spooldir);
3087 		else
3088 			slurmd_spooldir = slurm_conf_expand_slurmd_path(
3089 				conf->slurmd_spooldir, node_name);
3090 		slurm_conf_unlock();
3091 	}
3092 	return slurmd_spooldir;
3093 }
3094 
3095 /* slurm_get_layouts
3096  * RET comma seperated list of layouts in a string, must be xfreed by caller */
slurm_get_layouts(void)3097 char *slurm_get_layouts(void)
3098 {
3099 	char* layouts = NULL;
3100 	slurm_ctl_conf_t *conf;
3101 
3102 	if (slurmdbd_conf) {
3103 		layouts = xstrdup("");
3104 	} else {
3105 		conf = slurm_conf_lock();
3106 		layouts = xstrdup(conf->layouts);
3107 		slurm_conf_unlock();
3108 	}
3109 	return layouts;
3110 }
3111 
3112 /*  slurm_get_srun_eio_timeout()
3113  */
3114 int16_t
slurm_get_srun_eio_timeout(void)3115 slurm_get_srun_eio_timeout(void)
3116 {
3117 	int16_t eio_timeout = 0;
3118 	slurm_ctl_conf_t *conf;
3119 
3120 	if (slurmdbd_conf) {
3121 	} else {
3122 		conf = slurm_conf_lock();
3123 		eio_timeout = conf->eio_timeout;
3124 		slurm_conf_unlock();
3125 	}
3126 	return eio_timeout;
3127 }
3128 
3129 /* Change general slurm communication errors to slurmctld specific errors */
_remap_slurmctld_errno(void)3130 static void _remap_slurmctld_errno(void)
3131 {
3132 	int err = slurm_get_errno();
3133 
3134 	if (err == SLURM_COMMUNICATIONS_CONNECTION_ERROR)
3135 		slurm_seterrno(SLURMCTLD_COMMUNICATIONS_CONNECTION_ERROR);
3136 	else if (err ==  SLURM_COMMUNICATIONS_SEND_ERROR)
3137 		slurm_seterrno(SLURMCTLD_COMMUNICATIONS_SEND_ERROR);
3138 	else if (err == SLURM_COMMUNICATIONS_RECEIVE_ERROR)
3139 		slurm_seterrno(SLURMCTLD_COMMUNICATIONS_RECEIVE_ERROR);
3140 	else if (err == SLURM_COMMUNICATIONS_SHUTDOWN_ERROR)
3141 		slurm_seterrno(SLURMCTLD_COMMUNICATIONS_SHUTDOWN_ERROR);
3142 }
3143 
3144 /**********************************************************************\
3145  * general message management functions used by slurmctld, slurmd
3146 \**********************************************************************/
3147 
3148 /* In the socket implementation it creates a socket, binds to it, and
3149  *	listens for connections. Retry if bind() or listen() fail
3150  *      even if asked for an ephemeral port.
3151  *
3152  * IN  port     - port to bind the msg server to
3153  * RET int      - file descriptor of the connection created
3154  */
slurm_init_msg_engine_port(uint16_t port)3155 int slurm_init_msg_engine_port(uint16_t port)
3156 {
3157 	int cc;
3158 	slurm_addr_t addr;
3159 	int i;
3160 
3161 	slurm_setup_sockaddr(&addr, port);
3162 	cc = slurm_init_msg_engine(&addr);
3163 	if ((cc < 0) && (port == 0) && (errno == EADDRINUSE)) {
3164 		/* All ephemeral ports are in use, test other ports */
3165 		for (i = 10001; i < 65536; i++) {
3166 			slurm_setup_sockaddr(&addr, i);
3167 			cc = slurm_init_msg_engine(&addr);
3168 			if (cc >= 0)
3169 				break;
3170 		}
3171 	}
3172 	return cc;
3173 }
3174 
3175 /* slurm_init_msg_engine_ports()
3176  */
slurm_init_msg_engine_ports(uint16_t * ports)3177 int slurm_init_msg_engine_ports(uint16_t *ports)
3178 {
3179 	int cc;
3180 	int val;
3181 	int s;
3182 	int port;
3183 
3184 	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
3185 	if (s < 0)
3186 		return -1;
3187 
3188 	val = 1;
3189 	cc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int));
3190 	if (cc < 0) {
3191 		close(s);
3192 		return -1;
3193 	}
3194 
3195 	port = sock_bind_range(s, ports, false);
3196 	if (port < 0) {
3197 		close(s);
3198 		return -1;
3199 	}
3200 
3201 	cc = listen(s, SLURM_DEFAULT_LISTEN_BACKLOG);
3202 	if (cc < 0) {
3203 		close(s);
3204 		return -1;
3205 	}
3206 
3207 	return s;
3208 }
3209 
3210 /**********************************************************************\
3211  * msg connection establishment functions used by msg clients
3212 \**********************************************************************/
3213 
3214 /* In the bsd socket implementation it creates a SOCK_STREAM socket
3215  *	and calls connect on it a SOCK_DGRAM socket called with connect
3216  *	is defined to only receive messages from the address/port pair
3217  *	argument of the connect call slurm_address - for now it is
3218  *	really just a sockaddr_in
3219  * IN slurm_address	- slurm_addr_t of the connection destination
3220  * RET slurm_fd		- file descriptor of the connection created
3221  */
slurm_open_msg_conn(slurm_addr_t * slurm_address)3222 int slurm_open_msg_conn(slurm_addr_t * slurm_address)
3223 {
3224 	int fd = slurm_open_stream(slurm_address, false);
3225 	if (fd >= 0)
3226 		fd_set_close_on_exec(fd);
3227 	return fd;
3228 }
3229 
3230 /*
3231  * Calls connect to make a connection-less datagram connection
3232  *	primary or secondary slurmctld message engine
3233  * IN/OUT addr       - address of controller contacted
3234  * IN/OUT use_backup - IN: whether to try the backup first or not
3235  *                     OUT: set to true if connection established with backup
3236  * IN comm_cluster_rec	- Communication record (host/port/version)/
3237  * RET slurm_fd	- file descriptor of the connection created
3238  */
slurm_open_controller_conn(slurm_addr_t * addr,bool * use_backup,slurmdb_cluster_rec_t * comm_cluster_rec)3239 extern int slurm_open_controller_conn(slurm_addr_t *addr, bool *use_backup,
3240 				      slurmdb_cluster_rec_t *comm_cluster_rec)
3241 {
3242 	int fd = -1;
3243 	slurm_protocol_config_t *proto_conf = NULL;
3244 	int i, retry, max_retry_period;
3245 
3246 	if (!comm_cluster_rec) {
3247 		/* This means the addr wasn't set up already */
3248 		if (!(proto_conf = _slurm_api_get_comm_config()))
3249 			return SLURM_ERROR;
3250 
3251 		for (i = 0; i < proto_conf->control_cnt; i++) {
3252 			proto_conf->controller_addr[i].sin_port =
3253 					htons(slurmctld_conf.slurmctld_port +
3254 					(((time(NULL) + getpid()) %
3255 					slurmctld_conf.slurmctld_port_count)));
3256 		}
3257 
3258 		if (proto_conf->vip_addr_set) {
3259 			proto_conf->vip_addr.sin_port =
3260 					htons(slurmctld_conf.slurmctld_port +
3261 					(((time(NULL) + getpid()) %
3262 					slurmctld_conf.slurmctld_port_count)));
3263 		}
3264 	}
3265 
3266 #ifdef HAVE_NATIVE_CRAY
3267 	max_retry_period = 180;
3268 #else
3269 	max_retry_period = slurm_get_msg_timeout();
3270 #endif
3271 	for (retry = 0; retry < max_retry_period; retry++) {
3272 		if (retry)
3273 			sleep(1);
3274 		if (comm_cluster_rec) {
3275 			if (comm_cluster_rec->control_addr.sin_port == 0) {
3276 				slurm_set_addr(
3277 					&comm_cluster_rec->control_addr,
3278 					comm_cluster_rec->control_port,
3279 					comm_cluster_rec->control_host);
3280 			}
3281 			addr = &comm_cluster_rec->control_addr;
3282 
3283 			fd = slurm_open_msg_conn(addr);
3284 			if (fd >= 0)
3285 				goto end_it;
3286 			debug("Failed to contact controller: %m");
3287 		} else if (proto_conf->vip_addr_set) {
3288 			fd = slurm_open_msg_conn(&proto_conf->vip_addr);
3289 			if (fd >= 0)
3290 				goto end_it;
3291 			debug("Failed to contact controller: %m");
3292 		} else {
3293 			if (!*use_backup) {
3294 				fd = slurm_open_msg_conn(
3295 						&proto_conf->controller_addr[0]);
3296 				if (fd >= 0) {
3297 					*use_backup = false;
3298 					goto end_it;
3299 				}
3300 				debug("Failed to contact primary controller: %m");
3301 			}
3302 			if ((proto_conf->control_cnt > 1) || *use_backup) {
3303 				for (i = 1; i < proto_conf->control_cnt; i++) {
3304 					fd = slurm_open_msg_conn(
3305 						&proto_conf->controller_addr[i]);
3306 					if (fd >= 0) {
3307 						debug("Contacted backup controller %d",
3308 						      (i - 1));
3309 						*use_backup = true;
3310 						goto end_it;
3311 					}
3312 				}
3313 				*use_backup = false;
3314 				debug("Failed to contact backup controller: %m");
3315 			}
3316 		}
3317 	}
3318 	addr = NULL;
3319 	_slurm_api_free_comm_config(proto_conf);
3320 	slurm_seterrno_ret(SLURMCTLD_COMMUNICATIONS_CONNECTION_ERROR);
3321 
3322 end_it:
3323 	_slurm_api_free_comm_config(proto_conf);
3324 	return fd;
3325 }
3326 
3327 /*
3328  * Calls connect to make a connection-less datagram connection to a specific
3329  *	primary or backup slurmctld message engine
3330  * IN dest      - controller to contact (0=primary, 1=backup, 2=backup2, etc.)
3331  * IN comm_cluster_rec	- Communication record (host/port/version)/
3332  * RET int      - file descriptor of the connection created
3333  */
slurm_open_controller_conn_spec(int dest,slurmdb_cluster_rec_t * comm_cluster_rec)3334 extern int slurm_open_controller_conn_spec(int dest,
3335 				      slurmdb_cluster_rec_t *comm_cluster_rec)
3336 {
3337 	slurm_protocol_config_t *proto_conf = NULL;
3338 	slurm_addr_t *addr;
3339 	int rc;
3340 
3341 	if (comm_cluster_rec) {
3342 		if (comm_cluster_rec->control_addr.sin_port == 0) {
3343 			slurm_set_addr(
3344 				&comm_cluster_rec->control_addr,
3345 				comm_cluster_rec->control_port,
3346 				comm_cluster_rec->control_host);
3347 		}
3348 		addr = &comm_cluster_rec->control_addr;
3349 	} else {	/* Some backup slurmctld */
3350 		if (!(proto_conf = _slurm_api_get_comm_config())) {
3351 			debug3("Error: Unable to set default config");
3352 			return SLURM_ERROR;
3353 		}
3354 		addr = NULL;
3355 		if ((dest >= 0) && (dest <= proto_conf->control_cnt))
3356 			addr = &proto_conf->controller_addr[dest];
3357 		if (!addr) {
3358 			rc = SLURM_ERROR;
3359 			goto fini;
3360 		}
3361 	}
3362 
3363 	rc = slurm_open_msg_conn(addr);
3364 	if (rc == -1)
3365 		_remap_slurmctld_errno();
3366 fini:	_slurm_api_free_comm_config(proto_conf);
3367 	return rc;
3368 }
3369 
slurm_unpack_received_msg(slurm_msg_t * msg,int fd,Buf buffer)3370 extern int slurm_unpack_received_msg(slurm_msg_t *msg, int fd, Buf buffer)
3371 {
3372 	header_t header;
3373 	int rc;
3374 	void *auth_cred = NULL;
3375 
3376 	if (unpack_header(&header, buffer) == SLURM_ERROR) {
3377 		rc = SLURM_COMMUNICATIONS_RECEIVE_ERROR;
3378 		goto total_return;
3379 	}
3380 
3381 	if (check_header_version(&header) < 0) {
3382 		slurm_addr_t resp_addr;
3383 		char addr_str[32];
3384 		int uid = _unpack_msg_uid(buffer, header.version);
3385 
3386 		if (!slurm_get_peer_addr(fd, &resp_addr)) {
3387 			slurm_print_slurm_addr(
3388 				&resp_addr, addr_str, sizeof(addr_str));
3389 			error("%s: Invalid Protocol Version %u from uid=%d at %s",
3390 			      __func__, header.version, uid, addr_str);
3391 		} else {
3392 			error("%s: Invalid Protocol Version %u from uid=%d from "
3393 			      "problem connection: %m", __func__,
3394 			      header.version, uid);
3395 		}
3396 
3397 		rc = SLURM_PROTOCOL_VERSION_ERROR;
3398 		goto total_return;
3399 	}
3400 	//info("ret_cnt = %d",header.ret_cnt);
3401 	if (header.ret_cnt > 0) {
3402 		error("%s: we received more than one message back use "
3403 		      "slurm_receive_msgs instead", __func__);
3404 		header.ret_cnt = 0;
3405 		FREE_NULL_LIST(header.ret_list);
3406 		header.ret_list = NULL;
3407 	}
3408 
3409 	/* Forward message to other nodes */
3410 	if (header.forward.cnt > 0) {
3411 		error("%s: We need to forward this to other nodes use "
3412 		      "slurm_receive_msg_and_forward instead", __func__);
3413 	}
3414 
3415 	if ((auth_cred = g_slurm_auth_unpack(buffer, header.version)) == NULL) {
3416 		error("%s: authentication: %m", __func__);
3417 		rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3418 		goto total_return;
3419 	}
3420 	msg->auth_index = slurm_auth_index(auth_cred);
3421 	if (header.flags & SLURM_GLOBAL_AUTH_KEY) {
3422 		rc = g_slurm_auth_verify(auth_cred, _global_auth_key());
3423 	} else {
3424 		char *auth_info = slurm_get_auth_info();
3425 		rc = g_slurm_auth_verify(auth_cred, auth_info);
3426 		xfree(auth_info);
3427 	}
3428 
3429 	if (rc != SLURM_SUCCESS) {
3430 		error("%s: %s has authentication error: %s",
3431 		      __func__, rpc_num2string(header.msg_type),
3432 		      slurm_strerror(rc));
3433 		(void) g_slurm_auth_destroy(auth_cred);
3434 		rc = SLURM_PROTOCOL_AUTHENTICATION_ERROR;
3435 		goto total_return;
3436 	}
3437 
3438 	/*
3439 	 * Unpack message body
3440 	 */
3441 	msg->protocol_version = header.version;
3442 	msg->msg_type = header.msg_type;
3443 	msg->flags = header.flags;
3444 
3445 	msg->body_offset =  get_buf_offset(buffer);
3446 
3447 	if ((header.body_length > remaining_buf(buffer)) ||
3448 	    (unpack_msg(msg, buffer) != SLURM_SUCCESS)) {
3449 		rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3450 		(void) g_slurm_auth_destroy(auth_cred);
3451 		goto total_return;
3452 	}
3453 
3454 	msg->auth_cred = (void *)auth_cred;
3455 
3456 	rc = SLURM_SUCCESS;
3457 
3458 total_return:
3459 	destroy_forward(&header.forward);
3460 
3461 	slurm_seterrno(rc);
3462 	if (rc != SLURM_SUCCESS) {
3463 		msg->auth_cred = (void *) NULL;
3464 		error("%s: %s", __func__, slurm_strerror(rc));
3465 		rc = -1;
3466 		usleep(10000);	/* Discourage brute force attack */
3467 	} else {
3468 		rc = 0;
3469 	}
3470 	return rc;
3471 }
3472 
3473 /**********************************************************************\
3474  * receive message functions
3475 \**********************************************************************/
3476 
3477 /*
3478  * NOTE: memory is allocated for the returned msg must be freed at
3479  *       some point using the slurm_free_functions.
3480  * IN fd	- file descriptor to receive msg on
3481  * OUT msg	- a slurm_msg struct to be filled in by the function
3482  * IN timeout	- how long to wait in milliseconds
3483  * RET int	- returns 0 on success, -1 on failure and sets errno
3484  */
slurm_receive_msg(int fd,slurm_msg_t * msg,int timeout)3485 int slurm_receive_msg(int fd, slurm_msg_t *msg, int timeout)
3486 {
3487 	char *buf = NULL;
3488 	size_t buflen = 0;
3489 	int rc;
3490 	Buf buffer;
3491 	bool keep_buffer = false;
3492 
3493 	if (msg->flags & SLURM_MSG_KEEP_BUFFER)
3494 		keep_buffer = true;
3495 
3496 	if (msg->conn) {
3497 		persist_msg_t persist_msg;
3498 
3499 		buffer = slurm_persist_recv_msg(msg->conn);
3500 		if (!buffer) {
3501 			error("%s: No response to persist_init", __func__);
3502 			slurm_persist_conn_close(msg->conn);
3503 			return SLURM_ERROR;
3504 		}
3505 		memset(&persist_msg, 0, sizeof(persist_msg_t));
3506 		rc = slurm_persist_msg_unpack(msg->conn, &persist_msg, buffer);
3507 
3508 		if (keep_buffer)
3509 			msg->buffer = buffer;
3510 		else
3511 			free_buf(buffer);
3512 
3513 		if (rc) {
3514 			error("%s: Failed to unpack persist msg", __func__);
3515 			slurm_persist_conn_close(msg->conn);
3516 			return SLURM_ERROR;
3517 		}
3518 
3519 		msg->msg_type = persist_msg.msg_type;
3520 		msg->data = persist_msg.data;
3521 
3522 		return SLURM_SUCCESS;
3523 	}
3524 
3525 	xassert(fd >= 0);
3526 
3527 	msg->conn_fd = fd;
3528 
3529 	if (timeout <= 0)
3530 		/* convert secs to msec */
3531 		timeout  = slurm_get_msg_timeout() * MSEC_IN_SEC;
3532 
3533 	else if (timeout > (slurm_get_msg_timeout() * MSEC_IN_SEC * 10)) {
3534 		/* consider 10x the timeout to be very long */
3535 		debug("%s: You are receiving a message with very long "
3536 		      "timeout of %d seconds", __func__,
3537 		      (timeout / MSEC_IN_SEC));
3538 	} else if (timeout < MSEC_IN_SEC) {
3539 		/* consider a less than 1 second to be very short */
3540 		error("%s: You are receiving a message with a very short "
3541 		      "timeout of %d msecs", __func__, timeout);
3542 	}
3543 
3544 	/*
3545 	 * Receive a msg. slurm_msg_recvfrom() will read the message
3546 	 *  length and allocate space on the heap for a buffer containing
3547 	 *  the message.
3548 	 */
3549 	if (slurm_msg_recvfrom_timeout(fd, &buf, &buflen, 0, timeout) < 0) {
3550 		rc = errno;
3551 		goto endit;
3552 	}
3553 
3554 #if	_DEBUG
3555 	_print_data (buf, buflen);
3556 #endif
3557 	buffer = create_buf(buf, buflen);
3558 
3559 	rc = slurm_unpack_received_msg(msg, fd, buffer);
3560 
3561 	if (keep_buffer)
3562 		msg->buffer = buffer;
3563 	else
3564 		free_buf(buffer);
3565 
3566 endit:
3567 	slurm_seterrno(rc);
3568 
3569 	return rc;
3570 }
3571 
3572 /*
3573  * NOTE: memory is allocated for the returned list
3574  *       and must be freed at some point using the list_destroy function.
3575  * IN open_fd	- file descriptor to receive msg on
3576  * IN steps	- how many steps down the tree we have to wait for
3577  * IN timeout	- how long to wait in milliseconds
3578  * RET List	- List containing the responses of the children (if any) we
3579  *		  forwarded the message to. List containing type
3580  *		  (ret_data_info_t).
3581  */
slurm_receive_msgs(int fd,int steps,int timeout)3582 List slurm_receive_msgs(int fd, int steps, int timeout)
3583 {
3584 	char *buf = NULL;
3585 	size_t buflen = 0;
3586 	header_t header;
3587 	int rc;
3588 	void *auth_cred = NULL;
3589 	slurm_msg_t msg;
3590 	Buf buffer;
3591 	ret_data_info_t *ret_data_info = NULL;
3592 	List ret_list = NULL;
3593 	int orig_timeout = timeout;
3594 
3595 	xassert(fd >= 0);
3596 
3597 	slurm_msg_t_init(&msg);
3598 	msg.conn_fd = fd;
3599 
3600 	if (timeout <= 0) {
3601 		/* convert secs to msec */
3602 		timeout  = slurm_get_msg_timeout() * 1000;
3603 		orig_timeout = timeout;
3604 	}
3605 	if (steps) {
3606 		if (message_timeout < 0)
3607 			message_timeout = slurm_get_msg_timeout() * 1000;
3608 		orig_timeout = (timeout -
3609 				(message_timeout*(steps-1)))/steps;
3610 		steps--;
3611 	}
3612 
3613 	debug4("orig_timeout was %d we have %d steps and a timeout of %d",
3614 	       orig_timeout, steps, timeout);
3615 	/* we compare to the orig_timeout here because that is really
3616 	 *  what we are going to wait for each step
3617 	 */
3618 	if (orig_timeout >= (slurm_get_msg_timeout() * 10000)) {
3619 		debug("slurm_receive_msgs: "
3620 		      "You are sending a message with timeout's greater "
3621 		      "than %d seconds, your's is %d seconds",
3622 		      (slurm_get_msg_timeout() * 10),
3623 		      (timeout/1000));
3624 	} else if (orig_timeout < 1000) {
3625 		debug("slurm_receive_msgs: "
3626 		      "You are sending a message with a very short timeout of "
3627 		      "%d milliseconds each step in the tree has %d "
3628 		      "milliseconds", timeout, orig_timeout);
3629 	}
3630 
3631 
3632 	/*
3633 	 * Receive a msg. slurm_msg_recvfrom() will read the message
3634 	 *  length and allocate space on the heap for a buffer containing
3635 	 *  the message.
3636 	 */
3637 	if (slurm_msg_recvfrom_timeout(fd, &buf, &buflen, 0, timeout) < 0) {
3638 		forward_init(&header.forward);
3639 		rc = errno;
3640 		goto total_return;
3641 	}
3642 
3643 #if	_DEBUG
3644 	_print_data (buf, buflen);
3645 #endif
3646 	buffer = create_buf(buf, buflen);
3647 
3648 	if (unpack_header(&header, buffer) == SLURM_ERROR) {
3649 		free_buf(buffer);
3650 		rc = SLURM_COMMUNICATIONS_RECEIVE_ERROR;
3651 		goto total_return;
3652 	}
3653 
3654 	if (check_header_version(&header) < 0) {
3655 		slurm_addr_t resp_addr;
3656 		char addr_str[32];
3657 		int uid = _unpack_msg_uid(buffer, header.version);
3658 		if (!slurm_get_peer_addr(fd, &resp_addr)) {
3659 			slurm_print_slurm_addr(
3660 				&resp_addr, addr_str, sizeof(addr_str));
3661 			error("Invalid Protocol Version %u from uid=%d at %s",
3662 			      header.version, uid, addr_str);
3663 		} else {
3664 			error("Invalid Protocol Version %u from uid=%d from "
3665 			      "problem connection: %m",
3666 			      header.version, uid);
3667 		}
3668 
3669 		free_buf(buffer);
3670 		rc = SLURM_PROTOCOL_VERSION_ERROR;
3671 		goto total_return;
3672 	}
3673 	//info("ret_cnt = %d",header.ret_cnt);
3674 	if (header.ret_cnt > 0) {
3675 		if (header.ret_list)
3676 			ret_list = header.ret_list;
3677 		else
3678 			ret_list = list_create(destroy_data_info);
3679 		header.ret_cnt = 0;
3680 		header.ret_list = NULL;
3681 	}
3682 
3683 	/* Forward message to other nodes */
3684 	if (header.forward.cnt > 0) {
3685 		error("We need to forward this to other nodes use "
3686 		      "slurm_receive_msg_and_forward instead");
3687 	}
3688 
3689 	if ((auth_cred = g_slurm_auth_unpack(buffer, header.version)) == NULL) {
3690 		error("%s: authentication: %m", __func__);
3691 		free_buf(buffer);
3692 		rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3693 		goto total_return;
3694 	}
3695 	msg.auth_index = slurm_auth_index(auth_cred);
3696 	if (header.flags & SLURM_GLOBAL_AUTH_KEY) {
3697 		rc = g_slurm_auth_verify(auth_cred, _global_auth_key());
3698 	} else {
3699 		char *auth_info = slurm_get_auth_info();
3700 		rc = g_slurm_auth_verify(auth_cred, auth_info);
3701 		xfree(auth_info);
3702 	}
3703 
3704 	if (rc != SLURM_SUCCESS) {
3705 		error("%s: %s has authentication error: %m",
3706 		      __func__, rpc_num2string(header.msg_type));
3707 		(void) g_slurm_auth_destroy(auth_cred);
3708 		free_buf(buffer);
3709 		rc = SLURM_PROTOCOL_AUTHENTICATION_ERROR;
3710 		goto total_return;
3711 	}
3712 
3713 	/*
3714 	 * Unpack message body
3715 	 */
3716 	msg.protocol_version = header.version;
3717 	msg.msg_type = header.msg_type;
3718 	msg.flags = header.flags;
3719 
3720 	if ((header.body_length > remaining_buf(buffer)) ||
3721 	    (unpack_msg(&msg, buffer) != SLURM_SUCCESS)) {
3722 		(void) g_slurm_auth_destroy(auth_cred);
3723 		free_buf(buffer);
3724 		rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3725 		goto total_return;
3726 	}
3727 	g_slurm_auth_destroy(auth_cred);
3728 
3729 	free_buf(buffer);
3730 	rc = SLURM_SUCCESS;
3731 
3732 total_return:
3733 	destroy_forward(&header.forward);
3734 
3735 	if (rc != SLURM_SUCCESS) {
3736 		if (ret_list) {
3737 			ret_data_info = xmalloc(sizeof(ret_data_info_t));
3738 			ret_data_info->err = rc;
3739 			ret_data_info->type = RESPONSE_FORWARD_FAILED;
3740 			ret_data_info->data = NULL;
3741 			list_push(ret_list, ret_data_info);
3742 		}
3743 		error("slurm_receive_msgs: %s", slurm_strerror(rc));
3744 		usleep(10000);	/* Discourage brute force attack */
3745 	} else {
3746 		if (!ret_list)
3747 			ret_list = list_create(destroy_data_info);
3748 		ret_data_info = xmalloc(sizeof(ret_data_info_t));
3749 		ret_data_info->err = rc;
3750 		ret_data_info->node_name = NULL;
3751 		ret_data_info->type = msg.msg_type;
3752 		ret_data_info->data = msg.data;
3753 		list_push(ret_list, ret_data_info);
3754 	}
3755 
3756 
3757 	errno = rc;
3758 	return ret_list;
3759 
3760 }
3761 
3762 /* try to determine the UID associated with a message with different
3763  * message header version, return -1 if we can't tell */
_unpack_msg_uid(Buf buffer,uint16_t protocol_version)3764 static int _unpack_msg_uid(Buf buffer, uint16_t protocol_version)
3765 {
3766 	int uid = -1;
3767 	void *auth_cred = NULL, *auth_info;
3768 
3769 	if ((auth_cred = g_slurm_auth_unpack(buffer, protocol_version)) == NULL)
3770 		return uid;
3771 	auth_info = slurm_get_auth_info();
3772 	if (g_slurm_auth_verify(auth_cred, auth_info)) {
3773 		xfree(auth_info);
3774 		return uid;
3775 	}
3776 	xfree(auth_info);
3777 	uid = (int) g_slurm_auth_get_uid(auth_cred);
3778 	g_slurm_auth_destroy(auth_cred);
3779 
3780 	return uid;
3781 }
3782 
3783 /*
3784  * NOTE: memory is allocated for the returned msg and the returned list
3785  *       both must be freed at some point using the slurm_free_functions
3786  *       and list_destroy function.
3787  * IN open_fd	- file descriptor to receive msg on
3788  * IN/OUT msg	- a slurm_msg struct to be filled in by the function
3789  *		  we use the orig_addr from this var for forwarding.
3790  * IN timeout	- how long to wait in milliseconds
3791  * RET int	- returns 0 on success, -1 on failure and sets errno
3792  */
slurm_receive_msg_and_forward(int fd,slurm_addr_t * orig_addr,slurm_msg_t * msg,int timeout)3793 int slurm_receive_msg_and_forward(int fd, slurm_addr_t *orig_addr,
3794 				  slurm_msg_t *msg, int timeout)
3795 {
3796 	char *buf = NULL;
3797 	size_t buflen = 0;
3798 	header_t header;
3799 	int rc;
3800 	void *auth_cred = NULL;
3801 	Buf buffer;
3802 
3803 	xassert(fd >= 0);
3804 
3805 	if (msg->forward.init != FORWARD_INIT)
3806 		slurm_msg_t_init(msg);
3807 	/* set msg connection fd to accepted fd. This allows
3808 	 *  possibility for slurmd_req () to close accepted connection
3809 	 */
3810 	msg->conn_fd = fd;
3811 	/* this always is the connection */
3812 	memcpy(&msg->address, orig_addr, sizeof(slurm_addr_t));
3813 
3814 	/* where the connection originated from, this
3815 	 * might change based on the header we receive */
3816 	memcpy(&msg->orig_addr, orig_addr, sizeof(slurm_addr_t));
3817 
3818 	msg->ret_list = list_create(destroy_data_info);
3819 
3820 	if (timeout <= 0) {
3821 		/* convert secs to msec */
3822 		timeout  = slurm_get_msg_timeout() * 1000;
3823 	} else if (timeout < 1000) {
3824 		debug("%s: You are sending a message with a very short timeout of %d milliseconds",
3825 		      __func__, timeout);
3826 	} else if (timeout >= (slurm_get_msg_timeout() * 10000)) {
3827 		debug("slurm_receive_msg_and_forward: "
3828 		      "You are sending a message with timeout's greater "
3829 		      "than %d seconds, your's is %d seconds",
3830 		      (slurm_get_msg_timeout() * 10),
3831 		      (timeout/1000));
3832 	}
3833 
3834 	/*
3835 	 * Receive a msg. slurm_msg_recvfrom() will read the message
3836 	 *  length and allocate space on the heap for a buffer containing
3837 	 *  the message.
3838 	 */
3839 	if (slurm_msg_recvfrom_timeout(fd, &buf, &buflen, 0, timeout) < 0) {
3840 		forward_init(&header.forward);
3841 		rc = errno;
3842 		goto total_return;
3843 	}
3844 
3845 #if	_DEBUG
3846 	_print_data (buf, buflen);
3847 #endif
3848 	buffer = create_buf(buf, buflen);
3849 
3850 	if (unpack_header(&header, buffer) == SLURM_ERROR) {
3851 		free_buf(buffer);
3852 		rc = SLURM_COMMUNICATIONS_RECEIVE_ERROR;
3853 		goto total_return;
3854 	}
3855 
3856 	if (check_header_version(&header) < 0) {
3857 		slurm_addr_t resp_addr;
3858 		char addr_str[32];
3859 		int uid = _unpack_msg_uid(buffer, header.version);
3860 
3861 		if (!slurm_get_peer_addr(fd, &resp_addr)) {
3862 			slurm_print_slurm_addr(
3863 				&resp_addr, addr_str, sizeof(addr_str));
3864 			error("Invalid Protocol Version %u from uid=%d at %s",
3865 			      header.version, uid, addr_str);
3866 		} else {
3867 			error("Invalid Protocol Version %u from uid=%d from "
3868 			      "problem connection: %m",
3869 			      header.version, uid);
3870 		}
3871 
3872 		free_buf(buffer);
3873 		rc = SLURM_PROTOCOL_VERSION_ERROR;
3874 		goto total_return;
3875 	}
3876 	if (header.ret_cnt > 0) {
3877 		error("we received more than one message back use "
3878 		      "slurm_receive_msgs instead");
3879 		header.ret_cnt = 0;
3880 		FREE_NULL_LIST(header.ret_list);
3881 		header.ret_list = NULL;
3882 	}
3883 
3884 	/*
3885 	 * header.orig_addr will be set to where the first message
3886 	 * came from if this is a forward else we set the
3887 	 * header.orig_addr to our addr just in case we need to send it off.
3888 	 */
3889 	if (header.orig_addr.sin_addr.s_addr != 0) {
3890 		memcpy(&msg->orig_addr, &header.orig_addr, sizeof(slurm_addr_t));
3891 	} else {
3892 		memcpy(&header.orig_addr, orig_addr, sizeof(slurm_addr_t));
3893 	}
3894 
3895 	/* Forward message to other nodes */
3896 	if (header.forward.cnt > 0) {
3897 		debug2("forwarding to %u", header.forward.cnt);
3898 		msg->forward_struct = xmalloc(sizeof(forward_struct_t));
3899 		slurm_mutex_init(&msg->forward_struct->forward_mutex);
3900 		slurm_cond_init(&msg->forward_struct->notify, NULL);
3901 
3902 		msg->forward_struct->buf_len = remaining_buf(buffer);
3903 		msg->forward_struct->buf =
3904 			xmalloc(msg->forward_struct->buf_len);
3905 		memcpy(msg->forward_struct->buf,
3906 		       &buffer->head[buffer->processed],
3907 		       msg->forward_struct->buf_len);
3908 
3909 		msg->forward_struct->ret_list = msg->ret_list;
3910 		/* take out the amount of timeout from this hop */
3911 		msg->forward_struct->timeout = header.forward.timeout;
3912 		if (!msg->forward_struct->timeout)
3913 			msg->forward_struct->timeout = message_timeout;
3914 		msg->forward_struct->fwd_cnt = header.forward.cnt;
3915 
3916 		debug3("forwarding messages to %u nodes with timeout of %d",
3917 		       msg->forward_struct->fwd_cnt,
3918 		       msg->forward_struct->timeout);
3919 
3920 		if (forward_msg(msg->forward_struct, &header) == SLURM_ERROR) {
3921 			error("problem with forward msg");
3922 		}
3923 	}
3924 
3925 	if ((auth_cred = g_slurm_auth_unpack(buffer, header.version)) == NULL) {
3926 		error("%s: authentication: %m", __func__);
3927 		free_buf(buffer);
3928 		rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3929 		goto total_return;
3930 	}
3931 	msg->auth_index = slurm_auth_index(auth_cred);
3932 	if (header.flags & SLURM_GLOBAL_AUTH_KEY) {
3933 		rc = g_slurm_auth_verify(auth_cred, _global_auth_key());
3934 	} else {
3935 		char *auth_info = slurm_get_auth_info();
3936 		rc = g_slurm_auth_verify(auth_cred, auth_info);
3937 		xfree(auth_info);
3938 	}
3939 
3940 	if (rc != SLURM_SUCCESS) {
3941 		error("%s: %s has authentication error: %m",
3942 		      __func__, rpc_num2string(header.msg_type));
3943 		(void) g_slurm_auth_destroy(auth_cred);
3944 		free_buf(buffer);
3945 		rc = SLURM_PROTOCOL_AUTHENTICATION_ERROR;
3946 		goto total_return;
3947 	}
3948 
3949 	/*
3950 	 * Unpack message body
3951 	 */
3952 	msg->protocol_version = header.version;
3953 	msg->msg_type = header.msg_type;
3954 	msg->flags = header.flags;
3955 
3956 	if (header.msg_type == MESSAGE_COMPOSITE) {
3957 		slurm_send_rc_msg(msg, SLURM_SUCCESS);
3958 		msg_aggr_add_comp(buffer, auth_cred, &header);
3959 		goto total_return;
3960 	}
3961 
3962 	if ( (header.body_length > remaining_buf(buffer)) ||
3963 	     (unpack_msg(msg, buffer) != SLURM_SUCCESS) ) {
3964 		(void) g_slurm_auth_destroy(auth_cred);
3965 		free_buf(buffer);
3966 		rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3967 		goto total_return;
3968 	}
3969 	msg->auth_cred = (void *) auth_cred;
3970 
3971 	free_buf(buffer);
3972 	rc = SLURM_SUCCESS;
3973 
3974 total_return:
3975 	destroy_forward(&header.forward);
3976 
3977 	slurm_seterrno(rc);
3978 	if (rc != SLURM_SUCCESS) {
3979 		msg->msg_type = RESPONSE_FORWARD_FAILED;
3980 		msg->auth_cred = (void *) NULL;
3981 		msg->data = NULL;
3982 		error("slurm_receive_msg_and_forward: %s",
3983 		      slurm_strerror(rc));
3984 		usleep(10000);	/* Discourage brute force attack */
3985 	} else {
3986 		rc = 0;
3987 	}
3988 	return rc;
3989 
3990 }
3991 
3992 /**********************************************************************\
3993  * send message functions
3994 \**********************************************************************/
3995 
3996 /*
3997  *  Do the wonderful stuff that needs be done to pack msg
3998  *  and hdr into buffer
3999  */
4000 static void
_pack_msg(slurm_msg_t * msg,header_t * hdr,Buf buffer)4001 _pack_msg(slurm_msg_t *msg, header_t *hdr, Buf buffer)
4002 {
4003 	unsigned int tmplen, msglen;
4004 
4005 	tmplen = get_buf_offset(buffer);
4006 	pack_msg(msg, buffer);
4007 	msglen = get_buf_offset(buffer) - tmplen;
4008 
4009 	/* update header with correct cred and msg lengths */
4010 	update_header(hdr, msglen);
4011 
4012 	/* repack updated header */
4013 	tmplen = get_buf_offset(buffer);
4014 	set_buf_offset(buffer, 0);
4015 	pack_header(hdr, buffer);
4016 	set_buf_offset(buffer, tmplen);
4017 }
4018 
4019 /*
4020  *  Send a slurm message over an open file descriptor `fd'
4021  *    Returns the size of the message sent in bytes, or -1 on failure.
4022  */
slurm_send_node_msg(int fd,slurm_msg_t * msg)4023 int slurm_send_node_msg(int fd, slurm_msg_t * msg)
4024 {
4025 	header_t header;
4026 	Buf      buffer;
4027 	int      rc;
4028 	void *   auth_cred;
4029 	time_t   start_time = time(NULL);
4030 
4031 	if (msg->conn) {
4032 		persist_msg_t persist_msg;
4033 
4034 		memset(&persist_msg, 0, sizeof(persist_msg_t));
4035 		persist_msg.msg_type  = msg->msg_type;
4036 		persist_msg.data      = msg->data;
4037 		persist_msg.data_size = msg->data_size;
4038 
4039 		buffer = slurm_persist_msg_pack(msg->conn, &persist_msg);
4040 		if (!buffer)    /* pack error */
4041 			return SLURM_ERROR;
4042 
4043 		rc = slurm_persist_send_msg(msg->conn, buffer);
4044 		free_buf(buffer);
4045 
4046 		if ((rc < 0) && (errno == ENOTCONN)) {
4047 			debug3("slurm_persist_send_msg: persistent connection has disappeared for msg_type=%u",
4048 			       msg->msg_type);
4049 		} else if (rc < 0) {
4050 			slurm_addr_t peer_addr;
4051 			char addr_str[32];
4052 			if (!slurm_get_peer_addr(msg->conn->fd, &peer_addr)) {
4053 				slurm_print_slurm_addr(
4054 					&peer_addr, addr_str, sizeof(addr_str));
4055 				error("slurm_persist_send_msg: address:port=%s msg_type=%u: %m",
4056 				      addr_str, msg->msg_type);
4057 			} else
4058 				error("slurm_persist_send_msg: msg_type=%u: %m",
4059 				      msg->msg_type);
4060 		}
4061 
4062 		return rc;
4063 	}
4064 
4065 	/*
4066 	 * Initialize header with Auth credential and message type.
4067 	 * We get the credential now rather than later so the work can
4068 	 * can be done in parallel with waiting for message to forward,
4069 	 * but we may need to generate the credential again later if we
4070 	 * wait too long for the incoming message.
4071 	 */
4072 	if (msg->flags & SLURM_GLOBAL_AUTH_KEY) {
4073 		auth_cred = g_slurm_auth_create(msg->auth_index,
4074 						_global_auth_key());
4075 	} else {
4076 		char *auth_info = slurm_get_auth_info();
4077 		auth_cred = g_slurm_auth_create(msg->auth_index, auth_info);
4078 		xfree(auth_info);
4079 	}
4080 
4081 	if (msg->forward.init != FORWARD_INIT) {
4082 		forward_init(&msg->forward);
4083 		msg->ret_list = NULL;
4084 	}
4085 
4086 	if (!msg->forward.tree_width)
4087 		msg->forward.tree_width = slurm_get_tree_width();
4088 
4089 	forward_wait(msg);
4090 
4091 	if (difftime(time(NULL), start_time) >= 60) {
4092 		(void) g_slurm_auth_destroy(auth_cred);
4093 		if (msg->flags & SLURM_GLOBAL_AUTH_KEY) {
4094 			auth_cred = g_slurm_auth_create(msg->auth_index,
4095 							_global_auth_key());
4096 		} else {
4097 			char *auth_info = slurm_get_auth_info();
4098 			auth_cred = g_slurm_auth_create(msg->auth_index,
4099 							auth_info);
4100 			xfree(auth_info);
4101 		}
4102 	}
4103 	if (auth_cred == NULL) {
4104 		error("%s: authentication: %m", __func__);
4105 		slurm_seterrno_ret(SLURM_PROTOCOL_AUTHENTICATION_ERROR);
4106 	}
4107 
4108 	init_header(&header, msg, msg->flags);
4109 
4110 	/*
4111 	 * Pack header into buffer for transmission
4112 	 */
4113 	buffer = init_buf(BUF_SIZE);
4114 	pack_header(&header, buffer);
4115 
4116 	/*
4117 	 * Pack auth credential
4118 	 */
4119 	rc = g_slurm_auth_pack(auth_cred, buffer, header.version);
4120 	(void) g_slurm_auth_destroy(auth_cred);
4121 	if (rc) {
4122 		error("%s: authentication: %m", __func__);
4123 		free_buf(buffer);
4124 		slurm_seterrno_ret(SLURM_PROTOCOL_AUTHENTICATION_ERROR);
4125 	}
4126 
4127 	/*
4128 	 * Pack message into buffer
4129 	 */
4130 	_pack_msg(msg, &header, buffer);
4131 
4132 #if	_DEBUG
4133 	_print_data (get_buf_data(buffer),get_buf_offset(buffer));
4134 #endif
4135 	/*
4136 	 * Send message
4137 	 */
4138 	rc = slurm_msg_sendto(fd, get_buf_data(buffer),
4139 			      get_buf_offset(buffer));
4140 
4141 	if ((rc < 0) && (errno == ENOTCONN)) {
4142 		debug3("slurm_msg_sendto: peer has disappeared for msg_type=%u",
4143 		       msg->msg_type);
4144 	} else if (rc < 0) {
4145 		slurm_addr_t peer_addr;
4146 		char addr_str[32];
4147 		if (!slurm_get_peer_addr(fd, &peer_addr)) {
4148 			slurm_print_slurm_addr(
4149 				&peer_addr, addr_str, sizeof(addr_str));
4150 			error("slurm_msg_sendto: address:port=%s "
4151 			      "msg_type=%u: %m",
4152 			      addr_str, msg->msg_type);
4153 		} else if (errno == ENOTCONN)
4154 			debug3("slurm_msg_sendto: peer has disappeared "
4155 			       "for msg_type=%u",
4156 			       msg->msg_type);
4157 		else
4158 			error("slurm_msg_sendto: msg_type=%u: %m",
4159 			      msg->msg_type);
4160 	}
4161 
4162 	free_buf(buffer);
4163 	return rc;
4164 }
4165 
4166 /**********************************************************************\
4167  * stream functions
4168 \**********************************************************************/
4169 
4170 /* slurm_write_stream
4171  * writes a buffer out a stream file descriptor
4172  * IN open_fd		- file descriptor to write on
4173  * IN buffer		- buffer to send
4174  * IN size		- size of buffer send
4175  * IN timeout		- how long to wait in milliseconds
4176  * RET size_t		- bytes sent , or -1 on errror
4177  */
slurm_write_stream(int open_fd,char * buffer,size_t size)4178 size_t slurm_write_stream(int open_fd, char *buffer, size_t size)
4179 {
4180 	return slurm_send_timeout(open_fd, buffer, size,
4181 				  SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4182 				  (slurm_get_msg_timeout() * 1000));
4183 }
slurm_write_stream_timeout(int open_fd,char * buffer,size_t size,int timeout)4184 size_t slurm_write_stream_timeout(int open_fd, char *buffer,
4185 				  size_t size, int timeout)
4186 {
4187 	return slurm_send_timeout(open_fd, buffer, size,
4188 				  SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4189 				  timeout);
4190 }
4191 
4192 /* slurm_read_stream
4193  * read into buffer grom a stream file descriptor
4194  * IN open_fd	- file descriptor to read from
4195  * OUT buffer   - buffer to receive into
4196  * IN size	- size of buffer
4197  * IN timeout	- how long to wait in milliseconds
4198  * RET size_t	- bytes read , or -1 on errror
4199  */
slurm_read_stream(int open_fd,char * buffer,size_t size)4200 size_t slurm_read_stream(int open_fd, char *buffer, size_t size)
4201 {
4202 	return slurm_recv_timeout(open_fd, buffer, size,
4203 				   SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4204 				   (slurm_get_msg_timeout() * 1000));
4205 }
slurm_read_stream_timeout(int open_fd,char * buffer,size_t size,int timeout)4206 size_t slurm_read_stream_timeout(int open_fd, char *buffer,
4207 				 size_t size, int timeout)
4208 {
4209 	return slurm_recv_timeout(open_fd, buffer, size,
4210 				   SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4211 				   timeout);
4212 }
4213 
4214 /**********************************************************************\
4215  * address conversion and management functions
4216 \**********************************************************************/
4217 
4218 /* slurm_set_addr
4219  * initializes the slurm_address with the supplied port and host name
4220  * OUT slurm_address	- slurm_addr_t to be filled in
4221  * IN port		- port in host order
4222  * IN host		- hostname or dns name
4223  */
slurm_set_addr(slurm_addr_t * slurm_address,uint16_t port,char * host)4224 void slurm_set_addr(slurm_addr_t * slurm_address, uint16_t port, char *host)
4225 {
4226 	slurm_set_addr_char(slurm_address, port, host);
4227 }
4228 
4229 /* slurm_get_ip_str
4230  * given a slurm_address it returns its port and ip address string
4231  * IN slurm_address	- slurm_addr_t to be queried
4232  * OUT port		- port number
4233  * OUT ip		- ip address in dotted-quad string form
4234  * IN buf_len		- length of ip buffer
4235  */
slurm_get_ip_str(slurm_addr_t * slurm_address,uint16_t * port,char * ip,unsigned int buf_len)4236 void slurm_get_ip_str(slurm_addr_t * slurm_address, uint16_t * port,
4237 		      char *ip, unsigned int buf_len)
4238 {
4239 	unsigned char *uc = (unsigned char *)&slurm_address->sin_addr.s_addr;
4240 	*port = slurm_address->sin_port;
4241 	snprintf(ip, buf_len, "%u.%u.%u.%u", uc[0], uc[1], uc[2], uc[3]);
4242 }
4243 
4244 /* slurm_get_peer_addr
4245  * get the slurm address of the peer connection, similar to getpeeraddr
4246  * IN fd		- an open connection
4247  * OUT slurm_address	- place to park the peer's slurm_addr
4248  */
slurm_get_peer_addr(int fd,slurm_addr_t * slurm_address)4249 int slurm_get_peer_addr(int fd, slurm_addr_t * slurm_address)
4250 {
4251 	struct sockaddr name;
4252 	socklen_t namelen = (socklen_t) sizeof(struct sockaddr);
4253 	int rc;
4254 
4255 	if ((rc = getpeername((int) fd, &name, &namelen)))
4256 		return rc;
4257 	memcpy(slurm_address, &name, sizeof(slurm_addr_t));
4258 	return 0;
4259 }
4260 
4261 /**********************************************************************\
4262  * slurm_addr_t pack routines
4263 \**********************************************************************/
4264 
4265 /* slurm_pack_slurm_addr_array
4266  * packs an array of slurm_addrs into a buffer
4267  * OUT slurm_address	- slurm_addr_t to pack
4268  * IN size_val  	- how many to pack
4269  * IN/OUT buffer	- buffer to pack the slurm_addr_t from
4270  * returns		- Slurm error code
4271  */
slurm_pack_slurm_addr_array(slurm_addr_t * slurm_address,uint32_t size_val,Buf buffer)4272 void slurm_pack_slurm_addr_array(slurm_addr_t * slurm_address,
4273 				 uint32_t size_val, Buf buffer)
4274 {
4275 	int i = 0;
4276 	uint32_t nl = htonl(size_val);
4277 	pack32(nl, buffer);
4278 
4279 	for (i = 0; i < size_val; i++) {
4280 		slurm_pack_slurm_addr(slurm_address + i, buffer);
4281 	}
4282 
4283 }
4284 
4285 /* slurm_unpack_slurm_addr_array
4286  * unpacks an array of slurm_addrs from a buffer
4287  * OUT slurm_address	- slurm_addr_t to unpack to
4288  * IN size_val  	- how many to unpack
4289  * IN/OUT buffer	- buffer to upack the slurm_addr_t from
4290  * returns		- Slurm error code
4291  */
slurm_unpack_slurm_addr_array(slurm_addr_t ** slurm_address,uint32_t * size_val,Buf buffer)4292 int slurm_unpack_slurm_addr_array(slurm_addr_t ** slurm_address,
4293 				  uint32_t * size_val, Buf buffer)
4294 {
4295 	int i = 0;
4296 	uint32_t nl;
4297 
4298 	*slurm_address = NULL;
4299 	safe_unpack32(&nl, buffer);
4300 	if (nl > NO_VAL)
4301 		goto unpack_error;
4302 	*size_val = ntohl(nl);
4303 	*slurm_address = xcalloc(*size_val, sizeof(slurm_addr_t));
4304 
4305 	for (i = 0; i < *size_val; i++) {
4306 		if (slurm_unpack_slurm_addr_no_alloc((*slurm_address) + i,
4307 						     buffer))
4308 			goto unpack_error;
4309 
4310 	}
4311 	return SLURM_SUCCESS;
4312 
4313 unpack_error:
4314 	xfree(*slurm_address);
4315 	*slurm_address = NULL;
4316 	return SLURM_ERROR;
4317 }
4318 
_resp_msg_setup(slurm_msg_t * msg,slurm_msg_t * resp_msg,uint16_t msg_type,void * data)4319 static void _resp_msg_setup(slurm_msg_t *msg, slurm_msg_t *resp_msg,
4320 			    uint16_t msg_type, void *data)
4321 {
4322 	slurm_msg_t_init(resp_msg);
4323 	resp_msg->address = msg->address;
4324 	resp_msg->auth_index = msg->auth_index;
4325 	resp_msg->conn = msg->conn;
4326 	resp_msg->data = data;
4327 	resp_msg->flags = msg->flags;
4328 	resp_msg->forward = msg->forward;
4329 	resp_msg->forward_struct = msg->forward_struct;
4330 	resp_msg->msg_type = msg_type;
4331 	resp_msg->protocol_version = msg->protocol_version;
4332 	resp_msg->ret_list = msg->ret_list;
4333 	resp_msg->orig_addr = msg->orig_addr;
4334 }
4335 
_rc_msg_setup(slurm_msg_t * msg,slurm_msg_t * resp_msg,return_code_msg_t * rc_msg,int rc)4336 static void _rc_msg_setup(slurm_msg_t *msg, slurm_msg_t *resp_msg,
4337 			  return_code_msg_t *rc_msg, int rc)
4338 {
4339 	memset(rc_msg, 0, sizeof(return_code_msg_t));
4340 	rc_msg->return_code = rc;
4341 
4342 	_resp_msg_setup(msg, resp_msg, RESPONSE_SLURM_RC, rc_msg);
4343 }
4344 
4345 
4346 /**********************************************************************\
4347  * simplified communication routines
4348  * They open a connection do work then close the connection all within
4349  * the function
4350 \**********************************************************************/
4351 
4352 /* slurm_send_msg
4353  * given the original request message this function sends a
4354  *	arbitrary message back to the client that made the request
4355  * IN request_msg	- slurm_msg the request msg
4356  * IN msg_type          - message type being returned
4357  * IN resp_msg		- the message being returned to the client
4358  */
slurm_send_msg(slurm_msg_t * msg,uint16_t msg_type,void * resp)4359 int slurm_send_msg(slurm_msg_t *msg, uint16_t msg_type, void *resp)
4360 {
4361 	if (msg->msg_index && msg->ret_list) {
4362 		slurm_msg_t *resp_msg = xmalloc_nz(sizeof(slurm_msg_t));
4363 
4364 		_resp_msg_setup(msg, resp_msg, msg_type, resp);
4365 
4366 		resp_msg->msg_index = msg->msg_index;
4367 		resp_msg->ret_list = NULL;
4368 		/*
4369 		 * The return list here is the list we are sending to
4370 		 * the node, so after we attach this message to it set
4371 		 * it to NULL to remove it.
4372 		 */
4373 		list_append(msg->ret_list, resp_msg);
4374 		return SLURM_SUCCESS;
4375 	} else {
4376 		slurm_msg_t resp_msg;
4377 
4378 		if (msg->conn_fd < 0) {
4379 			slurm_seterrno(ENOTCONN);
4380 			return SLURM_ERROR;
4381 		}
4382 		_resp_msg_setup(msg, &resp_msg, msg_type, resp);
4383 
4384 		/* send message */
4385 		return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4386 	}
4387 }
4388 
4389 /* slurm_send_rc_msg
4390  * given the original request message this function sends a
4391  *	slurm_return_code message back to the client that made the request
4392  * IN request_msg	- slurm_msg the request msg
4393  * IN rc		- the return_code to send back to the client
4394  */
slurm_send_rc_msg(slurm_msg_t * msg,int rc)4395 int slurm_send_rc_msg(slurm_msg_t *msg, int rc)
4396 {
4397 	if (msg->msg_index && msg->ret_list) {
4398 		slurm_msg_t *resp_msg = xmalloc_nz(sizeof(slurm_msg_t));
4399 		return_code_msg_t *rc_msg =
4400 			xmalloc_nz(sizeof(return_code_msg_t));
4401 
4402 		_rc_msg_setup(msg, resp_msg, rc_msg, rc);
4403 
4404 		resp_msg->msg_index = msg->msg_index;
4405 		resp_msg->ret_list = NULL;
4406 		/* The return list here is the list we are sending to
4407 		   the node, so after we attach this message to it set
4408 		   it to NULL to remove it.
4409 		*/
4410 		list_append(msg->ret_list, resp_msg);
4411 		return SLURM_SUCCESS;
4412 	} else {
4413 		slurm_msg_t resp_msg;
4414 		return_code_msg_t rc_msg;
4415 
4416 		if (msg->conn_fd < 0) {
4417 			slurm_seterrno(ENOTCONN);
4418 			return SLURM_ERROR;
4419 		}
4420 		_rc_msg_setup(msg, &resp_msg, &rc_msg, rc);
4421 
4422 		/* send message */
4423 		return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4424 	}
4425 }
4426 
4427 /* slurm_send_rc_err_msg
4428  * given the original request message this function sends a
4429  *	slurm_return_code message back to the client that made the request
4430  * IN request_msg	- slurm_msg the request msg
4431  * IN rc		- the return_code to send back to the client
4432  * IN err_msg   	- message for user
4433  */
slurm_send_rc_err_msg(slurm_msg_t * msg,int rc,char * err_msg)4434 int slurm_send_rc_err_msg(slurm_msg_t *msg, int rc, char *err_msg)
4435 {
4436 	slurm_msg_t resp_msg;
4437 	return_code2_msg_t rc_msg;
4438 
4439 	if (msg->conn_fd < 0) {
4440 		slurm_seterrno(ENOTCONN);
4441 		return SLURM_ERROR;
4442 	}
4443 	rc_msg.return_code = rc;
4444 	rc_msg.err_msg     = err_msg;
4445 
4446 	_resp_msg_setup(msg, &resp_msg, RESPONSE_SLURM_RC_MSG, &rc_msg);
4447 
4448 	/* send message */
4449 	return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4450 }
4451 
4452 /*
4453  * Sends back reroute_msg_t which directs the client to make the request to
4454  * another cluster.
4455  *
4456  * IN msg	  - msg to respond to.
4457  * IN cluster_rec - cluster to direct msg to.
4458  */
slurm_send_reroute_msg(slurm_msg_t * msg,slurmdb_cluster_rec_t * cluster_rec)4459 int slurm_send_reroute_msg(slurm_msg_t *msg, slurmdb_cluster_rec_t *cluster_rec)
4460 {
4461 	slurm_msg_t resp_msg;
4462 	reroute_msg_t reroute_msg = {0};
4463 
4464 	if (msg->conn_fd < 0) {
4465 		slurm_seterrno(ENOTCONN);
4466 		return SLURM_ERROR;
4467 	}
4468 
4469 	/* Don't free the cluster_rec, it's pointing to the actual object. */
4470 	reroute_msg.working_cluster_rec = cluster_rec;
4471 
4472 	_resp_msg_setup(msg, &resp_msg, RESPONSE_SLURM_REROUTE_MSG,
4473 			&reroute_msg);
4474 
4475 	/* send message */
4476 	return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4477 }
4478 
4479 /*
4480  * Send and recv a slurm request and response on the open slurm descriptor
4481  * Doesn't close the connection.
4482  * IN fd	- file descriptor to receive msg on
4483  * IN req	- a slurm_msg struct to be sent by the function
4484  * OUT resp	- a slurm_msg struct to be filled in by the function
4485  * IN timeout	- how long to wait in milliseconds
4486  * RET int	- returns 0 on success, -1 on failure and sets errno
4487  */
slurm_send_recv_msg(int fd,slurm_msg_t * req,slurm_msg_t * resp,int timeout)4488 extern int slurm_send_recv_msg(int fd, slurm_msg_t *req,
4489 			       slurm_msg_t *resp, int timeout)
4490 {
4491 	int rc = -1;
4492 	slurm_msg_t_init(resp);
4493 
4494 	/* If we are using a persistent connection make sure it is the one we
4495 	 * actually want.  This should be the correct one already, but just make
4496 	 * sure.
4497 	 */
4498 	if (req->conn) {
4499 		fd = req->conn->fd;
4500 		resp->conn = req->conn;
4501 	}
4502 
4503 	if (slurm_send_node_msg(fd, req) >= 0) {
4504 		/* no need to adjust and timeouts here since we are not
4505 		   forwarding or expecting anything other than 1 message
4506 		   and the regular timeout will be altered in
4507 		   slurm_receive_msg if it is 0 */
4508 		rc = slurm_receive_msg(fd, resp, timeout);
4509 	}
4510 
4511 	return rc;
4512 }
4513 
4514 /*
4515  * Send and recv a slurm request and response on the open slurm descriptor
4516  * Closes the connection.
4517  * IN fd	- file descriptor to receive msg on
4518  * IN req	- a slurm_msg struct to be sent by the function
4519  * OUT resp	- a slurm_msg struct to be filled in by the function
4520  * IN timeout	- how long to wait in milliseconds
4521  * RET int	- returns 0 on success, -1 on failure and sets errno
4522  */
4523 static int
_send_and_recv_msg(int fd,slurm_msg_t * req,slurm_msg_t * resp,int timeout)4524 _send_and_recv_msg(int fd, slurm_msg_t *req,
4525 		   slurm_msg_t *resp, int timeout)
4526 {
4527 	int rc = slurm_send_recv_msg(fd, req, resp, timeout);
4528 	(void) close(fd);
4529 	return rc;
4530 }
4531 
4532 /*
4533  * Send and recv a slurm request and response on the open slurm descriptor
4534  * with a list containing the responses of the children (if any) we
4535  * forwarded the message to. List containing type (ret_data_info_t).
4536  * IN fd	- file descriptor to receive msg on
4537  * IN req	- a slurm_msg struct to be sent by the function
4538  * IN timeout	- how long to wait in milliseconds
4539  * RET List	- List containing the responses of the children (if any) we
4540  *		  forwarded the message to. List containing type
4541  *		  (ret_data_info_t).
4542  */
4543 static List
_send_and_recv_msgs(int fd,slurm_msg_t * req,int timeout)4544 _send_and_recv_msgs(int fd, slurm_msg_t *req, int timeout)
4545 {
4546 	List ret_list = NULL;
4547 	int steps = 0;
4548 
4549 	if (!req->forward.timeout) {
4550 		if (!timeout)
4551 			timeout = slurm_get_msg_timeout() * 1000;
4552 		req->forward.timeout = timeout;
4553 	}
4554 	if (slurm_send_node_msg(fd, req) >= 0) {
4555 		if (req->forward.cnt > 0) {
4556 			/* figure out where we are in the tree and set
4557 			 * the timeout for to wait for our children
4558 			 * correctly
4559 			 * (timeout+message_timeout sec per step)
4560 			 * to let the child timeout */
4561 			if (message_timeout < 0)
4562 				message_timeout =
4563 					slurm_get_msg_timeout() * 1000;
4564 			steps = req->forward.cnt + 1;
4565 			if (!req->forward.tree_width)
4566 				req->forward.tree_width =
4567 					slurm_get_tree_width();
4568 			if (req->forward.tree_width)
4569 				steps /= req->forward.tree_width;
4570 			timeout = (message_timeout * steps);
4571 			steps++;
4572 
4573 			timeout += (req->forward.timeout*steps);
4574 		}
4575 		ret_list = slurm_receive_msgs(fd, steps, timeout);
4576 	}
4577 
4578 	(void) close(fd);
4579 
4580 	return ret_list;
4581 }
4582 
4583 /*
4584  * slurm_send_recv_controller_msg
4585  * opens a connection to the controller, sends the controller a message,
4586  * listens for the response, then closes the connection
4587  * IN request_msg	- slurm_msg request
4588  * OUT response_msg	- slurm_msg response
4589  * IN comm_cluster_rec	- Communication record (host/port/version)/
4590  * RET int 		- returns 0 on success, -1 on failure and sets errno
4591  */
slurm_send_recv_controller_msg(slurm_msg_t * request_msg,slurm_msg_t * response_msg,slurmdb_cluster_rec_t * comm_cluster_rec)4592 extern int slurm_send_recv_controller_msg(slurm_msg_t * request_msg,
4593 				slurm_msg_t * response_msg,
4594 				slurmdb_cluster_rec_t *comm_cluster_rec)
4595 {
4596 	int fd = -1;
4597 	int rc = 0;
4598 	time_t start_time = time(NULL);
4599 	int retry = 1;
4600 	slurm_ctl_conf_t *conf;
4601 	bool have_backup;
4602 	uint16_t slurmctld_timeout;
4603 	slurm_addr_t ctrl_addr;
4604 	static bool use_backup = false;
4605 	slurmdb_cluster_rec_t *save_comm_cluster_rec = comm_cluster_rec;
4606 
4607 	/*
4608 	 * Just in case the caller didn't initialize his slurm_msg_t, and
4609 	 * since we KNOW that we are only sending to one node (the controller),
4610 	 * we initialize some forwarding variables to disable forwarding.
4611 	 */
4612 	forward_init(&request_msg->forward);
4613 	request_msg->ret_list = NULL;
4614 	request_msg->forward_struct = NULL;
4615 
4616 tryagain:
4617 	retry = 1;
4618 	if (comm_cluster_rec)
4619 		request_msg->flags |= SLURM_GLOBAL_AUTH_KEY;
4620 
4621 	if ((fd = slurm_open_controller_conn(&ctrl_addr, &use_backup,
4622 					     comm_cluster_rec)) < 0) {
4623 		rc = -1;
4624 		goto cleanup;
4625 	}
4626 
4627 	conf = slurm_conf_lock();
4628 	have_backup = conf->control_cnt > 1;
4629 	slurmctld_timeout = conf->slurmctld_timeout;
4630 	slurm_conf_unlock();
4631 
4632 	while (retry) {
4633 		/*
4634 		 * If the backup controller is in the process of assuming
4635 		 * control, we sleep and retry later
4636 		 */
4637 		retry = 0;
4638 		rc = _send_and_recv_msg(fd, request_msg, response_msg, 0);
4639 		if (response_msg->auth_cred)
4640 			g_slurm_auth_destroy(response_msg->auth_cred);
4641 		else
4642 			rc = -1;
4643 
4644 		if ((rc == 0) && (!comm_cluster_rec)
4645 		    && (response_msg->msg_type == RESPONSE_SLURM_RC)
4646 		    && ((((return_code_msg_t *)response_msg->data)->return_code)
4647 			== ESLURM_IN_STANDBY_MODE)
4648 		    && (have_backup)
4649 		    && (difftime(time(NULL), start_time)
4650 			< (slurmctld_timeout + (slurmctld_timeout / 2)))) {
4651 
4652 			debug("Primary not responding, backup not in control. "
4653 			      "sleep and retry");
4654 			slurm_free_return_code_msg(response_msg->data);
4655 			sleep(slurmctld_timeout / 2);
4656 			use_backup = false;
4657 			if ((fd = slurm_open_controller_conn(&ctrl_addr,
4658 							     &use_backup,
4659 							     comm_cluster_rec))
4660 			    < 0) {
4661 				rc = -1;
4662 			} else {
4663 				retry = 1;
4664 			}
4665 		}
4666 
4667 		if (rc == -1)
4668 			break;
4669 	}
4670 
4671 	if (!rc && (response_msg->msg_type == RESPONSE_SLURM_REROUTE_MSG)) {
4672 		reroute_msg_t *rr_msg = (reroute_msg_t *)response_msg->data;
4673 
4674 		/*
4675 		 * Don't expect mutliple hops but in the case it does
4676 		 * happen, free the previous rr cluster_rec.
4677 		 */
4678 		if (comm_cluster_rec &&
4679 		    (comm_cluster_rec != save_comm_cluster_rec))
4680 			slurmdb_destroy_cluster_rec(comm_cluster_rec);
4681 
4682 		comm_cluster_rec = rr_msg->working_cluster_rec;
4683 		slurmdb_setup_cluster_rec(comm_cluster_rec);
4684 		rr_msg->working_cluster_rec = NULL;
4685 		goto tryagain;
4686 	}
4687 
4688 	if (comm_cluster_rec != save_comm_cluster_rec)
4689 		slurmdb_destroy_cluster_rec(comm_cluster_rec);
4690 
4691 cleanup:
4692 	if (rc != 0)
4693  		_remap_slurmctld_errno();
4694 
4695 	return rc;
4696 }
4697 
4698 /* slurm_send_recv_node_msg
4699  * opens a connection to node, sends the node a message, listens
4700  * for the response, then closes the connection
4701  * IN request_msg	- slurm_msg request
4702  * OUT response_msg	- slurm_msg response
4703  * IN timeout		- how long to wait in milliseconds
4704  * RET int		- returns 0 on success, -1 on failure and sets errno
4705  */
slurm_send_recv_node_msg(slurm_msg_t * req,slurm_msg_t * resp,int timeout)4706 int slurm_send_recv_node_msg(slurm_msg_t *req, slurm_msg_t *resp, int timeout)
4707 {
4708 	int fd = -1;
4709 
4710 	resp->auth_cred = NULL;
4711 	if ((fd = slurm_open_msg_conn(&req->address)) < 0)
4712 		return -1;
4713 
4714 	return _send_and_recv_msg(fd, req, resp, timeout);
4715 
4716 }
4717 
4718 /* slurm_send_only_controller_msg
4719  * opens a connection to the controller, sends the controller a
4720  * message then, closes the connection
4721  * IN request_msg	- slurm_msg request
4722  * IN comm_cluster_rec	- Communication record (host/port/version)
4723  * RET int		- return code
4724  * NOTE: NOT INTENDED TO BE CROSS-CLUSTER
4725  */
slurm_send_only_controller_msg(slurm_msg_t * req,slurmdb_cluster_rec_t * comm_cluster_rec)4726 extern int slurm_send_only_controller_msg(slurm_msg_t *req,
4727 				slurmdb_cluster_rec_t *comm_cluster_rec)
4728 {
4729 	int      rc = SLURM_SUCCESS;
4730 	int fd = -1;
4731 	slurm_addr_t ctrl_addr;
4732 	bool     use_backup = false;
4733 
4734 	/*
4735 	 *  Open connection to Slurm controller:
4736 	 */
4737 	if ((fd = slurm_open_controller_conn(&ctrl_addr, &use_backup,
4738 					     comm_cluster_rec)) < 0) {
4739 		rc = SLURM_ERROR;
4740 		goto cleanup;
4741 	}
4742 
4743 	if ((rc = slurm_send_node_msg(fd, req)) < 0) {
4744 		rc = SLURM_ERROR;
4745 	} else {
4746 		debug3("slurm_send_only_controller_msg: sent %d", rc);
4747 		rc = SLURM_SUCCESS;
4748 	}
4749 
4750 	(void) close(fd);
4751 
4752 cleanup:
4753 	if (rc != SLURM_SUCCESS)
4754 		_remap_slurmctld_errno();
4755 	return rc;
4756 }
4757 
4758 /*
4759  *  Open a connection to the "address" specified in the slurm msg `req'
4760  *   Then, immediately close the connection w/out waiting for a reply.
4761  *
4762  *   Returns SLURM_SUCCESS on success SLURM_ERROR (< 0) for failure.
4763  *
4764  * DO NOT USE THIS IN NEW CODE
4765  * Use slurm_send_recv_rc_msg_only_one() or something similar instead.
4766  *
4767  * By not waiting for a response message, the message to be transmitted
4768  * may never be received by the remote end. The remote TCP stack may
4769  * acknowledge the data while the application itself has not had a chance
4770  * to receive it. The only way to tell that the application has processed
4771  * a given packet is for it to send back a message across the socket itself.
4772  *
4773  * The receive side looks like: poll() && read(), close(). If the poll() times
4774  * out, the kernel may still ACK the data while the application has jumped to
4775  * closing the connection. The send side cannot then distinguish between the
4776  * close happening as a result of the timeout vs. as a normal message shutdown.
4777  *
4778  * This is only one example of the many races inherent in this approach.
4779  *
4780  * See "UNIX Network Programming" Volume 1 (Third Edition) Section 7.5 on
4781  * SO_LINGER for a description of the subtle hazards inherent in abusing
4782  * TCP as a unidirectional pipe.
4783  */
slurm_send_only_node_msg(slurm_msg_t * req)4784 int slurm_send_only_node_msg(slurm_msg_t *req)
4785 {
4786 	int rc = SLURM_SUCCESS;
4787 	int fd = -1;
4788 	struct pollfd pfd;
4789 	int value = -1;
4790 	int pollrc;
4791 
4792 	if ((fd = slurm_open_msg_conn(&req->address)) < 0) {
4793 		return SLURM_ERROR;
4794 	}
4795 
4796 	if ((rc = slurm_send_node_msg(fd, req)) < 0) {
4797 		rc = SLURM_ERROR;
4798 	} else {
4799 		debug3("%s: sent %d", __func__, rc);
4800 		rc = SLURM_SUCCESS;
4801 	}
4802 
4803 	/*
4804 	 * Make sure message was received by remote, and that there isn't
4805 	 * and outstanding write() or that the connection has been reset.
4806 	 *
4807 	 * The shutdown() call intentionally falls through to the next block,
4808 	 * the poll() should hit POLLERR which gives the TICOUTQ count as an
4809 	 * additional diagnostic element.
4810 	 *
4811 	 * The steps below may result in a false-positive on occassion, in
4812 	 * which case the code path above may opt to retransmit an already
4813 	 * received message. If this is a concern, you should not be using
4814 	 * this function.
4815 	 */
4816 	if (shutdown(fd, SHUT_WR))
4817 		debug("%s: shutdown call failed: %m", __func__);
4818 
4819 again:
4820 	pfd.fd = fd;
4821 	pfd.events = POLLIN;
4822 	/*
4823 	 * Wait for 1000 ms for shutdown to respond.  We found this is long
4824 	 * enough to get a response, but any longer would start to produce a
4825 	 * delay that could be compounded if many of these started stacking up.
4826 	 * We were easily able to create this kind of scenario when restarting
4827 	 * the slurmds over and over with message aggregation turned on.
4828 	 */
4829 	pollrc = poll(&pfd, 1, 1000);
4830 	if (pollrc == -1) {
4831 		if (errno == EINTR)
4832 			goto again;
4833 		debug("%s: poll error: %m", __func__);
4834 		(void) close(fd);
4835 		return SLURM_ERROR;
4836 	}
4837 
4838 	if (pollrc == 0) {
4839 		if (ioctl(fd, TIOCOUTQ, &value))
4840 			debug("%s: TIOCOUTQ ioctl failed", __func__);
4841 		debug("%s: poll timed out with %d outstanding: %m", __func__, value);
4842 		(void) close(fd);
4843 		return SLURM_ERROR;
4844 	}
4845 
4846 	if (pfd.revents & POLLERR) {
4847 		int err;
4848 		socklen_t errlen = sizeof(err);
4849 		int value = -1;
4850 
4851 		if (ioctl(fd, TIOCOUTQ, &value))
4852 			debug("%s: TIOCOUTQ ioctl failed", __func__);
4853 		if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen))
4854 			debug("%s: getsockopt error with %d outstanding: %m",
4855 			      __func__, value);
4856 		else
4857 			debug("%s: poll error with %d outstanding: %s",
4858 			      __func__, value, strerror(err));
4859 		(void) close(fd);
4860 		return SLURM_ERROR;
4861 	}
4862 
4863 	(void) close(fd);
4864 
4865 	return rc;
4866 }
4867 
4868 /*
4869  * Open a connection to the "address" specified in the slurm msg `req'
4870  * Then, immediately close the connection w/out waiting for a reply.
4871  * Ignore any errors. This should only be used when you do not care if
4872  * the message is ever received.
4873  */
slurm_send_msg_maybe(slurm_msg_t * req)4874 void slurm_send_msg_maybe(slurm_msg_t *req)
4875 {
4876 	int fd = -1;
4877 
4878 	if ((fd = slurm_open_msg_conn(&req->address)) < 0) {
4879 		return;
4880 	}
4881 
4882 	(void) slurm_send_node_msg(fd, req);
4883 
4884 	(void) close(fd);
4885 }
4886 
4887 /*
4888  *  Send a message to the nodelist specificed using fanout
4889  *    Then return List containing type (ret_data_info_t).
4890  * IN nodelist	  - list of nodes to send to.
4891  * IN msg	  - a slurm_msg struct to be sent by the function
4892  * IN timeout	  - how long to wait in milliseconds
4893  * RET List	  - List containing the responses of the children
4894  *		    (if any) we forwarded the message to. List
4895  *		    containing type (ret_data_info_t).
4896  */
slurm_send_recv_msgs(const char * nodelist,slurm_msg_t * msg,int timeout)4897 List slurm_send_recv_msgs(const char *nodelist, slurm_msg_t *msg, int timeout)
4898 {
4899 	List ret_list = NULL;
4900 	hostlist_t hl = NULL;
4901 
4902 	if (!nodelist || !strlen(nodelist)) {
4903 		error("slurm_send_recv_msgs: no nodelist given");
4904 		return NULL;
4905 	}
4906 
4907 	hl = hostlist_create(nodelist);
4908 	if (!hl) {
4909 		error("slurm_send_recv_msgs: problem creating hostlist");
4910 		return NULL;
4911 	}
4912 
4913 	ret_list = start_msg_tree(hl, msg, timeout);
4914 	hostlist_destroy(hl);
4915 
4916 	return ret_list;
4917 }
4918 
4919 /*
4920  *  Send a message to msg->address
4921  *    Then return List containing type (ret_data_info_t).
4922  * IN msg	  - a slurm_msg struct to be sent by the function
4923  * IN timeout	  - how long to wait in milliseconds
4924  * RET List	  - List containing the responses of the children
4925  *		    (if any) we forwarded the message to. List
4926  *		    containing type (ret_types_t).
4927  */
slurm_send_addr_recv_msgs(slurm_msg_t * msg,char * name,int timeout)4928 List slurm_send_addr_recv_msgs(slurm_msg_t *msg, char *name, int timeout)
4929 {
4930 	static pthread_mutex_t conn_lock = PTHREAD_MUTEX_INITIALIZER;
4931 	static uint16_t conn_timeout = NO_VAL16, tcp_timeout = 2;
4932 	char addrbuf[32];
4933 	List ret_list = NULL;
4934 	int fd = -1;
4935 	ret_data_info_t *ret_data_info = NULL;
4936 	ListIterator itr;
4937 	int i;
4938 
4939 	slurm_mutex_lock(&conn_lock);
4940 	if (conn_timeout == NO_VAL16) {
4941 		conn_timeout = MAX(5, slurm_get_msg_timeout() / 2);
4942 		tcp_timeout = MAX(0, slurm_get_tcp_timeout() - 1);
4943 	}
4944 	slurm_mutex_unlock(&conn_lock);
4945 	slurm_print_slurm_addr(&msg->address, addrbuf, sizeof(addrbuf));
4946 
4947 	/* This connect retry logic permits Slurm hierarchical communications
4948 	 * to better survive slurmd restarts */
4949 	for (i = 0; i <= conn_timeout; i++) {
4950 		fd = slurm_open_msg_conn(&msg->address);
4951 		if ((fd >= 0) || (errno != ECONNREFUSED && errno != ETIMEDOUT))
4952 			break;
4953 
4954 		if (errno == ETIMEDOUT) {
4955 			if (i == 0)
4956 				debug3("Timed out connecting to %s, retrying...",
4957 					addrbuf);
4958 			i += tcp_timeout;
4959 		} else {
4960 			if (i == 0)
4961 				debug3("Connection refused by %s, retrying...",
4962 				addrbuf);
4963 			sleep(1);
4964 		}
4965 	}
4966 	if (fd < 0) {
4967 		debug2("Failed to connect to %s, %m", addrbuf);
4968 		mark_as_failed_forward(&ret_list, name,
4969 				       SLURM_COMMUNICATIONS_CONNECTION_ERROR);
4970 		errno = SLURM_COMMUNICATIONS_CONNECTION_ERROR;
4971 		return ret_list;
4972 	}
4973 
4974 	msg->ret_list = NULL;
4975 	msg->forward_struct = NULL;
4976 	if (!(ret_list = _send_and_recv_msgs(fd, msg, timeout))) {
4977 		mark_as_failed_forward(&ret_list, name, errno);
4978 		errno = SLURM_COMMUNICATIONS_CONNECTION_ERROR;
4979 		return ret_list;
4980 	} else {
4981 		itr = list_iterator_create(ret_list);
4982 		while ((ret_data_info = list_next(itr)))
4983 			if (!ret_data_info->node_name) {
4984 				ret_data_info->node_name = xstrdup(name);
4985 			}
4986 		list_iterator_destroy(itr);
4987 	}
4988 	return ret_list;
4989 }
4990 
4991 /*
4992  *  Open a connection to the "address" specified in the slurm msg "req".
4993  *    Then read back an "rc" message returning the "return_code" specified
4994  *    in the response in the "rc" parameter.
4995  * IN req	- a slurm_msg struct to be sent by the function
4996  * OUT rc	- return code from the sent message
4997  * IN timeout	- how long to wait in milliseconds
4998  * RET int either 0 for success or -1 for failure.
4999  */
slurm_send_recv_rc_msg_only_one(slurm_msg_t * req,int * rc,int timeout)5000 int slurm_send_recv_rc_msg_only_one(slurm_msg_t *req, int *rc, int timeout)
5001 {
5002 	int fd = -1;
5003 	int ret_c = 0;
5004 	slurm_msg_t resp;
5005 
5006 	slurm_msg_t_init(&resp);
5007 
5008 	/* Just in case the caller didn't initialize his slurm_msg_t, and
5009 	 * since we KNOW that we are only sending to one node,
5010 	 * we initialize some forwarding variables to disable forwarding.
5011 	 */
5012 	forward_init(&req->forward);
5013 	req->ret_list = NULL;
5014 	req->forward_struct = NULL;
5015 
5016 	if ((fd = slurm_open_msg_conn(&req->address)) < 0)
5017 		return -1;
5018 	if (!_send_and_recv_msg(fd, req, &resp, timeout)) {
5019 		if (resp.auth_cred)
5020 			g_slurm_auth_destroy(resp.auth_cred);
5021 		*rc = slurm_get_return_code(resp.msg_type, resp.data);
5022 		slurm_free_msg_data(resp.msg_type, resp.data);
5023 		ret_c = 0;
5024 	} else
5025 		ret_c = -1;
5026 	return ret_c;
5027 }
5028 
5029 /*
5030  * Send message to controller and get return code.
5031  * Make use of slurm_send_recv_controller_msg(), which handles
5032  * support for backup controller and retry during transistion.
5033  * IN req - request to send
5034  * OUT rc - return code
5035  * IN comm_cluster_rec	- Communication record (host/port/version)/
5036  * RET - 0 on success, -1 on failure
5037  */
slurm_send_recv_controller_rc_msg(slurm_msg_t * req,int * rc,slurmdb_cluster_rec_t * comm_cluster_rec)5038 extern int slurm_send_recv_controller_rc_msg(slurm_msg_t *req, int *rc,
5039 					slurmdb_cluster_rec_t *comm_cluster_rec)
5040 {
5041 	int ret_c;
5042 	slurm_msg_t resp;
5043 
5044 	if (!slurm_send_recv_controller_msg(req, &resp, comm_cluster_rec)) {
5045 		*rc = slurm_get_return_code(resp.msg_type, resp.data);
5046 		slurm_free_msg_data(resp.msg_type, resp.data);
5047 		ret_c = 0;
5048 	} else {
5049 		ret_c = -1;
5050 	}
5051 
5052 	return ret_c;
5053 }
5054 
5055 /* this is used to set how many nodes are going to be on each branch
5056  * of the tree.
5057  * IN total       - total number of nodes to send to
5058  * IN tree_width  - how wide the tree should be on each hop
5059  * RET int *	  - int array tree_width in length each space
5060  *		    containing the number of nodes to send to each hop
5061  *		    on the span.
5062  */
set_span(int total,uint16_t tree_width)5063 extern int *set_span(int total,  uint16_t tree_width)
5064 {
5065 	int *span = NULL;
5066 	int left = total;
5067 	int i = 0;
5068 
5069 	if (tree_width == 0)
5070 		tree_width = slurm_get_tree_width();
5071 
5072 	span = xcalloc(tree_width, sizeof(int));
5073 	//info("span count = %d", tree_width);
5074 	if (total <= tree_width) {
5075 		return span;
5076 	}
5077 
5078 	while (left > 0) {
5079 		for (i = 0; i < tree_width; i++) {
5080 			if ((tree_width-i) >= left) {
5081 				if (span[i] == 0) {
5082 					left = 0;
5083 					break;
5084 				} else {
5085 					span[i] += left;
5086 					left = 0;
5087 					break;
5088 				}
5089 			} else if (left <= tree_width) {
5090 				if (span[i] == 0)
5091 					left--;
5092 
5093 				span[i] += left;
5094 				left = 0;
5095 				break;
5096 			}
5097 
5098 			if (span[i] == 0)
5099 				left--;
5100 
5101 			span[i] += tree_width;
5102 			left -= tree_width;
5103 		}
5104 	}
5105 
5106 	return span;
5107 }
5108 
5109 /*
5110  * Free a slurm message's memebers but not the message itself
5111  */
slurm_free_msg_members(slurm_msg_t * msg)5112 extern void slurm_free_msg_members(slurm_msg_t *msg)
5113 {
5114 	if (msg) {
5115 		if (msg->auth_cred)
5116 			(void) g_slurm_auth_destroy(msg->auth_cred);
5117 		free_buf(msg->buffer);
5118 		slurm_free_msg_data(msg->msg_type, msg->data);
5119 		FREE_NULL_LIST(msg->ret_list);
5120 	}
5121 }
5122 
5123 /*
5124  * Free a slurm message
5125  */
slurm_free_msg(slurm_msg_t * msg)5126 extern void slurm_free_msg(slurm_msg_t *msg)
5127 {
5128 	if (msg) {
5129 		slurm_free_msg_members(msg);
5130 		xfree(msg);
5131 	}
5132 }
5133 
nodelist_nth_host(const char * nodelist,int inx)5134 extern char *nodelist_nth_host(const char *nodelist, int inx)
5135 {
5136 	hostlist_t hl = hostlist_create(nodelist);
5137 	char *name = hostlist_nth(hl, inx);
5138 	hostlist_destroy(hl);
5139 	return name;
5140 }
5141 
nodelist_find(const char * nodelist,const char * name)5142 extern int nodelist_find(const char *nodelist, const char *name)
5143 {
5144 	hostlist_t hl = hostlist_create(nodelist);
5145 	int id = hostlist_find(hl, name);
5146 	hostlist_destroy(hl);
5147 	return id;
5148 }
5149 
5150 /*
5151  * Convert number from one unit to another.
5152  * By default, Will convert num to largest divisible unit.
5153  * Appends unit type suffix -- if applicable.
5154  *
5155  * IN num: number to convert.
5156  * OUT buf: buffer to copy converted number into.
5157  * IN buf_size: size of buffer.
5158  * IN orig_type: The original type of num.
5159  * IN spec_type: Type to convert num to. If specified, num will be converted up
5160  * or down to this unit type.
5161  * IN divisor: size of type
5162  * IN flags: flags to control whether to convert exactly or not at all.
5163  */
convert_num_unit2(double num,char * buf,int buf_size,int orig_type,int spec_type,int divisor,uint32_t flags)5164 extern void convert_num_unit2(double num, char *buf, int buf_size,
5165 			      int orig_type, int spec_type, int divisor,
5166 			      uint32_t flags)
5167 {
5168 	char *unit = "\0KMGTP?";
5169 	uint64_t i;
5170 
5171 	if ((int64_t)num == 0) {
5172 		snprintf(buf, buf_size, "0");
5173 		return;
5174 	}
5175 
5176 	if (spec_type != NO_VAL) {
5177 		/* spec_type overrides all flags */
5178 		if (spec_type < orig_type) {
5179 			while (spec_type < orig_type) {
5180 				num *= divisor;
5181 				orig_type--;
5182 			}
5183 		} else if (spec_type > orig_type) {
5184 			while (spec_type > orig_type) {
5185 				num /= divisor;
5186 				orig_type++;
5187 			}
5188 		}
5189 	} else if (flags & CONVERT_NUM_UNIT_RAW) {
5190 		orig_type = UNIT_NONE;
5191 	} else if (flags & CONVERT_NUM_UNIT_NO) {
5192 		/* no op */
5193 	} else if (flags & CONVERT_NUM_UNIT_EXACT) {
5194 		/* convert until we would loose precision */
5195 		/* half values  (e.g., 2.5G) are still considered precise */
5196 
5197 		while (num >= divisor
5198 		       && ((uint64_t)num % (divisor / 2) == 0)) {
5199 			num /= divisor;
5200 			orig_type++;
5201 		}
5202 	} else {
5203 		/* aggressively convert values */
5204 		while (num >= divisor) {
5205 			num /= divisor;
5206 			orig_type++;
5207 		}
5208 	}
5209 
5210 	if (orig_type < UNIT_NONE || orig_type > UNIT_PETA)
5211 		orig_type = UNIT_UNKNOWN;
5212 	i = (uint64_t)num;
5213 	/* Here we are checking to see if these numbers are the same,
5214 	 * meaning the float has not floating point.  If we do have
5215 	 * floating point print as a float.
5216 	*/
5217 	if ((double)i == num)
5218 		snprintf(buf, buf_size, "%"PRIu64"%c", i, unit[orig_type]);
5219 	else
5220 		snprintf(buf, buf_size, "%.2f%c", num, unit[orig_type]);
5221 }
5222 
convert_num_unit(double num,char * buf,int buf_size,int orig_type,int spec_type,uint32_t flags)5223 extern void convert_num_unit(double num, char *buf, int buf_size,
5224 			     int orig_type, int spec_type, uint32_t flags)
5225 {
5226 	convert_num_unit2(num, buf, buf_size, orig_type, spec_type, 1024,
5227 			  flags);
5228 }
5229 
revert_num_unit(const char * buf)5230 extern int revert_num_unit(const char *buf)
5231 {
5232 	char *unit = "\0KMGTP\0";
5233 	int i = 1, j = 0, number = 0;
5234 
5235 	if (!buf)
5236 		return -1;
5237 	j = strlen(buf) - 1;
5238 	while (unit[i]) {
5239 		if (toupper((int)buf[j]) == unit[i])
5240 			break;
5241 		i++;
5242 	}
5243 
5244 	number = atoi(buf);
5245 	if (unit[i])
5246 		number *= (i*1024);
5247 
5248 	return number;
5249 }
5250 
get_convert_unit_val(int base_unit,char convert_to)5251 extern int get_convert_unit_val(int base_unit, char convert_to)
5252 {
5253 	int conv_unit = 0, conv_value = 0;
5254 
5255 	if ((conv_unit = get_unit_type(convert_to)) == SLURM_ERROR)
5256 		return SLURM_ERROR;
5257 
5258 	while (base_unit++ < conv_unit) {
5259 		if (!conv_value)
5260 			conv_value = 1024;
5261 		else
5262 			conv_value *= 1024;
5263 	}
5264 
5265 	return conv_value;
5266 }
5267 
get_unit_type(char unit)5268 extern int get_unit_type(char unit)
5269 {
5270 	char *units = "\0KMGTP";
5271 	char *tmp_char = NULL;
5272 
5273 	if (unit == '\0') {
5274 		error("Invalid unit type '%c'. Possible options are '%s'",
5275 		      unit, units + 1);
5276 		return SLURM_ERROR;
5277 	}
5278 
5279 	tmp_char = strchr(units + 1, toupper(unit));
5280 	if (!tmp_char) {
5281 		error("Invalid unit type '%c'. Possible options are '%s'",
5282 		      unit, units + 1);
5283 		return SLURM_ERROR;
5284 	}
5285 	return tmp_char - units;
5286 }
5287 
5288 #if _DEBUG
5289 
_print_data(char * data,int len)5290 static void _print_data(char *data, int len)
5291 {
5292 	int i;
5293 	for (i = 0; i < len; i++) {
5294 		if ((i % 10 == 0) && (i != 0))
5295 			printf("\n");
5296 		printf("%2.2x ", ((int) data[i] & 0xff));
5297 		if (i >= 200)
5298 			break;
5299 	}
5300 	printf("\n\n");
5301 }
5302 
5303 #endif
5304 
5305 /*
5306  * slurm_forward_data - forward arbitrary data to unix domain sockets on nodes
5307  * IN/OUT nodelist: Nodes to forward data to (if failure this list is changed to
5308  *                  reflect the failed nodes).
5309  * IN address: address of unix domain socket
5310  * IN len: length of data
5311  * IN data: real data
5312  * RET: error code
5313  */
slurm_forward_data(char ** nodelist,char * address,uint32_t len,const char * data)5314 extern int slurm_forward_data(
5315 	char **nodelist, char *address, uint32_t len, const char *data)
5316 {
5317 	List ret_list = NULL;
5318 	int temp_rc = 0, rc = 0;
5319 	ret_data_info_t *ret_data_info = NULL;
5320 	slurm_msg_t msg;
5321 	forward_data_msg_t req;
5322 	hostlist_t hl = NULL;
5323 	bool redo_nodelist = false;
5324 	slurm_msg_t_init(&msg);
5325 
5326 	debug2("slurm_forward_data: nodelist=%s, address=%s, len=%u",
5327 	       *nodelist, address, len);
5328 	req.address = address;
5329 	req.len = len;
5330 	req.data = (char *)data;
5331 
5332 	msg.msg_type = REQUEST_FORWARD_DATA;
5333 	msg.data = &req;
5334 
5335 	if ((ret_list = slurm_send_recv_msgs(*nodelist, &msg, 0))) {
5336 		if (list_count(ret_list) > 1)
5337 			redo_nodelist = true;
5338 
5339 		while ((ret_data_info = list_pop(ret_list))) {
5340 			temp_rc = slurm_get_return_code(ret_data_info->type,
5341 							ret_data_info->data);
5342 			if (temp_rc != SLURM_SUCCESS) {
5343 				rc = temp_rc;
5344 				if (redo_nodelist) {
5345 					if (!hl)
5346 						hl = hostlist_create(
5347 							ret_data_info->
5348 							node_name);
5349 					else
5350 						hostlist_push_host(
5351 							hl, ret_data_info->
5352 							node_name);
5353 				}
5354 			}
5355 			destroy_data_info(ret_data_info);
5356 		}
5357 	} else {
5358 		error("slurm_forward_data: no list was returned");
5359 		rc = SLURM_ERROR;
5360 	}
5361 
5362 	if (hl) {
5363 		xfree(*nodelist);
5364 		hostlist_sort(hl);
5365 		*nodelist = hostlist_ranged_string_xmalloc(hl);
5366 		hostlist_destroy(hl);
5367 	}
5368 
5369 	FREE_NULL_LIST(ret_list);
5370 
5371 	return rc;
5372 }
5373 
slurm_setup_sockaddr(struct sockaddr_in * sin,uint16_t port)5374 extern void slurm_setup_sockaddr(struct sockaddr_in *sin, uint16_t port)
5375 {
5376 	static uint32_t s_addr = NO_VAL;
5377 
5378 	memset(sin, 0, sizeof(struct sockaddr_in));
5379 	sin->sin_family = AF_INET;
5380 	sin->sin_port = htons(port);
5381 
5382 	if (s_addr == NO_VAL) {
5383 		/* On systems with multiple interfaces we might not
5384 		 * want to get just any address.  This is the case on
5385 		 * a Cray system with RSIP.
5386 		 */
5387 		char *comm_params = slurm_get_comm_parameters();
5388 		char *var;
5389 
5390 		if (running_in_slurmctld())
5391 			var = "NoCtldInAddrAny";
5392 		else
5393 			var = "NoInAddrAny";
5394 
5395 		if (xstrcasestr(comm_params, var)) {
5396 			char host[MAXHOSTNAMELEN];
5397 
5398 			if (!gethostname(host, MAXHOSTNAMELEN)) {
5399 				slurm_set_addr_char(sin, port, host);
5400 				s_addr = sin->sin_addr.s_addr;
5401 			} else
5402 				fatal("slurm_setup_sockaddr: "
5403 				      "Can't get hostname or addr: %m");
5404 		} else
5405 			s_addr = htonl(INADDR_ANY);
5406 
5407 		xfree(comm_params);
5408 	}
5409 
5410 	sin->sin_addr.s_addr = s_addr;
5411 }
5412 
5413 /*
5414  * Check if we can bind() the socket s to port port.
5415  *
5416  * IN: s - socket
5417  * IN: port - port number to attempt to bind
5418  * IN: local - only bind to localhost if true
5419  * OUT: true/false if port was bound successfully
5420  */
sock_bind_range(int s,uint16_t * range,bool local)5421 int sock_bind_range(int s, uint16_t *range, bool local)
5422 {
5423 	uint32_t count;
5424 	uint32_t min;
5425 	uint32_t max;
5426 	uint32_t port;
5427 	uint32_t num;
5428 
5429 	min = range[0];
5430 	max = range[1];
5431 
5432 	srand(getpid());
5433 	num = max - min + 1;
5434 	port = min + (random() % num);
5435 	count = num;
5436 
5437 	do {
5438 		if (_is_port_ok(s, port, local))
5439 			return port;
5440 
5441 		if (port == max)
5442 			port = min;
5443 		else
5444 			++port;
5445 		--count;
5446 	} while (count > 0);
5447 
5448 	error("%s: all ports in range (%u, %u) exhausted, cannot establish listening port",
5449 	      __func__, min, max);
5450 
5451 	return -1;
5452 }
5453 
5454 /*
5455  * Check if we can bind() the socket s to port port.
5456  *
5457  * IN: s - socket
5458  * IN: port - port number to attempt to bind
5459  * IN: local - only bind to localhost if true
5460  * OUT: true/false if port was bound successfully
5461  */
_is_port_ok(int s,uint16_t port,bool local)5462 static bool _is_port_ok(int s, uint16_t port, bool local)
5463 {
5464 	struct sockaddr_in sin;
5465 
5466 	slurm_setup_sockaddr(&sin, port);
5467 
5468 	if (local)
5469 		sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
5470 
5471 	if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
5472 		debug("%s: bind() failed port %d sock %d %m",
5473 		      __func__, port, s);
5474 		return false;
5475 	}
5476 
5477 	return true;
5478 }
5479 
5480 /* slurm_get_prolog_timeout
5481  * Get prolog/epilog timeout
5482  */
slurm_get_prolog_timeout(void)5483 uint16_t slurm_get_prolog_timeout(void)
5484 {
5485 	uint16_t timeout = 0;
5486 	slurm_ctl_conf_t *conf;
5487 
5488 	if (slurmdbd_conf) {
5489 	} else {
5490 		conf = slurm_conf_lock();
5491 		timeout = conf->prolog_epilog_timeout;
5492 		slurm_conf_unlock();
5493 	}
5494 
5495 	return timeout;
5496 }
5497 
slurm_hex_to_char(int v)5498 extern int slurm_hex_to_char(int v)
5499 {
5500 	if (v >= 0 && v < 10)
5501 		return '0' + v;
5502 	else if (v >= 10 && v < 16)
5503 		return ('a' - 10) + v;
5504 	else
5505 		return -1;
5506 }
5507 
slurm_char_to_hex(int c)5508 extern int slurm_char_to_hex(int c)
5509 {
5510 	int cl;
5511 
5512 	cl = tolower(c);
5513 	if (c >= '0' && c <= '9')
5514 		return c - '0';
5515 	else if (cl >= 'a' && cl <= 'f')
5516 		return cl + (10 - 'a');
5517 	else
5518 		return -1;
5519 }
5520