Example #1
0
/* Return the maximun suggested buffer size for both getpwname_r()
 * and getgrnam_r().
 *
 * This size may still not be big enough. in case getpwname_r()
 * and friends return ERANGE, a larger buffer should be supplied to
 * retry. (The man page did not specify the max size to stop at, we
 * will keep trying with doubling the buffer size for each round until
 * the size wrapps around size_t.  */
static size_t
get_sysconf_buffer_size(void)
{
    size_t bufsize, pwd_bs = 0, grp_bs = 0;
    const size_t default_bufsize = 1024;

    errno = 0;
    if ((pwd_bs = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) {
        if (errno) {
            VLOG_FATAL("%s: Read initial passwordd struct size "
                       "failed (%s), aborting. ", pidfile,
                       ovs_strerror(errno));
        }
    }

    if ((grp_bs = sysconf(_SC_GETGR_R_SIZE_MAX)) == -1) {
        if (errno) {
            VLOG_FATAL("%s: Read initial group struct size "
                       "failed (%s), aborting. ", pidfile,
                       ovs_strerror(errno));
        }
    }

    bufsize = MAX(pwd_bs, grp_bs);
    return bufsize ? bufsize : default_bufsize;
}
Example #2
0
/* Sets 'fd' to non-blocking mode.  Returns 0 if successful, otherwise a
 * positive errno value. */
int
set_nonblocking(int fd)
{
#ifndef _WIN32
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags != -1) {
        if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1) {
            return 0;
        } else {
            VLOG_ERR("fcntl(F_SETFL) failed: %s", ovs_strerror(errno));
            return errno;
        }
    } else {
        VLOG_ERR("fcntl(F_GETFL) failed: %s", ovs_strerror(errno));
        return errno;
    }
#else
    unsigned long arg = 1;
    if (ioctlsocket(fd, FIONBIO, &arg)) {
        int error = sock_errno();
        VLOG_ERR("set_nonblocking failed: %s", sock_strerror(error));
        return error;
    }
    return 0;
#endif
}
Example #3
0
/* If a pidfile has been configured, creates it and stores the running
 * process's pid in it.  Ensures that the pidfile will be deleted when the
 * process exits. */
