xref: /illumos-gate/usr/src/man/man4p/tcp.4p (revision 6dde88b51419b99fe0aab8e56184c693945826b8)
1.\"
2.\" This file and its contents are supplied under the terms of the
3.\" Common Development and Distribution License ("CDDL"), version 1.0.
4.\" You may only use this file in accordance with the terms of version
5.\" 1.0 of the CDDL.
6.\"
7.\" A full copy of the text of the CDDL should have accompanied this
8.\" source.  A copy of the CDDL is also available via the Internet at
9.\" http://www.illumos.org/license/CDDL.
10.\"
11.\"
12.\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved.
13.\" Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
14.\" Copyright 2019 Joyent, Inc.
15.\" Copyright 2024 Oxide Computer Company
16.\" Copyright 1989 AT&T
17.\"
18.Dd May 2, 2024
19.Dt TCP 4P
20.Os
21.Sh NAME
22.Nm tcp ,
23.Nm TCP
24.Nd Internet Transmission Control Protocol
25.Sh SYNOPSIS
26.In sys/socket.h
27.In netinet/in.h
28.In netinet/tcp.h
29.Bd -literal
30s = socket(AF_INET, SOCK_STREAM, 0);
31s = socket(AF_INET6, SOCK_STREAM, 0);
32t = t_open("/dev/tcp", O_RDWR);
33t = t_open("/dev/tcp6", O_RDWR);
34.Ed
35.Sh DESCRIPTION
36TCP is the virtual circuit protocol of the Internet protocol family.
37It provides reliable, flow-controlled, in-order, two-way transmission of data.
38It is a byte-stream protocol layered above the Internet Protocol
39.Pq Sy IP ,
40or the Internet Protocol Version 6
41.Pq Sy IPv6 ,
42the Internet protocol family's
43internetwork datagram delivery protocol.
44.Pp
45Programs can access TCP using the socket interface as a
46.Dv SOCK_STREAM
47socket type, or using the Transport Level Interface
48.Pq Sy TLI
49where it supports the connection-oriented
50.Pq Dv BT_COTS_ORD
51service type.
52.Pp
53A checksum over all data helps TCP provide reliable communication.
54Using a window-based flow control mechanism that makes use of positive
55acknowledgements, sequence numbers, and a retransmission strategy, TCP can
56usually recover when datagrams are damaged, delayed, duplicated or delivered
57out of order by the underlying medium.
58.Pp
59TCP provides several socket options, defined in
60.In netinet/tcp.h
61and described throughout this document,
62which may be set using
63.Xr setsockopt 3SOCKET
64and read using
65.Xr getsockopt 3SOCKET .
66The
67.Fa level
68argument for these calls is the protocol number for TCP, available from
69.Xr getprotobyname 3SOCKET .
70IP level options may also be used with TCP.
71See
72.Xr ip 4P
73and
74.Xr ip6 4P .
75.Ss "Listening And Connecting"
76TCP uses IP's host-level addressing and adds its own per-host
77collection of
78.Dq port addresses .
79The endpoints of a TCP connection are
80identified by the combination of an IPv4 or IPv6 address and a TCP
81port number.
82Although other protocols, such as the User Datagram Protocol
83.Pq Sy UDP ,
84may use the same host and port address format, the port space of these
85protocols is distinct.
86See
87.Xr inet 4P
88and
89.Xr inet6 4P
90for details on
91the common aspects of addressing in the Internet protocol family.
92.Pp
93Sockets utilizing TCP are either
94.Dq active
95or
96.Dq passive .
97Active sockets
98initiate connections to passive sockets.
99Passive sockets must have their local IPv4 or IPv6 address and TCP port number
100bound with the
101.Xr bind 3SOCKET
102system call after the socket is created.
103If an active socket has not been bound by the time
104.Xr connect 3SOCKET
105is called, then the operating system will choose a local address and port for
106the application.
107By default, TCP sockets are active.
108A passive socket is created by calling the
109.Xr listen 3SOCKET
110system call after binding, which establishes a queueing parameter for the
111passive socket.
112Connections to the passive socket can then be received using the
113.Xr accept 3SOCKET
114system call.
115Active sockets use the
116.Xr connect 3SOCKET
117call after binding to initiate connections.
118.Pp
119If incoming connection requests include an IP source route option, then the
120reverse source route will be used when responding.
121.Pp
122By using the special value
123.Dv INADDR_ANY
124with IPv4, or the unspecified
125address
126.Pq all zeroes
127with IPv6, the local IP address can be left unspecified in the
128.Fn bind
129call by either active or passive TCP
130sockets.
131This feature is usually used if the local address is either unknown or
132irrelevant.
133If left unspecified, the local IP address will be bound at connection time to
134the address of the network interface used to service the connection.
135For passive sockets, this is the destination address used by the connecting
136peer.
137For active sockets, this is usually an address on the same subnet as the
138destination or default gateway address, although the rules can be more complex.
139See
140.Sy "Source Address Selection"
141in
142.Xr inet6 4P
143for a detailed discussion of how this works in IPv6.
144.Pp
145Note that no two TCP sockets can be bound to the same port unless the bound IP
146addresses are different.
147IPv4
148.Dv INADDR_ANY
149and IPv6 unspecified addresses compare as equal to any IPv4 or IPv6 address.
150For example, if a socket is bound to
151.Dv INADDR_ANY
152or the unspecified address and port
153.Em N ,
154no other socket can bind to port
155.Em N ,
156regardless of the binding address.
157This special consideration of
158.Dv INADDR_ANY
159and the unspecified address can be changed using the socket option
160.Dv SO_REUSEADDR .
161If
162.Dv SO_REUSEADDR
163is set on a socket doing a bind, IPv4
164.Dv INADDR_ANY
165and the IPv6 unspecified address do not compare as equal to any IP address.
166This means that as long as the two sockets are not both bound to
167.Dv INADDR_ANY ,
168the unspecified address, or the same IP address, then the two sockets can be
169bound to the same port.
170.Pp
171If an application does not want to allow another socket using the
172.Dv SO_REUSEADDR
173option to bind to a port its socket is bound to, the
174application can set the socket-level
175.Pq Dv SOL_SOCKET
176option
177.Dv SO_EXCLBIND
178on a socket.
179The
180option values of 0 and 1 mean enabling and disabling the option respectively.
181Once this option is enabled on a socket, no other socket can be bound to the
182same port.
183.Ss "Sending And Receiving Data"
184Once a connection has been established, data can be exchanged using the
185.Xr read 2
186and
187.Xr write 2
188system calls.
189If, after sending data, the local TCP receives no acknowledgements from its
190peer for a period of time
191.Pq for example, if the remote machine crashes ,
192the connection is closed and an error is returned.
193.Pp
194When a peer is sending data, it will only send up to the advertised
195.Dq receive window ,
196which is determined by how much more data the recipient can fit in its buffer.
197Applications can use the socket-level option
198.Dv SO_RCVBUF
199to increase or decrease the receive buffer size.
200Similarly, the socket-level option
201.Dv SO_SNDBUF
202can be used to allow TCP to buffer more unacknowledged and unsent data locally.
203.Pp
204Under most circumstances, TCP will send data when it is written by the
205application.
206When outstanding data has not yet been acknowledged, though, TCP will gather
207small amounts of output to be sent as a single packet once an acknowledgement
208has been received.
209Usually referred to as Nagle's Algorithm
210.Pq RFC 896 ,
211this behavior helps prevent flooding the network with many small packets.
212.Pp
213However, for some highly interactive clients
214.Po
215such as remote shells or windowing systems that send a stream of keypresses or
216mouse events
217.Pc ,
218this
219batching may cause significant delays.
220To disable this behavior, TCP provides a boolean socket option,
221.Dv TCP_NODELAY .
222.Pp
223Conversely, for other applications, it may be desirable for TCP not to send out
224any data until a full TCP segment can be sent.
225To enable this behavior, an application can use the TCP-level socket option
226.Dv TCP_CORK .
227When set to a non-zero value, TCP will only send out a full TCP segment.
228When
229.Dv TCP_CORK
230is set to zero after it has been enabled, all currently buffered data is sent
231out
232.Po
233as permitted by the peer's receive window and the current congestion window
234.Pc .
235.Pp
236Still other latency-sensitive applications rely on receiving a quick
237notification that their packets have been successfully received.
238To satisfy the requirements of those applications, setting the
239.Dv TCP_QUICKACK
240option to a non-zero value will instruct the TCP stack to send an acknowledgment
241immediately upon receipt of a packet, rather than waiting to acknowledge
242multiple packets at once.
243.Pp
244TCP provides an urgent data mechanism, which may be invoked using the
245out-of-band provisions of
246.Xr send 3SOCKET .
247The caller may mark one byte as
248.Dq urgent
249with the
250.Dv MSG_OOB
251flag to
252.Xr send 3SOCKET .
253This sets an
254.Dq urgent pointer
255pointing to this byte in the TCP stream.
256The receiver on the other side of the stream is notified of the urgent data by a
257.Dv SIGURG
258signal.
259The
260.Dv SIOCATMARK
261.Xr ioctl 2
262request returns a value indicating whether the stream is at the urgent mark.
263Because the system never returns data across the urgent mark in a single
264.Xr read 2
265call, it is possible to
266advance to the urgent data in a simple loop which reads data, testing the
267socket with the
268.Dv SIOCATMARK
269.Fn ioctl
270request, until it reaches the mark.
271.Pp
272The
273.Dv TCP_MD5SIG
274option controls the use of MD5 digests
275.Pq as defined by RFC 2385
276on the specified socket.
277The option value is specified as an
278.Vt int .
279When enabled
280.Pq non-zero ,
281outgoing packets have a digest added to the TCP options in their header, and
282digests in incoming packets are verified.
283In order to use this function, TCPSIG security associations
284.Pq one for each direction
285must also be configured in the system security association database
286.Pq SADB
287using
288.Xr tcpkey 8 .
289A listening socket with the option enabled accepts connections with digests
290only from sources for which a security association exists.
291Connections without digests are only accepted from sources for which no
292security association is set up.
293The resulting connected socket only has TCP_MD5SIG set if the connection is
294protected with MD5 signatures.
295If no matching security association
296.Pq SA
297is found for traffic on a socket configured with the
298.Dv TCP_MD5SIG
299option, no outgoing segments are sent, and all inbound segments are dropped.
300In particular, the SA must be present prior to the socket being used in a
301call to
302.Xr connect 3SOCKET
303or
304.Xr accept 3SOCKET .
305Once the option is enabled and an SA is bound to a connection, it will be
306cached and used for all subsequent segments; it cannot be changed mid-stream.
307An SA which is in use can be deleted using
308.Xr tcpkey 8
309and will not be used for any new connections, but existing connections continue
310to use their cached copy.
311.Ss "Congestion Control"
312TCP follows the congestion control algorithm described in RFC 2581, and
313also supports the initial congestion window
314.Pq cwnd
315changes in RFC 3390.
316The initial cwnd calculation can be overridden by the socket option
317.Dv TCP_INIT_CWND .
318An application can use this option to set the initial cwnd to a
319specified number of TCP segments.
320This applies to the cases when the connection
321first starts and restarts after an idle period.
322The process must have the
323.Dv PRIV_SYS_NET_CONFIG
324privilege if it wants to specify a number greater than that
325calculated by RFC 3390.
326.Pp
327The operating system also provides alternative algorithms that may be more
328appropriate for your application, including the CUBIC congestion control
329algorithm described in RFC 8312.
330These can be configured system-wide using
331.Xr ipadm 8 ,
332or on a per-connection basis with the TCP-level socket option
333.Dv TCP_CONGESTION ,
334whose argument is the name of the algorithm to use
335.Pq for example Dq cubic .
336If the requested algorithm does not exist, then
337.Fn setsockopt
338will fail, and
339.Va errno
340will be set to
341.Er ENOENT .
342.Ss "TCP Keep-Alive"
343Since TCP determines whether a remote peer is no longer reachable by timing out
344waiting for acknowledgements, a host that never sends any new data may never
345notice a peer that has gone away.
346While consumers can avoid this problem by sending their own periodic heartbeat
347messages
348.Pq Transport Layer Security does this, for example,
349TCP describes an optional keep-alive mechanism in RFC 1122.
350Applications can enable it using the socket-level option
351.Dv SO_KEEPALIVE .
352When enabled, the first keep-alive probe is sent out after a TCP connection is
353idle for two hours.
354If the peer does not respond to the probe within eight minutes, the TCP
355connection is aborted.
356An application can alter the probe behavior using the following TCP-level
357socket options:
358.Bl -tag -offset indent -width 16m
359.It Dv TCP_KEEPALIVE_THRESHOLD
360Determines the interval for sending the first probe.
361The option value is specified as an unsigned integer in milliseconds.
362The system default is controlled by the TCP
363.Nm ndd
364parameter
365.Cm tcp_keepalive_interval .
366The minimum value is ten seconds.
367The maximum is ten days, while the default is two hours.
368.It Dv TCP_KEEPALIVE_ABORT_THRESHOLD
369If TCP does not receive a response to the probe, then this option determines
370how long to wait before aborting a TCP connection.
371The option value is an unsigned integer in milliseconds.
372The value zero indicates that TCP should never time
373out and abort the connection when probing.
374The system default is controlled by the TCP
375.Nm ndd
376parameter
377.Sy tcp_keepalive_abort_interval .
378The default is eight minutes.
379.It Dv TCP_KEEPIDLE
380This option, like
381.Dv TCP_KEEPALIVE_THRESHOLD ,
382determines the interval for sending the first probe, except that
383the option value is an unsigned integer in
384.Sy seconds .
385It is provided primarily for compatibility with other Unix flavors.
386.It Dv TCP_KEEPCNT
387This option specifies the number of keep-alive probes that should be sent
388without any response from the peer before aborting the connection.
389.It Dv TCP_KEEPINTVL
390This option specifies the interval in seconds between successive,
391unacknowledged keep-alive probes.
392.El
393.Ss "Additional Configuration"
394illumos supports TCP Extensions for High Performance
395.Pq RFC 7323
396which includes the window scale and timestamp options, and Protection Against
397Wrap Around Sequence Numbers
398.Pq Sy PAWS .
399Note that if timestamps are negotiated on
400a connection, received segments without timestamps on that connection are
401silently dropped per the suggestion in the RFC. illumos also supports Selective
402Acknowledgment
403.Pq Sy SACK
404capabilities
405.Pq RFC 2018
406and Explicit Congestion Notification
407.Pq Sy ECN
408mechanism
409.Pq RFC 3168 .
410.Pp
411Turn on the window scale option in one of the following ways:
412.Bl -bullet -offset indent -width 4m
413.It
414An application can set
415.Dv SO_SNDBUF
416or
417.Dv SO_RCVBUF
418size in the
419.Fn setsockopt
420option to be larger than 64K.
421This must be done
422.Em before
423the program calls
424.Fn listen
425or
426.Fn connect ,
427because the window scale
428option is negotiated when the connection is established.
429Once the connection
430has been made, it is too late to increase the send or receive window beyond the
431default TCP limit of 64K.
432.It
433For all applications, use
434.Xr ndd 8
435to modify the configuration parameter
436.Cm tcp_wscale_always .
437If
438.Cm tcp_wscale_always
439is set to
440.Sy 1 ,
441the
442window scale option will always be set when connecting to a remote system.
443If
444.Cm tcp_wscale_always
445is
446.Sy 0 ,
447the window scale option will be set only if
448the user has requested a send or receive window larger than 64K.
449The default value of
450.Cm tcp_wscale_always
451is
452.Sy 1 .
453.It
454Regardless of the value of
455.Cm tcp_wscale_always ,
456the window scale option
457will always be included in a connect acknowledgement if the connecting system
458has used the option.
459.El
460.Pp
461Turn on SACK capabilities in the following way:
462.Bl -bullet -offset indent -width 4m
463.It
464Use
465.Nm ndd
466to modify the configuration parameter
467.Cm tcp_sack_permitted .
468If
469.Cm tcp_sack_permitted
470is set to
471.Sy 0 ,
472TCP will not accept SACK or send out SACK information.
473If
474.Cm tcp_sack_permitted
475is
476set to
477.Sy 1 ,
478TCP will not initiate a connection with SACK permitted option in the
479.Sy SYN
480segment, but will respond with SACK permitted option in the
481.Sy SYN|ACK
482segment if an incoming connection request has the SACK permitted option.
483This means that TCP will only accept SACK information if the other side of the
484connection also accepts SACK information.
485If
486.Cm tcp_sack_permitted
487is set to
488.Sy 2 ,
489it will both initiate and accept connections with SACK information.
490The default for
491.Cm tcp_sack_permitted
492is
493.Sy 2
494.Pq active enabled .
495.El
496.Pp
497Turn on the TCP ECN mechanism in the following way:
498.Bl -bullet -offset indent -width 4m
499.It
500Use
501.Nm ndd
502to modify the configuration parameter
503.Cm tcp_ecn_permitted .
504If
505.Cm tcp_ecn_permitted
506is set to
507.Sy 0 ,
508then TCP will not negotiate with a peer that supports ECN mechanism.
509If
510.Cm tcp_ecn_permitted
511is set to
512.Sy 1
513when initiating a connection, TCP will not tell a peer that it supports
514.Sy ECN
515mechanism.
516However, it will tell a peer that it supports
517.Sy ECN
518mechanism when accepting a new incoming connection request if the peer
519indicates that it supports
520.Sy ECN
521mechanism in the
522.Sy SYN
523segment.
524If
525.Cm tcp_ecn_permitted
526is set to 2, in addition to negotiating with a peer on
527.Sy ECN
528mechanism when accepting connections, TCP will indicate in the outgoing
529.Sy SYN
530segment that it supports
531.Sy ECN
532mechanism when TCP makes active outgoing connections.
533The default for
534.Cm tcp_ecn_permitted
535is 1.
536.El
537.Pp
538Turn on the timestamp option in the following way:
539.Bl -bullet -offset indent -width 4m
540.It
541Use
542.Nm ndd
543to modify the configuration parameter
544.Cm tcp_tstamp_always .
545If
546.Cm tcp_tstamp_always
547is
548.Sy 1 ,
549the timestamp option will always be set
550when connecting to a remote machine.
551If
552.Cm tcp_tstamp_always
553is
554.Sy 0 ,
555the timestamp option will not be set when connecting to a remote system.
556The
557default for
558.Cm tcp_tstamp_always
559is
560.Sy 0 .
561.It
562Regardless of the value of
563.Cm tcp_tstamp_always ,
564the timestamp option will
565always be included in a connect acknowledgement
566.Pq and all succeeding packets
567if the connecting system has used the timestamp option.
568.El
569.Pp
570Use the following procedure to turn on the timestamp option only when the
571window scale option is in effect:
572.Bl -bullet -offset indent -width 4m
573.It
574Use
575.Nm ndd
576to modify the configuration parameter
577.Cm tcp_tstamp_if_wscale .
578Setting
579.Cm tcp_tstamp_if_wscale
580to
581.Sy 1
582will cause the timestamp option
583to be set when connecting to a remote system, if the window scale option has
584been set.
585If
586.Cm tcp_tstamp_if_wscale
587is
588.Sy 0 ,
589the timestamp option will
590not be set when connecting to a remote system.
591The default for
592.Cm tcp_tstamp_if_wscale
593is
594.Sy 1 .
595.El
596.Pp
597Protection Against Wrap Around Sequence Numbers
598.Pq Sy PAWS
599is always used when the
600timestamp option is set.
601.Pp
602The operating system also supports multiple methods of generating initial sequence numbers.
603One of these methods is the improved technique suggested in RFC 1948.
604We
605.Em HIGHLY
606recommend that you set sequence number generation parameters as
607close to boot time as possible.
608This prevents sequence number problems on
609connections that use the same connection-ID as ones that used a different
610sequence number generation.
611The
612.Sy svc:/network/initial:default
613service configures the initial sequence number generation.
614The service reads the value contained in the configuration file
615.Pa /etc/default/inetinit
616to determine which method to use.
617.Pp
618The
619.Pa /etc/default/inetinit
620file is an unstable interface, and may change in future releases.
621.Sh EXAMPLES
622.Ss Example 1: Connecting to a server
623.Bd -literal
624$ gcc -std=c99 -Wall -lsocket -o client client.c
625$ cat client.c
626#include <sys/socket.h>
627#include <netinet/in.h>
628#include <netinet/tcp.h>
629#include <netdb.h>
630#include <stdio.h>
631#include <string.h>
632#include <unistd.h>
633
634int
635main(int argc, char *argv[])
636{
637	struct addrinfo hints, *gair, *p;
638	int fd, rv, rlen;
639	char buf[1024];
640	int y = 1;
641
642	if (argc != 3) {
643		fprintf(stderr, "%s <host> <port>\en", argv[0]);
644		return (1);
645	}
646
647	memset(&hints, 0, sizeof (hints));
648	hints.ai_family = PF_UNSPEC;
649	hints.ai_socktype = SOCK_STREAM;
650
651	if ((rv = getaddrinfo(argv[1], argv[2], &hints, &gair)) != 0) {
652		fprintf(stderr, "getaddrinfo() failed: %s\en",
653		    gai_strerror(rv));
654		return (1);
655	}
656
657	for (p = gair; p != NULL; p = p->ai_next) {
658		if ((fd = socket(
659		    p->ai_family,
660		    p->ai_socktype,
661		    p->ai_protocol)) == -1) {
662			perror("socket() failed");
663			continue;
664		}
665
666		if (connect(fd, p->ai_addr, p->ai_addrlen) == -1) {
667			close(fd);
668			perror("connect() failed");
669			continue;
670		}
671
672		break;
673	}
674
675	if (p == NULL) {
676		fprintf(stderr, "failed to connect to server\en");
677		return (1);
678	}
679
680	freeaddrinfo(gair);
681
682	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &y,
683	    sizeof (y)) == -1) {
684		perror("setsockopt(SO_KEEPALIVE) failed");
685		return (1);
686	}
687
688	while ((rlen = read(fd, buf, sizeof (buf))) > 0) {
689		fwrite(buf, rlen, 1, stdout);
690	}
691
692	if (rlen == -1) {
693		perror("read() failed");
694	}
695
696	fflush(stdout);
697
698	if (close(fd) == -1) {
699		perror("close() failed");
700	}
701
702	return (0);
703}
704$ ./client 127.0.0.1 8080
705hello
706$ ./client ::1 8080
707hello
708.Ed
709.Ss Example 2: Accepting client connections
710.Bd -literal
711$ gcc -std=c99 -Wall -lsocket -o server server.c
712$ cat server.c
713#include <sys/socket.h>
714#include <netinet/in.h>
715#include <netinet/tcp.h>
716#include <netdb.h>
717#include <stdio.h>
718#include <string.h>
719#include <unistd.h>
720#include <arpa/inet.h>
721
722void
723logmsg(struct sockaddr *s, int bytes)
724{
725	char dq[INET6_ADDRSTRLEN];
726
727	switch (s->sa_family) {
728	case AF_INET: {
729		struct sockaddr_in *s4 = (struct sockaddr_in *)s;
730		inet_ntop(AF_INET, &s4->sin_addr, dq, sizeof (dq));
731		fprintf(stdout, "sent %d bytes to %s:%d\en",
732		    bytes, dq, ntohs(s4->sin_port));
733		break;
734	}
735	case AF_INET6: {
736		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)s;
737		inet_ntop(AF_INET6, &s6->sin6_addr, dq, sizeof (dq));
738		fprintf(stdout, "sent %d bytes to [%s]:%d\en",
739		    bytes, dq, ntohs(s6->sin6_port));
740		break;
741	}
742	default:
743		fprintf(stdout, "sent %d bytes to unknown client\en",
744		    bytes);
745		break;
746	}
747}
748
749int
750main(int argc, char *argv[])
751{
752	struct addrinfo hints, *gair, *p;
753	int sfd, cfd;
754	int slen, wlen, rv;
755
756	if (argc != 3) {
757		fprintf(stderr, "%s <port> <message>\en", argv[0]);
758		return (1);
759	}
760
761	slen = strlen(argv[2]);
762
763	memset(&hints, 0, sizeof (hints));
764	hints.ai_family = PF_UNSPEC;
765	hints.ai_socktype = SOCK_STREAM;
766	hints.ai_flags = AI_PASSIVE;
767
768	if ((rv = getaddrinfo(NULL, argv[1], &hints, &gair)) != 0) {
769		fprintf(stderr, "getaddrinfo() failed: %s\en",
770		    gai_strerror(rv));
771		return (1);
772	}
773
774	for (p = gair; p != NULL; p = p->ai_next) {
775		if ((sfd = socket(
776		    p->ai_family,
777		    p->ai_socktype,
778		    p->ai_protocol)) == -1) {
779			perror("socket() failed");
780			continue;
781		}
782
783		if (bind(sfd, p->ai_addr, p->ai_addrlen) == -1) {
784			close(sfd);
785			perror("bind() failed");
786			continue;
787		}
788
789		break;
790	}
791
792	if (p == NULL) {
793		fprintf(stderr, "server failed to bind()\en");
794		return (1);
795	}
796
797	freeaddrinfo(gair);
798
799	if (listen(sfd, 1024) != 0) {
800		perror("listen() failed");
801		return (1);
802	}
803
804	fprintf(stdout, "waiting for clients...\en");
805
806	for (int times = 0; times < 5; times++) {
807		struct sockaddr_storage stor;
808		socklen_t alen = sizeof (stor);
809		struct sockaddr *addr = (struct sockaddr *)&stor;
810
811		if ((cfd = accept(sfd, addr, &alen)) == -1) {
812			perror("accept() failed");
813			continue;
814		}
815
816		wlen = 0;
817
818		do {
819			wlen += write(cfd, argv[2] + wlen, slen - wlen);
820		} while (wlen < slen);
821
822		logmsg(addr, wlen);
823
824		if (close(cfd) == -1) {
825			perror("close(cfd) failed");
826		}
827	}
828
829	if (close(sfd) == -1) {
830		perror("close(sfd) failed");
831	}
832
833	fprintf(stdout, "finished.\en");
834
835	return (0);
836}
837$ ./server 8080 $'hello\en'
838waiting for clients...
839sent 6 bytes to [::ffff:127.0.0.1]:59059
840sent 6 bytes to [::ffff:127.0.0.1]:47448
841sent 6 bytes to [::ffff:127.0.0.1]:54949
842sent 6 bytes to [::ffff:127.0.0.1]:55186
843sent 6 bytes to [::1]:62256
844finished.
845.Ed
846.Sh DIAGNOSTICS
847A socket operation may fail if:
848.Bl -tag -offset indent -width 16m
849.It Er EISCONN
850A
851.Fn connect
852operation was attempted on a socket on which a
853.Fn connect
854operation had already been performed.
855.It Er ETIMEDOUT
856A connection was dropped due to excessive retransmissions.
857.It Er ECONNRESET
858The remote peer forced the connection to be closed (usually because the remote
859machine has lost state information about the connection due to a crash).
860.It Er ECONNREFUSED
861The remote peer actively refused connection establishment (usually because no
862process is listening to the port).
863.It Er EADDRINUSE
864A
865.Fn bind
866operation was attempted on a socket with a network address/port pair that has
867already been bound to another socket.
868.It Er EADDRNOTAVAIL
869A
870.Fn bind
871operation was attempted on a socket with a network address for which no network
872interface exists.
873.It Er EACCES
874A
875.Fn bind
876operation was attempted with a
877.Dq reserved
878port number and the effective user ID of the process was not the privileged
879user.
880.It Er ENOBUFS
881The system ran out of memory for internal data structures.
882.El
883.Sh SEE ALSO
884.Xr svcs 1 ,
885.Xr ioctl 2 ,
886.Xr read 2 ,
887.Xr write 2 ,
888.Xr accept 3SOCKET ,
889.Xr bind 3SOCKET ,
890.Xr connect 3SOCKET ,
891.Xr getprotobyname 3SOCKET ,
892.Xr getsockopt 3SOCKET ,
893.Xr listen 3SOCKET ,
894.Xr send 3SOCKET ,
895.Xr inet 4P ,
896.Xr inet6 4P ,
897.Xr ip 4P ,
898.Xr ip6 4P ,
899.Xr smf 7 ,
900.Xr ndd 8 ,
901.Xr svcadm 8 ,
902.Xr tcpkey 8
903.Rs
904.%A "K. Ramakrishnan"
905.%A "S. Floyd"
906.%A "D. Black"
907.%T "The Addition of Explicit Congestion Notification (ECN) to IP"
908.%R "RFC 3168"
909.%D "September 2001"
910.Re
911.Rs
912.%A "M. Mathias"
913.%A "J. Mahdavi"
914.%A "S. Ford"
915.%A "A. Romanow"
916.%T "TCP Selective Acknowledgement Options"
917.%R "RFC 2018"
918.%D "October 1996"
919.Re
920.Rs
921.%A "S. Bellovin"
922.%T "Defending Against Sequence Number Attacks"
923.%R "RFC 1948"
924.%D "May 1996"
925.Re
926.Rs
927.%A "D. Borman"
928.%A "B. Braden"
929.%A "V. Jacobson"
930.%A "R. Scheffenegger, Ed."
931.%T "TCP Extensions for High Performance"
932.%R "RFC 7323"
933.%D "September 2014"
934.Re
935.Rs
936.%A "Jon Postel"
937.%T "Transmission Control Protocol - DARPA Internet Program Protocol Specification"
938.%R "RFC 793"
939.%C "Network Information Center, SRI International, Menlo Park, CA."
940.%D "September 1981"
941.Re
942.Rs
943.%A "A. Heffernan"
944.%T "Protection of BGP Sessions via the TCP MD5 Signature Option"
945.%R "RFC 2385"
946.%D "August 1998"
947.Re
948.Sh NOTES
949The
950.Sy tcp
951service is managed by the service management facility,
952.Xr smf 7 ,
953under the service identifier
954.Sy svc:/network/initial:default .
955.Pp
956Administrative actions on this service, such as enabling, disabling, or
957requesting restart, can be performed using
958.Xr svcadm 8 .
959The service's
960status can be queried using the
961.Xr svcs 1
962command.
963