s4:dsdb: add dsdb_trust_domain_by_{sid,name}()
[Samba.git] / ctdb / common / system_util.c
blobf27eed7038da23e805b80254d322574b87906acb
1 /*
2 common system utilities
4 Copyright (C) Amitay Isaacs 2014
5 Copyright (C) Martin Schwenke 2014
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "replace.h"
22 #include "system/filesys.h"
23 #include "system/shmem.h"
24 #include "system/network.h"
26 #include <talloc.h>
27 #include <libgen.h>
29 #include "lib/util/debug.h"
31 #include "protocol/protocol.h"
33 #include "common/logging.h"
34 #include "common/system.h"
36 #if HAVE_SCHED_H
37 #include <sched.h>
38 #endif
40 #if HAVE_PROCINFO_H
41 #include <procinfo.h>
42 #endif
44 #include "lib/util/mkdir_p.h"
47 if possible, make this task real time
49 bool set_scheduler(void)
51 #ifdef _AIX_
52 #if HAVE_THREAD_SETSCHED
53 struct thrdentry64 te;
54 tid64_t ti;
56 ti = 0ULL;
57 if (getthrds64(getpid(), &te, sizeof(te), &ti, 1) != 1) {
58 DEBUG(DEBUG_ERR, ("Unable to get thread information\n"));
59 return false;
62 if (thread_setsched(te.ti_tid, 0, SCHED_RR) == -1) {
63 DEBUG(DEBUG_ERR, ("Unable to set scheduler to SCHED_RR (%s)\n",
64 strerror(errno)));
65 return false;
66 } else {
67 return true;
69 #endif
70 #else /* no AIX */
71 #if HAVE_SCHED_SETSCHEDULER
72 struct sched_param p;
74 p.sched_priority = 1;
76 if (sched_setscheduler(0, SCHED_FIFO, &p) == -1) {
77 DEBUG(DEBUG_CRIT,("Unable to set scheduler to SCHED_FIFO (%s)\n",
78 strerror(errno)));
79 return false;
80 } else {
81 return true;
83 #endif
84 #endif
85 DEBUG(DEBUG_CRIT,("No way to set real-time priority.\n"));
86 return false;
90 reset scheduler from real-time to normal scheduling
92 void reset_scheduler(void)
94 #ifdef _AIX_
95 #if HAVE_THREAD_SETSCHED
96 struct thrdentry64 te;
97 tid64_t ti;
99 ti = 0ULL;
100 if (getthrds64(getpid(), &te, sizeof(te), &ti, 1) != 1) {
101 DEBUG(DEBUG_ERR, ("Unable to get thread information\n"));
103 if (thread_setsched(te.ti_tid, 0, SCHED_OTHER) == -1) {
104 DEBUG(DEBUG_ERR, ("Unable to set scheduler to SCHED_OTHER\n"));
106 #endif
107 #else /* no AIX */
108 #if HAVE_SCHED_SETSCHEDULER
109 struct sched_param p;
111 p.sched_priority = 0;
112 if (sched_setscheduler(0, SCHED_OTHER, &p) == -1) {
113 DEBUG(DEBUG_ERR, ("Unable to set scheduler to SCHED_OTHER\n"));
115 #endif
116 #endif
119 static bool parse_ipv4(const char *s, unsigned port, struct sockaddr_in *sin)
121 sin->sin_family = AF_INET;
122 sin->sin_port = htons(port);
124 if (inet_pton(AF_INET, s, &sin->sin_addr) != 1) {
125 DEBUG(DEBUG_ERR, (__location__ " Failed to translate %s into sin_addr\n", s));
126 return false;
129 #ifdef HAVE_SOCK_SIN_LEN
130 sin->sin_len = sizeof(*sin);
131 #endif
132 return true;
135 static bool parse_ipv6(const char *s, const char *ifaces, unsigned port, ctdb_sock_addr *saddr)
137 saddr->ip6.sin6_family = AF_INET6;
138 saddr->ip6.sin6_port = htons(port);
139 saddr->ip6.sin6_flowinfo = 0;
140 saddr->ip6.sin6_scope_id = 0;
142 if (inet_pton(AF_INET6, s, &saddr->ip6.sin6_addr) != 1) {
143 DEBUG(DEBUG_ERR, (__location__ " Failed to translate %s into sin6_addr\n", s));
144 return false;
147 if (ifaces && IN6_IS_ADDR_LINKLOCAL(&saddr->ip6.sin6_addr)) {
148 if (strchr(ifaces, ',')) {
149 DEBUG(DEBUG_ERR, (__location__ " Link local address %s "
150 "is specified for multiple ifaces %s\n",
151 s, ifaces));
152 return false;
154 saddr->ip6.sin6_scope_id = if_nametoindex(ifaces);
157 #ifdef HAVE_SOCK_SIN_LEN
158 saddr->ip6.sin6_len = sizeof(*saddr);
159 #endif
160 return true;
164 parse an ip
166 static bool parse_ip(const char *addr, const char *ifaces, unsigned port,
167 ctdb_sock_addr *saddr)
169 char *p;
170 bool ret;
172 ZERO_STRUCTP(saddr); /* valgrind :-) */
174 /* IPv4 or IPv6 address?
176 * Use rindex() because we need the right-most ':' below for
177 * IPv4-mapped IPv6 addresses anyway...
179 p = rindex(addr, ':');
180 if (p == NULL) {
181 ret = parse_ipv4(addr, port, &saddr->ip);
182 } else {
183 uint8_t ipv4_mapped_prefix[12] = {
184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
187 ret = parse_ipv6(addr, ifaces, port, saddr);
188 if (! ret) {
189 return ret;
193 * Check for IPv4-mapped IPv6 address
194 * (e.g. ::ffff:192.0.2.128) - reparse as IPv4 if
195 * necessary
197 if (memcmp(&saddr->ip6.sin6_addr.s6_addr[0],
198 ipv4_mapped_prefix,
199 sizeof(ipv4_mapped_prefix)) == 0) {
200 /* Reparse as IPv4 */
201 ret = parse_ipv4(p+1, port, &saddr->ip);
205 return ret;
209 parse a ip/mask pair
211 bool parse_ip_mask(const char *str, const char *ifaces, ctdb_sock_addr *addr, unsigned *mask)
213 char *p;
214 char s[64]; /* Much longer than INET6_ADDRSTRLEN */
215 char *endp = NULL;
216 ssize_t len;
217 bool ret;
219 ZERO_STRUCT(*addr);
221 len = strlen(str);
222 if (len >= sizeof(s)) {
223 DEBUG(DEBUG_ERR, ("Address %s is unreasonably long\n", str));
224 return false;
227 strncpy(s, str, len+1);
229 p = rindex(s, '/');
230 if (p == NULL) {
231 DEBUG(DEBUG_ERR, (__location__ " This addr: %s does not contain a mask\n", s));
232 return false;
235 *mask = strtoul(p+1, &endp, 10);
236 if (endp == NULL || *endp != 0) {
237 /* trailing garbage */
238 DEBUG(DEBUG_ERR, (__location__ " Trailing garbage after the mask in %s\n", s));
239 return false;
241 *p = 0;
244 /* now is this a ipv4 or ipv6 address ?*/
245 ret = parse_ip(s, ifaces, 0, addr);
247 return ret;
250 /* we don't lock future pages here; it would increase the chance that
251 * we'd fail to mmap later on. */
252 void lockdown_memory(bool valgrinding)
254 #if defined(HAVE_MLOCKALL) && !defined(_AIX_)
255 /* Extra stack, please! */
256 char dummy[10000];
257 memset(dummy, 0, sizeof(dummy));
259 if (valgrinding) {
260 return;
263 /* Ignore when running in local daemons mode */
264 if (getuid() != 0) {
265 return;
268 /* Avoid compiler optimizing out dummy. */
269 mlock(dummy, sizeof(dummy));
270 if (mlockall(MCL_CURRENT) != 0) {
271 DEBUG(DEBUG_WARNING,("Failed to lockdown memory: %s'\n",
272 strerror(errno)));
274 #endif
277 void mkdir_p_or_die(const char *dir, int mode)
279 int ret;
281 ret = mkdir_p(dir, mode);
282 if (ret != 0) {
283 DEBUG(DEBUG_ALERT,
284 ("ctdb exiting with error: "
285 "failed to create directory \"%s\" (%s)\n",
286 dir, strerror(errno)));
287 exit(1);
291 void ctdb_wait_for_process_to_exit(pid_t pid)
293 while (kill(pid, 0) == 0 || errno != ESRCH) {
294 sleep(5);