/*
 * The olsr.org Optimized Link-State Routing daemon(olsrd)
 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 *
 * * Redistributions of source code must retain the above copyright 
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in 
 *   the documentation and/or other materials provided with the 
 *   distribution.
 * * Neither the name of olsr.org, olsrd nor the names of its 
 *   contributors may be used to endorse or promote products derived 
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Visit http://www.olsr.org for more information.
 *
 * If you find this software useful feel free to make a donation
 * to the project. For more information see the website or contact
 * the copyright holders.
 *
 * $Id: main.c,v 1.100 2007/09/17 22:24:22 bernd67 Exp $
 */

#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>

#include "defs.h"
#include "olsr.h"
#include "log.h"
#include "scheduler.h"
#include "parser.h"
#include "generate_msg.h"
#include "plugin_loader.h"
#include "socket_parser.h"
#include "apm.h"
#include "net_os.h"
#include "build_msg.h"

#if LINUX_POLICY_ROUTING
#include <linux/types.h>
#include <linux/rtnetlink.h>
#include <fcntl.h>
#endif

/* Global stuff externed in defs.h */
FILE *debug_handle;             /* Where to send debug(defaults to stdout) */
struct olsrd_config *olsr_cnf;  /* The global configuration */

#ifdef WIN32
#define close(x) closesocket(x)
int __stdcall SignalHandler(unsigned long signal) __attribute__((noreturn));
void ListInterfaces(void);
void DisableIcmpRedirects(void);
olsr_bool olsr_win32_end_request = OLSR_FALSE;
olsr_bool olsr_win32_end_flag = OLSR_FALSE;
#else
static void
olsr_shutdown(int) __attribute__((noreturn));
#endif

/*
 * Local function prototypes
 */
void
olsr_reconfigure(int) __attribute__((noreturn));

static void
print_usage(void);

static int
set_default_ifcnfs(struct olsr_if *, struct if_config_options *);

static int
olsr_process_arguments(int, char *[], 
		       struct olsrd_config *, 
		       struct if_config_options *);

static char **olsr_argv;

static char copyright_string[] = "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org) All rights reserved.";


/**
 * Main entrypoint
 */

int
main(int argc, char *argv[])
{
  struct if_config_options *default_ifcnf;
  char conf_file_name[FILENAME_MAX];
  struct tms tms_buf;

#ifdef WIN32
  WSADATA WsaData;
  int len;
#endif

  /* Stop the compiler from complaining */
  (void)copyright_string;

  debug_handle = stdout;
  olsr_argv = argv;

  setbuf(stdout, NULL);
  setbuf(stderr, NULL);

#ifndef WIN32
  /* Check if user is root */
  if(geteuid())
    {
      fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
      exit(EXIT_FAILURE);
    }
#else
  DisableIcmpRedirects();

  if (WSAStartup(0x0202, &WsaData))
    {
      fprintf(stderr, "Could not initialize WinSock.\n");
      olsr_exit(__func__, EXIT_FAILURE);
    }
#endif

  /* Grab initial timestamp */
  now_times = times(&tms_buf);

  /* Open syslog */
  olsr_openlog("olsrd");

  /* Get initial timestep */
  nowtm = NULL;
  while (nowtm == NULL)
    {
      nowtm = localtime((time_t *)&now.tv_sec);
    }
    
  printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", 
	 olsrd_version, 
	 build_date,
         build_host);
    
  /* Using PID as random seed */
  srandom(getpid());


  /*
   * Set configfile name and
   * check if a configfile name was given as parameter
   */
#ifdef WIN32
#ifndef WINCE
  GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
#else
  conf_file_name[0] = 0;
#endif
  
  len = strlen(conf_file_name);
  
  if (len == 0 || conf_file_name[len - 1] != '\\')
    conf_file_name[len++] = '\\';
  
  strcpy(conf_file_name + len, "olsrd.conf");
#else
  strncpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, FILENAME_MAX);
