保健励志美文体育育儿作文
投稿投诉
作文动态
热点娱乐
育儿情感
教程科技
体育养生
教案探索
美文旅游
财经日志
励志范文
论文时尚
保健游戏
护肤业界

Linuxnetlink详解

  熟悉Linuxwifi的同学都知道,wpasupplicant程序是基于netlink与wifi驱动进行通信的。(wpasupplicant是wifistation用户空间守护进程)
  本文学习下Linux的netlink,给出用户空间与内核空间基于netlink通信的示例。示例包括netlink和genericnetlink。用户空间程序包括基于原生LinuxAPI和基于libnlAPI。netlink基础
  netlink协议是一个基于socket的,用于内核与用户空间进程通信的一个协议。
  用户态创建netlinksocket的代码如下:intfdsocket(AFNETLINK,SOCKRAW,MYNETLINK)socket接口的原型为:intsocket(intdomain,inttype,intprotocol);这里用到了第三个入参protocol,即创建Netlinksocket时要指定协议号
  内核态创建netlinksocket的接口原型为:structsocknetlinkkernelcreate(structnetnet,intunit,structnetlinkkernelcfgcfg)这里的第二个参数unit为协议号,与用户空间的protocol相同
  Netlink消息有固定的格式,structnlmsghdrstructnlmsghdr{u32nlmsglen;Lengthofmessageincludingheaderu16nlmsgtype;Messagecontentu16nlmsgflags;Additionalflagsu32nlmsgseq;Sequencenumberu32nlmsgpid;SendingprocessportID};
  完整示例见github:https:github。comjiansoftnetlinkexamples
  下文为关键代码注释。原生LinuxAPI示例内核侧示例定义自己的netlink协议号defineMYNETLINK31接收回调,即内核侧收到用户发来的netlink消息回调staticvoidnetlinkrecvmsg(structskbuffskb){。。。nlh(structnlmsghdr)skbdata;取netlink消息头pidnlhnlmsgpid;pidofsendingprocessmsg(char)nlmsgdata(nlh);取netlink消息data部分msgsizestrlen(msg);printk(KERNINFOnetlinkkernel:Receivedfrompidd:s,pid,msg);。。。}定义netlinkkernelcfg,即声明接收回调structnetlinkkernelcfgcfg{。inputnetlinkrecvmsg,};创建内核测netlinksocketgnlsocknetlinkkernelcreate(initnet,MYNETLINK,cfg);if(!gnlsock){printk(KERNALERTnetlinkkernel:Errorcreatingsocket。);return10;}用户侧示例intmain(intargc,charargv〔〕){创建socketsockfdsocket(PFNETLINK,SOCKRAW,MYNETLINK);memset(srcaddr,0,sizeof(srcaddr));srcaddr。nlfamilyAFNETLINK;srcaddr。nlpidgetpid();selfpid绑定端口bind(sockfd,(structsockaddr)srcaddr,sizeof(srcaddr));设置目标地址为内核netlinkmemset(destaddr,0,sizeof(destaddr));destaddr。nlfamilyAFNETLINK;destaddr。nlpid0;ForLinuxKerneldestaddr。nlgroups0;unicast可以通过sendmsg或sendto两种接口向内核发送消息相应的有recvmsg和recvfrom两种接口接收来自内核的消息详见github,此处略}libnlAPI示例
  libnl对用户空间Linu原生的netlinkAPI进行了封装,使得用户空间程序更容易编写,尤其是对于genericnetlinkAPI。关于genericnetlinkAPI我们下一章节详细介绍。
  另外wpasupplicant与内核wifi驱动的通信就是用的libnlgenericnetlinkAPI。
  先介绍下libnl的主要接口,定义在头文件创建netlinksocket,libnl中用structnlsock表示一个socketincludenetlinksocket。hstructnlsocknlsocketalloc(void)voidnlsocketfree(structnlsocksk)回调配置structnlcbnlsocketgetcb(conststructnlsocksk);voidnlsocketsetcb(structnlsocksk,structnlcbcb);intnlsocketmodifycb(structnlsock,enumnlcbtype,enumnlcbkind,nlrecvmsgmsgcbt,void);发送intnlsendauto(structnlsocksk,structnlmsgmsg)intnlsend(structnlsocksk,structnlmsgmsg)intnlsendiovec(structnlsocksk,structnlmsgmsg,structioveciov,unsignediovlen)intnlsendmsg(structnlsocksk,structnlmsgmsg,structmsghdrhdr)nlsendmsg里调用Linux原生sendmsg接口intnlsendto(structnlsocksk,voidbuf,sizetsize)nlsendto调用Linux原生sendto接口intnlsendsimple(structnlsocksk,inttype,intflags,voidbuf,sizetsize)接收intnlrecvmsgsdefault(structnlsocksk)intnlrecvmsgs(structnlsocksk,structnlcbcb)如果socket是阻塞的,就阻塞式接收。recv到数据之后,通过cb进行处理libnl用户侧示例
  基于上一节的例子,内核测代码不变,用户侧使用libnl重写。includenetlinknetlink。hincludenetlinkmsg。hdefineMYNETLINK31defineMYNETLINKTYPESET0接收回调staticintmyinput(structnlmsgmsg,voidarg){structnlmsghdrnlhnlmsghdr(msg);chardatanlmsgdata(nlh);intdatalennlmsgdatalen(nlh);printf(inputcb:datalen:d,data:d,datalen,data);return0;}intmain(intargc,charargv〔〕){structnlsocksk;intret;创建并绑定socketsknlsocketalloc();retnlconnect(sk,MYNETLINK);修改接收回调函数,收到任何消息都会回调myinputnlsocketmodifycb(sk,NLCBMSGIN,NLCBCUSTOM,myinput,NULL);charmsg〔〕Hellolibnl!retnlsendsimple(sk,MYNETLINKTYPESET,0,msg,sizeof(msg));阻塞式等待接收。接收到内核发来的消息后,会进入接收回调myinputnlrecvmsgsdefault(sk);nlsocketfree(sk);}genericnetlink示例,基于libnl
  netlink通信协议在不修改内核源码的情况下,最大只支持定义32种协议。随着netlink的使用越来越多,32个协议号已不够用,所以引入了genericnetlink。genericnetlink其实是对netlink报文进行了又一次封装,genericnetlink使用的netlink协议号是NETLINKGENERIC16。
  genl的消息格式如下:012301234567890123456789012345678901Netlinkmessageheader(nlmsghdr)GenericNetlinkmessageheader(genlmsghdr)OptionaluserspecificmessageheaderOptionalGenericNetlinkmessagepayloadstructgenlmsghdr{u8cmd;u8version;u16reserved;};genl的messagepayload基于netlink的属性机制,即payload是由一个个nlattr组成NLAHDRLENNLAALIGN(payload)HeaderPadPayloadPad(structnlattr)ingingnlattrnlalenstructnlattr{u16nlalen;u16nlatype;};genl内核侧示例
  参考:https:wiki。linuxfoundation。orgnetworkinggenericnetlinkhowto
  注意:genlregisterops接口只在3。12及之前版本有;3。134。9版本用genlregisterfamilywithops;4。10版本及以后没有注册ops的接口,只有注册family的接口,ops要直接定义在family内。
  本文示例基于4。15内核。
  注册genericnetlinkfamily需要3步:定义操作定义family注册familyStep1:定义操作attributesenum{EXMPLAUNSPEC,EXMPLAMSG,EXMPLAMAX,};defineEXMPLAMAX(EXMPLAMAX1)attributepolicystaticstructnlapolicyexmplgenlpolicy〔EXMPLAMAX1〕{〔EXMPLAMSG〕{。typeNLANULSTRING},};handlerstaticintexmplecho(structskbuffskb,structgenlinfoinfo);commandsenum{EXMPLCUNSPEC,EXMPLCECHO,EXMPLCMAX,};defineEXMPLCMAX(EXMPLCMAX1)operationdefinitionstructgenlopsexmplgenlops〔EXMPLCMAX〕{{。cmdEXMPLCECHO,。doitexmplecho,。policyexmplgenlpolicy,}};defineFAMILYNAMEmygenlStep2:定义familyfamilydefinitionstaticstructgenlfamilymygenlfamily{。id0,。hdrsize0,表示没有用户自定义的额外header。nameFAMILYNAME,。version1,。opsexmplgenlops,。nopsARRAYSIZE(exmplgenlops),。maxattrEXMPLAMAX1,};handler的具体定义staticintexmplecho(structskbuffskb,structgenlinfoinfo){structnlattrna;structskbuffreplyskb;voidmsghead;intret;printk(sin。,func);内核已经解析好了每个attrnainfoattrs〔EXMPLAMSG〕;if(!na){printk(Error:attrEXMPLAMSGisnull);returnEINVAL;}printk(Recvmessage:s,nladata(na));将收到的消息发回去replyskbgenlmsgnew(NLMSGGOODSIZE,GFPKERNEL);填写genl消息头msgheadgenlmsgput(replyskb,infosndportid,infosndseq,mygenlfamily,0,EXMPLCECHO);向skb尾部填写attrnlaputstring(replyskb,EXMPLAMSG,nladata(na));Finalizethemessage:更新nlmsghdr中的nlmsglen字段genlmsgend(replyskb,msghead);Sendthemessagebackretgenlmsgreply(replyskb,info);if(ret!0){printk(genlmsgreplyreturnfail:d,ret);returnret;}return0;}Step3:注册famliyintret;retgenlregisterfamily(mygenlfamily);if(err!0){printk(genlregisterfamilyfail,ret:d,ret);returnret;}genl用户侧示例(基于libnl)defineMYFAMILYNAMEmygenl用户侧需要定义和内核侧相同的属性以及命令,所以通常把这一部分摘成一个独立的。h,内核和app共用这里没有摘成一个独立的。h,用户侧也重复定义一份attributesenum{EXMPLAUNSPEC,EXMPLAMSG,EXMPLAMAX,};defineEXMPLAMAX(EXMPLAMAX1)defineattributepolicystaticstructnlapolicyexmplgenlpolicy〔EXMPLAMAX1〕{〔EXMPLAMSG〕{。typeNLASTRING},};commandsenum{EXMPLCUNSPEC,EXMPLCECHO,EXMPLCMAX,};defineEXMPLCMAX(EXMPLCMAX1)接收回调定义intrecvcallback(structnlmsgrecvmsg,voidarg){structnlmsghdrnlhnlmsghdr(recvmsg);structnlattrtbmsg〔EXMPLAMAX1〕;if(nlhnlmsgtypeNLMSGERROR){printf(ReceivedNLMSGERRORmessage!);returnNLSTOP;}structgenlmsghdrgnlh(structgenlmsghdr)nlmsgdata(nlh);按照每attr解析内核发来的genl消息nlaparse(tbmsg,EXMPLAMAX,genlmsgattrdata(gnlh,0),genlmsgattrlen(gnlh,0),exmplgenlpolicy);判断是否包含属性EXMPLAMSGif(tbmsg〔EXMPLAMSG〕){parseitasstringcharpayloadmsgnlagetstring(tbmsg〔EXMPLAMSG〕);printf(Kernelreplied:s,payloadmsg);}else{printf(AttributeEXMPLAMSGismissing);}returnNLOK;}intmain(intargc,charargv〔〕){创建并连接genlsocketstructnlsocksknlsocketalloc();genlconnect(sk);根据FAMILYNAME获得对应的famlilyidintfamilyid;familyidgenlctrlresolve(sk,FAMILYNAME);if(familyid0){printf(genericnetlinkfamilyFAMILYNAMENOTREGISTERED);nlsocketfree(sk);exit(1);}else{printf(FamilyIDofgenericnetlinkfamilyFAMILYNAMEis:d,familyid);}设置接收回调nlsocketmodifycb(sk,NLCBMSGIN,NLCBCUSTOM,recvcallback,NULL);发送消息structnlmsgmsgnlmsgalloc();genlmsgput(msg,NLAUTOPORT,NLAUTOSEQ,familyid,0,NLMFREQUEST,EXMPLCECHO,1);NLAPUTSTRING(msg,EXMPLAMSG,genlmessagefromusertokernel);intresnlsendauto(sk,msg);nlmsgfree(msg);if(res0){printf(nlsendautofail,ret:d,res);}else{printf(nlsendautoOK,ret:d,res);}接收消息。接收到内核发来的消息后,触发回调recvcallbacknlrecvmsgsdefault(sk);nlaputfailure:referencedbyNLAPUTSTRINGnlsocketfree(sk);return0;}
  这里的示例是内核收到用户空间发来的genl消息后,根据发送端的structgenlinfoinfo,调用genlmsgreply(replyskb,info),将内核的genl消息单播给用户空间app。
  如果内核不知道用户空间的socket信息,内核如何将消息发送到用户空间呢?这时一般用组播netlink消息,即内核将消息组播出去。用户空间谁订阅了这个组播,谁就能收到内核发来的消息。关于组播netlink示例,后续有空再补一下
  完整示例见github:https:github。comjiansoftnetlinkexamples

