Exemplo n.º 1
0
void NLSocket::process_receive(std::size_t bytes_xferred,
                               unsigned int seq, unsigned int portid)
{
    const struct nlmsghdr *nlh = (const struct nlmsghdr *)recv_buffer_.data();
    for (;NLMSG_OK(nlh, bytes_xferred); nlh = NLMSG_NEXT(nlh, bytes_xferred)) {
        // Should be 0 for messages from the kernel.
        if (nlh->nlmsg_pid && portid && nlh->nlmsg_pid != portid)
            continue;
        if (seq && nlh->nlmsg_seq != seq)
            continue;

        if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
            process_nlmsg(nlh);
        } else {
            switch (nlh->nlmsg_type) {
            case NLMSG_ERROR: {
                fmt::print(stderr, "nlsocket: Received a NLMSG_ERROR: {}\n",
                           strerror(nlmsg_get_error(nlh)));
                auto nle = reinterpret_cast<struct nlmsgerr *>(NLMSG_DATA(nlh));
                fmt::print(stderr, "error={} len={} type={} flags={} seq={} pid={}\n",
                         nle->error, nle->msg.nlmsg_len, nle->msg.nlmsg_type,
                         nle->msg.nlmsg_flags, nle->msg.nlmsg_seq,
                         nle->msg.nlmsg_pid);
                break;
            }
            case NLMSG_OVERRUN:
                fmt::print(stderr, "nlsocket: Received a NLMSG_OVERRUN.\n");
            case NLMSG_NOOP:
            case NLMSG_DONE:
            default:
                break;
            }
        }
    }
}
Exemplo n.º 2
0
static int process_response(int wait_for_done, unsigned seq) {
    assert(fd >= 0);
    
    do {
        size_t bytes;
        ssize_t r;
        char replybuf[8*1024];
        char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
        struct msghdr msghdr;
        struct cmsghdr *cmsghdr;
        struct ucred *ucred;
        struct iovec iov; 
        struct nlmsghdr *p = (struct nlmsghdr *) replybuf;
        
        memset(&iov, 0, sizeof(iov));
        iov.iov_base = replybuf; 
 	iov.iov_len = sizeof(replybuf);

        memset(&msghdr, 0, sizeof(msghdr));
        msghdr.msg_name = (void*) NULL;
        msghdr.msg_namelen = 0; 
        msghdr.msg_iov = &iov; 
        msghdr.msg_iovlen = 1; 
        msghdr.msg_control = cred_msg; 
        msghdr.msg_controllen = sizeof(cred_msg); 
 	msghdr.msg_flags = 0;
        
        if ((r = recvmsg(fd, &msghdr, 0)) < 0) {
            daemon_log(LOG_ERR, "recvmsg() failed: %s", strerror(errno));
            return -1;
        }

        if (!(cmsghdr = CMSG_FIRSTHDR(&msghdr)) || cmsghdr->cmsg_type != SCM_CREDENTIALS) {
            daemon_log(LOG_WARNING, "No sender credentials received, ignoring data."); 
            return -1;
        }

        ucred = (struct ucred*) CMSG_DATA(cmsghdr);
        
        if (ucred->uid != 0)
            return -1;

        bytes = (size_t) r;
        
        for (; bytes > 0; p = NLMSG_NEXT(p, bytes)) {

            if (!NLMSG_OK(p, bytes) || bytes < sizeof(struct nlmsghdr) || bytes < p->nlmsg_len) {
                daemon_log(LOG_ERR, "Netlink packet too small.");
                return -1;
            }

            if (p->nlmsg_type == NLMSG_DONE && wait_for_done && p->nlmsg_seq == seq && (pid_t) p->nlmsg_pid == getpid())
                return 0;

            if (p->nlmsg_type == NLMSG_ERROR) {
                struct nlmsgerr *e = (struct nlmsgerr *) NLMSG_DATA (p);

                if (e->error) {
                    daemon_log(LOG_ERR, "Netlink error: %s", strerror(-e->error));
                    return -1;
                }
            }

            if (process_nlmsg(p) < 0)
                return -1;
        }
    } while (wait_for_done);

    return 0;
}