mirror of https://github.com/mkerrisk/man-pages
unix.7: Various additions and rewordings
Notable changes: * Clarify some details for pathname sockets. * Add some advice on portably coding with pathname sockets. * Note the "buggy" behavior for pathname sockets when the supplied pathname is 108 bytes (after a report by Tetsuo Handa). Commented-by: Carlos O'Donell <carlos@systemhalted.org> Commented-by: David Miller <davem@davemloft.net> Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
parent
a5c24f8c5f
commit
d02879f70a
215
man7/unix.7
215
man7/unix.7
|
@ -1,6 +1,8 @@
|
||||||
.\" This man page is Copyright (C) 1999 Andi Kleen <ak@muc.de>.
|
.\" This man page is Copyright (C) 1999 Andi Kleen <ak@muc.de>.
|
||||||
|
.\" and Copyright (C) 2008-2014, Michael Kerrisk <mtk.manpages@gmail.com>
|
||||||
.\"
|
.\"
|
||||||
.\" %%%LICENSE_START(VERBATIM_ONE_PARA)
|
.\" %%%LICENSE_START(VERBATIM_ONE_PARA)
|
||||||
|
.\" and Copyright (C) 2008, 2012 Michael Kerrisk <mtk.manpages@gmail.com>
|
||||||
.\" Permission is granted to distribute possibly modified copies
|
.\" Permission is granted to distribute possibly modified copies
|
||||||
.\" of this page provided the header is included verbatim,
|
.\" of this page provided the header is included verbatim,
|
||||||
.\" and in case of nontrivial modification author and date
|
.\" and in case of nontrivial modification author and date
|
||||||
|
@ -38,9 +40,9 @@ or bound to a filesystem pathname (marked as being of type socket).
|
||||||
Linux also supports an abstract namespace which is independent of the
|
Linux also supports an abstract namespace which is independent of the
|
||||||
filesystem.
|
filesystem.
|
||||||
|
|
||||||
Valid types are:
|
Valid socket types in the UNIX domain are:
|
||||||
.BR SOCK_STREAM ,
|
.BR SOCK_STREAM ,
|
||||||
for a stream-oriented socket and
|
for a stream-oriented socket;
|
||||||
.BR SOCK_DGRAM ,
|
.BR SOCK_DGRAM ,
|
||||||
for a datagram-oriented socket that preserves message boundaries
|
for a datagram-oriented socket that preserves message boundaries
|
||||||
(as on most UNIX implementations, UNIX domain datagram
|
(as on most UNIX implementations, UNIX domain datagram
|
||||||
|
@ -66,21 +68,37 @@ struct sockaddr_un {
|
||||||
.fi
|
.fi
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
|
The
|
||||||
.I sun_family
|
.I sun_family
|
||||||
always contains
|
field always contains
|
||||||
.BR AF_UNIX .
|
.BR AF_UNIX .
|
||||||
|
|
||||||
Three types of address are distinguished in this structure:
|
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.
|
||||||
|
|
||||||
|
Three types of address are distinguished in the
|
||||||
|
.I sockaddr_un
|
||||||
|
structure:
|
||||||
.IP * 3
|
.IP * 3
|
||||||
.IR pathname :
|
.IR pathname :
|
||||||
a UNIX domain socket can be bound to a null-terminated
|
a UNIX domain socket can be bound to a null-terminated
|
||||||
filesystem pathname using
|
filesystem pathname using
|
||||||
.BR bind (2).
|
.BR bind (2).
|
||||||
When the address of the socket is returned by
|
When the address of a pathname socket is returned
|
||||||
.BR getsockname (2),
|
(by one of the system calls noted above),
|
||||||
.BR getpeername (2),
|
|
||||||
and
|
|
||||||
.BR accept (2),
|
|
||||||
its length is
|
its length is
|
||||||
|
|
||||||
offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
|
offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
|
||||||
|
@ -88,6 +106,17 @@ its length is
|
||||||
and
|
and
|
||||||
.I sun_path
|
.I sun_path
|
||||||
contains the null-terminated pathname.
|
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.
|
||||||
.IP *
|
.IP *
|
||||||
.IR unnamed :
|
.IR unnamed :
|
||||||
A stream socket that has not been bound to a pathname using
|
A stream socket that has not been bound to a pathname using
|
||||||
|
@ -96,11 +125,7 @@ has no name.
|
||||||
Likewise, the two sockets created by
|
Likewise, the two sockets created by
|
||||||
.BR socketpair (2)
|
.BR socketpair (2)
|
||||||
are unnamed.
|
are unnamed.
|
||||||
When the address of an unnamed socket is returned by
|
When the address of an unnamed socket is returned,
|
||||||
.BR getsockname (2),
|
|
||||||
.BR getpeername (2),
|
|
||||||
and
|
|
||||||
.BR accept (2),
|
|
||||||
its length is
|
its length is
|
||||||
.IR "sizeof(sa_family_t)" ,
|
.IR "sizeof(sa_family_t)" ,
|
||||||
and
|
and
|
||||||
|
@ -110,7 +135,8 @@ should not be inspected.
|
||||||
.\" says the length is 16 bytes, HP-UX 11 says it's zero bytes.
|
.\" says the length is 16 bytes, HP-UX 11 says it's zero bytes.
|
||||||
.IP *
|
.IP *
|
||||||
.IR abstract :
|
.IR abstract :
|
||||||
an abstract socket address is distinguished by the fact that
|
an abstract socket address is distinguished (from a pathname socket)
|
||||||
|
by the fact that
|
||||||
.IR sun_path[0]
|
.IR sun_path[0]
|
||||||
is a null byte (\(aq\\0\(aq).
|
is a null byte (\(aq\\0\(aq).
|
||||||
The socket's address in this namespace is given by the additional
|
The socket's address in this namespace is given by the additional
|
||||||
|
@ -119,11 +145,7 @@ bytes in
|
||||||
that are covered by the specified length of the address structure.
|
that are covered by the specified length of the address structure.
|
||||||
(Null bytes in the name have no special significance.)
|
(Null bytes in the name have no special significance.)
|
||||||
The name has no connection with filesystem pathnames.
|
The name has no connection with filesystem pathnames.
|
||||||
When the address of an abstract socket is returned by
|
When the address of an abstract socket is returned,
|
||||||
.BR getsockname (2),
|
|
||||||
.BR getpeername (2),
|
|
||||||
and
|
|
||||||
.BR accept (2),
|
|
||||||
the returned
|
the returned
|
||||||
.I addrlen
|
.I addrlen
|
||||||
is greater than
|
is greater than
|
||||||
|
@ -134,6 +156,67 @@ the first
|
||||||
bytes of
|
bytes of
|
||||||
.IR sun_path .
|
.IR sun_path .
|
||||||
The abstract socket namespace is a nonportable Linux extension.
|
The abstract socket namespace is a nonportable Linux extension.
|
||||||
|
.SS Pathname sockets
|
||||||
|
When binding a socket to a pathname, a few rules should be observed
|
||||||
|
for maximum portability and ease of coding:
|
||||||
|
.IP * 3
|
||||||
|
The pathname in
|
||||||
|
.I sun_path
|
||||||
|
should be null-terminated.
|
||||||
|
.IP *
|
||||||
|
The length of the pathname, including the terminating null byte,
|
||||||
|
should not exceed the size of
|
||||||
|
.IR sun_path .
|
||||||
|
.IP *
|
||||||
|
The
|
||||||
|
.I addrlen
|
||||||
|
argument that describes the enclosing
|
||||||
|
.I sockaddr_un
|
||||||
|
structure should have a value of at least:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1
|
||||||
|
.fi
|
||||||
|
.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 .
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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 Socket options
|
.SS Socket options
|
||||||
For historical reasons these socket options are specified with a
|
For historical reasons these socket options are specified with a
|
||||||
.B SOL_SOCKET
|
.B SOL_SOCKET
|
||||||
|
@ -329,7 +412,7 @@ object already exists.
|
||||||
The remote address specified by
|
The remote address specified by
|
||||||
.BR connect (2)
|
.BR connect (2)
|
||||||
was not a listening socket.
|
was not a listening socket.
|
||||||
This error can also occur if the target filename is not a socket.
|
This error can also occur if the target pathname is not a socket.
|
||||||
.TP
|
.TP
|
||||||
.B ECONNRESET
|
.B ECONNRESET
|
||||||
Remote socket was unexpectedly closed.
|
Remote socket was unexpectedly closed.
|
||||||
|
@ -407,7 +490,7 @@ but the implementation details differ.)
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
In the Linux implementation, sockets which are visible in the
|
In the Linux implementation, sockets which are visible in the
|
||||||
filesystem honor the permissions of the directory they are in.
|
filesystem honor the permissions of the directory they are in.
|
||||||
Their owner, group and their permissions can be changed.
|
Their owner, group, and permissions can be changed.
|
||||||
Creation of a new socket will fail if the process does not have write and
|
Creation of a new socket will fail if the process does not have write and
|
||||||
search (execute) permission on the directory the socket is created in.
|
search (execute) permission on the directory the socket is created in.
|
||||||
Connecting to the socket object requires read/write permission.
|
Connecting to the socket object requires read/write permission.
|
||||||
|
@ -434,6 +517,94 @@ or
|
||||||
call.
|
call.
|
||||||
|
|
||||||
UNIX domain stream sockets do not support the notion of out-of-band data.
|
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 .
|
||||||
|
|
||||||
|
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 .
|
||||||
|
|
||||||
|
Applications that retrieve socket addresses can (portably) code
|
||||||
|
to handle the possibility that there is no null terminator in
|
||||||
|
.IR sun_path
|
||||||
|
by respecting the fact that the number of valid bytes in the pathname is:
|
||||||
|
|
||||||
|
strnlen(addr.sun_path, addrlen \- offsetof(sockaddr_un, sun_path))
|
||||||
|
.\" 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
|
||||||
|
|
||||||
|
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 :
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.in +3
|
||||||
|
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\\n", ((struct sockaddr_un *) addrp)\->sun_path);
|
||||||
|
.in
|
||||||
|
.fi
|
||||||
|
|
||||||
|
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 EXAMPLE
|
.SH EXAMPLE
|
||||||
See
|
See
|
||||||
.BR bind (2).
|
.BR bind (2).
|
||||||
|
|
Loading…
Reference in New Issue