2014-05-20 2 views
0

libnl에 단일 SSID 및 주파수를 보내 스캔하고 있지만 요청한 SSID 및 빈도와 함께 여러 스캔 결과가 나타납니다. 나는 그것을 달성하는 방법, 단일 스캔 결과 (요청한 SSID에 대해서만)가 필요합니다. 친절하게 도와주세요. 코드도 보내고 있습니다.이 코드가 실행됩니다.libnl에 단일 채널 스캔 요청을 보내고 해당 채널에 대한 단일 채널 스캔 완료 응답을 수신하는 방법

컴파일 : gcc가 -g -o 스캔 scantesthandler.c -L /usr/lib/i386-linux-gnu/libnl.so -lnl 디버그 로그와

실행 :

./scan NLCB = 디버그
#include<assert.h> 
#include<errno.h> 
#include<ifaddrs.h> 
#include<netdb.h> 
#include<stddef.h> 
#include <string.h> 
#include <time.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <asm/types.h> 
#include <linux/rtnetlink.h> 
#include <netlink/netlink.h> 
#include <netlink/msg.h> 
#include <netlink/cache.h> 
#include <netlink/socket.h> 
#include <netlink/genl/genl.h> 
#include <netlink/genl/ctrl.h> 
#include <stdlib.h> 
#include <netlink/genl/genl.h> 
#include <netlink/genl/ctrl.h> 
#include <netlink/route/link.h> 
#include <linux/nl80211.h> 

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; 
} 

이 코드를 복사하여 시스템에 붙여 넣기 만하면됩니다.

답변

1

내가 아는 한 (그리고 이미 보았 듯이) 스캔 명령과 결과는 공급 업체의 장치 드라이버에 따라 다릅니다. 한 가지 확실한 점은 특정 ssid를 검색하는 옵션이 없다는 것입니다. 대신에 모든 스캔 결과를 얻고 루프를 통해 ssid가 목록에 있는지 여부를 확인하십시오 (wpa_supplicant는이 구성을 사용하여 네트워크 구성을 검사 결과와 일치시킵니다).

이제 주파수에 대해 장치 드라이버에 해당 기능이있는 경우 특정 채널 만 검사 할 수 있어야합니다. 그러나 일반적으로 스캔 명령은 모든 채널을 스캔하고 SSID를 반환합니다 (네트워크 관리자를 생각하면 스캔 명령에 대해 사용 가능한 모든 SSID가 표시됩니다. 이는 기본적으로 cfg80211을 통해 장치 드라이버에서 게시됩니다).