1 /*
2 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3 * Copyright (c) 2006-2014 Sippy Software, Inc., http://www.sippysoft.com
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <sys/sysctl.h>
32 #include <sys/resource.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <stdint.h>
36 #include <signal.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include "config.h"
42
43 #include "rtpp_log.h"
44 #include "rtpp_cfg_stable.h"
45 #include "rtpp_defines.h"
46 #include "rtpp_util.h"
47 #include "rtpp_types.h"
48 #include "rtpp_log_obj.h"
49
50 void
seedrandom(void)51 seedrandom(void)
52 {
53 int fd;
54 unsigned long junk;
55 struct timeval tv;
56
57 fd = open("/dev/urandom", O_RDONLY, 0);
58 if (fd >= 0) {
59 read(fd, &junk, sizeof(junk));
60 close(fd);
61 } else {
62 junk = 0;
63 }
64
65 gettimeofday(&tv, NULL);
66 srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
67 }
68
69 int
set_rlimits(struct cfg * cf)70 set_rlimits(struct cfg *cf)
71 {
72 struct rlimit rlp;
73
74 if (getrlimit(RLIMIT_CORE, &rlp) < 0) {
75 RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "getrlimit(RLIMIT_CORE)");
76 return (-1);
77 }
78 rlp.rlim_cur = RLIM_INFINITY;
79 rlp.rlim_max = RLIM_INFINITY;
80 if (setrlimit(RLIMIT_CORE, &rlp) < 0) {
81 RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "setrlimit(RLIMIT_CORE)");
82 return (-1);
83 }
84 return (0);
85 }
86
87 int
drop_privileges(struct cfg * cf)88 drop_privileges(struct cfg *cf)
89 {
90
91 if (cf->stable->run_gname != NULL) {
92 if (setgid(cf->stable->run_gid) != 0) {
93 RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "can't set current group ID: %d", cf->stable->run_gid);
94 return -1;
95 }
96 }
97 if (cf->stable->run_uname == NULL)
98 return 0;
99 if (setuid(cf->stable->run_uid) != 0) {
100 RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "can't set current user ID: %d", cf->stable->run_uid);
101 return -1;
102 }
103 return 0;
104 }
105
106 /*
107 * Portable strsep(3) implementation, borrowed from FreeBSD. For license
108 * and other information see:
109 *
110 * $FreeBSD: src/lib/libc/string/strsep.c,v 1.6 2007/01/09 00:28:12 imp Exp $
111 */
112 char *
rtpp_strsep(char ** stringp,const char * delim)113 rtpp_strsep(char **stringp, const char *delim)
114 {
115 char *s;
116 const char *spanp;
117 int c, sc;
118 char *tok;
119
120 if ((s = *stringp) == NULL)
121 return (NULL);
122 for (tok = s;;) {
123 c = *s++;
124 spanp = delim;
125 do {
126 if ((sc = *spanp++) == c) {
127 if (c == 0)
128 s = NULL;
129 else
130 s[-1] = 0;
131 *stringp = s;
132 return (tok);
133 }
134 } while (sc != 0);
135 }
136 /* NOTREACHED */
137 }
138
139 /*
140 * Portable daemon(3) implementation, borrowed from FreeBSD. For license
141 * and other information see:
142 *
143 * $FreeBSD: src/lib/libc/gen/daemon.c,v 1.8 2007/01/09 00:27:53 imp Exp $
144 */
145 int
rtpp_daemon(int nochdir,int noclose)146 rtpp_daemon(int nochdir, int noclose)
147 {
148 struct sigaction osa, sa;
149 int fd;
150 pid_t newgrp;
151 int oerrno;
152 int osa_ok;
153
154 /* A SIGHUP may be thrown when the parent exits below. */
155 sigemptyset(&sa.sa_mask);
156 sa.sa_handler = SIG_IGN;
157 sa.sa_flags = 0;
158 osa_ok = sigaction(SIGHUP, &sa, &osa);
159
160 switch (fork()) {
161 case -1:
162 return (-1);
163 case 0:
164 break;
165 default:
166 _exit(0);
167 }
168
169 newgrp = setsid();
170 oerrno = errno;
171 if (osa_ok != -1)
172 sigaction(SIGHUP, &osa, NULL);
173
174 if (newgrp == -1) {
175 errno = oerrno;
176 return (-1);
177 }
178
179 if (!nochdir)
180 (void)chdir("/");
181
182 if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
183 (void)dup2(fd, STDIN_FILENO);
184 #if !defined(RTPP_DEBUG)
185 (void)dup2(fd, STDOUT_FILENO);
186 (void)dup2(fd, STDERR_FILENO);
187 #endif
188 if (fd > 2)
189 (void)close(fd);
190 }
191 return (0);
192 }
193
194 static int8_t hex2char[128] = {
195 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
196 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
197 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
198 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
199 -1, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, -1, -1, -1, -1, -1, -1, -1, -1, -1,
200 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
201 -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1,
202 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
203 };
204
205 int
url_unquote(unsigned char * buf,int len)206 url_unquote(unsigned char *buf, int len)
207 {
208 int outlen;
209 uint8_t *cp;
210
211 outlen = len;
212 while (len > 0) {
213 cp = memchr(buf, '%', len);
214 if (cp == NULL)
215 return (outlen);
216 if (cp - buf + 2 > len)
217 return (-1);
218 if (cp[1] > 127 || cp[2] > 127 ||
219 hex2char[cp[1]] == -1 || hex2char[cp[2]] == -1)
220 return (-1);
221 cp[0] = (hex2char[cp[1]] << 4) | hex2char[cp[2]];
222 len -= cp - buf + 3;
223 if (len > 0)
224 memmove(cp + 1, cp + 3, len);
225 buf = cp + 1;
226 outlen -= 2;
227 }
228 return (outlen);
229 }
230
231 #if defined(_SC_CLK_TCK) && !defined(__FreeBSD__)
232 #if defined(LINUX_XXX)
233 static int
rtpp_get_sched_hz_linux(void)234 rtpp_get_sched_hz_linux(void)
235 {
236 int fd, rlen;
237 char buf[16], *cp;
238 int64_t n;
239
240 fd = open("/proc/sys/kernel/sched_min_granularity_ns", O_RDONLY, 0);
241 if (fd == -1) {
242 return (-1);
243 }
244 rlen = read(fd, buf, sizeof(buf) - 1);
245 close(fd);
246 if (rlen <= 0) {
247 return (-1);
248 }
249 buf[rlen] = '\0';
250 n = strtol(buf, &cp, 10);
251 if (cp == buf) {
252 return (-1);
253 }
254 return ((int64_t)1000000000 / n);
255 }
256 #endif
257
258 int
rtpp_get_sched_hz(void)259 rtpp_get_sched_hz(void)
260 {
261 int sched_hz;
262
263 #if defined (LINUX_XXX)
264 sched_hz = rtpp_get_sched_hz_linux();
265 if (sched_hz > 0) {
266 return (sched_hz);
267 }
268 #endif
269 sched_hz = sysconf(_SC_CLK_TCK);
270 return (sched_hz > 0 ? sched_hz : 100);
271 }
272 #else
273 int
rtpp_get_sched_hz(void)274 rtpp_get_sched_hz(void)
275 {
276 int sched_hz;
277 size_t len;
278
279 len = sizeof(sched_hz);
280 if (sysctlbyname("kern.hz", &sched_hz, &len, NULL, 0) == -1 || sched_hz <= 0)
281 return 1000;
282 return (sched_hz);
283 }
284 #endif
285
286 #ifndef HAVE_STRLCPY
287 /*
288 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
289 * All rights reserved.
290 *
291 * Redistribution and use in source and binary forms, with or without
292 * modification, are permitted provided that the following conditions
293 * are met:
294 * 1. Redistributions of source code must retain the above copyright
295 * notice, this list of conditions and the following disclaimer.
296 * 2. Redistributions in binary form must reproduce the above copyright
297 * notice, this list of conditions and the following disclaimer in the
298 * documentation and/or other materials provided with the distribution.
299 * 3. The name of the author may not be used to endorse or promote products
300 * derived from this software without specific prior written permission.
301 *
302 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
303 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
304 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
305 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
306 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
307 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
308 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
309 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
310 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
311 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
312 */
313
314 /*
315 * Copy src to string dst of size siz. At most siz-1 characters
316 * will be copied. Always NUL terminates (unless siz == 0).
317 * Returns strlen(src); if retval >= siz, truncation occurred.
318 */
strlcpy(dst,src,siz)319 size_t strlcpy(dst, src, siz)
320 char *dst;
321 const char *src;
322 size_t siz;
323 {
324 char *d = dst;
325 const char *s = src;
326 size_t n = siz;
327
328 /* Copy as many bytes as will fit */
329 if (n != 0 && --n != 0) {
330 do {
331 if ((*d++ = *s++) == 0)
332 break;
333 } while (--n != 0);
334 }
335
336 /* Not enough room in dst, add NUL and traverse rest of src */
337 if (n == 0) {
338 if (siz != 0)
339 *d = '\0'; /* NUL-terminate dst */
340 while (*s++)
341 ;
342 }
343
344 return(s - src - 1); /* count does not include NUL */
345 }
346
347 #endif /* !HAVE_STRLCPY */
348