Beispiel #1
0
celix_status_t filter_match(filter_pt filter, properties_pt properties, bool *result) {
	switch (filter->operand) {
		case AND: {
			array_list_pt filters = (array_list_pt) filter->value;
			unsigned int i;
			for (i = 0; i < arrayList_size(filters); i++) {
				filter_pt sfilter = (filter_pt) arrayList_get(filters, i);
				bool mresult;
				filter_match(sfilter, properties, &mresult);
				if (!mresult) {
					*result = 0;
					return CELIX_SUCCESS;
				}
			}
			*result = 1;
			return CELIX_SUCCESS;
		}
		case OR: {
			array_list_pt filters = (array_list_pt) filter->value;
			unsigned int i;
			for (i = 0; i < arrayList_size(filters); i++) {
				filter_pt sfilter = (filter_pt) arrayList_get(filters, i);
				bool mresult;
				filter_match(sfilter, properties, &mresult);
				if (mresult) {
					*result = 1;
					return CELIX_SUCCESS;
				}
			}
			*result = 0;
			return CELIX_SUCCESS;
		}
		case NOT: {
			filter_pt sfilter = (filter_pt) filter->value;
			bool mresult;
			filter_match(sfilter, properties, &mresult);
			*result = !mresult;
			return CELIX_SUCCESS;
		}
		case SUBSTRING :
		case EQUAL :
		case GREATER :
        case GREATEREQUAL :
		case LESS :
        case LESSEQUAL :
		case APPROX : {
			char * value = (properties == NULL) ? NULL: (char*)properties_get(properties, filter->attribute);

			return filter_compare(filter->operand, value, filter->value, result);
		}
		case PRESENT: {
			char * value = (properties == NULL) ? NULL: (char*)properties_get(properties, filter->attribute);
			*result = value != NULL;
			return CELIX_SUCCESS;
		}
	}
	*result = 0;
	return CELIX_SUCCESS;
}
Beispiel #2
0
celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, bundle_pt owner, const char *serviceName, filter_pt filter, array_list_pt *references) {
	celix_status_t status = CELIX_SUCCESS;
	hash_map_values_pt registrations;
	hash_map_iterator_pt iterator;
	arrayList_create(references);

	celixThreadMutex_lock(&registry->mutex);
	registrations = hashMapValues_create(registry->serviceRegistrations);
	iterator = hashMapValues_iterator(registrations);
	while (hashMapIterator_hasNext(iterator)) {
		array_list_pt regs = (array_list_pt) hashMapIterator_nextValue(iterator);
		unsigned int regIdx;
		for (regIdx = 0; (regs != NULL) && regIdx < arrayList_size(regs); regIdx++) {
			service_registration_pt registration = (service_registration_pt) arrayList_get(regs, regIdx);
			properties_pt props = NULL;

			status = serviceRegistration_getProperties(registration, &props);
			if (status == CELIX_SUCCESS) {
				bool matched = false;
				bool matchResult = false;
				if (filter != NULL) {
					filter_match(filter, props, &matchResult);
				}
				if ((serviceName == NULL) && ((filter == NULL) || matchResult)) {
					matched = true;
				} else if (serviceName != NULL) {
					char *className = NULL;
					bool matchResult = false;
					serviceRegistration_getServiceName(registration, &className);
					if (filter != NULL) {
						filter_match(filter, props, &matchResult);
					}
					if ((strcmp(className, serviceName) == 0) && ((filter == NULL) || matchResult)) {
						matched = true;
					}
				}
				if (matched) {
					if (serviceRegistration_isValid(registration)) {
						service_reference_pt reference = NULL;
						serviceRegistry_createServiceReference(registry, owner, registration, &reference);
						arrayList_add(*references, reference);
					}
				}
			}
		}
	}
	hashMapIterator_destroy(iterator);
	hashMapValues_destroy(registrations);
	celixThreadMutex_unlock(&registry->mutex);

	framework_logIfError(logger, status, NULL, "Cannot get service references");

	return status;
}
Beispiel #3
0
TEST(filter, match_false){
	char * filter_str = my_strdup("(&(test_attr1=attr1)(&(test_attr2=attr2)(test_attr3=attr3)))");
	filter_pt filter = filter_create(filter_str);
	properties_pt props = properties_create();
	char * key = my_strdup("test_attr1");
	char * val = my_strdup("attr1");
	char * key2 = my_strdup("test_attr2");
	char * val2 = my_strdup("attr2");
	properties_set(props, key, val);
	properties_set(props, key2, val2);

	bool result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//cleanup
	properties_destroy(props);
	filter_destroy(filter);
	free(filter_str);
	free(key);
	free(key2);
	free(val);
	free(val2);

	mock().checkExpectations();
}
Beispiel #4
0
short
filter_evaluate(struct intercept_tlq *tls, struct filterq *fls,
    struct intercept_pid *icpid)
{
	struct filter *filter, *last = NULL;
	short action;

