Comment envoyer une demande d’parsing de canal unique à libnl et recevoir une réponse d’achèvement d’parsing de canal unique pour le canal correspondant

J’envoie un SSID et une fréquence uniques à libnl pour parsing, mais j’ai obtenu plusieurs résultats d’parsing avec le SSID et la fréquence demandés, mais j’ai besoin d’un résultat d’parsing unique (uniquement pour le SSID demandé). Aidez-moi, je vous envoie aussi mon code. Ce code fonctionnera.

Comstackr: gcc -g -o scan scantesthandler.c -L /usr/lib/i386-linux-gnu/libnl.so -lnl

Exécuter avec le journal de débogage: NLCB = debug ./scan

#include #include #include #include #include #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  static int expectedId; static int ifIndex; struct wpa_scan_res { unsigned char bssid[6]; int freq; }; static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { int *ret = arg; *ret = err->error; return NL_SKIP; } static int finish_handler(struct nl_msg *msg, void *arg) { int *ret = arg; *ret = 0; return NL_SKIP; } static int ack_handler(struct nl_msg *msg, void *arg) { int *err = arg; *err = 0; return NL_STOP; } static int bss_info_handler(struct nl_msg *msg, void *arg) { printf("\nFunction: %s, Line: %d\n",__FUNCTION__,__LINE__); struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *bss[NL80211_BSS_MAX + 1]; static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, [NL80211_BSS_TSF] = { .type = NLA_U64 }, [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, [NL80211_BSS_STATUS] = { .type = NLA_U32 }, [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 }, [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC }, }; struct wpa_scan_res *r = NULL; r = (struct wpa_scan_res*)malloc(sizeof(struct wpa_scan_res)); nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!tb[NL80211_ATTR_BSS]) return NL_SKIP; if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy)) return NL_SKIP; if (bss[NL80211_BSS_BSSID]) memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),6); if (bss[NL80211_BSS_FREQUENCY]) r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); printf("\nFrequency: %d ,BSSID: %2x:%2x:%2x:%2x:%2x:%2x",r->freq,r->bssid[0],r->bssid[1],r->bssid[2],r->bssid[3],r->bssid[4],r->bssid[5]); return NL_SKIP; } static struct nl_msg* nl80211_scan_common(uint8_t cmd, int expectedId) { const char* ssid = "amitssid"; int ret; struct nl_msg *msg; int err; size_t i; int flags = 0,ifIndex; msg = nlmsg_alloc(); if (!msg) return NULL; // setup the message if(NULL==genlmsg_put(msg, 0, 0, expectedId, 0, flags, cmd, 0)) { printf("\nError return genlMsg_put\n"); } else { printf("\nSuccess genlMsg_put\n"); } ifIndex = if_nametoindex("wlan1"); if(nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifIndex) < 0) { goto fail; } struct nl_msg *ssids = nlmsg_alloc(); if(nla_put(ssids, 1,strlen(ssid) ,ssid) <0) { nlmsg_free(ssids); goto fail; } err = nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS,ssids); nlmsg_free(ssids); if (err < 0) goto fail; struct nl_msg *freqs = nlmsg_alloc(); if( nla_put_u32(freqs,1 ,2437) < 0) //amitssid { printf("\nnla_put_fail\n"); goto fail; } else { printf("\nnla_put_u32 pass\n"); } //add message attributes if(nla_put_nested(msg, NL80211_FREQUENCY_ATTR_FREQ,freqs) < 0) { printf("\nnla_put_nested failing:\n"); } else { printf("\nnla_put_nested pass\n"); } nlmsg_free(freqs); if (err < 0) goto fail; return msg; nla_put_failure: printf("\nnla_put_failure\n"); nlmsg_free(msg); return NULL; fail: nlmsg_free(msg); return NULL; } int main(int argc, char** argv) { struct nl_msg *msg= NULL; int ret = -1; struct nl_cb *cb = NULL; int err = -ENOMEM; int returnvalue,getret; int ifIndex, callbackret=-1; struct nl_sock* sk = (void*)nl_handle_alloc(); if(sk == NULL) { printf("\nmemory error\n"); return; } cb = nl_cb_alloc(NL_CB_CUSTOM); if(cb == NULL) { printf("\nfailed to allocate netlink callback\n"); } enum nl80211_commands cmd; if(genl_connect((void*)sk)) { printf("\nConnected failed\n"); return; } //find the nl80211 driverID expectedId = genl_ctrl_resolve((void*)sk, "nl80211"); if(expectedId < 0) { printf("\nnegative error code returned\n"); return; } else { printf("\ngenl_ctrl_resolve returned:%d\n",expectedId); } msg = nl80211_scan_common(NL80211_CMD_TRIGGER_SCAN, expectedId); if (!msg) { printf("\nmsgbal:\n"); return -1; } err = nl_send_auto_complete((void*)sk, msg); if (err < 0) goto out; else { printf("\nSent successfully\n"); } 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); callbackret = nl_cb_set(cb,NL_CB_VALID,NL_CB_CUSTOM,bss_info_handler,&err); if(callbackret < 0) { printf("\n*************CallbackRet failed:***************** %d\n",callbackret); } else { printf("\n*************CallbackRet pass:***************** %d\n",callbackret); } returnvalue=nl_recvmsgs((void*)sk,cb); printf("\n returnval:%d\n",returnvalue); nlmsg_free(msg); msg = NULL; msg = nlmsg_alloc(); if (!msg) return -1; if(NULL==genlmsg_put(msg, 0, 0, expectedId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0)) { printf("\nError return genlMsg_put\n"); } else { printf("\nSuccess genlMsg_put\n"); } ifIndex = if_nametoindex("wlan1"); printf("\nGet Scaninterface returned :%d\n",ifIndex); nla_put_u32(msg,NL80211_ATTR_IFINDEX,ifIndex); err = nl_send_auto_complete((void*)sk,msg); if(err < 0) goto out; err = 1; getret= nl_recvmsgs((void*)sk,cb); printf("\nGt Scan resultreturn:%d\n",getret); out: nlmsg_free(msg); return err; nla_put_failure: printf("\nnla_put_failure\n"); nlmsg_free(msg); return err; } 

Vous pouvez simplement copier et coller ce code sur votre système et l’exécuter.

    Autant que je sache (et que j’ai déjà vu), la commande et le résultat de l’parsing dépendent du pilote de périphérique du fournisseur. Une chose est certaine, il n’ya pas d’option pour rechercher un SSID spécifique; au lieu de cela, vous pouvez obtenir tous les résultats de l’parsing et vérifier en boucle si le ssid est dans la liste ou non (wpa_supplicant utilise ce mécanisme pour faire correspondre la configuration réseau au résultat de l’parsing).

    En ce qui concerne la fréquence, il devrait être possible d’parsingr uniquement un certain canal si le pilote de périphérique dispose de cette fonctionnalité. Mais en règle générale, la commande scan parsing tous les canaux et renvoie le SSID (pensez à votre gestionnaire de réseau; il affiche tout le SSID disponible trouvé pour une commande de scan. Celui-ci est essentiellement publié par le pilote de périphérique via cfg80211).