static void
make_pidfile(void)
{
    int error;

    error = GetFileAttributes(pidfile);
    if (error != INVALID_FILE_ATTRIBUTES) {
        /* pidfile exists. Try to unlink() it. */
        error = unlink(pidfile);
        if (error) {
            VLOG_FATAL("Failed to delete existing pidfile %s (%s)", pidfile,
                       ovs_strerror(errno));
        }
    }

    filep_pidfile = fopen(pidfile, "w");
    if (filep_pidfile == NULL) {
        VLOG_FATAL("failed to open %s (%s)", pidfile, ovs_strerror(errno));
    }

    fatal_signal_add_hook(unlink_pidfile, NULL, NULL, true);

    fprintf(filep_pidfile, "%d\n", _getpid());
    if (fflush(filep_pidfile) == EOF) {
        VLOG_FATAL("Failed to write into the pidfile %s", pidfile);
    }

    /* Don't close the pidfile till the process exits. */
}
Example #4
0
static void
check_errno(int a, int b, const char *as, const char *file, int line)
{
    if (a != b) {
        char *str_b = xstrdup(ovs_strerror(abs(b)));
        ovs_fatal(0, "%s:%d: %s is %d (%s) but should be %d (%s)",
                  file, line, as, a, ovs_strerror(abs(a)), b, str_b);
    }
}
Example #5
0
int
FlowExecutor::WaitOnBarrier(OfpBuf& barrReq) {
    ovs_be32 barrXid = ((ofp_header *)barrReq.data())->xid;
    LOG(DEBUG) << "[" << swConn->getSwitchName() << "] "
               << "Sending barrier request xid=" << barrXid;
    int err = swConn->SendMessage(barrReq);
    if (err) {
        LOG(ERROR) << "[" << swConn->getSwitchName() << "] "
                   << "Error sending barrier request: "
                   << ovs_strerror(err);
        mutex_guard lock(reqMtx);
        requests.erase(barrXid);
        return err;
    }

    mutex_guard lock(reqMtx);
    RequestState& barrReqState = requests[barrXid];
    while (barrReqState.done == false) {
        reqCondVar.wait(lock);
    }
    int reqStatus = barrReqState.status;
    requests.erase(barrXid);

    return reqStatus;
}
/* Helper function for nl_dump_next(). */
static int
nl_dump_recv(struct nl_dump *dump)
{
    struct nlmsghdr *nlmsghdr;
    int retval;

    retval = nl_sock_recv__(dump->sock, &dump->buffer, true);
    if (retval) {
        return retval == EINTR ? EAGAIN : retval;
    }

    nlmsghdr = nl_msg_nlmsghdr(&dump->buffer);
    if (dump->seq != nlmsghdr->nlmsg_seq) {
        VLOG_DBG_RL(&rl, "ignoring seq %#"PRIx32" != expected %#"PRIx32,
                    nlmsghdr->nlmsg_seq, dump->seq);
        return EAGAIN;
    }

    if (nl_msg_nlmsgerr(&dump->buffer, &retval)) {
        VLOG_INFO_RL(&rl, "netlink dump request error (%s)",
                     ovs_strerror(retval));
        return retval && retval != EAGAIN ? retval : EPROTO;
    }

    return 0;
}
Example #7
0
/* Performs periodic maintenance on 'rpc', such as flushing output buffers. */
void
jsonrpc_run(struct jsonrpc *rpc)
{
    if (rpc->status) {
        return;
    }

    stream_run(rpc->stream);
    while (!list_is_empty(&rpc->output)) {
        struct ofpbuf *buf = ofpbuf_from_list(rpc->output.next);
        int retval;

        retval = stream_send(rpc->stream, buf->data, buf->size);
        if (retval >= 0) {
            rpc->backlog -= retval;
            ofpbuf_pull(buf, retval);
            if (!buf->size) {
                list_remove(&buf->list_node);
                rpc->output_count--;
                ofpbuf_delete(buf);
            }
        } else {
            if (retval != -EAGAIN) {
                VLOG_WARN_RL(&rl, "%s: send error: %s",
                             rpc->name, ovs_strerror(-retval));
                jsonrpc_error(rpc, -retval);
            }
            break;
        }
    }
}
Example #8
0
/* Initializes 'buffer' with 'n' bytes of high-quality random numbers.  Returns
 * 0 if successful, otherwise a positive errno value or EOF on error. */
int
get_entropy(void *buffer, size_t n)
{
#ifndef _WIN32
    size_t bytes_read;
    int error;
    int fd;

    fd = open(urandom, O_RDONLY);
    if (fd < 0) {
        VLOG_ERR("%s: open failed (%s)", urandom, ovs_strerror(errno));
        return errno ? errno : EINVAL;
    }

    error = read_fully(fd, buffer, n, &bytes_read);
    close(fd);

    if (error) {
        VLOG_ERR("%s: read error (%s)", urandom, ovs_retval_to_string(error));
    }
#else
    int error = 0;
    HCRYPTPROV   crypt_prov = 0;

    CryptAcquireContext(&crypt_prov, NULL, NULL,
                        PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!CryptGenRandom(crypt_prov, n, buffer)) {
        VLOG_ERR("CryptGenRandom: read error (%s)", ovs_lasterror_to_string());
        error = EINVAL;
    }

    CryptReleaseContext(crypt_prov, 0);
#endif
    return error;
}
Example #9
0
/* If 'error' is a valid OFPERR_* value, returns its name
 * (e.g. "OFPBRC_BAD_TYPE" for OFPBRC_BAD_TYPE).  Otherwise, assumes that
 * 'error' is a positive errno value and returns what ovs_strerror() produces
 * for 'error'.  */
