File:  [DragonFly] / src / usr.sbin / IPXrouted / tables.c
Revision 1.3: download - view: text, annotated - select for diffs
Thu Mar 11 09:38:59 2004 UTC (10 years, 7 months ago) by hmp
Branches: MAIN
CVS tags: HEAD, DragonFly_Stable, DragonFly_Snap29Sep2004, DragonFly_Snap13Sep2004, DragonFly_RELEASE_2_0_Slip, DragonFly_RELEASE_2_0, DragonFly_RELEASE_1_8_Slip, DragonFly_RELEASE_1_8, DragonFly_RELEASE_1_6_Slip, DragonFly_RELEASE_1_6, DragonFly_RELEASE_1_4_Slip, DragonFly_RELEASE_1_4, DragonFly_RELEASE_1_2_Slip, DragonFly_RELEASE_1_2, DragonFly_RELEASE_1_12_Slip, DragonFly_RELEASE_1_12, DragonFly_RELEASE_1_10_Slip, DragonFly_RELEASE_1_10, DragonFly_Preview, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Convert the code to ANSI style, and remove 'register' keywords.

No functional changes.

Submitted by:	Chris Pressey <cpressey@catseye.mine.nu>
             	(cpressey->commit_count++)

    1: /*
    2:  * Copyright (c) 1985, 1993
    3:  *	The Regents of the University of California.  All rights reserved.
    4:  *
    5:  * Copyright (c) 1995 John Hay.  All rights reserved.
    6:  *
    7:  * Redistribution and use in source and binary forms, with or without
    8:  * modification, are permitted provided that the following conditions
    9:  * are met:
   10:  * 1. Redistributions of source code must retain the above copyright
   11:  *    notice, this list of conditions and the following disclaimer.
   12:  * 2. Redistributions in binary form must reproduce the above copyright
   13:  *    notice, this list of conditions and the following disclaimer in the
   14:  *    documentation and/or other materials provided with the distribution.
   15:  * 3. All advertising materials mentioning features or use of this software
   16:  *    must display the following acknowledgement:
   17:  *	This product includes software developed by the University of
   18:  *	California, Berkeley and its contributors.
   19:  * 4. Neither the name of the University nor the names of its contributors
   20:  *    may be used to endorse or promote products derived from this software
   21:  *    without specific prior written permission.
   22:  *
   23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33:  * SUCH DAMAGE.
   34:  *
   35:  * $FreeBSD: src/usr.sbin/IPXrouted/tables.c,v 1.7 1999/08/28 01:15:05 peter Exp $
   36:  * $DragonFly: src/usr.sbin/IPXrouted/tables.c,v 1.3 2004/03/11 09:38:59 hmp Exp $
   37:  *
   38:  * @(#)tables.c	8.1 (Berkeley) 6/5/93
   39:  */
   40: 
   41: /*
   42:  * Routing Table Management Daemon
   43:  */
   44: #include "defs.h"
   45: #include <sys/ioctl.h>
   46: #include <errno.h>
   47: #include <stdlib.h>
   48: #include <unistd.h>
   49: 
   50: #ifndef DEBUG
   51: #define	DEBUG	0
   52: #endif
   53: 
   54: #define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));}
   55: 
   56: int	install = !DEBUG;		/* if 1 call kernel */
   57: int	delete = 1;
   58: 
   59: struct  rthash nethash[ROUTEHASHSIZ];
   60: 
   61: /*
   62:  * Lookup dst in the tables for an exact match.
   63:  */
   64: struct rt_entry *
   65: rtlookup(struct sockaddr *dst)
   66: {
   67: 	struct rt_entry *rt;
   68: 	struct rthash *rh;
   69: 	u_int hash;
   70: 	struct afhash h;
   71: 
   72: 	if (dst->sa_family >= AF_MAX)
   73: 		return (0);
   74: 	(*afswitch[dst->sa_family].af_hash)(dst, &h);
   75: 	hash = h.afh_nethash;
   76: 	rh = &nethash[hash & ROUTEHASHMASK];
   77: 	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
   78: 		if (rt->rt_hash != hash)
   79: 			continue;
   80: 		if (equal(&rt->rt_dst, dst))
   81: 			return (rt);
   82: 	}
   83: 	return (0);
   84: }
   85: 
   86: /*
   87:  * Find a route to dst as the kernel would.
   88:  */
   89: struct rt_entry *
   90: rtfind(struct sockaddr *dst)
   91: {
   92: 	struct rt_entry *rt;
   93: 	struct rthash *rh;
   94: 	u_int hash;
   95: 	struct afhash h;
   96: 	int af = dst->sa_family;
   97: 	int (*match)() = 0;
   98: 
   99: 	if (af >= AF_MAX)
  100: 		return (0);
  101: 	(*afswitch[af].af_hash)(dst, &h);
  102: 
  103: 	hash = h.afh_nethash;
  104: 	rh = &nethash[hash & ROUTEHASHMASK];
  105: 	match = afswitch[af].af_netmatch;
  106: 	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
  107: 		if (rt->rt_hash != hash)
  108: 			continue;
  109: 		if (rt->rt_dst.sa_family == af &&
  110: 		    (*match)(&rt->rt_dst, dst))
  111: 			return (rt);
  112: 	}
  113: 	return (0);
  114: }
  115: 
  116: void
  117: rtadd(struct sockaddr *dst, struct sockaddr *gate, short metric, short ticks,
  118:       int state)
  119: {
  120: 	struct afhash h;
  121: 	struct rt_entry *rt;
  122: 	struct rthash *rh;
  123: 	int af = dst->sa_family, flags;
  124: 	u_int hash;
  125: 
  126: 	FIXLEN(dst);
  127: 	FIXLEN(gate);
  128: 	if (af >= AF_MAX)
  129: 		return;
  130: 	(*afswitch[af].af_hash)(dst, &h);
  131: 	flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
  132: 	hash = h.afh_nethash;
  133: 	rh = &nethash[hash & ROUTEHASHMASK];
  134: 	rt = (struct rt_entry *)malloc(sizeof (*rt));
  135: 	if (rt == 0)
  136: 		return;
  137: 	rt->rt_hash = hash;
  138: 	rt->rt_dst = *dst;
  139: 	rt->rt_router = *gate;
  140: 	rt->rt_metric = metric;
  141: 	rt->rt_ticks = ticks;
  142: 	rt->rt_timer = 0;
  143: 	rt->rt_flags = RTF_UP | flags;
  144: 	rt->rt_state = state | RTS_CHANGED;
  145: 	rt->rt_ifp = if_ifwithnet(&rt->rt_router);
  146: 	rt->rt_clone = NULL;
  147: 	if (metric)
  148: 		rt->rt_flags |= RTF_GATEWAY;
  149: 	insque(rt, rh);
  150: 	TRACE_ACTION("ADD", rt);
  151: 	/*
  152: 	 * If the ioctl fails because the gateway is unreachable
  153: 	 * from this host, discard the entry.  This should only
  154: 	 * occur because of an incorrect entry in /etc/gateways.
  155: 	 */
  156: 	if (install && rtioctl(ADD, &rt->rt_rt) < 0) {
  157: 		if (errno != EEXIST)
  158: 			perror("SIOCADDRT");
  159: 		if (errno == ENETUNREACH) {
  160: 			TRACE_ACTION("DELETE", rt);
  161: 			remque(rt);
  162: 			free((char *)rt);
  163: 		}
  164: 	}
  165: }
  166: 
  167: void
  168: rtadd_clone(struct rt_entry *ort, struct sockaddr *dst, struct sockaddr *gate,
  169: 	    short metric, short ticks, int state)
  170: {
  171: 	struct afhash h;
  172: 	struct rt_entry *rt;
  173: 	struct rthash *rh;
  174: 	int af = dst->sa_family, flags;
  175: 	u_int hash;
  176: 
  177: 	FIXLEN(dst);
  178: 	FIXLEN(gate);
  179: 	if (af >= AF_MAX)
  180: 		return;
  181: 	(*afswitch[af].af_hash)(dst, &h);
  182: 	flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
  183: 	hash = h.afh_nethash;
  184: 	rh = &nethash[hash & ROUTEHASHMASK];
  185: 	rt = (struct rt_entry *)malloc(sizeof (*rt));
  186: 	if (rt == 0)
  187: 		return;
  188: 	rt->rt_hash = hash;
  189: 	rt->rt_dst = *dst;
  190: 	rt->rt_router = *gate;
  191: 	rt->rt_metric = metric;
  192: 	rt->rt_ticks = ticks;
  193: 	rt->rt_timer = 0;
  194: 	rt->rt_flags = RTF_UP | flags;
  195: 	rt->rt_state = state | RTS_CHANGED;
  196: 	rt->rt_ifp = if_ifwithnet(&rt->rt_router);
  197: 	rt->rt_clone = NULL;
  198: 	rt->rt_forw = NULL;
  199: 	rt->rt_back = NULL;
  200: 	if (metric)
  201: 		rt->rt_flags |= RTF_GATEWAY;
  202: 
  203: 	while(ort->rt_clone != NULL)
  204: 		ort = ort->rt_clone;
  205: 	ort->rt_clone = rt;
  206: 	TRACE_ACTION("ADD_CLONE", rt);
  207: }
  208: 
  209: void
  210: rtchange(struct rt_entry *rt, struct sockaddr *gate, short metric, short ticks)
  211: {
  212: 	int doioctl = 0, metricchanged = 0;
  213: 	struct rtuentry oldroute;
  214: 
  215: 	FIXLEN(gate);
  216: 	/*
  217:  	 * Handling of clones.
  218:  	 * When the route changed and it had clones, handle it special.
  219:  	 * 1. If the new route is cheaper than the clone(s), free the clones.
  220: 	 * 2. If the new route is the same cost, it may be one of the clones,
  221: 	 *    search for it and free it.
  222:  	 * 3. If the new route is more expensive than the clone(s), use the
  223:  	 *    values of the clone(s).
  224:  	 */
  225: 	if (rt->rt_clone) {
  226: 		if ((ticks < rt->rt_clone->rt_ticks) ||
  227: 		    ((ticks == rt->rt_clone->rt_ticks) &&
  228: 		     (metric < rt->rt_clone->rt_metric))) {
  229: 			/*
  230: 			 * Free all clones.
  231: 			 */
  232: 			struct rt_entry *trt, *nrt;
  233: 
  234: 			trt = rt->rt_clone;
  235: 			rt->rt_clone = NULL;
  236: 			while(trt) {
  237: 				nrt = trt->rt_clone;
  238: 				free((char *)trt);
  239: 				trt = nrt;
  240: 			}
  241: 		} else if ((ticks == rt->rt_clone->rt_ticks) &&
  242: 		     (metric == rt->rt_clone->rt_metric)) {
  243: 			struct rt_entry *prt, *trt;
  244: 
  245: 			prt = rt;
  246: 			trt = rt->rt_clone;
  247: 
  248: 			while(trt) {
  249: 				if (equal(&trt->rt_router, gate)) {
  250: 					prt->rt_clone = trt->rt_clone;
  251: 					free(trt);
  252: 					trt = prt->rt_clone;
  253: 				} else {
  254: 					prt = trt;
  255: 					trt = trt->rt_clone;
  256: 				}
  257: 			}
  258: 		} else {
  259: 			/*
  260: 			 * Use the values of the first clone. 
  261: 			 * Delete the corresponding clone.
  262: 			 */
  263: 			struct rt_entry *trt;
  264: 
  265: 			trt = rt->rt_clone;
  266: 			rt->rt_clone = rt->rt_clone->rt_clone;
  267: 			metric = trt->rt_metric;
  268: 			ticks = trt->rt_ticks;
  269: 			*gate = trt->rt_router;
  270: 			free((char *)trt);
  271: 		}
  272: 	}
  273: 
  274: 	if (!equal(&rt->rt_router, gate))
  275: 		doioctl++;
  276: 	if ((metric != rt->rt_metric) || (ticks != rt->rt_ticks))
  277: 		metricchanged++;
  278: 	if (doioctl || metricchanged) {
  279: 		TRACE_ACTION("CHANGE FROM", rt);
  280: 		if (doioctl) {
  281: 			oldroute = rt->rt_rt;
  282: 			rt->rt_router = *gate;
  283: 		}
  284: 		rt->rt_metric = metric;
  285: 		rt->rt_ticks = ticks;
  286: 		if ((rt->rt_state & RTS_INTERFACE) && metric) {
  287: 			rt->rt_state &= ~RTS_INTERFACE;
  288: 			if(rt->rt_ifp) 
  289: 				syslog(LOG_ERR,
  290: 				"changing route from interface %s (timed out)",
  291: 				rt->rt_ifp->int_name);
  292: 			else
  293: 				syslog(LOG_ERR,
  294: 				"changing route from interface ??? (timed out)");
  295: 		}
  296: 		if (metric)
  297: 			rt->rt_flags |= RTF_GATEWAY;
  298: 		else
  299: 			rt->rt_flags &= ~RTF_GATEWAY;
  300: 		rt->rt_ifp = if_ifwithnet(&rt->rt_router);
  301: 		rt->rt_state |= RTS_CHANGED;
  302: 		TRACE_ACTION("CHANGE TO", rt);
  303: 	}
  304: 	if (doioctl && install) {
  305: #ifndef RTM_ADD
  306: 		if (rtioctl(ADD, &rt->rt_rt) < 0)
  307: 		  syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
  308: 		   ipx_ntoa(&((struct sockaddr_ipx *)&rt->rt_dst)->sipx_addr),
  309: 		   ipx_ntoa(&((struct sockaddr_ipx *)&rt->rt_router)->sipx_addr));
  310: 		if (delete && rtioctl(DELETE, &oldroute) < 0)
  311: 			perror("rtioctl DELETE");
  312: #else
  313: 		if (delete == 0) {
  314: 			if (rtioctl(ADD, &rt->rt_rt) >= 0)
  315: 				return;
  316: 		} else {
  317: 			if (rtioctl(CHANGE, &rt->rt_rt) >= 0)
  318: 				return;
  319: 		}
  320: 	        syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
  321: 		   ipxdp_ntoa(&((struct sockaddr_ipx *)&rt->rt_dst)->sipx_addr),
  322: 		   ipxdp_ntoa(&((struct sockaddr_ipx *)&rt->rt_router)->sipx_addr));
  323: #endif
  324: 	}
  325: }
  326: 
  327: void
  328: rtdelete(struct rt_entry *rt)
  329: {
  330: 	struct sockaddr *sa = &(rt->rt_router);
  331: 
  332: 	FIXLEN(sa);
  333: 	sa = &(rt->rt_dst);
  334: 	FIXLEN(sa);
  335: 	if (rt->rt_clone) {
  336: 		/*
  337: 		 * If there is a clone we just do a rt_change to it.
  338: 		 */
  339: 		struct rt_entry *trt = rt->rt_clone;
  340: 		rtchange(rt, &trt->rt_router, trt->rt_metric, trt->rt_ticks);
  341: 		return;
  342: 	}
  343: 	if (rt->rt_state & RTS_INTERFACE) {
  344: 		if (rt->rt_ifp)
  345: 			syslog(LOG_ERR, 
  346: 				"deleting route to interface %s (timed out)",
  347: 				rt->rt_ifp->int_name);
  348: 		else
  349: 			syslog(LOG_ERR, 
  350: 				"deleting route to interface ??? (timed out)");
  351: 	}
  352: 	TRACE_ACTION("DELETE", rt);
  353: 	if (install && rtioctl(DELETE, &rt->rt_rt) < 0)
  354: 		perror("rtioctl DELETE");
  355: 	remque(rt);
  356: 	free((char *)rt);
  357: }
  358: 
  359: void
  360: rtinit(void)
  361: {
  362: 	struct rthash *rh;
  363: 
  364: 	for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
  365: 		rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
  366: }
  367: int seqno;
  368: 
  369: int
  370: rtioctl(int action, struct rtuentry *ort)
  371: {
  372: #ifndef RTM_ADD
  373: 	if (install == 0)
  374: 		return (errno = 0);
  375: 
  376: 	ort->rtu_rtflags = ort->rtu_flags;
  377: 
  378: 	switch (action) {
  379: 
  380: 	case ADD:
  381: 		return (ioctl(s, SIOCADDRT, (char *)ort));
  382: 
  383: 	case DELETE:
  384: 		return (ioctl(s, SIOCDELRT, (char *)ort));
  385: 
  386: 	default:
  387: 		return (-1);
  388: 	}
  389: #else /* RTM_ADD */
  390: 	struct {
  391: 		struct rt_msghdr w_rtm;
  392: 		struct sockaddr w_dst;
  393: 		struct sockaddr w_gate;
  394: 		struct sockaddr_ipx w_netmask;
  395: 	} w;
  396: #define rtm w.w_rtm
  397: 
  398: 	bzero((char *)&w, sizeof(w));
  399: 	rtm.rtm_msglen = sizeof(w);
  400: 	rtm.rtm_version = RTM_VERSION;
  401: 	rtm.rtm_type = (action == ADD ? RTM_ADD :
  402: 				(action == DELETE ? RTM_DELETE : RTM_CHANGE));
  403: 	rtm.rtm_flags = ort->rtu_flags;
  404: 	rtm.rtm_seq = ++seqno;
  405: 	rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
  406: 	bcopy((char *)&ort->rtu_dst, (char *)&w.w_dst, sizeof(w.w_dst));
  407: 	bcopy((char *)&ort->rtu_router, (char *)&w.w_gate, sizeof(w.w_gate));
  408: 	w.w_gate.sa_family = w.w_dst.sa_family = AF_IPX;
  409: 	w.w_gate.sa_len = w.w_dst.sa_len = sizeof(w.w_dst);
  410: 	if (rtm.rtm_flags & RTF_HOST) {
  411: 		rtm.rtm_msglen -= sizeof(w.w_netmask);
  412: 	} else {
  413: 		rtm.rtm_addrs |= RTA_NETMASK;
  414: 		w.w_netmask = ipx_netmask;
  415: 		rtm.rtm_msglen -= sizeof(w.w_netmask) - ipx_netmask.sipx_len;
  416: 	}
  417: 	errno = 0;
  418: 	return write(r, (char *)&w, rtm.rtm_msglen);
  419: #endif  /* RTM_ADD */
  420: }