예제 #1
0
static void
dpdk_nl_process_response(void *usockp, struct nlmsghdr *nlh)
{
    __u32 seq;
    unsigned int multi_flag = 0;
    bool write = true;

    struct vr_message *resp;

    struct nlmsghdr *resp_nlh;
    struct genlmsghdr *genlh, *resp_genlh;
    struct nlattr *resp_nla;

    seq = nlh->nlmsg_seq;
    genlh = (struct genlmsghdr *)((unsigned char *)nlh + NLMSG_HDRLEN);

    /* Process responses */
    while ((resp = (struct vr_message *)vr_message_dequeue_response())) {
        if (!write) {
            vr_message_free(resp);
            continue;
        }

        if (!vr_response_queue_empty()) {
            multi_flag = NLM_F_MULTI;
        } else {
            multi_flag = 0;
        }

        /* Update Netlink headers */
        resp_nlh = dpdk_nl_message_hdr(resp);
        resp_nlh->nlmsg_len = dpdk_nl_message_len(resp);
        resp_nlh->nlmsg_type = nlh->nlmsg_type;
        resp_nlh->nlmsg_flags = multi_flag;
        resp_nlh->nlmsg_seq = seq;
        resp_nlh->nlmsg_pid = 0;

        resp_genlh = (struct genlmsghdr *)((unsigned char *)resp_nlh +
                NLMSG_HDRLEN);
        memcpy(resp_genlh, genlh, sizeof(*genlh));

        resp_nla = (struct nlattr *)((unsigned char *)resp_genlh + GENL_HDRLEN);
        resp_nla->nla_len = resp->vr_message_len;
        resp_nla->nla_type = NL_ATTR_VR_MESSAGE_PROTOCOL;

        if (vr_usocket_message_write(usockp, resp) < 0) {
            write = false;
            vr_usocket_close(usockp);
        }
    }

    return;
}
예제 #2
0
static int
netlink_trans_request(struct sk_buff *in_skb, struct genl_info *info)
{
    char *buf;
    unsigned int len;
    uint32_t multi_flag;
    struct nlmsghdr *rep, *nlh = info->nlhdr;
    struct genlmsghdr *genlh;
    struct nlattr **aap = info->attrs;
    struct nlattr *nla;
    struct vr_message request, *response;
    struct sk_buff *skb;
    uint32_t netlink_id;

    if (!aap || !(nla = aap[NL_ATTR_VR_MESSAGE_PROTOCOL]))
        return -EINVAL;

    request.vr_message_buf = nla_data(nla);
    request.vr_message_len = nla_len(nla);

    vr_message_request(&request);

#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
    netlink_id =  NETLINK_CB(in_skb).pid;
#else
    netlink_id =  NETLINK_CB(in_skb).portid;
#endif

    multi_flag = 0;
    while ((response = vr_message_dequeue_response())) {
        if ((multi_flag == 0) && (!vr_response_queue_empty()))
            multi_flag = NLM_F_MULTI;

        buf = response->vr_message_buf;
        skb = netlink_skb(buf);
        if (!skb)
            continue;

        len = response->vr_message_len;
        len += GENL_HDRLEN + NLA_HDRLEN;
        len = NLMSG_ALIGN(len);
        rep = __nlmsg_put(skb, netlink_id, nlh->nlmsg_seq,
                        nlh->nlmsg_type, len, multi_flag);
        genlh = nlmsg_data(rep);
        memcpy(genlh, info->genlhdr, sizeof(*genlh));

        nla = (struct nlattr *)((char *)genlh + GENL_HDRLEN);
        nla->nla_len = response->vr_message_len;
        nla->nla_type = NL_ATTR_VR_MESSAGE_PROTOCOL;

        netlink_unicast(in_skb->sk, skb, netlink_id, MSG_DONTWAIT);

        response->vr_message_buf = NULL;
        vr_message_free(response);
    }

    if (multi_flag) {
        skb = alloc_skb(NLMSG_HDRLEN, GFP_ATOMIC);
        if (!skb)
            return 0;

        __nlmsg_put(skb, netlink_id, nlh->nlmsg_seq, NLMSG_DONE, 0, 0);
        netlink_unicast(in_skb->sk, skb, netlink_id, MSG_DONTWAIT);
    }


    return 0;
}
예제 #3
0
NTSTATUS
KsyncHandleWrite(PKSYNC_DEVICE_CONTEXT ctx,
                 uint8_t *buffer,
                 size_t buffer_size)
{
    struct vr_message request;
    struct vr_message *response;
    uint32_t multi_flag;
    int ret;

    /* Received buffer contains tightly packed Netlink headers, thus we can
       just increment appropriate headers */
    struct nlmsghdr   *nlh   = (struct nlmsghdr *)(buffer);
    struct genlmsghdr *genlh = (struct genlmsghdr *)(nlh + 1);
    struct nlattr     *nla   = (struct nlattr *)(genlh + 1);

    request.vr_message_buf = NLA_DATA(nla);
    request.vr_message_len = NLA_LEN(nla);

    ret = vr_message_request(&request);
    if (ret) {
        if (vr_send_response(ret)) {
            return STATUS_INVALID_PARAMETER;
        }
    }

    multi_flag = 0;
    while ((response = vr_message_dequeue_response())) {
        if (!multi_flag && !vr_response_queue_empty())
            multi_flag = NLM_F_MULTI;

        char *data = response->vr_message_buf - NETLINK_HEADER_LEN;
        size_t data_len = NLMSG_ALIGN(response->vr_message_len +
                                      NETLINK_HEADER_LEN);

        struct nlmsghdr *nlh_resp = (struct nlmsghdr *)(data);
        nlh_resp->nlmsg_len = data_len;
        nlh_resp->nlmsg_type = nlh->nlmsg_type;
        nlh_resp->nlmsg_flags = multi_flag;
        nlh_resp->nlmsg_seq = nlh->nlmsg_seq;
		nlh_resp->nlmsg_pid = 0;

        /* 'genlmsghdr' should be put directly after 'nlmsghdr', thus we can 
           just increment previous header pointer */
        struct genlmsghdr *genlh_resp = (struct genlmsghdr *)(nlh_resp + 1);
        WinRawMemCpy(genlh_resp, genlh, sizeof(*genlh_resp));

        /* 'nlattr' should be put directly after 'genlmsghdr', thus we can
           just increment previous header pointer */
        struct nlattr *nla_resp = (struct nlattr *)(genlh_resp + 1);
        nla_resp->nla_len = response->vr_message_len;
        nla_resp->nla_type = NL_ATTR_VR_MESSAGE_PROTOCOL;

        PKSYNC_RESPONSE ks_resp = KsyncResponseCreate();
        if (ks_resp != NULL) {
            ks_resp->message_len = data_len;
            WinRawMemCpy(ks_resp->buffer, data, ks_resp->message_len);
            KsyncAppendResponse(ctx, ks_resp);
        } else {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        vr_message_free(response);
    }

    if (multi_flag) {
        PKSYNC_RESPONSE ks_resp = KsyncResponseCreate();
        if (ks_resp == NULL) {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        struct nlmsghdr *nlh_done = (struct nlmsghdr *)ks_resp->buffer;
        nlh_done->nlmsg_len = NLMSG_HDRLEN;
        nlh_done->nlmsg_type = NLMSG_DONE;
        nlh_done->nlmsg_flags = 0;
        nlh_done->nlmsg_seq = nlh->nlmsg_seq;
        nlh_done->nlmsg_pid = 0;

        ks_resp->message_len = NLMSG_HDRLEN;

        KsyncAppendResponse(ctx, ks_resp);
    }

    return STATUS_SUCCESS;
}