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; }
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)); }
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)); }
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; }