static int nbd_negotiate_options(NBDClient *client)

{

    uint32_t flags;

    bool fixedNewstyle = false;



    /* Client sends:

        [ 0 ..   3]   client flags



        [ 0 ..   7]   NBD_OPTS_MAGIC

        [ 8 ..  11]   NBD option

        [12 ..  15]   Data length

        ...           Rest of request



        [ 0 ..   7]   NBD_OPTS_MAGIC

        [ 8 ..  11]   Second NBD option

        [12 ..  15]   Data length

        ...           Rest of request

    */



    if (nbd_negotiate_read(client->ioc, &flags, sizeof(flags)) !=

        sizeof(flags)) {

        LOG("read failed");

        return -EIO;

    }

    TRACE("Checking client flags");

    be32_to_cpus(&flags);

    if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {

        TRACE("Client supports fixed newstyle handshake");

        fixedNewstyle = true;

        flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;

    }

    if (flags != 0) {

        TRACE("Unknown client flags 0x%" PRIx32 " received", flags);

        return -EIO;

    }



    while (1) {

        int ret;

        uint32_t clientflags, length;

        uint64_t magic;



        if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=

            sizeof(magic)) {

            LOG("read failed");

            return -EINVAL;

        }

        TRACE("Checking opts magic");

        if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {

            LOG("Bad magic received");

            return -EINVAL;

        }



        if (nbd_negotiate_read(client->ioc, &clientflags,

                               sizeof(clientflags)) != sizeof(clientflags)) {

            LOG("read failed");

            return -EINVAL;

        }

        clientflags = be32_to_cpu(clientflags);



        if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=

            sizeof(length)) {

            LOG("read failed");

            return -EINVAL;

        }

        length = be32_to_cpu(length);



        TRACE("Checking option 0x%" PRIx32, clientflags);

        if (client->tlscreds &&

            client->ioc == (QIOChannel *)client->sioc) {

            QIOChannel *tioc;

            if (!fixedNewstyle) {

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                return -EINVAL;

            }

            switch (clientflags) {

            case NBD_OPT_STARTTLS:

                tioc = nbd_negotiate_handle_starttls(client, length);

                if (!tioc) {

                    return -EIO;

                }

                object_unref(OBJECT(client->ioc));

                client->ioc = QIO_CHANNEL(tioc);

                break;



            case NBD_OPT_EXPORT_NAME:

                /* No way to return an error to client, so drop connection */

                TRACE("Option 0x%x not permitted before TLS", clientflags);

                return -EINVAL;



            default:

                TRACE("Option 0x%" PRIx32 " not permitted before TLS",

                      clientflags);

                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {

                    return -EIO;

                }

                nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_TLS_REQD,

                                       clientflags);

                break;

            }

        } else if (fixedNewstyle) {

            switch (clientflags) {

            case NBD_OPT_LIST:

                ret = nbd_negotiate_handle_list(client, length);

                if (ret < 0) {

                    return ret;

                }

                break;



            case NBD_OPT_ABORT:

                return -EINVAL;



            case NBD_OPT_EXPORT_NAME:

                return nbd_negotiate_handle_export_name(client, length);



            case NBD_OPT_STARTTLS:

                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {

                    return -EIO;

                }

                if (client->tlscreds) {

                    TRACE("TLS already enabled");

                    nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_INVALID,

                                           clientflags);

                } else {

                    TRACE("TLS not configured");

                    nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_POLICY,

                                           clientflags);

                }

                break;

            default:

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {

                    return -EIO;

                }

                nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP,

                                       clientflags);

                break;

            }

        } else {

            /*

             * If broken new-style we should drop the connection

             * for anything except NBD_OPT_EXPORT_NAME

             */

            switch (clientflags) {

            case NBD_OPT_EXPORT_NAME:

                return nbd_negotiate_handle_export_name(client, length);



            default:

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                return -EINVAL;

            }

        }

    }

}

static int nbd_negotiate_options(NBDClient *client)

