[comp.sources.misc] v16i082: ATOS - Application-level Type Of Service routing, Part01/01

jude@orville.nas.nasa.go (Jude A George) (01/29/91)

Submitted-by: jude@orville.nas.nasa.go (Jude A George)
Posting-number: Volume 16, Issue 82
Archive-name: atos/part01

ATOS is a small bit of code that provides network applications with a way
to choose the best network path to a destination when multiple paths are
available.  For example, when two hosts share both an Ethernet and an
UltraNet, they want to route all of their ftp traffic through their UltraNet
interfaces and all of their telnets and rlogins through the Ethernet.
The higher-bandwidth network is better suited for ftp's large-packet
data transfers than for telnet/rlogin "tinygrams".  The proper interface
must be chosen by the application.  A name server ordinarily returns all of
the network addresses for a host, but in no particular order.  Thus the
calling code cannot normally make an intelligent choice of address.  Until
true type-of-service routing is handled by IP and the routing hardware,
we have to solve this problem at a higher layer.

The software does require a resolver that has the capability of returning
multiple (all available) network addresses in the hostent data structure.
If you use YP or a host table, as opposed to a name server, and can map only
one IP address to a hostname, ATOS will not help you.

Jude George

NAS Program, M/S 258-6
NASA Ames Research Center
Moffett Field, CA 94086

jude@nas.nasa.gov

----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	atos
# This archive created: Fri Jan 25 17:56:59 1991
export PATH; PATH=/bin:/usr/bin:$PATH
if test ! -d 'atos'
then
	mkdir 'atos'
fi
cd 'atos'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XATOS --  Application-Level Type-of-Service Routing
X
Xv0.96 October 24, 1990
X
XATOS is a small bit of code that provides network applications with a way
Xto choose the best network path to a destination when multiple paths are
Xavailable.  For example, when two hosts share both an Ethernet and an
XUltraNet, they want to route all of their ftp traffic through their UltraNet
Xinterfaces and all of their telnets and rlogins through the Ethernet.
XThe higher-bandwidth network is better suited for ftp's large-packet
Xdata transfers than for telnet/rlogin "tinygrams".  The proper interface
Xmust be chosen by the application.  A name server ordinarily returns all of
Xthe network addresses for a host, but in no particular order.  Thus the
Xcalling code cannot normally make an intelligent choice of address.  Until
Xtrue type-of-service routing is handled by IP and the routing hardware,
Xwe have to solve this problem at a higher layer.
X
XThe software does require a resolver that has the capability of returning
Xmultiple (all available) network addresses in the hostent data structure.
XIf you use YP or a host table, as opposed to a name server, and can map only
Xone IP address to a hostname, ATOS will not help you. 
X
XYou should have the following files:
X
Xatos/
X  README
X  makefile
X  man3/
X    atos.3n
X    sortaddrbytos.3n
X    tosroutes.3n
X  netinet/
X    atos.c
X    atos.h
X  test.c
X  tosroutes
X
XThe makefile requires this directory structure to build the test program.
X
XTo use ATOS, compile the source into any C code that makes a call to the
Xresolver.  After a gethostbyname() or similar call, call sortaddrbytos()
Xwith a pointer to the hostent structure and a TOS code.  This function will
Xsort the h_addr_list IP addresses in order of descending preference, with
Xthe "best" address at the top.  The sorting is done under the assumption
Xthat the calling code will choose its addresses from the top of the list,
Xmoving downwards.  An /etc/tosroutes file must also be present, which tells
Xthe sorting routine how to compare the available networks against the TOS
Xcodes.  The codes and the format of this file are explained in the man page.
XThe example file included with this distribution will not work for your
Xnetwork.
X
XTo get the maximum benefit from ATOS, incorporate it into heavily used
Xnetwork software such as ftp and telnet, on hosts that are homed on multiple
Xnetworks.  Use a tos code of "T" for ftp, and "D" for telnet.  This will
Xmaximize throughput on the one, and minimize delay on the other.  Caveat:
Xftp uses the same port for its control connection and its data connection.
XAll frequently-used network/tos combinations should be listed in the
X/etc/tosroutes file.
X
XA simple test program has been included.  To run the test, call the program
Xwith two parameters: the host to reach, and a TOS code.  The program will
Xreturn the unsorted address list from the nameserver, followed by the same
Xaddress list in the order sortaddrbytos() thinks it should be.  For example,
X"./test jonathan T" returns:
X
XOriginal address list for jonathan.nas.nasa.gov:
X
Xaddress: 129.99.23.30
Xaddress: 129.99.32.30
Xaddress: 129.99.48.30
Xaddress: 129.99.64.30
Xaddress: 129.99.196.30
X
XSorted address list for jonathan.nas.nasa.gov:
X
Xaddress: 129.99.196.30
Xaddress: 129.99.48.30
Xaddress: 129.99.64.30
Xaddress: 129.99.32.30
Xaddress: 129.99.23.30
X
XIf you find that the test returns only one address for a machine that is
Xknown to have multiple interfaces, it means that the host on which the
Xtest is running is probably using a host table, either directly or through
XYP.
X
XATOS has been tested on a VAX 11/780 running BSD 4.3 UNIX, a Cray Y-MP
Xrunning UNICOS 5.1.10, an Amdahl 5880 running UTS 1.2.4, a Sun 3/260 and
XSun 4/65 running SunOS 4.0.3, and  a Silicon Graphics Iris 4D/320 running
XIRIX 3.3.  ATOS is very simple in design, but because of its nature (it
Xdestructively modifies data structures in the calling code) any usage
Xshould be tested extensively.
X
XMany thanks go to John Lekashman and David Iannucci for their suggestions.
X
XJude George
X
XNAS Program, M/S 258-6
XNASA Ames Research Center
XMoffett Field, CA 94086
X
Xjude@nas.nasa.gov
SHAR_EOF
fi
if test ! -d 'netinet'
then
	mkdir 'netinet'
