📄 5.t
字号:
login server uses pseudo-terminals for remote login sessions.A user logging in to a machine across the network is provideda shell with a slave pseudo-terminal as standard input, output,and error. The server process then handles the communicationbetween the programs invoked by the remote shell and the user'slocal client process.When a user sends a character that generates an interrupton the remote machine that flushes terminal output,the pseudo-terminal generates a control message for the server process.The server then sends an out of band messageto the client process to signal a flush of data at the real terminaland on the intervening data buffered in the network..PPUnder 4.4BSD, the name of the slave side of a pseudo-terminal is of the form\fI/dev/ttyxy\fP, where \fIx\fP is a single letterstarting at `p' and continuing to `t'.\fIy\fP is a hexadecimal digit (i.e., a singlecharacter in the range 0 through 9 or `a' through `f').The master side of a pseudo-terminal is \fI/dev/ptyxy\fP,where \fIx\fP and \fIy\fP correspond to theslave side of the pseudo-terminal..PPIn general, the method of obtaining a pair of master andslave pseudo-terminals is tofind a pseudo-terminal whichis not currently in use.The master half of a pseudo-terminal is a single-open device;thus, each master may be opened in turn until an open succeeds.The slave side of the pseudo-terminal is then opened,and is set to the proper terminal modes if necessary.The process then \fIfork\fPs; the child closesthe master side of the pseudo-terminal, and \fIexec\fPs theappropriate program. Meanwhile, the parent closes theslave side of the pseudo-terminal and begins reading andwriting from the master side. Sample code making use ofpseudo-terminals is given in Figure 8; this code assumesthat a connection on a socket \fIs\fP exists, connectedto a peer who wants a service of some kind, and that theprocess has disassociated itself from any previous controlling terminal..KF.DSgotpty = 0;for (c = 'p'; !gotpty && c <= 's'; c++) { line = "/dev/ptyXX"; line[sizeof("/dev/pty")-1] = c; line[sizeof("/dev/ptyp")-1] = '0'; if (stat(line, &statbuf) < 0) break; for (i = 0; i < 16; i++) { line[sizeof("/dev/ptyp")-1] = "0123456789abcdef"[i]; master = open(line, O_RDWR); if (master > 0) { gotpty = 1; break; } }}if (!gotpty) { syslog(LOG_ERR, "All network ports in use"); exit(1);}line[sizeof("/dev/")-1] = 't';slave = open(line, O_RDWR); /* \fIslave\fP is now slave side */if (slave < 0) { syslog(LOG_ERR, "Cannot open slave pty %s", line); exit(1);}ioctl(slave, TIOCGETP, &b); /* Set slave tty modes */b.sg_flags = CRMOD|XTABS|ANYP;ioctl(slave, TIOCSETP, &b);i = fork();if (i < 0) { syslog(LOG_ERR, "fork: %m"); exit(1);} else if (i) { /* Parent */ close(slave); ...} else { /* Child */ (void) close(s); (void) close(master); dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); if (slave > 2) (void) close(slave); ...}.DE.ceFigure 8. Creation and use of a pseudo terminal.sp.KE.NH 2Selecting specific protocols.PPIf the third argument to the \fIsocket\fP call is 0,\fIsocket\fP will select a default protocol to use withthe returned socket of the type requested.The default protocol is usually correct, and alternate choices are notusually available.However, when using ``raw'' sockets to communicate directly withlower-level protocols or hardware interfaces,the protocol argument may be important for setting up demultiplexing.For example, raw sockets in the Internet family may be used to implementa new protocol above IP, and the socket will receive packetsonly for the protocol specified.To obtain a particular protocol one determines the protocol numberas defined within the communication domain. For the Internetdomain one may use one of the library routinesdiscussed in section 3, such as \fIgetprotobyname\fP:.DS#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h> ...pp = getprotobyname("newtcp");s = socket(AF_INET, SOCK_STREAM, pp->p_proto);.DEThis would result in a socket \fIs\fP using a streambased connection, but with protocol type of ``newtcp''instead of the default ``tcp.''.PPIn the NS domain, the available socket protocols are defined in<\fInetns/ns.h\fP>. To create a raw socket for Xerox Error Protocolmessages, one might use:.DS#include <sys/types.h>#include <sys/socket.h>#include <netns/ns.h> ...s = socket(AF_NS, SOCK_RAW, NSPROTO_ERROR);.DE.NH 2Address binding.PPAs was mentioned in section 2, binding addresses to sockets in the Internet and NS domains can befairly complex. As a brief reminder, these associationsare composed of local and foreignaddresses, and local and foreign ports. Port numbers areallocated out of separate spaces, one for each system and onefor each domain on that system.Through the \fIbind\fP system call, aprocess may specify half of an association, the<local address, local port> part, while the\fIconnect\fPand \fIaccept\fPprimitives are used to complete a socket's association byspecifying the <foreign address, foreign port> part.Since the association is created in two steps the associationuniqueness requirement indicated previously could be violated unlesscare is taken. Further, it is unrealistic to expect userprograms to always know proper values to use for the local addressand local port since a host may reside on multiple networks andthe set of allocated port numbers is not directly accessibleto a user..PPTo simplify local address binding in the Internet domain the notion of a\*(lqwildcard\*(rq address has been provided. When an addressis specified as INADDR_ANY (a manifest constant defined in<netinet/in.h>), the system interprets the address as \*(lqany valid address\*(rq. For example, to bind a specificport number to a socket, but leave the local address unspecified,the following code might be used:.DS#include <sys/types.h>#include <netinet/in.h> ...struct sockaddr_in sin; ...s = socket(AF_INET, SOCK_STREAM, 0);sin.sin_family = AF_INET;sin.sin_addr.s_addr = htonl(INADDR_ANY);sin.sin_port = htons(MYPORT);bind(s, (struct sockaddr *) &sin, sizeof (sin));.DESockets with wildcarded local addresses may receive messagesdirected to the specified port number, and sent to anyof the possible addresses assigned to a host. For example,if a host has addresses 128.32.0.4 and 10.0.0.78, and a socket is bound asabove, the process will beable to accept connection requests which are addressed to128.32.0.4 or 10.0.0.78.If a server process wished to only allow hosts on agiven network connect to it, it would bindthe address of the host on the appropriate network..PPIn a similar fashion, a local port may be left unspecified(specified as zero), in which case the system will select anappropriate port number for it. This shortcut will workboth in the Internet and NS domains. For example, tobind a specific local address to a socket, but to leave thelocal port number unspecified:.DShp = gethostbyname(hostname);if (hp == NULL) { ...}bcopy(hp->h_addr, (char *) sin.sin_addr, hp->h_length);sin.sin_port = htons(0);bind(s, (struct sockaddr *) &sin, sizeof (sin));.DEThe system selects the local port number based on two criteria.The first is that on 4BSD systems,Internet ports below IPPORT_RESERVED (1024) (for the Xerox domain,0 through 3000) are reservedfor privileged users (i.e., the super user);Internet ports above IPPORT_USERRESERVED (50000) are reservedfor non-privileged servers. The second isthat the port number is not currently bound to some othersocket. In order to find a free Internet port number in the privilegedrange the \fIrresvport\fP library routine may be used as followsto return a stream socket in with a privileged port number:.DSint lport = IPPORT_RESERVED \- 1;int s;\&...s = rresvport(&lport);if (s < 0) { if (errno == EAGAIN) fprintf(stderr, "socket: all ports in use\en"); else perror("rresvport: socket"); ...}.DEThe restriction on allocating ports was done to allow processesexecuting in a \*(lqsecure\*(rq environment to perform authenticationbased on the originating address and port number. For example,the \fIrlogin\fP(1) command allows users to log in across a networkwithout being asked for a password, if two conditions hold:First, the name of the system the useris logging in from is in the file\fI/etc/hosts.equiv\fP on the system he is loggingin to (or the system name and the user name are inthe user's \fI.rhosts\fP file in the user's homedirectory), and second, that the user's rloginprocess is coming from a privileged port on the machine from which he islogging. The port number and network address of themachine from which the user is logging in can be determined eitherby the \fIfrom\fP result of the \fIaccept\fP call, orfrom the \fIgetpeername\fP call..PPIn certain cases the algorithm used by the system in selectingport numbers is unsuitable for an application. This is becauseassociations are created in a two step process. For example,the Internet file transfer protocol, FTP, specifies that dataconnections must always originate from the same local port. However,duplicate associations are avoided by connecting to different foreignports. In this situation the system would disallow binding thesame local address and port number to a socket if a previous dataconnection's socket still existed. To override the default portselection algorithm, an option call must be performed priorto address binding:.DS ...int on = 1; ...setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));bind(s, (struct sockaddr *) &sin, sizeof (sin));.DEWith the above call, local addresses may be bound whichare already in use. This does not violate the uniquenessrequirement as the system still checks at connect time tobe sure any other sockets with the same local address andport do not have the same foreign address and port.If the association already exists, the error EADDRINUSE is returned.A related socket option, SO_REUSEPORT, which allows completely duplicate bindings, is described in the IP multicasting section..NH 2Socket Options.PPIt is possible to set and get a number of options on socketsvia the \fIsetsockopt\fP and \fIgetsockopt\fP system calls.These options include such things as marking a socket forbroadcasting, not to route, to linger on close, etc.In addition, there are protocol-specific options for IP and TCP,as described in.IR ip (4),.IR tcp (4),and in the section on multicasting below..PPThe general forms of the calls are:.DSsetsockopt(s, level, optname, optval, optlen);.DEand.DSgetsockopt(s, level, optname, optval, optlen);.DE.PPThe parameters to the calls are as follows: \fIs\fPis the socket on which the option is to be applied.\fILevel\fP specifies the protocol layer on which theoption is to be applied; in most cases this isthe ``socket level'', indicated by the symbolic constantSOL_SOCKET, defined in \fI<sys/socket.h>.\fPThe actual option is specified in \fIoptname\fP, and isa symbolic constant also defined in \fI<sys/socket.h>\fP.\fIOptval\fP and \fIOptlen\fP point to the value of theoption (in most cases, whether the option is to be turnedon or off), and the length of the value of the option,respectively.For \fIgetsockopt\fP, \fIoptlen\fP isa value-result parameter, initially set to the size ofthe storage area pointed to by \fIoptval\fP, and modifiedupon return to indicate the actual amount of storage used..PPAn example should help clarify things. It is sometimesuseful to determine the type (e.g., stream, datagram, etc.)of an existing socket; programsunder \fIinetd\fP (described below) may need to perform thistask. This can be accomplished as follows via theSO_TYPE socket option and the \fIgetsockopt\fP call:.DS#include <sys/types.h>#include <sys/socket.h>int type, size;size = sizeof (int);if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &type, &size) < 0) { ...}.DEAfter the \fIgetsockopt\fP call, \fItype\fP will be setto the value of the socket type, as defined in\fI<sys/socket.h>\fP. If, for example, the socket werea datagram socket, \fItype\fP would have the value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -