410 lines
14 KiB
Perl
410 lines
14 KiB
Perl
.\" Copyright (c) 1986, 1993
|
|
.\" The Regents of the University of California. All rights reserved.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\" 3. All advertising materials mentioning features or use of this software
|
|
.\" must display the following acknowledgement:
|
|
.\" This product includes software developed by the University of
|
|
.\" California, Berkeley and its contributors.
|
|
.\" 4. Neither the name of the University nor the names of its contributors
|
|
.\" may be used to endorse or promote products derived from this software
|
|
.\" without specific prior written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
.\" SUCH DAMAGE.
|
|
.\"
|
|
.\" @(#)3.t 8.1 (Berkeley) 6/8/93
|
|
.\"
|
|
.\".ds RH "Network Library Routines
|
|
.bp
|
|
.nr H1 3
|
|
.nr H2 0
|
|
.bp
|
|
.LG
|
|
.B
|
|
.ce
|
|
3. NETWORK LIBRARY ROUTINES
|
|
.sp 2
|
|
.R
|
|
.NL
|
|
.PP
|
|
The discussion in section 2 indicated the possible need to
|
|
locate and construct network addresses when using the
|
|
interprocess communication facilities in a distributed
|
|
environment. To aid in this task a number of routines
|
|
have been added to the standard C run-time library.
|
|
In this section we will consider the new routines provided
|
|
to manipulate network addresses. While the 4.4BSD networking
|
|
facilities support the Internet protocols
|
|
and the Xerox NS protocols,
|
|
most of the routines presented
|
|
in this section do not apply to the NS domain. Unless otherwise
|
|
stated, it should be assumed that the routines presented in this
|
|
section do not apply to the NS domain.
|
|
.PP
|
|
Locating a service on a remote host requires many levels of
|
|
mapping before client and server may
|
|
communicate. A service is assigned a name which is intended
|
|
for human consumption; e.g. \*(lqthe \fIlogin server\fP on host
|
|
monet\*(rq.
|
|
This name, and the name of the peer host, must then be translated
|
|
into network \fIaddresses\fP which are not necessarily suitable
|
|
for human consumption. Finally, the address must then used in locating
|
|
a physical \fIlocation\fP and \fIroute\fP to the service. The
|
|
specifics of these three mappings are likely to vary between
|
|
network architectures. For instance, it is desirable for a network
|
|
to not require hosts to
|
|
be named in such a way that their physical location is known by
|
|
the client host. Instead, underlying services in the network
|
|
may discover the actual location of the host at the time a client
|
|
host wishes to communicate. This ability to have hosts named in
|
|
a location independent manner may induce overhead in connection
|
|
establishment, as a discovery process must take place,
|
|
but allows a host to be physically mobile without requiring it to
|
|
notify its clientele of its current location.
|
|
.PP
|
|
Standard routines are provided for: mapping host names
|
|
to network addresses, network names to network numbers,
|
|
protocol names to protocol numbers, and service names
|
|
to port numbers and the appropriate protocol to
|
|
use in communicating with the server process. The
|
|
file <\fInetdb.h\fP> must be included when using any of these
|
|
routines.
|
|
.NH 2
|
|
Host names
|
|
.PP
|
|
An Internet host name to address mapping is represented by
|
|
the \fIhostent\fP structure:
|
|
.DS
|
|
.if t .ta 0.6i 1.1i 2.6i
|
|
struct hostent {
|
|
char *h_name; /* official name of host */
|
|
char **h_aliases; /* alias list */
|
|
int h_addrtype; /* host address type (e.g., AF_INET) */
|
|
int h_length; /* length of address */
|
|
char **h_addr_list; /* list of addresses, null terminated */
|
|
};
|
|
|
|
#define h_addr h_addr_list[0] /* first address, network byte order */
|
|
.DE
|
|
The routine \fIgethostbyname\fP(3N) takes an Internet host name
|
|
and returns a \fIhostent\fP structure,
|
|
while the routine \fIgethostbyaddr\fP(3N)
|
|
maps Internet host addresses into a \fIhostent\fP structure.
|
|
.PP
|
|
The official name of the host and its public aliases are
|
|
returned by these routines,
|
|
along with the address type (family) and a null terminated list of
|
|
variable length address. This list of addresses is
|
|
required because it is possible
|
|
for a host to have many addresses, all having the same name.
|
|
The \fIh_addr\fP definition is provided for backward compatibility,
|
|
and is defined to be the first address in the list of addresses
|
|
in the \fIhostent\fP structure.
|
|
.PP
|
|
The database for these calls is provided either by the
|
|
file \fI/etc/hosts\fP (\fIhosts\fP\|(5)),
|
|
or by use of a nameserver, \fInamed\fP\|(8).
|
|
Because of the differences in these databases and their access protocols,
|
|
the information returned may differ.
|
|
When using the host table version of \fIgethostbyname\fP,
|
|
only one address will be returned, but all listed aliases will be included.
|
|
The nameserver version may return alternate addresses,
|
|
but will not provide any aliases other than one given as argument.
|
|
.PP
|
|
Unlike Internet names, NS names are always mapped into host
|
|
addresses by the use of a standard NS \fIClearinghouse service\fP,
|
|
a distributed name and authentication server. The algorithms
|
|
for mapping NS names to addresses via a Clearinghouse are
|
|
rather complicated, and the routines are not part of the
|
|
standard libraries. The user-contributed Courier (Xerox
|
|
remote procedure call protocol) compiler contains routines
|
|
to accomplish this mapping; see the documentation and
|
|
examples provided therein for more information. It is
|
|
expected that almost all software that has to communicate
|
|
using NS will need to use the facilities of
|
|
the Courier compiler.
|
|
.PP
|
|
An NS host address is represented by the following:
|
|
.DS
|
|
union ns_host {
|
|
u_char c_host[6];
|
|
u_short s_host[3];
|
|
};
|
|
|
|
union ns_net {
|
|
u_char c_net[4];
|
|
u_short s_net[2];
|
|
};
|
|
|
|
struct ns_addr {
|
|
union ns_net x_net;
|
|
union ns_host x_host;
|
|
u_short x_port;
|
|
};
|
|
.DE
|
|
The following code fragment inserts a known NS address into
|
|
a \fIns_addr\fP:
|
|
.DS
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netns/ns.h>
|
|
...
|
|
u_long netnum;
|
|
struct sockaddr_ns dst;
|
|
...
|
|
bzero((char *)&dst, sizeof(dst));
|
|
|
|
/*
|
|
* There is no convenient way to assign a long
|
|
* integer to a ``union ns_net'' at present; in
|
|
* the future, something will hopefully be provided,
|
|
* but this is the portable way to go for now.
|
|
* The network number below is the one for the NS net
|
|
* that the desired host (gyre) is on.
|
|
*/
|
|
netnum = htonl(2266);
|
|
dst.sns_addr.x_net = *(union ns_net *) &netnum;
|
|
dst.sns_family = AF_NS;
|
|
|
|
/*
|
|
* host 2.7.1.0.2a.18 == "gyre:Computer Science:UofMaryland"
|
|
*/
|
|
dst.sns_addr.x_host.c_host[0] = 0x02;
|
|
dst.sns_addr.x_host.c_host[1] = 0x07;
|
|
dst.sns_addr.x_host.c_host[2] = 0x01;
|
|
dst.sns_addr.x_host.c_host[3] = 0x00;
|
|
dst.sns_addr.x_host.c_host[4] = 0x2a;
|
|
dst.sns_addr.x_host.c_host[5] = 0x18;
|
|
dst.sns_addr.x_port = htons(75);
|
|
.DE
|
|
.NH 2
|
|
Network names
|
|
.PP
|
|
As for host names, routines for mapping network names to numbers,
|
|
and back, are provided. These routines return a \fInetent\fP
|
|
structure:
|
|
.DS
|
|
.DT
|
|
/*
|
|
* Assumption here is that a network number
|
|
* fits in 32 bits -- probably a poor one.
|
|
*/
|
|
struct netent {
|
|
char *n_name; /* official name of net */
|
|
char **n_aliases; /* alias list */
|
|
int n_addrtype; /* net address type */
|
|
int n_net; /* network number, host byte order */
|
|
};
|
|
.DE
|
|
The routines \fIgetnetbyname\fP(3N), \fIgetnetbynumber\fP(3N),
|
|
and \fIgetnetent\fP(3N) are the network counterparts to the
|
|
host routines described above. The routines extract their
|
|
information from \fI/etc/networks\fP.
|
|
.PP
|
|
NS network numbers are determined either by asking your local
|
|
Xerox Network Administrator (and hardcoding the information
|
|
into your code), or by querying the Clearinghouse for addresses.
|
|
The internetwork router is the only process
|
|
that needs to manipulate network numbers on a regular basis; if
|
|
a process wishes to communicate with a machine, it should ask the
|
|
Clearinghouse for that machine's address (which will include
|
|
the net number).
|
|
.NH 2
|
|
Protocol names
|
|
.PP
|
|
For protocols, which are defined in \fI/etc/protocols\fP,
|
|
the \fIprotoent\fP structure defines the
|
|
protocol-name mapping
|
|
used with the routines \fIgetprotobyname\fP(3N),
|
|
\fIgetprotobynumber\fP(3N),
|
|
and \fIgetprotoent\fP(3N):
|
|
.DS
|
|
.DT
|
|
struct protoent {
|
|
char *p_name; /* official protocol name */
|
|
char **p_aliases; /* alias list */
|
|
int p_proto; /* protocol number */
|
|
};
|
|
.DE
|
|
.PP
|
|
In the NS domain, protocols are indicated by the "client type"
|
|
field of a IDP header. No protocol database exists; see section
|
|
5 for more information.
|
|
.NH 2
|
|
Service names
|
|
.PP
|
|
Information regarding services is a bit more complicated. A service
|
|
is expected to reside at a specific \*(lqport\*(rq and employ
|
|
a particular communication protocol. This view is consistent with
|
|
the Internet domain, but inconsistent with other network architectures.
|
|
Further, a service may reside on multiple ports.
|
|
If this occurs, the higher level library routines
|
|
will have to be bypassed or extended.
|
|
Services available are contained in the file \fI/etc/services\fP.
|
|
A service mapping is described by the \fIservent\fP structure,
|
|
.DS
|
|
.DT
|
|
struct servent {
|
|
char *s_name; /* official service name */
|
|
char **s_aliases; /* alias list */
|
|
int s_port; /* port number, network byte order */
|
|
char *s_proto; /* protocol to use */
|
|
};
|
|
.DE
|
|
The routine \fIgetservbyname\fP(3N) maps service
|
|
names to a servent structure by specifying a service name and,
|
|
optionally, a qualifying protocol. Thus the call
|
|
.DS
|
|
sp = getservbyname("telnet", (char *) 0);
|
|
.DE
|
|
returns the service specification for a telnet server using
|
|
any protocol, while the call
|
|
.DS
|
|
sp = getservbyname("telnet", "tcp");
|
|
.DE
|
|
returns only that telnet server which uses the TCP protocol.
|
|
The routines \fIgetservbyport\fP(3N) and \fIgetservent\fP(3N) are
|
|
also provided. The \fIgetservbyport\fP routine has an interface similar
|
|
to that provided by \fIgetservbyname\fP; an optional protocol name may
|
|
be specified to qualify lookups.
|
|
.PP
|
|
In the NS domain, services are handled by a central dispatcher
|
|
provided as part of the Courier remote procedure call facilities.
|
|
Again, the reader is referred to the Courier compiler documentation
|
|
and to the Xerox standard*
|
|
.FS
|
|
* \fICourier: The Remote Procedure Call Protocol\fP, XSIS 038112.
|
|
.FE
|
|
for further details.
|
|
.NH 2
|
|
Miscellaneous
|
|
.PP
|
|
With the support routines described above, an Internet application program
|
|
should rarely have to deal directly
|
|
with addresses. This allows
|
|
services to be developed as much as possible in a network independent
|
|
fashion. It is clear, however, that purging all network dependencies
|
|
is very difficult. So long as the user is required to supply network
|
|
addresses when naming services and sockets there will always some
|
|
network dependency in a program. For example, the normal
|
|
code included in client programs, such as the remote login program,
|
|
is of the form shown in Figure 1.
|
|
(This example will be considered in more detail in section 4.)
|
|
.PP
|
|
If we wanted to make the remote login program independent of the
|
|
Internet protocols and addressing scheme we would be forced to add
|
|
a layer of routines which masked the network dependent aspects from
|
|
the mainstream login code. For the current facilities available in
|
|
the system this does not appear to be worthwhile.
|
|
.PP
|
|
Aside from the address-related data base routines, there are several
|
|
other routines available in the run-time library which are of interest
|
|
to users. These are intended mostly to simplify manipulation of
|
|
names and addresses. Table 1 summarizes the routines
|
|
for manipulating variable length byte strings and handling byte
|
|
swapping of network addresses and values.
|
|
.KF
|
|
.DS B
|
|
.TS
|
|
box;
|
|
l | l
|
|
l | l.
|
|
Call Synopsis
|
|
_
|
|
bcmp(s1, s2, n) compare byte-strings; 0 if same, not 0 otherwise
|
|
bcopy(s1, s2, n) copy n bytes from s1 to s2
|
|
bzero(base, n) zero-fill n bytes starting at base
|
|
htonl(val) convert 32-bit quantity from host to network byte order
|
|
htons(val) convert 16-bit quantity from host to network byte order
|
|
ntohl(val) convert 32-bit quantity from network to host byte order
|
|
ntohs(val) convert 16-bit quantity from network to host byte order
|
|
.TE
|
|
.DE
|
|
.ce
|
|
Table 1. C run-time routines.
|
|
.KE
|
|
.PP
|
|
The byte swapping routines are provided because the operating
|
|
system expects addresses to be supplied in network order (aka ``big-endian'' order). On
|
|
``little-endian'' architectures, such as Intel x86 and VAX,
|
|
host byte ordering is different than
|
|
network byte ordering. Consequently,
|
|
programs are sometimes required to byte swap quantities. The
|
|
library routines which return network addresses provide them
|
|
in network order so that they may simply be copied into the structures
|
|
provided to the system. This implies users should encounter the
|
|
byte swapping problem only when \fIinterpreting\fP network addresses.
|
|
For example, if an Internet port is to be printed out the following
|
|
code would be required:
|
|
.DS
|
|
printf("port number %d\en", ntohs(sp->s_port));
|
|
.DE
|
|
On machines where unneeded these routines are defined as null
|
|
macros.
|
|
.DS
|
|
.if t .ta .5i 1.0i 1.5i 2.0i
|
|
.if n .ta .7i 1.4i 2.1i 2.8i
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <stdio.h>
|
|
#include <netdb.h>
|
|
...
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
struct sockaddr_in server;
|
|
struct servent *sp;
|
|
struct hostent *hp;
|
|
int s;
|
|
...
|
|
sp = getservbyname("login", "tcp");
|
|
if (sp == NULL) {
|
|
fprintf(stderr, "rlogin: tcp/login: unknown service\en");
|
|
exit(1);
|
|
}
|
|
hp = gethostbyname(argv[1]);
|
|
if (hp == NULL) {
|
|
fprintf(stderr, "rlogin: %s: unknown host\en", argv[1]);
|
|
exit(2);
|
|
}
|
|
bzero((char *)&server, sizeof (server));
|
|
bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
|
|
server.sin_family = hp->h_addrtype;
|
|
server.sin_port = sp->s_port;
|
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (s < 0) {
|
|
perror("rlogin: socket");
|
|
exit(3);
|
|
}
|
|
...
|
|
/* Connect does the bind() for us */
|
|
|
|
if (connect(s, (char *)&server, sizeof (server)) < 0) {
|
|
perror("rlogin: connect");
|
|
exit(5);
|
|
}
|
|
...
|
|
}
|
|
.DE
|
|
.ce
|
|
Figure 1. Remote login client code.
|