X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=net.c;h=1b142a3cd4a25b87fe2e31c86caaf32e4be5f51e;hp=8a190ddaa05100190761a7eecd918d78a546bb4d;hb=a13a1e0d202a8969374b9a70562556e689597f2d;hpb=093dda1824631372587d107d64601389027c6187 diff --git a/net.c b/net.c index 8a190dda..1b142a3c 100644 --- a/net.c +++ b/net.c @@ -1,16 +1,12 @@ /* - * Copyright (C) 2005-2014 Andre Noll + * Copyright (C) 2005 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ /** \file net.c Networking-related helper functions. */ -/* - * Since glibc 2.8, the _GNU_SOURCE feature test macro must be defined in order - * to obtain the definition of the ucred structure. - */ -#define _GNU_SOURCE +#include "para.h" #include #include @@ -32,7 +28,6 @@ #include -#include "para.h" #include "error.h" #include "net.h" #include "string.h" @@ -48,7 +43,7 @@ * \param netmask Value of the netmask part in \a cidr or the * default of 32 if not specified. * - * \return Pointer to \a addr if succesful, NULL on error. + * \return Pointer to \a addr if successful, NULL on error. * \sa RFC 4632 */ char *parse_cidr(const char *cidr, @@ -208,7 +203,7 @@ const char *stringify_port(int port, const char *transport) struct servent *se = getservbyport(htons(port), transport); if (se == NULL) - snprintf(service, sizeof(service), "%u", port); + snprintf(service, sizeof(service), "%d", port); else snprintf(service, sizeof(service), "%s", se->s_name); } @@ -601,7 +596,7 @@ static inline int estimated_header_overhead(const int af_type) * * \param sockfd The socket file descriptor. * - * The socket must be connected. See RFC 1122, 3.3.3. If the protocol familiy + * The socket must be connected. See RFC 1122, 3.3.3. If the protocol family * could not be determined, \p AF_INET is assumed. * * \return The maximum message size of the address family type. @@ -622,11 +617,9 @@ int generic_max_transport_msg_size(int sockfd) } /** - * Look up the local or remote side of a connected socket structure. + * Look up the remote side of a connected socket structure. * * \param fd The socket descriptor of the connected socket. - * \param getname Either \p getsockname() for local, or \p getpeername() for - * remote side. * * \return A static character string identifying hostname and port of the * chosen side in numeric host:port format. @@ -634,7 +627,7 @@ int generic_max_transport_msg_size(int sockfd) * \sa getsockname(2), getpeername(2), parse_url(), getnameinfo(3), * services(5), nsswitch.conf(5). */ -static char *__get_sock_name(int fd, typeof(getsockname) getname) +char *remote_name(int fd) { struct sockaddr_storage ss; const struct sockaddr *sa; @@ -643,7 +636,7 @@ static char *__get_sock_name(int fd, typeof(getsockname) getname) static char output[sizeof(hbuf) + sizeof(sbuf) + 4]; int ret; - if (getname(fd, (struct sockaddr *)&ss, &sslen) < 0) { + if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { PARA_ERROR_LOG("can not determine address from fd %d: %s\n", fd, strerror(errno)); snprintf(output, sizeof(output), "(unknown)"); @@ -663,36 +656,6 @@ static char *__get_sock_name(int fd, typeof(getsockname) getname) return output; } -/** - * Look up the local side of a connected socket structure. - * - * \param sockfd The file descriptor of the socket. - * - * \return A pointer to a static buffer containing hostname an port. This - * buffer must not be freed by the caller. - * - * \sa remote_name(). - */ -char *local_name(int sockfd) -{ - return __get_sock_name(sockfd, getsockname); -} - -/** - * Look up the remote side of a connected socket structure. - * - * \param sockfd The file descriptor of the socket. - * - * \return Analogous to the return value of \ref local_name() but for the - * remote side. - * - * \sa local_name(). - */ -char *remote_name(int sockfd) -{ - return __get_sock_name(sockfd, getpeername); -} - /** * Extract IPv4 or IPv6-mapped-IPv4 address from sockaddr_storage. * @@ -866,52 +829,66 @@ int dccp_available_ccids(uint8_t **ccid_array) * \return Positive on success, \p -E_NAME_TOO_LONG if \a name is longer * than \p UNIX_PATH_MAX. */ -static int init_unix_addr(struct sockaddr_un *u, const char *name) +static int init_unix_addr(struct sockaddr_un *u, const char *name, + bool abstract) { - if (strlen(name) >= UNIX_PATH_MAX) + if (strlen(name) + abstract >= 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, name); + strcpy(u->sun_path + abstract, name); return 1; } /** - * Prepare, create, and bind a socket for local communication. + * Create a socket for local communication and listen on it. * * \param name The socket pathname. - * \param unix_addr Pointer to the \p AF_UNIX socket structure. - * \param mode The desired mode of the socket. + * \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. * - * This function creates a local socket for sequenced, reliable, - * two-way, connection-based byte streams. + * 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 on errors. + * \return The file descriptor on success, negative error code on failure. * - * \sa socket(2) - * \sa bind(2) - * \sa chmod(2) + * \sa socket(2), \sa bind(2), \sa chmod(2), listen(2), unix(7). */ -int create_local_socket(const char *name, struct sockaddr_un *unix_addr, - mode_t mode) +int create_local_socket(const char *name, mode_t mode) { + struct sockaddr_un unix_addr; int fd, ret; + bool abstract = mode == 0; - ret = init_unix_addr(unix_addr, name); + ret = init_unix_addr(&unix_addr, name, abstract); if (ret < 0) return ret; ret = socket(PF_UNIX, SOCK_STREAM, 0); if (ret < 0) return -ERRNO_TO_PARA_ERROR(errno); fd = ret; - ret = bind(fd, (struct sockaddr *) unix_addr, UNIX_PATH_MAX); + ret = mark_fd_nonblocking(fd); + if (ret < 0) + goto err; + ret = bind(fd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)); if (ret < 0) { ret = -ERRNO_TO_PARA_ERROR(errno); goto err; } - ret = -E_CHMOD; - if (chmod(name, mode) < 0) + if (!abstract) { + ret = -E_CHMOD; + if (chmod(name, mode) < 0) + goto err; + } + if (listen(fd , 5) < 0) { + ret = -ERRNO_TO_PARA_ERROR(errno); goto err; + } return fd; err: close(fd); @@ -937,17 +914,22 @@ int connect_local_socket(const char *name) int fd, ret; PARA_DEBUG_LOG("connecting to %s\n", name); - ret = init_unix_addr(&unix_addr, name); - if (ret < 0) - return ret; fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) return -ERRNO_TO_PARA_ERROR(errno); - if (connect(fd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) == -1) { - ret = -ERRNO_TO_PARA_ERROR(errno); + /* first try (linux-only) abstract socket */ + ret = init_unix_addr(&unix_addr, name, true); + if (ret < 0) goto err; - } - return fd; + 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); + if (ret < 0) + goto err; + if (connect(fd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) != -1) + return fd; + ret = -ERRNO_TO_PARA_ERROR(errno); err: close(fd); return ret; @@ -1031,7 +1013,7 @@ static void dispose_fds(int *fds, unsigned num) */ int recv_cred_buffer(int fd, char *buf, size_t size) { - char control[255]; + char control[255] __a_aligned(8); struct msghdr msg; struct cmsghdr *cmsg; struct iovec iov;