X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=net.c;h=92ae217d6b4bf7cdc438ff018774f9c0d9bdbc03;hp=d9b3a9defa8164e98be1dda341df3a62b1e4bf9b;hb=1a05bcbf311d82afc8c39314be3ae035fe65c911;hpb=a5927501e41fa3fca2975452617474e78ffecc48 diff --git a/net.c b/net.c index d9b3a9de..92ae217d 100644 --- a/net.c +++ b/net.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2009 Andre Noll + * Copyright (C) 2005-2010 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -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. @@ -384,7 +383,7 @@ int makesock(unsigned l4type, bool passive, struct addrinfo *local = NULL, *src, *remote = NULL, *dst, hints; unsigned int l3type = AF_UNSPEC; - int rc, sockfd = -1, + int rc, on = 1, sockfd = -1, socktype = sock_type(l4type); char port[6]; /* port number has at most 5 digits */ @@ -429,6 +428,19 @@ int makesock(unsigned l4type, bool passive, if (sockfd < 0) goto get_next_dst; + /* + * 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) { + rc = errno; + close(sockfd); + PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n", + strerror(rc)); + return -ERRNO_TO_PARA_ERROR(rc); + } flowopt_setopts(sockfd, fo); if (src) { @@ -457,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; } @@ -479,20 +492,14 @@ get_next_src: */ int para_listen(unsigned l4type, uint16_t port, struct flowopts *fo) { - int fd, ret; - - if (fo == NULL) - fo = flowopt_new(); - - /* Reuse the address to avoid failure on restart. */ - OPT_ENABLE(fo, SOL_SOCKET, SO_REUSEADDR); + int ret, fd = makesock(l4type, 1, NULL, port, fo); - 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); @@ -769,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(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; } /**