Commit | Line | Data |
---|---|---|
f0b8d567 C |
1 | .ds RH "Network Library Routines |
2 | .bp | |
3 | .nr H1 3 | |
4 | .nr H2 0 | |
5 | .bp | |
6 | .LG | |
7 | .B | |
8 | .ce | |
9 | 3. NETWORK LIBRARY ROUTINES | |
10 | .sp 2 | |
11 | .R | |
12 | .NL | |
13 | .PP | |
14 | The discussion in section 2 indicated the possible need to | |
15 | locate and construct network addresses when using the | |
16 | interprocess communication facilities in a distributed | |
17 | environment. To aid in this task a number of routines | |
18 | have been added to the standard C run-time library. | |
19 | In this section we will consider the new routines provided | |
20 | to manipulate network addresses. While the 4.2BSD networking | |
21 | facilities support only the DARPA standard Internet protocols, | |
22 | these routines have been designed with flexibility in mind. | |
23 | As more communication protocols become available, we hope | |
24 | the same user interface will be maintained in accessing | |
25 | network-related address data bases. The only difference | |
26 | should be the values returned to the user. Since these | |
27 | values are normally supplied the system, users should | |
28 | not need to be directly aware of the communication protocol | |
29 | and/or naming conventions in use. | |
30 | .PP | |
31 | Locating a service on a remote host requires many levels of | |
32 | mapping before client and server may | |
33 | communicate. A service is assigned a name which is intended | |
34 | for human consumption; e.g. \*(lqthe \fIlogin server\fP on host | |
35 | monet\*(rq. | |
36 | This name, and the name of the peer host, must then be translated | |
37 | into network \fIaddresses\fP which are not necessarily suitable | |
38 | for human consumption. Finally, the address must then used in locating | |
39 | a physical \fIlocation\fP and \fIroute\fP to the service. The | |
40 | specifics of these three mappings is likely to vary between | |
41 | network architectures. For instance, it is desirable for a network | |
42 | to not require hosts | |
43 | be named in such a way that their physical location is known by | |
44 | the client host. Instead, underlying services in the network | |
45 | may discover the actual location of the host at the time a client | |
46 | host wishes to communicate. This ability to have hosts named in | |
47 | a location independent manner may induce overhead in connection | |
48 | establishment, as a discovery process must take place, | |
49 | but allows a host to be physically mobile without requiring it to | |
50 | notify its clientele of its current location. | |
51 | .PP | |
52 | Standard routines are provided for: mapping host names | |
53 | to network addresses, network names to network numbers, | |
54 | protocol names to protocol numbers, and service names | |
55 | to port numbers and the appropriate protocol to | |
56 | use in communicating with the server process. The | |
57 | file <\fInetdb.h\fP> must be included when using any of these | |
58 | routines. | |
59 | .NH 2 | |
60 | Host names | |
61 | .PP | |
62 | A host name to address mapping is represented by | |
63 | the \fIhostent\fP structure: | |
64 | .DS | |
65 | .DT | |
66 | struct hostent { | |
67 | char *h_name; /* official name of host */ | |
68 | char **h_aliases; /* alias list */ | |
69 | int h_addrtype; /* host address type */ | |
70 | int h_length; /* length of address */ | |
71 | char *h_addr; /* address */ | |
72 | }; | |
73 | .DE | |
74 | The official name of the host and its public aliases are | |
75 | returned, along with a variable length address and address | |
76 | type. The routine \fIgethostbyname\fP(3N) takes a host name | |
77 | and returns a \fIhostent\fP structure, | |
78 | while the routine \fIgethostbyaddr\fP(3N) | |
79 | maps host addresses into a \fIhostent\fP structure. It is possible | |
80 | for a host to have many addresses, all having the same name. | |
81 | \fIGethostybyname\fP returns the first matching entry in the data | |
82 | base file \fI/etc/hosts\fP; if this is unsuitable, the lower level | |
83 | routine \fIgethostent\fP(3N) may be used. For example, to | |
84 | obtain a \fIhostent\fP structure for a | |
85 | host on a particular network the following routine might be | |
86 | used (for simplicity, only Internet addresses are considered): | |
87 | .DS | |
88 | .if t .ta .5i 1.0i 1.5i 2.0i | |
89 | .\" 3.5i went to 3.8i | |
90 | .if n .ta .7i 1.4i 2.1i 2.8i 3.5i 4.2i | |
91 | #include <sys/types.h> | |
92 | #include <sys/socket.h> | |
93 | #include <netinet/in.h> | |
94 | #include <netdb.h> | |
95 | ... | |
96 | struct hostent * | |
97 | gethostbynameandnet(name, net) | |
98 | char *name; | |
99 | int net; | |
100 | { | |
101 | register struct hostent *hp; | |
102 | register char **cp; | |
103 | ||
104 | sethostent(0); | |
105 | while ((hp = gethostent()) != NULL) { | |
106 | if (hp->h_addrtype != AF_INET) | |
107 | continue; | |
108 | if (strcmp(name, hp->h_name)) { | |
109 | for (cp = hp->h_aliases; cp && *cp != NULL; cp++) | |
110 | if (strcmp(name, *cp) == 0) | |
111 | goto found; | |
112 | continue; | |
113 | } | |
114 | found: | |
115 | if (in_netof(*(struct in_addr *)hp->h_addr)) == net) | |
116 | break; | |
117 | } | |
118 | endhostent(0); | |
119 | return (hp); | |
120 | } | |
121 | .DE | |
122 | (\fIin_netof\fP(3N) is a standard routine which returns | |
123 | the network portion of an Internet address.) | |
124 | .NH 2 | |
125 | Network names | |
126 | .PP | |
127 | As for host names, routines for mapping network names to numbers, | |
128 | and back, are provided. These routines return a \fInetent\fP | |
129 | structure: | |
130 | .DS | |
131 | .DT | |
132 | /* | |
133 | * Assumption here is that a network number | |
134 | * fits in 32 bits -- probably a poor one. | |
135 | */ | |
136 | struct netent { | |
137 | char *n_name; /* official name of net */ | |
138 | char **n_aliases; /* alias list */ | |
139 | int n_addrtype; /* net address type */ | |
140 | int n_net; /* network # */ | |
141 | }; | |
142 | .DE | |
143 | The routines \fIgetnetbyname\fP(3N), \fIgetnetbynumber\fP(3N), | |
144 | and \fIgetnetent\fP(3N) are the network counterparts to the | |
145 | host routines described above. | |
146 | .NH 2 | |
147 | Protocol names | |
148 | .PP | |
149 | For protocols the \fIprotoent\fP structure defines the | |
150 | protocol-name mapping | |
151 | used with the routines \fIgetprotobyname\fP(3N), | |
152 | \fIgetprotobynumber\fP(3N), | |
153 | and \fIgetprotoent\fP(3N): | |
154 | .DS | |
155 | .DT | |
156 | struct protoent { | |
157 | char *p_name; /* official protocol name */ | |
158 | char **p_aliases; /* alias list */ | |
159 | int p_proto; /* protocol # */ | |
160 | }; | |
161 | .DE | |
162 | .NH 2 | |
163 | Service names | |
164 | .PP | |
165 | Information regarding services is a bit more complicated. A service | |
166 | is expected to reside at a specific \*(lqport\*(rq and employ | |
167 | a particular communication protocol. This view is consistent with | |
168 | the Internet domain, but inconsistent with other network architectures. | |
169 | Further, a service may reside on multiple ports or support multiple | |
170 | protocols. If either of these occurs, the higher level library routines | |
171 | will have to be bypassed in favor of homegrown routines similar in | |
172 | spirit to the \*(lqgethostbynameandnet\*(rq routine described above. | |
173 | A service mapping is described by the \fIservent\fP structure, | |
174 | .DS | |
175 | .DT | |
176 | struct servent { | |
177 | char *s_name; /* official service name */ | |
178 | char **s_aliases; /* alias list */ | |
179 | int s_port; /* port # */ | |
180 | char *s_proto; /* protocol to use */ | |
181 | }; | |
182 | .DE | |
183 | The routine \fIgetservbyname\fP(3N) maps service | |
184 | names to a servent structure by specifying a service name and, | |
185 | optionally, a qualifying protocol. Thus the call | |
186 | .DS | |
187 | sp = getservbyname("telnet", (char *)0); | |
188 | .DE | |
189 | returns the service specification for a telnet server using | |
190 | any protocol, while the call | |
191 | .DS | |
192 | sp = getservbyname("telnet", "tcp"); | |
193 | .DE | |
194 | returns only that telnet server which uses the TCP protocol. | |
195 | The routines \fIgetservbyport\fP(3N) and \fIgetservent\fP(3N) are | |
196 | also provided. The \fIgetservbyport\fP routine has an interface similar | |
197 | to that provided by \fIgetservbyname\fP; an optional protocol name may | |
198 | be specified to qualify lookups. | |
199 | .NH 2 | |
200 | Miscellaneous | |
201 | .PP | |
202 | With the support routines described above, an application program | |
203 | should rarely have to deal directly | |
204 | with addresses. This allows | |
205 | services to be developed as much as possible in a network independent | |
206 | fashion. It is clear, however, that purging all network dependencies | |
207 | is very difficult. So long as the user is required to supply network | |
208 | addresses when naming services and sockets there will always some | |
209 | network dependency in a program. For example, the normal | |
210 | code included in client programs, such as the remote login program, | |
211 | is of the form shown in Figure 1. | |
212 | .KF | |
213 | .DS | |
214 | .if t .ta .5i 1.0i 1.5i 2.0i | |
215 | .if n .ta .7i 1.4i 2.1i 2.8i | |
216 | #include <sys/types.h> | |
217 | #include <sys/socket.h> | |
218 | #include <netinet/in.h> | |
219 | #include <stdio.h> | |
220 | #include <netdb.h> | |
221 | ... | |
222 | main(argc, argv) | |
223 | char *argv[]; | |
224 | { | |
225 | struct sockaddr_in sin; | |
226 | struct servent *sp; | |
227 | struct hostent *hp; | |
228 | int s; | |
229 | ... | |
230 | sp = getservbyname("login", "tcp"); | |
231 | if (sp == NULL) { | |
232 | fprintf(stderr, "rlogin: tcp/login: unknown service\en"); | |
233 | exit(1); | |
234 | } | |
235 | hp = gethostbyname(argv[1]); | |
236 | if (hp == NULL) { | |
237 | fprintf(stderr, "rlogin: %s: unknown host\en", argv[1]); | |
238 | exit(2); | |
239 | } | |
240 | bzero((char *)&sin, sizeof (sin)); | |
241 | bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); | |
242 | sin.sin_family = hp->h_addrtype; | |
243 | sin.sin_port = sp->s_port; | |
244 | s = socket(AF_INET, SOCK_STREAM, 0); | |
245 | if (s < 0) { | |
246 | perror("rlogin: socket"); | |
247 | exit(3); | |
248 | } | |
249 | ... | |
250 | if (connect(s, (char *)&sin, sizeof (sin)) < 0) { | |
251 | perror("rlogin: connect"); | |
252 | exit(5); | |
253 | } | |
254 | ... | |
255 | } | |
256 | .DE | |
257 | .ce | |
258 | Figure 1. Remote login client code. | |
259 | .KE | |
260 | (This example will be considered in more detail in section 4.) | |
261 | .PP | |
262 | If we wanted to make the remote login program independent of the | |
263 | Internet protocols and addressing scheme we would be forced to add | |
264 | a layer of routines which masked the network dependent aspects from | |
265 | the mainstream login code. For the current facilities available in | |
266 | the system this does not appear to be worthwhile. Perhaps when the | |
267 | system is adapted to different network architectures the utilities | |
268 | will be reorganized more cleanly. | |
269 | .PP | |
270 | Aside from the address-related data base routines, there are several | |
271 | other routines available in the run-time library which are of interest | |
272 | to users. These are intended mostly to simplify manipulation of | |
273 | names and addresses. Table 1 summarizes the routines | |
274 | for manipulating variable length byte strings and handling byte | |
275 | swapping of network addresses and values. | |
276 | .KF | |
277 | .DS B | |
278 | .TS | |
279 | box; | |
280 | l | l | |
281 | l | l. | |
282 | Call Synopsis | |
283 | _ | |
284 | bcmp(s1, s2, n) compare byte-strings; 0 if same, not 0 otherwise | |
285 | bcopy(s1, s2, n) copy n bytes from s1 to s2 | |
286 | bzero(base, n) zero-fill n bytes starting at base | |
287 | htonl(val) convert 32-bit quantity from host to network byte order | |
288 | htons(val) convert 16-bit quantity from host to network byte order | |
289 | ntohl(val) convert 32-bit quantity from network to host byte order | |
290 | ntohs(val) convert 16-bit quantity from network to host byte order | |
291 | .TE | |
292 | .DE | |
293 | .ce | |
294 | Table 1. C run-time routines. | |
295 | .KE | |
296 | .PP | |
297 | The byte swapping routines are provided because the operating | |
298 | system expects addresses to be supplied in network order. On a | |
299 | VAX, or machine with similar architecture, this | |
300 | is usually reversed. Consequently, | |
301 | programs are sometimes required to byte swap quantities. The | |
302 | library routines which return network addresses provide them | |
303 | in network order so that they may simply be copied into the structures | |
304 | provided to the system. This implies users should encounter the | |
305 | byte swapping problem only when \fIinterpreting\fP network addresses. | |
306 | For example, if an Internet port is to be printed out the following | |
307 | code would be required: | |
308 | .DS | |
309 | printf("port number %d\en", ntohs(sp->s_port)); | |
310 | .DE | |
311 | On machines other than the VAX these routines are defined as null | |
312 | macros. |