2. ipip Protocol
Linux
2.6 Definition
A new protocol type
-- Ipip addresses described in this chapter
(
Ipproto_ipip
)
The main implementation is based on two files
New_tunnel.c
And
Ipip. C. Now, analyze the source code.
Ipip
Module loading and unloading.
Static int _ init ipip_init (void) <br/>{< br/> int err; <br/> printk (banner ); <br/> If (xfrm4_tunnel_register (& ipip_handler, af_inet) {<br/> printk (kern_info "ipip init: Can't register Tunnel/N "); <br/> return-eagain; <br/>}< br/> err = register_pernet_gen_device (& ipip_net_id, & ipip_net_ops); <br/> If (ERR) <br/> xfrm4_tunnel_deregister (& ipip_handler, af_inet); <br/> return err; <br/>}< br/>
First, use the ipip Protocol
Xfrm4_tunnel_register
Add the IP protocol type and priority to the IP tunnel, and then call the register_pernet_gen_device () function in the function to initialize the global init_net network space structure.
It can be seen that two parameter structures ipip_net_id and ipip_net_ops are passed to register_pernet_gen_device.
Static struct pernet_operations ipip_net_ops ={< br/>. init = ipip_init_net, <br/>. Exit = ipip_exit_net, <br/> };
Let's see how register_pernet_gen_device is implemented.
Int register_pernet_gen_device (int * ID, struct pernet_operations * OPS) <br/>{< br/> int error; <br/> mutex_lock (& net_mutex); <br/> again: <br/> error = ida_get_new_abve (& net_generic_ids, 1, ID); <br/> If (error) {<br/> If (error =-eagain) {<br/> ida_pre_get (& net_generic_ids, gfp_kernel); <br/> goto again; <br/>}< br/> goto out; <br/>}< br/> error = register_pernet_operations (& pernet_list, OPS); <br/> If (error) <br/> ida_remove (& net_generic_ids, * ID ); <br/> else if (first_device ==& pernet_list) <br/> first_device = & OPS-> list; <br/> out: <br/> mutex_unlock (& net_mutex); <br/> return error; <br/>
First, judge whether the init hook of ipipip_net_ops is linked. We can see that the above structure contains the ipip_init_net function, so we need to call this function to initialize the init_net network namespace.
Static int ipip_init_net (struct net * Net) <br/>{< br/> int err; <br/> struct ipip_net * IPN; <br/> err =-enomem; <br/> IPN = kzarloc (sizeof (struct ipip_net), gfp_kernel); <br/> If (IPN = NULL) <br/> goto err_alloc; <br/> err = net_assign_generic (net, ipip_net_id, IPN); <br/> If (ERR <0) <br/> goto err_assign; <br/> IPN-> tunnels [0] = IPN-> tunnels_wc; <br/> IPN-> tunnels [1] = IPN-> tunnels_l; <br/> IPN-> tunnels [2] = IPN-> tunnels_r; <br/> IPN-> tunnels [3] = IPN-> tunnels_r_l; <br/> IPN-> fb_tunnel_dev = alloc_netdev (sizeof (struct ip_tunnel), <br/> "tunl0", <br/> ipip_tunnel_setup); <br/> If (! IPN-> fb_tunnel_dev) {<br/> err =-enomem; <br/> goto err_alloc_dev; <br/>}< br/> dev_net_set (IPN-> fb_tunnel_dev, net); <br/> forward (IPN-> fb_tunnel_dev); <br/> If (ERR = register_netdev (IPN-> fb_tunnel_dev) <br/> goto err_reg_dev; <br/> return 0; <br/> err_reg_dev: <br/> free_netdev (IPN-> fb_tunnel_dev); <br/> err_alloc_dev: <br/>/* nothing */<br/> err_assign: <br/> kfree (IPN); <br/> err_alloc: <br/> return err; <br/>}
Initialize the network device parameters and register the network device. At this point, the initialization process is complete.
Detaching a network device is exactly the inverse process of the above process.
Static void ipip_exit_net (struct net * Net) <br/>{< br/> struct ipip_net * IPN; <br/> IPN = net_generic (net, ipip_net_id ); <br/> rtnl_lock (); <br/> ipip_destroy_tunnels (IPN); <br/> unregister_netdevice (IPN-> fb_tunnel_dev); <br/> rtnl_unlock (); <br/> kfree (IPN); <br/>}