Beispiel #1
0
def read_config(path, sep=' = '):
    """
    This helper function reads a simple configuration file with the following format:

     max_range = 50.0
     repeat    = 1
     blocks    = []
     goal      = ""
     ...

    :param path: path to the configuration file
    :param sep: separator between the key and the value
    :return: dictionary with the whole configuration
    """
    config = {}
    try:
        with open(join(path, 'simulation.conf')) as f:
            for line in f.readlines():
                if line.strip().startswith('#'):
                    continue
                try:
                    k, v = [x.strip() for x in line.split(sep)]
                except ValueError:
                    continue
                try:
                    v = ast.literal_eval(v)
                except ValueError:
                    pass
                config[k] = v
    except OSError:
        logger.error("Configuration file 'simulation.conf' does not exist !")
    return config
Beispiel #2
0
def read_config(path, sep=' = '):
    """
    This helper function reads a simple configuration file with the following format:

     max_range = 50.0
     repeat    = 1
     blocks    = []
     goal      = ""
     ...

    :param path: path to the configuration file
    :param sep: separator between the key and the value
    :return: dictionary with the whole configuration
    """
    config = {}
    try:
        with open(join(path, 'simulation.conf')) as f:
            for line in f.readlines():
                if line.strip().startswith('#'):
                    continue
                try:
                    k, v = [x.strip() for x in line.split(sep)]
                except ValueError:
                    continue
                try:
                    v = ast.literal_eval(v)
                except ValueError:
                    pass
                config[k] = v
    except OSError:
        logger.error("Configuration file 'simulation.conf' does not exist !")
    return config
Beispiel #3
0
def build(name, ask=True, **kwargs):
    """
    Build the malicious mote to its target hardware.

    :param name: experiment name (or absolute path to experiment)
    :param ask: ask confirmation
    :param path: expanded path of the experiment (dynamically filled in through 'command' decorator with 'expand'
    """
    def is_device_present():
        with settings(hide(*HIDDEN_ALL), warn_only=True):
            return local(
                "if [ -c /dev/ttyUSB0 ]; then echo 'ok'; else echo 'nok'; fi",
                capture=True) == 'ok'

    console = kwargs.get('console')
    counter, interval = 0.0, 0.5
    while not is_device_present():
        sleep(interval)
        counter += interval
        if counter % 5 == 0:
            logger.warning("Waiting for mote to be detected...")
        elif counter >= 120:
            logger.error(
                "Something failed with the mote ; check that it mounts to /dev/ttyUSB0"
            )
            return
    remake(name, build=True, **
           kwargs) if console is None else console.do_remake(
               name, build=True, **kwargs)
Beispiel #4
0
def __remake(name, build=False, **kwargs):
    """
    Remake the malicious mote of an experiment.
     (meaning that it lets all simulation's files unchanged except ./motes/malicious.[target])

    :param name: experiment name
    :param path: expanded path of the experiment (dynamically filled in through 'command' decorator with 'expand'
    """
    path = kwargs['path']
    logger.debug(" > Retrieving parameters...")
    params = read_config(path)
    ext_lib = params.get("ext_lib")
    if ext_lib and not exists(ext_lib):
        logger.error("External library does not exist !")
        logger.critical("Make aborted.")
        return False
    logger.debug(" > Recompiling malicious mote...")
    # remove former compiled malicious mote and prepare the template
    templates = get_path(path, 'templates', create=True)
    get_path(templates, 'motes', create=True)
    copy_files((TEMPLATES_FOLDER, 'experiment'), templates,
               ('motes/{}.c'.format(params["mtype_malicious"]), 'motes/malicious.c'))
    # recreate malicious C file from template and clean the temporary template
    replacements = render_templates(path, only_malicious=True, **params)
    # then clean the temporary folder with templates
    remove_folder(templates)
    # now recompile
    with settings(hide(*HIDDEN_ALL), warn_only=True):
        with_malicious = join(path, 'with-malicious', 'motes')
        without_malicious = join(path, 'without-malicious', 'motes')
        contiki = join(with_malicious, 'contiki')
        contiki_rpl = join(contiki, 'core', 'net', 'rpl')
        with lcd(with_malicious):
            malicious = 'malicious.{}'.format(params["malicious_target"])
            croot, csensor = 'root.{}'.format(params["target"]), 'sensor.{}'.format(params["target"])
            # handle the malicious mote recompilation
            copy_folder(CONTIKI_FOLDER, with_malicious, includes=get_contiki_includes(params["malicious_target"]))
            if ext_lib is not None:
                remove_folder(contiki_rpl)
                copy_folder(ext_lib, contiki_rpl)
            apply_replacements(contiki_rpl, replacements)
            logger.debug(" > Making '{}'...".format(malicious))
            stderr(local)("make malicious{} CONTIKI={}"
                          .format(['', '.upload'][build], contiki), capture=True)
            if build:
                build = get_path(path, 'build', create=True)
                move_files(with_malicious, build, 'tmpimage.ihex')
                copy_files(with_malicious, build, malicious)
            move_files(with_malicious, without_malicious, malicious)
            local('make clean')
            remove_files(with_malicious, 'malicious.c')
            move_files(without_malicious, with_malicious, malicious)
            copy_files(without_malicious, with_malicious, croot, csensor)
            remove_folder(contiki)
