Exemple #1
0
/**
 * \brief NFQ verdict function
 */
TmEcode NFQSetVerdict(Packet *p) {
    int iter = 0;
    int ret = 0;
    uint32_t verdict = NF_ACCEPT;
    /* we could also have a direct pointer but we need to have a ref counf in this case */
    NFQQueueVars *t = nfq_q + p->nfq_v.nfq_index;

    /** \todo add a test on validity of the entry NFQQueueVars could have been
     *  wipeout
     */

    /* can't verdict a "fake" packet */
    if (p->flags & PKT_PSEUDO_STREAM_END) {
        return TM_ECODE_OK;
    }

    //printf("%p verdicting on queue %" PRIu32 "\n", t, t->queue_num);
    NFQMutexLock(t);

    if (t->qh == NULL) {
        /* Somebody has started a clean-up, we leave */
        NFQMutexUnlock(t);
        return TM_ECODE_OK;
    }

    if (p->action & ACTION_DROP) {
        verdict = NF_DROP;
#ifdef COUNTERS
        t->dropped++;
#endif /* COUNTERS */
    } else {
        switch (nfq_config.mode) {
            default:
            case NFQ_ACCEPT_MODE:
                verdict = NF_ACCEPT;
                break;
            case NFQ_REPEAT_MODE:
                verdict = NF_REPEAT;
                break;
            case NFQ_ROUTE_MODE:
                verdict = ((uint32_t) NF_QUEUE) | nfq_config.next_queue;
                break;
        }

        if (p->flags & PKT_STREAM_MODIFIED) {
#ifdef COUNTERS
            t->replaced++;
#endif /* COUNTERS */
        }

#ifdef COUNTERS
        t->accepted++;
#endif /* COUNTERS */
    }

    do {
        switch (nfq_config.mode) {
            default:
            case NFQ_ACCEPT_MODE:
            case NFQ_ROUTE_MODE:
                if (p->flags & PKT_MARK_MODIFIED) {
#ifdef HAVE_NFQ_SET_VERDICT2
                    if (p->flags & PKT_STREAM_MODIFIED) {
                        ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
                                p->nfq_v.mark,
                                GET_PKT_LEN(p), GET_PKT_DATA(p));
                    } else {
                        ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
                                p->nfq_v.mark,
                                0, NULL);
                    }
#else /* fall back to old function */
                    if (p->flags & PKT_STREAM_MODIFIED) {
                        ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
                                htonl(p->nfq_v.mark),
                                GET_PKT_LEN(p), GET_PKT_DATA(p));
                    } else {
                        ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
                                htonl(p->nfq_v.mark),
                                0, NULL);
                    }
#endif /* HAVE_NFQ_SET_VERDICT2 */
                } else {
                    if (p->flags & PKT_STREAM_MODIFIED) {
                        ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict,
                                GET_PKT_LEN(p), GET_PKT_DATA(p));
                    } else {
                        ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict, 0, NULL);
                    }

                }
                break;
            case NFQ_REPEAT_MODE:
#ifdef HAVE_NFQ_SET_VERDICT2
                if (p->flags & PKT_STREAM_MODIFIED) {
                    ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
                            (nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask),
                            GET_PKT_LEN(p), GET_PKT_DATA(p));
                } else {
                    ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
                            (nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask),
                            0, NULL);
                }
#else /* fall back to old function */
                if (p->flags & PKT_STREAM_MODIFIED) {
                    ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
                            htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)),
                            GET_PKT_LEN(p), GET_PKT_DATA(p));
                } else {
                    ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
                            htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)),
                            0, NULL);
                }
#endif /* HAVE_NFQ_SET_VERDICT2 */
                break;
        }
    } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_TIME));

    NFQMutexUnlock(t);

    if (ret < 0) {
        SCLogWarning(SC_ERR_NFQ_SET_VERDICT, "nfq_set_verdict of %p failed %" PRId32 "", p, ret);
        return TM_ECODE_FAILED;
    }
    return TM_ECODE_OK;
}
Exemple #2
0
static int packet_input(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
              		struct nfq_data *nfa, void *data)
{
	divert_cb cb = (divert_cb) data;
	char *d;
	int len;
	int rc;
	unsigned int id;
	struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);
	struct ip *ip;
	int flags = 0;
	struct timeval tv;
	int rlen = 0;
	void *rdata = NULL;

	len = nfq_get_payload(nfa, &d);
	if (len < 0)
		err(1, "nfq_get_payload()");

	if (nfq_get_indev(nfa))
		flags |= DF_IN;

	if (nfq_get_timestamp(nfa, &tv) == 0)
		set_time(&tv);
	else {
		static int warn = 0;

		if (!warn && !_conf.cf_disable_timers)
			xprintf(XP_ALWAYS, "No timestamp provided in packet"
			                   " - expect low performance due to"
					   " calls to gettimeofday\n");
		warn = 1;	
	}

	rc = cb(d, len, flags);

	id = ntohl(ph->packet_id);

	switch (rc) {
	case DIVERT_MODIFY:
		ip    = (struct ip*) d;
		rlen  = ntohs(ip->ip_len);
		rdata = d;
		/* fallthrough */
	case DIVERT_ACCEPT:
		if (_mark) {
			unsigned int mark = 0;

			assert((mark & _mark) == 0);
			nfq_set_verdict_mark(qh, id, NF_REPEAT,
					     htonl(_mark | mark),
					     rlen, rdata);
		} else
			nfq_set_verdict(qh, id, NF_ACCEPT, rlen, rdata);
		break;

	case DIVERT_DROP:
		nfq_set_verdict(qh, id, NF_DROP, 0, NULL);
		break;

	default:
		printf("Unknown verdict %d\n", rc);
		abort();
	}

	return 0;
}