当前位置: 首页 > wzjs >正文

wordpress 上传大文件合肥网站优化 新浪博客

wordpress 上传大文件,合肥网站优化 新浪博客,广东建设行业招聘 什么网站,拨号地址怎么做网站最近在调试Hostapd,尝试通过配置使能一个支持MLO的AP,不过不知道hostapd conf里面哪些选项开启后可以使能,所以对Hostapd做一个整体解析. 本篇分析介绍hostapd的netlink信息如何发送到内核、内核如何处理这些信息、处理后如何调用cfg80211,内核如何发送cfg80211信息…

最近在调试Hostapd,尝试通过配置使能一个支持MLO的AP,不过不知道hostapd conf里面哪些选项开启后可以使能,所以对Hostapd做一个整体解析.

本篇分析介绍hostapd的netlink信息如何发送到内核、内核如何处理这些信息、处理后如何调用cfg80211,内核如何发送cfg80211信息,驱动如何处理cfg80211信息,最后如何start_ap。

 Hostapd的nl命令收发函数:

int send_and_recv(struct nl80211_global *global,struct nl_sock *nl_handle, struct nl_msg *msg,int (*valid_handler)(struct nl_msg *, void *),void *valid_data,int (*ack_handler_custom)(struct nl_msg *, void *),void *ack_data,struct nl80211_err_info *err_info)
{struct nl_cb *cb, *s_nl_cb;struct nl80211_ack_err_args err;int opt;if (!msg)return -ENOMEM;err.err = -ENOMEM;s_nl_cb = nl_socket_get_cb(nl_handle);cb = nl_cb_clone(s_nl_cb);nl_cb_put(s_nl_cb);if (!cb)goto out;/* try to set NETLINK_EXT_ACK to 1, ignoring errors */opt = 1;setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK,NETLINK_EXT_ACK, &opt, sizeof(opt));/* try to set NETLINK_CAP_ACK to 1, ignoring errors */opt = 1;setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK,NETLINK_CAP_ACK, &opt, sizeof(opt));err.err = nl_send_auto_complete(nl_handle, msg);if (err.err < 0) {wpa_printf(MSG_INFO,"nl80211: nl_send_auto_complete() failed: %s",nl_geterror(err.err));/* Need to convert libnl error code to an errno value. For now,* just hardcode this to EBADF; the real error reason is shown* in that error print above. */err.err = -EBADF;goto out;}err.err = 1;err.orig_msg = msg;err.err_info = err_info;nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);if (ack_handler_custom) {struct nl80211_ack_ext_arg *ext_arg = ack_data;ext_arg->err = &err.err;nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM,ack_handler_custom, ack_data);} else {nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);}if (valid_handler)nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,valid_handler, valid_data);while (err.err > 0) {int res = nl_recvmsgs(nl_handle, cb);if (res == -NLE_DUMP_INTR) {/* Most likely one of the nl80211 dump routines hit a* case where internal results changed while the dump* was being sent. The most common known case for this* is scan results fetching while associated were every* received Beacon frame from the AP may end up* incrementing bss_generation. This* NL80211_CMD_GET_SCAN case tries again in the caller;* other cases (of which there are no known common ones)* will stop and return an error. */wpa_printf(MSG_DEBUG, "nl80211: %s; convert to -EAGAIN",nl_geterror(res));err.err = -EAGAIN;} else if (res < 0) {wpa_printf(MSG_INFO,"nl80211: %s->nl_recvmsgs failed: %d (%s)",__func__, res, nl_geterror(res));}}out:nl_cb_put(cb);/* Always clear the message as it can potentially contain keys */nl80211_nlmsg_clear(msg);nlmsg_free(msg);return err.err;
}

其中涉及的nl函数及解析

nl_socket_get_cb(nl_handle);
nl_cb_clone(s_nl_cb);
nl_cb_put(s_nl_cb);
nl_socket_get_fd(nl_handle), SOL_NETLINK,
nl_send_auto_complete(nl_handle, msg);
nl_geterror(err.err));
nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);
nl_recvmsgs(nl_handle, cb);
nl80211_nlmsg_clear(msg);
nlmsg_free(msg);
nla_put_u32

nl_socket_get_cb

用于获取nl_sock对应的回调函数

 linbl还可为每个nl_sock设置消息处理回调函数,当该socket上收到消息后,就会回调此函数进行处理。 回调函数及其重写函数都封装在结构体 struct nl_cb中

struct nl_cb{nl_recvmsg_msg_cb_t      cb_set[NL_CB_TYPE_MAX+1];void * cb_args[NL_CB_TYPE_MAX+1];nl_recvmsg_err_cb_t      cb_err;void *cb_err_arg;/** May be used to replace nl_recvmsgs with your own implementation in all internal calls to nl_recvmsgs. */int  (*cb_recvmsgs_ow)(struct nl_sock *,     struct nl_cb *);/** Overwrite internal calls to nl_recv, must return the number of octets read and allocate a buffer for the received data. */int   (*cb_recv_ow)(struct nl_sock *, struct sockaddr_nl *,   unsigned char **, struct ucred **);/** Overwrites internal calls to nl_send, must send the netlink message. */int    (*cb_send_ow)(struct nl_sock *,  struct nl_msg *);int   cb_refcnt;};

设置回调:void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb);

获取该nl_sock设置的回调函数信息:struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk);

nl_cb_clone

初始化时的函数,

 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind);//分配新的nl_cb,返回新nl_cb地址或者NULL

 struct nl_cb *nl_cb_clone(struct nl_cb *orig) ;   //根据给定nl_cb复制新的nl_cb

