Commit | Line | Data |
---|---|---|
d60e8dff MK |
1 | .\" Copyright (c) 1986 Regents of the University of California. |
2 | .\" All rights reserved. The Berkeley software License Agreement | |
3 | .\" specifies the terms and conditions for redistribution. | |
4 | .\" | |
3c0dec46 | 5 | .\" @(#)3.t 1.3 (Berkeley) %G% |
d60e8dff | 6 | .\" |
200989e9 MK |
7 | .ds RH "Network Library Routines |
8 | .bp | |
9 | .nr H1 3 | |
10 | .nr H2 0 | |
11 | .bp | |
12 | .LG | |
13 | .B | |
14 | .ce | |
15 | 3. NETWORK LIBRARY ROUTINES | |
16 | .sp 2 | |
17 | .R | |
18 | .NL | |
19 | .PP | |
20 | The discussion in section 2 indicated the possible need to | |
21 | locate and construct network addresses when using the | |
22 | interprocess communication facilities in a distributed | |
23 | environment. To aid in this task a number of routines | |
24 | have been added to the standard C run-time library. | |
25 | In this section we will consider the new routines provided | |
d60e8dff MK |
26 | to manipulate network addresses. While the 4.3BSD networking |
27 | facilities support both the DARPA standard Internet protocols | |
28 | and the Xerox NS protocols, most of the routines presented | |
29 | in this section do not apply to the NS domain. Unless otherwise | |
30 | stated, it should be assumed that the routines presented in this | |
31 | section do not apply to the NS domain. | |
200989e9 MK |
32 | .PP |
33 | Locating a service on a remote host requires many levels of | |
34 | mapping before client and server may | |
35 | communicate. A service is assigned a name which is intended | |
36 | for human consumption; e.g. \*(lqthe \fIlogin server\fP on host | |
37 | monet\*(rq. | |
38 | This name, and the name of the peer host, must then be translated | |
39 | into network \fIaddresses\fP which are not necessarily suitable | |
40 | for human consumption. Finally, the address must then used in locating | |
41 | a physical \fIlocation\fP and \fIroute\fP to the service. The | |
d60e8dff | 42 | specifics of these three mappings are likely to vary between |
200989e9 | 43 | network architectures. For instance, it is desirable for a network |
d60e8dff | 44 | to not require hosts to |
200989e9 MK |
45 | be named in such a way that their physical location is known by |
46 | the client host. Instead, underlying services in the network | |
47 | may discover the actual location of the host at the time a client | |
48 | host wishes to communicate. This ability to have hosts named in | |
49 | a location independent manner may induce overhead in connection | |
50 | establishment, as a discovery process must take place, | |
51 | but allows a host to be physically mobile without requiring it to | |
52 | notify its clientele of its current location. | |
53 | .PP | |
54 | Standard routines are provided for: mapping host names | |
55 | to network addresses, network names to network numbers, | |
56 | protocol names to protocol numbers, and service names | |
57 | to port numbers and the appropriate protocol to | |
58 | use in communicating with the server process. The | |
59 | file <\fInetdb.h\fP> must be included when using any of these | |
60 | routines. | |
61 | .NH 2 | |
62 | Host names | |
63 | .PP | |
d60e8dff | 64 | An Internet host name to address mapping is represented by |
200989e9 MK |
65 | the \fIhostent\fP structure: |
66 | .DS | |
d60e8dff | 67 | .if t .ta 0.6i 1.1i 2.6i |
200989e9 MK |
68 | struct hostent { |
69 | char *h_name; /* official name of host */ | |
70 | char **h_aliases; /* alias list */ | |
d60e8dff | 71 | int h_addrtype; /* host address type (e.g., AF_INET) */ |
200989e9 | 72 | int h_length; /* length of address */ |
d60e8dff | 73 | char **h_addr_list; /* list of addresses, null terminated */ |
200989e9 | 74 | }; |
d60e8dff MK |
75 | |
76 | #define h_addr h_addr_list[0] /* first address, network byte order */ | |
200989e9 | 77 | .DE |
d60e8dff | 78 | The routine \fIgethostbyname\fP(3N) takes an Internet host name |
200989e9 MK |
79 | and returns a \fIhostent\fP structure, |
80 | while the routine \fIgethostbyaddr\fP(3N) | |
d60e8dff MK |
81 | maps Internet host addresses into a \fIhostent\fP structure. |
82 | .PP | |
83 | The official name of the host and its public aliases are | |
84 | returned by these routines, | |
85 | along with the address type (family) and a null terminated list of | |
86 | variable length address. This list of addresses is | |
87 | required because it is possible | |
200989e9 | 88 | for a host to have many addresses, all having the same name. |
d60e8dff MK |
89 | The \fIh_addr\fP definition is provided for backward compatibility, |
90 | and is defined to be the first address in the list of addresses | |
91 | in the \fIhostent\fP structure. | |
92 | .PP | |
93 | The database for these calls is provided either by the | |
94 | file \fI/etc/hosts\fP, or by use of a nameserver. If the data | |
95 | returned by \fIgethostbyname\fP are unsuitable, the lower level | |
200989e9 MK |
96 | routine \fIgethostent\fP(3N) may be used. For example, to |
97 | obtain a \fIhostent\fP structure for a | |
98 | host on a particular network the following routine might be | |
99 | used (for simplicity, only Internet addresses are considered): | |
100 | .DS | |
101 | .if t .ta .5i 1.0i 1.5i 2.0i | |
102 | .\" 3.5i went to 3.8i | |
103 | .if n .ta .7i 1.4i 2.1i 2.8i 3.5i 4.2i | |
104 | #include <sys/types.h> | |
105 | #include <sys/socket.h> | |
106 | #include <netinet/in.h> | |
107 | #include <netdb.h> | |
108 | ... | |
109 | struct hostent * | |
110 | gethostbynameandnet(name, net) | |
111 | char *name; | |
112 | int net; | |
113 | { | |
114 | register struct hostent *hp; | |
115 | register char **cp; | |
116 | ||
117 | sethostent(0); | |
118 | while ((hp = gethostent()) != NULL) { | |
119 | if (hp->h_addrtype != AF_INET) | |
120 | continue; | |
121 | if (strcmp(name, hp->h_name)) { | |
122 | for (cp = hp->h_aliases; cp && *cp != NULL; cp++) | |
123 | if (strcmp(name, *cp) == 0) | |
124 | goto found; | |
125 | continue; | |
126 | } | |
127 | found: | |
128 | if (in_netof(*(struct in_addr *)hp->h_addr)) == net) | |
129 | break; | |
130 | } | |
131 | endhostent(0); | |
132 | return (hp); | |
133 | } | |
134 | .DE | |
135 | (\fIin_netof\fP(3N) is a standard routine which returns | |
136 | the network portion of an Internet address.) | |
d60e8dff MK |
137 | \fIGethostent\fP can be used only |
138 | by systems which use the \fI/etc/hosts\fP database; systems | |
139 | using nameservers cannot execute such a call. | |
140 | .PP | |
141 | Unlike Internet names, NS names are always mapped into host | |
142 | addresses by the use of a standard NS \fIClearinghouse service\fP, | |
143 | a distributed name and authentication server. The algorithms | |
144 | for mapping NS names to addresses via a Clearinghouse are | |
145 | rather complicated, and the routines are not part of the | |
146 | standard libraries. The user-contributed Courier (Xerox | |
147 | remote procedure call protocol) compiler contains routines | |
148 | to accomplish this mapping; see the documentation and | |
149 | examples provided therein for more information. It is | |
150 | expected that almost all software that has to communicate | |
151 | using NS will need to use the facilities of | |
152 | the Courier compiler. | |
153 | .PP | |
154 | A NS host address is represented by the following: | |
155 | .DS | |
156 | union ns_host { | |
157 | u_char c_host[6]; | |
158 | u_short s_host[3]; | |
159 | }; | |
160 | ||
161 | union ns_net { | |
162 | u_char c_net[4]; | |
163 | u_short s_net[2]; | |
164 | }; | |
165 | ||
166 | struct ns_addr { | |
167 | union ns_net x_net; | |
168 | union ns_host x_host; | |
169 | u_short x_port; | |
170 | }; | |
171 | .DE | |
172 | The following code fragment inserts a known NS address into | |
173 | a \fIns_addr\fP: | |
174 | .DS | |
175 | #include <sys/types.h> | |
176 | #include <sys/socket.h> | |
177 | #include <netns/ns.h> | |
178 | ... | |
179 | u_long netnum; | |
180 | struct sockaddr_ns dst; | |
181 | ... | |
182 | bzero((char *)&dst, sizeof(dst)); | |
183 | ||
184 | /* | |
185 | * There is no convenient way to assign a long | |
186 | * integer to a ``union ns_net'' at present; in | |
187 | * the future, something will hopefully be provided, | |
188 | * but this is the portable way to go for now. | |
3c0dec46 MK |
189 | * The network number below is the one for the NS net |
190 | * that the desired host (gyre) is on. | |
d60e8dff MK |
191 | */ |
192 | netnum = htonl(2266); | |
193 | dst.sns_addr.x_net = *(union ns_net *) &netnum; | |
194 | dst.sns_family = AF_NS; | |
195 | ||
196 | /* | |
197 | * host 2.7.1.0.2a.18 == "gyre:Computer Science:UofMaryland" | |
198 | */ | |
199 | dst.sns_addr.x_host.c_host[0] = 0x02; | |
200 | dst.sns_addr.x_host.c_host[1] = 0x07; | |
201 | dst.sns_addr.x_host.c_host[2] = 0x01; | |
202 | dst.sns_addr.x_host.c_host[3] = 0x00; | |
203 | dst.sns_addr.x_host.c_host[4] = 0x2a; | |
204 | dst.sns_addr.x_host.c_host[5] = 0x18; | |
205 | dst.sns_addr.x_port = htons(75); | |
206 | .DE | |
200989e9 MK |
207 | .NH 2 |
208 | Network names | |
209 | .PP | |
210 | As for host names, routines for mapping network names to numbers, | |
211 | and back, are provided. These routines return a \fInetent\fP | |
212 | structure: | |
213 | .DS | |
214 | .DT | |
215 | /* | |
216 | * Assumption here is that a network number | |
217 | * fits in 32 bits -- probably a poor one. | |
218 | */ | |
219 | struct netent { | |
220 | char *n_name; /* official name of net */ | |
221 | char **n_aliases; /* alias list */ | |
222 | int n_addrtype; /* net address type */ | |
d60e8dff | 223 | int n_net; /* network number, host byte order */ |
200989e9 MK |
224 | }; |
225 | .DE | |
226 | The routines \fIgetnetbyname\fP(3N), \fIgetnetbynumber\fP(3N), | |
227 | and \fIgetnetent\fP(3N) are the network counterparts to the | |
d60e8dff MK |
228 | host routines described above. The routines extract their |
229 | information from \fI/etc/networks\fP. | |
230 | .PP | |
231 | NS network numbers are determined either by asking your local | |
232 | Xerox Network Administrator (and hardcoding the information | |
233 | into your code), or by querying the Clearinghouse for addresses. | |
234 | The internetwork router is the only process | |
235 | that needs to manipulate network numbers on a regular basis; if | |
236 | a process wishes to communicate with a machine, it should ask the | |
237 | Clearinghouse for that machine's address (which will include | |
238 | the net number). | |
200989e9 MK |
239 | .NH 2 |
240 | Protocol names | |
241 | .PP | |
d60e8dff MK |
242 | For protocols, which are defined in \fI/etc/protocols\fP, |
243 | the \fIprotoent\fP structure defines the | |
200989e9 MK |
244 | protocol-name mapping |
245 | used with the routines \fIgetprotobyname\fP(3N), | |
246 | \fIgetprotobynumber\fP(3N), | |
247 | and \fIgetprotoent\fP(3N): | |
248 | .DS | |
249 | .DT | |
250 | struct protoent { | |
251 | char *p_name; /* official protocol name */ | |
252 | char **p_aliases; /* alias list */ | |
d60e8dff | 253 | int p_proto; /* protocol number */ |
200989e9 MK |
254 | }; |
255 | .DE | |
d60e8dff MK |
256 | .PP |
257 | In the NS domain, protocols are indicated by the "client type" | |
258 | field of a IDP header. No protocol database exists; see section | |
259 | 5 for more information. | |
200989e9 MK |
260 | .NH 2 |
261 | Service names | |
262 | .PP | |
263 | Information regarding services is a bit more complicated. A service | |
264 | is expected to reside at a specific \*(lqport\*(rq and employ | |
265 | a particular communication protocol. This view is consistent with | |
266 | the Internet domain, but inconsistent with other network architectures. | |
d60e8dff MK |
267 | Further, a service may reside on multiple ports. |
268 | If this occurs, the higher level library routines | |
200989e9 MK |
269 | will have to be bypassed in favor of homegrown routines similar in |
270 | spirit to the \*(lqgethostbynameandnet\*(rq routine described above. | |
d60e8dff | 271 | Services available are contained in the file \fI/etc/services\fP. |
200989e9 MK |
272 | A service mapping is described by the \fIservent\fP structure, |
273 | .DS | |
274 | .DT | |
275 | struct servent { | |
276 | char *s_name; /* official service name */ | |
277 | char **s_aliases; /* alias list */ | |
d60e8dff | 278 | int s_port; /* port number, network byte order */ |
200989e9 MK |
279 | char *s_proto; /* protocol to use */ |
280 | }; | |
281 | .DE | |
282 | The routine \fIgetservbyname\fP(3N) maps service | |
283 | names to a servent structure by specifying a service name and, | |
284 | optionally, a qualifying protocol. Thus the call | |
285 | .DS | |
d60e8dff | 286 | sp = getservbyname("telnet", (char *) 0); |
200989e9 MK |
287 | .DE |
288 | returns the service specification for a telnet server using | |
289 | any protocol, while the call | |
290 | .DS | |
291 | sp = getservbyname("telnet", "tcp"); | |
292 | .DE | |
293 | returns only that telnet server which uses the TCP protocol. | |
294 | The routines \fIgetservbyport\fP(3N) and \fIgetservent\fP(3N) are | |
295 | also provided. The \fIgetservbyport\fP routine has an interface similar | |
296 | to that provided by \fIgetservbyname\fP; an optional protocol name may | |
297 | be specified to qualify lookups. | |
d60e8dff MK |
298 | .PP |
299 | In the NS domain, services are handled by a central dispatcher | |
300 | provided as part of the Courier remote procedure call facilities. | |
301 | Again, the reader is referred to the Courier compiler documentation | |
302 | and to the Xerox standard* | |
303 | .FS | |
304 | * \fICourier: The Remote Procedure Call Protocol\fP, XSIS 038112. | |
305 | .FE | |
306 | for further details. | |
200989e9 MK |
307 | .NH 2 |
308 | Miscellaneous | |
309 | .PP | |
d60e8dff | 310 | With the support routines described above, an Internet application program |
200989e9 MK |
311 | should rarely have to deal directly |
312 | with addresses. This allows | |
313 | services to be developed as much as possible in a network independent | |
314 | fashion. It is clear, however, that purging all network dependencies | |
315 | is very difficult. So long as the user is required to supply network | |
316 | addresses when naming services and sockets there will always some | |
317 | network dependency in a program. For example, the normal | |
318 | code included in client programs, such as the remote login program, | |
319 | is of the form shown in Figure 1. | |
200989e9 MK |
320 | (This example will be considered in more detail in section 4.) |
321 | .PP | |
322 | If we wanted to make the remote login program independent of the | |
323 | Internet protocols and addressing scheme we would be forced to add | |
324 | a layer of routines which masked the network dependent aspects from | |
325 | the mainstream login code. For the current facilities available in | |
d60e8dff | 326 | the system this does not appear to be worthwhile. |
200989e9 MK |
327 | .PP |
328 | Aside from the address-related data base routines, there are several | |
329 | other routines available in the run-time library which are of interest | |
330 | to users. These are intended mostly to simplify manipulation of | |
331 | names and addresses. Table 1 summarizes the routines | |
332 | for manipulating variable length byte strings and handling byte | |
333 | swapping of network addresses and values. | |
334 | .KF | |
335 | .DS B | |
336 | .TS | |
337 | box; | |
338 | l | l | |
339 | l | l. | |
340 | Call Synopsis | |
341 | _ | |
342 | bcmp(s1, s2, n) compare byte-strings; 0 if same, not 0 otherwise | |
343 | bcopy(s1, s2, n) copy n bytes from s1 to s2 | |
344 | bzero(base, n) zero-fill n bytes starting at base | |
345 | htonl(val) convert 32-bit quantity from host to network byte order | |
346 | htons(val) convert 16-bit quantity from host to network byte order | |
347 | ntohl(val) convert 32-bit quantity from network to host byte order | |
348 | ntohs(val) convert 16-bit quantity from network to host byte order | |
349 | .TE | |
350 | .DE | |
351 | .ce | |
352 | Table 1. C run-time routines. | |
353 | .KE | |
354 | .PP | |
355 | The byte swapping routines are provided because the operating | |
d60e8dff MK |
356 | system expects addresses to be supplied in network order. On |
357 | some architectures, such as the VAX, | |
358 | host byte ordering is different than | |
359 | network byte ordering. Consequently, | |
200989e9 MK |
360 | programs are sometimes required to byte swap quantities. The |
361 | library routines which return network addresses provide them | |
362 | in network order so that they may simply be copied into the structures | |
363 | provided to the system. This implies users should encounter the | |
364 | byte swapping problem only when \fIinterpreting\fP network addresses. | |
365 | For example, if an Internet port is to be printed out the following | |
366 | code would be required: | |
367 | .DS | |
368 | printf("port number %d\en", ntohs(sp->s_port)); | |
369 | .DE | |
d60e8dff | 370 | On machines where unneeded these routines are defined as null |
200989e9 | 371 | macros. |
d60e8dff MK |
372 | .DS |
373 | .if t .ta .5i 1.0i 1.5i 2.0i | |
374 | .if n .ta .7i 1.4i 2.1i 2.8i | |
375 | #include <sys/types.h> | |
376 | #include <sys/socket.h> | |
377 | #include <netinet/in.h> | |
378 | #include <stdio.h> | |
379 | #include <netdb.h> | |
380 | ... | |
381 | main(argc, argv) | |
382 | int argc; | |
383 | char *argv[]; | |
384 | { | |
385 | struct sockaddr_in server; | |
386 | struct servent *sp; | |
387 | struct hostent *hp; | |
388 | int s; | |
389 | ... | |
390 | sp = getservbyname("login", "tcp"); | |
391 | if (sp == NULL) { | |
392 | fprintf(stderr, "rlogin: tcp/login: unknown service\en"); | |
393 | exit(1); | |
394 | } | |
395 | hp = gethostbyname(argv[1]); | |
396 | if (hp == NULL) { | |
397 | fprintf(stderr, "rlogin: %s: unknown host\en", argv[1]); | |
398 | exit(2); | |
399 | } | |
400 | bzero((char *)&server, sizeof (server)); | |
401 | bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length); | |
402 | server.sin_family = hp->h_addrtype; | |
403 | server.sin_port = sp->s_port; | |
404 | s = socket(AF_INET, SOCK_STREAM, 0); | |
405 | if (s < 0) { | |
406 | perror("rlogin: socket"); | |
407 | exit(3); | |
408 | } | |
409 | ... | |
410 | /* Connect does the bind() for us */ | |
411 | ||
412 | if (connect(s, (char *)&server, sizeof (server)) < 0) { | |
413 | perror("rlogin: connect"); | |
414 | exit(5); | |
415 | } | |
416 | ... | |
417 | } | |
418 | .DE | |
419 | .ce | |
420 | Figure 1. Remote login client code. |