static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,

                                 struct iovec *iov, unsigned int iov_cnt)

{

    struct virtio_net_ctrl_mac mac_data;

    size_t s;

    NetClientState *nc = qemu_get_queue(n->nic);



    if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {

        if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {

            return VIRTIO_NET_ERR;

        }

        s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));

        assert(s == sizeof(n->mac));

        qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);

        rxfilter_notify(nc);



        return VIRTIO_NET_OK;

    }



    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {

        return VIRTIO_NET_ERR;

    }



    int in_use = 0;

    int first_multi = 0;

    uint8_t uni_overflow = 0;

    uint8_t multi_overflow = 0;

    uint8_t *macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);



    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,

                   sizeof(mac_data.entries));

    mac_data.entries = ldl_p(&mac_data.entries);

    if (s != sizeof(mac_data.entries)) {

        goto error;

    }

    iov_discard_front(&iov, &iov_cnt, s);



    if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) {

        goto error;

    }



    if (mac_data.entries <= MAC_TABLE_ENTRIES) {

        s = iov_to_buf(iov, iov_cnt, 0, macs,

                       mac_data.entries * ETH_ALEN);

        if (s != mac_data.entries * ETH_ALEN) {

            goto error;

        }

        in_use += mac_data.entries;

    } else {

        uni_overflow = 1;

    }



    iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN);



    first_multi = in_use;



    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,

                   sizeof(mac_data.entries));

    mac_data.entries = ldl_p(&mac_data.entries);

    if (s != sizeof(mac_data.entries)) {

        goto error;

    }



    iov_discard_front(&iov, &iov_cnt, s);



    if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) {

        goto error;

    }



    if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {

        s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],

                       mac_data.entries * ETH_ALEN);

        if (s != mac_data.entries * ETH_ALEN) {

            goto error;

        }

        in_use += mac_data.entries;

    } else {

        multi_overflow = 1;

    }



    n->mac_table.in_use = in_use;

    n->mac_table.first_multi = first_multi;

    n->mac_table.uni_overflow = uni_overflow;

    n->mac_table.multi_overflow = multi_overflow;

    memcpy(n->mac_table.macs, macs, MAC_TABLE_ENTRIES * ETH_ALEN);

    g_free(macs);

    rxfilter_notify(nc);



    return VIRTIO_NET_OK;



error:

    g_free(macs);

    return VIRTIO_NET_ERR;

}

static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,

                                 struct iovec *iov, unsigned int iov_cnt)

{

    struct virtio_net_ctrl_mac mac_data;

    size_t s;

    NetClientState *nc = qemu_get_queue(n->nic);



    if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {

        if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {

            return VIRTIO_NET_ERR;

        }

        s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));

        assert(s == sizeof(n->mac));

        qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);

        rxfilter_notify(nc);



        return VIRTIO_NET_OK;

    }



    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {

        return VIRTIO_NET_ERR;

    }



    int in_use = 0;

    int first_multi = 0;

    uint8_t uni_overflow = 0;

    uint8_t multi_overflow = 0;

    uint8_t *macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);



    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,

                   sizeof(mac_data.entries));

    mac_data.entries = ldl_p(&mac_data.entries);

    if (s != sizeof(mac_data.entries)) {

        goto error;

    }

    iov_discard_front(&iov, &iov_cnt, s);



    if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) {

        goto error;

    }



    if (mac_data.entries <= MAC_TABLE_ENTRIES) {

        s = iov_to_buf(iov, iov_cnt, 0, macs,

                       mac_data.entries * ETH_ALEN);

        if (s != mac_data.entries * ETH_ALEN) {

            goto error;

        }

        in_use += mac_data.entries;

    } else {

        uni_overflow = 1;

    }



    iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN);



    first_multi = in_use;



    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,

                   sizeof(mac_data.entries));

    mac_data.entries = ldl_p(&mac_data.entries);

    if (s != sizeof(mac_data.entries)) {

        goto error;

    }



    iov_discard_front(&iov, &iov_cnt, s);



    if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) {

        goto error;

    }



    if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {

        s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],

                       mac_data.entries * ETH_ALEN);

        if (s != mac_data.entries * ETH_ALEN) {

            goto error;

        }

        in_use += mac_data.entries;

    } else {

        multi_overflow = 1;

    }



    n->mac_table.in_use = in_use;

    n->mac_table.first_multi = first_multi;

    n->mac_table.uni_overflow = uni_overflow;

    n->mac_table.multi_overflow = multi_overflow;

    memcpy(n->mac_table.macs, macs, MAC_TABLE_ENTRIES * ETH_ALEN);

    g_free(macs);

    rxfilter_notify(nc);



    return VIRTIO_NET_OK;



