static int send_and_recv(struct nl_sock *nl_sock, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), void *valid_data) { struct nl_cb *cb; int err = -ENOMEM; cb = nl_cb_clone(nlcfg.nl_cb); if (!cb) goto out; err = nl_send_auto_complete(nl_sock, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); if (valid_handler) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); while (err > 0) nl_recvmsgs(nl_sock, cb); out: nl_cb_put(cb); nlmsg_free(msg); return err; }
static int wprobe_send_msg(struct nl_msg *msg, void *callback, void *arg) { struct nl_cb *cb; int err = 0; cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) goto out_no_cb; if (callback) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, arg); err = nl_send_auto_complete(handle, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); while (err > 0) nl_recvmsgs(handle, cb); out: nl_cb_put(cb); out_no_cb: nlmsg_free(msg); return err; }
int dhd_nl_sock_connect(struct dhd_netlink_info *dhd_nli) { dhd_nli->nl = nl_socket_alloc(); if (dhd_nli->nl == NULL) return -1; if (genl_connect(dhd_nli->nl) < 0) { fprintf(stderr, "netlink connection failed\n"); goto err; } dhd_nli->nl_id = genl_ctrl_resolve(dhd_nli->nl, "nl80211"); if (dhd_nli->nl_id < 0) { fprintf(stderr, "'nl80211' netlink not found\n"); goto err; } dhd_nli->cb = nl_cb_alloc(NL_CB_DEBUG); if (dhd_nli->cb == NULL) goto err; nl_socket_set_cb(dhd_nli->nl, dhd_nli->cb); return 0; err: nl_cb_put(dhd_nli->cb); nl_socket_free(dhd_nli->nl); fprintf(stderr, "nl80211 connection failed\n"); return -1; }
/** * Pickup netlink answer, parse is and return object * @arg sk Netlink socket * @arg parser Parser function to parse answer * @arg result Result pointer to return parsed object * * @return 0 on success or a negative error code. */ int nl_pickup(struct nl_sock *sk, int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, struct nlmsghdr *, struct nl_parser_param *), struct nl_object **result) { struct nl_cb *cb; int err; struct pickup_param pp = { .parser = parser, }; cb = nl_cb_clone(sk->s_cb); if (cb == NULL) return -NLE_NOMEM; nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp); err = nl_recvmsgs(sk, cb); if (err < 0) goto errout; *result = pp.result; errout: nl_cb_put(cb); return err; }
int unl_genl_request(struct unl *unl, struct nl_msg *msg, unl_cb handler, void *arg) { struct nlmsghdr *nlh; struct nl_cb *cb; int err; cb = nl_cb_alloc(NL_CB_CUSTOM); nlh = nlmsg_hdr(msg); err = nl_send_auto_complete(unl->sock, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); if (handler) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handler, arg); while (err > 0) nl_recvmsgs(unl->sock, cb); out: nlmsg_free(msg); nl_cb_put(cb); return err; }
static struct nl80211_msg_conveyor * nl80211_new(struct genl_family *family, int cmd, int flags) { static struct nl80211_msg_conveyor cv; struct nl_msg *req = NULL; struct nl_cb *cb = NULL; req = nlmsg_alloc(); if (!req) goto err; cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) goto err; genlmsg_put(req, 0, 0, genl_family_get_id(family), 0, flags, cmd, 0); cv.msg = req; cv.cb = cb; return &cv; err: nla_put_failure: if (cb) nl_cb_put(cb); if (req) nlmsg_free(req); return NULL; }
static struct nl80211_msg_conveyor * nl80211_send( struct nl80211_msg_conveyor *cv, int (*cb_func)(struct nl_msg *, void *), void *cb_arg ) { static struct nl80211_msg_conveyor rcv; int err = 1; if (cb_func) nl_cb_set(cv->cb, NL_CB_VALID, NL_CB_CUSTOM, cb_func, cb_arg); else nl_cb_set(cv->cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_msg_response, &rcv); if (nl_send_auto_complete(nls->nl_sock, cv->msg) < 0) goto err; nl_cb_err(cv->cb, NL_CB_CUSTOM, nl80211_msg_error, &err); nl_cb_set(cv->cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_msg_finish, &err); nl_cb_set(cv->cb, NL_CB_ACK, NL_CB_CUSTOM, nl80211_msg_ack, &err); while (err > 0) nl_recvmsgs(nls->nl_sock, cv->cb); return &rcv; err: nl_cb_put(cv->cb); nlmsg_free(cv->msg); return NULL; }
static int internal_pollin_handler(wifi_handle handle) { hal_info *info = getHalInfo(handle); struct nl_cb *cb = nl_socket_get_cb(info->event_sock); int res = nl_recvmsgs(info->event_sock, cb); nl_cb_put(cb); return res; }
int SoftapController::executeScanLinkCmd(const char *iface, int *iface_freq) { struct nl_cb *cb; struct nl_msg *msg; int devidx = 0; int err; // initialize to non-valid freq *iface_freq = 0; devidx = if_nametoindex(iface); if (devidx == 0) { LOGE("failed to translate ifname to idx"); return -errno; } msg = nlmsg_alloc(); if (!msg) { LOGE("failed to allocate netlink message"); return 2; } cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) { LOGE("failed to allocate netlink callbacks"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); // iface_freq will be filled out by the callback nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, linkDumpCbHandler, iface_freq); err = nl_send_auto_complete(nl_soc, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, NlErrorHandler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, NlFinishHandler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, NlAckHandler, &err); while (err > 0) nl_recvmsgs(nl_soc, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; nla_put_failure: LOGW("building message failed"); return 2; }
static int nl80211_add_mon_if(struct nl80211_state *state, const char *device, const char *mondevice) { int ifindex, ret; struct nl_msg *msg; struct nl_cb *cb = NULL; int finished = 0; ifindex = device_ifindex(device); msg = nl80211_nlmsg_xalloc(); genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_NEW_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR); ret = nl_send_auto_complete(state->nl_sock, msg); if (ret < 0) { if (ret == -ENFILE) { nlmsg_free(msg); return -EBUSY; } panic("Cannot send_auto_complete!\n"); } cb = nl_cb_alloc(NL_CB_CUSTOM); if (!cb) panic("Cannot alloc nl_cb!\n"); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl80211_wait_handler, &finished); nl_cb_err(cb, NL_CB_CUSTOM, nl80211_error_handler, NULL); nl_recvmsgs(state->nl_sock, cb); if (!finished) { ret = nl_wait_for_ack(state->nl_sock); if (ret < 0) { if (ret == -ENFILE) { nlmsg_free(msg); return -EBUSY; } panic("Waiting for netlink ack failed!\n"); } } nl_cb_put(cb); nlmsg_free(msg); return 0; nla_put_failure: panic("nla put failure!\n"); return -EIO; /* dummy */ }
static int handle_mgmt_dump(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv, enum id_input id) { struct nl_cb *mgmt_cb; char *ndev = argv[0]; int mgmt_argc = 5; char **mgmt_argv; unsigned int count = 0; int err = 0; int i; mgmt_argv = calloc(mgmt_argc, sizeof(char*)); if (!mgmt_argv) return -ENOMEM; mgmt_argv[0] = ndev; mgmt_argv[1] = "mgmt"; mgmt_argv[2] = "reg"; for (i = 3; i < argc; i += 3) { if (strcmp(argv[i], "count") == 0) { count = 1 + atoi(argv[i + 1]); break; } if (strcmp(argv[i], "frame") != 0) { err = 1; goto out; } mgmt_argv[3] = argv[i + 1]; mgmt_argv[4] = argv[i + 2]; err = handle_cmd(state, II_NETDEV, mgmt_argc, mgmt_argv); if (err) goto out; } mgmt_cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); if (!mgmt_cb) { err = 1; goto out; } /* need to turn off sequence number checking */ nl_cb_set(mgmt_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, seq_handler, NULL); nl_cb_set(mgmt_cb, NL_CB_VALID, NL_CB_CUSTOM, dump_mgmt_frame, NULL); while (--count) nl_recvmsgs(state->nl_sock, mgmt_cb); nl_cb_put(mgmt_cb); out: free(mgmt_argv); return err; }
/* NOTE: this function consumes 'msg' */ static int _nl80211_send_and_recv (struct nl_sock *nl_sock, struct nl_cb *nl_cb, struct nl_msg *msg, int (*valid_handler) (struct nl_msg *, void *), void *valid_data) { struct nl_cb *cb; int err, done; g_return_val_if_fail (msg != NULL, -ENOMEM); cb = nl_cb_clone (nl_cb); if (!cb) { err = -ENOMEM; goto out; } err = nl_send_auto_complete (nl_sock, msg); if (err < 0) goto out; done = 0; nl_cb_err (cb, NL_CB_CUSTOM, error_handler, &done); nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &done); nl_cb_set (cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &done); if (valid_handler) nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); /* Loop until one of our NL callbacks says we're done; on success * done will be 1, on error it will be < 0. */ while (!done) { err = nl_recvmsgs (nl_sock, cb); if (err && err != -NLE_AGAIN) { /* Kernel scan list can change while we are dumping it, as new scan * results from H/W can arrive. BSS info is assured to be consistent * and we don't need consistent view of whole scan list. Hence do * not warn on DUMP_INTR error for get scan command. */ if (err == -NLE_DUMP_INTR && genlmsg_hdr(nlmsg_hdr(msg))->cmd == NL80211_CMD_GET_SCAN) break; nm_log_warn (LOGD_WIFI, "nl_recvmsgs() error: (%d) %s", err, nl_geterror (err)); break; } } if (err == 0 && done < 0) err = done; out: nl_cb_put (cb); nlmsg_free (msg); return err; }
int main() { int ret; struct nl_cb * nl_cb; struct nl_handle * nl_handle; struct netlink_data * netlink; int ioctl_sock = -1; struct dl_list interfaces; int if_add_ifindex = -1; dl_list_init(&interfaces); /* * global_init */ ret = netlink_init_nl80211_event_rtm(&netlink,NULL,nl80211_event_rtm_newlink,nl80211_event_rtm_dellink); if (ret == -1 || netlink == NULL) { goto err; } ret = nl80211_init_event(&nl_cb, &nl_handle); if (ret == -1) { wpa_printf(MSG_DEBUG, "nl80211: Init failure "); goto err; } wpa_printf(MSG_INFO, "nl80211: wait for event... "); nl_cb_set(nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); nl_cb_set(nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, NULL); eloop_register_wrapper(nl_socket_get_fd(nl_handle), nl80211_event_receive, nl_cb, nl_handle); ioctl_sock = init_ioctl_sock(); if (ioctl_sock < 0) { perror("socket(PF_INET,SOCK_DGRAM)"); goto err; } /* * hapd_init */ eloop_run(); return 0; err: netlink_deinit(netlink); nl_destroy_handles(&nl_handle); nl_cb_put(nl_cb); if (ioctl_sock >= 0) { close(ioctl_sock); } return -1; }
static int internal_pollin_handler(wifi_handle handle) { hal_info *info = getHalInfo(handle); struct nl_cb *cb = nl_socket_get_cb(info->event_sock); int res = nl_recvmsgs(info->event_sock, cb); if(res) ALOGE("Error :%d while reading nl msg", res); nl_cb_put(cb); return res; }
static void wifi_nl80211_deinit (WifiData *parent) { WifiDataNl80211 *nl80211 = (WifiDataNl80211 *) parent; if (nl80211->nl_sock) nl_socket_free (nl80211->nl_sock); if (nl80211->nl_cb) nl_cb_put (nl80211->nl_cb); }
static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock) { struct nl_cb *cb = nl_socket_get_cb(sock); int res = nl_recvmsgs(sock, cb); if(res) ALOGE("Error :%d while reading nl msg", res); nl_cb_put(cb); return res; }
static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, int cmd, int flags) { static struct nl80211_msg_conveyor cv; int ifidx = -1, phyidx = -1; struct nl_msg *req = NULL; struct nl_cb *cb = NULL; if (nl80211_init() < 0) goto err; if (!strncmp(ifname, "phy", 3)) phyidx = atoi(&ifname[3]); else if (!strncmp(ifname, "radio", 5)) phyidx = atoi(&ifname[5]); else if (!strncmp(ifname, "mon.", 4)) ifidx = if_nametoindex(&ifname[4]); else ifidx = if_nametoindex(ifname); if ((ifidx < 0) && (phyidx < 0)) return NULL; req = nlmsg_alloc(); if (!req) goto err; cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) goto err; genlmsg_put(req, 0, 0, genl_family_get_id(nls->nl80211), 0, flags, cmd, 0); if (ifidx > -1) NLA_PUT_U32(req, NL80211_ATTR_IFINDEX, ifidx); if (phyidx > -1) NLA_PUT_U32(req, NL80211_ATTR_WIPHY, phyidx); cv.msg = req; cv.cb = cb; return &cv; err: nla_put_failure: if (cb) nl_cb_put(cb); if (req) nlmsg_free(req); return NULL; }
static int __nl_send_msg(struct nl_sock *sock, struct nl_msg *msg, int (*rx_handler)(struct nl_msg *, void *), int (*finish_handler)(struct nl_msg *, void *), void *data) { struct nl_cb *cb; int err, done; struct send_msg_data send_data; DBG(""); cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) return -ENOMEM; err = nl_send_auto_complete(sock, msg); if (err < 0) { nl_cb_put(cb); near_error("%s", strerror(err)); return err; } err = done = 0; send_data.done = &done; send_data.data = data; send_data.finish_handler = finish_handler; nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, __finish_handler, &send_data); nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &done); if (rx_handler) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, rx_handler, data); while (err == 0 && done == 0) nl_recvmsgs(sock, cb); nl_cb_put(cb); return err; }
static int go_offchan_freq(struct nl80211_state *state, int devidx, int freq) { struct nl_cb *cb; struct nl_cb *s_cb; struct nl_msg *msg; int err; msg = nlmsg_alloc(); if (!msg) { fprintf(stderr, "failed to allocate netlink message\n"); return 2; } cb = nl_cb_alloc(nl_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); s_cb = nl_cb_alloc(nl_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); if (!cb || !s_cb) { fprintf(stderr, "failed to allocate netlink callbacks\n"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_REMAIN_ON_CHANNEL, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); /* 5 seconds is the max allowed, values passed are in ms */ NLA_PUT_U32(msg, NL80211_ATTR_DURATION, 60); nl_socket_set_cb(state->nl_sock, s_cb); err = nl_send_auto_complete(state->nl_sock, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); while (err > 0) nl_recvmsgs(state->nl_sock, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; nla_put_failure: fprintf(stderr, "building message failed\n"); return 2; }
// Retrieve monitor interface for a given physical interface int ret_mon_IF(struct nl80211_state *state) { struct nl_msg *msg; struct nl_cb *cb, *s_cb; int err = 1; msg = nlmsg_alloc(); if (!msg) { fprintf(stderr, "failed to allocate netlink message\n"); return 2; } // Allocate a new callback handle. cb = nl_cb_alloc(NL_CB_DEFAULT); s_cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb || !s_cb) { fprintf(stderr, "failed to allocate netlink callbacks\n"); err = 2; goto out_free_msg; } // Add Generic Netlink header (i.e. NL80211_CMD_GET_INTERFACE) to Netlink message genlmsg_put(msg, 0, 0, state->nl80211_id, 0, 768, NL80211_CMD_GET_INTERFACE, 0); // Set up a valid callback function if (nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iface_handler, NULL)) goto out; // Attach the callback function to a netlink socket nl_socket_set_cb(state->nl_sock, s_cb); // Finalize and transmit Netlink message if(nl_send_auto_complete(state->nl_sock, msg) < 0) goto out; // Set up error, finish and acknowledgment callback function nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); while (err > 0) nl_recvmsgs(state->nl_sock, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; }
void unl_genl_loop(struct unl *unl, unl_cb handler, void *arg) { struct nl_cb *cb; cb = nl_cb_alloc(NL_CB_CUSTOM); unl->loop_done = false; nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handler, arg); while (!unl->loop_done) nl_recvmsgs(unl->sock, cb); nl_cb_put(cb); }
static int call_survey_freq(struct nl80211_state *state, int devidx, int freq) { struct nl_cb *cb; struct nl_cb *s_cb; struct nl_msg *msg; int err; msg = nlmsg_alloc(); if (!msg) { fprintf(stderr, "failed to allocate netlink message\n"); return 2; } cb = nl_cb_alloc(nl_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); s_cb = nl_cb_alloc(nl_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); if (!cb || !s_cb) { fprintf(stderr, "failed to allocate netlink callbacks\n"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, NLM_F_DUMP, NL80211_CMD_GET_SURVEY, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handle_survey_dump, (void *) &freq); nl_socket_set_cb(state->nl_sock, s_cb); err = nl_send_auto_complete(state->nl_sock, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); while (err > 0) nl_recvmsgs(state->nl_sock, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; nla_put_failure: fprintf(stderr, "building message failed\n"); return 2; }
static void nl80211_free(struct nl80211_msg_conveyor *cv) { if (cv) { if (cv->cb) nl_cb_put(cv->cb); if (cv->msg) nlmsg_free(cv->msg); cv->cb = NULL; cv->msg = NULL; } }
void ac_kmod_free(void) { if (g_ac.kmodhandle.nl) { nl_socket_free(g_ac.kmodhandle.nl); } if (g_ac.kmodhandle.nl_cb) { nl_cb_put(g_ac.kmodhandle.nl_cb); } if (g_ac.kmodhandle.nlmsg) { nl_socket_free(g_ac.kmodhandle.nlmsg); } if (g_ac.kmodhandle.nlmsg_cb) { nl_cb_put(g_ac.kmodhandle.nlmsg_cb); } /* */ capwap_lock_destroy(&g_ac.kmodhandle.msglock); /* */ memset(&g_ac.kmodhandle, 0, sizeof(struct ac_kmod_handle)); }
/** * Wait for ACK. * @arg sk Netlink socket. * @pre The netlink socket must be in blocking state. * * Waits until an ACK is received for the latest not yet acknowledged * netlink message. */ int nl_wait_for_ack(struct nl_sock *sk) { int err; struct nl_cb *cb; cb = nl_cb_clone(sk->s_cb); if (cb == NULL) return -NLE_NOMEM; nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL); err = nl_recvmsgs(sk, cb); nl_cb_put(cb); return err; }
/* function: netlink_sendrecv * send a nl_msg and return an int status - only supports OK/ERROR responses * msg - msg to send */ int netlink_sendrecv(struct nl_msg *msg) { struct nl_cb *callbacks = NULL; int retval = -EIO; callbacks = alloc_ack_callbacks(&retval); if(!callbacks) { return -ENOMEM; } send_netlink_msg(msg, callbacks); nl_cb_put(callbacks); return retval; }
/* NOTE: this function consumes 'msg' */ static int _nl80211_send_and_recv (struct nl_sock *nl_sock, struct nl_cb *nl_cb, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), void *valid_data) { struct nl_cb *cb; int err, done; g_return_val_if_fail (msg != NULL, -ENOMEM); cb = nl_cb_clone (nl_cb); if (!cb) { err = -ENOMEM; goto out; } err = nl_send_auto_complete (nl_sock, msg); if (err < 0) goto out; done = 0; nl_cb_err (cb, NL_CB_CUSTOM, error_handler, &done); nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &done); nl_cb_set (cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &done); if (valid_handler) nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); /* Loop until one of our NL callbacks says we're done; on success * done will be 1, on error it will be < 0. */ while (!done) { err = nl_recvmsgs (nl_sock, cb); if (err && err != -NLE_AGAIN) { nm_log_warn (LOGD_WIFI, "nl_recvmsgs() error: (%d) %s", err, nl_geterror (err)); break; } } if (err == 0 && done < 0) err = done; out: nl_cb_put (cb); nlmsg_free (msg); return err; }
static wifi_error wifi_init_user_sock(hal_info *info) { struct nl_sock *user_sock = wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK); if (user_sock == NULL) { ALOGE("Could not create diag sock"); return WIFI_ERROR_UNKNOWN; } /* Set the socket buffer size */ if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) { ALOGE("Could not set size for user_sock: %s", strerror(errno)); /* continue anyway with the default (smaller) buffer */ } else { ALOGV("nl_socket_set_buffer_size successful for user_sock"); } struct nl_cb *cb = nl_socket_get_cb(user_sock); if (cb == NULL) { ALOGE("Could not get cb"); return WIFI_ERROR_UNKNOWN; } info->user_sock_arg = 1; nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info); nl_cb_put(cb); int ret = nl_socket_add_membership(user_sock, 1); if (ret < 0) { ALOGE("Could not add membership"); return WIFI_ERROR_UNKNOWN; } info->user_sock = user_sock; ALOGV("Initiialized diag sock successfully"); return WIFI_SUCCESS; }
static wifi_error wifi_init_cld80211_sock_cb(hal_info *info) { struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock); if (cb == NULL) { ALOGE("Could not get cb"); return WIFI_ERROR_UNKNOWN; } info->user_sock_arg = 1; nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info); nl_cb_put(cb); return WIFI_SUCCESS; }
/* function: getinterface_ip * finds the first global non-privacy IP of the given family for the given interface, or returns NULL. caller frees pointer * interface - interface to look for * family - family */ union anyip *getinterface_ip(const char *interface, int family) { struct ifaddrmsg ifa; struct nl_cb *callbacks = NULL; struct target targ; union anyip *retval = NULL; targ.family = family; targ.foundip = 0; targ.ifindex = if_nametoindex(interface); if(targ.ifindex == 0) { return NULL; // interface not found } memset(&ifa, 0, sizeof(ifa)); ifa.ifa_family = targ.family; callbacks = nl_cb_alloc(NL_CB_DEFAULT); if(!callbacks) { goto cleanup; } nl_cb_set(callbacks, NL_CB_VALID, NL_CB_CUSTOM, getaddr_cb, &targ); nl_cb_err(callbacks, NL_CB_CUSTOM, error_handler, &targ); // sends message and waits for a response send_ifaddrmsg(RTM_GETADDR, NLM_F_REQUEST | NLM_F_ROOT, &ifa, callbacks); if(targ.foundip) { retval = malloc(sizeof(union anyip)); if(!retval) { logmsg(ANDROID_LOG_FATAL,"getinterface_ip/out of memory"); goto cleanup; } memcpy(retval, &targ.ip, sizeof(union anyip)); } cleanup: if(callbacks) nl_cb_put(callbacks); return retval; }