Keep AF_UNIX and file-based interfaces up whenever config re-loads

Whenever the daemon re-loads its config, it keeps any socket-based
(AF_INET) SOCK_DGRAM interfaces open that are matched by the new config,
but it used to close and then re-open all local (AF_UNIX) interfaces and
file-based interfaces such as SOCK_FILE dummy files and SOCK_STREAM
device files.  This made it very difficult to develop the new
'routejava' test suite, because the Java API test harness always causes
a config re-load when it sets the REST API user/password in the config,
which caused the local socket interfaces to bounce, which interfered
with the reachability of nodes.

Now, local socket and file-based interfaces remain up after a config
re-load, as long as they are still matched by the new configuration.

Added INFO messages for interfaces that remain up after a config
re-load, and tweak interface up/down INFO messages to be consistent.
This commit is contained in:
Andrew Bettison 2018-04-04 23:20:28 +09:30
parent 1930c51da4
commit cf9e0b4730
5 changed files with 255 additions and 114 deletions

View File

@ -788,6 +788,7 @@ int cf_fmt_socket_type(const char **textp, const short *typep)
case SOCK_DGRAM: t = "dgram"; break; case SOCK_DGRAM: t = "dgram"; break;
case SOCK_STREAM: t = "stream"; break; case SOCK_STREAM: t = "stream"; break;
case SOCK_FILE: t = "file"; break; case SOCK_FILE: t = "file"; break;
case SOCK_EXT: t = "external"; break;
} }
if (!t) if (!t)
return CFINVALID; return CFINVALID;

View File