const char *
ofperr_to_string(enum ofperr error)
{
    return (ofperr_is_valid(error)
            ? ofperr_get_name(error)
            : ovs_strerror(error));
}
Example #10
0
/* Connects to a fake_pvconn with vconn_open(), accepts that connection and
 * closes it immediately, and verifies that vconn_connect() reports
 * 'expected_error'. */
static void
test_accept_then_close(struct ovs_cmdl_context *ctx)
{
    const char *type = ctx->argv[1];
    struct fake_pvconn fpv;
    struct vconn *vconn;
    int error;

    fpv_create(type, &fpv);
    CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0);
    vconn_run(vconn);
    stream_close(fpv_accept(&fpv));
    fpv_close(&fpv);

    error = vconn_connect_block(vconn);
    if (!strcmp(type, "tcp") || !strcmp(type, "unix")) {
        if (error != ECONNRESET && error != EPIPE
#ifdef _WIN32
            && error != WSAECONNRESET
#endif
            ) {
            ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)",
                      error, ovs_strerror(error));
        }
    } else {
        CHECK_ERRNO(error, EPROTO);
    }

    vconn_close(vconn);
    fpv_destroy(&fpv);
}
Example #11
0
/* Initializes the fatal signal handling module.  Calling this function is
 * optional, because calling any other function in the module will also
 * initialize it.  However, in a multithreaded program, the module must be
 * initialized while the process is still single-threaded. */
void
fatal_signal_init(void)
{
    static bool inited = false;

    if (!inited) {
        size_t i;

        assert_single_threaded();
        inited = true;

        ovs_mutex_init_recursive(&mutex);
        xpipe_nonblocking(signal_fds);

        for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) {
            int sig_nr = fatal_signals[i];
            struct sigaction old_sa;

            xsigaction(sig_nr, NULL, &old_sa);
            if (old_sa.sa_handler == SIG_DFL
                && signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
        }
        atexit(atexit_handler);
    }
}
Example #12
0
/* Tries to make 'sock' stop listening to 'multicast_group'.  Returns 0 if
 * successful, otherwise a positive errno value.
 *
 * Multicast group numbers are always positive.
 *
 * It is not an error to attempt to leave a multicast group to which a socket
 * does not belong.
 *
 * On success, reading from 'sock' will still return any messages that were
 * received on 'multicast_group' before the group was left. */
int
nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
{
#ifdef _WIN32
    struct ofpbuf msg_buf;
    struct message_multicast
    {
        struct nlmsghdr;
        /* if true, join; if else, leave*/
        unsigned char join;
    };

    struct message_multicast msg = { 0 };
    nl_msg_put_nlmsghdr(&msg, sizeof(struct message_multicast),
                        multicast_group, 0);
    msg.join = 0;

    msg_buf.base_ = &msg;
    msg_buf.data_ = &msg;
    msg_buf.size_ = msg.nlmsg_len;

    nl_sock_send__(sock, &msg_buf, msg.nlmsg_seq, 0);
#else
    if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
                   &multicast_group, sizeof multicast_group) < 0) {
        VLOG_WARN("could not leave multicast group %u (%s)",
                  multicast_group, ovs_strerror(errno));
        return errno;
    }
#endif
    return 0;
}
Example #13
0
void
xgettimeofday(struct timeval *tv)
{
    if (gettimeofday(tv, NULL) == -1) {
        VLOG_FATAL("gettimeofday failed (%s)", ovs_strerror(errno));
    }
}
Example #14
0
/* Initializes the fatal signal handling module.  Calling this function is
 * optional, because calling any other function in the module will also
 * initialize it.  However, in a multithreaded program, the module must be
 * initialized while the process is still single-threaded. */
