Linux2.4.0ip layer forwarding process
Email: getmoon@163.com QQ: 505333 wants to take a moon
Download address: http://linuxsouce.home.sohu.com/download/ipforward.zip
Other documents download: http://linuxsouce.home.sohu.com/download/index.html
/ * About local reception of a packet is local transmission or forwarding, please see the IP layer data flow I painted * /
/ * Forward a packet * /
/ * All options have not been detailed to each option * /
INT ip_forward (struct SK_Buff * SKB)
{
Struct Net_Device * dev2; / * Output Device * /
Struct iphdr * iph; / * urheader * /
Struct RTable * rt; / * route we use * /
Struct ip_options * OPT = & (IPCB (SKB) -> OPT);
UNSIGNED SHORT MTU;
IF (IPCB (SKB) -> OPT.ROUTER_ALERT && IP_CALL_RA_CHAIN (SKB))
Return NET_RX_SUCCESS;
IF (SKB-> PKT_TYPE! = packet_host) / * broadcasted, multicast, mixed mode to be forwarded * /
Goto DROP;
/ *
* According to the RFC, We Must First Decrease the TTL Field. IF
* That Reaches Zero, WE Must Reply An ICMP Control Message Telling
* That the packet's lifetime expression.
* /
IPH = SKB-> NH.IPH;
RT = (struct RTable *) SKB-> DST; / * When this package, SKB-> DST is definitely content * /
IF (iPh-> TTL <= 1) / * TTL value is too small. * /
Goto TOO_MANY_HOPS;
IF (OPT-> IS_STRICTROUTE && RT-> RT_DST! = RT-> RT_GATEWAY) / * If the route is selected from the next station is not a gateway, discard this package * /
Goto SR_FaiLED;
/ *
* Having Picked A Route We Can now send the frame out
* after asseking the firewall permission to do so.
* /
SKB-> Priority = rt_tos2priority (iPh-> TOS); / * Priority * /
DEV2 = RT-> u.dst.dev; / * Send it through this device * /
MTU = RT-> u.dst.pmtu; / * Get this device to connect the network's MTU * /
/ *
* We now generate an icmp host redirect giving the route
* we Calculate.
* /
/ * When the routing is reordered and there is no source routing option, a redirected ICMP package must be generated * /
IF (RT-> RT_FLAGS & RTCF_DOREDIRECT &&! OPT-> SRR)
/ * Re-direction * /
IP_RT_SEND_REDIRECT (SKB);
/ * We are about to mark packet. Copy it! * /
IF ((SKB = SKB_COW (SKB, DEV2-> HARD_HEADER_LEN)) == NULL) / * Reorganize this SKBUFF structure * / return net_rx_drop;
IPH = SKB-> NH.IPH;
OPT = & (IPCB (SKB) -> OPT);
/ * Decrease TTLAFTER SKB COW DONE * /
/ * Reduce TTL, of course, re-calculate the checksum * /
IP_DECREASE_TTL (IPH);
/ *
* We now May Allocate A New Buffer, And Copy The DataGRAM INTO IT.
* If the indeicated interface is up and running, kick it.
* /
IF (SKB-> LEN> MTU & IP_DF)) / * If no slide is set, this package requires fragmentation, send ICMP packages * /
Goto frame_needed;
#ifdef config_ip_route_nat
IF (RT-> RT_FLAGS & RTCF_NAT) {/ * If the NAT conversion is compiled and this route is to be NAT conversion * /
IF (IP_DO_NAT (SKB)) {/ * NAT address conversion processing * /
Kfree_skb (SKB);
Return NET_RX_BAD;
}
}
#ENDIF
/ * Forward detection points, if you do not discard, call ip_forward_finish * /
Return nf_hook (PF_INET, NF_IP_FORWARD, SKB, SKB-> DEV, DEV2,
IP_forward_finish;
FRAG_NEEDED:
/ * Set DF, and it needs to be handled here * /
IP_INC_STATS_BH (IPFragfails);
ICMP_SEND (SKB, ICMP_DEST_UNREACH, ICMP_FRAG_NEED, HTONL (MTU));
Goto DROP;
SR_FaiLED:
/ *
* Strict routing permits no acid
* /
ICMP_SEND (SKB, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
Goto DROP;
TOO_MANY_HOPS:
/ * Tell the sender its packet died ... * /
ICMP_SEND (SKB, ICMP_TIME_EXCEED, ICMP_EXC_TTL, 0);
Drop:
Kfree_skb (SKB);
Return NET_RX_DROP;
}
Static inline int ip_forward_finish (struct SK_Buff * SKB)
{
Struct ip_options * OPT = & (IPCB (SKB) -> OPT); / * OPT pointing options * /
IP_inc_stats_bh (ipforwdatagrams);
IF (OPT-> OPTLEN == 0) {
#ifdef config_net_faSTroute
Struct RTable * RT = (struct RTable *) SKB-> DST;
IF (RT-> RT_FLAGS & RTCF_FAST &&! NetDev_faster_obstacles) {
STRUCT DST_ENTRY * OLD_DST;
Unsigned h = ((* (u8 *) & rt-> key.dst) ^ (* (u8 *) & rt-> key.src)) & NetDev_faster_hmask; write_lock_irq (& SKB-> dev-> fastpath_lock);
OLD_DST = SKB-> dev-> fastpath [h];
SKB-> dev-> fastpath [h] = dst_clone (& rt-> u.dst);
Write_unlock_irq (& SKB-> dev-> fastpath_lock);
DST_RELEASE (OLD_DST);
}
#ENDIF
Return (IP_SEND (SKB));
}
IP_forward_options (SKB); / * Options for forwarding * /
Return (IP_send (SKB)); / * Send Pack * /
}
Static Inline INT IP_SEND (STRUCT SK_BUFF * SKB)
{
IF (SKB-> LEN> SKB-> DST-> PMTU) / * Judging whether it is required * /
Return ip_fragment (SKB, IP_FINISH_OUTPUT); / * Split Split, IP_FINISH_OUTPUT is the callback function after the slice is finished * /
Else
Return IP_FINISH_OUTPUT (SKB); / * The forwarding process ends, send it out * /
}
__INline__ int ip_finish_output (struct SK_Buff * SKB)
{
Struct Net_Device * dev = SKB-> DST-> DEV;
SKB-> DEV = dev; / * Set the sending device * /
SKB-> protocol = __constant_htons (eth_p_ip); / * Protocol type of the package * /
/ * Before sending, if not discard, call ip_finish_output2 * /
Return nf_hook (PF_INET, NF_IP_POST_ROUTING, SKB, NULL, DEV,
IP_FINISH_OUTPUT2);
}
Static Inline INT IP_FINISH_OUTPUT2 (Struct SK_Buff * SKB)
{
STRUCT DST_ENTRY * DST = SKB-> DST;
Struct hh_cache * hh = dst-> hh;
#ifdef config_netfilter_debug
NF_DEBUG_IP_FINISH_OUTPUT2 (SKB);
#ENDIF / * config_netfilter_debug * /
IF (hh) {/ * has hardware cache structure * /
Read_lock_bh (& HH-> HH_LOCK);
Memcpy (SKB-> DATA - 16, HH-> HH_DATA, 16);
Read_unlock_bh (& HH-> HH_LOCK);
SKB_PUSH (SKB, HH-> HH_LEN);
Return hh-> hh_output (SKB); / * actually calls dev_queue_xmit * /
Else IF (DST-> neighbour)
Return DST-> neighbour-> output (SKB); / * neigh_resolve_output, after the hardware address parsing is over, it is called dev_queue_xmit * /
Printk (kern_debug "khm / n");
Kfree_skb (SKB);
Return-EinVal;
}