mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
simplified forward_udp_to_owner() by introducing oc_recvfrom_at()
This commit is contained in:
81
src/common.c
81
src/common.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
* Copyright (C) 2013-2015 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -448,6 +448,85 @@ void *_talloc_size2(void *ctx, size_t size)
|
||||
return talloc_size(ctx, size);
|
||||
}
|
||||
|
||||
/* like recvfrom but also returns the address of our interface.
|
||||
*
|
||||
* @def_port: is provided to fill in the missing port number
|
||||
* in our_addr.
|
||||
*/
|
||||
ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen,
|
||||
struct sockaddr *our_addr, socklen_t *our_addrlen,
|
||||
int def_port)
|
||||
{
|
||||
int ret;
|
||||
char cmbuf[256];
|
||||
struct iovec iov = { buf, len };
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr mh = {
|
||||
.msg_name = src_addr,
|
||||
.msg_namelen = *addrlen,
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmbuf,
|
||||
.msg_controllen = sizeof(cmbuf),
|
||||
};
|
||||
|
||||
ret = recvmsg(sockfd, &mh, 0);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* find our address */
|
||||
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg != NULL; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
|
||||
#if defined(IP_PKTINFO)
|
||||
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
|
||||
struct in_pktinfo *pi = CMSG_DATA(cmsg);
|
||||
struct sockaddr_in *a = (struct sockaddr_in*)our_addr;
|
||||
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in))
|
||||
return -1;
|
||||
|
||||
a->sin_family = AF_INET;
|
||||
memcpy(&a->sin_addr, &pi->ipi_addr, sizeof(struct in_addr));
|
||||
a->sin_port = htons(def_port);
|
||||
*our_addrlen = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
}
|
||||
#elif defined(IP_RECVDSTADDR)
|
||||
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
|
||||
struct in_addr *pi = CMSG_DATA(cmsg);
|
||||
struct sockaddr_in *a = (struct sockaddr_in*)our_addr;
|
||||
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in))
|
||||
return -1;
|
||||
|
||||
a->sin_family = AF_INET;
|
||||
memcpy(&a->sin_addr, &pi->ipi_addr, sizeof(struct in_addr));
|
||||
a->sin_port = htons(def_port);
|
||||
*our_addrlen = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
if (cmsg->cmsg_level != IPPROTO_IPV6 || cmsg->cmsg_type != IPV6_RECVPKTINFO) {
|
||||
struct in6_pktinfo *pi = CMSG_DATA(cmsg);
|
||||
struct sockaddr_in6 *a = (struct sockaddr_in6*)our_addr;
|
||||
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in6))
|
||||
return -1;
|
||||
|
||||
a->sin6_family = AF_INET6;
|
||||
memcpy(&a->sin6_addr, &pi->ipi6_addr, sizeof(struct in6_addr));
|
||||
a->sin6_port = htons(def_port);
|
||||
*our_addrlen = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
|
||||
/*
|
||||
|
||||
@@ -83,6 +83,11 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
|
||||
const char* cmd_request_to_str(unsigned cmd);
|
||||
|
||||
ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen,
|
||||
struct sockaddr *our_addr, socklen_t *our_addrlen,
|
||||
int def_port);
|
||||
|
||||
inline static
|
||||
void safe_memset(void *data, int c, size_t size)
|
||||
{
|
||||
|
||||
80
src/main.c
80
src/main.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 Nikos Mavrogiannopoulos
|
||||
* Copyright (C) 2013-2015 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -82,7 +82,7 @@ static void add_listener(void *pool, struct listen_list_st *list,
|
||||
tmp->family = family;
|
||||
tmp->sock_type = socktype;
|
||||
tmp->protocol = protocol;
|
||||
|
||||
|
||||
tmp->addr_len = addr_len;
|
||||
memcpy(&tmp->addr, addr, addr_len);
|
||||
|
||||
@@ -199,7 +199,7 @@ int _listen_ports(void *pool, struct cfg_st* config,
|
||||
}
|
||||
|
||||
set_common_socket_options(s);
|
||||
|
||||
|
||||
add_listener(pool, list, s, ptr->ai_family, ptr->ai_socktype==SOCK_STREAM?SOCK_TYPE_TCP:SOCK_TYPE_UDP,
|
||||
ptr->ai_protocol, ptr->ai_addr, ptr->ai_addrlen);
|
||||
|
||||
@@ -344,7 +344,7 @@ listen_ports(void *pool, struct cfg_st* config,
|
||||
|
||||
if (config->foreground != 0)
|
||||
fprintf(stderr, "listening on %d systemd sockets...\n", list->total);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -412,7 +412,7 @@ listen_ports(void *pool, struct cfg_st* config,
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ struct script_wait_st *stmp = NULL, *spos;
|
||||
|
||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||
estatus = WEXITSTATUS(status);
|
||||
|
||||
|
||||
if (pid == s->sec_mod_pid) {
|
||||
mslog(s, NULL, LOG_ERR, "ocserv-secmod died unexpectedly");
|
||||
terminate = 1;
|
||||
@@ -483,7 +483,7 @@ struct script_wait_st *stmp = NULL, *spos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
if (WTERMSIG(status) == SIGSEGV)
|
||||
mslog(s, NULL, LOG_ERR, "Child %u died with sigsegv\n", (unsigned)pid);
|
||||
@@ -535,7 +535,7 @@ static void drop_privileges(main_server_st* s)
|
||||
(int) s->config->gid, strerror(e));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
ret = setgroups(1, &s->config->gid);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
@@ -654,6 +654,7 @@ void request_reload(int signo)
|
||||
reload_conf = 1;
|
||||
}
|
||||
|
||||
|
||||
/* A UDP fd will not be forwarded to worker process before this number of
|
||||
* seconds has passed. That is to prevent a duplicate message messing the worker.
|
||||
*/
|
||||
@@ -667,76 +668,29 @@ int ret, e;
|
||||
struct sockaddr_storage cli_addr;
|
||||
struct sockaddr_storage our_addr;
|
||||
struct proc_st *proc_to_send = NULL;
|
||||
socklen_t cli_addr_size, our_addr_size = 0;
|
||||
socklen_t cli_addr_size, our_addr_size;
|
||||
uint8_t buffer[1024];
|
||||
char cmbuf[256];
|
||||
char tbuf[64];
|
||||
uint8_t *session_id = NULL;
|
||||
int session_id_size = 0;
|
||||
ssize_t buffer_size;
|
||||
int match_ip_only = 0;
|
||||
time_t now;
|
||||
struct iovec iov = { buffer, sizeof(buffer) };
|
||||
struct cmsghdr *cmsg;
|
||||
int sfd = -1;
|
||||
struct msghdr mh = {
|
||||
.msg_name = &cli_addr,
|
||||
.msg_namelen = sizeof(cli_addr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmbuf,
|
||||
.msg_controllen = sizeof(cmbuf),
|
||||
};
|
||||
|
||||
/* first receive from the correct client and connect socket */
|
||||
cli_addr_size = sizeof(cli_addr);
|
||||
ret = recvmsg(listener->fd, &mh, 0);
|
||||
our_addr_size = sizeof(our_addr);
|
||||
ret = oc_recvfrom_at(listener->fd, buffer, sizeof(buffer), 0,
|
||||
(struct sockaddr*)&cli_addr, &cli_addr_size,
|
||||
(struct sockaddr*)&our_addr, &our_addr_size,
|
||||
s->config->udp_port);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_INFO, "error receiving in UDP socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_size = ret;
|
||||
|
||||
/* find our address */
|
||||
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg != NULL; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
|
||||
#if defined(IP_PKTINFO)
|
||||
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
|
||||
struct in_pktinfo *pi = CMSG_DATA(cmsg);
|
||||
struct sockaddr_in *a = (struct sockaddr_in*)&our_addr;
|
||||
|
||||
a->sin_family = AF_INET;
|
||||
memcpy(&a->sin_addr, &pi->ipi_addr, sizeof(struct in_addr));
|
||||
a->sin_port = htons(s->config->udp_port);
|
||||
our_addr_size = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
}
|
||||
#elif defined(IP_RECVDSTADDR)
|
||||
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
|
||||
struct in_addr *pi = CMSG_DATA(cmsg);
|
||||
struct sockaddr_in *a = (struct sockaddr_in*)&our_addr;
|
||||
|
||||
a->sin_family = AF_INET;
|
||||
memcpy(&a->sin_addr, &pi->ipi_addr, sizeof(struct in_addr));
|
||||
a->sin_port = htons(s->config->udp_port);
|
||||
our_addr_size = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
if (cmsg->cmsg_level != IPPROTO_IPV6 || cmsg->cmsg_type != IPV6_RECVPKTINFO) {
|
||||
struct in6_pktinfo *pi = CMSG_DATA(cmsg);
|
||||
struct sockaddr_in6 *a = (struct sockaddr_in6*)&our_addr;
|
||||
|
||||
a->sin6_family = AF_INET6;
|
||||
memcpy(&a->sin6_addr, &pi->ipi6_addr, sizeof(struct in6_addr));
|
||||
a->sin6_port = htons(s->config->udp_port);
|
||||
our_addr_size = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* obtain the session id */
|
||||
if (buffer_size < RECORD_PAYLOAD_POS+HANDSHAKE_SESSION_ID_POS+GNUTLS_MAX_SESSION_ID+2) {
|
||||
mslog(s, NULL, LOG_INFO, "%s: too short UDP packet",
|
||||
@@ -1040,7 +994,7 @@ int main(int argc, char** argv)
|
||||
#ifdef HAVE_LIBWRAP
|
||||
allow_severity = LOG_DAEMON|LOG_INFO;
|
||||
deny_severity = LOG_DAEMON|LOG_WARNING;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (s->config->foreground == 0) {
|
||||
if (daemon(0, 0) == -1) {
|
||||
@@ -1051,7 +1005,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
write_pid_file();
|
||||
|
||||
|
||||
run_sec_mod(s);
|
||||
|
||||
ret = ctl_handler_init(s);
|
||||
|
||||
Reference in New Issue
Block a user