Use a Ragel-generated DFA parser for ifchd command dispatch.
This commit is contained in:
parent
930b92a268
commit
b7e6f59fc7
@ -2,7 +2,19 @@ project (ifchd)
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
set(RAGEL_IFCHD_PARSE ${CMAKE_CURRENT_BINARY_DIR}/ifchd-parse.c)
|
||||
|
||||
find_program(RAGEL ragel)
|
||||
add_custom_command(
|
||||
OUTPUT ${RAGEL_IFCHD_PARSE}
|
||||
COMMAND ${RAGEL} -G2 -o ${RAGEL_IFCHD_PARSE} ifchd-parse.rl
|
||||
DEPENDS ifchd-parse.rl
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Compiling Ragel state machine: ifchd-parse.rl"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
file(GLOB IFCHD_SRCS "*.c")
|
||||
|
||||
add_executable(ifchd ${IFCHD_SRCS})
|
||||
add_executable(ifchd ${RAGEL_IFCHD_PARSE} ${IFCHD_SRCS})
|
||||
target_link_libraries(ifchd ncmlib)
|
||||
|
@ -10,6 +10,24 @@
|
||||
#define CONN_TIMEOUT 60
|
||||
#define MAX_IFACES 10
|
||||
|
||||
enum ifchd_states {
|
||||
STATE_NOTHING,
|
||||
STATE_INTERFACE,
|
||||
STATE_IP,
|
||||
STATE_SUBNET,
|
||||
STATE_TIMEZONE,
|
||||
STATE_ROUTER,
|
||||
STATE_DNS,
|
||||
STATE_LPRSVR,
|
||||
STATE_HOSTNAME,
|
||||
STATE_DOMAIN,
|
||||
STATE_IPTTL,
|
||||
STATE_MTU,
|
||||
STATE_BROADCAST,
|
||||
STATE_NTPSVR,
|
||||
STATE_WINS
|
||||
};
|
||||
|
||||
#include <net/if.h>
|
||||
struct ifchd_client {
|
||||
/* Socket fd, current state, and idle time for connection. */
|
||||
@ -26,5 +44,14 @@ struct ifchd_client {
|
||||
char domains[MAX_BUF];
|
||||
};
|
||||
|
||||
extern void perform_timezone(struct ifchd_client *cl, const char *str, size_t len);
|
||||
extern void perform_dns(struct ifchd_client *cl, const char *str, size_t len);
|
||||
extern void perform_lprsvr(struct ifchd_client *cl, const char *str, size_t len);
|
||||
extern void perform_hostname(struct ifchd_client *cl, const char *str, size_t len);
|
||||
extern void perform_domain(struct ifchd_client *cl, const char *str, size_t len);
|
||||
extern void perform_ipttl(struct ifchd_client *cl, const char *str, size_t len);
|
||||
extern void perform_ntpsrv(struct ifchd_client *cl, const char *str, size_t len);
|
||||
extern void perform_wins(struct ifchd_client *cl, const char *str, size_t len);
|
||||
|
||||
#endif /* IFCHD_DEFINES_H_ */
|
||||
|
||||
|
151
ifchd/ifchd-parse.rl
Normal file
151
ifchd/ifchd-parse.rl
Normal file
@ -0,0 +1,151 @@
|
||||
/* ifchd-parse.rl - interface change daemon parser
|
||||
*
|
||||
* Copyright (c) 2004-2013 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ifchd-defines.h"
|
||||
#include "log.h"
|
||||
#include "ifch_proto.h"
|
||||
#include "strl.h"
|
||||
#include "linux.h"
|
||||
|
||||
%%{
|
||||
machine ifchd_parser;
|
||||
|
||||
action Reset { cl->state = STATE_NOTHING; }
|
||||
action ArgSt { arg_start = p; }
|
||||
action ArgEn {
|
||||
arg_len = p - arg_start;
|
||||
if (arg_len > sizeof tb - 1) {
|
||||
log_line("command argument would overflow");
|
||||
return -1;
|
||||
}
|
||||
memcpy(tb, arg_start, arg_len);
|
||||
tb[arg_len] = 0;
|
||||
}
|
||||
|
||||
action Dispatch {
|
||||
switch (cl->state) {
|
||||
case STATE_INTERFACE: perform_interface(cl, tb, arg_len); break;
|
||||
case STATE_IP: perform_ip(cl, tb, arg_len); break;
|
||||
case STATE_SUBNET: perform_subnet(cl, tb, arg_len); break;
|
||||
case STATE_TIMEZONE: perform_timezone(cl, tb, arg_len); break;
|
||||
case STATE_ROUTER: perform_router(cl, tb, arg_len); break;
|
||||
case STATE_DNS: perform_dns(cl, tb, arg_len); break;
|
||||
case STATE_LPRSVR: perform_lprsvr(cl, tb, arg_len); break;
|
||||
case STATE_HOSTNAME: perform_hostname(cl, tb, arg_len); break;
|
||||
case STATE_DOMAIN: perform_domain(cl, tb, arg_len); break;
|
||||
case STATE_IPTTL: perform_ipttl(cl, tb, arg_len); break;
|
||||
case STATE_MTU: perform_mtu(cl, tb, arg_len); break;
|
||||
case STATE_BROADCAST: perform_broadcast(cl, tb, arg_len); break;
|
||||
case STATE_NTPSVR: perform_ntpsrv(cl, tb, arg_len); break;
|
||||
case STATE_WINS: perform_wins(cl, tb, arg_len); break;
|
||||
default:
|
||||
log_line("error: invalid state in dispatch_work");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
interface = 'iface';
|
||||
ip = 'ip';
|
||||
subnet = 'snet';
|
||||
dns = 'dns';
|
||||
lprsvr = 'lpr';
|
||||
ntpsvr = 'ntp';
|
||||
wins = 'wins';
|
||||
router = 'routr';
|
||||
broadcast = 'bcast';
|
||||
timezone = 'tzone';
|
||||
hostname = 'host';
|
||||
domain = 'dom';
|
||||
ipttl = 'ipttl';
|
||||
mtu = 'mtu';
|
||||
|
||||
cmdname = (interface % { cl->state = STATE_INTERFACE; }
|
||||
|ip % { cl->state = STATE_IP; }
|
||||
|subnet % { cl->state = STATE_SUBNET; }
|
||||
|dns % { cl->state = STATE_DNS; }
|
||||
|lprsvr % { cl->state = STATE_LPRSVR; }
|
||||
|ntpsvr % { cl->state = STATE_NTPSVR; }
|
||||
|wins % { cl->state = STATE_WINS; }
|
||||
|router % { cl->state = STATE_ROUTER; }
|
||||
|broadcast % { cl->state = STATE_BROADCAST; }
|
||||
|timezone % { cl->state = STATE_TIMEZONE; }
|
||||
|hostname % { cl->state = STATE_HOSTNAME; }
|
||||
|domain % { cl->state = STATE_DOMAIN; }
|
||||
|ipttl % { cl->state = STATE_IPTTL; }
|
||||
|mtu % { cl->state = STATE_MTU; }
|
||||
);
|
||||
|
||||
command = cmdname ':' ([^;\0]+ > ArgSt % ArgEn) (';' > Dispatch);
|
||||
main := (command > Reset)+;
|
||||
}%%
|
||||
|
||||
%% write data;
|
||||
|
||||
/*
|
||||
* Returns -1 on fatal error; that leads to peer connection being closed.
|
||||
*/
|
||||
int execute_buffer(struct ifchd_client *cl, char *newbuf)
|
||||
{
|
||||
char buf[MAX_BUF * 2];
|
||||
char tb[MAX_BUF];
|
||||
|
||||
if (strnkcpy(buf, cl->ibuf, sizeof buf))
|
||||
goto buftooshort;
|
||||
if (strnkcat(buf, newbuf, sizeof buf)) {
|
||||
buftooshort:
|
||||
log_line("error: input is too long for buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t init_siz = strlen(buf);
|
||||
const char *p = buf;
|
||||
const char *pe = p + init_siz;
|
||||
const char *arg_start;
|
||||
size_t arg_len;
|
||||
unsigned int cs = 0;
|
||||
|
||||
%% write init;
|
||||
%% write exec;
|
||||
|
||||
size_t bytes_left = pe - p;
|
||||
if (bytes_left > 0) {
|
||||
size_t taken = init_siz - bytes_left;
|
||||
strnkcpy(cl->ibuf, buf + taken, MAX_BUF);
|
||||
}
|
||||
|
||||
if (cs < ifchd_parser_first_final) {
|
||||
log_line("error: received invalid commands");
|
||||
return -1;
|
||||
}
|
||||
log_line("Commands received and successfully executed.");
|
||||
return 0;
|
||||
}
|
||||
|
217
ifchd/ifchd.c
217
ifchd/ifchd.c
@ -1,6 +1,6 @@
|
||||
/* ifchd.c - interface change daemon
|
||||
*
|
||||
* Copyright (c) 2004-2012 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* Copyright (c) 2004-2013 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -60,24 +60,6 @@
|
||||
#include "linux.h"
|
||||
#include "seccomp-bpf.h"
|
||||
|
||||
enum states {
|
||||
STATE_NOTHING,
|
||||
STATE_INTERFACE,
|
||||
STATE_IP,
|
||||
STATE_SUBNET,
|
||||
STATE_TIMEZONE,
|
||||
STATE_ROUTER,
|
||||
STATE_DNS,
|
||||
STATE_LPRSVR,
|
||||
STATE_HOSTNAME,
|
||||
STATE_DOMAIN,
|
||||
STATE_IPTTL,
|
||||
STATE_MTU,
|
||||
STATE_BROADCAST,
|
||||
STATE_NTPSVR,
|
||||
STATE_WINS
|
||||
};
|
||||
|
||||
struct ifchd_client clients[SOCK_QUEUE];
|
||||
|
||||
static int epollfd, signalFd;
|
||||
@ -96,6 +78,8 @@ static pid_t peer_pid;
|
||||
|
||||
static int gflags_verbose = 0;
|
||||
|
||||
extern int execute_buffer(struct ifchd_client *cl, char *newbuf);
|
||||
|
||||
static void writeordie(int fd, const char *buf, int len)
|
||||
{
|
||||
if (safe_write(fd, buf, len) == -1)
|
||||
@ -240,7 +224,7 @@ static void write_resolve_conf(struct ifchd_client *cl)
|
||||
|
||||
off = lseek(resolv_conf_fd, 0, SEEK_CUR);
|
||||
if (off == -1) {
|
||||
log_line("write_resolve_conf: lseek returned error: %s\n",
|
||||
log_line("write_resolve_conf: lseek returned error: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
@ -249,64 +233,64 @@ static void write_resolve_conf(struct ifchd_client *cl)
|
||||
if (r == -1) {
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
log_line("write_resolve_conf: ftruncate returned error: %s\n",
|
||||
log_line("write_resolve_conf: ftruncate returned error: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
r = fsync(resolv_conf_fd);
|
||||
if (r == -1) {
|
||||
log_line("write_resolve_conf: fsync returned error: %s\n",
|
||||
log_line("write_resolve_conf: fsync returned error: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: addme */
|
||||
static void perform_timezone(struct ifchd_client *cl, char *str)
|
||||
void perform_timezone(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{}
|
||||
|
||||
/* Add a dns server to the /etc/resolv.conf -- we already have a fd. */
|
||||
static void perform_dns(struct ifchd_client *cl, char *str)
|
||||
void perform_dns(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
if (!str || resolv_conf_fd == -1)
|
||||
return;
|
||||
strnkcpy(cl->namesvrs, str, MAX_BUF);
|
||||
strnkcpy(cl->namesvrs, str, sizeof cl->namesvrs);
|
||||
write_resolve_conf(cl);
|
||||
}
|
||||
|
||||
/* Updates for print daemons are too non-standard to be useful. */
|
||||
static void perform_lprsvr(struct ifchd_client *cl, char *str)
|
||||
void perform_lprsvr(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{}
|
||||
|
||||
/* Sets machine hostname. */
|
||||
static void perform_hostname(struct ifchd_client *cl, char *str)
|
||||
void perform_hostname(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
if (!allow_hostname || !str)
|
||||
return;
|
||||
if (sethostname(str, strlen(str) + 1) == -1)
|
||||
log_line("sethostname returned %s\n", strerror(errno));
|
||||
log_line("sethostname returned %s", strerror(errno));
|
||||
}
|
||||
|
||||
/* update "domain" and "search" in /etc/resolv.conf */
|
||||
static void perform_domain(struct ifchd_client *cl, char *str)
|
||||
void perform_domain(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
if (!str || resolv_conf_fd == -1)
|
||||
return;
|
||||
strnkcpy(cl->domains, str, MAX_BUF);
|
||||
strnkcpy(cl->domains, str, sizeof cl->domains);
|
||||
write_resolve_conf(cl);
|
||||
}
|
||||
|
||||
/* I don't think this can be done without a netfilter extension
|
||||
* that isn't in the mainline kernels. */
|
||||
static void perform_ipttl(struct ifchd_client *cl, char *str)
|
||||
void perform_ipttl(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{}
|
||||
|
||||
/* XXX: addme */
|
||||
static void perform_ntpsrv(struct ifchd_client *cl, char *str)
|
||||
void perform_ntpsrv(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{}
|
||||
|
||||
/* Maybe Samba cares about this feature? I don't know. */
|
||||
static void perform_wins(struct ifchd_client *cl, char *str)
|
||||
void perform_wins(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{}
|
||||
|
||||
static inline void clock_or_die(struct timespec *ts)
|
||||
@ -378,165 +362,6 @@ static void close_idle_sk(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns -1 on fatal error.
|
||||
*/
|
||||
static int execute_buffer(struct ifchd_client *cl, char *newbuf)
|
||||
{
|
||||
char buf[MAX_BUF * 2];
|
||||
char *p = buf, *endp;
|
||||
|
||||
memset(buf, 0, sizeof buf);
|
||||
if (strnkcat(buf, cl->ibuf, sizeof buf))
|
||||
goto buftooshort;
|
||||
if (strnkcat(buf, newbuf, sizeof buf)) {
|
||||
buftooshort:
|
||||
log_line("error: input is too long for buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (endp = p;;p = endp) {
|
||||
if (cl->state == STATE_NOTHING) {
|
||||
char *colon = strchr(p, ':');
|
||||
if (!colon)
|
||||
break;
|
||||
char *semi = strchr(p, ';');
|
||||
if (semi && semi < colon) {
|
||||
log_line("bad syntax: STATE_NOTHING and a ';' came before ':'");
|
||||
return -1;
|
||||
}
|
||||
*colon = '\0';
|
||||
endp = colon + 1;
|
||||
} else {
|
||||
char *semi = strchr(p, ';');
|
||||
if (!semi)
|
||||
break;
|
||||
char *colon = strchr(p, ':');
|
||||
if (colon && colon < semi) {
|
||||
log_line("bad syntax: !STATE_NOTHING and a ':' came before ';'");
|
||||
return -1;
|
||||
}
|
||||
*semi = '\0';
|
||||
endp = semi + 1;
|
||||
}
|
||||
|
||||
if (!strlen(p))
|
||||
continue;
|
||||
|
||||
switch (cl->state) {
|
||||
case STATE_NOTHING:
|
||||
if (strncmp(p, CMD_INTERFACE, sizeof(CMD_INTERFACE)) == 0)
|
||||
cl->state = STATE_INTERFACE;
|
||||
if (strncmp(p, CMD_IP, sizeof(CMD_IP)) == 0)
|
||||
cl->state = STATE_IP;
|
||||
if (strncmp(p, CMD_SUBNET, sizeof(CMD_SUBNET)) == 0)
|
||||
cl->state = STATE_SUBNET;
|
||||
if (strncmp(p, CMD_TIMEZONE, sizeof(CMD_TIMEZONE)) == 0)
|
||||
cl->state = STATE_TIMEZONE;
|
||||
if (strncmp(p, CMD_ROUTER, sizeof(CMD_ROUTER)) == 0)
|
||||
cl->state = STATE_ROUTER;
|
||||
if (strncmp(p, CMD_DNS, sizeof(CMD_DNS)) == 0)
|
||||
cl->state = STATE_DNS;
|
||||
if (strncmp(p, CMD_LPRSVR, sizeof(CMD_LPRSVR)) == 0)
|
||||
cl->state = STATE_LPRSVR;
|
||||
if (strncmp(p, CMD_HOSTNAME, sizeof(CMD_HOSTNAME)) == 0)
|
||||
cl->state = STATE_HOSTNAME;
|
||||
if (strncmp(p, CMD_DOMAIN, sizeof(CMD_DOMAIN)) == 0)
|
||||
cl->state = STATE_DOMAIN;
|
||||
if (strncmp(p, CMD_IPTTL, sizeof(CMD_IPTTL)) == 0)
|
||||
cl->state = STATE_IPTTL;
|
||||
if (strncmp(p, CMD_MTU, sizeof(CMD_MTU)) == 0)
|
||||
cl->state = STATE_MTU;
|
||||
if (strncmp(p, CMD_BROADCAST, sizeof(CMD_BROADCAST)) == 0)
|
||||
cl->state = STATE_BROADCAST;
|
||||
if (strncmp(p, CMD_NTPSVR, sizeof(CMD_NTPSVR)) == 0)
|
||||
cl->state = STATE_NTPSVR;
|
||||
if (strncmp(p, CMD_WINS, sizeof(CMD_WINS)) == 0)
|
||||
cl->state = STATE_WINS;
|
||||
break;
|
||||
|
||||
case STATE_INTERFACE:
|
||||
perform_interface(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_IP:
|
||||
perform_ip(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_SUBNET:
|
||||
perform_subnet(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_TIMEZONE:
|
||||
perform_timezone(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_ROUTER:
|
||||
perform_router(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_DNS:
|
||||
perform_dns(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_LPRSVR:
|
||||
perform_lprsvr(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_HOSTNAME:
|
||||
perform_hostname(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_DOMAIN:
|
||||
perform_domain(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_IPTTL:
|
||||
perform_ipttl(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_MTU:
|
||||
perform_mtu(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_BROADCAST:
|
||||
perform_broadcast(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_NTPSVR:
|
||||
perform_ntpsrv(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
case STATE_WINS:
|
||||
perform_wins(cl, p);
|
||||
cl->state = STATE_NOTHING;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_line("warning: invalid state in dispatch_work\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t remsize = strlen(endp);
|
||||
if (remsize > MAX_BUF - 1)
|
||||
return -1;
|
||||
strnkcpy(cl->ibuf, endp, MAX_BUF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Opens a non-blocking listening socket with the appropriate properties. */
|
||||
static int get_listen(void)
|
||||
{
|
||||
@ -600,7 +425,7 @@ static void accept_conns(int *lsock)
|
||||
case EBADF:
|
||||
case ENOTSOCK:
|
||||
case EINVAL:
|
||||
log_line("warning: accept returned %s!\n", strerror(errno));
|
||||
log_line("warning: accept returned %s!", strerror(errno));
|
||||
|
||||
epoll_del(*lsock);
|
||||
close(*lsock);
|
||||
@ -612,11 +437,11 @@ static void accept_conns(int *lsock)
|
||||
case ECONNABORTED:
|
||||
case EMFILE:
|
||||
case ENFILE:
|
||||
log_line("warning: accept returned %s!\n", strerror(errno));
|
||||
log_line("warning: accept returned %s!", strerror(errno));
|
||||
return;
|
||||
|
||||
default:
|
||||
log_line("warning: accept returned a mysterious error: %s\n",
|
||||
log_line("warning: accept returned a mysterious error: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
@ -811,7 +636,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
case 'v':
|
||||
printf("ifchd %s, if change daemon.\n", IFCHD_VERSION);
|
||||
printf("Copyright (c) 2004-2012 Nicholas J. Kain\n"
|
||||
printf("Copyright (c) 2004-2013 Nicholas J. Kain\n"
|
||||
"All rights reserved.\n\n"
|
||||
"Redistribution and use in source and binary forms, with or without\n"
|
||||
"modification, are permitted provided that the following conditions are met:\n\n"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* linux.c - ifchd Linux-specific functions
|
||||
*
|
||||
* Copyright (c) 2004-2012 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* Copyright (c) 2004-2013 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -76,7 +76,7 @@ static int is_permitted(char *name)
|
||||
if (strcmp(name, okif[i]) == 0)
|
||||
return 1;
|
||||
}
|
||||
log_line("attempt to modify interface %s denied\n", name);
|
||||
log_line("attempt to modify interface %s denied", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -99,11 +99,11 @@ int authorized_peer(int sk, pid_t pid, uid_t uid, gid_t gid)
|
||||
(gid == 0 || cr.gid == gid))
|
||||
ret = 1;
|
||||
} else
|
||||
log_line("getsockopt returned an error: %s\n", strerror(errno));
|
||||
log_line("getsockopt returned an error: %s", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void perform_interface(struct ifchd_client *cl, char *str)
|
||||
void perform_interface(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
@ -123,21 +123,21 @@ static int set_if_flag(struct ifchd_client *cl, short flag)
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd == -1) {
|
||||
log_line("%s: (set_if_flag) failed to open interface socket: %s\n",
|
||||
log_line("%s: (set_if_flag) failed to open interface socket: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
goto out0;
|
||||
}
|
||||
|
||||
strnkcpy(ifrt.ifr_name, cl->ifnam, IFNAMSIZ);
|
||||
if (ioctl(fd, SIOCGIFFLAGS, &ifrt) < 0) {
|
||||
log_line("%s: unknown interface: %s\n", cl->ifnam, strerror(errno));
|
||||
log_line("%s: unknown interface: %s", cl->ifnam, strerror(errno));
|
||||
goto out1;
|
||||
}
|
||||
if (((ifrt.ifr_flags & flag ) ^ flag) & flag) {
|
||||
strnkcpy(ifrt.ifr_name, cl->ifnam, IFNAMSIZ);
|
||||
ifrt.ifr_flags |= flag;
|
||||
if (ioctl(fd, SIOCSIFFLAGS, &ifrt) < 0) {
|
||||
log_line("%s: failed to set interface flags: %s\n",
|
||||
log_line("%s: failed to set interface flags: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
goto out1;
|
||||
}
|
||||
@ -151,7 +151,7 @@ static int set_if_flag(struct ifchd_client *cl, short flag)
|
||||
}
|
||||
|
||||
/* Sets IP address on an interface and brings it up. */
|
||||
void perform_ip(struct ifchd_client *cl, char *str)
|
||||
void perform_ip(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
int fd;
|
||||
struct in_addr ipaddr;
|
||||
@ -175,18 +175,18 @@ void perform_ip(struct ifchd_client *cl, char *str)
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd == -1) {
|
||||
log_line("%s: (perform_ip) failed to open interface socket: %s\n",
|
||||
log_line("%s: (perform_ip) failed to open interface socket: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, SIOCSIFADDR, &ifrt) < 0)
|
||||
log_line("%s: failed to configure IP: %s\n",
|
||||
log_line("%s: failed to configure IP: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* Sets the subnet mask on an interface. */
|
||||
void perform_subnet(struct ifchd_client *cl, char *str)
|
||||
void perform_subnet(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
int fd;
|
||||
struct in_addr subnet;
|
||||
@ -208,20 +208,20 @@ void perform_subnet(struct ifchd_client *cl, char *str)
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd == -1) {
|
||||
log_line("%s: (perform_ip) failed to open interface socket: %s\n",
|
||||
log_line("%s: (perform_ip) failed to open interface socket: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, SIOCSIFNETMASK, &ifrt) < 0) {
|
||||
sin.sin_addr.s_addr = 0xffffffff;
|
||||
if (ioctl(fd, SIOCSIFNETMASK, &ifrt) < 0)
|
||||
log_line("%s: failed to configure subnet: %s\n",
|
||||
log_line("%s: failed to configure subnet: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void perform_router(struct ifchd_client *cl, char *str)
|
||||
void perform_router(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
struct rtentry rt;
|
||||
struct sockaddr_in *dest;
|
||||
@ -255,19 +255,19 @@ void perform_router(struct ifchd_client *cl, char *str)
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd == -1) {
|
||||
log_line("%s: (perform_router) failed to open interface socket: %s\n",
|
||||
log_line("%s: (perform_router) failed to open interface socket: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, SIOCADDRT, &rt)) {
|
||||
if (errno != EEXIST)
|
||||
log_line("%s: failed to set route: %s\n",
|
||||
log_line("%s: failed to set route: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void perform_mtu(struct ifchd_client *cl, char *str)
|
||||
void perform_mtu(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
int fd;
|
||||
unsigned int mtu;
|
||||
@ -287,17 +287,17 @@ void perform_mtu(struct ifchd_client *cl, char *str)
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd == -1) {
|
||||
log_line("%s: (perform_mtu) failed to open interface socket: %s\n",
|
||||
log_line("%s: (perform_mtu) failed to open interface socket: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, SIOCSIFMTU, &ifrt) < 0)
|
||||
log_line("%s: failed to set MTU (%d): %s\n", cl->ifnam, mtu,
|
||||
log_line("%s: failed to set MTU (%d): %s", cl->ifnam, mtu,
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void perform_broadcast(struct ifchd_client *cl, char *str)
|
||||
void perform_broadcast(struct ifchd_client *cl, const char *str, size_t len)
|
||||
{
|
||||
int fd;
|
||||
struct in_addr broadcast;
|
||||
@ -319,11 +319,11 @@ void perform_broadcast(struct ifchd_client *cl, char *str)
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd == -1) {
|
||||
log_line("%s: (perform_broadcast) failed to open interface socket: %s\n", cl->ifnam, strerror(errno));
|
||||
log_line("%s: (perform_broadcast) failed to open interface socket: %s", cl->ifnam, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, SIOCSIFBRDADDR, &ifrt) < 0)
|
||||
log_line("%s: failed to set broadcast: %s\n",
|
||||
log_line("%s: failed to set broadcast: %s",
|
||||
cl->ifnam, strerror(errno));
|
||||
close(fd);
|
||||
}
|
||||
|
@ -32,11 +32,11 @@ void clear_if_data(struct ifchd_client *cl);
|
||||
void initialize_if_data(void);
|
||||
void add_permitted_if(char *s);
|
||||
int authorized_peer(int sk, pid_t pid, uid_t uid, gid_t gid);
|
||||
void perform_interface(struct ifchd_client *cl, char *str);
|
||||
void perform_ip(struct ifchd_client *cl, char *str);
|
||||
void perform_subnet(struct ifchd_client *cl, char *str);
|
||||
void perform_router(struct ifchd_client *cl, char *str);
|
||||
void perform_mtu(struct ifchd_client *cl, char *str);
|
||||
void perform_broadcast(struct ifchd_client *cl, char *str);
|
||||
void perform_interface(struct ifchd_client *cl, const char *str, size_t len);
|
||||
void perform_ip(struct ifchd_client *cl, const char *str, size_t len);
|
||||
void perform_subnet(struct ifchd_client *cl, const char *str, size_t len);
|
||||
void perform_router(struct ifchd_client *cl, const char *str, size_t len);
|
||||
void perform_mtu(struct ifchd_client *cl, const char *str, size_t len);
|
||||
void perform_broadcast(struct ifchd_client *cl, const char *str, size_t len);
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user