Beispiel #5
0
def render_templates(path, only_malicious=False, **params):
    """
    This function is aimed to adapt and render the base templates dictionary with provided parameters.

    :param path: experiment folder path
    :param only_malicious: flag to indicate if all the templates have to be deployed or only malicious' one
    :param params: dictionary with all the parameters for the experiment
    :return: eventual replacements to be made in ContikiRPL files
    """
    templates = deepcopy(TEMPLATES)
    env = Environment(loader=FileSystemLoader(join(path, 'templates')))
    # fill in the different templates with input parameters
    constants, replacements = get_constants_and_replacements(params["blocks"])
    templates["motes/malicious.c"]["constants"] = "\n".join(
        ["#define {} {}".format(*c) for c in constants.items()])
    if only_malicious:
        template_malicious = "motes/malicious.c"
        write_template(join(path, "with-malicious"), env, template_malicious,
                       **templates[template_malicious])
        return replacements
    # generate the list of motes (first one is the root, last one is the malicious mote)
    motes = params['motes']
    if motes is None:
        # strictly check for WSN generation function (for avoiding code injection in 'eval')
        from core.common.wsngenerator import __all__ as wsn_algos
        wsn_algo = params["wsn_gen_algo"]
        if wsn_algo in wsn_algos:
            motes = eval(wsn_algo)(defaults=DEFAULTS, **params)
        else:
            logger.error("Bad list of motes")
            return
    # fill in simulation file templates
    templates["report.md"] = deepcopy(params)
    templates["motes/Makefile"]["target"] = params["target"]
    # important note: timeout is milliseconds in the simulation script
    templates["script.js"]["timeout"] = 1000 * params["duration"]
    # important note: sampling period is relative to the measured time in the simulation, which is in microseconds ;
    #                  the '10 * ' thus means that we take 100 measures regardless the duration of the simulation
    templates["script.js"][
        "sampling_period"] = templates["script.js"]["timeout"] * 10
    templates["simulation.csc"][
        "title"] = params["title"] + ' (with the malicious mote)'
    templates["simulation.csc"]["goal"] = params["goal"]
    templates["simulation.csc"]["notes"] = params["notes"]
    templates["simulation.csc"]["interference_range"] = params["int_range"]
    templates["simulation.csc"]["transmitting_range"] = params["tx_range"]
    templates["simulation.csc"]["target"] = params["target"]
    templates["simulation.csc"]["target_capitalized"] = params[
        "target"].capitalize()
    templates["simulation.csc"]["malicious_target"] = params[
        "malicious_target"]
    templates["simulation.csc"]["malicious_target_capitalized"] = params[
        "malicious_target"].capitalize()
    templates["simulation.csc"]["motes"] = motes
    for mote_type in templates["simulation.csc"]["mote_types"]:
        mote_type["target"] = params["target"] if mote_type[
            "name"] != "malicious" else params["malicious_target"]
    # render the templates for the simulation with the malicious mote
    for name, kwargs in templates.items():
        write_template(join(path, 'with-malicious'), env, name, **kwargs)
    # now, adapt the title and mote source template
    del templates["motes/Makefile"]
    del templates["motes/root.c"]
    del templates["motes/sensor.c"]
    del templates["motes/malicious.c"]
    templates["simulation.csc"][
        "title"] = params["title"] + ' (without the malicious mote)'
    templates["simulation.csc"]["motes"] = motes[:-1]
    del templates["simulation.csc"]["mote_types"][-1]
    # render the templates for the simulation without the malicious mote
    for name, kwargs in templates.items():
        write_template(join(path, 'without-malicious'), env, name, **kwargs)
    return replacements
