Пример #1
0
int nl_init_event_handler(void)
{
	STATE(event) = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS);
	if (!STATE(event))
		return -1;

	fcntl(nfct_fd(STATE(event)), F_SETFL, O_NONBLOCK);

	/* set up socket buffer size */
	if (CONFIG(netlink_buffer_size))
		nfnl_rcvbufsiz(nfct_nfnlh(STATE(event)), 
			       CONFIG(netlink_buffer_size));
	else {
		socklen_t socklen = sizeof(unsigned int);
		unsigned int read_size;

		/* get current buffer size */
		getsockopt(nfct_fd(STATE(event)), SOL_SOCKET,
			   SO_RCVBUF, &read_size, &socklen);

		CONFIG(netlink_buffer_size) = read_size;
	}

	/* ensure that maximum grown size is >= than maximum size */
	if (CONFIG(netlink_buffer_size_max_grown) < CONFIG(netlink_buffer_size))
		CONFIG(netlink_buffer_size_max_grown) = 
					CONFIG(netlink_buffer_size);

	/* register callback for events */
	nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL);

	return 0;
}
Пример #2
0
void nl_resize_socket_buffer(struct nfct_handle *h)
{
	unsigned int s = CONFIG(netlink_buffer_size) * 2;

	/* already warned that we have reached the maximum buffer size */
	if (warned)
		return;

	if (s > CONFIG(netlink_buffer_size_max_grown)) {
		dlog(STATE(log), "WARNING: maximum netlink socket buffer "
				 "size has been reached. We are likely to "
				 "be losing events, this may lead to "
				 "unsynchronized replicas. Please, consider "
				 "increasing netlink socket buffer size via "
				 "SocketBufferSize and "
				 "SocketBufferSizeMaxGrown clauses in "
				 "conntrackd.conf");
		s = CONFIG(netlink_buffer_size_max_grown);
		warned = 1;
	}

	CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s);

	/* notify the sysadmin */
	dlog(STATE(log), "netlink socket buffer size has been set to %u bytes", 
			  CONFIG(netlink_buffer_size));
}
Пример #3
0
void nl_resize_socket_buffer(struct nfct_handle *h)
{
	unsigned int s = CONFIG(netlink_buffer_size);

	/* already warned that we have reached the maximum buffer size */
	if (warned)
		return;

	/* since sock_setsockopt in net/core/sock.c doubles the size of socket
	   buffer passed to it using nfnl_rcvbufsiz, only call nfnl_rcvbufsiz
	   if new value is not greater than netlink_buffer_size_max_grown */
	if (s*2 > CONFIG(netlink_buffer_size_max_grown)) {
		dlog(LOG_WARNING,
		     "netlink event socket buffer size cannot "
		     "be doubled further since it will exceed "
		     "NetlinkBufferSizeMaxGrowth. We are likely to "
		     "be losing events, this may lead to "
		     "unsynchronized replicas. Please, consider "
		     "increasing netlink socket buffer size via "
		     "NetlinkBufferSize and "
		     "NetlinkBufferSizeMaxGrowth clauses in "
		     "conntrackd.conf");
		warned = 1;
		return;
	}

	CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s);

	/* notify the sysadmin */
	dlog(LOG_NOTICE, "netlink event socket buffer size has been doubled "
			 "to %u bytes", CONFIG(netlink_buffer_size));
}
Пример #4
0
/************************* main *******************************/
int main() {
    new_packet = (unsigned char *)malloc(MTU);
    if(new_packet == NULL) {
        printf("Malloc failed\n");
        exit(EXIT_FAILURE);
    }

    struct nfq_handle *h = get_handle();
    fd_set rfds;

    // start the downstream code, later move to a thread
    initializeRabin(powers);
    int max_fd = 0;
    int down_fd = createQueue(h, DOWN_MOBILE_QUEUE, &cbDown);
    if(down_fd > max_fd)
        max_fd = down_fd;
    int up_fd = createQueue(h, UP_MOBILE_QUEUE, &cbUp);
    if(up_fd > max_fd)
        max_fd = up_fd;

    printlog(logfile, system_loglevel, LOG_DEBUG, 
            "Queue packet descriptors, down_fd: %d, up_fd: %d\n",
            down_fd, up_fd);

    int n = 0, rv = 0;
    char buf[4096] __attribute__ ((aligned));
    nfnl_rcvbufsiz(nfq_nfnlh(h), 4096 * 4096);
    while(true) {
        FD_ZERO(&rfds);
        FD_SET(down_fd, &rfds);
        FD_SET(up_fd, &rfds);
        n = select(max_fd + 1, &rfds, NULL, NULL, NULL);
        if(n == -1) {
            printlog(logfile, system_loglevel, LOG_CRITICAL, 
                    "Select returned error: %s\n", strerror(errno));
        } 
        if(FD_ISSET(down_fd, &rfds)) {
            rv = recv(down_fd, buf, sizeof(buf), 0);
            if(rv < 0) {
                printlog(logfile, system_loglevel, LOG_CRITICAL, 
                        "recv call failed: %s\n", strerror(errno));
            } else {
                nfq_handle_packet(h, buf, rv);
            }
        } 
        if(FD_ISSET(up_fd, &rfds)) {
            rv = recv(up_fd, buf, sizeof(buf), 0);
            if(rv < 0) {
                printlog(logfile, system_loglevel, LOG_CRITICAL, 
                        "recv call failed: %s\n", strerror(errno));
            } else {
                nfq_handle_packet(h, buf, rv);
            }
        }
    }

    // start the upstream code, later move to a thread
    return 0;
}
Пример #5
0
int divert_open(int port, divert_cb cb)
{
	unsigned int bufsize = 1024 * 1024 * 1;
	unsigned int rc;
	char *m;
	int fd, flags;

        _h = nfq_open();
        if (!_h)
                err(1, "nfq_open()");

	rc = nfnl_rcvbufsiz(nfq_nfnlh(_h), bufsize);
	if (rc != bufsize)
		xprintf(XP_DEBUG, "Buffer size %u wanted %u\n", rc, bufsize);

	/* reset in case of previous crash */
	if (nfq_unbind_pf(_h, AF_INET) < 0)
		err(1, "nfq_unbind_pf()");

        if (nfq_bind_pf(_h, AF_INET) < 0)
                err(1, "nfq_bind_pf()");

        _q = nfq_create_queue(_h, port, packet_input, cb);
        if (!_q)
                err(1, "nfq_create_queue()");

        if (nfq_set_mode(_q, NFQNL_COPY_PACKET, 0xffff) < 0)
                err(1, "nfq_set_mode()");

	if (nfq_set_queue_maxlen(_q, 10000) < 0)
		err(1, "nfq_set_queue_maxlen()");

       	xprintf(XP_DEFAULT,
		"Divert packets using iptables -j NFQUEUE --queue-num %d\n",
                port);

	m = driver_param(0);
	if (m) {
		_mark = strtoul(m, NULL, 16);
		xprintf(XP_DEFAULT, "Also, add -m mark --mark 0x0/0x%x\n",
			_mark);
	}

	fd = nfq_fd(_h);

	flags = fcntl(fd, F_GETFL);
	if (flags == -1)
		err(1, "fcntl()");

	if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
		err(1, "fcntl()");

	open_raw();

	return fd;
}
Пример #6
0
int 
tc_nfq_socket_init(struct nfq_handle **h, struct nfq_q_handle **qh,
        nfq_callback *cb, int max_queue_len)
{
    int fd;

    tc_log_info(LOG_NOTICE, 0, "opening library handle");
    *h = nfq_open();
    if (!(*h)) {
        tc_log_info(LOG_ERR, errno, "error during nfq_open()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0,
            "unbinding existing nf_queue handler for AF_INET (if any)");
    if (nfq_unbind_pf((*h), AF_INET) < 0) {
        tc_log_info(LOG_ERR, errno, "error during nfq_unbind_pf()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0,
            "binding nfnetlink_queue as nf_queue handler for AF_INET");
    if (nfq_bind_pf((*h), AF_INET) < 0) {
        tc_log_info(LOG_ERR, errno, "error during nfq_bind_pf()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0, "binding this socket to queue");
    *qh = nfq_create_queue((*h),  0, cb, NULL);
    if (!(*qh)) {
        tc_log_info(LOG_ERR, errno, "error during nfq_create_queue()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0, "setting copy_packet mode");
    if (nfq_set_mode((*qh), NFQNL_COPY_PACKET, RESP_MAX_USEFUL_SIZE) < 0) {
        tc_log_info(LOG_ERR, errno, "can't set packet_copy mode");
        return TC_INVALID_SOCKET;
    }

    if (max_queue_len > 0) {
        if (nfq_set_queue_maxlen((*qh), (uint32_t) max_queue_len)  < 0) {
            tc_log_info(LOG_ERR, errno, "can't set queue max length:%d", 
                    max_queue_len);
            tc_log_info(LOG_WARN, 0, "unable to set queue maxlen");
            tc_log_info(LOG_WARN, 0, "your kernel probably doesn't support it");
        }
    }

    fd = nfq_fd(*h);

    nfnl_rcvbufsiz(nfq_nfnlh(*h), 16777216);

    return fd;
}
Пример #7
0
int 
tc_nfq_socket_init(struct nfq_handle **h, struct nfq_q_handle **qh,
        nfq_callback *cb)
{
    int fd;

    tc_log_info(LOG_NOTICE, 0, "opening library handle");
    *h = nfq_open();
    if (!(*h)) {
        tc_log_info(LOG_ERR, errno, "error during nfq_open()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0,
            "unbinding existing nf_queue handler for AF_INET (if any)");
    if (nfq_unbind_pf((*h), AF_INET) < 0) {
        tc_log_info(LOG_ERR, errno, "error during nfq_unbind_pf()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0,
            "binding nfnetlink_queue as nf_queue handler for AF_INET");
    if (nfq_bind_pf((*h), AF_INET) < 0) {
        tc_log_info(LOG_ERR, errno, "error during nfq_bind_pf()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0, "binding this socket to queue");
    *qh = nfq_create_queue((*h),  0, cb, NULL);
    if (!(*qh)) {
        tc_log_info(LOG_ERR, errno, "error during nfq_create_queue()");
        return TC_INVALID_SOCKET;
    }

    tc_log_info(LOG_NOTICE, 0, "setting copy_packet mode");
    if (nfq_set_mode((*qh), NFQNL_COPY_PACKET, RESP_MAX_USEFUL_SIZE) < 0) {
        tc_log_info(LOG_ERR, errno, "can't set packet_copy mode");
        return TC_INVALID_SOCKET;
    }

    fd = nfq_fd(*h);

    nfnl_rcvbufsiz(nfq_nfnlh(*h), 4096*4096);

    return fd;
}
Пример #8
0
int nflog_set_nlbufsiz(struct nflog_g_handle *gh, u_int32_t nlbufsiz)
{
	char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(u_int32_t))];
	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
	int status;

	nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id,
		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);

	nfnl_addattr32(nmh, sizeof(buf), NFULA_CFG_NLBUFSIZ, htonl(nlbufsiz));

	status = nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);

	/* we try to have space for at least 10 messages in the socket buffer */
	if (status >= 0)
		nfnl_rcvbufsiz(gh->h->nfnlh, 10*nlbufsiz);

	return status;
}
Пример #9
0
TmEcode NFQInitThread(NFQThreadVars *nfq_t, uint32_t queue_maxlen)
{
#ifndef OS_WIN32
    struct timeval tv;
    int opt;
#endif
    NFQQueueVars *nfq_q = NFQGetQueue(nfq_t->nfq_index);
    if (nfq_q == NULL) {
        SCLogError(SC_ERR_NFQ_OPEN, "no queue for given index");
        return TM_ECODE_FAILED;
    }
    SCLogDebug("opening library handle");
    nfq_q->h = nfq_open();
    if (!nfq_q->h) {
        SCLogError(SC_ERR_NFQ_OPEN, "nfq_open() failed");
        return TM_ECODE_FAILED;
    }

    if (nfq_g.unbind == 0)
    {
        /* VJ: on my Ubuntu Hardy system this fails the first time it's
         * run. Ignoring the error seems to have no bad effects. */
        SCLogDebug("unbinding existing nf_queue handler for AF_INET (if any)");
        if (nfq_unbind_pf(nfq_q->h, AF_INET) < 0) {
            SCLogError(SC_ERR_NFQ_UNBIND, "nfq_unbind_pf() for AF_INET failed");
            exit(EXIT_FAILURE);
        }
        if (nfq_unbind_pf(nfq_q->h, AF_INET6) < 0) {
            SCLogError(SC_ERR_NFQ_UNBIND, "nfq_unbind_pf() for AF_INET6 failed");
            exit(EXIT_FAILURE);
        }
        nfq_g.unbind = 1;

        SCLogDebug("binding nfnetlink_queue as nf_queue handler for AF_INET and AF_INET6");

        if (nfq_bind_pf(nfq_q->h, AF_INET) < 0) {
            SCLogError(SC_ERR_NFQ_BIND, "nfq_bind_pf() for AF_INET failed");
            exit(EXIT_FAILURE);
        }
        if (nfq_bind_pf(nfq_q->h, AF_INET6) < 0) {
            SCLogError(SC_ERR_NFQ_BIND, "nfq_bind_pf() for AF_INET6 failed");
            exit(EXIT_FAILURE);
        }
    }

    SCLogInfo("binding this thread %d to queue '%" PRIu32 "'", nfq_t->nfq_index, nfq_q->queue_num);

    /* pass the thread memory as a void ptr so the
     * callback function has access to it. */
    nfq_q->qh = nfq_create_queue(nfq_q->h, nfq_q->queue_num, &NFQCallBack, (void *)nfq_t);
    if (nfq_q->qh == NULL)
    {
        SCLogError(SC_ERR_NFQ_CREATE_QUEUE, "nfq_create_queue failed");
        return TM_ECODE_FAILED;
    }

    SCLogDebug("setting copy_packet mode");

    /* 05DC = 1500 */
    //if (nfq_set_mode(nfq_t->qh, NFQNL_COPY_PACKET, 0x05DC) < 0) {
    if (nfq_set_mode(nfq_q->qh, NFQNL_COPY_PACKET, 0xFFFF) < 0) {
        SCLogError(SC_ERR_NFQ_SET_MODE, "can't set packet_copy mode");
        return TM_ECODE_FAILED;
    }

#ifdef HAVE_NFQ_MAXLEN
    if (queue_maxlen > 0) {
        SCLogInfo("setting queue length to %" PRId32 "", queue_maxlen);

        /* non-fatal if it fails */
        if (nfq_set_queue_maxlen(nfq_q->qh, queue_maxlen) < 0) {
            SCLogWarning(SC_ERR_NFQ_MAXLEN, "can't set queue maxlen: your kernel probably "
                    "doesn't support setting the queue length");
        }
    }
#endif /* HAVE_NFQ_MAXLEN */

#ifndef OS_WIN32
    /* set netlink buffer size to a decent value */
    nfnl_rcvbufsiz(nfq_nfnlh(nfq_q->h), queue_maxlen * 1500);
    SCLogInfo("setting nfnl bufsize to %" PRId32 "", queue_maxlen * 1500);

    nfq_q->nh = nfq_nfnlh(nfq_q->h);
    nfq_q->fd = nfnl_fd(nfq_q->nh);
    NFQMutexInit(nfq_q);

    /* Set some netlink specific option on the socket to increase
	performance */
    opt = 1;
#ifdef NETLINK_BROADCAST_SEND_ERROR
    setsockopt(nfq_q->fd, SOL_NETLINK,
               NETLINK_BROADCAST_SEND_ERROR, &opt, sizeof(int));
#endif
    /* Don't send error about no buffer space available but drop the
	packets instead */
#ifdef NETLINK_NO_ENOBUFS
    setsockopt(nfq_q->fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(int));
#endif

#ifdef HAVE_NFQ_SET_QUEUE_FLAGS
    if (nfq_config.flags & NFQ_FLAG_FAIL_OPEN) {
        uint32_t flags = NFQA_CFG_F_FAIL_OPEN;
        uint32_t mask = NFQA_CFG_F_FAIL_OPEN;
        int r = nfq_set_queue_flags(nfq_q->qh, mask, flags);

        if (r == -1) {
            SCLogWarning(SC_ERR_NFQ_SET_MODE, "can't set fail-open mode: %s",
                         strerror(errno));
        } else {
            SCLogInfo("fail-open mode should be set on queue");
        }
    }
#endif

    /* set a timeout to the socket so we can check for a signal
     * in case we don't get packets for a longer period. */
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    if(setsockopt(nfq_q->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
        SCLogWarning(SC_ERR_NFQ_SETSOCKOPT, "can't set socket timeout: %s", strerror(errno));
    }

    SCLogDebug("nfq_q->h %p, nfq_q->nh %p, nfq_q->qh %p, nfq_q->fd %" PRId32 "",
            nfq_q->h, nfq_q->nh, nfq_q->qh, nfq_q->fd);
#else /* OS_WIN32 */
    NFQMutexInit(nfq_q);
    nfq_q->ovr.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    nfq_q->fd = nfq_fd(nfq_q->h);
    SCLogDebug("nfq_q->h %p, nfq_q->qh %p, nfq_q->fd %p", nfq_q->h, nfq_q->qh, nfq_q->fd);
#endif /* OS_WIN32 */

    return TM_ECODE_OK;
}
Пример #10
0
static struct packet_module_state *init_state(int thread_id)
{
	static const u_int16_t proto_family[] = { AF_INET, AF_INET6 };
	int i;
	struct packet_module_state *state = malloc(sizeof(struct packet_module_state));
	if (!state) {
		return NULL;
	}

	/* Setup nfqueue connection */
	state->handle = nfq_open();
	if (!state->handle) {
		message(HAKA_LOG_ERROR, MODULE_NAME, L"unable to open nfqueue handle");
		cleanup_state(state);
		return NULL;
	}

	for (i=0; i<sizeof(proto_family)/sizeof(proto_family[0]); ++i) {
		if (nfq_unbind_pf(state->handle, proto_family[i]) < 0) {
			message(HAKA_LOG_ERROR, MODULE_NAME, L"cannot unbind queue");
			cleanup_state(state);
			return NULL;
		}

		if (nfq_bind_pf(state->handle, proto_family[i]) < 0) {
			message(HAKA_LOG_ERROR, MODULE_NAME, L"cannot bind queue");
			cleanup_state(state);
			return NULL;
		}

		state->send_fd = open_send_socket(false);
		if (state->send_fd < 0) {
			cleanup_state(state);
			return NULL;
		}

		state->send_mark_fd = open_send_socket(true);
		if (state->send_fd < 0) {
			cleanup_state(state);
			return NULL;
		}
	}

	state->queue = nfq_create_queue(state->handle, thread_id,
			&packet_callback, state);
	if (!state->queue) {
		message(HAKA_LOG_ERROR, MODULE_NAME, L"cannot create queue");
		cleanup_state(state);
		return NULL;
	}

	if (nfq_set_mode(state->queue, NFQNL_COPY_PACKET,
			PACKET_BUFFER_SIZE) < 0) {
		message(HAKA_LOG_ERROR, MODULE_NAME, L"cannot set mode to copy packet");
		cleanup_state(state);
		return NULL;
	}

	state->fd = nfq_fd(state->handle);

	/* Change nfq queue len and netfilter receive size */
	if (nfq_set_queue_maxlen(state->queue, nfqueue_len) < 0) {
		message(HAKA_LOG_WARNING, MODULE_NAME, L"cannot change netfilter queue len");
	}

	nfnl_rcvbufsiz(nfq_nfnlh(state->handle), nfqueue_len * 1500);

	return state;
}
Пример #11
0
/**
 * Open a netlink connection and returns file descriptor
 */
int packetsrv_open(void *data)
{
	int ret;

	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
			"Opening netfilter queue socket");
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
			"[!] Don't forget to load kernel modules nfnetlink and nfnetlink_queue (using modprobe command)");

	/* opening library handle */
	h = nfq_open();
	if (!h) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Error during nfq_open()");
		return -1;
	}

	/* unbinding existing nf_queue handler for AF_INET (if any) */
	/* ignoring return, see http://www.spinics.net/lists/netfilter/msg42063.html */
	nfq_unbind_pf(h, AF_INET);

	/* binding nfnetlink_queue as nf_queue handler for AF_INET */
	if (nfq_bind_pf(h, AF_INET) < 0) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Error during nfq_bind_pf()");
		return -1;
	}

	if (!nufw_no_ipv6) {
		/* unbinding existing nf_queue handler for AF_INET6 (if any) */
		nfq_unbind_pf(h, AF_INET6);

		/* binding nfnetlink_queue as nf_queue handler for AF_INET6 */
		if (nfq_bind_pf(h, AF_INET6) < 0) {
			log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
					"[!] Error during nfq_bind_pf()");
			log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
					"Maybe you need to compile NF_NETLINK* kernel options as modules (not built in the kernel!)");
			return -1;
		}
	}

	ret = nfnl_rcvbufsiz(nfq_nfnlh(h), 10 * 65536);
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
			"rcv buf size set to %d (%d asked)",
			ret, 10 * 65536);

	/* binding this socket to queue number ::nfqueue_num
	 * and install our packet handler */
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
			"[+] Binding to netfilter queue %d", nfqueue_num);
	hndl = nfq_create_queue(h, nfqueue_num,
			     (nfq_callback *) & treat_packet, data);
	if (!hndl) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Error during nfq_create_queue() (queue %d busy ?)",
				nfqueue_num);
		return -1;
	}

	/* setting copy_packet mode */
	if (nfq_set_mode(hndl, NFQNL_COPY_PACKET, 0xffff) < 0) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Can't set packet_copy mode");
		return -1;
	}
