Code cleanup. Create struct ifchd_client and pull all of the global

static arrays that are indexed by the socket slot index into an array
of struct ifchd_clients.
This commit is contained in:
Nicholas J. Kain
2012-07-20 14:56:17 -04:00
parent c3272f07f4
commit 6e9d856a9d
3 changed files with 177 additions and 173 deletions

View File

@ -4,10 +4,35 @@
#include "defines.h" #include "defines.h"
#define PID_FILE_DEFAULT "/var/run/ifchd.pid" #define PID_FILE_DEFAULT "/var/run/ifchd.pid"
#define IFCHD_VERSION "0.8" #define IFCHD_VERSION "0.9"
#define MAX_BUF 1024 #define MAX_BUF 1024
#define SOCK_QUEUE 2 #define SOCK_QUEUE 2
#define CONN_TIMEOUT 60 #define CONN_TIMEOUT 60
#include <net/if.h>
#include "strlist.h"
struct ifchd_client {
/* Socket fd, current state, and idle time for connection. */
int fd;
int state;
int idle_time;
/*
* Per-connection pointers into the command lists. Respectively, the
* topmost item on the list, the current item, and the last item on the
* list.
*/
strlist_t *head, *curl, *last;
/* Lists of nameservers and search domains. Unfortunately they must be
* per-connection, since otherwise seperate clients could race against
* one another to write out unpredictable data.
*/
strlist_t *namesvrs, *domains;
/* Symbolic name of the interface associated with a connection. */
char ifnam[IFNAMSIZ];
/* Per-connection buffer. */
char ibuf[MAX_BUF];
};
#endif /* IFCHD_DEFINES_H_ */ #endif /* IFCHD_DEFINES_H_ */

View File

