Example #1
0
static void
do_usage(int exitcode)
{
	printf("Usage: relay [-vdst] -f <config> [-p <port>] [-w <workers>] [-b <size>] [-q <size>]\n");
	printf("\n");
	printf("Options:\n");
	printf("  -v  print version and exit\n");
	printf("  -f  read <config> for clusters and routes\n");
	printf("  -p  listen on <port> for connections, defaults to 2003\n");
	printf("  -i  listen on <interface> for connections, defaults to all\n");
	printf("  -l  write output to <file>, defaults to stdout/stderr\n");
	printf("  -w  use <workers> worker threads, defaults to %d\n", get_cores());
	printf("  -b  server send batch size, defaults to 2500\n");
	printf("  -q  server queue size, defaults to 25000\n");
	printf("  -S  statistics sending interval in seconds, defaults to 60\n");
	printf("  -m  send statistics like carbon-cache.py, e.g. not cumulative\n");
	printf("  -c  characters to allow next to [A-Za-z0-9], defaults to -_:#\n");
	printf("  -d  debug mode: currently writes statistics to log, prints hash\n"
	       "      ring contents and matching position in test mode (-t)\n");
	printf("  -s  submission mode: don't add any metrics to the stream like\n"
	       "      statistics, report drop counts and queue pressure to log\n");
	printf("  -t  config test mode: prints rule matches from input on stdin\n");
	printf("  -H  hostname: override hostname (used in statistics)\n");

	exit(exitcode);
}
Example #2
0
int
main(int argc, char * const argv[])
{
	int stream_sock[] = {0, 0, 0};  /* tcp4, tcp6, UNIX */
	int stream_socklen = sizeof(stream_sock) / sizeof(stream_sock[0]);
	int dgram_sock[] = {0, 0};  /* udp4, udp6 */
	int dgram_socklen = sizeof(dgram_sock) / sizeof(dgram_sock[0]);
	char id;
	unsigned short listenport = 2003;
	int ch;
	size_t numaggregators;
	size_t numcomputes;
	server *internal_submission;
	char *listeninterface = NULL;
	server **servers;
	char *allowed_chars = NULL;
	int i;
	enum { SUB, CUM } smode = CUM;

	if (gethostname(relay_hostname, sizeof(relay_hostname)) < 0)
		snprintf(relay_hostname, sizeof(relay_hostname), "127.0.0.1");

	while ((ch = getopt(argc, argv, ":hvdmstf:i:l:p:w:b:q:S:c:H:")) != -1) {
		switch (ch) {
			case 'v':
				do_version();
				break;
			case 'd':
				if (mode == TEST) {
					mode = DEBUGTEST;
				} else {
					mode = DEBUG;
				}
				break;
			case 'm':
				smode = SUB;
				break;
			case 's':
				mode = SUBMISSION;
				break;
			case 't':
				if (mode == DEBUG) {
					mode = DEBUGTEST;
				} else {
					mode = TEST;
				}
				break;
			case 'f':
				config = optarg;
				break;
			case 'i':
				listeninterface = optarg;
				break;
			case 'l':
				relay_logfile = optarg;
				break;
			case 'p':
				listenport = (unsigned short)atoi(optarg);
				if (listenport == 0) {
					fprintf(stderr, "error: port needs to be a number >0\n");
					do_usage(1);
				}
				break;
			case 'w':
				workercnt = (char)atoi(optarg);
				if (workercnt <= 0) {
					fprintf(stderr, "error: workers needs to be a number >0\n");
					do_usage(1);
				}
				break;
			case 'b':
				batchsize = atoi(optarg);
				if (batchsize <= 0) {
					fprintf(stderr, "error: batch size needs to be a number >0\n");
					do_usage(1);
				}
				break;
			case 'q':
				queuesize = atoi(optarg);
				if (queuesize <= 0) {
					fprintf(stderr, "error: queue size needs to be a number >0\n");
					do_usage(1);
				}
				break;
			case 'S':
				collector_interval = atoi(optarg);
				if (collector_interval <= 0) {
					fprintf(stderr, "error: sending interval needs to be "
							"a number >0\n");
					do_usage(1);
				}
				break;
			case 'c':
				allowed_chars = optarg;
				break;
			case 'H':
				snprintf(relay_hostname, sizeof(relay_hostname), "%s", optarg);
				break;
			case '?':
			case ':':
				do_usage(1);
				break;
			case 'h':
			default:
				do_usage(0);
				break;
		}
	}
	if (optind == 1 || config == NULL)
		do_usage(1);


	/* seed randomiser for dispatcher and aggregator "splay" */
	srand(time(NULL));

	if (workercnt == 0)
		workercnt = mode == SUBMISSION ? 2 : get_cores();

	/* any_of failover maths need batchsize to be smaller than queuesize */
	if (batchsize > queuesize) {
		fprintf(stderr, "error: batchsize must be smaller than queuesize\n");
		exit(-1);
	}

	if (relay_logfile != NULL && mode != TEST && mode != DEBUGTEST) {
		FILE *f = fopen(relay_logfile, "a");
		if (f == NULL) {
			fprintf(stderr, "error: failed to open logfile '%s': %s\n",
					relay_logfile, strerror(errno));
			exit(-1);
		}
		relay_stdout = f;
		relay_stderr = f;
	} else {
		relay_stdout = stdout;
		relay_stderr = stderr;
	}
	relay_can_log = 1;

	logout("starting carbon-c-relay v%s (%s), pid=%d\n",
			VERSION, GIT_VERSION, getpid());
	fprintf(relay_stdout, "configuration:\n");
	fprintf(relay_stdout, "    relay hostname = %s\n", relay_hostname);
	fprintf(relay_stdout, "    listen port = %u\n", listenport);
	if (listeninterface != NULL)
		fprintf(relay_stdout, "    listen interface = %s\n", listeninterface);
	fprintf(relay_stdout, "    workers = %d\n", workercnt);
	fprintf(relay_stdout, "    send batch size = %d\n", batchsize);
	fprintf(relay_stdout, "    server queue size = %d\n", queuesize);
	fprintf(relay_stdout, "    statistics submission interval = %ds\n",
			collector_interval);
	if (allowed_chars != NULL)
		fprintf(relay_stdout, "    extra allowed characters = %s\n",
				allowed_chars);
	if (mode == DEBUG || mode == DEBUGTEST)
		fprintf(relay_stdout, "    debug = true\n");
	else if (mode == SUBMISSION)
		fprintf(relay_stdout, "    submission = true\n");
	fprintf(relay_stdout, "    routes configuration = %s\n", config);
	fprintf(relay_stdout, "\n");

	if (router_readconfig(&clusters, &routes,
				config, queuesize, batchsize) == 0)
	{
		logerr("failed to read configuration '%s'\n", config);
		return 1;
	}
	router_optimise(&routes);

	numaggregators = aggregator_numaggregators();
	numcomputes = aggregator_numcomputes();
#define dbg (mode == DEBUG || mode == DEBUGTEST ? 2 : 0)
	if (numaggregators > 10 && !dbg) {
		fprintf(relay_stdout, "parsed configuration follows:\n"
				"(%zd aggregations with %zd computations omitted "
				"for brevity)\n", numaggregators, numcomputes);
		router_printconfig(relay_stdout, 0, clusters, routes);
	} else {
		fprintf(relay_stdout, "parsed configuration follows:\n");
		router_printconfig(relay_stdout, 1 + dbg, clusters, routes);
	}
	fprintf(relay_stdout, "\n");

	/* shortcut for rule testing mode */
	if (mode == TEST || mode == DEBUGTEST) {
		char metricbuf[METRIC_BUFSIZ];
		char *p;

		fflush(relay_stdout);
		while (fgets(metricbuf, sizeof(metricbuf), stdin) != NULL) {
			if ((p = strchr(metricbuf, '\n')) != NULL)
				*p = '\0';
			router_test(metricbuf, routes);
		}

		exit(0);
	}

	if (signal(SIGINT, exit_handler) == SIG_ERR) {
		logerr("failed to create SIGINT handler: %s\n", strerror(errno));
		return 1;
	}
	if (signal(SIGTERM, exit_handler) == SIG_ERR) {
		logerr("failed to create SIGTERM handler: %s\n", strerror(errno));
		return 1;
	}
	if (signal(SIGQUIT, exit_handler) == SIG_ERR) {
		logerr("failed to create SIGQUIT handler: %s\n", strerror(errno));
		return 1;
	}
	if (signal(SIGHUP, hup_handler) == SIG_ERR) {
		logerr("failed to create SIGHUP handler: %s\n", strerror(errno));
		return 1;
	}
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
		logerr("failed to ignore SIGPIPE: %s\n", strerror(errno));
		return 1;
	}

	workers = malloc(sizeof(dispatcher *) * (1 + workercnt + 1));
	if (workers == NULL) {
		logerr("failed to allocate memory for workers\n");
		return 1;
	}

	if (bindlisten(stream_sock, &stream_socklen,
				dgram_sock, &dgram_socklen,
				listeninterface, listenport) < 0) {
		logerr("failed to bind on port %s:%d: %s\n",
				listeninterface == NULL ? "" : listeninterface,
				listenport, strerror(errno));
		return -1;
	}
	for (ch = 0; ch < stream_socklen; ch++) {
		if (dispatch_addlistener(stream_sock[ch]) != 0) {
			logerr("failed to add listener\n");
			return -1;
		}
	}
	for (ch = 0; ch < dgram_socklen; ch++) {
		if (dispatch_addlistener_udp(dgram_sock[ch]) != 0) {
			logerr("failed to listen to datagram socket\n");
			return -1;
		}
	}
	if ((workers[0] = dispatch_new_listener()) == NULL)
		logerr("failed to add listener\n");

	if (allowed_chars == NULL)
		allowed_chars = "-_:#";
	logout("starting %d workers\n", workercnt);
	for (id = 1; id < 1 + workercnt; id++) {
		workers[id + 0] = dispatch_new_connection(routes, allowed_chars);
		if (workers[id + 0] == NULL) {
			logerr("failed to add worker %d\n", id);
			break;
		}
	}
	workers[id + 0] = NULL;
	if (id < 1 + workercnt) {
		logerr("shutting down due to errors\n");
		keep_running = 0;
	}

	/* server used for delivering metrics produced inside the relay,
	 * that is collector (statistics) and aggregator (aggregations) */
	if ((internal_submission = server_new("internal", listenport, CON_PIPE,
					NULL, 3000 + (numcomputes * 3), batchsize)) == NULL)
	{
		logerr("failed to create internal submission queue, shutting down\n");
		keep_running = 0;
	}

	if (numaggregators > 0) {
		logout("starting aggregator\n");
		if (!aggregator_start(internal_submission)) {
			logerr("shutting down due to failure to start aggregator\n");
			keep_running = 0;
		}
	}

	logout("starting statistics collector\n");
	collector_start(&workers[1], clusters, internal_submission, smode == CUM);

	logout("startup sequence complete\n");

	/* workers do the work, just wait */
	while (keep_running)
		sleep(1);

	logout("shutting down...\n");
	/* make sure we don't accept anything new anymore */
	for (ch = 0; ch < stream_socklen; ch++)
		dispatch_removelistener(stream_sock[ch]);
	destroy_usock(listenport);
	logout("listeners for port %u closed\n", listenport);
	/* since workers will be freed, stop querying the structures */
	collector_stop();
	logout("collector stopped\n");
	if (numaggregators > 0) {
		aggregator_stop();
		logout("aggregator stopped\n");
	}
	server_shutdown(internal_submission);
	/* give a little time for whatever the collector/aggregator wrote,
	 * to be delivered by the dispatchers */
	usleep(500 * 1000);  /* 500ms */
	/* make sure we don't write to our servers any more */
	logout("stopped worker");
	for (id = 0; id < 1 + workercnt; id++)
		dispatch_stop(workers[id + 0]);
	for (id = 0; id < 1 + workercnt; id++) {
		dispatch_shutdown(workers[id + 0]);
		fprintf(relay_stdout, " %d", id + 1);
		fflush(relay_stdout);
	}
	fprintf(relay_stdout, "\n");
	router_shutdown();
	servers = router_getservers(clusters);
	logout("stopped server");
	for (i = 0; servers[i] != NULL; i++)
		server_stop(servers[i]);
	for (i = 0; servers[i] != NULL; i++) {
		server_shutdown(servers[i]);
		fprintf(relay_stdout, " %d", i + 1);
		fflush(relay_stdout);
	}
	fprintf(relay_stdout, "\n");
	logout("routing stopped\n");

	router_free(clusters, routes);
	free(workers);
	return 0;
}
Example #3
0
static int
create_type9(RECORD **anrecord, struct finger_view_minutiae_record *fvmr, 
	     unsigned int idc)
{
	FIELD *field = NULL;
	SUBFIELD *subfield = NULL;
	ITEM *item = NULL;
	RECORD *lrecord;	// For local convenience
	struct finger_minutiae_data **fmds = NULL;
	struct ridge_count_data **rcds = NULL;
	struct core_data **cds;
	struct delta_data **dds;
	char buf[16];
	int mincnt, minidx, rdgcnt;
	int cnt, i;
	unsigned int x, y; 

	if (new_ANSI_NIST_record(anrecord, TYPE_9_ID) != 0) 
		ALLOC_ERR_EXIT("Type-9 Record");

	lrecord = *anrecord;

	/*** 9.001 - Length                                    ***/ 
	// Set to 0 now, will recalculate later
	APPEND_TYPE9_FIELD(lrecord, LEN_ID, "0");

	/*** 9.002 - IDC value                                 ***/ 
	snprintf(buf, sizeof(buf), IDC_FMT, idc);
	APPEND_TYPE9_FIELD(lrecord, IDC_ID, buf);

	/*** 9.003 - Impression type                           ***/ 
	CRW(fvmr->impression_type, MIN_TABLE_5_CODE, MAX_TABLE_5_CODE,
		"Impression type");
	snprintf(buf, sizeof(buf), "%d", fvmr->impression_type);
	APPEND_TYPE9_FIELD(lrecord, IMP_ID, buf);

	/*** 9.004 - Minutiae format                           ***/
	APPEND_TYPE9_FIELD(lrecord, FMT_ID, STD_STR);

	/*** 9.005 - Originating fingerprint reading system    ***/
	if (value2subfield(&subfield, "EXISTING IMAGE") != 0)
		ERR_OUT("creating Type-9 subfield");
	if (value2item(&item, AUTO_STR) != 0)
		ERR_OUT("creating Type-9 item");
	if (append_ANSI_NIST_subfield(subfield, item) != 0)
		ERR_OUT("appending Type-9 item");
	if (new_ANSI_NIST_field(&field, TYPE_9_ID, OFR_ID) != 0)
		ERR_OUT("creating Type-9 field");
	if (append_ANSI_NIST_field(field, subfield) != 0)
		ERR_OUT("appending Type-9 subfield");
	if (append_ANSI_NIST_record(lrecord, field) != 0)
		ERR_OUT("appending Type-9 field");

	/*** 9.006 - Finger position                           ***/ 
	snprintf(buf, sizeof(buf), "%02d", fvmr->finger_number);
	APPEND_TYPE9_FIELD(lrecord, FGP2_ID, buf);

	/*** 9.007 - Fingerprint pattern classification        ***/ 
	if (value2subfield(&subfield, TBL_STR) != 0)
		ERR_OUT("creating Type-9 subfield");
	if (value2item(&item, "UN") != 0)
		ERR_OUT("creating Type-9 item");
	if (append_ANSI_NIST_subfield(subfield, item) != 0)
		ERR_OUT("appending Type-9 item");
	if (new_ANSI_NIST_field(&field, TYPE_9_ID, FPC_ID) != 0)
		ERR_OUT("creating Type-9 field");
	if (append_ANSI_NIST_field(field, subfield) != 0)
		ERR_OUT("appending Type-9 subfield");
	if (append_ANSI_NIST_record(lrecord, field) != 0)
		ERR_OUT("appending Type-9 field");

	/*** 9.008 - Core position                             ***/ 
	cnt = get_core_count(fvmr);
	if (cnt > 0) {
		if (new_ANSI_NIST_field(&field, TYPE_9_ID, CRP_ID) != 0)
			ERR_OUT("allocating field");

		cds = (struct core_data **) malloc(
			cnt * sizeof(struct core_data **));
		if (cds == NULL)
			ALLOC_ERR_EXIT("Core data");

		if (get_cores(fvmr, cds) != cnt)
			ERR_OUT("retrieving core data");

		for (i = 0; i < cnt; i++) {
			convert_xy(fvmr->fmr->x_image_size, 
				   fvmr->fmr->y_image_size,
				   fvmr->fmr->x_resolution,
				   fvmr->fmr->y_resolution,
				   cds[i]->x_coord, 
				   cds[i]->y_coord, 
				   &x, &y);
			snprintf(buf, sizeof(buf), "%04u%04u", x, y);
			if (value2subfield(&subfield, buf) != 0)
				ERR_OUT("creating subfield");
			if (append_ANSI_NIST_field(field, subfield) != 0)
				ERR_OUT("appending subfield");
		}
		if (append_ANSI_NIST_record(lrecord, field) != 0)
			ERR_OUT("adding field to record");

	} else if (cnt < 0)
		ERR_OUT("getting core record count");

	/*** 9.009 - Delta(s) position                         ***/ 
	cnt = get_delta_count(fvmr);
	if (cnt > 0) {
		if (new_ANSI_NIST_field(&field, TYPE_9_ID, DLT_ID) != 0)
			ERR_OUT("creating Type-9 field");

		dds = (struct delta_data **) malloc(
			cnt * sizeof(struct delta_data **));
		if (dds == NULL)
			ALLOC_ERR_EXIT("Delta data");

		if (get_deltas(fvmr, dds) != cnt)
			ERR_OUT("retrieving delta data");

		for (i = 0; i < cnt; i++) {
			convert_xy(fvmr->fmr->x_image_size, 
				   fvmr->fmr->y_image_size,
				   fvmr->fmr->x_resolution,
				   fvmr->fmr->y_resolution,
				   dds[i]->x_coord, 
				   dds[i]->y_coord, 
				   &x, &y);
			snprintf(buf, sizeof(buf), "%04u%04u", x, y);
			if (value2subfield(&subfield, buf) != 0)
				ERR_OUT("creating subfield");
			if (append_ANSI_NIST_field(field, subfield) != 0)
				ERR_OUT("appending subfield");
		}
		if (append_ANSI_NIST_record(lrecord, field) != 0)
			ERR_OUT("adding field to record");

	} else if (cnt < 0)
		ERR_OUT("getting delta record count");

	/*** 9.010 - Number of minutiae                        ***/ 
	mincnt = get_fmd_count(fvmr);
	if (mincnt < 0)
		ERR_OUT("getting minutiae count");

	snprintf(buf, sizeof(buf), "%d", mincnt);
	APPEND_TYPE9_FIELD(lrecord, MIN_ID, buf);

	/*** 9.011 - Minutiae ridge count indicator            ***/ 
	rdgcnt = get_rcd_count(fvmr);
	if (rdgcnt > 0) {
		rcds = (struct ridge_count_data **) malloc(
			rdgcnt * sizeof(struct ridge_count_data **));
		if (rcds == NULL)
			ALLOC_ERR_EXIT("Ridge Count data");

		if (get_rcds(fvmr, rcds) != rdgcnt)
			ERR_OUT("retrieving ridge count data");

		APPEND_TYPE9_FIELD(lrecord, RDG_ID, "1");
	} else if (rdgcnt < 0)
		ERR_OUT("getting ridge record count");
	else
		APPEND_TYPE9_FIELD(lrecord, RDG_ID, "0");

	/*** 9.012 - Minutiae and ridge count data             ***/ 
	fmds = (struct finger_minutiae_data **) malloc(
		mincnt * sizeof(struct finger_minutiae_data **));
	if (fmds == NULL)
		ALLOC_ERR_EXIT("Finger Minutiae data");

	if (get_fmds(fvmr, fmds) != mincnt)
		ERR_OUT("retrieving minutiae data");

	if (new_ANSI_NIST_field(&field, TYPE_9_ID, MRC_ID) != 0)
		ERR_OUT("creating Type-9 field");

	for (minidx = 0; minidx < mincnt; minidx++) {
		unsigned int theta, rdgidx, minqual;
		char mintype;
		int idxnum = minidx + 1;

		// Index number
		snprintf(buf, sizeof(buf), "%03d", idxnum);
		if (value2subfield(&subfield, buf) != 0)
			ERR_OUT("creating Type-9 subfield");

		// X, Y, and theta values
		convert_xy(fvmr->fmr->x_image_size, fvmr->fmr->y_image_size,
			   fvmr->fmr->x_resolution, fvmr->fmr->y_resolution,
			   fmds[minidx]->x_coord, fmds[minidx]->y_coord, 
			   &x, &y);
		convert_theta(fmds[minidx]->angle, &theta);
		snprintf(buf, sizeof(buf), "%04u%04u%03u", x, y, theta);
		if (value2item(&item, buf) != 0)
			ERR_OUT("creating Type-9 item");
		if (append_ANSI_NIST_subfield(subfield, item) != 0)
			ERR_OUT("appending Type-9 item");

		// Quality measure
		convert_quality(fmds[minidx]->quality, &minqual);
		snprintf(buf, sizeof(buf), "%u", minqual);
		if (value2item(&item, buf) != 0)
			ERR_OUT("creating Type-9 item");
		if (append_ANSI_NIST_subfield(subfield, item) != 0)
			ERR_OUT("appending Type-9 item");

		// Minutia type designation
		convert_type(fmds[minidx]->type, &mintype);
		snprintf(buf, sizeof(buf), "%c", mintype);
		if (value2item(&item, buf) != 0)
			ERR_OUT("creating Type-9 item");
		if (append_ANSI_NIST_subfield(subfield, item) != 0)
			ERR_OUT("appending Type-9 item");

		// Ridge count data: If the one of the index numbers
		// in the record matches the minutia index, then add that
		// ridge count data to the Type-9 record, using the index
		// number that is the 'other'.
		for (rdgidx = 0; rdgidx < rdgcnt; rdgidx++) {
		    if ((rcds[rdgidx]->index_one == idxnum) ||
			(rcds[rdgidx]->index_two == idxnum)) {
			    snprintf(buf, sizeof(buf), "%u,%u", 
				(rcds[rdgidx]->index_one == idxnum) ?
			 	rcds[rdgidx]->index_two :
				rcds[rdgidx]->index_one,
				rcds[rdgidx]->count);

			    if (value2item(&item, buf) != 0)
					ERR_OUT("creating Type-9 item");
			    if (append_ANSI_NIST_subfield(subfield, item) != 0)
					ERR_OUT("appending Type-9 item");
		    }
		}

		if (append_ANSI_NIST_field(field, subfield) != 0)
			ERR_OUT("appending Type-9 subfield");
	}
	free(fmds);
	if (append_ANSI_NIST_record(lrecord, field) != 0)
		ERR_OUT("appending Type-9 field");
	/*** End of minutiae and ridge count                 */

	// Calculate and update the record length field
	if (update_ANSI_NIST_tagged_record_LEN(lrecord) != 0)
		ERR_OUT("updating Type-9 record length");

	return 0;

err_out:
	fprintf(stderr, "Error creating Type-9 record\n");
	if (item != NULL)
		free_ANSI_NIST_item(item);
	if (subfield != NULL)
		free_ANSI_NIST_subfield(subfield);
	if (field != NULL)
		free_ANSI_NIST_field(field);
	if (lrecord != NULL)
		free_ANSI_NIST_record(lrecord);
	if (fmds != NULL)
		free(fmds);

	return -1;
}
Example #4
0
int parse_options(int ch, char *a[]) {

  // clear the options structure
  bzero(&options, sizeof(options));

/*
  options.packets_to_collect = -1;
  options.bpf_filter[0] = '\0';
  options.interface[0] = '\0';
  options.verbose = 0;
  options.output_filename[0] = '\0';
  options.fp = stdout;
*/


  int c;

  while (1) {

    static struct option long_options[] = {
        /* These options set a flag. */
        {"verbose", no_argument, &(options.verbose), 1},
        {"brief", no_argument, &(options.verbose), 0},
        /* These options don’t set a flag. We distinguish them by their
           indices. */
        {"interface", required_argument, 0, 'i'},
        {"bpf", required_argument, 0, 'b'},
        {"packets", required_argument, 0, 'p'},
        {"help", no_argument, 0, 'h'},
        {"filename", required_argument, 0, 'f'},
        {"mqtthost", required_argument, 0, 'm'},
        {"mqttport", required_argument, 0, 'q'},
        {0, 0, 0, 0}};

    int option_index = 0;
    c = getopt_long(ch, a, "vbi:b:p:hf:m:q:", long_options, &option_index);
    if (c == -1)
      break;

    switch (c) {

    case 0:
      if (long_options[option_index].flag != 0)
        break;
      printf("option %s", long_options[option_index].name);
      if (optarg)
        printf(" with arg %s", optarg);
      printf("\n");
      break;

    case 'i':
      // printf ("option -i with value `%s'\n", optarg);
      strncpy(options.interface, optarg, DEFAULT_OPT_STRING_LEN-1);
      break;

    case 'p':
      options.packets_to_collect = atoi(optarg);
      break;

    case 'b':
      strncpy(options.bpf_filter, optarg, DEFAULT_OPT_STRING_LEN-1);
      break;

    case 'f':
      strncpy(options.output_filename, optarg, DEFAULT_OPT_STRING_LEN-1);
      struct stat st;
      stat(options.output_filename, &st);
      if (st.st_mode & S_IWUSR) {
        options.fp = fopen(options.output_filename, "a");
      }
      break;

    case 'h':
      usage();
      return -1;
      break;

    case 'm':
      strncpy(options.mqtt_host, optarg, DEFAULT_OPT_STRING_LEN-1);
      break;

    case 'q':
      options.mqtt_port = atoi(optarg);
      break;

    default:
      break;
    }
  }

  // Deal with the default options

  if (options.interface[0] == '\0') {
    syslog(LOG_ERR, "[Options] No interface specified");
    usage();
    return -1;
  }

  if (options.bpf_filter[0] == '\0') {
    strncpy(options.bpf_filter, DEFAULT_FILTER, strlen(DEFAULT_FILTER));
  }

  if (options.mqtt_host[0] == '\0') {
    strncpy(options.mqtt_host, DEFAULT_MQTT_HOST, strlen(DEFAULT_MQTT_HOST));
  }

  if (options.mqtt_port == 0) {
    options.mqtt_port = DEFAULT_MQTT_PORT;
  }

  if (options.fp == 0) {
    options.fp = stdout;
  }

  options.cores = get_cores();

  show_options();

  return 1;
}