]> Kevux Git Server - fll/commitdiff
Add Package: firewall
authorKevin Day <kevin@kevux.org>
Sun, 11 Mar 2012 06:14:38 +0000 (00:14 -0600)
committerKevin Day <kevin@kevux.org>
Sun, 11 Mar 2012 06:14:38 +0000 (00:14 -0600)
This package was missed during the conversion from svn to git.

level_3/firewall/c/firewall.c [new file with mode: 0644]
level_3/firewall/c/firewall.h [new file with mode: 0644]
level_3/firewall/c/main.c [new file with mode: 0644]
level_3/firewall/data/build/settings [new file with mode: 0644]
level_3/firewall/data/settings/default-blacklist [new file with mode: 0644]
level_3/firewall/data/settings/default-firewall [new file with mode: 0644]
level_3/firewall/data/settings/default-whitelist [new file with mode: 0644]
level_3/firewall/data/settings/example-device-firewall [new file with mode: 0644]

diff --git a/level_3/firewall/c/firewall.c b/level_3/firewall/c/firewall.c
new file mode 100644 (file)
index 0000000..dfd1366
--- /dev/null
@@ -0,0 +1,1648 @@
+/* FLL - Level 3
+ * Project:       Firewall
+ * Version:       0.3.x
+ * Licenses:      lgplv2.1
+ * Programmers:   Kevin Day
+ */
+#include <level_3/firewall.h>
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+// version printed may be used by scripts, so this will only print the version number and a newline, no extra information or colors
+#ifndef _di_firewall_print_version_
+  f_return_status firewall_print_version(const firewall_data data){
+    printf("%s\n", firewall_version);
+
+    return f_none;
+  }
+#endif // _firewall_print_version_
+
+#ifndef _di_firewall_print_help_
+  f_return_status firewall_print_help(const firewall_data data){
+    printf("\n");
+    fl_print_color(f_standard_output, data.context.title, data.context.reset, " %s", firewall_name_long);
+
+    printf("\n");
+    fl_print_color(f_standard_output, data.context.notable, data.context.reset, "  Version %s", firewall_version);
+
+    printf("\n\n");
+    fl_print_color(f_standard_output, data.context.important, data.context.reset, " Available Options: ");
+
+    printf("\n  %s", f_console_symbol_short_enable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_short_help);
+
+    printf(", %s", f_console_symbol_long_enable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_long_help);
+    printf("      Print this help message");
+
+    printf("\n  %s", f_console_symbol_short_disable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_short_light);
+
+    printf(", %s", f_console_symbol_long_disable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_long_light);
+    printf("     Output using colors that show up better on light backgrounds");
+
+    printf("\n  %s", f_console_symbol_short_disable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_short_no_color);
+
+    printf(", %s", f_console_symbol_long_disable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_long_no_color);
+    printf("  Do not output in color");
+
+    printf("\n  %s", f_console_symbol_short_enable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_short_version);
+
+    printf(", %s", f_console_symbol_long_enable);
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, f_console_standard_long_version);
+    printf("   Print only the version number");
+
+    printf("\n\n");
+    fl_print_color(f_standard_output, data.context.important, data.context.reset, " Available Commands: ");
+
+    printf("\n  ");
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, firewall_command_start);
+    printf("    Turn on the firewall");
+
+    printf("\n  ");
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, firewall_command_stop);
+    printf("     Turn off the firewall");
+
+    printf("\n  ");
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, firewall_command_restart);
+    printf("  Turn off and then turn on the firewall");
+
+    printf("\n  ");
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, firewall_command_lock);
+    printf("     Prevent all communication");
+
+    printf("\n  ");
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, firewall_command_show);
+    printf("     Show active firewall settings");
+
+    printf("\n\n");
+    fl_print_color(f_standard_output, data.context.important, data.context.reset, " Usage: ");
+
+    printf("\n  ");
+    fl_print_color(f_standard_output, data.context.standout, data.context.reset, firewall_name);
+
+    printf("  ");
+    fl_print_color(f_standard_output, data.context.notable, data.context.reset, "[");
+
+    printf(" options ");
+    fl_print_color(f_standard_output, data.context.notable, data.context.reset, "]");
+
+    printf("  ");
+    fl_print_color(f_standard_output, data.context.notable, data.context.reset, "[");
+
+    printf(" command ");
+    fl_print_color(f_standard_output, data.context.notable, data.context.reset, "]");
+
+    printf("\n\n");
+
+    return f_none;
+  }
+#endif // _di_firewall_print_help_
+
+#ifndef _di_firewall_main_
+  f_return_status firewall_perform_commands(const f_fss_objects objects, const f_fss_contents contents, const f_bool is_global, const f_string_length this_device, const f_dynamic_string buffer, const firewall_data data) __attribute__((visibility("internal")));
+
+  f_return_status firewall_main(const f_s_int argc, const f_string argv[], firewall_data *data){
+    f_status status            = f_status_initialize;
+    f_status allocation_status = f_status_initialize;
+
+    status = fl_process_parameters(argc, argv, data->parameters, firewall_total_parameters, &data->remaining);
+
+    // load colors when not told to show no colors
+    if (data->parameters[firewall_parameter_no_color].result == f_console_result_none){
+      fll_new_color_context(allocation_status, data->context);
+
+      if (allocation_status == f_none){
+        fll_colors_load_context(&data->context, data->parameters[firewall_parameter_light].result == f_console_result_found);
+      } else {
+        fprintf(f_standard_error, "Critical Error: unable to allocate memory\n");
+        firewall_delete_data(data);
+        return allocation_status;
+      }
+    }
+
+    if (status != f_none){
+      if (status == f_no_data){
+        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: One of the parameters you passed requires an additional parameter that you did not pass.");
+        // TODO: there is a way to identify which parameter is incorrect
+        //       to do this, one must look for any "has_additional" and then see if the "additiona" location is set to 0
+        //       nothing can be 0 as that represents the program name, unless argv[] is improperly created
+      } else if (f_macro_test_for_allocation_errors(status)){
+        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory");
+      } else if (status == f_invalid_parameter){
+        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_process_parameters()");
+      } else {
+        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_process_parameters()", status);
+      }
+
+      firewall_delete_data(data);
+      return status;
+    }
+
+    // execute parameter results
+    if (data->parameters[firewall_parameter_help].result == f_console_result_found){
+      firewall_print_help(*data);
+    } else if (data->parameters[firewall_parameter_version].result == f_console_result_found){
+      firewall_print_version(*data);
+    } else {
+      // now determine which command was placed first
+      f_bool  found_command = f_false;
+      f_u_int command       = 0;
+
+      if (data->parameters[firewall_parameter_command_start].result == f_console_result_found){
+        command       = firewall_parameter_command_start;
+        found_command = f_true;
+      }
+
+      if (data->parameters[firewall_parameter_command_stop].result == f_console_result_found){
+        if (found_command){
+          if (data->parameters[command].additional > data->parameters[firewall_parameter_command_stop].additional){
+            command = firewall_parameter_command_stop;
+          }
+        } else {
+          command       = firewall_parameter_command_stop;
+          found_command = f_true;
+        }
+      }
+
+      if (data->parameters[firewall_parameter_command_restart].result == f_console_result_found){
+        if (found_command){
+          if (data->parameters[command].additional > data->parameters[firewall_parameter_command_restart].additional){
+            command = firewall_parameter_command_restart;
+          }
+        } else {
+          command       = firewall_parameter_command_restart;
+          found_command = f_true;
+        }
+      }
+
+      if (data->parameters[firewall_parameter_command_lock].result == f_console_result_found){
+        if (found_command){
+          if (data->parameters[command].additional > data->parameters[firewall_parameter_command_lock].additional){
+            command = firewall_parameter_command_lock;
+          }
+        } else {
+          command       = firewall_parameter_command_lock;
+          found_command = f_true;
+        }
+      }
+
+      if (data->parameters[firewall_parameter_command_show].result == f_console_result_found){
+        if (found_command){
+          if (data->parameters[command].additional > data->parameters[firewall_parameter_command_show].additional){
+            command = firewall_parameter_command_show;
+          }
+        } else {
+          command       = firewall_parameter_command_show;
+          found_command = f_true;
+        }
+      }
+
+      if (found_command){
+        // load the global file
+        {
+          f_file file = f_file_initialize;
+
+          status = f_file_open(&file, (f_string) network_path firewall_file_default);
+
+          if (status != f_none){
+            if (status == f_invalid_parameter){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()");
+            } else if (status == f_file_not_found){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", network_path firewall_file_default);
+            } else if (status == f_file_open_error){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", network_path firewall_file_default);
+            } else if (status == f_file_descriptor_error){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", network_path firewall_file_default);
+            } else {
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", status);
+            }
+
+            firewall_delete_data(data);
+            return status;
+          }
+
+          // TODO: this file size set functionality might be turned into an fl_file (or f_file) function
+          if (data->file_position.total_elements == 0){
+            fseek(file.file, 0, SEEK_END);
+            data->file_position.total_elements = ftell(file.file);
+            fseek(file.file, 0, SEEK_SET);
+          }
+
+          status = fl_file_read(file, data->file_position, &data->buffer);
+
+          f_file_close(&file);
+
+          if (status != f_none && status != f_none_on_eof){
+            if (status == f_invalid_parameter){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()");
+            } else if (status == f_overflow){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", network_path firewall_file_default);
+            } else if (status == f_file_not_open){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", network_path firewall_file_default);
+            } else if (status == f_file_seek_error){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", network_path firewall_file_default);
+            } else if (status == f_file_read_error){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", network_path firewall_file_default);
+            } else if (f_macro_test_for_allocation_errors(status)){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory");
+            } else {
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", status);
+            }
+
+            firewall_delete_data(data);
+            return status;
+          } else {
+            f_string_location input = f_string_location_initialize;
+
+            input.stop = data->buffer.used - 1;
+
+            status = fll_fss_basic_list_read(&data->buffer, &input, &data->objects, &data->contents);
+          }
+
+          if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content){
+            if (status == f_invalid_parameter){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_basic_list_read() for the file '%s'", network_path firewall_file_default);
+            } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: No relevant data was found within the file '%s'", network_path firewall_file_default);
+            } else if (f_macro_test_for_allocation_errors(status)){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory");
+            } else {
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_basic_list_read() for the file '%s'", status, network_path firewall_file_default);
+            }
+
+            firewall_delete_data(data);
+            return status;
+          }
+        }
+
+        if (command == firewall_parameter_command_show){
+          // Warning: these are hardcoded print commands (I am not certain how I am going to implement external 'show' rules as the default-firewall setting file is the wrong place to put this)
+          f_bool show_nat    = f_true;
+          f_bool show_mangle = f_true;
+          f_bool show_ports  = f_true;
+
+          f_dynamic_strings arguments = f_dynamic_strings_initialize;
+          f_s_int           results   = 0;
+
+          if (data->remaining.used > 0){
+            show_nat    = f_false;
+            show_mangle = f_false;
+            show_ports  = f_false;
+
+            f_string_length counter = f_string_length_initialize;
+
+            for (; counter < data->remaining.used; counter++){
+              if (strncmp("nat", argv[data->remaining.array[counter]], 4) != 0){
+                if (strncmp("mangle",  argv[data->remaining.array[counter]], 7) != 0){
+                  if (strncmp("ports",  argv[data->remaining.array[counter]], 6) != 0){
+                    fl_print_color_line(f_standard_warning, data->context.warning, data->context.reset, "WARNING: '%s' is not a valid show option", argv[data->remaining.array[counter]]);
+                  } else {
+                    show_ports = f_true;
+                  }
+                } else {
+                  show_mangle = f_true;
+                }
+              } else {
+                show_nat = f_true;
+              }
+            } // for
+          }
+
+          f_resize_dynamic_strings(status, arguments, 7);
+
+          if (f_macro_test_for_allocation_errors(status)){
+            fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory");
+            firewall_delete_data(data);
+            return status;
+          }
+
+          if (show_nat){
+            fl_print_color(f_standard_output, data->context.standout, data->context.reset, "=========================== ");
+            fl_print_color(f_standard_output, data->context.title, data->context.reset, "NAT");
+            fl_print_color_line(f_standard_output, data->context.standout, data->context.reset, " ============================");
+            fflush(f_standard_output);
+
+            arguments.used = 7;
+
+            arguments.array[0].string = (f_string) firewall_program_name;
+            arguments.array[1].string = (f_string) "-x";
+            arguments.array[2].string = (f_string) "-v";
+            arguments.array[3].string = (f_string) "-t";
+            arguments.array[4].string = (f_string) "nat";
+            arguments.array[5].string = (f_string) "--numeric";
+            arguments.array[6].string = (f_string) "--list";
+
+            arguments.array[0].used = firewall_program_name_length;
+            arguments.array[1].used = 2;
+            arguments.array[2].used = 2;
+            arguments.array[3].used = 2;
+            arguments.array[4].used = 3;
+            arguments.array[5].used = 9;
+            arguments.array[6].used = 6;
+
+            status = fll_execute_program((f_string) firewall_program_name, arguments, &results);
+
+            fprintf(f_standard_output, "\n");
+            fflush(f_standard_output);
+          }
+
+          if (status != f_failure && show_mangle){
+            fl_print_color(f_standard_output, data->context.standout, data->context.reset, "========================== ");
+            fl_print_color(f_standard_output, data->context.title, data->context.reset, "MANGLE");
+            fl_print_color_line(f_standard_output, data->context.standout, data->context.reset, " ==========================");
+            fflush(f_standard_output);
+
+            arguments.used = 7;
+
+            arguments.array[0].string = (f_string) firewall_program_name;
+            arguments.array[1].string = (f_string) "-x";
+            arguments.array[2].string = (f_string) "-v";
+            arguments.array[3].string = (f_string) "-t";
+            arguments.array[4].string = (f_string) "mangle";
+            arguments.array[5].string = (f_string) "--numeric";
+            arguments.array[6].string = (f_string) "--list";
+
+            arguments.array[0].used = firewall_program_name_length;
+            arguments.array[1].used = 2;
+            arguments.array[2].used = 2;
+            arguments.array[3].used = 2;
+            arguments.array[4].used = 3;
+            arguments.array[5].used = 9;
+            arguments.array[6].used = 6;
+
+            status = fll_execute_program((f_string) firewall_program_name, arguments, &results);
+
+            fprintf(f_standard_output, "\n");
+            fflush(f_standard_output);
+          }
+
+          if (status != f_failure && show_ports){
+            fl_print_color(f_standard_output, data->context.standout, data->context.reset, "========================== ");
+            fl_print_color(f_standard_output, data->context.title, data->context.reset, "PORTS");
+            fl_print_color_line(f_standard_output, data->context.standout, data->context.reset, " ===========================");
+            fflush(f_standard_output);
+
+            arguments.used = 5;
+
+            arguments.array[0].string = (f_string) firewall_program_name;
+            arguments.array[1].string = (f_string) "-x";
+            arguments.array[2].string = (f_string) "-v";
+            arguments.array[3].string = (f_string) "--numeric";
+            arguments.array[4].string = (f_string) "--list";
+
+            arguments.array[0].used = firewall_program_name_length;
+            arguments.array[1].used = 2;
+            arguments.array[2].used = 2;
+            arguments.array[3].used = 9;
+            arguments.array[4].used = 6;
+
+            status = fll_execute_program((f_string) firewall_program_name, arguments, &results);
+
+            fprintf(f_standard_output, "\n");
+            fflush(f_standard_output);
+          }
+
+          if (status == f_failure){
+            fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Failed to perform requested %s operation:", firewall_program_name);
+            fprintf(f_standard_error, "  ");
+
+            f_string_length i = f_string_length_initialize;
+
+            fl_print_color_code(f_standard_error, data->context.error);
+
+            for (; i < arguments.used; i++){
+              fprintf(f_standard_error, "%s ", arguments.array[i].string);
+            }
+
+            fl_print_color_code(f_standard_error, data->context.reset);
+            fprintf(f_standard_error, "\n");
+          } else if (f_macro_test_for_allocation_errors(status)){
+            fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory");
+          }
+
+          arguments.array[0].string = 0;
+          arguments.array[1].string = 0;
+          arguments.array[2].string = 0;
+          arguments.array[3].string = 0;
+          arguments.array[4].string = 0;
+          arguments.array[5].string = 0;
+          arguments.array[6].string = 0;
+          arguments.array[0].used = 0;
+          arguments.array[1].used = 0;
+          arguments.array[2].used = 0;
+          arguments.array[3].used = 0;
+          arguments.array[4].used = 0;
+          arguments.array[5].used = 0;
+          arguments.array[6].used = 0;
+          f_delete_dynamic_strings(status, arguments);
+
+          firewall_delete_data(data);
+          return f_none;
+        }
+
+        // load all network devices
+        status = fl_directory_list((f_string) network_devices, &data->devices);
+
+        if (f_macro_test_for_allocation_errors(status)){
+          fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory");
+          firewall_delete_data(data);
+          return status;
+        } else if (status == f_no_data){
+          fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: could not find any network devices");
+          firewall_delete_data(data);
+          return status;
+        } else if (status == f_failure){
+          fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: failed to read the device directory '%s'", network_devices);
+          firewall_delete_data(data);
+          return status;
+        }
+
+        // remove "lo" (loopback) from the device listing
+        {
+          f_string_length counter = f_string_length_initialize;
+
+          for (; counter < data->devices.used; counter++){
+            if (fl_compare_strings((f_string) "lo", data->devices.array[counter].string, 3, data->devices.array[counter].used) == f_equal_to){
+              f_dynamic_string swap_string = data->devices.array[counter];
+
+              data->devices.used--;
+
+              for (; counter < data->devices.used; counter++){
+                data->devices.array[counter] = data->devices.array[counter+1];
+              }
+
+              data->devices.array[data->devices.used] = swap_string;
+            }
+          }
+        }
+
+        // if at least one specific device was specified, then only use the specified devices, otherwise use all
+        if (data->remaining.used > 0){
+          f_string_length device  = f_string_length_initialize;
+          f_string_length counter = f_string_length_initialize;
+          f_string_length total   = f_string_length_initialize;
+          f_string_length i       = f_string_length_initialize;
+          f_bool          matched = f_false;
+
+          for (total = data->devices.used; device < total; device++){
+            matched = f_false;
+
+            for (counter = 0; counter < data->remaining.used; counter++){
+              if (strncmp(data->devices.array[device].string, argv[data->remaining.array[counter]], strlen(argv[data->remaining.array[counter]])) == 0){
+                matched = f_true;
+              }
+            }
+
+            if (!matched){
+              f_dynamic_string swap_string = data->devices.array[device];
+
+              data->devices.used--;
+
+              for (i = device; i < data->devices.used; i++){
+                data->devices.array[i] = data->devices.array[i+1];
+              }
+
+              data->devices.array[data->devices.used] = swap_string;
+
+              total--;
+              device--;
+            }
+          }
+        }
+
+        // report and remove all "invalid" devices that are specified in the "remaining" variable
+        {
+          f_string_length device  = f_string_length_initialize;
+          f_string_length counter = f_string_length_initialize;
+          f_bool          matched = f_false;
+
+          for (; counter < data->remaining.used; counter++){
+            matched = f_false;
+
+            for (device = 0; device < data->devices.used; device++){
+              if (strncmp(data->devices.array[device].string, argv[data->remaining.array[counter]], strlen(argv[data->remaining.array[counter]])) == 0){
+                matched = f_true;
+              }
+            }
+
+            if (!matched){
+              fl_print_color_line(f_standard_warning, data->context.warning, data->context.reset, "WARNING: There is no device by the name of '%s'", argv[data->remaining.array[counter]]);
+            }
+          }
+
+          // cleanup, the 'remaining' parameters are no longer needed
+          f_delete_string_locations(status, data->remaining);
+        }
+
+        // identify global firewall settings
+        f_string_length first = f_string_length_initialize;
+        f_string_length last  = f_string_length_initialize;
+        f_string_length stop  = f_string_length_initialize;
+        f_string_length lock  = f_string_length_initialize;
+
+        f_bool found_first = f_false;
+        f_bool found_last  = f_false;
+        f_bool found_stop  = f_false;
+        f_bool found_lock  = f_false;
+
+        f_string_length length  = f_string_length_initialize;
+        f_string_length counter = f_string_length_initialize;
+
+        // identify which position is which
+        for (; counter < data->objects.used; counter++){
+          length = data->objects.array[counter].stop - data->objects.array[counter].start + 1;
+
+          if (!found_first && length >= firewall_group_first_length){
+            if (fl_compare_strings((f_string) firewall_group_first, data->buffer.string + data->objects.array[counter].start, firewall_group_first_length, length) == f_equal_to){
+              first       = counter;
+              found_first = f_true;
+            }
+          }
+
+          if (!found_last && length >= firewall_group_last_length){
+            if (fl_compare_strings((f_string) firewall_group_last, data->buffer.string + data->objects.array[counter].start, firewall_group_last_length, length) == f_equal_to){
+              last       = counter;
+              found_last = f_true;
+            }
+          }
+
+          if (!found_stop && length >= firewall_group_stop_length){
+            if (fl_compare_strings((f_string) firewall_group_stop, data->buffer.string + data->objects.array[counter].start, firewall_group_stop_length, length) == f_equal_to){
+              stop       = counter;
+              found_stop = f_true;
+            }
+          }
+
+          if (!found_lock && length >= firewall_group_lock_length){
+            if (fl_compare_strings((f_string) firewall_group_lock, data->buffer.string + data->objects.array[counter].start, firewall_group_lock_length, length) == f_equal_to){
+              lock       = counter;
+              found_lock = f_true;
+            }
+          }
+        }
+
+        if (found_first && found_last && found_stop && found_lock){
+          f_string_length error_file = f_string_length_initialize;
+          status = f_none;
+
+          f_fss_objects  extended_objects  = f_fss_objects_initialize;
+          f_fss_contents extended_contents = f_fss_contents_initialize;
+
+          if (command == firewall_parameter_command_lock){
+            f_string_location input = f_string_location_initialize;
+
+            input.start = data->contents.array[lock].array[0].start;
+            input.stop  = data->contents.array[lock].array[0].stop;
+            error_file  = lock;
+
+            status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents);
+
+            if (status == f_none || status == f_none_on_stop || status == f_none_on_eos){
+              status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data);
+
+              if (status != f_none){
+                if (f_macro_test_for_allocation_errors(status)){
+                  fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                } else if (status == f_failure){
+                  // the error message has already been displayed
+                } else {
+                  fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status);
+                }
+
+                f_delete_fss_objects(allocation_status, extended_objects);
+                f_delete_fss_contents(allocation_status, extended_contents);
+
+                firewall_delete_data(data);
+                return status;
+              }
+            }
+          } else {
+            if (command == firewall_parameter_command_stop || command == firewall_parameter_command_restart){
+              f_string_location input = f_string_location_initialize;
+
+              input.start = data->contents.array[stop].array[0].start;
+              input.stop  = data->contents.array[stop].array[0].stop;
+              error_file  = stop;
+
+              status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents);
+
+              if (status == f_none || status == f_none_on_stop || status == f_none_on_eos){
+                status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data);
+              }
+            }
+
+            if ((status == f_none || status == f_none_on_stop || status == f_none_on_eos) && (command == firewall_parameter_command_start || command == firewall_parameter_command_restart)){
+              f_delete_fss_objects(status, extended_objects);
+              f_delete_fss_contents(status, extended_contents);
+
+              f_string_location input = f_string_location_initialize;
+
+              input.start = data->contents.array[first].array[0].start;
+              input.stop  = data->contents.array[first].array[0].stop;
+              error_file  = first;
+
+              status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents);
+
+              if (status == f_none || status == f_none_on_stop || status == f_none_on_eos){
+                status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data);
+
+                if (status != f_none){
+                  if (f_macro_test_for_allocation_errors(status)){
+                    fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                  } else if (status == f_failure){
+                    // the error message has already been displayed
+                  } else {
+                    fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status);
+                  }
+
+                  f_delete_fss_objects(allocation_status, extended_objects);
+                  f_delete_fss_contents(allocation_status, extended_contents);
+
+                  firewall_delete_data(data);
+                  return status;
+                } else {
+                  f_delete_fss_objects(status, extended_objects);
+                  f_delete_fss_contents(status, extended_contents);
+
+                  f_string_length counter = f_string_length_initialize;
+
+                  for (; counter < data->devices.used; counter++){
+                    f_file           file          = f_file_initialize;
+                    f_dynamic_string file_path     = f_dynamic_string_initialize;
+                    f_dynamic_string buffer        = f_dynamic_string_initialize;
+                    f_file_position  file_position = f_file_position_initialize;
+
+                    f_fss_objects  list_objects  = f_fss_objects_initialize;
+                    f_fss_contents list_contents = f_fss_objects_initialize;
+
+                    f_resize_dynamic_string(status, file_path, network_path_length + data->devices.array[counter].used + firewall_file_suffix_length + 1);
+
+                    if (status == f_none){
+                      strncat(file_path.string, network_path, network_path_length);
+                      strncat(file_path.string + network_path_length, data->devices.array[counter].string, data->devices.array[counter].used);
+                      strncat(file_path.string, firewall_file_suffix, firewall_file_suffix_length);
+                      file_path.used = file_path.size;
+                      file_path.string[file_path.used] = 0;
+
+                      status = f_file_open(&file, file_path.string);
+                    }
+
+                    if (status != f_none){
+                      if (status == f_invalid_parameter){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()");
+                      } else if (status == f_file_not_found){
+                        // If these files do not exist, it is not a problem (they are not required)
+                      } else if (status == f_file_open_error){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", file_path.string);
+                      } else if (status == f_file_descriptor_error){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", file_path.string);
+                      } else if (f_macro_test_for_allocation_errors(status)){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+
+                        f_file_close(&file);
+                        f_delete_dynamic_string(allocation_status, file_path);
+                        firewall_delete_data(data);
+                        return status;
+                      } else {
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", status);
+                      }
+
+                      f_file_close(&file);
+                      f_delete_dynamic_string(allocation_status, file_path);
+                      continue;
+                    }
+
+
+                    if (data->file_position.total_elements == 0){
+                      fseek(file.file, 0, SEEK_END);
+                      data->file_position.total_elements = ftell(file.file);
+                      fseek(file.file, 0, SEEK_SET);
+                    }
+
+                    status = fl_file_read(file, file_position, &buffer);
+
+                    f_file_close(&file);
+
+                    if (status != f_none && status != f_none_on_eof){
+                      if (status == f_invalid_parameter){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()");
+                      } else if (status == f_overflow){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", file_path.string);
+                      } else if (status == f_file_not_open){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", file_path.string);
+                      } else if (status == f_file_seek_error){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", file_path.string);
+                      } else if (status == f_file_read_error){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", file_path.string);
+                      } else if (f_macro_test_for_allocation_errors(status)){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+
+                        f_delete_dynamic_string(allocation_status, buffer);
+                        f_delete_dynamic_string(allocation_status, file_path);
+                        firewall_delete_data(data);
+                        return status;
+                      } else {
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", status);
+                      }
+
+                      f_delete_dynamic_string(allocation_status, buffer);
+                      f_delete_dynamic_string(allocation_status, file_path);
+                      continue;
+                    }
+
+                    {
+                      f_string_location input = f_string_location_initialize;
+
+                      input.stop = buffer.used - 1;
+
+                      status = fll_fss_basic_list_read(&buffer, &input, &list_objects, &list_contents);
+                    }
+
+                    if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content){
+                      if (status == f_invalid_parameter){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_basic_list_read() for the file '%s'", file_path.string);
+                      } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: No relevant data was found within the file '%s'", file_path.string);
+                      } else if (f_macro_test_for_allocation_errors(status)){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                      } else {
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_basic_list_read() for the file '%s'", status, file_path.string);
+                      }
+
+                      f_delete_dynamic_string(allocation_status, buffer);
+                      f_delete_dynamic_string(allocation_status, file_path);
+                      f_delete_fss_objects(allocation_status, list_objects);
+                      f_delete_fss_contents(allocation_status, list_contents);
+                      firewall_delete_data(data);
+                      return status;
+                    }
+
+                    {
+                      f_string_length buffer_counter = f_string_length_initialize;
+                      f_string_length name_length    = f_string_length_initialize;
+
+                      for (; buffer_counter < list_objects.used; buffer_counter++){
+                        name_length = list_objects.array[buffer_counter].stop - list_objects.array[buffer_counter].start + 1;
+
+                        if (name_length >= firewall_group_main_length){
+                          if (fl_compare_strings((f_string) firewall_group_main, buffer.string + list_objects.array[buffer_counter].start, firewall_group_main_length, length) == f_equal_to){
+                            f_string_location input = f_string_location_initialize;
+
+                            input.start = list_contents.array[buffer_counter].array[0].start;
+                            input.stop  = list_contents.array[buffer_counter].array[0].stop;
+
+                            status = fll_fss_extended_read(&buffer, &input, &extended_objects, &extended_contents);
+
+                            if (status == f_none || status == f_none_on_stop || status == f_none_on_eos){
+                              status = firewall_perform_commands(extended_objects, extended_contents, f_false, counter, buffer, *data);
+
+                              if (status != f_none){
+                                if (f_macro_test_for_allocation_errors(status)){
+                                  fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                                } else if (status == f_failure){
+                                  // the error message has already been displayed
+                                } else {
+                                  fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status);
+                                }
+                              }
+                            } else {
+                              if (status == f_invalid_parameter){
+                                fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_extended_read() for the file '%s'", file_path.string);
+                              } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop){
+                                fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: No relevant data was found within the file '%s'", file_path.string);
+                              } else if (f_macro_test_for_allocation_errors(status)){
+                                fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                              } else {
+                                fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_extended_read() for the file '%s'", status, file_path.string);
+                              }
+                            }
+
+                            break;
+                          }
+
+                          // TODO: consider supporting "lock" and "stop" rules for individual devices
+                        }
+                      }
+                    }
+
+                    f_delete_dynamic_string(allocation_status, buffer);
+                    f_delete_dynamic_string(allocation_status, file_path);
+                    f_delete_fss_objects(allocation_status, list_objects);
+                    f_delete_fss_contents(allocation_status, list_contents);
+                    f_delete_fss_objects(allocation_status, extended_objects);
+                    f_delete_fss_contents(allocation_status, extended_contents);
+                  }
+
+                  input.start = data->contents.array[last].array[0].start;
+                  input.stop  = data->contents.array[last].array[0].stop;
+                  error_file  = last;
+
+                  status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents);
+
+                  if (status == f_none || status == f_none_on_stop || status == f_none_on_eos){
+                    status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data);
+
+                    if (status != f_none){
+                      if (f_macro_test_for_allocation_errors(status)){
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                      } else if (status == f_failure){
+                        // the error message has already been displayed
+                      } else {
+                        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status);
+                      }
+
+                      f_delete_fss_objects(allocation_status, extended_objects);
+                      f_delete_fss_contents(allocation_status, extended_contents);
+
+                      firewall_delete_data(data);
+                      return status;
+                    }
+                  }
+                }
+              }
+            }
+          }
+
+          if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content){
+            if (status == f_invalid_parameter){
+              fl_print_color_code(f_standard_error, data->context.error);
+              fprintf(f_standard_error, "INTERNAL ERROR: Invalid parameter when calling fll_fss_extended_read() for the file '");
+              f_print_partial_dynamic_string(f_standard_error, data->buffer, data->contents.array[error_file].array[0]);
+              fprintf(f_standard_error, "'");
+              fl_print_color_code(f_standard_error, data->context.reset);
+              fprintf(f_standard_error, "\n");
+            } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop){
+              if (error_file == first || error_file == last || error_file == stop || error_file == lock){
+                fl_print_color_code(f_standard_error, data->context.error);
+                fprintf(f_standard_error, "ERROR: No relevant data was found within the file '");
+                f_print_partial_dynamic_string(f_standard_error, data->buffer, data->contents.array[error_file].array[0]);
+                fprintf(f_standard_error, "'");
+                fl_print_color_code(f_standard_error, data->context.reset);
+                fprintf(f_standard_error, "\n");
+              }
+            } else if (f_macro_test_for_allocation_errors(status)){
+              fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+            } else if (status == f_failure){
+              // the error message has already been displayed
+            } else {
+              fl_print_color_code(f_standard_error, data->context.error);
+              fprintf(f_standard_error, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_extended_read() for the file '", status);
+              f_print_partial_dynamic_string(f_standard_error, data->buffer, data->contents.array[error_file].array[0]);
+              fprintf(f_standard_error, "'");
+              fl_print_color_code(f_standard_error, data->context.reset);
+              fprintf(f_standard_error, "\n");
+            }
+          }
+
+          f_delete_fss_objects(allocation_status, extended_objects);
+          f_delete_fss_contents(allocation_status, extended_contents);
+        } else {
+          const f_autochar *string = f_null;
+
+          if (!found_first){
+            string = firewall_group_first;
+          } else if (!found_last){
+            string = firewall_group_last;
+          } else if (!found_stop){
+            string = firewall_group_stop;
+          } else if (!found_lock){
+            string = firewall_group_lock;
+          }
+
+          fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: The required basic list '%s' was not found inside of the file '%s'", string, network_path firewall_file_default);
+        }
+
+        // cleanup
+        f_delete_fss_contents(allocation_status, data->contents);
+        f_delete_fss_objects(allocation_status, data->objects);
+        f_delete_dynamic_string(allocation_status, data->buffer);
+      } else {
+        fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: You did not pass a command");
+        status = f_invalid_parameter;
+      }
+    }
+
+    firewall_delete_data(data);
+    return status;
+  }
+
+    f_return_status firewall_perform_commands(const f_fss_objects objects, const f_fss_contents contents, const f_bool is_global, const f_string_length this_device, const f_dynamic_string buffer, const firewall_data data){
+    f_status status            = f_status_initialize;
+    f_status allocation_status = f_status_initialize;
+
+    f_string_length   counter   = f_string_length_initialize;
+    f_dynamic_string  argument  = f_dynamic_string_initialize;
+    f_dynamic_strings arguments = f_dynamic_strings_initialize;
+
+    f_s_int          results    = 0;
+    f_string_length  length     = f_string_length_initialize;
+    f_bool           invalid    = f_false;
+    f_bool           is_ip_list = f_false;
+    f_dynamic_string ip_list    = f_dynamic_string_initialize;
+
+    // iptables command arguments
+    f_bool direction_input   = f_true;
+    f_bool direction_output  = f_false;
+    f_bool device_all        = f_false;
+    f_bool ip_list_direction = f_false; // false = source, true = destination
+
+    f_string_length  direction = firewall_direction_none_id;
+    f_dynamic_string device    = f_dynamic_string_initialize;
+    f_string_length  action    = firewall_action_append_id;
+
+    if (is_global){
+      device_all = f_true;
+    } else {
+      f_resize_dynamic_string(status, device, data.devices.array[this_device].used);
+
+      if (f_macro_test_for_allocation_errors(status)){
+        f_delete_dynamic_string(allocation_status, device);
+
+        return status;
+      }
+
+      strncat(device.string, data.devices.array[this_device].string, data.devices.array[this_device].used);
+      device.used = data.devices.array[this_device].used;
+    }
+
+    for (; counter < objects.used; counter++){
+      length  = (objects.array[counter].stop - objects.array[counter].start) + 1;
+      invalid = f_false;
+
+      is_ip_list        = f_false;
+      ip_list_direction = f_false;
+
+      f_delete_dynamic_string(allocation_status, ip_list);
+
+      if (length >= firewall_direction_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_direction, length, firewall_direction_length) == f_equal_to){
+        length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1;
+
+        if (contents.array[counter].used <= 0 || contents.array[counter].used > 1){
+          invalid = f_true;
+        } else {
+          if (length < firewall_direction_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_input, length, firewall_direction_input_length) == f_not_equal_to){
+            if (length < firewall_direction_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_output, length, firewall_direction_output_length) == f_not_equal_to){
+              if (length < firewall_direction_forward_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_forward, length, firewall_direction_forward_length) == f_not_equal_to){
+                if (length < firewall_direction_postrouting_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_postrouting, length, firewall_direction_postrouting_length) == f_not_equal_to){
+                  if (length < firewall_direction_prerouting_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_prerouting, length, firewall_direction_prerouting_length) == f_not_equal_to){
+                    if (length < firewall_direction_none_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_none, length, firewall_direction_none_length) == f_not_equal_to){
+                      if (length < firewall_direction_forward_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_forward_input, length, firewall_direction_forward_input_length) == f_not_equal_to){
+                        if (length < firewall_direction_forward_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_forward_output, length, firewall_direction_forward_output_length) == f_not_equal_to){
+                          if (length < firewall_direction_postrouting_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_postrouting_input, length, firewall_direction_postrouting_input_length) == f_not_equal_to){
+                            if (length < firewall_direction_postrouting_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_postrouting_output, length, firewall_direction_postrouting_output_length) == f_not_equal_to){
+                              if (length < firewall_direction_prerouting_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_prerouting_input, length, firewall_direction_prerouting_input_length) == f_not_equal_to){
+                                if (length < firewall_direction_prerouting_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_prerouting_output, length, firewall_direction_prerouting_output_length) == f_not_equal_to){
+                                  invalid = f_true;
+                                } else {
+                                  direction_input  = f_false;
+                                  direction_output = f_true;
+                                  direction        = firewall_direction_prerouting_id;
+                                }
+                              } else {
+                                direction_input  = f_true;
+                                direction_output = f_false;
+                                direction        = firewall_direction_prerouting_id;
+                              }
+                            } else {
+                              direction_input  = f_false;
+                              direction_output = f_true;
+                              direction        = firewall_direction_postrouting_id;
+                            }
+                          } else {
+                            direction_input  = f_true;
+                            direction_output = f_false;
+                            direction        = firewall_direction_postrouting_id;
+                          }
+                        } else {
+                          direction_input  = f_false;
+                          direction_output = f_true;
+                          direction        = firewall_direction_forward_id;
+                        }
+                      } else {
+                        direction_input  = f_true;
+                        direction_output = f_false;
+                        direction        = firewall_direction_forward_id;
+                      }
+                    } else {
+                      direction_input  = f_false;
+                      direction_output = f_false;
+                      direction        = firewall_direction_none_id;
+                    }
+                  } else {
+                    direction_input  = f_false;
+                    direction_output = f_false;
+                    direction        = firewall_direction_postrouting_id;
+                  }
+                } else {
+                  direction_input  = f_false;
+                  direction_output = f_false;
+                  direction        = firewall_direction_prerouting_id;
+                }
+              } else {
+                direction_input  = f_false;
+                direction_output = f_false;
+                direction        = firewall_direction_forward_id;
+              }
+            } else {
+              direction_input  = f_false;
+              direction_output = f_true;
+              direction        = firewall_direction_none_id;
+            }
+          } else {
+            direction_input  = f_true;
+            direction_output = f_false;
+            direction        = firewall_direction_none_id;
+          }
+        }
+
+        if (!invalid) continue;
+      } else if (length >= firewall_device_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_device, length, firewall_device_length) == f_equal_to){
+        length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1;
+
+        if (contents.array[counter].used <= 0 || contents.array[counter].used > 1){
+          invalid = f_true;
+        } else if (length >= firewall_device_all_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_device_all, length, firewall_device_all_length) == f_equal_to){
+          f_delete_dynamic_string(status, device);
+          device_all = f_true;
+          continue;
+        } else if (length >= firewall_device_this_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_device_this, length, firewall_device_this_length) == f_equal_to){
+          f_delete_dynamic_string(status, device);
+          f_resize_dynamic_string(status, device, data.devices.array[this_device].used);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(device.string, data.devices.array[this_device].string, data.devices.array[this_device].used);
+          device.used = data.devices.array[this_device].used;
+          device_all  = f_false;
+          continue;
+        }
+
+        if (!invalid){
+          f_delete_dynamic_string(status, device);
+          f_resize_dynamic_string(status, device, length);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(device.string, buffer.string + contents.array[counter].array[0].start, length);
+          device.used  = length;
+          device_all  = f_false;
+          continue;
+        }
+      } else if (length >= firewall_action_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_action, length, firewall_action_length) == f_equal_to){
+        length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1;
+
+        if (contents.array[counter].used <= 0 || contents.array[counter].used > 1){
+          invalid = f_true;
+        } else if (length < firewall_action_append_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_append, length, firewall_action_append_length) == f_not_equal_to){
+          if (length < firewall_action_insert_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_insert, length, firewall_action_insert_length) == f_not_equal_to){
+            if (length < firewall_action_policy_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_policy, length, firewall_action_policy_length) == f_not_equal_to){
+              if (length < firewall_action_none_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_none, length, firewall_action_none_length) == f_not_equal_to){
+                invalid = f_true;
+              } else {
+                action = firewall_action_none_id;
+              }
+            } else {
+              action = firewall_action_policy_id;
+            }
+          } else {
+            action = firewall_action_insert_id;
+          }
+        } else {
+          action = firewall_action_append_id;
+        }
+
+        if (!invalid) continue;
+      } else if (length >= firewall_ip_list_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_ip_list, length, firewall_ip_list_length) == f_equal_to){
+        length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1;
+        is_ip_list = f_true;
+
+        if (length >= firewall_ip_list_source_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_ip_list_source, length, firewall_ip_list_source_length) == f_equal_to){
+          ip_list_direction = f_false;
+        } else if (length >= firewall_ip_list_destination_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_ip_list_destination, length, firewall_ip_list_destination_length) == f_equal_to){
+          ip_list_direction = f_true;
+        } else {
+          invalid = f_true;
+        }
+      } else if (length < firewall_rule_length || fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_rule, length, firewall_rule_length) == f_not_equal_to){
+        if (length > 0){
+          fl_print_color_code(f_standard_warning, data.context.warning);
+          fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) counter);
+          f_print_string(f_standard_warning, buffer.string + objects.array[counter].start, length);
+          fprintf(f_standard_warning, "' is invalid");
+          fl_print_color_code(f_standard_warning, data.context.reset);
+        } else {
+          fprintf(f_standard_warning, "WARNING: At line %u, the object is missing", (unsigned int) counter);
+        }
+
+        fprintf(f_standard_warning, "\n");
+        continue;
+      }
+
+      if (invalid){
+        length = (objects.array[counter].stop - objects.array[counter].start) + 1;
+
+        if (length > 0){
+          fl_print_color_code(f_standard_warning, data.context.warning);
+          fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) counter);
+          f_print_string(f_standard_warning, buffer.string + objects.array[counter].start, length);
+          fprintf(f_standard_warning, "' has invalid content '");
+          f_print_string(f_standard_warning, buffer.string + contents.array[counter].array[0].start, contents.array[counter].array[0].stop - contents.array[counter].array[0].start + 1);
+          fprintf(f_standard_warning, "'");
+          fl_print_color_code(f_standard_warning, data.context.reset);
+          fprintf(f_standard_warning, "\n");
+        } else {
+          fl_print_color_line(f_standard_warning, data.context.warning, data.context.reset, "WARNING: At line %u, the object has no content", (unsigned int) counter);
+        }
+
+        continue;
+      }
+
+
+      // first add the program name
+      f_delete_dynamic_strings(status, arguments);
+      f_resize_dynamic_strings(status, arguments, arguments.used + 1);
+
+      if (f_macro_test_for_allocation_errors(status)) break;
+
+      f_resize_dynamic_string(status, argument, firewall_program_name_length);
+
+      if (f_macro_test_for_allocation_errors(status)) break;
+
+      strncat(argument.string, firewall_program_name, firewall_program_name_length);
+      argument.used = firewall_program_name_length;
+
+      arguments.array[arguments.used].string = argument.string;
+      arguments.array[arguments.used].size   = argument.size;
+      arguments.array[arguments.used].used   = argument.used;
+      arguments.used++;
+      argument.string = f_null;
+      argument.size   = 0;
+      argument.used   = 0;
+
+
+      // FIXME: (this issue is probably everywhere) Implement an strncat function for dynamic strings or if I already have one implement, make sure it is used in every applicable place
+      //        (this way I can automatically handle updating the used buffer)
+      //        also look into auto-allocated space if necessary with the said function
+      if (action == firewall_action_append_id){
+        f_resize_dynamic_string(status, argument, firewall_action_append_command_length);
+
+        if (f_macro_test_for_allocation_errors(status)) break;
+
+        strncat(argument.string, firewall_action_append_command, firewall_action_append_command_length);
+        argument.used = firewall_action_append_command_length;
+      } else if (action == firewall_action_insert_id){
+        f_resize_dynamic_string(status, argument, firewall_action_insert_command_length);
+
+        if (f_macro_test_for_allocation_errors(status)) break;
+
+        strncat(argument.string, firewall_action_insert_command, firewall_action_insert_command_length);
+        argument.used = firewall_action_insert_command_length;
+      } else if (action == firewall_action_policy_id){
+        f_resize_dynamic_string(status, argument, firewall_action_policy_command_length);
+
+        if (f_macro_test_for_allocation_errors(status)) break;
+
+        strncat(argument.string, firewall_action_policy_command, firewall_action_policy_command_length);
+        argument.used = firewall_action_policy_command_length;
+      }
+
+      if (argument.used > 0){
+        f_resize_dynamic_strings(status, arguments, arguments.used + 1);
+
+        if (f_macro_test_for_allocation_errors(status)) break;
+
+        arguments.array[arguments.used].string = argument.string;
+        arguments.array[arguments.used].size   = argument.size;
+        arguments.array[arguments.used].used   = argument.used;
+        arguments.used++;
+        argument.string = f_null;
+        argument.size   = 0;
+        argument.used   = 0;
+      }
+
+      if (action != firewall_action_none_id){
+        if (direction == firewall_direction_forward_id){
+          f_resize_dynamic_string(status, argument, firewall_direction_forward_command_length);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, firewall_direction_forward_command, firewall_direction_forward_command_length);
+          argument.used = firewall_direction_forward_command_length;
+        } else if (direction == firewall_direction_postrouting_id){
+          f_resize_dynamic_string(status, argument, firewall_direction_postrouting_command_length);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, firewall_direction_postrouting_command, firewall_direction_postrouting_command_length);
+          argument.used += firewall_direction_postrouting_command_length;
+        } else if (direction == firewall_direction_prerouting_id){
+          f_resize_dynamic_string(status, argument, firewall_direction_prerouting_command_length);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, firewall_direction_prerouting_command, firewall_direction_prerouting_command_length);
+          argument.used = firewall_direction_prerouting_command_length;
+        } else if (direction_input){
+          f_resize_dynamic_string(status, argument, firewall_direction_input_command_length);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, firewall_direction_input_command, firewall_direction_input_command_length);
+          argument.used = firewall_direction_input_command_length;
+        } else if (direction_output){
+          f_resize_dynamic_string(status, argument, firewall_direction_output_command_length);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, firewall_direction_output_command, firewall_direction_output_command_length);
+          argument.used = firewall_direction_output_command_length;
+        }
+      }
+
+      if (argument.used > 0){
+        f_resize_dynamic_strings(status, arguments, arguments.used + 1);
+
+        if (f_macro_test_for_allocation_errors(status)) break;
+
+        arguments.array[arguments.used].string = argument.string;
+        arguments.array[arguments.used].size   = argument.size;
+        arguments.array[arguments.used].used   = argument.used;
+        arguments.used++;
+        argument.string = f_null;
+        argument.size   = 0;
+        argument.used   = 0;
+      }
+
+      if (device.used > 0){
+        if (length < firewall_device_all_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_device_all, length, firewall_device_all_length) == f_not_equal_to){
+          if (direction_input){
+            f_resize_dynamic_string(status, argument, firewall_device_input_command_length);
+            if (f_macro_test_for_allocation_errors(status)) break;
+
+            strncat(argument.string, firewall_device_input_command, firewall_device_input_command_length);
+            argument.used = firewall_device_input_command_length;
+          } else if (direction_output){
+            f_resize_dynamic_string(status, argument, firewall_device_output_command_length);
+            if (f_macro_test_for_allocation_errors(status)) break;
+
+            strncat(argument.string, firewall_device_output_command, firewall_device_output_command_length);
+            argument.used = firewall_device_output_command_length;
+          }
+        }
+
+        if (argument.used > 0){
+          f_resize_dynamic_strings(status, arguments, arguments.used + 1);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          arguments.array[arguments.used].string = argument.string;
+          arguments.array[arguments.used].size   = argument.size;
+          arguments.array[arguments.used].used   = argument.used;
+          arguments.used++;
+          argument.string = f_null;
+          argument.size   = 0;
+          argument.used   = 0;
+        }
+
+        if (direction_input || direction_output){
+          f_resize_dynamic_string(status, argument, device.used);
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, device.string, device.used);
+          argument.used = device.used;
+        }
+      }
+
+      if (argument.used > 0){
+        f_resize_dynamic_strings(status, arguments, arguments.used + 1);
+
+        if (f_macro_test_for_allocation_errors(status)) break;
+
+        arguments.array[arguments.used].string = argument.string;
+        arguments.array[arguments.used].size   = argument.size;
+        arguments.array[arguments.used].used   = argument.used;
+        arguments.used++;
+        argument.string = f_null;
+        argument.size   = 0;
+        argument.used   = 0;
+      }
+
+      // last up is the "rule"
+      if ((!is_ip_list && contents.array[counter].used > 0) || (is_ip_list && contents.array[counter].used > 1)){
+        f_string_length subcounter = f_string_length_initialize;
+
+        if (is_ip_list){
+          // skip past the direction
+          subcounter++;
+
+          length = (contents.array[counter].array[subcounter].stop - contents.array[counter].array[subcounter].start) + 1;
+
+          f_resize_dynamic_string(status, ip_list, length);
+
+          if (f_macro_test_for_allocation_errors(status)){
+            subcounter = contents.array[counter].used;
+          } else {
+            strncat(ip_list.string, buffer.string + contents.array[counter].array[subcounter].start, length);
+            ip_list.used = length;
+
+            subcounter++;
+          }
+        }
+
+        for (; subcounter < contents.array[counter].used; subcounter++){
+          length = (contents.array[counter].array[subcounter].stop - contents.array[counter].array[subcounter].start) + 1;
+
+          f_resize_dynamic_string(status, argument, length);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, buffer.string + contents.array[counter].array[subcounter].start, length);
+          argument.used = length;
+
+          if (length > 0){
+            f_resize_dynamic_strings(status, arguments, arguments.used + 1);
+
+            if (f_macro_test_for_allocation_errors(status)) break;
+
+            arguments.array[arguments.used].string = argument.string;
+            arguments.array[arguments.used].size   = argument.size;
+            arguments.array[arguments.used].used   = argument.used;
+            arguments.used++;
+            argument.string = f_null;
+            argument.size   = 0;
+            argument.used   = 0;
+          }
+        }
+      } else {
+        length = (objects.array[counter].stop - objects.array[counter].start) + 1;
+
+        fl_print_color_code(f_standard_warning, data.context.warning);
+        fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) counter);
+        f_print_string(f_standard_warning, buffer.string + objects.array[counter].start, objects.array[counter].stop - objects.array[counter].start + 1);
+        fprintf(f_standard_warning, "' has no content");
+        fl_print_color_code(f_standard_warning, data.context.reset);
+        fprintf(f_standard_warning, "\n");
+
+        break;
+      }
+
+      if (arguments.used > 1){
+        if (is_ip_list){
+          f_file           file          = f_file_initialize;
+          f_dynamic_string file_path     = f_dynamic_string_initialize;
+          f_dynamic_string local_buffer  = f_dynamic_string_initialize;
+          f_file_position  file_position = f_file_position_initialize;
+
+          f_fss_objects  basic_objects  = f_fss_objects_initialize;
+          f_fss_contents basic_contents = f_fss_objects_initialize;
+
+          f_resize_dynamic_string(status, file_path, network_path_length + ip_list.used + 1);
+
+          if (status == f_none){
+            strncat(file_path.string, network_path, network_path_length);
+            strncat(file_path.string + network_path_length, ip_list.string, ip_list.used);
+            file_path.used = file_path.size;
+            file_path.string[file_path.used] = 0;
+
+            status = f_file_open(&file, file_path.string);
+          }
+
+          if (status != f_none){
+            if (status == f_invalid_parameter){
+              fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()");
+            } else if (status == f_file_not_found){
+              // the file does not have to exist
+              fl_print_color_line(f_standard_warning, data.context.warning, data.context.reset, "WARNING: Cannot find the file '%s'", file_path.string);
+              status = f_none;
+            } else if (status == f_file_open_error){
+              fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "ERROR: Unable to open the file '%s'", file_path.string);
+            } else if (status == f_file_descriptor_error){
+              fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "ERROR: File descriptor error while trying to open the file '%s'", file_path.string);
+            } else if (f_macro_test_for_allocation_errors(status)){
+              fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+            } else {
+              fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", status);
+            }
+
+            f_file_close(&file);
+          } else {
+            if (file_position.total_elements == 0){
+              fseek(file.file, 0, SEEK_END);
+              file_position.total_elements = ftell(file.file);
+              fseek(file.file, 0, SEEK_SET);
+            }
+
+            status = fl_file_read(file, file_position, &local_buffer);
+
+            f_file_close(&file);
+
+            if (status != f_none && status != f_none_on_eof){
+              if (status == f_invalid_parameter){
+                fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()");
+              } else if (status == f_overflow){
+                fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", file_path.string);
+              } else if (status == f_file_not_open){
+                fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: The file '%s' is no longer open", file_path.string);
+              } else if (status == f_file_seek_error){
+                fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "ERROR: A seek error occurred while accessing the file '%s'", file_path.string);
+              } else if (status == f_file_read_error){
+                fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "ERROR: A read error occurred while accessing the file '%s'", file_path.string);
+              } else if (f_macro_test_for_allocation_errors(status)){
+                fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+              } else {
+                fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", status);
+              }
+            } else {
+              {
+                f_string_location input = f_string_location_initialize;
+
+                input.stop = local_buffer.used - 1;
+
+                status = fll_fss_basic_read(&local_buffer, &input, &basic_objects, &basic_contents);
+              }
+
+              if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content){
+                if (status == f_invalid_parameter){
+                  fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_basic_read() for the file '%s'", file_path.string);
+                } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop){
+                  // empty files are to be silently ignored
+                } else if (f_macro_test_for_allocation_errors(status)){
+                  fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                } else {
+                  fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_basic_read() for the file '%s'", status, file_path.string);
+                }
+              } else {
+                f_string_length  buffer_counter = f_string_length_initialize;
+                f_string_length  ip_length      = f_string_length_initialize;
+                f_dynamic_string ip_argument    = f_dynamic_string_initialize;
+                f_dynamic_string ip_list_action = f_dynamic_string_initialize;
+
+                if (ip_list_direction){
+                  f_resize_dynamic_string(status, ip_list_action, firewall_ip_list_destination_action_length + 1);
+                  strncat(ip_list_action.string, firewall_ip_list_destination_action, firewall_ip_list_destination_action_length);
+                } else {
+                  f_resize_dynamic_string(status, ip_list_action, firewall_ip_list_source_action_length + 1);
+                  strncat(ip_list_action.string, firewall_ip_list_source_action, firewall_ip_list_source_action_length);
+                }
+
+                ip_list_action.used = ip_list_action.size;
+                ip_list_action.string[ip_list_action.used] = 0;
+
+                if (f_macro_test_for_allocation_errors(status)){
+                  fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                } else {
+                  ip_list_action.used = ip_list_action.size;
+
+                  f_resize_dynamic_strings(status, arguments, arguments.used + 2);
+
+                  if (f_macro_test_for_allocation_errors(status)){
+                    fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                  } else {
+                    arguments.array[arguments.used].string = ip_list_action.string;
+                    arguments.array[arguments.used].size   = ip_list_action.size;
+                    arguments.array[arguments.used].used   = ip_list_action.used;
+                    arguments.used++;
+
+                    // the ip_list file contains objects and no content, all objects are what matter an nothing else
+                    for (; buffer_counter < basic_objects.used; buffer_counter++){
+                      ip_length = (basic_objects.array[buffer_counter].stop - basic_objects.array[buffer_counter].start) + 1;
+
+                      f_resize_dynamic_string(status, ip_argument, ip_length);
+
+                      if (f_macro_test_for_allocation_errors(status)){
+                        fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory", status);
+                        break;
+                      }
+
+                      strncat(ip_argument.string, local_buffer.string + basic_objects.array[buffer_counter].start, ip_length);
+                      ip_argument.used = ip_argument.size;
+                      ip_argument.string[ip_argument.used] = 0;
+
+                      arguments.array[arguments.used].string = ip_argument.string;
+                      arguments.array[arguments.used].size   = ip_argument.size;
+                      arguments.array[arguments.used].used   = ip_argument.used;
+                      arguments.used++;
+
+                      status = fll_execute_program((f_string) firewall_program_name, arguments, &results);
+
+                      if (status == f_failure){
+                        fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "ERROR: Failed to perform requested %s operation:", firewall_program_name);
+                        fprintf(f_standard_error, "  ");
+
+                        f_string_length i = f_string_length_initialize;
+
+                        fl_print_color_code(f_standard_error, data.context.error);
+
+                        for (; i < arguments.used; i++){
+                          fprintf(f_standard_error, "%s ", arguments.array[i].string);
+                        }
+
+                        fl_print_color_code(f_standard_error, data.context.reset);
+                        fprintf(f_standard_error, "\n");
+
+                        arguments.used--;
+                        arguments.array[arguments.used].string = 0;
+                        arguments.array[arguments.used].size   = 0;
+                        arguments.array[arguments.used].used   = 0;
+
+                        break;
+                      } else if (status == f_invalid_parameter){
+                        fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_execute_path()");
+
+                        arguments.used--;
+                        arguments.array[arguments.used].string = 0;
+                        arguments.array[arguments.used].size   = 0;
+                        arguments.array[arguments.used].used   = 0;
+
+                        break;
+                      }
+
+                      arguments.used--;
+                      arguments.array[arguments.used].string = 0;
+                      arguments.array[arguments.used].size   = 0;
+                      arguments.array[arguments.used].used   = 0;
+
+                      f_delete_dynamic_string(allocation_status, ip_argument);
+                    }
+                  }
+                }
+
+                f_delete_dynamic_string(allocation_status, ip_argument);
+                f_delete_dynamic_string(allocation_status, ip_list_action);
+
+                arguments.used--;
+                arguments.array[arguments.used].string = 0;
+                arguments.array[arguments.used].size   = 0;
+                arguments.array[arguments.used].used   = 0;
+              }
+            }
+          }
+
+          f_delete_dynamic_string(allocation_status, local_buffer);
+          f_delete_dynamic_string(allocation_status, file_path);
+          f_delete_fss_objects(allocation_status, basic_objects);
+          f_delete_fss_contents(allocation_status, basic_contents);
+
+          if (status == f_failure || status == f_invalid_parameter) break;
+        } else {
+          status = fll_execute_program((f_string) firewall_program_name, arguments, &results);
+
+          if (status == f_failure){
+            fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "ERROR: Failed to perform requested %s operation:", firewall_program_name);
+            fprintf(f_standard_error, "  ");
+
+            f_string_length i = f_string_length_initialize;
+
+            fl_print_color_code(f_standard_error, data.context.error);
+
+            for (; i < arguments.used; i++){
+              fprintf(f_standard_error, "%s ", arguments.array[i].string);
+            }
+
+            fl_print_color_code(f_standard_error, data.context.reset);
+            fprintf(f_standard_error, "\n");
+
+            break;
+          } else if (status == f_invalid_parameter){
+            fl_print_color_line(f_standard_error, data.context.error, data.context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_execute_path()");
+            break;
+          }
+        }
+      }
+    }
+
+    f_delete_dynamic_string(allocation_status, ip_list);
+    f_delete_dynamic_string(allocation_status, argument);
+    f_delete_dynamic_strings(allocation_status, arguments);
+    f_delete_dynamic_string(allocation_status, device);
+
+    return status;
+  }
+#endif // _di_firewall_main_
+
+#ifndef _di_firewall_delete_data_
+  f_return_status firewall_delete_data(firewall_data *data){
+    f_status status = f_status_initialize;
+
+    f_delete_fss_contents(status, data->contents);
+    f_delete_fss_objects(status, data->objects);
+    f_delete_dynamic_string(status, data->buffer);
+    f_delete_string_lengths(status, data->remaining);
+    f_delete_dynamic_strings(status, data->devices);
+
+    fll_delete_color_context(status, data->context);
+
+    return f_none;
+  }
+#endif // _di_firewall_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/firewall/c/firewall.h b/level_3/firewall/c/firewall.h
new file mode 100644 (file)
index 0000000..a06ab4a
--- /dev/null
@@ -0,0 +1,272 @@
+/* FLL - Level 3
+ * Project:       Firewall
+ * Version:       0.3.x
+ * Licenses:      lgplv2.1
+ * Programmers:   Kevin Day
+ * Documentation:
+ *
+ * This is the Kevux Operating System Firewall program.
+ * This program utilizes the Featureless Linux Library.
+ * This program processes firewall commands and passes them to iptables from netfiler.org
+ */
+#ifndef _firewall_h
+
+// libc includes
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+
+// fll-0 includes
+#include <level_0/types.h>
+#include <level_0/strings.h>
+#include <level_0/file.h>
+#include <level_0/console.h>
+#include <level_0/output.h>
+
+// fll-1 includes
+#include <level_1/colors.h>
+#include <level_1/console.h>
+#include <level_1/file.h>
+#include <level_1/strings.h>
+#include <level_1/directory.h>
+
+// fll-2 includes
+#include <level_2/execute.h>
+#include <level_2/fss_basic.h>
+#include <level_2/fss_basic_list.h>
+#include <level_2/fss_extended.h>
+#include <level_2/colors.h>
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#ifndef _di_firewall_version_
+  #define firewall_major_version "0"
+  #define firewall_minor_version "3"
+  #define firewall_micro_version "0"
+  #define firewall_version firewall_major_version "." firewall_minor_version "." firewall_micro_version
+#endif // _di_firewall_version_
+
+#ifndef _di_firewall_name_
+  #define firewall_name "firewall"
+  #define firewall_name_long "Kevux Firewall Manager"
+#endif // _di_firewall_name_
+
+#ifndef _di_firewall_paths_
+  #define network_path          "/etc/network/" // TODO: this should be moved to a network project library, possibly the Paths project in fot the network project
+  #define network_devices       "/sys/class/net/" // TODO: this should also be moved to a network project library
+  #define firewall_file_default "default-firewall"
+  #define firewall_file_suffix  "-firewall"
+  #define firewall_program_name "iptables"
+
+  #define network_path_length          13
+  #define network_devices_length       15
+  #define firewall_file_default_length 16
+  #define firewall_file_suffix_length  9
+  #define firewall_program_length      8
+  #define firewall_program_name_length 8
+#endif // _di_firewall_paths_
+
+#ifndef _di_firewall_defines_
+  #define firewall_group_first "first"
+  #define firewall_group_last "last"
+  #define firewall_group_stop "stop"
+  #define firewall_group_lock "lock"
+  #define firewall_group_main "main"
+
+  #define firewall_group_first_length 5
+  #define firewall_group_last_length  4
+  #define firewall_group_stop_length  4
+  #define firewall_group_lock_length  4
+  #define firewall_group_main_length  4
+
+  #define firewall_command_start   "start"
+  #define firewall_command_stop    "stop"
+  #define firewall_command_restart "restart"
+  #define firewall_command_lock    "lock"
+  #define firewall_command_show    "show"
+
+  #define firewall_command_start_length   5
+  #define firewall_command_stop_length    4
+  #define firewall_command_restart_length 7
+  #define firewall_command_lock_length    4
+  #define firewall_command_show_length    4
+
+  #define firewall_ip_list                    "ip_list"
+  #define firewall_ip_list_source             "source"
+  #define firewall_ip_list_source_action      "-s"
+  #define firewall_ip_list_destination        "destination"
+  #define firewall_ip_list_destination_action "-d"
+
+  #define firewall_ip_list_length                    7
+  #define firewall_ip_list_source_length             6
+  #define firewall_ip_list_source_action_length      2
+  #define firewall_ip_list_destination_length        11
+  #define firewall_ip_list_destination_action_length 2
+
+  #define firewall_rule        "rule"
+  #define firewall_rule_length 4
+
+  #define firewall_direction             "direction"
+  #define firewall_direction_input       "input"
+  #define firewall_direction_output      "output"
+  #define firewall_direction_forward     "forward"
+  #define firewall_direction_postrouting "postrouting"
+  #define firewall_direction_prerouting  "prerouting"
+  #define firewall_direction_none        "none"
+
+  #define firewall_direction_length             9
+  #define firewall_direction_input_length       5
+  #define firewall_direction_output_length      6
+  #define firewall_direction_forward_length     7
+  #define firewall_direction_postrouting_length 12
+  #define firewall_direction_prerouting_length  11
+  #define firewall_direction_none_length        4
+
+  #define firewall_direction_forward_input      "forward-input"
+  #define firewall_direction_forward_output     "forward-output"
+  #define firewall_direction_postrouting_input  "postrouting-input"
+  #define firewall_direction_postrouting_output "postrouting-output"
+  #define firewall_direction_prerouting_input   "prerouting-input"
+  #define firewall_direction_prerouting_output  "prerouting-output"
+
+  #define firewall_direction_forward_input_length      13
+  #define firewall_direction_forward_output_length     14
+  #define firewall_direction_postrouting_input_length  17
+  #define firewall_direction_postrouting_output_length 18
+  #define firewall_direction_prerouting_input_length   16
+  #define firewall_direction_prerouting_output_length  17
+
+  #define firewall_direction_input_command       "INPUT"
+  #define firewall_direction_output_command      "OUTPUT"
+  #define firewall_direction_forward_command     "FORWARD"
+  #define firewall_direction_postrouting_command "POSTROUTING"
+  #define firewall_direction_prerouting_command  "PREROUTING"
+
+  #define firewall_direction_input_command_length       5
+  #define firewall_direction_output_command_length      6
+  #define firewall_direction_forward_command_length     7
+  #define firewall_direction_postrouting_command_length 12
+  #define firewall_direction_prerouting_command_length  11
+
+  #define firewall_action        "action"
+  #define firewall_action_append "append"
+  #define firewall_action_insert "insert"
+  #define firewall_action_policy "policy"
+  #define firewall_action_none   "none"
+
+  #define firewall_action_length        6
+  #define firewall_action_append_length 6
+  #define firewall_action_insert_length 6
+  #define firewall_action_policy_length 6
+  #define firewall_action_none_length   4
+
+  #define firewall_action_append_command "-A"
+  #define firewall_action_insert_command "-I"
+  #define firewall_action_policy_command "-P"
+
+  #define firewall_action_append_command_length 2
+  #define firewall_action_insert_command_length 2
+  #define firewall_action_policy_command_length 2
+
+  #define firewall_device      "device"
+  #define firewall_device_all  "all"
+  #define firewall_device_this "this"
+
+  #define firewall_device_length      6
+  #define firewall_device_all_length  3
+  #define firewall_device_this_length 4
+
+  #define firewall_device_input_command  "-i"
+  #define firewall_device_output_command "-o"
+
+  #define firewall_device_input_command_length  2
+  #define firewall_device_output_command_length 2
+
+  enum {
+    firewall_parameter_help,
+    firewall_parameter_light,
+    firewall_parameter_no_color,
+    firewall_parameter_version,
+    firewall_parameter_command_start,
+    firewall_parameter_command_stop,
+    firewall_parameter_command_restart,
+    firewall_parameter_command_lock,
+    firewall_parameter_command_show,
+
+    firewall_direction_forward_id,
+    firewall_direction_postrouting_id,
+    firewall_direction_prerouting_id,
+    firewall_direction_none_id,
+
+    firewall_action_append_id,
+    firewall_action_insert_id,
+    firewall_action_policy_id,
+    firewall_action_none_id,
+  };
+
+  #define f_console_parameter_initialize_firewall \
+    { \
+      f_console_parameter_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_false, f_console_type_normal, 0), \
+      f_console_parameter_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_false, f_console_type_inverse, 0), \
+      f_console_parameter_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, 0, f_false, f_console_type_inverse, 0), \
+      f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_false, f_console_type_normal, 0), \
+      f_console_parameter_initialize(0, 0, 0, firewall_command_start, f_false, f_console_type_other, firewall_command_start_length), \
+      f_console_parameter_initialize(0, 0, 0, firewall_command_stop, f_false, f_console_type_other, firewall_command_stop_length), \
+      f_console_parameter_initialize(0, 0, 0, firewall_command_restart, f_false, f_console_type_other, firewall_command_restart_length), \
+      f_console_parameter_initialize(0, 0, 0, firewall_command_lock, f_false, f_console_type_other, firewall_command_lock_length), \
+      f_console_parameter_initialize(0, 0, 0, firewall_command_show, f_false, f_console_type_other, firewall_command_show_length), \
+    }
+
+  #define firewall_total_parameters 9
+#endif // _di_firewall_defines_
+
+#ifndef _di_firewall_data_
+  typedef struct {
+    f_console_parameter parameters[firewall_total_parameters];
+
+    f_dynamic_string  buffer;
+    f_fss_objects     objects;
+    f_fss_contents    contents;
+    f_file_position   file_position;
+    f_string_lengths  remaining;
+    f_dynamic_strings devices;
+
+    fll_color_context context;
+  } firewall_data;
+
+  #define firewall_data_initialize \
+    { \
+      f_console_parameter_initialize_firewall, \
+      f_dynamic_string_initialize, \
+      f_fss_objects_initialize, \
+      f_fss_contents_initialize, \
+      f_file_position_initialize, \
+      f_string_lengths_initialize, \
+      f_dynamic_strings_initialize, \
+      fll_color_context_initialize, \
+    }
+#endif // _di_firewall_data_
+
+#ifndef _di_firewall_print_version_
+  extern f_return_status firewall_print_version(const firewall_data data);
+#endif // _di_firewall_print_version_
+
+#ifndef _di_firewall_print_help_
+  extern f_return_status firewall_print_help(const firewall_data data);
+#endif // _di_firewall_print_help_
+
+#ifndef _di_firewall_main_
+  extern f_return_status firewall_main(const f_s_int argc, const f_string argv[], firewall_data *data);
+#endif // _di_firewall_main_
+
+#ifndef _di_firewall_delete_data_
+  extern f_return_status firewall_delete_data(firewall_data *data);
+#endif // _di_firewall_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _firewall_h
diff --git a/level_3/firewall/c/main.c b/level_3/firewall/c/main.c
new file mode 100644 (file)
index 0000000..de08204
--- /dev/null
@@ -0,0 +1,7 @@
+#include <level_3/firewall.h>
+
+int main(const f_s_int argc, const f_string argv[]){
+  firewall_data data = firewall_data_initialize;
+
+  return firewall_main(argc, argv, &data);
+}
diff --git a/level_3/firewall/data/build/settings b/level_3/firewall/data/build/settings
new file mode 100644 (file)
index 0000000..4a71b85
--- /dev/null
@@ -0,0 +1,21 @@
+# fss-0000
+
+project_name firewall
+project_level 3
+
+version_major 0
+version_minor 3
+version_micro 0
+
+build_compiler gcc
+build_libraries -lc -lf_memory -lf_console -lf_conversion -lf_output -lf_file -lfl_fss -lfl_console -lfl_file -lfl_strings -lfl_colors -lfl_directory -lfll_execute -lfll_fss -lfll_colors -lf_pipe
+build_sources_library firewall.c
+build_sources_program main.c
+build_sources_headers firewall.h
+build_shared yes
+
+flags_all -z now
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE -lfirewall
diff --git a/level_3/firewall/data/settings/default-blacklist b/level_3/firewall/data/settings/default-blacklist
new file mode 100644 (file)
index 0000000..4f13080
--- /dev/null
@@ -0,0 +1 @@
+# fss-0000
diff --git a/level_3/firewall/data/settings/default-firewall b/level_3/firewall/data/settings/default-firewall
new file mode 100644 (file)
index 0000000..37bf801
--- /dev/null
@@ -0,0 +1,340 @@
+# fss-0002
+# valid direction: input, output, forward, postrouting, prerouting, none
+# valid device: all, this, (any device name goes here without parenthesis)
+# valid action: append, insert, policy, none
+
+first:
+  # initialize the firewall
+  direction none
+  device all
+  action none
+
+  rule -F
+  rule -X
+  rule -Z
+  rule -t nat -F
+  rule -t mangle -F
+
+  # setup initial operations
+  direction input
+  device all
+  action append
+
+
+  # Enable ALL local connections (loopback)
+  device lo
+  direction output
+  rule -j ACCEPT
+
+  direction input
+  rule -j ACCEPT
+  device all
+
+  # the above loopback rules should catch all true loopback connections
+  # the following loopback rules will only catch anything if a loopback spoofing is happending
+  # therefore, do not allow spoof by REJECTing
+  device lo
+  direction input
+  rule -s 127.0.0.1 -j REJECT
+  rule -d 127.0.0.1 -j REJECT
+  device all
+
+
+  # the ip_list command will search for a file in the network settings directory and then apply an action of each of the ip addresses in the file
+  # the file is simply a set of ip addresses separated by whitespace, preferable each on a newline
+  # either 'source' or 'destination' must follow the ip_list
+  # following 'source' or 'destination' is the filename
+  # this is primarily for whitelisting and blacklisting, below are whitelist & blacklist usage cases
+  ip_list source default-whitelist -j ACCEPT
+  ip_list source default-blacklist -j REJECT
+  ip_list destination default-whitelist -j ACCEPT
+  ip_list destination default-blacklist -j REJECT
+
+
+  ## Explicitly deny dhcp renewals
+  #rule -p udp -s 0.0.0.0 --sport 67 -d 255.255.255.255 --dport 68 -j REJECT
+
+
+  ## Log Network Time Protocol Traffic
+  #direction output
+  #rule -p udp --sport 123 --dport 123 -j LOG --log-prefix "TRAFFIC:NTP "
+  #
+  #direction input
+  #rule -p udp --sport 123 --dport 123 -j LOG --log-prefix "TRAFFIC:NTP "
+
+
+  ## Log DHCP Client Traffic
+  #$I -p udp -s 0.0.0.0 --sport 67 -d 255.255.255.255 --dport 68 -j LOG --log-prefix "TRAFFIC:DHCP "
+
+
+  ## Log Web Traffic
+  #direction output
+  #rule -p tcp --sport 80 -j LOG --log-prefix "TRAFFIC:WEB "
+  #
+  #direction input
+  #rule -p tcp --dport 80 -j LOG --log-prefix "TRAFFIC:WEB "
+
+
+  ## Log SSH Traffic
+  #direction output
+  #rule -p tcp --sport 22 -j LOG --log-prefix "TRAFFIC:SSH "
+  #
+  #direction input
+  #rule -p tcp --dport 22 -j LOG --log-prefix "TRAFFIC:SSH "
+
+
+  ## Log VNC Traffic
+  # (uses more than just 5900, so this is a little incomplete)
+  #direction output
+  #rule -p tcp --sport 5900 -j LOG --log-prefix "TRAFFIC:VNC "
+  #
+  #direction input
+  #rule -p tcp --dport 5900 -j LOG --log-prefix "TRAFFIC:VNC "
+
+
+  # Allow ALL input connections that have already been established by this host
+  rule -m state --state ESTABLISHED,RELATED -j ACCEPT
+
+
+  ## Drop all broadcast and multicast packets sent to this machine
+  #rule -m addrtype --dst-type BROADCAST,MULTICAST -j REJECT
+
+
+  ## global forwarding (to/from eth1)
+  #direction forward
+  #rule -j ACCEPT -m state --state ESTABLISHED,RELATED -o eth1
+  #rule -j ACCEPT -m state --state ESTABLISHED,RELATED -i eth1
+  #direction input
+
+
+  ## masquerading
+  #direction postrouting
+  #rule -t nat -o eth0 -j MASQUERADE
+  #direction input
+
+
+  ## Supply a DMZ to all things to an entire subnet of 192.168.1.0 for eth0
+  #direction prerouting
+  #rule -t nat -j DNAT --to-destination 192.168.1.0-192.168.1.254 -i eth0
+  #direction input
+
+
+  ## Change the source address before packet leaves the machine
+  #direction postrouting
+  #rule -t nat -j SNAT --to-source 222.111.222.11 -o eth0
+  #direction input
+
+  # Prevent an XMAS attack
+  rule -p tcp --tcp-flags ALL ALL -j DROP
+
+  # Prevent NULL attack
+  rule -p tcp --tcp-flags ALL NONE -j DROP
+
+  # Force SYN packets check
+  rule -p tcp ! --syn -m state --state NEW -j DROP
+
+  ## Open Moko usb network support (host=eth0 openmoko=usb0)
+  #direction postrouting
+  #rule -t nat -o eth0 -j MASQUERADE
+  #direction forward
+  #rule -j ACCEPT -o usb0
+  #rule -j ACCEPT -i usb0
+  #direction input
+
+
+  # 113 = identd, firewalling this is safer as well as reducing clutter from ftp-servers and chat programs
+  rule -p tcp --dport 113 -j REJECT
+
+
+  ## Log all dropped packets for debug purposes
+  #rule 1 -p tcp -m state --state INVALID -j LOG --log-prefix "FIREWALL:INVALID "
+
+
+  # Drop all INVALID packets so they aren't even processed
+  action insert
+  direction output
+  rule -m state --state INVALID -j REJECT
+
+  direction input
+  rule -m state --state INVALID -j REJECT
+  action append
+
+
+  # Disable X's Open Port
+  # Will X server work with this blocked? Is this needed for X11 Fowarding?
+  #direction output
+  #rule -p tcp --dport 6000 -j REJECT
+  #direction input
+  rule -p tcp --dport 6000 -j REJECT
+
+
+  ## Prevent IP-Spoof attacks (should not come from outside the network, and therefore should only be enabled on a machine that has access outside network) (eth0 = outside network)
+  #rule -s 10.0.0.0/8     -j REJECT -i eth0
+  #rule -s 172.16.0.0/12  -j REJECT -i eth0
+  #rule -s 192.168.0.0/16 -j REJECT -i eth0
+
+
+  # Allow dhcp client renewels. If these are blocked, you will not be able to renew easily
+  rule -p udp -s 0.0.0.0 --sport 67 -d 255.255.255.255 --dport 68 -j ACCEPT
+
+
+  # Allow Network Time Protocal Communication
+  #direction output
+  #rule -p udp --sport 123 --dport 123 -j ACCEPT
+  #direction input
+
+
+  ## Allows for Samba/Windows Shared Network Communication
+  ## By default this is set to REJECT, because window shares generally flood the network, which would then flood the firewall rules making them hard to see
+  ## Windows Ports Uses, and these should never be allowed on WORLD:
+  ## tcp 136 = Profile Naming System
+  ## UDP 137 = NETBIOS Name Service
+  ## UDP 138 = NETBIOS Datagram Service
+  ## TCP 139 = NETBIOS Session Service
+  ## TCP 445 = Windows File and Print Sharing
+  ## TCP/UDP 593 = DCE endpoint resolution, mirror of 135
+  #rule -p tcp --dport 136 -j REJECT
+  #rule -p udp --dport 137 -j REJECT
+  #rule -p udp --dport 138 -j REJECT
+  #rule -p tcp --dport 139 -j REJECT
+  #rule -p tcp --dport 445 -j REJECT
+  #rule -p tcp --sport 136 -j REJECT
+  #rule -p udp --sport 137 -j REJECT
+  #rule -p udp --sport 138 -j REJECT
+  #rule -p tcp --sport 139 -j REJECT
+  #rule -p tcp --sport 445 -j REJECT
+
+
+  ## ICMP ping/pong (receiving pings)
+  #rule -p icmp --icmp-type 8 -m limit --limit 1/s -j ACCEPT
+
+
+  ## iSCSI Target
+  #rule -p tcp --dport 3260 -j ACCEPT
+
+
+last:
+  # setup initial operations
+  direction input
+  device all
+  action append
+
+
+  ## allow Well-known port output: 0-1023
+  #rule -p tcp --dport 0:1023 -j ACCEPT
+  #rule -p udp --dport 0:1023 -j ACCEPT
+
+
+  ## allow registered ports: 1024-49151
+  #rule -p tcp --dport 1024:49151 -j ACCEPT
+  #rule -p udp --dport 1024:49151 -j ACCEPT
+
+
+  ## allow all other ports: 49152-61000
+  ## For ease of the uneducated, enable these by default
+  rule -p tcp --dport 49152:61000 -j ACCEPT
+  rule -p udp --dport 49152:61000 -j ACCEPT
+
+
+  ## allow all other ports: 61001-65535
+  ## For ease of the uneducated, enable these by default
+  rule -p tcp --dport 61001:65535 -j ACCEPT
+  rule -p udp --dport 61001:65535 -j ACCEPT
+
+  # Log everything else (input)
+  # everything that reaches this point without being accepted, reject, or otherwise handled will be logged
+  rule -j LOG --log-prefix "FIREWALL:INPUT "
+
+  # now handle output rules
+  direction output
+
+  # allow Well-known port output: 0-1023
+  rule -p tcp --dport 0:1023 -j ACCEPT
+  rule -p udp --dport 0:1023 -j ACCEPT
+
+
+  # allow registered ports: 1024-49151
+  rule -p tcp --dport 1024:49151 -j ACCEPT
+  rule -p udp --dport 1024:49151 -j ACCEPT
+
+
+  # allow all other ports: 49152-61000
+  # For ease of the uneducated, enable these by default
+  rule -p tcp --dport 49152:61000 -j ACCEPT
+  rule -p udp --dport 49152:61000 -j ACCEPT
+
+
+  # allow all other ports: 61001-65535
+  # For ease of the uneducated, enable these by default
+  rule -p tcp --dport 61001:65535 -j ACCEPT
+  rule -p udp --dport 61001:65535 -j ACCEPT
+
+  ## Log everything else (output)
+  #rule -j LOG --log-prefix "FIREWALL:OUTPUT "
+
+  # allow icmp output, such as pings
+  rule -p icmp -j ACCEPT
+
+  # the catch-all policies
+  action policy
+  direction input
+  rule DROP
+
+  direction output
+  rule DROP
+
+  direction forward
+  rule DROP
+
+stop:
+  device all
+  action policy
+
+  direction input
+  rule ACCEPT
+
+  direction output
+  rule ACCEPT
+
+  direction forward
+  rule ACCEPT
+
+  direction none
+  action none
+  rule --flush
+  rule -t nat --flush
+  rule -t mangle --flush
+  rule --delete-chain
+  rule -t nat --delete-chain
+  rule -t mangle --delete-chain
+
+lock:
+  device all
+  action policy
+
+  direction input
+  rule DROP
+
+  direction output
+  rule DROP
+
+  direction forward
+  rule DROP
+
+  direction none
+  action none
+  rule --flush
+  rule -t nat --flush
+  rule -t mangle --flush
+  rule --delete-chain
+  rule -t nat --delete-chain
+  rule -t mangle --delete-chain
+
+  action insert
+  direction input
+  device lo
+  rule -j ACCEPT
+
+  direction output
+  device lo
+  rule -j ACCEPT
diff --git a/level_3/firewall/data/settings/default-whitelist b/level_3/firewall/data/settings/default-whitelist
new file mode 100644 (file)
index 0000000..4f13080
--- /dev/null
@@ -0,0 +1 @@
+# fss-0000
diff --git a/level_3/firewall/data/settings/example-device-firewall b/level_3/firewall/data/settings/example-device-firewall
new file mode 100644 (file)
index 0000000..d5bf363
--- /dev/null
@@ -0,0 +1,80 @@
+# fss-0002
+
+main:
+  # setup initial operations
+  direction input
+  device this
+  action append
+
+
+  # Define a blacklist and a whitelist, put ip addresses in the file named 'example-device-whitelist' separated by whitespace to whitelist an ip address
+  ip_list source example-device-whitelist -j ACCEPT
+  ip_list source example-device-blacklist -j REJECT
+  ip_list destination example-device-whitelist -j ACCEPT
+  ip_list destination example-device-blacklist -j REJECT
+
+
+  ## DNS Server (Bind or Maradns) (zoneserver from maradns does this portion)
+  ## is tcp needed?
+  #direction output
+  #rule -p udp --dport 53 -j ACCEPT
+  #direction input
+  #rule -p udp --dport 53 -j ACCEPT
+
+
+  ## Http / Web
+  #rule -p tcp --dport 80 --j LOG --log-prefix "TRAFFIC:WEB "
+  #rule -p tcp --dport 80 -j ACCEPT
+
+
+  ## Https / Secure Web
+  #rule -p tcp --dport 443 --j LOG --log-prefix "TRAFFIC:WEB "
+  #rule -p tcp --dport 443 -j ACCEPT
+
+
+  ## MySQL
+  #rule -p tcp --dport 3306 -j ACCEPT
+
+
+  ## Music Player Daemon
+  #rule -p tcp --dport 6600 -j ACCEPT
+
+
+  ## Camsource
+  #rule -p tcp --dport 9192 -j ACCEPT
+
+
+  ## Cups Printer Administration
+  #rule -p tcp --dport 631 -j ACCEPT
+
+
+  ## Ssh (OpenSSH)
+  #rule -p tcp --dport 22 -j LOG --log-prefix "TRAFFIC:SSH "
+  #rule -p tcp --dport 22 -j ACCEPT
+
+
+  ## clamd (Clam Antivirus) - remote access, not needed for normal
+  #rule -p tcp --dport 3310 -j ACCEPT
+
+
+  ## Virtual Network Client Server (add 1 for each seperat vnc server)
+  #rule -p tcp --dport 5900 -j ACCEPT
+
+
+  ## Printer Port, is probably open...safer to close unless you are SERVING a printer
+  #rule -p tcp --dport 515 -j REJECT
+
+
+  ## Subversion server
+  #rule -p tcp --dport 3690 -j ACCEPT
+  #rule -p udp --dport 3690 -j ACCEPT
+
+
+  ## Silc server
+  #rule -p tcp --dport 706 -j ACCEPT
+
+
+  ## Worms of Prey
+  #rule -p tcp --dport 47288 -j ACCEPT
+  #rule -p udp --sport 47288:47544 -j ACCEPT
+  #rule -p udp --dport 47288:47544 -j ACCEPT