\section{Méthodes}

\subsection{route}

La méthode "route" retourne la route (\Colorbox{light-gray}{\lstinline|Route|}), utilisée par l'équipement (\Colorbox{light-gray}{\lstinline|Device|}) pour atteindre le réseau spécifié. C'est une mise en application de ce qui est expliqué dans la section \ref{subsec:network:ip:routing}. Pour y arriver, il faut donc obtenir celles dont les adresses limites du réseau comprennent celle du réseau voulu.

\vspace{3mm}
\begin{lstlisting}[language=Ruby, title="app/model/routing\_table.rb"]
  # Params:
  # * network: an IPv4 network to test
  def route(network)
    ip_net = IPAddr.new network
    ip = ip_net.to_i

    candidate_routes = routes.where(:start_ip.lte => ip, :end_ip.gte => ip)

    choosed_route(candidate_routes)
  end
\end{lstlisting}
\vspace{3mm}

Une fois les routes possibles obtenues, il faut encore isoler celle qui est la plus précise. Pour cela, il suffit de calculer le nombre d'adresses disponibles dans le réseau et de choisir celle qui en a le moins.

\vspace{3mm}
\begin{lstlisting}[language=Ruby, title="app/model/routing\_table.rb"]
  # Params:
  # * candidate_routes: a list of Route
  def choosed_route(candidate_routes)
    network_length = 4_294_967_296
    choose_route = nil

    candidate_routes.each do |candidate|
      network = IPAddr.new candidate.network
      network_size = network.to_range.last.to_i - network.to_range.first.to_i
      if network_size < network_length
        network_length = network_size
        choose_route = candidate
      end
    end

    choose_route
  end
\end{lstlisting}
\vspace{3mm}

\subsection{crossed?}
\label{sec:methodes:crossed}

La méthode "crossed?" est un élément essentiel pour l'analyse des règles de sécurité (\Colorbox{light-gray}{\lstinline|Policy|}). Elle permet de déterminer si un équipement (\Colorbox{light-gray}{\lstinline|Device|}) est traversé par un flux définit par deux réseaux. Pour cela, il faut utiliser la méthode "route" de la table de routage (\Colorbox{light-gray}{\lstinline|RoutingTable|}) de l'équipement en question et comparer l'interface de sortie des deux routes obtenues. Si elles sont différentes, cela signifique que le flux traverse ce firewall.

\begin{lstlisting}[language=Ruby, title="app/model/device.rb"]
  # Params:
  # * network1: the *source* network
  # * network2: the *destination* network
  def crossed?(network1, network2)
    return false unless routing_table
    route1 = routing_table.route(network1)
    route2 = routing_table.route(network2)

    return false unless route1 && route2
    route1.interface != route2.interface
  end
\end{lstlisting}

\subsection{matched\_policies}
\label{sec:methodes:matched_policies}

Cette méthode permet de gérer la fonctionnalité principale de l'application, soit de rechercher une règle spécifique en précisant une réseau source et distination, un protocole et un numéro de port.

\begin{lstlisting}[language=Ruby, title="app/model/device.rb"]
  # Params:
  # * request: the PolicyRequest with all the required informations
  def matched_policies(request)
    policies = []
    policies_found = find_policies(request)

    if !policies_found.empty? && request.include_all
      policies += policies_found
    elsif !policies_found.empty?
      policies << policies_found.first
    else
      policies << implicit_policy
    end

    policies
  end
\end{lstlisting}

Le but ici est de faire la requête de recherche et de retourner toutes les règles de sécurité obtenues ou bien uniquement la première en fonction de ce qui a été demandé dans la requête. Si aucune règle de sécurité n'est trouvée, la méthode va retourner une règle qui correspond à une règle implicite de blocage (par défaut sur firewall, ce qui n'est pas explicitement autorisé est bloqué).

\begin{lstlisting}[language=Ruby, title="app/model/device.rb"]
  # Params:
  # * request: the PolicyRequest with all the required informations
  def find_policies(request)
    source = matched_addresses(request.source)
    source += matched_address_groups(source)
    destination = matched_addresses(request.destination)
    destination += matched_address_groups(destination)
    service = matched_services(request.protocol, request.port)
    service += matched_service_groups(service)
    source_interface = zone_name(
      routing_table.route(request.source).interface
    )
    destination_interface = zone_name(
      routing_table.route(request.destination).interface
    )

    policies.where(
      source_interface: source_interface,
      destination_interface: destination_interface
    ).any_in(
      source: source,
      destination: destination,
      service: service
    )
  end
\end{lstlisting}

La requête sur la base de donnée qui permet d'obtenir les règles de sécurité voulues est définie dans la fonction ci-dessus. Pour cela, il faut commencer par isoler les adresses source et destination ainsi que les services. On cherche ici à comparer des tableaux de String entre eux et à savoir si au moins un des éléments de ce tableau se retrouvent dans l'autre tableau. La méthode utilisée pour cela est "any\_in"\cite{stackanyin} en lui précisant les paramètres.