int kern_bcache_init() { supsocket_t *sock; nl_bcache = nl_handle_alloc(); nl_disable_sequence_check(nl_bcache); nl_join_groups(nl_bcache, ~0); nl_cb_set(nl_handle_get_cb(nl_bcache), NL_CB_VALID, NL_CB_CUSTOM, nl_bcache_event, NULL); if (nl_connect(nl_bcache, NETLINK_IP6MBLTY) < 0) { debug_log(1, "nl_connect(NETLINK_IP6MBLTY) failed: %s.\n", strerror(errno)); nl_close(nl_bcache); nl_bcache = NULL; return -1; } fcntl(nl_handle_get_fd(nl_bcache), F_SETFL, O_NONBLOCK); sock = support_register_socket(nl_handle_get_fd(nl_bcache), nl_bcache_events_waiting, NULL, NULL); sock->mode = SUPSOCKET_READ; return 0; }
static struct nl_handle *init_netlink(void) { struct nl_handle *handle; int ret, multicast_id; handle = nl_handle_alloc(); if (!handle){ elog("Cannot allocate netlink handle!\n"); return NULL; } nl_disable_sequence_check(handle); ret = genl_connect(handle); if (ret < 0){ elog("Cannot connect to netlink socket\n"); return NULL; } /* familyid = genl_ctrl_resolve(handle, SAMPLE_NL_FAMILY_NAME); if (!familyid){ elog("Cannot resolve family name(%s)\n", SAMPLE_NL_FAMILY_NAME); return NULL; } dlog("familyid %d\n", familyid); */ multicast_id = nl_get_multicast_id(handle, SAMPLE_NL_FAMILY_NAME, SAMPLE_NL_GRP_NAME); if (multicast_id < 0){ elog("Cannot resolve grp name(%d)\n", SAMPLE_NL_GRP_NAME); return NULL; } ret = nl_socket_add_membership(handle, multicast_id); if (ret < 0){ elog("Cannot join fs multicast group\n"); return NULL; } ret = nl_socket_modify_cb(handle, NL_CB_VALID, NL_CB_CUSTOM, sample_nl_cb, NULL); if (ret < 0){ elog("Cannot register callback for" " netlink messages\n"); return NULL; } return handle; }
int usnic_rtnl_sk_alloc(struct usnic_rtnl_sk **p_sk) { struct usnic_rtnl_sk *unlsk; struct nl_handle *nlh; int err; unlsk = calloc(1, sizeof(*unlsk)); if (!unlsk) { usnic_err("Failed to allocate usnic_rtnl_sk struct\n"); return -ENOMEM; } nlh = nl_handle_alloc(); if (!nlh) { usnic_err("Failed to allocate nl handle\n"); err = -ENOMEM; goto err_free_unlsk; } err = nl_connect(nlh, NETLINK_ROUTE); if (err < 0) { usnic_err("Failed to connnect netlink route socket\n"); goto err_free_nlh; } nl_disable_sequence_check(nlh); err = nl_set_recv_timeout(nlh); if (err < 0) goto err_close_nlh; unlsk->nlh = nlh; unlsk->seq = time(NULL); *p_sk = unlsk; return 0; err_close_nlh: nl_close(nlh); err_free_nlh: nl_handle_destroy(nlh); err_free_unlsk: free(unlsk); return err; }
static void obj_input(struct nl_object *obj, void *arg) { struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) obj; struct nl_dump_params dp = { .dp_type = NL_DUMP_STATS, .dp_fd = stdout, .dp_dump_msgtype = 1, }; nfnl_queue_msg_set_verdict(msg, NF_ACCEPT); nl_object_dump(obj, &dp); nfnl_queue_msg_send_verdict(nfnlh, msg); } static int event_input(struct nl_msg *msg, void *arg) { if (nl_msg_parse(msg, &obj_input, NULL) < 0) fprintf(stderr, "<<EVENT>> Unknown message type\n"); /* Exit nl_recvmsgs_def() and return to the main select() */ return NL_STOP; } int main(int argc, char *argv[]) { struct nl_handle *rtnlh; struct nl_cache *link_cache; struct nfnl_queue *queue; enum nfnl_queue_copy_mode copy_mode; uint32_t copy_range; int err = 1; int family; if (nltool_init(argc, argv) < 0) return -1; nfnlh = nltool_alloc_handle(); if (nfnlh == NULL) return -1; nl_disable_sequence_check(nfnlh); nl_socket_modify_cb(nfnlh, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) { printf("Usage: nf-queue family group [ copy_mode ] " "[ copy_range ]\n"); return 2; } if (nfnl_connect(nfnlh) < 0) { fprintf(stderr, "%s\n", nl_geterror()); goto errout; } family = nl_str2af(argv[1]); if (family == AF_UNSPEC) { fprintf(stderr, "Unknown family: %s\n", argv[1]); goto errout; } nfnl_queue_pf_unbind(nfnlh, family); if (nfnl_queue_pf_bind(nfnlh, family) < 0) { fprintf(stderr, "%s\n", nl_geterror()); goto errout; } queue = nfnl_queue_alloc(); if (queue == NULL) { fprintf(stderr, "%s\n", nl_geterror()); goto errout; } nfnl_queue_set_group(queue, atoi(argv[2])); copy_mode = NFNL_QUEUE_COPY_PACKET; if (argc > 3) { copy_mode = nfnl_queue_str2copy_mode(argv[3]); if (copy_mode < 0) { fprintf(stderr, "%s\n", nl_geterror()); goto errout; } } nfnl_queue_set_copy_mode(queue, copy_mode); copy_range = 0xFFFF; if (argc > 4) copy_range = atoi(argv[4]); nfnl_queue_set_copy_range(queue, copy_range); if (nfnl_queue_create(nfnlh, queue) < 0) { fprintf(stderr, "%s\n", nl_geterror()); goto errout; } rtnlh = nltool_alloc_handle(); if (rtnlh == NULL) { goto errout_close; } if (nl_connect(rtnlh, NETLINK_ROUTE) < 0) { fprintf(stderr, "%s\n", nl_geterror()); goto errout; } if ((link_cache = rtnl_link_alloc_cache(rtnlh)) == NULL) { fprintf(stderr, "%s\n", nl_geterror()); goto errout_close; } nl_cache_mngt_provide(link_cache); while (1) { fd_set rfds; int nffd, rtfd, maxfd, retval; FD_ZERO(&rfds); maxfd = nffd = nl_socket_get_fd(nfnlh); FD_SET(nffd, &rfds); rtfd = nl_socket_get_fd(rtnlh); FD_SET(rtfd, &rfds); if (maxfd < rtfd) maxfd = rtfd; /* wait for an incoming message on the netlink socket */ retval = select(maxfd+1, &rfds, NULL, NULL, NULL); if (retval) { if (FD_ISSET(nffd, &rfds)) nl_recvmsgs_default(nfnlh); if (FD_ISSET(rtfd, &rfds)) nl_recvmsgs_default(rtnlh); } } nl_cache_mngt_unprovide(link_cache); nl_cache_free(link_cache); nfnl_queue_put(queue); nl_close(rtnlh); nl_handle_destroy(rtnlh); errout_close: nl_close(nfnlh); nl_handle_destroy(nfnlh); errout: return err; }
/** * Setups generic netlink connection with the kernel module and retrieves assocaited family id * * @return 0 on success */ static int initialize_netlink_family(void) { struct nl_handle* hndl; struct nl_msg* msg = NULL; struct nl_msg *ans_msg = NULL; struct nlmsghdr *nl_hdr; struct genlmsghdr* genl_hdr; struct nlattr *nla; int ret_val = 0; hndl = nl_handle_alloc(); nl_set_buffer_size(hndl, 15000000, 15000000); //nl_handle_set_peer_pid(hndl, 0); //nl_set_passcred(hndl, 1); nl_disable_sequence_check(hndl); if ( (ret_val=nl_connect(hndl, NETLINK_GENERIC)) ) goto init_return; nl_set_buffer_size(hndl, 15000000, 15000000); if ( (ret_val=prepare_request_message(hndl, CTRL_CMD_GETFAMILY, GENL_ID_CTRL, &msg) ) != 0 ) { goto init_return; } ret_val = nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, "DIRECTORCHNL"); if (ret_val != 0) goto init_return; if ( (ret_val = send_request_message(hndl, msg, 0) ) != 0 ) goto init_return; if ( (ret_val = read_message(hndl, &ans_msg) ) != 0 ) goto init_return; genl_hdr = nl_msg_genlhdr(ans_msg); if (genl_hdr == NULL || genl_hdr->cmd != CTRL_CMD_NEWFAMILY) { ret_val = -EBADMSG; goto init_return; } nla = nlmsg_find_attr(nlmsg_hdr(ans_msg), sizeof(struct genlmsghdr), CTRL_ATTR_FAMILY_ID); if (nla == NULL) { ret_val = -EBADMSG; goto init_return; } state.gnl_fid = nla_get_u16(nla); if (state.gnl_fid == 0) { ret_val = -EBADMSG; goto init_return; } state.handle = hndl; return 0; init_return: nlmsg_free(ans_msg); if ( state.handle == NULL ) { nl_close(hndl); nl_handle_destroy(hndl); } return -EINVAL; }
int netlink_wrapper::open_channel() { auto_unlocker lock(m_cache_lock); nl_logdbg("opening netlink channel"); /* // build to subscriptions groups mask for indicating what type of events the kernel will send on channel unsigned subscriptions = ~RTMGRP_TC; if (netlink_route_group_mask & nlgrpLINK) { subscriptions |= (1 << (RTNLGRP_LINK - 1)); } if (netlink_route_group_mask & nlgrpADDRESS) { if (!m_preferred_family || m_preferred_family == AF_INET) subscriptions |= (1 << (RTNLGRP_IPV4_IFADDR - 1)); if (!m_preferred_family || m_preferred_family == AF_INET6) subscriptions |= (1 << (RTNLGRP_IPV6_IFADDR - 1)); } if (netlink_route_group_mask & nlgrpROUTE) { if (!m_preferred_family || m_preferred_family == AF_INET) subscriptions |= (1 << (RTNLGRP_IPV4_ROUTE - 1)); if (!m_preferred_family || m_preferred_family == AF_INET6) subscriptions |= (1 << (RTNLGRP_IPV4_ROUTE - 1)); } if (netlink_route_group_mask & nlgrpPREFIX) { if (!m_preferred_family || m_preferred_family == AF_INET6) subscriptions |= (1 << (RTNLGRP_IPV6_PREFIX - 1)); } if (netlink_route_group_mask & nlgrpNEIGH) { subscriptions |= (1 << (RTNLGRP_NEIGH - 1)); } */ // Allocate a new netlink handle m_handle = nl_handle_alloc(); BULLSEYE_EXCLUDE_BLOCK_START if (m_handle == NULL) { nl_logerr("failed to allocate netlink handle, nl_errno=%d", nl_get_errno()); return -1; } BULLSEYE_EXCLUDE_BLOCK_END // set internal structure to pass the handle with callbacks from netlink g_nl_rcv_arg.handle = m_handle; // if multiple handles being allocated then a unique netlink PID need to be provided // If port is 0, a unique port identifier will be generated automatically as a unique PID nl_socket_set_local_port(m_handle, 0); //Disables checking of sequence numbers on the netlink handle. //This is required to allow messages to be processed which were not requested by a preceding request message, e.g. netlink events. nl_disable_sequence_check(m_handle); //joining group //nl_join_groups(m_handle, 0); // Allocate a new cache manager for RTNETLINK // NL_AUTO_PROVIDE = automatically provide the caches added to the manager. m_mngr = nl_cache_mngr_alloc(m_handle, NETLINK_ROUTE, NL_AUTO_PROVIDE); BULLSEYE_EXCLUDE_BLOCK_START if (!m_mngr) { nl_logerr("Fail to allocate cac he manager"); return -1; } BULLSEYE_EXCLUDE_BLOCK_END nl_logdbg("netlink socket is open"); m_cache_neigh = nl_cache_mngr_add(m_mngr, "route/neigh", neigh_cache_callback); m_cache_link = nl_cache_mngr_add(m_mngr, "route/link", link_cache_callback); m_cache_route = nl_cache_mngr_add(m_mngr, "route/route", route_cache_callback); // set custom callback for every message to update message nl_socket_modify_cb(m_handle, NL_CB_MSG_IN, NL_CB_CUSTOM, nl_msg_rcv_cb ,NULL); // set the socket non-blocking BULLSEYE_EXCLUDE_BLOCK_START if (nl_socket_set_nonblocking(m_handle)) { nl_logerr("Failed to set the socket non-blocking"); return -1; } BULLSEYE_EXCLUDE_BLOCK_END return 0; }
static void obj_input(struct nl_object *obj, void *arg) { struct nl_dump_params dp = { .dp_type = NL_DUMP_STATS, .dp_fd = stdout, .dp_dump_msgtype = 1, }; nl_object_dump(obj, &dp); } static int event_input(struct nl_msg *msg, void *arg) { if (nl_msg_parse(msg, &obj_input, NULL) < 0) fprintf(stderr, "<<EVENT>> Unknown message type\n"); /* Exit nl_recvmsgs_def() and return to the main select() */ return NL_STOP; } int main(int argc, char *argv[]) { struct nl_handle *nlh; int err = 1; int i, idx; static const struct { enum nfnetlink_groups gr_id; const char* gr_name; } known_groups[] = { { NFNLGRP_CONNTRACK_NEW, "ct-new" }, { NFNLGRP_CONNTRACK_UPDATE, "ct-update" }, { NFNLGRP_CONNTRACK_DESTROY, "ct-destroy" }, { NFNLGRP_NONE, NULL } }; if (nltool_init(argc, argv) < 0) return -1; nlh = nltool_alloc_handle(); if (nlh == NULL) return -1; nl_disable_sequence_check(nlh); nl_socket_modify_cb(nlh, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); if (argc > 1 && !strcasecmp(argv[1], "-h")) { printf("Usage: nf-monitor [<groups>]\n"); printf("Known groups:"); for (i = 0; known_groups[i].gr_id != NFNLGRP_NONE; i++) printf(" %s", known_groups[i].gr_name); printf("\n"); return 2; } if (nfnl_connect(nlh) < 0) { fprintf(stderr, "%s\n", nl_geterror()); goto errout; } for (idx = 1; argc > idx; idx++) { for (i = 0; known_groups[i].gr_id != NFNLGRP_NONE; i++) { if (!strcmp(argv[idx], known_groups[i].gr_name)) { if (nl_socket_add_membership(nlh, known_groups[i].gr_id) < 0) { fprintf(stderr, "%s: %s\n", argv[idx], nl_geterror()); goto errout; } break; } } if (known_groups[i].gr_id == NFNLGRP_NONE) fprintf(stderr, "Warning: Unknown group: %s\n", argv[idx]); } while (1) { fd_set rfds; int fd, retval; fd = nl_socket_get_fd(nlh); FD_ZERO(&rfds); FD_SET(fd, &rfds); /* wait for an incoming message on the netlink socket */ retval = select(fd+1, &rfds, NULL, NULL, NULL); if (retval) { /* FD_ISSET(fd, &rfds) will be true */ nl_recvmsgs_default(nlh); } } nl_close(nlh); errout: return err; }
static gboolean open_connection (NMNetlinkListener *listener, GError **error) { NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener); int fd; GError *channel_error = NULL; GIOFlags channel_flags; g_return_val_if_fail (priv->io_channel == NULL, FALSE); priv->nlh_cb = nl_cb_alloc (NL_CB_DEFAULT); priv->nlh = nl_handle_alloc_cb (priv->nlh_cb); if (!priv->nlh) { g_set_error (error, NM_NETLINK_LISTENER_ERROR, NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_HANDLE, _("unable to allocate netlink handle: %s"), nl_geterror ()); goto error; } nl_disable_sequence_check (priv->nlh); nl_socket_modify_cb (priv->nlh, NL_CB_VALID, NL_CB_CUSTOM, netlink_event_input, listener); if (nl_connect (priv->nlh, NETLINK_ROUTE) < 0) { g_set_error (error, NM_NETLINK_LISTENER_ERROR, NM_NETLINK_LISTENER_ERROR_NETLINK_CONNECT, _("unable to connect to netlink: %s"), nl_geterror ()); goto error; } fd = nl_socket_get_fd (priv->nlh); priv->io_channel = g_io_channel_unix_new (fd); g_io_channel_set_encoding (priv->io_channel, NULL, &channel_error); /* Encoding is NULL, so no conversion error can possibly occur */ g_assert (channel_error == NULL); g_io_channel_set_close_on_unref (priv->io_channel, TRUE); channel_flags = g_io_channel_get_flags (priv->io_channel); channel_error = NULL; g_io_channel_set_flags (priv->io_channel, channel_flags | G_IO_FLAG_NONBLOCK, &channel_error); if (channel_error != NULL) { g_propagate_error (error, channel_error); goto error; } priv->event_id = g_io_add_watch (priv->io_channel, (NM_NETLINK_LISTENER_EVENT_CONDITIONS | NM_NETLINK_LISTENER_ERROR_CONDITIONS | NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS), nm_netlink_listener_event_handler, listener); return TRUE; error: if (priv->io_channel) close_connection (listener); if (priv->nlh) { nl_handle_destroy (priv->nlh); priv->nlh = NULL; } if (priv->nlh_cb) { nl_cb_put (priv->nlh_cb); priv->nlh_cb = NULL; } return FALSE; }