# Targets to build
STATIC=libiw.a
DYNAMIC=libiw.so.$(WT_VERSION)
PROGS= iwconfig iwlist iwpriv iwspy iwgetid iwevent ifrename #PROGS这个变量就是要编译的工具
MANPAGES8=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8 iwgetid.8 iwevent.8 ifrename.8
MANPAGES7=wireless.7
MANPAGES5=iftab.5
EXTRAPROGS= macaddr iwmulticall
# Composition of the library :
OBJS = iwlib.o
# Select which library to build and to link tool with
BUILD_STATIC = 1 #将iwlib编译成.a
ifdef BUILD_STATIC
IWLIB=$(STATIC)
IWLIB_INSTALL=install-static
else
IWLIB=$(DYNAMIC)
IWLIB_INSTALL=install-dynamic
endif
# Standard compilation targets
all:: $(IWLIB) $(PROGS)
%: %.o
$(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS)
%.o: %.c wireless.h
$(CC) $(XCFLAGS) -c $<
%.so: %.c wireless.h
$(CC) $(XCFLAGS) $(PICFLAG) -c -o $@ $<
iwconfig: iwconfig.o $(IWLIB)
iwlist: iwlist.o $(IWLIB)
iwpriv: iwpriv.o $(IWLIB)
iwspy: iwspy.o $(IWLIB)
iwgetid: iwgetid.o $(IWLIB)
iwevent: iwevent.o $(IWLIB)
ifrename: ifrename.o $(IWLIB)
macaddr: macaddr.o $(IWLIB)
# Always do symbol stripping here
iwmulticall: iwmulticall.o
$(CC) $(LDFLAGS) -Wl,-s $(XCFLAGS) -o $@ $^ $(LIBS)
# It's a kind of magic...
wireless.h:
cp $(WEXT_HEADER) wireless.h
# Compilation of the dynamic library
$(DYNAMIC): $(OBJS:.o=.so)
$(CC) -shared -o $@ -Wl,-soname,$@ $(STRIPFLAGS) $(LIBS) -lc $^
# Compilation of the static library
$(STATIC): $(OBJS:.o=.so)
$(RM) $@
$(AR) cru $@ $^
$(RANLIB) $@
先上修改后的Makefile快照,这个Makefile的目的是选择性的将iwxxx.c链接成wifiopt.a
# Always use local header for wireless extensions
WEXT_HEADER = wireless.$(WE_VERSION).h
# Targets to build
STATIC=libiw.a
DYNAMIC=libiw.so.$(WT_VERSION)
PROGS= iwpriv iwspy iwgetid ifrename #这里不选编译iwconfig.c iwlist.c iwevent.c iwmulticall.c因为它们的main函数改成接口函数
MANPAGES8=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8 iwgetid.8 iwevent.8 ifrename.8
MANPAGES7=wireless.7
MANPAGES5=iftab.5
EXTRAPROGS= macaddr iwmulticall
# Composition of the library :
OBJS = iwlib.o
OPWIFI = iwconfig.c iwlist.c iwevent.c iwmulticall.c #新增变量将这里的.c编成libwifi_opt.a
SRC_WIFI = $(wildcard $(OPWIFI))
OBJ_WIFI = $(SRC_WIFI:%.c=%.o)
BUILD_STATIC :=1
# Select which library to build and to link tool with
ifdef BUILD_STATIC
IWLIB=$(STATIC)
IWLIB_INSTALL=install-static
else
IWLIB=$(DYNAMIC)
IWLIB_INSTALL=install-dynamic
endif
# Standard name for dynamic library so that the dynamic linker can pick it.
# We will just create a symbolic link to the real thing.
DYNAMIC_LINK= libiw.so
# Various commands
RM = rm -f
RM_CMD = $(RM) *.BAK *.bak *.d *.o *.so ,* *~ *.a *.orig *.rej *.out ../../../../osdrv/rootfs_scripts/rootfs/usr/lib/libiw.so.29
LDCONFIG = ldconfig
# Do we want to build with or without libm ?
ifdef BUILD_NOLIBM
LIBS=
WELIB_FLAG= -DWE_NOLIBM=y
else
LIBS= -lm
endif
# Other flags
CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \
-Wpointer-arith -Wcast-qual -Winline -I.
#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I.
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG) $(WEDEF_FLAG)
PICFLAG=-fPIC
# Standard compilation targets
all:: $(IWLIB) $(PROGS)
%: %.o
$(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS)
%.o: %.c wireless.h
$(CC) $(XCFLAGS) -c $<
%.so: %.c wireless.h
$(CC) $(XCFLAGS) $(PICFLAG) -c -o $@ $<
iwconfig: iwconfig.o $(IWLIB)
iwlist: iwlist.o $(IWLIB)
iwpriv: iwpriv.o $(IWLIB)
iwspy: iwspy.o $(IWLIB)
iwgetid: iwgetid.o $(IWLIB)
iwevent: iwevent.o $(IWLIB)
ifrename: ifrename.o $(IWLIB)
macaddr: macaddr.o $(IWLIB)
wifiopt: libwifi_opt.a
##############################################################################
libwifi_opt.a: $(OBJ_WIFI) #利用OBJ_WIFI 生成libwifi_opt.a
$(AR) -r libwifi_opt.a $^
%.o: %.c wireless.h
$(CC) $(XCFLAGS) -c $<
%.a: %.c wireless.h
$(CC) $(XCFLAGS) $(PICFLAG) -c -o $@ $<
##############################################################################
# It's a kind of magic... '
wireless.h:
cp $(WEXT_HEADER) wireless.h
# Compilation of the dynamic library
$(DYNAMIC): $(OBJS:.o=.so)
$(CC) -shared -o $@ -Wl,-soname,$@ $(STRIPFLAGS) $(LIBS) -lc $^
# Compilation of the static library
$(STATIC): $(OBJS:.o=.so)
$(RM) $@
$(AR) cru $@ $^
$(RANLIB) $@
好了,做到这里已经完成一大半了,剩下的工具只需要在原main函数做入口做过滤驱动就好了。(前提仔细分析iwxxx.c结构)。
这里详细分析如何借助iwlist.c获取搜索WiFi状态,获取WiFi信息的都是大同小异的。(详细请看文末github源码)
先上修改过的iwmulticall.c源码(这个是提供接口.c)
/*create by jinfa
*这是一个应用接口,它依赖于iwlist.c iwevent.c iwconfig.c
*由之前的iwmulticall.c改成
*
*/
/***************************** INCLUDES *****************************/
#include /* Basename */
#include "iwlib.h"
#define WITHNO_ACCOUNT 0
#define WITH_ACCOUNT 1
/*
*获取wifi对象信息
*operstate fd 为0时 link参数无效。
*/
struct p_curwifi *get_curwifi_info(struct p_curwifi *cur_wifi, int operstate_fd) //调用iwconfig
{
if(main_iwconfig(cur_wifi, operstate_fd))
return NULL;
return cur_wifi;
}
//获取wifi列表
void get_wifi_list(struct p_wifi_list *wifi_list_head) //调用iwlist
{
main_iwlist(wifi_list_head);
}
/*
*功能:给用户提供链接wifi接口
*参数:
*conn_wifi:用户传入需要链接的对象
*mode: 用户指定系统是否只使用conn_wifi这个信息链接wifi
*当mode为WITH_ACCOUNT系统只使用conn_wifi这个信息链接wifi
*当mode为WITHNO_ACCOUNT系统使用当前wpa2_wpa.conf脚本存留的信息链接wifi \
*这种情况多用于,用户已经配置wifi并系统刚启动的情况
*/
int link_wifi(struct p_connect *conn_wifi, int mode)
{
char acount[256] = {0};
if(mode == WITH_ACCOUNT)
{
sprintf(acount, "sed -i \" s/ssid=.*/ssid=\"\\\"%s\"\\\" / ; s/psk=.*/psk=\"\\\"%s\"\\\" /\" /etc/wpa_wpa2.conf", \
conn_wifi->essid, conn_wifi->password_wifi);
system(acount);
}
system("wpa_supplicant -iwlan0 -B -c /etc/wpa_wpa2.conf");
return 0;
}
很明显main_iwlist,就是以前iwlist的main函数。
那我们看看iwlist改成啥样了。
/******************************* MAIN ********************************/
/*------------------------------------------------------------------*/
/*
* The main !
*/
int main_iwlist(struct p_wifi_list *wifi_list_head)
{
int skfd; /* generic raw socket desc. */
char *dev = "wlan0"; /* device name */
char **args; /* Command arguments */
int count; /* Number of arguments */
int argc = 3;
char *argv[3];
argv[0] = "iwlist";
argv[1] = "wlan0";
argv[2] = "scanning";
args = argv + 3;
count = argc - 3;
//我们不需要让iwlist找寻命令
#if 0
/* find a command */
iwcmd = find_command(cmd);
if(iwcmd == NULL)
return 1;
/* Check arg numbers */
if((iwcmd->max_count >= 0) && (count > iwcmd->max_count))
{
fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n",
iwcmd->cmd, iwcmd->max_count);
return 1;
}
/* Create a channel to the NET kernel. */
if((skfd = iw_sockets_open()) < 0)
{
perror("socket");
return -1;
}
/* do the actual work */
if (dev)
(*iwcmd->fn)(skfd, dev, args, count);
else
iw_enum_devices(skfd, iwcmd->fn, args, count);
#endif
/* Create a channel to the NET kernel. */
if((skfd = iw_sockets_open()) < 0)
{
perror("socket");
return -1;
}
/* do the actual work */
print_scanning_info(skfd, dev, args, count, wifi_list_head); //我们在这里传入wifi_list_head头结点
/* Close the socket. */
iw_sockets_close(skfd);
return 0;
}
继续分析print_scanning_info函数
static int
print_scanning_info(int skfd,
char * ifname,
char * args[], /* Command line args */
int count, struct p_wifi_list *wifi_list_head) /* Args count */
...
...
直接看改动的地方。。大概在865行增加这些。
struct p_wifi_list *node = NULL;
do
{
/* Extract an event and print it */
ret = iw_extract_event_stream(&stream, &iwe,
range.we_version_compiled); //扫描一次
if(ret > 0){
if(iwe.cmd == SIOCGIWESSID){
node = creat_wifi_list_node(); //创建节点
}
print_scanning_token(&stream, &iwe, &state,
&range, has_range, wifi_list_head, node); //打印一次,通过这个函数能获取我们想要的。
if(iwe.cmd == IWEVQUAL){
add_list_tail(wifi_list_head, node); //加入链表头,其实这里完成一次截取。
}
}
}while(ret > 0);
继续分析print_scanning_token函数
print_scanning_token(struct stream_descr * stream, /* Stream of events */
struct iw_event * event, /* Extracted token */
struct iwscan_state * state,
struct iw_range * iw_range, /* Range info */
int has_range,
struct p_wifi_list *wifi_list_head, struct p_wifi_list *node)
...
...
直接看改动的地方。。
在512行增加 strcpy(node->ESSID, essid);
在587行增加node->Singal = event->u.qual.level -256;
我们看下自定义的p_wifi_list结构体
struct p_wifi_list {
char *ESSID;
short Singal;
struct p_wifi_list *next;
};
总结,在这些过滤代码的支持下,应用就可以借助开源软件的优势来达到获取WiFi信息的目的。
github:https://github.com/Mr-jinfa/iwtools4wifi