@ -2,6 +2,7 @@
Serval DNA overlay network interfaces Serval DNA overlay network interfaces
Copyright (C) 2010 Paul Gardner-Stephen Copyright (C) 2010 Paul Gardner-Stephen
Copyright (C) 2012-2013 Serval Project Inc. Copyright (C) 2012-2013 Serval Project Inc.
Copyright (C) 2016-2018 Flinders University
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
@ -95,8 +96,10 @@ void overlay_interface_close(overlay_interface *interface)
interface->state=INTERFACE_STATE_DOWN; interface->state=INTERFACE_STATE_DOWN;
INFOF("Interface %s addr %s is down", INFOF("Interface %s is down: type %s addr %s",
interface->name, alloca_socket_address(&interface->address)); interface->name,
interface_type_name(interface->interface_type),
alloca_socket_address(&interface->address));
unsigned i, count=0; unsigned i, count=0;
for (i=0;i<OVERLAY_MAX_INTERFACES;i++){ for (i=0;i<OVERLAY_MAX_INTERFACES;i++){
@ -166,6 +169,35 @@ void interface_state_html(struct strbuf *b, struct overlay_interface *interface)
strbuf_sprintf(b, "RX: %d<br>", interface->recv_count); strbuf_sprintf(b, "RX: %d<br>", interface->recv_count);
} }
static int
form_dummy_file_path(char *buf, size_t bufsiz, const char *configured_file_path) {
assert(configured_file_path);
assert(configured_file_path[0]);
return formf_serval_tmp_path(buf, bufsiz, "%s/%s", config.server.interface_path, configured_file_path);
}
static int
form_dgram_file_socket_address(struct socket_address *addr, const char *file_path) {
assert(file_path[0]);
if (!FORMF_SERVAL_RUN_PATH(addr->local.sun_path, "%s/%s", config.server.interface_path, file_path))
return 0;
addr->local.sun_family = AF_UNIX;
addr->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(addr->local.sun_path) + 1;
return 1;
}
static void
form_broadcast_file_socket_address(struct socket_address *broadcast, struct socket_address *addr) {
assert(addr->local.sun_family == AF_UNIX);
assert(addr->addrlen >= offsetof(struct sockaddr_un, sun_path) + 2);
assert(addr->addrlen <= sizeof(addr->local));
*broadcast = *addr;
size_t len = broadcast->addrlen - offsetof(struct sockaddr_un, sun_path) - 1;
while (len && broadcast->local.sun_path[len] != '/')
broadcast->local.sun_path[len--] = '\0';
broadcast->addrlen = offsetof(struct sockaddr_un, sun_path) + len + 2;
}
// create a socket with options common to all our UDP sockets // create a socket with options common to all our UDP sockets
static int static int
overlay_bind_socket(const struct socket_address *addr){ overlay_bind_socket(const struct socket_address *addr){
@ -294,19 +326,19 @@ overlay_interface * overlay_interface_find(struct in_addr addr, int return_defau
} }
// find an interface by name and/or exact address // find an interface by name and/or exact address
overlay_interface * overlay_interface_find_name_addr(const char *name, struct socket_address *addr){ overlay_interface * overlay_interface_find_name_file_addr(const char *name, const char *file_path, struct socket_address *addr) {
int i; assert(name || file_path || addr);
assert(name || addr); assert(!name || name[0]); // name is non-empty if given
for(i = 0; i < OVERLAY_MAX_INTERFACES; i++){ assert(!file_path || file_path[0]); // file_path is non-empty if given
if (overlay_interfaces[i].state!=INTERFACE_STATE_UP) unsigned i;
continue; for (i = 0; i < OVERLAY_MAX_INTERFACES; ++i) {
struct overlay_interface *interface = &overlay_interfaces[i];
if ((!addr || cmp_sockaddr(addr, &overlay_interfaces[i].address)==0) if (interface->state == INTERFACE_STATE_UP
&& (!name || strcasecmp(overlay_interfaces[i].name, name)==0)){ && (!addr || cmp_sockaddr(addr, &interface->address) == 0)
return &overlay_interfaces[i]; && (!file_path || strcasecmp(file_path, interface->file_path) == 0)
} && (!name || strcasecmp(name, interface->name) == 0))
return interface;
} }
return NULL; return NULL;
} }
@ -531,7 +563,8 @@ int overlay_interface_configure(struct overlay_interface *interface, const struc
*/ */
int int
overlay_interface_init(const char *name, overlay_interface_init(const char *name,
short detected_type, const char *file_path,
short interface_type,
const struct socket_address *addr, const struct socket_address *addr,
const struct socket_address *netmask, const struct socket_address *netmask,
const struct socket_address *broadcast, const struct socket_address *broadcast,
@ -557,7 +590,9 @@ overlay_interface_init(const char *name,
buf_strncpy_nul(interface->name, name); buf_strncpy_nul(interface->name, name);
interface->detected_type = detected_type; buf_strncpy_nul(interface->file_path, file_path);
interface->interface_type = interface_type;
interface->destination = new_destination(interface); interface->destination = new_destination(interface);
interface->alarm.poll.fd=-1; interface->alarm.poll.fd=-1;
@ -578,7 +613,6 @@ overlay_interface_init(const char *name,
FATALF("Invalid interface definition. We only support dropping packets on dummy file interfaces"); FATALF("Invalid interface definition. We only support dropping packets on dummy file interfaces");
interface->netmask = netmask->inet.sin_addr; interface->netmask = netmask->inet.sin_addr;
interface->local_echo = 1; interface->local_echo = 1;
overlay_bind_interface(interface); overlay_bind_interface(interface);
break; break;
@ -589,16 +623,14 @@ overlay_interface_init(const char *name,
case SOCK_STREAM: case SOCK_STREAM:
case SOCK_FILE: case SOCK_FILE:
{ {
char read_file[1024]; assert(interface->file_path[0]);
interface->local_echo = ifconfig->point_to_point?0:1; interface->local_echo = ifconfig->point_to_point?0:1;
if (!FORMF_SERVAL_TMP_PATH(read_file, "%s/%s", config.server.interface_path, ifconfig->file)) if ((interface->alarm.poll.fd = open(interface->file_path, O_APPEND|O_RDWR)) == -1) {
return -1;
if ((interface->alarm.poll.fd = open(read_file, O_APPEND|O_RDWR)) == -1) {
if (errno == ENOENT && ifconfig->socket_type == SOCK_FILE) { if (errno == ENOENT && ifconfig->socket_type == SOCK_FILE) {
cleanup_ret = 1; cleanup_ret = 1;
WARNF("dummy interface not enabled: %s does not exist", alloca_str_toprint(read_file)); WARNF("dummy interface %s not enabled: %s does not exist", interface->name, alloca_str_toprint(interface->file_path));
} else { } else {
cleanup_ret = WHYF_perror("file interface not enabled: open(%s, O_APPEND|O_RDWR)", alloca_str_toprint(read_file)); cleanup_ret = WHYF_perror("dummy interface %s not enabled: open(%s, O_APPEND|O_RDWR)", interface->name, alloca_str_toprint(interface->file_path));
} }
goto cleanup; goto cleanup;
} }
@ -612,7 +644,6 @@ overlay_interface_init(const char *name,
interface->alarm.poll.events=POLLIN|POLLOUT; interface->alarm.poll.events=POLLIN|POLLOUT;
watch(&interface->alarm); watch(&interface->alarm);
break; break;
case SOCK_FILE: case SOCK_FILE:
/* Seek to end of file as initial reading point */ /* Seek to end of file as initial reading point */
interface->recv_offset = lseek(interface->alarm.poll.fd,0,SEEK_END); interface->recv_offset = lseek(interface->alarm.poll.fd,0,SEEK_END);
@ -625,9 +656,9 @@ overlay_interface_init(const char *name,
return -1; return -1;
interface->state=INTERFACE_STATE_UP; interface->state=INTERFACE_STATE_UP;
INFOF("Interface %s type %s addr %s, is up", INFOF("Interface %s is up: type %s addr %s",
interface->name, interface->name,
interface_type_name(interface->detected_type), interface_type_name(interface->interface_type),
alloca_socket_address(addr)); alloca_socket_address(addr));
INFOF("Allowing a maximum of %d packets every %"PRId64"ms", INFOF("Allowing a maximum of %d packets every %"PRId64"ms",
interface->destination->transfer_limit.burst_size, interface->destination->transfer_limit.burst_size,
@ -1072,23 +1103,64 @@ int overlay_broadcast_ensemble(struct network_destination *destination, struct o
} }
} }
static const struct config_network_interface *find_interface_config(const char *name, short detected_type, int socket_type) static int match_interface_config(const struct config_network_interface *ifconfig,
int socket_type,
short interface_type,
const char *name,
const char *file_path)
{
assert (name || file_path);
if (ifconfig->socket_type != socket_type)
return 0;
if (ifconfig->match_type != OVERLAY_INTERFACE_ANY
&& ifconfig->match_type != interface_type
&& interface_type != OVERLAY_INTERFACE_UNKNOWN)
return 0;
if (name) {
unsigned i;
for (i = 0; i < ifconfig->match.patc && fnmatch(ifconfig->match.patv[i], name, 0) != 0; ++i)
;
if (i && i == ifconfig->match.patc)
return 0;
}
if (file_path && ifconfig->file[0]) {
switch (ifconfig->socket_type) {
case SOCK_DGRAM:
{
struct socket_address addr;
if (!form_dgram_file_socket_address(&addr, ifconfig->file))
return 0;
if (strcmp(addr.local.sun_path, file_path) != 0)
return 0;
}
break;
case SOCK_STREAM:
case SOCK_FILE:
{
char ifconfig_file_path[256];
if (!form_dummy_file_path(ifconfig_file_path, sizeof ifconfig_file_path, ifconfig->file))
return 0;
if (strcmp(ifconfig_file_path, file_path) != 0)
return 0;
}
break;
case SOCK_EXT:
return 0;
default:
return 0;
}
}
return 1;
}
static const struct config_network_interface *
find_first_matching_interface_config(int socket_type, short interface_type, const char *name, const char *file_path)
{ {
// Find a matching non-dummy interface rule.
unsigned i; unsigned i;
for (i = 0; i < config.interfaces.ac; ++i) { for (i = 0; i < config.interfaces.ac; ++i) {
const struct config_network_interface *ifconfig = &config.interfaces.av[i].value; const struct config_network_interface *ifconfig = &config.interfaces.av[i].value;
if (ifconfig->socket_type==socket_type && ( if (match_interface_config(ifconfig, socket_type, interface_type, name, file_path))
detected_type == ifconfig->match_type return ifconfig;
|| detected_type == OVERLAY_INTERFACE_UNKNOWN
|| ifconfig->match_type == OVERLAY_INTERFACE_ANY
)) {
unsigned j;
for (j = 0; j < ifconfig->match.patc; ++j){
if (fnmatch(ifconfig->match.patv[j], name, 0) == 0)
return ifconfig;
}
}
} }
return NULL; return NULL;
} }
@ -1100,9 +1172,12 @@ overlay_interface_register(const char *name,
const struct socket_address *netmask, const struct socket_address *netmask,
struct socket_address *broadcast) struct socket_address *broadcast)
{ {
short detected_type = OVERLAY_INTERFACE_UNKNOWN; assert(name);
assert(name[0]);
short detected_interface_type = OVERLAY_INTERFACE_UNKNOWN;
#ifdef linux #ifdef linux
detected_type = OVERLAY_INTERFACE_OTHER; detected_interface_type = OVERLAY_INTERFACE_OTHER;
// Try to determine the interface type from /sys/class/net/<name>/ // Try to determine the interface type from /sys/class/net/<name>/
char path[256]; char path[256];
struct stat file_stat; struct stat file_stat;
@ -1110,7 +1185,7 @@ overlay_interface_register(const char *name,
strbuf_sprintf(sb, "/sys/class/net/%s/phy80211", name); strbuf_sprintf(sb, "/sys/class/net/%s/phy80211", name);
if (stat(path, &file_stat)==0){ if (stat(path, &file_stat)==0){
// This interface has a symlink to a physical wifi device // This interface has a symlink to a physical wifi device
detected_type = OVERLAY_INTERFACE_WIFI; detected_interface_type = OVERLAY_INTERFACE_WIFI;
}else{ }else{
WARNF_perror("stat(%s)", path); WARNF_perror("stat(%s)", path);
strbuf_reset(sb); strbuf_reset(sb);
@ -1119,15 +1194,16 @@ overlay_interface_register(const char *name,
if (fd >= 0){ if (fd >= 0){
// this interface implements the ethtool get_settings method // this interface implements the ethtool get_settings method
// we *could* read this file to set config based on link speed // we *could* read this file to set config based on link speed
detected_type = OVERLAY_INTERFACE_ETHERNET; detected_interface_type = OVERLAY_INTERFACE_ETHERNET;
close(fd); close(fd);
}else{ }else{
WARNF_perror("open(%s)", path); WARNF_perror("open(%s)", path);
} }
} }
#endif #endif
// Find the matching non-dummy interface rule. // find the first socket interface config rule that matches the name and detected interface type
const struct config_network_interface *ifconfig = find_interface_config(name, detected_type, SOCK_DGRAM); const struct config_network_interface *ifconfig =
find_first_matching_interface_config(SOCK_DGRAM, detected_interface_type, name, NULL);
if (!ifconfig) { if (!ifconfig) {
DEBUGF(overlayinterfaces, "Interface %s does not match any rule", name); DEBUGF(overlayinterfaces, "Interface %s does not match any rule", name);
return 0; return 0;
@ -1136,46 +1212,43 @@ overlay_interface_register(const char *name,
DEBUGF(overlayinterfaces, "Interface %s is explicitly excluded", name); DEBUGF(overlayinterfaces, "Interface %s is explicitly excluded", name);
return 0; return 0;
} }
// fill in the configured port number
if (addr->addr.sa_family==AF_INET) if (addr->addr.sa_family==AF_INET)
addr->inet.sin_port = htons(ifconfig->port); addr->inet.sin_port = htons(ifconfig->port);
if (broadcast->addr.sa_family==AF_INET) if (broadcast->addr.sa_family==AF_INET)
broadcast->inet.sin_port = htons(ifconfig->port); broadcast->inet.sin_port = htons(ifconfig->port);
struct overlay_interface *interface = overlay_interface_find_name_addr(name, addr);
// nothing to do if a matching interface is already up // nothing to do if a matching interface is already up
if (interface) if (overlay_interface_find_name_file_addr(name, NULL, addr))
return 0; return 0;
/* New interface, so register it */ // new interface, so register it
if (overlay_interface_init(name, detected_type, addr, netmask, broadcast, ifconfig)) if (overlay_interface_init(name, NULL, detected_interface_type, addr, netmask, broadcast, ifconfig))
return WHYF("Could not initialise newly seen interface %s", name); return WHYF("Could not initialise newly seen interface %s", name);
overlay_interface_init_any(ifconfig->port); overlay_interface_init_any(ifconfig->port);
inet_up_count++; inet_up_count++;
return 0; return 0;
} }
#ifdef HAVE_LINUX_NETLINK_H #ifdef HAVE_LINUX_NETLINK_H
static int interface_unregister(const char *name, static void interface_unregister(const char *name, struct socket_address *addr)
struct socket_address *addr
)
{ {
// Find the matching non-dummy interface rule. // close all socket interfaces whose names and addresses both match
const struct config_network_interface *ifconfig = find_interface_config(name, OVERLAY_INTERFACE_UNKNOWN, SOCK_DGRAM); unsigned i;
if (!ifconfig) for (i = 0; i < OVERLAY_MAX_INTERFACES; i++) {
return 0; struct overlay_interface *interface = &overlay_interfaces[i];
if (interface->state == INTERFACE_STATE_UP
if (addr->addr.sa_family==AF_INET) && match_interface_config(&interface->ifconfig, SOCK_DGRAM, OVERLAY_INTERFACE_UNKNOWN, name, NULL)) {
addr->inet.sin_port = htons(ifconfig->port); if (addr->addr.sa_family == AF_INET)
addr->inet.sin_port = htons(interface->ifconfig.port);
struct overlay_interface *interface = overlay_interface_find_name_addr(name, addr); if (cmp_sockaddr(addr, &interface->address) == 0)
if (interface) overlay_interface_close(interface);
overlay_interface_close(interface); }
}
return 0;
} }
DEFINE_ALARM(netlink_poll); DEFINE_ALARM(netlink_poll);
@ -1393,11 +1466,15 @@ void overlay_interface_discover(struct sched_ent *alarm)
static void file_interface_init(const struct config_network_interface *ifconfig) static void file_interface_init(const struct config_network_interface *ifconfig)
{ {
assert(ifconfig->file[0]);
char file_path[256];
struct socket_address addr, netmask, broadcast; struct socket_address addr, netmask, broadcast;
bzero(&addr, sizeof addr); bzero(&addr, sizeof addr);
bzero(&netmask, sizeof addr); bzero(&netmask, sizeof addr);
bzero(&broadcast, sizeof broadcast); bzero(&broadcast, sizeof broadcast);
switch(ifconfig->socket_type){ switch(ifconfig->socket_type){
case SOCK_FILE: case SOCK_FILE:
// use a fake inet address // use a fake inet address
@ -1415,37 +1492,35 @@ static void file_interface_init(const struct config_network_interface *ifconfig)
broadcast.inet.sin_family=AF_INET; broadcast.inet.sin_family=AF_INET;
broadcast.inet.sin_port=htons(ifconfig->port); broadcast.inet.sin_port=htons(ifconfig->port);
broadcast.inet.sin_addr.s_addr=ifconfig->dummy_address.s_addr | ~ifconfig->dummy_netmask.s_addr; broadcast.inet.sin_addr.s_addr=ifconfig->dummy_address.s_addr | ~ifconfig->dummy_netmask.s_addr;
break;
FALLTHROUGH;
case SOCK_STREAM: case SOCK_STREAM:
if (!form_dummy_file_path(file_path, sizeof file_path, ifconfig->file))
return; // ignore if path is too long
break; break;
case SOCK_DGRAM: case SOCK_DGRAM:
{ {
// use a local dgram socket // use a local dgram socket
// no abstract sockets for now // no abstract sockets for now
if (!FORMF_SERVAL_RUN_PATH(addr.local.sun_path, "%s/%s", config.server.interface_path, ifconfig->file)) if (!form_dgram_file_socket_address(&addr, ifconfig->file))
return; return;
form_broadcast_file_socket_address(&broadcast, &addr);
assert(strlen(addr.local.sun_path) + 1 <= sizeof file_path);
strcpy(file_path, addr.local.sun_path);
unlink(addr.local.sun_path); unlink(addr.local.sun_path);
addr.local.sun_family=AF_UNIX;
size_t len = strlen(addr.local.sun_path);
addr.addrlen = offsetof(struct sockaddr_un, sun_path) + len + 1;
broadcast = addr;
while(len && broadcast.local.sun_path[len]!='/')
broadcast.local.sun_path[len--]='\0';
broadcast.addrlen = offsetof(struct sockaddr_un, sun_path) + len + 2;
break; break;
} }
default: default:
// ignore return; // ignore
return;
} }
overlay_interface_init(ifconfig->file, OVERLAY_INTERFACE_UNKNOWN, &addr, &netmask, &broadcast, ifconfig); // nothing to do if a matching interface is already up
if (overlay_interface_find_name_file_addr(ifconfig->file, file_path, &addr))
return;
overlay_interface_init(ifconfig->file, file_path, OVERLAY_INTERFACE_UNKNOWN, &addr, &netmask, &broadcast, ifconfig);
} }
static void rescan_soon(time_ms_t run_at){ static void rescan_soon(time_ms_t run_at){
@ -1471,35 +1546,85 @@ static void overlay_interface_config_change()
if (!serverMode) if (!serverMode)
return; return;
// bring down all interfaces that no longer match any configuration
unsigned i; unsigned i;
int real_interface = 0; for (i = 0; i < OVERLAY_MAX_INTERFACES; i++) {
struct overlay_interface *interface = &overlay_interfaces[i];
// bring down any interface that no longer matches configuration if (interface->state == INTERFACE_STATE_UP) {
for (i = 0; i < OVERLAY_MAX_INTERFACES; i++){ switch (interface->ifconfig.socket_type) {
if (overlay_interfaces[i].state!=INTERFACE_STATE_UP || case SOCK_EXT:
overlay_interfaces[i].ifconfig.socket_type == SOCK_EXT) // leave external interfaces alone... they do not get configured from the config file, but
continue; // from packets received from MDP clients
INFOF("Interface %s remains up: external %s", interface->name, alloca_socket_address(&interface->address));
const struct config_network_interface *ifconfig = find_interface_config( break;
overlay_interfaces[i].name,
OVERLAY_INTERFACE_UNKNOWN, case SOCK_DGRAM:
overlay_interfaces[i].ifconfig.socket_type {
); const struct config_network_interface *ifconfig = NULL;
int remain = 0;
if (!ifconfig || ifconfig->exclude){ switch (interface->address.local.sun_family) {
overlay_interface_close(&overlay_interfaces[i]); case AF_UNIX:
continue; ifconfig = find_first_matching_interface_config(SOCK_DGRAM, interface->interface_type, NULL, interface->address.local.sun_path);
remain = ifconfig && !ifconfig->exclude;
break;
case AF_INET:
ifconfig = find_first_matching_interface_config(SOCK_DGRAM, interface->interface_type, interface->name, NULL);
remain = ifconfig && !ifconfig->exclude;
break;
default:
remain = 1; // leave interfaces with unknown addresses alone
break;
}
if (remain)
INFOF("Interface %s remains up: type %s addr %s",
interface->name,
interface_type_name(interface->interface_type),
alloca_socket_address(&interface->address));
else
overlay_interface_close(interface);
}
break;
case SOCK_STREAM:
case SOCK_FILE:
// find a config interface rule whose absolute path matches the current interface's absolute
// file path
{
assert(interface->file_path[0]);
const struct config_network_interface *ifconfig = find_first_matching_interface_config(
interface->ifconfig.socket_type,
interface->interface_type,
NULL,
interface->file_path);
if (ifconfig && !ifconfig->exclude)
INFOF("Interface %s remains up: type %s path %s",
interface->name,
interface_type_name(interface->interface_type),
interface->file_path);
else
overlay_interface_close(interface);
}
break;
default:
// leave interfaces with an unrecognised socket type alone
INFOF("Interface %s remains up: unrecognised socket_type=%#02x",
interface->name,
interface->ifconfig.socket_type);
break;
}
} }
} }
// create dummy file or AF_UNIX interfaces // create dummy file or AF_UNIX interfaces
int real_interface = 0;
for (i = 0; i < config.interfaces.ac; ++i) { for (i = 0; i < config.interfaces.ac; ++i) {
const struct config_network_interface *ifconfig = &config.interfaces.av[i].value; const struct config_network_interface *ifconfig = &config.interfaces.av[i].value;
if (ifconfig->exclude) if (ifconfig->exclude)
continue; continue;
// ignore real interfaces, we'll deal with them later // ignore real interfaces, we'll deal with them later
if (!*ifconfig->file) { if (!ifconfig->file[0]) {
real_interface = 1; real_interface = 1;
continue; continue;
} }

View File

@ -67,10 +67,24 @@ struct network_destination {
typedef struct overlay_interface { typedef struct overlay_interface {
struct sched_ent alarm; struct sched_ent alarm;
// depending on ifconfig.socket_type (and address.addr.sa_family):
// - for SOCK_DGRAM (AF_INET): the interface name
// - for SOCK_DGRAM (AF_UNIX): the configured socket path (short, usually relative)
// - for SOCK_FILE: not used (zero filled)
// - for SOCK_STREAM: not used (zero filled)
// - for SOCK_EXT: not used (zero filled)
char name[256]; char name[256];
short detected_type; // depending on ifconfig.socket_type (and address.addr.sa_family):
// - for SOCK_DGRAM (AF_INET): not used (zero filled)
// - for SOCK_DGRAM (AF_UNIX): the local socket path (absolute)
// - for SOCK_FILE: the absolute path of the configured dummy file
// - for SOCK_STREAM: the absolute path of the configured device file
// - for SOCK_EXT: not used (zero filled)
char file_path[256];
short interface_type; // OVERLAY_INTERFACE_ETHERNET etc.
off_t recv_offset; /* file offset */ off_t recv_offset; /* file offset */
int recv_count; int recv_count;
@ -78,7 +92,7 @@ typedef struct overlay_interface {
struct radio_link_state *radio_link_state; struct radio_link_state *radio_link_state;
struct config_network_interface ifconfig; struct config_network_interface ifconfig; // copy
char local_echo; char local_echo;
@ -117,6 +131,7 @@ int overlay_interface_configure(struct overlay_interface *interface, const struc
int int
overlay_interface_init(const char *name, overlay_interface_init(const char *name,
const char *file_path,
short detected_type, short detected_type,
const struct socket_address *addr, const struct socket_address *addr,
const struct socket_address *netmask, const struct socket_address *netmask,
@ -130,7 +145,7 @@ int overlay_interface_register(const char *name,
struct socket_address *broadcast); struct socket_address *broadcast);
overlay_interface * overlay_interface_get_default(); overlay_interface * overlay_interface_get_default();
overlay_interface * overlay_interface_find(struct in_addr addr, int return_default); overlay_interface * overlay_interface_find(struct in_addr addr, int return_default);
overlay_interface * overlay_interface_find_name_addr(const char *name, struct socket_address *addr); overlay_interface * overlay_interface_find_name_file_addr(const char *name, const char *file_path, struct socket_address *addr);
int overlay_interface_compare(overlay_interface *one, overlay_interface *two); int overlay_interface_compare(overlay_interface *one, overlay_interface *two);
int overlay_broadcast_ensemble(struct network_destination *destination, struct overlay_buffer *buffer); int overlay_broadcast_ensemble(struct network_destination *destination, struct overlay_buffer *buffer);
void interface_state_html(struct strbuf *b, struct overlay_interface *interface); void interface_state_html(struct strbuf *b, struct overlay_interface *interface);

View File

@ -94,7 +94,7 @@ struct network_destination *load_subscriber_address(struct subscriber *subscribe
const struct config_host *hostc = &config.hosts.av[i].value; const struct config_host *hostc = &config.hosts.av[i].value;
overlay_interface *interface = NULL; overlay_interface *interface = NULL;
if (*hostc->interface){ if (*hostc->interface){
interface = overlay_interface_find_name_addr(hostc->interface, NULL); interface = overlay_interface_find_name_file_addr(hostc->interface, NULL, NULL);
if (!interface){ if (!interface){
WARNF("Can't find configured interface %s", hostc->interface); WARNF("Can't find configured interface %s", hostc->interface);
return NULL; return NULL;

View File

@ -1412,9 +1412,9 @@ static void mdp_interface_packet(struct socket_address *client, struct mdp_heade
} }
if (result == CFOK || result == CFEMPTY){ if (result == CFOK || result == CFEMPTY){
struct overlay_interface *interface=overlay_interface_find_name_addr(NULL, client); struct overlay_interface *interface=overlay_interface_find_name_file_addr(NULL, NULL, client);
if (!interface){ if (!interface){
overlay_interface_init(ifconfig.match.patv[0], OVERLAY_INTERFACE_UNKNOWN, client, NULL, NULL, &ifconfig); overlay_interface_init(ifconfig.match.patv[0], NULL, OVERLAY_INTERFACE_UNKNOWN, client, NULL, NULL, &ifconfig);
}else{ }else{
// reconfigure the interface with new / current settings // reconfigure the interface with new / current settings
if (overlay_interface_configure(interface, &ifconfig)==-1) if (overlay_interface_configure(interface, &ifconfig)==-1)
@ -1423,12 +1423,12 @@ static void mdp_interface_packet(struct socket_address *client, struct mdp_heade
} }
}break; }break;
case MDP_INTERFACE_DOWN:{ case MDP_INTERFACE_DOWN:{
struct overlay_interface *interface=overlay_interface_find_name_addr(NULL, client); struct overlay_interface *interface=overlay_interface_find_name_file_addr(NULL, NULL, client);
if (interface) if (interface)
overlay_interface_close(interface); overlay_interface_close(interface);
}break; }break;
case MDP_INTERFACE_RECV:{ case MDP_INTERFACE_RECV:{
struct overlay_interface *interface=overlay_interface_find_name_addr(NULL, client); struct overlay_interface *interface=overlay_interface_find_name_file_addr(NULL, NULL, client);
if (interface){ if (interface){
struct socket_address addr; struct socket_address addr;
addr.addrlen = ob_get(payload); addr.addrlen = ob_get(payload);