Пример #1
0
isc_result_t
named_log_init(isc_boolean_t safe) {
	isc_result_t result;
	isc_logconfig_t *lcfg = NULL;

	named_g_categories = categories;
	named_g_modules = modules;

	/*
	 * Setup a logging context.
	 */
	result = isc_log_create(named_g_mctx, &named_g_lctx, &lcfg);
	if (result != ISC_R_SUCCESS)
		return (result);

	/*
	 * named-checktool.c:setup_logging() needs to be kept in sync.
	 */
	isc_log_registercategories(named_g_lctx, named_g_categories);
	isc_log_registermodules(named_g_lctx, named_g_modules);
	isc_log_setcontext(named_g_lctx);
	dns_log_init(named_g_lctx);
	dns_log_setcontext(named_g_lctx);
	cfg_log_init(named_g_lctx);
	ns_log_init(named_g_lctx);
	ns_log_setcontext(named_g_lctx);

	if (safe)
		result = named_log_setsafechannels(lcfg);
	else
		result = named_log_setdefaultchannels(lcfg);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	result = named_log_setdefaultcategory(lcfg);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	return (ISC_R_SUCCESS);

 cleanup:
	isc_log_destroy(&named_g_lctx);
	isc_log_setcontext(NULL);
	dns_log_setcontext(NULL);

	return (result);
}
Пример #2
0
static void
setup(void) {
	isc_result_t result;
	isc_resourcevalue_t old_openfiles;
#ifdef HAVE_LIBSCF
	char *instance = NULL;
#endif

	/*
	 * Get the user and group information before changing the root
	 * directory, so the administrator does not need to keep a copy
	 * of the user and group databases in the chroot'ed environment.
	 */
	ns_os_inituserinfo(ns_g_username);

	/*
	 * Initialize time conversion information
	 */
	ns_os_tzset();

	ns_os_opendevnull();

#ifdef HAVE_LIBSCF
	/* Check if named is under smf control, before chroot. */
	result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
	/* We don't care about instance, just check if we got one. */
	if (result == ISC_R_SUCCESS)
		ns_smf_got_instance = 1;
	else
		ns_smf_got_instance = 0;
	if (instance != NULL)
		isc_mem_free(ns_g_mctx, instance);
#endif /* HAVE_LIBSCF */

#ifdef PATH_RANDOMDEV
	/*
	 * Initialize system's random device as fallback entropy source
	 * if running chroot'ed.
	 */
	if (ns_g_chrootdir != NULL) {
		result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy);
		if (result != ISC_R_SUCCESS)
			ns_main_earlyfatal("isc_entropy_create() failed: %s",
					   isc_result_totext(result));

		result = isc_entropy_createfilesource(ns_g_fallbackentropy,
						      PATH_RANDOMDEV);
		if (result != ISC_R_SUCCESS) {
			ns_main_earlywarning("could not open pre-chroot "
					     "entropy source %s: %s",
					     PATH_RANDOMDEV,
					     isc_result_totext(result));
			isc_entropy_detach(&ns_g_fallbackentropy);
		}
	}
#endif

#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * Check for the number of cpu's before ns_os_chroot().
	 */
	ns_g_cpus_detected = isc_os_ncpus();