	TAILQ_FOREACH(filter, fls, next) {
		action = filter->match_action;

		if (filter_predicate(icpid, &filter->match_predicate) &&
		    filter_match(icpid, tls, filter->logicroot)) {
			/* Profile feedback optimization */
			filter->match_count++;
			if (last != NULL && last->match_action == action &&
			    last->match_flags == filter->match_flags &&
			    filter->match_count > last->match_count) {
				TAILQ_REMOVE(fls, last, next);
				TAILQ_INSERT_AFTER(fls, filter, last, next);
			}

			if (action == ICPOLICY_NEVER)
				action = filter->match_error;
			icpid->uflags = filter->match_flags;

			/* Policy requests privilege elevation */
			if (filter->elevate.e_flags)
				icpid->elevate = &filter->elevate;
			return (action);
		}

		/* Keep track of last processed filtered in a group */
		last = filter;
	}
Beispiel #5
0
/**
 * find a client 
 */ 
p_client next_client_by_message(p_client client, char *message) {
	
	static int oldclient = 0;
	
	// return to start if client is null
	if (client == 0) {
		oldclient =0;
	}
	
	p_client check = get_client_idx(oldclient);
	// if some unknown client is given, find it.
	if (client != check) {
		oldclient = find_client_idx(client);
	} 
	
	// check next client
	oldclient++;
	if ( oldclient < count_clients()) {
		// if it matches the message, return it 
		check = get_client_idx(oldclient);
		if (filter_match(check, message)) {
			return check;
		} 
		
		// else check next client
		return next_client_by_message(check, message);
	}
	return 0;
}
celix_status_t wiringTopologyManager_wiringEndpointListenerAdded(void* handle, service_reference_pt reference, void* service) {
    celix_status_t status = CELIX_SUCCESS;
    wiring_topology_manager_pt manager = handle;
    char *scope = NULL;
    char* wtm = NULL;

    serviceReference_getProperty(reference, (char *) INAETICS_WIRING_ENDPOINT_LISTENER_SCOPE, &scope);
    serviceReference_getProperty(reference, "WTM", &wtm);

    if (wtm != NULL && strcmp(wtm, "true") == 0) {
        printf("WTM: Ignoring own ENDPOINT_LISTENER\n");
    }
    else {
        status = celixThreadMutex_lock(&manager->listenerListLock);

        if (status == CELIX_SUCCESS) {
            hashMap_put(manager->listenerList, reference, NULL);
            celixThreadMutex_unlock(&manager->listenerListLock);
        }

        filter_pt filter = filter_create(scope);
        status = celixThreadMutex_lock(&manager->exportedWiringEndpointsLock);

        if (status == CELIX_SUCCESS) {
            hash_map_iterator_pt propIter = hashMapIterator_create(manager->exportedWiringEndpoints);

            while (hashMapIterator_hasNext(propIter)) {
                hash_map_pt wiringAdminList = hashMapIterator_nextValue(propIter);
                hash_map_iterator_pt waIter = hashMapIterator_create(wiringAdminList);

                while (hashMapIterator_hasNext(waIter)) {
                    wiring_endpoint_description_pt wEndpoint = hashMapIterator_nextValue(waIter);

                    bool matchResult = false;
                    filter_match(filter, wEndpoint->properties, &matchResult);

                    if (matchResult) {
                        wiring_endpoint_listener_pt listener = (wiring_endpoint_listener_pt) service;
                        status = listener->wiringEndpointAdded(listener->handle, wEndpoint, scope);
                    }
                }
                hashMapIterator_destroy(waIter);
            }
            hashMapIterator_destroy(propIter);

            celixThreadMutex_unlock(&manager->exportedWiringEndpointsLock);
        }
        filter_destroy(filter);

    }


    return status;
}
Beispiel #7
0
static int
do_filter(struct filter *f, const unsigned char *id,
          const unsigned char *prefix, unsigned short plen,
          const unsigned char *neigh, unsigned int ifindex, int proto)
{
    while(f) {
        if(filter_match(f, id, prefix, plen, neigh, ifindex, proto))
            return f->result;
        f = f->next;
    }
    return -1;
}
Beispiel #8
0
static const filter_element_t *filter_match(const filter_element_t *const fe,
                               const uint32_t channel,
                               const char *message, const char *signal)
{
  if(fe != NULL) {
    if(fe->channel_wildcard || (fe->channel == channel))
      if(0 == fnmatch(fe->message, message,0))
        if(0 == fnmatch(fe->signal, signal,0))
          return fe;
    return filter_match(fe->next, channel, message, signal);
  } else {
    return NULL;
  }
}
Beispiel #9
0
static void process_items(rss_t rss, struct target *t) {

	int i;
	struct rss_item item;

	while(rss_walk_next(rss, &item)) {

		struct http_file *file = NULL;

		if (proc_cache_lookup(item.link))
			continue;

		for(i=0; i < t->nr; i++) {
			struct filter *filter = &t->filter[i];

			if (dlhist_lookup(item.title, filter->dest) ||
				!filter_match(filter->pattern, item.title))
				continue;

			/* fetch the file if we haven't already. */
			if (file == NULL) {
				file = http_fetch_file(item.link);
				if (file == NULL) {
					error("download failed");
					continue;
				}
			}

			/* At this point, mark the item as downloaded.
			   Even if we encounter an error while saving to disk. */
			dlhist_mark(item.title, filter->dest);

			if (write_http_file(file, filter->dest) < 0)
				continue;

			printf("Downloaded: %s (%s) to %s\n",
				item.title, item.link, filter->dest);
		}

		proc_cache_update(item.link);

		http_free_file(file);
	}
}
Beispiel #10
0
char *
filter_apply(const filter_t *filter, const uint32_t channel,
             const char *message, const char *signal)
{
  char *mat_name = NULL;
  const filter_element_t *el;

  if(filter) {
    el = filter_match(filter->first, channel, message, signal);
    if(el != NULL) {             /* element found? */
      if(el->operation == '+') { /* accept? */
        if(el->newname) {        /* new name given? */
          mat_name = strdup(el->newname);
        } else {                 /* no new name given */
          mat_name = standard_name(message, signal);
        }
      }
    }
  } else {                       /* no filter */
    mat_name = standard_name(message, signal);
  }
  return mat_name;
}
Beispiel #11
0
int packet_filter_match(struct filter *f, struct proto_process_stack *stack) {

	return filter_match(f, stack);
}
int stream_pfring_read(struct stream_pfring* st, cap_head** header, const struct filter* filter, struct timeval* timeout){
	/* I heard ext is a pretty cool guy, uses goto and doesn't afraid of anything */
  retry:

	/* empty buffer */
	if ( !st->read_ptr ){
		if ( !read_packet(st, BLOCK) ){
			return EAGAIN;
		}

		char* frame = st->frame[st->base.readPos];
		struct sendhead* sh = (struct sendhead*)(frame + sizeof(struct ethhdr));
		st->read_ptr = frame + sizeof(struct ethhdr) + sizeof(struct sendhead);
		st->num_packets = ntohl(sh->nopkts);
	}

	/* always read if there is space available */
	if ( st->base.writePos != st->base.readPos ){
		read_packet(st, NONBLOCK);
	}

	/* no packets available */
	if ( st->num_packets == 0 ){
		return EAGAIN;
	}

	/* fetch next matching packet */
	struct cap_header* cp = (struct cap_header*)(st->read_ptr);
	const size_t packet_size = sizeof(struct cap_header) + cp->caplen;
	st->num_packets--;
	st->read_ptr += packet_size;

	if ( st->num_packets == 0 ){
		st->base.readPos = (st->base.readPos+1) % st->num_frames;
		if ( st->base.readPos == st->base.writePos ){
			st->read_ptr = NULL;
		} else {
			char* frame = st->frame[st->base.readPos];
			struct sendhead* sh = (struct sendhead*)(frame + sizeof(struct ethhdr));
			st->read_ptr = frame + sizeof(struct ethhdr) + sizeof(struct sendhead);
			st->num_packets = ntohl(sh->nopkts);
		}
	}

	if ( cp->caplen == 0 ){
		return ERROR_CAPFILE_INVALID;
	}

	assert(packet_size > 0);

	/* set next packet and advance the read pointer */
	*header = cp;
	st->base.stat.read++;
	st->base.stat.buffer_usage = 0;

	if ( filter && !filter_match(filter, cp->payload, cp) ){
		goto retry;
	}

	st->base.stat.matched++;
	return 0;
}
Beispiel #13
0
TEST(filter, match_operators){
	char * filter_str;
	filter_pt filter;
	properties_pt props = properties_create();
	char * key = my_strdup("test_attr1");
	char * val = my_strdup("attr1");
	char * key2 = my_strdup("test_attr2");
	char * val2 = my_strdup("attr2");
	properties_set(props, key, val);
	properties_set(props, key2, val2);

	//test EQUALS
	filter_str = my_strdup("(test_attr1=attr1)");
	filter = filter_create(filter_str);
	bool result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test EQUALS false
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1=falseString)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test APPROX TODO: update this test once APPROX is implemented
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1~=attr1)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test APROX false TODO: update this test once APPROX is implemented
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1~=ATTR1)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test PRESENT
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1=*)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test PRESENT false
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr3=*)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test LESSEQUAL less
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1<=attr5)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test LESSEQUAL equals
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2<=attr2)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test LESSEQUAL false
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2<=attr1)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test GREATEREQUAL greater
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2>=attr1)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test GREATEREQUAL equals
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2>=attr2)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test GREATEREQUAL false
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1>=attr5)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test LESS less
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1<attr5)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test LESS equals
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2<attr2)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test LESS false
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2<attr1)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test GREATER greater
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2>attr1)");
	filter = filter_create(filter_str);
	result = false;
	filter_match(filter, props, &result);
	CHECK(result);

	//test GREATER equals
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr2>attr2)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test GREATER false
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1>attr5)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//test SUBSTRING equals
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1=attr*)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK(result);

	//test SUBSTRING false
	filter_destroy(filter);
	free(filter_str);
	filter_str = my_strdup("(test_attr1=attr*charsNotPresent)");
	filter = filter_create(filter_str);
	result = true;
	filter_match(filter, props, &result);
	CHECK_FALSE(result);

	//cleanup
	properties_destroy(props);
	filter_destroy(filter);
	free(filter_str);
	free(key);
	free(key2);
	free(val);
	free(val2);

	mock().checkExpectations();
}
Beispiel #14
0
/*
  dispatch one inotify event

  the cookies are used to correctly handle renames
*/
static void inotify_dispatch(struct inotify_private *in,
                             struct inotify_event *e,
                             uint32_t prev_cookie,
                             struct inotify_event *e2)
{
    struct inotify_watch_context *w, *next;
    struct notify_event ne;