#endif

  if ((argc > 1) && (strcmp(argv[1], "-f") == 0)) 
    {
      struct stat statbuf;

      argv++; argc--;
      if(argc == 1)
	{
	  fprintf(stderr, "You must provide a filename when using the -f switch!\n");
	  exit(EXIT_FAILURE);
	}

      if (stat(argv[1], &statbuf) < 0)
	{
	  fprintf(stderr, "Could not find specified config file %s!\n%s\n\n", argv[1], strerror(errno));
	  exit(EXIT_FAILURE);
	}
		 
      strncpy(conf_file_name, argv[1], FILENAME_MAX);
      argv++; argc--;

    }

  /*
   * set up configuration prior to processing commandline options
   */
  if((olsr_cnf = olsrd_parse_cnf(conf_file_name)) == NULL)
    {
      printf("Using default config values(no configfile)\n");
      olsr_cnf = olsrd_get_default_cnf();
    }
  if((default_ifcnf = get_default_if_config()) == NULL)
    {
      fprintf(stderr, "No default ifconfig found!\n");
      exit(EXIT_FAILURE);
    }

  /* Initialize tick resolution */
#ifndef WIN32
  olsr_cnf->system_tick_divider = 1000/sysconf(_SC_CLK_TCK);
#else
  olsr_cnf->system_tick_divider = 1;
#endif

  /*
   * Process olsrd options.
   */
  if(olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0)
    {
      print_usage();
      olsr_exit(__func__, EXIT_FAILURE);
    }

  /*
   * Set configuration for command-line specified interfaces
   */
  set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);

  /* free the default ifcnf */
  free(default_ifcnf);

  /* Sanity check configuration */
  if(olsrd_sanity_check_cnf(olsr_cnf) < 0)
    {
      fprintf(stderr, "Bad configuration!\n");
      olsr_exit(__func__, EXIT_FAILURE);      
    }

  /*
   * Print configuration 
   */
  if(olsr_cnf->debug_level > 1)
    olsrd_print_cnf(olsr_cnf);

#ifndef WIN32
  /* Disable redirects globally */
  disable_redirects_global(olsr_cnf->ip_version);
#endif

  /*
   *socket for icotl calls
   */
  if ((olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0)) < 0) 

    {
      olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
      olsr_exit(__func__, 0);
    }

#if LINUX_POLICY_ROUTING
  if ((olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) 
    {
      olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
      olsr_exit(__func__, 0);
    }
  fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
#endif

#if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
  if ((olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
    {
      olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
      olsr_exit(__func__, 0);
    }
#endif

  /* Init empty TC timer */
  set_empty_tc_timer(GET_TIMESTAMP(0));

  /*
   *enable ip forwarding on host
   */
  enable_ip_forwarding(olsr_cnf->ip_version);

  /* Initialize parser */
  olsr_init_parser();

  /* Initialize route-exporter */
  olsr_init_export_route();

  /* Initialize message sequencnumber */
  init_msg_seqno();

  /* Initialize dynamic willingness calculation */
  olsr_init_willingness();

  /*
   *Set up willingness/APM
   */
  if(olsr_cnf->willingness_auto)
    {
      if(apm_init() < 0)
	{
	  OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);

	  olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);

	  olsr_cnf->willingness_auto = 0;
	  olsr_cnf->willingness = WILL_DEFAULT;
	}
      else
	{
	  olsr_cnf->willingness = olsr_calculate_willingness();

	  OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
	}
    }

  /* Set ipsize */
  if(olsr_cnf->ip_version == AF_INET6)
    {
      OLSR_PRINTF(1, "Using IP version %d\n", 6);
      olsr_cnf->ipsize = sizeof(struct in6_addr);
      olsr_cnf->maxplen = 128;
    }
  else
    {
      OLSR_PRINTF(1, "Using IP version %d\n", 4);
      olsr_cnf->ipsize = sizeof(struct in_addr);
      olsr_cnf->maxplen = 32;
    }

  /* Initialize net */
  init_net();

  /* Initializing networkinterfaces */
  if(!ifinit())
    {
      if(olsr_cnf->allow_no_interfaces)
	{
	  fprintf(stderr, "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
	  sleep(5);
	}
      else
	{
	  fprintf(stderr, "No interfaces detected!\nBailing out!\n");
	  olsr_exit(__func__, EXIT_FAILURE);
	}
    }

  /* Print heartbeat to stdout */

#if !defined WINCE
  if(olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO))
    olsr_register_scheduler_event(&generate_stdout_pulse, NULL, STDOUT_PULSE_INT, 0, NULL);
#endif
  
  gettimeofday(&now, NULL);


  /* Initialize the IPC socket */

  if(olsr_cnf->open_ipc)
      ipc_init();

  /* Initialisation of different tables to be used.*/
  olsr_init_tables();

  /* daemon mode */
#ifndef WIN32
  if((olsr_cnf->debug_level == 0) && (!olsr_cnf->no_fork))
    {
      printf("%s detaching from the current process...\n", olsrd_version);
      if(daemon(0, 0) < 0)
	{
	  printf("daemon(3) failed: %s\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}
    }
#endif

  /* Load plugins */
  olsr_load_plugins();

  OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&olsr_cnf->main_addr));

  /* Start syslog entry */
  olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);

  /*
   *signal-handlers
   */

  /* ctrl-C and friends */
