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)
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)

View File

@ -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
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
*
* 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"

View File

@ -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);
}

View File

@ -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