]> Kevux Git Server - fll/commitdiff
Cleanup: Move private functions into its own source and header files
authorKevin Day <kevin@kevux.org>
Tue, 3 Apr 2012 23:16:40 +0000 (18:16 -0500)
committerKevin Day <kevin@kevux.org>
Tue, 3 Apr 2012 23:16:40 +0000 (18:16 -0500)
It has become painfully apparent that much of the firewall main function needs to be broken down into smaller functions for managability and readability purposes.
The first step in doing such is to create a privte header and source files and move all internal functions there.
Everything in the private-* files are intended to never be exposed in the library.
Its only purpose is to make programming large projects more managable and readable.
As such, none of the functions should ever be considered part of the libraries/programs api.

level_3/firewall/c/firewall.c
level_3/firewall/c/private-firewall.c [new file with mode: 0644]
level_3/firewall/c/private-firewall.h [new file with mode: 0644]
level_3/firewall/data/build/settings

index bc0012e..c4924d4 100644 (file)
@@ -5,6 +5,7 @@
  * Programmers:   Kevin Day
  */
 #include <level_3/firewall.h>
+#include "private-firewall.h"
 
 #ifdef __cplusplus
 extern "C"{
@@ -106,8 +107,6 @@ extern "C"{
 #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, const f_dynamic_string *custom_chain) __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;
@@ -1433,706 +1432,6 @@ extern "C"{
     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, const f_dynamic_string *custom_chain) {
-    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 (custom_chain != f_null) {
-          f_resize_dynamic_string(status, argument, custom_chain->used);
-
-          if (f_macro_test_for_allocation_errors(status)) break;
-
-          strncat(argument.string, custom_chain->string, custom_chain->used);
-          argument.used = custom_chain->used;
-        } else 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_
diff --git a/level_3/firewall/c/private-firewall.c b/level_3/firewall/c/private-firewall.c
new file mode 100644 (file)
index 0000000..b846bde
--- /dev/null
@@ -0,0 +1,706 @@
+/**
+ * Private source file for firewall.c.
+ */
+#include <level_3/firewall.h>
+
+#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, const f_dynamic_string *custom_chain) {
+    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 (custom_chain != f_null) {
+          f_resize_dynamic_string(status, argument, custom_chain->used);
+
+          if (f_macro_test_for_allocation_errors(status)) break;
+
+          strncat(argument.string, custom_chain->string, custom_chain->used);
+          argument.used = custom_chain->used;
+        } else 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_
diff --git a/level_3/firewall/c/private-firewall.h b/level_3/firewall/c/private-firewall.h
new file mode 100644 (file)
index 0000000..cd37595
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * Private include file for firewall.c.
+ */
+
+#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, const f_dynamic_string *custom_chain) __attribute__((visibility("internal")));
+#endif // _di_firewall_main_
index 4a71b85..957966a 100644 (file)
@@ -9,7 +9,7 @@ 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_library firewall.c private-firewall.c
 build_sources_program main.c
 build_sources_headers firewall.h
 build_shared yes