From patchwork Sat Sep 22 21:53:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 10451 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:1286:0:0:0:0:0 with SMTP id 6-v6csp931882jap; Sat, 22 Sep 2018 14:53:42 -0700 (PDT) X-Google-Smtp-Source: ACcGV60JHga60eBkkSESeX5QG+Xaa94Z7UmpfUEkdHUON2ffOUbxjf1fRQXE/SlaFzfmPb/lfSta X-Received: by 2002:adf:8167:: with SMTP id 94-v6mr3210902wrm.127.1537653222759; Sat, 22 Sep 2018 14:53:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537653222; cv=none; d=google.com; s=arc-20160816; b=OR+/QUpVeNxVRRB9eniDUYsPIeqD1N5M2HFjc8w+vTS+RXEXGgycLK89ftx5ghMRzv tnuj0Min+x0UeIK6IbzXjdfdPxiEvXZ/5QqTYFQhNXEQD1zgUjlY6FODo0br77e0rw/L ybQBuZqy3hialiejGmzhA/pniPdDvSgkk4qJaNDq751UdC84dBClJrtS2JAkZbYaImuA ZfhHnyHHmzy5Zkvp9hZ17fPoTqpkg0l6E7AxSU0KBEl33YmXkKMgC3dIAkPxbN8qLYiY nCkodazKpqir9UmFLv1RXpFexVcoJkFvD5xaogPU4IFITasytRvGw9sIrtOMPeVtc4al TR6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:delivered-to; bh=2MHY5SWFwJLEg3BCYT1SwW2/qdyT9/Ofin09KZ4e79I=; b=xT5Po3NYGBNPVZVzuL+CHN50yUR2xNza+FNHPbU7EVfBe1zEwYICnvupa2CMuO4K19 5kN3NJASxbCerbK9Q8wrdyd20nI7iCR9HCjhqXgqyRuS1lmNc9eZX7PG2juJmKkQVM9C HRK3BH+b08zEsdwLsCfekb0ML9H3s7vPWoLGj7k12MCtDMgPqGYF8ZxetrztODGRfOVq WucPNjkWWipxWvjAnsFVYed/1TvPzx7ebQYuZdI24AXFkuYOAHl8RWTuqhUIBFdcN4ny D6zjDwqgb9slmO1MXdHb5e9IcAuY+10VXEC4GICBCD2elzaSUT43QEajYIvS7z91dPqn zOvA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o192-v6si9394704wmg.199.2018.09.22.14.53.42; Sat, 22 Sep 2018 14:53:42 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 696F168A624; Sun, 23 Sep 2018 00:53:25 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A849B68A571 for ; Sun, 23 Sep 2018 00:53:19 +0300 (EEST) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 63B97E0802; Sat, 22 Sep 2018 23:53:34 +0200 (CEST) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id GivP3Tw5qExZ; Sat, 22 Sep 2018 23:53:33 +0200 (CEST) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 0BCFCE04A9; Sat, 22 Sep 2018 23:53:33 +0200 (CEST) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 22 Sep 2018 23:53:22 +0200 Message-Id: <20180922215328.18053-1-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: References: Subject: [FFmpeg-devel] [PATCH 1/7] avformat/ip: factorize some IP filtering and resolving functions to a new file X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" These are based on the very similar UDP and RTP protocol functions. Signed-off-by: Marton Balint --- libavformat/ip.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/ip.h | 74 +++++++++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 libavformat/ip.c create mode 100644 libavformat/ip.h diff --git a/libavformat/ip.c b/libavformat/ip.c new file mode 100644 index 0000000000..d88055ebda --- /dev/null +++ b/libavformat/ip.c @@ -0,0 +1,165 @@ +/* + * IP common code + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software * Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ip.h" + +static int compare_addr(const struct sockaddr_storage *a, + const struct sockaddr_storage *b) +{ + if (a->ss_family != b->ss_family) + return 1; + if (a->ss_family == AF_INET) { + return (((const struct sockaddr_in *)a)->sin_addr.s_addr != + ((const struct sockaddr_in *)b)->sin_addr.s_addr); + } + +#if HAVE_STRUCT_SOCKADDR_IN6 + if (a->ss_family == AF_INET6) { + const uint8_t *s6_addr_a = ((const struct sockaddr_in6 *)a)->sin6_addr.s6_addr; + const uint8_t *s6_addr_b = ((const struct sockaddr_in6 *)b)->sin6_addr.s6_addr; + return memcmp(s6_addr_a, s6_addr_b, 16); + } +#endif + return 1; +} + +int ff_ip_check_source_lists(struct sockaddr_storage *source_addr_ptr, IPSourceFilters *s) +{ + int i; + if (s->nb_exclude_addrs) { + for (i = 0; i < s->nb_exclude_addrs; i++) { + if (!compare_addr(source_addr_ptr, &s->exclude_addrs[i])) + return 1; + } + } + if (s->nb_include_addrs) { + for (i = 0; i < s->nb_include_addrs; i++) { + if (!compare_addr(source_addr_ptr, &s->include_addrs[i])) + return 0; + } + return 1; + } + return 0; +} + +struct addrinfo *ff_ip_resolve_host(void *log_ctx, + const char *hostname, int port, + int type, int family, int flags) +{ + struct addrinfo hints = { 0 }, *res = 0; + int error; + char sport[16]; + const char *node = 0, *service = "0"; + + if (port > 0) { + snprintf(sport, sizeof(sport), "%d", port); + service = sport; + } + if ((hostname) && (hostname[0] != '\0') && (hostname[0] != '?')) { + node = hostname; + } + hints.ai_socktype = type; + hints.ai_family = family; + hints.ai_flags = flags; + if ((error = getaddrinfo(node, service, &hints, &res))) { + res = NULL; + av_log(log_ctx, AV_LOG_ERROR, "getaddrinfo(%s, %s): %s\n", + node ? node : "unknown", + service, + gai_strerror(error)); + } + + return res; +} + + +static int ip_parse_addr_list(void *log_ctx, char *buf, + struct sockaddr_storage **address_list_ptr, + int *address_list_size_ptr) +{ + struct addrinfo *ai = NULL; + char tmp = '\0', *p = buf, *next; + + /* Resolve all of the IPs */ + + while (p && p[0]) { + next = strchr(p, ','); + + if (next) { + tmp = *next; + *next = '\0'; + } + + ai = ff_ip_resolve_host(log_ctx, p, 0, SOCK_DGRAM, AF_UNSPEC, 0); + + if (next) { + *next = tmp; + p = next + 1; + } else { + p = NULL; + } + + if (ai) { + struct sockaddr_storage source_addr = {0}; + memcpy(&source_addr, ai->ai_addr, ai->ai_addrlen); + freeaddrinfo(ai); + av_dynarray2_add((void **)address_list_ptr, address_list_size_ptr, sizeof(source_addr), (uint8_t *)&source_addr); + if (!*address_list_ptr) + return AVERROR(ENOMEM); + } else { + return AVERROR(EINVAL); + } + } + + return 0; +} + +static int ip_parse_sources_and_blocks(void *log_ctx, char *buf, IPSourceFilters *filters, int parse_include_list) +{ + int ret; + if (parse_include_list) + ret = ip_parse_addr_list(log_ctx, buf, &filters->include_addrs, &filters->nb_include_addrs); + else + ret = ip_parse_addr_list(log_ctx, buf, &filters->exclude_addrs, &filters->nb_exclude_addrs); + + if (ret >= 0 && filters->nb_include_addrs && filters->nb_exclude_addrs) { + av_log(log_ctx, AV_LOG_ERROR, "Simultaneously including and excluding sources is not supported.\n"); + return AVERROR(EINVAL); + } + return ret; +} + +int ff_ip_parse_sources(void *log_ctx, char *buf, IPSourceFilters *filters) +{ + return ip_parse_sources_and_blocks(log_ctx, buf, filters, 1); +} + +int ff_ip_parse_blocks(void *log_ctx, char *buf, IPSourceFilters *filters) +{ + return ip_parse_sources_and_blocks(log_ctx, buf, filters, 0); +} + +void ff_ip_reset_filters(IPSourceFilters *filters) +{ + av_freep(&filters->exclude_addrs); + av_freep(&filters->include_addrs); + filters->nb_include_addrs = 0; + filters->nb_exclude_addrs = 0; +} diff --git a/libavformat/ip.h b/libavformat/ip.h new file mode 100644 index 0000000000..380143ff58 --- /dev/null +++ b/libavformat/ip.h @@ -0,0 +1,74 @@ +/* + * IP common code + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software * Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_IP_H +#define AVFORMAT_IP_H + +#include "network.h" + +/** + * Structure for storing IP (UDP) source filters or block lists. + */ +typedef struct IPSourceFilters { + int nb_include_addrs; + int nb_exclude_addrs; + struct sockaddr_storage *include_addrs; + struct sockaddr_storage *exclude_addrs; +} IPSourceFilters; + +/** + * Checks the source address against a given IP source filter. + * @return 0 if packet should be processed based on the filter, 1 if the packet + * can be dropped. + */ +int ff_ip_check_source_lists(struct sockaddr_storage *source_addr_ptr, IPSourceFilters *s); + +/** + * Resolves hostname into an addrinfo structure. + * @return addrinfo structure which should be freed by the user, NULL in case + * of error. + */ +struct addrinfo *ff_ip_resolve_host(void *log_ctx, + const char *hostname, int port, + int type, int family, int flags); + +/** + * Parses the address[,address] source list in buf and adds it to the filters + * in the IPSourceFilters structure. + * @param buf is the source list, which is not changed, but must be writable + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_ip_parse_sources(void *log_ctx, char *buf, IPSourceFilters *filters); + +/** + * Parses the address[,address] source block list in buf and adds it to the + * filters in the IPSourceFilters structure. + * @param buf is the source list, which is not changed, but must be writable + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_ip_parse_blocks(void *log_ctx, char *buf, IPSourceFilters *filters); + +/** + * Resets the IP filter list and frees the internal fields of an + * IPSourceFilters structure. + */ +void ff_ip_reset_filters(IPSourceFilters *filters); + +#endif /* AVFORMAT_IP_H */