iproute.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:20k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Lower half of IP, consisting of gateway routines
  2.  * Includes routing and options processing code
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include "config.h"
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "iface.h"
  10. #include "timer.h"
  11. #include "internet.h"
  12. #include "ip.h"
  13. #include "tcp.h"
  14. #include "netuser.h"
  15. #include "icmp.h"
  16. #include "rip.h"
  17. #include "trace.h"
  18. #include "pktdrvr.h"
  19. #include "bootp.h"
  20. #ifdef IPSEC
  21. #include "ipsec.h"
  22. #endif
  23. struct route *Routes[32][HASHMOD]; /* Routing table */
  24. struct route R_default = { /* Default route entry */
  25. NULL, NULL,
  26. 0,0,0,
  27. RIP_INFINITY /* Init metric to infinity */
  28. };
  29. static struct rt_cache Rt_cache[HASHMOD];
  30. int32 Rtlookups;
  31. int32 Rtchits;
  32. static int q_pkt(struct iface *iface,int32 gateway,struct ip *ip,
  33. struct mbuf **bpp,int ckgood);
  34. /* Initialize modulo lookup table used by hash_ip() in pcgen.asm */
  35. void
  36. ipinit(void)
  37. {
  38. int i;
  39. for(i=0;i<256;i++)
  40. Hashtab[i] = i % HASHMOD;
  41. }
  42. /* Route an IP datagram. This is the "hopper" through which all IP datagrams,
  43.  * coming or going, must pass.
  44.  *
  45.  * "rxbroadcast" is set to indicate that the packet came in on a subnet
  46.  * broadcast. The router will kick the packet upstairs regardless of the
  47.  * IP destination address.
  48.  */
  49. int
  50. ip_route(
  51. struct iface *i_iface, /* Input interface */
  52. struct mbuf **bpp, /* Input packet */
  53. int rxbroadcast /* True if packet had link broadcast address */
  54. ){
  55. struct ip ip; /* IP header being processed */
  56. uint16 ip_len; /* IP header length */
  57. uint16 length; /* Length of data portion */
  58. int32 gateway; /* Gateway IP address */
  59. register struct route *rp; /* Route table entry */
  60. struct iface *iface; /* Output interface, possibly forwarded */
  61. uint16 offset; /* Starting offset of current datagram */
  62. uint16 mf_flag; /* Original datagram MF flag */
  63. int strict = 0; /* Strict source routing flag */
  64. uint16 opt_len; /* Length of current option */
  65. uint8 *opt; /* -> beginning of current option */
  66. int i;
  67. int ckgood = IP_CS_OLD; /* Has good checksum without modification */
  68. int pointer; /* Relative pointer index for sroute/rroute */
  69. if(i_iface != NULL){
  70. ipInReceives++; /* Not locally generated */
  71. i_iface->iprecvcnt++;
  72. }
  73. if(len_p(*bpp) < IPLEN){
  74. /* The packet is shorter than a legal IP header */
  75. ipInHdrErrors++;
  76. free_p(bpp);
  77. return -1;
  78. }
  79. /* Sneak a peek at the IP header's IHL field to find its length */
  80. ip_len = ((*bpp)->data[0] & 0xf) << 2;
  81. if(ip_len < IPLEN){
  82. /* The IP header length field is too small */
  83. ipInHdrErrors++;
  84. free_p(bpp);
  85. return -1;
  86. }
  87. if(cksum(NULL,*bpp,ip_len) != 0){
  88. /* Bad IP header checksum; discard */
  89. ipInHdrErrors++;
  90. free_p(bpp);
  91. return -1;
  92. }
  93. /* Extract IP header */
  94. ntohip(&ip,bpp);
  95. if(ip.version != IPVERSION){
  96. /* We can't handle this version of IP */
  97. ipInHdrErrors++;
  98. free_p(bpp);
  99. return -1;
  100. }
  101. /* If we're running low on memory, return a source quench */
  102. if(!rxbroadcast && availmem() != 0)
  103. icmp_output(&ip,*bpp,ICMP_QUENCH,0,NULL);
  104. /* Process options, if any. Also compute length of secondary IP
  105.  * header in case fragmentation is needed later
  106.  */
  107. strict = 0;
  108. for(i=0;i<ip.optlen;i += opt_len){
  109. /* First check for the two special 1-byte options */
  110. switch(ip.options[i] & OPT_NUMBER){
  111. case IP_EOL:
  112. goto no_opt; /* End of options list, we're done */
  113. case IP_NOOP:
  114. opt_len = 1;
  115. continue; /* No operation, skip to next option */
  116. }
  117. /* Not a 1-byte option, so ensure that there's at least
  118.  * two bytes of option left, that the option length is
  119.  * at least two, and that there's enough space left for
  120.  * the specified option length.
  121.  */
  122. if(ip.optlen - i < 2
  123.  || ((opt_len = ip.options[i+1]) < 2)
  124.  || ip.optlen - i < opt_len){
  125. /* Truncated option, send ICMP and drop packet */
  126. if(!rxbroadcast){
  127. union icmp_args icmp_args;
  128. icmp_args.pointer = IPLEN + i;
  129. icmp_output(&ip,*bpp,ICMP_PARAM_PROB,0,&icmp_args);
  130. }
  131. free_p(bpp);
  132. return -1;
  133. }
  134. opt = &ip.options[i];
  135. switch(opt[0] & OPT_NUMBER){
  136. case IP_SSROUTE: /* Strict source route & record route */
  137. strict = 1; /* note fall-thru */
  138. case IP_LSROUTE: /* Loose source route & record route */
  139. /* Source routes are ignored unless we're in the
  140.  * destination field
  141.  */
  142. if(opt_len < 3){
  143. /* Option is too short to be a legal sroute.
  144.  * Send an ICMP message and drop it.
  145.  */
  146. if(!rxbroadcast){
  147. union icmp_args icmp_args;
  148. icmp_args.pointer = IPLEN + i;
  149. icmp_output(&ip,*bpp,ICMP_PARAM_PROB,0,&icmp_args);
  150. }
  151. free_p(bpp);
  152. return -1;
  153. }
  154. if(ismyaddr(ip.dest) == NULL)
  155. break; /* Skip to next option */
  156. pointer = opt[2];
  157. if(pointer + 4 > opt_len)
  158. break; /* Route exhausted; it's for us */
  159. /* Put address for next hop into destination field,
  160.  * put our address into the route field, and bump
  161.  * the pointer. We've already ensured enough space.
  162.  */
  163. ip.dest = get32(&opt[pointer]);
  164. put32(&opt[pointer],locaddr(ip.dest));
  165. opt[2] += 4;
  166. ckgood = IP_CS_NEW;
  167. break;
  168. case IP_RROUTE: /* Record route */
  169. if(opt_len < 3){
  170. /* Option is too short to be a legal rroute.
  171.  * Send an ICMP message and drop it.
  172.  */
  173. if(!rxbroadcast){
  174. union icmp_args icmp_args;
  175. icmp_args.pointer = IPLEN + i;
  176. icmp_output(&ip,*bpp,ICMP_PARAM_PROB,0,&icmp_args);
  177. }
  178. free_p(bpp);
  179. return -1;
  180. }
  181. pointer = opt[2];
  182. if(pointer + 4 > opt_len){
  183. /* Route area exhausted; send an ICMP msg */
  184. if(!rxbroadcast){
  185. union icmp_args icmp_args;
  186. icmp_args.pointer = IPLEN + i;
  187. icmp_output(&ip,*bpp,ICMP_PARAM_PROB,0,&icmp_args);
  188. }
  189. /* Also drop if odd-sized */
  190. if(pointer != opt_len){
  191. free_p(bpp);
  192. return -1;
  193. }
  194. } else {
  195. /* Add our address to the route.
  196.  * We've already ensured there's enough space.
  197.  */
  198. put32(&opt[pointer],locaddr(ip.dest));
  199.   opt[2] += 4;
  200. ckgood = IP_CS_NEW;
  201. }
  202. break;
  203. }
  204. }
  205. no_opt:
  206. /* See if it's a broadcast or addressed to us, and kick it upstairs */
  207. if(ismyaddr(ip.dest) != NULL || rxbroadcast ||
  208. (WantBootp && bootp_validPacket(&ip, *bpp))){
  209. #ifdef GWONLY
  210. /* We're only a gateway, we have no host level protocols */
  211. if(!rxbroadcast)
  212. icmp_output(&ip,*bpp,ICMP_DEST_UNREACH,
  213.  ICMP_PROT_UNREACH,NULL);
  214. ipInUnknownProtos++;
  215. free_p(bpp);
  216. #else
  217. ip_recv(i_iface,&ip,bpp,rxbroadcast,0);
  218. #endif
  219. return 0;
  220. }
  221. /* Packet is not destined to us. If it originated elsewhere, count
  222.  * it as a forwarded datagram.
  223.  */
  224. if(i_iface != NULL)
  225. ipForwDatagrams++;
  226. /* Adjust the header checksum to allow for the modified TTL */
  227. ip.checksum += 0x100;
  228. if((ip.checksum & 0xff00) == 0)
  229. ip.checksum++; /* end-around carry */
  230. /* Decrement TTL and discard if zero. We don't have to check
  231.  * rxbroadcast here because it's already been checked
  232.  */
  233. if(--ip.ttl == 0){
  234. /* Send ICMP "Time Exceeded" message */
  235. icmp_output(&ip,*bpp,ICMP_TIME_EXCEED,0,NULL);
  236. ipInHdrErrors++;
  237. free_p(bpp);
  238. return -1;
  239. }
  240. /* Look up target address in routing table */
  241. if((rp = rt_lookup(ip.dest)) == NULL){
  242. /* No route exists, return unreachable message (we already
  243.  * know this can't be a broadcast)
  244.  */
  245. icmp_output(&ip,*bpp,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,NULL);
  246. free_p(bpp);
  247. ipOutNoRoutes++;
  248. return -1;
  249. }
  250. rp->uses++;
  251. /* Check for output forwarding and divert if necessary */
  252. iface = rp->iface;
  253. if(iface->forw != NULL)
  254. iface = iface->forw;
  255. /* Find gateway; zero gateway in routing table means "send direct" */
  256. if(rp->gateway == 0)
  257. gateway = ip.dest;
  258. else
  259. gateway = rp->gateway;
  260. if(strict && gateway != ip.dest){
  261. /* Strict source routing requires a direct entry
  262.  * Again, we know this isn't a broadcast
  263.  */
  264. icmp_output(&ip,*bpp,ICMP_DEST_UNREACH,ICMP_ROUTE_FAIL,NULL);
  265. free_p(bpp);
  266. ipOutNoRoutes++;
  267. return -1;
  268. }
  269. #ifdef IPSEC
  270. if(sec_output(iface,&ip,bpp) != 0){
  271. /* We inserted a security header, recompute hdr checksum */
  272. ckgood = IP_CS_NEW; /* Recompute IP checksum */
  273. }
  274. #endif
  275. if(ip.length <= iface->mtu){
  276. /* Datagram smaller than interface MTU; put header
  277.  * back on and send normally.
  278.  */
  279. return q_pkt(iface,gateway,&ip,bpp,ckgood);
  280. }
  281. /* Fragmentation needed */
  282. if(ip.flags.df){
  283. /* Don't Fragment set; return ICMP message and drop */
  284. union icmp_args icmp_args;
  285. icmp_args.mtu = iface->mtu;
  286. icmp_output(&ip,*bpp,ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED,&icmp_args);
  287. free_p(bpp);
  288. ipFragFails++;
  289. return -1;
  290. }
  291. /* Create fragments */
  292. offset = ip.offset; /* Remember starting offset */
  293. mf_flag = ip.flags.mf; /* Save original MF flag */
  294. length = ip.length - ip_len; /* Length of data portion */
  295. while(length != 0){ /* As long as there's data left */
  296. uint16 fragsize; /* Size of this fragment's data */
  297. struct mbuf *f_data; /* Data portion of fragment */
  298. /* After the first fragment, should remove those
  299.  * options that aren't supposed to be copied on fragmentation
  300.  */
  301. if(length + ip_len <= iface->mtu){
  302. /* Last fragment; send all that remains */
  303. fragsize = length;
  304. ip.flags.mf = mf_flag; /* Pass original MF flag */
  305. } else {
  306. /* More to come, so send multiple of 8 bytes */
  307. fragsize = (iface->mtu - ip_len) & 0xfff8;
  308. ip.flags.mf = 1;
  309. }
  310. ip.length = fragsize + ip_len;
  311. /* Duplicate the fragment */
  312. dup_p(&f_data,*bpp,ip.offset-offset,fragsize);
  313. if(f_data == NULL){
  314. free_p(bpp);
  315. ipFragFails++;
  316. return -1;
  317. }
  318. if(q_pkt(iface,gateway,&ip,&f_data,IP_CS_NEW) == -1){
  319. free_p(bpp);
  320. ipFragFails++;
  321. return -1;
  322. }
  323. ipFragCreates++;
  324. ip.offset += fragsize;
  325. length -= fragsize;
  326. }
  327. ipFragOKs++;
  328. free_p(bpp);
  329. return 0;
  330. }
  331. /* Direct IP input routine for packets without link-level header */
  332. void
  333. ip_proc(
  334. struct iface *iface,
  335. struct mbuf **bpp
  336. ){
  337. ip_route(iface,bpp,0);
  338. }
  339. /* Add an IP datagram to an interface output queue, sorting first by
  340.  * the precedence field in the IP header, and secondarily by an
  341.  * "interactive" flag set by peeking at the transport layer to see
  342.  * if the packet belongs to what appears to be an interactive session.
  343.  * A layer violation, yes, but a useful one...
  344.  */
  345. static int
  346. q_pkt(
  347. struct iface *iface,
  348. int32 gateway,
  349. struct ip *ip,
  350. struct mbuf **bpp,
  351. int ckgood
  352. ){
  353. struct mbuf *tlast,*tbp;
  354. struct tcp tcp;
  355. struct qhdr qhdr,qtmp;
  356. int i;
  357. iface->ipsndcnt++;
  358. htonip(ip,bpp,ckgood);
  359. /* create priority field consisting of tos with 2 unused
  360.  * low order bits stripped, one of which we'll use as an
  361.  * "interactive" flag.
  362.  */
  363. qhdr.tos = (ip->tos & 0xfc);
  364. qhdr.gateway = gateway;
  365. if(iface->outq == NULL){
  366. /* Queue empty, no priority decisions to be made
  367.  * This is the usual case for fast networks like Ethernet,
  368.  * so we can avoid some time-consuming stuff
  369.  */
  370. pushdown(bpp,&qhdr,sizeof(qhdr));
  371. iface->outq = *bpp;
  372. *bpp = NULL;
  373. } else {
  374. /* See if this packet references a "priority" TCP port number */
  375. if(ip->protocol == TCP_PTCL && ip->offset == 0){
  376. /* Extract a copy of the TCP header */
  377. if(dup_p(&tbp,*bpp,sizeof(struct qhdr)+IPLEN+
  378.  ip->optlen,TCPLEN+TCP_MAXOPT) >= TCPLEN){
  379. ntohtcp(&tcp,&tbp);
  380. for(i=0;Tcp_interact[i] != -1;i++){
  381. if(tcp.source == Tcp_interact[i]
  382.  || tcp.dest == Tcp_interact[i]){
  383. qhdr.tos |= 1;
  384. break;
  385. }
  386. }
  387. }
  388. free_p(&tbp);
  389. }
  390. pushdown(bpp,&qhdr,sizeof(qhdr));
  391. /* Search the queue looking for the first packet with precedence
  392.  * lower than our packet
  393.  */
  394. tlast = NULL;
  395. for(tbp = iface->outq;tbp != NULL;tlast=tbp,tbp = tbp->anext){
  396. memcpy(&qtmp,tbp->data,sizeof(qtmp));
  397. if(qhdr.tos > qtmp.tos){
  398. break; /* Add it just before tbp */
  399. }
  400. }
  401. (*bpp)->anext = tbp;
  402. if(tlast == NULL){
  403. /* First on queue */
  404. iface->outq = *bpp;
  405. } else {
  406. tlast->anext = *bpp;
  407. }
  408. *bpp = NULL;
  409. }
  410. ksignal(&iface->outq,1);
  411. if(iface->outlim != 0 && len_q(iface->outq) >= iface->outlim){
  412. /* Output queue is at limit; return source quench to
  413.  * the sender of a randomly selected packet on the queue
  414.  */
  415. rquench(iface,0);
  416. }
  417. return 0;
  418. }
  419. int
  420. ip_encap(
  421. struct mbuf **bpp,
  422. struct iface *iface,
  423. int32 gateway,
  424. uint8 tos
  425. ){
  426. struct ip ip;
  427. dump(iface,IF_TRACE_OUT,*bpp);
  428. iface->rawsndcnt++;
  429. iface->lastsent = secclock();
  430. if(gateway == 0L){
  431. /* Gateway must be specified */
  432. ntohip(&ip,bpp);
  433. icmp_output(&ip,*bpp,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,NULL);
  434. free_p(bpp);
  435. ipOutNoRoutes++;
  436. return -1;
  437. }
  438. /* Encapsulate in an IP packet from us to the gateway.
  439.  * The outer source address is taken from the encap interface
  440.  * structure. This defaults to INADDR_ANY, so unless it is
  441.  * changed (with iface encap ipaddr ...), the IP address
  442.  * of the physical interface used to reach the encap gateway
  443.  * will be used.
  444.  */
  445. return ip_send(Encap.addr,gateway,IP_PTCL,tos,0,bpp,0,0,0);
  446. }
  447. /* Add an entry to the IP routing table. Returns 0 on success, -1 on failure */
  448. struct route *
  449. rt_add(
  450. int32 target, /* Target IP address prefix */
  451. unsigned int bits, /* Size of target address prefix in bits (0-32) */
  452. int32 gateway, /* Optional gateway to be reached via interface */
  453. struct iface *iface, /* Interface to which packet is to be routed */
  454. int32 metric, /* Metric for this route entry */
  455. int32 ttl, /* Lifetime of this route entry in sec */
  456. uint8 private /* Inhibit advertising this entry ? */
  457. ){
  458. struct route *rp,**hp;
  459. int i;
  460. if(iface == NULL)
  461. return NULL;
  462. if(bits > 32)
  463. bits = 32; /* Bulletproofing */
  464. if(bits == 32 && ismyaddr(target))
  465. return NULL; /* Don't accept routes to ourselves */
  466. /* Mask off don't-care bits of target */
  467. target &= ~0L << (32-bits);
  468. /* Encapsulated routes must specify gateway, and it can't be
  469.  *  ourselves
  470.  */
  471. if(iface == &Encap && (gateway == 0 || ismyaddr(gateway)))
  472. return NULL;
  473. for(i=0;i<HASHMOD;i++)
  474. Rt_cache[i].route = NULL; /* Flush cache */
  475. /* Zero bits refers to the default route */
  476. if(bits == 0){
  477. rp = &R_default;
  478. } else {
  479. rp = rt_blookup(target,bits);
  480. }
  481. if(rp == NULL){
  482. /* The target is not already in the table, so create a new
  483.  * entry and put it in.
  484.  */
  485. rp = (struct route *)callocw(1,sizeof(struct route));
  486. /* Insert at head of table */
  487. rp->prev = NULL;
  488. hp = &Routes[bits-1][hash_ip(target)];
  489. rp->next = *hp;
  490. if(rp->next != NULL)
  491. rp->next->prev = rp;
  492. *hp = rp;
  493. rp->uses = 0;
  494. }
  495. rp->target = target;
  496. rp->bits = bits;
  497. rp->gateway = gateway;
  498. rp->metric = metric;
  499. rp->iface = iface;
  500. rp->flags.rtprivate = private; /* Should anyone be told of this route? */
  501. rp->timer.func = rt_timeout;  /* Set the timer field */
  502. rp->timer.arg = (void *)rp;
  503. set_timer(&rp->timer,ttl*1000L);
  504. stop_timer(&rp->timer);
  505. start_timer(&rp->timer); /* start the timer if appropriate */
  506. return rp;
  507. }
  508. /* Remove an entry from the IP routing table. Returns 0 on success, -1
  509.  * if entry was not in table.
  510.  */
  511. int
  512. rt_drop(
  513. int32 target,
  514. unsigned int bits
  515. ){
  516. register struct route *rp;
  517. int i;
  518. for(i=0;i<HASHMOD;i++)
  519. Rt_cache[i].route = NULL; /* Flush the cache */
  520. if(bits == 0){
  521. /* Nail the default entry */
  522. stop_timer(&R_default.timer);
  523. R_default.iface = NULL;
  524. return 0;
  525. }
  526. if(bits > 32)
  527. bits = 32;
  528. /* Mask off target according to width */
  529. target &= ~0L << (32-bits);
  530. /* Search appropriate chain for existing entry */
  531. for(rp = Routes[bits-1][hash_ip(target)];rp != NULL;rp = rp->next){
  532. if(rp->target == target)
  533. break;
  534. }
  535. if(rp == NULL)
  536. return -1; /* Not in table */
  537. stop_timer(&rp->timer);
  538. if(rp->next != NULL)
  539. rp->next->prev = rp->prev;
  540. if(rp->prev != NULL)
  541. rp->prev->next = rp->next;
  542. else
  543. Routes[bits-1][hash_ip(target)] = rp->next;
  544. free(rp);
  545. return 0;
  546. }
  547. #ifdef notdef
  548. /* Compute hash function on IP address */
  549. static uint16
  550. hash_ip(
  551. int32 addr
  552. ){
  553. register uint16 ret;
  554. ret = hiword(addr);
  555. ret ^= loword(addr);
  556. return (uint16)(ret % HASHMOD);
  557. }
  558. #endif
  559. #ifndef GWONLY
  560. /* Given an IP address, return the MTU of the local interface used to
  561.  * reach that destination. This is used by TCP to avoid local fragmentation
  562.  */
  563. uint16
  564. ip_mtu(
  565. int32 addr
  566. ){
  567. register struct route *rp;
  568. struct iface *iface;
  569. rp = rt_lookup(addr);
  570. if(rp == NULL || rp->iface == NULL)
  571. return 0;
  572. if(rp->iface == &Encap){
  573. /* Recurse to the actual hardware interface */
  574. return ip_mtu(rp->gateway) - IPLEN; /* no options? */
  575. }
  576. iface = rp->iface;
  577. #ifdef IPSEC
  578. if(iface->forw != NULL)
  579. return iface->forw->mtu - sec_overhead(addr);
  580. else
  581. return iface->mtu - sec_overhead(addr);
  582. #else
  583. if(iface->forw != NULL)
  584. return iface->forw->mtu;
  585. else
  586. return iface->mtu;
  587. #endif
  588. }
  589. /* Given a destination address, return the IP address of the local
  590.  * interface that will be used to reach it. If there is no route
  591.  * to the destination, pick the first non-loopback address.
  592.  */
  593. int32
  594. locaddr(addr)
  595. int32 addr;
  596. {
  597. register struct route *rp;
  598. struct iface *ifp;
  599. if(ismyaddr(addr) != NULL)
  600. return addr; /* Loopback case */
  601. if((rp = rt_lookup(addr)) != NULL)
  602. ifp = rp->iface;
  603. else
  604. ifp = NULL;
  605. if(ifp == &Encap){
  606. if((rp = rt_lookup(rp->gateway)) != NULL)
  607. ifp = rp->iface;
  608. else
  609. ifp = NULL;
  610. }
  611. if(ifp == NULL){
  612. /* No route currently exists, so just pick the first real
  613.  * interface and use its address
  614.  */
  615. for(ifp = Ifaces;ifp != NULL;ifp = ifp->next){
  616. if(ifp != &Loopback && ifp != &Encap)
  617. break;
  618. }
  619. }
  620. if(ifp == NULL || ifp == &Loopback)
  621. return 0; /* No dice */
  622. if(ifp->forw != NULL)
  623. return ifp->forw->addr;
  624. else
  625. return ifp->addr;
  626. }
  627. #endif
  628. /* Look up target in hash table, matching the entry having the largest number
  629.  * of leading bits in common. Return default route if not found;
  630.  * if default route not set, return NULL
  631.  */
  632. struct route *
  633. rt_lookup(target)
  634. int32 target;
  635. {
  636. register struct route *rp;
  637. int bits;
  638. int32 tsave;
  639. int32 mask;
  640. struct rt_cache *rcp;
  641. Rtlookups++;
  642. /* Examine cache first */
  643. rcp = &Rt_cache[hash_ip(target)];
  644. if(target == rcp->target && (rp = rcp->route) != NULL){
  645. Rtchits++;
  646. return rp;
  647. }
  648. tsave = target;
  649. mask = ~0; /* All ones */
  650. for(bits = 31;bits >= 0; bits--){
  651. target &= mask;
  652. for(rp = Routes[bits][hash_ip(target)];rp != NULL;rp = rp->next){
  653. if(rp->target != target
  654.  || (rp->iface == &Encap && rp->gateway == tsave))
  655. continue;
  656. /* Stash in cache and return */
  657. rcp->target = tsave;
  658. rcp->route = rp;
  659. return rp;
  660. }
  661. mask <<= 1;
  662. }
  663. if(R_default.iface != NULL){
  664. rcp->target = tsave;
  665. rcp->route = &R_default;
  666. return &R_default;
  667. } else
  668. return NULL;
  669. }
  670. /* Search routing table for entry with specific width */
  671. struct route *
  672. rt_blookup(target,bits)
  673. int32 target;
  674. unsigned int bits;
  675. {
  676. register struct route *rp;
  677. if(bits == 0){
  678. if(R_default.iface != NULL)
  679. return &R_default;
  680. else
  681. return NULL;
  682. }
  683. /* Mask off target according to width */
  684. target &= ~0L << (32-bits);
  685. for(rp = Routes[bits-1][hash_ip(target)];rp != NULL;rp = rp->next){
  686. if(rp->target == target){
  687. return rp;
  688. }
  689. }
  690. return NULL;
  691. }
  692. /* Scan the routing table. For each entry, see if there's a less-specific
  693.  * one that points to the same interface and gateway. If so, delete
  694.  * the more specific entry, since it is redundant.
  695.  */
  696. void
  697. rt_merge(
  698. int trace
  699. ){
  700. int bits,i,j;
  701. struct route *rp,*rpnext,*rp1;
  702. for(bits=32;bits>0;bits--){
  703. for(i = 0;i<HASHMOD;i++){
  704. for(rp = Routes[bits-1][i];rp != NULL;rp = rpnext){
  705. rpnext = rp->next;
  706. for(j=bits-1;j >= 0;j--){
  707. if((rp1 = rt_blookup(rp->target,j)) != NULL
  708.  && rp1->iface == rp->iface
  709.  && rp1->gateway == rp->gateway){
  710. if(trace > 1)
  711. printf("merge %s %dn",
  712.  inet_ntoa(rp->target),
  713.  rp->bits);
  714. rt_drop(rp->target,rp->bits);
  715. break;
  716. }
  717. }
  718. }
  719. }
  720. }
  721. }