void
fatal_signal_init(void)
{
    static bool inited = false;

    if (!inited) {
        size_t i;

        assert_single_threaded();
        inited = true;

        ovs_mutex_init_recursive(&mutex);
#ifndef _WIN32
        xpipe_nonblocking(signal_fds);
#else
        wevent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!wevent) {
            char *msg_buf = ovs_lasterror_to_string();
            VLOG_FATAL("Failed to create a event (%s).", msg_buf);
        }

        /* Register a function to handle Ctrl+C. */
        SetConsoleCtrlHandler(ConsoleHandlerRoutine, true);
#endif

        for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) {
            int sig_nr = fatal_signals[i];
#ifndef _WIN32
            struct sigaction old_sa;

            xsigaction(sig_nr, NULL, &old_sa);
            if (old_sa.sa_handler == SIG_DFL
                && signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
#else
            if (signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
#endif
        }
        atexit(fatal_signal_atexit_handler);
    }
}
/* Sends the 'request' member of the 'n' transactions in 'transactions' on
 * 'sock', in order, and receives responses to all of them.  Fills in the
 * 'error' member of each transaction with 0 if it was successful, otherwise
 * with a positive errno value.  If 'reply' is nonnull, then it will be filled
 * with the reply if the message receives a detailed reply.  In other cases,
 * i.e. where the request failed or had no reply beyond an indication of
 * success, 'reply' will be cleared if it is nonnull.
 *
 * The caller is responsible for destroying each request and reply, and the
 * transactions array itself.
 *
 * Before sending each message, this function will finalize nlmsg_len in each
 * 'request' to match the ofpbuf's size,  set nlmsg_pid to 'sock''s pid, and
 * initialize nlmsg_seq.
 *
 * Bare Netlink is an unreliable transport protocol.  This function layers
 * reliable delivery and reply semantics on top of bare Netlink.  See
 * nl_sock_transact() for some caveats.
 */
void
nl_sock_transact_multiple(struct nl_sock *sock,
                          struct nl_transaction **transactions, size_t n)
{
    int max_batch_count;
    int error;

    if (!n) {
        return;
    }

    /* In theory, every request could have a 64 kB reply.  But the default and
     * maximum socket rcvbuf size with typical Dom0 memory sizes both tend to
     * be a bit below 128 kB, so that would only allow a single message in a
     * "batch".  So we assume that replies average (at most) 4 kB, which allows
     * a good deal of batching.
     *
     * In practice, most of the requests that we batch either have no reply at
     * all or a brief reply. */
    max_batch_count = MAX(sock->rcvbuf / 4096, 1);
    max_batch_count = MIN(max_batch_count, max_iovs);

    while (n > 0) {
        size_t count, bytes;
        size_t done;

        /* Batch up to 'max_batch_count' transactions.  But cap it at about a
         * page of requests total because big skbuffs are expensive to
         * allocate in the kernel.  */
#if defined(PAGESIZE)
        enum { MAX_BATCH_BYTES = MAX(1, PAGESIZE - 512) };
#else
        enum { MAX_BATCH_BYTES = 4096 - 512 };
#endif
        bytes = transactions[0]->request->size;
        for (count = 1; count < n && count < max_batch_count; count++) {
            if (bytes + transactions[count]->request->size > MAX_BATCH_BYTES) {
                break;
            }
            bytes += transactions[count]->request->size;
        }

        error = nl_sock_transact_multiple__(sock, transactions, count, &done);
        transactions += done;
        n -= done;

        if (error == ENOBUFS) {
            VLOG_DBG_RL(&rl, "receive buffer overflow, resending request");
        } else if (error) {
            VLOG_ERR_RL(&rl, "transaction error (%s)", ovs_strerror(error));
            nl_sock_record_errors__(transactions, n, error);
        }
    }
}
Example #16
0
/* Checks whether a process with the given 'pidfile' is already running and,
 * if so, aborts.  If 'pidfile' is stale, deletes it. */
