diff --git a/ifchd/CMakeLists.txt b/ifchd/CMakeLists.txt index 60d2018..70bc6a7 100644 --- a/ifchd/CMakeLists.txt +++ b/ifchd/CMakeLists.txt @@ -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) diff --git a/ifchd/ifchd-defines.h b/ifchd/ifchd-defines.h index 078ba38..3d2db51 100644 --- a/ifchd/ifchd-defines.h +++ b/ifchd/ifchd-defines.h @@ -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 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_ */ diff --git a/ifchd/ifchd-parse.rl b/ifchd/ifchd-parse.rl new file mode 100644 index 0000000..0e93605 --- /dev/null +++ b/ifchd/ifchd-parse.rl @@ -0,0 +1,151 @@ +/* ifchd-parse.rl - interface change daemon parser + * + * Copyright (c) 2004-2013 Nicholas J. Kain + * 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 +#include + +#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; +} + diff --git a/ifchd/ifchd.c b/ifchd/ifchd.c index d46597f..570b820 100644 --- a/ifchd/ifchd.c +++ b/ifchd/ifchd.c @@ -1,6 +1,6 @@ /* ifchd.c - interface change daemon * - * Copyright (c) 2004-2012 Nicholas J. Kain + * Copyright (c) 2004-2013 Nicholas J. Kain * 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" diff --git a/ifchd/linux.c b/ifchd/linux.c index 69d4467..51197b9 100644 --- a/ifchd/linux.c +++ b/ifchd/linux.c @@ -1,6 +1,6 @@ /* linux.c - ifchd Linux-specific functions * - * Copyright (c) 2004-2012 Nicholas J. Kain + * Copyright (c) 2004-2013 Nicholas J. Kain * 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); } diff --git a/ifchd/linux.h b/ifchd/linux.h index 2faaaa1..3ebe438 100644 --- a/ifchd/linux.h +++ b/ifchd/linux.h @@ -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