2 * radmin.c RADIUS Administration tool.
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 #include <freeradius-devel/ident.h>
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/radpaths.h>
30 #ifdef HAVE_READLINE_READLINE_H
31 #include <readline/readline.h>
32 #include <readline/history.h>
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
48 * For configuration file stuff.
50 const char *radius_dir = RADDBDIR;
51 const char *progname = "radmin";
54 * The rest of this is because the conffile.c, etc. assume
55 * they're running inside of the server. And we don't (yet)
56 * have a "libfreeradius-server", or "libfreeradius-util".
59 struct main_config_t mainconfig;
60 char *request_log_file = NULL;
61 char *debug_log_file = NULL;
62 int radius_xlat(UNUSED char *out, UNUSED int outlen, UNUSED const char *fmt,
63 UNUSED REQUEST *request, UNUSED RADIUS_ESCAPE_STRING func)
68 static int fr_domain_socket(const char *path)
73 struct sockaddr_un saremote;
76 if (len >= sizeof(saremote.sun_path)) {
77 fprintf(stderr, "%s: Path too long in filename\n", progname);
81 if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
82 fprintf(stderr, "%s: Failed creating socket: %s\n",
83 progname, strerror(errno));
87 saremote.sun_family = AF_UNIX;
88 memcpy(saremote.sun_path, path, len); /* not zero terminated */
90 socklen = sizeof(saremote.sun_family) + len;
92 if (connect(sockfd, (struct sockaddr *)&saremote, socklen) < 0) {
93 fprintf(stderr, "%s: Failed connecting to %s: %s\n",
94 progname, path, strerror(errno));
103 if ((flags = fcntl(sockfd, F_GETFL, NULL)) < 0) {
104 fprintf(stderr, "%s: Failure getting socket flags: %s",
105 progname, strerror(errno));
111 if( fcntl(sockfd, F_SETFL, flags) < 0) {
112 fprintf(stderr, "%s: Failure setting socket flags: %s",
113 progname, strerror(errno));
123 static int usage(void)
125 printf("Usage: %s [ -d raddb_dir ] [ -f socket_file ] [ -n name ] [ -q ]\n", progname);
126 printf(" -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
127 printf(" -f socket_file Open socket_file directly, without reading radius.conf\n");
128 printf(" -n name Read raddb/name.conf instead of raddb/radiusd.conf\n");
129 printf(" -q Quiet mode.\n");
134 int main(int argc, char **argv)
136 int argval, quiet = 0;
137 int done_license = 0;
142 const char *file = NULL;
143 const char *name = "radiusd";
144 char *p, buffer[2048];
146 if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
151 while ((argval = getopt(argc, argv, "d:hf:n:q")) != EOF) {
155 fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
183 CONF_SECTION *cs, *subcs;
185 file = NULL; /* MUST read it from the conffile now */
187 snprintf(buffer, sizeof(buffer), "%s/%s.conf",
190 cs = cf_file_read(buffer);
192 fprintf(stderr, "%s: Errors reading %s\n",
198 while ((subcs = cf_subsection_find_next(cs, subcs, "listen")) != NULL) {
200 CONF_PAIR *cp = cf_pair_find(subcs, "type");
204 value = cf_pair_value(cp);
205 if (!value) continue;
207 if (strcmp(value, "control") != 0) continue;
210 * Now find the socket name (sigh)
212 rcode = cf_item_parse(subcs, "socket",
216 fprintf(stderr, "%s: Failed parsing listen section\n", progname);
221 fprintf(stderr, "%s: No path given for socket\n",
229 fprintf(stderr, "%s: Could not find control socket in %s\n",
235 if (!isatty(STDIN_FILENO)) quiet = 1;
237 #ifdef HAVE_READLINE_READLINE_H
240 rl_bind_key('\t', rl_insert);
246 * FIXME: Get destination from command line, if possible?
248 sockfd = fr_domain_socket(file);
254 * Read initial magic && version information.
256 for (size = 0; size < 8; size += len) {
257 len = read(sockfd, buffer + size, 8 - size);
259 fprintf(stderr, "%s: Error reading initial data from socket: %s\n",
260 progname, strerror(errno));
265 memcpy(&magic, buffer, 4);
266 magic = ntohl(magic);
267 if (magic != 0xf7eead15) {
268 fprintf(stderr, "%s: Socket %s is not FreeRADIUS administration socket\n", progname, file);
272 memcpy(&magic, buffer + 4, 4);
273 magic = ntohl(magic);
275 fprintf(stderr, "%s: Socket version mismatch: Need 1, got %d\n",
280 if (!done_license && !quiet) {
281 printf("radmin " RADIUSD_VERSION " - FreeRADIUS Server administration tool.\n");
282 printf("Copyright (C) 2008 The FreeRADIUS server project and contributors.\n");
283 printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
284 printf("PARTICULAR PURPOSE.\n");
285 printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
286 printf("GNU General Public License v2.\n");
297 #ifndef HAVE_READLINE_READLINE_H
301 line = readline("radmin> ");
312 } else { /* quiet, or no readline */
314 line = fgets(buffer, sizeof(buffer), stdin);
317 p = strchr(buffer, '\n');
319 fprintf(stderr, "%s: Input line too long\n",
327 if (strcmp(line, "reconnect") == 0) {
333 * Write the text to the socket.
335 if (write(sockfd, line, strlen(line)) < 0) break;
336 if (write(sockfd, "\r\n", 2) < 0) break;
341 if ((strcmp(line, "exit") == 0) ||
342 (strcmp(line, "quit") == 0)) {
353 memset(buffer, 0, sizeof(buffer));
360 FD_SET(sockfd, &readfds);
362 rcode = select(sockfd + 1, &readfds, NULL, NULL, NULL);
364 if (errno == EINTR) continue;
366 fprintf(stderr, "%s: Failed selecting: %s\n",
367 progname, strerror(errno));
371 len = recv(sockfd, buffer + size,
372 sizeof(buffer) - size - 1, MSG_DONTWAIT);
375 * No data: keep looping
377 if ((errno == EAGAIN) || (errno == EINTR)) {
381 fprintf(stderr, "%s: Error reading socket: %s\n",
382 progname, strerror(errno));
385 if (len == 0) break; /* clean close of socket */
391 * There really has to be a better way of
394 p = strstr(buffer, "radmin> ");
401 if (p[-1] == '\n') p[-1] = '\0';
409 * Blank prompt. Go get another line.
411 if (!buffer[0]) continue;
413 buffer[size] = '\0'; /* this is at least right */