Selecting the IP Header's ID Field
The main function for the initialization of the IP
packet ID is _ _ip_select_ident. This function can be
called both directly and indirectly via ip_select_ident
or ip_select_ident_more. Both of these wrapper
functions differentiate between packets that can and cannot be fragmented (based on the MF
flag). Two cases are defined:
- Packets cannot be fragmented (DF=1)
This case was added to handle a bug found with some Windows systems' IP stacks.[*] The ID is extracted indirectly from the
sockdata structures (inet_sk(sk)->sk), where it is incremented each time the wrapper accesses it. This ensures that the IP ID changes at every transmission.- Packets can be fragmented (DF=0)
ip_select_identtakes care of the ID.
ip_select_ident_more, which is used by TCP (see
ip_queue_xmit), receives one more input parameter
(more) that is used in those cases where the device
supports TCP offloading.
Let's go back to _ _ip_select_ident:
void _ _ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
{
struct rtable *rt = (struct rtable *) dst;
if (rt) {
if (rt->peer == NULL)
rt_bind_peer(rt, 1);
if (rt->peer) {
iph->id = htons(inet_getid(rt->peer, more));
return;
}
} else
printk(KERN_DEBUG "rt_bind_peer(0) @%p\n",
_ _builtin_return_address(0));
ip_select_fb_ident(iph);
}We saw in the section "Long-Living IP Peer
Information" that for each IP peer there is an inet_peer data structure that keeps, among other things, a counter that can be used to set the ...