Close interfaces on socket errors or when not detected

This commit is contained in:
Jeremy Lakeman 2012-07-25 16:53:44 +09:30
parent 74095e5356
commit 6e7c2196ba
4 changed files with 219 additions and 160 deletions

9
lsif.c
View File

@ -133,6 +133,7 @@ lsif(void) {
ifc.ifc_buf = buf;
if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) {
WHY_perror("ioctl(SIOCGIFCONF)");
close(sck);
return 1;
}
@ -163,8 +164,10 @@ lsif(void) {
}
/* Get broadcast address */
if (ioctl(sck, SIOCGIFBRDADDR, ifr, sizeof(*ifr)) == -1)
FATAL_perror("ioctl(SIOCGIFBRDADDR)");
if (ioctl(sck, SIOCGIFBRDADDR, ifr, sizeof(*ifr)) == -1){
WHY_perror("ioctl(SIOCGIFBRDADDR)");
continue;
}
broadcast = (struct sockaddr_in *)&ifr->ifr_ifru.ifru_broadaddr;
@ -177,7 +180,7 @@ lsif(void) {
nInterfaces++;
}
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Examined %d interface addresses\n", nInterfaces);
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Examined %d interface addresses", nInterfaces);
close(sck);
return 0;

View File

@ -186,37 +186,44 @@ int overlay_interface_args(const char *arg)
return 0;
}
void overlay_interface_close(overlay_interface *interface){
INFOF("Interface %s is down", interface->name);
unschedule(&interface->alarm);
unwatch(&interface->alarm);
close(interface->alarm.poll.fd);
interface->alarm.poll.fd=-1;
interface->state=INTERFACE_STATE_DOWN;
}
int
overlay_interface_init_socket(int interface, struct sockaddr_in *src_addr, struct sockaddr_in *broadcast) {
overlay_interface_init_socket(int interface) {
char srctxt[INET_ADDRSTRLEN];
#define I(X) overlay_interfaces[interface].X
bcopy(broadcast, &I(broadcast_address), sizeof(struct sockaddr_in));
I(fileP) = 0;
I(alarm.poll.fd) = socket(PF_INET,SOCK_DGRAM,0);
if (I(alarm.poll.fd) < 0) {
WHY_perror("socket");
WHYF("Could not create UDP socket for interface: %s",strerror(errno));
goto error;
} else
INFOF("interface #%d fd=%d",interface, I(alarm.poll.fd));
WHY_perror("socket");
WHYF("Could not create UDP socket for interface: %s",strerror(errno));
goto error;
}
int reuseP = 1;
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_REUSEADDR, &reuseP, sizeof(reuseP)) < 0) {
WHY_perror("setsockopt(SO_REUSEADR)");
goto error;
}
WHY_perror("setsockopt(SO_REUSEADR)");
goto error;
}
#ifdef SO_REUSEPORT
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_REUSEPORT, &reuseP, sizeof(reuseP)) < 0) {
WHY_perror("setsockopt(SO_REUSEPORT)");
goto error;
}
WHY_perror("setsockopt(SO_REUSEPORT)");
goto error;
}
#endif
int broadcastP = 1;
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_BROADCAST, &broadcastP, sizeof(broadcastP)) < 0) {
WHY_perror("setsockopt");
WHY_perror("setsockopt(SO_BROADCAST)");
goto error;
}
@ -225,6 +232,17 @@ overlay_interface_init_socket(int interface, struct sockaddr_in *src_addr, struc
a bad signal. */
fcntl(I(alarm.poll.fd), F_SETFL, fcntl(I(alarm.poll.fd), F_GETFL, NULL) | O_CLOEXEC);
#ifdef SO_BINDTODEVICE
/*
Limit incoming and outgoing packets to this interface, no matter what the routing table says.
This should allow for a device with multiple interfaces on the same subnet.
Don't abort if this fails, just log it.
*/
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_BINDTODEVICE, I(name), strlen(I(name))+1) < 0) {
WHY_perror("setsockopt(SO_BINDTODEVICE)");
}
#endif
/* @PGS/20120615
Use the broadcast address, so that we can reliably receive broadcast
traffic on all platforms. BUT on OSX we really need a non-broadcast socket
@ -252,11 +270,13 @@ overlay_interface_init_socket(int interface, struct sockaddr_in *src_addr, struc
I(alarm.deadline)=I(alarm.alarm)+10;
schedule(&I(alarm));
I(state)=INTERFACE_STATE_UP;
INFOF("Interface %s addr %s, is up",I(name), inet_ntoa(I(broadcast_address.sin_addr)));
return 0;
error:
close(I(alarm.poll.fd));
I(alarm.poll.fd)=-1;
overlay_interface_close(&overlay_interfaces[interface]);
return -1;
#undef I
}
@ -274,7 +294,7 @@ int overlay_interface_init(char *name,struct sockaddr_in *src_addr,struct sockad
/* Pick a reasonable default MTU.
This will ultimately get tuned by the bandwidth and other properties of the interface */
I(mtu)=1200;
I(observed)=1;
I(state)=INTERFACE_STATE_DOWN;
I(bits_per_second)=speed_in_bits;
I(port)=port;
I(type)=type;
@ -324,8 +344,14 @@ int overlay_interface_init(char *name,struct sockaddr_in *src_addr,struct sockad
dummy_poll_stats.name="overlay_dummy_poll";
I(alarm.stats)=&dummy_poll_stats;
schedule(&I(alarm));
I(state)=INTERFACE_STATE_UP;
INFOF("Dummy interface %s is up",I(name));
} else {
if (overlay_interface_init_socket(overlay_interface_count,src_addr,broadcast))
bcopy(src_addr, &I(address), sizeof(struct sockaddr_in));
bcopy(broadcast, &I(broadcast_address), sizeof(struct sockaddr_in));
if (overlay_interface_init_socket(overlay_interface_count))
return WHY("overlay_interface_init_socket() failed");
}
@ -344,13 +370,17 @@ void overlay_interface_poll(struct sched_ent *alarm)
socklen_t addrlen = sizeof(src_addr);
if (alarm->poll.revents==0){
// tick the interface
unsigned long long now = overlay_gettime_ms();
int i = (interface - overlay_interfaces);
overlay_tick_interface(i, now);
alarm->alarm=now+interface->tick_ms;
alarm->deadline=alarm->alarm+interface->tick_ms/2;
schedule(alarm);
if (interface->state==INTERFACE_STATE_UP){
// tick the interface
unsigned long long now = overlay_gettime_ms();
int i = (interface - overlay_interfaces);
overlay_tick_interface(i, now);
alarm->alarm=now+interface->tick_ms;
alarm->deadline=alarm->alarm+interface->tick_ms/2;
schedule(alarm);
}
return;
}
@ -358,16 +388,20 @@ void overlay_interface_poll(struct sched_ent *alarm)
enable stats to accurately count packets received */
int recvttl=1;
plen = recvwithttl(alarm->poll.fd,packet, sizeof(packet), &recvttl, &src_addr, &addrlen);
if (plen != -1) {
/* We have a frame from this interface */
if (debug&DEBUG_PACKETRX)
serval_packetvisualise(open_logging(),"Read from real interface", packet,plen);
if (debug&DEBUG_OVERLAYINTERFACES) DEBUGF("Received %d bytes on interface %s",plen,interface->name);
if (packetOk(interface,packet,plen,NULL,recvttl,&src_addr,addrlen,1)) {
WHY("Malformed packet");
// Do we really want to attempt to parse it again?
//serval_packetvisualise(open_logging(), "Malformed packet", packet,plen);
}
if (plen == -1) {
WHY_perror("recvwithttl(c)");
overlay_interface_close(interface);
return;
}
/* We have a frame from this interface */
if (debug&DEBUG_PACKETRX)
serval_packetvisualise(open_logging(),"Read from real interface", packet,plen);
if (debug&DEBUG_OVERLAYINTERFACES) DEBUGF("Received %d bytes on interface %s",plen,interface->name);
if (packetOk(interface,packet,plen,NULL,recvttl,&src_addr,addrlen,1)) {
WHY("Malformed packet");
// Do we really want to attempt to parse it again?
//serval_packetvisualise(open_logging(), "Malformed packet", packet,plen);
}
}
@ -404,8 +438,6 @@ void overlay_dummy_poll(struct sched_ent *alarm)
if (alarm->alarm > interface->last_tick_ms + interface->tick_ms)
alarm->alarm = interface->last_tick_ms + interface->tick_ms;
if (debug&DEBUG_OVERLAYINTERFACES)
DEBUGF("At end of input on dummy interface %s", interface->name);
}
else
{
@ -466,6 +498,9 @@ int overlay_broadcast_ensemble(int interface_number,
overlay_interface *interface = &overlay_interfaces[interface_number];
if (interface->state!=INTERFACE_STATE_UP){
return WHYF("Cannot send to interface %s as it is down", interface->name);
}
memset(&s, '\0', sizeof(struct sockaddr_in));
if (recipientaddr) {
bcopy(recipientaddr,&s,sizeof(struct sockaddr_in));
@ -535,8 +570,11 @@ int overlay_broadcast_ensemble(int interface_number,
else
{
if(sendto(interface->alarm.poll.fd,
bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) != len)
return WHY_perror("sendto(c)");
bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) != len){
WHY_perror("sendto(c)");
overlay_interface_close(interface);
return -1;
}
return 0;
}
}
@ -575,105 +613,116 @@ overlay_interface_register(char *name,
return 0;
}
/* Search in the exist list of interfaces */
for(i = 0; i < overlay_interface_count; i++)
if (!strcasecmp(overlay_interfaces[i].name, name))
break;
int found_interface= -1;
if (i < overlay_interface_count) {
/* We already know about this interface, so just update it. */
/* Check if the broadcast address is the same
TODO: This only applies on Linux because only there can you bind to the bcast addr
DOC 20120608
*/
/* Search in the exist list of interfaces */
for(i = 0; i < overlay_interface_count; i++){
int broadcast_match = 0;
int name_match =0;
if ((overlay_interfaces[i].broadcast_address.sin_addr.s_addr & 0xffffffff)
== (broadcast->sin_addr.s_addr & 0xffffffff)) {
/* Same address, mark it as being seen */
overlay_interfaces[i].observed = 1;
return 0;
} else {
if (0) {
/* Interface has changed.
TODO: We should register each address we understand in a list and check them.
DOC 20120608 */
INFOF("Interface changed %08llx.%08llx vs %08llx.%08llx",
/* overlay_interfaces[i].local_address.sin_addr.s_addr */0,
overlay_interfaces[i].broadcast_address.sin_addr.s_addr,
local->sin_addr.s_addr,
broadcast->sin_addr.s_addr);
unwatch(&overlay_interfaces[i].alarm);
close(overlay_interfaces[i].alarm.poll.fd);
overlay_interfaces[i].alarm.poll.fd = -1;
if (overlay_interface_init_socket(i, local, broadcast))
INFOF("Could not reinitialise changed interface %s", name);
}
== (broadcast->sin_addr.s_addr & 0xffffffff)){
broadcast_match = 1;
}
} else {
/* New interface, so register it */
if (overlay_interface_init(name, local, broadcast, me->speed_in_bits, me->port, me->type))
WHYF("Could not initialise newly seen interface %s", name);
else
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Registered interface %s", name);
name_match = !strcasecmp(overlay_interfaces[i].name, name);
if (name_match && broadcast_match){
// mark this interface as still alive
if (overlay_interfaces[i].state==INTERFACE_STATE_DETECTING)
overlay_interfaces[i].state=INTERFACE_STATE_UP;
// try to bring the interface back up again
if (overlay_interfaces[i].state==INTERFACE_STATE_DOWN){
bcopy(local, &overlay_interfaces[i].address, sizeof(struct sockaddr_in));
overlay_interface_init_socket(i);
}
// we already know about this interface, and it's up so stop looking immediately
return 0;
}
// remember this slot to bring the interface back up again, even if the address has changed
if (name_match && overlay_interfaces[i].state==INTERFACE_STATE_DOWN)
found_interface=i;
}
if (found_interface>=0){
bcopy(local, &overlay_interfaces[i].address, sizeof(struct sockaddr_in));
bcopy(broadcast, &overlay_interfaces[i].broadcast_address, sizeof(struct sockaddr_in));
return overlay_interface_init_socket(i);
}
/* New interface, so register it */
if (overlay_interface_init(name, local, broadcast, me->speed_in_bits, me->port, me->type))
return WHYF("Could not initialise newly seen interface %s", name);
else
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Registered interface %s", name);
return 0;
}
void overlay_interface_discover(struct sched_ent *alarm){
int no_route, i;
int i;
struct interface_rules *r;
struct sockaddr_in dummyaddr;
/* Mark all interfaces as not observed, so that we know if we need to cull any */
int detect_real_interfaces = 0;
/* Mark all UP interfaces as DETECTING, so we can tell which interfaces are new, and which are dead */
for(i = 0; i < overlay_interface_count; i++)
overlay_interfaces[i].observed = 0;
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
overlay_interfaces[i].state=INTERFACE_STATE_DETECTING;
/* Check through for any virtual dummy interfaces */
for (r = interface_filter; r != NULL; r = r->next) {
if (r->namespec[0] != '>')
if (r->namespec[0] != '>'){
detect_real_interfaces = 1;
continue;
}
for(i = 0; i < overlay_interface_count; i++)
if (!strcasecmp(overlay_interfaces[i].name,r->namespec))
if (!strcasecmp(overlay_interfaces[i].name,r->namespec)){
if (overlay_interfaces[i].state==INTERFACE_STATE_DETECTING)
overlay_interfaces[i].state=INTERFACE_STATE_UP;
break;
if (i < overlay_interface_count)
/* We already know about this interface, so just update it */
overlay_interfaces[i].observed = 1;
else {
/* New interface, so register it */
if (overlay_interface_init(r->namespec,&dummyaddr,&dummyaddr,
1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI)) {
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Could not initialise newly seen interface %s", r->namespec);
}
else
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Registered interface %s",r->namespec);
if (i >= overlay_interface_count){
/* New interface, so register it */
overlay_interface_init(r->namespec,&dummyaddr,&dummyaddr,1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI);
}
}
/* Look for real interfaces */
no_route = 1;
if (detect_real_interfaces){
int no_route = 1;
#ifdef HAVE_IFADDRS_H
if (no_route != 0)
no_route = doifaddrs();
if (no_route != 0)
no_route = doifaddrs();
#endif
#ifdef SIOCGIFCONF
if (no_route != 0)
no_route = lsif();
if (no_route != 0)
no_route = lsif();
#endif
#ifdef linux
if (no_route != 0)
no_route = scrapeProcNetRoute();
if (no_route != 0)
no_route = scrapeProcNetRoute();
#endif
if (no_route != 0) {
FATAL("Unable to get any interface information");
if (no_route != 0) {
FATAL("Unable to get any interface information");
}
}
// detect if any interfaces have gone away and need to be closed
for(i = 0; i < overlay_interface_count; i++)
if (overlay_interfaces[i].state==INTERFACE_STATE_DETECTING)
overlay_interface_close(&overlay_interfaces[i]);
alarm->alarm = overlay_gettime_ms()+5000;
alarm->deadline = alarm->alarm + 10000;
schedule(alarm);
@ -822,7 +871,7 @@ void overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue
int i;
for(i=0;i<OVERLAY_MAX_INTERFACES;i++)
{
if (overlay_interfaces[i].observed>0)
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
if (!frame->broadcast_sent_via[i]){
overlay_init_packet(packet, i);
break;
@ -863,7 +912,7 @@ void overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue
// check if there is still a broadcast to be sent
for(i=0;i<OVERLAY_MAX_INTERFACES;i++)
{
if (overlay_interfaces[i].observed>0)
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
if (!frame->broadcast_sent_via[i]){
keep_payload=1;
break;
@ -940,8 +989,9 @@ int overlay_tick_interface(int i, long long now)
struct outgoing_packet packet;
IN();
if (overlay_interfaces[i].bits_per_second<1) {
/* An interface with no speed budget is for listening only, so doesn't get ticked */
/* An interface with no speed budget is for listening only, so doesn't get ticked */
if (overlay_interfaces[i].bits_per_second<1
|| overlay_interfaces[i].state!=INTERFACE_STATE_UP) {
RETURN(0);
}

View File

@ -401,7 +401,8 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface)
*interface=0;
for(i=1;i<OVERLAY_MAX_INTERFACES;i++) {
if (direct_neighbour->scores[i]>direct_neighbour->scores[*interface]) *interface=i;
if (overlay_interfaces[i].state==INTERFACE_STATE_UP &&
direct_neighbour->scores[i]>direct_neighbour->scores[*interface]) *interface=i;
}
if (direct_neighbour->scores[*interface]>0) {
bcopy(d,nexthop,SID_SIZE);
@ -430,7 +431,8 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface)
overlay_route_recalc_neighbour_metrics(neighbour, now);
for(i=1;i<OVERLAY_MAX_INTERFACES;i++) {
if (neighbour->scores[i]*score>best_score) {
if (overlay_interfaces[i].state==INTERFACE_STATE_UP &&
neighbour->scores[i]*score>best_score) {
bcopy(&neighbour->node->sid[0],&nexthop[0],SID_SIZE);
*interface=i;
best_o=o;
@ -847,7 +849,8 @@ int overlay_route_recalc_node_metrics(overlay_node *n,long long now)
int i;
for(i=0;i<overlay_interface_count;i++)
{
if (overlay_neighbours[n->neighbour_id].scores[i]>best_score)
if (overlay_interfaces[i].state==INTERFACE_STATE_UP &&
overlay_neighbours[n->neighbour_id].scores[i]>best_score)
{
best_score=overlay_neighbours[n->neighbour_id].scores[i];
best_observation=-1;
@ -935,50 +938,45 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
Also, we might like to take into account the interface we received
the announcements on. */
for(i=0;i<OVERLAY_MAX_OBSERVATIONS;i++) {
if (n->observations[i].valid&&n->observations[i].s1) {
/* Work out the interval covered by the observation.
The times are represented as lowest 32 bits of a 64-bit
millisecond clock. This introduces modulo problems,
however by using 32-bit modulo arithmatic here, we avoid
most of them. */
unsigned int interval=n->observations[i].s2-n->observations[i].s1;
if (!n->observations[i].valid ||
!n->observations[i].s1 ||
n->observations[i].sender_interface>=OVERLAY_MAX_INTERFACES ||
overlay_interfaces[n->observations[i].sender_interface].state!=INTERFACE_STATE_UP)
continue;
/* Work out the interval covered by the observation.
The times are represented as lowest 32 bits of a 64-bit
millisecond clock. This introduces modulo problems,
however by using 32-bit modulo arithmatic here, we avoid
most of them. */
unsigned int interval=n->observations[i].s2-n->observations[i].s1;
/* Check the observation age, and ignore if too old */
int obs_age=now-n->observations[i].time_ms;
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("tallying obs: %dms old, %dms long", obs_age,interval);
/* Ignore very large intervals (>1hour) as being likely to be erroneous.
(or perhaps a clock wrap due to the modulo arithmatic)
One tick per hour should be well and truly slow enough to do
50KB per 12 hours, which is the minimum traffic charge rate
on an expensive BGAN satellite link.
*/
if (interval>=3600000 || obs_age>200000)
continue;
/* Check the observation age, and ignore if too old */
int obs_age=now-n->observations[i].time_ms;
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("tallying obs: %dms old, %dms long", obs_age,interval);
if (obs_age>200000) continue;
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("adding %dms (interface %d '%s')",
interval,n->observations[i].sender_interface,
overlay_interfaces[n->observations[i].sender_interface].name);
/* Ignore very large intervals (>1hour) as being likely to be erroneous.
(or perhaps a clock wrap due to the modulo arithmatic)
One tick per hour should be well and truly slow enough to do
50KB per 12 hours, which is the minimum traffic charge rate
on an expensive BGAN satellite link.
*/
if (interval<3600000) {
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("adding %dms (interface %d '%s')",
interval,n->observations[i].sender_interface,
overlay_interfaces[n->observations[i].sender_interface].name);
/* sender_interface is unsigned, so a single-sided test is sufficient for bounds checking */
if (n->observations[i].sender_interface<OVERLAY_MAX_INTERFACES)
{
ms_observed_200sec[n->observations[i].sender_interface]+=interval;
if (obs_age<=5000){
ms_observed_5sec[n->observations[i].sender_interface]+=(interval>5000?5000:interval);
}
}
else
{
WHY("Invalid interface ID in observation");
DEBUGF("XXXXXXX adding %dms (interface %d)",interval,n->observations[i].sender_interface);
}
}
if (n->observations[i].time_ms>most_recent_observation) most_recent_observation=n->observations[i].time_ms;
ms_observed_200sec[n->observations[i].sender_interface]+=interval;
if (obs_age<=5000){
ms_observed_5sec[n->observations[i].sender_interface]+=(interval>5000?5000:interval);
}
if (n->observations[i].time_ms>most_recent_observation) most_recent_observation=n->observations[i].time_ms;
}
/* From the sum of observations calculate the metrics.

View File

@ -508,6 +508,11 @@ extern int overlayMode;
#define OVERLAY_INTERFACE_WIFI 2
#define OVERLAY_INTERFACE_PACKETRADIO 3
#define INTERFACE_STATE_FREE 0
#define INTERFACE_STATE_UP 1
#define INTERFACE_STATE_DOWN 2
#define INTERFACE_STATE_DETECTING 3
typedef struct overlay_interface {
struct sched_ent alarm;
char name[80];
@ -540,9 +545,11 @@ typedef struct overlay_interface {
int sequence_number;
/* XXX need recent packet buffers to support the above */
/* Broadcast address and netmask, if known
/* We need to make sure that interface name and broadcast address is unique for all interfaces that are UP.
We bind a separate socket per interface / broadcast address Broadcast address and netmask, if known
We really only case about distinct broadcast addresses on interfaces.
Also simplifies aliases on interfaces. */
struct sockaddr_in address;
struct sockaddr_in broadcast_address;
/* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface.
@ -550,10 +557,11 @@ typedef struct overlay_interface {
potentially two quite different values. */
int mtu;
/* If the interface still exists on the local machine.
If not, it we keep track of it for a few seconds before purging it, incase of flapping, e.g.,
due to DHCP renewal */
int observed;
/* Use one of the INTERFACE_STATE_* constants to indicate the state of this interface.
If the interface stops working or disappears, it will be marked as DOWN and the socket closed.
But if it comes back up again, we should try to reuse this structure, even if the broadcast address has changed.
*/
int state;
} overlay_interface;
/* Maximum interface count is rather arbitrary.
@ -862,7 +870,7 @@ long long parse_quantity(char *q);
int overlay_interface_init(char *name,struct sockaddr_in *src_addr,struct sockaddr_in *broadcast,
int speed_in_bits,int port,int type);
int overlay_interface_init_socket(int i,struct sockaddr_in *src_addr,struct sockaddr_in *broadcast);
int overlay_interface_init_socket(int i);
long long overlay_time_until_next_tick();
int overlay_rx_messages();