#ifdef WIN32
#ifndef WINCE
  SetConsoleCtrlHandler(SignalHandler, OLSR_TRUE);
#endif
#else
  signal(SIGHUP, olsr_reconfigure);  
  signal(SIGINT, olsr_shutdown);  
  signal(SIGTERM, olsr_shutdown);  
  signal(SIGPIPE, SIG_IGN);
#endif

  /* Register socket poll event */
  olsr_register_timeout_function(&poll_sockets, OLSR_FALSE);

  /* Starting scheduler */
  scheduler();

  /* Stop the compiler from complaining */
  (void)copyright_string;

  /* Like we're ever going to reach this ;-) */
  return 1;
} /* main */



/**
 * Reconfigure olsrd. Currently kind of a hack...
 *
 *@param signal the signal that triggered this callback
 */
#ifndef WIN32
void
olsr_reconfigure(int signal __attribute__((unused)))
{
  if(!fork())
    {
      /* New process */
      sleep(3);
      printf("Restarting %s\n", olsr_argv[0]);
      execv(olsr_argv[0], olsr_argv);
    }
  olsr_shutdown(0);

  printf("RECONFIGURING!\n");
}
#endif


/**
 *Function called at shutdown. Signal handler
 *
 * @param signal the signal that triggered this call
 */
#ifdef WIN32
int __stdcall
SignalHandler(unsigned long signal)
#else
static void
olsr_shutdown(int signal)
#endif
{
  struct interface *ifn;

  OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signal);

#ifdef WIN32
  OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");

  olsr_win32_end_request = TRUE;

  while (!olsr_win32_end_flag)
    Sleep(100);

  OLSR_PRINTF(1, "Scheduler stopped.\n");
#endif

  olsr_delete_all_kernel_routes();

  OLSR_PRINTF(1, "Closing sockets...\n");

  /* front-end IPC socket */
  if(olsr_cnf->open_ipc)
    shutdown_ipc();

  /* OLSR sockets */
  for (ifn = ifnet; ifn; ifn = ifn->int_next) 
    close(ifn->olsr_socket);

  /* Closing plug-ins */
  olsr_close_plugins();

  /* Reset network settings */
  restore_settings(olsr_cnf->ip_version);

  /* ioctl socket */
  close(olsr_cnf->ioctl_s);

#if LINUX_POLICY_ROUTING
  close(olsr_cnf->rtnl_s);
#endif

#if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
  /* routing socket */
  close(olsr_cnf->rts);
#endif

  olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);

  OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);

  exit(olsr_cnf->exit_value);
}

/**
 * Print the command line usage
 */
static void
print_usage(void)
{

  fprintf(stderr,
          "An error occured somwhere between your keyboard and your chair!\n"
          "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
          "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
          "  [-lql <LQ level>] [-lqw <LQ winsize>]\n"
          "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
          "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
          "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
          "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n"
          "  [-lql <LQ level>] [-lqw <LQ winsize>]\n");
}


/**
 * Sets the provided configuration on all unconfigured
 * interfaces
 *
 * @param ifs a linked list of interfaces to check and possible update
 * @param cnf the default configuration to set on unconfigured interfaces
 */