static void
check_already_running(void)
{
    long int pid = read_pidfile__(pidfile, true);
    if (pid > 0) {
        VLOG_FATAL("%s: already running as pid %ld, aborting", pidfile, pid);
    } else if (pid < 0) {
        VLOG_FATAL("%s: pidfile check failed (%s), aborting",
                   pidfile, ovs_strerror(-pid));
    }
}
/* Tries to make 'sock' stop listening to 'multicast_group'.  Returns 0 if
 * successful, otherwise a positive errno value.
 *
 * Multicast group numbers are always positive.
 *
 * It is not an error to attempt to leave a multicast group to which a socket
 * does not belong.
 *
 * On success, reading from 'sock' will still return any messages that were
 * received on 'multicast_group' before the group was left. */
int
nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
{
    if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
                   &multicast_group, sizeof multicast_group) < 0) {
        VLOG_WARN("could not leave multicast group %u (%s)",
                  multicast_group, ovs_strerror(errno));
        return errno;
    }
    return 0;
}
Example #18
0
static int
create_link_to_desc_files(char *manufacturer, char *product_name)
{
    char        hw_desc_dir[1024];
    int         rc = 0;
    struct stat sbuf;
    extern char *g_hw_desc_dir;

    snprintf(hw_desc_dir, sizeof(hw_desc_dir), "%s/%s/%s",
             HWDESC_FILES_PATH, manufacturer, product_name);

    VLOG_INFO("Location to HW descrptor files: %s", hw_desc_dir);

    g_hw_desc_dir = strdup(hw_desc_dir);

    if (stat(hw_desc_dir, &sbuf) != 0) {
        VLOG_ERR("Unable to find hardware description files at %s", hw_desc_dir);
        return -1;
    }

    /* Remove old link if it exists */
    remove(HWDESC_FILE_LINK);

    /* mkdir for the new link */
    rc = mkdir(HWDESC_FILE_LINK_PATH, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    if (rc == -1 && errno != EEXIST) {
        VLOG_ERR("Failed to create %s, Error %s",
                 HWDESC_FILE_LINK_PATH, ovs_strerror(errno));
        return -1;
    }

    /* Create link to these files */
    if (-1 == symlink(hw_desc_dir, HWDESC_FILE_LINK)) {
        VLOG_ERR("Unable to create  soft link to %s -> %s. Error %s",
                 HWDESC_FILE_LINK, hw_desc_dir, ovs_strerror(errno));
        return -1;
    }

    return 0;

} /* create_link_to_desc_files */
Example #19
0
/* Connects to a fake_pvconn with vconn_open(), then closes the listener and
 * verifies that vconn_connect() reports 'expected_error'. */
static void
test_refuse_connection(struct ovs_cmdl_context *ctx)
{
    const char *type = ctx->argv[1];
    struct fake_pvconn fpv;
    struct vconn *vconn;
    int error;

    fpv_create(type, &fpv);
    CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0);
    fpv_close(&fpv);
    vconn_run(vconn);

    error = vconn_connect_block(vconn);
    if (!strcmp(type, "tcp")) {
        if (error != ECONNRESET && error != EPIPE
#ifdef _WIN32
            && error != WSAECONNRESET
#endif
            ) {
            ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)",
                      error, ovs_strerror(error));
        }
    } else if (!strcmp(type, "unix")) {
#ifndef _WIN32
        CHECK_ERRNO(error, EPIPE);
#else
        CHECK_ERRNO(error, WSAECONNRESET);
#endif
    } else if (!strcmp(type, "ssl")) {
        if (error != EPROTO && error != ECONNRESET) {
            ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)",
                      error, ovs_strerror(error));
        }
    } else {
        ovs_fatal(0, "invalid connection type %s", type);
    }

    vconn_close(vconn);
    fpv_destroy(&fpv);
}
Example #20
0
void
get_sys_cmd_out(char *cmd, char **output)
{
    FILE        *fd = NULL;
    char        *buf = NULL;
    size_t      nbytes = 0, size = 0;

    *output = NULL;

    fd = popen(cmd, "r");
    if (fd == (FILE *) NULL) {
        VLOG_ERR("popen failed for %s: Error: %s", cmd, ovs_strerror(errno));
        return;
    }

    while (1) {

        buf = NULL;
        size = 0;
        nbytes = getline(&buf, &size, fd);
        if (nbytes <= 0) {
            VLOG_ERR("Failed to parse output. rc=%s", ovs_strerror(errno));
            return;
        }

        /* Ignore the comments that starts with '#'. */
        if (buf[0] == '#') {
            continue;
        } else if (buf[0] != '\0') {
            /* Return the buffer, caller will free the buffer. */
            buf[nbytes-1] = '\0';
            *output = buf;
            break;
        }
        /* getline allocates buffer, it should be freed. */
        free(buf);
    }
    pclose(fd);

} /* get_sys_cmd_out */
Example #21
0
static int
tcp_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
{
    int fd, error;

    error = inet_open_active(SOCK_STREAM, suffix, -1, NULL, &fd, dscp);
    if (fd >= 0) {
        return new_tcp_stream(xstrdup(name), fd, error, streamp);
    } else {
        VLOG_ERR("%s: connect: %s", name, ovs_strerror(error));
        return error;
    }
}
Example #22
0
/* Forks, then:
 *
 *   - In the parent, waits for the child to signal that it has completed its
 *     startup sequence.  Then stores -1 in '*fdp' and returns the child's
 *     pid in '*child_pid' argument.
 *
 *   - In the child, stores a fd in '*fdp' and returns 0 through '*child_pid'
 *     argument.  The caller should pass the fd to fork_notify_startup() after
 *     it finishes its startup sequence.
 *
 * Returns 0 on success.  If something goes wrong and child process was not
 * able to signal its readiness by calling fork_notify_startup(), then this
 * function returns -1. However, even in case of failure it still sets child
 * process id in '*child_pid'. */