#endif

	ns_os_chroot(ns_g_chrootdir);

	/*
	 * For operating systems which have a capability mechanism, now
	 * is the time to switch to minimal privs and change our user id.
	 * On traditional UNIX systems, this call will be a no-op, and we
	 * will change the user ID after reading the config file the first
	 * time.  (We need to read the config file to know which possibly
	 * privileged ports to bind() to.)
	 */
	ns_os_minprivs();

	result = ns_log_init(ISC_TF(ns_g_username != NULL));
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("ns_log_init() failed: %s",
				   isc_result_totext(result));

	/*
	 * Now is the time to daemonize (if we're not running in the
	 * foreground).  We waited until now because we wanted to get
	 * a valid logging context setup.  We cannot daemonize any later,
	 * because calling create_managers() will create threads, which
	 * would be lost after fork().
	 */
	if (!ns_g_foreground)
		ns_os_daemonize();

	/*
	 * We call isc_app_start() here as some versions of FreeBSD's fork()
	 * destroys all the signal handling it sets up.
	 */
	result = isc_app_start();
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("isc_app_start() failed: %s",
				   isc_result_totext(result));

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE, "starting %s %s%s%s <id:%s>%s",
		      ns_g_product, ns_g_version,
		      *ns_g_description ? " " : "", ns_g_description,
		      ns_g_srcid, saved_command_line);

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE, "running on %s", ns_os_uname());

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE, "built with %s", ns_g_configargs);

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "----------------------------------------------------");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "BIND 9 is maintained by Internet Systems Consortium,");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "Inc. (ISC), a non-profit 501(c)(3) public-benefit ");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "corporation.  Support and training for BIND 9 are ");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "available at https://www.isc.org/support");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "----------------------------------------------------");

	dump_symboltable();

	/*
	 * Get the initial resource limits.
	 */
	(void)isc_resource_getlimit(isc_resource_stacksize,
				    &ns_g_initstacksize);
	(void)isc_resource_getlimit(isc_resource_datasize,
				    &ns_g_initdatasize);
	(void)isc_resource_getlimit(isc_resource_coresize,
				    &ns_g_initcoresize);
	(void)isc_resource_getlimit(isc_resource_openfiles,
				    &ns_g_initopenfiles);

	/*
	 * System resources cannot effectively be tuned on some systems.
	 * Raise the limit in such cases for safety.
	 */
	old_openfiles = ns_g_initopenfiles;
	ns_os_adjustnofile();
	(void)isc_resource_getlimit(isc_resource_openfiles,
				    &ns_g_initopenfiles);
	if (old_openfiles != ns_g_initopenfiles) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
			      "adjusted limit on open files from "
			      "%" ISC_PRINT_QUADFORMAT "u to "
			      "%" ISC_PRINT_QUADFORMAT "u",
			      old_openfiles, ns_g_initopenfiles);
	}

	/*
	 * If the named configuration filename is relative, prepend the current
	 * directory's name before possibly changing to another directory.
	 */
	if (! isc_file_isabsolute(ns_g_conffile)) {
		result = isc_file_absolutepath(ns_g_conffile,
					       absolute_conffile,
					       sizeof(absolute_conffile));
		if (result != ISC_R_SUCCESS)
			ns_main_earlyfatal("could not construct absolute path "
					   "of configuration file: %s",
					   isc_result_totext(result));
		ns_g_conffile = absolute_conffile;
	}

	/*
	 * Record the server's startup time.
	 */
	result = isc_time_now(&ns_g_boottime);
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("isc_time_now() failed: %s",
				   isc_result_totext(result));

	result = create_managers();
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("create_managers() failed: %s",
				   isc_result_totext(result));

	ns_builtin_init();

	/*
	 * Add calls to register sdb drivers here.
	 */
	/* xxdb_init(); */

#ifdef ISC_DLZ_DLOPEN
	/*
	 * Register the DLZ "dlopen" driver.
	 */
	result = dlz_dlopen_init(ns_g_mctx);
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("dlz_dlopen_init() failed: %s",
				   isc_result_totext(result));
#endif

#if CONTRIB_DLZ
	/*
	 * Register any other contributed DLZ drivers.
	 */
	result = dlz_drivers_init();
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("dlz_drivers_init() failed: %s",
				   isc_result_totext(result));
#endif

	ns_server_create(ns_g_mctx, &ns_g_server);

#ifdef HAVE_LIBSECCOMP
	setup_seccomp();
