2 * command.c Command socket processing.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2008 The FreeRADIUS server project
21 * Copyright 2008 Alan DeKok <aland@deployingradius.com>
24 #ifdef WITH_COMMAND_SOCKET
26 #include <freeradius-devel/modpriv.h>
27 #include <freeradius-devel/conffile.h>
28 #include <freeradius-devel/stats.h>
29 #include <freeradius-devel/realms.h>
34 #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
38 #ifdef HAVE_SYS_STAT_H
50 typedef struct fr_command_table_t fr_command_table_t;
52 typedef int (*fr_command_func_t)(rad_listen_t *, int, char *argv[]);
57 struct fr_command_table_t {
59 int mode; /* read/write */
61 fr_command_func_t func;
62 fr_command_table_t *table;
65 #define COMMAND_BUFFER_SIZE (1024)
67 typedef struct fr_command_socket_t {
69 char *copy; /* <sigh> */
79 * The next few entries handle fake packets injected by
82 fr_ipaddr_t src_ipaddr; /* src_port is always 0 */
83 fr_ipaddr_t dst_ipaddr;
85 rad_listen_t *inject_listener;
86 RADCLIENT *inject_client;
89 * The next few entries do buffer management.
93 char buffer[COMMAND_BUFFER_SIZE];
94 } fr_command_socket_t;
96 static const CONF_PARSER command_config[] = {
97 { "socket", PW_TYPE_STRING_PTR,
98 offsetof(fr_command_socket_t, path), NULL, "${run_dir}/radiusd.sock"},
99 { "uid", PW_TYPE_STRING_PTR,
100 offsetof(fr_command_socket_t, uid_name), NULL, NULL},
101 { "gid", PW_TYPE_STRING_PTR,
102 offsetof(fr_command_socket_t, gid_name), NULL, NULL},
103 { "mode", PW_TYPE_STRING_PTR,
104 offsetof(fr_command_socket_t, mode_name), NULL, NULL},
106 { NULL, -1, 0, NULL, NULL } /* end the list */
109 static FR_NAME_NUMBER mode_names[] = {
111 { "read-only", FR_READ },
112 { "read-write", FR_READ | FR_WRITE },
113 { "rw", FR_READ | FR_WRITE },
118 static ssize_t cprintf(rad_listen_t *listener, const char *fmt, ...)
120 __attribute__ ((format (printf, 2, 3)))
124 #ifndef HAVE_GETPEEREID
125 static int getpeereid(int s, uid_t *euid, gid_t *egid)
131 socklen_t cl = sizeof(cr);
133 if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cl) < 0) {
140 #endif /* SO_PEERCRED */
142 #endif /* HAVE_GETPEEREID */
145 static int fr_server_domain_socket(const char *path)
150 struct sockaddr_un salocal;
154 if (len >= sizeof(salocal.sun_path)) {
155 radlog(L_ERR, "Path too long in socket filename.");
159 if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
160 radlog(L_ERR, "Failed creating socket: %s",
165 memset(&salocal, 0, sizeof(salocal));
166 salocal.sun_family = AF_UNIX;
167 memcpy(salocal.sun_path, path, len + 1); /* SUN_LEN does strlen */
169 socklen = SUN_LEN(&salocal);
174 if (stat(path, &buf) < 0) {
175 if (errno != ENOENT) {
176 radlog(L_ERR, "Failed to stat %s: %s",
177 path, strerror(errno));
182 * FIXME: Check the enclosing directory?
184 } else { /* it exists */
185 if (!S_ISREG(buf.st_mode)
187 && !S_ISSOCK(buf.st_mode)
190 radlog(L_ERR, "Cannot turn %s into socket", path);
195 * Refuse to open sockets not owned by us.
197 if (buf.st_uid != geteuid()) {
198 radlog(L_ERR, "We do not own %s", path);
202 if (unlink(path) < 0) {
203 radlog(L_ERR, "Failed to delete %s: %s",
204 path, strerror(errno));
209 if (bind(sockfd, (struct sockaddr *)&salocal, socklen) < 0) {
210 radlog(L_ERR, "Failed binding to %s: %s",
211 path, strerror(errno));
217 * FIXME: There's a race condition here. But Linux
218 * doesn't seem to permit fchmod on domain sockets.
220 if (chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0) {
221 radlog(L_ERR, "Failed setting permissions on %s: %s",
222 path, strerror(errno));
227 if (listen(sockfd, 8) < 0) {
228 radlog(L_ERR, "Failed listening to %s: %s",
229 path, strerror(errno));
238 if ((flags = fcntl(sockfd, F_GETFL, NULL)) < 0) {
239 radlog(L_ERR, "Failure getting socket flags: %s",
246 if( fcntl(sockfd, F_SETFL, flags) < 0) {
247 radlog(L_ERR, "Failure setting socket flags: %s",
259 static void command_close_socket(rad_listen_t *this)
261 this->status = RAD_LISTEN_STATUS_CLOSED;
264 * This removes the socket from the event fd, so no one
265 * will be calling us any more.
273 static ssize_t cprintf(rad_listen_t *listener, const char *fmt, ...)
280 len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
283 if (listener->status == RAD_LISTEN_STATUS_CLOSED) return 0;
285 len = write(listener->fd, buffer, len);
286 if (len <= 0) command_close_socket(listener);
289 * FIXME: Keep writing until done?
294 static int command_hup(rad_listen_t *listener, int argc, char *argv[])
297 module_instance_t *mi;
300 radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
304 cs = cf_section_find("modules");
307 mi = find_module_instance(cs, argv[0], 0);
309 cprintf(listener, "ERROR: No such module \"%s\"\n", argv[0]);
313 if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) {
314 cprintf(listener, "ERROR: Module %s cannot be hup'd\n",
319 if (!module_hup_module(mi->cs, mi, time(NULL))) {
320 cprintf(listener, "ERROR: Failed to reload module\n");
324 return 1; /* success */
327 static int command_terminate(UNUSED rad_listen_t *listener,
328 UNUSED int argc, UNUSED char *argv[])
330 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
332 return 1; /* success */
335 extern time_t fr_start_time;
337 static int command_uptime(rad_listen_t *listener,
338 UNUSED int argc, UNUSED char *argv[])
342 CTIME_R(&fr_start_time, buffer, sizeof(buffer));
343 cprintf(listener, "Up since %s", buffer); /* no \r\n */
345 return 1; /* success */
348 static const char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
351 * FIXME: Recurse && indent?
353 static void cprint_conf_parser(rad_listen_t *listener, int indent, CONF_SECTION *cs,
359 const char *name1 = cf_section_name1(cs);
360 const char *name2 = cf_section_name2(cs);
361 const CONF_PARSER *variables = cf_section_parse_table(cs);
365 cprintf(listener, "%.*s%s %s {\n", indent, tabs, name1, name2);
367 cprintf(listener, "%.*s%s {\n", indent, tabs, name1);
375 if (variables) for (i = 0; variables[i].name != NULL; i++) {
377 * No base struct offset, data must be the pointer.
378 * If data doesn't exist, ignore the entry, there
379 * must be something wrong.
382 if (!variables[i].data) {
386 data = variables[i].data;;
388 } else if (variables[i].data) {
389 data = variables[i].data;;
392 data = (((const char *)base) + variables[i].offset);
395 switch (variables[i].type) {
397 cprintf(listener, "%.*s%s = ?\n", indent, tabs,
401 case PW_TYPE_INTEGER:
402 cprintf(listener, "%.*s%s = %u\n", indent, tabs,
403 variables[i].name, *(const int *) data);
407 inet_ntop(AF_INET, data, buffer, sizeof(buffer));
410 case PW_TYPE_IPV6ADDR:
411 inet_ntop(AF_INET6, data, buffer, sizeof(buffer));
414 case PW_TYPE_BOOLEAN:
415 cprintf(listener, "%.*s%s = %s\n", indent, tabs,
417 ((*(const int *) data) == 0) ? "no" : "yes");
420 case PW_TYPE_STRING_PTR:
421 case PW_TYPE_FILENAME:
423 * FIXME: Escape things in the string!
425 if (*(const char * const *) data) {
426 cprintf(listener, "%.*s%s = \"%s\"\n", indent, tabs,
427 variables[i].name, *(const char * const *) data);
429 cprintf(listener, "%.*s%s = \n", indent, tabs,
439 cprintf(listener, "%.*s}\n", indent, tabs);
442 static int command_show_module_config(rad_listen_t *listener, int argc, char *argv[])
445 module_instance_t *mi;
448 cprintf(listener, "ERROR: No module name was given\n");
452 cs = cf_section_find("modules");
455 mi = find_module_instance(cs, argv[0], 0);
457 cprintf(listener, "ERROR: No such module \"%s\"\n", argv[0]);
461 cprint_conf_parser(listener, 0, mi->cs, mi->insthandle);
463 return 1; /* success */
466 static const char *method_names[RLM_COMPONENT_COUNT] = {
478 static int command_show_module_methods(rad_listen_t *listener, int argc, char *argv[])
482 const module_instance_t *mi;
486 cprintf(listener, "ERROR: No module name was given\n");
490 cs = cf_section_find("modules");
493 mi = find_module_instance(cs, argv[0], 0);
495 cprintf(listener, "ERROR: No such module \"%s\"\n", argv[0]);
499 mod = mi->entry->module;
501 for (i = 0; i < RLM_COMPONENT_COUNT; i++) {
502 if (mod->methods[i]) cprintf(listener, "\t%s\n", method_names[i]);
505 return 1; /* success */
509 static int command_show_module_flags(rad_listen_t *listener, int argc, char *argv[])
512 const module_instance_t *mi;
516 cprintf(listener, "ERROR: No module name was given\n");
520 cs = cf_section_find("modules");
523 mi = find_module_instance(cs, argv[0], 0);
525 cprintf(listener, "ERROR: No such module \"%s\"\n", argv[0]);
529 mod = mi->entry->module;
531 if ((mod->type & RLM_TYPE_THREAD_SAFE) != 0)
532 cprintf(listener, "\tthread-safe\n");
535 if ((mod->type & RLM_TYPE_CHECK_CONFIG_SAFE) != 0)
536 cprintf(listener, "\twill-check-config\n");
539 if ((mod->type & RLM_TYPE_HUP_SAFE) != 0)
540 cprintf(listener, "\treload-on-hup\n");
542 return 1; /* success */
547 * Show all loaded modules
549 static int command_show_modules(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
551 CONF_SECTION *cs, *subcs;
553 cs = cf_section_find("modules");
557 while ((subcs = cf_subsection_find_next(cs, subcs, NULL)) != NULL) {
558 const char *name1 = cf_section_name1(subcs);
559 const char *name2 = cf_section_name2(subcs);
561 module_instance_t *mi;
564 mi = find_module_instance(cs, name2, 0);
567 cprintf(listener, "\t%s (%s)\n", name2, name1);
569 mi = find_module_instance(cs, name1, 0);
572 cprintf(listener, "\t%s\n", name1);
576 return 1; /* success */
580 static int command_show_home_servers(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
584 const char *type, *state;
588 for (i = 0; i < 256; i++) {
589 home = home_server_bynumber(i);
593 * Internal "virtual" home server.
595 if (home->ipaddr.af == AF_UNSPEC) continue;
597 if (home->type == HOME_TYPE_AUTH) {
600 } else if (home->type == HOME_TYPE_ACCT) {
605 if (home->state == HOME_STATE_ALIVE) {
608 } else if (home->state == HOME_STATE_ZOMBIE) {
611 } else if (home->state == HOME_STATE_IS_DEAD) {
616 cprintf(listener, "%s\t%d\t%s\t%s\t%d\n",
617 ip_ntoh(&home->ipaddr, buffer, sizeof(buffer)),
618 home->port, type, state,
619 home->currently_outstanding);
626 static int command_show_clients(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
632 for (i = 0; i < 256; i++) {
633 client = client_findbynumber(NULL, i);
636 ip_ntoh(&client->ipaddr, buffer, sizeof(buffer));
638 if (((client->ipaddr.af == AF_INET) &&
639 (client->prefix != 32)) ||
640 ((client->ipaddr.af == AF_INET6) &&
641 (client->prefix != 128))) {
642 cprintf(listener, "\t%s/%d\n", buffer, client->prefix);
644 cprintf(listener, "\t%s\n", buffer);
652 static int command_show_xml(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
655 FILE *fp = fdopen(dup(listener->fd), "a");
658 cprintf(listener, "ERROR: Can't dup %s\n", strerror(errno));
663 cprintf(listener, "ERROR: <reference> is required\n");
667 ci = cf_reference_item(mainconfig.config, mainconfig.config, argv[0]);
669 cprintf(listener, "ERROR: No such item <reference>\n");
673 if (cf_item_is_section(ci)) {
674 cf_section2xml(fp, cf_itemtosection(ci));
676 } else if (cf_item_is_pair(ci)) {
677 cf_pair2xml(fp, cf_itemtopair(ci));
680 cprintf(listener, "ERROR: No such item <reference>\n");
687 return 1; /* success */
690 static int command_show_version(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
692 cprintf(listener, "%s\n", radiusd_version);
696 static int command_debug_level(rad_listen_t *listener, int argc, char *argv[])
701 cprintf(listener, "ERROR: Must specify <number>\n");
705 number = atoi(argv[0]);
706 if ((number < 0) || (number > 4)) {
707 cprintf(listener, "ERROR: <number> must be between 0 and 4\n");
711 fr_debug_flag = debug_flag = number;
716 char *debug_log_file = NULL;
717 static char debug_log_file_buffer[1024];
719 static int command_debug_file(rad_listen_t *listener, int argc, char *argv[])
721 if (debug_flag && mainconfig.radlog_dest == RADLOG_STDOUT) {
722 cprintf(listener, "ERROR: Cannot redirect debug logs to a file when already in debugging mode.\n");
726 if ((argc > 0) && (strchr(argv[0], FR_DIR_SEP) != NULL)) {
727 cprintf(listener, "ERROR: Cannot direct debug logs to absolute path.\n");
730 debug_log_file = NULL;
732 if (argc == 0) return 0;
735 * This looks weird, but it's here to avoid locking
736 * a mutex for every log message.
738 memset(debug_log_file_buffer, 0, sizeof(debug_log_file_buffer));
741 * Debug files always go to the logging directory.
743 snprintf(debug_log_file_buffer, sizeof(debug_log_file_buffer),
744 "%s/%s", radlog_dir, argv[0]);
746 debug_log_file = &debug_log_file_buffer[0];
751 extern char *debug_condition;
752 static int command_debug_condition(UNUSED rad_listen_t *listener, int argc, char *argv[])
755 * Delete old condition.
757 * This is thread-safe because the condition is evaluated
758 * in the main server thread, as is this code.
760 free(debug_condition);
761 debug_condition = NULL;
770 debug_condition = strdup(argv[0]);
775 static int command_show_debug_condition(rad_listen_t *listener,
776 UNUSED int argc, UNUSED char *argv[])
778 if (!debug_condition) return 0;
780 cprintf(listener, "%s\n", debug_condition);
785 static int command_show_debug_file(rad_listen_t *listener,
786 UNUSED int argc, UNUSED char *argv[])
788 if (!debug_log_file) return 0;
790 cprintf(listener, "%s\n", debug_log_file);
795 static int command_show_debug_level(rad_listen_t *listener,
796 UNUSED int argc, UNUSED char *argv[])
798 cprintf(listener, "%d\n", debug_flag);
803 static RADCLIENT *get_client(rad_listen_t *listener, int argc, char *argv[])
809 cprintf(listener, "ERROR: Must specify <ipaddr>\n");
813 if (ip_hton(argv[0], AF_UNSPEC, &ipaddr) < 0) {
814 cprintf(listener, "ERROR: Failed parsing IP address; %s\n",
819 client = client_find(NULL, &ipaddr);
821 cprintf(listener, "ERROR: No such client\n");
829 static int command_show_client_config(rad_listen_t *listener, int argc, char *argv[])
834 client = get_client(listener, argc, argv);
839 if (!client->cs) return 1;
841 fp = fdopen(dup(listener->fd), "a");
843 cprintf(listener, "ERROR: Can't dup %s\n", strerror(errno));
847 cf_section2file(fp, client->cs);
854 static home_server *get_home_server(rad_listen_t *listener, int argc, char *argv[])
861 cprintf(listener, "ERROR: Must specify <ipaddr> <port>\n");
865 if (ip_hton(argv[0], AF_UNSPEC, &ipaddr) < 0) {
866 cprintf(listener, "ERROR: Failed parsing IP address; %s\n",
871 port = atoi(argv[1]);
873 home = home_server_find(&ipaddr, port);
875 cprintf(listener, "ERROR: No such home server\n");
882 static int command_show_home_server_config(rad_listen_t *listener, int argc, char *argv[])
887 home = get_home_server(listener, argc, argv);
892 if (!home->cs) return 1;
894 fp = fdopen(dup(listener->fd), "a");
896 cprintf(listener, "ERROR: Can't dup %s\n", strerror(errno));
900 cf_section2file(fp, home->cs);
906 extern void revive_home_server(void *ctx);
907 extern void mark_home_server_dead(home_server *home, struct timeval *when);
909 static int command_set_home_server_state(rad_listen_t *listener, int argc, char *argv[])
914 cprintf(listener, "ERROR: Must specify <ipaddr> <port> <state>\n");
918 home = get_home_server(listener, argc, argv);
923 if (strcmp(argv[2], "alive") == 0) {
924 revive_home_server(home);
926 } else if (strcmp(argv[2], "dead") == 0) {
929 gettimeofday(&now, NULL); /* we do this WAY too ofetn */
930 mark_home_server_dead(home, &now);
933 cprintf(listener, "ERROR: Unknown state \"%s\"\n", argv[2]);
940 static int command_show_home_server_state(rad_listen_t *listener, int argc, char *argv[])
944 home = get_home_server(listener, argc, argv);
949 switch (home->state) {
950 case HOME_STATE_ALIVE:
951 cprintf(listener, "alive\n");
954 case HOME_STATE_IS_DEAD:
955 cprintf(listener, "dead\n");
958 case HOME_STATE_ZOMBIE:
959 cprintf(listener, "zombie\n");
963 cprintf(listener, "unknown\n");
972 * For encode/decode stuff
974 static int null_socket_dencode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
979 static int null_socket_send(UNUSED rad_listen_t *listener, REQUEST *request)
985 output_file = request_data_reference(request, null_socket_send, 0);
987 radlog(L_ERR, "WARNING: No output file for injected packet %d",
992 fp = fopen(output_file, "w");
994 radlog(L_ERR, "Failed to send injected file to %s: %s",
995 output_file, strerror(errno));
999 if (request->reply->code != 0) {
1000 const char *what = "reply";
1003 if (request->reply->code < FR_MAX_PACKET_CODE) {
1004 what = fr_packet_codes[request->reply->code];
1007 fprintf(fp, "%s\n", what);
1010 request->radlog(L_DBG, 0, request,
1011 "Injected %s packet to host %s port 0 code=%d, id=%d",
1013 inet_ntop(request->reply->src_ipaddr.af,
1014 &request->reply->src_ipaddr.ipaddr,
1015 buffer, sizeof(buffer)),
1016 request->reply->code, request->reply->id);
1019 for (vp = request->reply->vps; vp != NULL; vp = vp->next) {
1020 vp_prints(buffer, sizeof(buffer), vp);
1021 fprintf(fp, "%s\n", buffer);
1023 request->radlog(L_DBG, 0, request, "\t%s",
1033 static int command_inject_to(rad_listen_t *listener, int argc, char *argv[])
1036 RAD_LISTEN_TYPE type;
1037 fr_command_socket_t *sock = listener->data;
1039 rad_listen_t *found = NULL;
1042 cprintf(listener, "ERROR: Must specify [auth/acct]\n");
1046 if (strcmp(argv[0], "auth") == 0) {
1047 type = RAD_LISTEN_AUTH;
1049 } else if (strcmp(argv[0], "acct") == 0) {
1050 #ifdef WITH_ACCOUNTING
1051 type = RAD_LISTEN_ACCT;
1053 cprintf(listener, "ERROR: This server was built without accounting support.\n");
1058 cprintf(listener, "ERROR: Unknown socket type\n");
1063 cprintf(listener, "ERROR: No <ipaddr> <port> was given\n");
1068 * FIXME: Look for optional arg 4, and bind interface.
1071 if (ip_hton(argv[1], AF_UNSPEC, &ipaddr) < 0) {
1072 cprintf(listener, "ERROR: Failed parsing IP address; %s\n",
1076 port = atoi(argv[2]);
1078 found = listener_find_byipaddr(&ipaddr, port);
1080 cprintf(listener, "ERROR: Could not find matching listener\n");
1084 sock->inject_listener = found;
1085 sock->dst_ipaddr = ipaddr;
1086 sock->dst_port = port;
1091 static int command_inject_from(rad_listen_t *listener, int argc, char *argv[])
1094 fr_command_socket_t *sock = listener->data;
1097 cprintf(listener, "ERROR: No <ipaddr> was given\n");
1101 if (!sock->inject_listener) {
1102 cprintf(listener, "ERROR: You must specify \"inject to\" before using \"inject from\"\n");
1106 sock->src_ipaddr.af = AF_UNSPEC;
1107 if (ip_hton(argv[0], AF_UNSPEC, &sock->src_ipaddr) < 0) {
1108 cprintf(listener, "ERROR: Failed parsing IP address; %s\n",
1113 client = client_listener_find(sock->inject_listener, &sock->src_ipaddr,
1116 cprintf(listener, "ERROR: No such client %s\n", argv[0]);
1119 sock->inject_client = client;
1124 static int command_inject_file(rad_listen_t *listener, int argc, char *argv[])
1126 static int inject_id = 0;
1128 fr_command_socket_t *sock = listener->data;
1130 REQUEST *request = NULL;
1131 RADIUS_PACKET *packet;
1134 RAD_REQUEST_FUNP fun = NULL;
1138 cprintf(listener, "ERROR: You must specify <input-file> <output-file>\n");
1143 * Output files always go to the logging directory.
1145 snprintf(buffer, sizeof(buffer), "%s/%s", radlog_dir, argv[1]);
1147 fp = fopen(argv[0], "r");
1149 cprintf(listener, "ERROR: Failed opening %s: %s\n",
1150 argv[0], strerror(errno));
1154 vp = readvp2(fp, &filedone, "");
1157 cprintf(listener, "ERROR: Failed reading attributes from %s: %s\n",
1158 argv[0], fr_strerror());
1162 fake = rad_malloc(sizeof(*fake));
1163 memcpy(fake, sock->inject_listener, sizeof(*fake));
1166 * Re-write the IO for the listener.
1168 fake->encode = null_socket_dencode;
1169 fake->decode = null_socket_dencode;
1170 fake->send = null_socket_send;
1172 packet = rad_alloc(0);
1173 packet->src_ipaddr = sock->src_ipaddr;
1174 packet->src_port = 0;
1176 packet->dst_ipaddr = sock->dst_ipaddr;
1177 packet->dst_port = sock->dst_port;
1179 packet->id = inject_id++;
1181 if (fake->type == RAD_LISTEN_AUTH) {
1182 packet->code = PW_AUTHENTICATION_REQUEST;
1183 fun = rad_authenticate;
1186 #ifdef WITH_ACCOUNTING
1187 packet->code = PW_ACCOUNTING_REQUEST;
1188 fun = rad_accounting;
1190 cprintf(listener, "ERROR: This server was built without accounting support.\n");
1197 if (!received_request(fake, packet, &request, sock->inject_client)) {
1198 cprintf(listener, "ERROR: Failed to inject request. See log file for details\n");
1205 * Remember what the output file is, and remember to
1206 * delete the fake listener when done.
1208 request_data_add(request, null_socket_send, 0, strdup(buffer), free);
1209 request_data_add(request, null_socket_send, 1, fake, free);
1212 request->radlog(L_DBG, 0, request,
1213 "Injected %s packet from host %s port 0 code=%d, id=%d",
1214 fr_packet_codes[packet->code],
1215 inet_ntop(packet->src_ipaddr.af,
1216 &packet->src_ipaddr.ipaddr,
1217 buffer, sizeof(buffer)),
1218 packet->code, packet->id);
1220 for (vp = packet->vps; vp != NULL; vp = vp->next) {
1221 vp_prints(buffer, sizeof(buffer), vp);
1222 request->radlog(L_DBG, 0, request, "\t%s", buffer);
1227 * And go process it.
1229 thread_pool_addrequest(request, fun);
1235 static fr_command_table_t command_table_inject[] = {
1237 "inject to <ipaddr> <port> - Inject packets to the destination IP and port.",
1238 command_inject_to, NULL },
1241 "inject from <ipaddr> - Inject packets as if they came from <ipaddr>",
1242 command_inject_from, NULL },
1245 "inject file <input-file> <output-file> - Inject packet from input-file>, with results sent to <output-file>",
1246 command_inject_file, NULL },
1248 { NULL, 0, NULL, NULL, NULL }
1251 static fr_command_table_t command_table_debug[] = {
1252 { "condition", FR_WRITE,
1253 "debug condition [condition] - Enable debugging for requests matching [condition]",
1254 command_debug_condition, NULL },
1256 { "level", FR_WRITE,
1257 "debug level <number> - Set debug level to <number>. Higher is more debugging.",
1258 command_debug_level, NULL },
1261 "debug file [filename] - Send all debugging output to [filename]",
1262 command_debug_file, NULL },
1264 { NULL, 0, NULL, NULL, NULL }
1267 static fr_command_table_t command_table_show_debug[] = {
1268 { "condition", FR_READ,
1269 "show debug condition - Shows current debugging condition.",
1270 command_show_debug_condition, NULL },
1273 "show debug level - Shows current debugging level.",
1274 command_show_debug_level, NULL },
1277 "show debug file - Shows current debugging file.",
1278 command_show_debug_file, NULL },
1280 { NULL, 0, NULL, NULL, NULL }
1283 static fr_command_table_t command_table_show_module[] = {
1284 { "config", FR_READ,
1285 "show module config <module> - show configuration for given module",
1286 command_show_module_config, NULL },
1288 "show module flags <module> - show other module properties",
1289 command_show_module_flags, NULL },
1291 "show module list - shows list of loaded modules",
1292 command_show_modules, NULL },
1293 { "methods", FR_READ,
1294 "show module methods <module> - show sections where <module> may be used",
1295 command_show_module_methods, NULL },
1297 { NULL, 0, NULL, NULL, NULL }
1300 static fr_command_table_t command_table_show_client[] = {
1301 { "config", FR_READ,
1302 "show client config <ipaddr> - show configuration for given client",
1303 command_show_client_config, NULL },
1305 "show client list - shows list of global clients",
1306 command_show_clients, NULL },
1308 { NULL, 0, NULL, NULL, NULL }
1312 static fr_command_table_t command_table_show_home[] = {
1313 { "config", FR_READ,
1314 "show home_server config <ipaddr> <port> - show configuration for given home server",
1315 command_show_home_server_config, NULL },
1317 "show home_server list - shows list of home servers",
1318 command_show_home_servers, NULL },
1320 "show home_server state <ipaddr> <port> - shows state of given home server",
1321 command_show_home_server_state, NULL },
1323 { NULL, 0, NULL, NULL, NULL }
1328 static fr_command_table_t command_table_show[] = {
1329 { "client", FR_READ,
1330 "show client <command> - do sub-command of client",
1331 NULL, command_table_show_client },
1333 "show debug <command> - show debug properties",
1334 NULL, command_table_show_debug },
1336 { "home_server", FR_READ,
1337 "show home_server <command> - do sub-command of home_server",
1338 NULL, command_table_show_home },
1340 { "module", FR_READ,
1341 "show module <command> - do sub-command of module",
1342 NULL, command_table_show_module },
1343 { "uptime", FR_READ,
1344 "show uptime - shows time at which server started",
1345 command_uptime, NULL },
1346 { "version", FR_READ,
1347 "show version - Prints version of the running server",
1348 command_show_version, NULL },
1350 "show xml <reference> - Prints out configuration as XML",
1351 command_show_xml, NULL },
1352 { NULL, 0, NULL, NULL, NULL }
1356 static int command_set_module_config(rad_listen_t *listener, int argc, char *argv[])
1361 module_instance_t *mi;
1362 const CONF_PARSER *variables;
1366 cprintf(listener, "ERROR: No module name or variable was given\n");
1370 cs = cf_section_find("modules");
1373 mi = find_module_instance(cs, argv[0], 0);
1375 cprintf(listener, "ERROR: No such module \"%s\"\n", argv[0]);
1379 if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) {
1380 cprintf(listener, "ERROR: Cannot change configuration of module as it is cannot be HUP'd.\n");
1384 variables = cf_section_parse_table(mi->cs);
1386 cprintf(listener, "ERROR: Cannot find configuration for module\n");
1391 for (i = 0; variables[i].name != NULL; i++) {
1393 * FIXME: Recurse into sub-types somehow...
1395 if (variables[i].type == PW_TYPE_SUBSECTION) continue;
1397 if (strcmp(variables[i].name, argv[1]) == 0) {
1404 cprintf(listener, "ERROR: No such variable \"%s\"\n", argv[1]);
1408 i = rcode; /* just to be safe */
1411 * It's not part of the dynamic configuration. The module
1412 * needs to re-parse && validate things.
1414 if (variables[i].data) {
1415 cprintf(listener, "ERROR: Variable cannot be dynamically updated\n");
1419 data = ((char *) mi->insthandle) + variables[i].offset;
1421 cp = cf_pair_find(mi->cs, argv[1]);
1425 * Replace the OLD value in the configuration file with
1428 * FIXME: Parse argv[2] depending on it's data type!
1429 * If it's a string, look for leading single/double quotes,
1430 * end then call tokenize functions???
1432 cf_pair_replace(mi->cs, cp, argv[2]);
1434 rcode = cf_item_parse(mi->cs, argv[1], variables[i].type,
1437 cprintf(listener, "ERROR: Failed to parse value\n");
1441 return 1; /* success */
1444 static int command_set_module_status(rad_listen_t *listener, int argc, char *argv[])
1447 module_instance_t *mi;
1450 cprintf(listener, "ERROR: No module name or status was given\n");
1454 cs = cf_section_find("modules");
1457 mi = find_module_instance(cs, argv[0], 0);
1459 cprintf(listener, "ERROR: No such module \"%s\"\n", argv[0]);
1464 if (strcmp(argv[1], "alive") == 0) {
1467 } else if (strcmp(argv[1], "dead") == 0) {
1471 cprintf(listener, "ERROR: Unknown status \"%s\"\n", argv[2]);
1475 return 1; /* success */
1478 static int command_print_stats(rad_listen_t *listener, fr_stats_t *stats,
1481 cprintf(listener, "\trequests\t%u\n", stats->total_requests);
1482 cprintf(listener, "\tresponses\t%u\n", stats->total_responses);
1485 cprintf(listener, "\taccepts\t\t%u\n",
1486 stats->total_access_accepts);
1487 cprintf(listener, "\trejects\t\t%u\n",
1488 stats->total_access_rejects);
1489 cprintf(listener, "\tchallenges\t%u\n",
1490 stats->total_access_challenges);
1493 cprintf(listener, "\tdup\t\t%u\n", stats->total_dup_requests);
1494 cprintf(listener, "\tinvalid\t\t%u\n", stats->total_invalid_requests);
1495 cprintf(listener, "\tmalformed\t%u\n", stats->total_malformed_requests);
1496 cprintf(listener, "\tbad_signature\t%u\n", stats->total_bad_authenticators);
1497 cprintf(listener, "\tdropped\t\t%u\n", stats->total_packets_dropped);
1498 cprintf(listener, "\tunknown_types\t%u\n", stats->total_unknown_types);
1505 static FR_NAME_NUMBER state_names[] = {
1506 { "unopened", STATE_UNOPENED },
1507 { "unlocked", STATE_UNLOCKED },
1508 { "header", STATE_HEADER },
1509 { "reading", STATE_READING },
1510 { "queued", STATE_QUEUED },
1511 { "running", STATE_RUNNING },
1512 { "no-reply", STATE_NO_REPLY },
1513 { "replied", STATE_REPLIED },
1518 static int command_stats_detail(rad_listen_t *listener, int argc, char *argv[])
1521 listen_detail_t *data;
1525 cprintf(listener, "ERROR: Must specify <filename>\n");
1530 for (this = mainconfig.listen; this != NULL; this = this->next) {
1531 if (this->type != RAD_LISTEN_DETAIL) continue;
1534 if (strcmp(argv[1], data->filename) != 0) continue;
1539 cprintf(listener, "\tstate\t%s\n",
1540 fr_int2str(state_names, data->state, "?"));
1542 if ((data->state == STATE_UNOPENED) ||
1543 (data->state == STATE_UNLOCKED)) {
1548 * Race conditions: file might not exist.
1550 if (stat(data->filename_work, &buf) < 0) {
1551 cprintf(listener, "packets\t0\n");
1552 cprintf(listener, "tries\t0\n");
1553 cprintf(listener, "offset\t0\n");
1554 cprintf(listener, "size\t0\n");
1558 cprintf(listener, "packets\t%d\n", data->packets);
1559 cprintf(listener, "tries\t%d\n", data->tries);
1560 cprintf(listener, "offset\t%u\n", (unsigned int) data->offset);
1561 cprintf(listener, "size\t%u\n", (unsigned int) buf.st_size);
1568 static int command_stats_home_server(rad_listen_t *listener, int argc, char *argv[])
1573 cprintf(listener, "ERROR: Must specify [auth/acct] OR <ipaddr> <port>\n");
1578 #ifdef WITH_ACCOUNTING
1579 if (strcmp(argv[0], "acct") == 0) {
1580 return command_print_stats(listener,
1581 &proxy_acct_stats, 0);
1584 if (strcmp(argv[0], "auth") == 0) {
1585 return command_print_stats(listener,
1586 &proxy_auth_stats, 1);
1589 cprintf(listener, "ERROR: Should specify [auth/acct]\n");
1593 home = get_home_server(listener, argc, argv);
1598 command_print_stats(listener, &home->stats,
1599 (home->type == HOME_TYPE_AUTH));
1600 cprintf(listener, "\toutstanding\t%d\n", home->currently_outstanding);
1605 static int command_stats_client(rad_listen_t *listener, int argc, char *argv[])
1611 cprintf(listener, "ERROR: Must specify [auth/acct]\n");
1615 if (strcmp(argv[0], "auth") == 0) {
1618 } else if (strcmp(argv[0], "acct") == 0) {
1619 #ifdef WITH_ACCOUNTING
1622 cprintf(listener, "ERROR: This server was built without accounting support.\n");
1627 cprintf(listener, "ERROR: Unknown statistics type\n");
1632 * Global results for all client.
1635 #ifdef WITH_ACCOUNTING
1637 return command_print_stats(listener,
1638 &radius_acct_stats, auth);
1641 return command_print_stats(listener, &radius_auth_stats, auth);
1644 client = get_client(listener, argc - 1, argv + 1);
1649 #ifdef WITH_ACCOUNTING
1651 return command_print_stats(listener, client->acct, auth);
1655 return command_print_stats(listener, client->auth, auth);
1659 static int command_add_client_file(rad_listen_t *listener, int argc, char *argv[])
1664 cprintf(listener, "ERROR: <file> is required\n");
1669 * Read the file and generate the client.
1671 c = client_read(argv[0], FALSE, FALSE);
1673 cprintf(listener, "ERROR: Unknown error reading client file.\n");
1677 if (!client_add(NULL, c)) {
1678 cprintf(listener, "ERROR: Unknown error inserting new client.\n");
1687 static int command_del_client(rad_listen_t *listener, int argc, char *argv[])
1689 #ifdef WITH_DYNAMIC_CLIENTS
1692 client = get_client(listener, argc - 1, argv + 1);
1693 if (!client) return 0;
1695 if (!client->dynamic) {
1696 cprintf(listener, "ERROR: Client %s was not dynamically defined.\n", argv[1]);
1701 * DON'T delete it. Instead, mark it as "dead now". The
1702 * next time we receive a packet for the client, it will
1705 * If we don't receive a packet from it, the client
1706 * structure will stick around for a while. Oh well...
1708 client->lifetime = 1;
1710 cprintf(listener, "ERROR: Dynamic clients are not supported.\n");
1717 static fr_command_table_t command_table_del_client[] = {
1718 { "ipaddr", FR_WRITE,
1719 "del client ipaddr <ipaddr> - Delete a dynamically created client",
1720 command_del_client, NULL },
1722 { NULL, 0, NULL, NULL, NULL }
1726 static fr_command_table_t command_table_del[] = {
1727 { "client", FR_WRITE,
1728 "del client <command> - Delete client configuration commands",
1729 NULL, command_table_del_client },
1731 { NULL, 0, NULL, NULL, NULL }
1735 static fr_command_table_t command_table_add_client[] = {
1737 "add client file <filename> - Add new client definition from <filename>",
1738 command_add_client_file, NULL },
1740 { NULL, 0, NULL, NULL, NULL }
1744 static fr_command_table_t command_table_add[] = {
1745 { "client", FR_WRITE,
1746 "add client <command> - Add client configuration commands",
1747 NULL, command_table_add_client },
1749 { NULL, 0, NULL, NULL, NULL }
1754 static fr_command_table_t command_table_set_home[] = {
1755 { "state", FR_WRITE,
1756 "set home_server state <ipaddr> <port> [alive|dead] - set state for given home server",
1757 command_set_home_server_state, NULL },
1759 { NULL, 0, NULL, NULL, NULL }
1763 static fr_command_table_t command_table_set_module[] = {
1764 { "config", FR_WRITE,
1765 "set module config <module> variable value - set configuration for <module>",
1766 command_set_module_config, NULL },
1768 { "status", FR_WRITE,
1769 "set module status [alive|dead] - set the module to be alive or dead (always return \"fail\")",
1770 command_set_module_status, NULL },
1772 { NULL, 0, NULL, NULL, NULL }
1776 static fr_command_table_t command_table_set[] = {
1777 { "module", FR_WRITE,
1778 "set module <command> - set module commands",
1779 NULL, command_table_set_module },
1781 { "home_server", FR_WRITE,
1782 "set home_server <command> - set home server commands",
1783 NULL, command_table_set_home },
1786 { NULL, 0, NULL, NULL, NULL }
1790 static fr_command_table_t command_table_stats[] = {
1791 { "client", FR_READ,
1792 "stats client [auth/acct] <ipaddr> - show statistics for given client, or for all clients (auth or acct)",
1793 command_stats_client, NULL },
1795 { "home_server", FR_READ,
1796 "stats home_server [<ipaddr>/auth/acct] <port> - show statistics for given home server (ipaddr and port), or for all home servers (auth or acct)",
1797 command_stats_home_server, NULL },
1801 { "detail", FR_READ,
1802 "stats detail <filename> - show statistics for the given detail file",
1803 command_stats_detail, NULL },
1806 { NULL, 0, NULL, NULL, NULL }
1809 static fr_command_table_t command_table[] = {
1810 { "add", FR_WRITE, NULL, NULL, command_table_add },
1811 { "debug", FR_WRITE,
1812 "debug <command> - debugging commands",
1813 NULL, command_table_debug },
1814 { "del", FR_WRITE, NULL, NULL, command_table_del },
1816 "hup [module] - sends a HUP signal to the server, or optionally to one module",
1817 command_hup, NULL },
1818 { "inject", FR_WRITE,
1819 "inject <command> - commands to inject packets into a running server",
1820 NULL, command_table_inject },
1821 { "reconnect", FR_READ,
1822 "reconnect - reconnect to a running server",
1823 NULL, NULL }, /* just here for "help" */
1824 { "terminate", FR_WRITE,
1825 "terminate - terminates the server, and cause it to exit",
1826 command_terminate, NULL },
1827 { "set", FR_WRITE, NULL, NULL, command_table_set },
1828 { "show", FR_READ, NULL, NULL, command_table_show },
1829 { "stats", FR_READ, NULL, NULL, command_table_stats },
1831 { NULL, 0, NULL, NULL, NULL }
1835 static void command_socket_free(rad_listen_t *this)
1837 fr_command_socket_t *sock = this->data;
1846 * Parse the unix domain sockets.
1848 * FIXME: TCP + SSL, after RadSec is in.
1850 static int command_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
1852 fr_command_socket_t *sock;
1854 if (check_config) return 0;
1858 if (cf_section_parse(cs, sock, command_config) < 0) {
1863 if (sock->path) sock->copy = strdup(sock->path);
1865 #if defined(HAVE_GETPEEREID) || defined (SO_PEERCRED)
1866 if (sock->uid_name) {
1869 pw = getpwnam(sock->uid_name);
1871 radlog(L_ERR, "Failed getting uid for %s: %s",
1872 sock->uid_name, strerror(errno));
1876 sock->uid = pw->pw_uid;
1879 if (sock->gid_name) {
1882 gr = getgrnam(sock->gid_name);
1884 radlog(L_ERR, "Failed getting gid for %s: %s",
1885 sock->gid_name, strerror(errno));
1888 sock->gid = gr->gr_gid;
1891 #else /* can't get uid or gid of connecting user */
1893 if (sock->uid_name || sock->gid_name) {
1894 radlog(L_ERR, "System does not support uid or gid authentication for sockets");
1900 if (!sock->mode_name) {
1901 sock->mode = FR_READ;
1903 sock->mode = fr_str2int(mode_names, sock->mode_name, 0);
1905 radlog(L_ERR, "Invalid mode name \"%s\"",
1912 * FIXME: check for absolute pathnames?
1913 * check for uid/gid on the other end...
1916 this->fd = fr_server_domain_socket(sock->path);
1924 static int command_socket_print(const rad_listen_t *this, char *buffer, size_t bufsize)
1926 fr_command_socket_t *sock = this->data;
1928 snprintf(buffer, bufsize, "command file %s", sock->path);
1934 * String split routine. Splits an input string IN PLACE
1935 * into pieces, based on spaces.
1937 static int str2argv(char *str, char **argv, int max_argc)
1944 if (argc >= max_argc) return argc;
1947 * Chop out comments early.
1954 while ((*str == ' ') ||
1957 (*str == '\n')) *(str++) = '\0';
1959 if (!*str) return argc;
1961 if ((*str == '\'') || (*str == '"')) {
1965 token = gettoken((const char **) &p, buffer,
1967 if ((token != T_SINGLE_QUOTED_STRING) &&
1968 (token != T_DOUBLE_QUOTED_STRING)) {
1972 len = strlen(buffer);
1973 if (len >= (size_t) (p - str)) {
1977 memcpy(str, buffer, len + 1);
1990 (*str != '\n')) str++;
1996 static void print_help(rad_listen_t *listener,
1997 fr_command_table_t *table, int recursive)
2001 for (i = 0; table[i].command != NULL; i++) {
2002 if (table[i].help) {
2003 cprintf(listener, "%s\n",
2006 cprintf(listener, "%s <command> - do sub-command of %s\n",
2007 table[i].command, table[i].command);
2010 if (recursive && table[i].table) {
2011 print_help(listener, table[i].table, recursive);
2016 #define MAX_ARGV (16)
2019 * Check if an incoming request is "ok"
2021 * It takes packets, not requests. It sees if the packet looks
2022 * OK. If so, it does a number of sanity checks on it.
2024 static int command_domain_recv(rad_listen_t *listener,
2025 UNUSED RAD_REQUEST_FUNP *pfun,
2026 UNUSED REQUEST **prequest)
2031 char *my_argv[MAX_ARGV], **argv;
2032 fr_command_table_t *table;
2033 fr_command_socket_t *co = listener->data;
2042 len = recv(listener->fd, co->buffer + co->offset,
2043 sizeof(co->buffer) - co->offset - 1, 0);
2044 if (len == 0) goto close_socket; /* clean close */
2047 if ((errno == EAGAIN) || (errno == EINTR)) {
2056 if ((co->offset == 0) && (co->buffer[0] == 0x04)) {
2058 command_close_socket(listener);
2063 * See if there are multiple lines in the buffer.
2065 p = co->buffer + co->offset;
2068 for (c = 0; c < len; c++) {
2069 if ((*p == '\r') || (*p == '\n')) {
2074 * FIXME: do real buffering...
2075 * handling of CTRL-C, etc.
2080 * \r \n followed by ASCII...
2091 * Saw CR/LF. Set next element, and exit.
2094 co->next = p - co->buffer;
2098 if (co->offset >= (ssize_t) (sizeof(co->buffer) - 1)) {
2099 radlog(L_ERR, "Line too long!");
2106 DEBUG("radmin> %s", co->buffer);
2108 argc = str2argv(co->buffer, my_argv, MAX_ARGV);
2109 if (argc == 0) goto do_next; /* empty strings are OK */
2112 cprintf(listener, "ERROR: Failed parsing command.\n");
2118 for (len = 0; len <= co->offset; len++) {
2119 if (co->buffer[len] < 0x20) {
2120 co->buffer[len] = '\0';
2126 * Hard-code exit && quit.
2128 if ((strcmp(argv[0], "exit") == 0) ||
2129 (strcmp(argv[0], "quit") == 0)) goto close_socket;
2133 if (strcmp(argv[0], "login") != 0) {
2134 cprintf(listener, "ERROR: Login required\n");
2139 cprintf(listener, "ERROR: login <user> <password>\n");
2144 * FIXME: Generate && process fake RADIUS request.
2146 if ((strcmp(argv[1], "root") == 0) &&
2147 (strcmp(argv[2], "password") == 0)) {
2148 strlcpy(co->user, argv[1], sizeof(co->user));
2152 cprintf(listener, "ERROR: Login incorrect\n");
2157 table = command_table;
2160 for (i = 0; table[i].command != NULL; i++) {
2161 if (strcmp(table[i].command, argv[0]) == 0) {
2163 * Check permissions.
2165 if (((co->mode & FR_WRITE) == 0) &&
2166 ((table[i].mode & FR_WRITE) != 0)) {
2167 cprintf(listener, "ERROR: You do not have write permission. See \"mode = rw\" in the \"listen\" section for this socket.\n");
2171 if (table[i].table) {
2173 * This is the last argument, but
2174 * there's a sub-table. Print help.
2178 table = table[i].table;
2184 table = table[i].table;
2188 if ((argc == 2) && (strcmp(argv[1], "?") == 0)) goto do_help;
2190 if (!table[i].func) {
2191 cprintf(listener, "ERROR: Invalid command\n");
2196 rcode = table[i].func(listener,
2197 argc - 1, argv + 1);
2206 if ((strcmp(argv[0], "help") == 0) ||
2207 (strcmp(argv[0], "?") == 0)) {
2211 if ((argc > 1) && (strcmp(argv[1], "-r") == 0)) {
2217 print_help(listener, table, recursive);
2221 cprintf(listener, "ERROR: Unknown command \"%s\"\n",
2226 cprintf(listener, "radmin> ");
2228 if (co->next <= co->offset) {
2231 memmove(co->buffer, co->buffer + co->next,
2232 co->offset - co->next);
2233 co->offset -= co->next;
2240 static int command_domain_accept(rad_listen_t *listener,
2241 UNUSED RAD_REQUEST_FUNP *pfun,
2242 UNUSED REQUEST **prequest)
2248 struct sockaddr_storage src;
2249 fr_command_socket_t *sock = listener->data;
2251 salen = sizeof(src);
2253 DEBUG2(" ... new connection request on command socket.");
2258 newfd = accept(listener->fd, (struct sockaddr *) &src, &salen);
2261 * Non-blocking sockets must handle this.
2263 if (errno == EWOULDBLOCK) {
2267 DEBUG2(" ... failed to accept connection.");
2272 * Perform user authentication.
2274 if (sock->uid_name || sock->gid_name) {
2278 if (getpeereid(listener->fd, &uid, &gid) < 0) {
2279 radlog(L_ERR, "Failed getting peer credentials for %s: %s",
2280 sock->path, strerror(errno));
2285 if (sock->uid_name && (sock->uid != uid)) {
2286 radlog(L_ERR, "Unauthorized connection to %s from uid %ld",
2287 sock->path, (long int) uid);
2292 if (sock->gid_name && (sock->gid != gid)) {
2293 radlog(L_ERR, "Unauthorized connection to %s from gid %ld",
2294 sock->path, (long int) gid);
2301 * Write 32-bit magic number && version information.
2303 magic = htonl(0xf7eead15);
2304 if (write(newfd, &magic, 4) < 0) {
2305 radlog(L_ERR, "Failed writing initial data to socket: %s",
2310 magic = htonl(1); /* protocol version */
2311 if (write(newfd, &magic, 4) < 0) {
2312 radlog(L_ERR, "Failed writing initial data to socket: %s",
2320 * Add the new listener.
2322 this = listen_alloc(listener->type);
2323 if (!this) return 0;
2326 * Copy everything, including the pointer to the socket
2330 memcpy(this, listener, sizeof(*this));
2331 this->status = RAD_LISTEN_STATUS_INIT;
2333 this->data = sock; /* fix it back */
2336 sock->user[0] = '\0';
2337 sock->path = ((fr_command_socket_t *) listener->data)->path;
2338 sock->mode = ((fr_command_socket_t *) listener->data)->mode;
2341 this->recv = command_domain_recv;
2344 * Tell the event loop that we have a new FD
2353 * Send an authentication response packet
2355 static int command_domain_send(UNUSED rad_listen_t *listener,
2356 UNUSED REQUEST *request)
2362 static int command_socket_encode(UNUSED rad_listen_t *listener,
2363 UNUSED REQUEST *request)
2369 static int command_socket_decode(UNUSED rad_listen_t *listener,
2370 UNUSED REQUEST *request)
2375 #endif /* WITH_COMMAND_SOCKET */