This is if_rt.c in view mode; [Download] [Up]
/*
* $Header: /disk/d/src/devel/gated/dist/src/RCS/if_rt.c,v 2.1 92/02/24 14:12:38 jch Exp $
*/
/*%Copyright%*/
/************************************************************************
* *
* GateD, Release 2 *
* *
* Copyright (c) 1990,1991,1992 by Cornell University *
* All rights reserved. *
* *
* THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY *
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT *
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY *
* AND FITNESS FOR A PARTICULAR PURPOSE. *
* *
* Royalty-free licenses to redistribute GateD Release *
* 2 in whole or in part may be obtained by writing to: *
* *
* GateDaemon Project *
* Information Technologies/Network Resources *
* 143 Caldwell Hall *
* Cornell University *
* Ithaca, NY 14853-2602 *
* *
* GateD is based on Kirton's EGP, UC Berkeley's routing *
* daemon (routed), and DCN's HELLO routing Protocol. *
* Development of Release 2 has been supported by the *
* National Science Foundation. *
* *
* Please forward bug fixes, enhancements and questions to the *
* gated mailing list: gated-people@gated.cornell.edu. *
* *
* Authors: *
* *
* Jeffrey C Honig <jch@gated.cornell.edu> *
* Scott W Brim <swb@gated.cornell.edu> *
* *
*************************************************************************
* *
* Portions of this software may fall under the following *
* copyrights: *
* *
* Copyright (c) 1988 Regents of the University of California. *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms are *
* permitted provided that the above copyright notice and *
* this paragraph are duplicated in all such forms and that *
* any documentation, advertising materials, and other *
* materials related to such distribution and use *
* acknowledge that the software was developed by the *
* University of California, Berkeley. The name of the *
* University may not be used to endorse or promote *
* products derived from this software without specific *
* prior written permission. THIS SOFTWARE IS PROVIDED *
* ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
* *
************************************************************************/
/*
* Routines for handling routes to interfaces
*/
#include "include.h"
/*******************************************************************************/
/* if_rtdown updates the routing table when an interface has transitioned */
/* down. It is also used at init when an interface is found to be down */
/* by having init_flag be TRUE. */
/* */
/* At init time, routes to direct interfaces are assumed to be */
/* RTPROTO_KERNEL as read from the kernel's routing table. When an */
/* interface transitions down routes are assumed to be RTPROTO_DIRECT. */
/* */
/* If the interface is point-to-point, the hostroute to the other side */
/* of the link is deleted. If not, the route to the attached interface */
/* is deleted. If the interface is subnetted, the internal route to */
/* the whole net is deleted if this interface is the gateway. */
/*******************************************************************************/
void
if_rtdown(ifp)
if_entry *ifp;
{
sockaddr_un dst;
rt_entry *rt;
if (ifp->int_state & IFS_LOOPBACK) {
/* Delete or declare unreachable route to loopback host */
if (rt = rt_locate(RTS_HOSTROUTE, &ifp->int_addr, RTPROTO_DIRECT)) {
(void) rt_unreach(rt);
}
} else if (ifp->int_state & IFS_POINTOPOINT) {
/* Delete or declare unreachable route to host at other end of point-to-point link */
if (rt = rt_locate(RTS_HOSTROUTE, &ifp->int_dstaddr, RTPROTO_DIRECT)) {
(void) rt_unreach(rt);
}
} else {
/* Delete or declare unreachable route to subnet and full net */
sockclear_in(&dst);
if (rt = rt_locate(RTS_INTERIOR, &ifp->int_subnet, RTPROTO_DIRECT)) {
if (rt->rt_ifp == ifp) {
(void) rt_unreach(rt);
}
}
if (ifp->int_state & IFS_SUBNET) {
if (rt = rt_locate(RTS_INTERIOR, &ifp->int_net, RTPROTO_DIRECT)) {
if (rt->rt_ifp == ifp) {
(void) rt_unreach(rt);
}
}
}
}
}
/*******************************************************************************/
/* if_rtbest() is used to make sure the route to an interface is the one */
/* with the best metric. */
/*******************************************************************************/
static void
if_rtbest(ifp, dst, mask, iflags)
if_entry *ifp;
sockaddr_un *dst;
sockaddr_un *mask;
flag_t iflags;
{
rt_entry *rt;
if (rt = rt_locate(RTS_INTERIOR, dst, RTPROTO_DIRECT)) {
/* Route exists */
if ((ifp->int_metric < rt->rt_ifp->int_metric) || (rt->rt_state & RTS_HOLDDOWN)) {
/* This interface is the most attractive route, update existing route */
rt->rt_state = (rt->rt_state & ~RTS_NOAGE) | (iflags & RTS_NOAGE);
(void) rt_change(rt,
&ifp->int_addr,
ifp->int_metric,
(time_t) 0,
ifp->int_preference);
}
} else {
/* No route to the net exists, add an interface route to our tables only */
(void) rt_add(dst,
mask,
&ifp->int_addr,
(gw_entry *) 0,
ifp->int_metric,
iflags | RTS_INTERIOR,
RTPROTO_DIRECT,
0,
(time_t) 0,
ifp->int_preference);
}
}
/*******************************************************************************/
/* if_rtup processes an interface transition to up or an interface that */
/* is up at init time. */
/* */
/* If the interface is point-to-point, any host route to that interface */
/* is deleted and a host route to the interface with a protocol of */
/* RTPROTO_DIRECT is added to the routing table. */
/* */
/* For non-point-to-point interfaces, the route to the attached network */
/* is deleted from the routing table and a RTPROTO_DIRECT route is */
/* added. */
/* */
/* If non-point-to-point subnetted interfaces, the routing table is */
/* searched for a direct route to this interface */
/*******************************************************************************/
void
if_rtup(ifp)
if_entry *ifp;
{
sockaddr_un dst;
rt_entry *rt;
flag_t iflags = 0;
if (ifp->int_state & IFS_NOAGE) {
iflags |= RTS_NOAGE;
}
if (ifp->int_state & IFS_LOOPBACK) {
/* Delete all routes to the loopback host and then add a host route to it */
if (rt = rt_locate(RTS_HOSTROUTE, &ifp->int_addr, RTPROTO_DIRECT)) {
(void) rt_unreach(rt);
}
(void) rt_add(&ifp->int_addr,
&ifp->int_subnetmask,
&ifp->int_addr,
(gw_entry *) 0,
ifp->int_metric,
RTS_HOSTROUTE | iflags,
RTPROTO_DIRECT,
0,
(time_t) 0,
ifp->int_preference);
} else if (ifp->int_state & IFS_POINTOPOINT) {
/* Delete all routes to the destination of this interface */
iflags |= RTS_POINTOPOINT;
if (rt = rt_locate(RTS_HOSTROUTE, &ifp->int_dstaddr, RTPROTO_DIRECT)) {
(void) rt_unreach(rt);
}
/* Add a route to the interface. For a P2P link, the gateway */
/* should be the dstaddr, not the interface address. */
(void) rt_add(&ifp->int_dstaddr,
&ifp->int_subnetmask,
&ifp->int_dstaddr,/* Gateway is destination */
(gw_entry *) 0,
ifp->int_metric,
RTS_HOSTROUTE | iflags,
RTPROTO_DIRECT,
0,
(time_t) 0,
ifp->int_preference);
} else {
/* Delete any routes to this subnet and add an interface route to */
/* it if we are the most attractive. */
sockclear_in(&dst);
if_rtbest(ifp, &ifp->int_subnet, &ifp->int_subnetmask, iflags | ((ifp->int_state & IFS_SUBNET) ? RTS_SUBNET : 0));
iflags |= RTS_NOTINSTALL;
if (ifp->int_state & IFS_SUBNET) {
/* Interface is to a subnet. Must update route to the main net */
/* if this is the most attractive interface to it. */
if_rtbest(ifp, &ifp->int_net, &ifp->int_netmask, iflags);
}
}
}
/*******************************************************************************/
/* if_rtupdate() is used when a routing packet is received from an */
/* interface to make sure that a route to this interface exists. */
/* */
/* If the route to this interface exists, it's metric is set to the */
/* interface metric of this interface and it's timer is reset. If this */
/* is a subnet route, the internal route to the main net is also updated. */
/* */
/* If the route to this interface does not exist, if_rtup is called to */
/* add it to the routing table. */
/*******************************************************************************/
void
if_rtupdate(ifp)
if_entry *ifp;
{
int open = FALSE;
rt_entry *rt;
sockaddr_un dst;
if (ifp->int_state & IFS_LOOPBACK) {
/* Refresh the loopback route */
if ((rt = rt_locate(RTS_HOSTROUTE, &ifp->int_addr,
RTPROTO_DIRECT)) && (rt->rt_ifp == ifp) && (ifp->int_state & IFS_UP)) {
open = TRUE;
rt_open(if_task);
if (rt->rt_metric != ifp->int_metric) {
(void) rt_change(rt,
&rt->rt_router,
ifp->int_metric,
rt->rt_timer_max,
ifp->int_preference);
} else {
rt_refresh(rt);
}
} else {
if_check(if_task->task_timer[0], (time_t) 0);
}
} else if (ifp->int_state & IFS_POINTOPOINT) {
/* Refresh a pointopoint route */
if ((rt = rt_locate(RTS_HOSTROUTE, &ifp->int_addr,
RTPROTO_DIRECT)) && (rt->rt_ifp == ifp) && (ifp->int_state & IFS_UP)) {
open = TRUE;
rt_open(if_task);
if (rt->rt_metric != ifp->int_metric) {
(void) rt_change(rt,
&rt->rt_router,
ifp->int_metric,
rt->rt_timer_max,
ifp->int_preference);
} else {
rt_refresh(rt);
}
} else {
if_check(if_task->task_timer[0], (time_t) 0);
}
} else {
/* If the route to this (sub)net is ours, refresh it. */
sockclear_in(&dst);
if ((rt = rt_locate(RTS_NETROUTE, &ifp->int_subnet, RTPROTO_DIRECT)) &&
(rt->rt_ifp == ifp) && (ifp->int_state & IFS_UP)) {
open = TRUE;
rt_open(if_task);
if (rt->rt_metric != ifp->int_metric) {
(void) rt_change(rt,
&rt->rt_router,
ifp->int_metric,
rt->rt_timer_max,
ifp->int_preference);
} else {
rt_refresh(rt);
}
} else {
if_check(if_task->task_timer[0], (time_t) 0);
}
if (ifp->int_state & IFS_SUBNET) {
/* Interface is to a subnet. Must update route to the main net */
/* if this is the most attractive interface to it. */
if (!open) {
open = TRUE;
rt_open(if_task);
}
if ((rt = rt_locate(RTS_NETROUTE, &ifp->int_net, RTPROTO_DIRECT)) &&
(rt->rt_ifp == ifp)) {
if (rt->rt_metric != ifp->int_metric) {
(void) rt_change(rt,
&rt->rt_router,
ifp->int_metric,
rt->rt_timer_max,
ifp->int_preference);
} else {
rt_refresh(rt);
}
} else {
/* Should never happen */
if_rtup(ifp);
}
}
}
if (open && rt_close(if_task, (gw_entry *) 0, 0)) {
task_flash(if_task);
}
}
/*******************************************************************************/
/* if_rtinit() initializes the interior routing table with direct nets as */
/* per the interface table. Such routes read from the kernel routing tables */
/* are deleted from the exterior routing table. */
/*******************************************************************************/
void
if_rtinit()
{
register if_entry *ifp;
trace(TR_RT, 0, NULL);
trace(TR_RT, 0, "if_rtinit: interior routes for direct interfaces:");
rt_open(if_task);
IF_LIST(ifp) {
/* If this interface can not hear it's own packets, or we are not actively participating in a routing protocol, */
/* mark the interface as passive. */
if ((ifp->int_state & IFS_SIMPLEX) ||
((ifp->int_state & (IFS_NORIPIN | IFS_NORIPOUT)) && (ifp->int_state & (IFS_NOHELLOIN | IFS_NOHELLOOUT))) ||
!if_rtactive) {
ifp->int_state |= IFS_NOAGE;
trace(TR_INT, 0, "if_rtinit: interface %s: %A marked passive",
ifp->int_name,
&ifp->int_addr);
}
if (ifp->int_state & IFS_UP) {
if_rtup(ifp);
} else {
if_rtdown(ifp);
}
} IF_LISTEND(ifp) ;
rt_close(if_task, (gw_entry *) 0, n_interfaces + 1);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.