Beispiel #6
0
def __make(name, ask=True, **kwargs):
    """
    Make a new experiment.

    :param name: experiment name (or path to the experiment, if expanded in the 'command' decorator)
    :param ask: ask confirmation
    :param path: expanded path of the experiment (dynamically filled in through 'command' decorator with 'expand'
    :param kwargs: simulation keyword arguments (see the documentation for more information)
    """
    global reuse_bin_path
    path = kwargs['path']
    logger.debug(" > Validating parameters...")
    params = validated_parameters(kwargs)
    ext_lib = params.get("ext_lib")
    if ext_lib and not exists(ext_lib):
        logger.error("External library does not exist !")
        logger.critical("Make aborded.")
        return False
    logger.debug(" > Creating simulation...")
    # create experiment's directories
    check_structure(path, create=True, remove=True)
    templates = get_path(path, 'templates', create=True)
    get_path(templates, 'motes', create=True)
    # select the right malicious mote template and duplicate the simulation file
    copy_files((TEMPLATES_FOLDER, 'experiment'), templates,
               ('motes/{}.c'.format(params["mtype_root"]), 'motes/root.c'),
               ('motes/{}.c'.format(params["mtype_sensor"]), 'motes/sensor.c'),
               ('motes/{}.c'.format(params["mtype_malicious"]), 'motes/malicious.c'),
               'motes/Makefile', 'Makefile', 'simulation.csc', 'script.js')
    # create experiment's files from templates then clean the templates folder
    replacements = render_templates(path, **params)
    remove_folder(templates)
    # now, write the config file without the list of motes
    del params['motes']
    write_config(path, params)
    # now compile
    with settings(hide(*HIDDEN_ALL), warn_only=True):
        with_malicious = join(path, 'with-malicious', 'motes')
        without_malicious = join(path, 'without-malicious', 'motes')
        contiki = join(with_malicious, 'contiki')
        contiki_rpl = join(contiki, 'core', 'net', 'rpl')
        # copy a reduced version of Contiki where the debug flags can be set for RPL files set in DEBUG_FILES
        copy_folder(CONTIKI_FOLDER, with_malicious,
                    includes=get_contiki_includes(params["target"], params["malicious_target"]))
        apply_debug_flags(contiki_rpl, debug=['NONE', 'PRINT'][params["debug"]])
        with lcd(with_malicious):
            # first, compile root and sensor mote types
            croot, csensor = 'root.{}'.format(params["target"]), 'sensor.{}'.format(params["target"])
            if reuse_bin_path is None or reuse_bin_path == with_malicious:
                logger.debug(" > Making '{}'...".format(croot))
                stderr(local)("make root CONTIKI={}".format(contiki), capture=True)
                logger.debug(" > Making '{}'...".format(csensor))
                stderr(local)("make sensor CONTIKI={}".format(contiki), capture=True)
                # here, files are moved ; otherwise, 'make clean' would also remove *.z1
                move_files(with_malicious, without_malicious, croot, csensor)
                # after compiling, clean artifacts
                local('make clean')
                remove_files(with_malicious, 'root.c', 'sensor.c')
            else:
                copy_files(reuse_bin_path, without_malicious, croot, csensor)
            # second, handle the malicious mote compilation
            malicious = 'malicious.{}'.format(params["malicious_target"])
            if ext_lib is not None:
                remove_folder(contiki_rpl)
                copy_folder(ext_lib, contiki_rpl)
            apply_replacements(contiki_rpl, replacements)
            logger.debug(" > Making '{}'...".format(malicious))
            stderr(local)("make malicious CONTIKI={} TARGET={}"
                          .format(contiki, params["malicious_target"]), capture=True)
            # temporary move compiled malicious mote, clean the compilation artifacts, move the malicious mote back
            #  from the temporary location and copy compiled root and sensor motes
            move_files(with_malicious, without_malicious, malicious)
            local('make clean')
            move_files(without_malicious, with_malicious, malicious)
            copy_files(without_malicious, with_malicious, croot, csensor)
            # finally, remove compilation sources
            remove_files(with_malicious, 'malicious.c')
            remove_folder(contiki)
