home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / net / inet / route.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-12  |  13.2 KB  |  673 lines

  1. /*
  2.  * INET        An implementation of the TCP/IP protocol suite for the LINUX
  3.  *        operating system.  INET is implemented using the  BSD Socket
  4.  *        interface as the means of communication with the user level.
  5.  *
  6.  *        ROUTE - implementation of the IP router.
  7.  *
  8.  * Version:    @(#)route.c    1.0.14    05/31/93
  9.  *
  10.  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  11.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12.  *        Alan Cox, <gw4pts@gw4pts.ampr.org>
  13.  *        Linus Torvalds, <Linus.Torvalds@helsinki.fi>
  14.  *
  15.  * Fixes:
  16.  *        Alan Cox    :    Verify area fixes.
  17.  *        Alan Cox    :    cli() protects routing changes
  18.  *        Rui Oliveira    :    ICMP routing table updates
  19.  *        (rco@di.uminho.pt)    Routing table insertion and update
  20.  *        Linus Torvalds    :    Rewrote bits to be sensible
  21.  *        Alan Cox    :    Added BSD route gw semantics
  22.  *        Alan Cox    :    Super /proc >4K 
  23.  *        Alan Cox    :    MTU in route table
  24.  *        Alan Cox    :     MSS actually. Also added the window
  25.  *                    clamper.
  26.  *        Sam Lantinga    :    Fixed route matching in rt_del()
  27.  *
  28.  *        This program is free software; you can redistribute it and/or
  29.  *        modify it under the terms of the GNU General Public License
  30.  *        as published by the Free Software Foundation; either version
  31.  *        2 of the License, or (at your option) any later version.
  32.  */
  33.  
  34. #include <asm/segment.h>
  35. #include <asm/system.h>
  36. #include <linux/types.h>
  37. #include <linux/kernel.h>
  38. #include <linux/sched.h>
  39. #include <linux/mm.h>
  40. #include <linux/string.h>
  41. #include <linux/socket.h>
  42. #include <linux/sockios.h>
  43. #include <linux/errno.h>
  44. #include <linux/in.h>
  45. #include <linux/inet.h>
  46. #include <linux/netdevice.h>
  47. #include "ip.h"
  48. #include "protocol.h"
  49. #include "route.h"
  50. #include "tcp.h"
  51. #include <linux/skbuff.h>
  52. #include "sock.h"
  53. #include "icmp.h"
  54.  
  55. /*
  56.  *    The routing table list
  57.  */
  58.  
  59. static struct rtable *rt_base = NULL;
  60.  
  61. /*
  62.  *    Pointer to the loopback route
  63.  */
  64.  
  65. static struct rtable *rt_loopback = NULL;
  66.  
  67. /*
  68.  *    Remove a routing table entry.
  69.  */
  70.  
  71. static void rt_del(unsigned long dst, char *devname)
  72. {
  73.     struct rtable *r, **rp;
  74.     unsigned long flags;
  75.  
  76.     rp = &rt_base;
  77.     
  78.     /*
  79.      *    This must be done with interrupts off because we could take
  80.      *    an ICMP_REDIRECT.
  81.      */
  82.      
  83.     save_flags(flags);
  84.     cli();
  85.     while((r = *rp) != NULL) 
  86.     {
  87.         /* Make sure both the destination and the device match */
  88.         if ( r->rt_dst != dst ||
  89.         (devname != NULL && strcmp((r->rt_dev)->name,devname) != 0) )
  90.         {
  91.             rp = &r->rt_next;
  92.             continue;
  93.         }
  94.         *rp = r->rt_next;
  95.         
  96.         /*
  97.          *    If we delete the loopback route update its pointer.
  98.          */
  99.          
  100.         if (rt_loopback == r)
  101.             rt_loopback = NULL;
  102.         kfree_s(r, sizeof(struct rtable));
  103.     } 
  104.     restore_flags(flags);
  105. }
  106.  
  107.  
  108. /*
  109.  *    Remove all routing table entries for a device. This is called when
  110.  *    a device is downed.
  111.  */
  112.  
  113. void ip_rt_flush(struct device *dev)
  114. {
  115.     struct rtable *r;
  116.     struct rtable **rp;
  117.     unsigned long flags;
  118.  
  119.     rp = &rt_base;
  120.     save_flags(flags);
  121.     cli();
  122.     while ((r = *rp) != NULL) {
  123.         if (r->rt_dev != dev) {
  124.             rp = &r->rt_next;
  125.             continue;
  126.         }
  127.         *rp = r->rt_next;
  128.         if (rt_loopback == r)
  129.             rt_loopback = NULL;
  130.         kfree_s(r, sizeof(struct rtable));
  131.     } 
  132.     restore_flags(flags);
  133. }
  134.  
  135. /*
  136.  *    Used by 'rt_add()' when we can't get the netmask any other way..
  137.  *
  138.  *    If the lower byte or two are zero, we guess the mask based on the
  139.  *    number of zero 8-bit net numbers, otherwise we use the "default"
  140.  *    masks judging by the destination address and our device netmask.
  141.  */
  142.  
  143. static inline unsigned long default_mask(unsigned long dst)
  144. {
  145.     dst = ntohl(dst);
  146.     if (IN_CLASSA(dst))
  147.         return htonl(IN_CLASSA_NET);
  148.     if (IN_CLASSB(dst))
  149.         return htonl(IN_CLASSB_NET);
  150.     return htonl(IN_CLASSC_NET);
  151. }
  152.  
  153.  
  154. /*
  155.  *    If no mask is specified then generate a default entry.
  156.  */
  157.  
  158. static unsigned long guess_mask(unsigned long dst, struct device * dev)
  159. {
  160.     unsigned long mask;
  161.  
  162.     if (!dst)
  163.         return 0;
  164.     mask = default_mask(dst);
  165.     if ((dst ^ dev->pa_addr) & mask)
  166.         return mask;
  167.     return dev->pa_mask;
  168. }
  169.  
  170.  
  171. /*
  172.  *    Find the route entry through which our gateway will be reached
  173.  */
  174.  
  175. static inline struct device * get_gw_dev(unsigned long gw)
  176. {
  177.     struct rtable * rt;
  178.  
  179.     for (rt = rt_base ; ; rt = rt->rt_next) 
  180.     {
  181.         if (!rt)
  182.             return NULL;
  183.         if ((gw ^ rt->rt_dst) & rt->rt_mask)
  184.             continue;
  185.         /* 
  186.          *    Gateways behind gateways are a no-no 
  187.          */
  188.          
  189.         if (rt->rt_flags & RTF_GATEWAY)
  190.             return NULL;
  191.         return rt->rt_dev;
  192.     }
  193. }
  194.  
  195. /*
  196.  *    Rewrote rt_add(), as the old one was weird - Linus
  197.  *
  198.  *    This routine is used to update the IP routing table, either
  199.  *    from the kernel (ICMP_REDIRECT) or via an ioctl call issued
  200.  *    by the superuser.
  201.  */
  202.  
  203. void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
  204.     unsigned long gw, struct device *dev, unsigned short mtu, unsigned long window)
  205. {
  206.     struct rtable *r, *rt;
  207.     struct rtable **rp;
  208.     unsigned long cpuflags;
  209.  
  210.     /*
  211.      *    A host is a unique machine and has no network bits.
  212.      */
  213.      
  214.     if (flags & RTF_HOST) 
  215.     {
  216.         mask = 0xffffffff;
  217.     } 
  218.     
  219.     /*
  220.      *    Calculate the network mask
  221.      */
  222.      
  223.     else if (!mask) 
  224.     {
  225.         if (!((dst ^ dev->pa_addr) & dev->pa_mask)) 
  226.         {
  227.             mask = dev->pa_mask;
  228.             flags &= ~RTF_GATEWAY;
  229.             if (flags & RTF_DYNAMIC) 
  230.             {
  231.                 /*printk("Dynamic route to my own net rejected\n");*/
  232.                 return;
  233.             }
  234.         } 
  235.         else
  236.             mask = guess_mask(dst, dev);
  237.         dst &= mask;
  238.     }
  239.     
  240.     /*
  241.      *    A gateway must be reachable and not a local address
  242.      */
  243.      
  244.     if (gw == dev->pa_addr)
  245.         flags &= ~RTF_GATEWAY;
  246.         
  247.     if (flags & RTF_GATEWAY) 
  248.     {
  249.         /*
  250.          *    Don't try to add a gateway we can't reach.. 
  251.          */
  252.          
  253.         if (dev != get_gw_dev(gw))
  254.             return;
  255.             
  256.         flags |= RTF_GATEWAY;
  257.     } 
  258.     else
  259.         gw = 0;
  260.         
  261.     /*
  262.      *    Allocate an entry and fill it in.
  263.      */
  264.      
  265.     rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
  266.     if (rt == NULL) 
  267.     {
  268.         return;
  269.     }
  270.     memset(rt, 0, sizeof(struct rtable));
  271.     rt->rt_flags = flags | RTF_UP;
  272.     rt->rt_dst = dst;
  273.     rt->rt_dev = dev;
  274.     rt->rt_gateway = gw;
  275.     rt->rt_mask = mask;
  276.     rt->rt_mss = dev->mtu - HEADER_SIZE;
  277.     rt->rt_window = 0;    /* Default is no clamping */
  278.  
  279.     /* Are the MSS/Window valid ? */
  280.  
  281.     if(rt->rt_flags & RTF_MSS)
  282.         rt->rt_mss = mtu;
  283.         
  284.     if(rt->rt_flags & RTF_WINDOW)
  285.         rt->rt_window = window;
  286.  
  287.     /*
  288.      *    What we have to do is loop though this until we have
  289.      *    found the first address which has a higher generality than
  290.      *    the one in rt.  Then we can put rt in right before it.
  291.      *    The interrupts must be off for this process.
  292.      */
  293.  
  294.     save_flags(cpuflags);
  295.     cli();
  296.  
  297.     /*
  298.      *    Remove old route if we are getting a duplicate. 
  299.      */
  300.      
  301.     rp = &rt_base;
  302.     while ((r = *rp) != NULL) 
  303.     {
  304.         if (r->rt_dst != dst || 
  305.             r->rt_mask != mask) 
  306.         {
  307.             rp = &r->rt_next;
  308.             continue;
  309.         }
  310.         *rp = r->rt_next;
  311.         if (rt_loopback == r)
  312.             rt_loopback = NULL;
  313.         kfree_s(r, sizeof(struct rtable));
  314.     }
  315.     
  316.     /*
  317.      *    Add the new route 
  318.      */
  319.      
  320.     rp = &rt_base;
  321.     while ((r = *rp) != NULL) {
  322.         if ((r->rt_mask & mask) != mask)
  323.             break;
  324.         rp = &r->rt_next;
  325.     }
  326.     rt->rt_next = r;
  327.     *rp = rt;
  328.     
  329.     /*
  330.      *    Update the loopback route
  331.      */
  332.      
  333.     if ((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback)
  334.         rt_loopback = rt;
  335.         
  336.     /*
  337.      *    Restore the interrupts and return
  338.      */
  339.      
  340.     restore_flags(cpuflags);
  341.     return;
  342. }
  343.  
  344.  
  345. /*
  346.  *    Check if a mask is acceptable.
  347.  */
  348.  
  349. static inline int bad_mask(unsigned long mask, unsigned long addr)
  350. {
  351.     if (addr & (mask = ~mask))
  352.         return 1;
  353.     mask = ntohl(mask);
  354.     if (mask & (mask+1))
  355.         return 1;
  356.     return 0;
  357. }
  358.  
  359. /*
  360.  *    Process a route add request from the user
  361.  */
  362.  
  363. static int rt_new(struct rtentry *r)
  364. {
  365.     int err;
  366.     char * devname;
  367.     struct device * dev = NULL;
  368.     unsigned long flags, daddr, mask, gw;
  369.  
  370.     /*
  371.      *    If a device is specified find it.
  372.      */
  373.      
  374.     if ((devname = r->rt_dev) != NULL) 
  375.     {
  376.         err = getname(devname, &devname);
  377.         if (err)
  378.             return err;
  379.         dev = dev_get(devname);
  380.         putname(devname);
  381.         if (!dev)
  382.             return -EINVAL;
  383.     }
  384.     
  385.     /*
  386.      *    If the device isn't INET, don't allow it
  387.      */
  388.  
  389.     if (r->rt_dst.sa_family != AF_INET)
  390.         return -EAFNOSUPPORT;
  391.  
  392.     /*
  393.      *    Make local copies of the important bits
  394.      */
  395.      
  396.     flags = r->rt_flags;
  397.     daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
  398.     mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
  399.     gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
  400.  
  401.  
  402.     /*
  403.      *    BSD emulation: Permits route add someroute gw one-of-my-addresses
  404.      *    to indicate which iface. Not as clean as the nice Linux dev technique
  405.      *    but people keep using it... 
  406.      */
  407.      
  408.     if (!dev && (flags & RTF_GATEWAY)) 
  409.     {
  410.         struct device *dev2;
  411.         for (dev2 = dev_base ; dev2 != NULL ; dev2 = dev2->next) 
  412.         {
  413.             if ((dev2->flags & IFF_UP) && dev2->pa_addr == gw) 
  414.             {
  415.                 flags &= ~RTF_GATEWAY;
  416.                 dev = dev2;
  417.                 break;
  418.             }
  419.         }
  420.     }
  421.  
  422.     /*
  423.      *    Ignore faulty masks
  424.      */
  425.      
  426.     if (bad_mask(mask, daddr))
  427.         mask = 0;
  428.  
  429.     /*
  430.      *    Set the mask to nothing for host routes.
  431.      */
  432.      
  433.     if (flags & RTF_HOST)
  434.         mask = 0xffffffff;
  435.     else if (mask && r->rt_genmask.sa_family != AF_INET)
  436.         return -EAFNOSUPPORT;
  437.  
  438.     /*
  439.      *    You can only gateway IP via IP..
  440.      */
  441.      
  442.     if (flags & RTF_GATEWAY) 
  443.     {
  444.         if (r->rt_gateway.sa_family != AF_INET)
  445.             return -EAFNOSUPPORT;
  446.         if (!dev)
  447.             dev = get_gw_dev(gw);
  448.     } 
  449.     else if (!dev)
  450.         dev = ip_dev_check(daddr);
  451.  
  452.     /*
  453.      *    Unknown device.
  454.      */
  455.      
  456.     if (dev == NULL)
  457.         return -ENETUNREACH;
  458.  
  459.     /*
  460.      *    Add the route
  461.      */
  462.      
  463.     ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window);
  464.     return 0;
  465. }
  466.  
  467.  
  468. /*
  469.  *    Remove a route, as requested by the user.
  470.  */
  471.  
  472. static int rt_kill(struct rtentry *r)
  473. {
  474.     struct sockaddr_in *trg;
  475.     char *devname;
  476.     int err;
  477.  
  478.     trg = (struct sockaddr_in *) &r->rt_dst;
  479.     if ((devname = r->rt_dev) != NULL) 
  480.     {
  481.         err = getname(devname, &devname);
  482.         if (err)
  483.             return err;
  484.     }
  485.     rt_del(trg->sin_addr.s_addr, devname);
  486.     if ( devname != NULL )
  487.         putname(devname);
  488.     return 0;
  489. }
  490.  
  491.  
  492. /* 
  493.  *    Called from the PROCfs module. This outputs /proc/net/route.
  494.  */
  495.  
  496. int rt_get_info(char *buffer, char **start, off_t offset, int length)
  497. {
  498.     struct rtable *r;
  499.     int len=0;
  500.     off_t pos=0;
  501.     off_t begin=0;
  502.     int size;
  503.  
  504.     len += sprintf(buffer,
  505.          "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\n");
  506.     pos=len;
  507.   
  508.     /*
  509.      *    This isn't quite right -- r->rt_dst is a struct! 
  510.      */
  511.      
  512.     for (r = rt_base; r != NULL; r = r->rt_next) 
  513.     {
  514.             size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\t%d\t%lu\n",
  515.             r->rt_dev->name, r->rt_dst, r->rt_gateway,
  516.             r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
  517.             r->rt_mask, (int)r->rt_mss, r->rt_window);
  518.         len+=size;
  519.         pos+=size;
  520.         if(pos<offset)
  521.         {
  522.             len=0;
  523.             begin=pos;
  524.         }
  525.         if(pos>offset+length)
  526.             break;
  527.       }
  528.       
  529.       *start=buffer+(offset-begin);
  530.       len-=(offset-begin);
  531.       if(len>length)
  532.           len=length;
  533.       return len;
  534. }
  535.  
  536. /*
  537.  *    This is hackish, but results in better code. Use "-S" to see why.
  538.  */
  539.  
  540. #define early_out ({ goto no_route; 1; })
  541.  
  542. /*
  543.  *    Route a packet. This needs to be fairly quick. Florian & Co. 
  544.  *    suggested a unified ARP and IP routing cache. Done right its
  545.  *    probably a brilliant idea. I'd actually suggest a unified
  546.  *    ARP/IP routing/Socket pointer cache. Volunteers welcome
  547.  */
  548.  
  549. struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr)
  550. {
  551.     struct rtable *rt;
  552.  
  553.     for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next) 
  554.     {
  555.         if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
  556.             break;
  557.         /*
  558.          *    broadcast addresses can be special cases.. 
  559.          */
  560.         if (rt->rt_flags & RTF_GATEWAY)
  561.             continue;         
  562.         if ((rt->rt_dev->flags & IFF_BROADCAST) &&
  563.             (rt->rt_dev->pa_brdaddr == daddr))
  564.             break;
  565.     }
  566.     
  567.     if(src_addr!=NULL)
  568.         *src_addr= rt->rt_dev->pa_addr;
  569.         
  570.     if (daddr == rt->rt_dev->pa_addr) {
  571.         if ((rt = rt_loopback) == NULL)
  572.             goto no_route;
  573.     }
  574.     rt->rt_use++;
  575.     return rt;
  576. no_route:
  577.     return NULL;
  578. }
  579.  
  580. struct rtable * ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr)
  581. {
  582.     struct rtable *rt;
  583.  
  584.     for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next) 
  585.     {
  586.         /*
  587.          *    No routed addressing.
  588.          */
  589.         if (rt->rt_flags&RTF_GATEWAY)
  590.             continue;
  591.             
  592.         if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
  593.             break;
  594.         /*
  595.          *    broadcast addresses can be special cases.. 
  596.          */
  597.          
  598.         if ((rt->rt_dev->flags & IFF_BROADCAST) &&
  599.              rt->rt_dev->pa_brdaddr == daddr)
  600.             break;
  601.     }
  602.     
  603.     if(src_addr!=NULL)
  604.         *src_addr= rt->rt_dev->pa_addr;
  605.         
  606.     if (daddr == rt->rt_dev->pa_addr) {
  607.         if ((rt = rt_loopback) == NULL)
  608.             goto no_route;
  609.     }
  610.     rt->rt_use++;
  611.     return rt;
  612. no_route:
  613.     return NULL;
  614. }
  615.  
  616. /*
  617.  *    Backwards compatibility
  618.  */
  619.  
  620. static int ip_get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
  621. {
  622.     int err;
  623.     struct old_rtentry tmp;
  624.  
  625.     err=verify_area(VERIFY_READ, src, sizeof(*src));
  626.     if (err)
  627.         return err;
  628.     memcpy_fromfs(&tmp, src, sizeof(*src));
  629.     memset(rt, 0, sizeof(*rt));
  630.     rt->rt_dst = tmp.rt_dst;
  631.     rt->rt_gateway = tmp.rt_gateway;
  632.     rt->rt_genmask.sa_family = AF_INET;
  633.     ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
  634.     rt->rt_flags = tmp.rt_flags;
  635.     rt->rt_dev = tmp.rt_dev;
  636.     printk("Warning: obsolete routing request made.\n");
  637.     return 0;
  638. }
  639.  
  640. /*
  641.  *    Handle IP routing ioctl calls. These are used to manipulate the routing tables
  642.  */
  643.  
  644. int ip_rt_ioctl(unsigned int cmd, void *arg)
  645. {
  646.     int err;
  647.     struct rtentry rt;
  648.  
  649.     switch(cmd) 
  650.     {
  651.         case SIOCADDRTOLD:    /* Old style add route */
  652.         case SIOCDELRTOLD:    /* Old style delete route */
  653.             if (!suser())
  654.                 return -EPERM;
  655.             err = ip_get_old_rtent((struct old_rtentry *) arg, &rt);
  656.             if (err)
  657.                 return err;
  658.             return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
  659.  
  660.         case SIOCADDRT:        /* Add a route */
  661.         case SIOCDELRT:        /* Delete a route */
  662.             if (!suser())
  663.                 return -EPERM;
  664.             err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
  665.             if (err)
  666.                 return err;
  667.             memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
  668.             return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
  669.     }
  670.  
  671.     return -EINVAL;
  672. }
  673.