error:

    g_free(macs);

    return VIRTIO_NET_ERR;

}

    if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
static int FUNC_0(VirtIONet *VAR_0, uint8_t VAR_1,

                                 struct iovec *VAR_2, unsigned int VAR_3)

{

    struct virtio_net_ctrl_mac VAR_4;

    size_t s;

    NetClientState *nc = qemu_get_queue(VAR_0->nic);



    if (VAR_1 == VIRTIO_NET_CTRL_MAC_ADDR_SET) {

        if (iov_size(VAR_2, VAR_3) != sizeof(VAR_0->mac)) {

            return VIRTIO_NET_ERR;

        }

        s = iov_to_buf(VAR_2, VAR_3, 0, &VAR_0->mac, sizeof(VAR_0->mac));

        assert(s == sizeof(VAR_0->mac));

        qemu_format_nic_info_str(qemu_get_queue(VAR_0->nic), VAR_0->mac);

        rxfilter_notify(nc);



        return VIRTIO_NET_OK;

    }



    if (VAR_1 != VIRTIO_NET_CTRL_MAC_TABLE_SET) {

        return VIRTIO_NET_ERR;

    }



    int VAR_5 = 0;

    int VAR_6 = 0;

    uint8_t uni_overflow = 0;

    uint8_t multi_overflow = 0;

    uint8_t *macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);



    s = iov_to_buf(VAR_2, VAR_3, 0, &VAR_4.entries,

                   sizeof(VAR_4.entries));

    VAR_4.entries = ldl_p(&VAR_4.entries);

    if (s != sizeof(VAR_4.entries)) {

        goto error;

    }

    iov_discard_front(&VAR_2, &VAR_3, s);



    if (VAR_4.entries * ETH_ALEN > iov_size(VAR_2, VAR_3)) {

        goto error;

    }



    if (VAR_4.entries <= MAC_TABLE_ENTRIES) {

        s = iov_to_buf(VAR_2, VAR_3, 0, macs,

                       VAR_4.entries * ETH_ALEN);

        if (s != VAR_4.entries * ETH_ALEN) {

            goto error;

        }

        VAR_5 += VAR_4.entries;

    } else {

        uni_overflow = 1;

    }



    iov_discard_front(&VAR_2, &VAR_3, VAR_4.entries * ETH_ALEN);



    VAR_6 = VAR_5;



    s = iov_to_buf(VAR_2, VAR_3, 0, &VAR_4.entries,

                   sizeof(VAR_4.entries));

    VAR_4.entries = ldl_p(&VAR_4.entries);

    if (s != sizeof(VAR_4.entries)) {

        goto error;

    }



    iov_discard_front(&VAR_2, &VAR_3, s);



    if (VAR_4.entries * ETH_ALEN != iov_size(VAR_2, VAR_3)) {

        goto error;

    }



    if (VAR_5 + VAR_4.entries <= MAC_TABLE_ENTRIES) {

        s = iov_to_buf(VAR_2, VAR_3, 0, &macs[VAR_5 * ETH_ALEN],

                       VAR_4.entries * ETH_ALEN);

        if (s != VAR_4.entries * ETH_ALEN) {

            goto error;

        }

        VAR_5 += VAR_4.entries;

    } else {

        multi_overflow = 1;

    }



    VAR_0->mac_table.VAR_5 = VAR_5;

    VAR_0->mac_table.VAR_6 = VAR_6;

    VAR_0->mac_table.uni_overflow = uni_overflow;

    VAR_0->mac_table.multi_overflow = multi_overflow;

    memcpy(VAR_0->mac_table.macs, macs, MAC_TABLE_ENTRIES * ETH_ALEN);

    g_free(macs);

    rxfilter_notify(nc);



    return VIRTIO_NET_OK;