@ -80,22 +80,12 @@ enum states {
STATE_WINS STATE_WINS
}; };
struct ifchd_client clients[SOCK_QUEUE];
static int epollfd, signalFd; static int epollfd, signalFd;
/* Extra two event slots are for signalFd and the listen socket. */ /* Extra two event slots are for signalFd and the listen socket. */
static struct epoll_event events[SOCK_QUEUE+2]; static struct epoll_event events[SOCK_QUEUE+2];
/* Socket fd, current state, and idle time for connections. */
static int sks[SOCK_QUEUE], state[SOCK_QUEUE], idle_time[SOCK_QUEUE];
/* Per-connection buffers. */
static char ibuf[SOCK_QUEUE][MAX_BUF];
/*
* Per-connection pointers into the command lists. Respectively, the
* topmost item on the list, the current item, and the last item on the list.
*/
static strlist_t *head[SOCK_QUEUE], *curl[SOCK_QUEUE], *last[SOCK_QUEUE];
int resolv_conf_fd = -1; int resolv_conf_fd = -1;
/* int ntp_conf_fd = -1; */ /* int ntp_conf_fd = -1; */
@ -108,13 +98,6 @@ static pid_t peer_pid;
static int gflags_verbose = 0; static int gflags_verbose = 0;
/* Lists of nameservers and search domains. Unfortunately they must be
* per-connection, since otherwise seperate clients could race against
* one another to write out unpredictable data.
*/
static strlist_t *namesvrs[SOCK_QUEUE];
static strlist_t *domains[SOCK_QUEUE];
static void die_nulstr(strlist_t *p) static void die_nulstr(strlist_t *p)
{ {
if (!p) if (!p)
@ -229,8 +212,8 @@ static void write_resolve_conf(int idx)
if (lseek(resolv_conf_fd, 0, SEEK_SET) == -1) if (lseek(resolv_conf_fd, 0, SEEK_SET) == -1)
return; return;
write_resolve_list("nameserver ", namesvrs[idx]); write_resolve_list("nameserver ", clients[idx].namesvrs);
write_resolve_list("search ", domains[idx]); write_resolve_list("search ", clients[idx].domains);
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\n",
@ -294,7 +277,7 @@ static void perform_dns(int idx, char *str)
{ {
if (!str || resolv_conf_fd == -1) if (!str || resolv_conf_fd == -1)
return; return;
parse_list(idx, str, &(namesvrs[idx]), &write_resolve_conf); parse_list(idx, str, &clients[idx].namesvrs, &write_resolve_conf);
} }
/* Updates for print daemons are too non-standard to be useful. */ /* Updates for print daemons are too non-standard to be useful. */
@ -315,7 +298,7 @@ static void perform_domain(int idx, char *str)
{ {
if (!str || resolv_conf_fd == -1) if (!str || resolv_conf_fd == -1)
return; return;
parse_list(idx, str, &(domains[idx]), &write_resolve_conf); parse_list(idx, str, &clients[idx].domains, &write_resolve_conf);
} }
/* I don't think this can be done without a netfilter extension /* I don't think this can be done without a netfilter extension
@ -331,22 +314,38 @@ static void perform_ntpsrv(int idx, char *str)
static void perform_wins(int idx, char *str) static void perform_wins(int idx, char *str)
{} {}
/* Wipes all state associated with a given connection. */ static void ifchd_client_init(struct ifchd_client *p)
static void new_sk(int idx, int val)
{ {
sks[idx] = val; p->fd = -1;
memset(ibuf[idx], '\0', sizeof(ibuf[idx])); p->idle_time = time(NULL);
free_strlist(head[idx]); p->state = STATE_NOTHING;
free_strlist(namesvrs[idx]);
free_strlist(domains[idx]); memset(p->ibuf, 0, sizeof p->ibuf);
head[idx] = NULL; memset(p->ifnam, 0, sizeof p->ifnam);
curl[idx] = NULL; p->head = NULL;
last[idx] = NULL; p->curl = NULL;
namesvrs[idx] = NULL; p->last = NULL;
domains[idx] = NULL; p->namesvrs = NULL;
idle_time[idx] = time(NULL); p->domains = NULL;
state[idx] = STATE_NOTHING; }
clear_if_data(idx);
static void ifchd_client_wipe(struct ifchd_client *p)
{
if (p->fd >= 0) {
epoll_del(p->fd);
close(p->fd);
}
free_strlist(p->head);
free_strlist(p->namesvrs);
free_strlist(p->domains);
ifchd_client_init(p);
}
static void ifchd_client_new(struct ifchd_client *p, int fd)
{
ifchd_client_wipe(p);
p->fd = fd;
epoll_add(fd);
} }
/* Conditionally accepts a new connection and initializes data structures. */ /* Conditionally accepts a new connection and initializes data structures. */
@ -355,13 +354,14 @@ static void add_sk(int sk)
int i; int i;
if (authorized_peer(sk, peer_pid, peer_uid, peer_gid)) { if (authorized_peer(sk, peer_pid, peer_uid, peer_gid)) {
for (i = 0; i < SOCK_QUEUE; i++) for (i = 0; i < SOCK_QUEUE; i++) {
if (sks[i] == -1) { struct ifchd_client *p = &clients[i];
new_sk(i, sk); if (p->fd == -1) {
epoll_add(sk); ifchd_client_new(p, sk);
return; return;
} }
} }
}
close(sk); close(sk);
} }
@ -371,13 +371,11 @@ static void close_idle_sk(void)
int i; int i;
for (i=0; i<SOCK_QUEUE; i++) { for (i=0; i<SOCK_QUEUE; i++) {
if (sks[i] == -1) struct ifchd_client *p = &clients[i];
if (p->fd == -1)
continue; continue;
if (time(NULL) - idle_time[i] > CONN_TIMEOUT) { if (time(NULL) - p->idle_time > CONN_TIMEOUT)
epoll_del(sks[i]); ifchd_client_wipe(p);
close(sks[i]);
new_sk(i, -1);
}
} }
} }
@ -385,29 +383,30 @@ static void close_idle_sk(void)
static int stream_onto_list(int i) static int stream_onto_list(int i)
{ {
int e, s; int e, s;
struct ifchd_client *cl = &clients[i];
for (e = 0, s = 0; ibuf[i][e] != '\0'; e++) { for (e = 0, s = 0; cl->ibuf[e] != '\0'; e++) {
if (ibuf[i][e] == ':') { if (cl->ibuf[e] == ':') {
/* Zero-length command: skip. */ /* Zero-length command: skip. */
if (s == e) { if (s == e) {
s = e + 1; s = e + 1;
continue; continue;
} }
curl[i] = xmalloc(sizeof(strlist_t)); cl->curl = xmalloc(sizeof(strlist_t));
if (head[i] == NULL) { if (cl->head == NULL) {
head[i] = curl[i]; cl->head = cl->curl;
last[i] = NULL; cl->last = NULL;
} }
curl[i]->next = NULL; cl->curl->next = NULL;
if (last[i] != NULL) if (cl->last != NULL)
last[i]->next = curl[i]; cl->last->next = cl->curl;
curl[i]->str = xmalloc(e - s + 1); cl->curl->str = xmalloc(e - s + 1);
strlcpy(curl[i]->str, ibuf[i] + s, e - s + 1); strlcpy(cl->curl->str, cl->ibuf + s, e - s + 1);
last[i] = curl[i]; cl->last = cl->curl;
s = e + 1; s = e + 1;
} }
} }
@ -419,132 +418,133 @@ static int stream_onto_list(int i)
static void execute_list(int i) static void execute_list(int i)
{ {
char *p; char *p;
struct ifchd_client *cl = &clients[i];
for (;;) { for (;;) {
if (!curl[i]) if (!cl->curl)
break; break;
die_nulstr(curl[i]); die_nulstr(cl->curl);
p = curl[i]->str; p = cl->curl->str;
if (gflags_verbose) if (gflags_verbose)
log_line("execute_list - p = '%s'", p); log_line("execute_list - p = '%s'", p);
switch (state[i]) { switch (cl->state) {
case STATE_NOTHING: case STATE_NOTHING:
if (strncmp(p, CMD_INTERFACE, sizeof(CMD_INTERFACE)) == 0) if (strncmp(p, CMD_INTERFACE, sizeof(CMD_INTERFACE)) == 0)
state[i] = STATE_INTERFACE; cl->state = STATE_INTERFACE;
if (strncmp(p, CMD_IP, sizeof(CMD_IP)) == 0) if (strncmp(p, CMD_IP, sizeof(CMD_IP)) == 0)
state[i] = STATE_IP; cl->state = STATE_IP;
if (strncmp(p, CMD_SUBNET, sizeof(CMD_SUBNET)) == 0) if (strncmp(p, CMD_SUBNET, sizeof(CMD_SUBNET)) == 0)
state[i] = STATE_SUBNET; cl->state = STATE_SUBNET;
if (strncmp(p, CMD_TIMEZONE, sizeof(CMD_TIMEZONE)) == 0) if (strncmp(p, CMD_TIMEZONE, sizeof(CMD_TIMEZONE)) == 0)
state[i] = STATE_TIMEZONE; cl->state = STATE_TIMEZONE;
if (strncmp(p, CMD_ROUTER, sizeof(CMD_ROUTER)) == 0) if (strncmp(p, CMD_ROUTER, sizeof(CMD_ROUTER)) == 0)
state[i] = STATE_ROUTER; cl->state = STATE_ROUTER;
if (strncmp(p, CMD_DNS, sizeof(CMD_DNS)) == 0) if (strncmp(p, CMD_DNS, sizeof(CMD_DNS)) == 0)
state[i] = STATE_DNS; cl->state = STATE_DNS;
if (strncmp(p, CMD_LPRSVR, sizeof(CMD_LPRSVR)) == 0) if (strncmp(p, CMD_LPRSVR, sizeof(CMD_LPRSVR)) == 0)
state[i] = STATE_LPRSVR; cl->state = STATE_LPRSVR;
if (strncmp(p, CMD_HOSTNAME, sizeof(CMD_HOSTNAME)) == 0) if (strncmp(p, CMD_HOSTNAME, sizeof(CMD_HOSTNAME)) == 0)
state[i] = STATE_HOSTNAME; cl->state = STATE_HOSTNAME;
if (strncmp(p, CMD_DOMAIN, sizeof(CMD_DOMAIN)) == 0) if (strncmp(p, CMD_DOMAIN, sizeof(CMD_DOMAIN)) == 0)
state[i] = STATE_DOMAIN; cl->state = STATE_DOMAIN;
if (strncmp(p, CMD_IPTTL, sizeof(CMD_IPTTL)) == 0) if (strncmp(p, CMD_IPTTL, sizeof(CMD_IPTTL)) == 0)
state[i] = STATE_IPTTL; cl->state = STATE_IPTTL;
if (strncmp(p, CMD_MTU, sizeof(CMD_MTU)) == 0) if (strncmp(p, CMD_MTU, sizeof(CMD_MTU)) == 0)
state[i] = STATE_MTU; cl->state = STATE_MTU;
if (strncmp(p, CMD_BROADCAST, sizeof(CMD_BROADCAST)) == 0) if (strncmp(p, CMD_BROADCAST, sizeof(CMD_BROADCAST)) == 0)
state[i] = STATE_BROADCAST; cl->state = STATE_BROADCAST;
if (strncmp(p, CMD_NTPSVR, sizeof(CMD_NTPSVR)) == 0) if (strncmp(p, CMD_NTPSVR, sizeof(CMD_NTPSVR)) == 0)
state[i] = STATE_NTPSVR; cl->state = STATE_NTPSVR;
if (strncmp(p, CMD_WINS, sizeof(CMD_WINS)) == 0) if (strncmp(p, CMD_WINS, sizeof(CMD_WINS)) == 0)
state[i] = STATE_WINS; cl->state = STATE_WINS;
free_stritem(&(curl[i])); free_stritem(&cl->curl);
break; break;
case STATE_INTERFACE: case STATE_INTERFACE:
perform_interface(i, p); perform_interface(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_IP: case STATE_IP:
perform_ip(i, p); perform_ip(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_SUBNET: case STATE_SUBNET:
perform_subnet(i, p); perform_subnet(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_TIMEZONE: case STATE_TIMEZONE:
perform_timezone(i, p); perform_timezone(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_ROUTER: case STATE_ROUTER:
perform_router(i, p); perform_router(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_DNS: case STATE_DNS:
perform_dns(i, p); perform_dns(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_LPRSVR: case STATE_LPRSVR:
perform_lprsvr(i, p); perform_lprsvr(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_HOSTNAME: case STATE_HOSTNAME:
perform_hostname(i, p); perform_hostname(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_DOMAIN: case STATE_DOMAIN:
perform_domain(i, p); perform_domain(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_IPTTL: case STATE_IPTTL:
perform_ipttl(i, p); perform_ipttl(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_MTU: case STATE_MTU:
perform_mtu(i, p); perform_mtu(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_BROADCAST: case STATE_BROADCAST:
perform_broadcast(i, p); perform_broadcast(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_NTPSVR: case STATE_NTPSVR:
perform_ntpsrv(i, p); perform_ntpsrv(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
case STATE_WINS: case STATE_WINS:
perform_wins(i, p); perform_wins(i, p);
free_stritem(&(curl[i])); free_stritem(&cl->curl);
state[i] = STATE_NOTHING; cl->state = STATE_NOTHING;
break; break;
default: default:
@ -552,7 +552,7 @@ static void execute_list(int i)
break; break;
} }
} }
head[i] = curl[i]; cl->head = cl->curl;
} }
/* Opens a non-blocking listening socket with the appropriate properties. */ /* Opens a non-blocking listening socket with the appropriate properties. */
@ -690,18 +690,19 @@ static void process_client_fd(int fd)
char buf[MAX_BUF]; char buf[MAX_BUF];
int r, index, sqidx = -1; int r, index, sqidx = -1;
for (int j = 0; j < SOCK_QUEUE; ++j) { for (int j = 0; j < SOCK_QUEUE; ++j) {
if (sks[j] == fd) { if (clients[j].fd == fd) {
sqidx = j; sqidx = j;
break; break;
} }
} }
if (sqidx == -1) if (sqidx == -1)
suicide("epoll returned pending read for untracked fd"); suicide("epoll returned pending read for untracked fd");
struct ifchd_client *cl = &clients[sqidx];
idle_time[sqidx] = time(NULL); cl->idle_time = time(NULL);
memset(buf, '\0', sizeof buf); memset(buf, '\0', sizeof buf);
r = safe_read(sks[sqidx], buf, sizeof buf / 2 - 1); r = safe_read(cl->fd, buf, sizeof buf / 2 - 1);
if (r == 0) if (r == 0)
goto fail; goto fail;
else if (r < 0) { else if (r < 0) {
@ -713,31 +714,29 @@ static void process_client_fd(int fd)
/* Discard everything and close connection if we risk overflow. /* Discard everything and close connection if we risk overflow.
* This approach is maximally conservative... worst case is that * This approach is maximally conservative... worst case is that
* some client requests will get dropped. */ * some client requests will get dropped. */
index = strlen(ibuf[sqidx]); index = strlen(cl->ibuf);
if (index + strlen(buf) > sizeof buf - 2) if (index + strlen(buf) > sizeof buf - 2)
goto fail; goto fail;
/* Append new stream input avoiding overflow. */ /* Append new stream input avoiding overflow. */
strlcpy(ibuf[sqidx] + index, buf, sizeof ibuf[sqidx] - index); strlcpy(cl->ibuf + index, buf, sizeof cl->ibuf - index);
/* Decompose ibuf contents onto strlist. */ /* Decompose ibuf contents onto strlist. */
index = stream_onto_list(sqidx); index = stream_onto_list(sqidx);
/* Remove everything that we've parsed into the list. */ /* Remove everything that we've parsed into the list. */
strlcpy(buf, ibuf[sqidx] + index, sizeof buf); strlcpy(buf, cl->ibuf + index, sizeof buf);
strlcpy(ibuf[sqidx], buf, sizeof ibuf[sqidx]); strlcpy(cl->ibuf, buf, sizeof cl->ibuf);
/* Now we have a strlist of commands and arguments. /* Now we have a strlist of commands and arguments.
* Decompose and execute it. */ * Decompose and execute it. */
if (!head[sqidx]) if (!cl->head)
return; return;
curl[sqidx] = head[sqidx]; cl->curl = cl->head;
execute_list(sqidx); execute_list(sqidx);
return; return;
fail: fail:
epoll_del(sks[sqidx]); ifchd_client_wipe(cl);
close(sks[sqidx]);
new_sk(sqidx, -1);
} }
/* Core function that handles connections, gathers input, and calls /* Core function that handles connections, gathers input, and calls
@ -748,8 +747,7 @@ static void dispatch_work(void)
/* Initialize all structures to blank state. */ /* Initialize all structures to blank state. */
for (int i = 0; i < SOCK_QUEUE; i++) for (int i = 0; i < SOCK_QUEUE; i++)
sks[i] = -1; ifchd_client_init(&clients[i]);
initialize_if_data();
lsock = get_listen(); lsock = get_listen();
@ -1002,11 +1000,8 @@ int main(int argc, char** argv) {
dispatch_work(); dispatch_work();
/* Explicitly freed so memory debugger output has less static. */ /* Explicitly freed so memory debugger output has less static. */
for (c=0; c<SOCK_QUEUE; ++c) { for (size_t i = 0; i < SOCK_QUEUE; ++i)
free_strlist(head[c]); ifchd_client_wipe(&clients[i]);
free_strlist(namesvrs[c]);
free_strlist(domains[c]);
}
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }

View File

@ -51,25 +51,9 @@
#include "ifch_proto.h" #include "ifch_proto.h"
#include "strl.h" #include "strl.h"
/* Symbolic name of the interface associated with a connection. */ extern struct ifchd_client clients[SOCK_QUEUE];
static char ifnam[SOCK_QUEUE][IFNAMSIZ];
static strlist_t *okif; static strlist_t *okif;
/* Clear a specified ifnam structure. */
void clear_if_data(int idx)
{
memset(ifnam[idx], '\0', IFNAMSIZ);
}
/* Clear all ifnam structures. */
void initialize_if_data(void)
{
int i;
for (i = 0; i < SOCK_QUEUE; i++) {
clear_if_data(i);
}
}
/* Adds to the list of interface names ifchd clients are allowed to change. */ /* Adds to the list of interface names ifchd clients are allowed to change. */
void add_permitted_if(char *s) void add_permitted_if(char *s)
{ {
@ -128,8 +112,8 @@ void perform_interface(int idx, char *str)
return; return;
/* Update interface name. */ /* Update interface name. */
memset(ifnam[idx], '\0', IFNAMSIZ); memset(clients[idx].ifnam, '\0', IFNAMSIZ);
strlcpy(ifnam[idx], str, IFNAMSIZ); strlcpy(clients[idx].ifnam, str, IFNAMSIZ);
} }
static int set_if_flag(int idx, short flag) static int set_if_flag(int idx, short flag)
@ -137,27 +121,27 @@ static int set_if_flag(int idx, short flag)
int fd, ret = -1; int fd, ret = -1;
struct ifreq ifrt; struct ifreq ifrt;
if (!is_permitted(ifnam[idx])) if (!is_permitted(clients[idx].ifnam))
goto out0; goto out0;
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\n",
ifnam[idx], strerror(errno)); clients[idx].ifnam, strerror(errno));
goto out0; goto out0;
} }
strlcpy(ifrt.ifr_name, ifnam[idx], IFNAMSIZ); strlcpy(ifrt.ifr_name, clients[idx].ifnam, IFNAMSIZ);
if (ioctl(fd, SIOCGIFFLAGS, &ifrt) < 0) { if (ioctl(fd, SIOCGIFFLAGS, &ifrt) < 0) {
log_line("%s: unknown interface: %s\n", ifnam[idx], strerror(errno)); log_line("%s: unknown interface: %s\n", clients[idx].ifnam, strerror(errno));
goto out1; goto out1;
} }
if (((ifrt.ifr_flags & flag ) ^ flag) & flag) { if (((ifrt.ifr_flags & flag ) ^ flag) & flag) {
strlcpy(ifrt.ifr_name, ifnam[idx], IFNAMSIZ); strlcpy(ifrt.ifr_name, clients[idx].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\n",
ifnam[idx], strerror(errno)); clients[idx].ifnam, strerror(errno));
goto out1; goto out1;
} }
} else } else
@ -179,14 +163,14 @@ void perform_ip(int idx, char *str)
if (!str) if (!str)
return; return;
if (!is_permitted(ifnam[idx])) if (!is_permitted(clients[idx].ifnam))
return; return;
if (!inet_pton(AF_INET, str, &ipaddr)) if (!inet_pton(AF_INET, str, &ipaddr))
return; return;
if (set_if_flag(idx, (IFF_UP | IFF_RUNNING))) if (set_if_flag(idx, (IFF_UP | IFF_RUNNING)))
return; return;
strlcpy(ifrt.ifr_name, ifnam[idx], IFNAMSIZ); strlcpy(ifrt.ifr_name, clients[idx].ifnam, IFNAMSIZ);
memset(&sin, 0, sizeof(struct sockaddr)); memset(&sin, 0, sizeof(struct sockaddr));
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr = ipaddr; sin.sin_addr = ipaddr;
@ -195,12 +179,12 @@ void perform_ip(int idx, 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\n",
ifnam[idx], strerror(errno)); clients[idx].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\n",
ifnam[idx], strerror(errno)); clients[idx].ifnam, strerror(errno));
close(fd); close(fd);
} }
@ -214,12 +198,12 @@ void perform_subnet(int idx, char *str)
if (!str) if (!str)
return; return;
if (!is_permitted(ifnam[idx])) if (!is_permitted(clients[idx].ifnam))
return; return;
if (!inet_pton(AF_INET, str, &subnet)) if (!inet_pton(AF_INET, str, &subnet))
return; return;
strlcpy(ifrt.ifr_name, ifnam[idx], IFNAMSIZ); strlcpy(ifrt.ifr_name, clients[idx].ifnam, IFNAMSIZ);
memset(&sin, 0, sizeof(struct sockaddr)); memset(&sin, 0, sizeof(struct sockaddr));
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr = subnet; sin.sin_addr = subnet;
@ -228,14 +212,14 @@ void perform_subnet(int idx, 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\n",
ifnam[idx], strerror(errno)); clients[idx].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\n",
ifnam[idx], strerror(errno)); clients[idx].ifnam, strerror(errno));
} }
close(fd); close(fd);
} }
@ -251,7 +235,7 @@ void perform_router(int idx, char *str)
if (!str) if (!str)
return; return;
if (!is_permitted(ifnam[idx])) if (!is_permitted(clients[idx].ifnam))
return; return;
if (!inet_pton(AF_INET, str, &router)) if (!inet_pton(AF_INET, str, &router))
return; return;
@ -269,19 +253,19 @@ void perform_router(int idx, char *str)
rt.rt_flags = RTF_UP | RTF_GATEWAY; rt.rt_flags = RTF_UP | RTF_GATEWAY;
if (mask->sin_addr.s_addr == 0xffffffff) rt.rt_flags |= RTF_HOST; if (mask->sin_addr.s_addr == 0xffffffff) rt.rt_flags |= RTF_HOST;
rt.rt_dev = ifnam[idx]; rt.rt_dev = clients[idx].ifnam;
rt.rt_metric = 1; rt.rt_metric = 1;
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\n",
ifnam[idx], strerror(errno)); clients[idx].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\n",
ifnam[idx], strerror(errno)); clients[idx].ifnam, strerror(errno));
} }
close(fd); close(fd);
} }
@ -294,21 +278,21 @@ void perform_mtu(int idx, char *str)
if (!str) if (!str)
return; return;
if (!is_permitted(ifnam[idx])) if (!is_permitted(clients[idx].ifnam))
return; return;
mtu = strtol(str, NULL, 10); mtu = strtol(str, NULL, 10);
ifrt.ifr_mtu = mtu; ifrt.ifr_mtu = mtu;
strlcpy(ifrt.ifr_name, ifnam[idx], IFNAMSIZ); strlcpy(ifrt.ifr_name, clients[idx].ifnam, IFNAMSIZ);
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\n",
ifnam[idx], strerror(errno)); clients[idx].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", ifnam[idx], mtu, log_line("%s: failed to set MTU (%d): %s\n", clients[idx].ifnam, mtu,
strerror(errno)); strerror(errno));
close(fd); close(fd);
} }
@ -322,12 +306,12 @@ void perform_broadcast(int idx, char *str)
if (!str) if (!str)
return; return;
if (!is_permitted(ifnam[idx])) if (!is_permitted(clients[idx].ifnam))
return; return;
if (!inet_pton(AF_INET, str, &broadcast)) if (!inet_pton(AF_INET, str, &broadcast))
return; return;
strlcpy(ifrt.ifr_name, ifnam[idx], IFNAMSIZ); strlcpy(ifrt.ifr_name, clients[idx].ifnam, IFNAMSIZ);
memset(&sin, 0, sizeof(struct sockaddr)); memset(&sin, 0, sizeof(struct sockaddr));
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr = broadcast; sin.sin_addr = broadcast;
@ -335,11 +319,11 @@ void perform_broadcast(int idx, 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", ifnam[idx], strerror(errno)); log_line("%s: (perform_broadcast) failed to open interface socket: %s\n", clients[idx].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\n",
ifnam[idx], strerror(errno)); clients[idx].ifnam, strerror(errno));
close(fd); close(fd);
} }