#endif /* HAVE_LIBSECCOMP */
}
int main(int argc, char *argv[])
{
    struct sc_desc sd;
    struct sc_lb_group lbg1;
    struct sc_lb_group lbg2;
    int ha_port = -1;
    int stack_size = -1;
    int nfes = -1;
    int tcam_index = 18;
    int lbg_index = 3;

    ns_log_init(NS_LOG_COLOR | NS_LOG_CONSOLE);
    ns_log_lvl_set(NS_LOG_LVL_INFO);

    int c;
    while ((c = getopt_long(argc, argv, "p:l:ht:s:n:i:", __long_options, NULL)) != -1) {
        switch (c) {
            case 'p':
                ha_port = strtol(optarg,0,0);
                break;
            case 'l':
                ns_log_lvl_set((unsigned int)strtoul(optarg,0,0));
                break;
            case 't':
                tcam_index = strtol(optarg,0,0);
                break;
            case 's':
                stack_size = strtol(optarg,0,0);
                break;
            case 'n':
                nfes = strtol(optarg,0,0);
                break;
            case 'i':
                lbg_index = strtol(optarg,0,0);
                break;
            case 'h':
            default:
                print_usage(argv[0]);
        }
    }

    if (optind != argc || argc == 1)
    print_usage(argv[0]);

    if (ha_port < 0 || ha_port > SCMD_MAX_PORTS) {
        fprintf(stderr, "Bad HA port value\n");
        exit(1);
    }
    if (tcam_index < SC_TCAM_RESERVED || tcam_index > 3000) {
        fprintf(stderr, "Bad tcam index value\n");
        exit(1);
    }
    if (stack_size < 1 || stack_size > 4) {
        fprintf(stderr, "Bad stack size value\n");
        exit(1);
    }
    if (nfes < 1 || nfes > MAX_NFE || nfes == 3) {
        fprintf(stderr, "Bad nfes value\n");
        exit(1);
    }
    if (lbg_index < SC_LB_MIN_GROUP || lbg_index > (SC_LB_MAX_GROUP-1)) {
        fprintf(stderr, "Bad load-balance group value\n");
        exit(1);
    }

    /* Pick out unsupported NFE/Stack_size combinations */
    if (nfes < 2 && stack_size > 3) {
        fprintf(stderr, "Bad NFE and stack size combination\n");
        exit(1);
    }

    if (open_scmd_handle(&sd,SC_AP_ID_PORTBYPASS) != 0)
        exit(1);

    if (create_load_balance_groups(&sd, &lbg1, &lbg2, lbg_index, stack_size, nfes) != 0) {
        scmd_close(&sd);
        exit(1);
    }
    scmd_close(&sd);

    if (open_scmd_handle(&sd,SC_AP_ID_TCAM) != 0)
        exit(1);

    if (create_tcam_rules(&sd, ha_port, tcam_index, lbg_index) != 0) {
        scmd_close(&sd);
        exit(1);
    }

    return 0;
}
int main(int argc, char *argv[])
{
  ns_rule_handle_h *rh = NULL;
  ns_nfm_ret_t ret = NS_NFM_SUCCESS;
  unsigned int host_id = 15;
  unsigned int device = 0;
  unsigned int nrules = 32768;
  unsigned int i;

  ns_log_init(NS_LOG_COLOR | NS_LOG_CONSOLE);
  ns_log_lvl_set(NS_LOG_LVL_INFO);

  int c;
  while ((c = getopt_long(argc, argv, "l:hd:", __long_options, NULL)) != -1) {
    switch (c) {
    case 'l':
      ns_log_lvl_set((unsigned int)strtoul(optarg,0,0));
      break;
    case 'i':
      host_id = (unsigned int)strtoul(optarg,0,0);
      if (host_id > 31) {
        fprintf(stderr, "Host_id %d is out of range (0-31)\n", device);
        exit(1);
      }
      break;
    case 'd':
      device = (unsigned int)strtoul(optarg,0,0);
      if (device > 3) {
        fprintf(stderr, "Device %d is out of range (0-3)\n", device);
        exit(1);
      }
      break;
    case 'h':
    default:
      print_usage(argv[0]);
    }
  }

  if (optind < argc - 1)
    print_usage(argv[0]);

  if (optind < argc) {
    nrules = strtoul(argv[optind], NULL, 0);
    if (nrules > NUM_RULES) {
      fprintf(stderr, "Max rules is %u\n", NUM_RULES);
      return 1;
    }
  }

  // Init the rules lib
  printf("opening connection to rules daemon\n");
  rh = ns_rules_init(RULESD_Q_NAME, RQNAME, device);
  if (!rh) {
    fprintf(stderr, "ns_rules_init() failed\n");
    return 1;
  }

  // Send default config to rulesd
  ret = ns_rules_setup(rh);
  if (ret != NS_NFM_SUCCESS) {
    fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
    goto fail;
  }

  printf("\tflushing rules...\n");
  // Flush all the existing rules.
  ret = ns_rule_flush_hw(rh);
  if (ret != NS_NFM_SUCCESS) {
    fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
    goto fail;
  }

  printf("\tcreating %u rules...\n", nrules);
  for (i = 0; i < nrules; i++) {
    sprintf(rnames[i], "rule %u", i);
    ret = add_rule(rh, rnames[i], SEND_ACTION_PASS,
                   FST_30_SECOND_LIST_NUM);
    if (ret != NS_NFM_SUCCESS) {
      fprintf(stderr, "failure @ %s: %d on rule %u\n", __FILE__, __LINE__, i);
      goto fail;
    }
  }

  // Commit
  printf("\tcommitting new rules...\n");
  ret = ns_rule_commit_rulesdb(rh);
  if (ret != NS_NFM_SUCCESS) {
    fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
    goto fail;
  }

  // Close the rules library.
  printf("done\n");
  ns_rules_close(rh);
  if (ret != NS_NFM_SUCCESS) {
    fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
    goto fail;
  }

  return 0;

fail:
  ns_rules_close(rh);
  return 1;
}
int main(int argc, char *argv[])
{
  ns_flow_ha_h *h;
  ns_nfm_ret_t ret;
  unsigned char *buf;
  unsigned int remote_req = 0;
  unsigned int flowmask = 0;
  unsigned int syncmask = 0;
  unsigned int flowsync = 0;
  unsigned int clearmask = 0;
  int as = -1; // address space
  uint64_t size = BUF_SIZE;
  uint32_t flows, i, nfe;

  ns_packet_device_h dev;

  ns_log_init(NS_LOG_COLOR | NS_LOG_CONSOLE);
  ns_log_lvl_set(NS_LOG_LVL_INFO);

  int c;
  while ((c = getopt_long(argc, argv, "a:l:h:rfstc", __long_options, NULL)) != -1) {
    switch (c) {
    case 'a':
      as = strtol(optarg,0,0);
      break;
    case 'l':
      ns_log_lvl_set((unsigned int)strtoul(optarg,0,0));
      break;
    case 'r':
      remote_req = 1;
      break;
    case 'f':
      flowmask = 1;
      break;
    case 's':
      syncmask = 1;
      break;
    case 'c':
      clearmask = 1;
      break;
    case 't':
      flowsync = 1;
      break;
    case 'h':
    default:
      print_usage(argv[0]);
    }
  }

  if (optind != argc || argc == 1)
    print_usage(argv[0]);

  buf = calloc(BUF_SIZE, sizeof(unsigned char));
  if (buf == NULL) {
      fprintf(stderr, "Failed to allocate memory\n");
      exit(1);
  }

  ret = ns_flow_ha_open(&h);
  if (ret != NS_NFM_SUCCESS) {
      fprintf(stderr, "Failed to open flow HA handle\n");
      free(buf);
      exit(1);
  }

  if (flowmask) {
    for (nfe = 0; nfe < MAX_NFE; nfe++) {
      bzero(buf, BUF_SIZE * sizeof(unsigned char));
      if (remote_req)
          ret = ns_flow_ha_get_remote_flowmask(h, nfe, as, buf, &size, &flows);
      else
          ret = ns_flow_ha_get_flowmask(h, nfe, as, buf, &size, &flows);

      if (ret != NS_NFM_SUCCESS)
        continue;

      if (as != -1)
        printf("%s%s NFE%u: address space %d, %u flows:\n", (nfe)?"\n":"",
               (remote_req)?"remote":"local", nfe, as, flows);
      else
        printf("%s%s NFE%u: %u flows:\n", (nfe)?"\n":"",
               (remote_req)?"remote":"local", nfe, flows);
      for (i = 0; i < (size * BITS_PER_BYTE); i++) {
        if (buf[i / BITS_PER_BYTE] & (0x1 << (i % BITS_PER_BYTE)))
          printf("NFE%u: Flow ID %u active\n", nfe, i);
      }
    }
  }

  if (syncmask) {
    for (nfe = 0; nfe < MAX_NFE; nfe++) {
      bzero(buf, BUF_SIZE * sizeof(unsigned char));
      if (remote_req)
          ret = ns_flow_ha_get_remote_syncmask(h, nfe, buf, &size);
      else
          ret = ns_flow_ha_get_syncmask(h, nfe, buf, &size);
      if (ret != NS_NFM_SUCCESS)
        continue;

      printf("%s%s NFE%u:\n", (nfe)?"\n":"",(remote_req)?"remote":"local", nfe);
      for (i = 0; i < (size * BITS_PER_BYTE); i++) {
        if (buf[i / BITS_PER_BYTE] & (0x1 << (i % BITS_PER_BYTE)))
          printf("NFE%u: Flow ID %u synced\n", nfe, i);
      }
    }
  }

  if (flowsync) {
    for (nfe = 0; nfe < MAX_NFE; nfe++) {
      bzero(buf, BUF_SIZE * sizeof(unsigned char));
      ret = ns_flow_ha_get_flowmask(h, nfe, as, buf, &size, &flows);
      if (ret != NS_NFM_SUCCESS)
        continue;

      if (as != -1)
        printf("%slocal NFE%u address space %d:\n", (nfe)?"\n":"", nfe, as);
      else
        printf("%slocal NFE%u:\n", (nfe)?"\n":"", nfe);
      ret = ns_packet_open_device(&dev, NFM_CARD_ENDPOINT_ID(nfe, 1, NFM_ANY_ID));
      if (ret!=NS_NFM_SUCCESS) {
        fprintf(stderr, "Failed to open packet device\n");
        continue;
      }

      for (i = 0; i < (size * BITS_PER_BYTE); i++) {
        if (buf[i / BITS_PER_BYTE] & (0x1 << (i % BITS_PER_BYTE))) {
          printf("NFE%u: Sending flow update for flow ID %u \n", nfe, i);
          if (ns_flow_ha_sync_flow(h, &dev, i) != 0)
            fprintf(stderr, "NFE%u: Error sending flow update\n", nfe);
        }
      }

      ns_packet_close_device(dev);
    }
  }

  if (clearmask) {
      for (nfe = 0; nfe < MAX_NFE; nfe++) {
      ret = ns_flow_ha_clear_syncmask(h, nfe);
      if (ret==NS_NFM_SUCCESS)
          printf("Cleared NFE%u syncmask\n", nfe);
      }
  }

  ret = ns_flow_ha_close(&h);
  free(buf);

  return 0;
}
int main(int argc, char *argv[])
{
  ns_rule_handle_h *rh = NULL;
  uint32_t prio = 0,rule_read = 0;
  char *endptr;
  ns_rule_key_size_t key_size = SUPPORTED_TCAM_KEY_SIZE;
  ns_nfm_ret_t ret;
  unsigned int host_id = 15;
  unsigned int device = 0;

  ns_log_init(NS_LOG_COLOR | NS_LOG_CONSOLE);
  ns_log_lvl_set(NS_LOG_LVL_INFO);

  int c;
  while ((c = getopt_long(argc, argv, "l:hi:d:k:rn:", __long_options, NULL)) != -1) {
    switch (c) {
      case 'l':
        ns_log_lvl_set((unsigned int)strtoul(optarg,0,0));
        break;
      case 'i':
        host_id = (unsigned int)strtoul(optarg,0,0);
        if (host_id > 31) {
          fprintf(stderr, "Host_id %d is out of range (0-31)\n", device);
          exit(1);
        }
        break;
      case 'd':
        device = (unsigned int)strtoul(optarg,0,0);
        if (device > 3) {
          fprintf(stderr, "Device %d is out of range (0-3)\n", device);
          exit(1);
        }
        break;
      case 'k':
        key_size = strtoul(optarg, &endptr, 0);
        if (*endptr != '\0') {
          fprintf(stderr, "Invalid keysize %s\n", optarg);
          return 1;
        }
        if (key_size != SUPPORTED_TCAM_KEY_SIZE) {
                                        fprintf(stderr, "Invalid keysize %s, please use " SUPPORTED_TCAM_KEY_SIZE_STR "\n", optarg);
          print_usage(argv[0]);
        }
        break;
      case 'r':
        // Read Rule
        rule_read = 1;
        break;
      case 'n':
        // Rule name to be read or written
        strcpy(rnames, optarg);
        break;
      case 'h':
      default:
        print_usage(argv[0]);
    }
  }

  if (optind != argc)
    print_usage(argv[0]);

  // Init the rules lib
  rh = ns_rules_init(RULESD_Q_NAME, RQNAME, device);
  if (!rh) {
    fprintf(stderr, "ns_rules_init() failed\n");
    return 1;
  }

  if(!rule_read) {
    if (key_size == SUPPORTED_TCAM_KEY_SIZE) {
      /*
       * Reset the configuration.  This is ignored if there was no
       * configuration.  Note that this also flushes the rules from the
       * hardware.
       */
      ret = ns_rules_config_reset(rh);
      if (ret != NS_NFM_SUCCESS) {
        fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
        goto fail;
      }

      // Set the desired lookup key size
      ret = ns_rules_config_set_key_size(rh, key_size);
      if (ret != NS_NFM_SUCCESS) {
        fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
        goto fail;
      }
    }

    // Send config to rulesd
    ret = ns_rules_setup(rh);
    if (ret != NS_NFM_SUCCESS) {
      fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
      goto fail;
    }

    // Add a single rule to send traffic to host.
    // Prepare to add the rule
    //sprintf(rnames[num], "v6sample %d", num);
    ret = add_rule(rh, rnames, prio, SEND_ACTION_VIA_HOST,
        FST_30_MINUTE_LIST_NUM, host_id);
    if (ret != NS_NFM_SUCCESS) {
      fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
      goto fail;
    }

    // Commit
    ret = ns_rule_commit_rulesdb(rh);
    if (ret != NS_NFM_SUCCESS) {
      fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
      goto fail;
    }
  }
  else {

    if(read_rule(rh, rnames)) {
      fprintf(stderr, "failure to read rules @ %s: %d\n", __FILE__, __LINE__);
    }
  }

  // Dump
  ret = ns_rule_dump_rules(rh);
  if (ret != NS_NFM_SUCCESS) {
    fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
    goto fail;
  }

  // Close the rules library.
  ret = ns_rules_close(rh);
  if (ret != NS_NFM_SUCCESS) {
    fprintf(stderr, "failure @ %s: %d\n", __FILE__, __LINE__);
    goto fail;
  }

  return 0;

fail:
  ns_rules_close(rh);
  return 1;
}
int main(int argc, char* argv[])
{
  ns_nfm_ret_t ret;
  ns_log_init(NS_LOG_COLOR | NS_LOG_CONSOLE);
  ns_log_lvl_set(NS_LOG_LVL_INFO);
  unsigned int i, k, t, min, max;
  unsigned int slot, netmod, iface, nm_intfs;
  uint32_t nm_mask;
  uint8_t nm_type;
  const char *nm_name;

  int c;
  while ((c = getopt_long(argc, argv, "l:d:h", __long_options, NULL)) != -1) {
    switch (c) {
    case 'l':
      ns_log_lvl_set((unsigned int)strtoul(optarg,0,0));
      break;
    case 'h':
    default:
      print_usage(argv[0]);
    }
  }

  if (optind != argc)
    print_usage(argv[0]);

  ret = nfm_get_nfes_present(&k);
  CKRET(ret, "Error getting # of NFEs present");
  printf("%u NFEs present\n", k);

  ret = nfm_get_nmsbs_present(&k);
  CKRET(ret, "Error getting # of NMSBs present");
  printf("%u NMSBs present\n", k);
  if ( k < 1 ) { // No NMSB: geryon by now
      min = max = 1;
      ret = nfm_get_external_min_port(&min);
      CKRET(ret, "Error getting external minimum port");
      
      ret = nfm_get_external_max_port(&max);
      CKRET(ret, "Error getting external maximum port");
      
      printf("Port list\n");
      
      printf("%16s%16s\n", "Port", "Hardware ID");
      for (i = min; i <= max; i++) {
	  ret = nfm_get_internal_port_from_external(i, &k);
	  CKRET(ret, "Error converting external port # to internal");
	  
	  printf("%16u%16u\n", i, k);
	  /* sanity check */
	  ret = nfm_get_external_port_from_internal(k, &t);
	  CKRET(ret, "Error converting internal port # to external");
	  if (t != i)
	      NS_LOG_ERROR("Error conversion ext -> int -> ext "
			   "produced %u -> %u -> %u", i, k, t);
      }
  }
  else { // NMSB: cayenne
      ret = nfm_get_netmods_present(&nm_mask);
      CKRET(ret, "Error getting # of netmods present");
      ret = nfm_get_min_netmod(&min);
      CKRET(ret, "Error getting minimum netmod");
      ret = nfm_get_max_netmod(&max);
      CKRET(ret, "Error getting maximum netmod");

      /* Enumerate the Installed Netmods */
      printf("netmods present (mask=%#x, %u - %u):\n", nm_mask, min, max);
      printf("%16s%16s%16s%16s\n",
	     "Netmod", "Slot ID", "Netmod Type", "# Interfaces");
      while (1) {
	  slot = ffs(nm_mask);
	  if (!slot)
	      break;
	  slot = slot - 1; /* ffs() count bits starting at 1. We don't */
	  nm_mask &= ~(1 << slot);
	  ret = nfm_get_nmsb_attached_card(slot, &nm_type);
	  CKRET(ret, "Error getting card type");
	  ret = nfm_get_nmsb_card_intfs(slot, &nm_intfs);
	  CKRET(ret, "Error getting number of interfaces");
	  ret = nfm_get_nmsb_card_name(slot, &nm_name);
	  CKRET(ret, "Error getting card name");
	  printf("%16s%16u%16u%16u\n", nm_name, slot, nm_type, nm_intfs);
      }
      printf("\n");

      /* Enumerate the ports */
      ret = nfm_get_external_min_port(&min);
      CKRET(ret, "Error getting external minimum port");
      ret = nfm_get_external_max_port(&max);
      CKRET(ret, "Error getting external maximum port");

      printf("Port list\n");
      printf("%16s%16s%16s%16s\n", "Port", "Hardware ID", "Netmod", "NM Interface");
      for (i = min; i <= max; i++) {
	  ret = nfm_get_internal_port_from_external(i, &k);
	  CKRET(ret, "Error converting external port # to internal");
	  ret = nfm_get_slot_from_external(i, &netmod, &iface);
	  CKRET(ret, "Error converting external port # to netmod pair");
	  ret = nfm_get_nmsb_card_name(netmod, &nm_name);
	  CKRET(ret, "Error getting card name");
	  printf("%16u%16u%16s%16u\n", i, k, nm_name, iface);
	  /* sanity check */
	  ret = nfm_get_external_port_from_internal(k, &t);
	  CKRET(ret, "Error converting internal port # to external");
	  if (t != i)
	      NS_LOG_ERROR("Error conversion ext -> int -> ext "
			   "produced %u -> %u -> %u", i, k, t);
      }
  }
  printf("\n");

  return 0;
}