diff --git a/http.c b/http.c index 34fd765e..5cfec9db 100644 --- a/http.c +++ b/http.c @@ -831,8 +831,8 @@ int do_https_request(struct openconnect_info *vpninfo, const char *method, /* Forget existing challenges */ clear_auth_states(vpninfo, vpninfo->http_auth, 0); } - if (vpninfo->proto.add_http_headers) - vpninfo->proto.add_http_headers(vpninfo, buf); + if (vpninfo->proto->add_http_headers) + vpninfo->proto->add_http_headers(vpninfo, buf); if (request_body_type) { rlen = request_body->pos; diff --git a/library.c b/library.c index 8524c159..b258bbbe 100644 --- a/library.c +++ b/library.c @@ -104,43 +104,53 @@ struct openconnect_info *openconnect_vpninfo_new(const char *useragent, return NULL; } -int openconnect_set_protocol(struct openconnect_info *vpninfo, const char *protocol) -{ - if (!strcmp(protocol, "anyconnect")) { - vpninfo->proto.vpn_close_session = cstp_bye; - vpninfo->proto.tcp_connect = cstp_connect; - vpninfo->proto.tcp_mainloop = cstp_mainloop; - vpninfo->proto.add_http_headers = cstp_common_headers; - vpninfo->proto.obtain_cookie = cstp_obtain_cookie; +const struct vpn_proto openconnect_protos[] = { + { + .name = "anyconnect", + .vpn_close_session = cstp_bye, + .tcp_connect = cstp_connect, + .tcp_mainloop = cstp_mainloop, + .add_http_headers = cstp_common_headers, + .obtain_cookie = cstp_obtain_cookie, #ifdef HAVE_DTLS - vpninfo->proto.udp_setup = dtls_setup; - vpninfo->proto.udp_mainloop = dtls_mainloop; - vpninfo->proto.udp_close = dtls_close; - vpninfo->proto.udp_shutdown = dtls_shutdown; -#else - vpninfo->dtls_state = DTLS_DISABLED; + .udp_setup = dtls_setup, + .udp_mainloop = dtls_mainloop, + .udp_close = dtls_close, + .udp_shutdown = dtls_shutdown, #endif - } else if (!strcmp(protocol, "nc")) { - vpninfo->proto.vpn_close_session = NULL; - vpninfo->proto.tcp_connect = oncp_connect; - vpninfo->proto.tcp_mainloop = oncp_mainloop; - vpninfo->proto.add_http_headers = oncp_common_headers; - vpninfo->proto.obtain_cookie = oncp_obtain_cookie; + }, { + .name = "nc", + .vpn_close_session = NULL, + .tcp_connect = oncp_connect, + .tcp_mainloop = oncp_mainloop, + .add_http_headers = oncp_common_headers, + .obtain_cookie = oncp_obtain_cookie, #if defined(ESP_GNUTLS) || defined(ESP_OPENSSL) - vpninfo->proto.udp_setup = esp_setup; - vpninfo->proto.udp_mainloop = esp_mainloop; - vpninfo->proto.udp_close = esp_close; - vpninfo->proto.udp_shutdown = esp_shutdown; -#else - vpninfo->dtls_state = DTLS_DISABLED; + .udp_setup = esp_setup, + .udp_mainloop = esp_mainloop, + .udp_close = esp_close, + .udp_shutdown = esp_shutdown, #endif - } else { - vpn_progress(vpninfo, PRG_ERR, - _("Unknown VPN protocol '%s'\n"), protocol); - return -EINVAL; - } + }, + { /* NULL */ } +}; - return 0; +int openconnect_set_protocol(struct openconnect_info *vpninfo, const char *protocol) +{ + const struct vpn_proto *p; + + for (p = openconnect_protos; p->name; p++) { + if (strcasecmp(p->name, protocol)) + continue; + vpninfo->proto = p; + if (!p->udp_setup) + vpninfo->dtls_state = DTLS_DISABLED; + + return 0; + } + vpn_progress(vpninfo, PRG_ERR, + _("Unknown VPN protocol '%s'\n"), protocol); + return -EINVAL; } void openconnect_set_loglevel(struct openconnect_info *vpninfo, @@ -153,8 +163,8 @@ int openconnect_setup_dtls(struct openconnect_info *vpninfo, int attempt_period) { - if (vpninfo->proto.udp_setup) - return vpninfo->proto.udp_setup(vpninfo, attempt_period); + if (vpninfo->proto->udp_setup) + return vpninfo->proto->udp_setup(vpninfo, attempt_period); vpn_progress(vpninfo, PRG_ERR, _("Built against SSL library with no Cisco DTLS support\n")); @@ -163,12 +173,12 @@ int openconnect_setup_dtls(struct openconnect_info *vpninfo, int openconnect_obtain_cookie(struct openconnect_info *vpninfo) { - return vpninfo->proto.obtain_cookie(vpninfo); + return vpninfo->proto->obtain_cookie(vpninfo); } int openconnect_make_cstp_connection(struct openconnect_info *vpninfo) { - return vpninfo->proto.tcp_connect(vpninfo); + return vpninfo->proto->tcp_connect(vpninfo); } int openconnect_set_reported_os(struct openconnect_info *vpninfo, @@ -227,8 +237,8 @@ static void free_optlist(struct oc_vpn_option *opt) void openconnect_vpninfo_free(struct openconnect_info *vpninfo) { openconnect_close_https(vpninfo, 1); - if (vpninfo->proto.udp_shutdown) - vpninfo->proto.udp_shutdown(vpninfo); + if (vpninfo->proto->udp_shutdown) + vpninfo->proto->udp_shutdown(vpninfo); if (vpninfo->tncc_fd != -1) closesocket(vpninfo->tncc_fd); if (vpninfo->cmd_fd_write != -1) { diff --git a/mainloop.c b/mainloop.c index c1a7eb9b..a474861e 100644 --- a/mainloop.c +++ b/mainloop.c @@ -213,7 +213,7 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, } } - ret = vpninfo->proto.udp_mainloop(vpninfo, &timeout); + ret = vpninfo->proto->udp_mainloop(vpninfo, &timeout); if (vpninfo->quit_reason) break; did_work += ret; @@ -225,7 +225,7 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, break; } - ret = vpninfo->proto.tcp_mainloop(vpninfo, &timeout); + ret = vpninfo->proto->tcp_mainloop(vpninfo, &timeout); if (vpninfo->quit_reason) break; did_work += ret; @@ -252,7 +252,7 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, openconnect_mainloop() again */ openconnect_close_https(vpninfo, 0); if (vpninfo->dtls_state > DTLS_DISABLED) { - vpninfo->proto.udp_close(vpninfo); + vpninfo->proto->udp_close(vpninfo); vpninfo->dtls_state = DTLS_SLEEPING; vpninfo->new_dtls_started = 0; } @@ -303,8 +303,8 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, #endif } - if (vpninfo->quit_reason && vpninfo->proto.vpn_close_session) - vpninfo->proto.vpn_close_session(vpninfo, vpninfo->quit_reason); + if (vpninfo->quit_reason && vpninfo->proto->vpn_close_session) + vpninfo->proto->vpn_close_session(vpninfo, vpninfo->quit_reason); if (tun_is_up(vpninfo)) os_shutdown_tun(vpninfo); diff --git a/openconnect-internal.h b/openconnect-internal.h index 4ded7612..fb2d558a 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -245,6 +245,7 @@ struct http_auth_state { }; struct vpn_proto { + const char *name; int (*vpn_close_session)(struct openconnect_info *vpninfo, const char *reason); /* This does the full authentication, calling back as appropriate */ @@ -326,7 +327,7 @@ struct esp { }; struct openconnect_info { - struct vpn_proto proto; + const struct vpn_proto *proto; #ifdef HAVE_ICONV iconv_t ic_legacy_to_utf8; diff --git a/ssl.c b/ssl.c index 118fb2de..9aa8fea1 100644 --- a/ssl.c +++ b/ssl.c @@ -1003,7 +1003,7 @@ int ssl_reconnect(struct openconnect_info *vpninfo) free(vpninfo->tun_pkt); vpninfo->tun_pkt = NULL; - while ((ret = vpninfo->proto.tcp_connect(vpninfo))) { + while ((ret = vpninfo->proto->tcp_connect(vpninfo))) { if (timeout <= 0) return ret; if (ret == -EPERM) {