Use a Ragel-generated DFA parser for ifchd command dispatch.

This commit is contained in:
Nicholas J. Kain 2013-05-08 06:27:22 -04:00
parent 930b92a268
commit b7e6f59fc7
6 changed files with 240 additions and 225 deletions

View File

@ -2,7 +2,19 @@ project (ifchd)
cmake_minimum_required (VERSION 2.6) 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") file(GLOB IFCHD_SRCS "*.c")
add_executable(ifchd ${IFCHD_SRCS}) add_executable(ifchd ${RAGEL_IFCHD_PARSE} ${IFCHD_SRCS})
target_link_libraries(ifchd ncmlib) target_link_libraries(ifchd ncmlib)

View File

@ -10,6 +10,24 @@
#define CONN_TIMEOUT 60 #define CONN_TIMEOUT 60
#define MAX_IFACES 10 #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> #include <net/if.h>
struct ifchd_client { struct ifchd_client {
/* Socket fd, current state, and idle time for connection. */ /* Socket fd, current state, and idle time for connection. */
@ -26,5 +44,14 @@ struct ifchd_client {
char domains[MAX_BUF]; 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_ */ #endif /* IFCHD_DEFINES_H_ */

151
ifchd/ifchd-parse.rl Normal file
View 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;
}

View File

@ -1,6 +1,6 @@
/* ifchd.c - interface change daemon /* 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -60,24 +60,6 @@
#include "linux.h" #include "linux.h"
#include "seccomp-bpf.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]; struct ifchd_client clients[SOCK_QUEUE];
static int epollfd, signalFd; static int epollfd, signalFd;
@ -96,6 +78,8 @@ static pid_t peer_pid;
static int gflags_verbose = 0; 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) static void writeordie(int fd, const char *buf, int len)
{ {
if (safe_write(fd, buf, len) == -1) 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); off = lseek(resolv_conf_fd, 0, SEEK_CUR);
if (off == -1) { if (off == -1) {
log_line("write_resolve_conf: lseek returned error: %s\n", log_line("write_resolve_conf: lseek returned error: %s",
strerror(errno)); strerror(errno));
return; return;
} }
@ -249,64 +233,64 @@ static void write_resolve_conf(struct ifchd_client *cl)
if (r == -1) { if (r == -1) {
if (errno == EINTR) if (errno == EINTR)
goto retry; goto retry;
log_line("write_resolve_conf: ftruncate returned error: %s\n", log_line("write_resolve_conf: ftruncate returned error: %s",
strerror(errno)); strerror(errno));
return; return;
} }
r = fsync(resolv_conf_fd); r = fsync(resolv_conf_fd);
if (r == -1) { if (r == -1) {
log_line("write_resolve_conf: fsync returned error: %s\n", log_line("write_resolve_conf: fsync returned error: %s",
strerror(errno)); strerror(errno));
return; return;
} }
} }
/* XXX: addme */ /* 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. */ /* 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) if (!str || resolv_conf_fd == -1)
return; return;
strnkcpy(cl->namesvrs, str, MAX_BUF); strnkcpy(cl->namesvrs, str, sizeof cl->namesvrs);
write_resolve_conf(cl); write_resolve_conf(cl);
} }
/* Updates for print daemons are too non-standard to be useful. */ /* 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. */ /* 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) if (!allow_hostname || !str)
return; return;
if (sethostname(str, strlen(str) + 1) == -1) 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 */ /* 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) if (!str || resolv_conf_fd == -1)
return; return;
strnkcpy(cl->domains, str, MAX_BUF); strnkcpy(cl->domains, str, sizeof cl->domains);
write_resolve_conf(cl); write_resolve_conf(cl);
} }
/* I don't think this can be done without a netfilter extension /* I don't think this can be done without a netfilter extension
* that isn't in the mainline kernels. */ * 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 */ /* 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. */ /* 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) 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. */ /* Opens a non-blocking listening socket with the appropriate properties. */
static int get_listen(void) static int get_listen(void)
{ {
@ -600,7 +425,7 @@ static void accept_conns(int *lsock)
case EBADF: case EBADF:
case ENOTSOCK: case ENOTSOCK:
case EINVAL: case EINVAL:
log_line("warning: accept returned %s!\n", strerror(errno)); log_line("warning: accept returned %s!", strerror(errno));
epoll_del(*lsock); epoll_del(*lsock);
close(*lsock); close(*lsock);
@ -612,11 +437,11 @@ static void accept_conns(int *lsock)
case ECONNABORTED: case ECONNABORTED:
case EMFILE: case EMFILE:
case ENFILE: case ENFILE:
log_line("warning: accept returned %s!\n", strerror(errno)); log_line("warning: accept returned %s!", strerror(errno));
return; return;
default: default:
log_line("warning: accept returned a mysterious error: %s\n", log_line("warning: accept returned a mysterious error: %s",
strerror(errno)); strerror(errno));
return; return;
} }
@ -811,7 +636,7 @@ int main(int argc, char** argv) {
case 'v': case 'v':
printf("ifchd %s, if change daemon.\n", IFCHD_VERSION); 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" "All rights reserved.\n\n"
"Redistribution and use in source and binary forms, with or without\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" "modification, are permitted provided that the following conditions are met:\n\n"

View File

@ -1,6 +1,6 @@
/* linux.c - ifchd Linux-specific functions /* 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) if (strcmp(name, okif[i]) == 0)
return 1; return 1;
} }
log_line("attempt to modify interface %s denied\n", name); log_line("attempt to modify interface %s denied", name);
return 0; 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)) (gid == 0 || cr.gid == gid))
ret = 1; ret = 1;
} else } else
log_line("getsockopt returned an error: %s\n", strerror(errno)); log_line("getsockopt returned an error: %s", strerror(errno));
return ret; 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) if (!str)
return; return;
@ -123,21 +123,21 @@ static int set_if_flag(struct ifchd_client *cl, short flag)
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) { 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)); cl->ifnam, strerror(errno));
goto out0; goto out0;
} }
strnkcpy(ifrt.ifr_name, cl->ifnam, IFNAMSIZ); strnkcpy(ifrt.ifr_name, cl->ifnam, IFNAMSIZ);
if (ioctl(fd, SIOCGIFFLAGS, &ifrt) < 0) { 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; goto out1;
} }
if (((ifrt.ifr_flags & flag ) ^ flag) & flag) { if (((ifrt.ifr_flags & flag ) ^ flag) & flag) {
strnkcpy(ifrt.ifr_name, cl->ifnam, IFNAMSIZ); strnkcpy(ifrt.ifr_name, cl->ifnam, IFNAMSIZ);
ifrt.ifr_flags |= flag; ifrt.ifr_flags |= flag;
if (ioctl(fd, SIOCSIFFLAGS, &ifrt) < 0) { 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)); cl->ifnam, strerror(errno));
goto out1; 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. */ /* 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; int fd;
struct in_addr ipaddr; struct in_addr ipaddr;
@ -175,18 +175,18 @@ void perform_ip(struct ifchd_client *cl, char *str)
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) { 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)); cl->ifnam, strerror(errno));
return; return;
} }
if (ioctl(fd, SIOCSIFADDR, &ifrt) < 0) 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)); cl->ifnam, strerror(errno));
close(fd); close(fd);
} }
/* Sets the subnet mask on an interface. */ /* 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; int fd;
struct in_addr subnet; struct in_addr subnet;
@ -208,20 +208,20 @@ void perform_subnet(struct ifchd_client *cl, char *str)
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) { 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)); cl->ifnam, strerror(errno));
return; return;
} }
if (ioctl(fd, SIOCSIFNETMASK, &ifrt) < 0) { if (ioctl(fd, SIOCSIFNETMASK, &ifrt) < 0) {
sin.sin_addr.s_addr = 0xffffffff; sin.sin_addr.s_addr = 0xffffffff;
if (ioctl(fd, SIOCSIFNETMASK, &ifrt) < 0) 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)); cl->ifnam, strerror(errno));
} }
close(fd); 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 rtentry rt;
struct sockaddr_in *dest; struct sockaddr_in *dest;
@ -255,19 +255,19 @@ void perform_router(struct ifchd_client *cl, char *str)
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) { 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)); cl->ifnam, strerror(errno));
return; return;
} }
if (ioctl(fd, SIOCADDRT, &rt)) { if (ioctl(fd, SIOCADDRT, &rt)) {
if (errno != EEXIST) if (errno != EEXIST)
log_line("%s: failed to set route: %s\n", log_line("%s: failed to set route: %s",
cl->ifnam, strerror(errno)); cl->ifnam, strerror(errno));
} }
close(fd); 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; int fd;
unsigned int mtu; unsigned int mtu;
@ -287,17 +287,17 @@ void perform_mtu(struct ifchd_client *cl, char *str)
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) { 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)); cl->ifnam, strerror(errno));
return; return;
} }
if (ioctl(fd, SIOCSIFMTU, &ifrt) < 0) 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)); strerror(errno));
close(fd); 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; int fd;
struct in_addr broadcast; struct in_addr broadcast;
@ -319,11 +319,11 @@ void perform_broadcast(struct ifchd_client *cl, char *str)
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) { 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; return;
} }
if (ioctl(fd, SIOCSIFBRDADDR, &ifrt) < 0) 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)); cl->ifnam, strerror(errno));
close(fd); close(fd);
} }

View File

@ -32,11 +32,11 @@ void clear_if_data(struct ifchd_client *cl);
void initialize_if_data(void); void initialize_if_data(void);
void add_permitted_if(char *s); void add_permitted_if(char *s);
int authorized_peer(int sk, pid_t pid, uid_t uid, gid_t gid); 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_interface(struct ifchd_client *cl, const char *str, size_t len);
void perform_ip(struct ifchd_client *cl, char *str); void perform_ip(struct ifchd_client *cl, const char *str, size_t len);
void perform_subnet(struct ifchd_client *cl, char *str); void perform_subnet(struct ifchd_client *cl, const char *str, size_t len);
void perform_router(struct ifchd_client *cl, char *str); void perform_router(struct ifchd_client *cl, const char *str, size_t len);
void perform_mtu(struct ifchd_client *cl, char *str); void perform_mtu(struct ifchd_client *cl, const char *str, size_t len);
void perform_broadcast(struct ifchd_client *cl, char *str); void perform_broadcast(struct ifchd_client *cl, const char *str, size_t len);
#endif #endif