Server 端接收数据时,按照相反的过程从网卡驱动中将数据包一层层上交,直到通过 Socket 抽象层接口将用户数据上交到用户态 Server 进程处理。
数据包在实际现网传输过程中,会经过各类交换机,路由器的转发处理,在这个过程中,路由器一般只处理到网络层。这里我们仅对 Linux 内核中网络层接收,发送以及转发数据的流程进行简单介绍。
下图为基于 Linux 2.6.38 版本内核的网络层相关接口在数据包收发过程的调用逻辑图:
[attach]52924[/attach]
注:
1)不同版本内核在函数名上可能存在一定差异,但整体调用逻辑基本不变;
2)该图仅展示 IPv4 的处理流程,IPv6 不在该图的函数中处理,但整体流程基本相似;
3)该图展示的流程仅为普通单播并且未进行 IP 分片的数据包处理流程,组播,多播,IP 分片的数据包在某些流程上存在差异;
// include/linux/netfilter.h/* Function to register/unregister hook points. */int nf_register_hook(struct nf_hook_ops *reg);void nf_unregister_hook(struct nf_hook_ops *reg);int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);这些函数用于将自定义的钩子操作(struct nf_hook_ops)注册到指定的钩子节点中。
钩子操作数据结构
// include/linux/netfilter.hstruct nf_hook_ops {struct list_head list;/* User fills in from here down. */nf_hookfn *hook;struct module *owner;u_int8_t pf;unsigned int hooknum;/* Hooks are ordered in ascending priority. */int priority;};这个结构体中存储了自定义的钩子函数(nf_hookfn),函数优先级(priority),处理协议类型(pf),钩子函数生效的钩子节点(hooknum)等信息。