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:
@ -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_ */
|
||||||
|
|
||||||
|
249
ifchd/ifchd.c
249
ifchd/ifchd.c
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user