openbmc/build/tmp/deploy/sdk/witherspoon-2019-08-08/sysroots/armv6-openbmc-linux-gnueabi/usr/src/debug/nbd/3.19-r0/nbd-3.19/nbd-server.c
CLIENT* negotiate(int net, GArray* servers, struct generic_conf* genconf)
{
    uint16_t smallflags = NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES;
    uint64_t magic;
    uint32_t cflags = 0;
    uint32_t opt;
    CLIENT* client = g_new0(CLIENT, 1);
    client->net = net;
    client->socket_read = socket_read_notls;
    client->socket_write = socket_write_notls;
    client->socket_closed = socket_closed_negotiate;

    assert(servers != NULL);
    socket_write(client, INIT_PASSWD, 8);
    magic = htonll(opts_magic);
    socket_write(client, &magic, sizeof(magic));

    smallflags = htons(smallflags);
    socket_write(client, &smallflags, sizeof(uint16_t));
    socket_read(client, &cflags, sizeof(cflags));
    cflags = htonl(cflags);
    if (cflags & NBD_FLAG_C_NO_ZEROES)
    {
        glob_flags |= F_NO_ZEROES;
    }
    do
    {
        socket_read(client, &magic, sizeof(magic));
        magic = ntohll(magic);
        if (magic != opts_magic)
        {
            err_nonfatal("Negotiation failed/5a: magic mismatch");
            goto handler_err;
        }
        socket_read(client, &opt, sizeof(opt));
        opt = ntohl(opt);
        if (client->tls_session == NULL && glob_flags & F_FORCEDTLS &&
            opt != NBD_OPT_STARTTLS)
        {
            if (opt == NBD_OPT_EXPORT_NAME)
            {
                // can't send an error message for EXPORT_NAME,
                // so must do hard close
                goto handler_err;
            }
            if (opt == NBD_OPT_ABORT)
            {
                // handled below
                break;
            }
            consume_len(client);
            send_reply(client, opt, NBD_REP_ERR_TLS_REQD, -1,
                       "TLS is required on this server");
            continue;
        }
        switch (opt)
        {
            case NBD_OPT_EXPORT_NAME:
                // NBD_OPT_EXPORT_NAME must be the last
                // selected option, so return from here
                // if that is chosen.
                if (handle_export_name(client, opt, servers, cflags) != NULL)
                {
                    return client;
                }
                else
                {
                    goto handler_err;
                }
                break;
            case NBD_OPT_LIST:
                handle_list(client, opt, servers, cflags);
                break;
            case NBD_OPT_ABORT:
                // handled below
                break;
            case NBD_OPT_STARTTLS:
#if !HAVE_GNUTLS
                consume_len(client);
                send_reply(client, opt, NBD_REP_ERR_PLATFORM, -1,
                           "This nbd-server was compiled without TLS support");
#else
                if (client->tls_session != NULL)
                {
                    consume_len(client);
                    send_reply(client, opt, NBD_REP_ERR_INVALID, -1,
                               "Invalid STARTTLS request: TLS has already been "
                               "negotiated!");
                    continue;
                }
                if (genconf->keyfile == NULL)
                {
                    consume_len(client);
                    send_reply(client, opt, NBD_REP_ERR_POLICY, -1,
                               "TLS not allowed on this server");
                    continue;
                }
                if (handle_starttls(client, opt, servers, cflags, genconf) ==
                    NULL)
                {
                    // can't recover from failed TLS negotiation.
                    goto handler_err;
                }
#endif
                break;
            case NBD_OPT_GO:
            case NBD_OPT_INFO:
                if (handle_info(client, opt, servers, cflags) &&
                    opt == NBD_OPT_GO)
                {
                    return client;
                }
                break;
            default:
                consume_len(client);
                send_reply(client, opt, NBD_REP_ERR_UNSUP, -1,
                           "The given option is unknown to this server "
                           "implementation");
                break;
        }
    } while ((opt != NBD_OPT_EXPORT_NAME) && (opt != NBD_OPT_ABORT));
    if (opt == NBD_OPT_ABORT)
    {
        err_nonfatal("Session terminated by client");
        goto handler_err;
    }
    err_nonfatal(
        "Weird things happened: reached end of negotiation without success");
handler_err:
    g_free(client);
    return NULL;
}
/**
 * Do the initial negotiation.
 *
 * @param net The socket we're doing the negotiation over.
 * @param servers The array of known servers.
 * @param genconf the global options (needed for accessing TLS config data)
 **/