fi
cd 'netinet'
if test -f 'atos.h'
then
	echo shar: "will not over-write existing file 'atos.h'"
else
sed 's/^X//' << \SHAR_EOF > 'atos.h'
X/*\
X *	ATOS -- Application-Level Type-of-Service Routing
X *
X *	FILE: atos.h
X *
X *	v0.96, 24 October 1990
X *
X *	sortaddrbytos() takes a host entry (struct hostent *) and a tos
X *	(type of service) code, and rearranges the h_addr_list in the
X *	host entry in order of preference for that particular tos.
X *	This is an attempt to solve the problem of routing by tos above
X *	the ip layer, when multiple physical network paths to the
X *	destination host are available.
X *
X *	The function relies on the existence of a file /etc/tosroutes
X *	with each line consisting of three fields: tos, addr, pref.
X *	The tos field is a single character indicating the network
X *	requirements of the calling code: "D" for low delay, "T" for
X *	high throughput, or "R" for high reliability.  Multiple
X *	requirements (low delay AND high throughput) may not be entered.
X *	The addr field is either a network #, subnet #, or full IP #,
X *	and specifies a possible destination.  Typically, only subnet
X *	#'s are useful.  The pref field is a number from 0 to 9 indicating
X *	that tos' preference for that network address, 0 being the most
X *	preferred addr for that tos.
X *
X *	There should be an entry for every local network or subnet,
X *	as a net/subnet that the function does not recognize will always
X *	be sorted down to the bottom of the list.
X *	sortaddrbytos() returns 0, or -1 if there was an error.
X\*/
X
X#define	ADDRSIZE	16
X#define	STRSIZE		16
X#define	TOSFILE		"/etc/tosroutes"
X#define	ALT_TOSFILE	"./tosroutes"
Xint sortaddrbytos();
SHAR_EOF
fi
if test -f 'atos.c'
then
	echo shar: "will not over-write existing file 'atos.c'"
