/*

                                   _JNJ`                        
                               .JNMH`                           
                              JMMF`       `;.                   
                            .NMM)          `MN.                 
                            MMM)            (MML                
                           (MMM`             MMML               
                     M  I  D  N  I  G  H  T    C  o  D  E       
                           (NMMF             MHNH               
                            NMML            .MMM                
                             NMML          .NMH                 
                              4MMNL       .#F                   
                               `4HNNL_   `                      
                                   `"""`                        

                          Copyright (C) 2004-2006
       "Ian (Larry) Latter" <ian dot latter at midnightcode dot org>

    Midnight Code is a registered trademark of Ian Latter.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, and mirrored at the Midnight Code web
    site; as at version 2 of the License only.
  
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    (version 2) along with this program; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA, or see http://midnightcode.org/gplv2.txt

*/

/* route.c :: Midnight Code route example program			*/


#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>


#include <libmidnightcode.h>


int
main(int argc, char **argv) {
  struct in_addr cfg_net;
  struct in_addr cfg_mask;
  struct in_addr cfg_gway;
  int cfg_help = 0;
  char cfg_eth[10];
  char net_str[21];
  char mask_str[21];
  char gway_str[21];
  char scope[8];
  char * scope_ptr;
  struct midnightcode_config_head_t * config_list_head_p;
  struct midnightcode_route_head_t * route_list_head_p;
  struct midnightcode_route_element_t * now_route;
  void * tmp_void_p;
  int ret_i;

 
  // Prepare switches
  struct midnightcode_switch_t switches[] = {
    { "n", "net", "Network address",
      MIDNIGHTCODE_PARSE_TYPE_HOST, 0, 0, &cfg_net.s_addr },
    { "m", "mask", "Address mask",
      MIDNIGHTCODE_PARSE_TYPE_HOST, 0, 0, &cfg_mask.s_addr },
    { "g", "gateway", "Gateway address",
      MIDNIGHTCODE_PARSE_TYPE_HOST, 0, 0, &cfg_gway.s_addr },
    { "i", "int", "Interface name",
      MIDNIGHTCODE_PARSE_TYPE_STRING, 10, 0, &cfg_eth },
    { "h", "help", "Display this help/usage screen",
      MIDNIGHTCODE_PARSE_TYPE_NONE, 0, 0, &cfg_help },
    { 0 }
  };



  // Set-up initial values;
  memset(&cfg_eth, 0, 10);
  memset(&net_str, 0, 21);
  memset(&mask_str, 0, 21);
  memset(&gway_str, 0, 21);
  memset(&cfg_net, 0, sizeof(struct in_addr));
  memset(&cfg_mask, 0, sizeof(struct in_addr));
  memset(&cfg_gway, 0, sizeof(struct in_addr));


  midnightcode_list_init(config_struct_head,
                         midnightcode_config_element_t);
  tmp_void_p = (void *)&config_struct_head;
  config_list_head_p = tmp_void_p;
  midnightcode_list_init(route_struct_head,
                         midnightcode_route_element_t);
  tmp_void_p = (void *)&route_struct_head;
  route_list_head_p = tmp_void_p;



  // Process switches
  if((ret_i = midnightcode_switch_process(argc, argv, switches)) != 0) {
    fprintf(stdout, "\n");
    midnightcode_logo(0, MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON);
    midnightcode_license(0, MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON, 
      MIDNIGHTCODE_LICENSE_TEXT_COPYRIGHT);
    fprintf(stdout, "    Error in switches, switch \"%s\" is unkown"
      " at parameter number %d.\n\n", argv[ret_i], ret_i);
    midnightcode_switch_usage(MIDNIGHTCODE_SWITCH_STYLE_SOFT, argv[0],
      switches);
    exit(1);
  }
  if(cfg_help) {
    midnightcode_logo(0, MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON);
    midnightcode_license(0, MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON, 
      MIDNIGHTCODE_LICENSE_TEXT_COPYRIGHT);
    midnightcode_switch_usage(MIDNIGHTCODE_SWITCH_STYLE_SOFT, argv[0],
      switches);
    exit(1);
  }
  fflush(stdout);



  // Process license and logo
  midnightcode_logo(0, MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON);
  midnightcode_license(0, MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON, 
    MIDNIGHTCODE_LICENSE_TEXT_ALL);



  // Program title
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_H1,
    MIDNIGHTCODE_STATUS_STYLE_NORMAL, "Route tool example: %s", argv[0]);

  fprintf(stdout, "\n");
  fflush(stdout);




  // Validate user params
  snprintf(net_str, 21, "%s", inet_ntoa(cfg_net));
  snprintf(mask_str, 21, "%s", inet_ntoa(cfg_mask));
  snprintf(gway_str, 21, "%s", inet_ntoa(cfg_gway));


  if(cfg_gway.s_addr != 0) {

    midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
      MIDNIGHTCODE_STATUS_STYLE_NORMAL,
      "Route add %s/%s via %s on %s", net_str, mask_str, gway_str, cfg_eth);
    if(midnightcode_route_add(net_str, mask_str, gway_str, cfg_eth) < 0) {
      midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    } else {
      midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
    }

  }


  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Retrieving all host routes");
  // if((ret_i = midnightcode_route_default(route_list_head_p)) < 0) {
  if((ret_i = midnightcode_route_list(route_list_head_p)) < 0) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }

  printf("\n\n");
  printf("  %-16.16s %-16.16s %-16.16s %-6.6s %-8.8s [%s] %s\n",
      "Target", "Mask", "Gateway", "Metric", "Flags", "If", "Scope");
  printf("\n");
  scope_ptr = scope;
  midnightcode_list_for_each(now_route, route_list_head_p) {

    memset(scope_ptr, 0, 8);
    if(now_route->scope == MIDNIGHTCODE_ROUTE_SCOPE_GLOBAL) {
      snprintf(scope_ptr, 8 - 1, "global");
    } else {
      midnightcode_route_scope(scope_ptr, 8, now_route->scope);
    }

    printf("  %-16.16s %-16.16s %-16.16s %-6.6d %-8.8x [%d] %s\n",
        now_route->ipv4_destination_s,
        now_route->ipv4_destmask_s,
        now_route->ipv4_gateway_s,
        now_route->metric,
        now_route->flags,
        now_route->out_ifindex,
        scope);

  }
  fprintf(stdout, "\n\n");

  /*
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
    MIDNIGHTCODE_STATUS_STYLE_NORMAL,
    "Adding routes to config");
  if(midnightcode_route_to_config(route_list_head_p,
    config_list_head_p) != 0) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
    MIDNIGHTCODE_STATUS_STYLE_NORMAL,
    "Config write to file");
  if(midnightcode_config_write("./route.cfg",
    config_list_head_p, MIDNIGHTCODE_CONFIG_TYPE_NEWSET, 0) != 0) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }
  */



  exit(0);
}