Do the initial negotiation.
@param net The socket we're doing the negotiation over.
@param servers The array of known servers.
@param genconf the global options (needed for accessing TLS config data)
Do the initial negotiation . @param net The socket we ' re doing the negotiation over . @param servers The array of known servers . @param genconf the global options ( needed for accessing TLS config data )
CLIENT* negotiate(int net, GArray* servers, struct generic_conf* genconf)
{
    uint16_t smallflags = NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES;
    uint64_t magic;
    uint32_t cflags = 0;
    uint32_t opt;
    CLIENT* client = g_new0(CLIENT, 1);
    client->net = net;
    client->socket_read = socket_read_notls;
    client->socket_write = socket_write_notls;
    client->socket_closed = socket_closed_negotiate;
    assert(servers != NULL);
    socket_write(client, INIT_PASSWD, 8);
    magic = htonll(opts_magic);
    socket_write(client, &magic, sizeof(magic));
    smallflags = htons(smallflags);
    socket_write(client, &smallflags, sizeof(uint16_t));
    socket_read(client, &cflags, sizeof(cflags));
    cflags = htonl(cflags);
    if (cflags & NBD_FLAG_C_NO_ZEROES)
    {
        glob_flags |= F_NO_ZEROES;
    }
    do
    {
        socket_read(client, &magic, sizeof(magic));
        magic = ntohll(magic);
        if (magic != opts_magic)
        {
            err_nonfatal("Negotiation failed/5a: magic mismatch");
            goto handler_err;
        }
        socket_read(client, &opt, sizeof(opt));
        opt = ntohl(opt);
        if (client->tls_session == NULL && glob_flags & F_FORCEDTLS &&
            opt != NBD_OPT_STARTTLS)
        {
            if (opt == NBD_OPT_EXPORT_NAME)
            {
                goto handler_err;
            }
            if (opt == NBD_OPT_ABORT)
            {
                break;
            }
            consume_len(client);
            send_reply(client, opt, NBD_REP_ERR_TLS_REQD, -1,
                       "TLS is required on this server");
            continue;
        }
        switch (opt)
        {
            case NBD_OPT_EXPORT_NAME:
                if (handle_export_name(client, opt, servers, cflags) != NULL)
                {
                    return client;
                }
                else
                {
                    goto handler_err;
                }
                break;
            case NBD_OPT_LIST:
                handle_list(client, opt, servers, cflags);
                break;
            case NBD_OPT_ABORT:
                break;
            case NBD_OPT_STARTTLS:
#if !HAVE_GNUTLS
                consume_len(client);
                send_reply(client, opt, NBD_REP_ERR_PLATFORM, -1,
                           "This nbd-server was compiled without TLS support");
#else
                if (client->tls_session != NULL)
                {
                    consume_len(client);
                    send_reply(client, opt, NBD_REP_ERR_INVALID, -1,
                               "Invalid STARTTLS request: TLS has already been "
                               "negotiated!");
                    continue;
                }
                if (genconf->keyfile == NULL)
                {
                    consume_len(client);
                    send_reply(client, opt, NBD_REP_ERR_POLICY, -1,
                               "TLS not allowed on this server");
                    continue;
                }
                if (handle_starttls(client, opt, servers, cflags, genconf) ==
                    NULL)
                {
                    goto handler_err;
                }
#endif
                break;
            case NBD_OPT_GO:
            case NBD_OPT_INFO:
                if (handle_info(client, opt, servers, cflags) &&
                    opt == NBD_OPT_GO)
                {
                    return client;
                }
                break;
            default:
                consume_len(client);
                send_reply(client, opt, NBD_REP_ERR_UNSUP, -1,
                           "The given option is unknown to this server "
                           "implementation");
                break;
        }
    } while ((opt != NBD_OPT_EXPORT_NAME) && (opt != NBD_OPT_ABORT));
    if (opt == NBD_OPT_ABORT)
    {
        err_nonfatal("Session terminated by client");
        goto handler_err;
    }
    err_nonfatal(
        "Weird things happened: reached end of negotiation without success");
handler_err:
    g_free(client);
    return NULL;
}
CLIENT * negotiate ( int net , GArray * servers , struct generic_conf * genconf ) { uint16_t smallflags = NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES ; uint64_t magic ; uint32_t cflags = 0 ; uint32_t opt ; CLIENT * client = g_new0 ( CLIENT , 1 ) ; client -> net = net ; client -> socket_read = socket_read_notls ; client -> socket_write = socket_write_notls ; client -> socket_closed = socket_closed_negotiate ; assert ( servers != NULL ) ; socket_write ( client , INIT_PASSWD , 8 ) ; magic = htonll ( opts_magic ) ; socket_write ( client , & magic , sizeof ( magic ) ) ; smallflags = htons ( smallflags ) ; socket_write ( client , & smallflags , sizeof ( uint16_t ) ) ; socket_read ( client , & cflags , sizeof ( cflags ) ) ; cflags = htonl ( cflags ) ; if ( cflags & NBD_FLAG_C_NO_ZEROES ) { glob_flags |= F_NO_ZEROES ; } do { socket_read ( client , & magic , sizeof ( magic ) ) ; magic = ntohll ( magic ) ; if ( magic != opts_magic ) { err_nonfatal ( " " ) ; goto handler_err ; } socket_read ( client , & opt , sizeof ( opt ) ) ; opt = ntohl ( opt ) ; if ( client -> tls_session == NULL && glob_flags & F_FORCEDTLS && opt != NBD_OPT_STARTTLS ) { if ( opt == NBD_OPT_EXPORT_NAME ) { goto handler_err ; } if ( opt == NBD_OPT_ABORT ) { break ; } consume_len ( client ) ; send_reply ( client , opt , NBD_REP_ERR_TLS_REQD , -1 , " " ) ; continue ; } switch ( opt ) { case NBD_OPT_EXPORT_NAME : if ( handle_export_name ( client , opt , servers , cflags ) != NULL ) { return client ; } else { goto handler_err ; } break ; case NBD_OPT_LIST : handle_list ( client , opt , servers , cflags ) ; break ; case NBD_OPT_ABORT : break ; case NBD_OPT_STARTTLS : #if ! HAVE_GNUTLS consume_len ( client ) ; send_reply ( client , opt , NBD_REP_ERR_PLATFORM , -1 , " " ) ; #else if ( client -> tls_session != NULL ) { consume_len ( client ) ; send_reply ( client , opt , NBD_REP_ERR_INVALID , -1 , " " " " ) ; continue ; } if ( genconf -> keyfile == NULL ) { consume_len ( client ) ; send_reply ( client , opt , NBD_REP_ERR_POLICY , -1 , " " ) ; continue ; } if ( handle_starttls ( client , opt , servers , cflags , genconf ) == NULL ) { goto handler_err ; } #endif break ; case NBD_OPT_GO : case NBD_OPT_INFO : if ( handle_info ( client , opt , servers , cflags ) && opt == NBD_OPT_GO ) { return client ; } break ; default : consume_len ( client ) ; send_reply ( client , opt , NBD_REP_ERR_UNSUP , -1 , " " " " ) ; break ; } } while ( ( opt != NBD_OPT_EXPORT_NAME ) && ( opt != NBD_OPT_ABORT ) ) ; if ( opt == NBD_OPT_ABORT ) { err_nonfatal ( " " ) ; goto handler_err ; } err_nonfatal ( " " ) ; handler_err : g_free ( client ) ; return NULL ; }
Do the initial negotiation.
Do the initial negotiation .
// can't send an error message for EXPORT_NAME, // so must do hard close // handled below // NBD_OPT_EXPORT_NAME must be the last // selected option, so return from here // if that is chosen. // handled below // can't recover from failed TLS negotiation.