    DEBUG(10, ("inotify_dispatch called with mask=%x, name=[%s]\n",
               e->mask, e->len ? e->name : ""));

    /* ignore extraneous events, such as unmount and IN_IGNORED events */
    if ((e->mask & (IN_ATTRIB|IN_MODIFY|IN_CREATE|IN_DELETE|
                    IN_MOVED_FROM|IN_MOVED_TO)) == 0) {
        return;
    }

    /* map the inotify mask to a action. This gets complicated for
       renames */
    if (e->mask & IN_CREATE) {
        ne.action = NOTIFY_ACTION_ADDED;
    } else if (e->mask & IN_DELETE) {
        ne.action = NOTIFY_ACTION_REMOVED;
    } else if (e->mask & IN_MOVED_FROM) {
        if (e2 != NULL && e2->cookie == e->cookie) {
            ne.action = NOTIFY_ACTION_OLD_NAME;
        } else {
            ne.action = NOTIFY_ACTION_REMOVED;
        }
    } else if (e->mask & IN_MOVED_TO) {
        if (e->cookie == prev_cookie) {
            ne.action = NOTIFY_ACTION_NEW_NAME;
        } else {
            ne.action = NOTIFY_ACTION_ADDED;
        }
    } else {
        ne.action = NOTIFY_ACTION_MODIFIED;
    }
    ne.path = e->name;

