static gboolean nlh_setup (struct nl_sock *nlh, nl_recvmsg_msg_cb_t valid_func, gpointer cb_data, GError **error) { int err; nl_socket_modify_cb (nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, cb_data); if (valid_func) nl_socket_modify_cb (nlh, NL_CB_VALID, NL_CB_CUSTOM, valid_func, cb_data); err = nl_connect (nlh, NETLINK_ROUTE); if (err < 0) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, _("unable to connect to netlink for monitoring link status: %s"), nl_geterror (err)); return FALSE; } /* Enable unix socket peer credentials which we use for verifying that the * sender of the message is actually the kernel. */ if (nl_socket_set_passcred (nlh, 1) < 0) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, _("unable to enable netlink handle credential passing: %s"), nl_geterror (err)); return FALSE; } return TRUE; }
void CNL80211::scan() { //Get interface index for device: unsigned int devidx = if_nametoindex(m_ifname.toAscii().constData()); if (devidx == 0) { emit message("Could not get interface index"); return; } //Allocate a new netlink message nl_msg * msg; msg = nlmsg_alloc(); if (!msg) { emit message("Could not allocate netlink message"); return; } //allocate the callback function with default verbosity // nl_cb * cb = nl_cb_alloc(NL_CB_DEFAULT); // if (!cb) { // emit message("Could not allocate netlink callback"); // nlmsg_free(msg); // return; // } nl_socket_modify_cb(m_nlSocket, NL_CB_VALID, NL_CB_CUSTOM, &cbForScanResults, this); genlmsg_put(msg, 0, 0, genl_family_get_id(m_nlFamily), 0, (NLM_F_REQUEST | NLM_F_DUMP), NL80211_CMD_GET_SCAN, 0); //Set the interface we want to operate on nla_put_u32(msg, NL80211_ATTR_IFNAME,devidx); //hier kommt noch was rein //Send the message nl_send_auto_complete(m_nlSocket,msg); nlmsg_free(msg); }
int iface_mon_start(iface_mon_cb cb) { int err; iface_mon_sock = nl_socket_alloc(); if (!iface_mon_sock) { fprintf(stderr, "Failed to allocate netlink socket.\n"); return -ENOMEM; } nl_socket_disable_seq_check(iface_mon_sock); nl_socket_modify_cb(iface_mon_sock, NL_CB_VALID, NL_CB_CUSTOM, iface_mon_handler, cb); if (nl_connect(iface_mon_sock, NETLINK_ROUTE)) { fprintf(stderr, "Failed to connect to generic netlink.\n"); err = -ENOLINK; goto out_handle_destroy; } nl_socket_add_membership(iface_mon_sock, RTNLGRP_LINK); return 0; out_handle_destroy: nl_socket_free(iface_mon_sock); return err; }
int netlink_request(void *request, __u16 request_len, int (*cb)(struct nl_msg *, void *), void *cb_arg) { struct nl_sock *sk; enum nl_cb_type callbacks[] = { NL_CB_VALID, NL_CB_FINISH, NL_CB_ACK }; int i; int error; sk = nl_socket_alloc(); if (!sk) { log_err(ERR_ALLOC_FAILED, "Could not allocate a socket; cannot speak to the NAT64."); return -ENOMEM; } for (i = 0; i < (sizeof(callbacks) / sizeof(callbacks[0])); i++) { error = nl_socket_modify_cb(sk, callbacks[i], NL_CB_CUSTOM, cb, cb_arg); if (error < 0) { log_err(ERR_NETLINK, "Could not register response handler. " "I won't be able to parse the NAT64's response, so I won't send the request.\n" "Netlink error message: %s (Code %d)", nl_geterror(error), error); goto fail_free; } } error = nl_connect(sk, NETLINK_USERSOCK); if (error < 0) { log_err(ERR_NETLINK, "Could not bind the socket to the NAT64.\n" "Netlink error message: %s (Code %d)", nl_geterror(error), error); goto fail_free; } error = nl_send_simple(sk, MSG_TYPE_NAT64, 0, request, request_len); if (error < 0) { log_err(ERR_NETLINK, "Could not send the request to the NAT64 (is it really up?).\n" "Netlink error message: %s (Code %d)", nl_geterror(error), error); goto fail_close; } error = nl_recvmsgs_default(sk); if (error < 0) { log_err(ERR_NETLINK, "%s (System error %d)", nl_geterror(error), error); goto fail_close; } nl_close(sk); nl_socket_free(sk); return 0; fail_close: nl_close(sk); /* Fall through. */ fail_free: nl_socket_free(sk); return -EINVAL; }
int netlink_request(void *request, __u32 request_len, jool_response_cb cb, void *cb_arg) { struct nl_msg *msg; struct response_cb callback = { .cb = cb, .arg = cb_arg }; int error; error = nl_socket_modify_cb(sk, NL_CB_MSG_IN, NL_CB_CUSTOM, response_handler, &callback); if (error < 0) { log_err("Could not register response handler."); log_err("I will not be able to parse Jool's response, so I won't send the request."); return netlink_print_error(error); } msg = nlmsg_alloc(); if (!msg) { log_err("Could not allocate the message to the kernel; it seems we're out of memory."); return -ENOMEM; } if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family, 0, 0, JOOL_COMMAND, 1)) { log_err("Unknown error building the packet to the kernel."); nlmsg_free(msg); return -EINVAL; } error = nla_put(msg, ATTR_DATA, request_len, request); if (error) { log_err("Could not write on the packet to kernelspace."); nlmsg_free(msg); return netlink_print_error(error); } error = nl_send_auto(sk, msg); nlmsg_free(msg); if (error < 0) { log_err("Could not dispatch the request to kernelspace."); return netlink_print_error(error); } error = nl_recvmsgs_default(sk); if (error < 0) { if (error_handler_called) { error_handler_called = false; return error; } log_err("Error receiving the kernel module's response."); return netlink_print_error(error); } return 0; }
static bool nl_new(struct dionaea *d) { g_debug("%s", __PRETTY_FUNCTION__); nl_runtime.sock = nl_socket_alloc(); struct nl_sock *sock = nl_runtime.sock; nl_socket_disable_seq_check(sock); nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, nl_event_input, NULL); nl_join_groups(sock, RTMGRP_LINK); int err; if ( (err = nl_connect(sock, NETLINK_ROUTE)) < 0) { g_error("Could not connect netlink (%s)", nl_geterror(err)); } nl_socket_add_membership(sock, RTNLGRP_LINK); nl_socket_add_membership(sock, RTNLGRP_NEIGH); nl_socket_add_membership(sock, RTNLGRP_IPV4_IFADDR); nl_socket_add_membership(sock, RTNLGRP_IPV6_IFADDR); if( (err=rtnl_neigh_alloc_cache(sock, &nl_runtime.neigh_cache)) != 0 ) { g_error("Could not allocate neigh cache! (%s)", nl_geterror(err)); } #if LIBNL_RTNL_LINK_ALLOC_CACHE_ARGC == 3 if( (err=rtnl_link_alloc_cache(sock, AF_UNSPEC, &nl_runtime.link_cache)) != 0 ) #elif LIBNL_RTNL_LINK_ALLOC_CACHE_ARGC == 2 if( (err=rtnl_link_alloc_cache(sock, &nl_runtime.link_cache)) != 0 ) #endif { g_error("Could not allocate link cache! (%s)", nl_geterror(err)); } if( (err=rtnl_addr_alloc_cache(sock, &nl_runtime.addr_cache)) != 0 ) { g_error("Could not allocate addr cache! (%s)", nl_geterror(err)); } nl_cache_mngt_provide(nl_runtime.neigh_cache); nl_cache_mngt_provide(nl_runtime.link_cache); nl_cache_mngt_provide(nl_runtime.addr_cache); nl_runtime.ihandler = ihandler_new("dionaea.connection.*.accept", nl_ihandler_cb, NULL); ev_io_init(&nl_runtime.io_in, nl_io_in_cb, nl_socket_get_fd(sock), EV_READ); ev_io_start(g_dionaea->loop, &nl_runtime.io_in); nl_runtime.link_addr_cache = g_hash_table_new(g_int_hash, g_int_equal); nl_cache_foreach(nl_runtime.link_cache, nl_obj_input, NULL); nl_cache_foreach(nl_runtime.addr_cache, nl_obj_input, NULL); return true; }
int ipvs_nl_send_message(struct nl_msg *msg, nl_recvmsg_msg_cb_t func, void *arg) { int err = EINVAL; sock = nl_socket_alloc(); if (!sock) { nlmsg_free(msg); return -1; } if (genl_connect(sock) < 0) goto fail_genl; family = genl_ctrl_resolve(sock, IPVS_GENL_NAME); if (family < 0) goto fail_genl; /* To test connections and set the family */ if (msg == NULL) { nl_socket_free(sock); sock = NULL; return 0; } if (nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, func, arg) != 0) goto fail_genl; if (nl_send_auto_complete(sock, msg) < 0) goto fail_genl; if ((err = -nl_recvmsgs_default(sock)) > 0) goto fail_genl; nlmsg_free(msg); nl_socket_free(sock); return 0; fail_genl: nl_socket_free(sock); sock = NULL; nlmsg_free(msg); errno = err; #ifndef FALLBACK_LIBNL1 errno = nlerr2syserr(err); #endif return -1; }
static int get_interface_info(struct config *conf) { struct nl_msg *msg; nl802154_init(conf); /* Build and send message */ nl_socket_modify_cb(conf->nl_sock, NL_CB_VALID, NL_CB_CUSTOM, nl_msg_cb, conf); msg = nlmsg_alloc(); genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, conf->nl802154_id, 0, NLM_F_DUMP, NL802154_CMD_GET_INTERFACE, 0); nla_put_string(msg, NL802154_ATTR_IFNAME, "conf->interface"); nl_send_sync(conf->nl_sock, msg); nl802154_cleanup(conf); return 0; }
static void show(void) { struct nl_msg *msg = nlmsg_alloc(); struct ovs_header *hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ovs_datapath_family, sizeof(*hdr), NLM_F_DUMP, OVS_DP_CMD_GET, OVS_DATAPATH_VERSION); hdr->dp_ifindex = 0; if (nl_send_auto(sk, msg) < 0) { abort(); } nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, show_datapath__, NULL); nl_recvmsgs_default(sk); }
int setup_socket(struct nl_sock *sk, struct options *opt) { int ret; nl_socket_disable_seq_check(sk); if((ret = nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, netlink_msg_handler, opt)) < 0) return ret; if((ret = nl_connect(sk, NETLINK_ROUTE)) < 0) return ret; if((ret = nl_socket_add_memberships(sk, RTNLGRP_TC_STATS, 0)) < 0) return ret; return 0; }
/** * Query the wireless device for information * about the current connection */ bool wireless_network::query(bool accumulate) { if (!network::query(accumulate)) { return false; } struct nl_sock* sk = nl_socket_alloc(); if (sk == nullptr) { return false; } if (genl_connect(sk) < 0) { return false; } int driver_id = genl_ctrl_resolve(sk, "nl80211"); if (driver_id < 0) { nl_socket_free(sk); return false; } if (nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, scan_cb, this) != 0) { nl_socket_free(sk); return false; } struct nl_msg* msg = nlmsg_alloc(); if (msg == nullptr) { nl_socket_free(sk); return false; } if ((genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0) == nullptr) || nla_put_u32(msg, NL80211_ATTR_IFINDEX, m_ifid) < 0) { nlmsg_free(msg); nl_socket_free(sk); return false; } // nl_send_sync always frees msg if (nl_send_sync(sk, msg) < 0) { nl_socket_free(sk); return false; } nl_socket_free(sk); return true; }
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 nf10_reg_wr(uint32_t addr, uint32_t val) { struct nl_msg *msg; int err; err = driver_connect(); if(err) return err; msg = nlmsg_alloc(); if(msg == NULL) { driver_disconnect(); return -NLE_NOMEM; } /* genlmsg_put will fill in the fields of the nlmsghdr and the genlmsghdr. */ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, nf10_genl_family, 0, 0, NF10_GENL_C_REG_WR, NF10_GENL_FAMILY_VERSION); nla_put_u32(msg, NF10_GENL_A_ADDR32, addr); nla_put_u32(msg, NF10_GENL_A_REGVAL32, val); /* nl_send_auto will automatically fill in the PID and the sequence number, * and also add an NLM_F_REQUEST flag. It will also add an NLM_F_ACK * flag unless the netlink socket has the NL_NO_AUTO_ACK flag set. */ err = nl_send_auto(nf10_genl_sock, msg); if(err < 0) { nlmsg_free(msg); driver_disconnect(); return err; } nlmsg_free(msg); nl_socket_modify_cb(nf10_genl_sock, NL_CB_ACK, NL_CB_CUSTOM, nf10_reg_wr_recv_ack_cb, NULL); /* FIXME: this function will return even if there's no ACK in the buffer. I.E. it doesn't * seem to wait for the ACK to be received... Ideally we'd have the behavior that getting an * ACK tells us everything is OK, otherwise we time out on waiting for an ACK and tell this * to the user. */ err = nl_recvmsgs_default(nf10_genl_sock); driver_disconnect(); return err; }
static void show_vports__(int dp_ifindex) { struct nl_msg *msg = nlmsg_alloc(); struct ovs_header *hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ovs_vport_family, sizeof(*hdr), NLM_F_DUMP, OVS_VPORT_CMD_GET, OVS_VPORT_VERSION); hdr->dp_ifindex = dp_ifindex; if (nl_send_auto(sk2, msg) < 0) { abort(); } nl_socket_modify_cb(sk2, NL_CB_VALID, NL_CB_CUSTOM, show_vport__, NULL); nl_recvmsgs_default(sk2); nlmsg_free(msg); }
/** * Allocate new cache manager * @arg sk Netlink socket. * @arg protocol Netlink Protocol this manager is used for * @arg flags Flags * @arg result Result pointer * * @return 0 on success or a negative error code. */ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, struct nl_cache_mngr **result) { struct nl_cache_mngr *mngr; int err = -NLE_NOMEM; if (sk == NULL) BUG(); mngr = calloc(1, sizeof(*mngr)); if (!mngr) goto errout; mngr->cm_handle = sk; mngr->cm_nassocs = 32; mngr->cm_protocol = protocol; mngr->cm_flags = flags; mngr->cm_assocs = calloc(mngr->cm_nassocs, sizeof(struct nl_cache_assoc)); if (!mngr->cm_assocs) goto errout; nl_socket_modify_cb(mngr->cm_handle, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); /* Required to receive async event notifications */ nl_socket_disable_seq_check(mngr->cm_handle); if ((err = nl_connect(mngr->cm_handle, protocol) < 0)) goto errout; if ((err = nl_socket_set_nonblocking(mngr->cm_handle) < 0)) goto errout; NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", mngr, protocol, mngr->cm_nassocs); *result = mngr; return 0; errout: nl_cache_mngr_free(mngr); return err; }
static struct nl_sock * setup_socket (void) { struct nl_sock *sk; int err; sk = nl_socket_alloc (); g_return_val_if_fail (sk, NULL); /* Only ever accept messages from kernel */ err = nl_socket_modify_cb (sk, NL_CB_MSG_IN, NL_CB_CUSTOM, verify_source, NULL); g_assert (!err); err = nl_connect (sk, NETLINK_XFRM); g_assert (!err); err = nl_socket_set_passcred (sk, 1); g_assert (!err); return sk; }
int nf10_reg_rd(uint32_t addr, uint32_t *val_ptr) { struct nl_msg *msg; int err; err = driver_connect(); if(err) return err; msg = nlmsg_alloc(); if(msg == NULL) { driver_disconnect(); return -NLE_NOMEM; } /* genlmsg_put will fill in the fields of the nlmsghdr and the genlmsghdr. */ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, nf10_genl_family, 0, 0, NF10_GENL_C_REG_RD, NF10_GENL_FAMILY_VERSION); nla_put_u32(msg, NF10_GENL_A_ADDR32, addr); /* nl_send_auto will automatically fill in the PID and the sequence number, * and also add an NLM_F_REQUEST flag. It will also add an NLM_F_ACK * flag unless the netlink socket has the NL_NO_AUTO_ACK flag set. */ err = nl_send_auto(nf10_genl_sock, msg); if(err < 0) { nlmsg_free(msg); driver_disconnect(); return err; } nlmsg_free(msg); nl_socket_modify_cb(nf10_genl_sock, NL_CB_VALID, NL_CB_CUSTOM, nf10_reg_rd_recv_msg_cb, (void*)val_ptr); err = nl_recvmsgs_default(nf10_genl_sock); driver_disconnect(); return err; }
int main() { /* create socket */ struct nl_sock *sk = NULL; sk = nl_socket_alloc(); genl_connect(sk); nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, get_cw, NULL); /* setup message */ int driver_id, if_index; struct nl_msg *msg = NULL; driver_id = genl_ctrl_resolve(sk, "nl80211"); if_index = if_nametoindex("wlan0"); msg = nlmsg_alloc(); genlmsg_put(msg, 0, 0, driver_id, 0, 0, NL80211_CMD_GET_WIPHY, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_index); //struct nlattr *nested; //nested = nla_nest_start(msg,NL80211_ATTR_WIPHY_TXQ_PARAMS); //NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMIN,cw_min); //NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMAX,cw_max); //nla_nest_end(msg,nested); /* send/recv/ack */ int r; r = nl_send_auto_complete(sk, msg); printf("atlasd: nl_send_auto_complete returned %d\n", r); nl_recvmsgs_default(sk); nl_wait_for_ack(sk); nla_put_failure: /* from NLA_PUT_* macros */ fail: if (sk) nl_socket_free(sk); if (msg) nlmsg_free(msg); }
static void dump_flows(const char *datapath) { unsigned int dp_ifindex = if_nametoindex(datapath); if (dp_ifindex == 0) { fprintf(stderr, "Failed: no such datapath '%s'\n", datapath); exit(1); } struct nl_msg *msg = nlmsg_alloc(); struct ovs_header *hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ovs_flow_family, sizeof(*hdr), NLM_F_DUMP, OVS_FLOW_CMD_GET, OVS_FLOW_VERSION); hdr->dp_ifindex = dp_ifindex; if (nl_send_auto(sk2, msg) < 0) { abort(); } nl_socket_modify_cb(sk2, NL_CB_VALID, NL_CB_CUSTOM, show_kflow__, NULL); nl_recvmsgs_default(sk2); nlmsg_free(msg); }
int main (int argc, char **argv) { struct nl_sock *sk; int err; sk = setup_socket (); g_assert (sk); err = nl_send_simple (sk, XFRM_MSG_GETPOLICY, NLM_F_DUMP, NULL, 0); if (err < 0) { g_warning ("Error sending: %d %s", err, nl_geterror (err)); return 1; } nl_socket_modify_cb (sk, NL_CB_VALID, NL_CB_CUSTOM, parse_reply, NULL); err = nl_recvmsgs_default (sk); if (err < 0) { g_warning ("Error parsing: %d %s", err, nl_geterror (err)); return 1; } return 0; }
int main(int argc, char **argv) { int c; int i; int family; int group; struct nl_sock *nl; struct nl_msg *msg; char *dummy = NULL; /* Currently processed command info */ struct iz_cmd cmd; /* Parse options */ while (1) { #ifdef HAVE_GETOPT_LONG int opt_idx = -1; c = getopt_long(argc, argv, "d::vh", iz_long_opts, &opt_idx); #else c = getopt(argc, argv, "d::vh"); #endif if (c == -1) break; switch(c) { case 'd': if (optarg) { i = strtol(optarg, &dummy, 10); if (*dummy == '\0') iz_debug = nl_debug = i; else { fprintf(stderr, "Error: incorrect debug level: '%s'\n", optarg); exit(1); } } else iz_debug = nl_debug = 1; break; case 'v': printf( "iz " VERSION "\n" "Copyright (C) 2008, 2009 by Siemens AG\n" "License GPLv2 GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.\n" "This is free software: you are free to change and redistribute it.\n" "There is NO WARRANTY, to the extent permitted by law.\n" "\n" "Written by Dmitry Eremin-Solenikov, Sergey Lapin and Maxim Osipov\n"); return 0; case 'h': iz_help(argv[0]); return 0; default: iz_help(argv[0]); return 1; } } if (optind >= argc) { iz_help(argv[0]); return 1; } memset(&cmd, 0, sizeof(cmd)); cmd.argc = argc - optind; cmd.argv = argv + optind; /* Parse command */ cmd.desc = get_cmd(argv[optind]); if (!cmd.desc) { printf("Unknown command %s!\n", argv[optind]); return 1; } if (cmd.desc->parse) { i = cmd.desc->parse(&cmd); if (i == IZ_STOP_OK) { return 0; } else if (i == IZ_STOP_ERR) { printf("Command line parsing error!\n"); return 1; } } /* Prepare NL command */ nl = nl_socket_alloc(); if (!nl) { nl_perror(NLE_NOMEM, "Could not allocate NL handle"); return 1; } genl_connect(nl); family = genl_ctrl_resolve(nl, IEEE802154_NL_NAME); group = nl_get_multicast_id(nl, IEEE802154_NL_NAME, IEEE802154_MCAST_COORD_NAME); if (group < 0) { fprintf(stderr, "Could not get multicast group ID: %s\n", strerror(-group)); return 1; } nl_socket_add_membership(nl, group); iz_seq = nl_socket_use_seq(nl) + 1; nl_socket_modify_cb(nl, NL_CB_VALID, NL_CB_CUSTOM, iz_cb_valid, (void*)&cmd); nl_socket_modify_cb(nl, NL_CB_FINISH, NL_CB_CUSTOM, iz_cb_finish, (void*)&cmd); nl_socket_modify_cb(nl, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, iz_cb_seq_check, (void*)&cmd); /* Send request, if necessary */ if (cmd.desc->request) { msg = nlmsg_alloc(); if (!msg) { nl_perror(NLE_NOMEM, "Could not allocate NL message!\n"); /* FIXME: err */ return 1; } genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, cmd.flags, cmd.desc->nl_cmd, 1); if (cmd.desc->request(&cmd, msg) != IZ_CONT_OK) { printf("Request processing error!\n"); return 1; } dprintf(1, "nl_send_auto_complete\n"); nl_send_auto_complete(nl, msg); cmd.seq = nlmsg_hdr(msg)->nlmsg_seq; dprintf(1, "nlmsg_free\n"); nlmsg_free(msg); } /* Received message handling loop */ while (iz_exit == IZ_CONT_OK) { int err = nl_recvmsgs_default(nl); if (err != NLE_SUCCESS) { nl_perror(err, "Receive failed"); return 1; } } nl_close(nl); if (iz_exit == IZ_STOP_ERR) return 1; return 0; }
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; }
int opal_btl_usnic_nl_ip_rt_lookup(struct usnic_rtnl_sk *unlsk, const char *src_ifname, uint32_t src_addr, uint32_t dst_addr, int *metric) { struct nl_msg *nlm; struct rtmsg rmsg; struct nl_lookup_arg arg; int msg_cnt; int err; int oif; oif = if_nametoindex(src_ifname); if (0 == oif) { return errno; } arg.nh_addr = 0; arg.oif = oif; arg.found = 0; arg.replied = 0; arg.unlsk = unlsk; arg.msg_count = msg_cnt = 0; memset(&rmsg, 0, sizeof(rmsg)); rmsg.rtm_family = AF_INET; rmsg.rtm_dst_len = sizeof(dst_addr)*8; rmsg.rtm_src_len = sizeof(src_addr)*8; nlm = nlmsg_alloc_simple(RTM_GETROUTE, 0); nlmsg_append(nlm, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); nla_put_u32(nlm, RTA_DST, dst_addr); nla_put_u32(nlm, RTA_SRC, src_addr); err = rtnl_send_ack_disable(unlsk, nlm); nlmsg_free(nlm); if (err < 0) { usnic_err("Failed to send nl route message to kernel, " "error %s\n", nl_geterror()); return err; } err = nl_socket_modify_cb(unlsk->nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, rtnl_raw_parse_cb, &arg); if (err != 0) { usnic_err("Failed to setup callback function, error %s\n", nl_geterror()); return err; } while (!arg.replied) { err = nl_recvmsgs_default(unlsk->nlh); if (err < 0) { usnic_err("Failed to receive nl route message from " "kernel, error %s\n", nl_geterror()); return err; } /* * the return value of nl_recvmsgs_default does not tell * whether it returns because of successful read or socket * timeout. So we compare msg count before and after the call * to decide if no new message arrives. In such case, * this function needs to terminate to prevent the caller from * blocking forever * NL_CB_MSG_IN traps every received message, so * there should be no premature exit */ if (msg_cnt != arg.msg_count) msg_cnt = arg.msg_count; else break; } if (arg.found) { if (metric != NULL) { *metric = arg.metric; } return 0; } else { return -1; } }
static ni_socket_t * __ni_rtevent_sock_open(void) { unsigned int recv_buff_len = __ni_rtevent_config_recv_buff_len(); unsigned int mesg_buff_len = __ni_rtevent_config_mesg_buff_len(); ni_rtevent_handle_t *handle; ni_socket_t *sock; int fd, ret; if (!(handle = __ni_rtevent_handle_new())) { ni_error("Unable to allocate rtnetlink event handle: %m"); return NULL; } if (!(handle->nlsock = nl_socket_alloc())) { ni_error("Cannot allocate rtnetlink event socket: %m"); __ni_rtevent_handle_free(handle); return NULL; } /* * Modify the callback for processing valid messages... * We may pass some kind of data (event filter?) too... */ nl_socket_modify_cb(handle->nlsock, NL_CB_VALID, NL_CB_CUSTOM, __ni_rtevent_process_cb, NULL); /* Required to receive async event notifications */ nl_socket_disable_seq_check(handle->nlsock); if ((ret = nl_connect(handle->nlsock, NETLINK_ROUTE)) < 0) { ni_error("Cannot open rtnetlink: %s", nl_geterror(ret)); __ni_rtevent_handle_free(handle); return NULL; } /* Enable non-blocking processing */ nl_socket_set_nonblocking(handle->nlsock); fd = nl_socket_get_fd(handle->nlsock); if (!(sock = ni_socket_wrap(fd, SOCK_DGRAM))) { ni_error("Cannot wrap rtnetlink event socket: %m"); __ni_rtevent_handle_free(handle); return NULL; } if (recv_buff_len) { if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, (char *)&recv_buff_len, sizeof(recv_buff_len)) && setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buff_len, sizeof(recv_buff_len))) { ni_warn("Unable to set netlink event receive buffer to %u bytes: %m", recv_buff_len); } else { ni_info("Using netlink event receive buffer of %u bytes", recv_buff_len); } } if (mesg_buff_len) { if (nl_socket_set_msg_buf_size(handle->nlsock, mesg_buff_len)) { ni_warn("Unable to set netlink event message buffer to %u bytes", mesg_buff_len); } else { ni_info("Using netlink event message buffer of %u bytes", mesg_buff_len); } } sock->user_data = handle; sock->receive = __ni_rtevent_receive; sock->close = __ni_rtevent_close; sock->handle_error = __ni_rtevent_sock_error_handler; sock->release_user_data = __ni_rtevent_sock_release_data; return sock; }
int ompi_btl_usnic_nl_ip_rt_lookup(struct usnic_rtnl_sk *unlsk, const char *src_ifname, uint32_t src_addr, uint32_t dst_addr, int *metric) { struct nl_msg *nlm; struct rtmsg rmsg; struct nl_lookup_arg arg; int msg_cnt; int err; int oif; oif = if_nametoindex(src_ifname); if (0 == oif) { return errno; } arg.nh_addr = 0; arg.oif = oif; arg.found = 0; arg.replied = 0; arg.unlsk = unlsk; arg.msg_count = msg_cnt = 0; memset(&rmsg, 0, sizeof(rmsg)); rmsg.rtm_family = AF_INET; rmsg.rtm_dst_len = sizeof(dst_addr)*8; rmsg.rtm_src_len = sizeof(src_addr)*8; nlm = nlmsg_alloc_simple(RTM_GETROUTE, 0); nlmsg_append(nlm, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); nla_put_u32(nlm, RTA_DST, dst_addr); nla_put_u32(nlm, RTA_SRC, src_addr); err = rtnl_send_ack_disable(unlsk, nlm); nlmsg_free(nlm); if (err < 0) { usnic_err("Failed to send rtnl query %s\n", nl_geterror(err)); return err; } err = nl_socket_modify_cb(unlsk->sock, NL_CB_MSG_IN, NL_CB_CUSTOM, rtnl_raw_parse_cb, &arg); if (err != 0) { usnic_err("Failed to setup callback function, error %s\n", nl_geterror(err)); return err; } while (!arg.replied) { err = nl_recvmsgs_default(unlsk->sock); if (err < 0) { /* err will be returned as -NLE_AGAIN if the socket times out */ usnic_err("Failed to receive rtnl query results %s\n", nl_geterror(err)); return err; } } if (arg.found) { if (metric != NULL) { *metric = arg.metric; } return 0; } else { return -1; } }
int main(int argc, char *argv[]) { struct nl_handle *nlh; struct nl_cache *link_cache, *route_cache; struct nl_addr *dst; struct rtnl_route *route; struct ip_lookup_res res; struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_FULL }; int err = 1; if (argc < 2 || !strcmp(argv[1], "-h")) print_usage(); if (nltool_init(argc, argv) < 0) goto errout; nlh = nltool_alloc_handle(); if (!nlh) goto errout; route = rtnl_route_alloc(); if (!route) goto errout_free_handle; if (nltool_connect(nlh, NETLINK_ROUTE) < 0) goto errout_free_route; link_cache = nltool_alloc_link_cache(nlh); if (!link_cache) goto errout_close; dst = nltool_addr_parse(argv[1]); if (!dst) goto errout_link_cache; route_cache = nltool_alloc_route_cache(nlh); if (!route_cache) goto errout_addr_put; { struct nl_msg *m; struct rtmsg rmsg = { .rtm_family = nl_addr_get_family(dst), .rtm_dst_len = nl_addr_get_prefixlen(dst), }; m = nlmsg_alloc_simple(RTM_GETROUTE, 0); nlmsg_append(m, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); nla_put_addr(m, RTA_DST, dst); if ((err = nl_send_auto_complete(nlh, m)) < 0) { nlmsg_free(m); fprintf(stderr, "%s\n", nl_geterror()); goto errout_route_cache; } nlmsg_free(m); nl_socket_modify_cb(nlh, NL_CB_VALID, NL_CB_CUSTOM, cb, route_cache); if (nl_recvmsgs_default(nlh) < 0) { fprintf(stderr, "%s\n", nl_geterror()); goto errout_route_cache; } } rtnl_route_set_dst(route, dst); nl_cache_dump_filter(route_cache, ¶ms, (struct nl_object *) route); memset(&res, 0, sizeof(res)); nl_cache_foreach_filter(route_cache, (struct nl_object *) route, route_proc_cb, &res); printf("ip lookup result: oif idx: %d oif name %s ", res.oif, res.oifname); if (res.nh_addr) { char buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &res.nh_addr, buf, sizeof(buf)); printf("via %s", buf); } printf ("\n"); err = 0; errout_route_cache: nl_cache_free(route_cache); errout_addr_put: nl_addr_put(dst); errout_link_cache: nl_cache_free(link_cache); errout_close: nl_close(nlh); errout_free_route: rtnl_route_put(route); errout_free_handle: nl_handle_destroy(nlh); errout: return err; }
static struct nl_addr *process_get_neigh_mac( struct get_neigh_handler *neigh_handler) { int err; struct nl_addr *ll_addr = get_neigh_mac(neigh_handler); struct rtnl_neigh *neigh_filter; fd_set fdset; int sock_fd; int fd; int nfds; int timer_fd; int ret; struct skt addr_dst; char buff[sizeof(SEND_PAYLOAD)] = SEND_PAYLOAD; int retries = 0; if (NULL != ll_addr) return ll_addr; err = nl_socket_add_membership(neigh_handler->sock, RTNLGRP_NEIGH); if (err < 0) return NULL; neigh_filter = create_filter_neigh_for_dst(neigh_handler->dst, neigh_handler->oif); if (neigh_filter == NULL) return NULL; set_neigh_filter(neigh_handler, neigh_filter); nl_socket_disable_seq_check(neigh_handler->sock); nl_socket_modify_cb(neigh_handler->sock, NL_CB_VALID, NL_CB_CUSTOM, &get_neigh_cb, neigh_handler); fd = nl_socket_get_fd(neigh_handler->sock); err = create_socket(neigh_handler, &addr_dst, &sock_fd); if (err) return NULL; err = try_send_to(sock_fd, buff, sizeof(buff), &addr_dst); if (err) goto close_socket; timer_fd = create_timer(neigh_handler); if (timer_fd < 0) goto close_socket; nfds = MAX(fd, timer_fd) + 1; while (1) { FD_ZERO(&fdset); FD_SET(fd, &fdset); FD_SET(timer_fd, &fdset); /* wait for an incoming message on the netlink socket */ ret = select(nfds, &fdset, NULL, NULL, NULL); if (ret == -1) { goto select_err; } else if (ret) { if (FD_ISSET(fd, &fdset)) { nl_recvmsgs_default(neigh_handler->sock); if (neigh_handler->found_ll_addr) break; } else { nl_cache_refill(neigh_handler->sock, neigh_handler->neigh_cache); ll_addr = get_neigh_mac(neigh_handler); if (NULL != ll_addr) { break; } else if (FD_ISSET(timer_fd, &fdset) && retries < NUM_OF_RETRIES) { try_send_to(sock_fd, buff, sizeof(buff), &addr_dst); } } if (FD_ISSET(timer_fd, &fdset)) { uint64_t read_val; ssize_t rc; rc = read(timer_fd, &read_val, sizeof(read_val)); assert(rc == sizeof(read_val)); if (++retries >= NUM_OF_TRIES) { if (!errno) errno = EDESTADDRREQ; break; } } } } select_err: close(timer_fd); close_socket: close(sock_fd); return ll_addr ? ll_addr : neigh_handler->found_ll_addr; }
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(nf_sock, 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_sock *rt_sock; 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; nf_sock = nfnl_queue_socket_alloc(); if (nf_sock == NULL) nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket"); nl_socket_disable_seq_check(nf_sock); nl_socket_modify_cb(nf_sock, 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"); printf("family: [ inet | inet6 | ... ] \n"); printf("group: the --queue-num arg that you gave to iptables\n"); printf("copy_mode: [ none | meta | packet ] \n"); return 2; } nl_cli_connect(nf_sock, NETLINK_NETFILTER); if ((family = nl_str2af(argv[1])) == AF_UNSPEC) nl_cli_fatal(NLE_INVAL, "Unknown family \"%s\"", argv[1]); nfnl_queue_pf_unbind(nf_sock, family); if ((err = nfnl_queue_pf_bind(nf_sock, family)) < 0) nl_cli_fatal(err, "Unable to bind logger: %s", nl_geterror(err)); queue = alloc_queue(); 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) nl_cli_fatal(copy_mode, "Unable to parse copy mode \"%s\": %s", argv[3], nl_geterror(copy_mode)); } 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 ((err = nfnl_queue_create(nf_sock, queue)) < 0) nl_cli_fatal(err, "Unable to bind queue: %s", nl_geterror(err)); rt_sock = nl_cli_alloc_socket(); nl_cli_connect(rt_sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(rt_sock); nl_socket_set_buffer_size(nf_sock, 1024*127, 1024*127); while (1) { fd_set rfds; int nffd, rtfd, maxfd, retval; FD_ZERO(&rfds); maxfd = nffd = nl_socket_get_fd(nf_sock); FD_SET(nffd, &rfds); rtfd = nl_socket_get_fd(rt_sock); 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(nf_sock); if (FD_ISSET(rtfd, &rfds)) nl_recvmsgs_default(rt_sock); } } return 0; }
int usnic_nl_rt_lookup(uint32_t src_addr, uint32_t dst_addr, int oif, uint32_t *nh_addr) { struct usnic_nl_sk *unlsk; struct nl_msg *nlm; struct rtmsg rmsg; struct usnic_rt_cb_arg arg; int err; retry: unlsk = NULL; err = usnic_nl_sk_alloc(&unlsk, NETLINK_ROUTE); if (err) return err; memset(&rmsg, 0, sizeof(rmsg)); rmsg.rtm_family = AF_INET; rmsg.rtm_dst_len = sizeof(dst_addr) * CHAR_BIT; rmsg.rtm_src_len = sizeof(src_addr) * CHAR_BIT; nlm = nlmsg_alloc_simple(RTM_GETROUTE, 0); if (!nlm) { usnic_err("Failed to alloc nl message, %s\n", NL_GETERROR(err)); err = ENOMEM; goto out; } nlmsg_append(nlm, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); nla_put_u32(nlm, RTA_DST, dst_addr); nla_put_u32(nlm, RTA_SRC, src_addr); err = usnic_nl_send_query(unlsk, nlm, NETLINK_ROUTE, NLM_F_REQUEST); nlmsg_free(nlm); if (err < 0) { usnic_err("Failed to send RTM_GETROUTE query message, error %s\n", NL_GETERROR(err)); err = EINVAL; goto out; } memset(&arg, 0, sizeof(arg)); arg.oif = oif; arg.unlsk = unlsk; err = nl_socket_modify_cb(unlsk->nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, usnic_rt_raw_parse_cb, &arg); if (err != 0) { usnic_err("Failed to setup callback function, error %s\n", NL_GETERROR(err)); err = EINVAL; goto out; } /* Sometimes the recvmsg can fail because something is * temporarily out of resources. In this case, delay a little * and try again. */ do { err = 0; NL_RECVMSGS(unlsk->nlh, arg, EAGAIN, err, out); if (err == EAGAIN) { usleep(5); } } while (err == EAGAIN); /* If we got a reply back that indicated that the kernel was * too busy to handle this request, delay a little and try * again. */ if (arg.retry) { usleep(5); goto retry; } if (arg.found) { *nh_addr = arg.nh_addr; err = 0; } else { err = EHOSTUNREACH; } out: usnic_nl_sk_free(unlsk); return err; }
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_sock *nf_sock; struct nl_sock *rt_sock; struct nl_cache *link_cache; struct nfnl_log *log; enum nfnl_log_copy_mode copy_mode; uint32_t copy_range; int err; int family; nf_sock = nl_cli_alloc_socket(); nl_socket_disable_seq_check(nf_sock); nl_socket_modify_cb(nf_sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) { printf("Usage: nf-log family group [ copy_mode ] " "[copy_range] \n"); return 2; } nl_cli_connect(nf_sock, NETLINK_NETFILTER); family = nl_str2af(argv[1]); if (family == AF_UNSPEC) nl_cli_fatal(NLE_INVAL, "Unknown family \"%s\": %s", argv[1], nl_geterror(family)); nfnl_log_pf_unbind(nf_sock, family); if ((err = nfnl_log_pf_bind(nf_sock, family)) < 0) nl_cli_fatal(err, "Unable to bind logger: %s", nl_geterror(err)); log = alloc_log(); nfnl_log_set_group(log, atoi(argv[2])); copy_mode = NFNL_LOG_COPY_META; if (argc > 3) { copy_mode = nfnl_log_str2copy_mode(argv[3]); if (copy_mode < 0) nl_cli_fatal(copy_mode, "Unable to parse copy mode \"%s\": %s", argv[3], nl_geterror(copy_mode)); } nfnl_log_set_copy_mode(log, copy_mode); copy_range = 0xFFFF; if (argc > 4) copy_mode = atoi(argv[4]); nfnl_log_set_copy_range(log, copy_range); if ((err = nfnl_log_create(nf_sock, log)) < 0) nl_cli_fatal(err, "Unable to bind instance: %s", nl_geterror(err)); { struct nl_dump_params dp = { .dp_type = NL_DUMP_STATS, .dp_fd = stdout, .dp_dump_msgtype = 1, }; printf("log params: "); nl_object_dump((struct nl_object *) log, &dp); } rt_sock = nl_cli_alloc_socket(); nl_cli_connect(rt_sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(rt_sock); while (1) { fd_set rfds; int nffd, rtfd, maxfd, retval; FD_ZERO(&rfds); maxfd = nffd = nl_socket_get_fd(nf_sock); FD_SET(nffd, &rfds); rtfd = nl_socket_get_fd(rt_sock); FD_SET(rtfd, &rfds); if (maxfd < rtfd) maxfd = rtfd; /* wait for an incoming message on the netlink nf_socket */ retval = select(maxfd+1, &rfds, NULL, NULL, NULL); if (retval) { if (FD_ISSET(nffd, &rfds)) nl_recvmsgs_default(nf_sock); if (FD_ISSET(rtfd, &rfds)) nl_recvmsgs_default(rt_sock); } } return 0; }