]> git.meshlink.io Git - meshlink-tiny/blob - test/blackbox/common/common_handlers.c
e728f4383684176f9b8fe409eb4b6d5252c63652
[meshlink-tiny] / test / blackbox / common / common_handlers.c
1 /*
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>
5
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.
10
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.
15
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.
19 */
20
21 #ifdef NDEBUG
22 #undef NDEBUG
23 #endif
24
25 #include <stdio.h>
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/ioctl.h>
32 #include <net/if.h>
33 #include <arpa/inet.h>
34 #include <sys/socket.h>
35 #include <netdb.h>
36 #include <ifaddrs.h>
37 #include <ctype.h>
38 #include "test_step.h"
39 #include "common_handlers.h"
40
41 char *lxc_bridge = NULL;
42 black_box_state_t *state_ptr = NULL;
43
44 bool meta_conn_status[10];
45
46 bool test_running;
47
48 static int meshlink_get_node_in_container(const char *name) {
49         int i;
50
51         for(i = 0; i < state_ptr->num_nodes; i++) {
52                 if(!strcasecmp(state_ptr->node_names[i], name)) {
53                         return i;
54                         break;
55                 }
56         }
57
58         return -1;
59 }
60
61 void mesh_close_signal_handler(int signum) {
62         (void)signum;
63         test_running = false;
64
65         exit(EXIT_SUCCESS);
66 }
67
68 void setup_signals(void) {
69         test_running = true;
70         signal(SIGTERM, mesh_close_signal_handler);
71 }
72
73 /* Return the IP Address of the Interface 'if_name'
74     The caller is responsible for freeing the dynamically allocated string that is returned */
75 char *get_ip(const char *if_name) {
76         struct ifaddrs *ifaddr, *ifa;
77         char *ip;
78         int family;
79
80         ip = malloc(NI_MAXHOST);
81         assert(ip);
82         assert(getifaddrs(&ifaddr) != -1);
83
84         for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
85                 if(ifa->ifa_addr == NULL) {
86                         continue;
87                 }
88
89                 family = ifa->ifa_addr->sa_family;
90
91                 if(family == AF_INET && !strcmp(ifa->ifa_name, if_name)) {
92                         assert(!getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST));
93                         break;
94                 }
95         }
96
97         return ip;
98 }
99
100 /* Return the IP Address of the Interface 'if_name'
101     The caller is responsible for freeing the dynamically allocated string that is returned */
102 char *get_netmask(const char *if_name) {
103         struct ifaddrs *ifaddr, *ifa;
104         char *ip;
105         int family;
106
107         ip = malloc(NI_MAXHOST);
108         assert(ip);
109         assert(getifaddrs(&ifaddr) != -1);
110
111         for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
112                 if(ifa->ifa_addr == NULL) {
113                         continue;
114                 }
115
116                 family = ifa->ifa_addr->sa_family;
117
118                 if(family == AF_INET && !strcmp(ifa->ifa_name, if_name)) {
119                         assert(!getnameinfo(ifa->ifa_netmask, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST));
120                         break;
121                 }
122         }
123
124         return ip;
125 }
126
127 /* Change the IP Address of an interface */
128 void set_ip(const char *if_name, const char *new_ip) {
129         char set_ip_cmd[100];
130         assert(snprintf(set_ip_cmd, sizeof(set_ip_cmd), "ifconfig %s %s", if_name, new_ip) >= 0);
131         assert(system(set_ip_cmd) == 0);
132 }
133
134 /* Change the Netmask of an interface */
135 void set_netmask(const char *if_name, const char *new_netmask) {
136         char set_mask_cmd[100];
137         assert(snprintf(set_mask_cmd, sizeof(set_mask_cmd), "ifconfig %s netmask %s", if_name, new_netmask) >= 0);
138         assert(system(set_mask_cmd) == 0);
139 }
140
141 /* Bring a network interface down (before making changes such as the IP Address) */
142 void stop_nw_intf(const char *if_name) {
143         char nw_down_cmd[100];
144         assert(snprintf(nw_down_cmd, sizeof(nw_down_cmd), "ifconfig %s down", if_name) >= 0);
145         assert(system(nw_down_cmd) == 0);
146 }
147
148 /* Bring a network interface up (after bringing it down and making changes such as
149     the IP Address) */
150 void start_nw_intf(const char *if_name) {
151         char nw_up_cmd[100];
152         assert(snprintf(nw_up_cmd, sizeof(nw_up_cmd), "ifconfig %s up", if_name) >= 0);
153         assert(system(nw_up_cmd) == 0);
154 }
155
156 void meshlink_callback_node_status(meshlink_handle_t *mesh, meshlink_node_t *node,
157                                    bool reachable) {
158         (void)mesh;
159         fprintf(stderr, "Node %s became %s\n", node->name, (reachable) ? "reachable" : "unreachable");
160 }
161
162 void meshlink_callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
163                               const char *text) {
164         (void)mesh;
165         (void)level;
166
167         fprintf(stderr, "meshlink>> %s\n", text);
168
169         if(state_ptr) {
170                 bool status;
171                 char name[100];
172
173                 if(sscanf(text, "Connection with %s activated", name) == 1) {
174                         status = true;
175                 } else if(sscanf(text, "Already connected to %s", name) == 1) {
176                         status = true;
177                 } else if(sscanf(text, "Connection closed by %s", name) == 1) {
178                         status = false;
179                 } else if(sscanf(text, "Closing connection with %s", name) == 1) {
180                         status = false;
181                 } else {
182                         return;
183                 }
184
185                 int i = meshlink_get_node_in_container(name);
186                 assert(i != -1);
187                 meta_conn_status[i] = status;
188         }
189 }