int openconnect_setup_tun_fd(struct openconnect_info *vpninfo, int tun_fd) { set_fd_cloexec(tun_fd); if (vpninfo->tun_fd != -1) unmonitor_read_fd(vpninfo, tun); vpninfo->tun_fd = tun_fd; monitor_fd_new(vpninfo, tun); monitor_read_fd(vpninfo, tun); set_sock_nonblock(tun_fd); return 0; }
static int esp_send_probes(struct openconnect_info *vpninfo) { struct pkt *pkt; int pktlen; if (vpninfo->dtls_fd == -1) { int fd = udp_connect(vpninfo); if (fd < 0) return fd; /* We are not connected until we get an ESP packet back */ vpninfo->dtls_state = DTLS_SLEEPING; vpninfo->dtls_fd = fd; monitor_fd_new(vpninfo, dtls); monitor_read_fd(vpninfo, dtls); monitor_except_fd(vpninfo, dtls); } pkt = malloc(sizeof(*pkt) + 1 + vpninfo->pkt_trailer); if (!pkt) return -ENOMEM; pkt->len = 1; pkt->data[0] = 0; pktlen = encrypt_esp_packet(vpninfo, pkt); if (pktlen >= 0) send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0); pkt->len = 1; pkt->data[0] = 0; pktlen = encrypt_esp_packet(vpninfo, pkt); if (pktlen >= 0) send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0); free(pkt); vpninfo->dtls_times.last_tx = time(&vpninfo->new_dtls_started); return 0; };
int connect_dtls_socket(struct openconnect_info *vpninfo) { int dtls_fd, ret, sndbuf; /* Sanity check for the removal of new_dtls_{fd,ssl} */ if (vpninfo->dtls_fd != -1) { vpn_progress(vpninfo, PRG_ERR, _("DTLS connection attempted with an existing fd\n")); vpninfo->dtls_attempt_period = 0; return -EINVAL; } if (!vpninfo->dtls_addr) { vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n")); vpninfo->dtls_attempt_period = 0; return -EINVAL; } if (!vpninfo->dtls_cipher) { /* We probably didn't offer it any ciphers it liked */ vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n")); vpninfo->dtls_attempt_period = 0; return -EINVAL; } if (vpninfo->proxy) { /* XXX: Theoretically, SOCKS5 proxies can do UDP too */ vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n")); vpninfo->dtls_attempt_period = 0; return -EINVAL; } dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); if (dtls_fd < 0) { 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, (void *)&sndbuf, sizeof(sndbuf)); if (vpninfo->dtls_local_port) { union { struct sockaddr_in in; struct sockaddr_in6 in6; } dtls_bind_addr; int dtls_bind_addrlen; memset(&dtls_bind_addr, 0, sizeof(dtls_bind_addr)); if (vpninfo->peer_addr->sa_family == AF_INET) { struct sockaddr_in *addr = &dtls_bind_addr.in; dtls_bind_addrlen = sizeof(*addr); addr->sin_family = AF_INET; addr->sin_addr.s_addr = INADDR_ANY; addr->sin_port = htons(vpninfo->dtls_local_port); } else if (vpninfo->peer_addr->sa_family == AF_INET6) { struct sockaddr_in6 *addr = &dtls_bind_addr.in6; dtls_bind_addrlen = sizeof(*addr); addr->sin6_family = AF_INET6; addr->sin6_addr = in6addr_any; addr->sin6_port = htons(vpninfo->dtls_local_port); } else { vpn_progress(vpninfo, PRG_ERR, _("Unknown protocol family %d. Cannot do DTLS\n"), vpninfo->peer_addr->sa_family); vpninfo->dtls_attempt_period = 0; closesocket(dtls_fd); return -EINVAL; } if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) { perror(_("Bind UDP socket for DTLS")); closesocket(dtls_fd); return -EINVAL; } } if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) { perror(_("UDP (DTLS) connect:\n")); closesocket(dtls_fd); return -EINVAL; } set_fd_cloexec(dtls_fd); set_sock_nonblock(dtls_fd); ret = start_dtls_handshake(vpninfo, dtls_fd); if (ret) { closesocket(dtls_fd); return ret; } vpninfo->dtls_state = DTLS_CONNECTING; vpninfo->dtls_fd = dtls_fd; monitor_fd_new(vpninfo, dtls); monitor_read_fd(vpninfo, dtls); monitor_except_fd(vpninfo, dtls); time(&vpninfo->new_dtls_started); return dtls_try_handshake(vpninfo); }