diff --git a/dtls.c b/dtls.c index a7bffcff..66c85a53 100644 --- a/dtls.c +++ b/dtls.c @@ -486,6 +486,8 @@ int connect_dtls_socket(struct openconnect_info *vpninfo) perror(_("Open UDP socket for DTLS:")); return -EINVAL; } + if (vpninfo->protect_socket) + vpninfo->protect_socket(vpninfo->cbdata, dtls_fd); sndbuf = vpninfo->ip_info.mtu * 2; setsockopt(dtls_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); diff --git a/libopenconnect.map.in b/libopenconnect.map.in index 3b730678..694dcc25 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -48,6 +48,7 @@ OPENCONNECT_3.1 { openconnect_get_ifname; openconnect_set_reqmtu; openconnect_get_ip_info; + openconnect_set_protect_socket_handler; } OPENCONNECT_3.0; OPENCONNECT_PRIVATE { diff --git a/library.c b/library.c index 4c34cd23..c38255b7 100644 --- a/library.c +++ b/library.c @@ -527,3 +527,9 @@ int openconnect_set_stoken_mode(struct openconnect_info *vpninfo, return openconnect_set_token_mode(vpninfo, token_mode, token_str); } + +void openconnect_set_protect_socket_handler(struct openconnect_info *vpninfo, + openconnect_protect_socket_vfn protect_socket) +{ + vpninfo->protect_socket = protect_socket; +} diff --git a/openconnect-internal.h b/openconnect-internal.h index 6f270461..5c1a15cc 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -301,6 +301,7 @@ struct openconnect_info { openconnect_write_new_config_vfn write_new_config; openconnect_process_auth_form_vfn process_auth_form; openconnect_progress_vfn progress; + openconnect_protect_socket_vfn protect_socket; }; #if (defined(DTLS_OPENSSL) && defined(SSL_OP_CISCO_ANYCONNECT)) || \ diff --git a/openconnect.h b/openconnect.h index 64841fcf..6a5cb73b 100644 --- a/openconnect.h +++ b/openconnect.h @@ -366,6 +366,13 @@ struct openconnect_info *openconnect_vpninfo_new(char *useragent, void *privdata); void openconnect_vpninfo_free(struct openconnect_info *vpninfo); +/* Callback to allow binding a newly created socket's file descriptor to + a specific interface, e.g. with SO_BINDTODEVICE. This tells the kernel + not to route the traffic in question over the VPN tunnel. */ +typedef void (*openconnect_protect_socket_vfn) (void *privdata, int fd); +void openconnect_set_protect_socket_handler(struct openconnect_info *vpninfo, + openconnect_protect_socket_vfn protect_socket); + /* SSL certificate capabilities. openconnect_has_pkcs11_support() means that we can accept PKCS#11 URLs in place of filenames, for the certificate and key. */ int openconnect_has_pkcs11_support(void); diff --git a/ssl.c b/ssl.c index 4a0210ab..4dfbee61 100644 --- a/ssl.c +++ b/ssl.c @@ -66,6 +66,8 @@ static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd, int maxfd = sockfd; fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + if (vpninfo->protect_socket) + vpninfo->protect_socket(vpninfo->cbdata, sockfd); if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS) return -1;