
Linux 内核
文章平均质量分 71
yyyyyyyuande
这个作者很懒,什么都没留下…
展开
-
使用netfilter框架处理ARP报文
内核开发交流群 745510310 欢迎加入学习利用netfilter的框架实现对arp报文的处理,这里只是打印arp报文信息,更多的处理可以在此基础上实现。arp 首部封装格式:内核版本 :,不同版本内核头文件可能不一样带来编译出错问题,可以参考这篇博客https://blog.youkuaiyun.com/fuyuande/article/details/79429441 更新一下内核。源码如下:/* ...原创 2018-03-31 19:19:51 · 2866 阅读 · 0 评论 -
linux 内核抓包功能实现基础(一)设计思路
linux平台下面已经有了抓包工具tcpdump, 非常经典,使用起来也非常方便。但是因为某些系统架构上或者其它方面的原因,有时候tcpdump并不能满足产品实际需要,公司的产品是电信运营商相关的软硬件集成产品,平常在使用的时候经常需要抓包来分析、定位问题,之前的抓包功能是基于tcpdump的基础上的,但是因为系统架构方面的原因,抓包功能始终无法抓到所有进出报文,每次只能抓到特定一部分报文,此外因...原创 2018-06-24 20:51:38 · 2989 阅读 · 1 评论 -
linux 内核抓包功能实现基础(二) netfilter处理
上篇博客主要介绍了内核抓包设计思路与效果,并没有给出详细的设计实现,看起来就像一个花架子,华而不实。本篇博客就结合具体的代码介绍一下抓包的实现过程。先大致概括一下代码的思路,抓包模块启动后,就去netfilter上面注册两个钩子函数,分别放在PRE_ROUTING链和POSTROUTING链上,抓取进来的报文和出去的报文。当报文进入到netfilter层面处理时,钩子函数对报文做一下简单的匹配判断...原创 2018-07-01 12:17:07 · 3866 阅读 · 8 评论 -
Linux 内核抓包功能实现基础(三) 抓包服务器的实现
上回博客我们讲到了内核抓包内核端的实现,通过上篇博客的例子我们就能够开始抓包了,整个抓包的拓扑图如下:当开始抓包后,抓包机器将抓到的报文送到服务器上,假设服务器地址是192.168.199.123:8099,如果在抓包服务器上打开wireshark可以看到送过来的报文,如下图这样子:可以看到抓包服务器上收到了报文,但是这样子的报文我们是无法直接拿来分析的,因为实际的报文是封装起来的,需要把数据提取...原创 2018-07-08 01:02:27 · 2610 阅读 · 1 评论 -
Linux 内核 网络地址转换函数 in_aton、 in4_pton 和 in6_pton 定义与使用
Linux内核网络编程经常用到地址转换函数,如字符串转换成网络字节序。这三个函数就提供了相应的功能。先看一下这三个函数的声明:#ifndef _LINUX_INET_H#define _LINUX_INET_H#include <linux/types.h>/* * These mimic similar macros defined in user-space ...原创 2018-07-18 20:19:56 · 6732 阅读 · 0 评论 -
Linux 内核抓包功能实现基础(四) 手动查找邻居缓存填充MAC地址
之前写了三篇关于内核抓包功能的实现,包括抓包原理、实现以及抓包服务器的实现。基本的功能都已经有了,但是还有些小问题有待解决。今天有空就解决一下。 开发版本基于内核3.4.39。 先介绍一下问题背景,抓包框架是基于netfilter的,通过在Pre-Routing和Post-Routing链上分别挂一个钩子函数来对报文处理。抓包基...原创 2018-07-28 15:27:24 · 1479 阅读 · 1 评论 -
Linux 内核定时器使用 一 低精度定时器
内核定时器是一个数据结构,它告诉内核在用户定义的时间点使用用户定义的参数来执行一个用户定义的函数。其实现位于<linux/timer.h>中。内核提供了一组用来声明、注册和删除内核定时器的函数,相关接口如下:struct timer_list { /* * All fields that change during normal runtime grouped to...原创 2018-08-20 22:32:23 · 873 阅读 · 0 评论 -
Linux 内核定时器使用 二 高精度定时器 hrtimer 的用例
之前介绍了timer_list内核定时器,它的精度在毫秒级别,再高一点它就无能为力了,所幸内核提供了高精度定时器 hrtimer。源文件在linux/kernel/hrtimer.c中。接口简单。下面介绍一下相关接口1. 定时器定义与绑定超时回调函数static struct hrtimer timer;/* 设置回调函数 */timer.function = hrtimer_h...原创 2018-08-29 22:33:26 · 9018 阅读 · 2 评论 -
Linux内核模块开发 Slab高速缓存接口与用例
在内核模块开发或者驱动开发中经常会使用到内存分配,常见的方式是调用 kmalloc 接口分配内存。static __always_inline void *kmalloc(size_t size, gfp_t flags);kmalloc接口使用简单,并且不会对所获取的空间清零,分配的空间仍然保持着原有的数据。但是根据<linux设备驱动程序>一书中的说法,kmalloc能够...原创 2018-09-08 21:33:44 · 962 阅读 · 0 评论 -
Linux 内核抓包功能实现基础(五) 常见问题解析
之前在部门产品上开发了内核抓包模块,基于openwrt平台,通过netfilter框架实现相关功能。核心功能就是在netfilter 的PRE_ROUTING 和 POST_ROUTING链上增加两个钩子函数,实现对报文的匹配,复制和发送功能。功能已经上线三个月,根据反馈结果来看,基本的抓包功能正常,不过也有几个问题需要解决一下,之前陆陆续续写了四篇博客介绍相关功能的开发,在本篇就把产品实际应用中...原创 2018-09-15 22:31:37 · 720 阅读 · 1 评论 -
Unable to handle kernel paging request at virtual address 问题定位
调试模块的时候出现这个问题,看panic 系统调用堆栈,cpu执行到连接跟踪模块那里,难道是内核模块有问题?不可能,想起之前内核奔溃的教训,问题肯定是出在自己的模块上。又重新详细看日志,看到最后一行有个last unloaded ddos,这是我修改的模块,问题应该还是自己模块问题,反复定位,结果发现是卸载模块的时候没有释放定时器,导致定时器超时引起内核奔溃,以前也遇到过类似调试问题,在模块中启动...原创 2018-12-11 19:16:22 · 6831 阅读 · 0 评论 -
ip6tables 无法基于端口过滤IPv6 分片报文问题解决
问题现象:使用ip6tables 添加端口过滤规则,只允许指定端口IPv6报文进来,测试结果显示如果是分片报文,只有第一个分片报文能够收到,后续分片会被丢弃。内核版本:3.4.39问题原因: 因为同样的规则如果是IPv4分片报文则能够生效,通过分析内核源码,发现问题出在netfilter IPv6连接跟踪模块。netfilter IPv4 连接跟踪模块会对分片报文进行重组处理使得系统网...原创 2018-12-24 19:21:17 · 1655 阅读 · 0 评论 -
Linux SKB结构体中各个长度字段的含义(len, data_len, headlen, pagelen)
结构体sk_buff是Linux内核网络子系统的一个基本结构体,关于它的长度有很多定义和操作,非常容易弄混,这里给出一个简单的说明。下面这幅图是《深入理解Linux网络技术内幕》里面的图,一个skb用于存储一个报文,如果一个报文特别大的话,线性存储区放不下就需要多个skb来存储,这就是下面frag_list的作用,保存连续的skb,但是如果内核支持分散聚集技术的话,并且报文长度刚好又不大于mt...原创 2018-12-24 19:58:07 · 7625 阅读 · 3 评论 -
skb_shinfo(skb)->dataref 含义
dataref表示对共享数据区的引用数目。通常克隆报文的时候,所有报文共享一个数据区。如下图所示,dataref = 2,表示有两个引用指向该区域。原创 2018-12-28 09:07:28 · 2010 阅读 · 0 评论 -
tcp/ip 协议栈Linux源码分析一 IPv4分片报文重组分析一
内核版本:3.4.39之前因工作原因接触到了IPv4 报文重组这个话题,一直以来对这个重组流程不是很清楚,所以很多功能的实现都避开了分片报文的处理,一方面是因为重组比较复杂,另一方面是经验不多无从下手,最近几周抽空详细看了下内核源码关于IPv4重组的流程,这里简要说明下,有描述不对的地方还请指出。先简单描述下ipv4重组的流程:内核在传输层(L3层)收到分片报文后在传递给L4(TCP/UD...原创 2019-01-19 17:32:50 · 2008 阅读 · 0 评论 -
tcp/ip 协议栈Linux源码分析二 IPv4分片报文重组分析二
继续接着上篇讲,之前我们说过,收到分片报文后首先会检查分片报文所占内存是否过大,如果超过阈值的话就要调用ip_evictor函数去释放一些旧的分片队列,关于如何释放分片队列资源上一篇已经总结完成,接下来来看下进一步的处理,即如何查找分片队列的,先看下代码: /* Lookup (or create) queue header */ /* 这里根据分片五元组(源地址、目的地址、IP ID,p...原创 2019-01-23 23:31:59 · 1005 阅读 · 0 评论 -
tcp/ip 协议栈Linux源码分析三 IPv4分片报文重组分析三
继续上篇,上次讲到了分片队列的查找操作,剩下的就是分片队列插入和重组两个部分了,这个也是分片重组的关键部分。将收到的分片插入到分片队列是由函数inet_frag_queue()函数完成,这个函数比较长,多看几遍就好了 :-)/* Add new segment to existing queue. *//* 添加一个新的片段到分片队列里面 */static int ip_frag_q...原创 2019-01-27 16:16:20 · 1311 阅读 · 1 评论 -
Linux内核和应用层程序通信get/setsockopt示例
最近开发一个realtek网卡配置程序,基于realtek提供的一套配置程序代码开发,分析代码的时候发现用户层和驱动之间传递消息是使用的是setsockopt、getsockopt,这个对我来说比较新鲜,以前见到的大都是netlink、proc等等,使用这种方式特别简单,应用层这边只需要创建套接字,而内核层只需要注册一个struct nf_sockopt_ops 结构体就可以了,这种方式以后可能会...原创 2019-03-03 17:32:21 · 1398 阅读 · 0 评论 -
tcp/ip 协议栈Linux源码分析四 IPv4分片 ip_fragment函数分析
内核版本:3.4.39很多项目涉及到IP分片的时候都是绕过去了,感觉分片挺难的。但是老这么做也不行啊,抽空分析了内核的分片处理函数ip_fragment,也不是特别复杂,感觉挺简单的,看来事情只有实际去做才知道。int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)){ struct iphdr *ip...原创 2019-04-11 17:18:25 · 1697 阅读 · 0 评论 -
tcp/ip 协议栈Linux源码分析五 IPv6分片报文重组分析一
做防火墙模块的时候遇到过IPv6分片报文处理的问题是,当时的问题是netfilter无法基于传输层的端口拦截IPv6分片报文,但是IPv4的分片报文可以。分析了内核源码得知是因为netfilter的连接跟踪模块重组了IPv4分片报文,但是对于IPv6的分片报文没有重归组导致,自3.10.x版本后的内核修改了这一块,在PRE_ROUTING前netfilter重组了IPv6分片报文。之前写过几篇...原创 2019-05-15 08:52:00 · 3023 阅读 · 1 评论 -
tcp/ip 协议栈Linux内核源码分析六 路由子系统分析一路由缓存
内核版本:3.4.39收到报文或者发送报文的时候都需要查找路由表,频繁的路由表查找操作时需要耗费一部分CPU的,Linux提供了路由缓存来减少路由表的查询,路由缓存由hash表组织而成,路由缓存的初始化放在路由初始化函数ip_rt_init中,当路由缓存没有命中的时候会去查找路由表,查找成功则会添加到路由缓存里。有两个地方需要查找缓存,一个是ip_rcv()接收报文的时候,另一个是发送报文...原创 2019-05-27 18:45:02 · 1744 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析七 路由子系统分析二 策略路由
内核版本:3.4.39策略路由就是根据配置策略查找路由表,早期的Linux版本是不支持策略路由的,默认的查找策略就是先查找local路由表,找不到再继续查找main表,当支持策略路由功能时,内核最多可以配置255个路由表,这时候根据先匹配策略,匹配后再去查找该策略指定的路由表,内核最多支持32768张策略表,初始化的时候创建了local表,main表和default表。策略表按照优先级从高到低...原创 2019-05-27 22:00:10 · 1696 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析八 路由子系统分析三 路由表
内核版本:3.4.39Linux路由子系统代码量虽说不是很多,但是难度还是有的,最近在分析路由子系统这一块,对它的框架有了基本的了解,如果要想掌握的话估计还得再花点时间阅读代码,先把框架记录下来。路由子系统可以划分为三个子部分,路由缓存,路由策略和路由表,前两者已经总结过了,今天再总结下路由表。路由表和其它模块类似,都有初始化、添加、删除、查询等操作,要说区别吧,可能是数据结构组织不一样,不同...原创 2019-05-28 09:05:39 · 2713 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析九 IPv6分片ip6_fragment 分析
内核版本:3.4.39IPv6的分片流程和IPv4基本一致,这一点内核源码作者也说了。流程比较简单,分片的时候判断是否满足快速分片,满足的话直接一个接一个加上分片扩展选项发送出去,不满足的话就只能走慢速分片通道了,这时候需要重新分配每一个skb,然后从原始SKB报文那里复制数据发送出去。int ip6_fragment(struct sk_buff *skb, int (*output)...原创 2019-05-28 10:29:20 · 1658 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析十 邻居子系统分析一 概述通用邻居框架
内核版本:3.4.39为什么需要邻居子系统呢?因为在网络上发送报文的时候除了需要知道目的IP地址还需要知道邻居的L2 mac地址,为什么是邻居的L2地址而不是目的地的L2地址呢,这是因为目的地网络可能不在同一个网段甚至不在同一个地区,因此需要借助其它离目的地近的网点帮我们传输下,这里离目的地近的网点通常就是网关,也就是邻居。如果目的地和我们在同一个LAN上的话,它们就是邻居。邻居子系统的核心功...原创 2019-05-30 13:06:05 · 1158 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析11 邻居子系统分析二 arp协议的实现处理
内核版本:3.4.39内核邻居子系统定义了一个基本的框架,使得不同的邻居协议可以共用一套代码。比起其它的内核模块,邻居子系统框架代码还是比较简单易懂的。邻居子系统位于网络层和流量控制子系统中间,它提供给L3向下发送的接口。看下网络层发送函数的部分代码:static inline int ip_finish_output2(struct sk_buff *skb){ /* ...原创 2019-05-30 14:40:52 · 820 阅读 · 0 评论 -
添加一个hello wrold系统调用到内核
分析socket()函数的时候看到了系统调用,以往也见过好多次系统调用,不是特别明白如何从用户空间跳到内核空间,google了一篇参考文章动添加一个系统调用试试。在做实验之前先了解下什么是系统调用以及系统调用运行的原理,什么是系统调用?Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。用户可以通过系统调用命令在自己的应用程序中调用它们。从某种角度来看,系统调用和普通...原创 2019-05-30 17:53:19 · 562 阅读 · 1 评论 -
tcp/ip 协议栈Linux内核源码分析12 udp套接字发送流程一
内核版本:3.4.39因为过往的开发工作中既包括内核网络层模块的开发,又包括应用层程序的开发,所以对于网络数据的通信有那么一些了解。但是对于网络通信过程中,内核和应用层之间接口是如何运作的不是很清楚,很多问题无从回答,比如应用层数据如何传递给内核协议栈,网卡硬件收到报文后传递给网络协议栈,协议栈又是如何传递给用户层的?多线程共用同一个UDP套接字发送,数据会错乱吗?那么多套接字,内核如何区分?...原创 2019-05-31 15:42:28 · 735 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析13 udp套接字发送流程二
内核版本:3.4.39继续UDP套接字发送,上一篇讲到了sock_sendmsg,这里继续,下面是sock_sendmsg的相关代码int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size){ /* kiocb为内核通用的IO请求结构 */ struct kiocb iocb; struct soc...原创 2019-05-31 16:28:03 · 616 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析14 udp套接字接收流程一
内核版本:3.4.39前面两篇文章分析了UDP套接字从应用层发送数据到内核层的处理流程,这里继续分析相反的流程,看看数据是怎么从内核送到应用层的。与发送类似,内核也提供了多个接收数据的系统调用接口,接口定义如下:#include <sys/types.h>#include <sys/socket.h>ssize_t recv(int sockfd, voi...原创 2019-05-31 17:00:24 · 613 阅读 · 0 评论 -
tcp/ip 协议栈Linux内核源码分析15 udp套接字接收流程二
内核版本:3.4.39上篇我们分析了UDP套接字如何接收数据的流程,最终它是在内核套接字的接收队列里取出报文,剩下的问题就是谁会去写入这个队列,当然,这部分工作由内核来完成,本篇剩下的文章主要分析内核网络层收到UDP报文后如何将报文插入到对应套接字的接收队列里面。我们直到网络层到传输层的最终的接口是ip_local_deliver_finish,下面是它的代码:static int ...原创 2019-05-31 17:09:51 · 618 阅读 · 0 评论 -
Linux虚拟内存和进程虚拟地址空间简述
后台开发经常会问此类问题,虽说难度不大,但是知道和不知道还是有区别的。以下的内容总结自《深入理解Linux内核》第一章,仅仅是简述,没有深入研究,毕竟内存管理这一块内容超级多,感兴趣的同学可以去啃啃这本书。虚拟内存所有新近的Unix系统都提供了一种有用的抽象,叫虚拟内存(virtual memory)。虚拟内存作为一种逻辑层,处于应用程序的内存请求与硬件内存管理单元(Memory Manag...原创 2019-09-08 10:23:56 · 830 阅读 · 0 评论