X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=net.c;h=f34ab8522eaf7b36b1bc5996c226cc5cd8b0bcb0;hp=d85321d931d51f2d21a0fa8e8ea160df432b1ece;hb=cf2dd5eac38421fdeaaccd08ec34efe27f9a858d;hpb=ed0c68b07ddbc130e033035baa1cc0862e511b46 diff --git a/net.c b/net.c index d85321d9..f34ab852 100644 --- a/net.c +++ b/net.c @@ -279,7 +279,7 @@ struct flowopts *flowopt_new(void) * Append new socket option to flowopt queue. * * \param fo The flowopt queue to append to. - * \param lev Level at which \opt resides. + * \param lev Level at which \a opt resides. * \param opt New option to add. * \param name Stringified name of \a opt. * \param val The value to set \a opt to. @@ -351,7 +351,6 @@ static void flowopt_cleanup(struct flowopts *fo) /** * Resolve IPv4/IPv6 address and create a ready-to-use active or passive socket. * - * \param l3type The layer-3 type (\p AF_INET, \p AF_INET6, \p AF_UNSPEC). * \param l4type The layer-4 type (\p IPPROTO_xxx). * \param passive Whether this is a passive (1) or active (0) socket. * \param host Remote or local hostname or IPv/6 address string. @@ -377,12 +376,13 @@ static void flowopt_cleanup(struct flowopts *fo) * * \sa ipv6(7), getaddrinfo(3), bind(2), connect(2). */ -int makesock(unsigned l3type, unsigned l4type, int passive, - const char *host, unsigned short port_number, +int makesock(unsigned l4type, bool passive, + const char *host, uint16_t port_number, struct flowopts *fo) { struct addrinfo *local = NULL, *src, *remote = NULL, *dst, hints; + unsigned int l3type = AF_UNSPEC; int rc, on = 1, sockfd = -1, socktype = sock_type(l4type); char port[6]; /* port number has at most 5 digits */ @@ -429,15 +429,17 @@ int makesock(unsigned l3type, unsigned l4type, int passive, goto get_next_dst; /* - * Set those options that need to be set before establishing - * the connection. Reuse the address on passive (listening) - * sockets to avoid failure on restart. + * Reuse the address on passive sockets to avoid failure on + * restart (protocols using listen()) and when creating + * multiple listener instances (UDP multicast). */ if (passive && setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)) == -1) { + &on, sizeof(on)) == -1) { + rc = errno; + close(sockfd); PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n", - strerror(errno)); - return -ERRNO_TO_PARA_ERROR(errno); + strerror(rc)); + return -ERRNO_TO_PARA_ERROR(rc); } flowopt_setopts(sockfd, fo); @@ -467,10 +469,11 @@ get_next_src: flowopt_cleanup(fo); if (src == NULL && dst == NULL) { + rc = errno; PARA_ERROR_LOG("can not create %s socket %s#%s.\n", layer4_name(l4type), host? host : (passive? "[loopback]" : "[localhost]"), port); - return -ERRNO_TO_PARA_ERROR(errno); + return -ERRNO_TO_PARA_ERROR(rc); } return sockfd; } @@ -478,24 +481,25 @@ get_next_src: /** * Create a passive / listening socket. * - * \param l3type The network-layer type (\p AF_xxx). * \param l4type The transport-layer type (\p IPPROTO_xxx). * \param port The decimal port number to listen on. + * \param fo Flowopts (if any) to set before starting to listen. * * \return Positive integer (socket descriptor) on success, negative value * otherwise. * * \sa makesock(), ip(7), ipv6(7), bind(2), listen(2). */ -int para_listen(unsigned l3type, unsigned l4type, unsigned short port) +int para_listen(unsigned l4type, uint16_t port, struct flowopts *fo) { - int ret, fd = makesock(l3type, l4type, 1, NULL, port, NULL); + int ret, fd = makesock(l4type, 1, NULL, port, fo); if (fd > 0) { ret = listen(fd, BACKLOG); if (ret < 0) { + ret = errno; close(fd); - return -ERRNO_TO_PARA_ERROR(errno); + return -ERRNO_TO_PARA_ERROR(ret); } PARA_INFO_LOG("listening on %s port %u, fd %d\n", layer4_name(l4type), port, fd); @@ -772,30 +776,35 @@ int para_accept(int fd, void *addr, socklen_t size) } /** - * Probe the list of DCCP CCIDs supported locally by the host. - * \param ccids Array to be filled in. - * \param nccids Length of \a ccids. - * \return Pointer to \a ccids, NULL on failure. + * Probe the list of DCCP CCIDs configured on this host. + * \param ccid_array Pointer to return statically allocated array in. + * \return Number of elements returned in \a ccid_array or error. * * NB: This feature is only available on Linux > 2.6.30; on older kernels * ENOPROTOOPT ("Protocol not available") will be returned. */ -const uint8_t *dccp_available_ccids(uint8_t *ccids, uint8_t *nccids) +int dccp_available_ccids(uint8_t **ccid_array) { - int fd = makesock(AF_UNSPEC, IPPROTO_DCCP, 1, NULL, 0, NULL); + static uint8_t ccids[DCCP_MAX_HOST_CCIDS]; + socklen_t nccids = sizeof(ccids); + int ret, fd; - if (fd < 0) - return NULL; + ret = fd = makesock(IPPROTO_DCCP, 1, NULL, 0, NULL); + if (ret < 0) + return ret; if (getsockopt(fd, SOL_DCCP, DCCP_SOCKOPT_AVAILABLE_CCIDS, - ccids, (socklen_t *)nccids) < 0) { + ccids, &nccids) < 0) { + ret = errno; + close(fd); PARA_ERROR_LOG("No DCCP_SOCKOPT_AVAILABLE_CCIDS: %s\n", - strerror(errno)); - *nccids = 0; + strerror(ret)); + return -ERRNO_TO_PARA_ERROR(ret); } - close(fd); - return *nccids ? ccids : NULL; + close(fd); + *ccid_array = ccids; + return nccids; } /**