2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-23 18:38:00 +00:00
isc-dhcp/common/interact.c

243 lines
6.7 KiB
C

/* interact.c
Text interactor for dhcp servers. */
/*
* Copyright (c) 1998 The Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of The Internet Software Consortium nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This software was written for the Internet Software Consortium by
* Ted Lemon <mellon@fugue.com> in cooperation with Vixie Enterprises.
* To learn more about the Internet Software Consortium, see
* ``http://www.vix.com/isc''. To learn more about Vixie Enterprises,
* see ``http://www.vix.com''.
*/
#ifndef lint
static char copyright[] =
"$Id: interact.c,v 1.1 1998/04/09 05:18:56 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
int interact_initialized;
int interact_fd;
static struct interact_client *interact_clients;
void interact_startup ()
{
struct sockaddr_un name;
static int once;
int len;
mode_t m;
/* Only initialize interact once. */
if (interact_initialized)
error ("attempted to reinitialize interact protocol");
interact_initialized = 1;
/* Make a socket... */
interact_fd = socket (AF_UNIX, SOCK_STREAM, 0);
if (interact_fd < 0)
error ("unable to create interact socket: %m");
/* XXX for now... */
name.sun_family = PF_UNIX;
strcpy (name.sun_path, "/var/run/dhcpctl");
#if defined (HAVE_SA_LEN)
name.sun_len =
#endif
len = ((sizeof name) - (sizeof name.sun_path) +
strlen (name.sun_path));
unlink (name.sun_path);
/* interact socket should be accessible only by root. */
m = umask (0700);
/* Bind to it... */
if (bind (interact_fd, (struct sockaddr *)&name, len) < 0) {
warn ("can't bind to interact socket: %m");
close (interact_fd);
umask (m);
return;
}
umask (m);
/* Listen for connections... */
if (listen (interact_fd, 1) < 0) {
warn ("can't listen on interact socket: %m");
close (interact_fd);
unlink (name.sun_path);
return;
}
add_protocol ("interact", interact_fd, new_interact_connection, 0);
}
void new_interact_connection (proto)
struct protocol *proto;
{
struct sockaddr_un name;
int namelen;
struct interact_client *tmp;
int new_fd;
int arg;
tmp = (struct interact_client *)malloc (sizeof *tmp);
if (!tmp)
error ("Can't find memory for new client!");
memset (tmp, 0, sizeof *tmp);
namelen = sizeof name;
new_fd = accept (proto -> fd, (struct sockaddr *)&name, &namelen);
if (new_fd < 0) {
warn ("accept: %m");
free (tmp);
return;
}
if ((arg = fcntl (new_fd, F_GETFL, 0)) < 0) {
bad_flag:
warn ("Can't set flags on new interactive client: %m");
close (new_fd);
free (tmp);
return;
}
arg |= O_NONBLOCK;
if (fcntl (new_fd, F_SETFL, arg) < 0)
goto bad_flag;
tmp -> next = interact_clients;
tmp -> fd = new_fd;
interact_clients = tmp;
tmp -> cur_node_actions = top_level_actions;
tmp -> proto = add_protocol ("aclient", new_fd,
interact_client_input, tmp);
}
void interact_client_input (proto)
struct protocol *proto;
{
int status;
char *eobuf;
struct interact_client *client = proto -> local;
status = read (proto -> fd, &client -> ibuf [client -> ibuflen],
(sizeof client -> ibuf) - client -> ibuflen);
if (status < 0) {
warn ("interact_client_input: %m");
blow:
close (proto -> fd);
remove_protocol (proto);
free (client);
return;
}
/* EOF: get lost. */
if (status == 0)
goto blow;
client -> ibuflen += status;
eobuf = memchr (client -> ibuf, '\n', client -> ibuflen);
if (!eobuf) {
if (client -> ibuflen == sizeof client -> ibuf) {
warn ("interact_client_input: buffer overflow.");
goto blow;
}
return;
}
/* NUL terminate and blow away newline. */
*eobuf = 0;
if (!strcmp (client -> ibuf, "ls"))
(*client -> cur_node_actions.ls) (client);
else if (!strncmp (client -> ibuf, "print ", 6))
(*client -> cur_node_actions.print) (client,
&client -> ibuf [6]);
else if (!strncmp (client -> ibuf, "set ", 4))
(*client -> cur_node_actions.set) (client,
&client -> ibuf [4]);
else if (!strncmp (client -> ibuf, "rm ", 3))
(*client -> cur_node_actions.rm) (client,
&client -> ibuf [3]);
else if (!strcmp (client -> ibuf, "cd .."))
(*client -> cur_node_actions.cdup) (client);
else if (!strncmp (client -> ibuf, "cd ", 3))
(*client -> cur_node_actions.cd) (client,
&client -> ibuf [3]);
else if (!strcmp (client -> ibuf, "exit")) {
interact_client_write (client, "done.", 1);
goto blow;
} else
interact_client_write (client, "invalid command", 1);
/* In case the client wrote more than one command. */
if (client -> ibuflen -= eobuf - &client -> ibuf [0] + 1)
memmove (client -> ibuf, eobuf, client -> ibuflen);
}
int interact_client_write (client, string, lastp)
struct interact_client *client;
char *string;
int lastp;
{
static char *obuf;
static int obufmax;
char *bp;
/* Unlikely to loop, but why not be sure? */
if (obufmax < strlen (string)) {
if (obuf)
free (obuf);
obufmax = (strlen (string) + 1025) & ~1023;
obuf = malloc (obufmax);
if (!obuf) {
warn ("interact_client_write: out of memory");
blow:
close (client -> proto -> fd);
remove_protocol (client -> proto);
free (client);
return 0;
}
}
bp = obuf;
if (!lastp)
*bp++ = '-';
strcpy (bp, string);
bp += strlen (bp);
*bp++ = '\n';
if (write (client -> fd, obuf, bp - obuf) < 0)
return 0;
return 1;
}