diff options
Diffstat (limited to 'man7/unix.7')
-rw-r--r-- | man7/unix.7 | 1205 |
1 files changed, 1205 insertions, 0 deletions
diff --git a/man7/unix.7 b/man7/unix.7 new file mode 100644 index 0000000..cfa4188 --- /dev/null +++ b/man7/unix.7 @@ -0,0 +1,1205 @@ +.\" SPDX-License-Identifier: Linux-man-pages-1-para +.\" +.\" This man page is Copyright (C) 1999 Andi Kleen <ak@muc.de>, +.\" Copyright (C) 2008-2014, Michael Kerrisk <mtk.manpages@gmail.com>, +.\" and Copyright (C) 2016, Heinrich Schuchardt <xypron.glpk@gmx.de> +.\" +.\" Modified, 2003-12-02, Michael Kerrisk, <mtk.manpages@gmail.com> +.\" Modified, 2003-09-23, Adam Langley +.\" Modified, 2004-05-27, Michael Kerrisk, <mtk.manpages@gmail.com> +.\" Added SOCK_SEQPACKET +.\" 2008-05-27, mtk, Provide a clear description of the three types of +.\" address that can appear in the sockaddr_un structure: pathname, +.\" unnamed, and abstract. +.\" +.TH UNIX 7 2023-07-15 "Linux man-pages 6.05.01" +.SH NAME +unix \- sockets for local interprocess communication +.SH SYNOPSIS +.nf +.B #include <sys/socket.h> +.B #include <sys/un.h> +.PP +.IB unix_socket " = socket(AF_UNIX, type, 0);" +.IB error " = socketpair(AF_UNIX, type, 0, int *" sv ");" +.fi +.SH DESCRIPTION +The +.B AF_UNIX +(also known as +.BR AF_LOCAL ) +socket family is used to communicate between processes on the same machine +efficiently. +Traditionally, UNIX domain sockets can be either unnamed, +or bound to a filesystem pathname (marked as being of type socket). +Linux also supports an abstract namespace which is independent of the +filesystem. +.PP +Valid socket types in the UNIX domain are: +.BR SOCK_STREAM , +for a stream-oriented socket; +.BR SOCK_DGRAM , +for a datagram-oriented socket that preserves message boundaries +(as on most UNIX implementations, UNIX domain datagram +sockets are always reliable and don't reorder datagrams); +and (since Linux 2.6.4) +.BR SOCK_SEQPACKET , +for a sequenced-packet socket that is connection-oriented, +preserves message boundaries, +and delivers messages in the order that they were sent. +.PP +UNIX domain sockets support passing file descriptors or process credentials +to other processes using ancillary data. +.SS Address format +A UNIX domain socket address is represented in the following structure: +.PP +.in +4n +.EX +.\" #define UNIX_PATH_MAX 108 +.\" +struct sockaddr_un { + sa_family_t sun_family; /* AF_UNIX */ + char sun_path[108]; /* Pathname */ +}; +.EE +.in +.PP +The +.I sun_family +field always contains +.BR AF_UNIX . +On Linux, +.I sun_path +is 108 bytes in size; see also BUGS, below. +.PP +Various systems calls (for example, +.BR bind (2), +.BR connect (2), +and +.BR sendto (2)) +take a +.I sockaddr_un +argument as input. +Some other system calls (for example, +.BR getsockname (2), +.BR getpeername (2), +.BR recvfrom (2), +and +.BR accept (2)) +return an argument of this type. +.PP +Three types of address are distinguished in the +.I sockaddr_un +structure: +.TP +pathname +a UNIX domain socket can be bound to a null-terminated +filesystem pathname using +.BR bind (2). +When the address of a pathname socket is returned +(by one of the system calls noted above), +its length is +.IP +.in +4n +.EX +offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1 +.EE +.in +.IP +and +.I sun_path +contains the null-terminated pathname. +(On Linux, the above +.BR offsetof () +expression equates to the same value as +.IR sizeof(sa_family_t) , +but some other implementations include other fields before +.IR sun_path , +so the +.BR offsetof () +expression more portably describes the size of the address structure.) +.IP +For further details of pathname sockets, see below. +.TP +unnamed +A stream socket that has not been bound to a pathname using +.BR bind (2) +has no name. +Likewise, the two sockets created by +.BR socketpair (2) +are unnamed. +When the address of an unnamed socket is returned, +its length is +.IR "sizeof(sa_family_t)" , +and +.I sun_path +should not be inspected. +.\" There is quite some variation across implementations: FreeBSD +.\" says the length is 16 bytes, HP-UX 11 says it's zero bytes. +.TP +abstract +an abstract socket address is distinguished (from a pathname socket) +by the fact that +.I sun_path[0] +is a null byte (\[aq]\e0\[aq]). +The socket's address in this namespace is given by the additional +bytes in +.I sun_path +that are covered by the specified length of the address structure. +(Null bytes in the name have no special significance.) +The name has no connection with filesystem pathnames. +When the address of an abstract socket is returned, +the returned +.I addrlen +is greater than +.I sizeof(sa_family_t) +(i.e., greater than 2), and the name of the socket is contained in +the first +.I (addrlen \- sizeof(sa_family_t)) +bytes of +.IR sun_path . +.SS Pathname sockets +When binding a socket to a pathname, a few rules should be observed +for maximum portability and ease of coding: +.IP \[bu] 3 +The pathname in +.I sun_path +should be null-terminated. +.IP \[bu] +The length of the pathname, including the terminating null byte, +should not exceed the size of +.IR sun_path . +.IP \[bu] +The +.I addrlen +argument that describes the enclosing +.I sockaddr_un +structure should have a value of at least: +.IP +.in +4n +.EX +offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1 +.EE +.in +.IP +or, more simply, +.I addrlen +can be specified as +.IR "sizeof(struct sockaddr_un)" . +.PP +There is some variation in how implementations handle UNIX domain +socket addresses that do not follow the above rules. +For example, some (but not all) implementations +.\" Linux does this, including for the case where the supplied path +.\" is 108 bytes +append a null terminator if none is present in the supplied +.IR sun_path . +.PP +When coding portable applications, +keep in mind that some implementations +.\" HP-UX +have +.I sun_path +as short as 92 bytes. +.\" Modern BSDs generally have 104, Tru64 and AIX have 104, +.\" Solaris and Irix have 108 +.PP +Various system calls +.RB ( accept (2), +.BR recvfrom (2), +.BR getsockname (2), +.BR getpeername (2)) +return socket address structures. +When applied to UNIX domain sockets, the value-result +.I addrlen +argument supplied to the call should be initialized as above. +Upon return, the argument is set to indicate the +.I actual +size of the address structure. +The caller should check the value returned in this argument: +if the output value exceeds the input value, +then there is no guarantee that a null terminator is present in +.IR sun_path . +(See BUGS.) +.\" +.SS Pathname socket ownership and permissions +In the Linux implementation, +pathname sockets honor the permissions of the directory they are in. +Creation of a new socket fails if the process does not have write and +search (execute) permission on the directory in which the socket is created. +.PP +On Linux, +connecting to a stream socket object requires write permission on that socket; +sending a datagram to a datagram socket likewise +requires write permission on that socket. +POSIX does not make any statement about the effect of the permissions +on a socket file, and on some systems (e.g., older BSDs), +the socket permissions are ignored. +Portable programs should not rely on +this feature for security. +.PP +When creating a new socket, the owner and group of the socket file +are set according to the usual rules. +The socket file has all permissions enabled, +other than those that are turned off by the process +.BR umask (2). +.PP +The owner, group, and permissions of a pathname socket can be changed (using +.BR chown (2) +and +.BR chmod (2)). +.\" However, fchown() and fchmod() do not seem to have an effect +.\" +.SS Abstract sockets +Socket permissions have no meaning for abstract sockets: +the process +.BR umask (2) +has no effect when binding an abstract socket, +and changing the ownership and permissions of the object (via +.BR fchown (2) +and +.BR fchmod (2)) +has no effect on the accessibility of the socket. +.PP +Abstract sockets automatically disappear when all open references +to the socket are closed. +.PP +The abstract socket namespace is a nonportable Linux extension. +.\" +.SS Socket options +For historical reasons, these socket options are specified with a +.B SOL_SOCKET +type even though they are +.B AF_UNIX +specific. +They can be set with +.BR setsockopt (2) +and read with +.BR getsockopt (2) +by specifying +.B SOL_SOCKET +as the socket family. +.TP +.B SO_PASSCRED +Enabling this socket option causes receipt of the credentials of +the sending process in an +.B SCM_CREDENTIALS ancillary +message in each subsequently received message. +The returned credentials are those specified by the sender using +.BR SCM_CREDENTIALS , +or a default that includes the sender's PID, real user ID, and real group ID, +if the sender did not specify +.B SCM_CREDENTIALS +ancillary data. +.IP +When this option is set and the socket is not yet connected, +a unique name in the abstract namespace will be generated automatically. +.IP +The value given as an argument to +.BR setsockopt (2) +and returned as the result of +.BR getsockopt (2) +is an integer boolean flag. +.TP +.B SO_PASSSEC +Enables receiving of the SELinux security label of the peer socket +in an ancillary message of type +.B SCM_SECURITY +(see below). +.IP +The value given as an argument to +.BR setsockopt (2) +and returned as the result of +.BR getsockopt (2) +is an integer boolean flag. +.IP +The +.B SO_PASSSEC +option is supported for UNIX domain datagram sockets +.\" commit 877ce7c1b3afd69a9b1caeb1b9964c992641f52a +since Linux 2.6.18; +support for UNIX domain stream sockets was added +.\" commit 37a9a8df8ce9de6ea73349c9ac8bdf6ba4ec4f70 +in Linux 4.2. +.TP +.B SO_PEEK_OFF +See +.BR socket (7). +.TP +.B SO_PEERCRED +This read-only socket option returns the +credentials of the peer process connected to this socket. +The returned credentials are those that were in effect at the time +of the call to +.BR connect (2) +or +.BR socketpair (2). +.IP +The argument to +.BR getsockopt (2) +is a pointer to a +.I ucred +structure; define the +.B _GNU_SOURCE +feature test macro to obtain the definition of that structure from +.IR <sys/socket.h> . +.IP +The use of this option is possible only for connected +.B AF_UNIX +stream sockets and for +.B AF_UNIX +stream and datagram socket pairs created using +.BR socketpair (2). +.TP +.B SO_PEERSEC +This read-only socket option returns the +security context of the peer socket connected to this socket. +By default, this will be the same as the security context of +the process that created the peer socket unless overridden +by the policy or by a process with the required permissions. +.IP +The argument to +.BR getsockopt (2) +is a pointer to a buffer of the specified length in bytes +into which the security context string will be copied. +If the buffer length is less than the length of the security +context string, then +.BR getsockopt (2) +returns \-1, sets +.I errno +to +.BR ERANGE , +and returns the required length via +.IR optlen . +The caller should allocate at least +.B NAME_MAX +bytes for the buffer initially, although this is not guaranteed +to be sufficient. +Resizing the buffer to the returned length +and retrying may be necessary. +.IP +The security context string may include a terminating null character +in the returned length, but is not guaranteed to do so: a security +context "foo" might be represented as either {'f','o','o'} of length 3 +or {'f','o','o','\\0'} of length 4, which are considered to be +interchangeable. +The string is printable, does not contain non-terminating null characters, +and is in an unspecified encoding (in particular, it +is not guaranteed to be ASCII or UTF-8). +.IP +The use of this option for sockets in the +.B AF_UNIX +address family is supported since Linux 2.6.2 for connected stream sockets, +and since Linux 4.18 +.\" commit 0b811db2cb2aabc910e53d34ebb95a15997c33e7 +also for stream and datagram socket pairs created using +.BR socketpair (2). +.\" +.SS Autobind feature +If a +.BR bind (2) +call specifies +.I addrlen +as +.IR sizeof(sa_family_t) , +.\" i.e., sizeof(short) +or the +.B SO_PASSCRED +socket option was specified for a socket that was +not explicitly bound to an address, +then the socket is autobound to an abstract address. +The address consists of a null byte +followed by 5 bytes in the character set +.IR [0\-9a\-f] . +Thus, there is a limit of 2\[ha]20 autobind addresses. +(From Linux 2.1.15, when the autobind feature was added, +8 bytes were used, and the limit was thus 2\[ha]32 autobind addresses. +The change to 5 bytes came in Linux 2.3.15.) +.SS Sockets API +The following paragraphs describe domain-specific details and +unsupported features of the sockets API for UNIX domain sockets on Linux. +.PP +UNIX domain sockets do not support the transmission of +out-of-band data (the +.B MSG_OOB +flag for +.BR send (2) +and +.BR recv (2)). +.PP +The +.BR send (2) +.B MSG_MORE +flag is not supported by UNIX domain sockets. +.PP +Before Linux 3.4, +.\" commit 9f6f9af7694ede6314bed281eec74d588ba9474f +the use of +.B MSG_TRUNC +in the +.I flags +argument of +.BR recv (2) +was not supported by UNIX domain sockets. +.PP +The +.B SO_SNDBUF +socket option does have an effect for UNIX domain sockets, but the +.B SO_RCVBUF +option does not. +For datagram sockets, the +.B SO_SNDBUF +value imposes an upper limit on the size of outgoing datagrams. +This limit is calculated as the doubled (see +.BR socket (7)) +option value less 32 bytes used for overhead. +.SS Ancillary messages +Ancillary data is sent and received using +.BR sendmsg (2) +and +.BR recvmsg (2). +For historical reasons, the ancillary message types listed below +are specified with a +.B SOL_SOCKET +type even though they are +.B AF_UNIX +specific. +To send them, set the +.I cmsg_level +field of the struct +.I cmsghdr +to +.B SOL_SOCKET +and the +.I cmsg_type +field to the type. +For more information, see +.BR cmsg (3). +.TP +.B SCM_RIGHTS +Send or receive a set of open file descriptors from another process. +The data portion contains an integer array of the file descriptors. +.IP +Commonly, this operation is referred to as "passing a file descriptor" +to another process. +However, more accurately, +what is being passed is a reference to an open file description (see +.BR open (2)), +and in the receiving process it is likely that a different +file descriptor number will be used. +Semantically, this operation is equivalent to duplicating +.RB ( dup (2)) +a file descriptor into the file descriptor table of another process. +.IP +If the buffer used to receive the ancillary data containing +file descriptors is too small (or is absent), +then the ancillary data is truncated (or discarded) +and the excess file descriptors are automatically closed +in the receiving process. +.IP +If the number of file descriptors received in the ancillary data would +cause the process to exceed its +.B RLIMIT_NOFILE +resource limit (see +.BR getrlimit (2)), +the excess file descriptors are automatically closed +in the receiving process. +.IP +The kernel constant +.B SCM_MAX_FD +defines a limit on the number of file descriptors in the array. +Attempting to send an array larger than this limit causes +.BR sendmsg (2) +to fail with the error +.BR EINVAL . +.B SCM_MAX_FD +has the value 253 +.\" commit bba14de98753cb6599a2dae0e520714b2153522d +(or 255 before Linux 2.6.38). +.TP +.B SCM_CREDENTIALS +Send or receive UNIX credentials. +This can be used for authentication. +The credentials are passed as a +.I struct ucred +ancillary message. +This structure is defined in +.I <sys/socket.h> +as follows: +.IP +.in +4n +.EX +struct ucred { + pid_t pid; /* Process ID of the sending process */ + uid_t uid; /* User ID of the sending process */ + gid_t gid; /* Group ID of the sending process */ +}; +.EE +.in +.IP +Since glibc 2.8, the +.B _GNU_SOURCE +feature test macro must be defined (before including +.I any +header files) in order to obtain the definition +of this structure. +.IP +The credentials which the sender specifies are checked by the kernel. +A privileged process is allowed to specify values that do not match its own. +The sender must specify its own process ID (unless it has the capability +.BR CAP_SYS_ADMIN , +in which case the PID of any existing process may be specified), +its real user ID, effective user ID, or saved set-user-ID (unless it has +.BR CAP_SETUID ), +and its real group ID, effective group ID, or saved set-group-ID +(unless it has +.BR CAP_SETGID ). +.IP +To receive a +.I struct ucred +message, the +.B SO_PASSCRED +option must be enabled on the socket. +.TP +.B SCM_SECURITY +Receive the SELinux security context (the security label) +of the peer socket. +The received ancillary data is a null-terminated string containing +the security context. +The receiver should allocate at least +.B NAME_MAX +bytes in the data portion of the ancillary message for this data. +.IP +To receive the security context, the +.B SO_PASSSEC +option must be enabled on the socket (see above). +.PP +When sending ancillary data with +.BR sendmsg (2), +only one item of each of the above types may be included in the sent message. +.PP +At least one byte of real data should be sent when sending ancillary data. +On Linux, this is required to successfully send ancillary data over +a UNIX domain stream socket. +When sending ancillary data over a UNIX domain datagram socket, +it is not necessary on Linux to send any accompanying real data. +However, portable applications should also include at least one byte +of real data when sending ancillary data over a datagram socket. +.PP +When receiving from a stream socket, +ancillary data forms a kind of barrier for the received data. +For example, suppose that the sender transmits as follows: +.PP +.RS +.PD 0 +.IP (1) 5 +.BR sendmsg (2) +of four bytes, with no ancillary data. +.IP (2) +.BR sendmsg (2) +of one byte, with ancillary data. +.IP (3) +.BR sendmsg (2) +of four bytes, with no ancillary data. +.PD +.RE +.PP +Suppose that the receiver now performs +.BR recvmsg (2) +calls each with a buffer size of 20 bytes. +The first call will receive five bytes of data, +along with the ancillary data sent by the second +.BR sendmsg (2) +call. +The next call will receive the remaining four bytes of data. +.PP +If the space allocated for receiving incoming ancillary data is too small +then the ancillary data is truncated to the number of headers +that will fit in the supplied buffer (or, in the case of an +.B SCM_RIGHTS +file descriptor list, the list of file descriptors may be truncated). +If no buffer is provided for incoming ancillary data (i.e., the +.I msg_control +field of the +.I msghdr +structure supplied to +.BR recvmsg (2) +is NULL), +then the incoming ancillary data is discarded. +In both of these cases, the +.B MSG_CTRUNC +flag will be set in the +.I msg.msg_flags +value returned by +.BR recvmsg (2). +.\" +.SS Ioctls +The following +.BR ioctl (2) +calls return information in +.IR value . +The correct syntax is: +.PP +.RS +.nf +.BI int " value"; +.IB error " = ioctl(" unix_socket ", " ioctl_type ", &" value ");" +.fi +.RE +.PP +.I ioctl_type +can be: +.TP +.B SIOCINQ +For +.B SOCK_STREAM +sockets, this call returns the number of unread bytes in the receive buffer. +The socket must not be in LISTEN state, otherwise an error +.RB ( EINVAL ) +is returned. +.B SIOCINQ +is defined in +.IR <linux/sockios.h> . +.\" FIXME . https://www.sourceware.org/bugzilla/show_bug.cgi?id=12002, +.\" filed 2010-09-10, may cause SIOCINQ to be defined in glibc headers +Alternatively, +you can use the synonymous +.BR FIONREAD , +defined in +.IR <sys/ioctl.h> . +.\" SIOCOUTQ also has an effect for UNIX domain sockets, but not +.\" quite what userland might expect. It seems to return the number +.\" of bytes allocated for buffers containing pending output. +.\" That number is normally larger than the number of bytes of pending +.\" output. Since this info is, from userland's point of view, imprecise, +.\" and it may well change, probably best not to document this now. +For +.B SOCK_DGRAM +sockets, +the returned value is the same as +for Internet domain datagram sockets; +see +.BR udp (7). +.SH ERRORS +.TP +.B EADDRINUSE +The specified local address is already in use or the filesystem socket +object already exists. +.TP +.B EBADF +This error can occur for +.BR sendmsg (2) +when sending a file descriptor as ancillary data over +a UNIX domain socket (see the description of +.BR SCM_RIGHTS , +above), and indicates that the file descriptor number that +is being sent is not valid (e.g., it is not an open file descriptor). +.TP +.B ECONNREFUSED +The remote address specified by +.BR connect (2) +was not a listening socket. +This error can also occur if the target pathname is not a socket. +.TP +.B ECONNRESET +Remote socket was unexpectedly closed. +.TP +.B EFAULT +User memory address was not valid. +.TP +.B EINVAL +Invalid argument passed. +A common cause is that the value +.B AF_UNIX +was not specified in the +.I sun_type +field of passed addresses, or the socket was in an +invalid state for the applied operation. +.TP +.B EISCONN +.BR connect (2) +called on an already connected socket or a target address was +specified on a connected socket. +.TP +.B ENFILE +The system-wide limit on the total number of open files has been reached. +.TP +.B ENOENT +The pathname in the remote address specified to +.BR connect (2) +did not exist. +.TP +.B ENOMEM +Out of memory. +.TP +.B ENOTCONN +Socket operation needs a target address, but the socket is not connected. +.TP +.B EOPNOTSUPP +Stream operation called on non-stream oriented socket or tried to +use the out-of-band data option. +.TP +.B EPERM +The sender passed invalid credentials in the +.IR "struct ucred" . +.TP +.B EPIPE +Remote socket was closed on a stream socket. +If enabled, a +.B SIGPIPE +is sent as well. +This can be avoided by passing the +.B MSG_NOSIGNAL +flag to +.BR send (2) +or +.BR sendmsg (2). +.TP +.B EPROTONOSUPPORT +Passed protocol is not +.BR AF_UNIX . +.TP +.B EPROTOTYPE +Remote socket does not match the local socket type +.RB ( SOCK_DGRAM +versus +.BR SOCK_STREAM ). +.TP +.B ESOCKTNOSUPPORT +Unknown socket type. +.TP +.B ESRCH +While sending an ancillary message containing credentials +.RB ( SCM_CREDENTIALS ), +the caller specified a PID that does not match any existing process. +.TP +.B ETOOMANYREFS +This error can occur for +.BR sendmsg (2) +when sending a file descriptor as ancillary data over +a UNIX domain socket (see the description of +.BR SCM_RIGHTS , +above). +It occurs if the number of "in-flight" file descriptors exceeds the +.B RLIMIT_NOFILE +resource limit and the caller does not have the +.B CAP_SYS_RESOURCE +capability. +An in-flight file descriptor is one that has been sent using +.BR sendmsg (2) +but has not yet been accepted in the recipient process using +.BR recvmsg (2). +.IP +This error is diagnosed since mainline Linux 4.5 +(and in some earlier kernel versions where the fix has been backported). +.\" commit 712f4aad406bb1ed67f3f98d04c044191f0ff593 +In earlier kernel versions, +it was possible to place an unlimited number of file descriptors in flight, +by sending each file descriptor with +.BR sendmsg (2) +and then closing the file descriptor so that it was not accounted against the +.B RLIMIT_NOFILE +resource limit. +.PP +Other errors can be generated by the generic socket layer or +by the filesystem while generating a filesystem socket object. +See the appropriate manual pages for more information. +.SH VERSIONS +.B SCM_CREDENTIALS +and the abstract namespace were introduced with Linux 2.2 and should not +be used in portable programs. +(Some BSD-derived systems also support credential passing, +but the implementation details differ.) +.SH NOTES +Binding to a socket with a filename creates a socket +in the filesystem that must be deleted by the caller when it is no +longer needed (using +.BR unlink (2)). +The usual UNIX close-behind semantics apply; the socket can be unlinked +at any time and will be finally removed from the filesystem when the last +reference to it is closed. +.PP +To pass file descriptors or credentials over a +.B SOCK_STREAM +socket, you must +send or receive at least one byte of nonancillary data in the same +.BR sendmsg (2) +or +.BR recvmsg (2) +call. +.PP +UNIX domain stream sockets do not support the notion of out-of-band data. +.\" +.SH BUGS +When binding a socket to an address, +Linux is one of the implementations that appends a null terminator +if none is supplied in +.IR sun_path . +In most cases this is unproblematic: +when the socket address is retrieved, +it will be one byte longer than that supplied when the socket was bound. +However, there is one case where confusing behavior can result: +if 108 non-null bytes are supplied when a socket is bound, +then the addition of the null terminator takes the length of +the pathname beyond +.IR sizeof(sun_path) . +Consequently, when retrieving the socket address +(for example, via +.BR accept (2)), +.\" The behavior on Solaris is quite similar. +if the input +.I addrlen +argument for the retrieving call is specified as +.IR "sizeof(struct sockaddr_un)" , +then the returned address structure +.I won't +have a null terminator in +.IR sun_path . +.PP +In addition, some implementations +.\" i.e., traditional BSD +don't require a null terminator when binding a socket (the +.I addrlen +argument is used to determine the length of +.IR sun_path ) +and when the socket address is retrieved on these implementations, +there is no null terminator in +.IR sun_path . +.PP +Applications that retrieve socket addresses can (portably) code +to handle the possibility that there is no null terminator in +.I sun_path +by respecting the fact that the number of valid bytes in the pathname is: +.PP +.in +4n +.EX +strnlen(addr.sun_path, addrlen \- offsetof(sockaddr_un, sun_path)) +.EE +.in +.\" The following patch to amend kernel behavior was rejected: +.\" http://thread.gmane.org/gmane.linux.kernel.api/2437 +.\" Subject: [patch] Fix handling of overlength pathname in AF_UNIX sun_path +.\" 2012-04-17 +.\" And there was a related discussion in the Austin list: +.\" http://thread.gmane.org/gmane.comp.standards.posix.austin.general/5735 +.\" Subject: Having a sun_path with no null terminator +.\" 2012-04-18 +.\" +.\" FIXME . Track http://austingroupbugs.net/view.php?id=561 +.PP +Alternatively, an application can retrieve +the socket address by allocating a buffer of size +.I "sizeof(struct sockaddr_un)+1" +that is zeroed out before the retrieval. +The retrieving call can specify +.I addrlen +as +.IR "sizeof(struct sockaddr_un)" , +and the extra zero byte ensures that there will be +a null terminator for the string returned in +.IR sun_path : +.PP +.in +4n +.EX +void *addrp; +\& +addrlen = sizeof(struct sockaddr_un); +addrp = malloc(addrlen + 1); +if (addrp == NULL) + /* Handle error */ ; +memset(addrp, 0, addrlen + 1); +\& +if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == \-1) + /* handle error */ ; +\& +printf("sun_path = %s\en", ((struct sockaddr_un *) addrp)\->sun_path); +.EE +.in +.PP +This sort of messiness can be avoided if it is guaranteed +that the applications that +.I create +pathname sockets follow the rules outlined above under +.IR "Pathname sockets" . +.SH EXAMPLES +The following code demonstrates the use of sequenced-packet +sockets for local interprocess communication. +It consists of two programs. +The server program waits for a connection from the client program. +The client sends each of its command-line arguments in separate messages. +The server treats the incoming messages as integers and adds them up. +The client sends the command string "END". +The server sends back a message containing the sum of the client's integers. +The client prints the sum and exits. +The server waits for the next client to connect. +To stop the server, the client is called with the command-line argument "DOWN". +.PP +The following output was recorded while running the server in the background +and repeatedly executing the client. +Execution of the server program ends when it receives the "DOWN" command. +.SS Example output +.in +4n +.EX +$ \fB./server &\fP +[1] 25887 +$ \fB./client 3 4\fP +Result = 7 +$ \fB./client 11 \-5\fP +Result = 6 +$ \fB./client DOWN\fP +Result = 0 +[1]+ Done ./server +$ +.EE +.in +.SS Program source +\& +.EX +/* + * File connection.h + */ +\& +#define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket" +#define BUFFER_SIZE 12 +\& +/* + * File server.c + */ +\& +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include "connection.h" +\& +int +main(int argc, char *argv[]) +{ + struct sockaddr_un name; + int down_flag = 0; + int ret; + int connection_socket; + int data_socket; + int result; + char buffer[BUFFER_SIZE]; +\& + /* Create local socket. */ +\& + connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (connection_socket == \-1) { + perror("socket"); + exit(EXIT_FAILURE); + } +\& + /* + * For portability clear the whole structure, since some + * implementations have additional (nonstandard) fields in + * the structure. + */ +\& + memset(&name, 0, sizeof(name)); +\& + /* Bind socket to socket name. */ +\& + name.sun_family = AF_UNIX; + strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) \- 1); +\& + ret = bind(connection_socket, (const struct sockaddr *) &name, + sizeof(name)); + if (ret == \-1) { + perror("bind"); + exit(EXIT_FAILURE); + } +\& + /* + * Prepare for accepting connections. The backlog size is set + * to 20. So while one request is being processed other requests + * can be waiting. + */ +\& + ret = listen(connection_socket, 20); + if (ret == \-1) { + perror("listen"); + exit(EXIT_FAILURE); + } +\& + /* This is the main loop for handling connections. */ +\& + for (;;) { +\& + /* Wait for incoming connection. */ +\& + data_socket = accept(connection_socket, NULL, NULL); + if (data_socket == \-1) { + perror("accept"); + exit(EXIT_FAILURE); + } +\& + result = 0; + for (;;) { +\& + /* Wait for next data packet. */ +\& + ret = read(data_socket, buffer, sizeof(buffer)); + if (ret == \-1) { + perror("read"); + exit(EXIT_FAILURE); + } +\& + /* Ensure buffer is 0\-terminated. */ +\& + buffer[sizeof(buffer) \- 1] = 0; +\& + /* Handle commands. */ +\& + if (!strncmp(buffer, "DOWN", sizeof(buffer))) { + down_flag = 1; + break; + } +\& + if (!strncmp(buffer, "END", sizeof(buffer))) { + break; + } +\& + /* Add received summand. */ +\& + result += atoi(buffer); + } +\& + /* Send result. */ +\& + sprintf(buffer, "%d", result); + ret = write(data_socket, buffer, sizeof(buffer)); + if (ret == \-1) { + perror("write"); + exit(EXIT_FAILURE); + } +\& + /* Close socket. */ +\& + close(data_socket); +\& + /* Quit on DOWN command. */ +\& + if (down_flag) { + break; + } + } +\& + close(connection_socket); +\& + /* Unlink the socket. */ +\& + unlink(SOCKET_NAME); +\& + exit(EXIT_SUCCESS); +} +\& +/* + * File client.c + */ +\& +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include "connection.h" +\& +int +main(int argc, char *argv[]) +{ + struct sockaddr_un addr; + int ret; + int data_socket; + char buffer[BUFFER_SIZE]; +\& + /* Create local socket. */ +\& + data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (data_socket == \-1) { + perror("socket"); + exit(EXIT_FAILURE); + } +\& + /* + * For portability clear the whole structure, since some + * implementations have additional (nonstandard) fields in + * the structure. + */ +\& + memset(&addr, 0, sizeof(addr)); +\& + /* Connect socket to socket address. */ +\& + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) \- 1); +\& + ret = connect(data_socket, (const struct sockaddr *) &addr, + sizeof(addr)); + if (ret == \-1) { + fprintf(stderr, "The server is down.\en"); + exit(EXIT_FAILURE); + } +\& + /* Send arguments. */ +\& + for (size_t i = 1; i < argc; ++i) { + ret = write(data_socket, argv[i], strlen(argv[i]) + 1); + if (ret == \-1) { + perror("write"); + break; + } + } +\& + /* Request result. */ +\& + strcpy(buffer, "END"); + ret = write(data_socket, buffer, strlen(buffer) + 1); + if (ret == \-1) { + perror("write"); + exit(EXIT_FAILURE); + } +\& + /* Receive result. */ +\& + ret = read(data_socket, buffer, sizeof(buffer)); + if (ret == \-1) { + perror("read"); + exit(EXIT_FAILURE); + } +\& + /* Ensure buffer is 0\-terminated. */ +\& + buffer[sizeof(buffer) \- 1] = 0; +\& + printf("Result = %s\en", buffer); +\& + /* Close socket. */ +\& + close(data_socket); +\& + exit(EXIT_SUCCESS); +} +.EE +.PP +For examples of the use of +.BR SCM_RIGHTS , +see +.BR cmsg (3) +and +.BR seccomp_unotify (2). +.SH SEE ALSO +.BR recvmsg (2), +.BR sendmsg (2), +.BR socket (2), +.BR socketpair (2), +.BR cmsg (3), +.BR capabilities (7), +.BR credentials (7), +.BR socket (7), +.BR udp (7) |