else
sed 's/^X//' << \SHAR_EOF > 'atos.c'
X/*\
X *	ATOS -- Application-Level Type-of-Service Routing
X *
X *	FILE: atos.c
X *
X *	v0.96, 24 October 1990
X *
X *	sortaddrbytos() takes a host entry (struct hostent *) and a tos
X *	(type of service) code, and rearranges the h_addr_list in the
X *	host entry in order of preference for that particular tos.
X *	This is an attempt to solve the problem of routing by tos above
X *	the ip layer, when multiple physical network paths to the
X *	destination host are available.
X *
X *	The function relies on the existence of a file /etc/tosroutes
X *	with each line consisting of three fields: tos, addr, pref.
X *	The tos field is a single character indicating the network
X *	requirements of the calling code: "D" for low delay, "T" for
X *	high throughput, or "R" for high reliability.  Multiple
X *	requirements (low delay AND high throughput) may not be entered.
X *	The addr field is either a network #, subnet #, or full IP #,
X *	and specifies a possible destination.  Typically, only subnet
X *	#'s are useful.  The pref field is a number from 0 to 9 indicating
X *	that tos' preference for that network address, 0 being the most
X *	preferred addr for that tos.
X *
X *	There should be an entry for every local network or subnet,
X *	as a net/subnet that the function does not recognize will always
X *	be sorted down to the bottom of the list.
X *	sortaddrbytos() returns 0, or -1 if there was an error.
X\*/
X
X#include <stdio.h>
X#include <netdb.h>
X
X#include <netinet/atos.h>
X
Xstruct tos_ent {
X    struct tos_ent *next;
X    char addr[ADDRSIZE];
X    char tos[STRSIZE];
X    int pref;
X};
X
X/*\
X * Insert an entry into the tos list, sorted by pref.  Low pref value,
X * i.e. more preferred entries, will be placed closer to the head of
X * the list.
X\*/
Xtos_insert(entry,list_ptr)
Xstruct tos_ent *entry;
Xstruct tos_ent **list_ptr;
X{
X    struct tos_ent *cur_ent, *prev_ent;
X
X    if (*list_ptr == NULL) {
X	*list_ptr = entry;
X	return;
X    }
X    prev_ent = NULL;
X    cur_ent = *list_ptr;
X    while(cur_ent != NULL) {
X	if (entry->pref <= cur_ent->pref) {
X	    entry->next = cur_ent;
X	    if (prev_ent == NULL)
X		*list_ptr = entry;
X	    else
X		prev_ent->next = entry;
X	    break;
X	}
X	prev_ent = cur_ent;
X	cur_ent = cur_ent->next;
X    }
X}
X
X/*\
X * Sort host_entry->h_addr_list based on tos and the tos file.  Note that
X * a network or subnet entry in the tos file can match a full IP address
X * from the h_addr_list.  (e.g. 129.99 matches 129.99.23.20).
X\*/
Xint sortaddrbytos(host_entry, tos)
Xstruct hostent *host_entry;
Xchar  *tos;
X{
X    struct tos_ent *tos_list, *cur_ent;
X    unsigned char **cur_addr, **cur_addr_top;
X    unsigned char *temp;
X    char addrbuf[ADDRSIZE];
X    int numents = 0;
X    int rval = 1;
X    FILE *fp;
X
X    /*
X     * If host entry is NULL, return with an error.
X     */
X    if (host_entry == NULL)
X	return -1;
X
X    /*
X     * Open the tos file for reading; if file doesn't exist, search for
X     * an alternate.  If still not found, return with an error but don't
X     * change the addr_list.
X     */
X    fp = fopen(TOSFILE,"r");
X    if (fp == NULL) {
X	fp = fopen(ALT_TOSFILE,"r");
X	if (fp == NULL)
X	    return -1;
X    }
X
X    /*
X     * Read all tos file entries that have our tos code, and make a list,
X     * sorting in order of pref.
X     */
X    tos_list = NULL;
X    while(rval != EOF) {
X	cur_ent = (struct tos_ent *)malloc(sizeof(struct tos_ent));
X	cur_ent->pref = -1;
X	cur_ent->next = NULL;
X	bzero(cur_ent->addr, ADDRSIZE);
X	bzero(cur_ent->tos, STRSIZE);
X	rval = fscanf(fp, "%s %s %d", cur_ent->tos, cur_ent->addr,
X		      &cur_ent->pref);
X	if (!strcmp(cur_ent->tos, tos))
X	    tos_insert(cur_ent, &tos_list);
X    }
X    fclose(fp);
X
X    /*
X     * Sort the h_addr_list in order of "preference", using the sorted
X     * tos_list as a guide.  Go down the tos_list; for each entry, look
X     * through the h_addr_list from cur_addr_top downwards; if a match
X     * is found in the h_addr_list, swap that match with the cur_addr_top
X     * of the h_addr_list and lower the cur_addr_top by one.  Keep looking
X     * down the list in case there are multiple matches.  Cur_addr_top is
X     * initially at the head of the h_addr_list.  Note: the string
X     * comparison is performed only up to the length of the tos file's addr
X     * entry, to allow a network or subnet id to match a host's ip address.
X     */
X    cur_addr_top = (unsigned char **)host_entry->h_addr_list;
X    for (cur_ent = tos_list; cur_ent != NULL; cur_ent = cur_ent->next)
X	for (cur_addr = cur_addr_top; *cur_addr != 0; cur_addr++) {
X	    bzero(addrbuf, ADDRSIZE);
X	    sprintf(addrbuf, "%u.%u.%u.%u", (*cur_addr)[0], (*cur_addr)[1],
X		    (*cur_addr)[2], (*cur_addr)[3]);
X	    if (!strncmp(addrbuf, cur_ent->addr, strlen(cur_ent->addr))) {
X		temp = *cur_addr_top;
X		*cur_addr_top++ = *cur_addr;
X		*cur_addr = temp;
X	    }
X	}
X    return 0;
X}
SHAR_EOF
fi
cd ..
if test -f 'test.c'
then
	echo shar: "will not over-write existing file 'test.c'"
