IP数据包在net/core/dev.c:dev_add_pack()中完成注册,后者被net/ipv4/ip_output.c:ip_init()调用从而完成该项任务。Linux内核网络协议栈里,负责处理ipv4数据包处理函数是net/ipv4/ip_input.c:ip_rcv()。在一些初始化检验(如数据包是否针对该主机等)后,ip检验和被计算出来。其余一些检验如数据包的长度、协议版本号等也已经做好了。没用通过有效性检验的数据包都将被丢弃。一旦数据包通过了上述检验,数据包的大小就被计算出来,一些用于传输介质的无效填充字段将被截去。接下来是首次netfilter钩子函数将要被调用的时机了。Netrilter提供了一个泛化的一致性标准编程接口。它当前被用于数据包过滤、mangling、NAT和将数据包拷贝到用户空间。你可以在我的’Thenetfilter subsystem in linux 2.4’中获得详细的参考,此外还有一篇叫做’thenetfilter-hacking guide’也是很不错的参考读物。成功的穿过netfilter钩子函数后,net/ipv4/ipv_input.c:in_rcv_finish()函数被调用。在ip_rcv_finish()内,数据包的目的是根据调用函数net/ipv4/route.c:ip_route_input()来决定的。尤有进者,如果我们的ip数据包含有ip选项,它们会在此处被处理。数据包的传递路径可能会有几条,依net/ipv4/route.c:ip_route_slow()中做出的裁决而定。net/ipv4/ip_input.c:ip_local_deliver()数据包的目的地是本地,我们必须处理layer4协议并把数据包传递给用户空间。net/ipv4/ip_forward.c:ip_forward()数据包的目的地不是本地,我们要把它路由到其它网络。net/ipv4/route.c:ip_error()遇到了错误,我们无法在路由表中找到何时的项。net/ipv4/ipmr.c:ip_mr_input()是多播数据包,我们需要做多播路由。