#ifdef HAVE_NFQ_SET_QUEUE_MAXLEN
	/* setting queue length */
	if (queue_maxlen) {
		if (nfq_set_queue_maxlen(hndl, queue_maxlen) < 0) {
			if (nufw_set_mark) {
				log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
						"[!] Can't set queue length, and mark will be set, leaving !");
				exit(EXIT_FAILURE);
			} else {
				log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
						"[!] Can't set queue length, continuing anyway");
			}
		}
	}
#endif

	return nfq_fd(h);
}
Пример #12
0
struct nfct_handle *nl_init_event_handler(void)
{
	struct nfct_handle *h;

	h = nfct_open(CONFIG(netlink).subsys_id, CONFIG(netlink).groups);
	if (h == NULL)
		return NULL;

	if (CONFIG(netlink).events_reliable) {
		int on = 1;

		setsockopt(nfct_fd(h), SOL_NETLINK,
			   NETLINK_BROADCAST_SEND_ERROR, &on, sizeof(int));

		setsockopt(nfct_fd(h), SOL_NETLINK,
			   NETLINK_NO_ENOBUFS, &on, sizeof(int));

		dlog(LOG_NOTICE, "reliable ctnetlink event delivery "
				 "is ENABLED.");
	}

	if (STATE(filter)) {
		if (CONFIG(filter_from_kernelspace)) {
			if (nfct_filter_attach(nfct_fd(h),
					       STATE(filter)) == -1) {
				dlog(LOG_ERR, "cannot set event filtering: %s",
				     strerror(errno));
			}
			dlog(LOG_NOTICE, "using kernel-space event filtering");
		} else
			dlog(LOG_NOTICE, "using user-space event filtering");

		nfct_filter_destroy(STATE(filter));
	}

	fcntl(nfct_fd(h), F_SETFL, O_NONBLOCK);

	/* set up socket buffer size */
	if (CONFIG(netlink_buffer_size) &&
	    CONFIG(netlink_buffer_size) <=
			CONFIG(netlink_buffer_size_max_grown)) {
		/* we divide netlink_buffer_size by 2 here since value passed
		   to kernel gets doubled in SO_RCVBUF; see net/core/sock.c */
		CONFIG(netlink_buffer_size) =
		  nfnl_rcvbufsiz(nfct_nfnlh(h), CONFIG(netlink_buffer_size)/2);
	} else {
		dlog(LOG_NOTICE, "NetlinkBufferSize is either not set or "
				 "is greater than NetlinkBufferSizeMaxGrowth. "
				 "Using current system buffer size");

		socklen_t socklen = sizeof(unsigned int);
		unsigned int read_size;

		/* get current buffer size */
		getsockopt(nfct_fd(h), SOL_SOCKET,
			   SO_RCVBUF, &read_size, &socklen);

		CONFIG(netlink_buffer_size) = read_size;
	}

	dlog(LOG_NOTICE, "netlink event socket buffer size has been set "
			 "to %u bytes", CONFIG(netlink_buffer_size));

	return h;
}