summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHåkon Nessjøen <haakon.nessjoen@gmail.com>2011-11-13 09:54:22 +0100
committerHåkon Nessjøen <haakon.nessjoen@gmail.com>2011-11-13 09:54:22 +0100
commita5b710a45671c1b9504130d83d3ebe7fe8a65c5a (patch)
treeb649ed1012d8a9195c1349ab19252224764acf99
parent4d3923c1cc947fbf1a6b23e2adf6915c47aac8d1 (diff)
downloadMAC-Telnet-a5b710a45671c1b9504130d83d3ebe7fe8a65c5a.tar.gz
MAC-Telnet-a5b710a45671c1b9504130d83d3ebe7fe8a65c5a.zip
Added support for reloading list of interfaces/addresses on HUP signal, and fixed notification to connections of TERM signal.
-rw-r--r--interfaces.c2
-rw-r--r--interfaces.h1
-rw-r--r--mactelnetd.c153
3 files changed, 107 insertions, 49 deletions
diff --git a/interfaces.c b/interfaces.c
index d1d177c..f0bff9b 100644
--- a/interfaces.c
+++ b/interfaces.c
@@ -42,7 +42,7 @@
#include "interfaces.h"
-static struct net_interface *net_get_interface_ptr(struct net_interface *interfaces, int max_devices, char *name, int create) {
+struct net_interface *net_get_interface_ptr(struct net_interface *interfaces, int max_devices, char *name, int create) {
int i;
for (i = 0; i < max_devices; ++i) {
diff --git a/interfaces.h b/interfaces.h
index afb3e72..1dab785 100644
--- a/interfaces.h
+++ b/interfaces.h
@@ -38,6 +38,7 @@ struct net_interface {
extern int net_get_interfaces(struct net_interface *interfaces, int max_devices);
+extern struct net_interface *net_get_interface_ptr(struct net_interface *interfaces, int max_devices, char *name, int create);
extern int net_init_raw_socket();
extern int net_send_udp(const int socket, struct net_interface *interface, const unsigned char *sourcemac, const unsigned char *destmac, const struct in_addr *sourceip, const int sourceport, const struct in_addr *destip, const int destport, const unsigned char *data, const int datalen);
extern unsigned short in_cksum(unsigned short *addr, int len);
diff --git a/mactelnetd.c b/mactelnetd.c
index 99829d3..d3d462d 100644
--- a/mactelnetd.c
+++ b/mactelnetd.c
@@ -95,6 +95,8 @@ enum mt_connection_state {
/** Connection struct */
struct mt_connection {
struct net_interface *interface;
+ char interface_name[256];
+
unsigned short seskey;
unsigned int incounter;
unsigned int outcounter;
@@ -206,40 +208,41 @@ static int find_socket(unsigned char *mac) {
static void setup_sockets() {
int i;
- if (net_get_interfaces(interfaces, MAX_INTERFACES) <= 0) {
- fprintf(stderr, "Error: No suitable devices found\n");
- exit(1);
- }
-
for (i = 0; i < MAX_INTERFACES; ++i) {
- if (interfaces[i].in_use == 0 || !interfaces[i].has_mac) {
- continue;
- }
-
int optval = 1;
struct sockaddr_in si_me;
+ struct ether_addr *mac = (struct ether_addr *)&(interfaces[i].mac_addr);
- interfaces[i].socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (interfaces[i].socketfd < 0) {
+ if (interfaces[i].in_use == 0 || !interfaces[i].has_mac) {
continue;
}
- if (setsockopt(interfaces[i].socketfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof (optval))==-1) {
- perror("SO_BROADCAST");
- continue;
- }
+ if (!use_raw_socket) {
+ interfaces[i].socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (interfaces[i].socketfd < 0) {
+ continue;
+ }
- setsockopt(interfaces[i].socketfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+ if (setsockopt(interfaces[i].socketfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof (optval))==-1) {
+ perror("SO_BROADCAST");
+ continue;
+ }
- /* Initialize receiving socket on the device chosen */
- si_me.sin_family = AF_INET;
- si_me.sin_port = htons(MT_MACTELNET_PORT);
- memcpy(&(si_me.sin_addr.s_addr), interfaces[i].ipv4_addr, IPV4_ALEN);
+ setsockopt(interfaces[i].socketfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
- if (bind(interfaces[i].socketfd, (struct sockaddr *)&si_me, sizeof(si_me))==-1) {
- fprintf(stderr, "Error binding to %s:%d, %s\n", inet_ntoa(si_me.sin_addr), sourceport, strerror(errno));
- continue;
+ /* Initialize receiving socket on the device chosen */
+ si_me.sin_family = AF_INET;
+ si_me.sin_port = htons(MT_MACTELNET_PORT);
+ memcpy(&(si_me.sin_addr.s_addr), interfaces[i].ipv4_addr, IPV4_ALEN);
+
+ if (bind(interfaces[i].socketfd, (struct sockaddr *)&si_me, sizeof(si_me))==-1) {
+ fprintf(stderr, "Error binding to %s:%d, %s\n", inet_ntoa(si_me.sin_addr), sourceport, strerror(errno));
+ continue;
+ }
}
+
+ syslog(LOG_NOTICE, "Listening on %s for %s\n", interfaces[i].name, ether_ntoa(mac));
+
}
}
@@ -604,11 +607,6 @@ static void handle_data_packet(struct mt_connection *curconn, struct mt_mactelne
}
}
-static void terminate() {
- syslog(LOG_NOTICE, "Exiting.");
- exit(0);
-}
-
static void handle_packet(unsigned char *data, int data_len, const struct sockaddr_in *address) {
struct mt_mactelnet_hdr pkthdr;
struct mt_connection *curconn = NULL;
@@ -644,6 +642,8 @@ static void handle_packet(unsigned char *data, int data_len, const struct sockad
curconn->lastdata = time(NULL);
curconn->state = STATE_AUTH;
curconn->interface = &interfaces[interface_index];
+ strncpy(curconn->interface_name, interfaces[interface_index].name, 254);
+ curconn->interface_name[255] = '\0';
memcpy(curconn->srcmac, pkthdr.srcaddr, ETH_ALEN);
memcpy(curconn->srcip, &(address->sin_addr), IPV4_ALEN);
curconn->srcport = htons(address->sin_port);
@@ -799,6 +799,76 @@ void mndp_broadcast() {
}
}
+void sigterm_handler() {
+ struct mt_connection *p;
+ struct mt_packet pdata;
+ char message[] = "\r\n\r\nDaemon shutting down.\r\n";
+
+ syslog(LOG_NOTICE, "Daemon shutting down");
+
+ for (p = connections_head; p != NULL; p = p->next) {
+ if (p->state == STATE_ACTIVE) {
+ init_packet(&pdata, MT_PTYPE_DATA, p->interface->mac_addr, p->srcmac, p->seskey, p->outcounter);
+ add_control_packet(&pdata, MT_CPTYPE_PLAINDATA, message, strlen(message));
+ send_udp(p, &pdata);
+
+ init_packet(&pdata, MT_PTYPE_END, p->interface->mac_addr, p->srcmac, p->seskey, p->outcounter);
+ send_udp(p, &pdata);
+ }
+ }
+
+ /* Doesn't hurt to tidy up */
+ close(sockfd);
+ close(insockfd);
+ if (!use_raw_socket) {
+ int i;
+ for (i = 0; i < MAX_INTERFACES; ++i) {
+ if (interfaces[i].in_use && interfaces[i].socketfd > 0)
+ close(interfaces[i].socketfd);
+ }
+ }
+ closelog();
+ exit(0);
+}
+
+void sighup_handler() {
+ int i;
+ struct mt_connection *p;
+
+ syslog(LOG_NOTICE, "SIGHUP: Reloading interfaces");
+
+ if (!use_raw_socket) {
+ for (i = 0; i < MAX_INTERFACES; ++i) {
+ close(interfaces[i].socketfd);
+ }
+ }
+
+ bzero(interfaces, sizeof(interfaces));
+
+ if (net_get_interfaces(interfaces, MAX_INTERFACES) <= 0) {
+ syslog(LOG_ERR, "No devices found! Exiting.\n");
+ exit(1);
+ }
+
+ setup_sockets();
+
+ /* Reassign outgoing interfaces to connections again, since they may have changed */
+ for (p = connections_head; p != NULL; p = p->next) {
+ if (p->interface_name != NULL) {
+ struct net_interface *interface = net_get_interface_ptr(interfaces, MAX_INTERFACES, p->interface_name, 0);
+ if (interface != NULL) {
+ p->interface = interface;
+ } else {
+ struct mt_connection tmp;
+ syslog(LOG_NOTICE, "(%d) Connection closed because interface %s is gone.", p->seskey, p->interface_name);
+ tmp.next = p->next;
+ list_remove_connection(p);
+ p = &tmp;
+ }
+ }
+ }
+}
+
/*
* TODO: Rewrite main() when all sub-functionality is tested
*/
@@ -918,12 +988,13 @@ int main (int argc, char **argv) {
fprintf(stderr, "MNDP: Error binding to %s:%d, %s\n", inet_ntoa(si_me_mndp.sin_addr), MT_MNDP_PORT, strerror(errno));
}
+ openlog("mactelnetd", LOG_PID, LOG_DAEMON);
+ syslog(LOG_NOTICE, "Bound to %s:%d", inet_ntoa(si_me.sin_addr), sourceport);
+
/* Enumerate available interfaces */
net_get_interfaces(interfaces, MAX_INTERFACES);
- if (!use_raw_socket) {
- setup_sockets();
- }
+ setup_sockets();
if (!foreground) {
daemonize();
@@ -934,15 +1005,11 @@ int main (int argc, char **argv) {
signal(SIGTSTP,SIG_IGN);
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
-
- openlog("mactelnetd", LOG_PID, LOG_DAEMON);
-
- syslog(LOG_NOTICE, "Bound to %s:%d", inet_ntoa(si_me.sin_addr), sourceport);
+ signal(SIGHUP, sighup_handler);
+ signal(SIGTERM, sigterm_handler);
for (i = 0; i < MAX_INTERFACES; ++i) {
if (interfaces[i].in_use && interfaces[i].has_mac) {
- struct ether_addr *mac = (struct ether_addr *)&(interfaces[i].mac_addr);
- syslog(LOG_NOTICE, "Listening on %s for %16s\n", interfaces[i].name, ether_ntoa(mac));
interface_count++;
}
}
@@ -952,8 +1019,6 @@ int main (int argc, char **argv) {
exit(1);
}
- signal(SIGTERM, terminate);
-
while (1) {
int reads;
struct mt_connection *p;
@@ -1067,14 +1132,6 @@ int main (int argc, char **argv) {
}
}
- close(sockfd);
- close(insockfd);
- if (!use_raw_socket) {
- for (i = 0; i < MAX_INTERFACES; ++i) {
- if (interfaces[i].in_use && interfaces[i].socketfd > 0)
- close(interfaces[i].socketfd);
- }
- }
- closelog();
+ /* Never reached */
return 0;
}