kernel32.dll走流量怎么办

扫一扫体验手机阅读
Linux内核中流量控制(15)
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。msn: 来源:
&
5.15. Qdisc的netlink控制
各网卡的Qdisc的用户层操作控制是通过rtnetlink接口实现用户空间和内核之间的通信的: rtnetlink_link, rtnetlink是专门针对路由控制的netlink接口.
/* include/linux/rtnetlink.h */
struct rtnetlink_link{// 就两个成员函数, 操作和输出&int (*doit)(struct sk_buff *, struct nlmsghdr*, void *attr);&int (*dumpit)(struct sk_buff *, struct netlink_callback *cb);};
// 全局数组, 具体在 net/core/rtnetlink.c中定义extern struct rtnetlink_link * rtnetlink_links[NPROTO];
其中的两个成员定义如下:
/* net/core/rtnetlink.c */
void __init rtnetlink_init(void){......&rtnetlink_links[PF_UNSPEC] = link_rtnetlink_&rtnetlink_links[PF_PACKET] = link_rtnetlink_......}
其中link_rtnetlink_table是一个数组, 定义为:
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] ={// 数组基本元素, 处理路由, 邻居ARP等相关信息, 这些不是本文重点, // 只是Qdisc的相关操作也是定义在这个数组中&[RTM_GETLINK&&&& - RTM_BASE] = { .doit&& = rtnl_getlink,&&&&& .dumpit = rtnl_dump_ifinfo& },&[RTM_SETLINK&&&& - RTM_BASE] = { .doit&& = rtnl_setlink&& },&[RTM_GETADDR&&&& - RTM_BASE] = { .dumpit = rtnl_dump_all& },&[RTM_GETROUTE&&& - RTM_BASE] = { .dumpit = rtnl_dump_all& },&[RTM_NEWNEIGH&&& - RTM_BASE] = { .doit&& = neigh_add&& },&[RTM_DELNEIGH&&& - RTM_BASE] = { .doit&& = neigh_delete&& },&[RTM_GETNEIGH&&& - RTM_BASE] = { .dumpit = neigh_dump_info& },#ifdef CONFIG_FIB_RULES&[RTM_NEWRULE&&&& - RTM_BASE] = { .doit&& = fib_nl_newrule& },&[RTM_DELRULE&&&& - RTM_BASE] = { .doit&& = fib_nl_delrule& },#endif&[RTM_GETRULE&&&& - RTM_BASE] = { .dumpit = rtnl_dump_all& },&[RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info& },&[RTM_SETNEIGHTBL - RTM_BASE] = { .doit&& = neightbl_set&& },};
&
5.15.1 初始化
初始化过程是定义对应tc的qdisc和class的操作命令的处理函数:
/* net/sched/sch_api.c */
static int __init pktsched_init(void){&struct rtnetlink_link *link_p;
// 流控调度的时钟初始化#ifdef CONFIG_NET_SCH_CLK_CPU&if (psched_calibrate_clock() & 0)&&return -1;#elif defined(CONFIG_NET_SCH_CLK_JIFFIES)&psched_tick_per_us = HZ&&PSCHED_JSCALE;&psched_us_per_tick = 1000000;#endif
// 使用PF_UNSPEC(0)号rtnetlink_links元素用来作为QDISC操作的接口&link_p = rtnetlink_links[PF_UNSPEC];
&/* Setup rtnetlink links. It is made here to avoid&&& exporting large number of public symbols.& */// link_p将指向link_rtnetlink_table数组&if (link_p) {// 对数组中流控相关元素进行赋值// Qdisc操作, 也就是对应tc qdisc add/modify等操作&&link_p[RTM_NEWQDISC-RTM_BASE].doit = tc_modify_// 删除/获取Qdisc操作 &&link_p[RTM_DELQDISC-RTM_BASE].doit = tc_get_&&link_p[RTM_GETQDISC-RTM_BASE].doit = tc_get_// 获取Qdisc信息, 也就是对应tc qdisc show&&link_p[RTM_GETQDISC-RTM_BASE].dumpit = tc_dump_// class操作, 也就是对应tc class add/delete/modify/get等操作, 在后续文章中分析&&link_p[RTM_NEWTCLASS-RTM_BASE].doit = tc_ctl_&&link_p[RTM_DELTCLASS-RTM_BASE].doit = tc_ctl_&&link_p[RTM_GETTCLASS-RTM_BASE].doit = tc_ctl_&&link_p[RTM_GETTCLASS-RTM_BASE].dumpit = tc_dump_&}// 登记FIFO流控处理, 这是网卡设备基本流控方法, 缺省必有的&register_qdisc(&pfifo_qdisc_ops);&register_qdisc(&bfifo_qdisc_ops);&proc_net_fops_create("psched", 0, &psched_fops);
&return 0;}
5.15.2 相关操作
以下函数中用到的Qdisc操作函数可见本系列第一篇, 第4节
5.15.2.1 创建/修改qdisc
/*&& Create/change qdisc.&*/
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg){&struct tcmsg *&struct rtattr **&struct net_device *&u32&struct Qdisc *q, *p;&
replay:&/* Reinit, just in case something touches this. */// tc消息指针&tcm = NLMSG_DATA(n);&tca =// class id&clid = tcm-&tcm_&q = p = NULL;
// 该tc命令针对的网卡&if ((dev = __dev_get_by_index(tcm-&tcm_ifindex)) == NULL)&&return -ENODEV;
&if (clid) {// 指定了类别ID的情况&&if (clid != TC_H_ROOT) {// 如果不是根节点&&&if (clid != TC_H_INGRESS) {// 非ingress节点时, 根据类别ID的高16位查找Qdisc节点&&&&if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)&&&&&return -ENOENT;// 获取p节点的叶子节点, 将调用p-&ops-&cl_ops-&leaf()函数&&&&q = qdisc_leaf(p, clid);&&&} else { /*ingress */// 使用设备ingress流控&&&&q = dev-&qdisc_&&&}&&} else {// 根节点情况下流控用的是设备的qdisc_sleeping&&&q = dev-&qdisc_&&}
&&/* It may be default qdisc, ignore it */// 如果找到的Qdisc的句柄为0, 放弃q &&if (q && q-&handle == 0)&&&q = NULL;
&&if (!q || !tcm-&tcm_handle || q-&handle != tcm-&tcm_handle) {// 没找到Qdisc节点, 或没在tc消息中指定句柄值, 或者找到的Qdisc句柄和tc消息中// 的句柄不同&&&if (tcm-&tcm_handle) {// TC指定了句柄// 如果Qdisc存在但不是更新命令, 返回对象存在错误&&&&if (q && !(n-&nlmsg_flags&NLM_F_REPLACE))&&&&&return -EEXIST;// TC句柄低16位不能位0&&&&if (TC_H_MIN(tcm-&tcm_handle))&&&&&return -EINVAL;// 根据TC句柄查找该设备上的Qdisc, 找不到的话跳转到创建新节点操作&&&&if ((q = qdisc_lookup(dev, tcm-&tcm_handle)) == NULL)&&&&&goto create_n_// 找到但设置了NLM_F_EXCL排斥标志, 返回对象存在错误&&&&if (n-&nlmsg_flags&NLM_F_EXCL)&&&&&return -EEXIST;// 比较TC命令中的算法名称和Qdisc名称算法相同&&&&if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q-&ops-&id))&&&&&return -EINVAL;// 检查算法出现回环情况, p是用clid找到的Qdisc&&&&if (q == p ||&&&&&&& (p && check_loop(q, p, 0)))&&&&&return -ELOOP;// 新找到的Qdisc有效, 转到嫁接操作&&&&atomic_inc(&q-&refcnt);&&&&&&&} else {// 没指定TC句柄, 如果没找到Qdisc, 跳转到创建新节点&&&&if (q == NULL)&&&&&goto create_n_
&&&&/* This magic test requires explanation.&&&& *&&&& *&& We know, that some child q is already&&&& *&& attached to this parent and have choice:&&&& *&& either to change it or to create/graft new one.&&&& *&&&& *&& 1. We are allowed to create/graft only&&&& *&& if CREATE and REPLACE flags are set.&&&& *&&&& *&& 2. If EXCL is set, requestor wanted to say,&&&& *&& that qdisc tcm_handle is not expected&&&& *&& to exist, so that we choose create/graft too.&&&& *&&&& *&& 3. The last case is when no flags are set.&&&& *&& Alas, it is sort of hole in API, we&&&& *&& cannot decide what to do unambiguously.&&&& *&& For now we select create/graft, if&&&& *&& user gave KIND, which does not match existing.&&&& */// 检查各种标志是否冲突, Qdisc名称是否正确&&&&if ((n-&nlmsg_flags&NLM_F_CREATE) &&&&&&&&& (n-&nlmsg_flags&NLM_F_REPLACE) &&&&&&&&& ((n-&nlmsg_flags&NLM_F_EXCL) ||&&&&&&&& (tca[TCA_KIND-1] &&&&&&&&&&& rtattr_strcmp(tca[TCA_KIND-1], q-&ops-&id))))&&&&&goto create_n_&&&}&&}&} else {// 如果没指定类别ID, 从tc消息的句柄来查找Qdisc&&if (!tcm-&tcm_handle)&&&return -EINVAL;&&q = qdisc_lookup(dev, tcm-&tcm_handle);&}// 到这里是属于Qdisc修改操作&/* Change qdisc parameters */// 没找到Qdisc节点, 返回错误&if (q == NULL)&&return -ENOENT;// 找到Qdisc节点, 但设置了NLM_F_EXCL(排斥)标志, 返回对象存在错误&if (n-&nlmsg_flags&NLM_F_EXCL)&&return -EEXIST;// 检查找到的Qdisc节点的名称和tc中指定的是否匹配&if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q-&ops-&id))&&return -EINVAL;// 修改Qdisc参数&err = qdisc_change(q, tca);&if (err == 0)&&qdisc_notify(skb, n, clid, NULL, q);&
create_n_graft:// 创建新Qdisc节点// 如果TC命令中没有创建标志, 返回错误&if (!(n-&nlmsg_flags&NLM_F_CREATE))&&return -ENOENT;// 创建新Qdisc节点&if (clid == TC_H_INGRESS)&&q = qdisc_create(dev, tcm-&tcm_parent, tca, &err);&&&&&&& else&&q = qdisc_create(dev, tcm-&tcm_handle, tca, &err);&if (q == NULL) {// 创建失败, 如果不是EAGAIN(重来一次), 返回失败&&if (err == -EAGAIN)&&&&&&}
graft:// 嫁接操作&if (1) {&&struct Qdisc *old_q = NULL;// 进行嫁接操作, 返回老节点&&err = qdisc_graft(dev, p, clid, q, &old_q);&&if (err) {// 失败, 释放新建立的Qdisc&&&if (q) {&&&&spin_lock_bh(&dev-&queue_lock);&&&&qdisc_destroy(q);&&&&spin_unlock_bh(&dev-&queue_lock);&&&}&&&&&}// Qdisc通告&&qdisc_notify(skb, n, clid, old_q, q);&&if (old_q) {// 如果存在老Qdisc节点, 释放之&&&spin_lock_bh(&dev-&queue_lock);&&&qdisc_destroy(old_q);&&&spin_unlock_bh(&dev-&queue_lock);&&}&}&return 0;}
5.15.2.2 获取/删除qdisc
/*&* Delete/get qdisc.&*/
static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg){&struct tcmsg *tcm = NLMSG_DATA(n);&struct rtattr **tca =&struct net_device *// class id&u32 clid = tcm-&tcm_&struct Qdisc *q = NULL;&struct Qdisc *p = NULL;&// 根据TC参数中的网卡索引号查找网卡设备&if ((dev = __dev_get_by_index(tcm-&tcm_ifindex)) == NULL)&&return -ENODEV;
// 根据类别ID或TC句柄查找Qdisc, 和上面函数类似&if (clid) {&&if (clid != TC_H_ROOT) {&&&if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {&&&&if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)&&&&&return -ENOENT;&&&&q = qdisc_leaf(p, clid);&&&} else { /* ingress */&&&&q = dev-&qdisc_&&&&&&&&&&&&&&&&&&&&&&& }&&} else {&&&q = dev-&qdisc_&&}&&if (!q)&&&return -ENOENT;
&&if (tcm-&tcm_handle && q-&handle != tcm-&tcm_handle)&&&return -EINVAL;&} else {&&if ((q = qdisc_lookup(dev, tcm-&tcm_handle)) == NULL)&&&return -ENOENT;&}// 检查找到的Qdisc名称和TC命令中指定的是否一致&if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q-&ops-&id))&&return -EINVAL;
// 删除Qdisc操作&if (n-&nlmsg_type == RTM_DELQDISC) {// 必须指定类别ID&&if (!clid)&&&return -EINVAL;// 如果找到的Qdisc句柄为0, 返回错误&&if (q-&handle == 0)&&&return -ENOENT;// 进行Qdisc嫁接操作, 新节点是NULL, 即将叶子节点替换为NULL, 即删除了原叶子节点// 原叶子节点返回到q&&if ((err = qdisc_graft(dev, p, clid, NULL, &q)) != 0)&&&&&if (q) {// 释放原叶子节点&&&qdisc_notify(skb, n, clid, q, NULL);&&&spin_lock_bh(&dev-&queue_lock);&&&qdisc_destroy(q);&&&spin_unlock_bh(&dev-&queue_lock);&&}&} else {// 非删除操作, 通告一下, q作为获得的Qdisc参数返回&&qdisc_notify(skb, n, clid, NULL, q);&}&return 0;}
// 发送Qdisc通知信息, new是处理后新Qdisc节点信息, old是处理前老节点信息static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n,&&&u32 clid, struct Qdisc *old, struct Qdisc *new){&struct sk_buff *&u32 pid = oskb ? NETLINK_CB(oskb).pid : 0;// 分配netlink数据包&skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);&if (!skb)&&return -ENOBUFS;
&if (old && old-&handle) {// 填充老Qdisc的信息&&if (tc_fill_qdisc(skb, old, clid, pid, n-&nlmsg_seq, 0, RTM_DELQDISC) & 0)&&&goto err_&}&if (new) {// 填充新Qdisc的信息&&if (tc_fill_qdisc(skb, new, clid, pid, n-&nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) & 0)&&&goto err_&}// 发送数据包&if (skb-&len)&&return rtnetlink_send(skb, pid, RTNLGRP_TC, n-&nlmsg_flags&NLM_F_ECHO);
err_out:// 错误处理, 释放数据包&kfree_skb(skb);&return -EINVAL;}
5.15.2.3 输出网卡qdisc参数
static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb){&int idx, q_&int s_idx, s_q_&struct net_device *&struct Qdisc *q;// 起始网卡索引&s_idx = cb-&args[0];// 起始Qdisc索引&s_q_idx = q_idx = cb-&args[1];&read_lock(&dev_base_lock);// 遍历所有网卡&for (dev=dev_base, idx=0; dev = dev-&next, idx++) {// 索引值小于所提供的起始索引值, 跳过// 这个索引和网卡的索引号应该没啥关系&&if (idx & s_idx)&&&// 索引值大于所提供的起始索引值, 将起始Qdisc索引清零&&if (idx & s_idx)&&&s_q_idx = 0;&&read_lock(&qdisc_tree_lock);// q_idx清零, 这样前面也用不着在初始化时赋值&&q_idx = 0;// 遍历该网卡设备的所有Qdisc&&list_for_each_entry(q, &dev-&qdisc_list, list) {// 当前Qdisc索引小于起始Qdisc索引, 跳过// 所以当idx & s_idx时, s_q_idx = 0, 只处理第一个Qdisc// 当idx == s_idx时, 处理从s_q_idx开始的所有Qdisc&&&if (q_idx & s_q_idx) {&&&&q_idx++;&&&&&&&}// 填充Qdisc信息到数据包&&&if (tc_fill_qdisc(skb, q, q-&parent, NETLINK_CB(cb-&skb).pid,&&&&&& cb-&nlh-&nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) &= 0) {&&&&read_unlock(&qdisc_tree_lock);&&&&&&&}&&&q_idx++;&&}&&read_unlock(&qdisc_tree_lock);&}
done:&read_unlock(&dev_base_lock);// 返回处理的所有网卡数和Qdisc数&cb-&args[0] =&cb-&args[1] = q_
&return skb-&}
// 填充Qdisc信息到skb数据包static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,&&& u32 pid, u32 seq, u16 flags, int event){&struct tcmsg *&struct nlmsghdr& *&unsigned char& *b = skb-&&struct gnet_// skb中的netlink数据头位置&nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);// TC信息数据头位置&tcm = NLMSG_DATA(nlh);// 填充TC信息参数&tcm-&tcm_family = AF_UNSPEC;&tcm-&tcm__pad1 = 0;&tcm-&tcm__pad2 = 0;&tcm-&tcm_ifindex = q-&dev-&&tcm-&tcm_parent =&tcm-&tcm_handle = q-&&tcm-&tcm_info = atomic_read(&q-&refcnt);&RTA_PUT(skb, TCA_KIND, IFNAMSIZ, q-&ops-&id);// Qdisc的输出函数&if (q-&ops-&dump && q-&ops-&dump(q, skb) & 0)&&goto rtattr_&q-&qstats.qlen = q-&q.// 准备开始拷贝统计信息&if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,&&&TCA_XSTATS, q-&stats_lock, &d) & 0)&&goto rtattr_// 输出统计信息&if (q-&ops-&dump_stats && q-&ops-&dump_stats(q, &d) & 0)&&goto rtattr_
// 拷贝基本统计信息, 流控速率统计信息, 队列统计信息&if (gnet_stats_copy_basic(&d, &q-&bstats) & 0 ||#ifdef CONFIG_NET_ESTIMATOR&&&& gnet_stats_copy_rate_est(&d, &q-&rate_est) & 0 ||#endif&&&& gnet_stats_copy_queue(&d, &q-&qstats) & 0)&&goto rtattr_// 结束封口操作&&if (gnet_stats_finish_copy(&d) & 0)&&goto rtattr_&&nlh-&nlmsg_len = skb-&tail -&return skb-&
nlmsg_failure:rtattr_failure:&skb_trim(skb, b - skb-&data);&return -1;}
&
5.16 Qdisc小结
&
关于流控(Qdisc)的分析就此告一段落, 后面将继续分析分类(class), 过滤(filter)和动作(action)的处理过程.
...... 待续 ......
<span type="1" blog_id="158039" userid='
223篇文章,30W+人气,0粉丝
高并发架构之路
¥51.00124人订阅
新西兰资深网工运维之道
¥51.00416人订阅
前百度高级工程师的架构高可用实战
¥51.00232人订阅
<span type="1" blog_id="158039" userid='Linux 内核被爆流量劫持威胁,八成安卓设备受影响
目前,据外媒ZDNET 的报道,目前市面上大约8成Android 设备面临一个Linux 内核缺陷的安全威胁。
消息援引安全公司Lookout 在週一发表的文章表示,这一缺陷将影响所有运行Android 4.4及以上版本的Android 设备。
Windows和Mac 电脑并不受本次影响。7月11日发佈的Linux 补丁软体已经修复本次漏洞,9月份推送Android 更新包将有可能修正这一缺陷。
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
电影、电视剧都没有问题!
从业、媒体(男)女神,不能少它
今日搜狐热点kernel走流量,还挺多,谢谢大侠解释并提供解决方法,谢谢【华为mate8吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:77,074贴子:
kernel走流量,还挺多,谢谢大侠解释并提供解决方法,谢谢收藏
苏宁易购华为手机,正品行货+百城半日达,全国联保,服务一站式,全场为你而省!苏宁易购华为手机,支持货到付款,让您省钱省心!
流量是被系统吃掉的,占每月总流量三分之一左右。禁用数据选项是灰色的,根本限制不了。坑爹
同样的问题,不知道是什么鬼!
登录百度帐号android kernel ap会不会跑流量_百度知道
android kernel ap会不会跑流量
我有更好的答案
android kernel和标准linux kernel的区别 总的区别可以归纳如下: ARCH -- 这是Android修改了arch/arm下面的一些文件: arch/arm: Chg: arch/arm/kernel/entry-armv.S Chg: arch/arm/kernel/module.c Chg: arch/arm/kernel/process.c Chg: arch/...
采纳率:90%
来自团队:
为您推荐:
其他类似问题
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。Linux内核现流量劫持缺陷 8成Android设备中枪
Android安全缺陷
北京时间8月16日消息,据科技网站ZDNET报道,多达8成Android设备会因最近披露的一个Linux内核缺陷面临安全风险。
安全公司Lookout当地时间周一发表博文称,该缺陷影响所有运行4.4 KitKat及之后Android版本的智能手机和平板电脑。Windows和Mac计算机不会受到影响。
该缺陷相当复杂,要利用它发动攻击很困难。利用该缺陷,黑客可以在未经加密的互联网流量中注入恶意代码。但是,要劫持流量,黑客需要知道源和目的IP地址,这无疑增加了攻击难度。
如果连接经过加密,即使不能读取流量,黑客也能切断连接。
7月11日发布的Linux补丁软件已经修正了该缺陷,但最新发布的Android更新包并未修正该缺陷。不过,该缺陷可能会在9月份的Android更新包中得到修正。
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
今日搜狐热点}

我要回帖

更多关于 kernelbase.dll故障 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信