Blame usbredirparser/usbredirparser.c

Packit 9795e1
/* usbredirparser.c usb redirection protocol parser
Packit 9795e1
Packit 9795e1
   Copyright 2010-2012 Red Hat, Inc.
Packit 9795e1
Packit 9795e1
   Red Hat Authors:
Packit 9795e1
   Hans de Goede <hdegoede@redhat.com>
Packit 9795e1
Packit 9795e1
   This library is free software; you can redistribute it and/or
Packit 9795e1
   modify it under the terms of the GNU Lesser General Public
Packit 9795e1
   License as published by the Free Software Foundation; either
Packit 9795e1
   version 2.1 of the License, or (at your option) any later version.
Packit 9795e1
Packit 9795e1
   This library is distributed in the hope that it will be useful,
Packit 9795e1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9795e1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 9795e1
   Lesser General Public License for more details.
Packit 9795e1
Packit 9795e1
   You should have received a copy of the GNU Lesser General Public
Packit 9795e1
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit 9795e1
*/
Packit 9795e1
#include "config.h"
Packit 9795e1
Packit 9795e1
#include <stdio.h>
Packit 9795e1
#include <stdlib.h>
Packit 9795e1
#include <stdarg.h>
Packit 9795e1
#include <string.h>
Packit 9795e1
#include "usbredirproto-compat.h"
Packit 9795e1
#include "usbredirparser.h"
Packit 9795e1
#include "usbredirfilter.h"
Packit 9795e1
Packit 9795e1
/* Put *some* upper limit on bulk transfer sizes */
Packit 9795e1
#define MAX_BULK_TRANSFER_SIZE (128u * 1024u * 1024u)
Packit 9795e1
Packit 9795e1
/* Locking convenience macros */
Packit 9795e1
#define LOCK(parser) \
Packit 9795e1
    do { \
Packit 9795e1
        if ((parser)->lock) \
Packit 9795e1
            (parser)->callb.lock_func((parser)->lock); \
Packit 9795e1
    } while (0)
Packit 9795e1
Packit 9795e1
#define UNLOCK(parser) \
Packit 9795e1
    do { \
Packit 9795e1
        if ((parser)->lock) \
Packit 9795e1
            (parser)->callb.unlock_func((parser)->lock); \
Packit 9795e1
    } while (0)