    DEBUG(10, ("inotify_dispatch: ne.action = %d, ne.path = %s\n",
               ne.action, ne.path));

    /* find any watches that have this watch descriptor */
    for (w=in->watches; w; w=next) {
        next = w->next;
        if (w->wd == e->wd && filter_match(w, e)) {
            w->callback(in->ctx, w->private_data, &ne);
        }
    }

    /* SMB expects a file rename to generate three events, two for
       the rename and the other for a modify of the
       destination. Strange! */
    if (ne.action != NOTIFY_ACTION_NEW_NAME ||
            (e->mask & IN_ISDIR) != 0) {
        return;
    }

    ne.action = NOTIFY_ACTION_MODIFIED;
    e->mask = IN_ATTRIB;

    for (w=in->watches; w; w=next) {
        next = w->next;
        if (w->wd == e->wd && filter_match(w, e) &&
                !(w->filter & FILE_NOTIFY_CHANGE_CREATION)) {
            w->callback(in->ctx, w->private_data, &ne);
        }
    }
}
Beispiel #15
0
static int
filter_match(struct intercept_pid *icpid, struct intercept_tlq *tls,
    struct logic *logic)
{
	struct intercept_translate *tl;
	int off = 0, res;

	switch (logic->op) {
	case LOGIC_NOT:
		return (!filter_match(icpid, tls, logic->left));
	case LOGIC_OR:
		if (filter_match(icpid, tls, logic->left))
			return (1);
		return (filter_match(icpid, tls, logic->right));
	case LOGIC_AND:
		if (!filter_match(icpid, tls, logic->left))
			return (0);
		return (filter_match(icpid, tls, logic->right));
	default:
		break;
	}

