__attribute__ ((format (printf, 1, 2)))
#endif
;
+extern bool fr_assert_cond(char const *file, int line, char const *expr, bool cond);
+#define fr_assert(_x) fr_assert_cond(__FILE__, __LINE__, #_x, (_x))
+
+extern void _fr_exit(char const *file, int line, int status);
+#define fr_exit(_x) _fr_exit(__FILE__, __LINE__, (_x))
+
+extern void _fr_exit_now(char const *file, int line, int status);
+#define fr_exit_now(_x) _fr_exit_now(__FILE__, __LINE__, (_x))
+
extern char const *fr_strerror(void);
extern int fr_dns_lookups; /* 0 = no dns lookups */
extern int fr_debug_flag; /* 0 = no debugging information */
/*
* Several handy miscellaneous functions.
*/
+void fr_debug_break(void);
char const *ip_ntoa(char *, uint32_t);
char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid);
uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid);
fr_event_t *ev;
ev = fr_heap_peek(el->times);
- if (!ev) _exit(42);
+ if (!ev) fr_exit_now(42);
gettimeofday(&el->now, NULL);
fr_fifo_t *fi;
fi = fr_fifo_create(MAX, NULL);
- if (!fi) exit(1);
+ if (!fi) fr_exit(1);
for (j = 0; j < 5; j++) {
#define SPLIT (MAX/3)
if (!fr_fifo_push(fi, &array[COUNT % MAX])) {
fprintf(stderr, "%d %d\tfailed pushing %d\n",
j, i, COUNT);
- exit(2);
+ fr_exit(2);
}
if (fr_fifo_num_elements(fi) != (i + 1)) {
fprintf(stderr, "%d %d\tgot size %d expected %d\n",
j, i, i + 1, fr_fifo_num_elements(fi));
- exit(1);
+ fr_exit(1);
}
}
if (fr_fifo_num_elements(fi) != SPLIT) {
fprintf(stderr, "HALF %d %d\n",
fr_fifo_num_elements(fi), SPLIT);
- exit(1);
+ fr_exit(1);
}
for (i = 0; i < SPLIT; i++) {
p = fr_fifo_pop(fi);
if (!p) {
fprintf(stderr, "No pop at %d\n", i);
- exit(3);
+ fr_exit(3);
}
if (*p != COUNT) {
fprintf(stderr, "%d %d\tgot %d expected %d\n",
j, i, *p, COUNT);
- exit(4);
+ fr_exit(4);
}
if (fr_fifo_num_elements(fi) != SPLIT - (i + 1)) {
fprintf(stderr, "%d %d\tgot size %d expected %d\n",
j, i, SPLIT - (i + 1), fr_fifo_num_elements(fi));
- exit(1);
+ fr_exit(1);
}
}
if (fr_fifo_num_elements(fi) != 0) {
fprintf(stderr, "ZERO %d %d\n",
fr_fifo_num_elements(fi), 0);
- exit(1);
+ fr_exit(1);
}
}
fr_fifo_free(fi);
- exit(0);
+ fr_exit(0);
}
#endif
ht = fr_hash_table_create(hash_int, NULL, NULL);
if (!ht) {
fprintf(stderr, "Hash create failed\n");
- exit(1);
+ fr_exit(1);
}
array = malloc(sizeof(int) * MAX);
- if (!array) exit(1);
+ if (!array) fr_exit(1);
for (i = 0; i < MAX; i++) {
p = array + i;
if (!fr_hash_table_insert(ht, p)) {
fprintf(stderr, "Failed insert %08x\n", i);
- exit(1);
+ fr_exit(1);
}
#ifdef TEST_INSERT
q = fr_hash_table_finddata(ht, p);
if (q != p) {
fprintf(stderr, "Bad data %d\n", i);
- exit(1);
+ fr_exit(1);
}
#endif
}
q = fr_hash_table_finddata(ht, &i);
if (!q || *q != i) {
fprintf(stderr, "Failed finding %d\n", i);
- exit(1);
+ fr_exit(1);
}
#if 0
if (!fr_hash_table_delete(ht, &i)) {
fprintf(stderr, "Failed deleting %d\n", i);
- exit(1);
+ fr_exit(1);
}
q = fr_hash_table_finddata(ht, &i);
if (q) {
fprintf(stderr, "Failed to delete %08x\n", i);
- exit(1);
+ fr_exit(1);
}
#endif
}
fr_hash_table_free(ht);
free(array);
- exit(0);
+ fr_exit(0);
}
#endif
hp = fr_heap_create(heap_cmp, 0);
if (!hp) {
fprintf(stderr, "Failed creating heap!\n");
- exit(1);
+ fr_exit(1);
}
for (i = 0; i < 1024; i++) {
array[i] = (i * 257) % 65537;
if (!fr_heap_insert(hp, &array[i])) {
fprintf(stderr, "Failed inserting %d\n", i);
- exit(1);
+ fr_exit(1);
}
}
if (!p) {
fprintf(stderr, "Failed peeking %d\n", i);
- exit(1);
+ fr_exit(1);
}
printf("%d\t%d\n", i, *p);
if (!fr_heap_extract(hp, NULL)) {
fprintf(stderr, "Failed extracting %d\n", i);
- exit(1);
+ fr_exit(1);
}
}
fprintf(stderr, "%s\n", fr_strerror());
va_end(ap);
}
+
+bool fr_assert_cond(char const *file, int line, char const *expr, bool cond)
+{
+ if (!cond) {
+ fr_perror("SOFT ASSERT FAILED %s[%u]: %s\n", file, line, expr);
+ return false;
+ }
+
+ return cond;
+}
+
+void NEVER_RETURNS _fr_exit(char const *file, int line, int status)
+{
+ fr_perror("EXIT CALLED %s[%u]: %i\n", file, line, status);
+ fflush(stderr);
+
+ fr_debug_break(); /* If running under GDB we'll break here */
+
+ exit(status);
+}
+
+void NEVER_RETURNS _fr_exit_now(char const *file, int line, int status)
+{
+ fr_perror("_EXIT CALLED %s[%u]: %i\n", file, line, status);
+ fflush(stderr);
+
+ fr_debug_break(); /* If running under GDB we'll break here */
+
+ _exit(status);
+}
#include <ctype.h>
#include <sys/file.h>
#include <fcntl.h>
+#include <signal.h>
int fr_dns_lookups = 0;
int fr_debug_flag = 0;
+
+static int fr_debugger_present = -1;
+
+/** Stub callback to see if the SIGTRAP handler is overriden
+ *
+ * @param signum signal raised.
+ */
+static void _sigtrap_handler(UNUSED int signum)
+{
+ fr_debugger_present = 0;
+ signal(SIGTRAP, SIG_DFL);
+}
+
+/** Break in GDB (if were running under GDB)
+ *
+ * If the server is running under GDB this will raise a SIGTRAP which
+ * will pause the running process.
+ *
+ * If the server is not running under GDB then this will do nothing.
+ */
+void fr_debug_break(void)
+{
+ if (fr_debugger_present == -1) {
+ fr_debugger_present = 0;
+ signal(SIGTRAP, _sigtrap_handler);
+ raise(SIGTRAP);
+ } else if (fr_debugger_present == 1) {
+ raise(SIGTRAP);
+ }
+}
+
/*
* Return an IP address in standard dot notation
*
#if 0
if (!ps->id[(request->id >> 3) & 0x1f] & (1 << (request->id & 0x07))) {
- exit(1);
+ fr_exit(1);
}
#endif
/* setup new node */
if ((X = malloc (sizeof(*X))) == NULL) {
- exit(1); /* FIXME! */
+ fr_exit(1); /* FIXME! */
}
X->Data = Data;
client_socket = socket(PF_INET, SOCK_DGRAM, 0);
if (udpfromto_init(client_socket) != 0) {
perror("udpfromto_init");
- _exit(0);
+ fr_exit_now(0);
}
/* bind client on different port */
in.sin_port = htons(port+1);
if (bind(client_socket, (struct sockaddr *)&in, sizeof(in)) < 0) {
perror("client: bind");
- _exit(0);
+ fr_exit_now(0);
}
in.sin_port = htons(port);
if (sendto(client_socket, TESTSTRING, TESTLEN, 0,
(struct sockaddr *)&in, sizeof(in)) < 0) {
perror("client: sendto");
- _exit(0);
+ fr_exit_now(0);
}
printf("client: waiting for reply from server on INADDR_ANY:%d\n", port+1);
(struct sockaddr *)&from, &fl,
(struct sockaddr *)&to, &tl)) < 0) {
perror("client: recvfromto");
- _exit(0);
+ fr_exit_now(0);
}
printf("client: received a packet of %d bytes [%s] ", n, buf);
printf(" dst ip:port %s:%d)\n",
inet_ntoa(to.sin_addr), ntohs(to.sin_port));
- _exit(0);
+ fr_exit_now(0);
}
#endif /* TESTING */
cs->section_tree = rbtree_create(section_cmp, NULL, 0);
if (!cs->section_tree) {
ERROR("Out of memory");
- _exit(1);
+ fr_exit_now(1);
}
}
if (!data->fp) {
ERROR("FATAL: Failed to re-open detail file %s: %s",
data->filename, strerror(errno));
- exit(1);
+ fr_exit(1);
}
/*
packet = rad_alloc(NULL, 1);
if (!packet) {
ERROR("FATAL: Failed allocating memory for detail");
- exit(1);
+ fr_exit(1);
}
memset(packet, 0, sizeof(*packet));
if (rcode != 0) {
ERROR("Thread create failed: %s",
strerror(rcode));
- exit(1);
+ fr_exit(1);
}
DEBUG("Thread %d for %s\n", i, buffer);
if (getresuid(&ruid, &euid, &suid) < 0) {
ERROR("Failed getting saved UID's");
- _exit(1);
+ fr_exit_now(1);
}
if (setresuid(-1, suid, -1) < 0) {
ERROR("Failed switching to privileged user");
- _exit(1);
+ fr_exit_now(1);
}
if (geteuid() != suid) {
ERROR("Switched to unknown UID");
- _exit(1);
+ fr_exit_now(1);
}
}
if (setresuid(-1, server_uid, geteuid()) < 0) {
fprintf(stderr, "%s: Failed switching to uid %s: %s\n",
progname, uid_name, strerror(errno));
- _exit(1);
+ fr_exit_now(1);
}
if (geteuid() != server_uid) {
fprintf(stderr, "%s: Failed switching uid: UID is incorrect\n",
progname);
- _exit(1);
+ fr_exit_now(1);
}
fr_set_dumpable();
if (setresuid(server_uid, server_uid, server_uid) < 0) {
ERROR("Failed in permanent switch to uid %s: %s",
uid_name, strerror(errno));
- _exit(1);
+ fr_exit_exit(1);
}
if (geteuid() != server_uid) {
ERROR("Switched to unknown uid");
- _exit(1);
+ fr_exit_now(1);
}
fr_set_dumpable();
if (setuid(server_uid) < 0) {
fprintf(stderr, "%s: Failed switching to uid %s: %s\n",
progname, uid_name, strerror(errno));
- _exit(1);
+ fr_exit(1);
}
fr_set_dumpable();
/*
* Switch users as early as possible.
*/
- if (!switch_users(cs)) exit(1);
+ if (!switch_users(cs)) fr_exit(1);
#endif
/*
if (depth >= MODCALL_STACK_MAX) {
ERROR("Internal sanity check failed: module stack is too deep");
- exit(1);
+ fr_exit(1);
}
/*
if (depth >= MODCALL_STACK_MAX) {
ERROR("Internal sanity check failed: module stack is too deep");
- exit(1);
+ fr_exit(1);
}
/*
#define INSERT_EVENT(_function, _ctx) if (!fr_event_insert(el, _function, _ctx, &((_ctx)->when), &((_ctx)->ev))) { _rad_panic(__FILE__, __LINE__, "Failed to insert event"); }
-static void NEVER_RETURNS _rad_panic(char const *file, unsigned int line,
- char const *msg)
+static void _rad_panic(char const *file, unsigned int line, char const *msg)
{
ERROR("[%s:%d] %s", file, line, msg);
#ifndef NDEBUG
rad_assert(0 == 1);
#endif
- _exit(1);
+ fr_exit(1);
}
#define rad_panic(x) _rad_panic(__FILE__, __LINE__, x)
#endif
{
rad_assert("Internal sanity check failed");
- exit(2);
+ fr_exit(2);
}
gettimeofday(&now, NULL);
buffer);
rad_panic("Socket was closed on us!");
- _exit(1);
+ fr_exit_now(1);
}
listener->recv(listener);
if (!fr_event_insert(el, event_poll_detail, this,
&when, &detail->ev)) {
ERROR("Failed creating handler");
- exit(1);
+ fr_exit(1);
}
}
#endif
if (!fr_event_fd_insert(el, 0, this->fd,
event_socket_handler, this)) {
ERROR("Failed adding event handler for socket!");
- exit(1);
+ fr_exit(1);
}
FD_MUTEX_UNLOCK(&fd_mutex);
this->fd)) {
radlog(L_ERR, "Fatal error freezing socket: %s",
fr_strerror());
- exit(1);
+ fr_exit(1);
}
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
}
if (devnull < 0) {
ERROR("FATAL failure opening /dev/null: %s",
strerror(errno));
- exit(1);
+ fr_exit(1);
}
if (dup2(devnull, this->fd) < 0) {
ERROR("FATAL failure closing socket: %s",
strerror(errno));
- exit(1);
+ fr_exit(1);
}
close(devnull);
if (!fr_packet_list_socket_del(proxy_list, this->fd)) {
ERROR("Fatal error removing socket: %s",
fr_strerror());
- exit(1);
+ fr_exit(1);
}
if (sock->home && sock->home->limit.num_connections) {
sock->home->limit.num_connections--;
if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
ERROR("FATAL: Failed to initialize proxy mutex: %s",
strerror(errno));
- exit(1);
+ fr_exit(1);
}
#endif
}
*/
if (have_children && !check_config &&
(thread_pool_init(cs, &have_children) < 0)) {
- exit(1);
+ fr_exit(1);
}
#endif
mainconfig.name);
if (listen_init(cs, &head, spawn_flag) < 0) {
fflush(NULL);
- exit(1);
+ fr_exit(1);
}
return 1;
}
if (pipe(self_pipe) < 0) {
ERROR("radiusd: Error opening internal pipe: %s",
strerror(errno));
- exit(1);
+ fr_exit(1);
}
if ((fcntl(self_pipe[0], F_SETFL, O_NONBLOCK) < 0) ||
(fcntl(self_pipe[0], F_SETFD, FD_CLOEXEC) < 0)) {
ERROR("radiusd: Error setting internal flags: %s",
strerror(errno));
- exit(1);
+ fr_exit(1);
}
if ((fcntl(self_pipe[1], F_SETFL, O_NONBLOCK) < 0) ||
(fcntl(self_pipe[1], F_SETFD, FD_CLOEXEC) < 0)) {
ERROR("radiusd: Error setting internal flags: %s",
strerror(errno));
- exit(1);
+ fr_exit(1);
}
if (!fr_event_fd_insert(el, 0, self_pipe[0],
event_signal_handler, el)) {
ERROR("Failed creating handler for signals");
- exit(1);
+ fr_exit(1);
}
#endif /* WITH_SELF_PIPE */
* uid.
*/
if (listen_init(cs, &head, spawn_flag) < 0) {
- _exit(1);
+ fr_exit_now(1);
}
mainconfig.listen = head;
request->proxy = rad_alloc(request, true);
if (!request->proxy) {
ERROR("no memory");
- exit(1);
+ fr_exit(1);
}
/*
#else
thread_pool.queue = dispatch_queue_create("org.freeradius.threads", NULL);
if (!thread_pool.queue) {
- ERROR("Failed creating dispatch queue: %s\n",
- strerror(errno));
- exit(1);
+ ERROR("Failed creating dispatch queue: %s", strerror(errno));
+ fr_exit(1);
}
#endif
if (ptr == NULL) {
ERROR("no memory");
- exit(1);
+ fr_exit(1);
}
return ptr;
if (!vp) {
ERROR("No memory!");
rad_assert("No memory" == NULL);
- _exit(1);
+ fr_exit_now(1);
}
if (vps) pairadd(vps, vp);