Message ID | 20180924064927.5536-1-cus@passwd.hu |
---|---|
State | Accepted |
Commit | 45fa756fa4dd88d3631f28fe569a04119634f7f7 |
Headers | show |
On Mon, Sep 24, 2018 at 08:49:27AM +0200, Marton Balint wrote: > These are based on the very similar UDP and RTP protocol functions. > > Signed-off-by: Marton Balint <cus@passwd.hu> > --- > libavformat/ip.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > libavformat/ip.h | 72 +++++++++++++++++++++++++ > 2 files changed, 231 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..70c5529b72 > --- /dev/null > +++ b/libavformat/ip.c > @@ -0,0 +1,159 @@ > +/* > + * 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" > +#include "libavutil/avstring.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, const char *buf, > + struct sockaddr_storage **address_list_ptr, > + int *address_list_size_ptr) > +{ > + struct addrinfo *ai = NULL; > + > + /* Resolve all of the IPs */ > + > + while (buf && buf[0]) { > + char* host = av_get_token(&buf, ","); > + if (!host) > + return AVERROR(ENOMEM); > + > + ai = ff_ip_resolve_host(log_ctx, host, 0, SOCK_DGRAM, AF_UNSPEC, 0); > + av_freep(&host); > + > + 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); > + } > + > + if (*buf) > + buf++; > + } > + > + return 0; > +} > + > +static int ip_parse_sources_and_blocks(void *log_ctx, const 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, const char *buf, IPSourceFilters *filters) > +{ > + return ip_parse_sources_and_blocks(log_ctx, buf, filters, 1); > +} > + > +int ff_ip_parse_blocks(void *log_ctx, const 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..b76cdab91c > --- /dev/null > +++ b/libavformat/ip.h > @@ -0,0 +1,72 @@ > +/* > + * 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. > + * @return 0 on success, < 0 AVERROR code on error. > + */ > +int ff_ip_parse_sources(void *log_ctx, const char *buf, IPSourceFilters *filters); > + > +/** > + * Parses the address[,address] source block list in buf and adds it to the > + * filters in the IPSourceFilters structure. > + * @return 0 on success, < 0 AVERROR code on error. > + */ > +int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters); Thanks [...]
On Mon, 24 Sep 2018, Michael Niedermayer wrote: > On Mon, Sep 24, 2018 at 08:49:27AM +0200, Marton Balint wrote: >> These are based on the very similar UDP and RTP protocol functions. >> >> Signed-off-by: Marton Balint <cus@passwd.hu> >> --- >> libavformat/ip.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> libavformat/ip.h | 72 +++++++++++++++++++++++++ >> 2 files changed, 231 insertions(+) >> create mode 100644 libavformat/ip.c >> create mode 100644 libavformat/ip.h [...] >> + * Parses the address[,address] source block list in buf and adds it to the >> + * filters in the IPSourceFilters structure. >> + * @return 0 on success, < 0 AVERROR code on error. >> + */ > >> +int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters); > > Thanks Ping for the whole series... Thanks, Marton
On Sun, 30 Sep 2018, Marton Balint wrote: > > On Mon, 24 Sep 2018, Michael Niedermayer wrote: > >> On Mon, Sep 24, 2018 at 08:49:27AM +0200, Marton Balint wrote: >>> These are based on the very similar UDP and RTP protocol functions. >>> >>> Signed-off-by: Marton Balint <cus@passwd.hu> >>> --- >>> libavformat/ip.c | 159 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ >>> libavformat/ip.h | 72 +++++++++++++++++++++++++ >>> 2 files changed, 231 insertions(+) >>> create mode 100644 libavformat/ip.c >>> create mode 100644 libavformat/ip.h > > [...] > >>> + * Parses the address[,address] source block list in buf and adds it to > the >>> + * filters in the IPSourceFilters structure. >>> + * @return 0 on success, < 0 AVERROR code on error. >>> + */ >> >>> +int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters > *filters); >> >> Thanks > > Ping for the whole series... Pushed the patchset. Regards, Marton
diff --git a/libavformat/ip.c b/libavformat/ip.c new file mode 100644 index 0000000000..70c5529b72 --- /dev/null +++ b/libavformat/ip.c @@ -0,0 +1,159 @@ +/* + * 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" +#include "libavutil/avstring.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, const char *buf, + struct sockaddr_storage **address_list_ptr, + int *address_list_size_ptr) +{ + struct addrinfo *ai = NULL; + + /* Resolve all of the IPs */ + + while (buf && buf[0]) { + char* host = av_get_token(&buf, ","); + if (!host) + return AVERROR(ENOMEM); + + ai = ff_ip_resolve_host(log_ctx, host, 0, SOCK_DGRAM, AF_UNSPEC, 0); + av_freep(&host); + + 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); + } + + if (*buf) + buf++; + } + + return 0; +} + +static int ip_parse_sources_and_blocks(void *log_ctx, const 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, const char *buf, IPSourceFilters *filters) +{ + return ip_parse_sources_and_blocks(log_ctx, buf, filters, 1); +} + +int ff_ip_parse_blocks(void *log_ctx, const 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..b76cdab91c --- /dev/null +++ b/libavformat/ip.h @@ -0,0 +1,72 @@ +/* + * 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. + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_ip_parse_sources(void *log_ctx, const char *buf, IPSourceFilters *filters); + +/** + * Parses the address[,address] source block list in buf and adds it to the + * filters in the IPSourceFilters structure. + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_ip_parse_blocks(void *log_ctx, const 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 */
These are based on the very similar UDP and RTP protocol functions. Signed-off-by: Marton Balint <cus@passwd.hu> --- libavformat/ip.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/ip.h | 72 +++++++++++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 libavformat/ip.c create mode 100644 libavformat/ip.h