这是一年前研究移动ipv6时候写的一个文档。贴出来共享。
1、总体说明
以MIPL项目组的mipv6-2.0.2版本为样本,进行程序分析。MIPL项目组的MIPv6的实现分成两部分,一部分是对内核的修改,对内核打了一个长长的补丁;另一部分是用户空间的一个守护进程。这一部分仅仅是MIPv6的用户空间部分的代码,内核空间的代码另外的文档进行解读。其结构可以用下图来表示(摘录自NEPL (NEMO Platform for Linux) HOWTO.htm中的第一个图),这个NEMO的结构,和MIPL的结构其实是一样的。
在这个图中,可以看到内核和用户空间的接口。程序对于内核的修改,主要是为了给应用层提供接口。比如用户用于tunnel management的ioctl,用于icmp6的raw socket和用于mobility header的raw socket接口。要提供这些接口,就必须对内核进行一部分修改。内核的补丁就是做这个工作。
nemod(MIPL程序也一样)则是应用这些接口,将数据提取到用户空间的程序中,然后进行处理。处理结果再通过ioctl、xfrm或者RT Netlink等接口修改内核的一些行为。
本文档中,对于程序的注释,短的注释直接在程序语句的后面,长的注释放在程序语句的下一行。
看这个程序的时候,请务必参照MIPv6的有关协议来看,对照RFC的规定。不然很多地方就看不懂。
程序中变量和函数的命名有很多简写,要注意其含义。比较不好懂的含义,我基本上都在这篇文档中写出来了。还有一些比较常见的,比如CoTI之类的,就没有一一写出来。随便google一下,或者讲解MIPv6的书籍中,都会讲。理解这些简写的含义,对于理解程序的作用非常有帮助。
从我觉得,由于移动头部的处理和icmpv6的处理都在用户空间程序中,因此基本上可以不改动内核的代码,只改动这个程序的代码,就应该能够实现MIPv6的功能修改。
2、主函数注释
主函数在main.c中,从这里开始程序的分析。
int main(int argc, char **argv)
{
pthread_t sigth;
sigset_t sigblock;
// 声明一个信号集,关于unix信号,具体可以参见《unix环境高级编程》
int logflags = 0;
int ret = 1;
sdbg = stderr;
sigemptyset(&sigblock); //将信号集清空
sigaddset(&sigblock, SIGHUP); //添加信号集中的信号,SIGHUP是连接断开信号
sigaddset(&sigblock, SIGINT); //SIGINT是终端中断符信号
sigaddset(&sigblock, SIGTERM); //终止信号
#ifdef ENABLE_VT
sigaddset(&sigblock, SIGPIPE); //SIGPIPE是写至无读进程的管道信号,这些信号
//缺省的动作都是终止进程
#endif
pthread_sigmask(SIG_BLOCK, &sigblock, NULL);
//设置线程的私有信号掩码,当一个线程创建的时候,它会继承创造它的线程的信号掩码,
//具体可以参见《POSIX多线程程序设计》中第六章对信号的说明
if (conf_parse(&conf, argc, argv))
return 1;
//这个函数对用户从shell命令行传递过来的参数进行解析,然后存放在一个mip6_config
//结构体中,这个结构体保存着很多跟