mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
The worker process receives the client's IPs from the main process.
That eliminates the need to read the IP address from the tun device (which can be quite tricky to implement in a clean portable way).
This commit is contained in:
@@ -46,7 +46,7 @@ ocserv-args.c: $(srcdir)/ocserv-args.def
|
||||
ocserv-args.h: ocserv-args.c
|
||||
|
||||
ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
cookies.c worker-tun.c main-misc.c main-ctl-handler.c \
|
||||
cookies.c main-misc.c main-ctl-handler.c \
|
||||
group-config.c ip-lease.c ip-lease.h \
|
||||
vpn.h cookies.h tlslib.h log.c tun.c tun.h \
|
||||
config.c pam.c pam.h worker-resume.c worker.h main-resume.c main.h \
|
||||
|
||||
16
src/common.c
16
src/common.c
@@ -214,7 +214,7 @@ int send_socket_msg(int fd, uint8_t cmd,
|
||||
if (length > 0) {
|
||||
packed = malloc(length);
|
||||
if (packed == NULL) {
|
||||
syslog(LOG_ERR, "%s:%u: memory error", __func__, __LINE__);
|
||||
syslog(LOG_ERR, "%s:%u: memory error", __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ int send_socket_msg(int fd, uint8_t cmd,
|
||||
|
||||
ret = pack(msg, packed);
|
||||
if (ret == 0) {
|
||||
syslog(LOG_ERR, "%s:%u: packing error", __func__, __LINE__);
|
||||
syslog(LOG_ERR, "%s:%u: packing error", __FILE__, __LINE__);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -245,7 +245,7 @@ int send_socket_msg(int fd, uint8_t cmd,
|
||||
ret = sendmsg(fd, &hdr, 0);
|
||||
if (ret < 0) {
|
||||
int e = errno;
|
||||
syslog(LOG_ERR, "%s:%u: %s", __func__, __LINE__, strerror(e));
|
||||
syslog(LOG_ERR, "%s:%u: %s", __FILE__, __LINE__, strerror(e));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@@ -293,12 +293,12 @@ int recv_socket_msg(int fd, uint8_t cmd,
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg: %s", __func__, __LINE__, strerror(e));
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__, __LINE__, strerror(e));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg returned zero", __func__, __LINE__);
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg returned zero", __FILE__, __LINE__);
|
||||
return ERR_WORKER_TERMINATED;
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ int recv_socket_msg(int fd, uint8_t cmd,
|
||||
if (socketfd != NULL) {
|
||||
if ( (cmptr = CMSG_FIRSTHDR(&hdr)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||
if (cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != SCM_RIGHTS) {
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg returned invalid msg type", __func__, __LINE__);
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg returned invalid msg type", __FILE__, __LINE__);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -330,14 +330,14 @@ int recv_socket_msg(int fd, uint8_t cmd,
|
||||
ret = force_read(fd, data, length);
|
||||
if (ret < length) {
|
||||
int e = errno;
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg: %s", __func__, __LINE__, strerror(e));
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__, __LINE__, strerror(e));
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*msg = unpack(NULL, length, data);
|
||||
if (*msg == NULL) {
|
||||
syslog(LOG_ERR, "%s:%u: unpacking error", __func__, __LINE__);
|
||||
syslog(LOG_ERR, "%s:%u: unpacking error", __FILE__, __LINE__);
|
||||
ret = ERR_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
14
src/config.c
14
src/config.c
@@ -157,7 +157,16 @@ unsigned j;
|
||||
fprintf(stderr, "Configuration option %s is mandatory.\n", name); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
|
||||
#define READ_STATIC_STRING(name, s_name) \
|
||||
val = get_option(name, &mand); \
|
||||
if (val != NULL && val->valType == OPARG_TYPE_STRING) \
|
||||
snprintf(s_name, sizeof(s_name), "%s", val->v.strVal); \
|
||||
else if (mand != 0) { \
|
||||
fprintf(stderr, "Configuration option %s is mandatory.\n", name); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define READ_TF(name, s_name, def) \
|
||||
{ char* tmp_tf = NULL; \
|
||||
READ_STRING(name, tmp_tf); \
|
||||
@@ -383,7 +392,7 @@ unsigned force_cert_auth;
|
||||
config->gid = grp->gr_gid;
|
||||
}
|
||||
|
||||
READ_STRING("device", config->network.name);
|
||||
READ_STATIC_STRING("device", config->network.name);
|
||||
READ_STRING("cgroup", config->cgroup);
|
||||
|
||||
READ_STRING("ipv4-network", config->network.ipv4);
|
||||
@@ -560,7 +569,6 @@ unsigned i;
|
||||
DEL(config->connect_script);
|
||||
DEL(config->disconnect_script);
|
||||
|
||||
DEL(config->network.name);
|
||||
DEL(config->network.ipv4);
|
||||
DEL(config->network.ipv4_netmask);
|
||||
DEL(config->network.ipv4_dns);
|
||||
|
||||
@@ -82,17 +82,23 @@ message auth_reply_msg
|
||||
optional string user_name = 5;
|
||||
optional string msg = 6;
|
||||
|
||||
/* the ips of the tun device */
|
||||
optional string ipv4 = 7;
|
||||
optional string ipv6 = 8;
|
||||
optional string ipv4_local = 9;
|
||||
optional string ipv6_local = 10;
|
||||
|
||||
/* additional config */
|
||||
optional string ipv4_dns = 7;
|
||||
optional string ipv6_dns = 8;
|
||||
optional string ipv4_nbns = 9;
|
||||
optional string ipv6_nbns = 10;
|
||||
optional string ipv4_netmask = 11;
|
||||
optional string ipv6_netmask = 12;
|
||||
optional uint32 rx_per_sec = 13;
|
||||
optional uint32 tx_per_sec = 14;
|
||||
optional uint32 net_priority = 15;
|
||||
repeated string routes = 16;
|
||||
optional string ipv4_dns = 11;
|
||||
optional string ipv6_dns = 12;
|
||||
optional string ipv4_nbns = 13;
|
||||
optional string ipv6_nbns = 14;
|
||||
optional string ipv4_netmask = 15;
|
||||
optional string ipv6_netmask = 16;
|
||||
optional uint32 rx_per_sec = 17;
|
||||
optional uint32 tx_per_sec = 18;
|
||||
optional uint32 net_priority = 19;
|
||||
repeated string routes = 20;
|
||||
}
|
||||
|
||||
/* RESUME_FETCH_REQ + RESUME_DELETE_REQ */
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
#include <worker.h>
|
||||
#include <main.h>
|
||||
|
||||
const char *human_addr2(const struct sockaddr *sa, socklen_t salen,
|
||||
char *human_addr2(const struct sockaddr *sa, socklen_t salen,
|
||||
void *_buf, size_t buflen, unsigned full)
|
||||
{
|
||||
const char *save_buf = _buf;
|
||||
char *save_buf = _buf;
|
||||
char *buf = _buf;
|
||||
size_t l;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <gnutls/crypto.h>
|
||||
#include <tlslib.h>
|
||||
#include <script-list.h>
|
||||
#include <ip-lease.h>
|
||||
#include "str.h"
|
||||
|
||||
#include <vpn.h>
|
||||
@@ -74,6 +75,10 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
}
|
||||
|
||||
if (r == AUTH_REPLY_MSG__AUTH__REP__OK && proc->tun_lease.name[0] != 0) {
|
||||
char ipv6[MAX_IP_STR];
|
||||
char ipv4[MAX_IP_STR];
|
||||
char ipv6_local[MAX_IP_STR];
|
||||
char ipv4_local[MAX_IP_STR];
|
||||
|
||||
/* fill message */
|
||||
msg.reply = AUTH_REPLY_MSG__AUTH__REP__OK;
|
||||
@@ -88,6 +93,20 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
msg.vname = proc->tun_lease.name;
|
||||
msg.user_name = proc->username;
|
||||
|
||||
if (proc->ipv4 && proc->ipv4->rip_len > 0) {
|
||||
msg.ipv4 = human_addr2((struct sockaddr*)&proc->ipv4->rip, proc->ipv4->rip_len,
|
||||
ipv4, sizeof(ipv4), 0);
|
||||
msg.ipv4_local = human_addr2((struct sockaddr*)&proc->ipv4->lip, proc->ipv4->lip_len,
|
||||
ipv4_local, sizeof(ipv4_local), 0);
|
||||
}
|
||||
|
||||
if (proc->ipv6 && proc->ipv6->rip_len > 0) {
|
||||
msg.ipv6 = human_addr2((struct sockaddr*)&proc->ipv6->rip, proc->ipv6->rip_len,
|
||||
ipv6, sizeof(ipv6), 0);
|
||||
msg.ipv6_local = human_addr2((struct sockaddr*)&proc->ipv6->lip, proc->ipv6->lip_len,
|
||||
ipv6_local, sizeof(ipv6_local), 0);
|
||||
}
|
||||
|
||||
msg.ipv4_dns = proc->config.ipv4_dns;
|
||||
msg.ipv6_dns = proc->config.ipv6_dns;
|
||||
msg.ipv4_nbns = proc->config.ipv4_nbns;
|
||||
|
||||
@@ -106,6 +106,8 @@ typedef struct
|
||||
unsigned int entries;
|
||||
} hash_db_st;
|
||||
|
||||
#define MAX_IP_STR 46
|
||||
|
||||
struct group_cfg_st {
|
||||
/* routes to be forwarded to the client */
|
||||
char **routes;
|
||||
@@ -133,7 +135,7 @@ struct group_cfg_st {
|
||||
};
|
||||
|
||||
struct vpn_st {
|
||||
char *name; /* device name */
|
||||
char name[IFNAMSIZ];
|
||||
char *ipv4_netmask;
|
||||
char *ipv4;
|
||||
char *ipv4_local; /* local IPv4 address */
|
||||
@@ -246,7 +248,7 @@ struct main_server_st;
|
||||
|
||||
#include <tun.h>
|
||||
|
||||
const char *human_addr2(const struct sockaddr *sa, socklen_t salen,
|
||||
char *human_addr2(const struct sockaddr *sa, socklen_t salen,
|
||||
void *buf, size_t buflen, unsigned full);
|
||||
|
||||
#define human_addr(x, y, z, w) human_addr2(x, y, z, w, 1)
|
||||
|
||||
@@ -251,7 +251,7 @@ static int recv_auth_reply(worker_st * ws, char *txt, size_t max_txt_size)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
snprintf(ws->tun_name, sizeof(ws->tun_name), "%s",
|
||||
snprintf(ws->vinfo.name, sizeof(ws->vinfo.name), "%s",
|
||||
msg->vname);
|
||||
snprintf(ws->username, sizeof(ws->username), "%s",
|
||||
msg->user_name);
|
||||
@@ -265,6 +265,38 @@ static int recv_auth_reply(worker_st * ws, char *txt, size_t max_txt_size)
|
||||
memcpy(ws->session_id, msg->session_id.data,
|
||||
msg->session_id.len);
|
||||
|
||||
if (msg->ipv4 != NULL) {
|
||||
free(ws->vinfo.ipv4);
|
||||
if (strcmp(msg->ipv4, "0.0.0.0") == 0)
|
||||
ws->vinfo.ipv4 = NULL;
|
||||
else
|
||||
ws->vinfo.ipv4 = strdup(msg->ipv4);
|
||||
}
|
||||
|
||||
if (msg->ipv6 != NULL) {
|
||||
free(ws->vinfo.ipv6);
|
||||
if (strcmp(msg->ipv6, "::") == 0)
|
||||
ws->vinfo.ipv6 = NULL;
|
||||
else
|
||||
ws->vinfo.ipv6 = strdup(msg->ipv6);
|
||||
}
|
||||
|
||||
if (msg->ipv4_local != NULL) {
|
||||
free(ws->vinfo.ipv4_local);
|
||||
if (strcmp(msg->ipv4_local, "0.0.0.0") == 0)
|
||||
ws->vinfo.ipv4_local = NULL;
|
||||
else
|
||||
ws->vinfo.ipv4_local = strdup(msg->ipv4_local);
|
||||
}
|
||||
|
||||
if (msg->ipv6_local != NULL) {
|
||||
free(ws->vinfo.ipv6_local);
|
||||
if (strcmp(msg->ipv6_local, "::") == 0)
|
||||
ws->vinfo.ipv6_local = NULL;
|
||||
else
|
||||
ws->vinfo.ipv6_local = strdup(msg->ipv6_local);
|
||||
}
|
||||
|
||||
/* Read any additional data */
|
||||
if (msg->ipv4_dns != NULL) {
|
||||
free(ws->config->network.ipv4_dns);
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <worker.h>
|
||||
#include <cookies.h>
|
||||
@@ -132,3 +136,72 @@ udp_fd_fail:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Completes the VPN device information.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int complete_vpn_info(worker_st * ws, struct vpn_st *vinfo)
|
||||
{
|
||||
int ret, fd;
|
||||
struct ifreq ifr;
|
||||
|
||||
if (vinfo->ipv4 == NULL && vinfo->ipv6 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#define LOCAL "local"
|
||||
if (ws->config->network.ipv4_dns
|
||||
&& strcmp(ws->config->network.ipv4_dns, LOCAL) == 0)
|
||||
vinfo->ipv4_dns = vinfo->ipv4_local;
|
||||
else
|
||||
vinfo->ipv4_dns = ws->config->network.ipv4_dns;
|
||||
|
||||
if (ws->config->network.ipv6_dns
|
||||
&& strcmp(ws->config->network.ipv6_dns, LOCAL) == 0)
|
||||
vinfo->ipv6_dns = vinfo->ipv6_local;
|
||||
else
|
||||
vinfo->ipv6_dns = ws->config->network.ipv6_dns;
|
||||
|
||||
if (ws->config->network.ipv4_nbns
|
||||
&& strcmp(ws->config->network.ipv4_nbns, LOCAL) == 0)
|
||||
vinfo->ipv4_nbns = vinfo->ipv4_local;
|
||||
else
|
||||
vinfo->ipv4_nbns = ws->config->network.ipv4_nbns;
|
||||
|
||||
if (ws->config->network.ipv6_nbns
|
||||
&& strcmp(ws->config->network.ipv6_nbns, LOCAL) == 0)
|
||||
vinfo->ipv6_nbns = vinfo->ipv6_local;
|
||||
else
|
||||
vinfo->ipv6_nbns = ws->config->network.ipv6_nbns;
|
||||
|
||||
vinfo->routes_size = ws->config->network.routes_size;
|
||||
if (ws->config->network.routes_size > 0)
|
||||
vinfo->routes = ws->config->network.routes;
|
||||
|
||||
vinfo->ipv4_netmask = ws->config->network.ipv4_netmask;
|
||||
vinfo->ipv6_netmask = ws->config->network.ipv6_netmask;
|
||||
|
||||
if (ws->config->network.mtu != 0) {
|
||||
vinfo->mtu = ws->config->network.mtu;
|
||||
} else {
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name);
|
||||
ret = ioctl(fd, SIOCGIFMTU, (caddr_t) & ifr);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR,
|
||||
"cannot obtain MTU for %s. Assuming 1500",
|
||||
vinfo->name);
|
||||
vinfo->mtu = 1500;
|
||||
} else {
|
||||
vinfo->mtu = ifr.ifr_mtu;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
244
src/worker-tun.c
244
src/worker-tun.c
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* This file is part of ocserv.
|
||||
*
|
||||
* ocserv is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuTLS is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/dtls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <worker.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
#include <ifaddrs.h>
|
||||
|
||||
static
|
||||
int get_ips(struct worker_st *ws, struct vpn_st *vinfo, char **buffer,
|
||||
size_t * buffer_size)
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int ret, e;
|
||||
void *p;
|
||||
|
||||
/* getifaddrs looks like a waste, especially when the number of devices/clients
|
||||
* is large. We should instead get that info from the main process
|
||||
*/
|
||||
|
||||
ret = getifaddrs(&ifaddr);
|
||||
if (ret != 0) {
|
||||
e = errno;
|
||||
oclog(ws, LOG_ERR, "getifaddrs error: %s", strerror(e));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue;
|
||||
|
||||
if (strcmp(vinfo->name, ifa->ifa_name) == 0) {
|
||||
p = (char *)inet_ntop(ifa->ifa_addr->sa_family,
|
||||
SA_IN_P_TYPE(ifa->ifa_addr,
|
||||
ifa->ifa_addr->
|
||||
sa_family), *buffer,
|
||||
*buffer_size);
|
||||
if (p == NULL) {
|
||||
e = errno;
|
||||
oclog(ws, LOG_ERR, "inet_ntop error: %s",
|
||||
strerror(e));
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = strlen(p) + 1;
|
||||
*buffer += ret;
|
||||
*buffer_size -= ret;
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET) {
|
||||
if (strcmp(p, "0.0.0.0") == 0)
|
||||
p = NULL;
|
||||
vinfo->ipv4_local = p;
|
||||
} else {
|
||||
if (strcmp(p, "::") == 0)
|
||||
p = NULL;
|
||||
vinfo->ipv6_local = p;
|
||||
}
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
/* no DST address */
|
||||
struct in6_addr ip;
|
||||
|
||||
memcpy(&ip,
|
||||
SA_IN_P_TYPE(ifa->ifa_addr,
|
||||
ifa->ifa_addr->sa_family),
|
||||
sizeof(ip));
|
||||
((uint8_t *) & ip)[15]++;
|
||||
|
||||
p = (char *)inet_ntop(AF_INET6,
|
||||
&ip, *buffer,
|
||||
*buffer_size);
|
||||
if (p == NULL) {
|
||||
e = errno;
|
||||
oclog(ws, LOG_ERR,
|
||||
"inet_ntop error: %s",
|
||||
strerror(e));
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = strlen(p) + 1;
|
||||
*buffer += ret;
|
||||
*buffer_size -= ret;
|
||||
|
||||
if (strcmp(p, "::") == 0)
|
||||
p = NULL;
|
||||
vinfo->ipv6 = p;
|
||||
} else {
|
||||
/* DST */
|
||||
if (ifa->ifa_dstaddr == NULL)
|
||||
continue;
|
||||
|
||||
p = (char *)inet_ntop(ifa->ifa_dstaddr->
|
||||
sa_family,
|
||||
SA_IN_P_TYPE(ifa->
|
||||
ifa_dstaddr,
|
||||
ifa->
|
||||
ifa_dstaddr->
|
||||
sa_family),
|
||||
*buffer, *buffer_size);
|
||||
if (p == NULL) {
|
||||
e = errno;
|
||||
oclog(ws, LOG_ERR,
|
||||
"inet_ntop error: %s",
|
||||
strerror(e));
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = strlen(p) + 1;
|
||||
*buffer += ret;
|
||||
*buffer_size -= ret;
|
||||
|
||||
if (strcmp(p, "0.0.0.0") == 0)
|
||||
p = NULL;
|
||||
vinfo->ipv4 = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns information based on an VPN network stored in worker_st but
|
||||
* using real time information for many fields. Nothing is allocated,
|
||||
* the provided buffer is used.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int get_rt_vpn_info(worker_st * ws,
|
||||
struct vpn_st *vinfo, char *buffer, size_t buffer_size)
|
||||
{
|
||||
int ret, fd;
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(vinfo, 0, sizeof(*vinfo));
|
||||
vinfo->name = ws->tun_name;
|
||||
|
||||
/* get the remote IPs */
|
||||
ret = get_ips(ws, vinfo, &buffer, &buffer_size);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_DEBUG, "cannot obtain IPs for %s", vinfo->name);
|
||||
}
|
||||
|
||||
if (vinfo->ipv4 == NULL && vinfo->ipv6 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#define LOCAL "local"
|
||||
if (ws->config->network.ipv4_dns
|
||||
&& strcmp(ws->config->network.ipv4_dns, LOCAL) == 0)
|
||||
vinfo->ipv4_dns = vinfo->ipv4_local;
|
||||
else
|
||||
vinfo->ipv4_dns = ws->config->network.ipv4_dns;
|
||||
|
||||
if (ws->config->network.ipv6_dns
|
||||
&& strcmp(ws->config->network.ipv6_dns, LOCAL) == 0)
|
||||
vinfo->ipv6_dns = vinfo->ipv6_local;
|
||||
else
|
||||
vinfo->ipv6_dns = ws->config->network.ipv6_dns;
|
||||
|
||||
if (ws->config->network.ipv4_nbns
|
||||
&& strcmp(ws->config->network.ipv4_nbns, LOCAL) == 0)
|
||||
vinfo->ipv4_nbns = vinfo->ipv4_local;
|
||||
else
|
||||
vinfo->ipv4_nbns = ws->config->network.ipv4_nbns;
|
||||
|
||||
if (ws->config->network.ipv6_nbns
|
||||
&& strcmp(ws->config->network.ipv6_nbns, LOCAL) == 0)
|
||||
vinfo->ipv6_nbns = vinfo->ipv6_local;
|
||||
else
|
||||
vinfo->ipv6_nbns = ws->config->network.ipv6_nbns;
|
||||
|
||||
vinfo->routes_size = ws->config->network.routes_size;
|
||||
if (ws->config->network.routes_size > 0)
|
||||
vinfo->routes = ws->config->network.routes;
|
||||
|
||||
vinfo->ipv4_netmask = ws->config->network.ipv4_netmask;
|
||||
vinfo->ipv6_netmask = ws->config->network.ipv6_netmask;
|
||||
|
||||
if (ws->config->network.mtu != 0) {
|
||||
vinfo->mtu = ws->config->network.mtu;
|
||||
} else {
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name);
|
||||
ret = ioctl(fd, SIOCGIFMTU, (caddr_t) & ifr);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR,
|
||||
"cannot obtain MTU for %s. Assuming 1500",
|
||||
vinfo->name);
|
||||
vinfo->mtu = 1500;
|
||||
} else {
|
||||
vinfo->mtu = ifr.ifr_mtu;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1083,7 +1083,7 @@ static int connect_handler(worker_st * ws)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = get_rt_vpn_info(ws, &ws->vinfo, (char *)ws->buffer, ws->buffer_size);
|
||||
ret = complete_vpn_info(ws, &ws->vinfo);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR,
|
||||
"no networks are configured; rejecting client");
|
||||
|
||||
@@ -148,7 +148,8 @@ typedef struct worker_st {
|
||||
unsigned buffer_size;
|
||||
|
||||
/* the following are set only if authentication is complete */
|
||||
char tun_name[IFNAMSIZ];
|
||||
|
||||
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
char hostname[MAX_HOSTNAME_SIZE];
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
@@ -194,8 +195,8 @@ void __attribute__ ((format(printf, 3, 4)))
|
||||
# define oclog _oclog
|
||||
#endif
|
||||
|
||||
int get_rt_vpn_info(worker_st * ws,
|
||||
struct vpn_st* vinfo, char* buffer, size_t buffer_size);
|
||||
int complete_vpn_info(worker_st * ws,
|
||||
struct vpn_st* vinfo);
|
||||
|
||||
int send_tun_mtu(worker_st *ws, unsigned int mtu);
|
||||
int handle_worker_commands(struct worker_st *ws);
|
||||
|
||||
Reference in New Issue
Block a user