NOEXPORT SOCKET bind_port(SERVICE_OPTIONS *opt, int listening_section, unsigned i) {
    SOCKET fd;
    SOCKADDR_UNION *addr=opt->local_addr.addr+i;
#ifdef HAVE_STRUCT_SOCKADDR_UN
    struct stat sb; /* buffer for lstat() */
#endif

    if(listening_section<systemd_fds) {
        fd=(SOCKET)(listen_fds_start+listening_section);
        s_log(LOG_DEBUG,
            "Listening file descriptor received from systemd (FD=%ld)",
            (long)fd);
    } else {
        fd=s_socket(addr->sa.sa_family, SOCK_STREAM, 0, 1, "accept socket");
        if(fd==INVALID_SOCKET)
            return INVALID_SOCKET;
        s_log(LOG_DEBUG, "Listening file descriptor created (FD=%ld)",
            (long)fd);
    }

    if(socket_options_set(opt, fd, 0)<0) {
        closesocket(fd);
        return INVALID_SOCKET;
    }

    /* we don't bind or listen on a socket inherited from systemd */
    if(listening_section>=systemd_fds) {
        if(bind(fd, &addr->sa, addr_len(addr))) {
            int err=get_last_socket_error();
            char *requested_bind_address;

            /* local socket can't be unnamed */
            requested_bind_address=s_ntop(addr, addr_len(addr));
            s_log(LOG_NOTICE, "Binding service [%s] to %s: %s (%d)",
                opt->servname, requested_bind_address, s_strerror(err), err);
            str_free(requested_bind_address);
            closesocket(fd);
            return INVALID_SOCKET;
        }
        if(listen(fd, SOMAXCONN)) {
            sockerror("listen");
            closesocket(fd);
            return INVALID_SOCKET;
        }
    }

#ifdef HAVE_STRUCT_SOCKADDR_UN
    /* chown the UNIX socket, errors are ignored */
    if(addr->sa.sa_family==AF_UNIX &&
            (opt->uid || opt->gid)) {
        /* fchown() does *not* work on UNIX sockets */
        if(!lchown(addr->un.sun_path, opt->uid, opt->gid))
            s_log(LOG_DEBUG,
                "Socket chown succeeded: %s, UID=%u, GID=%u",
                addr->un.sun_path,
                (unsigned)opt->uid, (unsigned)opt->gid);
        else if(lstat(addr->un.sun_path, &sb))
            sockerror(addr->un.sun_path);
        else if(sb.st_uid==opt->uid && sb.st_gid==opt->gid)
            s_log(LOG_DEBUG,
                "Socket chown unneeded: %s, UID=%u, GID=%u",
                addr->un.sun_path,
                (unsigned)opt->uid, (unsigned)opt->gid);
        else
            s_log(LOG_ERR, "Socket chown failed: %s, UID=%u, GID=%u",
                addr->un.sun_path,
                (unsigned)opt->uid, (unsigned)opt->gid);
    }
#endif

    {
        SOCKADDR_UNION assigned_addr;
        socklen_t assigned_addr_len=sizeof assigned_addr;
        char *assigned_bind_address;

        if(getsockname(fd, &assigned_addr.sa, &assigned_addr_len)) {
            sockerror("getsockname");
            closesocket(fd);
            return INVALID_SOCKET;
        }
        assigned_bind_address=s_ntop(&assigned_addr, addr_len(&assigned_addr));
        s_log(LOG_INFO, "Service [%s] (FD=%ld) bound to %s",
            opt->servname, (long)fd, assigned_bind_address);
        str_free(assigned_bind_address);
    }
    return fd;
}
NOEXPORT SOCKET bind_port(SERVICE_OPTIONS *opt, int listening_section, unsigned i) {
    SOCKET fd;
    SOCKADDR_UNION *addr=opt->local_addr.addr+i;
#ifdef HAVE_STRUCT_SOCKADDR_UN
    struct stat sb;  
#endif

    if(listening_section<systemd_fds) {
        fd=(SOCKET)(listen_fds_start+listening_section);
        s_log(LOG_DEBUG,
            "Listening file descriptor received from systemd (FD=%ld)",
            (long)fd);
    } else {
        fd=s_socket(addr->sa.sa_family, SOCK_STREAM, 0, 1, "accept socket");
        if(fd==INVALID_SOCKET)
            return INVALID_SOCKET;
        s_log(LOG_DEBUG, "Listening file descriptor created (FD=%ld)",
            (long)fd);
    }

    if(socket_options_set(opt, fd, 0)<0) {
        closesocket(fd);
        return INVALID_SOCKET;
    }

     
    if(listening_section>=systemd_fds) {
        if(bind(fd, &addr->sa, addr_len(addr))) {
            int err=get_last_socket_error();
            char *requested_bind_address;

             
            requested_bind_address=s_ntop(addr, addr_len(addr));
            s_log(LOG_NOTICE, "Binding service [%s] to %s: %s (%d)",
                opt->servname, requested_bind_address, s_strerror(err), err);
            str_free(requested_bind_address);
            closesocket(fd);
            return INVALID_SOCKET;
        }
        if(listen(fd, SOMAXCONN)) {
            sockerror("listen");
            closesocket(fd);
            return INVALID_SOCKET;
        }
    }

#ifdef HAVE_STRUCT_SOCKADDR_UN
     
    if(addr->sa.sa_family==AF_UNIX &&
            (opt->uid || opt->gid)) {
         
        if(!lchown(addr->un.sun_path, opt->uid, opt->gid))
            s_log(LOG_DEBUG,
                "Socket chown succeeded: %s, UID=%u, GID=%u",
                addr->un.sun_path,
                (unsigned)opt->uid, (unsigned)opt->gid);
        else if(lstat(addr->un.sun_path, &sb))
            sockerror(addr->un.sun_path);
        else if(sb.st_uid==opt->uid && sb.st_gid==opt->gid)
            s_log(LOG_DEBUG,
                "Socket chown unneeded: %s, UID=%u, GID=%u",
                addr->un.sun_path,
                (unsigned)opt->uid, (unsigned)opt->gid);
        else
            s_log(LOG_ERR, "Socket chown failed: %s, UID=%u, GID=%u",
                addr->un.sun_path,
                (unsigned)opt->uid, (unsigned)opt->gid);
    }
#endif

    {
        SOCKADDR_UNION assigned_addr;
        socklen_t assigned_addr_len=sizeof assigned_addr;
        char *assigned_bind_address;

        if(getsockname(fd, &assigned_addr.sa, &assigned_addr_len)) {
            sockerror("getsockname");
            closesocket(fd);
            return INVALID_SOCKET;
        }
        assigned_bind_address=s_ntop(&assigned_addr, addr_len(&assigned_addr));
        s_log(LOG_INFO, "Service [%s] (FD=%ld) bound to %s",
            opt->servname, (long)fd, assigned_bind_address);
        str_free(assigned_bind_address);
    }
    return fd;
}