diff options
author | Håkon Nessjøen <haakon.nessjoen@gmail.com> | 2011-11-13 09:54:22 +0100 |
---|---|---|
committer | Håkon Nessjøen <haakon.nessjoen@gmail.com> | 2011-11-13 09:54:22 +0100 |
commit | a5b710a45671c1b9504130d83d3ebe7fe8a65c5a (patch) | |
tree | b649ed1012d8a9195c1349ab19252224764acf99 | |
parent | 4d3923c1cc947fbf1a6b23e2adf6915c47aac8d1 (diff) | |
download | MAC-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.c | 2 | ||||
-rw-r--r-- | interfaces.h | 1 | ||||
-rw-r--r-- | mactelnetd.c | 153 |
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; } |