mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-18 20:57:56 +00:00
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:
parent
1930c51da4
commit
cf9e0b4730
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user