Beispiel #7
0
def __run(name, **kwargs):
    """
    Run an experiment.

    :param name: experiment name
    :param path: expanded path of the experiment (dynamically filled in through 'command' decorator with 'expand'
    """
    set_logging(kwargs.get('loglevel'))
    path = kwargs['path']
    check_structure(path, remove=True)
    with settings(hide(*HIDDEN_ALL), warn_only=True):
        for sim in ["without", "with"]:
            sim_path = join(path, "{}-malicious".format(sim))
            data, results = join(sim_path, 'data'), join(sim_path, 'results')
            # the Makefile is at experiment's root ('path')
            logger.debug(
                " > Running simulation {} the malicious mote...".format(sim))
            with lcd(sim_path):
                output = local("make run TASK={}".format(kwargs['task']),
                               capture=True)
            remove_files(sim_path, '.{}'.format(kwargs['task']))
            error, interrupt, error_buffer = False, False, []
            for line in output.split('\n'):
                if line.strip().startswith("FATAL") or line.strip().startswith(
                        "ERROR"):
                    error, interrupt = True, True
                elif line.strip().startswith("INFO"):
                    error = False
                    if len(error_buffer) > 0:
                        logger.error('Cooja error:\n' +
                                     '\n'.join(error_buffer))
                        error_buffer = []
                if error:
                    error_buffer.append(line)
            if interrupt:
                logger.warn(
                    "Cooja failed to execute ; 'run' interrupted (no parsing done)"
                )
                raise Exception("Cooja failed to execute")
            # once the execution is over, gather the screenshots into a single GIF and keep the first and
            #  the last screenshots ; move these to the results folder
            logger.debug(" > Gathering screenshots in an animated GIF...")
            with lcd(data):
                local(
                    'convert -delay 10 -loop 0 network*.png wsn-{}-malicious.gif'
                    .format(sim),
                    capture=True)
            network_images = {
                int(fn.split('.')[0].split('_')[-1]): fn
                for fn in listdir(data) if fn.startswith('network_')
            }
            move_files(data, results, 'wsn-{}-malicious.gif'.format(sim))
            net_start_old = network_images[min(network_images.keys())]
            net_start, ext = splitext(net_start_old)
            net_start_new = 'wsn-{}-malicious_start{}'.format(sim, ext)
            net_end_old = network_images[max(network_images.keys())]
            net_end, ext = splitext(net_end_old)
            net_end_new = 'wsn-{}-malicious_end{}'.format(sim, ext)
            move_files(data, results, (net_start_old, net_start_new),
                       (net_end_old, net_end_new))
            remove_files(data, *network_images.values())
            # then start the parsing functions to derive more results
            logger.debug(" > Parsing simulation results...")
            parsing_chain(sim_path)
            move_files(sim_path, results, 'COOJA.log')
Beispiel #8
0
def __remake(name, build=False, **kwargs):
    """
    Remake the malicious mote of an experiment.
     (meaning that it lets all simulation's files unchanged except ./motes/malicious.[target])

    :param name: experiment name
    :param path: expanded path of the experiment (dynamically filled in through 'command' decorator with 'expand'
    """
    set_logging(kwargs.get('loglevel'))
    path = kwargs['path']
    logger.debug(" > Retrieving parameters...")
    params = read_config(path)
    ext_lib = params.get("ext_lib")
    if ext_lib and not exists(ext_lib):
        logger.error("External library does not exist !")
        logger.critical("Make aborted.")
        return False
    logger.debug(" > Recompiling malicious mote...")
    # remove former compiled malicious mote and prepare the template
    templates = get_path(path, 'templates', create=True)
    get_path(templates, 'motes', create=True)
    copy_files(
        (TEMPLATES_FOLDER, 'experiment'), templates,
        ('motes/{}.c'.format(params["mtype_malicious"]), 'motes/malicious.c'))
    # recreate malicious C file from template and clean the temporary template
    replacements = render_templates(path, only_malicious=True, **params)
    # then clean the temporary folder with templates
    remove_folder(templates)
    # now recompile
    with settings(hide(*HIDDEN_ALL), warn_only=True):
        with_malicious = join(path, 'with-malicious', 'motes')
        without_malicious = join(path, 'without-malicious', 'motes')
        contiki = join(with_malicious, split(CONTIKI_FOLDER)[-1])
        contiki_rpl = join(contiki, 'core', 'net', 'rpl')
        with lcd(with_malicious):
            malicious = 'malicious.{}'.format(params["malicious_target"])
            croot, csensor = 'root.{}'.format(
                params["target"]), 'sensor.{}'.format(params["target"])
            # handle the malicious mote recompilation
            copy_folder(CONTIKI_FOLDER,
                        with_malicious,
                        includes=get_contiki_includes(
                            params["malicious_target"]))
            if ext_lib is not None:
                remove_folder(contiki_rpl)
                copy_folder(ext_lib, contiki_rpl)
            apply_replacements(contiki_rpl, replacements)
            if build:
                logger.debug(" > Building '{}'...".format(malicious))
                stderr(local)(
                    "sudo make malicious.upload CONTIKI={} TARGET={}".format(
                        contiki, params["malicious_target"]))
                build = get_path(path, 'build', create=True)
                move_files(with_malicious, build, 'tmpimage.ihex')
                copy_files(with_malicious, build, malicious)
            else:
                logger.debug(" > Making '{}'...".format(malicious))
                stderr(local)("make malicious CONTIKI={} TARGET={}".format(
                    contiki, params["malicious_target"]),
                              capture=True)
            move_files(with_malicious, without_malicious, malicious)
            local('make clean')
            remove_files(with_malicious, 'malicious.c')
            move_files(without_malicious, with_malicious, malicious)
            copy_files(without_malicious, with_malicious, croot, csensor)
            remove_folder(contiki)
