home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / network / src_1218.zip / RIP.C < prev    next >
C/C++ Source or Header  |  1991-04-23  |  17KB  |  676 lines

  1. /* This file contains code to implement the Routing Information Protocol (RIP)
  2.  * and is derived from 4.2BSD code. Mike Karels of Berkeley has stated on
  3.  * TCP-IP that the code may be freely used as long as UC Berkeley is
  4.  * credited. (Well, here's some credit :-). AGB 4-28-88
  5.  
  6.  * Further documentation on the RIP protocol is now available in Charles
  7.  * Hedrick's draft RFC, as yet unnumbered. AGB 5-6-88
  8.  *
  9.  * The RIP RFC has now been issued as RFC1058. AGB 7-23-88
  10.  *
  11.  * Code gutted and substantially rewritten. KA9Q 9/89
  12.  */
  13. #include "global.h"
  14. #include "mbuf.h"
  15. #include "netuser.h"
  16. #include "udp.h"
  17. #include "timer.h"
  18. #include "iface.h"
  19. #include "ip.h"
  20. #include "internet.h"
  21. #include "rip.h"
  22. #include "arp.h"
  23.  
  24. struct rip_stat Rip_stat;
  25. int16 Rip_trace;
  26. int Rip_merge;
  27. struct rip_list *Rip_list;
  28. struct udp_cb *Rip_cb;
  29.  
  30. struct rip_refuse *Rip_refuse;
  31.  
  32. static void rip_rx __ARGS((struct iface *iface,struct udp_cb *sock,int cnt));
  33. static void proc_rip __ARGS((struct iface *iface,int32 gateway,
  34.     struct rip_route *ep));
  35. static char *putheader __ARGS((char *cp,char command,char version));
  36. static char *putentry __ARGS((char *cp,int16 fam,int32 target,int32 metric));
  37. static void rip_shout __ARGS((void *p));
  38. static void send_routes __ARGS((int32 dest,int16 port,int split,int trig));
  39.  
  40. /* Send RIP CMD_RESPONSE packet(s) to the specified rip_list entry */
  41. static void
  42. rip_shout(p)
  43. void *p;
  44. {
  45.     register struct rip_list *rl;
  46.  
  47.     rl = (struct rip_list *)p;
  48.     stop_timer(&rl->rip_time);
  49.     send_routes(rl->dest,RIP_PORT,(rl->flags & RIP_SPLIT),0);
  50.     set_timer(&rl->rip_time,rl->interval*1000L);
  51.     start_timer(&rl->rip_time);
  52. }
  53.  
  54. /* Send the routing table. */
  55. static void
  56. send_routes(dest,port,split,trig)
  57. int32 dest;        /* IP destination address to send to */
  58. int16 port;
  59. int split;        /* Do split horizon? */
  60. int trig;        /* Send only triggered updates? */
  61. {
  62.     char *cp;
  63.     int i,bits,numroutes,maxroutes;
  64.     int16 pktsize;
  65.     struct mbuf *bp;
  66.     struct route *rp;
  67.     struct socket lsock,fsock;
  68.     struct iface *iface;
  69.  
  70.     if((rp = rt_lookup(dest)) == NULLROUTE)
  71.         return;    /* No route exists, can't do it */
  72.     iface = rp->iface;
  73.  
  74.     /* Compute maximum packet size and number of routes we can send */
  75.     pktsize = ip_mtu(dest) - IPLEN;
  76.     pktsize = min(pktsize,MAXRIPPACKET);
  77.     maxroutes = (pktsize - RIPHEADER) / RIPROUTE;
  78.  
  79.     lsock.address = INADDR_ANY;
  80.     lsock.port = RIP_PORT;
  81.     fsock.address = dest;
  82.     fsock.port = port;
  83.  
  84.     /* Allocate space for a full size RIP packet and generate header */
  85.     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  86.         return; 
  87.     numroutes = 0;
  88.     cp = putheader(bp->data,RIPCMD_RESPONSE,RIPVERSION);
  89.  
  90.     /* Emit default route, if appropriate */
  91.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)
  92.      && (!trig || (R_default.flags & RTTRIG))){
  93.         if(!split || iface != R_default.iface){
  94.              cp = putentry(cp,RIP_IPFAM,0,R_default.metric);
  95.             numroutes++;
  96.         } else if(trig){
  97.             cp = putentry(cp,RIP_IPFAM,0,RIP_INFINITY);
  98.             numroutes++;
  99.         }
  100.     }
  101.     for(bits=0;bits<32;bits++){
  102.         for(i=0;i<HASHMOD;i++){
  103.             for(rp = Routes[bits][i];rp != NULLROUTE;rp=rp->next){
  104.                 if((rp->flags & RTPRIVATE)
  105.                  || (trig && !(rp->flags & RTTRIG))) 
  106.                     continue;
  107.  
  108.                 if(numroutes >= maxroutes){
  109.                     /* Packet full, flush and make another */
  110.                     bp->cnt = RIPHEADER + numroutes * RIPROUTE;
  111.                     send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  112.                     Rip_stat.output++;
  113.                     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  114.                         return; 
  115.                     numroutes = 0;
  116.                     cp = putheader(bp->data,RIPCMD_RESPONSE,RIPVERSION);
  117.                 }
  118.                 if(!split || iface != rp->iface){
  119.                      cp = putentry(cp,RIP_IPFAM,rp->target,rp->metric);
  120.                     numroutes++;
  121.                 } else if(trig){
  122.                      cp = putentry(cp,RIP_IPFAM,rp->target,RIP_INFINITY);
  123.                     numroutes++;
  124.                 }
  125.             }
  126.         }
  127.     }
  128.     if(numroutes != 0){
  129.         bp->cnt = RIPHEADER + numroutes * RIPROUTE;
  130.         send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  131.         Rip_stat.output++;
  132.     } else {
  133.         free_p(bp);
  134.     }
  135. }
  136. /* Add an entry to the rip broadcast list */
  137. int
  138. rip_add(dest,interval,flags)
  139. int32 dest;
  140. int32 interval;
  141. char flags;
  142. {
  143.     register struct rip_list *rl;
  144.     struct route *rp;
  145.  
  146.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  147.         if(rl->dest == dest)
  148.             return 0;
  149.  
  150.     if((rp = rt_lookup(dest)) == NULLROUTE){
  151.         tprintf("%s is unreachable\n",inet_ntoa(dest));
  152.         return 1;
  153.     }
  154.     /* get a chunk of memory for the rip interface descriptor */
  155.     rl = (struct rip_list *)callocw(1,sizeof(struct rip_list));
  156.  
  157.     /* tack this record on as the first in the list */
  158.     rl->next = Rip_list;
  159.     if(rl->next != NULLRL)
  160.         rl->next->prev = rl;
  161.     Rip_list = rl;
  162.  
  163.     rl->dest = dest;
  164.  
  165.     /* and the interface ptr, tick interval and flags */
  166.     rl->iface = rp->iface;
  167.     rl->interval = interval;
  168.     rl->flags = flags;
  169.  
  170.     /* and set up the timer stuff */
  171.     set_timer(&rl->rip_time,interval*1000L);
  172.     rl->rip_time.func = rip_shout;
  173.     rl->rip_time.arg = rl;
  174.     start_timer(&rl->rip_time);
  175.     return 0;
  176. }
  177.  
  178. /* add a gateway to the rip_refuse list which allows us to ignore their
  179.  * advertisements
  180. */
  181. int
  182. riprefadd(gateway)
  183. int32 gateway;
  184. {
  185.     register struct rip_refuse *rl;
  186.  
  187.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  188.         if(rl->target == gateway)
  189.             return 0;    /* Already in table */
  190.   
  191.  
  192.     /* get a chunk of memory for the rip interface descriptor */
  193.     rl = (struct rip_refuse *)callocw(1,sizeof(struct rip_refuse));
  194.  
  195.     /* tack this record on as the first in the list */
  196.     rl->next = Rip_refuse;
  197.     if(rl->next != NULLREF)
  198.         rl->next->prev = rl;
  199.     Rip_refuse = rl;
  200.  
  201.     /* fill in the gateway to ignore */
  202.     rl->target = gateway;
  203.     return 0;
  204. }
  205.  
  206. /* drop a RIP target */
  207. int
  208. rip_drop(dest)
  209. int32    dest;
  210. {
  211.     register struct rip_list *rl;
  212.  
  213.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  214.         if(rl->dest == dest)
  215.             break;
  216.  
  217.     /* leave if we didn't find it */
  218.     if(rl == NULLRL)
  219.         return 0;
  220.  
  221.     /* stop the timer */
  222.     stop_timer(&rl->rip_time);
  223.  
  224.     /* Unlink from list */
  225.     if(rl->next != NULLRL)
  226.         rl->next->prev = rl->prev;
  227.     if(rl->prev != NULLRL)
  228.         rl->prev->next = rl->next;
  229.     else
  230.         Rip_list = rl->next;
  231.  
  232.     /* and deallocate the descriptor memory */
  233.     free((char *)rl);
  234.     return 0;
  235. }
  236.  
  237. /* drop a RIP-refuse target from the rip_refuse list */
  238. int
  239. riprefdrop(gateway)
  240. int32 gateway;
  241. {
  242.     register struct rip_refuse *rl;
  243.     
  244.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  245.         if(rl->target == gateway)
  246.             break;
  247.   
  248.     /* leave if we didn't find it */
  249.     if(rl == NULLREF)
  250.         return 0;
  251.  
  252.     /* Unlink from list */
  253.     if(rl->next != NULLREF)
  254.         rl->next->prev = rl->prev;
  255.     if(rl->prev != NULLREF)
  256.         rl->prev->next = rl->next;
  257.     else
  258.         Rip_refuse = rl->next;
  259.  
  260.     /* and deallocate the structure memory */
  261.     free((char *)rl);
  262.     return 0;
  263. }
  264.  
  265. /* function to output a RIP CMD_RESPONSE packet for the rip_trigger list */
  266. void
  267. rip_trigger()
  268. {
  269.     register struct rip_list *rl;
  270.     int bits,i;
  271.     struct route *rp;
  272.  
  273.     for(rl=Rip_list;rl != NULLRL;rl = rl->next){
  274.         send_routes(rl->dest,RIP_PORT,(rl->flags & RIP_SPLIT),1);
  275.     }
  276.     /* Clear the trigger list */
  277.     R_default.flags &= ~RTTRIG;
  278.     for(bits=0;bits<32;bits++){
  279.         for(i=0;i<HASHMOD;i++){
  280.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  281.                 rp->flags &= ~RTTRIG;
  282.             }
  283.         }
  284.     }
  285. }
  286.  
  287. /* Start RIP agent listening at local RIP UDP port */
  288. int
  289. rip_init()
  290. {
  291.     struct socket lsock;
  292.  
  293.     lsock.address = INADDR_ANY;
  294.     lsock.port = RIP_PORT;
  295.  
  296.     if(Rip_cb == NULLUDP)
  297.         Rip_cb = open_udp(&lsock,rip_rx);
  298.  
  299.     return 0;
  300. }
  301.  
  302. /* Process RIP input received from 'interface'. */
  303. static void
  304. rip_rx(iface,sock,cnt)
  305. struct iface *iface;
  306. struct udp_cb *sock;
  307. int cnt;
  308. {
  309.     struct mbuf *bp;
  310.     struct socket fsock;
  311.     int cmd;
  312.     register struct rip_refuse *rfl;
  313.     struct rip_route entry;
  314.     struct route *rp;
  315.  
  316.     /* receive the RIP packet */
  317.     recv_udp(sock,&fsock,&bp);
  318.  
  319.     /* increment the rcvd cnt */
  320.     Rip_stat.rcvd++;
  321.  
  322.     /* check the gateway of this packet against the rip_refuse list and
  323.      * discard it if a match is found
  324.      */
  325.     for(rfl=Rip_refuse;rfl != NULLREF;rfl = rfl->next){
  326.         if(fsock.address == rfl->target){
  327.             Rip_stat.refusals++;
  328.             if(Rip_trace > 1)
  329.                 printf("RIP refused from %s\n",
  330.                  inet_ntoa(fsock.address));
  331.             free_p(bp);
  332.             return;
  333.          }
  334.     }
  335.     cmd = PULLCHAR(&bp);
  336.     /* Check the version of the frame */
  337.     if(PULLCHAR(&bp) != RIPVERSION){
  338.         free_p(bp);
  339.         Rip_stat.version++;
  340.         return;
  341.     }
  342.     switch(cmd){
  343.     case RIPCMD_RESPONSE:
  344.         if(Rip_trace > 1)
  345.             printf("RIPCMD_RESPONSE from %s \n",inet_ntoa(fsock.address));
  346.  
  347.         Rip_stat.response++;
  348.         (void)pull16(&bp);    /* remove one word of padding */
  349.         while(len_p(bp) >= RIPROUTE){
  350.             pullentry(&entry,&bp);
  351.             proc_rip(iface,fsock.address,&entry);
  352.         }
  353.         /* If we can't reach the sender of this update, or if
  354.          * our existing route is not through the interface we
  355.          * got this update on, add him as a host specific entry
  356.          */
  357.         if((rp = rt_blookup(fsock.address,32)) != NULLROUTE){
  358.             /* Host-specific route already exists, refresh it */
  359.             start_timer(&rp->timer);
  360.         } else if((rp = rt_lookup(fsock.address)) == NULLROUTE
  361.          || rp->iface != iface){
  362.             entry.addr_fam = RIP_IPFAM;
  363.             entry.target = fsock.address;
  364.             entry.metric = 0; /* will get incremented to 1 */
  365.             proc_rip(iface,fsock.address,&entry);
  366.         }
  367.         if(Rip_merge)
  368.             rt_merge(Rip_trace);
  369.         rip_trigger();
  370.         break;
  371.     case RIPCMD_REQUEST:
  372.         if(Rip_trace > 1)
  373.             printf("RIPCMD_REQUEST\n");
  374.  
  375.         Rip_stat.request++;
  376.         /* For now, just send the whole table with split horizon
  377.          * enabled when the source port is RIP_PORT, and send
  378.          * the whole table with split horizon disable when another
  379.          * source port is used. This should be replaced with a more
  380.          * complete implementation that checks for non-global requests
  381.          */
  382.         if(fsock.port == RIP_PORT)
  383.             send_routes(fsock.address,fsock.port,1,0);
  384.         else
  385.             send_routes(fsock.address,fsock.port,0,0);
  386.         break;
  387.     default:
  388.         if(Rip_trace > 1)
  389.             printf("RIPCMD: Unknown Type\n");
  390.  
  391.         Rip_stat.unknown++;
  392.         break;
  393.     } /* switch */
  394.     free_p(bp);
  395. }
  396. /* Apply a set of heuristics for determining the number of significant bits
  397.  * (i.e., the address mask) in the target address. Needed since RIP doesn't
  398.  * include the address mask for each entry.
  399.  */
  400. int
  401. nbits(target)
  402. int32 target;
  403. {
  404.     int bits;
  405.  
  406.     if(target == 0)
  407.         return 0;    /* Special case: 0.0.0.0 is the default route */
  408.  
  409.     /* Check the host-part bytes of
  410.      * the address to check for byte-wide zeros
  411.      * which we'll consider to be subnet routes.
  412.      * e.g.    44.80.0.0 will be considered to be equal to 44.80/16
  413.      * whereas 44.80.1.0 will be considered to be 44.80.1/24
  414.      */
  415.     switch (hibyte(hiword(target)) >> 6) {
  416.     case 3:    /* Class C address */
  417.         /*is it a host address ? i.e. are there any 1's in the
  418.          * host part ?
  419.          */
  420.         if(target & 0xff)
  421.             bits = 32;
  422.         else
  423.             bits = 24;
  424.         break;
  425.     case 2:  /* Class B address */
  426.         if(target & 0xff)
  427.             bits = 32;
  428.         else if(target & 0xff00)
  429.             bits = 24;
  430.         else
  431.             bits = 16;
  432.         break;
  433.         case 0:      /* Class A address */
  434.         case 1:
  435.         if(target & 0xff)
  436.             bits = 32;
  437.         else if(target & 0xff00)
  438.             bits = 24;
  439.         else if(target & 0xff0000)
  440.             bits = 16;
  441.         else
  442.             bits = 8;
  443.     }
  444.  
  445.     return bits;
  446. }
  447. /* Remove and process a RIP response entry from a packet */
  448. static void
  449. proc_rip(iface,gateway,ep)
  450. struct iface *iface;
  451. int32 gateway;
  452. register struct rip_route *ep;
  453. {
  454.     int32 interval;
  455.     unsigned int bits;
  456.     register struct route *rp;
  457.     struct rip_list *rl;
  458.     int add = 0;    /* action flags */
  459.     int drop = 0;
  460.     int trigger = 0;
  461.  
  462.     if(ep->addr_fam != RIP_IPFAM) {
  463.         /* Skip non-IP addresses */
  464.         if(Rip_trace > 1)
  465.             printf("RIP_rx: Not an IP RIP packet !\n");
  466.         Rip_stat.addr_family++;
  467.         return;
  468.     }
  469.     /* Guess at the mask, since it's not explicit */
  470.     bits = nbits(ep->target);
  471.  
  472.     /* Don't ever add a route to myself through somebody! */
  473.     if(bits == 32 && ismyaddr(ep->target) != NULLIF){
  474.         if(Rip_trace > 1){
  475.             printf("route to self: %s %ld\n",
  476.              inet_ntoa(ep->target),ep->metric);
  477.         }
  478.         return;
  479.     }
  480.     /* Update metric to reflect link cost */
  481.     ep->metric++;
  482.     ep->metric = min(ep->metric,RIP_INFINITY);
  483.  
  484.     /* Find existing entry, if any */
  485.     rp = rt_blookup(ep->target,bits);
  486.  
  487.     /* Don't touch private routes */
  488.     if(rp != NULLROUTE && (rp->flags & RTPRIVATE))
  489.         return;
  490.  
  491.     if(rp == NULLROUTE){
  492.         if(ep->metric < RIP_INFINITY){
  493.             /* New route; add it and trigger an update */
  494.             add++;
  495.             trigger++;
  496.         }
  497.     } else if(rp->metric == RIP_INFINITY){
  498.         /* Route is in hold-down; ignore this guy */
  499.         if(Rip_trace > 0){
  500.             printf("ignored (hold-down): %s %lu\n",
  501.              inet_ntoa(ep->target),ep->metric);
  502.         }
  503.     } else if(rp->gateway == gateway && rp->iface == iface){
  504.         /* This is the gateway for the entry we already have;
  505.          * restart the timer
  506.          */
  507.         start_timer(&rp->timer);
  508.         if(rp->metric != ep->metric){
  509.             /* Metric has changed. Update it and trigger an
  510.              * update. If route has become unavailable, start
  511.              * the hold-down timeout.
  512.              */
  513.             if(Rip_trace){
  514.                 printf("metric change: %s %lu -> %lu\n",
  515.                  inet_ntoa(ep->target),rp->metric,ep->metric);
  516.             }
  517.             if(ep->metric == RIP_INFINITY)
  518.                 rt_timeout(rp);    /* Enter hold-down timeout */
  519.             else
  520.                 rp->metric = ep->metric;
  521.             trigger++;
  522.         }
  523.     } else {
  524.         /* Entry is from a different gateway than the current route */
  525.         if(ep->metric < rp->metric){
  526.             /* Switch to a new gateway */
  527.             if(Rip_trace > 0){
  528.                 printf("metric better: %s %lu\n",
  529.                  inet_ntoa(ep->target),ep->metric);
  530.             }
  531.             drop++;
  532.             add++;
  533.             trigger++;
  534.         } else {
  535.             /* Metric is no better, stay with current route */
  536.             if(Rip_trace > 1){
  537.                 printf("metric not better: %s %lu\n",
  538.                  inet_ntoa(ep->target),ep->metric);
  539.             }
  540.         }
  541.     }
  542.     if(drop){
  543.         /* Switching to a better gateway; delete old entry */
  544.         if(Rip_trace){
  545.             printf("route drop [%s]/%u",
  546.              inet_ntoa(ep->target),bits);
  547.             if(rp != NULLROUTE)
  548.                 printf(" %s %s %lu",rp->iface->name,
  549.                  inet_ntoa(rp->gateway),rp->metric);
  550.             printf("\n");
  551.         }
  552.         rt_drop(ep->target,bits);
  553.     }
  554.     if(add){
  555.         /* Add a new entry */
  556.         interval = RIP_TTL;
  557.         for(rl=Rip_list; rl != NULLRL; rl = rl->next){
  558.             if(rl->iface == iface){
  559.                 interval = rl->interval * 4;
  560.                 break;
  561.             }
  562.         }
  563.         if(Rip_trace > 0){
  564.             printf("route add [%s]/%u %s",inet_ntoa(ep->target),
  565.              bits,iface->name);
  566.             printf(" [%s] %u\n",inet_ntoa(gateway),
  567.              (int)ep->metric);
  568.         }
  569.         rp = rt_add(ep->target,(unsigned) bits,gateway,iface,
  570.          (int) ep->metric,interval,0);
  571.     }
  572.     /* If the route changed, mark it for a triggered update */
  573.     if(trigger){
  574.         rp->flags |= RTTRIG;
  575.     }
  576. }
  577. /* Send a RIP request packet to the specified destination */
  578. int
  579. ripreq(dest,replyport)
  580. int32 dest;
  581. int16 replyport;
  582. {
  583.     struct mbuf *bp;
  584.     struct socket lsock,fsock;
  585.     char *cp;
  586.  
  587.     lsock.address = INADDR_ANY;
  588.     lsock.port = replyport;
  589.  
  590.     /* if we were given a valid dest addr, ask it (the routers on that net)
  591.      * for a default gateway
  592.      */
  593.     if(dest == 0)
  594.         return 0;
  595.  
  596.     fsock.address = dest;
  597.     fsock.port = RIP_PORT;
  598.  
  599.     /* Send out one RIP Request packet as a broadcast to 'dest'  */
  600.     if((bp = alloc_mbuf(RIPHEADER + RIPROUTE)) == NULLBUF)
  601.         return -1;
  602.  
  603.     cp = putheader(bp->data,RIPCMD_REQUEST,RIPVERSION);
  604.     cp = putentry(cp,0,0L,RIP_INFINITY);
  605.     bp->cnt = RIPHEADER + RIPROUTE;
  606.     send_udp(&lsock, &fsock,0,0,bp,bp->cnt,0,0);
  607.     Rip_stat.output++;
  608.     return 0;
  609. }
  610. void
  611. pullentry(ep,bpp)
  612. register struct rip_route *ep;
  613. struct mbuf **bpp;
  614. {
  615.     ep->addr_fam = pull16(bpp);
  616.     (void)pull16(bpp);
  617.     ep->target = pull32(bpp);
  618.     (void)pull32(bpp);
  619.     (void)pull32(bpp);
  620.     ep->metric = pull32(bpp);
  621. }
  622.  
  623. /* Write the header of a RIP packet */
  624. static char *
  625. putheader(cp,command,version)
  626. register char *cp;
  627. char command;
  628. char version;
  629. {
  630.     *cp++ = command;
  631.     *cp++ = version;
  632.     return put16(cp,0);
  633. }
  634.  
  635. /* Write a single entry into a rip packet */
  636. static char *
  637. putentry(cp,fam,target,metric)
  638. register char *cp;
  639. int16 fam;
  640. int32 target;
  641. int32 metric;
  642. {
  643.     cp = put16(cp,fam);
  644.     cp = put16(cp,0);
  645.     cp = put32(cp,target);
  646.     cp = put32(cp,0L);
  647.     cp = put32(cp,0L);
  648.     return put32(cp,metric);
  649. }
  650. /* Route timeout handler. If route has already been marked for deletion
  651.  * then delete it. Otherwise mark for deletion and restart timer.
  652.  */
  653. void
  654. rt_timeout(s)
  655. void *s;
  656. {
  657.     register struct route *rp = (struct route *)s;
  658.  
  659.     stop_timer(&rp->timer);
  660.     if(rp->metric < RIP_INFINITY){
  661.         rp->metric = RIP_INFINITY;
  662.         if(dur_timer(&rp->timer) == 0)
  663.             set_timer(&rp->timer,RIP_TTL*1000L);
  664.         /* wait 2/3 of timeout before garbage collect */
  665.         set_timer(&rp->timer,dur_timer(&rp->timer)*2/3);
  666.         rp->timer.func = (void *)rt_timeout;
  667.         rp->timer.arg = (void *)rp;
  668.         start_timer(&rp->timer);
  669.         /* Route changed; mark it for triggered update */
  670.         rp->flags |= RTTRIG;
  671.         rip_trigger();
  672.     } else {
  673.         rt_drop(rp->target,rp->bits);
  674.     }
  675. }
  676.