From 4152c77defac24ace3b1b6b9cc81a4f614254e4f Mon Sep 17 00:00:00 2001 From: srijan-sivakumar Date: Sat, 18 Jul 2020 05:59:09 +0530 Subject: [PATCH 527/532] Events: Socket creation after getaddrinfo and IPv4 and IPv6 packet capture Issue: Currently, the socket creation is done prior to getaddrinfo function being invoked. This can cause mismatch in the protocol and address families of the created socket and the result of the getaddrinfo api. Also, the glustereventsd UDP server by default only captures IPv4 packets hence IPv6 packets are not even captured. Code Changes: 1. Modified the socket creation in such a way that the parameters taken in are dependent upon the result of the getaddrinfo function. 2. Created a subclass for adding address family in glustereventsd.py for both AF_INET and AF_INET6. 3. Modified addresses in the eventsapiconf.py.in Reasoning behind the approach: 1. If we are using getaddrinfo function then socket creation should happen only after we check if we received back valid addresses. Hence socket creation should come after the call to getaddrinfo 2. The listening server which pushes the events to the webhook has to listen for both IPv4 and IPv6 messages as we would not be sure as to what address family is picked in _gf_event. >Fixes: #1377 >Change-Id: I568dcd1a977c8832f0fef981e1f81cac7043c760 >Signed-off-by: srijan-sivakumar Upstream patch: https://review.gluster.org/c/glusterfs/+/24722 BUG: 1814744 Change-Id: I568dcd1a977c8832f0fef981e1f81cac7043c760 Signed-off-by: srijan-sivakumar Reviewed-on: https://code.engineering.redhat.com/gerrit/225567 Tested-by: RHGS Build Bot Reviewed-by: Ravishankar Narayanankutty --- events/src/eventsapiconf.py.in | 2 ++ events/src/glustereventsd.py | 37 ++++++++++++++++++++++++++++++------- libglusterfs/src/events.c | 27 +++++++++++++++++++-------- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/events/src/eventsapiconf.py.in b/events/src/eventsapiconf.py.in index 76b5954..700093b 100644 --- a/events/src/eventsapiconf.py.in +++ b/events/src/eventsapiconf.py.in @@ -28,6 +28,8 @@ def get_glusterd_workdir(): return glusterd_workdir SERVER_ADDRESS = "0.0.0.0" +SERVER_ADDRESSv4 = "0.0.0.0" +SERVER_ADDRESSv6 = "::1" DEFAULT_CONFIG_FILE = "@SYSCONF_DIR@/glusterfs/eventsconfig.json" CUSTOM_CONFIG_FILE_TO_SYNC = "/events/config.json" CUSTOM_CONFIG_FILE = get_glusterd_workdir() + CUSTOM_CONFIG_FILE_TO_SYNC diff --git a/events/src/glustereventsd.py b/events/src/glustereventsd.py index c4c7b65..341a3b6 100644 --- a/events/src/glustereventsd.py +++ b/events/src/glustereventsd.py @@ -13,6 +13,7 @@ from __future__ import print_function import sys import signal +import threading try: import socketserver except ImportError: @@ -23,10 +24,17 @@ from argparse import ArgumentParser, RawDescriptionHelpFormatter from eventtypes import all_events import handlers import utils -from eventsapiconf import SERVER_ADDRESS, PID_FILE +from eventsapiconf import SERVER_ADDRESSv4, SERVER_ADDRESSv6, PID_FILE from eventsapiconf import AUTO_BOOL_ATTRIBUTES, AUTO_INT_ATTRIBUTES from utils import logger, PidFile, PidFileLockFailed, boolify +# Subclass so that specifically IPv4 packets are captured +class UDPServerv4(socketserver.ThreadingUDPServer): + address_family = socket.AF_INET + +# Subclass so that specifically IPv6 packets are captured +class UDPServerv6(socketserver.ThreadingUDPServer): + address_family = socket.AF_INET6 class GlusterEventsRequestHandler(socketserver.BaseRequestHandler): @@ -89,6 +97,10 @@ def signal_handler_sigusr2(sig, frame): utils.restart_webhook_pool() +def UDP_server_thread(sock): + sock.serve_forever() + + def init_event_server(): utils.setup_logger() utils.load_all() @@ -99,15 +111,26 @@ def init_event_server(): sys.stderr.write("Unable to get Port details from Config\n") sys.exit(1) - # Start the Eventing Server, UDP Server + # Creating the Eventing Server, UDP Server for IPv4 packets + try: + serverv4 = UDPServerv4((SERVER_ADDRESSv4, port), + GlusterEventsRequestHandler) + except socket.error as e: + sys.stderr.write("Failed to start Eventsd for IPv4: {0}\n".format(e)) + sys.exit(1) + # Creating the Eventing Server, UDP Server for IPv6 packets try: - server = socketserver.ThreadingUDPServer( - (SERVER_ADDRESS, port), - GlusterEventsRequestHandler) + serverv6 = UDPServerv6((SERVER_ADDRESSv6, port), + GlusterEventsRequestHandler) except socket.error as e: - sys.stderr.write("Failed to start Eventsd: {0}\n".format(e)) + sys.stderr.write("Failed to start Eventsd for IPv6: {0}\n".format(e)) sys.exit(1) - server.serve_forever() + server_thread1 = threading.Thread(target=UDP_server_thread, + args=(serverv4,)) + server_thread2 = threading.Thread(target=UDP_server_thread, + args=(serverv6,)) + server_thread1.start() + server_thread2.start() def get_args(): diff --git a/libglusterfs/src/events.c b/libglusterfs/src/events.c index 6d1e383..4d720ca 100644 --- a/libglusterfs/src/events.c +++ b/libglusterfs/src/events.c @@ -40,6 +40,7 @@ _gf_event(eventtypes_t event, const char *fmt, ...) char *host = NULL; struct addrinfo hints; struct addrinfo *result = NULL; + struct addrinfo *iter_result_ptr = NULL; xlator_t *this = THIS; char *volfile_server_transport = NULL; @@ -51,13 +52,6 @@ _gf_event(eventtypes_t event, const char *fmt, ...) goto out; } - /* Initialize UDP socket */ - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - ret = EVENT_ERROR_SOCKET; - goto out; - } - if (ctx) { volfile_server_transport = ctx->cmd_args.volfile_server_transport; } @@ -66,7 +60,6 @@ _gf_event(eventtypes_t event, const char *fmt, ...) } /* host = NULL returns localhost */ - host = NULL; if (ctx && ctx->cmd_args.volfile_server && (strcmp(volfile_server_transport, "unix"))) { /* If it is client code then volfile_server is set @@ -84,6 +77,24 @@ _gf_event(eventtypes_t event, const char *fmt, ...) goto out; } + // iterate over the result and break when socket creation is success. + for (iter_result_ptr = result; iter_result_ptr != NULL; + iter_result_ptr = iter_result_ptr->ai_next) { + sock = socket(iter_result_ptr->ai_family, iter_result_ptr->ai_socktype, + iter_result_ptr->ai_protocol); + if (sock != -1) { + break; + } + } + /* + * If none of the addrinfo structures lead to a successful socket + * creation, socket creation has failed. + */ + if (sock < 0) { + ret = EVENT_ERROR_SOCKET; + goto out; + } + va_start(arguments, fmt); ret = gf_vasprintf(&msg, fmt, arguments); va_end(arguments); -- 1.8.3.1