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.