news 2026/9/16 9:43:19

【2016-02-23】Linux无线模块WEXT简单分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【2016-02-23】Linux无线模块WEXT简单分析

[历史归档]本文原发布于 cstriker1407.info 个人博客,内容为历史存档,仅供参考。
发布时间:2016-02-23| 标题:Linux无线模块WEXT简单分析分类:操作系统 / linux / kernel |标签:linux·kernel·wext


Linux无线模块WEXT简单分析

在新版本的linux中,WIFI使用过nl80211来配置的,但是wext也是保留的,方便其他工具使用。作者最近就在工作中遇到了这个问题,很多配置需要通过iw工具集来实现。那么这里就简单的笔记下wext吧。

PS:作者对于linux网络架构理解的非常浅显,可能有错误,还请大家多多指正。而且有ioctl的数目繁多,这里就简单的笔记下主干分发过程,具体驱动在具体分析吧。

当我们调用socket进行协议调用时,会在文件操作中支持ioctl操作:
/net/socket.c

/* * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear * in the operation structures but are done directly via the socketcall() multiplexor. */staticconststructfile_operationssocket_file_ops={。。。.unlocked_ioctl=sock_ioctl,#ifdefCONFIG_COMPAT.compat_ioctl=compat_sock_ioctl,#endif};/* 由于socket是通用架构,因此这里不会有具体的ioctl的实现,而是基于每个注册到该协议里的dev的实现 */staticlongsock_ioctl(structfile*file,unsignedcmd,unsignedlongarg){structsocket*sock;structsock*sk;void__user*argp=(void__user*)arg;intpid,err;structnet*net;sock=file->private_data;sk=sock->sk;net=sock_net(sk);/* 可以看到,只要是cmd符合一定的要求的,全部路由到指定dev中实现 */if(cmd>=SIOCDEVPRIVATE&&cmd<=(SIOCDEVPRIVATE+15)){err=dev_ioctl(net,cmd,argp);}else#ifdefCONFIG_WIRELESS_EXTif(cmd>=SIOCIWFIRST&&cmd<=SIOCIWLAST){err=dev_ioctl(net,cmd,argp);}else#endif/* CONFIG_WIRELESS_EXT */switch(cmd){caseFIOSETOWN:caseSIOCSPGRP:err=-EFAULT;if(get_user(pid,(int__user*)argp))break;err=f_setown(sock->file,pid,1);break;caseFIOGETOWN:caseSIOCGPGRP:err=put_user(f_getown(sock->file),(int__user*)argp);break;caseSIOCGIFBR:caseSIOCSIFBR:caseSIOCBRADDBR:caseSIOCBRDELBR:err=-ENOPKG;if(!br_ioctl_hook)request_module("bridge");mutex_lock(&br_ioctl_mutex);if(br_ioctl_hook)err=br_ioctl_hook(net,cmd,argp);mutex_unlock(&br_ioctl_mutex);break;caseSIOCGIFVLAN:caseSIOCSIFVLAN:err=-ENOPKG;if(!vlan_ioctl_hook)request_module("8021q");mutex_lock(&vlan_ioctl_mutex);if(vlan_ioctl_hook)err=vlan_ioctl_hook(net,argp);mutex_unlock(&vlan_ioctl_mutex);break;caseSIOCADDDLCI:caseSIOCDELDLCI:err=-ENOPKG;if(!dlci_ioctl_hook)request_module("dlci");mutex_lock(&dlci_ioctl_mutex);if(dlci_ioctl_hook)err=dlci_ioctl_hook(cmd,argp);mutex_unlock(&dlci_ioctl_mutex);break;default:err=sock->ops->ioctl(sock,cmd,arg);/* * If this ioctl is unknown try to hand it down * to the NIC driver. */if(err==-ENOIOCTLCMD)err=dev_ioctl(net,cmd,argp);break;}returnerr;}

/net/core/dev.c

/* 同样,dev也是通用代码,但是在代码的最后会有wext的配置 */intdev_ioctl(structnet*net,unsignedintcmd,void__user*arg){structifreqifr;intret;char*colon;/* One special case: SIOCGIFCONF takes ifconf argument and requires shared lock, because it sleeps writing to user space. */if(cmd==SIOCGIFCONF){rtnl_lock();ret=dev_ifconf(net,(char__user*)arg);rtnl_unlock();returnret;}if(cmd==SIOCGIFNAME)returndev_ifname(net,(structifreq__user*)arg);if(copy_from_user(&ifr,arg,sizeof(structifreq)))return-EFAULT;ifr.ifr_name[IFNAMSIZ-1]=0;colon=strchr(ifr.ifr_name,':');if(colon)*colon=0;/* * See which interface the caller is talking about. */switch(cmd){/* * These ioctl calls: * - can be done by all. * - atomic and do not require locking. * - return a value */caseSIOCGIFFLAGS:caseSIOCGIFMETRIC:caseSIOCGIFMTU:caseSIOCGIFHWADDR:caseSIOCGIFSLAVE:caseSIOCGIFMAP:caseSIOCGIFINDEX:caseSIOCGIFTXQLEN:dev_load(net,ifr.ifr_name);read_lock(&dev_base_lock);ret=dev_ifsioc_locked(net,&ifr,cmd);read_unlock(&dev_base_lock);if(!ret){if(colon)*colon=':';if(copy_to_user(arg,&ifr,sizeof(structifreq)))ret=-EFAULT;}returnret;caseSIOCETHTOOL:dev_load(net,ifr.ifr_name);rtnl_lock();ret=dev_ethtool(net,&ifr);rtnl_unlock();if(!ret){if(colon)*colon=':';if(copy_to_user(arg,&ifr,sizeof(structifreq)))ret=-EFAULT;}returnret;/* * These ioctl calls: * - require superuser power. * - require strict serialization. * - return a value */caseSIOCGMIIPHY:caseSIOCGMIIREG:caseSIOCSIFNAME:if(!capable(CAP_NET_ADMIN))return-EPERM;dev_load(net,ifr.ifr_name);rtnl_lock();ret=dev_ifsioc(net,&ifr,cmd);rtnl_unlock();if(!ret){if(colon)*colon=':';if(copy_to_user(arg,&ifr,sizeof(structifreq)))ret=-EFAULT;}returnret;/* * These ioctl calls: * - require superuser power. * - require strict serialization. * - do not return a value */caseSIOCSIFFLAGS:caseSIOCSIFMETRIC:caseSIOCSIFMTU:caseSIOCSIFMAP:caseSIOCSIFHWADDR:caseSIOCSIFSLAVE:caseSIOCADDMULTI:caseSIOCDELMULTI:caseSIOCSIFHWBROADCAST:caseSIOCSIFTXQLEN:caseSIOCSMIIREG:caseSIOCBONDENSLAVE:caseSIOCBONDRELEASE:caseSIOCBONDSETHWADDR:caseSIOCBONDCHANGEACTIVE:caseSIOCBRADDIF:caseSIOCBRDELIF:caseSIOCSHWTSTAMP:if(!capable(CAP_NET_ADMIN))return-EPERM;/* fall through */caseSIOCBONDSLAVEINFOQUERY:caseSIOCBONDINFOQUERY:dev_load(net,ifr.ifr_name);rtnl_lock();ret=dev_ifsioc(net,&ifr,cmd);rtnl_unlock();returnret;caseSIOCGIFMEM:/* Get the per device memory space. We can add this but * currently do not support it */caseSIOCSIFMEM:/* Set the per device memory buffer space. * Not applicable in our case */caseSIOCSIFLINK:return-EINVAL;/* * Unknown or private ioctl. */default:if(cmd==SIOCWANDEV||(cmd>=SIOCDEVPRIVATE&&cmd<=SIOCDEVPRIVATE+15)){dev_load(net,ifr.ifr_name);rtnl_lock();ret=dev_ifsioc(net,&ifr,cmd);rtnl_unlock();if(!ret&&copy_to_user(arg,&ifr,sizeof(structifreq)))ret=-EFAULT;returnret;}/* 如果ioctl号码在wext中,那么额外处理 *//* Take care of Wireless Extensions */if(cmd>=SIOCIWFIRST&&cmd<=SIOCIWLAST)returnwext_handle_ioctl(net,&ifr,cmd,arg);return-EINVAL;}}

/net/wireless/wext.c

/* wext针对ioctl的路由主函数 */intwext_handle_ioctl(structnet*net,structifreq*ifr,unsignedintcmd,void__user*arg){structiw_request_infoinfo={.cmd=cmd,.flags=0};intret;/* 继续分发 */ret=wext_ioctl_dispatch(net,ifr,cmd,&info,ioctl_standard_call,ioctl_private_call);if(ret>=0&&IW_IS_GET(cmd)&&copy_to_user(arg,ifr,sizeof(structiwreq)))return-EFAULT;returnret;}/* entry point from dev ioctl */staticintwext_ioctl_dispatch(structnet*net,structifreq*ifr,unsignedintcmd,structiw_request_info*info,wext_ioctl_func standard,wext_ioctl_func private){intret=wext_permission_check(cmd);if(ret)returnret;dev_load(net,ifr->ifr_name);rtnl_lock();/* 继续分发 */ret=wireless_process_ioctl(net,ifr,cmd,info,standard,private);rtnl_unlock();returnret;}在分析wireless_process_ioctl之前,先看下standand和private两个函数/* standand函数实现 这里是wext的标准ioctl的实现 由于wext已经不再开发,只是维护,因此这里代码会尽可能的转到nl80211上去,(wireless_send_event 会通过构建nlmsg发到内核netlink队列里,然后同nl80211进行实现),不过也有可能WIFI驱动定义了自己的 标准的IOCTL的实现函数,这里不再分析。 */staticintioctl_standard_call(structnet_device*dev,structiwreq*iwr,unsignedintcmd,structiw_request_info*info,iw_handler handler){conststructiw_ioctl_description*descr;intret=-EINVAL;/* Get the description of the IOCTL */if((cmd-SIOCIWFIRST)>=standard_ioctl_num)return-EOPNOTSUPP;descr=&(standard_ioctl);/* Check if we have a pointer to user space data or not */if(descr->header_type!=IW_HEADER_TYPE_POINT){/* No extra arguments. Trivial to handle */ret=handler(dev,info,&(iwr->u),NULL);/* Generate an event to notify listeners of the change */if((descr->flags&IW_DESCR_FLAG_EVENT)&&((ret==0)||(ret==-EIWCOMMIT)))wireless_send_event(dev,cmd,&(iwr->u),NULL);}else{ret=ioctl_standard_iw_point(&iwr->u.data,cmd,descr,handler,dev,info);}/* Call commit handler if needed and defined */if(ret==-EIWCOMMIT)ret=call_commit_handler(dev);/* Here, we will generate the appropriate event if needed */returnret;}/* private函数实现 由于这里的ioctl都不是标准的,因此只能通过驱动中自定义的ioctl来实现 */staticintioctl_private_call(structnet_device*dev,structiwreq*iwr,unsignedintcmd,structiw_request_info*info,iw_handler handler){intextra_size=0,ret=-EINVAL;conststructiw_priv_args*descr;extra_size=get_priv_descr_and_size(dev,cmd,&descr);/* Check if we have a pointer to user space data or not. */if(extra_size==0){/* No extra arguments. Trivial to handle */ret=handler(dev,info,&(iwr->u),(char*)&(iwr->u));}else{ret=ioctl_private_iw_point(&iwr->u.data,cmd,descr,handler,dev,info,extra_size);}/* Call commit handler if needed and defined */if(ret==-EIWCOMMIT)ret=call_commit_handler(dev);returnret;}最后在来分析wireless_process_ioctl函数/* ioctl分发实现函数 */staticintwireless_process_ioctl(structnet*net,structifreq*ifr,unsignedintcmd,structiw_request_info*info,wext_ioctl_func standard,wext_ioctl_func private){structiwreq*iwr=(structiwreq*)ifr;structnet_device*dev;iw_handler handler;/* Permissions are already checked in dev_ioctl() before calling us. * The copy_to/from_user() of ifr is also dealt with in there *//* Make sure the device exist */if((dev=__dev_get_by_name(net,ifr->ifr_name))==NULL)return-ENODEV;/* 调用标准实现 *//* A bunch of special cases, then the generic case... * Note that 'cmd' is already filtered in dev_ioctl() with * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */if(cmd==SIOCGIWSTATS)returnstandard(dev,iwr,cmd,info,&iw_handler_get_iwstats);if(cmd==SIOCGIWPRIV&&dev->wireless_handlers)returnstandard(dev,iwr,cmd,info,&iw_handler_get_private);/* Basic check */if(!netif_device_present(dev))return-ENODEV;/* 如果WIFI驱动定义了自己的ioctl的实现函数,那么这里就可以处理 *//* New driver API : try to find the handler */handler=get_handler(dev,cmd);if(handler){/* Standard and private are not the same */if(cmd<SIOCIWFIRSTPRIV)returnstandard(dev,iwr,cmd,info,handler);elsereturnprivate(dev,iwr,cmd,info,handler);}/* 如果WIFI驱动没有定义自己的ioctl实现,但是定义了ndo_do_ioctl函数,也可以调用该函数进行实现 *//* Old driver API : call driver ioctl handler */if(dev->netdev_ops->ndo_do_ioctl)returndev->netdev_ops->ndo_do_ioctl(dev,ifr,cmd);return-EOPNOTSUPP;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 9:43:01

固定资产新增API实战:从表设计到接口联调全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 9:42:49

新闻资讯微信小程序毕设开发全攻略:从选题到答辩避坑指南

每年到毕设季&#xff0c;都会有大量同学来问同一个问题&#xff1a;做什么题目既好过、又能写进简历&#xff0c;最好还能拿出来演示不丢人。我做了这么多年开发&#xff0c;也带过不少实习生&#xff0c;实话实说&#xff0c;新闻资讯微信小程序这类题目始终是稳妥之选。它不…

作者头像 李华
网站建设 2026/9/16 9:42:00

转向器壳体三维夹具设计:提升加工精度与效率

1. 项目概述&#xff1a;转向器壳体夹具的三维设计在汽车零部件制造领域&#xff0c;转向器壳体作为转向系统的核心承载部件&#xff0c;其加工精度直接影响整车的操控性能和安全系数。传统二维夹具设计存在定位误差大、调试周期长的问题&#xff0c;而三维数字化设计能实现加工…

作者头像 李华
网站建设 2026/9/16 9:40:29

企业级Agent平台如何让“超级个体”进化为“超级团队”?

1. 单打独斗的 Agent 撑不起企业场景&#xff1a;WorkBuddy Enterprise 到底在补什么课过去一年半&#xff0c;圈子里最热的概念就是“超级个体”。一个人挂三五个 Agent&#xff0c;写代码、做数据分析、画图、写周报全包&#xff0c;感觉一个人就是一支队伍。这个说法确实有吸…

作者头像 李华
网站建设 2026/9/16 9:40:07

51单片机车载酒精检测系统设计与工程实践

简介&#xff1a;本资源是一套完整的基于STC系列51单片机的车载防酒驾智能控制系统毕业设计解决方案&#xff0c;面向电子类、自动化及嵌入式方向本科生与初学者&#xff0c;解决酒精浓度实时检测、声光报警与点火联锁控制等核心工程问题。压缩包共44个文件&#xff0c;约998KB…

作者头像 李华
网站建设 2026/9/16 9:39:52

ETL全面解析:从抽取转换加载到数仓实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华