* 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.
/**
* 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.
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 */
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;
+ PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n",
+ strerror(rc));
+ return -ERRNO_TO_PARA_ERROR(rc);
+ }
flowopt_setopts(sockfd, fo);
if (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) {