我想有个星期八每一个学生天天都像在马拉松跑步一般,每一天都累的气喘吁吁,喘不过气来。在学校里面的时候,老师把功课安排的满满的,放学以后回到家里,父母买来的课外习题是永远也做不完的,哎!想在周……秋天的童话秋天时的风让我一起静静的守候着。农民伯伯说:ldquo;秋天是一个身穿金衣的窈窕淑女,吹浮着大地,让我们的丰收。rdquo;老师说:ldquo;秋天是让我们看那学生……遏制电商超长预售,需要监管超长待机冬天买的衣服快到夏天了还没发货,预售是在考验我对店家的忠诚度吗?谁说顾客是上帝?现在的卖家才是!近期,有关网红电商预售的话题引发了大量讨论,多名网友表示对随处可见的预售已逐渐失……有关写诚信小学作文诚信是中华民族的传统美德,也是每个人必备的品格,人可以失去金钱,但不可以失去诚信。下面是小编给大家介绍的写诚信小学作文,欢迎阅读。【篇一:诚信作文】无数事实告诉我们,交往……mybirthday英语作文带翻译50字一年一次生日,是我们最期待的时刻,你的生日是如何度过的呢?大家不妨写一篇关于mybirthday的50字英语作文描述一下吧。下面是品学网小编为大家整理的带翻译的mybirthd……这本书,讲了四岁到十五岁孩子的梦。四岁的梦是天真;五岁的梦是可爱;六岁的梦是奇怪;七岁的梦是美妙;八岁的梦是联想;九岁的梦是美丽;十岁的梦是向往;十一岁的梦是奔放;十二岁……石榴树品学网专稿未经允许不得转载有人喜欢高大的梧桐树,有人喜欢整齐的柳树,有人喜欢高贵的玉兰树,但是我却喜欢那平凡的石榴树。小时候,我最喜欢从小区里的石榴树上摘下一个小小的石榴……显卡哪个品牌性价比最高?这是七彩虹相对一些热门的型号,作个对比吧这是索泰的性比高的部分显卡,作个对比吧〕这是微星的部分显卡这是映众的部分显卡这些都是你所问得,不过像我经常组装的……JS解密入门案例python有道翻译JS解密前言嗨喽!大家好呀,这里是魔王课程亮点:系统分析网页结构动态数据抓包演示json数据解析JS解密环境介绍:python3。8pycharm需要安装nodejs插件Node……歌词集第三百七十五篇题目:青春旋律之感情热火一(一)生活虽然起起伏伏那些年老的岁月品味了痛苦白驹过隙花儿的青春也留不住情感的风为我倾诉你要抬头望一望人生路……家乡美我的家乡是四川。那里最漂亮的地方就是九寨沟了。早晨,太阳还没升起,九寨沟的五彩池隐隐约约的,像披上一件衣裳。这件衣服上面还带一些小小的、彩色的点点。原来是有些地方的水颜色……十一国庆作文800字精选爱我中华,实现梦想如果你问我最想对世界说什么,我一定会毫不犹豫地说:ldquo;我是中国人!。rdquo;没有一个不爱自己国家的国民。我当然也不例外,我爱养育了我12年的土地,她是举世闻名……
linux系统下怎么关闭tomcat?linux怎么关闭tomcat在Linux系统下,启动和关闭Tomcat使用命令操作。进入Tomcat下的bin目录cdjavatomcatbin停止Tomc……我成熟了作文范例成熟,是一个美丽的字眼。而成熟是每个人必经的历程。以下是我成熟了作文范例,以供赏析和参考借鉴!我成熟了作文范例1成熟,是一个美丽的字眼。对于处在青春期的我们。对成熟的渴望……在疫情中成长的初二作文范文在疫情中成长的初二作文范文1最近因为冠状病毒肺炎疫情的爆发,大家都在家闭关,就在昨天,爸爸终于按奈不住了,开始蠢蠢欲动了,时不时的朝窗户外面看了看。没多久,果然不岀我的预……共创文明作文600字文明象一阵清风吹进人们的心田,文明是一场雨,洒落在人们的心灵。光明是盏灯,照亮了前程的光明。我们是城市的小主人,应该和家人一起共创文明。近期,江门市正在积极地申报全国文明城市,……机构三星手机第一季在美国市占率28,创近8年新高韩联社5月4日消息,据市场调研机构对位研究(CounterpointResearch)于4日发布的报告,三星电子第一季度在美国智能手机市场的占有率为28,创近8年新高,大幅缩小……最纯洁善良的灵魂最纯洁善良的灵魂(本文纯属虚构)一天,一个盲人带着导盲犬一起过马路,走到半路,突然冲出来一辆大卡车,导盲犬见大卡车要撞到主人了,为了保护主人,它用力一跳把主人撞到了……小学生作文要人人献出一点爱星期六的一个下午,我的腿摔破了,妈妈带我去医院包扎。包扎好后,妈妈要顺便查体,让我去找在医院工作的二姑玩。我找了很长时间都没找到,这才知道二姑今天不上班。我坐在过道里玩时……快乐的春节作文1300字今天是春节,大年初一。新的一年到了,新的一年,新的开始,新的。一年,新的相貌今天五点几的时候,我被一些炮火惊醒,因为家家在迎接新年,放炮火是一种特俗。虽然我很理解这种习惯……以金黄的秋为题的小学生600字作文范文九月一到,就有了秋意,秋意在一个多雾的黎明溜来,到了炎热的下午便不见踪影。它踮起脚尖掠过树顶,染红几片叶子,然后乘着一簇飞掠过山谷离开。走进田野。哇!进入我眼前的是一片金……用好大数据,助力市场数字化升级随着我国数字经济不断发展壮大,对市场的影响程度越来越深、辐射范围越来越广。以抢数字先机,享数字价值为主题的2022中国国际大数据产业博览会(简称数博会)线上活动,将于5月26日……深耕数字贸易卓尔智联营收首破千亿大关日前,卓尔智联发布了2021年度经审核的业绩报告。年报显示,2021年卓尔智联营业收入达1045。52亿元,同比增长43。69;毛利8。98亿元。公告称,收入增加主要是由于供应……特斯拉给复工生产的员工每天工资以外多400块钱的补助有人认为特斯拉给那些复工生产的员工每天工资以外多给400块钱的补助,他们这样做其实是破坏了这个规矩,他们是在出幺蛾子,其实我不这么认为,我认为特斯拉并不是什么幺蛾子,他这种举动……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网