{

    uint32_t flags;

    bool fixedNewstyle = false;



    



























    if (nbd_negotiate_read(client->ioc, &flags, sizeof(flags)) !=

        sizeof(flags)) {

        LOG("read failed");

        return -EIO;

    }

    TRACE("Checking client flags");

    be32_to_cpus(&flags);

    if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {

        TRACE("Client supports fixed newstyle handshake");

        fixedNewstyle = true;

        flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;

    }

    if (flags != 0) {

        TRACE("Unknown client flags 0x%" PRIx32 " received", flags);

        return -EIO;

    }



    while (1) {

        int ret;

        uint32_t clientflags, length;

        uint64_t magic;



        if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=

            sizeof(magic)) {

            LOG("read failed");

            return -EINVAL;

        }

        TRACE("Checking opts magic");

        if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {

            LOG("Bad magic received");

            return -EINVAL;

        }



        if (nbd_negotiate_read(client->ioc, &clientflags,

                               sizeof(clientflags)) != sizeof(clientflags)) {

            LOG("read failed");

            return -EINVAL;

        }

        clientflags = be32_to_cpu(clientflags);



        if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=

            sizeof(length)) {

            LOG("read failed");

            return -EINVAL;

        }

        length = be32_to_cpu(length);



        TRACE("Checking option 0x%" PRIx32, clientflags);

        if (client->tlscreds &&

            client->ioc == (QIOChannel *)client->sioc) {

            QIOChannel *tioc;

            if (!fixedNewstyle) {

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                return -EINVAL;

            }

            switch (clientflags) {

            case NBD_OPT_STARTTLS:

                tioc = nbd_negotiate_handle_starttls(client, length);

                if (!tioc) {

                    return -EIO;

                }

                object_unref(OBJECT(client->ioc));

                client->ioc = QIO_CHANNEL(tioc);

                break;



            case NBD_OPT_EXPORT_NAME:

                

                TRACE("Option 0x%x not permitted before TLS", clientflags);

                return -EINVAL;



            default:

                TRACE("Option 0x%" PRIx32 " not permitted before TLS",

                      clientflags);

                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {

                    return -EIO;

                }

                nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_TLS_REQD,

                                       clientflags);

                break;

            }

        } else if (fixedNewstyle) {

            switch (clientflags) {

            case NBD_OPT_LIST:

                ret = nbd_negotiate_handle_list(client, length);

                if (ret < 0) {

                    return ret;

                }

                break;



            case NBD_OPT_ABORT:

                return -EINVAL;



            case NBD_OPT_EXPORT_NAME:

                return nbd_negotiate_handle_export_name(client, length);



            case NBD_OPT_STARTTLS:

                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {

                    return -EIO;

                }

                if (client->tlscreds) {

                    TRACE("TLS already enabled");

                    nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_INVALID,

                                           clientflags);

                } else {

                    TRACE("TLS not configured");

                    nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_POLICY,

                                           clientflags);

                }

                break;

            default:

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {

                    return -EIO;

                }

                nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP,

                                       clientflags);

                break;

            }

        } else {

            







            switch (clientflags) {

            case NBD_OPT_EXPORT_NAME:

                return nbd_negotiate_handle_export_name(client, length);



            default:

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                return -EINVAL;

            }

        }

    }

}

                nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_TLS_REQD,                                        clientflags);                     nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_INVALID,                                            clientflags);                     nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_POLICY,                                            clientflags);                 nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP,                                        clientflags);
static int FUNC_0(NBDClient *VAR_0)

{

    uint32_t flags;

    bool fixedNewstyle = false;



    



























    if (nbd_negotiate_read(VAR_0->ioc, &flags, sizeof(flags)) !=

        sizeof(flags)) {

        LOG("read failed");

        return -EIO;

    }

    TRACE("Checking VAR_0 flags");

    be32_to_cpus(&flags);

    if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {

        TRACE("Client supports fixed newstyle handshake");

        fixedNewstyle = true;

        flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;

    }

    if (flags != 0) {

        TRACE("Unknown VAR_0 flags 0x%" PRIx32 " received", flags);

        return -EIO;

    }



    while (1) {

        int VAR_1;

        uint32_t clientflags, length;

        uint64_t magic;



        if (nbd_negotiate_read(VAR_0->ioc, &magic, sizeof(magic)) !=

            sizeof(magic)) {

            LOG("read failed");

            return -EINVAL;

        }

        TRACE("Checking opts magic");

        if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {

            LOG("Bad magic received");

            return -EINVAL;

        }



        if (nbd_negotiate_read(VAR_0->ioc, &clientflags,

                               sizeof(clientflags)) != sizeof(clientflags)) {

            LOG("read failed");

            return -EINVAL;

        }

        clientflags = be32_to_cpu(clientflags);



        if (nbd_negotiate_read(VAR_0->ioc, &length, sizeof(length)) !=

            sizeof(length)) {

            LOG("read failed");

            return -EINVAL;

        }

        length = be32_to_cpu(length);



        TRACE("Checking option 0x%" PRIx32, clientflags);

        if (VAR_0->tlscreds &&

            VAR_0->ioc == (QIOChannel *)VAR_0->sioc) {

            QIOChannel *tioc;

            if (!fixedNewstyle) {

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                return -EINVAL;

            }

            switch (clientflags) {

            case NBD_OPT_STARTTLS:

                tioc = nbd_negotiate_handle_starttls(VAR_0, length);

                if (!tioc) {

                    return -EIO;

                }

                object_unref(OBJECT(VAR_0->ioc));

                VAR_0->ioc = QIO_CHANNEL(tioc);

                break;



            case NBD_OPT_EXPORT_NAME:

                

                TRACE("Option 0x%x not permitted before TLS", clientflags);

                return -EINVAL;



            default:

                TRACE("Option 0x%" PRIx32 " not permitted before TLS",

                      clientflags);

                if (nbd_negotiate_drop_sync(VAR_0->ioc, length) != length) {

                    return -EIO;

                }

                nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_TLS_REQD,

                                       clientflags);

                break;

            }

        } else if (fixedNewstyle) {

            switch (clientflags) {

            case NBD_OPT_LIST:

                VAR_1 = nbd_negotiate_handle_list(VAR_0, length);

                if (VAR_1 < 0) {

                    return VAR_1;

                }

                break;



            case NBD_OPT_ABORT:

                return -EINVAL;



            case NBD_OPT_EXPORT_NAME:

                return nbd_negotiate_handle_export_name(VAR_0, length);



            case NBD_OPT_STARTTLS:

                if (nbd_negotiate_drop_sync(VAR_0->ioc, length) != length) {

                    return -EIO;

                }

                if (VAR_0->tlscreds) {

                    TRACE("TLS already enabled");

                    nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_INVALID,

                                           clientflags);

                } else {

                    TRACE("TLS not configured");

                    nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_POLICY,

                                           clientflags);

                }

                break;

            default:

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                if (nbd_negotiate_drop_sync(VAR_0->ioc, length) != length) {

                    return -EIO;

                }

                nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_UNSUP,

                                       clientflags);

                break;

            }

        } else {

            







            switch (clientflags) {

            case NBD_OPT_EXPORT_NAME:

                return nbd_negotiate_handle_export_name(VAR_0, length);



            default:

                TRACE("Unsupported option 0x%" PRIx32, clientflags);

                return -EINVAL;

            }

        }

    }

}