Packit 9795e1
Packit 9795e1
struct usbredirparser_buf {
Packit 9795e1
    uint8_t *buf;
Packit 9795e1
    int pos;
Packit 9795e1
    int len;
Packit 9795e1
Packit 9795e1
    struct usbredirparser_buf *next;
Packit 9795e1
};
Packit 9795e1
Packit 9795e1
struct usbredirparser_priv {
Packit 9795e1
    struct usbredirparser callb;
Packit 9795e1
    int flags;
Packit 9795e1
Packit 9795e1
    int have_peer_caps;
Packit 9795e1
    uint32_t our_caps[USB_REDIR_CAPS_SIZE];
Packit 9795e1
    uint32_t peer_caps[USB_REDIR_CAPS_SIZE];
Packit 9795e1
Packit 9795e1
    void *lock;
Packit 9795e1
Packit 9795e1
    union {
Packit 9795e1
        struct usb_redir_header header;
Packit 9795e1
        struct usb_redir_header_32bit_id header_32bit_id;
Packit 9795e1
    };
Packit 9795e1
    uint8_t type_header[288];
Packit 9795e1
    int header_read;
Packit 9795e1
    int type_header_len;
Packit 9795e1
    int type_header_read;
Packit 9795e1
    uint8_t *data;
Packit 9795e1
    int data_len;
Packit 9795e1
    int data_read;
Packit 9795e1
    int to_skip;
Packit 9795e1
    struct usbredirparser_buf *write_buf;
Packit 9795e1
    int write_buf_count;
Packit 9795e1
};
Packit 9795e1
Packit 9795e1
static void
Packit 9795e1
#if defined __GNUC__
Packit 9795e1
__attribute__((format(printf, 3, 4)))
Packit 9795e1
#endif
Packit 9795e1
va_log(struct usbredirparser_priv *parser, int verbose, const char *fmt, ...)
Packit 9795e1
{
Packit 9795e1
    char buf[512];
Packit 9795e1
    va_list ap;
Packit 9795e1
    int n;
Packit 9795e1
Packit 9795e1
    n = sprintf(buf, "usbredirparser: ");
Packit 9795e1
    va_start(ap, fmt);
Packit 9795e1
    vsnprintf(buf + n, sizeof(buf) - n, fmt, ap);
Packit 9795e1
    va_end(ap);
Packit 9795e1
Packit 9795e1
    parser->callb.log_func(parser->callb.priv, verbose, buf);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
#define ERROR(...)   va_log(parser, usbredirparser_error, __VA_ARGS__)
Packit 9795e1
#define WARNING(...) va_log(parser, usbredirparser_warning, __VA_ARGS__)
Packit 9795e1
#define INFO(...)    va_log(parser, usbredirparser_info, __VA_ARGS__)
Packit 9795e1
#define DEBUG(...)    va_log(parser, usbredirparser_debug, __VA_ARGS__)
Packit 9795e1
Packit 9795e1
#if 0 /* Can be enabled and called from random place to test serialization */
Packit 9795e1
static void serialize_test(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    struct usbredirparser_buf *wbuf, *next_wbuf;
Packit 9795e1
    uint8_t *data;
Packit 9795e1
    int len;
Packit 9795e1
Packit 9795e1
    if (usbredirparser_serialize(parser_pub, &data, &len))
Packit 9795e1
        return;
Packit 9795e1
Packit 9795e1
    wbuf = parser->write_buf;
Packit 9795e1
    while (wbuf) {
Packit 9795e1
        next_wbuf = wbuf->next;
Packit 9795e1
        free(wbuf->buf);
Packit 9795e1
        free(wbuf);
Packit 9795e1
        wbuf = next_wbuf;
Packit 9795e1
    }
Packit 9795e1
    parser->write_buf = NULL;
Packit 9795e1
    parser->write_buf_count = 0;
Packit 9795e1
Packit 9795e1
    free(parser->data);
Packit 9795e1
    parser->data = NULL;
Packit 9795e1
Packit 9795e1
    parser->type_header_len = parser->data_len = parser->have_peer_caps = 0;
Packit 9795e1
Packit 9795e1
    usbredirparser_unserialize(parser_pub, data, len);
Packit 9795e1
    free(data);
Packit 9795e1
}
Packit 9795e1
#endif
Packit 9795e1
Packit 9795e1
static void usbredirparser_queue(struct usbredirparser *parser, uint32_t type,
Packit 9795e1
    uint64_t id, void *type_header_in, uint8_t *data_in, int data_len);
Packit 9795e1
static int usbredirparser_caps_get_cap(struct usbredirparser_priv *parser,
Packit 9795e1
    uint32_t *caps, int cap);
Packit 9795e1
Packit 9795e1
struct usbredirparser *usbredirparser_create(void)
Packit 9795e1
{
Packit 9795e1
    return calloc(1, sizeof(struct usbredirparser_priv));
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static void usbredirparser_verify_caps(struct usbredirparser_priv *parser,
Packit 9795e1
    uint32_t *caps, const char *desc)
Packit 9795e1
{
Packit 9795e1
    if (usbredirparser_caps_get_cap(parser, caps,
Packit 9795e1
                                    usb_redir_cap_bulk_streams) &&
Packit 9795e1
        !usbredirparser_caps_get_cap(parser, caps,
Packit 9795e1
                                     usb_redir_cap_ep_info_max_packet_size)) {
Packit 9795e1
        ERROR("error %s caps contains cap_bulk_streams without"
Packit 9795e1
              "cap_ep_info_max_packet_size", desc);
Packit 9795e1
        caps[0] &= ~(1 << usb_redir_cap_bulk_streams);
Packit 9795e1
    }
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_init(struct usbredirparser *parser_pub,
Packit 9795e1
    const char *version, uint32_t *caps, int caps_len, int flags)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    struct usb_redir_hello_header hello = { { 0 }, };
Packit 9795e1
Packit 9795e1
    parser->flags = (flags & ~usbredirparser_fl_no_hello);
Packit 9795e1
    if (parser->callb.alloc_lock_func) {
Packit 9795e1
        parser->lock = parser->callb.alloc_lock_func();
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    snprintf(hello.version, sizeof(hello.version), "%s", version);
Packit 9795e1
    if (caps_len > USB_REDIR_CAPS_SIZE) {
Packit 9795e1
        caps_len = USB_REDIR_CAPS_SIZE;
Packit 9795e1
    }
Packit 9795e1
    memcpy(parser->our_caps, caps, caps_len * sizeof(uint32_t));
Packit 9795e1
    /* libusbredirparser handles sending the ack internally */
Packit 9795e1
    if (!(flags & usbredirparser_fl_usb_host))
Packit 9795e1
        usbredirparser_caps_set_cap(parser->our_caps,
Packit 9795e1
                                    usb_redir_cap_device_disconnect_ack);
Packit 9795e1
    usbredirparser_verify_caps(parser, parser->our_caps, "our");
Packit 9795e1
    if (!(flags & usbredirparser_fl_no_hello))
Packit 9795e1
        usbredirparser_queue(parser_pub, usb_redir_hello, 0, &hello,
Packit 9795e1
                             (uint8_t *)parser->our_caps,
Packit 9795e1
                             USB_REDIR_CAPS_SIZE * sizeof(uint32_t));
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_destroy(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    struct usbredirparser_buf *wbuf, *next_wbuf;
Packit 9795e1
Packit 9795e1
    wbuf = parser->write_buf;
Packit 9795e1
    while (wbuf) {
Packit 9795e1
        next_wbuf = wbuf->next;
Packit 9795e1
        free(wbuf->buf);
Packit 9795e1
        free(wbuf);
Packit 9795e1
        wbuf = next_wbuf;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    if (parser->lock)
Packit 9795e1
        parser->callb.free_lock_func(parser->lock);
Packit 9795e1
Packit 9795e1
    free(parser);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int usbredirparser_caps_get_cap(struct usbredirparser_priv *parser,
Packit 9795e1
    uint32_t *caps, int cap)
Packit 9795e1
{
Packit 9795e1
    if (cap / 32 >= USB_REDIR_CAPS_SIZE) {
Packit 9795e1
        ERROR("error request for out of bounds cap: %d", cap);
Packit 9795e1
        return 0;
Packit 9795e1
    }
Packit 9795e1
    if (caps[cap / 32] & (1 << (cap % 32))) {
Packit 9795e1
        return 1;
Packit 9795e1
    } else {
Packit 9795e1
        return 0;
Packit 9795e1
    }
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_caps_set_cap(uint32_t *caps, int cap)
Packit 9795e1
{
Packit 9795e1
    caps[cap / 32] |= 1 << (cap % 32);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_have_peer_caps(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
Packit 9795e1
    return parser->have_peer_caps;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_peer_has_cap(struct usbredirparser *parser_pub, int cap)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    return usbredirparser_caps_get_cap(parser, parser->peer_caps, cap);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_have_cap(struct usbredirparser *parser_pub, int cap)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    return usbredirparser_caps_get_cap(parser, parser->our_caps, cap);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int usbredirparser_using_32bits_ids(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    return !usbredirparser_have_cap(parser_pub, usb_redir_cap_64bits_ids) ||
Packit 9795e1
           !usbredirparser_peer_has_cap(parser_pub, usb_redir_cap_64bits_ids);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static void usbredirparser_handle_hello(struct usbredirparser *parser_pub,
Packit 9795e1
    struct usb_redir_hello_header *hello, uint8_t *data, int data_len)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    uint32_t *peer_caps = (uint32_t *)data;
Packit 9795e1
    char buf[64];
Packit 9795e1
    int i;
Packit 9795e1
Packit 9795e1
    if (parser->have_peer_caps) {
Packit 9795e1
        ERROR("Received second hello message, ignoring");
Packit 9795e1
        return;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    /* In case hello->version is not 0 terminated (which would be a protocol
Packit 9795e1
       violation)_ */
Packit 9795e1
    strncpy(buf, hello->version, sizeof(buf));
Packit 9795e1
    buf[sizeof(buf)-1] = '\0';
Packit 9795e1
Packit 9795e1
    memset(parser->peer_caps, 0, sizeof(parser->peer_caps));
Packit 9795e1
    if (data_len > sizeof(parser->peer_caps)) {
Packit 9795e1
        data_len = sizeof(parser->peer_caps);
Packit 9795e1
    }
Packit 9795e1
    for (i = 0; i < data_len / sizeof(uint32_t); i++) {
Packit 9795e1
        parser->peer_caps[i] = peer_caps[i];
Packit 9795e1
    }
Packit 9795e1
    usbredirparser_verify_caps(parser, parser->peer_caps, "peer");
Packit 9795e1
    parser->have_peer_caps = 1;
Packit 9795e1
    free(data);
Packit 9795e1
Packit 9795e1
    INFO("Peer version: %s, using %d-bits ids", buf,
Packit 9795e1
         usbredirparser_using_32bits_ids(parser_pub) ? 32 : 64);
Packit 9795e1
Packit 9795e1
    /* Added in 0.3.2, so no guarantee it is there */
Packit 9795e1
    if (parser->callb.hello_func)
Packit 9795e1
        parser->callb.hello_func(parser->callb.priv, hello);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int usbredirparser_get_header_len(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    if (usbredirparser_using_32bits_ids(parser_pub))
Packit 9795e1
        return sizeof(struct usb_redir_header_32bit_id);
Packit 9795e1
    else
Packit 9795e1
        return sizeof(struct usb_redir_header);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int usbredirparser_get_type_header_len(
Packit 9795e1
    struct usbredirparser *parser_pub, int32_t type, int send)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    int command_for_host = 0;
Packit 9795e1
Packit 9795e1
    if (parser->flags & usbredirparser_fl_usb_host) {
Packit 9795e1
        command_for_host = 1;
Packit 9795e1
    }
Packit 9795e1
    if (send) {
Packit 9795e1
        command_for_host = !command_for_host;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    switch (type) {
Packit 9795e1
    case usb_redir_hello:
Packit 9795e1
        return sizeof(struct usb_redir_hello_header);
Packit 9795e1
    case usb_redir_device_connect:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            if (usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                    usb_redir_cap_connect_device_version) &&
Packit 9795e1
                usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                    usb_redir_cap_connect_device_version)) {
Packit 9795e1
                return sizeof(struct usb_redir_device_connect_header);
Packit 9795e1
            } else {
Packit 9795e1
                return sizeof(struct usb_redir_device_connect_header_no_device_version);
Packit 9795e1
            }
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_device_disconnect:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return 0;
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_reset:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return 0; /* No packet type specific header */
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_interface_info:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_interface_info_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_ep_info:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            if (usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                    usb_redir_cap_bulk_streams) &&
Packit 9795e1
                usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                    usb_redir_cap_bulk_streams)) {
Packit 9795e1
                return sizeof(struct usb_redir_ep_info_header);
Packit 9795e1
            } else if (usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                    usb_redir_cap_ep_info_max_packet_size) &&
Packit 9795e1
                       usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                    usb_redir_cap_ep_info_max_packet_size)) {
Packit 9795e1
                return sizeof(struct usb_redir_ep_info_header_no_max_streams);
Packit 9795e1
            } else {
Packit 9795e1
                return sizeof(struct usb_redir_ep_info_header_no_max_pktsz);
Packit 9795e1
            }
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_set_configuration:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_set_configuration_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1; /* Should never be send to a guest */
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_get_configuration:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return 0; /* No packet type specific header */
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_configuration_status:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_configuration_status_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_set_alt_setting:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_set_alt_setting_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_get_alt_setting:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_get_alt_setting_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_alt_setting_status:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_alt_setting_status_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_start_iso_stream:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_start_iso_stream_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_stop_iso_stream:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_stop_iso_stream_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_iso_stream_status:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_iso_stream_status_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_start_interrupt_receiving:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_start_interrupt_receiving_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_stop_interrupt_receiving:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_stop_interrupt_receiving_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_interrupt_receiving_status:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_interrupt_receiving_status_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_alloc_bulk_streams:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_alloc_bulk_streams_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_free_bulk_streams:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_free_bulk_streams_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_bulk_streams_status:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_bulk_streams_status_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_cancel_data_packet:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return 0; /* No packet type specific header */
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_filter_reject:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return 0;
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_filter_filter:
Packit 9795e1
        return 0;
Packit 9795e1
    case usb_redir_device_disconnect_ack:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return 0;
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_start_bulk_receiving:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_start_bulk_receiving_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_stop_bulk_receiving:
Packit 9795e1
        if (command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_stop_bulk_receiving_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_bulk_receiving_status:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_bulk_receiving_status_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_control_packet:
Packit 9795e1
        return sizeof(struct usb_redir_control_packet_header);
Packit 9795e1
    case usb_redir_bulk_packet:
Packit 9795e1
        if (usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                usb_redir_cap_32bits_bulk_length) &&
Packit 9795e1
            usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                usb_redir_cap_32bits_bulk_length)) {
Packit 9795e1
            return sizeof(struct usb_redir_bulk_packet_header);
Packit 9795e1
        } else {
Packit 9795e1
            return sizeof(struct usb_redir_bulk_packet_header_16bit_length);
Packit 9795e1
        }
Packit 9795e1
    case usb_redir_iso_packet:
Packit 9795e1
        return sizeof(struct usb_redir_iso_packet_header);
Packit 9795e1
    case usb_redir_interrupt_packet:
Packit 9795e1
        return sizeof(struct usb_redir_interrupt_packet_header);
Packit 9795e1
    case usb_redir_buffered_bulk_packet:
Packit 9795e1
        if (!command_for_host) {
Packit 9795e1
            return sizeof(struct usb_redir_buffered_bulk_packet_header);
Packit 9795e1
        } else {
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    default:
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
/* Note this function only checks if extra data is allowed for the
Packit 9795e1
   packet type being read at all, a check if it is actually allowed
Packit 9795e1
   given the direction of the packet + ep is done in _erify_type_header */
Packit 9795e1
static int usbredirparser_expect_extra_data(struct usbredirparser_priv *parser)
Packit 9795e1
{
Packit 9795e1
    switch (parser->header.type) {
Packit 9795e1
    case usb_redir_hello: /* For the variable length capabilities array */
Packit 9795e1
    case usb_redir_filter_filter:
Packit 9795e1
    case usb_redir_control_packet:
Packit 9795e1
    case usb_redir_bulk_packet:
Packit 9795e1
    case usb_redir_iso_packet:
Packit 9795e1
    case usb_redir_interrupt_packet:
Packit 9795e1
    case usb_redir_buffered_bulk_packet:
Packit 9795e1
        return 1;
Packit 9795e1
    default:
Packit 9795e1
        return 0;
Packit 9795e1
    }
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int usbredirparser_verify_bulk_recv_cap(
Packit 9795e1
    struct usbredirparser *parser_pub, int send)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
Packit 9795e1
    if ((send && !usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                              usb_redir_cap_bulk_receiving)) ||
Packit 9795e1
        (!send && !usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                           usb_redir_cap_bulk_receiving))) {
Packit 9795e1
        ERROR("error bulk_receiving without cap_bulk_receiving");
Packit 9795e1
        return 0;
Packit 9795e1
    }
Packit 9795e1
    return 1; /* Verify ok */
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int usbredirparser_verify_type_header(
Packit 9795e1
    struct usbredirparser *parser_pub,
Packit 9795e1
    int32_t type, void *header, uint8_t *data, int data_len, int send)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    int command_for_host = 0, expect_extra_data = 0;
Packit 9795e1
    int length = 0, ep = -1;
Packit 9795e1
Packit 9795e1
    if (parser->flags & usbredirparser_fl_usb_host) {
Packit 9795e1
        command_for_host = 1;
Packit 9795e1
    }
Packit 9795e1
    if (send) {
Packit 9795e1
        command_for_host = !command_for_host;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    switch (type) {
Packit 9795e1
    case usb_redir_interface_info: {
Packit 9795e1
        struct usb_redir_interface_info_header *intf_info = header;
Packit 9795e1
Packit 9795e1
        if (intf_info->interface_count > 32) {
Packit 9795e1
            ERROR("error interface_count > 32");
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_start_interrupt_receiving: {
Packit 9795e1
        struct usb_redir_start_interrupt_receiving_header *start_int = header;
Packit 9795e1
Packit 9795e1
        if (!(start_int->endpoint & 0x80)) {
Packit 9795e1
            ERROR("start int receiving on non input ep %02x",
Packit 9795e1
                  start_int->endpoint);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_stop_interrupt_receiving: {
Packit 9795e1
        struct usb_redir_stop_interrupt_receiving_header *stop_int = header;
Packit 9795e1
Packit 9795e1
        if (!(stop_int->endpoint & 0x80)) {
Packit 9795e1
            ERROR("stop int receiving on non input ep %02x",
Packit 9795e1
                  stop_int->endpoint);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_interrupt_receiving_status: {
Packit 9795e1
        struct usb_redir_interrupt_receiving_status_header *int_status = header;
Packit 9795e1
Packit 9795e1
        if (!(int_status->endpoint & 0x80)) {
Packit 9795e1
            ERROR("int receiving status for non input ep %02x",
Packit 9795e1
                  int_status->endpoint);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_filter_reject:
Packit 9795e1
        if ((send && !usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                             usb_redir_cap_filter)) ||
Packit 9795e1
            (!send && !usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                             usb_redir_cap_filter))) {
Packit 9795e1
            ERROR("error filter_reject without cap_filter");
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_filter_filter:
Packit 9795e1
        if ((send && !usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                             usb_redir_cap_filter)) ||
Packit 9795e1
            (!send && !usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                             usb_redir_cap_filter))) {
Packit 9795e1
            ERROR("error filter_filter without cap_filter");
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        if (data_len < 1) {
Packit 9795e1
            ERROR("error filter_filter without data");
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        if (data[data_len - 1] != 0) {
Packit 9795e1
            ERROR("error non 0 terminated filter_filter data");
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_device_disconnect_ack:
Packit 9795e1
        if ((send && !usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                     usb_redir_cap_device_disconnect_ack)) ||
Packit 9795e1
            (!send && !usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                     usb_redir_cap_device_disconnect_ack))) {
Packit 9795e1
            ERROR("error device_disconnect_ack without cap_device_disconnect_ack");
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_start_bulk_receiving: {
Packit 9795e1
        struct usb_redir_start_bulk_receiving_header *start_bulk = header;
Packit 9795e1
Packit 9795e1
        if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) {
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        if (start_bulk->bytes_per_transfer > MAX_BULK_TRANSFER_SIZE) {
Packit 9795e1
            ERROR("start bulk receiving length exceeds limits %u > %u",
Packit 9795e1
                  start_bulk->bytes_per_transfer, MAX_BULK_TRANSFER_SIZE);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        if (!(start_bulk->endpoint & 0x80)) {
Packit 9795e1
            ERROR("start bulk receiving on non input ep %02x",
Packit 9795e1
                  start_bulk->endpoint);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_stop_bulk_receiving: {
Packit 9795e1
        struct usb_redir_stop_bulk_receiving_header *stop_bulk = header;
Packit 9795e1
Packit 9795e1
        if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) {
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        if (!(stop_bulk->endpoint & 0x80)) {
Packit 9795e1
            ERROR("stop bulk receiving on non input ep %02x",
Packit 9795e1
                  stop_bulk->endpoint);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_bulk_receiving_status: {
Packit 9795e1
        struct usb_redir_bulk_receiving_status_header *bulk_status = header;
Packit 9795e1
Packit 9795e1
        if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) {
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        if (!(bulk_status->endpoint & 0x80)) {
Packit 9795e1
            ERROR("bulk receiving status for non input ep %02x",
Packit 9795e1
                  bulk_status->endpoint);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_control_packet:
Packit 9795e1
        length = ((struct usb_redir_control_packet_header *)header)->length;
Packit 9795e1
        ep = ((struct usb_redir_control_packet_header *)header)->endpoint;
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_bulk_packet: {
Packit 9795e1
        struct usb_redir_bulk_packet_header *bulk_packet = header;
Packit 9795e1
        if (usbredirparser_have_cap(parser_pub,
Packit 9795e1
                                usb_redir_cap_32bits_bulk_length) &&
Packit 9795e1
            usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                usb_redir_cap_32bits_bulk_length)) {
Packit 9795e1
            length = (bulk_packet->length_high << 16) | bulk_packet->length;
Packit 9795e1
        } else {
Packit 9795e1
            length = bulk_packet->length;
Packit 9795e1
            if (!send)
Packit 9795e1
                bulk_packet->length_high = 0;
Packit 9795e1
        }
Packit 9795e1
        if ((uint32_t)length > MAX_BULK_TRANSFER_SIZE) {
Packit 9795e1
            ERROR("bulk transfer length exceeds limits %u > %u",
Packit 9795e1
                  (uint32_t)length, MAX_BULK_TRANSFER_SIZE);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        ep = bulk_packet->endpoint;
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_iso_packet:
Packit 9795e1
        length = ((struct usb_redir_iso_packet_header *)header)->length;
Packit 9795e1
        ep = ((struct usb_redir_iso_packet_header *)header)->endpoint;
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_interrupt_packet:
Packit 9795e1
        length = ((struct usb_redir_interrupt_packet_header *)header)->length;
Packit 9795e1
        ep = ((struct usb_redir_interrupt_packet_header *)header)->endpoint;
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_buffered_bulk_packet: {
Packit 9795e1
        struct usb_redir_buffered_bulk_packet_header *buf_bulk_pkt = header;
Packit 9795e1
        length = buf_bulk_pkt->length;
Packit 9795e1
        if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) {
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        if ((uint32_t)length > MAX_BULK_TRANSFER_SIZE) {
Packit 9795e1
            ERROR("buffered bulk transfer length exceeds limits %u > %u",
Packit 9795e1
                  (uint32_t)length, MAX_BULK_TRANSFER_SIZE);
Packit 9795e1
            return 0;
Packit 9795e1
        }
Packit 9795e1
        ep = buf_bulk_pkt->endpoint;
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    if (ep != -1) {
Packit 9795e1
        if (((ep & 0x80) && !command_for_host) ||
Packit 9795e1
            (!(ep & 0x80) && command_for_host)) {
Packit 9795e1
            expect_extra_data = 1;
Packit 9795e1
        }
Packit 9795e1
        if (expect_extra_data) {
Packit 9795e1
            if (data_len != length) {
Packit 9795e1
                ERROR("error data len %d != header len %d ep %02X",
Packit 9795e1
                      data_len, length, ep);
Packit 9795e1
                return 0;
Packit 9795e1
            }
Packit 9795e1
        } else {
Packit 9795e1
            if (data || data_len) {
Packit 9795e1
                ERROR("error unexpected extra data ep %02X", ep);
Packit 9795e1
                return 0;
Packit 9795e1
            }
Packit 9795e1
            switch (type) {
Packit 9795e1
            case usb_redir_iso_packet:
Packit 9795e1
                ERROR("error iso packet send in wrong direction");
Packit 9795e1
                return 0;
Packit 9795e1
            case usb_redir_interrupt_packet:
Packit 9795e1
                if (command_for_host) {
Packit 9795e1
                    ERROR("error interrupt packet send in wrong direction");
Packit 9795e1
                    return 0;
Packit 9795e1
                }
Packit 9795e1
                break;
Packit 9795e1
            case usb_redir_buffered_bulk_packet:
Packit 9795e1
                ERROR("error buffered bulk packet send in wrong direction");
Packit 9795e1
                return 0;
Packit 9795e1
            }
Packit 9795e1
        }
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    return 1; /* Verify ok */
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static void usbredirparser_call_type_func(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    uint64_t id;
Packit 9795e1
Packit 9795e1
    if (usbredirparser_using_32bits_ids(parser_pub))
Packit 9795e1
        id = parser->header_32bit_id.id;
Packit 9795e1
    else
Packit 9795e1
        id = parser->header.id;
Packit 9795e1
Packit 9795e1
    switch (parser->header.type) {
Packit 9795e1
    case usb_redir_hello:
Packit 9795e1
        usbredirparser_handle_hello(parser_pub,
Packit 9795e1
            (struct usb_redir_hello_header *)parser->type_header,
Packit 9795e1
            parser->data, parser->data_len);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_device_connect:
Packit 9795e1
        parser->callb.device_connect_func(parser->callb.priv,
Packit 9795e1
            (struct usb_redir_device_connect_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_device_disconnect:
Packit 9795e1
        parser->callb.device_disconnect_func(parser->callb.priv);
Packit 9795e1
        if (usbredirparser_peer_has_cap(parser_pub,
Packit 9795e1
                                        usb_redir_cap_device_disconnect_ack))
Packit 9795e1
            usbredirparser_queue(parser_pub, usb_redir_device_disconnect_ack,
Packit 9795e1
                                 0, NULL, NULL, 0);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_reset:
Packit 9795e1
        parser->callb.reset_func(parser->callb.priv);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_interface_info:
Packit 9795e1
        parser->callb.interface_info_func(parser->callb.priv,
Packit 9795e1
            (struct usb_redir_interface_info_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_ep_info:
Packit 9795e1
        parser->callb.ep_info_func(parser->callb.priv,
Packit 9795e1
            (struct usb_redir_ep_info_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_set_configuration:
Packit 9795e1
        parser->callb.set_configuration_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_set_configuration_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_get_configuration:
Packit 9795e1
        parser->callb.get_configuration_func(parser->callb.priv, id);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_configuration_status:
Packit 9795e1
        parser->callb.configuration_status_func(parser->callb.priv, id,
Packit 9795e1
          (struct usb_redir_configuration_status_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_set_alt_setting:
Packit 9795e1
        parser->callb.set_alt_setting_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_set_alt_setting_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_get_alt_setting:
Packit 9795e1
        parser->callb.get_alt_setting_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_get_alt_setting_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_alt_setting_status:
Packit 9795e1
        parser->callb.alt_setting_status_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_alt_setting_status_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_start_iso_stream:
Packit 9795e1
        parser->callb.start_iso_stream_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_start_iso_stream_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_stop_iso_stream:
Packit 9795e1
        parser->callb.stop_iso_stream_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_stop_iso_stream_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_iso_stream_status:
Packit 9795e1
        parser->callb.iso_stream_status_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_iso_stream_status_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_start_interrupt_receiving:
Packit 9795e1
        parser->callb.start_interrupt_receiving_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_start_interrupt_receiving_header *)
Packit 9795e1
            parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_stop_interrupt_receiving:
Packit 9795e1
        parser->callb.stop_interrupt_receiving_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_stop_interrupt_receiving_header *)
Packit 9795e1
            parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_interrupt_receiving_status:
Packit 9795e1
        parser->callb.interrupt_receiving_status_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_interrupt_receiving_status_header *)
Packit 9795e1
            parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_alloc_bulk_streams:
Packit 9795e1
        parser->callb.alloc_bulk_streams_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_alloc_bulk_streams_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_free_bulk_streams:
Packit 9795e1
        parser->callb.free_bulk_streams_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_free_bulk_streams_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_bulk_streams_status:
Packit 9795e1
        parser->callb.bulk_streams_status_func(parser->callb.priv, id,
Packit 9795e1
          (struct usb_redir_bulk_streams_status_header *)parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_cancel_data_packet:
Packit 9795e1
        parser->callb.cancel_data_packet_func(parser->callb.priv, id);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_filter_reject:
Packit 9795e1
        parser->callb.filter_reject_func(parser->callb.priv);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_filter_filter: {
Packit 9795e1
        struct usbredirfilter_rule *rules;
Packit 9795e1
        int r, count;
Packit 9795e1
Packit 9795e1
        r = usbredirfilter_string_to_rules((char *)parser->data, ",", "|",
Packit 9795e1
                                           &rules, &count);
Packit 9795e1
        if (r) {
Packit 9795e1
            ERROR("error parsing filter (%d), ignoring filter message", r);
Packit 9795e1
            break;
Packit 9795e1
        }
Packit 9795e1
        parser->callb.filter_filter_func(parser->callb.priv, rules, count);
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
    case usb_redir_device_disconnect_ack:
Packit 9795e1
        parser->callb.device_disconnect_ack_func(parser->callb.priv);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_start_bulk_receiving:
Packit 9795e1
        parser->callb.start_bulk_receiving_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_start_bulk_receiving_header *)
Packit 9795e1
            parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_stop_bulk_receiving:
Packit 9795e1
        parser->callb.stop_bulk_receiving_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_stop_bulk_receiving_header *)
Packit 9795e1
            parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_bulk_receiving_status:
Packit 9795e1
        parser->callb.bulk_receiving_status_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_bulk_receiving_status_header *)
Packit 9795e1
            parser->type_header);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_control_packet:
Packit 9795e1
        parser->callb.control_packet_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_control_packet_header *)parser->type_header,
Packit 9795e1
            parser->data, parser->data_len);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_bulk_packet:
Packit 9795e1
        parser->callb.bulk_packet_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_bulk_packet_header *)parser->type_header,
Packit 9795e1
            parser->data, parser->data_len);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_iso_packet:
Packit 9795e1
        parser->callb.iso_packet_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_iso_packet_header *)parser->type_header,
Packit 9795e1
            parser->data, parser->data_len);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_interrupt_packet:
Packit 9795e1
        parser->callb.interrupt_packet_func(parser->callb.priv, id,
Packit 9795e1
            (struct usb_redir_interrupt_packet_header *)parser->type_header,
Packit 9795e1
            parser->data, parser->data_len);
Packit 9795e1
        break;
Packit 9795e1
    case usb_redir_buffered_bulk_packet:
Packit 9795e1
        parser->callb.buffered_bulk_packet_func(parser->callb.priv, id,
Packit 9795e1
          (struct usb_redir_buffered_bulk_packet_header *)parser->type_header,
Packit 9795e1
          parser->data, parser->data_len);
Packit 9795e1
        break;
Packit 9795e1
    }
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_do_read(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    int r, header_len, type_header_len, data_len;
Packit 9795e1
    uint8_t *dest;
Packit 9795e1
Packit 9795e1
    header_len = usbredirparser_get_header_len(parser_pub);
Packit 9795e1
Packit 9795e1
    /* Skip forward to next packet (only used in error conditions) */
Packit 9795e1
    while (parser->to_skip > 0) {
Packit 9795e1
        uint8_t buf[65536];
Packit 9795e1
        r = (parser->to_skip > sizeof(buf)) ? sizeof(buf) : parser->to_skip;
Packit 9795e1
        r = parser->callb.read_func(parser->callb.priv, buf, r);
Packit 9795e1
        if (r <= 0)
Packit 9795e1
            return r;
Packit 9795e1
        parser->to_skip -= r;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    /* Consume data until read would block or returns an error */
Packit 9795e1
    while (1) {
Packit 9795e1
        if (parser->header_read < header_len) {
Packit 9795e1
            r = header_len - parser->header_read;
Packit 9795e1
            dest = (uint8_t *)&parser->header + parser->header_read;
Packit 9795e1
        } else if (parser->type_header_read < parser->type_header_len) {
Packit 9795e1
            r = parser->type_header_len - parser->type_header_read;
Packit 9795e1
            dest = parser->type_header + parser->type_header_read;
Packit 9795e1
        } else {
Packit 9795e1
            r = parser->data_len - parser->data_read;
Packit 9795e1
            dest = parser->data + parser->data_read;
Packit 9795e1
        }
Packit 9795e1
Packit 9795e1
        if (r > 0) {
Packit 9795e1
            r = parser->callb.read_func(parser->callb.priv, dest, r);
Packit 9795e1
            if (r <= 0) {
Packit 9795e1
                return r;
Packit 9795e1
            }
Packit 9795e1
        }
Packit 9795e1
Packit 9795e1
        if (parser->header_read < header_len) {
Packit 9795e1
            parser->header_read += r;
Packit 9795e1
            if (parser->header_read == header_len) {
Packit 9795e1
                type_header_len =
Packit 9795e1
                    usbredirparser_get_type_header_len(parser_pub,
Packit 9795e1
                                                       parser->header.type, 0);
Packit 9795e1
                if (type_header_len < 0) {
Packit 9795e1
                    ERROR("error invalid usb-redir packet type: %u",
Packit 9795e1
                          parser->header.type);
Packit 9795e1
                    parser->to_skip = parser->header.length;
Packit 9795e1
                    parser->header_read = 0;
Packit 9795e1
                    return -2;
Packit 9795e1
                }
Packit 9795e1
                /* This should never happen */
Packit 9795e1
                if (type_header_len > sizeof(parser->type_header)) {
Packit 9795e1
                    ERROR("error type specific header buffer too small, please report!!");
Packit 9795e1
                    parser->to_skip = parser->header.length;
Packit 9795e1
                    parser->header_read = 0;
Packit 9795e1
                    return -2;
Packit 9795e1
                }
Packit 9795e1
                if ((int)parser->header.length < type_header_len ||
Packit 9795e1
                    ((int)parser->header.length > type_header_len &&
Packit 9795e1
                     !usbredirparser_expect_extra_data(parser))) {
Packit 9795e1
                    ERROR("error invalid packet type %u length: %u",
Packit 9795e1
                          parser->header.type, parser->header.length);
Packit 9795e1
                    parser->to_skip = parser->header.length;
Packit 9795e1
                    parser->header_read = 0;
Packit 9795e1
                    return -2;
Packit 9795e1
                }
Packit 9795e1
                data_len = parser->header.length - type_header_len;
Packit 9795e1
                if (data_len) {
Packit 9795e1
                    parser->data = malloc(data_len);
Packit 9795e1
                    if (!parser->data) {
Packit 9795e1
                        ERROR("Out of memory allocating data buffer");
Packit 9795e1
                        parser->to_skip = parser->header.length;
Packit 9795e1
                        parser->header_read = 0;
Packit 9795e1
                        return -2;
Packit 9795e1
                    }
Packit 9795e1
                }
Packit 9795e1
                parser->type_header_len = type_header_len;
Packit 9795e1
                parser->data_len = data_len;
Packit 9795e1
            }
Packit 9795e1
        } else if (parser->type_header_read < parser->type_header_len) {
Packit 9795e1
            parser->type_header_read += r;
Packit 9795e1
        } else {
Packit 9795e1
            parser->data_read += r;
Packit 9795e1
            if (parser->data_read == parser->data_len) {
Packit 9795e1
                r = usbredirparser_verify_type_header(parser_pub,
Packit 9795e1
                         parser->header.type, parser->type_header,
Packit 9795e1
                         parser->data, parser->data_len, 0);
Packit 9795e1
                if (r)
Packit 9795e1
                    usbredirparser_call_type_func(parser_pub);
Packit 9795e1
                parser->header_read = 0;
Packit 9795e1
                parser->type_header_len  = 0;
Packit 9795e1
                parser->type_header_read = 0;
Packit 9795e1
                parser->data_len  = 0;
Packit 9795e1
                parser->data_read = 0;
Packit 9795e1
                parser->data = NULL;
Packit 9795e1
                if (!r)
Packit 9795e1
                    return -2;
Packit 9795e1
                /* header len may change if this was an hello packet */
Packit 9795e1
                header_len = usbredirparser_get_header_len(parser_pub);
Packit 9795e1
            }
Packit 9795e1
        }
Packit 9795e1
    }
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_has_data_to_write(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    return parser->write_buf_count;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_do_write(struct usbredirparser *parser_pub)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    struct usbredirparser_buf* wbuf;
Packit 9795e1
    int w, ret = 0;
Packit 9795e1
Packit 9795e1
    LOCK(parser);
Packit 9795e1
    for (;;) {
Packit 9795e1
        wbuf = parser->write_buf;
Packit 9795e1
        if (!wbuf)
Packit 9795e1
            break;
Packit 9795e1
Packit 9795e1
        w = wbuf->len - wbuf->pos;
Packit 9795e1
        w = parser->callb.write_func(parser->callb.priv,
Packit 9795e1
                                     wbuf->buf + wbuf->pos, w);
Packit 9795e1
        if (w <= 0) {
Packit 9795e1
            ret = w;
Packit 9795e1
            break;
Packit 9795e1
        }
Packit 9795e1
Packit 9795e1
        /* See usbredirparser_write documentation */
Packit 9795e1
        if ((parser->flags & usbredirparser_fl_write_cb_owns_buffer) &&
Packit 9795e1
                w != wbuf->len)
Packit 9795e1
            abort();
Packit 9795e1
Packit 9795e1
        wbuf->pos += w;
Packit 9795e1
        if (wbuf->pos == wbuf->len) {
Packit 9795e1
            parser->write_buf = wbuf->next;
Packit 9795e1
            if (!(parser->flags & usbredirparser_fl_write_cb_owns_buffer))
Packit 9795e1
                free(wbuf->buf);
Packit 9795e1
            free(wbuf);
Packit 9795e1
            parser->write_buf_count--;
Packit 9795e1
        }
Packit 9795e1
    }
Packit 9795e1
    UNLOCK(parser);
Packit 9795e1
    return ret;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_free_write_buffer(struct usbredirparser *parser,
Packit 9795e1
    uint8_t *data)
Packit 9795e1
{
Packit 9795e1
    free(data);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_free_packet_data(struct usbredirparser *parser,
Packit 9795e1
    uint8_t *data)
Packit 9795e1
{
Packit 9795e1
    free(data);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static void usbredirparser_queue(struct usbredirparser *parser_pub,
Packit 9795e1
    uint32_t type, uint64_t id, void *type_header_in,
Packit 9795e1
    uint8_t *data_in, int data_len)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    uint8_t *buf, *type_header_out, *data_out;
Packit 9795e1
    struct usb_redir_header *header;
Packit 9795e1
    struct usbredirparser_buf *wbuf, *new_wbuf;
Packit 9795e1
    int header_len, type_header_len;
Packit 9795e1
Packit 9795e1
    header_len = usbredirparser_get_header_len(parser_pub);
Packit 9795e1
    type_header_len = usbredirparser_get_type_header_len(parser_pub, type, 1);
Packit 9795e1
    if (type_header_len < 0) { /* This should never happen */
Packit 9795e1
        ERROR("error packet type unknown with internal call, please report!!");
Packit 9795e1
        return;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    if (!usbredirparser_verify_type_header(parser_pub, type, type_header_in,
Packit 9795e1
                                           data_in, data_len, 1)) {
Packit 9795e1
        ERROR("error usbredirparser_send_* call invalid params, please report!!");
Packit 9795e1
        return;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    new_wbuf = calloc(1, sizeof(*new_wbuf));
Packit 9795e1
    buf = malloc(header_len + type_header_len + data_len);
Packit 9795e1
    if (!new_wbuf || !buf) {
Packit 9795e1
        ERROR("Out of memory allocating buffer to send packet, dropping!");
Packit 9795e1
        free(new_wbuf); free(buf);
Packit 9795e1
        return;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    new_wbuf->buf = buf;
Packit 9795e1
    new_wbuf->len = header_len + type_header_len + data_len;
Packit 9795e1
Packit 9795e1
    header = (struct usb_redir_header *)buf;
Packit 9795e1
    type_header_out = buf + header_len;
Packit 9795e1
    data_out = type_header_out + type_header_len;
Packit 9795e1
Packit 9795e1
    header->type   = type;
Packit 9795e1
    header->length = type_header_len + data_len;
Packit 9795e1
    if (usbredirparser_using_32bits_ids(parser_pub))
Packit 9795e1
        ((struct usb_redir_header_32bit_id *)header)->id = id;
Packit 9795e1
    else
Packit 9795e1
        header->id = id;
Packit 9795e1
    memcpy(type_header_out, type_header_in, type_header_len);
Packit 9795e1
    memcpy(data_out, data_in, data_len);
Packit 9795e1
Packit 9795e1
    LOCK(parser);
Packit 9795e1
    if (!parser->write_buf) {
Packit 9795e1
        parser->write_buf = new_wbuf;
Packit 9795e1
    } else {
Packit 9795e1
        /* limiting the write_buf's stack depth is our users responsibility */
Packit 9795e1
        wbuf = parser->write_buf;
Packit 9795e1
        while (wbuf->next)
Packit 9795e1
            wbuf = wbuf->next;
Packit 9795e1
Packit 9795e1
        wbuf->next = new_wbuf;
Packit 9795e1
    }
Packit 9795e1
    parser->write_buf_count++;
Packit 9795e1
    UNLOCK(parser);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_device_connect(struct usbredirparser *parser,
Packit 9795e1
    struct usb_redir_device_connect_header *device_connect)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_device_connect, 0, device_connect,
Packit 9795e1
                         NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_device_disconnect(struct usbredirparser *parser)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_device_disconnect, 0, NULL,
Packit 9795e1
                         NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_reset(struct usbredirparser *parser)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_reset, 0, NULL, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_interface_info(struct usbredirparser *parser,
Packit 9795e1
    struct usb_redir_interface_info_header *interface_info)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_interface_info, 0, interface_info,
Packit 9795e1
                         NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_ep_info(struct usbredirparser *parser,
Packit 9795e1
    struct usb_redir_ep_info_header *ep_info)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_ep_info, 0, ep_info, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_set_configuration(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_set_configuration_header *set_configuration)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_set_configuration, id,
Packit 9795e1
                         set_configuration, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_get_configuration(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_get_configuration, id,
Packit 9795e1
                         NULL, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_configuration_status(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_configuration_status_header *configuration_status)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_configuration_status, id,
Packit 9795e1
                         configuration_status, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_set_alt_setting(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_set_alt_setting_header *set_alt_setting)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_set_alt_setting, id,
Packit 9795e1
                         set_alt_setting, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_get_alt_setting(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_get_alt_setting_header *get_alt_setting)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_get_alt_setting, id,
Packit 9795e1
                         get_alt_setting, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_alt_setting_status(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_alt_setting_status_header *alt_setting_status)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_alt_setting_status, id,
Packit 9795e1
                         alt_setting_status, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_start_iso_stream(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_start_iso_stream_header *start_iso_stream)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_start_iso_stream, id,
Packit 9795e1
                         start_iso_stream, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_stop_iso_stream(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_stop_iso_stream_header *stop_iso_stream)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_stop_iso_stream, id,
Packit 9795e1
                         stop_iso_stream, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_iso_stream_status(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_iso_stream_status_header *iso_stream_status)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_iso_stream_status, id,
Packit 9795e1
                         iso_stream_status, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_start_interrupt_receiving(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_start_interrupt_receiving_header *start_interrupt_receiving)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_start_interrupt_receiving, id,
Packit 9795e1
                         start_interrupt_receiving, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_stop_interrupt_receiving(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_stop_interrupt_receiving_header *stop_interrupt_receiving)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_stop_interrupt_receiving, id,
Packit 9795e1
                         stop_interrupt_receiving, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_interrupt_receiving_status(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_interrupt_receiving_status_header *interrupt_receiving_status)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_interrupt_receiving_status, id,
Packit 9795e1
                         interrupt_receiving_status, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_alloc_bulk_streams(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_alloc_bulk_streams_header *alloc_bulk_streams)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_alloc_bulk_streams, id,
Packit 9795e1
                         alloc_bulk_streams, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_free_bulk_streams(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_free_bulk_streams_header *free_bulk_streams)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_free_bulk_streams, id,
Packit 9795e1
                         free_bulk_streams, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_bulk_streams_status(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_bulk_streams_status_header *bulk_streams_status)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_bulk_streams_status, id,
Packit 9795e1
                         bulk_streams_status, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_cancel_data_packet(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_cancel_data_packet, id,
Packit 9795e1
                         NULL, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_filter_reject(struct usbredirparser *parser)
Packit 9795e1
{
Packit 9795e1
    if (!usbredirparser_peer_has_cap(parser, usb_redir_cap_filter))
Packit 9795e1
        return;
Packit 9795e1
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_filter_reject, 0, NULL, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_filter_filter(struct usbredirparser *parser_pub,
Packit 9795e1
    const struct usbredirfilter_rule *rules, int rules_count)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    char *str;
Packit 9795e1
Packit 9795e1
    if (!usbredirparser_peer_has_cap(parser_pub, usb_redir_cap_filter))
Packit 9795e1
        return;
Packit 9795e1
Packit 9795e1
    str = usbredirfilter_rules_to_string(rules, rules_count, ",", "|");
Packit 9795e1
    if (!str) {
Packit 9795e1
        ERROR("error creating filter string, not sending filter");
Packit 9795e1
        return;
Packit 9795e1
    }
Packit 9795e1
    usbredirparser_queue(parser_pub, usb_redir_filter_filter, 0, NULL,
Packit 9795e1
                         (uint8_t *)str, strlen(str) + 1);
Packit 9795e1
    free(str);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_start_bulk_receiving(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_start_bulk_receiving_header *start_bulk_receiving)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_start_bulk_receiving, id,
Packit 9795e1
                         start_bulk_receiving, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_stop_bulk_receiving(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_stop_bulk_receiving_header *stop_bulk_receiving)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_stop_bulk_receiving, id,
Packit 9795e1
                         stop_bulk_receiving, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_bulk_receiving_status(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_bulk_receiving_status_header *bulk_receiving_status)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_bulk_receiving_status, id,
Packit 9795e1
                         bulk_receiving_status, NULL, 0);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
/* Data packets: */
Packit 9795e1
void usbredirparser_send_control_packet(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_control_packet_header *control_header,
Packit 9795e1
    uint8_t *data, int data_len)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_control_packet, id, control_header,
Packit 9795e1
                         data, data_len);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_bulk_packet(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_bulk_packet_header *bulk_header,
Packit 9795e1
    uint8_t *data, int data_len)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_bulk_packet, id, bulk_header,
Packit 9795e1
                         data, data_len);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_iso_packet(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_iso_packet_header *iso_header,
Packit 9795e1
    uint8_t *data, int data_len)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_iso_packet, id, iso_header,
Packit 9795e1
                         data, data_len);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_interrupt_packet(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_interrupt_packet_header *interrupt_header,
Packit 9795e1
    uint8_t *data, int data_len)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_interrupt_packet, id,
Packit 9795e1
                         interrupt_header, data, data_len);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
void usbredirparser_send_buffered_bulk_packet(struct usbredirparser *parser,
Packit 9795e1
    uint64_t id,
Packit 9795e1
    struct usb_redir_buffered_bulk_packet_header *buffered_bulk_header,
Packit 9795e1
    uint8_t *data, int data_len)
Packit 9795e1
{
Packit 9795e1
    usbredirparser_queue(parser, usb_redir_buffered_bulk_packet, id,
Packit 9795e1
                         buffered_bulk_header, data, data_len);
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
/****** Serialization support ******/
Packit 9795e1
Packit 9795e1
#define USBREDIRPARSER_SERIALIZE_MAGIC        0x55525031
Packit 9795e1
#define USBREDIRPARSER_SERIALIZE_BUF_SIZE     65536
Packit 9795e1
Packit 9795e1
/* Serialization format, send and receiving endian are expected to be the same!
Packit 9795e1
    uint32 MAGIC: 0x55525031 ascii: URP1 (UsbRedirParser version 1)
Packit 9795e1
    uint32 len: length of the entire serialized state, including MAGIC
Packit 9795e1
    uint32 our_caps_len
Packit 9795e1
    uint32 our_caps[our_caps_len]
Packit 9795e1
    uint32 peer_caps_len
Packit 9795e1
    uint32 peer_caps[peer_caps_len]
Packit 9795e1
    uint32 to_skip
Packit 9795e1
    uint32 header_read
Packit 9795e1
    uint8  header[header_read]
Packit 9795e1
    uint32 type_header_read
Packit 9795e1
    uint8  type_header[type_header_read]
Packit 9795e1
    uint32 data_read
Packit 9795e1
    uint8  data[data_read]
Packit 9795e1
    uint32 write_buf_count: followed by write_buf_count times:
Packit 9795e1
        uint32 write_buf_len
Packit 9795e1
        uint8  write_buf_data[write_buf_len]
Packit 9795e1
*/
Packit 9795e1
Packit 9795e1
static int serialize_alloc(struct usbredirparser_priv *parser,
Packit 9795e1
                           uint8_t **state, uint8_t **pos,
Packit 9795e1
                           uint32_t *remain, uint32_t needed)
Packit 9795e1
{
Packit 9795e1
    uint8_t *old_state = *state;
Packit 9795e1
    uint32_t used, size;
Packit 9795e1
Packit 9795e1
    if (*remain >= needed)
Packit 9795e1
        return 0;
Packit 9795e1
Packit 9795e1
    used = *pos - *state;
Packit 9795e1
    size = (used + needed + USBREDIRPARSER_SERIALIZE_BUF_SIZE - 1) &
Packit 9795e1
           ~(USBREDIRPARSER_SERIALIZE_BUF_SIZE - 1);
Packit 9795e1
Packit 9795e1
    *state = realloc(*state, size);
Packit 9795e1
    if (!*state) {
Packit 9795e1
        free(old_state);
Packit 9795e1
        ERROR("Out of memory allocating serialization buffer");
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    *pos = *state + used;
Packit 9795e1
    *remain = size - used;
Packit 9795e1
Packit 9795e1
    return 0;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int serialize_int(struct usbredirparser_priv *parser,
Packit 9795e1
                         uint8_t **state, uint8_t **pos, uint32_t *remain,
Packit 9795e1
                         uint32_t val, const char *desc)
Packit 9795e1
{
Packit 9795e1
    DEBUG("serializing int %08x : %s", val, desc);
Packit 9795e1
Packit 9795e1
    if (serialize_alloc(parser, state, pos, remain, sizeof(uint32_t)))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    memcpy(*pos, &val, sizeof(uint32_t));
Packit 9795e1
    *pos += sizeof(uint32_t);
Packit 9795e1
    *remain -= sizeof(uint32_t);
Packit 9795e1
Packit 9795e1
    return 0;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int unserialize_int(struct usbredirparser_priv *parser,
Packit 9795e1
                           uint8_t **pos, uint32_t *remain, uint32_t *val,
Packit 9795e1
                           const char *desc)
Packit 9795e1
{
Packit 9795e1
    if (*remain < sizeof(uint32_t)) {
Packit 9795e1
        ERROR("error buffer underrun while unserializing state");
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
    memcpy(val, *pos, sizeof(uint32_t));
Packit 9795e1
    *pos += sizeof(uint32_t);
Packit 9795e1
    *remain -= sizeof(uint32_t);
Packit 9795e1
Packit 9795e1
    DEBUG("unserialized int %08x : %s", *val, desc);
Packit 9795e1
Packit 9795e1
    return 0;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
static int serialize_data(struct usbredirparser_priv *parser,
Packit 9795e1
                          uint8_t **state, uint8_t **pos, uint32_t *remain,
Packit 9795e1
                          uint8_t *data, uint32_t len, const char *desc)
Packit 9795e1
{
Packit 9795e1
    DEBUG("serializing %d bytes of %s data", len, desc);
Packit 9795e1
    if (len >= 8)
Packit 9795e1
        DEBUG("First 8 bytes of %s: %02x %02x %02x %02x %02x %02x %02x %02x",
Packit 9795e1
              desc, data[0], data[1], data[2], data[3],
Packit 9795e1
                    data[4], data[5], data[6], data[7]);
Packit 9795e1
Packit 9795e1
    if (serialize_alloc(parser, state, pos, remain, sizeof(uint32_t) + len))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    memcpy(*pos, &len, sizeof(uint32_t));
Packit 9795e1
    *pos += sizeof(uint32_t);
Packit 9795e1
    *remain -= sizeof(uint32_t);
Packit 9795e1
Packit 9795e1
    memcpy(*pos, data, len);
Packit 9795e1
    *pos += len;
Packit 9795e1
    *remain -= len;
Packit 9795e1
Packit 9795e1
    return 0;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
/* If *data == NULL, allocs buffer dynamically, else len_in_out must contain
Packit 9795e1
   the length of the passed in buffer. */
Packit 9795e1
static int unserialize_data(struct usbredirparser_priv *parser,
Packit 9795e1
                            uint8_t **pos, uint32_t *remain,
Packit 9795e1
                            uint8_t **data, uint32_t *len_in_out,
Packit 9795e1
                            const char *desc)
Packit 9795e1
{
Packit 9795e1
    uint32_t len;
Packit 9795e1
Packit 9795e1
    if (*remain < sizeof(uint32_t)) {
Packit 9795e1
        ERROR("error buffer underrun while unserializing state");
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
    memcpy(&len, *pos, sizeof(uint32_t));
Packit 9795e1
    *pos += sizeof(uint32_t);
Packit 9795e1
    *remain -= sizeof(uint32_t);
Packit 9795e1
Packit 9795e1
    if (*remain < len) {
Packit 9795e1
        ERROR("error buffer underrun while unserializing state");
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
    if (*data == NULL && len > 0) {
Packit 9795e1
        *data = malloc(len);
Packit 9795e1
        if (!*data) {
Packit 9795e1
            ERROR("Out of memory allocating unserialize buffer");
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    } else {
Packit 9795e1
        if (*len_in_out < len) {
Packit 9795e1
            ERROR("error buffer overrun while unserializing state");
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    memcpy(*data, *pos, len);
Packit 9795e1
    *pos += len;
Packit 9795e1
    *remain -= len;
Packit 9795e1
    *len_in_out = len;
Packit 9795e1
Packit 9795e1
    DEBUG("unserialized %d bytes of %s data", len, desc);
Packit 9795e1
    if (len >= 8)
Packit 9795e1
        DEBUG("First 8 bytes of %s: %02x %02x %02x %02x %02x %02x %02x %02x",
Packit 9795e1
              desc, (*data)[0], (*data)[1], (*data)[2], (*data)[3],
Packit 9795e1
              (*data)[4], (*data)[5], (*data)[6], (*data)[7]);
Packit 9795e1
Packit 9795e1
    return 0;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_serialize(struct usbredirparser *parser_pub,
Packit 9795e1
                             uint8_t **state_dest, int *state_len)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    struct usbredirparser_buf *wbuf;
Packit 9795e1
    uint8_t *write_buf_count_pos, *state = NULL, *pos = NULL;
Packit 9795e1
    uint32_t write_buf_count = 0, len, remain = 0;
Packit 9795e1
Packit 9795e1
    *state_dest = NULL;
Packit 9795e1
    *state_len = 0;
Packit 9795e1
Packit 9795e1
    if (serialize_int(parser, &state, &pos, &remain,
Packit 9795e1
                                   USBREDIRPARSER_SERIALIZE_MAGIC, "magic"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    /* To be replaced with length later */
Packit 9795e1
    if (serialize_int(parser, &state, &pos, &remain, 0, "length"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    if (serialize_data(parser, &state, &pos, &remain,
Packit 9795e1
                       (uint8_t *)parser->our_caps,
Packit 9795e1
                       USB_REDIR_CAPS_SIZE * sizeof(int32_t), "our_caps"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    if (parser->have_peer_caps) {
Packit 9795e1
        if (serialize_data(parser, &state, &pos, &remain,
Packit 9795e1
                           (uint8_t *)parser->peer_caps,
Packit 9795e1
                           USB_REDIR_CAPS_SIZE * sizeof(int32_t), "peer_caps"))
Packit 9795e1
            return -1;
Packit 9795e1
    } else {
Packit 9795e1
        if (serialize_int(parser, &state, &pos, &remain, 0, "peer_caps_len"))
Packit 9795e1
            return -1;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    if (serialize_int(parser, &state, &pos, &remain, parser->to_skip, "skip"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    if (serialize_data(parser, &state, &pos, &remain,
Packit 9795e1
                       (uint8_t *)&parser->header, parser->header_read,
Packit 9795e1
                       "header"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    if (serialize_data(parser, &state, &pos, &remain,
Packit 9795e1
                       parser->type_header, parser->type_header_read,
Packit 9795e1
                       "type_header"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    if (serialize_data(parser, &state, &pos, &remain,
Packit 9795e1
                       parser->data, parser->data_read, "packet-data"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    write_buf_count_pos = pos;
Packit 9795e1
    /* To be replaced with write_buf_count later */
Packit 9795e1
    if (serialize_int(parser, &state, &pos, &remain, 0, "write_buf_count"))
Packit 9795e1
        return -1;
Packit 9795e1
Packit 9795e1
    wbuf = parser->write_buf;
Packit 9795e1
    while (wbuf) {
Packit 9795e1
        if (serialize_data(parser, &state, &pos, &remain,
Packit 9795e1
                           wbuf->buf + wbuf->pos, wbuf->len - wbuf->pos,
Packit 9795e1
                           "write-buf"))
Packit 9795e1
            return -1;
Packit 9795e1
        write_buf_count++;
Packit 9795e1
        wbuf = wbuf->next;
Packit 9795e1
    }
Packit 9795e1
    /* Patch in write_buf_count */
Packit 9795e1
    memcpy(write_buf_count_pos, &write_buf_count, sizeof(int32_t));
Packit 9795e1
Packit 9795e1
    /* Patch in length */
Packit 9795e1
    len = pos - state;
Packit 9795e1
    memcpy(state + sizeof(int32_t), &len, sizeof(int32_t));
Packit 9795e1
Packit 9795e1
    *state_dest = state;
Packit 9795e1
    *state_len = len;
Packit 9795e1
Packit 9795e1
    return 0;
Packit 9795e1
}
Packit 9795e1
Packit 9795e1
int usbredirparser_unserialize(struct usbredirparser *parser_pub,
Packit 9795e1
                               uint8_t *state, int len)
Packit 9795e1
{
Packit 9795e1
    struct usbredirparser_priv *parser =
Packit 9795e1
        (struct usbredirparser_priv *)parser_pub;
Packit 9795e1
    struct usbredirparser_buf *wbuf, **next;
Packit 9795e1
    uint32_t orig_caps[USB_REDIR_CAPS_SIZE];
Packit 9795e1
    uint8_t *data;
Packit 9795e1
    uint32_t i, l, header_len, remain = len;
Packit 9795e1
Packit 9795e1
    if (unserialize_int(parser, &state, &remain, &i, "magic"))
Packit 9795e1
        return -1;
Packit 9795e1
    if (i != USBREDIRPARSER_SERIALIZE_MAGIC) {
Packit 9795e1
        ERROR("error unserialize magic mismatch");
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    if (unserialize_int(parser, &state, &remain, &i, "length"))
Packit 9795e1
        return -1;
Packit 9795e1
    if (i != len) {
Packit 9795e1
        ERROR("error unserialize length mismatch");
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    data = (uint8_t *)parser->our_caps;
Packit 9795e1
    i = USB_REDIR_CAPS_SIZE * sizeof(int32_t);
Packit 9795e1
    memcpy(orig_caps, parser->our_caps, i);
Packit 9795e1
    if (unserialize_data(parser, &state, &remain, &data, &i, "our_caps"))
Packit 9795e1
        return -1;
Packit 9795e1
    for (i =0; i < USB_REDIR_CAPS_SIZE; i++) {
Packit 9795e1
        if (parser->our_caps[i] != orig_caps[i]) {
Packit 9795e1
            /* orig_caps is our original settings
Packit 9795e1
             * parser->our_caps is off the wire.
Packit 9795e1
             * We want to allow reception from an older
Packit 9795e1
             * usbredir that doesn't have all our features.
Packit 9795e1
             */
Packit 9795e1
            if (parser->our_caps[i] & ~orig_caps[i]) {
Packit 9795e1
                /* Source has a cap we don't */
Packit 9795e1
                ERROR("error unserialize caps mismatch ours: %x recv: %x",
Packit 9795e1
                      orig_caps[i], parser->our_caps[i]);
Packit 9795e1
                return -1;
Packit 9795e1
            } else {
Packit 9795e1
                /* We've got a cap the source doesn't - that's OK */
Packit 9795e1
                WARNING("unserialize missing some caps; ours: %x recv: %x",
Packit 9795e1
                      orig_caps[i], parser->our_caps[i]);
Packit 9795e1
            }
Packit 9795e1
        }
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    data = (uint8_t *)parser->peer_caps;
Packit 9795e1
    i = USB_REDIR_CAPS_SIZE * sizeof(int32_t);
Packit 9795e1
    if (unserialize_data(parser, &state, &remain, &data, &i, "peer_caps"))
Packit 9795e1
        return -1;
Packit 9795e1
    if (i)
Packit 9795e1
        parser->have_peer_caps = 1;
Packit 9795e1
Packit 9795e1
    if (unserialize_int(parser, &state, &remain, &i, "skip"))
Packit 9795e1
        return -1;
Packit 9795e1
    parser->to_skip = i;
Packit 9795e1
Packit 9795e1
    header_len = usbredirparser_get_header_len(parser_pub);
Packit 9795e1
    data = (uint8_t *)&parser->header;
Packit 9795e1
    i = header_len;
Packit 9795e1
    if (unserialize_data(parser, &state, &remain, &data, &i, "header"))
Packit 9795e1
        return -1;
Packit 9795e1
    parser->header_read = i;
Packit 9795e1
Packit 9795e1
    /* Set various length field froms the header (if we've a header) */
Packit 9795e1
    if (parser->header_read == header_len) {
Packit 9795e1
                int type_header_len =
Packit 9795e1
                    usbredirparser_get_type_header_len(parser_pub,
Packit 9795e1
                                                       parser->header.type, 0);
Packit 9795e1
                if (type_header_len < 0 ||
Packit 9795e1
                    type_header_len > sizeof(parser->type_header) ||
Packit 9795e1
                    parser->header.length < type_header_len ||
Packit 9795e1
                    (parser->header.length > type_header_len &&
Packit 9795e1
                     !usbredirparser_expect_extra_data(parser))) {
Packit 9795e1
                    ERROR("error unserialize packet header invalid");
Packit 9795e1
                    return -1;
Packit 9795e1
                }
Packit 9795e1
                parser->type_header_len = type_header_len;
Packit 9795e1
                parser->data_len = parser->header.length - type_header_len;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    data = parser->type_header;
Packit 9795e1
    i = parser->type_header_len;
Packit 9795e1
    if (unserialize_data(parser, &state, &remain, &data, &i, "type_header"))
Packit 9795e1
        return -1;
Packit 9795e1
    parser->type_header_read = i;
Packit 9795e1
Packit 9795e1
    if (parser->data_len) {
Packit 9795e1
        parser->data = malloc(parser->data_len);
Packit 9795e1
        if (!parser->data) {
Packit 9795e1
            ERROR("Out of memory allocating unserialize buffer");
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
    }
Packit 9795e1
    i = parser->data_len;
Packit 9795e1
    if (unserialize_data(parser, &state, &remain, &parser->data, &i, "data"))
Packit 9795e1
        return -1;
Packit 9795e1
    parser->data_read = i;
Packit 9795e1
Packit 9795e1
    /* Get the write buffer count and the write buffers */
Packit 9795e1
    if (unserialize_int(parser, &state, &remain, &i, "write_buf_count"))
Packit 9795e1
        return -1;
Packit 9795e1
    next = &parser->write_buf;
Packit 9795e1
    while (i) {
Packit 9795e1
        wbuf = calloc(1, sizeof(*wbuf));
Packit 9795e1
        if (!wbuf) {
Packit 9795e1
            ERROR("Out of memory allocating unserialize buffer");
Packit 9795e1
            return -1;
Packit 9795e1
        }
Packit 9795e1
        *next = wbuf;
Packit 9795e1
        l = 0;
Packit 9795e1
        if (unserialize_data(parser, &state, &remain, &wbuf->buf, &l, "wbuf"))
Packit 9795e1
            return -1;
Packit 9795e1
        wbuf->len = l;
Packit 9795e1
        next = &wbuf->next;
Packit 9795e1
        i--;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    if (remain) {
Packit 9795e1
        ERROR("error unserialize %d bytes of extraneous state data", remain);
Packit 9795e1
        return -1;
Packit 9795e1
    }
Packit 9795e1
Packit 9795e1
    return 0;
Packit 9795e1
}