13 #include "meshlink-tiny.h"
14 #include "netns_utils.h"
21 /// Create meshlink instances and network namespaces for a list of peers
22 static void create_peers(peer_config_t *peers, int npeers, const char *prefix) {
23 // We require root for network namespaces
28 for(int i = 0; i < npeers; i++) {
29 bool full = peers[i].full;
31 assert(asprintf(&peers[i].netns_name, "%s%d", prefix, i) > 0);
33 assert(asprintf(&command,
34 "/bin/ip netns delete %1$s 2>/dev/null || true;"
35 "/bin/ip netns add %1$s;"
36 "/bin/ip netns exec %1$s ip link set dev lo up;",
37 peers[i].netns_name));
39 assert(system(command) == 0);
42 char *netns_path = NULL;
43 assert(asprintf(&netns_path, "/run/netns/%s", peers[i].netns_name));
45 peers[i].netns = open(netns_path, O_RDONLY);
46 assert(peers[i].netns != -1);
49 char *conf_path = NULL;
50 assert(asprintf(&conf_path, "%s_conf.%d", prefix, i + 1) > 0);
52 assert(full ? full_meshlink_destroy(conf_path) : meshlink_destroy(conf_path));
54 meshlink_open_params_t *params = full
55 ? full_meshlink_open_params_init(conf_path, peers[i].name, prefix, peers[i].devclass)
56 : meshlink_open_params_init(conf_path, peers[i].name, prefix, peers[i].devclass);
59 ? full_meshlink_open_params_set_netns(params, peers[i].netns)
60 : meshlink_open_params_set_netns(params, peers[i].netns)
63 peers[i].mesh = full ? full_meshlink_open_ex(params) : meshlink_open_ex(params);
64 assert(peers[i].mesh);
69 full_meshlink_enable_discovery(peers[i].mesh, false);
74 /// Set up a LAN topology where all peers can see each other directly
75 static void setup_lan_topology(peer_config_t *peers, int npeers) {
76 // Set up the LAN bridge
79 assert(asprintf(&command,
80 "/bin/ip netns exec %1$s /bin/ip link add eth0 type bridge;"
81 "/bin/ip netns exec %1$s /bin/ip link set eth0 up;",
82 peers[0].netns_name));
84 assert(system(command) == 0);
87 // Add an interface to each peer that is connected to the bridge
88 for(int i = 1; i < npeers; i++) {
90 assert(asprintf(&command,
91 "/bin/ip netns exec %1$s /bin/ip link add eth0 type veth peer eth%3$d netns %2$s;"
92 "/bin/ip netns exec %1$s /bin/ip link set dev eth0 up;"
93 "/bin/ip netns exec %2$s /bin/ip link set dev eth%3$d master eth0 up;",
94 peers[i].netns_name, peers[0].netns_name, i));
96 assert(system(command) == 0);
100 // Configure addresses
101 for(int i = 0; i < npeers; i++) {
102 change_peer_ip(&peers[i]);
106 /// Set up an indirect topology where all peers can only access the relay
107 static void setup_indirect_topology(peer_config_t *peers, int npeers) {
108 // Add an interface to each peer that is connected to the relay
109 for(int i = 1; i < npeers; i++) {
110 char *command = NULL;
111 assert(asprintf(&command,
112 "/bin/ip netns exec %1$s /bin/ip link add eth0 type veth peer eth%3$d netns %2$s;"
113 "/bin/ip netns exec %1$s ip addr flush dev eth0;"
114 "/bin/ip netns exec %1$s ip addr add 192.168.%3$d.2/24 dev eth0;"
115 "/bin/ip netns exec %1$s /bin/ip link set dev eth0 up;"
116 "/bin/ip netns exec %2$s ip addr flush dev eth%3$d;"
117 "/bin/ip netns exec %2$s ip addr add 192.168.%3$d.1/24 dev eth%3$d;"
118 "/bin/ip netns exec %2$s /bin/ip link set dev eth%3$d up;",
119 peers[i].netns_name, peers[0].netns_name, i));
121 assert(system(command) == 0);
126 /// Give a peer a unique IP address
127 void change_peer_ip(peer_config_t *peer) {
128 char *command = NULL;
129 assert(asprintf(&command,
130 "/bin/ip netns exec %1$s ip addr flush dev eth0;"
131 "/bin/ip netns exec %1$s ip addr add 203.0.113.%2$d/24 dev eth0;",
132 peer->netns_name, ip));
135 assert(system(command) == 0);
139 /// Let the first peer in a list invite all the subsequent peers
140 static void invite_peers(peer_config_t *peers, int npeers) {
141 assert(peers[0].full);
142 assert(full_meshlink_start(peers[0].mesh));
144 for(int i = 1; i < npeers; i++) {
145 char *invitation = full_meshlink_invite_ex(peers[0].mesh, NULL, peers[i].name, MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_NUMERIC);
147 printf("%s\n", invitation);
148 assert(peers[i].full ? full_meshlink_join(peers[i].mesh, invitation) : meshlink_join(peers[i].mesh, invitation));
152 full_meshlink_stop(peers[0].mesh);
155 /// Close meshlink instances and clean up
156 static void close_peers(peer_config_t *peers, int npeers) {
157 for(int i = 0; i < npeers; i++) {
158 peers[i].full ? full_meshlink_close(peers[i].mesh) : meshlink_close(peers[i].mesh);
159 close(peers[i].netns);
160 free(peers[i].netns_name);
164 /// Set up relay, peer and NUT that are directly connected
165 peer_config_t *setup_relay_peer_nut(const char *prefix) {
166 static peer_config_t peers[] = {
167 {"relay", DEV_CLASS_BACKBONE, NULL, 0, true, NULL},
168 {"peer", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
169 {"nut", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
172 create_peers(peers, 3, prefix);
173 setup_lan_topology(peers, 3);
174 invite_peers(peers, 3);
179 /// Set up relay, peer and NUT that are directly connected
180 peer_config_t *setup_relay_peer_nut_indirect(const char *prefix) {
181 static peer_config_t peers[] = {
182 {"relay", DEV_CLASS_BACKBONE, NULL, 0, true, NULL},
183 {"peer", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
184 {"nut", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
187 create_peers(peers, 3, prefix);
188 setup_indirect_topology(peers, 3);
189 assert(full_meshlink_add_invitation_address(peers[0].mesh, "192.168.1.1", NULL));
190 assert(full_meshlink_add_invitation_address(peers[0].mesh, "192.168.2.1", NULL));
191 invite_peers(peers, 3);
196 /// Make all nodes only be able to communicate via TCP
197 void set_peers_tcponly(peer_config_t *peers, int npeers) {
198 for(int i = 0; i < npeers; i++) {
199 char *command = NULL;
200 assert(asprintf(&command,
201 "/bin/ip netns exec %1$s iptables -A INPUT -p udp -j DROP;"
202 "/bin/ip netns exec %1$s iptables -A OUTPUT -p udp -j DROP;",
203 peers[i].netns_name));
205 assert(system(command) == 0);
210 void close_relay_peer_nut(peer_config_t *peers) {
211 close_peers(peers, 3);