4 Copyright 1995 Philip Homburg
21 #define OROUTE_STATIC_NR 16
22 #define OROUTE_HASH_ASS_NR 4
23 #define OROUTE_HASH_NR 32
24 #define OROUTE_HASH_MASK (OROUTE_HASH_NR-1)
26 #define hash_oroute(port_nr, ipaddr, hash_tmp) (hash_tmp= (ipaddr), \
27 hash_tmp= (hash_tmp >> 20) ^ hash_tmp, \
28 hash_tmp= (hash_tmp >> 10) ^ hash_tmp, \
29 hash_tmp= (hash_tmp >> 5) ^ hash_tmp, \
30 (hash_tmp + (port_nr)) & OROUTE_HASH_MASK)
32 typedef struct oroute_hash
38 PRIVATE oroute_t oroute_table
[OROUTE_NR
];
39 PRIVATE oroute_t
*oroute_head
;
40 PRIVATE
int static_oroute_nr
;
41 PRIVATE oroute_hash_t oroute_hash_table
[OROUTE_HASH_NR
][OROUTE_HASH_ASS_NR
];
44 #define IROUTE_HASH_ASS_NR 4
45 #define IROUTE_HASH_NR 32
46 #define IROUTE_HASH_MASK (IROUTE_HASH_NR-1)
48 #define hash_iroute(port_nr, ipaddr, hash_tmp) (hash_tmp= (ipaddr), \
49 hash_tmp= (hash_tmp >> 20) ^ hash_tmp, \
50 hash_tmp= (hash_tmp >> 10) ^ hash_tmp, \
51 hash_tmp= (hash_tmp >> 5) ^ hash_tmp, \
52 (hash_tmp + (port_nr)) & IROUTE_HASH_MASK)
54 typedef struct iroute_hash
60 PRIVATE iroute_t iroute_table
[IROUTE_NR
];
61 PRIVATE iroute_hash_t iroute_hash_table
[IROUTE_HASH_NR
][IROUTE_HASH_ASS_NR
];
63 FORWARD oroute_t
*oroute_find_ent
ARGS(( int port_nr
, ipaddr_t dest
));
64 FORWARD
void oroute_del
ARGS(( oroute_t
*oroute
));
65 FORWARD oroute_t
*sort_dists
ARGS(( oroute_t
*oroute
));
66 FORWARD oroute_t
*sort_gws
ARGS(( oroute_t
*oroute
));
67 FORWARD
void oroute_uncache_nw
ARGS(( ipaddr_t dest
, ipaddr_t netmask
));
68 FORWARD
void iroute_uncache_nw
ARGS(( ipaddr_t dest
, ipaddr_t netmask
));
70 PUBLIC
void ipr_init()
76 for (i
= 0, oroute
= oroute_table
; i
<OROUTE_NR
; i
++, oroute
++)
77 oroute
->ort_flags
= ORTF_EMPTY
;
79 assert(OROUTE_HASH_ASS_NR
== 4);
81 for (i
= 0, iroute
= iroute_table
; i
<IROUTE_NR
; i
++, iroute
++)
82 iroute
->irt_flags
= IRTF_EMPTY
;
83 assert(IROUTE_HASH_ASS_NR
== 4);
87 PUBLIC iroute_t
*iroute_frag(port_nr
, dest
)
92 iroute_hash_t
*iroute_hash
;
93 iroute_hash_t tmp_hash
;
94 iroute_t
*iroute
, *bestroute
;
95 unsigned long hash_tmp
;
98 hash
= hash_iroute(port_nr
, dest
, hash_tmp
);
99 iroute_hash
= &iroute_hash_table
[hash
][0];
100 if (iroute_hash
[0].irh_addr
== dest
)
101 iroute
= iroute_hash
[0].irh_route
;
102 else if (iroute_hash
[1].irh_addr
== dest
)
104 tmp_hash
= iroute_hash
[1];
105 iroute_hash
[1]= iroute_hash
[0];
106 iroute_hash
[0]= tmp_hash
;
107 iroute
= tmp_hash
.irh_route
;
109 else if (iroute_hash
[2].irh_addr
== dest
)
111 tmp_hash
= iroute_hash
[2];
112 iroute_hash
[2]= iroute_hash
[1];
113 iroute_hash
[1]= iroute_hash
[0];
114 iroute_hash
[0]= tmp_hash
;
115 iroute
= tmp_hash
.irh_route
;
117 else if (iroute_hash
[3].irh_addr
== dest
)
119 tmp_hash
= iroute_hash
[3];
120 iroute_hash
[3]= iroute_hash
[2];
121 iroute_hash
[2]= iroute_hash
[1];
122 iroute_hash
[1]= iroute_hash
[0];
123 iroute_hash
[0]= tmp_hash
;
124 iroute
= tmp_hash
.irh_route
;
132 for (i
= 0, iroute
= iroute_table
; i
< IROUTE_NR
; i
++, iroute
++)
134 if (!(iroute
->irt_flags
& IRTF_INUSE
))
136 if (((dest
^ iroute
->irt_dest
) & iroute
->irt_subnetmask
) != 0)
144 /* More specific netmasks are better */
145 if (iroute
->irt_subnetmask
!= bestroute
->irt_subnetmask
)
147 /* Using two ntohl macros in one expression
148 * is not allowed (tmp_l is modified twice)
150 tmp_mask
= ntohl(iroute
->irt_subnetmask
);
151 if (tmp_mask
> ntohl(bestroute
->irt_subnetmask
))
156 /* Dynamic routes override static routes */
157 if ((iroute
->irt_flags
& IRTF_STATIC
) !=
158 (bestroute
->irt_flags
& IRTF_STATIC
))
160 if (bestroute
->irt_flags
& IRTF_STATIC
)
165 /* A route to the local interface give an opportunity
168 if (iroute
->irt_port
!= bestroute
->irt_port
)
170 if (iroute
->irt_port
== port_nr
)
175 if (bestroute
== NULL
)
178 iroute_hash
[3]= iroute_hash
[2];
179 iroute_hash
[2]= iroute_hash
[1];
180 iroute_hash
[1]= iroute_hash
[0];
181 iroute_hash
[0].irh_addr
= dest
;
182 iroute_hash
[0].irh_route
= bestroute
;
187 PUBLIC
int oroute_frag(port_nr
, dest
, ttl
, msgsize
, nexthop
)
196 oroute
= oroute_find_ent(port_nr
, dest
);
197 if (!oroute
|| oroute
->ort_dist
> ttl
)
199 if (msgsize
&& oroute
->ort_mtu
&&
200 oroute
->ort_mtu
< msgsize
)
205 *nexthop
= oroute
->ort_gateway
;
210 PUBLIC
int ipr_add_oroute(port_nr
, dest
, subnetmask
, gateway
,
211 timeout
, dist
, mtu
, static_route
, preference
, oroute_p
)
225 oroute_t
*oroute
, *oldest_route
, *prev
, *nw_route
, *gw_route
,
227 time_t currtim
, exp_tim
, exp_tim_orig
;
232 exp_tim
= timeout
+currtim
;
237 printf("ip[%d]: adding oroute to ", port_nr
);
239 printf("["); writeIpAddr(subnetmask
); printf("] through ");
240 writeIpAddr(gateway
);
241 printf(" timeout: %lds, distance %d, pref %ld, mtu %d\n",
242 (long)timeout
/HZ
, dist
, (long)preference
, mtu
));
244 ip_port
= &ip_port_table
[port_nr
];
246 /* Validate gateway */
247 if (((gateway
^ ip_port
->ip_ipaddr
) & ip_port
->ip_subnetmask
) != 0)
249 DBLOCK(1, printf("ip[%d]: (ipr_add_oroute) invalid gateway: ",
250 port_nr
); writeIpAddr(gateway
); printf("\n"));
256 if (static_oroute_nr
>= OROUTE_STATIC_NR
)
262 /* Try to track down any old routes. */
263 for(oroute
= oroute_head
; oroute
; oroute
= oroute
->ort_nextnw
)
265 if (oroute
->ort_port
!= port_nr
)
267 if (oroute
->ort_dest
== dest
&&
268 oroute
->ort_subnetmask
== subnetmask
)
273 for(; oroute
; oroute
= oroute
->ort_nextgw
)
275 if (oroute
->ort_gateway
== gateway
)
278 for(; oroute
; oroute
= oroute
->ort_nextdist
)
280 if ((oroute
->ort_flags
& ORTF_STATIC
) != 0)
282 if (oroute
->ort_dist
> dist
)
288 assert(oroute
->ort_port
== port_nr
);
291 /* The new expire should not be later
292 * than the old expire time. Except for
293 * default routes, where the expire time
294 * is simple set to the new value.
296 exp_tim_orig
= oroute
->ort_exp_tim
;
298 exp_tim
= exp_tim_orig
;
299 else if (exp_tim_orig
&&
300 exp_tim
> exp_tim_orig
)
302 exp_tim
= exp_tim_orig
;
306 oroute
->ort_flags
= 0;
307 oldest_route
= oroute
;
311 if (oldest_route
== NULL
)
313 /* Look for an unused entry, or remove an existing one */
314 for (i
= 0, oroute
= oroute_table
; i
<OROUTE_NR
; i
++, oroute
++)
316 if ((oroute
->ort_flags
& ORTF_INUSE
) == 0)
318 if (oroute
->ort_exp_tim
&& oroute
->ort_exp_tim
<
322 oroute
->ort_flags
= 0;
325 if (oroute
->ort_flags
& ORTF_STATIC
)
327 if (oroute
->ort_dest
== 0)
329 /* Never remove default routes. */
332 if (oldest_route
== NULL
)
334 oldest_route
= oroute
;
337 if (oroute
->ort_timestamp
< oldest_route
->ort_timestamp
)
339 oldest_route
= oroute
;
343 oldest_route
= oroute
;
346 assert(oldest_route
);
347 oroute_del(oldest_route
);
348 oldest_route
->ort_flags
= 0;
352 oldest_route
->ort_dest
= dest
;
353 oldest_route
->ort_gateway
= gateway
;
354 oldest_route
->ort_subnetmask
= subnetmask
;
355 oldest_route
->ort_exp_tim
= exp_tim
;
356 oldest_route
->ort_timestamp
= currtim
;
357 oldest_route
->ort_dist
= dist
;
358 oldest_route
->ort_mtu
= mtu
;
359 oldest_route
->ort_port
= port_nr
;
360 oldest_route
->ort_flags
= ORTF_INUSE
;
361 oldest_route
->ort_pref
= preference
;
363 oldest_route
->ort_flags
|= ORTF_STATIC
;
365 /* Insert the route by tearing apart the routing table,
366 * and insert the entry during the reconstruction.
368 for (prev
= 0, nw_route
= oroute_head
; nw_route
;
369 prev
= nw_route
, nw_route
= nw_route
->ort_nextnw
)
371 if (nw_route
->ort_port
!= port_nr
)
373 if (nw_route
->ort_dest
== dest
&&
374 nw_route
->ort_subnetmask
== subnetmask
)
377 prev
->ort_nextnw
= nw_route
->ort_nextnw
;
379 oroute_head
= nw_route
->ort_nextnw
;
383 prev_route
= nw_route
;
384 for(prev
= NULL
, gw_route
= nw_route
; gw_route
;
385 prev
= gw_route
, gw_route
= gw_route
->ort_nextgw
)
387 if (gw_route
->ort_gateway
== gateway
)
390 prev
->ort_nextgw
= gw_route
->ort_nextgw
;
392 nw_route
= gw_route
->ort_nextgw
;
396 oldest_route
->ort_nextdist
= gw_route
;
397 gw_route
= oldest_route
;
398 gw_route
= sort_dists(gw_route
);
399 gw_route
->ort_nextgw
= nw_route
;
401 nw_route
= sort_gws(nw_route
);
402 nw_route
->ort_nextnw
= oroute_head
;
403 oroute_head
= nw_route
;
404 if (nw_route
!= prev_route
)
405 oroute_uncache_nw(nw_route
->ort_dest
, nw_route
->ort_subnetmask
);
406 if (oroute_p
!= NULL
)
407 *oroute_p
= oldest_route
;
411 PUBLIC
int ipr_del_oroute(port_nr
, dest
, subnetmask
, gateway
, static_route
)
421 for(i
= 0, oroute
= oroute_table
; i
<OROUTE_NR
; i
++, oroute
++)
423 if ((oroute
->ort_flags
& ORTF_INUSE
) == 0)
425 if (oroute
->ort_port
!= port_nr
||
426 oroute
->ort_dest
!= dest
||
427 oroute
->ort_subnetmask
!= subnetmask
||
428 oroute
->ort_gateway
!= gateway
)
432 if (!!(oroute
->ort_flags
& ORTF_STATIC
) != static_route
)
444 oroute
->ort_flags
&= ~ORTF_INUSE
;
450 PUBLIC
void ipr_chk_otab(port_nr
, addr
, mask
)
459 printf("ip[%d] (ipr_chk_otab): addr ", port_nr
);
468 /* Special hack to flush entries for an interface that
471 addr
= mask
= HTONL(0xffffffff);
474 for(i
= 0, oroute
= oroute_table
; i
<OROUTE_NR
; i
++, oroute
++)
476 if ((oroute
->ort_flags
& ORTF_INUSE
) == 0)
478 if (oroute
->ort_port
!= port_nr
||
479 ((oroute
->ort_gateway
^ addr
) & mask
) == 0)
483 DBLOCK(1, printf("ip[%d] (ipr_chk_otab): deleting route to ",
485 writeIpAddr(oroute
->ort_dest
);
487 writeIpAddr(oroute
->ort_gateway
);
490 if (oroute
->ort_flags
& ORTF_STATIC
)
493 oroute
->ort_flags
&= ~ORTF_INUSE
;
498 PUBLIC
void ipr_gateway_down(port_nr
, gateway
, timeout
)
509 for (i
= 0, route_ind
= oroute_table
; i
<OROUTE_NR
; i
++, route_ind
++)
511 if (!(route_ind
->ort_flags
& ORTF_INUSE
))
513 if (route_ind
->ort_gateway
!= gateway
)
515 if (route_ind
->ort_exp_tim
&& route_ind
->ort_exp_tim
< currtim
)
517 result
= ipr_add_oroute(port_nr
, route_ind
->ort_dest
,
518 route_ind
->ort_subnetmask
, gateway
,
519 timeout
, ORTD_UNREACHABLE
, route_ind
->ort_mtu
,
521 assert(result
== NW_OK
);
526 PUBLIC
void ipr_destunrch(port_nr
, dest
, netmask
, timeout
)
535 oroute
= oroute_find_ent(port_nr
, dest
);
539 DBLOCK(1, printf("ip[%d]: got a dest unreachable for ",
541 writeIpAddr(dest
); printf("but no route present\n"));
545 result
= ipr_add_oroute(port_nr
, dest
, netmask
, oroute
->ort_gateway
,
546 timeout
, ORTD_UNREACHABLE
, oroute
->ort_mtu
, FALSE
, 0, NULL
);
547 assert(result
== NW_OK
);
551 PUBLIC
void ipr_redirect(port_nr
, dest
, netmask
, old_gateway
, new_gateway
,
556 ipaddr_t old_gateway
;
557 ipaddr_t new_gateway
;
564 ip_port
= &ip_port_table
[port_nr
];
565 oroute
= oroute_find_ent(port_nr
, dest
);
569 DBLOCK(1, printf("ip[%d]: got a redirect for ", port_nr
);
570 writeIpAddr(dest
); printf("but no route present\n"));
573 if (oroute
->ort_gateway
!= old_gateway
)
575 DBLOCK(1, printf("ip[%d]: got a redirect from ", port_nr
);
576 writeIpAddr(old_gateway
); printf(" for ");
577 writeIpAddr(dest
); printf(" but curr gateway is ");
578 writeIpAddr(oroute
->ort_gateway
); printf("\n"));
581 if ((new_gateway
^ ip_port
->ip_ipaddr
) & ip_port
->ip_subnetmask
)
583 DBLOCK(1, printf("ip[%d]: redirect from ", port_nr
);
584 writeIpAddr(old_gateway
); printf(" for ");
585 writeIpAddr(dest
); printf(" but new gateway ");
586 writeIpAddr(new_gateway
);
587 printf(" is not on local subnet\n"));
590 if (oroute
->ort_flags
& ORTF_STATIC
)
592 if (oroute
->ort_dest
== dest
)
594 DBLOCK(1, printf("ip[%d]: got a redirect for ",
597 printf("but route is fixed\n"));
603 result
= ipr_add_oroute(port_nr
, dest
, netmask
,
604 oroute
->ort_gateway
, HZ
, ORTD_UNREACHABLE
,
605 oroute
->ort_mtu
, FALSE
, 0, NULL
);
606 assert(result
== NW_OK
);
608 result
= ipr_add_oroute(port_nr
, dest
, netmask
, new_gateway
,
609 timeout
, 1, oroute
->ort_mtu
, FALSE
, 0, NULL
);
610 assert(result
== NW_OK
);
614 PUBLIC
void ipr_ttl_exc(port_nr
, dest
, netmask
, timeout
)
624 oroute
= oroute_find_ent(port_nr
, dest
);
628 DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ",
630 writeIpAddr(dest
); printf("but no route present\n"));
634 new_dist
= oroute
->ort_dist
* 2;
635 if (new_dist
> IP_DEF_TTL
)
637 new_dist
= oroute
->ort_dist
+1;
638 if (new_dist
>= IP_DEF_TTL
)
640 DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ",
643 printf(" but dist is %d\n",
649 result
= ipr_add_oroute(port_nr
, dest
, netmask
, oroute
->ort_gateway
,
650 timeout
, new_dist
, oroute
->ort_mtu
, FALSE
, 0, NULL
);
651 assert(result
== NW_OK
);
654 PUBLIC
void ipr_mtu(port_nr
, dest
, mtu
, timeout
)
663 oroute
= oroute_find_ent(port_nr
, dest
);
667 DBLOCK(1, printf("ip[%d]: got a mtu exceeded for ",
669 writeIpAddr(dest
); printf("but no route present\n"));
673 if (mtu
< IP_MIN_MTU
)
675 if (oroute
->ort_mtu
&& mtu
>= oroute
->ort_mtu
)
676 return; /* Only decrease mtu */
678 result
= ipr_add_oroute(port_nr
, dest
, HTONL(0xffffffff),
679 oroute
->ort_gateway
, timeout
, oroute
->ort_dist
, mtu
,
681 assert(result
== NW_OK
);
685 PUBLIC
int ipr_get_oroute(ent_no
, route_ent
)
687 nwio_route_t
*route_ent
;
691 if (ent_no
<0 || ent_no
>= OROUTE_NR
)
694 oroute
= &oroute_table
[ent_no
];
695 if ((oroute
->ort_flags
& ORTF_INUSE
) && oroute
->ort_exp_tim
&&
696 oroute
->ort_exp_tim
< get_time())
699 oroute
->ort_flags
&= ~ORTF_INUSE
;
702 route_ent
->nwr_ent_no
= ent_no
;
703 route_ent
->nwr_ent_count
= OROUTE_NR
;
704 route_ent
->nwr_dest
= oroute
->ort_dest
;
705 route_ent
->nwr_netmask
= oroute
->ort_subnetmask
;
706 route_ent
->nwr_gateway
= oroute
->ort_gateway
;
707 route_ent
->nwr_dist
= oroute
->ort_dist
;
708 route_ent
->nwr_flags
= NWRF_EMPTY
;
709 if (oroute
->ort_flags
& ORTF_INUSE
)
711 route_ent
->nwr_flags
|= NWRF_INUSE
;
712 if (oroute
->ort_flags
& ORTF_STATIC
)
713 route_ent
->nwr_flags
|= NWRF_STATIC
;
715 route_ent
->nwr_pref
= oroute
->ort_pref
;
716 route_ent
->nwr_mtu
= oroute
->ort_mtu
;
717 route_ent
->nwr_ifaddr
= ip_get_ifaddr(oroute
->ort_port
);
722 PRIVATE oroute_t
*oroute_find_ent(port_nr
, dest
)
727 oroute_hash_t
*oroute_hash
;
728 oroute_hash_t tmp_hash
;
729 oroute_t
*oroute
, *bestroute
;
731 unsigned long hash_tmp
;
736 hash
= hash_oroute(port_nr
, dest
, hash_tmp
);
737 oroute_hash
= &oroute_hash_table
[hash
][0];
738 if (oroute_hash
[0].orh_addr
== dest
)
739 oroute
= oroute_hash
[0].orh_route
;
740 else if (oroute_hash
[1].orh_addr
== dest
)
742 tmp_hash
= oroute_hash
[1];
743 oroute_hash
[1]= oroute_hash
[0];
744 oroute_hash
[0]= tmp_hash
;
745 oroute
= tmp_hash
.orh_route
;
747 else if (oroute_hash
[2].orh_addr
== dest
)
749 tmp_hash
= oroute_hash
[2];
750 oroute_hash
[2]= oroute_hash
[1];
751 oroute_hash
[1]= oroute_hash
[0];
752 oroute_hash
[0]= tmp_hash
;
753 oroute
= tmp_hash
.orh_route
;
755 else if (oroute_hash
[3].orh_addr
== dest
)
757 tmp_hash
= oroute_hash
[3];
758 oroute_hash
[3]= oroute_hash
[2];
759 oroute_hash
[2]= oroute_hash
[1];
760 oroute_hash
[1]= oroute_hash
[0];
761 oroute_hash
[0]= tmp_hash
;
762 oroute
= tmp_hash
.orh_route
;
768 assert(oroute
->ort_port
== port_nr
);
769 if (oroute
->ort_exp_tim
&& oroute
->ort_exp_tim
<currtim
)
772 oroute
->ort_flags
&= ~ORTF_INUSE
;
779 for (oroute
= oroute_head
; oroute
; oroute
= oroute
->ort_nextnw
)
781 if (((dest
^ oroute
->ort_dest
) & oroute
->ort_subnetmask
) != 0)
783 if (oroute
->ort_port
!= port_nr
)
790 assert(oroute
->ort_dest
!= bestroute
->ort_dest
);
791 /* Using two ntohl macros in one expression
792 * is not allowed (tmp_l is modified twice)
794 tmp_mask
= ntohl(oroute
->ort_subnetmask
);
795 if (tmp_mask
> ntohl(bestroute
->ort_subnetmask
))
801 if (bestroute
== NULL
)
804 oroute_hash
[3]= oroute_hash
[2];
805 oroute_hash
[2]= oroute_hash
[1];
806 oroute_hash
[1]= oroute_hash
[0];
807 oroute_hash
[0].orh_addr
= dest
;
808 oroute_hash
[0].orh_route
= bestroute
;
814 PRIVATE
void oroute_del(oroute
)
817 oroute_t
*prev
, *nw_route
, *gw_route
, *dist_route
, *prev_route
;
820 printf("ip[%d]: deleting oroute to ", oroute
->ort_port
);
821 writeIpAddr(oroute
->ort_dest
);
822 printf("["); writeIpAddr(oroute
->ort_subnetmask
);
823 printf("] through ");
824 writeIpAddr(oroute
->ort_gateway
);
826 " timestamp %lds, timeout: %lds, distance %d pref %ld mtu %ld ",
827 (long)oroute
->ort_timestamp
/HZ
,
828 (long)oroute
->ort_exp_tim
/HZ
, oroute
->ort_dist
,
829 (long)oroute
->ort_pref
, (long)oroute
->ort_mtu
);
830 printf("flags 0x%x\n", oroute
->ort_flags
));
832 for (prev
= NULL
, nw_route
= oroute_head
; nw_route
;
833 prev
= nw_route
, nw_route
= nw_route
->ort_nextnw
)
835 if (oroute
->ort_port
== nw_route
->ort_port
&&
836 oroute
->ort_dest
== nw_route
->ort_dest
&&
837 oroute
->ort_subnetmask
== nw_route
->ort_subnetmask
)
844 prev
->ort_nextnw
= nw_route
->ort_nextnw
;
846 oroute_head
= nw_route
->ort_nextnw
;
847 prev_route
= nw_route
;
848 for (prev
= NULL
, gw_route
= nw_route
; gw_route
;
849 prev
= gw_route
, gw_route
= gw_route
->ort_nextgw
)
851 if (oroute
->ort_gateway
== gw_route
->ort_gateway
)
856 prev
->ort_nextgw
= gw_route
->ort_nextgw
;
858 nw_route
= gw_route
->ort_nextgw
;
859 for (prev
= NULL
, dist_route
= gw_route
; dist_route
;
860 prev
= dist_route
, dist_route
= dist_route
->ort_nextdist
)
862 if (oroute
== dist_route
)
867 prev
->ort_nextdist
= dist_route
->ort_nextdist
;
869 gw_route
= dist_route
->ort_nextdist
;
870 gw_route
= sort_dists(gw_route
);
871 if (gw_route
!= NULL
)
873 gw_route
->ort_nextgw
= nw_route
;
876 nw_route
= sort_gws(nw_route
);
877 if (nw_route
!= NULL
)
879 nw_route
->ort_nextnw
= oroute_head
;
880 oroute_head
= nw_route
;
882 if (nw_route
!= prev_route
)
884 oroute_uncache_nw(prev_route
->ort_dest
,
885 prev_route
->ort_subnetmask
);
890 PRIVATE oroute_t
*sort_dists(oroute
)
893 oroute_t
*r
, *prev
, *best
, *best_prev
;
894 int best_dist
, best_pref
;
897 best_dist
= best_pref
= 0;
899 for (prev
= NULL
, r
= oroute
; r
; prev
= r
, r
= r
->ort_nextdist
)
902 ; /* Force assignment to best */
903 else if (r
->ort_dist
!= best_dist
)
905 if (r
->ort_dist
> best_dist
)
910 if (r
->ort_pref
<= best_pref
)
915 best_dist
= r
->ort_dist
;
916 best_pref
= r
->ort_pref
;
920 assert(oroute
== NULL
);
925 assert(best
== oroute
);
928 best_prev
->ort_nextdist
= best
->ort_nextdist
;
929 best
->ort_nextdist
= oroute
;
934 PRIVATE oroute_t
*sort_gws(oroute
)
937 oroute_t
*r
, *prev
, *best
, *best_prev
;
938 int best_dist
, best_pref
;
941 best_dist
= best_pref
= 0;
943 for (prev
= NULL
, r
= oroute
; r
; prev
= r
, r
= r
->ort_nextgw
)
946 ; /* Force assignment to best */
947 else if (r
->ort_dist
!= best_dist
)
949 if (r
->ort_dist
> best_dist
)
954 if (r
->ort_pref
<= best_pref
)
959 best_dist
= r
->ort_dist
;
960 best_pref
= r
->ort_pref
;
964 assert(oroute
== NULL
);
969 assert(best
== oroute
);
972 best_prev
->ort_nextgw
= best
->ort_nextgw
;
973 best
->ort_nextgw
= oroute
;
978 PRIVATE
void oroute_uncache_nw(dest
, netmask
)
983 oroute_hash_t
*oroute_hash
;
985 for (i
= 0, oroute_hash
= &oroute_hash_table
[0][0];
986 i
<OROUTE_HASH_NR
; i
++, oroute_hash
+= OROUTE_HASH_ASS_NR
)
988 for (j
= 0; j
<OROUTE_HASH_ASS_NR
; j
++)
990 if (((oroute_hash
[j
].orh_addr
^ dest
) & netmask
) == 0)
992 oroute_hash
[j
].orh_addr
= 0;
993 oroute_hash
[j
].orh_route
= NULL
;
1004 PUBLIC
int ipr_get_iroute(ent_no
, route_ent
)
1006 nwio_route_t
*route_ent
;
1010 if (ent_no
<0 || ent_no
>= IROUTE_NR
)
1013 iroute
= &iroute_table
[ent_no
];
1015 route_ent
->nwr_ent_no
= ent_no
;
1016 route_ent
->nwr_ent_count
= IROUTE_NR
;
1017 route_ent
->nwr_dest
= iroute
->irt_dest
;
1018 route_ent
->nwr_netmask
= iroute
->irt_subnetmask
;
1019 route_ent
->nwr_gateway
= iroute
->irt_gateway
;
1020 route_ent
->nwr_dist
= iroute
->irt_dist
;
1021 route_ent
->nwr_flags
= NWRF_EMPTY
;
1022 if (iroute
->irt_flags
& IRTF_INUSE
)
1024 route_ent
->nwr_flags
|= NWRF_INUSE
;
1025 if (iroute
->irt_flags
& IRTF_STATIC
)
1026 route_ent
->nwr_flags
|= NWRF_STATIC
;
1027 if (iroute
->irt_dist
== IRTD_UNREACHABLE
)
1028 route_ent
->nwr_flags
|= NWRF_UNREACHABLE
;
1030 route_ent
->nwr_pref
= 0;
1031 route_ent
->nwr_mtu
= iroute
->irt_mtu
;
1032 route_ent
->nwr_ifaddr
= ip_get_ifaddr(iroute
->irt_port
);
1037 PUBLIC
int ipr_add_iroute(port_nr
, dest
, subnetmask
, gateway
,
1038 dist
, mtu
, static_route
, iroute_p
)
1041 ipaddr_t subnetmask
;
1046 iroute_t
**iroute_p
;
1049 iroute_t
*iroute
, *unused_route
;
1052 ip_port
= &ip_port_table
[port_nr
];
1055 if (((gateway
^ ip_port
->ip_ipaddr
) & ip_port
->ip_subnetmask
) != 0 &&
1058 DBLOCK(1, printf("ip[%d] (ipr_add_iroute): invalid gateway: ",
1060 writeIpAddr(gateway
); printf("\n"));
1067 /* Static routes are not reused automatically, so we look
1068 * for an unused entry.
1070 for(i
= 0, iroute
= iroute_table
; i
<IROUTE_NR
; i
++, iroute
++)
1072 if ((iroute
->irt_flags
& IRTF_INUSE
) == 0)
1076 unused_route
= iroute
;
1080 /* Try to track down any old routes, and look for an
1083 for(i
= 0, iroute
= iroute_table
; i
<IROUTE_NR
; i
++, iroute
++)
1085 if ((iroute
->irt_flags
& IRTF_INUSE
) == 0)
1087 unused_route
= iroute
;
1090 if ((iroute
->irt_flags
& IRTF_STATIC
) != 0)
1092 if (iroute
->irt_port
!= port_nr
||
1093 iroute
->irt_dest
!= dest
||
1094 iroute
->irt_subnetmask
!= subnetmask
||
1095 iroute
->irt_gateway
!= gateway
)
1102 unused_route
= iroute
;
1105 if (unused_route
== NULL
)
1107 iroute
= unused_route
;
1109 iroute
->irt_port
= port_nr
;
1110 iroute
->irt_dest
= dest
;
1111 iroute
->irt_subnetmask
= subnetmask
;
1112 iroute
->irt_gateway
= gateway
;
1113 iroute
->irt_dist
= dist
;
1114 iroute
->irt_mtu
= mtu
;
1115 iroute
->irt_flags
= IRTF_INUSE
;
1117 iroute
->irt_flags
|= IRTF_STATIC
;
1119 iroute_uncache_nw(iroute
->irt_dest
, iroute
->irt_subnetmask
);
1120 if (iroute_p
!= NULL
)
1126 PUBLIC
int ipr_del_iroute(port_nr
, dest
, subnetmask
, gateway
, static_route
)
1129 ipaddr_t subnetmask
;
1136 /* Try to track down any old routes, and look for an
1139 for(i
= 0, iroute
= iroute_table
; i
<IROUTE_NR
; i
++, iroute
++)
1141 if ((iroute
->irt_flags
& IRTF_INUSE
) == 0)
1143 if (iroute
->irt_port
!= port_nr
||
1144 iroute
->irt_dest
!= dest
||
1145 iroute
->irt_subnetmask
!= subnetmask
||
1146 iroute
->irt_gateway
!= gateway
)
1150 if (!!(iroute
->irt_flags
& IRTF_STATIC
) != static_route
)
1158 iroute_uncache_nw(iroute
->irt_dest
, iroute
->irt_subnetmask
);
1159 iroute
->irt_flags
= IRTF_EMPTY
;
1164 PUBLIC
void ipr_chk_itab(port_nr
, addr
, mask
)
1173 printf("ip[%d] (ipr_chk_itab): addr ", port_nr
);
1182 /* Special hack to flush entries for an interface that
1185 addr
= mask
= HTONL(0xffffffff);
1188 for(i
= 0, iroute
= iroute_table
; i
<IROUTE_NR
; i
++, iroute
++)
1190 if ((iroute
->irt_flags
& IRTF_INUSE
) == 0)
1192 if (iroute
->irt_port
!= port_nr
)
1194 if (iroute
->irt_gateway
== 0)
1196 /* Special case: attached network. */
1197 if (iroute
->irt_subnetmask
== mask
&&
1198 iroute
->irt_dest
== (addr
& mask
))
1200 /* Nothing changed. */
1204 if (((iroute
->irt_gateway
^ addr
) & mask
) == 0)
1207 DBLOCK(1, printf("ip[%d] (ipr_chk_itab): deleting route to ",
1209 writeIpAddr(iroute
->irt_dest
);
1211 writeIpAddr(iroute
->irt_gateway
);
1214 iroute_uncache_nw(iroute
->irt_dest
, iroute
->irt_subnetmask
);
1215 iroute
->irt_flags
&= ~IRTF_INUSE
;
1220 PRIVATE
void iroute_uncache_nw(dest
, netmask
)
1225 iroute_hash_t
*iroute_hash
;
1227 for (i
= 0, iroute_hash
= &iroute_hash_table
[0][0];
1228 i
<IROUTE_HASH_NR
; i
++, iroute_hash
+= IROUTE_HASH_ASS_NR
)
1230 for (j
= 0; j
<IROUTE_HASH_ASS_NR
; j
++)
1232 if (((iroute_hash
[j
].irh_addr
^ dest
) &
1235 iroute_hash
[j
].irh_addr
= 0;
1236 iroute_hash
[j
].irh_route
= NULL
;
1245 * $PchId: ipr.c,v 1.23 2003/01/22 11:49:58 philip Exp $