else
sed 's/^X//' << \SHAR_EOF > 'test.c'
X/*\
X *	FILE: test.c
X *
X *	Test function for sortaddrbytos().
X\*/
X
X#include <stdio.h>
X#include <netdb.h>
X
X#include <netinet/atos.h>
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X    struct hostent *test_host;
X    unsigned char **addr_list, **i;
X
X    if (argc != 3) {
X	printf("Usage:  %s hostname tos\n", argv[0]);
X	exit(0);
X    }
X
X    test_host = gethostbyname(argv[1]);
X
X    if (test_host == NULL) {
X	printf("Bad host name.\n");
X	exit(-1);
X    }
X
X    addr_list = (unsigned char **)test_host->h_addr_list;
X
X    printf("\nOriginal address list for %s:\n\n", test_host->h_name);
X    for(i = addr_list; *i != 0; i++)
X	printf("address: %u.%u.%u.%u\n",(*i)[0],(*i)[1],(*i)[2],(*i)[3]);
X
X    sortaddrbytos(test_host, argv[2]);
X
X    printf("\nSorted address list for %s:\n\n", test_host->h_name);
X    for(i = addr_list; *i != 0; i++)
X	printf("address: %u.%u.%u.%u\n",(*i)[0],(*i)[1],(*i)[2],(*i)[3]);
X}
SHAR_EOF
fi
if test -f 'makefile'
then
	echo shar: "will not over-write existing file 'makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile'
X#
X#	Makefile for sortaddrbytos() test.  If you do not have a system
X#	similar to BSD 4.3, you may have to modify the CFLAGS to include
X#	additional libraries, or change the #include paths.  This makefile
X#	should work, unchanged, on the following systems:  BSD 4.3,
X#	IRIX 3.3, SunOS 4.0.3.  For UNICOS, add -lbsd -lnet.  For UTS,
X#	add -lnet -la.
X#
X#	The install option will install the ATOS source files and man
X#	page in the appropriate directories, if you have write-access.
X#	I will not presume to guess which protection bits you use.
X#	You must also create an /etc/tosroutes file as explained in the
X#	documentation.
X#
X
XSRCDIR=		/usr/include/netinet
XINCLDIR=	/usr/include/netinet
XMANDIR=		/usr/man/man3
X
XMAN=		man3/atos.3n man3/tosroutes.3n man3/sortaddrbytos.3n
X
XCFLAGS=		-O -I.
X
Xall:		test
X
Xtest:		netinet/atos.h netinet/atos.c test.c
X		${CC} ${CFLAGS} netinet/atos.c test.c -o test
X
Xinstall:	netinet/atos.h netinet/atos.c ${MAN}
X		cp netinet/atos.c ${SRCDIR}
X		cp netinet/atos.h ${INCLDIR}
X		cp ${MAN} ${MANDIR}
X
Xclean:		
X		rm -f atos.o test.o
X
Xspotless:	
X		rm -f atos.o test.o test
SHAR_EOF
fi
if test -f 'tosroutes'
then
	echo shar: "will not over-write existing file 'tosroutes'"
else
sed 's/^X//' << \SHAR_EOF > 'tosroutes'
XT	129.99.23	5
XT	129.99.32	5
XT	129.99.64	5
XT	129.99.48	5
XT	129.99.196	2
XD	129.99.23	3
XD	129.99.196	4
XD	129.99.32	4
XD	129.99.48	4
XD	129.99.64	4
XD	128.102		7
XT	128.102		7
SHAR_EOF
fi
if test ! -d 'man3'
then
	mkdir 'man3'
fi
cd 'man3'
if test -f 'sortaddrbytos.3n'
then
	echo shar: "will not over-write existing file 'sortaddrbytos.3n'"
