]> git.meshlink.io Git - meshlink/blobdiff - test/blackbox/common/containers.c
Ensure NDEBUG is not set in the test suite.
[meshlink] / test / blackbox / common / containers.c
index d96b1a3715c4b987389f26dc1bf78deda1fa6a2c..c11ca430ec7ca745bdc8c9f411f38f9e83fd936f 100644 (file)
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
@@ -54,7 +58,7 @@ void rename_container(const char *old_name, const char *new_name) {
        struct lxc_container *old_container;
 
        /* Stop the old container if its still running */
-       assert(old_container = find_container(old_name));
+       assert((old_container = find_container(old_name)));
        old_container->shutdown(old_container, CONTAINER_SHUTDOWN_TIMEOUT);
        /* Call stop() in case shutdown() fails - one of these two will always succeed */
        old_container->stop(old_container);
@@ -69,38 +73,51 @@ void rename_container(const char *old_name, const char *new_name) {
        assert(rename_status == 0);
 }
 
+char *run_in_container(const char *cmd, const char *container_name, bool daemonize) {
+       char container_find_name[1000];
+       struct lxc_container *container;
+
+       assert(cmd);
+       assert(container_name);
+       assert(snprintf(container_find_name, sizeof(container_find_name), "%s_%s",
+                       state_ptr->test_case_name, container_name) >= 0);
+       assert((container = find_container(container_find_name)));
+
+       return run_in_container_ex(cmd, container, daemonize);
+}
+
+char *execute_in_container(const char *cmd, const char *container_name, bool daemonize) {
+       struct lxc_container *container;
+
+       assert(cmd);
+       assert(container_name);
+       assert((container = find_container(container_name)));
+
+       return run_in_container_ex(cmd, container, daemonize);
+}
+
 /* Run 'cmd' inside the Container created for 'node' and return the first line of the output
     or NULL if there is no output - useful when, for example, a meshlink invite is generated
     by a node running inside a Container
     'cmd' is run as a daemon if 'daemonize' is true - this mode is useful for running node
     simulations in Containers
     The caller is responsible for freeing the returned string */
-char *run_in_container(const char *cmd, const char *node, bool daemonize) {
-       char attach_command[400];
-       char *attach_argv[4];
-       char container_find_name[100];
-       struct lxc_container *container;
-       FILE *attach_fp;
+char *run_in_container_ex(const char *cmd, struct lxc_container *container, bool daemonize) {
        char *output = NULL;
-       size_t output_len;
-       int i;
-
-       assert(snprintf(container_find_name, sizeof(container_find_name), "%s_%s",
-                       state_ptr->test_case_name, node) >= 0);
-       assert(container = find_container(container_find_name));
+       size_t output_len = 0;
 
        /* Run the command within the Container, either as a daemon or foreground process */
        /* TO DO: Perform this operation using the LXC API - currently does not work using the API
            Need to determine why it doesn't work, and make it work */
        if(daemonize) {
-               for(i = 0; i < 3; i++) {
-                       assert(attach_argv[i] = malloc(DAEMON_ARGV_LEN));
-               }
+               char run_script_path[100];
+               char *attach_argv[4];
 
-               assert(snprintf(attach_argv[0], DAEMON_ARGV_LEN, "%s/" LXC_UTIL_REL_PATH "/" LXC_RUN_SCRIPT,
+               assert(snprintf(run_script_path, sizeof(run_script_path), "%s/" LXC_UTIL_REL_PATH "/" LXC_RUN_SCRIPT,
                                meshlink_root_path) >= 0);
-               strncpy(attach_argv[1], cmd, DAEMON_ARGV_LEN);
-               strncpy(attach_argv[2], container->name, DAEMON_ARGV_LEN);
+               attach_argv[0] = run_script_path;
+               attach_argv[1] = (char *)cmd;
+               attach_argv[2] = container->name;
                attach_argv[3] = NULL;
 
                /* To daemonize, create a child process and detach it from its parent (this program) */
@@ -108,19 +125,24 @@ char *run_in_container(const char *cmd, const char *node, bool daemonize) {
                        assert(daemon(1, 0) != -1);    // Detach from the parent process
                        assert(execv(attach_argv[0], attach_argv) != -1);   // Run exec() in the child process
                }
-
-               for(i = 0; i < 3; i++) {
-                       free(attach_argv[i]);
-               }
        } else {
-               assert(snprintf(attach_command, sizeof(attach_command),
+               char *attach_command;
+               size_t attach_command_len;
+               int i;
+               attach_command_len = strlen(meshlink_root_path) + strlen(LXC_UTIL_REL_PATH) + strlen(LXC_RUN_SCRIPT) + strlen(cmd) + strlen(container->name) + 10;
+               attach_command = malloc(attach_command_len);
+               assert(attach_command);
+
+               assert(snprintf(attach_command, attach_command_len,
                                "%s/" LXC_UTIL_REL_PATH "/" LXC_RUN_SCRIPT " \"%s\" %s", meshlink_root_path, cmd,
                                container->name) >= 0);
-               assert(attach_fp = popen(attach_command, "r"));
+               FILE *attach_fp;
+               assert((attach_fp = popen(attach_command, "r")));
+               free(attach_command);
                /* If the command has an output, strip out any trailing carriage returns or newlines and
                    return it, otherwise return NULL */
-               assert(output = malloc(100));
-               output_len = sizeof(output);
+               output = NULL;
+               output_len = 0;
 
                if(getline(&output, &output_len, attach_fp) != -1) {
                        i = strlen(output) - 1;
@@ -143,26 +165,40 @@ char *run_in_container(const char *cmd, const char *node, bool daemonize) {
 
 /* Wait for a starting Container to obtain an IP Address, then save that IP for future use */
 void container_wait_ip(int node) {
-       char container_name[100], lxcls_command[200];
+       char container_name[100];
+       char *ip;
+
+       assert(snprintf(container_name, sizeof(container_name), "%s_%s", state_ptr->test_case_name,
+                       state_ptr->node_names[node]) >= 0);
+       ip = container_wait_ip_ex(container_name);
+
+       strncpy(container_ips[node], ip, sizeof(container_ips[node])); // Save the IP for future use
+       PRINT_TEST_CASE_MSG("Node '%s' has IP Address %s\n", state_ptr->node_names[node],
+                           container_ips[node]);
+       free(ip);
+}
+
+char *container_wait_ip_ex(const char *container_name) {
        struct lxc_container *test_container;
+       char  lxcls_command[200];
        char *ip;
        size_t ip_len;
-       int i;
        bool ip_found;
+       int i;
+       int timeout;
        FILE *lxcls_fp;
 
-       assert(snprintf(container_name, sizeof(container_name), "%s_%s", state_ptr->test_case_name,
-                       state_ptr->node_names[node]) >= 0);
-       assert(test_container = find_container(container_name));
+       assert((test_container = find_container(container_name)));
        assert(snprintf(lxcls_command, sizeof(lxcls_command),
                        "lxc-ls -f | grep %s | tr -s ' ' | cut -d ' ' -f 5", test_container->name) >= 0);
        PRINT_TEST_CASE_MSG("Waiting for Container '%s' to acquire IP\n", test_container->name);
-       assert(ip = malloc(20));
+       assert((ip = malloc(20)));
        ip_len = sizeof(ip);
        ip_found = false;
+       timeout = 60;
 
-       while(!ip_found) {
-               assert(lxcls_fp = popen(lxcls_command, "r"));   // Run command
+       while(!ip_found && timeout) {
+               assert((lxcls_fp = popen(lxcls_command, "r")));   // Run command
                assert(getline((char **)&ip, &ip_len, lxcls_fp) != -1); // Read its output
                /* Strip newlines and carriage returns from output */
                i = strlen(ip) - 1;
@@ -175,13 +211,13 @@ void container_wait_ip(int node) {
                ip_found = (strcmp(ip, "-") != 0);  // If the output is not "-", IP has been acquired
                assert(pclose(lxcls_fp) != -1);
                sleep(1);
+               timeout--;
        }
 
-       strncpy(container_ips[node], ip, sizeof(container_ips[node])); // Save the IP for future use
-       PRINT_TEST_CASE_MSG("Node '%s' has IP Address %s\n", state_ptr->node_names[node],
-                           container_ips[node]);
+       // Fail if IP cannot be read
+       assert(timeout);
 
-       free(ip);
+       return ip;
 }
 
 /* Create all required test containers */
@@ -189,7 +225,7 @@ void create_containers(const char *node_names[], int num_nodes) {
        int i;
        char container_name[100];
        int create_status, snapshot_status, snap_restore_status;
-       struct lxc_container *first_container;
+       struct lxc_container *first_container = NULL;
 
        for(i = 0; i < num_nodes; i++) {
                assert(snprintf(container_name, sizeof(container_name), "run_%s", node_names[i]) >= 0);
@@ -197,7 +233,7 @@ void create_containers(const char *node_names[], int num_nodes) {
                /* If this is the first Container, create it otherwise restore the snapshot saved
                    for the first Container to create an additional Container */
                if(i == 0) {
-                       assert(first_container = lxc_container_new(container_name, NULL));
+                       assert((first_container = lxc_container_new(container_name, NULL)));
                        assert(!first_container->is_defined(first_container));
                        create_status = first_container->createl(first_container, "download", NULL, NULL,
                                        LXC_CREATE_QUIET, "-d", "ubuntu", "-r", "trusty", "-a", choose_arch, NULL);
@@ -209,6 +245,7 @@ void create_containers(const char *node_names[], int num_nodes) {
                                first_container->error_num, first_container->error_string);
                        assert(snapshot_status != -1);
                } else {
+                       assert(first_container);
                        snap_restore_status = first_container->snapshot_restore(first_container, "snap0",
                                              container_name);
                        fprintf(stderr, "Snapshot restore to Container '%s' status: %d - %s\n", container_name,
@@ -223,7 +260,7 @@ void create_containers(const char *node_names[], int num_nodes) {
     after setting the state of the test case to an instance of black_box_state_t */
 void setup_containers(void **state) {
        black_box_state_t *test_state = (black_box_state_t *)(*state);
-       int i, confbase_del_status;
+       int i;
        char build_command[200];
        struct lxc_container *test_container, *new_container;
        char container_find_name[100];
@@ -238,7 +275,7 @@ void setup_containers(void **state) {
                                test_state->node_names[i]) >= 0);
 
                if(!(test_container = find_container(container_find_name))) {
-                       assert(test_container = lxc_container_new(container_find_name, NULL));
+                       assert((test_container = lxc_container_new(container_find_name, NULL)));
                        assert(!test_container->is_defined(test_container));
                        create_status = test_container->createl(test_container, "download", NULL, NULL,
                                                                LXC_CREATE_QUIET, "-d", "ubuntu", "-r", "trusty", "-a", choose_arch, NULL);
@@ -259,7 +296,7 @@ void setup_containers(void **state) {
 
                if(!(new_container = find_container(container_new_name))) {
                        rename_container(test_container->name, container_new_name);
-                       assert(new_container = find_container(container_new_name));
+                       assert((new_container = find_container(container_new_name)));
                }
 
                /* Start the Container */
@@ -320,7 +357,7 @@ void restart_all_containers(void) {
                /* Shutdown, then start the Container, then wait for it to acquire an IP Address */
                assert(snprintf(container_name, sizeof(container_name), "%s_%s", state_ptr->test_case_name,
                                state_ptr->node_names[i]) >= 0);
-               assert(test_container = find_container(container_name));
+               assert((test_container = find_container(container_name)));
                test_container->shutdown(test_container, CONTAINER_SHUTDOWN_TIMEOUT);
                test_container->stop(test_container);
                test_container->start(test_container, 0, NULL);
@@ -337,7 +374,24 @@ char *invite_in_container(const char *inviter, const char *invitee) {
        assert(snprintf(invite_command, sizeof(invite_command),
                        "LD_LIBRARY_PATH=/home/ubuntu/test/.libs /home/ubuntu/test/gen_invite %s %s "
                        "2> gen_invite.log", inviter, invitee) >= 0);
-       assert(invite_url = run_in_container(invite_command, inviter, false));
+       assert((invite_url = run_in_container(invite_command, inviter, false)));
+       PRINT_TEST_CASE_MSG("Invite Generated from '%s' to '%s': %s\n", inviter,
+                           invitee, invite_url);
+
+       return invite_url;
+}
+
+/* Run the gen_invite command inside the 'inviter' container to generate an invite
+    for 'invitee' belonging to pparticular submesh, and return the generated invite
+    which is output on the terminal */
+char *submesh_invite_in_container(const char *inviter, const char *invitee, const char *submesh) {
+       char invite_command[200];
+       char *invite_url;
+
+       assert(snprintf(invite_command, sizeof(invite_command),
+                       "LD_LIBRARY_PATH=/home/ubuntu/test/.libs /home/ubuntu/test/gen_invite %s %s %s "
+                       "2> gen_invite.log", inviter, invitee, submesh) >= 0);
+       assert((invite_url = run_in_container(invite_command, inviter, false)));
        PRINT_TEST_CASE_MSG("Invite Generated from '%s' to '%s': %s\n", inviter,
                            invitee, invite_url);
 
@@ -346,34 +400,47 @@ char *invite_in_container(const char *inviter, const char *invitee) {
 
 /* Run the node_sim_<nodename> program inside the 'node''s container */
 void node_sim_in_container(const char *node, const char *device_class, const char *invite_url) {
-       char node_sim_command[200];
+       char *node_sim_command;
+       size_t node_sim_command_len;
 
-       assert(snprintf(node_sim_command, sizeof(node_sim_command),
+       node_sim_command_len = 500 + (invite_url ? strlen(invite_url) : 0);
+       node_sim_command = calloc(1, node_sim_command_len);
+       assert(node_sim_command);
+       assert(snprintf(node_sim_command, node_sim_command_len,
                        "LD_LIBRARY_PATH=/home/ubuntu/test/.libs /home/ubuntu/test/node_sim_%s %s %s %s "
                        "1>&2 2>> node_sim_%s.log", node, node, device_class,
                        (invite_url) ? invite_url : "", node) >= 0);
        run_in_container(node_sim_command, node, true);
        PRINT_TEST_CASE_MSG("node_sim_%s started in Container\n", node);
+
+       free(node_sim_command);
 }
 
 /* Run the node_sim_<nodename> program inside the 'node''s container with event handling capable */
 void node_sim_in_container_event(const char *node, const char *device_class,
                                  const char *invite_url, const char *clientId, const char *import) {
-       char node_sim_command[200];
-
-       assert(snprintf(node_sim_command, sizeof(node_sim_command),
+       char *node_sim_command;
+       size_t node_sim_command_len;
+
+       assert(node && device_class && clientId && import);
+       node_sim_command_len = 500 + (invite_url ? strlen(invite_url) : 0);
+       node_sim_command = calloc(1, node_sim_command_len);
+       assert(node_sim_command);
+       assert(snprintf(node_sim_command, node_sim_command_len,
                        "LD_LIBRARY_PATH=/home/ubuntu/test/.libs /home/ubuntu/test/node_sim_%s %s %s %s %s %s "
                        "1>&2 2>> node_sim_%s.log", node, node, device_class,
                        clientId, import, (invite_url) ? invite_url : "", node) >= 0);
        run_in_container(node_sim_command, node, true);
-       PRINT_TEST_CASE_MSG("node_sim_%s(Client Id :%s) started in Container with event handling\n",
-                           node, clientId);
+       PRINT_TEST_CASE_MSG("node_sim_%s(Client Id :%s) started in Container with event handling\n%s\n",
+                           node, clientId, node_sim_command);
+
+       free(node_sim_command);
 }
 
 /* Run the node_step.sh script inside the 'node''s container to send the 'sig' signal to the
     node_sim program in the container */
 void node_step_in_container(const char *node, const char *sig) {
-       char node_step_command[200];
+       char node_step_command[1000];
 
        assert(snprintf(node_step_command, sizeof(node_step_command),
                        "/home/ubuntu/test/node_step.sh lt-node_sim_%s %s 1>&2 2> node_step.log",
@@ -386,7 +453,7 @@ void node_step_in_container(const char *node, const char *sig) {
     Changes begin from X.X.X.254 and continue iteratively till an available address is found */
 void change_ip(int node) {
        char *gateway_addr;
-       char new_ip[20];
+       char new_ip[20] = "";
        char *netmask;
        char *last_dot_in_ip;
        int last_ip_byte = 254;
@@ -398,14 +465,14 @@ void change_ip(int node) {
 
        /* Get IP Address of LXC Bridge Interface - this will be set up as the Gateway Address
            of the Static IP assigned to the Container */
-       assert(gateway_addr = get_ip(lxc_bridge));
+       assert((gateway_addr = get_ip(lxc_bridge)));
        /* Get Netmask of LXC Brdige Interface */
-       assert(netmask = get_netmask(lxc_bridge));
+       assert((netmask = get_netmask(lxc_bridge)));
 
        /* Replace last byte of Container's IP with 254 to form the new Container IP */
        assert(container_ips[node]);
-       strncpy(new_ip, container_ips[node], sizeof(new_ip));
-       assert(last_dot_in_ip = strrchr(new_ip, '.'));
+       strncpy(new_ip, container_ips[node], sizeof(new_ip) - 1);
+       assert((last_dot_in_ip = strrchr(new_ip, '.')));
        assert(snprintf(last_dot_in_ip + 1, 4, "%d", last_ip_byte) >= 0);
 
        /* Check that the new IP does not match the Container's existing IP
@@ -417,7 +484,7 @@ void change_ip(int node) {
        }
 
        /* Create new 'interfaces' file for Container */
-       assert(if_fp = fopen("interfaces", "w"));
+       assert((if_fp = fopen("interfaces", "w")));
        fprintf(if_fp, "auto lo\n");
        fprintf(if_fp, "iface lo inet loopback\n");
        fprintf(if_fp, "\n");
@@ -440,22 +507,56 @@ void change_ip(int node) {
        /* Restart Container to apply new IP Address */
        assert(snprintf(container_name, sizeof(container_name), "%s_%s", state_ptr->test_case_name,
                        state_ptr->node_names[node]) >= 0);
-       assert(container = find_container(container_name));
+       assert((container = find_container(container_name)));
        container->shutdown(container, CONTAINER_SHUTDOWN_TIMEOUT);
        /* Call stop() in case shutdown() fails
            One of these two calls with always succeed */
        container->stop(container);
        assert(container->start(container, 0, NULL));
 
-       strncpy(container_ips[node], new_ip, sizeof(new_ip));   // Save the new IP Addres
+       strncpy(container_ips[node], new_ip, sizeof(container_ips[node]));   // Save the new IP Address
        PRINT_TEST_CASE_MSG("Node '%s' IP Address changed to %s\n", state_ptr->node_names[node],
                            container_ips[node]);
 }
 
+char **get_container_interface_ips(const char *container_name, const char *interface_name) {
+       char **ips;
+       struct lxc_container *container = find_container(container_name);
+       assert(container);
+
+       char **interfaces = container->get_interfaces(container);
+       assert(interfaces);
+
+       int i;
+       ips = NULL;
+
+       for(i = 0; interfaces[i]; i++) {
+               if(!strcasecmp(interfaces[i], interface_name)) {
+                       ips = container->get_ips(container, interface_name, "inet", 0);
+                       assert(ips);
+                       break;
+               }
+       }
+
+       free(interfaces);
+
+       return ips;
+}
+
+/* Install an app in a container */
+void install_in_container(const char *node, const char *app) {
+       char install_cmd[100];
+
+       assert(snprintf(install_cmd, sizeof(install_cmd),
+                       "apt-get install %s -y >> /dev/null", app) >= 0);
+       run_in_container(install_cmd, node, false);
+       // TODO: Check in container whether app has installed or not with a timeout
+       sleep(10);
+}
+
 /* Return container's IP address */
 char *get_container_ip(const char *node_name) {
-       char *ip;
-       int n, node = -1, i;
+       int node = -1, i;
 
        for(i = 0; i < state_ptr->num_nodes; i++) {
                if(!strcasecmp(state_ptr->node_names[i], node_name)) {
@@ -468,25 +569,12 @@ char *get_container_ip(const char *node_name) {
                return NULL;
        }
 
-       n = strlen(container_ips[node]) + 1;
-       ip = malloc(n);
+       char *ip = strdup(container_ips[node]);
        assert(ip);
-       strncpy(ip, container_ips[node], n);
 
        return ip;
 }
 
-/* Install an app in a container */
-void install_in_container(const char *node, const char *app) {
-       char install_cmd[100];
-
-       assert(snprintf(install_cmd, sizeof(install_cmd),
-                       "apt-get install %s -y >> /dev/null", app) >= 0);
-       char *ret = run_in_container(install_cmd, node, false);
-       // TODO: Check in container whether app has installed or not with a timeout
-       sleep(10);
-}
-
 /* Simulate a network failure by adding NAT rule in the container with it's IP address */
 void block_node_ip(const char *node) {
        char block_cmd[100];
@@ -511,7 +599,7 @@ void accept_port_rule(const char *node, const char *chain, const char *protocol,
 
        assert(port >= 0 && port < 65536);
        assert(!strcmp(chain, "INPUT") || !strcmp(chain, "FORWARD") || !strcmp(chain, "OUTPUT"));
-       assert(!strcmp(protocol, "all") || !strcmp(protocol, "tcp") || !strcmp(protocol, "udp"));
+       assert(!strcmp(protocol, "all") || !strcmp(protocol, "tcp") || !strcmp(protocol, "udp") || !strcmp(protocol, "icmp"));
        assert(snprintf(block_cmd, sizeof(block_cmd), "iptables -A %s -p %s --dport %d -j ACCEPT", chain, protocol, port) >= 0);
        run_in_container(block_cmd, node, false);
 }
@@ -533,6 +621,134 @@ void unblock_node_ip(const char *node) {
        run_in_container(unblock_cmd, node, false);
 }
 
+char *block_icmp(const char *container_name) {
+       char block_cmd[500];
+       assert(container_name);
+       assert(snprintf(block_cmd, sizeof(block_cmd), "iptables -A FORWARD -p icmp -j DROP") >= 0);
+       return execute_in_container(block_cmd, container_name, false);
+}
+
+char *unblock_icmp(const char *container_name) {
+       char block_cmd[500];
+       assert(container_name);
+       assert(snprintf(block_cmd, sizeof(block_cmd), "iptables -D FORWARD -p icmp -j DROP") >= 0);
+       return execute_in_container(block_cmd, container_name, false);
+}
+
+char *change_container_mtu(const char *container_name, const char *interface_name, int mtu) {
+       char cmd[500];
+       assert(container_name);
+       assert(snprintf(cmd, sizeof(cmd), "ifconfig %s mtu %d", interface_name, mtu) >= 0);
+       return execute_in_container(cmd, container_name, false);
+}
+
+char *flush_conntrack(const char *container_name) {
+       assert(container_name);
+
+       return execute_in_container("conntrack -F", container_name, false);
+}
+
+void flush_nat_rules(const char *container_name, const char *chain) {
+       char *ret;
+       char flush_cmd[500];
+
+       assert(container_name);
+       assert(snprintf(flush_cmd, sizeof(flush_cmd), "iptables -F %s", chain ? chain : "") >= 0);
+       ret = execute_in_container("iptables -F", container_name, false);
+       assert(ret == NULL);
+}
+
+void add_full_cone_nat_rules(const char *container_name, const char *pub_interface, const char *priv_interface_listen_address) {
+       char nat_cmd[500];
+
+       char **pub_interface_ips = get_container_interface_ips(container_name, pub_interface);
+       assert(pub_interface_ips[0]);
+       char *pub_interface_ip = pub_interface_ips[0];
+
+       assert(snprintf(nat_cmd, sizeof(nat_cmd),
+                       "%s/" LXC_UTIL_REL_PATH "/" LXC_NAT_FULL_CONE " %s %s %s %s >/dev/null",
+                       meshlink_root_path, container_name, pub_interface, pub_interface_ip, priv_interface_listen_address) >= 0);
+       assert(system(nat_cmd) == 0);
+       free(pub_interface_ips);
+}
+
+/* Create a NAT and a bridge, bridge connected to NAT and containers to be NATed can be switched
+    to the NAT bridge from lxcbr0 */
+void nat_create(const char *nat_name, const char *nat_bridge, int nat_type) {
+       (void)nat_type;
+
+       char build_command[200];
+       assert(snprintf(build_command, sizeof(build_command),
+                       "%s/" LXC_UTIL_REL_PATH "/" LXC_NAT_BUILD " %s %s %s >/dev/stderr",
+                       meshlink_root_path, nat_name, nat_bridge, meshlink_root_path) >= 0);
+       assert(system(build_command) == 0);
+}
+
+void nat_destroy(const char *nat_name) {
+       char build_command[200];
+       assert(snprintf(build_command, sizeof(build_command),
+                       "%s/" LXC_UTIL_REL_PATH "/" LXC_NAT_DESTROY " %s +x >/dev/null",
+                       meshlink_root_path, nat_name) >= 0);
+       assert(system(build_command) == 0);
+}
+
+/* Switches a container from current bridge to a new bridge */
+void container_switch_bridge(const char *container_name, char *lxc_conf_path, const char *current_bridge, const char *new_bridge) {
+       char config_path[500];
+       char buffer[500];
+       struct lxc_container *container;
+       char *lxc_path_temp;
+       char *ip;
+
+       PRINT_TEST_CASE_MSG("Switiching container %s from bridge '%s' to bridge '%s'", container_name, current_bridge, new_bridge);
+       lxc_path_temp = lxc_path;
+       lxc_path = lxc_conf_path;
+       container = find_container(container_name);
+       assert(container);
+       lxc_path = lxc_path_temp;
+       assert(snprintf(config_path, sizeof(config_path), "%s/%s/config", lxc_conf_path, container_name) >= 0);
+       FILE *fp = fopen(config_path, "r");
+       assert(fp);
+       FILE *fp_temp = fopen(".temp_file", "w");
+       assert(fp_temp);
+
+       int net_no;
+
+       while((fgets(buffer, sizeof(buffer), fp)) != NULL) {
+               if(sscanf(buffer, "lxc.net.%d.link", &net_no) == 1) {
+                       char *ptr;
+                       int len;
+
+                       if((ptr = strstr(buffer, current_bridge)) != NULL) {
+                               len = strlen(current_bridge);
+
+                               if(((*(ptr - 1) == ' ') || (*(ptr - 1) == '\t') || (*(ptr - 1) == '=')) && ((ptr[len] == '\n') || (ptr[len] == '\t') || (ptr[len] == '\0') || (ptr[len] == ' '))) {
+                                       sprintf(buffer, "lxc.net.%d.link = %s\n", net_no, new_bridge);
+                               }
+                       }
+               }
+
+               fputs(buffer, fp_temp);
+       }
+
+       fclose(fp_temp);
+       fclose(fp);
+       remove(config_path);
+       rename(".temp_file", config_path);
+
+       /* Restart the Container after building it and wait for it to acquire an IP */
+       char cmd[200];
+       int sys_ret;
+       assert(snprintf(cmd, sizeof(cmd), "lxc-stop %s", container_name) >= 0);
+       sys_ret = system(cmd);
+       assert(snprintf(cmd, sizeof(cmd), "lxc-start %s", container_name) >= 0);
+       sys_ret = system(cmd);
+       assert(sys_ret == 0);
+       ip = container_wait_ip_ex(container_name);
+       PRINT_TEST_CASE_MSG("Obtained IP address: %s for container %s after switching bridge", ip, container_name);
+       free(ip);
+}
+
 /* Takes bridgeName as input parameter and creates a bridge */
 void create_bridge(const char *bridgeName) {
        char command[100] = "brctl addbr ";
@@ -583,7 +799,6 @@ void add_veth_pair(const char *vethName1, const char *vethName2) {
 /* Bring the interface up for the bridge created */
 void bring_if_up(const char *bridgeName) {
        char command[300] = "ifconfig ";
-       char dhcommand[300] = "dhclient ";
        strcat(command, bridgeName);
        strcat(command, " up");
        int if_up_status = system(command);
@@ -698,7 +913,7 @@ void create_container_on_bridge(const char *containerName, const char *bridgeNam
        int container_create_status = system(command);
        assert(container_create_status == 0);
        sleep(3);
-       assert(fPtr = fopen(path, "a+"));
+       assert((fPtr = fopen(path, "a+")));
        fprintf(fPtr, "lxc.net.0.name = eth0\n");
        fprintf(fPtr, "\n");
        fprintf(fPtr, "lxc.net.1.type = veth\n");
@@ -774,8 +989,8 @@ void config_nat(const char *containerName, const char *listenAddress) {
        char *last_dot_in_ip;
        int last_ip_byte = 0;
        char new_ip[300] = {0};
-       strncpy(new_ip, listenAddress, sizeof(new_ip));
-       assert(last_dot_in_ip = strrchr(new_ip, '.'));
+       strncpy(new_ip, listenAddress, sizeof(new_ip) - 1);
+       assert((last_dot_in_ip = strrchr(new_ip, '.')));
        assert(snprintf(last_dot_in_ip + 1, 4, "%d", last_ip_byte) >= 0);
        char comd[300] = "echo \"iptables -t nat -A POSTROUTING -s ";
        strcat(comd, new_ip);
@@ -891,3 +1106,29 @@ void outgoing_firewall_ipv6(const char *packetType, int portNumber) {
        PRINT_TEST_CASE_MSG("Firewall for outgoing requests added on IPv6");
        assert(system("ip6tables -L") == 0);
 }
+
+void bridge_add(const char *bridge_name) {
+       char cmd[500];
+
+       assert(bridge_name);
+       assert(snprintf(cmd, sizeof(cmd), "brctl addbr %s", bridge_name) >= 0);
+       assert(system(cmd) == 0);
+       assert(snprintf(cmd, sizeof(cmd), "ifconfig %s up", bridge_name) >= 0);
+       assert(system(cmd) == 0);
+}
+
+void bridge_delete(const char *bridge_name) {
+       char cmd[500];
+
+       assert(bridge_name);
+       assert(snprintf(cmd, sizeof(cmd), "brctl delbr %s", bridge_name) >= 0);
+       assert(system(cmd) == 0);
+}
+
+void bridge_add_interface(const char *bridge_name, const char *interface_name) {
+       char cmd[500];
+
+       assert(bridge_name || interface_name);
+       assert(snprintf(cmd, sizeof(cmd), "brctl addif %s %s", bridge_name, interface_name) >= 0);
+       assert(system(cmd) == 0);
+}