示例#1
0
文件: netlink.cpp 项目: vyvy/vasum
void Netlink::open(int netNsPid)
{
    auto fdFactory = []{ return socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); };

    assert(mFd == -1);
    if (netNsPid == 0 || netNsPid == 1 || netNsPid == ::getpid()) {
        mFd = fdFactory();
        if (mFd == -1) {
            LOGE("Can't open socket: " << getSystemErrorMessage());
        }
    } else {
        mFd = utils::passNamespacedFd(netNsPid, CLONE_NEWNET, fdFactory);
    }
    if (mFd == -1) {
        throw VasumException("Can't open netlink connection (zone not running)");
    }

    sockaddr_nl local = utils::make_clean<sockaddr_nl>();
    local.nl_family = AF_NETLINK;

    if (bind(mFd, (struct sockaddr *)&local, sizeof(local)) < 0) {
        int err = errno;
        close();
        const std::string msg = "Can't bind to socket: " + getSystemErrorMessage(err);
        LOGE(msg);
        throw VasumException(msg);
    }
}
示例#2
0
文件: socket.cpp 项目: hallor/vasum
Socket::Type Socket::getType() const
{
    int family;
    socklen_t length = sizeof(family);

    if (::getsockopt(mFD, SOL_SOCKET, SO_DOMAIN, &family, &length)) {
        if (errno == EBADF) {
            return Type::INVALID;
        } else {
            const std::string msg = "Error getting socket type: " + getSystemErrorMessage();
            LOGE(msg);
            throw IPCException(msg);
        }
    }


    if (family == AF_UNIX || family == AF_LOCAL) {
        return Type::UNIX;
    }

    if (family == AF_INET || family == AF_INET6) {
        return Type::INET;
    }

    return Type::INVALID;
}
示例#3
0
文件: socket.cpp 项目: hallor/vasum
std::shared_ptr<Socket> Socket::accept()
{
    int sockfd = ::accept(mFD, nullptr, nullptr);
    if (sockfd == -1) {
        const std::string msg = "Error in accept: " + getSystemErrorMessage();
        LOGE(msg);
        throw IPCException(msg);
    }
    setFdOptions(sockfd);
    return std::make_shared<Socket>(sockfd);
}
示例#4
0
bool waitPid(pid_t pid, int& status)
{
    LOGD("Wait pid " << pid);

    while (::waitpid(pid, &status, 0) == -1) {
        if (errno != EINTR) {
            LOGE("waitpid() failed: " << getSystemErrorMessage());
            return false;
        }
    }
    return true;
}
示例#5
0
bool executeAndWait(const uid_t uid, const char* fname, const char* const* argv, int& status)
{
    LOGD("Execute " << (uid == UNSPEC_UID ? "" : "as " + std::to_string(uid) + " ") << fname << argv);

    pid_t pid = ::fork();
    if (pid == -1) {
        LOGE("Fork failed: " << getSystemErrorMessage());
        return false;
    }

    if (pid == 0) {
        if (uid != UNSPEC_UID && ::setuid(uid) < 0) {
            LOGW("Failed to become uid(" << uid << "): " << getSystemErrorMessage());
            ::_exit(EXIT_FAILURE);
        }
        ::execv(fname, const_cast<char* const*>(argv));
        LOGE("execv(" << fname << ") failed: " << getSystemErrorMessage());
        ::_exit(EXIT_FAILURE);
    }
    return waitPid(pid, status);
}
示例#6
0
文件: netlink.cpp 项目: vyvy/vasum
std::unique_ptr<std::vector<char>> Netlink::rcv(unsigned int nlmsgSeq)
{
    std::unique_ptr<std::vector<char>> buf(new std::vector<char>());

    msghdr msg = utils::make_clean<msghdr>();
    sockaddr_nl nladdr = utils::make_clean<sockaddr_nl>();
    iovec iov = utils::make_clean<iovec>();

    msg.msg_name = &nladdr;
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    nladdr.nl_family = AF_NETLINK;

    nlmsghdr* answer;
    nlmsghdr* lastOk = NULL;
    size_t offset = 0;
    do {
        buf->resize(offset + NLMSG_RCV_GOOD_SIZE);
        answer = reinterpret_cast<nlmsghdr*>(buf->data() + offset);
        iov.iov_base = answer;
        iov.iov_len = buf->size() - offset;
        unsigned int ret = vsm_recvmsg(mFd, &msg, 0);
        for (unsigned int len = ret; NLMSG_OK(answer, len); answer = NLMSG_NEXT(answer, len)) {
            lastOk = answer;
            if (answer->nlmsg_type == NLMSG_ERROR) {
                // It is NACK/ACK message
                nlmsgerr *err = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(answer));
                if (answer->nlmsg_seq != nlmsgSeq) {
                    throw VasumException("Receive failed: answer message was mismatched");
                }
                if (err->error) {
                    throw VasumException("Receive failed: " + getSystemErrorMessage(-err->error));
                }
            } else if (answer->nlmsg_type == NLMSG_OVERRUN) {
                throw VasumException("Receive failed: data lost");
            }
        }
        if (lastOk == NULL) {
            const std::string msg = "Can't receive data from the system";
            LOGE(msg);
            throw VasumException(msg);
        }
        offset +=  NLMSG_ALIGN(ret);
    } while (lastOk->nlmsg_type != NLMSG_DONE && lastOk->nlmsg_flags & NLM_F_MULTI);

    buf->resize(offset);
    return buf;
}
示例#7
0
文件: socket.cpp 项目: hallor/vasum
unsigned short Socket::getPort() const
{
    ::sockaddr_storage address = {0, 0, {0}};
    ::socklen_t length = sizeof(address);
    if (::getsockname(mFD, reinterpret_cast<sockaddr*>(&address), &length) != 0) {
        const std::string msg = "Failed to get socked address: " + getSystemErrorMessage();
        LOGE(msg);
        throw IPCException(msg);
    }

    if (length == sizeof(sockaddr_in)) {
        return ntohs(reinterpret_cast<const sockaddr_in*>(&address)->sin_port);
    } else {
        return ntohs(reinterpret_cast<const sockaddr_in6*>(&address)->sin6_port);
    }
}
示例#8
0
void close(int fd) noexcept
{
    if (fd < 0) {
        return;
    }

    for (;;) {
        if (-1 == ::close(fd)) {
            if (errno == EINTR) {
                LOGT("close() interrupted by a signal, retrying");
                continue;
            }
            LOGE("Error in close: " << getSystemErrorMessage());
        }
        break;
    }
}
示例#9
0
文件: socket.cpp 项目: hallor/vasum
int Socket::getSystemdSocketInternal(const std::string& path)
{
    int n = ::sd_listen_fds(-1 /*Block further calls to sd_listen_fds*/);
    if (n < 0) {
        const std::string msg = "sd_listen_fds failed: " + getSystemErrorMessage(-n);
        LOGE(msg);
        throw IPCException(msg);
    }

    for (int fd = SD_LISTEN_FDS_START;
            fd < SD_LISTEN_FDS_START + n;
            ++fd) {
        if (0 < ::sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0)) {
            setFdOptions(fd);
            return fd;
        }
    }
    LOGW("No usable sockets were passed by systemd.");
    return -1;
}
示例#10
0
文件: img.cpp 项目: vyvy/vasum
bool umountImage(const std::string& path, const std::string& loopdev)
{
    if (::umount(path.c_str()) != 0) {
        LOGD("Umount failed for '" << path << "': " << getSystemErrorMessage());
        return false;
    }

    // clear loop device
    int loopFD = ::open(loopdev.c_str(), O_RDWR);
    if (loopFD < 0) {
        LOGD("Failed to open fd for loop device 0");
        return false;
    }

    if (::ioctl(loopFD, LOOP_CLR_FD, 0) < 0) {
        LOGD("Failed to clear loop device.");
        close(loopFD);
        return false;
    }

    close(loopFD);
    return true;
}
示例#11
0
std::string getSystemErrorMessage()
{
    return getSystemErrorMessage(errno);
}