home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / RIP.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  37KB  |  1,156 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.  * Mods by PA0GRI
  14.  *
  15.  *  Changes Copyright (c) 1993 Jeff White - N0POY, All Rights Reserved.
  16.  *  Permission granted for non-commercial copying and use, provided
  17.  *  this notice is retained.
  18.  *
  19.  * Rehack for RIP-2 (RFC1388) by N0POY 4/1993
  20.  *  Modules needed for changes:  rip.c, rip.h, ripcmd.c, ripdump.c, ip.h
  21.  *                               commands.h, iface.h, iface.c, version.c
  22.  *
  23.  * Beta release 11/16/93 V0.95
  24.  *
  25.  * Bug fix that prevented split horizon routing to work fixed.
  26.  * 2/19/94 release V1.0
  27.  *
  28.  */
  29.   
  30. #include <stdarg.h>
  31. #include <ctype.h>
  32. #include <time.h>
  33. #include "global.h"
  34. #ifdef RIP
  35. #include "mbuf.h"
  36. #include "netuser.h"
  37. #include "udp.h"
  38. #include "timer.h"
  39. #include "iface.h"
  40. #include "ip.h"
  41. #include "internet.h"
  42. #include "rip.h"
  43. #include "arp.h"
  44. #include "socket.h"
  45.   
  46. struct rip_stat Rip_stat;
  47. int16 Rip_trace;
  48. FILE *Rip_trace_file = NULLFILE;
  49. char *Rip_trace_fname = NULLCHAR;
  50. int16 Rip_merge;
  51. int32 Rip_ttl = RIP_TTL;
  52. int16 Rip_ver_refuse = 0;
  53. int16 Rip_default_refuse = FALSE;
  54. struct rip_list *Rip_list;
  55. struct udp_cb *Rip_cb;
  56. struct rip_auth *Rip_auth;
  57. struct rip_refuse *Rip_refuse;
  58. char Rip_nullpass[RIP_AUTH_SIZE];
  59.   
  60. static void rip_rx __ARGS((struct iface *iface,struct udp_cb *sock,int cnt));
  61. static void proc_rip __ARGS((struct iface *iface,int32 gateway,
  62. struct rip_route *ep,unsigned char version));
  63. static char *putheader __ARGS((char *cp,char command,char version,int16 domain));
  64. static char *putentry __ARGS((char *cp,int16 fam,int16 tag,int32 target,
  65. int32 targmask,int32 router,int32 metric));
  66. static void send_routes __ARGS((int32 dest,int16 port,int trig,
  67. int flags,char version, struct rip_list *rdata));
  68. static void pullauthentication __ARGS((struct rip_authenticate *ep, struct mbuf **bpp));
  69. static void pullheader __ARGS((struct rip_head *ep, struct mbuf **bpp));
  70. static int check_authentication __ARGS((struct rip_auth *auth,
  71. struct mbuf **bpp, struct rip_head *header, int32 srcaddr, char *ifcname,
  72. struct rip_authenticate *entry));
  73. static char *putauth  __ARGS((char *cp, int16 authtype,
  74. char *authpass));
  75. static void rip_trace(short level, char *errstr, ...);
  76.   
  77. /* Send RIP CMD_RESPONSE packet(s) to the specified rip_list entry */
  78.   
  79. void
  80. rip_shout(p)
  81. void *p;
  82. {
  83.     register struct rip_list *rl;
  84.   
  85.     rl = (struct rip_list *)p;
  86.     stop_timer(&rl->rip_time);
  87.     send_routes(rl->dest,RIP_PORT,0,rl->flags,rl->rip_version,rl);
  88.     set_timer(&rl->rip_time,rl->interval*1000L);
  89.     start_timer(&rl->rip_time);
  90. }
  91.   
  92. /* Send the routing table. */
  93. static void
  94. send_routes(dest,port,trig,flags,version,rdata)
  95. int32 dest;                   /* IP destination address to send to */
  96. int16 port;
  97. int trig;                     /* Send only triggered updates? */
  98. int flags;
  99. char version;                 /* Version of RIP packet */
  100. struct rip_list *rdata;       /* Used for RIP-2 packets */
  101. {
  102.     char *cp;
  103.     int i,bits,numroutes,maxroutes;
  104.     int16 pktsize;
  105.     struct mbuf *bp;
  106.     struct route *rp;
  107.     struct socket lsock,fsock;
  108.     struct iface *iface;
  109.   
  110.     if((rp = rt_lookup(dest)) == NULLROUTE) {
  111.         rip_trace(1, "No route to [%s] exists, cannot send", inet_ntoa(dest));
  112.         return;                 /* No route exists, can't do it */
  113.     }
  114.     iface = rp->iface;
  115.   
  116.    /* Compute maximum packet size and number of routes we can send */
  117.     pktsize = ip_mtu(dest) - IPLEN;
  118.     pktsize = min(pktsize,RIP_PKTSIZE);
  119.     maxroutes = (pktsize - RIP_HEADER) / RIP_ENTRY;
  120.   
  121.     lsock.address = INADDR_ANY;
  122.     lsock.port = RIP_PORT;
  123.     fsock.address = dest;
  124.     fsock.port = port;
  125.   
  126.    /* Allocate space for a full size RIP packet and generate header */
  127.     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  128.         return;
  129.     numroutes = 0;
  130.   
  131.    /* See if we know information about what to send out */
  132.   
  133.     if ((version >= RIP_VERSION_2) && (rdata != NULLRL)) {
  134.         cp = putheader(bp->data,RIPCMD_RESPONSE, version, rdata->domain);
  135.       /* See if we need to put an authentication header on */
  136.         if (flags & RIP_AUTHENTICATE) {
  137.             cp = putauth(cp, RIP_AUTH_SIMPLE, rdata->rip_auth_code);
  138.             numroutes++;
  139.         }
  140.     } else {
  141.         cp = putheader(bp->data,RIPCMD_RESPONSE, version, 0);
  142.     }
  143.   
  144.    /* Emit route to ourselves, if requested */
  145.     if(flags & RIP_US) {
  146.         if (version == RIP_VERSION_1)
  147.             cp = putentry(cp,RIP_AF_INET,0,iface->addr,0,0,1);
  148.         else
  149.             cp = putentry(cp,RIP_AF_INET,0,iface->addr,0xFFFFFFFFL,0,1);
  150.         numroutes++;
  151.     }
  152.   
  153.    /* Emit default route, if appropriate */
  154.   
  155.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)
  156.     && (!trig || (R_default.flags & RTTRIG))){
  157.         if(!(flags & RIP_SPLIT) || iface != R_default.iface){
  158.             if (version == RIP_VERSION_1)
  159.                 cp = putentry(cp,RIP_AF_INET,0,0,0,0,R_default.metric);
  160.             else
  161.                 cp = putentry(cp,RIP_AF_INET,R_default.route_tag,0,0,0,R_default.metric);
  162.             numroutes++;
  163.         } else if (trig && (flags & RIP_POISON)) {
  164.          /* Poisoned reverse */
  165.             if (version == RIP_VERSION_1)
  166.                 cp = putentry(cp,RIP_AF_INET,0,0,0,0,RIP_METRIC_UNREACHABLE);
  167.             else
  168.                 cp = putentry(cp,RIP_AF_INET,R_default.route_tag,0,0,0,
  169.                 RIP_METRIC_UNREACHABLE);
  170.             numroutes++;
  171.         }
  172.     }
  173.   
  174.     for(bits=0;bits<32;bits++){
  175.         for(i=0;i<HASHMOD;i++){
  176.             for(rp = Routes[bits][i];rp != NULLROUTE;rp=rp->next){
  177.                 if((rp->flags & RTPRIVATE)
  178.                     || (trig && !(rp->flags & RTTRIG)))
  179.                     continue;
  180.   
  181.                 if(numroutes >= maxroutes){
  182.                /* Packet full, flush and make another */
  183.                     bp->cnt = RIP_HEADER + numroutes * RIP_ENTRY;
  184.                     send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  185.                     Rip_stat.vdata[version].output++;
  186.                     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  187.                         return;
  188.                     numroutes = 0;
  189.   
  190.                     if (version >= RIP_VERSION_2 && rdata != NULLRL) {
  191.                         cp = putheader(bp->data,RIPCMD_RESPONSE, version,
  192.                         rdata->domain);
  193.                   /* See if we need to put an authentication header on */
  194.                         if (flags & RIP_AUTHENTICATE) {
  195.                             cp = putauth(cp, RIP_AUTH_SIMPLE, rdata->rip_auth_code);
  196.                             numroutes++;
  197.                         }
  198.                     } else {
  199.                         cp = putheader(bp->data,RIPCMD_RESPONSE, version, 0);
  200.                     }
  201.                 }
  202.   
  203.                 if(!(flags & RIP_SPLIT) || iface != rp->iface){
  204.                     if (version == RIP_VERSION_1)
  205.                         cp = putentry(cp,RIP_AF_INET,0,rp->target,0,0,rp->metric);
  206.                     else
  207.                         cp = putentry(cp,RIP_AF_INET,rp->route_tag,rp->target,
  208.                         (0xFFFFFFFFL << (32 - rp->bits)),rdata?rdata->proxy_route:0,
  209.                         rp->metric);
  210.                     numroutes++;
  211.                 } else if(trig && (flags & RIP_POISON)) {
  212.                     if (version == RIP_VERSION_1)
  213.                         cp = putentry(cp,RIP_AF_INET,0,rp->target,0,0,RIP_METRIC_UNREACHABLE);
  214.                     else
  215.                         cp = putentry(cp,RIP_AF_INET,rp->route_tag,rp->target,
  216.                         (0xFFFFFFFFL << (32 - rp->bits)),rdata?rdata->proxy_route:0,
  217.                         RIP_METRIC_UNREACHABLE);
  218.                     numroutes++;
  219.                 }
  220.             }
  221.         }
  222.     }
  223.     if(numroutes != 0){
  224.         bp->cnt = RIP_HEADER + numroutes * RIP_ENTRY;
  225.         send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  226.         Rip_stat.vdata[version].output++;
  227.     } else {
  228.         free_p(bp);
  229.     }
  230. }
  231.   
  232. /* Add an entry to the rip broadcast list */
  233.   
  234. int
  235. rip_add(dest,interval,flags,version,authpass,domain,route_tag,proxy)
  236. int32 dest;
  237. int32 interval;
  238. char flags;
  239. char version;
  240. char authpass[RIP_AUTH_SIZE];
  241. int16 domain;
  242. int16 route_tag;
  243. int32 proxy;
  244. {
  245.     register struct rip_list *rl;
  246.     struct route *rp;
  247.   
  248.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  249.         if((rl->dest == dest) && (rl->domain == domain))
  250.             return 0;
  251.   
  252.     if((rp = rt_lookup(dest)) == NULLROUTE){
  253.         tprintf("%s is unreachable\n",inet_ntoa(dest));
  254.         return 0;
  255.     }
  256.   
  257.    /* get a chunk of memory for the rip interface descriptor */
  258.     rl = (struct rip_list *)callocw(1,sizeof(struct rip_list));
  259.   
  260.    /* tack this record on as the first in the list */
  261.     rl->next = Rip_list;
  262.     if(rl->next != NULLRL)
  263.         rl->next->prev = rl;
  264.     Rip_list = rl;
  265.   
  266.     rl->dest = dest;
  267.   
  268.     rip_trace(9, "Rip added V%d Flags %d Tag %d Proxy %s Domain %d Auth %s Interval %d",
  269.     version, flags, route_tag, inet_ntoa(proxy), domain, authpass, interval);
  270.   
  271.    /* and the interface ptr, tick interval and flags */
  272.     rl->iface = rp->iface;
  273.     rl->rip_version = version;
  274.     rl->interval = interval;
  275.     rl->flags = flags;
  276.     rl->proxy_route = proxy;
  277.     rl->route_tag = route_tag;
  278.     rl->domain = domain;
  279.     memcpy(rl->rip_auth_code,authpass,RIP_AUTH_SIZE);
  280.   
  281.    /* and set up the timer stuff */
  282.     set_timer(&rl->rip_time,interval*1000L);
  283.     rl->rip_time.func = rip_shout;
  284.     rl->rip_time.arg = rl;
  285.     start_timer(&rl->rip_time);
  286.     return 1;
  287. }
  288.   
  289. /* add a gateway to the rip_refuse list which allows us to ignore their
  290.  * advertisements
  291.  */
  292.   
  293. int
  294. riprefadd(gateway)
  295. int32 gateway;
  296. {
  297.     register struct rip_refuse *rl;
  298.   
  299.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  300.         if(rl->target == gateway)
  301.             return 0;         /* Already in table */
  302.   
  303.    /* get a chunk of memory for the rip interface descriptor */
  304.     rl = (struct rip_refuse *)callocw(1,sizeof(struct rip_refuse));
  305.   
  306.    /* tack this record on as the first in the list */
  307.     rl->next = Rip_refuse;
  308.     if(rl->next != NULLREF)
  309.         rl->next->prev = rl;
  310.     Rip_refuse = rl;
  311.   
  312.    /* fill in the gateway to ignore */
  313.     rl->target = gateway;
  314.     return 0;
  315. }
  316.   
  317. /* Add an authentication type to an interface name */
  318.   
  319. int
  320. ripauthadd(ifcname, domain, password)
  321. char *ifcname;
  322. int16 domain;
  323. char *password;
  324. {
  325.     register struct rip_auth *ra;
  326.     char *name;
  327.     int x;
  328.   
  329.     for(ra = Rip_auth; ra != NULLAUTH; ra = ra->next)
  330.         if(!strcmp(ifcname,ra->ifc_name) && (ra->domain == domain))
  331.             return 1;         /* Already in table */
  332.   
  333.    /* get a chunk of memory for the rip interface descriptor */
  334.     ra = (struct rip_auth *)callocw(1,sizeof(struct rip_auth));
  335.   
  336.    /* tack this record on as the first in the list */
  337.     ra->next = Rip_auth;
  338.     if(ra->next != NULLAUTH)
  339.         ra->next->prev = ra;
  340.     Rip_auth = ra;
  341.   
  342.    /* fill in the data */
  343.     ra->ifc_name = mallocw(strlen(ifcname)+1);
  344.     strcpy(ra->ifc_name, ifcname);
  345.     ra->domain = domain;
  346.     for (x = 0; x < RIP_AUTH_SIZE+1; x++)
  347.         ra->rip_auth_code[x] = '\0';
  348.     strcpy(ra->rip_auth_code, password);
  349.     return 0;
  350. }
  351.   
  352. /* Drop an authentication to an interface name */
  353.   
  354. int
  355. ripauthdrop(ifcname, domain)
  356. char *ifcname;
  357. int16 domain;
  358. {
  359.     register struct rip_auth *ra;
  360.     char *name;
  361.   
  362.     for(ra = Rip_auth; ra != NULLAUTH; ra = ra->next)
  363.         if(!strcmp(ifcname,ra->ifc_name) && (ra->domain == domain))
  364.             break;
  365.   
  366.    /* leave if we didn't find it */
  367.     if(ra == NULLAUTH)
  368.         return 0;
  369.   
  370.    /* Unlink from list */
  371.     if(ra->next != NULLAUTH)
  372.         ra->next->prev = ra->prev;
  373.     if(ra->prev != NULLAUTH)
  374.         ra->prev->next = ra->next;
  375.     else
  376.         Rip_auth = ra->next;
  377.   
  378.     free((char *)ra->ifc_name);
  379.     free((char *)ra);
  380.     return 0;
  381. }
  382.   
  383. /* drop a RIP target */
  384.   
  385. int
  386. rip_drop(dest,domain)
  387. int32   dest;
  388. int16 domain;
  389. {
  390.     register struct rip_list *rl;
  391.   
  392.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  393.         if((rl->dest == dest) && (rl->domain == domain))
  394.             break;
  395.   
  396.    /* leave if we didn't find it */
  397.     if(rl == NULLRL)
  398.         return 0;
  399.   
  400.    /* stop the timer */
  401.     stop_timer(&rl->rip_time);
  402.   
  403.    /* Unlink from list */
  404.     if(rl->next != NULLRL)
  405.         rl->next->prev = rl->prev;
  406.     if(rl->prev != NULLRL)
  407.         rl->prev->next = rl->next;
  408.     else
  409.         Rip_list = rl->next;
  410.   
  411.    /* and deallocate the descriptor memory */
  412.     free((char *)rl);
  413.     return 0;
  414. }
  415.   
  416. /* drop a RIP-refuse target from the rip_refuse list */
  417.   
  418. int
  419. riprefdrop(gateway)
  420. int32 gateway;
  421. {
  422.     register struct rip_refuse *rl;
  423.   
  424.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  425.         if(rl->target == gateway)
  426.             break;
  427.   
  428.    /* leave if we didn't find it */
  429.     if(rl == NULLREF)
  430.         return 0;
  431.   
  432.    /* Unlink from list */
  433.     if(rl->next != NULLREF)
  434.         rl->next->prev = rl->prev;
  435.     if(rl->prev != NULLREF)
  436.         rl->prev->next = rl->next;
  437.     else
  438.         Rip_refuse = rl->next;
  439.   
  440.    /* and deallocate the structure memory */
  441.     free((char *)rl);
  442.     return 0;
  443. }
  444.   
  445. /* function to output a RIP CMD_RESPONSE packet for the rip_trigger list */
  446.   
  447. void
  448. rip_trigger()
  449. {
  450.     register struct rip_list *rl;
  451.     int bits,i;
  452.     struct route *rp;
  453.   
  454.     for(rl=Rip_list;rl != NULLRL;rl = rl->next){
  455.         send_routes(rl->dest,RIP_PORT,1,rl->flags,rl->rip_version,rl);
  456.     }
  457.    /* Clear the trigger list */
  458.     R_default.flags &= ~RTTRIG;
  459.     for(bits=0;bits<32;bits++){
  460.         for(i=0;i<HASHMOD;i++){
  461.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  462.                 rp->flags &= ~RTTRIG;
  463.             }
  464.         }
  465.     }
  466. }
  467.   
  468. /* Start RIP agent listening at local RIP UDP port */
  469. int
  470. rip_init()
  471. {
  472.     struct socket lsock;
  473.     int x;
  474.   
  475.     lsock.address = INADDR_ANY;
  476.     lsock.port = RIP_PORT;
  477.   
  478.     if(Rip_cb == NULLUDP)
  479.         Rip_cb = open_udp(&lsock,rip_rx);
  480.   
  481.     for (x = 0; x < RIP_AUTH_SIZE; x++)
  482.         Rip_nullpass[x] = 0;
  483.   
  484.     Rip_trace = 0;
  485.   
  486.    /* Add the 0 domain with no password */
  487.   
  488.     ripauthadd(DEFAULTIFC, 0, RIP_NO_AUTH);
  489.   
  490.     return 0;
  491. }
  492.   
  493. /* Process RIP input received from 'interface'. */
  494. static void
  495. rip_rx(iface,sock,cnt)
  496. struct iface *iface;
  497. struct udp_cb *sock;
  498. int cnt;
  499. {
  500.     struct mbuf *bp;
  501.     struct socket fsock;
  502.     struct rip_refuse *rfl;
  503.     struct rip_route entry;
  504.     struct rip_head header;
  505.     struct route *rp;
  506.     struct rip_list *rl;
  507.   
  508.    /* receive the RIP packet */
  509.     recv_udp(sock,&fsock,&bp);
  510.   
  511.    /* check the gateway of this packet against the rip_refuse list and
  512.     * discard it if a match is found
  513.     */
  514.   
  515.     for(rfl=Rip_refuse;rfl != NULLREF;rfl = rfl->next){
  516.         if(fsock.address == rfl->target){
  517.             Rip_stat.refusals++;
  518.             rip_trace(2, "RIP refused from %s",inet_ntoa(fsock.address));
  519.             free_p(bp);
  520.             return;
  521.         }
  522.     }
  523.   
  524.     pullheader(&header, &bp);
  525.   
  526.    /* increment the rcvd cnt */
  527.     Rip_stat.vdata[header.rip_vers].rcvd++;
  528.   
  529.    /* Check to see if we'll accept this version on this interface */
  530.   
  531.     if (header.rip_vers <= Rip_ver_refuse) {
  532.         rip_trace(3, "RIP version %d refused from [%s]", header.rip_vers,
  533.         inet_ntoa(fsock.address));
  534.         Rip_stat.refusals++;
  535.         free_p(bp);
  536.         return;
  537.     }
  538.   
  539.     /* Check the version of the frame */
  540.     switch (header.rip_vers) {
  541.         case RIP_VERSION_2 :
  542.             break;
  543.   
  544.         case RIP_VERSION_0 :
  545.             rip_trace(1, "RIP Version 0 refused from [%s]", inet_ntoa(fsock.address));
  546.             Rip_stat.version++;
  547.             free_p(bp);
  548.             return;
  549.   
  550.         case RIP_VERSION_1 :
  551.          /* Toss RIP if header is bogus for V1 */
  552.             if (header.rip_domain != 0) {
  553.                 rip_trace(1, "RIP-1 bogus header, data in null fields from [%s]",
  554.                 inet_ntoa(fsock.address));
  555.                 Rip_stat.vdata[RIP_VERSION_1].unknown++;
  556.                 free_p(bp);
  557.                 return;
  558.             }
  559.             break;
  560.     }
  561.   
  562.     rip_trace(2, "RIP Packet version %d processing",header.rip_vers);
  563.   
  564.     switch(header.rip_cmd){
  565.         case RIPCMD_RESPONSE:
  566.             rip_trace(2, "RIPCMD_RESPONSE from [%s] domain %d",inet_ntoa(fsock.address),
  567.             header.rip_domain);
  568.   
  569.             Rip_stat.vdata[header.rip_vers].response++;
  570.             pullentry(&entry,&bp);
  571.   
  572.             if (header.rip_vers >= RIP_VERSION_2) {
  573.          /* We still have the authentication entry from above */
  574.   
  575.                 if (!check_authentication(Rip_auth, &bp, &header,fsock.address,
  576.                 iface->name, (struct rip_authenticate *)&entry)) {
  577.                     free_p(bp);
  578.                     return;
  579.                 }
  580.             }
  581.             proc_rip(iface,fsock.address,&entry,header.rip_vers);
  582.   
  583.             while(len_p(bp) >= RIP_ENTRY){
  584.                 pullentry(&entry,&bp);
  585.                 proc_rip(iface,fsock.address,&entry,header.rip_vers);
  586.             }
  587.   
  588.         /* If we can't reach the sender of this update, or if
  589.          * our existing route is not through the interface we
  590.          * got this update on, add him as a host specific entry
  591.          */
  592.             if((rp = rt_blookup(fsock.address,32)) != NULLROUTE){
  593.             /* Host-specific route already exists, refresh it */
  594.                 start_timer(&rp->timer);
  595.             } else if((rp = rt_lookup(fsock.address)) == NULLROUTE
  596.             || rp->iface != iface) {
  597.                 entry.rip_family = RIP_AF_INET;
  598.                 entry.rip_tag = 0;
  599.                 entry.rip_dest = fsock.address;
  600.                 if (header.rip_vers > RIP_VERSION_1)
  601.                     entry.rip_dest_mask = 32;
  602.                 else
  603.                     entry.rip_dest_mask = 0;
  604.                 entry.rip_router = 0;
  605.                 entry.rip_metric = 0;       /* will get incremented to 1 */
  606.                 proc_rip(iface,fsock.address,&entry,header.rip_vers);
  607.             }
  608.             if(Rip_merge)
  609.                 rt_merge(Rip_trace);
  610.             rip_trigger();
  611.             break;
  612.   
  613.         case RIPCMD_REQUEST:
  614.             rip_trace(2, "RIPCMD_REQUEST from [%s] domain %d",inet_ntoa(fsock.address),
  615.             header.rip_domain);
  616.   
  617.             Rip_stat.vdata[header.rip_vers].request++;
  618.         /* For now, just send the whole table with split horizon
  619.          * enabled when the source port is RIP_PORT, and send
  620.          * the whole table with split horizon disable when another
  621.          * source port is used. This should be replaced with a more
  622.          * complete implementation that checks for non-global requests
  623.          */
  624.   
  625.             if (header.rip_vers > RIP_VERSION_1) {
  626.          /* RIP-2, let's see if we know something about this guy */
  627.                 rp = rt_lookup(fsock.address);
  628.                 for (rl = Rip_list; rl != NULLRL; rl = rl->next)
  629.                     if ((rl->dest == rp->target) && (rl->domain == header.rip_domain))
  630.                         break;
  631.   
  632.                 if (rl == NULLRL)
  633.                     if (fsock.port == RIP_PORT)
  634.                         send_routes(fsock.address,fsock.port,0,(RIP_BROADCAST & RIP_SPLIT &
  635.                         RIP_POISON),header.rip_vers,NULLRL);
  636.                     else
  637.                         send_routes(fsock.address,fsock.port,0,(RIP_BROADCAST),
  638.                         header.rip_vers,NULLRL);
  639.                     else
  640.                         if (fsock.port == RIP_PORT)
  641.                             send_routes(fsock.address,fsock.port,0,rl->flags,header.rip_vers,rl);
  642.                         else
  643.                             send_routes(fsock.address,fsock.port,0,(rl->flags & ~(RIP_SPLIT | RIP_POISON)),
  644.                             header.rip_vers,rl);
  645.             } else {
  646.                 if(fsock.port == RIP_PORT)
  647.                     send_routes(fsock.address,fsock.port,0,(RIP_SPLIT & RIP_BROADCAST & RIP_POISON),
  648.                     header.rip_vers,NULLRL);
  649.                 else
  650.                     send_routes(fsock.address,fsock.port,0,RIP_BROADCAST,
  651.                     header.rip_vers,NULLRL);
  652.             }
  653.             break;
  654.   
  655.         default:
  656.             rip_trace(1, "RIPCMD Unknown or not implemented from [%s] command %d",
  657.             inet_ntoa(fsock.address),header.rip_cmd);
  658.             Rip_stat.vdata[header.rip_vers].unknown++;
  659.             break;
  660.     } /* switch */
  661.     free_p(bp);
  662. }
  663.   
  664. /* Apply a set of heuristics for determining the number of significant bits
  665.  * (i.e., the address mask) in the target address. Needed since RIP doesn't
  666.  * include the address mask for each entry.  Applies only to RIP-1 packets.
  667.  */
  668.   
  669. int
  670. nbits(target)
  671. int32 target;
  672. {
  673.     int bits;
  674.   
  675.     if(target == 0)
  676.         return 0;   /* Special case: 0.0.0.0 is the default route */
  677.   
  678.    /* Check the host-part bytes of
  679.     * the address to check for byte-wide zeros
  680.     * which we'll consider to be subnet routes.
  681.     * e.g.  44.80.0.0 will be considered to be equal to 44.80/16
  682.     * whereas 44.80.1.0 will be considered to be 44.80.1/24
  683.     */
  684.     switch (hibyte(hiword(target)) >> 6) {
  685.         case 3:     /* Class C address */
  686.       /*is it a host address ? i.e. are there any 1's in the
  687.        * host part ?
  688.        */
  689.             if(target & 0xff)
  690.                 bits = 32;
  691.             else
  692.                 bits = 24;
  693.             break;
  694.         case 2:     /* Class B address */
  695.             if(target & 0xff)
  696.                 bits = 32;
  697.             else if(target & 0xff00)
  698.                 bits = 24;
  699.             else
  700.                 bits = 16;
  701.             break;
  702.         case 0:     /* Class A address */
  703.         case 1:
  704.             if(target & 0xff)
  705.                 bits = 32;
  706.             else if(target & 0xff00)
  707.                 bits = 24;
  708.             else if(target & 0xff0000L)
  709.                 bits = 16;
  710.             else
  711.                 bits = 8;
  712.     }
  713.   
  714.     return bits;
  715. }
  716.   
  717. /* Remove and process a RIP response entry from a packet */
  718.   
  719. static void
  720. proc_rip(iface,gateway,ep,version)
  721. struct iface *iface;
  722. int32 gateway;
  723. register struct rip_route *ep;
  724. unsigned char version;
  725. {
  726.     int32 interval;
  727.     int32 target;
  728.     unsigned int bits;
  729.     register struct route *rp;
  730.     struct rip_list *rl;
  731.     int add = 0;   /* action flags */
  732.     int drop = 0;
  733.     int trigger = 0;
  734.   
  735.     if(ep->rip_family != RIP_AF_INET) {
  736.         if (ep->rip_family == RIP_AF_AUTH)
  737.             return;
  738.       /* Skip non-IP addresses */
  739.         rip_trace(1, "RIP_rx: Not an IP family packet\n");
  740.         Rip_stat.addr_family++;
  741.         return;
  742.     }
  743.   
  744.    /* RIP-1 says all unused fields must be zero */
  745.     if (version == RIP_VERSION_1) {
  746.         if (ep->rip_tag != 0 || ep->rip_dest_mask != 0 || ep->rip_router != 0) {
  747.             rip_trace(1,"RIP_rx: RIP-1 entry bad, data in null fields");
  748.             Rip_stat.vdata[version].unknown++;
  749.         }
  750.     /* Guess at the mask, since it's not explicit for RIP-1 */
  751.         bits = nbits(ep->rip_dest);
  752.         target = ep->rip_dest;
  753.     } else {
  754.       /* Assume RIP-2 */
  755.         if (!ep->rip_dest_mask) {
  756.          /* No netmask, guess */
  757.             bits = nbits(ep->rip_dest);
  758.         } else {
  759.             bits = mask2width(ep->rip_dest_mask);
  760.         }
  761.         target = ep->rip_dest;
  762.       /* Check for "proxy" rip */
  763.         if (ep->rip_router) {
  764.             rip_trace(3, "Proxy rip pointing to [%s]", inet_ntoa(ep->rip_router));
  765.             gateway = ep->rip_router;
  766.         }
  767.     }
  768.   
  769.    /* Don't ever add a route to myself through somebody! */
  770.     if(bits == 32 && ismyaddr(target) != NULLIF) {
  771.         rip_trace(2, "Route to self [%s]/32 metric %lu", inet_ntoa(target),
  772.         ep->rip_metric);
  773.         return;
  774.     }
  775.   
  776.    /* Check to see if we'll take a default route, zero bits mean default */
  777.   
  778.     if (Rip_default_refuse && bits == 0) {
  779.         rip_trace(2, "Default route refused from [%s]", inet_ntoa(target));
  780.         return;
  781.     }
  782.   
  783.    /* Update metric to reflect link cost */
  784.     ep->rip_metric++;
  785.     ep->rip_metric = min(ep->rip_metric,RIP_METRIC_UNREACHABLE);
  786.   
  787.    /* Find existing entry, if any */
  788.     rp = rt_blookup(target,bits);
  789.   
  790.    /* Don't touch private routes */
  791.     if(rp != NULLROUTE && (rp->flags & RTPRIVATE)) {
  792.         rip_trace(3, "Route to [%s]/%u unchanged, private", inet_ntoa(target),
  793.         bits);
  794.         return;
  795.     }
  796.   
  797.     if(rp == NULLROUTE) {
  798.         if(ep->rip_metric < RIP_METRIC_UNREACHABLE) {
  799.          /* New route; add it and trigger an update */
  800.             add++;
  801.             trigger++;
  802.         }
  803.     } else if(rp->metric == RIP_METRIC_UNREACHABLE) {
  804.       /* Route is in hold-down; ignore this guy */
  805.         rip_trace(2, "Route to [%s]/%u ignored (hold-down) metric %lu",
  806.         inet_ntoa(target), bits, ep->rip_metric);
  807.     } else if(rp->gateway == gateway && rp->iface == iface) {
  808.       /* This is the gateway for the entry we already have;
  809.        * restart the timer
  810.        */
  811.         start_timer(&rp->timer);
  812.         if(rp->metric != ep->rip_metric) {
  813.          /* Metric has changed. Update it and trigger an
  814.           * update. If route has become unavailable, start
  815.           * the hold-down timeout.
  816.           */
  817.             rip_trace(3, "Metric change [%s]/%u %lu -> %lu", inet_ntoa(target),
  818.             bits, rp->metric, ep->rip_metric);
  819.             if(ep->rip_metric == RIP_METRIC_UNREACHABLE)
  820.                 rt_timeout(rp);      /* Enter hold-down timeout */
  821.             else
  822.                 rp->metric = ep->rip_metric;
  823.             trigger++;
  824.         }
  825.     } else {
  826.       /* Entry is from a different gateway than the current route */
  827.         if(ep->rip_metric < rp->metric) {
  828.          /* Switch to a new gateway */
  829.             rip_trace(3, "Metric better [%s]/%u new: %lu old: %lu", inet_ntoa(target),
  830.             bits, ep->rip_metric, rp->metric);
  831.             drop++;
  832.             add++;
  833.             trigger++;
  834.         } else {
  835.          /* Metric is no better, stay with current route */
  836.             rip_trace(3, "Metric not better [%s]/%u new: %lu old: %lu", inet_ntoa(target),
  837.             bits, ep->rip_metric, rp->metric);
  838.         }
  839.     }
  840.     if(drop) {
  841.       /* Switching to a better gateway; delete old entry */
  842.   
  843.         rip_trace(2, "Route drop [%s]/%u", inet_ntoa(target), bits);
  844.         rt_drop(target,bits);
  845.     }
  846.   
  847.     if(add) {
  848.       /* Add a new entry */
  849.         interval = Rip_ttl;
  850.         for(rl=Rip_list; rl != NULLRL; rl = rl->next){
  851.             if(rl->iface == iface){
  852.                 interval = rl->interval * 4;
  853.                 break;
  854.             }
  855.         }
  856.         rip_trace(2, "Route add [%s]/%u through %s via ",
  857.         inet_ntoa(target), bits, iface->name);
  858.         rip_trace(2, "[%s] metric %lu", inet_ntoa(gateway),
  859.         ep->rip_metric);
  860.   
  861.         rp = rt_add(target,(unsigned) bits,gateway,iface,
  862.         (int) ep->rip_metric,interval,0);
  863.   
  864.       /* Add in the routing tag for RIP-2 */
  865.   
  866.         if (version >= RIP_VERSION_2)
  867.             rp->route_tag = ep->rip_tag;
  868.         else
  869.             rp->route_tag = 0;
  870.     }
  871.    /* If the route changed, mark it for a triggered update */
  872.     if(trigger){
  873.         rp->flags |= RTTRIG;
  874.     }
  875. }
  876.   
  877. /* Send a RIP request packet to the specified destination */
  878.   
  879. int
  880. ripreq(dest,replyport,version)
  881. int32 dest;
  882. int16 replyport;
  883. int16 version;
  884. {
  885.     struct mbuf *bp;
  886.     struct socket lsock,fsock;
  887.     char *cp;
  888.     register struct rip_list *rl;
  889.   
  890.     lsock.address = INADDR_ANY;
  891.     lsock.port = replyport;
  892.   
  893.    /* if we were given a valid dest addr, ask it (the routers on that net)
  894.     * for a default gateway
  895.     */
  896.   
  897.     if(dest == 0)
  898.         return 0;
  899.   
  900.     fsock.address = dest;
  901.     fsock.port = RIP_PORT;
  902.   
  903.    /* Send out one RIP Request packet as a broadcast to 'dest'  */
  904.     if((bp = alloc_mbuf(RIP_HEADER + RIP_ENTRY)) == NULLBUF)
  905.         return -1;
  906.   
  907.    /* Check to see if we already know something about who we're   */
  908.    /* requesting the RIP from */
  909.   
  910.     for (rl = Rip_list; rl != NULLRL; rl = rl->next)
  911.         if (rl->dest == dest)
  912.             break;
  913.   
  914.     bp->cnt = RIP_HEADER + RIP_ENTRY;
  915.     if (rl != NULLRL) {
  916.         cp = putheader(bp->data,RIPCMD_REQUEST,rl->rip_version, rl->domain);
  917.         if (rl->rip_version >= RIP_VERSION_2) {
  918.             if (rl->flags & RIP_AUTHENTICATE) {
  919.                 cp = putauth(cp,RIP_AUTH_SIMPLE,rl->rip_auth_code);
  920.                 bp->cnt += RIP_ENTRY;
  921.             }
  922.         }
  923.         Rip_stat.vdata[rl->rip_version].output++;
  924.     } else {
  925.         cp = putheader(bp->data,RIPCMD_REQUEST,version, 0);
  926.         Rip_stat.vdata[version].output++;
  927.     }
  928.   
  929.     cp = putentry(cp,0,0,0L,0L,0L,RIP_METRIC_UNREACHABLE);
  930.     send_udp(&lsock, &fsock,0,0,bp,bp->cnt,0,0);
  931.     return 0;
  932. }
  933.   
  934. /* Write the authentication packet */
  935.   
  936. static char *
  937. putauth(cp,authtype,authpass)
  938. register char *cp;
  939. int16 authtype;
  940. char *authpass;
  941. {
  942.     int x;
  943.   
  944.     cp = put16(cp, 0xFFFF);
  945.     cp = put16(cp, authtype);
  946.   
  947.    /* Put the password in big-endian (network) byte order */
  948.    /* This probably is not the best way to do this, since it */
  949.    /* would hose up on a real big-endian machine.  Oh well */
  950.    /* Something to fix in the future.  Whip me, beat me, make */
  951.    /* me use an Intel micro brain.  -N0POY */
  952.   
  953.     for (x = 0; x < RIP_AUTH_SIZE; x += 4) {
  954.         *cp++ = authpass[x+3];
  955.         *cp++ = authpass[x+2];
  956.         *cp++ = authpass[x+1];
  957.         *cp++ = authpass[x];
  958.     }
  959.     return(cp);
  960. }
  961.   
  962. /* Write the header of a RIP packet */
  963.   
  964. static char *
  965. putheader(cp,command,version,domain)
  966. register char *cp;
  967. char command;
  968. char version;
  969. int16 domain;
  970. {
  971.     *cp++ = command;
  972.     *cp++ = version;
  973.     return put16(cp,domain);
  974. }
  975.   
  976. /* Write a single entry into a rip packet */
  977.   
  978. static char *
  979. putentry(cp,fam,tag,target,targmask,router,metric)
  980. register char *cp;
  981. int16 fam;
  982. int16 tag;
  983. int32 target;
  984. int32 targmask;
  985. int32 router;
  986. int32 metric;
  987.   
  988. {
  989.     cp = put16(cp,fam);
  990.     cp = put16(cp,tag);
  991.     cp = put32(cp,target);
  992.     cp = put32(cp,targmask);
  993.     cp = put32(cp,router);
  994.     return put32(cp,metric);
  995. }
  996.   
  997. /* Check the authentication of RIP-II packets */
  998. int
  999. check_authentication(auth,bpp,header,srcaddr,ifcname,entry)
  1000. struct rip_auth *auth;
  1001. struct mbuf **bpp;
  1002. struct rip_head *header;
  1003. int32 srcaddr;
  1004. char *ifcname;
  1005. struct rip_authenticate *entry;
  1006. {
  1007.     struct rip_auth *rd;
  1008.   
  1009.     for (rd = auth; rd != NULLAUTH; rd = rd->next) {
  1010.         if ((strcmp(ifcname, rd->ifc_name) == 0) ||
  1011.         (strcmp(DEFAULTIFC, rd->ifc_name) == 0)) {
  1012.             if (rd->domain == header->rip_domain) {
  1013.             /* We'll take this domain, check against a NULL password */
  1014.                 if (strcmp(rd->rip_auth_code, RIP_NO_AUTH) == 0) {
  1015.                     rip_trace(3, "RIP-2 taken due to no password from [%s] domain %d",
  1016.                     inet_ntoa(srcaddr), header->rip_domain);
  1017.                     return(TRUE);
  1018.                 } else {
  1019.   
  1020.                /* Okay, we need an authentication */
  1021.   
  1022.                     if (entry->rip_family != RIP_AF_AUTH) {
  1023.                      /* It doesn't have an authentication packet */
  1024.                         rip_trace(2, "RIP-2 lacking authentication packet from [%s] domain %d",
  1025.                         inet_ntoa(srcaddr), header->rip_domain);
  1026.                         Rip_stat.auth_fail++;
  1027.                         return(FALSE);
  1028.                     }
  1029.   
  1030.                     if (entry->rip_auth_type != RIP_AUTH_SIMPLE) {
  1031.                      /* Only support simple authentication */
  1032.                         rip_trace(2, "RIP-2 wrong type of authentication from [%s]",
  1033.                         inet_ntoa(srcaddr));
  1034.                         Rip_stat.auth_fail++;
  1035.                         return(FALSE);
  1036.                     }
  1037.   
  1038.                     if (memcmp(rd->rip_auth_code,entry->rip_auth_str,RIP_AUTH_SIZE) == 0) {
  1039.                         rip_trace(3, "RIP-2 authenticated from [%s] domain %d",
  1040.                         inet_ntoa(srcaddr), header->rip_domain);
  1041.                         return(TRUE);
  1042.                     } else {
  1043.                         rip_trace(2, "RIP-2 authentication failed from [%s] domain %d,\n attempted password '%.16s' right password '%.16s'",
  1044.                         inet_ntoa(srcaddr), header->rip_domain, entry->rip_auth_str, rd->rip_auth_code);
  1045.                         Rip_stat.auth_fail++;
  1046.                         return(FALSE);
  1047.                     }
  1048.                 }
  1049.             }
  1050.         }
  1051.     }
  1052.    /* Didn't find the right routing domain for this packet */
  1053.     rip_trace(3, "RIP-2 domain %d not accepted from [%s]", header->rip_domain,
  1054.     inet_ntoa(srcaddr));
  1055.     Rip_stat.wrong_domain++;
  1056.     return(FALSE);
  1057. }
  1058.   
  1059. /* Route timeout handler. If route has already been marked for deletion
  1060.  * then delete it. Otherwise mark for deletion and restart timer.
  1061.  */
  1062. void
  1063. rt_timeout(s)
  1064. void *s;
  1065. {
  1066.     register struct route *rp = (struct route *)s;
  1067.   
  1068.     stop_timer(&rp->timer);
  1069.     if(rp->metric < RIP_METRIC_UNREACHABLE){
  1070.         rip_trace(5, "RIP:  route to [%s]/%d expired - hold down", inet_ntoa(rp->target),
  1071.         rp->bits);
  1072.         rp->metric = RIP_METRIC_UNREACHABLE;
  1073.         if(dur_timer(&rp->timer) == 0)
  1074.             set_timer(&rp->timer,Rip_ttl*1000L);
  1075.       /* wait 2/3 of timeout before garbage collect */
  1076.         set_timer(&rp->timer,dur_timer(&rp->timer)*2/3);
  1077.         rp->timer.func = (void *)rt_timeout;
  1078.         rp->timer.arg = (void *)rp;
  1079.         start_timer(&rp->timer);
  1080.       /* Route changed; mark it for triggered update */
  1081.         rp->flags |= RTTRIG;
  1082.         rip_trigger();
  1083.     } else {
  1084.         rip_trace(5, "RIP:  route to [%s]/%d expired - dropped", inet_ntoa(rp->target),
  1085.         rp->bits);
  1086.         rt_drop(rp->target,rp->bits);
  1087.     }
  1088. }
  1089.   
  1090. void
  1091. pullheader(ep,bpp)
  1092. struct rip_head *ep;
  1093. struct mbuf **bpp;
  1094. {
  1095.     ep->rip_cmd = pullchar(bpp);
  1096.     ep->rip_vers = pullchar(bpp);
  1097.     ep->rip_domain = pull16(bpp);
  1098. }
  1099.   
  1100. void
  1101. pullauthentication(ep,bpp)
  1102. struct rip_authenticate *ep;
  1103. struct mbuf **bpp;
  1104. {
  1105.     int x;
  1106.   
  1107.     ep->rip_family = pull16(bpp);
  1108.     ep->rip_auth_type = pull16(bpp);
  1109.     for (x = 0; x < RIP_AUTH_SIZE; x++)
  1110.         ep->rip_auth_str[x] = pullchar(bpp);
  1111. }
  1112.   
  1113. void rip_trace(short level, char *errstr, ...)
  1114. {
  1115.     if (level <= Rip_trace) {
  1116.         char *timestr;
  1117.         time_t timer;
  1118.         va_list argptr;
  1119.   
  1120.         if (Rip_trace_fname != NULLCHAR) {
  1121.             time(&timer);
  1122.             timestr = ctime(&timer);
  1123.             timestr[24] = '\0';
  1124.             Rip_trace_file = fopen(Rip_trace_fname, APPEND_TEXT);
  1125.             fprintf(Rip_trace_file, "%s - ", timestr);
  1126.   
  1127.             va_start(argptr, errstr);
  1128.             vfprintf(Rip_trace_file, errstr, argptr);
  1129.             va_end(argptr);
  1130.             fprintf(Rip_trace_file, "\n");
  1131.             fclose(Rip_trace_file);
  1132.         } else {
  1133.             va_start(argptr, errstr);
  1134.             usvprintf(Curproc->output, errstr, argptr);
  1135.             va_end(argptr);
  1136.             tprintf("\n");
  1137.         }
  1138.     }
  1139. }
  1140.   
  1141. void
  1142. pullentry(ep,bpp)
  1143. register struct rip_route *ep;
  1144. struct mbuf **bpp;
  1145. {
  1146.     ep->rip_family = pull16(bpp);
  1147.     ep->rip_tag = pull16(bpp);
  1148.     ep->rip_dest = pull32(bpp);
  1149.     ep->rip_dest_mask = pull32(bpp);
  1150.     ep->rip_router = pull32(bpp);
  1151.     ep->rip_metric = pull32(bpp);
  1152. }
  1153.   
  1154. #endif /* RIP */
  1155.   
  1156.