	/* Now we just have a logic single */
	if (logic->type == NULL)
		goto match;

	if (tls == NULL)
		errx(1, "filter_match has no translators");

	TAILQ_FOREACH(tl, tls, next) {
		if (!tl->trans_valid)
			continue;

		if (strcasecmp(tl->name, logic->type))
			continue;

		if (logic->typeoff == -1 || logic->typeoff == off)
			break;

		off++;
	}

	if (tl == NULL)
		return (0);

 match:
	/* We need to do dynamic expansion on the data */
	if (logic->filterdata && (logic->flags & LOGIC_NEEDEXPAND)) {
		char *old = logic->filterdata;
		size_t oldlen = logic->filterlen;

		logic->filterdata = filter_dynamicexpand(icpid, old);
		logic->filterlen = strlen(logic->filterdata) + 1;

		res = logic->filter_match(tl, logic);

		logic->filterdata = old;
		logic->filterlen = oldlen;
	} else
		res = logic->filter_match(tl, logic);

	return (res);
}
Beispiel #16
0
int main(int argc, char **argv){
	/* extract program name from path. e.g. /path/to/MArCd -> MArCd */
	const char* separator = strrchr(argv[0], '/');
	if ( separator ){
		program_name = separator + 1;
	} else {
		program_name = argv[0];
	}

	struct filter filter;
	if ( filter_from_argv(&argc, argv, &filter) != 0 ){
		return 0; /* error already shown */
	}

	int op, option_index = -1;
	while ( (op = getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1 ){
		switch (op){
		case 0:   /* long opt */
		case '?': /* unknown opt */
			break;

		case '1':
		case '2':
		case '3':
		case '4':
		{
			const unsigned int mask = (7<<FORMAT_LAYER_BIT);
			flags &= ~mask; /* reset all layer bits */
			flags |= (op-'0')<<FORMAT_LAYER_BIT;
			break;
		}

		case 'd': /* --calender */
			flags |= FORMAT_DATE_STR | FORMAT_DATE_UTC;
			break;

		case 'D': /* --localtime */
			flags |= FORMAT_DATE_STR | FORMAT_DATE_LOCALTIME;
			break;

		case 'a': /* --absolute */
			flags &= ~FORMAT_REL_TIMESTAMP;
			break;

		case 'r': /* --relative */
			flags |= FORMAT_REL_TIMESTAMP;
			break;

		case 'H': /* --headers */
			flags |= FORMAT_HEADER;
			break;

		case 'p': /* --packets */
			max_packets = atoi(optarg);
			break;

		case 'c': /* --packets */
			max_matched_packets = atoi(optarg);
			break;

		case 't': /* --timeout */
		{
			int tmp = atoi(optarg);
			timeout.tv_sec  = tmp / 1000;
			timeout.tv_usec = tmp % 1000 * 1000;
		}
		break;

		case 'x': /* --hexdump */
			flags |= FORMAT_HEXDUMP;
			break;

		case 'i': /* --iface */
			iface = optarg;
			break;

		case ARGUMENT_VERSION: /* --version */
			show_version();
			return 0;

		case 'h': /* --help */
			show_usage();
			return 0;

		default:
			fprintf (stderr, "%s: argument '-%c' declared but not handled\n", argv[0], op);
		}
	}

	int ret;

	/* Open stream(s) */
	struct stream* stream;
	if ( (ret=stream_from_getopt(&stream, argv, optind, argc, iface, "-", program_name, 0)) != 0 ) {
		return ret; /* Error already shown */
	}
	const stream_stat_t* stat = stream_get_stat(stream);
	stream_print_info(stream, stderr);

	/* handle C-c */
	signal(SIGINT, handle_sigint);

	/* setup formatter */
	struct format format;
	format_setup(&format, flags);

	uint64_t matched = 0;
	while ( keep_running ) {
		/* A short timeout is used to allow the application to "breathe", i.e
		 * terminate if SIGINT was received. */
		struct timeval tv = timeout;

		/* Read the next packet */
		cap_head* cp;
		ret = stream_read(stream, &cp, NULL, &tv);
		if ( ret == EAGAIN ){
			continue; /* timeout */
		} else if ( ret != 0 ){
			break; /* shutdown or error */
		}

		/* identify connection even if filter doesn't match so id will be
		 * deterministic when changing the filter */
		connection_id(cp);

		if ( filter_match(&filter, cp->payload, cp) ){
			format_pkg(stdout, &format, cp);
			matched++;
		} else {
			format_ignore(stdout, &format, cp);
		}

		if ( max_packets > 0 && stat->matched >= max_packets) {
			/* Read enough pkts lets break. */
			break;
		}
		if ( max_matched_packets > 0 && matched >= max_matched_packets) {
			/* Read enough pkts lets break. */
			break;
		}
	}

	/* if ret == -1 the stream was closed properly (e.g EOF or TCP shutdown)
	 * In addition EINTR should not give any errors because it is implied when the
	 * user presses C-c */
	if ( ret > 0 && ret != EINTR ){
		fprintf(stderr, "stream_read() returned 0x%08X: %s\n", ret, caputils_error_string(ret));
	}

	/* Write stats */
	fprintf(stderr, "%"PRIu64" packets read.\n", stat->read);
	fprintf(stderr, "%"PRIu64" packets matched filter.\n", matched);

	/* Release resources */
	stream_close(stream);
	filter_close(&filter);

	return 0;
}