error:

    g_free(macs);

    return VIRTIO_NET_ERR;

}

static int FUNC_0(VirtIONet *VAR_0, uint8_t VAR_1,
struct iovec *VAR_2, unsigned int VAR_3)
{ struct virtio_net_ctrl_mac VAR_4; size_t s; NetClientState *nc = qemu_get_queue(VAR_0->nic); if (VAR_1 == VIRTIO_NET_CTRL_MAC_ADDR_SET) { if (iov_size(VAR_2, VAR_3) != sizeof(VAR_0->mac)) { return VIRTIO_NET_ERR; } s = iov_to_buf(VAR_2, VAR_3, 0, &VAR_0->mac, sizeof(VAR_0->mac)); assert(s == sizeof(VAR_0->mac)); qemu_format_nic_info_str(qemu_get_queue(VAR_0->nic), VAR_0->mac); rxfilter_notify(nc); return VIRTIO_NET_OK; } if (VAR_1 != VIRTIO_NET_CTRL_MAC_TABLE_SET) { return VIRTIO_NET_ERR; } int VAR_5 = 0; int VAR_6 = 0; uint8_t uni_overflow = 0; uint8_t multi_overflow = 0; uint8_t *macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); s = iov_to_buf(VAR_2, VAR_3, 0, &VAR_4.entries,
sizeof(VAR_4.entries)); VAR_4.entries = ldl_p(&VAR_4.entries); if (s != sizeof(VAR_4.entries)) { goto error; } iov_discard_front(&VAR_2, &VAR_3, s); if (VAR_4.entries * ETH_ALEN > iov_size(VAR_2, VAR_3)) { goto error; } if (VAR_4.entries <= MAC_TABLE_ENTRIES) { s = iov_to_buf(VAR_2, VAR_3, 0, macs,
VAR_4.entries * ETH_ALEN); if (s != VAR_4.entries * ETH_ALEN) { goto error; } VAR_5 += VAR_4.entries; } else { uni_overflow = 1; } iov_discard_front(&VAR_2, &VAR_3, VAR_4.entries * ETH_ALEN); VAR_6 = VAR_5; s = iov_to_buf(VAR_2, VAR_3, 0, &VAR_4.entries,
sizeof(VAR_4.entries)); VAR_4.entries = ldl_p(&VAR_4.entries); if (s != sizeof(VAR_4.entries)) { goto error; } iov_discard_front(&VAR_2, &VAR_3, s); if (VAR_4.entries * ETH_ALEN != iov_size(VAR_2, VAR_3)) { goto error; } if (VAR_5 + VAR_4.entries <= MAC_TABLE_ENTRIES) { s = iov_to_buf(VAR_2, VAR_3, 0, &macs[VAR_5 * ETH_ALEN],
VAR_4.entries * ETH_ALEN); if (s != VAR_4.entries * ETH_ALEN) { goto error; } VAR_5 += VAR_4.entries; } else { multi_overflow = 1; } VAR_0->mac_table.VAR_5 = VAR_5; VAR_0->mac_table.VAR_6 = VAR_6; VAR_0->mac_table.uni_overflow = uni_overflow; VAR_0->mac_table.multi_overflow = multi_overflow; memcpy(VAR_0->mac_table.macs, macs, MAC_TABLE_ENTRIES * ETH_ALEN); g_free(macs); rxfilter_notify(nc); return VIRTIO_NET_OK; error:
g_free(macs); return VIRTIO_NET_ERR; }