Beispiel #9
0
def __make(name, ask=True, **kwargs):
    """
    Make a new experiment.

    :param name: experiment name (or path to the experiment, if expanded in the 'command' decorator)
    :param ask: ask confirmation
    :param path: expanded path of the experiment (dynamically filled in through 'command' decorator with 'expand'
    :param kwargs: simulation keyword arguments (see the documentation for more information)
    """
    global reuse_bin_path
    set_logging(kwargs.get('loglevel'))
    path = kwargs['path']
    logger.debug(" > Validating parameters...")
    params = validated_parameters(kwargs)
    ext_lib = params.get("ext_lib")
    if ext_lib and not exists(ext_lib):
        logger.error("External library does not exist !")
        logger.critical("Make aborded.")
        return False
    logger.debug(" > Creating simulation...")
    # create experiment's directories
    check_structure(path, create=True, remove=True)
    templates = get_path(path, 'templates', create=True)
    get_path(templates, 'motes', create=True)
    # select the right malicious mote template and duplicate the simulation file
    copy_files(
        (TEMPLATES_FOLDER, 'experiment'), templates,
        ('motes/{}.c'.format(params["mtype_root"]), 'motes/root.c'),
        ('motes/{}.c'.format(params["mtype_sensor"]), 'motes/sensor.c'),
        ('motes/{}.c'.format(params["mtype_malicious"]), 'motes/malicious.c'),
        'motes/Makefile', 'Makefile', 'simulation.csc', 'script.js')
    # create experiment's files from templates then clean the templates folder
    replacements = render_templates(path, **params)
    remove_folder(templates)
    # now, write the config file without the list of motes
    del params['motes']
    write_config(path, params)
    # now compile
    with settings(hide(*HIDDEN_ALL), warn_only=True):
        with_malicious = join(path, 'with-malicious', 'motes')
        without_malicious = join(path, 'without-malicious', 'motes')
        contiki = join(with_malicious, split(CONTIKI_FOLDER)[-1])
        contiki_rpl = join(contiki, 'core', 'net', 'rpl')
        # copy a reduced version of Contiki where the debug flags can be set for RPL files set in DEBUG_FILES
        copy_folder(CONTIKI_FOLDER,
                    with_malicious,
                    includes=get_contiki_includes(params["target"],
                                                  params["malicious_target"]))
        apply_debug_flags(contiki_rpl,
                          debug=['NONE', 'PRINT'][params["debug"]])
        with lcd(with_malicious):
            # first, compile root and sensor mote types
            croot, csensor = 'root.{}'.format(
                params["target"]), 'sensor.{}'.format(params["target"])
            if reuse_bin_path is None or reuse_bin_path == with_malicious:
                logger.debug(" > Making '{}'...".format(croot))
                stderr(local)("make root CONTIKI={}".format(contiki),
                              capture=True)
                logger.debug(" > Making '{}'...".format(csensor))
                stderr(local)("make sensor CONTIKI={}".format(contiki),
                              capture=True)
                # here, files are moved ; otherwise, 'make clean' would also remove *.z1
                move_files(with_malicious, without_malicious, croot, csensor)
                # after compiling, clean artifacts
                local('make clean')
                remove_files(with_malicious, 'root.c', 'sensor.c')
            else:
                copy_files(reuse_bin_path, without_malicious, croot, csensor)
            # second, handle the malicious mote compilation
            malicious = 'malicious.{}'.format(params["malicious_target"])
            if ext_lib is not None:
                remove_folder(contiki_rpl)
                copy_folder(ext_lib, contiki_rpl)
            apply_replacements(contiki_rpl, replacements)
            logger.debug(" > Making '{}'...".format(malicious))
            stderr(local)("make malicious CONTIKI={} TARGET={}".format(
                contiki, params["malicious_target"]),
                          capture=True)
            # temporary move compiled malicious mote, clean the compilation artifacts, move the malicious mote back
            #  from the temporary location and copy compiled root and sensor motes
            move_files(with_malicious, without_malicious, malicious)
            local('make clean')
            move_files(without_malicious, with_malicious, malicious)
            copy_files(without_malicious, with_malicious, croot, csensor)
            # finally, remove compilation sources
            remove_files(with_malicious, 'malicious.c')
            remove_folder(contiki)