nl_cb_put

nl_socket_get_fd

获取nl_sock对应的文件描述符fd

 介于netlink采用BSD socket,因此每个socket对应一个文件描述符      

#include <netlink/socket.h>

int nl_socket_get_fd(const struct nl_sock *sk);

int nl_socket_set_nonblocking(const struct nl_sock *sk); //若socket用于接收notification,则最好设为非阻塞并定期查询

nl_send_auto_complete

一个nl message发送函数。

(1) nl_send_auto_complete()将 自动填充netlink message header,并根据nl_sock里面的选项或地址设置完成寻址,而后调用 nl_send()。

ps:所有nl_send_auto()内部调用都会使用nl_send()传输信息。如果nl_send()不能满足要求,可以调用nl_cb_overwrite_send()重写自己的send函数。

(2) nl_send()将netlink message插入到struct iovec结构体中,而后调用 nl_send_iovec();

ps: struct iovec结构体定义一个向量元素,  对于每一个传输的元素,指针成员iov_base指向一个缓冲区,这个缓冲区是存放的是readv所接收的数据或是writev将要发送的数据。成员iov_len在各种情况下分别确定了接收的最大长度以及实际写入的长度。

struct iovec{

     void *iov_base; /* Pointer to data. */

     size_t iov_len; /* Length of data. */

};

- int readv(int fd, const struct iovec *vector, int count);

- int writev(int fd, const struct iovec *vector, int count);

(3)nl_send_iovec()将利用nl_msg填充msghdr结构体,并检查寻址状态,而后调用nl_sendmsg()继续发送数据

(4)nl_sendmsg()调用sendmsg()下发数据

 通过netlink socket发送raw data:

int nl_sendto(struct nl_sock *sock, void *buf, size_t size);

nl_geterror

nl_cb_err

给nl_cb的nl_cb_kind(也就是某一个报错MSG) 增加错误回调函数

设置error message callback hook:

typedef int(* nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg);

int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,   nl_recvmsg_err_cb_t func, void * arg);  //设置错误callback

nl_cb_set

给nl_cb的nl_cb_kind(也就是某一个NL MSG) 增加回调函数

设置callback: 

typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);

int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,   nl_recvmsg_msg_cb_t func, void *arg); //设置给定kind_type的callback

nl_recvmsgs

就是一个接收NLMSG的函数

 libnl调用nl_recvmsgs_default()按照socket格式规定调用nl_recvmsgs() 接收数据。

nl_recvmsgs()在netlink message到来前保持阻塞,可以通过nl_cb_overwrite_recvmsgs()重写。nl_recvmsgs()调用recvmsgs()接收数据。

nl80211_nlmsg_clear

nlmsg_free

对应alloc的free

  /*释放*/

void nlmsg_free(struct nl_msg *msg);

nla_put_u32

int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value);

把value填充到nl msg里面

struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int len);

为netlink消息添加属性的接口是基于常规消息构造接口的。它假设消息头和最终协议头已经添加到消息中。函数nla_reserve()在消息的末尾添加一个属性头,并为len字节的有效负载保留空间。该函数返回一个指向消息内部属性有效负载部分的指针。在属性的末尾添加填充,以确保下一个属性正确对齐。 

int nla_put(struct nl_msg *msg, int attrtype, int attrlen, const void *data);

函数nla_put()以nla_reserve()为基础,但接受一个额外的指针数据,该指针数据指向包含属性有效负载的缓冲区。它将自动将缓冲区复制到消息中。

参考:

Netlink协议详解-CSDN博客

http://www.dtcms.com/wzjs/543094.html

相关文章:

  • 珠海 电商 网站建设福田公司门口
  • 许昌住房和城乡建设部网站中国建设银行官方网站下载
  • 自动化毕设题目网站开发宁波无痛人流医院哪家好
  • 艺术学校网站模板有没有什么做高数的网站
  • 网站排名大全wordpress优化 春哥
  • 浙江建设职业技术学院塘栖校区网站山西省智慧建筑信息平台
  • 太原流量大的网站找设计公司上哪个网站
  • 货运代理网站模板设计logo多少钱
  • html网站制作教程免费软件app下载大全正能量网站
  • 电商网站建设服务百度网盘登录入口官网
  • 网站开发价格表公司网页设计图
  • 免费制作广州网站做一个网站需要哪些步骤
  • 全国备案网站数量微网站建设图片
  • 怎么查找一个网站开发时间网站设计有什么前景
  • 潘多拉固件建设网站好的摄影网站推荐
  • 北京社交网站建设网站首页关键如何优化
  • opencms做网站 谁优质的seo网站排名优化软件
  • 做网站需要画原型图么泰州网站建设制作工作室
  • 网站运营 策划 推广 维护新手如何做网站维护
  • 甘肃网站建设推广手机建网站 优帮云
  • 厦门网页设计培训班深圳推广优化公司
  • 古蔺网站建设漳州做网站含博大选
  • 旅游类网站做百度竞价沈阳造价信息网官网
  • 网站开发用px好还是em好江苏华江建设集团网站
  • 如何 做镜像网站个人备案做分站的网站吗
  • 深入网站开发和运维 pdf做网站用到的技术
  • 我要在58上面做网站上海专业网站建设信息
  • 吉安工商注册官方网站外贸seo是什么意思啊
  • 企业门户定制网站建设公司东莞厚街做网站
  • 为什么要立刻做网站南京安居建设集团网站