LINUX内核协议栈分析
目 录
1 说明
本文档制作基于版本 linux-2.6.32,本文档的目的是让有一定的网络协议基础的人了解到网络数据包在协议栈中的传输流程,大致理解到从网卡收到数据包传输到应用层所经历的步骤,以及每个步骤所做的事情。 图片贴到最后。
本文档阅读基础:C语言基础,C语言回调函数,UML建模基础,C++面向对象封装思想,TCP/IP协议或网络基础。
2 TCP协议
本章摘自[TCP-IP详解卷一] 第一章。
2.1分层
网络协议通常分不同层次进行开发,每一层分别负责不同的通信功能。一个协议族,比如T C P / I P,是一组不同层次上的多个协议的组合。T C P / I P通常被认为是一个四层协议系统,如图1 - 1所示。每一层负责不同的功能:
1)链路层,有时也称作数据链路层或网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理与电缆(或其他任何传输媒介)的物理接口细节。
2)网络层,有时也称作互联网层,处理分组在网络中的活动,例如分组的选路。在
TC P / I P协议族中,网络层协议包括I P协议(网际协议),I C M P协议(I n t e r n e t互联网控制报文协议),以及I G M P协议(I n t e r n e t组管理协议)。
3) 运输层主要为两台主机上的应用程序提供端到端的通信。在T C P / I P协议族中,有两个互不相同的传输协议:T C P(传输控制协议)和U D P(用户数据报协议)。T C P为两台主机提供高可靠性的数据通信。它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。而另一方面,U D P则为应用层提供一种非常简单的服务。它只是把称作数据报的分组从一台主机发送到另一台主机,但并不保证该数据报能到达另一端。任何必需的可靠性必须由应用层来提供。
这两种运输层协议分别在不同的应用程序中有不同的用途,这一点将在后面看到。
4 ) 应用层负责处理特定的应用程序细节。几乎各种不同的T C P / I P实现都会提供下面这些通用的应用程序:
• Telnet 远程登录。
• FTP 文件传输协议。
• SMTP 简单邮件传送协议。
• SNMP 简单网络管理协议。
2.2TCP/IP的分层
在TC P / I P协议族中,有很多种协议。图1 - 4给出了本书将要讨论的其他协议。
T C P和U D P是两种最为著名的运输层协议,二者都使用I P作为网络层协议。
虽然T C P使用不可靠的I P服务,但它却提供一种可靠的运输层服务。本书第1 7~2 2章将详细讨论T C P的内部操作细节。然后,我们将介绍一些T C P的应用,如第2 6章中的Te l n e t和R l o g i n、第2 7章中的F T P以及第2 8章中的S M T P等。这些应用通常都是用户进程。
U D P为应用程序发送和接收数据报。一个数据报是指从发送方传输到接收方的一个信息单元(例如,发送方指定的一定字节数的信息)。但是与T C P不同的是,U D P是不可靠的,它不能保证数据报能安全无误地到达最终目的。本书第11章将讨论U D P,然后在第1 4章(D N S :域名系统),第1 5章(T F T P:简单文件传送协议),以及第1 6章(BO OT P:引导程序协议)介绍使用U D P的应用程序。S N M P也使用了U D P协议,但是由于它还要处理许多其他的协议,因此本书把它留到第2 5章再进行讨论。
I P是网络层上的主要协议,同时被T C P和U D P使用。T C P和U D P的每组数据都通过端系统和每个中间路由器中的I P层在互联网中进行传输。在图1 - 4中,我们给出了一个直接访问I P的应用程序。这是很少见的,但也是可能的(一些较老的选路协议就是以这种方式来实现的。当然新的运输层协议也有可能使用这种方式)。第3章主要讨论I P协议,但是为了使内容更加有针对性,一些细节将留在后面的章节中进行讨论。第9章和第1 0章讨论I P如何进行选路。
I C M P是I P协议的附属协议。I P层用它来与其他主机或路由器交换错误报文和其他重要信息。
第6章对I C M P的有关细节进行讨论。尽管I C M P主要被I P使用,但应用程序也有可能访问它。我们将分析两个流行的诊断工具,P i n g和Tr a c e r o u t e(第7章和第8章),它们都使用了I C M P。
I G M P是I n t e r n e t组管理协议。它用来把一个U D P数据报多播到多个主机。我们在第1 2章中描述广播(把一个U D P数据报发送到某个指定网络上的所有主机)和多播的一般特性,然后在第1 3章中对I G M P协议本身进行描述。
A R P(地址解析协议)和R A R P(逆地址解析协议)是某些网络接口(如以太网和令牌环网)使用的特殊协议,用来转换I P层和网络接口层使用的地址。我们分别在第4章和第5章对这两种协议进行分析和介绍。
2.3互联网的地址
互联网上的每个接口必须有一个唯一的I n t er n e t地址(也称作I P地址)。I P地址长32 bit。I n t e r n e t地址并不采用平面形式的地址空间,如1、2、3等。I P地址具有一定的结构,五类不同 的互联网地址格式如图1 - 5所示。
这些3 2位的地址通常写成四个十进制的数,其中每个整数对应一个字节。这种表示方法称作“点分十进制表示法(Dotted decimal notation)”。例如,作者的系统就是一个B类地址,它表示为:1 4 0 . 2 5 2 .1 3 . 3 3。
区分各类地址的最简单方法是看它的第一个十进制整数。图1 - 6列出了各类地址的起止范围,其中第一个十进制整数用加黑字体表示。
需要再次指出的是,多接口主机具有多个I P地址,其中每个接口都对应一个I P地址。
由于互联网上的每个接口必须有一个唯一的I P地址,因此必须要有一个管理机构为接入互联网的网络分配I P地址。这个管理机构就是互联网络信息中心(Internet Network InformationC e n t r e),称作I n t e r N I C。I n t e r N I C只分配网络号。主机号的分配由系统管理员来负责。
I n t e r n e t注册服务( I P地址和D N S域名)过去由N I C来负责,其网络地址是n i c . d d n . m i l。1 9 9 3年4月1日,I n t e r N I C成立。现在,N I C只负责处理国防数据网的注册请求,所有其他的I n t e r n e t用户注册请求均由I n t e rN I C负责处理,其网址是:r s . i n t er n i c . n e t。
事实上I n t e r N I C由三部分组成:注册服务(r s. i n t e r n i c . n e t),目录和数据库服
务(d s . i n t e r n i c. n e t),以及信息服务(i s . i n t e rn i c . n e t)。有关I n t e r N I C的其他信息参见习题1 . 8。
有三类I P地址:单播地址(目的为单个主机)、广播地址(目的端为给定网络上的所有主机)以及多播地址(目的端为同一组内的所有主机)。第1 2章和第1 3章将分别讨论广播和多播的更多细节。
在3 . 4节中,我们在介绍I P选路以后将进一步介绍子网的概念。图3 - 9给出了几个特殊的I P地址:主机号和网络号为全0或全1。
2.4封装
当应用程序用T C P传送数据时,数据被送入协议栈中,然后逐个通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部信息(有时还要增加尾部信息),该过程如图1 - 7所示。T C P传给I P的数据单元称作T C P报文段或简称为T C P段(T C P s e g m e n t)。I P传给网络接口层的数据单元称作I P数据报(IP datagram)。通过以太网传输的比特流称作帧(Fr a m e )。1 - 7中帧头和帧尾下面所标注的数字是典型以太网帧首部的字节长度
2.5分用
当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由底向上升,同时去掉各
层协议加上的报文首部。每层协议盒都要去检查报文首部中的协议标识,以确定接收数据的
上层协议。这个过程称作分用( D e m u lt i p l e x i n g),图1 - 8显示了该过程是如何发生的。[TCP-IP详解卷一]
3 数据包格式
3.1ethhdr
描述以太网头部
/*
* Thisis an Ethernet frame header.
*/
struct ethhdr {
unsigned char h_dest[ETH_ALEN];/* destination ethaddr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
__be16 h_proto; /* packet type ID field */
} __attribute__((packed));
/*
* Theseare the defined Ethernet Protocol ID's.
*/
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define ETH_P_X25 0x0805 /* CCITT X.25 */
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25Ethernet Packet [ NOT AN OFFICIALLYREGISTERED ID ] */
#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */
#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */
#define ETH_P_DEC 0x6000 /* DEC Assigned proto */
#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */
#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */
#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */
#define ETH_P_LAT 0x6004 /* DEC LAT */
#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */
#define ETH_P_CUST 0x6006 /* DEC Customer use */
#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */
#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */
#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
#define ETH_P_ATALK 0x809B /* Appletalk DDP */
#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
#define ETH_P_IPX 0x8137 /* IPX over DIX */
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */
#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */
#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol
* defined in draft-wilson-wrec-wccp-v2-00.txt*/
#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */
#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */
#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */
#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */
#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */
#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport
* over Ethernet
*/
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
#define ETH_P_TIPC 0x88CA /* TIPC */
#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */
#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */
#define ETH_P_TDLS 0x890D /* TDLS */
#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */
#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID] */
#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ]*/
3.2iphdr
描述ip头部
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix<asm/byteorder.h>"
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};
3.3udphdr
描述udp头部
struct udphdr {
__be16 source;
__be16 dest;
__be16 len;
__sum16 check;
};
4 数据结构
内核协议栈涉及的数据结较多,错综复杂,这里只是粘贴了设计到的数据结构的源码。源码和注释用10字体,高亮显示;重要的成员和方法用加粗11号字体标出。例如
4.1内核协议栈分层结构
图4-1 内核协议栈分层结构
Physical device hardware : 指的实实在在的物理设备。 对应physical layer
Device agnostic interface : 设备无关层。 对应Link layer
Network protocols : 网络层。 对应Ip layer 和 transportlayer
Protocol agnostic interface: 协议无关层 适配系统调用层,屏蔽了协议的细节
System callinterface:系统调用层 提供给应用层的系统调用,屏蔽了socket操作的细节
BSD socket: BSD Socket层 提供统一socket操作的接口, socket结构关系紧密
Inet socket: inet socket 层 调用ip层协议的统一接口,sock结构关系紧密
4.2msghdr
描述了从应用层传递下来的消息格式,包含有用户空间地址,消息标记等重要信息。
/*
* Aswe do 4.4BSD message passing we use a 4.4BSD message passing
* system,not 4.3. Thus msg_accrights(len) are now missing. They
* belongin an obscure libc emulation or the bin.
*/
struct msghdr {
void * msg_name; /* Socket name */
int msg_namelen; /* Length of name */
struct iovec* msg_iov; /* Data blocks */
__kernel_size_t msg_iovlen; /* Number of blocks */
void * msg_control; /* Per protocolmagic (eg BSD file descriptor passing) */
__kernel_size_t msg_controllen; /* Length of cmsglist */
unsigned msg_flags;
};
4.3iovec
描述了用户空间地址的起始位置。
/*
* Berkeleystyle UIO structures - Alan Cox 1994.
*
* Thisprogram is free software; you can redistribute it and/or
* modifyit under the terms of the GNU General Public License
* aspublished by the Free Software Foundation; either version
* 2of the License, or (at your option) any later version.
*/
struct iovec {
void __user*iov_base; /* BSD uses caddr_t(1003.1g requires void *) */
__kernel_size_t iov_len;/* Must be size_t(1003.1g) */
};
4.4file
描述文件属性的结构体,与文件描述符一一对应。
struct file {
/*
* fu_list becomes invalid after file_free iscalled and queued via
* fu_rcuhead for RCU freeing
*/
union {
struct list_head fu_list;
struct rcu_head fu_rcuhead;
} f_u;
struct path f_path;
#define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt
const struct file_operations *f_op;
spinlock_t f_lock; /* f_ep_links,f_flags, no IRQ */
atomic_long_t f_count;
unsigned int f_flags;
fmode_t f_mode;
loff_t f_pos;
struct fown_struct f_owner;
const struct cred *f_cred;
struct file_ra_state f_ra;
u64 f_version;
#ifdef CONFIG_SECURITY
void *f_security;
#endif
/* needed for tty driver, and maybeothers */
void *private_data;
#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link allthe hooks to this file */
struct list_head f_ep_links;
#endif /*#ifdef CONFIG_EPOLL */
struct address_space*f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
unsigned long f_mnt_write_state;
#endif
};
4.5file_operations
文件操作相关结构体,包括read(), write(), open(),ioctl()等。
/*
* NOTE:
* read, write, poll, fsync, readv,writev, unlocked_ioctl and compat_ioctl
* can be called without the bigkernel lock held in all filesystems.
*/
structfile_operations {
struct module *owner;
loff_t (*llseek)(struct file*, loff_t,int);
ssize_t (*read) (struct file*,char __user*,size_t, loff_t*);
ssize_t (*write) (struct file*,constchar __user*,size_t, loff_t*);
ssize_t (*aio_read)(struct kiocb*, const struct iovec *,unsignedlong, loff_t);
ssize_t (*aio_write)(struct kiocb*, const struct iovec *,unsignedlong, loff_t);
int (*readdir)(struct file*,void*, filldir_t);
unsigned int (*poll)(struct file*,struct poll_table_struct *);
int (*ioctl) (struct inode*,struct file*,unsignedint,unsignedlong);
long (*unlocked_ioctl)(struct file*, unsigned int,unsignedlong);
long (*compat_ioctl)(struct file*, unsigned int,unsignedlong);
int (*mmap)(struct file*,struct vm_area_struct *);
int (*open) (struct inode*,struct file*);
int (*flush)(struct file*, fl_owner_t id);
int (*release)(struct inode*,struct file *);
int (*fsync)(struct file*,struct dentry *,int datasync);
int (*aio_fsync)(struct kiocb*, int datasync);
int (*fasync)(int,struct file *,int);
int (*lock)(struct file*,int,struct file_lock *);
ssize_t (*sendpage)(struct file*, struct page *, int, size_t, loff_t *,int);
unsigned long (*get_unmapped_area)(struct file*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);
int (*check_flags)(int);
int (*flock)(struct file*,int,struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info*,struct file *, loff_t*,size_t,unsignedint);
ssize_t (*splice_read)(struct file*, loff_t *,struct pipe_inode_info*,size_t,unsignedint);
int (*setlease)(struct file*,long,struct file_lock **);
};
4.6socket
向应用层提供的BSD socket操作结构体,协议无关,主要作用为应用层提供统一的socket操作。BSD: BerkeleySoftwareDistribution)
/**