else
sed 's/^X//' << \SHAR_EOF > 'sortaddrbytos.3n'
X.\" @(#)sortaddrbytos.3n 0.96 90/10/24;
X.TH SORTADDRBYTOS 3N "24 October 1990"
X.SH NAME
Xsortaddrbytos \- sort host addresses by type of service and preferred
Xnetwork
X.SH SYNOPSIS
X.nf
X.ft B
X#include <stdio.h>
X#include <netdb.h>
X#include <tosroute.h>
X.LP
X.ft B
Xint sortaddrbytos(host_entry, tos)
Xstruct hostent *host_entry;
Xchar *tos;
X.ft R
X.fi
X.IX  "tosroutes file"  ""  "\fLtosroutes\fP \(em network preference codes"
X.SH DESCRIPTION
X.BR sortaddrbytos()
Xtakes a host entry and an internet-standard tos (type of service) code
Xand rearranges the h_addr_list in the host entry in order of preference
Xfor that particular tos.  This is an attempt to solve the problem of routing
Xby tos above the ip layer, when multiple physical network paths to the
Xdestination host are available.  A name server ordinarily returns all of
Xthe network addresses for a host, but in no particular order.  Thus
Xthe calling code cannot normally make an intelligent choice of address.
X.BR sortaddrbytos()
Xshould be called immediately after
X.BR gethostent(),
X.BR gethostbyname(),
Xor
X.BR gethostbyaddr()
Xin the application program.
X.LP
XThe function relies on the existence of a
Xfile /etc/tosroutes with each line consisting of three fields: tos, addr,
Xand pref.  
XThe tos field is a single character indicating the
Xnetwork requirements of the calling code: "D" for low delay,
X"T" for high throughput, or "R" for high reliability.  Multiple
Xrequirements (low delay AND high throughput) may not be entered.
XThe addr field is either a network id, subnet id, or full IP address,
Xand specifies a possible destination.  Typically, only subnet ids are
Xuseful.  The pref field is a number from 0 to 9 indicating that tos'
Xpreference for that network address, 0 being the most preferred addr
Xfor that tos.  Fields may be separated by tabs or spaces.  
X.LP
XThere should be an entry for every local subnet, as a net/subnet that the
Xfunction does not recognize will always be sorted to the bottom of the
Xlist.  Of course, hosts connected to different subnets will have slightly
Xdifferent entries in their tosroutes files.
X.SH EXAMPLE
X.LP
XHere is portion of an example /etc/tosroutes file for a host that can reach
Xfour networks; 191.255.1 is a low-throughput Ethernet, 191.255.2 is a
Xmedium-throughput FDDI ring, 191.255.3 is a high-throughput UltraNet, and
X191.255.10 is a low-throughput, high-delay satellite link.  In addition,
X191.255.5 is another Ethernet that is an extra hop away, and hence may
Xexperience slightly higher delay than the first Ethernet.
X.LP
X    T       191.255.1       5
X    T       191.255.2       2
X    T       191.255.3       0
X    T       191.255.10      9
X    T       191.255.5       5
X    D       191.255.1       2
X    D       191.255.2       2
X    D       191.255.3       2
X    D       191.255.10      9
X    D       191.255.5       3
X.LP
XA program that wants the best path for high-throughput traffic (e.g. ftp)
Xwould call sortaddrbytos() with "T" as the tos code.  If the destination
Xhost has interfaces 191.255.1.50, 191.255.2, and 191.255.3, the sorting
Xalgorithm will return them in the order 191.255.3, 191.255.2, 191.255.1.
X.SH FILES
X/etc/tosroutes
X.LP
XIf tosroutes is not found in /etc, the current working directory of the
Xcalling code will be searched.
X.SH SEE ALSO
Xgethostent(3N), services(5)
X.SH BUGS
XA name server should be used instead of a static file.  Ideally, this
Xfunction should be integrated into
X.BR gethostent()
Xand the resolver library.
X.LP
XThe function is not very forgiving of errors in the tosroutes file.
X
XThe function uses fscanf() and sprintf().
X
X.SH AUTHOR
XJude Anand George (jude@nas.nasa.gov)
SHAR_EOF
fi
if test -f 'tosroutes.3n'
then
	echo shar: "will not over-write existing file 'tosroutes.3n'"
else
sed 's/^X//' << \SHAR_EOF > 'tosroutes.3n'
X.so man3/sortaddrbytos.3n
X.\" @(#)tosroutes.3n 0.96 90/10/24;
SHAR_EOF
fi
if test -f 'atos.3n'
then
	echo shar: "will not over-write existing file 'atos.3n'"
else
sed 's/^X//' << \SHAR_EOF > 'atos.3n'
X.so man3/sortaddrbytos.3n
X.\" @(#)atos.3n 0.96 90/10/24;
SHAR_EOF
fi
cd ..
cd ..
exit 0
#	End of shell archive

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.