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; }
/** * Pickup netlink answer, parse is and return object with preserving system error * @arg sk Netlink socket * @arg parser Parser function to parse answer * @arg result Result pointer to return parsed object * @arg syserr Result pointer for the system error in case of failure * * @return 0 on success or a negative error code. */ int nl_pickup_keep_syserr(struct nl_sock *sk, int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, struct nlmsghdr *, struct nl_parser_param *), struct nl_object **result, int *syserror) { 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); if (syserror) { *syserror = 0; pp.syserror = syserror; nl_cb_err(cb, NL_CB_CUSTOM, __pickup_answer_syserr, &pp); } err = nl_recvmsgs(sk, cb); if (err < 0) goto errout; *result = pp.result; errout: nl_cb_put(cb); 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; }
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 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 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 */ }
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; }
/* 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; }
/* function: alloc_ack_callbacks * allocates a set of netlink callbacks. returns NULL on failure. callbacks will modify retval with <0 meaning failure * retval - shared state between caller and callback functions */ struct nl_cb *alloc_ack_callbacks(int *retval) { struct nl_cb *callbacks; callbacks = nl_cb_alloc(NL_CB_DEFAULT); if(!callbacks) { return NULL; } nl_cb_set(callbacks, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, retval); nl_cb_err(callbacks, NL_CB_CUSTOM, error_handler, retval); return callbacks; }
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; }
int main() { struct nl_sock * sk; int cbarg; // nl_debug = 4; // setup netlink socket sk = nl_socket_alloc(); nl_socket_disable_seq_check(sk); // disable sequence number check genl_connect(sk); int id = genl_ctrl_resolve(sk, DEMO_FAMILY_NAME); struct nl_msg * msg; // create a messgae msg = nlmsg_alloc(); genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, id, 0, // hdrlen 0, // flags DEMO_CMD, // numeric command identifier DEMO_VERSION // interface version ); nla_put_string(msg, DEMO_ATTR1_STRING, "hola"); nla_put_u16(msg, DEMO_ATTR2_UINT16, 0xf1); // send it nl_send_auto(sk, msg); // handle reply struct nl_cb * cb = NULL; cb = nl_cb_alloc(NL_CB_CUSTOM); //nl_cb_set_all(cb, NL_CB_DEBUG, NULL, NULL); nl_cb_set_all(cb, NL_CB_CUSTOM, cb_handler, &cbarg); nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL); int nrecv = nl_recvmsgs_report(sk, cb); printf("cbarg %d nrecv %d\n", cbarg, nrecv); // cleanup nlmsg_free(msg); nl_close(sk); nl_socket_free(sk); return 0; }
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; }
/* 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; }
int nlt_get_ifinfo(struct nl_sock *sk, struct nlt_ifinfo *ifinfo) { struct nl_msg *msg = nlmsg_alloc(); if (!msg) return -1; int flags = NLM_F_DUMP; int family_id = genl_ctrl_resolve(sk, "nl80211"); genlmsg_put(msg, 0, NL_AUTO_SEQ, family_id, 0, flags, NL80211_CMD_GET_INTERFACE, 0); // NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, 0); nl_send_auto(sk, msg); int err; struct nl_cb *nl_cb = nl_cb_alloc(NL_CB_CUSTOM); nl_cb_set(nl_cb, NL_CB_VALID, NL_CB_CUSTOM, get_ifinfo_cb, ifinfo); nl_cb_err(nl_cb, NL_CB_CUSTOM, error_handler, &err); int nlr; // do { nlr = nl_recvmsgs(sk, nl_cb); // printf("round %d\n",nlr); // }while(1);; //int nlr = nl_recvmsgs_default(sk); // cw_log(LOG_ERR, "iGet if index: Make if %d - %s", nlr, nl_geterror(nlr)); // nla_put_failure: nlmsg_free(msg); return 0; }
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; }
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; }
/* 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; }
/** * Allocate a new callback handle * @arg kind callback kind to be used for initialization * @return Newly allocated callback handle or NULL */ struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) { int i; struct nl_cb *cb; if (kind < 0 || kind > NL_CB_KIND_MAX) return NULL; cb = calloc(1, sizeof(*cb)); if (!cb) return NULL; cb->cb_refcnt = 1; for (i = 0; i <= NL_CB_TYPE_MAX; i++) nl_cb_set(cb, i, kind, NULL, NULL); nl_cb_err(cb, kind, NULL, NULL); return cb; }
/* function: get_default_route * finds the first default route with the given family and interface, returns the gateway (if it exists) in the struct * default_route - requested family and interface, and response storage */ int get_default_route(struct default_route_data *default_route) { struct rtmsg msg; struct nl_cb *callbacks = NULL; struct nl_msg *nlmsg = NULL; int retval = 0; default_route->reply_has_gateway = 0; default_route->reply_found_route = 0; memset(&msg,'\0',sizeof(msg)); msg.rtm_family = default_route->request_family; msg.rtm_table = RT_TABLE_MAIN; msg.rtm_protocol = RTPROT_KERNEL; msg.rtm_scope = RT_SCOPE_UNIVERSE; callbacks = nl_cb_alloc(NL_CB_DEFAULT); if(!callbacks) { retval = -ENOMEM; goto cleanup; } // get_default_route_cb sets the response fields in default_route nl_cb_set(callbacks, NL_CB_VALID, NL_CB_CUSTOM, get_default_route_cb, default_route); nl_cb_err(callbacks, NL_CB_CUSTOM, error_handler, &retval); nlmsg = nlmsg_alloc_rtmsg(RTM_GETROUTE, NLM_F_REQUEST | NLM_F_ROOT, &msg); if(!nlmsg) { retval = -ENOMEM; goto cleanup; } send_netlink_msg(nlmsg, callbacks); cleanup: if(callbacks) nl_cb_put(callbacks); if(nlmsg) nlmsg_free(nlmsg); return retval; }
static int send_and_recv(struct nl_handle* handle, struct nl_msg* msg, struct nl_cb* cb) { int err = -1; struct nl_cb *tmp_cb; tmp_cb = nl_cb_clone(cb); if (!cb) goto out; err = nl_send_auto_complete(handle, msg); if (err < 0) goto out; err = 1; nl_cb_err(tmp_cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(tmp_cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(tmp_cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); while(err > 0) nl_recvmsgs(handle, tmp_cb); out: nlmsg_free(msg); nl_cb_put(tmp_cb); return err; }
int dhd_nl_do_testmode(struct dhd_netlink_info *dhd_nli, dhd_ioctl_t *ioc) { struct nl_msg *msg; int err; msg = nlmsg_alloc(); if (msg == NULL) return -ENOMEM; /* fill testmode message */ genlmsg_put(msg, 0, 0, dhd_nli->nl_id, 0, 0, NL80211_CMD_TESTMODE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dhd_nli->ifidx); NLA_PUT(msg, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc); err = nl_send_auto_complete(dhd_nli->nl, msg); if (err < 0) goto out; err = 1; nl_cb_err(dhd_nli->cb, NL_CB_CUSTOM, dhd_nl_error_handler, &err); nl_cb_set(dhd_nli->cb, NL_CB_ACK, NL_CB_CUSTOM, dhd_nl_ack_handler, &err); nl_cb_set(dhd_nli->cb, NL_CB_FINISH, NL_CB_CUSTOM, dhd_nl_finish_handler, &err); nl_cb_set(dhd_nli->cb, NL_CB_VALID, NL_CB_CUSTOM, dhd_nl_valid_handler, &err); while (err > 0) nl_recvmsgs(dhd_nli->nl, dhd_nli->cb); out: nlmsg_free(msg); return err; nla_put_failure: fprintf(stderr, "setting netlink attribute failed\n"); err = -EFAULT; goto out; }
static int ac_kmod_send_and_recv(struct nl_sock* nl, struct nl_cb* nl_cb, struct nl_msg* msg, ac_kmod_valid_cb valid_cb, void* data) { int result; struct nl_cb* cb; /* Clone netlink callback */ cb = nl_cb_clone(nl_cb); if (!cb) { return -1; } /* */ capwap_lock_enter(&g_ac.kmodhandle.msglock); /* Complete send message */ result = nl_send_auto_complete(nl, msg); if (result >= 0) { /* Customize message callback */ nl_cb_err(cb, NL_CB_CUSTOM, ac_kmod_error_handler, &result); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, ac_kmod_finish_handler, &result); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ac_kmod_ack_handler, &result); if (valid_cb) { nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_cb, data); } result = 1; while (result > 0) { nl_recvmsgs(nl, cb); } } /* */ capwap_lock_exit(&g_ac.kmodhandle.msglock); nl_cb_put(cb); return result; }
wifi_error wifi_initialize(wifi_handle *handle) { int err = 0; bool driver_loaded = false; wifi_error ret = WIFI_SUCCESS; wifi_interface_handle iface_handle; srand(getpid()); ALOGI("Initializing wifi"); hal_info *info = (hal_info *)malloc(sizeof(hal_info)); if (info == NULL) { ALOGE("Could not allocate hal_info"); return WIFI_ERROR_UNKNOWN; } memset(info, 0, sizeof(*info)); ALOGI("Creating socket"); struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT); if (cmd_sock == NULL) { ALOGE("Could not create handle"); return WIFI_ERROR_UNKNOWN; } struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT); if (event_sock == NULL) { ALOGE("Could not create handle"); nl_socket_free(cmd_sock); return WIFI_ERROR_UNKNOWN; } struct nl_cb *cb = nl_socket_get_cb(event_sock); if (cb == NULL) { ALOGE("Could not create handle"); return WIFI_ERROR_UNKNOWN; } err = 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, &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); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); nl_cb_put(cb); info->cmd_sock = cmd_sock; info->event_sock = event_sock; info->clean_up = false; info->in_event_loop = false; info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; info->num_event_cb = 0; info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); info->alloc_cmd = DEFAULT_CMD_SIZE; info->num_cmd = 0; info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); if (info->nl80211_family_id < 0) { ALOGE("Could not resolve nl80211 familty id"); nl_socket_free(cmd_sock); nl_socket_free(event_sock); free(info); return WIFI_ERROR_UNKNOWN; } ALOGI("%s: family_id:%d", __func__, info->nl80211_family_id); *handle = (wifi_handle) info; wifi_add_membership(*handle, "scan"); wifi_add_membership(*handle, "mlme"); wifi_add_membership(*handle, "regulatory"); wifi_add_membership(*handle, "vendor"); if (!is_wifi_driver_loaded()) { ret = (wifi_error)wifi_load_driver(); if(ret != WIFI_SUCCESS) { ALOGE("%s Failed to load driver : %d\n", __func__, ret); return WIFI_ERROR_UNKNOWN; } driver_loaded = true; } ret = wifi_init_interfaces(*handle); if (ret != WIFI_SUCCESS) { ALOGI("Failed to init interfaces"); goto unload; } if (info->num_interfaces == 0) { ALOGI("No interfaces found"); ret = WIFI_ERROR_UNINITIALIZED; goto unload; } iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle, (info->interfaces[0])->name); if (iface_handle == NULL) { int i; for (i = 0; i < info->num_interfaces; i++) { free(info->interfaces[i]); } ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name); return WIFI_ERROR_UNKNOWN; } ret = acquire_supported_features(iface_handle, &info->supported_feature_set); if (ret != WIFI_SUCCESS) { ALOGI("Failed to get supported feature set : %d", ret); //acquire_supported_features failure is acceptable condition as legacy //drivers might not support the required vendor command. So, do not //consider it as failure of wifi_initialize ret = WIFI_SUCCESS; } ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d Supported" " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set); unload: if (driver_loaded) wifi_unload_driver(); return ret; }
wifi_error wifi_initialize(wifi_handle *handle) { int err = 0; wifi_error ret = WIFI_SUCCESS; wifi_interface_handle iface_handle; struct nl_sock *cmd_sock = NULL; struct nl_sock *event_sock = NULL; struct nl_cb *cb = NULL; int status = 0; ALOGI("Initializing wifi"); hal_info *info = (hal_info *)malloc(sizeof(hal_info)); if (info == NULL) { ALOGE("Could not allocate hal_info"); return WIFI_ERROR_OUT_OF_MEMORY; } memset(info, 0, sizeof(*info)); cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT, NETLINK_GENERIC); if (cmd_sock == NULL) { ALOGE("Failed to create command socket port"); ret = WIFI_ERROR_UNKNOWN; goto unload; } /* Set the socket buffer size */ if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) { ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s", strerror(errno)); /* continue anyway with the default (smaller) buffer */ } event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC); if (event_sock == NULL) { ALOGE("Failed to create event socket port"); ret = WIFI_ERROR_UNKNOWN; goto unload; } /* Set the socket buffer size */ if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) { ALOGE("Could not set nl_socket RX buffer size for event_sock: %s", strerror(errno)); /* continue anyway with the default (smaller) buffer */ } cb = nl_socket_get_cb(event_sock); if (cb == NULL) { ALOGE("Failed to get NL control block for event socket port"); ret = WIFI_ERROR_UNKNOWN; goto unload; } err = 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, &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); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); nl_cb_put(cb); info->cmd_sock = cmd_sock; info->event_sock = event_sock; info->clean_up = false; info->in_event_loop = false; info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); if (info->event_cb == NULL) { ALOGE("Could not allocate event_cb"); ret = WIFI_ERROR_OUT_OF_MEMORY; goto unload; } info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; info->num_event_cb = 0; info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); if (info->cmd == NULL) { ALOGE("Could not allocate cmd info"); ret = WIFI_ERROR_OUT_OF_MEMORY; goto unload; } info->alloc_cmd = DEFAULT_CMD_SIZE; info->num_cmd = 0; info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); if (info->nl80211_family_id < 0) { ALOGE("Could not resolve nl80211 familty id"); ret = WIFI_ERROR_UNKNOWN; goto unload; } pthread_mutex_init(&info->cb_lock, NULL); pthread_mutex_init(&info->pkt_fate_stats_lock, NULL); *handle = (wifi_handle) info; wifi_add_membership(*handle, "scan"); wifi_add_membership(*handle, "mlme"); wifi_add_membership(*handle, "regulatory"); wifi_add_membership(*handle, "vendor"); info->cldctx = cld80211_init(); if (info->cldctx != NULL) { info->user_sock = info->cldctx->sock; ret = wifi_init_cld80211_sock_cb(info); if (ret != WIFI_SUCCESS) { ALOGE("Could not set cb for CLD80211 family"); goto cld80211_cleanup; } status = cld80211_add_mcast_group(info->cldctx, "host_logs"); if (status) { ALOGE("Failed to add mcast group host_logs :%d", status); goto cld80211_cleanup; } status = cld80211_add_mcast_group(info->cldctx, "fw_logs"); if (status) { ALOGE("Failed to add mcast group fw_logs :%d", status); goto cld80211_cleanup; } status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats"); if (status) { ALOGE("Failed to add mcast group per_pkt_stats :%d", status); goto cld80211_cleanup; } status = cld80211_add_mcast_group(info->cldctx, "diag_events"); if (status) { ALOGE("Failed to add mcast group diag_events :%d", status); goto cld80211_cleanup; } status = cld80211_add_mcast_group(info->cldctx, "fatal_events"); if (status) { ALOGE("Failed to add mcast group fatal_events :%d", status); goto cld80211_cleanup; } } else { ret = wifi_init_user_sock(info); if (ret != WIFI_SUCCESS) { ALOGE("Failed to alloc user socket"); goto unload; } } ret = wifi_init_interfaces(*handle); if (ret != WIFI_SUCCESS) { ALOGE("Failed to init interfaces"); goto unload; } if (info->num_interfaces == 0) { ALOGE("No interfaces found"); ret = WIFI_ERROR_UNINITIALIZED; goto unload; } iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle, (info->interfaces[0])->name); if (iface_handle == NULL) { int i; for (i = 0; i < info->num_interfaces; i++) { free(info->interfaces[i]); } ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name); goto unload; } ret = acquire_supported_features(iface_handle, &info->supported_feature_set); if (ret != WIFI_SUCCESS) { ALOGI("Failed to get supported feature set : %d", ret); //acquire_supported_features failure is acceptable condition as legacy //drivers might not support the required vendor command. So, do not //consider it as failure of wifi_initialize ret = WIFI_SUCCESS; } ret = get_firmware_bus_max_size_supported(iface_handle); if (ret != WIFI_SUCCESS) { ALOGE("Failed to get supported bus size, error : %d", ret); info->firmware_bus_max_size = 1520; } ret = wifi_logger_ring_buffers_init(info); if (ret != WIFI_SUCCESS) { ALOGE("Wifi Logger Ring Initialization Failed"); goto unload; } ret = wifi_get_capabilities(iface_handle); if (ret != WIFI_SUCCESS) ALOGE("Failed to get wifi Capabilities, error: %d", ret); info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s)); if (!info->pkt_stats) { ALOGE("%s: malloc Failed for size: %zu", __FUNCTION__, sizeof(struct pkt_stats_s)); ret = WIFI_ERROR_OUT_OF_MEMORY; goto unload; } info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU * PKT_STATS_BUF_SIZE; info->rx_aggr_pkts = (wifi_ring_buffer_entry *)malloc(info->rx_buf_size_allocated); if (!info->rx_aggr_pkts) { ALOGE("%s: malloc Failed for size: %d", __FUNCTION__, info->rx_buf_size_allocated); ret = WIFI_ERROR_OUT_OF_MEMORY; info->rx_buf_size_allocated = 0; goto unload; } memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated); info->exit_sockets[0] = -1; info->exit_sockets[1] = -1; if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) { ALOGE("Failed to create exit socket pair"); ret = WIFI_ERROR_UNKNOWN; goto unload; } ALOGV("Initializing Gscan Event Handlers"); ret = initializeGscanHandlers(info); if (ret != WIFI_SUCCESS) { ALOGE("Initializing Gscan Event Handlers Failed"); goto unload; } ret = initializeRSSIMonitorHandler(info); if (ret != WIFI_SUCCESS) { ALOGE("Initializing RSSI Event Handler Failed"); goto unload; } ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported" " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set); cld80211_cleanup: if (status != 0 || ret != WIFI_SUCCESS) { ret = WIFI_ERROR_UNKNOWN; cld80211lib_cleanup(info); } unload: if (ret != WIFI_SUCCESS) { if (cmd_sock) nl_socket_free(cmd_sock); if (event_sock) nl_socket_free(event_sock); if (info) { if (info->cmd) free(info->cmd); if (info->event_cb) free(info->event_cb); if (info->cldctx) { cld80211lib_cleanup(info); } else if (info->user_sock) { nl_socket_free(info->user_sock); } if (info->pkt_stats) free(info->pkt_stats); if (info->rx_aggr_pkts) free(info->rx_aggr_pkts); cleanupGscanHandlers(info); cleanupRSSIMonitorHandler(info); free(info); } } return ret; }
int nl80211_get_chanlist(const char *interface, int *ret_num_chans, int **ret_chan_list, char *errstr) { nl80211_channel_block_t cblock; #ifndef HAVE_LINUX_NETLINK snprintf(errstr, LORCON_STATUS_MAX, "LORCON was not compiled with netlink/nl80211 " "support, check the output of ./configure for why"); return NL80211_CHANLIST_NOT_NL80211; #else void *handle, *cache, *family; struct nl_cb *cb; int err; struct nl_msg *msg; cblock.phyname = nl80211_find_parent(interface); if (strlen(cblock.phyname) == 0) { if (if_nametoindex(interface) <= 0) { snprintf(errstr, LORCON_STATUS_MAX, "Interface %s doesn't exist", interface); return NL80211_CHANLIST_NO_INTERFACE; } snprintf(errstr, LORCON_STATUS_MAX, "LORCON could not find a parent phy device " "for interface %s, it isn't nl80211?", interface); return NL80211_CHANLIST_NOT_NL80211; } if (nl80211_connect(interface, &handle, &cache, &family, errstr) < 0) { return NL80211_CHANLIST_GENERIC; } msg = nlmsg_alloc(); cb = nl_cb_alloc(NL_CB_DEFAULT); err = 1; nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_freqlist_cb, &cblock); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_finish_cb, &err); nl_cb_err(cb, NL_CB_CUSTOM, nl80211_error_cb, &err); genlmsg_put(msg, 0, 0, genl_family_get_id((struct genl_family *) family), 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0); if (nl_send_auto_complete((struct nl_sock *) handle, msg) < 0) { snprintf(errstr, LORCON_STATUS_MAX, "%s: Failed to write nl80211 message", __FUNCTION__); nl80211_disconnect(handle); return NL80211_CHANLIST_GENERIC; } while (err) nl_recvmsgs((struct nl_sock *) handle, cb); nl80211_disconnect(handle); (*ret_num_chans) = cblock.nfreqs; (*ret_chan_list) = (int *) malloc(sizeof(int) * cblock.nfreqs); memcpy(*ret_chan_list, cblock.channel_list, sizeof(int) * cblock.nfreqs); free(cblock.channel_list); free(cblock.phyname); return (*ret_num_chans); #endif }
static int execute_nl_interface_cmd(const char *iface, enum nl80211_iftype type, uint8_t cmd) { struct nl_cb *cb; struct nl_msg *msg; int devidx = 0; int err; int add_interface = (cmd == NL80211_CMD_NEW_INTERFACE); if (add_interface) { devidx = phy_lookup(); } else { devidx = if_nametoindex(iface); if (devidx == 0) { ALOGE("failed to translate ifname to idx"); return -errno; } } msg = nlmsg_alloc(); if (!msg) { ALOGE("failed to allocate netlink message"); return 2; } cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) { ALOGE("failed to allocate netlink callbacks"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, 0, cmd, 0); if (add_interface) { NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, devidx); } else { NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); } if (add_interface) { NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, iface); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type); } err = nl_send_auto_complete(nl_soc, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, nl_error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, &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: ALOGW("building message failed"); return 2; }
wifi_error wifi_initialize(wifi_handle *handle) { int err = 0; srand(getpid()); ALOGI("Initializing wifi"); hal_info *info = (hal_info *)malloc(sizeof(hal_info)); if (info == NULL) { ALOGE("Could not allocate hal_info"); return WIFI_ERROR_UNKNOWN; } memset(info, 0, sizeof(*info)); ALOGI("Creating socket"); struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT); if (cmd_sock == NULL) { ALOGE("Could not create handle"); return WIFI_ERROR_UNKNOWN; } struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT); if (event_sock == NULL) { ALOGE("Could not create handle"); nl_socket_free(cmd_sock); return WIFI_ERROR_UNKNOWN; } struct nl_cb *cb = nl_socket_get_cb(event_sock); if (cb == NULL) { ALOGE("Could not create handle"); return WIFI_ERROR_UNKNOWN; } err = 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, &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); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); nl_cb_put(cb); info->cmd_sock = cmd_sock; info->event_sock = event_sock; info->clean_up = false; info->in_event_loop = false; info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; info->num_event_cb = 0; info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); info->alloc_cmd = DEFAULT_CMD_SIZE; info->num_cmd = 0; info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); if (info->nl80211_family_id < 0) { ALOGE("Could not resolve nl80211 familty id"); nl_socket_free(cmd_sock); nl_socket_free(event_sock); free(info); return WIFI_ERROR_UNKNOWN; } ALOGI("%s: family_id:%d", __func__, info->nl80211_family_id); *handle = (wifi_handle) info; wifi_add_membership(*handle, "scan"); wifi_add_membership(*handle, "mlme"); wifi_add_membership(*handle, "regulatory"); wifi_add_membership(*handle, "vendor"); wifi_init_interfaces(*handle); // ALOGI("Found %d interfaces", info->num_interfaces); ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d handle %p", NL80211_CMD_VENDOR , *handle); return WIFI_SUCCESS; }
static int __handle_cmd(struct nl80211_state *state, const char *iface, int get) { struct nl_cb *cb; struct nl_msg *msg; int devidx = 0; int err; devidx = if_nametoindex(iface); if (devidx == 0) devidx = -1; if (devidx < 0) return -errno; msg = nlmsg_alloc(); if (!msg) { fprintf(stderr, "failed to allocate netlink message\n"); return 2; } cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) { fprintf(stderr, "failed to allocate netlink callbacks\n"); err = 2; goto out_free_msg; } if (get) genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_GET_POWER_SAVE, 0); else genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_SET_POWER_SAVE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); if (get) err = get_power_save(state, cb, msg); else err = set_power_save(state, cb, msg); if (err) goto out; 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; }