Radcli library 2.0.0
A simple radius library -- legacy API reference
Loading...
Searching...
No Matches
util.c
1/*
2 * Copyright (C) 1995,1996,1997 Lars Fenneberg
3 *
4 * Copyright 1992 Livingston Enterprises, Inc.
5 *
6 * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
7 * and Merit Network, Inc. All Rights Reserved
8 *
9 * See the file COPYRIGHT for the respective terms and conditions.
10 * If the file is missing contact me at lf@elemental.net
11 * and I'll send you a copy.
12 *
13 */
14
15#define _GNU_SOURCE
16
17#include <sys/time.h>
18
19#include <config.h>
20#include <includes.h>
21#include <radcli/radcli.h>
22#include "util.h"
23
24#define RC_BUFSIZ 1024
25
26#ifdef __linux__
27#include <sched.h>
28#define NSNET_SZ (128)
29#endif
30
31
32static char const * months[] =
33 {
34 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
35 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
36 };
37
38/*- Turns printable string into correct tm struct entries
39 *
40 * @param valstr the printable date in 'day month year' format.
41 * @param tm the output struct.
42 * @return 0 on success, -1 if the month name in valstr was not recognized
43 * (tm is left untouched in that case).
44 -*/
45int rc_str2tm (char const *valstr, struct tm *tm)
46{
47 int i;
48
49 /* Get the month */
50 for (i = 0; i < 12; i++)
51 {
52 if (strncmp (months[i], valstr, 3) == 0)
53 break;
54 }
55 if (i == 12)
56 return -1;
57 tm->tm_mon = i;
58
59 /* Get the Day */
60 tm->tm_mday = atoi (&valstr[4]);
61
62 /* Now the year */
63 tm->tm_year = atoi (&valstr[7]) - 1900;
64
65 return 0;
66}
67
68/*- Returns the current monotonic time as a double
69 *
70 * @return Get monotonic time seconds since some fixed start) expressed as
71 * double-precision floating point number.
72 -*/
73double rc_getmtime(void)
74{
75#ifdef HAVE_CLOCK_GETTIME
76 struct timespec timespec;
77
78 if (clock_gettime(CLOCK_MONOTONIC, &timespec) != 0)
79 return -1;
80
81 return timespec.tv_sec + ((double)timespec.tv_nsec) / 1000000000.0;
82#else
83 struct timeval timev;
84
85 if (gettimeofday(&timev, NULL) == -1)
86 return -1;
87
88 return timev.tv_sec + ((double)timev.tv_usec) / 1000000.0;
89#endif
90}
91
92/*
93 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
94 *
95 * Permission to use, copy, modify, and distribute this software for any
96 * purpose with or without fee is hereby granted, provided that the above
97 * copyright notice and this permission notice appear in all copies.
98 *
99 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
100 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
101 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
102 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
103 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
104 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
105 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
106 *
107 * Copyright 2006 The FreeRADIUS server project
108 */
109
110#ifdef RC_NEED_STRLCPY
111
112/*-
113 * Copy src to string dst of size siz. At most siz-1 characters
114 * will be copied. Always NUL terminates (unless siz == 0).
115 * Returns strlen(src); if retval >= siz, truncation occurred.
116 -*/
117size_t
118rc_strlcpy(char *dst, char const *src, size_t siz)
119{
120 char *d = dst;
121 char const *s = src;
122 size_t n = siz;
123
124 /* Copy as many bytes as will fit */
125 if (n != 0 && --n != 0) {
126 do {
127 if ((*d++ = *s++) == 0)
128 break;
129 } while (--n != 0);
130 }
131
132 /* Not enough room in dst, add NUL and traverse rest of src */
133 if (n == 0) {
134 if (siz != 0)
135 *d = '\0'; /* NUL-terminate dst */
136 while (*s++)
137 ;
138 }
139
140 return(s - src - 1); /* count does not include NUL */
141}
142
143#endif /* RC_NEED_STRLCPY */
144
145/*- Set the network namespace for the current thread (or process, if
146 * single-threaded).
147 *
148 * @param net_namespace the name of the namespace to switch into.
149 * @param prev_ns_handle set to a handle for the namespace active before
150 * the switch, for a later rc_reset_netns() call.
151 * @return 0 on success, -1 on failure.
152 -*/
153int rc_set_netns(const char *net_namespace, int *prev_ns_handle)
154{
155 int rc = 0;
156#ifdef __linux__
157 rc = -1;
158 static const char* crt_nsnet = "/proc/self/ns/net";
159 int sock_ns_fd = -1;
160 char sock_nsnet[NSNET_SZ];
161
162 if (NULL == net_namespace) {
163 rc_log(LOG_ERR, "Namespace not provided");
164 return rc;
165 }
166 if (NULL == prev_ns_handle) {
167 rc_log(LOG_ERR, "NULL NS handle for: %s", net_namespace);
168 return rc;
169 }
170 *prev_ns_handle = -1;
171 snprintf(sock_nsnet, NSNET_SZ, "/var/run/netns/%s", net_namespace);
172 do {
173 *prev_ns_handle = open(crt_nsnet, O_RDONLY);
174 if (*prev_ns_handle < 0) {
175 rc_log(LOG_ERR, "Cannot open %s errno=%s(%d)", crt_nsnet, strerror (errno), errno);
176 break;
177 }
178 sock_ns_fd = open(sock_nsnet, O_RDONLY);
179 if (sock_ns_fd < 0) {
180 rc_log(LOG_ERR, "Cannot open %s errno=%s(%d)", sock_nsnet, strerror (errno), errno);
181 break;
182 }
183 if (setns(sock_ns_fd, CLONE_NEWNET) < 0) {
184 rc_log(LOG_ERR, "'setns' set failed for %s errno=%s(%d)", sock_nsnet,
185 strerror(errno), errno);
186 break;
187 }
188 rc = 0;
189 }while (0);
190 if (sock_ns_fd >= 0) {
191 (void)close(sock_ns_fd);
192 }
193 if (rc != 0) {
194 if (*prev_ns_handle >=0 ) {
195 (void)close(*prev_ns_handle);
196 *prev_ns_handle = -1;
197 }
198 }
199#else
200 rc_log(LOG_ERR, "Not a Linux system. No operation performed");
201#endif
202 return rc;
203}
204
205/*- Restore the network namespace saved by rc_set_netns(); prev_ns_handle
206 * is invalid after this call.
207 *
208 * @param prev_ns_handle a handle from rc_set_netns().
209 * @return 0 on success, -1 on failure.
210 -*/
211int rc_reset_netns(int *prev_ns_handle)
212{
213 int rc = 0;
214#ifdef __linux__
215 if (NULL == prev_ns_handle) {
216 rc_log(LOG_ERR, "NULL NS handle");
217 return -1;
218 }
219 if (setns(*prev_ns_handle, CLONE_NEWNET) < 0) {
220 rc_log(LOG_ERR, "'setns' - reset failed errno=%s(%d)", strerror (errno), errno);
221 }
222 if (close(*prev_ns_handle) != 0) {
223 rc_log(LOG_ERR, "Close error fd=%d errno=%s(%d)", *prev_ns_handle, strerror (errno), errno);
224 rc = -1;
225 }
226 *prev_ns_handle = -1;
227#else
228 rc_log(LOG_ERR, "Not a Linux system. No operation performed");
229#endif
230 return rc;
231}