static int
fork_and_wait_for_startup(int *fdp, pid_t *child_pid)
{
    int fds[2];
    pid_t pid;
    int ret = 0;

    xpipe(fds);

    pid = fork_and_clean_up();
    if (pid > 0) {
        /* Running in parent process. */
        size_t bytes_read;
        char c;

        close(fds[1]);
        if (read_fully(fds[0], &c, 1, &bytes_read) != 0) {
            int retval;
            int status;

            do {
                retval = waitpid(pid, &status, 0);
            } while (retval == -1 && errno == EINTR);

            if (retval == pid) {
                if (WIFEXITED(status) && WEXITSTATUS(status)) {
                    /* Child exited with an error.  Convey the same error
                     * to our parent process as a courtesy. */
                    exit(WEXITSTATUS(status));
                } else {
                    char *status_msg = process_status_msg(status);
                    VLOG_ERR("fork child died before signaling startup (%s)",
                             status_msg);
                    ret = -1;
                }
            } else if (retval < 0) {
                VLOG_FATAL("waitpid failed (%s)", ovs_strerror(errno));
            } else {
                OVS_NOT_REACHED();
            }
        }
        close(fds[0]);
        *fdp = -1;
    } else if (!pid) {
        /* Running in child process. */
        close(fds[0]);
        *fdp = fds[1];
    }
    *child_pid = pid;
    return ret;
}
Example #23
0
static void
fork_notify_startup(int fd)
{
    if (fd != -1) {
        size_t bytes_written;
        int error;

        error = write_fully(fd, "", 1, &bytes_written);
        if (error) {
            VLOG_FATAL("pipe write failed (%s)", ovs_strerror(error));
        }

        close(fd);
    }
}
Example #24
0
static void
queue_tx(struct lswitch *sw, struct ofpbuf *b)
{
    int retval = rconn_send_with_limit(sw->rconn, b, sw->queued, 10);
    if (retval && retval != ENOTCONN) {
        if (retval == EAGAIN) {
            VLOG_INFO_RL(&rl, "%016llx: %s: tx queue overflow",
                         sw->datapath_id, rconn_get_name(sw->rconn));
        } else {
            VLOG_WARN_RL(&rl, "%016llx: %s: send: %s",
                         sw->datapath_id, rconn_get_name(sw->rconn),
                         ovs_strerror(retval));
        }
    }
}
Example #25
0
static bool
parse_sockaddr_components(struct sockaddr_storage *ss,
                          char *host_s,
                          const char *port_s, uint16_t default_port,
                          const char *s)
{
    struct sockaddr_in *sin = ALIGNED_CAST(struct sockaddr_in *, ss);
    int port;

    if (port_s && port_s[0]) {
        if (!str_to_int(port_s, 10, &port) || port < 0 || port > 65535) {
            VLOG_ERR("%s: bad port number \"%s\"", s, port_s);
            goto exit;
        }
    } else {
        port = default_port;
    }

    memset(ss, 0, sizeof *ss);
    if (host_s && strchr(host_s, ':')) {
        struct sockaddr_in6 *sin6
            = ALIGNED_CAST(struct sockaddr_in6 *, ss);

        char *addr = strsep(&host_s, "%");

        sin6->sin6_family = AF_INET6;
        sin6->sin6_port = htons(port);
        if (!addr || !*addr || !ipv6_parse(addr, &sin6->sin6_addr)) {
            VLOG_ERR("%s: bad IPv6 address \"%s\"", s, addr ? addr : "");
            goto exit;
        }

#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
        char *scope = strsep(&host_s, "%");
        if (scope && *scope) {
            if (!scope[strspn(scope, "0123456789")]) {
                sin6->sin6_scope_id = atoi(scope);
            } else {
                sin6->sin6_scope_id = if_nametoindex(scope);
                if (!sin6->sin6_scope_id) {
                    VLOG_ERR("%s: bad IPv6 scope \"%s\" (%s)",
                             s, scope, ovs_strerror(errno));
                    goto exit;
                }
            }
        }
#endif
    } else {
Example #26
0
/* Returns a readable and writable fd for /dev/null, if successful, otherwise
 * a negative errno value.  The caller must not close the returned fd (because
 * the same fd will be handed out to subsequent callers). */
static int
get_null_fd(void)
{
    static int null_fd;

    if (!null_fd) {
        null_fd = open("/dev/null", O_RDWR);
        if (null_fd < 0) {
            int error = errno;
            VLOG_ERR("could not open /dev/null: %s", ovs_strerror(error));
            null_fd = -error;
        }
    }

    return null_fd;
}
Example #27
0
/* Initializes 'buffer' with 'n' bytes of high-quality random numbers.  Returns
 * 0 if successful, otherwise a positive errno value or EOF on error. */
int
get_entropy(void *buffer, size_t n)
{
#ifndef _WIN32
    size_t bytes_read;
    int error;
    int fd;

    fd = open(urandom, O_RDONLY);
    if (fd < 0) {
        VLOG_ERR("%s: open failed (%s)", urandom, ovs_strerror(errno));
        return errno ? errno : EINVAL;
    }

    error = read_fully(fd, buffer, n, &bytes_read);
    close(fd);

    if (error) {
        VLOG_ERR("%s: read error (%s)", urandom, ovs_retval_to_string(error));
    }
#else
    int error = 0;
    HCRYPTPROV   crypt_prov = 0;
    LPVOID msg_buf;

    CryptAcquireContext(&crypt_prov, NULL, NULL,
                        PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!CryptGenRandom(crypt_prov, n, buffer)) {
        error = EINVAL;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
                      | FORMAT_MESSAGE_FROM_SYSTEM
                      | FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL,
                      GetLastError(),
                      0,
                      (LPTSTR)&msg_buf,
                      0,
                      NULL
            );
        VLOG_ERR("CryptGenRandom: read error (%s)", msg_buf);
        LocalFree(msg_buf);
    }

    CryptReleaseContext(crypt_prov, 0);
#endif
    return error;
}
Example #28
0
/* Connects to a fake_pvconn with vconn_open(), accepts that connection and
 * reads the hello message from it, then closes the connection and verifies
 * that vconn_connect() reports 'expected_error'. */
static void
test_read_hello(struct ovs_cmdl_context *ctx)
{
    const char *type = ctx->argv[1];
    struct fake_pvconn fpv;
    struct vconn *vconn;
    struct stream *stream;
    int error;

    fpv_create(type, &fpv);
    CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0);
    vconn_run(vconn);
    stream = fpv_accept(&fpv);
    fpv_destroy(&fpv);
    for (;;) {
       struct ofp_header hello;
       int retval;

       retval = stream_recv(stream, &hello, sizeof hello);
       if (retval == sizeof hello) {
           enum ofpraw raw;

           CHECK(hello.version, OFP13_VERSION);
           CHECK(ofpraw_decode_partial(&raw, &hello, sizeof hello), 0);
           CHECK(raw, OFPRAW_OFPT_HELLO);
           CHECK(ntohs(hello.length), sizeof hello);
           break;
       } else {
           CHECK_ERRNO(retval, -EAGAIN);
       }

       vconn_run(vconn);
       CHECK_ERRNO(vconn_connect(vconn), EAGAIN);
       vconn_run_wait(vconn);
       vconn_connect_wait(vconn);
       stream_recv_wait(stream);
       poll_block();
    }
    stream_close(stream);
    error = vconn_connect_block(vconn);
    if (error != ECONNRESET && error != EPIPE) {
        ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)",
                  error, ovs_strerror(error));
    }
    vconn_close(vconn);
}
Example #29
0
static void
lswitch_handshake(struct lswitch *sw)
{
    enum ofputil_protocol protocol;
    enum ofp_version version;

    send_features_request(sw);

	send_controller_id(sw);

    version = rconn_get_version(sw->rconn);
    protocol = ofputil_protocol_from_ofp_version(version);
    
    if (sw->default_flows) {
        struct ofpbuf *msg = NULL;
        int error = 0;
        size_t i;

        if (!(protocol & sw->usable_protocols)) {
            enum ofputil_protocol want = rightmost_1bit(sw->usable_protocols);
            while (!error) {
                msg = ofputil_encode_set_protocol(protocol, want, &protocol);
                if (!msg) {
                    break;
                }
                error = rconn_send(sw->rconn, msg, NULL);
            }
        }
        if (protocol & sw->usable_protocols) {
            for (i = 0; !error && i < sw->n_default_flows; i++) {
                msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol);
                error = rconn_send(sw->rconn, msg, NULL);
            }

            if (error) {
                VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)",
                             rconn_get_name(sw->rconn), ovs_strerror(error));
            }
        } else {
            VLOG_INFO_RL(&rl, "%s: failed to set usable protocol",
                         rconn_get_name(sw->rconn));
        }
    }
    sw->protocol = protocol;
}
Example #30
0
static int
unix_open(const char *name, char *suffix, struct stream **streamp,
          uint8_t dscp OVS_UNUSED)
{
    char *connect_path;
    int fd;

    connect_path = abs_file_name(ovs_rundir(), suffix);
    fd = make_unix_socket(SOCK_STREAM, true, NULL, connect_path);

    if (fd < 0) {
        VLOG_DBG("%s: connection failed (%s)",
                 connect_path, ovs_strerror(-fd));
        free(connect_path);
        return -fd;
    }

    free(connect_path);
    return new_fd_stream(name, fd, check_connection_completion(fd), streamp);
}