struct addrinfo *addr = NULL, hints;
*result = NULL;
- sprintf(port, "%u", port_number & 0xffff);
+ sprintf(port, "%d", port_number & 0xffff);
/* Set up address hint structure */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
*/
int generic_max_transport_msg_size(int sockfd)
{
- struct sockaddr_storage ss;
+ struct sockaddr_storage ss = {0};
socklen_t sslen = sizeof(ss);
int af_type = AF_INET;
*/
char *remote_name(int fd)
{
- struct sockaddr_storage ss;
+ struct sockaddr_storage ss = {0};
const struct sockaddr *sa;
socklen_t sslen = sizeof(ss);
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
return nccids;
}
-/**
- * Prepare a structure for \p AF_UNIX socket addresses.
- *
- * \param u Pointer to the struct to be prepared.
- * \param name The socket pathname.
+/*
+ * Prepare a structure for AF_UNIX socket addresses.
*
- * This just copies \a name to the sun_path component of \a u.
+ * This just copies name to the sun_path component of u, prepending a zero byte
+ * if abstract sockets are supported.
*
- * \return Positive on success, \p -E_NAME_TOO_LONG if \a name is longer
- * than \p UNIX_PATH_MAX.
+ * The first call to this function tries to bind a socket to the abstract name
+ * space. The result of this test is stored in a static variable. Subsequent
+ * calls read this variable and create abstract sockets on systems that support
+ * them.
*/
-static int init_unix_addr(struct sockaddr_un *u, const char *name,
- bool abstract)
+static int init_unix_addr(struct sockaddr_un *u, const char *name)
{
- if (strlen(name) + abstract >= UNIX_PATH_MAX)
+ static int use_abstract;
+
+ if (strlen(name) + 1 >= UNIX_PATH_MAX)
return -E_NAME_TOO_LONG;
memset(u->sun_path, 0, UNIX_PATH_MAX);
u->sun_family = PF_UNIX;
- strcpy(u->sun_path + abstract, name);
+ if (use_abstract == 0) { /* executed only once */
+ int fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ memcpy(u->sun_path, "\0x\0", 3);
+ if (bind(fd, (struct sockaddr *)u, sizeof(*u)) == 0)
+ use_abstract = 1; /* yes */
+ else
+ use_abstract = -1; /* no */
+ close(fd);
+ PARA_NOTICE_LOG("%susing abstract socket namespace\n",
+ use_abstract == 1? "" : "not ");
+ }
+ strcpy(u->sun_path + (use_abstract == 1? 1 : 0), name);
return 1;
}
* Create a socket for local communication and listen on it.
*
* \param name The socket pathname.
- * \param mode The desired permissions of the socket.
*
* This function creates a passive local socket for sequenced, reliable,
* two-way, connection-based byte streams. The socket file descriptor is set to
* nonblocking mode and listen(2) is called to prepare the socket for
* accepting incoming connection requests.
*
- * If mode is zero, an abstract socket (a non-portable Linux extension) is
- * created. In this case the socket name has no connection with filesystem
- * pathnames.
- *
* \return The file descriptor on success, negative error code on failure.
*
* \sa socket(2), \sa bind(2), \sa chmod(2), listen(2), unix(7).
*/
-int create_local_socket(const char *name, mode_t mode)
+int create_local_socket(const char *name)
{
struct sockaddr_un unix_addr;
int fd, ret;
- bool abstract = mode == 0;
- ret = init_unix_addr(&unix_addr, name, abstract);
+ ret = init_unix_addr(&unix_addr, name);
if (ret < 0)
return ret;
ret = socket(PF_UNIX, SOCK_STREAM, 0);
ret = -ERRNO_TO_PARA_ERROR(errno);
goto err;
}
- if (!abstract) {
+ if (unix_addr.sun_path[0] != 0) { /* pathname socket */
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
+ | S_IROTH | S_IWOTH;
ret = -E_CHMOD;
if (chmod(name, mode) < 0)
goto err;
fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
return -ERRNO_TO_PARA_ERROR(errno);
- /* first try (linux-only) abstract socket */
- ret = init_unix_addr(&unix_addr, name, true);
- if (ret < 0)
- goto err;
- if (connect(fd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) != -1)
- return fd;
- /* next try pathname socket */
- ret = init_unix_addr(&unix_addr, name, false);
+ ret = init_unix_addr(&unix_addr, name);
if (ret < 0)
goto err;
if (connect(fd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) != -1)