2 common_handlers.c -- Implementation of common callback handling and signal handling
3 functions for black box tests
4 Copyright (C) 2018 Guus Sliepen <guus@meshlink.io>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <sys/ioctl.h>
28 #include <arpa/inet.h>
29 #include <sys/socket.h>
33 #include "test_step.h"
34 #include "common_handlers.h"
36 #define GET_IP_FAMILY AF_INET
38 char *lxc_bridge = NULL;
39 black_box_state_t *state_ptr = NULL;
41 bool meta_conn_status[10];
42 bool node_reachable_status[10];
46 void mesh_close_signal_handler(int a) {
52 void mesh_stop_start_signal_handler(int a) {
53 /* Stop the Mesh if it is running, otherwise start it again */
54 (mesh_started) ? execute_stop() : execute_start();
57 void setup_signals(void) {
59 signal(SIGTERM, mesh_close_signal_handler);
60 signal(SIGINT, mesh_stop_start_signal_handler);
63 /* Return the IP Address of the Interface 'if_name'
64 The caller is responsible for freeing the dynamically allocated string that is returned */
65 char *get_ip(const char *if_name) {
66 struct ifaddrs *ifaddr, *ifa;
70 ip = malloc(NI_MAXHOST);
72 assert(getifaddrs(&ifaddr) != -1);
74 for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
75 if(ifa->ifa_addr == NULL) {
79 family = ifa->ifa_addr->sa_family;
81 if(family == GET_IP_FAMILY && !strcmp(ifa->ifa_name, if_name)) {
82 assert(!getnameinfo(ifa->ifa_addr, (family == GET_IP_FAMILY) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST));
90 /* Return the IP Address of the Interface 'if_name'
91 The caller is responsible for freeing the dynamically allocated string that is returned */
92 char *get_netmask(const char *if_name) {
93 struct ifaddrs *ifaddr, *ifa;
97 ip = malloc(NI_MAXHOST);
99 assert(getifaddrs(&ifaddr) != -1);
101 for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
102 if(ifa->ifa_addr == NULL) {
106 family = ifa->ifa_addr->sa_family;
108 if(family == GET_IP_FAMILY && !strcmp(ifa->ifa_name, if_name)) {
109 assert(!getnameinfo(ifa->ifa_netmask, (family == GET_IP_FAMILY) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST));
117 /* Change the IP Address of an interface */
118 void set_ip(const char *if_name, const char *new_ip) {
119 char set_ip_cmd[100];
120 assert(snprintf(set_ip_cmd, sizeof(set_ip_cmd), "ifconfig %s %s", if_name, new_ip) >= 0);
121 assert(system(set_ip_cmd) == 0);
124 /* Change the Netmask of an interface */
125 void set_netmask(const char *if_name, const char *new_netmask) {
126 char set_mask_cmd[100];
127 assert(snprintf(set_mask_cmd, sizeof(set_mask_cmd), "ifconfig %s netmask %s", if_name, new_netmask) >= 0);
128 assert(system(set_mask_cmd) == 0);
131 /* Bring a network interface down (before making changes such as the IP Address) */
132 void stop_nw_intf(const char *if_name) {
133 char nw_down_cmd[100];
134 assert(snprintf(nw_down_cmd, sizeof(nw_down_cmd), "ifconfig %s down", if_name) >= 0);
135 assert(system(nw_down_cmd) == 0);
138 /* Bring a network interface up (after bringing it down and making changes such as
140 void start_nw_intf(const char *if_name) {
142 assert(snprintf(nw_up_cmd, sizeof(nw_up_cmd), "ifconfig %s up", if_name) >= 0);
143 assert(system(nw_up_cmd) == 0);
146 void meshlink_callback_node_status(meshlink_handle_t *mesh, meshlink_node_t *node,
151 fprintf(stderr, "Node %s became %s\n", node->name, (reachable) ? "reachable" : "unreachable");
154 for(i = 0; i < state_ptr->num_nodes; i++)
155 if(strcmp(node->name, state_ptr->node_names[i]) == 0) {
156 node_reachable_status[i] = reachable;
160 void meshlink_callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
163 char connection_match_msg[100];
167 fprintf(stderr, "meshlink>> %s\n", text);
169 if(state_ptr && (strstr(text, "Connection") || strstr(text, "connection"))) {
170 for(i = 0; i < state_ptr->num_nodes; i++) {
171 assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
172 "Connection with %s", state_ptr->node_names[i]) >= 0);
174 if(strstr(text, connection_match_msg) && strstr(text, "activated")) {
175 meta_conn_status[i] = true;
179 assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
180 "Already connected to %s", state_ptr->node_names[i]) >= 0);
182 if(strstr(text, connection_match_msg)) {
183 meta_conn_status[i] = true;
187 assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
188 "Connection closed by %s", state_ptr->node_names[i]) >= 0);
190 if(strstr(text, connection_match_msg)) {
191 meta_conn_status[i] = false;
195 assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
196 "Closing connection with %s", state_ptr->node_names[i]) >= 0);
198 if(strstr(text, connection_match_msg)) {
199 meta_conn_status[i] = false;