Beispiel #10
0
def render_templates(path, only_malicious=False, **params):
    """
    This function is aimed to adapt and render the base templates dictionary with provided parameters.

    :param path: experiment folder path
    :param only_malicious: flag to indicate if all the templates have to be deployed or only malicious' one
    :param params: dictionary with all the parameters for the experiment
    :return: eventual replacements to be made in ContikiRPL files
    """
    templates = deepcopy(TEMPLATES)
    env = Environment(loader=FileSystemLoader(join(path, 'templates')))
    # fill in the different templates with input parameters
    constants, replacements = get_constants_and_replacements(params["blocks"])
    templates["motes/malicious.c"]["constants"] = "\n".join(["#define {} {}".format(*c) for c in constants.items()])
    if only_malicious:
        template_malicious = "motes/malicious.c"
        write_template(join(path, "with-malicious"), env, template_malicious, **templates[template_malicious])
        return replacements
    # generate the list of motes (first one is the root, last one is the malicious mote)
    motes = params['motes']
    if motes is None:
        # strictly check for WSN generation function (for avoiding code injection in 'eval')
        from core.common.wsngenerator import __all__ as wsn_algos
        wsn_algo = params["wsn_gen_algo"]
        if wsn_algo in wsn_algos:
            motes = eval(wsn_algo)(defaults=DEFAULTS, **params)
        else:
            logger.error("Bad list of motes")
            return
    # fill in simulation file templates
    templates["report.md"] = deepcopy(params)
    templates["motes/Makefile"]["target"] = params["target"]
    # important note: timeout is milliseconds in the simulation script
    templates["script.js"]["timeout"] = 1000 * params["duration"]
    # important note: sampling period is relative to the measured time in the simulation, which is in microseconds ;
    #                  the '10 * ' thus means that we take 100 measures regardless the duration of the simulation
    templates["script.js"]["sampling_period"] = templates["script.js"]["timeout"] * 10
    templates["simulation.csc"]["title"] = params["title"] + ' (with the malicious mote)'
    templates["simulation.csc"]["goal"] = params["goal"]
    templates["simulation.csc"]["notes"] = params["notes"]
    templates["simulation.csc"]["interference_range"] = params["int_range"]
    templates["simulation.csc"]["transmitting_range"] = params["tx_range"]
    templates["simulation.csc"]["target"] = params["target"]
    templates["simulation.csc"]["target_capitalized"] = params["target"].capitalize()
    templates["simulation.csc"]["malicious_target"] = params["malicious_target"]
    templates["simulation.csc"]["malicious_target_capitalized"] = params["malicious_target"].capitalize()
    templates["simulation.csc"]["motes"] = motes
    for mote_type in templates["simulation.csc"]["mote_types"]:
        mote_type["target"] = params["target"] if mote_type["name"] != "malicious" else params["malicious_target"]
    # render the templates for the simulation with the malicious mote
    for name, kwargs in templates.items():
        write_template(join(path, 'with-malicious'), env, name, **kwargs)
    # now, adapt the title and mote source template
    del templates["motes/Makefile"]
    del templates["motes/root.c"]
    del templates["motes/sensor.c"]
    del templates["motes/malicious.c"]
    templates["simulation.csc"]["title"] = params["title"] + ' (without the malicious mote)'
    templates["simulation.csc"]["motes"] = motes[:-1]
    del templates["simulation.csc"]["mote_types"][-1]
    # render the templates for the simulation without the malicious mote
    for name, kwargs in templates.items():
        write_template(join(path, 'without-malicious'), env, name, **kwargs)
    return replacements