void qdra_conn_link_route_create_CT(qdr_core_t         *core,
                                    qd_iterator_t      *name,
                                    qdr_query_t        *query,
                                    qd_parsed_field_t  *in_body)
{
    char *pattern = NULL;

    query->status = QD_AMQP_BAD_REQUEST;

    // fail if creating via a configuration file
    if (query->in_conn == 0) {
        query->status.description = "Can only create via management CREATE";
        goto exit;
    }

    // find the associated connection
    qdr_connection_t *conn = _find_conn_CT(core, query->in_conn);
    if (!conn) {
        query->status.description = "Parent connection no longer exists";
        goto exit;
    }

    // fail if forbidden by policy
    if (!conn->policy_allow_dynamic_link_routes) {
        query->status = QD_AMQP_FORBIDDEN;
        goto exit;
    }

    if (!qd_parse_is_map(in_body)) {
        query->status.description = "Body of request must be a map";
        goto exit;
    }

    //
    // Extract the fields from the request
    //
    qd_parsed_field_t *pattern_field    = qd_parse_value_by_key(in_body, qdr_conn_link_route_columns[QDR_CONN_LINK_ROUTE_PATTERN]);
    qd_parsed_field_t *dir_field        = qd_parse_value_by_key(in_body, qdr_conn_link_route_columns[QDR_CONN_LINK_ROUTE_DIRECTION]);

    if (!pattern_field) {
        query->status.description = "Pattern field is required";
        goto exit;
    }

    const char *error = NULL;
    pattern = qdra_config_address_validate_pattern_CT(pattern_field, false, &error);
    if (!pattern) {
        query->status.description = error;
        goto exit;
    }

    qd_direction_t dir;
    error = qdra_link_route_direction_CT(dir_field, &dir);
    if (error) {
        query->status.description = error;
        goto exit;
    }

    qdr_link_route_t *lr = qdr_route_add_conn_route_CT(core, conn, name, pattern, dir);
    if (!lr) {
        query->status.description = "creation failed";
        goto exit;
    }

    query->status = QD_AMQP_CREATED;
    _write_as_map_CT(query, lr);

exit:
    free(pattern);
    if (query->status.status != QD_AMQP_CREATED.status) {
        qd_log(core->agent_log, QD_LOG_ERROR, "Error performing CREATE of %s: %s",
               CONN_LINK_ROUTE_TYPE, query->status.description);
        qd_compose_insert_null(query->body);  // no body map
    }
    qdr_agent_enqueue_response_CT(core, query);
}
void qdra_config_link_route_create_CT(qdr_core_t          *core,
                                      qd_field_iterator_t *name,
                                      qdr_query_t         *query,
                                      qd_parsed_field_t   *in_body)
{
    while (true) {
        //
        // Ensure there isn't a duplicate name and that the body is a map
        //
        qdr_link_route_t *lr = DEQ_HEAD(core->link_routes);
        while (lr) {
            if (name && lr->name && qd_field_iterator_equal(name, (const unsigned char*) lr->name))
                break;
            lr = DEQ_NEXT(lr);
        }

        if (!!lr) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = "Name conflicts with an existing entity";
            break;
        }

        if (!qd_parse_is_map(in_body)) {
            query->status = QD_AMQP_BAD_REQUEST;
            break;
        }

        //
        // Extract the fields from the request
        //
        qd_parsed_field_t *prefix_field     = qd_parse_value_by_key(in_body, qdr_config_link_route_columns[QDR_CONFIG_LINK_ROUTE_PREFIX]);
        qd_parsed_field_t *distrib_field    = qd_parse_value_by_key(in_body, qdr_config_link_route_columns[QDR_CONFIG_LINK_ROUTE_DISTRIBUTION]);
        qd_parsed_field_t *connection_field = qd_parse_value_by_key(in_body, qdr_config_link_route_columns[QDR_CONFIG_LINK_ROUTE_CONNECTION]);
        qd_parsed_field_t *container_field  = qd_parse_value_by_key(in_body, qdr_config_link_route_columns[QDR_CONFIG_LINK_ROUTE_CONTAINER_ID]);
        qd_parsed_field_t *dir_field        = qd_parse_value_by_key(in_body, qdr_config_link_route_columns[QDR_CONFIG_LINK_ROUTE_DIR]);

        //
        // Prefix and dir fields are mandatory.  Fail if they're not both here.
        //
        if (!prefix_field || !dir_field) {
            query->status = QD_AMQP_BAD_REQUEST;
            break;
        }

        qd_direction_t dir;
        const char *error = qdra_link_route_direction_CT(dir_field, &dir);
        if (error) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = error;
            break;
        }

        qd_address_treatment_t trt;
        error = qdra_link_route_treatment_CT(distrib_field, &trt);
        if (error) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = error;
            break;
        }

        //
        // The request is good.  Create the entity.
        //
        bool               is_container = !!container_field;
        qd_parsed_field_t *in_use_conn  = is_container ? container_field : connection_field;

        lr = qdr_route_add_link_route_CT(core, name, prefix_field, in_use_conn, is_container, trt, dir);

        //
        // Compose the result map for the response.
        //
        if (query->body) {
            qd_compose_start_map(query->body);
            for (int col = 0; col < QDR_CONFIG_LINK_ROUTE_COLUMN_COUNT; col++)
                qdr_config_link_route_insert_column_CT(lr, col, query->body, true);
            qd_compose_end_map(query->body);
        }

        query->status = QD_AMQP_CREATED;
        break;
    }

    //
    // Enqueue the response if there is a body. If there is no body, this is a management
    // operation created internally by the configuration file parser.
    //
    if (query->body) {
        //
        // If there was an error in processing the create, insert a NULL value into the body.
        //
        if (query->status.status / 100 > 2)
            qd_compose_insert_null(query->body);
        qdr_agent_enqueue_response_CT(core, query);
    } else {
        if (query->status.status / 100 > 2)
            qd_log(core->log, QD_LOG_ERROR, "Error configuring linkRoute: %s", query->status.description);
        qdr_query_free(query);
    }
}