int
set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf)
{
  int changes = 0;

  while(ifs)
    {
      if(ifs->cnf == NULL)
	{
	  ifs->cnf = olsr_malloc(sizeof(struct if_config_options), "Set default config");
	  *ifs->cnf = *cnf;
	  changes++;
	}
      ifs = ifs->next;
    }
  return changes;
}


#define NEXT_ARG argv++;argc--
#define CHECK_ARGC if(!argc) { \
      if((argc - 1) == 1){ \
      fprintf(stderr, "Error parsing command line options!\n"); \
      olsr_exit(__func__, EXIT_FAILURE); \
      } else { \
      argv--; \
      fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
      olsr_exit(__func__, EXIT_FAILURE); \
     } \
     }

/**
 * Process command line arguments passed to olsrd
 *
 */
static int
olsr_process_arguments(int argc, char *argv[], 
		       struct olsrd_config *cnf, 
		       struct if_config_options *ifcnf)
{
  while (argc > 1)
    {
      NEXT_ARG;
#ifdef WIN32
      /*
       *Interface list
       */
      if (strcmp(*argv, "-int") == 0)
        {
          ListInterfaces();
          exit(0);
        }
#endif

      /*
       *Configfilename
       */
      if(strcmp(*argv, "-f") == 0) 
	{
	  fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
	  olsr_exit(__func__, EXIT_FAILURE);
	}

      /*
       *Use IP version 6
       */
      if(strcmp(*argv, "-ipv6") == 0) 
	{
	  cnf->ip_version = AF_INET6;
	  continue;
	}

      /*
       *Broadcast address
       */
      if(strcmp(*argv, "-bcast") == 0) 
	{
	  struct in_addr in;
	  NEXT_ARG;
          CHECK_ARGC;

	  if (inet_aton(*argv, &in) == 0)
	    {
	      printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
	      continue;
	    }
	  memcpy(&ifcnf->ipv4_broadcast.v4, &in.s_addr, sizeof(olsr_u32_t));  
	  continue;
	}

      /*
       * Set LQ level
       */
      if (strcmp(*argv, "-lql") == 0) 
	{
	  int tmp_lq_level;
	  NEXT_ARG;
          CHECK_ARGC;
	  
	  /* Sanity checking is done later */
	  sscanf(*argv, "%d", &tmp_lq_level);
	  olsr_cnf->lq_level = tmp_lq_level;
	  continue;
	}

      /*
       * Set LQ winsize
       */
      if (strcmp(*argv, "-lqw") == 0) 
	{
	  int tmp_lq_wsize;
	  NEXT_ARG;
          CHECK_ARGC;
	  
	  sscanf(*argv, "%d", &tmp_lq_wsize);

	  if(tmp_lq_wsize < MIN_LQ_WSIZE || tmp_lq_wsize > MAX_LQ_WSIZE)
	    {
	      printf("LQ winsize %d not allowed. Range [%d-%d]\n", 
		     tmp_lq_wsize, MIN_LQ_WSIZE, MAX_LQ_WSIZE);
	      olsr_exit(__func__, EXIT_FAILURE);
	    }
	  olsr_cnf->lq_wsize = tmp_lq_wsize;
	  continue;
	}
      
      /*
       * Enable additional debugging information to be logged.
       */
      if (strcmp(*argv, "-d") == 0) 
	{
	  NEXT_ARG;
          CHECK_ARGC;

	  sscanf(*argv,"%d", &cnf->debug_level);
	  continue;
	}

		
      /*
       * Interfaces to be used by olsrd.
       */
      if (strcmp(*argv, "-i") == 0) 
	{
	  NEXT_ARG;
          CHECK_ARGC;

	  if(*argv[0] == '-')
	    {
	      fprintf(stderr, "You must provide an interface label!\n");
	      olsr_exit(__func__, EXIT_FAILURE);
	    }
	  printf("Queuing if %s\n", *argv);
	  queue_if(*argv, OLSR_FALSE);

	  while((argc - 1) && (argv[1][0] != '-'))
	    {
	      NEXT_ARG;
	      printf("Queuing if %s\n", *argv);
	      queue_if(*argv, OLSR_FALSE);
	    }

	  continue;
	}
      /*
       * Set the hello interval to be used by olsrd.
       * 
       */
      if (strcmp(*argv, "-hint") == 0) 
	{
	  NEXT_ARG;
          CHECK_ARGC;
	  sscanf(*argv,"%f", &ifcnf->hello_params.emission_interval);
          ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval * 3;
	  continue;
	}

      /*
       * Set the HNA interval to be used by olsrd.
       * 
       */
      if (strcmp(*argv, "-hnaint") == 0) 
	{
	  NEXT_ARG;
          CHECK_ARGC;
	  sscanf(*argv,"%f", &ifcnf->hna_params.emission_interval);
          ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
	  continue;
	}

      /*
       * Set the MID interval to be used by olsrd.
       * 
       */
      if (strcmp(*argv, "-midint") == 0) 
	{
	  NEXT_ARG;
          CHECK_ARGC;
	  sscanf(*argv,"%f", &ifcnf->mid_params.emission_interval);
          ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
	  continue;
	}

      /*
       * Set the tc interval to be used by olsrd.
       * 
       */
      if (strcmp(*argv, "-tcint") == 0) 
	{
	  NEXT_ARG;
          CHECK_ARGC;
	  sscanf(*argv,"%f", &ifcnf->tc_params.emission_interval);
          ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
	  continue;
	}

      /*
       * Set the polling interval to be used by olsrd.
       */
      if (strcmp(*argv, "-T") == 0) 
	{
	  NEXT_ARG;
          CHECK_ARGC;
	  sscanf(*argv,"%f",&cnf->pollrate);
	  continue;
	}


      /*
       * Should we display the contents of packages beeing sent?
       */
      if (strcmp(*argv, "-dispin") == 0) 
	{
	  parser_set_disp_pack_in(OLSR_TRUE);
	  continue;
	}

      /*
       * Should we display the contents of incoming packages?
       */
      if (strcmp(*argv, "-dispout") == 0) 
	{
	  net_set_disp_pack_out(OLSR_TRUE);
	  continue;
	}


      /*
       * Should we set up and send on a IPC socket for the front-end?
       */
      if (strcmp(*argv, "-ipc") == 0) 
	{
	  cnf->ipc_connections = 1;
	  cnf->open_ipc = OLSR_TRUE;
	  continue;
	}

      /*
       * IPv6 multicast addr
       */
      if (strcmp(*argv, "-multi") == 0) 
	{
	  struct in6_addr in6;
	  NEXT_ARG;
          CHECK_ARGC;
	  if(inet_pton(AF_INET6, *argv, &in6) <= 0)
	    {
	      fprintf(stderr, "Failed converting IP address %s\n", *argv);
	      exit(EXIT_FAILURE);
	    }

	  memcpy(&ifcnf->ipv6_multi_glbl, &in6, sizeof(struct in6_addr));

	  continue;
	}

      /*
       * Host emulation
       */
      if (strcmp(*argv, "-hemu") == 0) 
	{
	  struct in_addr in;
	  struct olsr_if *ifa;
      
	  NEXT_ARG;
          CHECK_ARGC;
	  if(inet_pton(AF_INET, *argv, &in) <= 0)
	    {
	      fprintf(stderr, "Failed converting IP address %s\n", *argv);
	      exit(EXIT_FAILURE);
	    }
	  /* Add hemu interface */

	  ifa = queue_if("hcif01", OLSR_TRUE);

	  if(!ifa)
	    continue;

	  ifa->cnf = get_default_if_config();
	  ifa->host_emul = OLSR_TRUE;
	  memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
	  cnf->host_emul = OLSR_TRUE;

	  continue;
	}


      /*
       * Delete possible default GWs
       */
      if (strcmp(*argv, "-delgw") == 0) 
	{
	  olsr_cnf->del_gws = OLSR_TRUE;
	  continue;
	}


      if (strcmp(*argv, "-nofork") == 0) 
	{
	  cnf->no_fork = OLSR_TRUE;
	  continue;
	}

      return -1;
    }
  return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1