NOEXPORT int servername_cb(SSL *ssl, int *ad, void *arg) {
    const char *servername=SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    CLI *c=SSL_get_ex_data(ssl, index_ssl_cli);
    SERVERNAME_LIST *list;

    /* leave the alert type at SSL_AD_UNRECOGNIZED_NAME */
    (void)ad; /* squash the unused parameter warning */
    (void)arg; /* squash the unused parameter warning */

    /* handle trivial cases first */
    if(!c->opt->servername_list_head) {
        s_log(LOG_DEBUG, "SNI: no virtual services defined");
        return SSL_TLSEXT_ERR_OK;
    }
    if(!servername) {
        s_log(LOG_NOTICE, "SNI: no servername received");
        return SSL_TLSEXT_ERR_NOACK;
    }

    /* find a matching section */
    s_log(LOG_INFO, "SNI: requested servername: %s", servername);
    for(list=c->opt->servername_list_head; list; list=list->next)
        if(matches_wildcard(servername, list->servername))
            break;
    if(!list) {
        s_log(LOG_ERR, "SNI: no pattern matched servername: %s", servername);
        return SSL_TLSEXT_ERR_OK;
    }
    s_log(LOG_DEBUG, "SNI: matched pattern: %s", list->servername);

    /* switch to the new section */
#ifndef USE_FORK
    service_up_ref(list->opt);
    service_free(c->opt);
#endif
    c->opt=list->opt;
    SSL_set_SSL_CTX(ssl, c->opt->ctx);
    SSL_set_verify(ssl, SSL_CTX_get_verify_mode(c->opt->ctx),
        SSL_CTX_get_verify_callback(c->opt->ctx));
    s_log(LOG_NOTICE, "SNI: switched to service [%s]", c->opt->servname);
#ifdef USE_LIBWRAP
    libwrap_auth(c); /* retry on a service switch */
#endif /* USE_LIBWRAP */
    return SSL_TLSEXT_ERR_OK;
}
NOEXPORT int servername_cb(SSL *ssl, int *ad, void *arg) {
    const char *servername=SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    CLI *c=SSL_get_ex_data(ssl, index_ssl_cli);
    SERVERNAME_LIST *list;

     
    (void)ad;  
    (void)arg;  

     
    if(!c->opt->servername_list_head) {
        s_log(LOG_DEBUG, "SNI: no virtual services defined");
        return SSL_TLSEXT_ERR_OK;
    }
    if(!servername) {
        s_log(LOG_NOTICE, "SNI: no servername received");
        return SSL_TLSEXT_ERR_NOACK;
    }

     
    s_log(LOG_INFO, "SNI: requested servername: %s", servername);
    for(list=c->opt->servername_list_head; list; list=list->next)
        if(matches_wildcard(servername, list->servername))
            break;
    if(!list) {
        s_log(LOG_ERR, "SNI: no pattern matched servername: %s", servername);
        return SSL_TLSEXT_ERR_OK;
    }
    s_log(LOG_DEBUG, "SNI: matched pattern: %s", list->servername);

     
#ifndef USE_FORK
    service_up_ref(list->opt);
    service_free(c->opt);
#endif
    c->opt=list->opt;
    SSL_set_SSL_CTX(ssl, c->opt->ctx);
    SSL_set_verify(ssl, SSL_CTX_get_verify_mode(c->opt->ctx),
        SSL_CTX_get_verify_callback(c->opt->ctx));
    s_log(LOG_NOTICE, "SNI: switched to service [%s]", c->opt->servname);
#ifdef USE_LIBWRAP
    libwrap_auth(c);  
#endif  
    return SSL_TLSEXT_ERR_OK;
}