static int FUNC_0(NBDClient *VAR_0)
{ uint32_t flags; bool fixedNewstyle = false; if (nbd_negotiate_read(VAR_0->ioc, &flags, sizeof(flags)) !=
sizeof(flags)) { LOG("read failed"); return -EIO; } TRACE("Checking VAR_0 flags"); be32_to_cpus(&flags); if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) { TRACE("Client supports fixed newstyle handshake"); fixedNewstyle = true; flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE; } if (flags != 0) { TRACE("Unknown VAR_0 flags 0x%" PRIx32 " received", flags); return -EIO; } while (1) { int VAR_1; uint32_t clientflags, length; uint64_t magic; if (nbd_negotiate_read(VAR_0->ioc, &magic, sizeof(magic)) !=
sizeof(magic)) { LOG("read failed"); return -EINVAL; } TRACE("Checking opts magic"); if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) { LOG("Bad magic received"); return -EINVAL; } if (nbd_negotiate_read(VAR_0->ioc, &clientflags,
sizeof(clientflags)) != sizeof(clientflags)) { LOG("read failed"); return -EINVAL; } clientflags = be32_to_cpu(clientflags); if (nbd_negotiate_read(VAR_0->ioc, &length, sizeof(length)) !=
sizeof(length)) { LOG("read failed"); return -EINVAL; } length = be32_to_cpu(length); TRACE("Checking option 0x%" PRIx32, clientflags); if (VAR_0->tlscreds &&
VAR_0->ioc == (QIOChannel *)VAR_0->sioc) { QIOChannel *tioc; if (!fixedNewstyle) { TRACE("Unsupported option 0x%" PRIx32, clientflags); return -EINVAL; } switch (clientflags) { case NBD_OPT_STARTTLS:
tioc = nbd_negotiate_handle_starttls(VAR_0, length); if (!tioc) { return -EIO; } object_unref(OBJECT(VAR_0->ioc)); VAR_0->ioc = QIO_CHANNEL(tioc); break; case NBD_OPT_EXPORT_NAME:
TRACE("Option 0x%x not permitted before TLS", clientflags); return -EINVAL; default:
TRACE("Option 0x%" PRIx32 " not permitted before TLS",
clientflags); if (nbd_negotiate_drop_sync(VAR_0->ioc, length) != length) { return -EIO; } nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_TLS_REQD,
clientflags); break; } } else if (fixedNewstyle) { switch (clientflags) { case NBD_OPT_LIST:
VAR_1 = nbd_negotiate_handle_list(VAR_0, length); if (VAR_1 < 0) { return VAR_1; } break; case NBD_OPT_ABORT:
return -EINVAL; case NBD_OPT_EXPORT_NAME:
return nbd_negotiate_handle_export_name(VAR_0, length); case NBD_OPT_STARTTLS:
if (nbd_negotiate_drop_sync(VAR_0->ioc, length) != length) { return -EIO; } if (VAR_0->tlscreds) { TRACE("TLS already enabled"); nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_INVALID,
clientflags); } else { TRACE("TLS not configured"); nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_POLICY,
clientflags); } break; default:
TRACE("Unsupported option 0x%" PRIx32, clientflags); if (nbd_negotiate_drop_sync(VAR_0->ioc, length) != length) { return -EIO; } nbd_negotiate_send_rep(VAR_0->ioc, NBD_REP_ERR_UNSUP,
clientflags); break; } } else { switch (clientflags) { case NBD_OPT_EXPORT_NAME:
return nbd_negotiate_handle_export_name(VAR_0, length); default:
TRACE("Unsupported option 0x%" PRIx32, clientflags); return -EINVAL; } } } }