ftp.nice.ch/pub/next/unix/network/system/gated.2.1pl2.NI.bs.tar.gz#/gated-2.1/src/if_rt.c

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.