From patchwork Fri Mar 20 10:25:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Doucha X-Patchwork-Id: 1258794 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48kKfS0TFvz9sRN for ; Fri, 20 Mar 2020 21:25:18 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 1236A3C5397 for ; Fri, 20 Mar 2020 11:25:15 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-4.smtp.seeweb.it (in-4.smtp.seeweb.it [IPv6:2001:4b78:1:20::4]) by picard.linux.it (Postfix) with ESMTP id 97E4C3C03B1 for ; Fri, 20 Mar 2020 11:25:13 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id 004851001962 for ; Fri, 20 Mar 2020 11:25:12 +0100 (CET) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 3F91AAB3D for ; Fri, 20 Mar 2020 10:25:12 +0000 (UTC) From: Martin Doucha To: ltp@lists.linux.it Date: Fri, 20 Mar 2020 11:25:09 +0100 Message-Id: <20200320102511.20568-1-mdoucha@suse.cz> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.0 required=7.0 tests=SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-4.smtp.seeweb.it Subject: [LTP] [PATCH v5 1/3] Create separate .c file for include/tst_net.h X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Signed-off-by: Martin Doucha --- Changes since v1: - new patch Changes since v2: - Also separate print_svar*() - Added tst_ prefix to functions separated into tst_net.c Changes since v3: - Split off tst_private.h from tst_net.h - Make some helper functions in tst_net.c static Changes since v4: - Licence and #include cleanup include/tst_net.h | 139 +-------------------------- include/tst_private.h | 31 ++++++ lib/tst_net.c | 135 ++++++++++++++++++++++++++ testcases/lib/tst_net_iface_prefix.c | 10 +- testcases/lib/tst_net_ip_prefix.c | 11 ++- testcases/lib/tst_net_vars.c | 65 +++++++------ 6 files changed, 213 insertions(+), 178 deletions(-) create mode 100644 include/tst_private.h create mode 100644 lib/tst_net.c diff --git a/include/tst_net.h b/include/tst_net.h index e1edc7200..e2100f641 100644 --- a/include/tst_net.h +++ b/include/tst_net.h @@ -4,141 +4,6 @@ */ #include -#include -#include -#include -#include -#define MAX_IPV4_PREFIX 32 -#define MAX_IPV6_PREFIX 128 - -#define tst_res_comment(...) { \ - fprintf(stderr, "# "); \ - tst_res(__VA_ARGS__); } \ - - -#define tst_brk_comment(...) { \ - fprintf(stderr, "# "); \ - tst_brk(TCONF, __VA_ARGS__); } \ - -static inline void print_svar(const char *name, const char *val) -{ - if (name && val) - printf("export %s=\"%s\"\n", name, val); -} - -static inline void print_svar_change(const char *name, const char *val) -{ - if (name && val) - printf("export %s=\"${%s:-%s}\"\n", name, name, val); -} - -/* - * Function bit_count is from ipcalc project, ipcalc.c. - */ -static inline int bit_count(uint32_t i) -{ - int c = 0; - unsigned int seen_one = 0; - - while (i > 0) { - if (i & 1) { - seen_one = 1; - c++; - } else { - if (seen_one) - return -1; - } - i >>= 1; - } - - return c; -} - -/* - * Function mask2prefix is from ipcalc project, ipcalc.c. - */ -static inline int mask2prefix(struct in_addr mask) -{ - return bit_count(ntohl(mask.s_addr)); -} - -/* - * Function ipv4_mask_to_int is from ipcalc project, ipcalc.c. - */ -static inline int ipv4_mask_to_int(const char *prefix) -{ - int ret; - struct in_addr in; - - ret = inet_pton(AF_INET, prefix, &in); - if (ret == 0) - return -1; - - return mask2prefix(in); -} - -/* - * Function safe_atoi is from ipcalc project, ipcalc.c. - */ -static inline int safe_atoi(const char *s, int *ret_i) -{ - char *x = NULL; - long l; - - errno = 0; - l = strtol(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - - if ((long)(int)l != l) - return -ERANGE; - - *ret_i = (int)l; - - return 0; -} - -/* - * Function get_prefix use code from ipcalc project, str_to_prefix/ipcalc.c. - */ -static inline int get_prefix(const char *ip_str, int is_ipv6) -{ - char *prefix_str = NULL; - int prefix = -1, r; - - prefix_str = strchr(ip_str, '/'); - if (!prefix_str) - return -1; - - *(prefix_str++) = '\0'; - - if (!is_ipv6 && strchr(prefix_str, '.')) - prefix = ipv4_mask_to_int(prefix_str); - else { - r = safe_atoi(prefix_str, &prefix); - if (r != 0) - tst_brk_comment("conversion error: '%s' is not integer", - prefix_str); - } - - if (prefix < 0 || ((is_ipv6 && prefix > MAX_IPV6_PREFIX) || - (!is_ipv6 && prefix > MAX_IPV4_PREFIX))) - tst_brk_comment("bad %s prefix: %s", is_ipv6 ? "IPv6" : "IPv4", - prefix_str); - - return prefix; -} - -static inline void get_in_addr(const char *ip_str, struct in_addr *ip) -{ - if (inet_pton(AF_INET, ip_str, ip) <= 0) - tst_brk_comment("bad IPv4 address: '%s'", ip_str); -} - -static inline void get_in6_addr(const char *ip_str, struct in6_addr *ip6) -{ - if (inet_pton(AF_INET6, ip_str, ip6) <= 0) - tst_brk_comment("bad IPv6 address: '%s'", ip_str); -} +void tst_get_in_addr(const char *ip_str, struct in_addr *ip); +void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6); diff --git a/include/tst_private.h b/include/tst_private.h new file mode 100644 index 000000000..00cd17fce --- /dev/null +++ b/include/tst_private.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2017-2019 Petr Vorel + * + * Internal helper functions for the shell library. Do not use directly + * in test programs. + */ + +#ifndef TST_PRIVATE_H_ +#define TST_PRIVATE_H_ + +#include + +#define MAX_IPV4_PREFIX 32 +#define MAX_IPV6_PREFIX 128 + +#define tst_res_comment(...) { \ + fprintf(stderr, "# "); \ + tst_res(__VA_ARGS__); } \ + + +#define tst_brk_comment(...) { \ + fprintf(stderr, "# "); \ + tst_brk(TCONF, __VA_ARGS__); } \ + +void tst_print_svar(const char *name, const char *val); +void tst_print_svar_change(const char *name, const char *val); + +int tst_get_prefix(const char *ip_str, int is_ipv6); + +#endif diff --git a/lib/tst_net.c b/lib/tst_net.c new file mode 100644 index 000000000..6913c7b40 --- /dev/null +++ b/lib/tst_net.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2017-2019 Petr Vorel + */ + +#include +#include +#include + +#define TST_NO_DEFAULT_MAIN +#include "tst_test.h" +#include "tst_net.h" +#include "tst_private.h" + +void tst_print_svar(const char *name, const char *val) +{ + if (name && val) + printf("export %s=\"%s\"\n", name, val); +} + +void tst_print_svar_change(const char *name, const char *val) +{ + if (name && val) + printf("export %s=\"${%s:-%s}\"\n", name, name, val); +} + +/* + * Function bit_count is from ipcalc project, ipcalc.c. + */ +static int tst_bit_count(uint32_t i) +{ + int c = 0; + unsigned int seen_one = 0; + + while (i > 0) { + if (i & 1) { + seen_one = 1; + c++; + } else { + if (seen_one) + return -1; + } + i >>= 1; + } + + return c; +} + +/* + * Function mask2prefix is from ipcalc project, ipcalc.c. + */ +static int tst_mask2prefix(struct in_addr mask) +{ + return tst_bit_count(ntohl(mask.s_addr)); +} + +/* + * Function ipv4_mask_to_int is from ipcalc project, ipcalc.c. + */ +static int tst_ipv4_mask_to_int(const char *prefix) +{ + int ret; + struct in_addr in; + + ret = inet_pton(AF_INET, prefix, &in); + if (ret == 0) + return -1; + + return tst_mask2prefix(in); +} + +/* + * Function safe_atoi is from ipcalc project, ipcalc.c. + */ +static int tst_safe_atoi(const char *s, int *ret_i) +{ + char *x = NULL; + long l; + + errno = 0; + l = strtol(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((long)(int)l != l) + return -ERANGE; + + *ret_i = (int)l; + + return 0; +} + +/* + * Function get_prefix use code from ipcalc project, str_to_prefix/ipcalc.c. + */ +int tst_get_prefix(const char *ip_str, int is_ipv6) +{ + char *prefix_str = NULL; + int prefix = -1, r; + + prefix_str = strchr(ip_str, '/'); + if (!prefix_str) + return -1; + + *(prefix_str++) = '\0'; + + if (!is_ipv6 && strchr(prefix_str, '.')) + prefix = tst_ipv4_mask_to_int(prefix_str); + else { + r = tst_safe_atoi(prefix_str, &prefix); + if (r != 0) + tst_brk_comment("conversion error: '%s' is not integer", + prefix_str); + } + + if (prefix < 0 || ((is_ipv6 && prefix > MAX_IPV6_PREFIX) || + (!is_ipv6 && prefix > MAX_IPV4_PREFIX))) + tst_brk_comment("bad %s prefix: %s", is_ipv6 ? "IPv6" : "IPv4", + prefix_str); + + return prefix; +} + +void tst_get_in_addr(const char *ip_str, struct in_addr *ip) +{ + if (inet_pton(AF_INET, ip_str, ip) <= 0) + tst_brk_comment("bad IPv4 address: '%s'", ip_str); +} + +void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6) +{ + if (inet_pton(AF_INET6, ip_str, ip6) <= 0) + tst_brk_comment("bad IPv6 address: '%s'", ip_str); +} diff --git a/testcases/lib/tst_net_iface_prefix.c b/testcases/lib/tst_net_iface_prefix.c index a40a8edc2..4b024872d 100644 --- a/testcases/lib/tst_net_iface_prefix.c +++ b/testcases/lib/tst_net_iface_prefix.c @@ -13,6 +13,7 @@ #include "tst_test.h" #include "tst_net.h" +#include "tst_private.h" static char *iface; static int prefix; @@ -124,7 +125,7 @@ int main(int argc, char *argv[]) prefix_str = strchr(ip_str, '/'); if (prefix_str) { - prefix = get_prefix(ip_str, is_ipv6); + prefix = tst_get_prefix(ip_str, is_ipv6); tst_res_comment(TINFO, "IP address '%s' contains prefix %d, using it and don't search for iface.\n", ip_str, prefix); @@ -136,11 +137,12 @@ int main(int argc, char *argv[]) /* checks for validity of IP string */ if (is_ipv6) - get_in6_addr(ip_str, &ip6); + tst_get_in6_addr(ip_str, &ip6); else - get_in_addr(ip_str, &ip); + tst_get_in_addr(ip_str, &ip); - print_svar_change(is_rhost ? "RHOST_IFACES" : "LHOST_IFACES", iface); + tst_print_svar_change(is_rhost ? "RHOST_IFACES" : "LHOST_IFACES", + iface); if (is_ipv6) print_ivar(is_rhost ? "IPV6_RPREFIX" : "IPV6_LPREFIX", prefix); else diff --git a/testcases/lib/tst_net_ip_prefix.c b/testcases/lib/tst_net_ip_prefix.c index 2ac06e724..59c70ba7d 100644 --- a/testcases/lib/tst_net_ip_prefix.c +++ b/testcases/lib/tst_net_ip_prefix.c @@ -10,6 +10,7 @@ #include "tst_test.h" #include "tst_net.h" +#include "tst_private.h" #define DEFAULT_IPV4_PREFIX 24 #define DEFAULT_IPV6_PREFIX 64 @@ -67,22 +68,22 @@ int main(int argc, char *argv[]) prefix_str = strchr(ip_str, '/'); if (prefix_str) - prefix = get_prefix(ip_str, is_ipv6); + prefix = tst_get_prefix(ip_str, is_ipv6); else prefix = is_ipv6 ? DEFAULT_IPV6_PREFIX : DEFAULT_IPV4_PREFIX; /* checks for validity of IP string */ if (is_ipv6) - get_in6_addr(ip_str, &ip6); + tst_get_in6_addr(ip_str, &ip6); else - get_in_addr(ip_str, &ip); + tst_get_in_addr(ip_str, &ip); if (is_ipv6) { print_ivar(is_rhost ? "IPV6_RPREFIX" : "IPV6_LPREFIX", prefix); - print_svar(is_rhost ? "IPV6_RHOST" : "IPV6_LHOST", ip_str); + tst_print_svar(is_rhost ? "IPV6_RHOST" : "IPV6_LHOST", ip_str); } else { print_ivar(is_rhost ? "IPV4_RPREFIX" : "IPV4_LPREFIX", prefix); - print_svar(is_rhost ? "IPV4_RHOST" : "IPV4_LHOST", ip_str); + tst_print_svar(is_rhost ? "IPV4_RHOST" : "IPV4_LHOST", ip_str); } exit(EXIT_SUCCESS); diff --git a/testcases/lib/tst_net_vars.c b/testcases/lib/tst_net_vars.c index 7c5507ed7..e7bf0e56a 100644 --- a/testcases/lib/tst_net_vars.c +++ b/testcases/lib/tst_net_vars.c @@ -22,6 +22,7 @@ #include "tst_test.h" #include "tst_net.h" +#include "tst_private.h" #define BASE_IPV4_PREFIX 8 #define BASE_IPV6_PREFIX 16 @@ -217,7 +218,7 @@ static char *get_ipv4_net16_unused(const struct in_addr *ip, DEFAULT_IPV4_UNUSED_PART2); sprintf(buf, "%s.0.0", net_unused); - get_in_addr(buf, &network); + tst_get_in_addr(buf, &network); if (!is_in_subnet_ipv4(ip, &mask, &network)) return strdup(net_unused); @@ -229,7 +230,7 @@ static char *get_ipv4_net16_unused(const struct in_addr *ip, (rand() % 128) + (((ip->s_addr >> 8) & 0xff) < 128 ? 128 : 0)); sprintf(buf, "%s.0.0", net_unused); - get_in_addr(buf, &network); + tst_get_in_addr(buf, &network); if (!is_in_subnet_ipv4(ip, &mask, &network)) return strdup(net_unused); @@ -239,7 +240,7 @@ static char *get_ipv4_net16_unused(const struct in_addr *ip, < 128 ? 128 : 0), DEFAULT_IPV4_UNUSED_PART2); sprintf(buf, "%s.0.0", net_unused); - get_in_addr(buf, &network); + tst_get_in_addr(buf, &network); if (!is_in_subnet_ipv4(ip, &mask, &network)) return strdup(net_unused); @@ -281,7 +282,7 @@ static char *get_ipv6_net32_unused(const struct in6_addr *ip6, DEFAULT_IPV6_UNUSED_PART2); sprintf(buf, "%s::", net_unused); - get_in6_addr(buf, &network); + tst_get_in6_addr(buf, &network); if (!is_in_subnet_ipv6(ip6, &mask, &network)) return strdup(net_unused); @@ -294,7 +295,7 @@ static char *get_ipv6_net32_unused(const struct in6_addr *ip6, DEFAULT_IPV6_UNUSED_PART2); sprintf(buf, "%s::", net_unused); - get_in6_addr(buf, &network); + tst_get_in6_addr(buf, &network); if (!is_in_subnet_ipv6(ip6, &mask, &network)) return strdup(net_unused); @@ -305,7 +306,7 @@ static char *get_ipv6_net32_unused(const struct in6_addr *ip6, 128 : 0), DEFAULT_IPV6_UNUSED_PART2); sprintf(buf, "%s::", net_unused); - get_in6_addr(buf, &network); + tst_get_in6_addr(buf, &network); if (!is_in_subnet_ipv6(ip6, &mask, &network)) return strdup(net_unused); @@ -503,8 +504,8 @@ static void get_ipv4_info(const char *lip_str, const char *rip_str, int lprefix, lprefix_round = round_down_prefix(lprefix, 0); rprefix_round = round_down_prefix(rprefix, 0); - get_in_addr(lip_str, &lip); - get_in_addr(rip_str, &rip); + tst_get_in_addr(lip_str, &lip); + tst_get_in_addr(rip_str, &rip); vars.ipv4_lbroadcast = get_ipv4_broadcast(lip, lprefix); vars.ipv4_rbroadcast = get_ipv4_broadcast(rip, rprefix); @@ -530,8 +531,8 @@ static void get_ipv6_info(const char *lip_str, const char *rip_str, lprefix_round = round_down_prefix(lprefix, 1); rprefix_round = round_down_prefix(rprefix, 1); - get_in6_addr(lip_str, &lip); - get_in6_addr(rip_str, &rip); + tst_get_in6_addr(lip_str, &lip); + tst_get_in6_addr(rip_str, &rip); vars.ipv6_lnetmask = get_ipv6_netmask(lprefix); vars.ipv6_rnetmask = get_ipv6_netmask(rprefix); @@ -548,23 +549,23 @@ static void get_ipv6_info(const char *lip_str, const char *rip_str, static void print_vars(int is_ipv6) { if (is_ipv6) { - print_svar("IPV6_LNETMASK", vars.ipv6_lnetmask); - print_svar_change("IPV6_RNETMASK", vars.ipv6_rnetmask); - print_svar("IPV6_LNETWORK", vars.ipv6_lnetwork); - print_svar("IPV6_RNETWORK", vars.ipv6_rnetwork); - print_svar("LHOST_IPV6_HOST", vars.lhost_ipv6_host); - print_svar("RHOST_IPV6_HOST", vars.rhost_ipv6_host); - print_svar("IPV6_NET32_UNUSED", vars.ipv6_net32_unused); + tst_print_svar("IPV6_LNETMASK", vars.ipv6_lnetmask); + tst_print_svar_change("IPV6_RNETMASK", vars.ipv6_rnetmask); + tst_print_svar("IPV6_LNETWORK", vars.ipv6_lnetwork); + tst_print_svar("IPV6_RNETWORK", vars.ipv6_rnetwork); + tst_print_svar("LHOST_IPV6_HOST", vars.lhost_ipv6_host); + tst_print_svar("RHOST_IPV6_HOST", vars.rhost_ipv6_host); + tst_print_svar("IPV6_NET32_UNUSED", vars.ipv6_net32_unused); } else { - print_svar("IPV4_LBROADCAST", vars.ipv4_lbroadcast); - print_svar_change("IPV4_RBROADCAST", vars.ipv4_rbroadcast); - print_svar("IPV4_LNETMASK", vars.ipv4_lnetmask); - print_svar_change("IPV4_RNETMASK", vars.ipv4_rnetmask); - print_svar("IPV4_LNETWORK", vars.ipv4_lnetwork); - print_svar("IPV4_RNETWORK", vars.ipv4_rnetwork); - print_svar("LHOST_IPV4_HOST", vars.lhost_ipv4_host); - print_svar("RHOST_IPV4_HOST", vars.rhost_ipv4_host); - print_svar("IPV4_NET16_UNUSED", vars.ipv4_net16_unused); + tst_print_svar("IPV4_LBROADCAST", vars.ipv4_lbroadcast); + tst_print_svar_change("IPV4_RBROADCAST", vars.ipv4_rbroadcast); + tst_print_svar("IPV4_LNETMASK", vars.ipv4_lnetmask); + tst_print_svar_change("IPV4_RNETMASK", vars.ipv4_rnetmask); + tst_print_svar("IPV4_LNETWORK", vars.ipv4_lnetwork); + tst_print_svar("IPV4_RNETWORK", vars.ipv4_rnetwork); + tst_print_svar("LHOST_IPV4_HOST", vars.lhost_ipv4_host); + tst_print_svar("RHOST_IPV4_HOST", vars.rhost_ipv4_host); + tst_print_svar("IPV4_NET16_UNUSED", vars.ipv4_net16_unused); } } @@ -586,19 +587,19 @@ int main(int argc, char *argv[]) rip_str = argv[2]; is_ipv6 = !!strchr(lip_str, ':'); - lprefix = get_prefix(lip_str, is_ipv6); - rprefix = get_prefix(rip_str, is_ipv6); + lprefix = tst_get_prefix(lip_str, is_ipv6); + rprefix = tst_get_prefix(rip_str, is_ipv6); if (is_ipv6) - get_in6_addr(lip_str, &ip6); + tst_get_in6_addr(lip_str, &ip6); else - get_in_addr(lip_str, &ip); + tst_get_in_addr(lip_str, &ip); tmp = !!strchr(rip_str, ':'); if (tmp) - get_in6_addr(rip_str, &ip6); + tst_get_in6_addr(rip_str, &ip6); else - get_in_addr(rip_str, &ip); + tst_get_in_addr(rip_str, &ip); if (is_ipv6 != tmp) tst_brk_comment("mixed IPv4 and IPv6 addresses ('%s', '%s')", From patchwork Fri Mar 20 10:25:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Doucha X-Patchwork-Id: 1258795 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48kKff1G7Dz9sPF for ; Fri, 20 Mar 2020 21:25:30 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 59F2D3C538D for ; Fri, 20 Mar 2020 11:25:26 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-5.smtp.seeweb.it (in-5.smtp.seeweb.it [IPv6:2001:4b78:1:20::5]) by picard.linux.it (Postfix) with ESMTP id 9632E3C0270 for ; Fri, 20 Mar 2020 11:25:13 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-5.smtp.seeweb.it (Postfix) with ESMTPS id BDDB260149A for ; Fri, 20 Mar 2020 11:25:12 +0100 (CET) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 4C54FAC79 for ; Fri, 20 Mar 2020 10:25:12 +0000 (UTC) From: Martin Doucha To: ltp@lists.linux.it Date: Fri, 20 Mar 2020 11:25:10 +0100 Message-Id: <20200320102511.20568-2-mdoucha@suse.cz> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200320102511.20568-1-mdoucha@suse.cz> References: <20200320102511.20568-1-mdoucha@suse.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-5.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.0 required=7.0 tests=SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-5.smtp.seeweb.it Subject: [LTP] [PATCH v5 2/3] Add socket address initialization functions to tst_net library X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Signed-off-by: Martin Doucha --- Changes since v1: - new patch Changes since v2: - Added tst_ prefix to the new functions Changes since v3: - Added #define protection against multiple #includes to tst_net.h include/tst_net.h | 21 ++++++++++++++ lib/tst_net.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/include/tst_net.h b/include/tst_net.h index e2100f641..855f4fc13 100644 --- a/include/tst_net.h +++ b/include/tst_net.h @@ -3,7 +3,28 @@ * Copyright (c) 2017-2019 Petr Vorel */ +#ifndef TST_NET_H_ +#define TST_NET_H_ + #include +#include +#include +#include void tst_get_in_addr(const char *ip_str, struct in_addr *ip); void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6); + +/* + * Find valid connection address for a given bound socket + */ +socklen_t tst_get_connect_address(int sock, struct sockaddr_storage *addr); + +/* + * Initialize AF_INET/AF_INET6 socket address structure with address and port + */ +void tst_init_sockaddr_inet(struct sockaddr_in *sa, const char *ip_str, uint16_t port); +void tst_init_sockaddr_inet_bin(struct sockaddr_in *sa, uint32_t ip_val, uint16_t port); +void tst_init_sockaddr_inet6(struct sockaddr_in6 *sa, const char *ip_str, uint16_t port); +void tst_init_sockaddr_inet6_bin(struct sockaddr_in6 *sa, const struct in6_addr *ip_val, uint16_t port); + +#endif diff --git a/lib/tst_net.c b/lib/tst_net.c index 6913c7b40..22c990e62 100644 --- a/lib/tst_net.c +++ b/lib/tst_net.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017-2019 Petr Vorel + * Copyright (c) 2019 Martin Doucha */ #include @@ -133,3 +134,73 @@ void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6) if (inet_pton(AF_INET6, ip_str, ip6) <= 0) tst_brk_comment("bad IPv6 address: '%s'", ip_str); } + +socklen_t tst_get_connect_address(int sock, struct sockaddr_storage *addr) +{ + struct sockaddr_in *inet_ptr; + struct sockaddr_in6 *inet6_ptr; + size_t tmp_size; + socklen_t ret = sizeof(*addr); + + SAFE_GETSOCKNAME(sock, (struct sockaddr*)addr, &ret); + + /* Sanitize wildcard addresses */ + switch (addr->ss_family) { + case AF_INET: + inet_ptr = (struct sockaddr_in*)addr; + + switch (ntohl(inet_ptr->sin_addr.s_addr)) { + case INADDR_ANY: + case INADDR_BROADCAST: + inet_ptr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + break; + } + + break; + + case AF_INET6: + inet6_ptr = (struct sockaddr_in6*)addr; + tmp_size = sizeof(struct in6_addr); + + if (!memcmp(&inet6_ptr->sin6_addr, &in6addr_any, tmp_size)) { + memcpy(&inet6_ptr->sin6_addr, &in6addr_loopback, + tmp_size); + } + + break; + } + + return ret; +} + +void tst_init_sockaddr_inet(struct sockaddr_in *sa, const char *ip_str, uint16_t port) +{ + memset(sa, 0, sizeof(struct sockaddr_in)); + sa->sin_family = AF_INET; + sa->sin_port = htons(port); + tst_get_in_addr(ip_str, &sa->sin_addr); +} + +void tst_init_sockaddr_inet_bin(struct sockaddr_in *sa, uint32_t ip_val, uint16_t port) +{ + memset(sa, 0, sizeof(struct sockaddr_in)); + sa->sin_family = AF_INET; + sa->sin_port = htons(port); + sa->sin_addr.s_addr = htonl(ip_val); +} + +void tst_init_sockaddr_inet6(struct sockaddr_in6 *sa, const char *ip_str, uint16_t port) +{ + memset(sa, 0, sizeof(struct sockaddr_in6)); + sa->sin6_family = AF_INET6; + sa->sin6_port = htons(port); + tst_get_in6_addr(ip_str, &sa->sin6_addr); +} + +void tst_init_sockaddr_inet6_bin(struct sockaddr_in6 *sa, const struct in6_addr *ip_val, uint16_t port) +{ + memset(sa, 0, sizeof(struct sockaddr_in6)); + sa->sin6_family = AF_INET6; + sa->sin6_port = htons(port); + memcpy(&sa->sin6_addr, ip_val, sizeof(struct in6_addr)); +} From patchwork Fri Mar 20 10:25:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Doucha X-Patchwork-Id: 1258796 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48kKfs4QWKz9sPF for ; Fri, 20 Mar 2020 21:25:41 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 00A843C539A for ; Fri, 20 Mar 2020 11:25:38 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-6.smtp.seeweb.it (in-6.smtp.seeweb.it [217.194.8.6]) by picard.linux.it (Postfix) with ESMTP id B77953C0889 for ; Fri, 20 Mar 2020 11:25:13 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-6.smtp.seeweb.it (Postfix) with ESMTPS id E2F221402018 for ; Fri, 20 Mar 2020 11:25:12 +0100 (CET) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 654DBACB8 for ; Fri, 20 Mar 2020 10:25:12 +0000 (UTC) From: Martin Doucha To: ltp@lists.linux.it Date: Fri, 20 Mar 2020 11:25:11 +0100 Message-Id: <20200320102511.20568-3-mdoucha@suse.cz> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200320102511.20568-1-mdoucha@suse.cz> References: <20200320102511.20568-1-mdoucha@suse.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-6.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.0 required=7.0 tests=SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-6.smtp.seeweb.it Subject: [LTP] [PATCH v5 3/3] Add connection tests for bind() X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Add two new test programs to verify that bind() will open sockets for incoming connections. Both programs follow the same test scenario: - Create and bind() a socket - Wait for connection from peer thread - Send request to peer thread - Receive and verify response from peer thread bind04 tests stream-oriented sockets (SOCK_STREAM and SOCK_SEQPACKET). bind05 tests datagram-oriented sockets (SOCK_DGRAM). Both programs test the following socket types: - AF_UNIX (pathname and abstract addresses) - AF_INET (loopback) - AF_INET6 (loopback) Signed-off-by: Martin Doucha --- Changes since v1: - added UDPLITE and SCTP test cases - common constants and test_case data structure moved to libbind.h Changes since v2: - Code style fixes - Makefile fix Changes since v4: - Use SAFE_ACCEPT() runtest/syscalls | 2 + testcases/kernel/syscalls/bind/.gitignore | 2 + testcases/kernel/syscalls/bind/Makefile | 2 + testcases/kernel/syscalls/bind/bind04.c | 169 ++++++++++++++++++++ testcases/kernel/syscalls/bind/bind05.c | 186 ++++++++++++++++++++++ testcases/kernel/syscalls/bind/libbind.h | 29 ++++ 6 files changed, 390 insertions(+) create mode 100644 testcases/kernel/syscalls/bind/bind04.c create mode 100644 testcases/kernel/syscalls/bind/bind05.c create mode 100644 testcases/kernel/syscalls/bind/libbind.h diff --git a/runtest/syscalls b/runtest/syscalls index 6f2dcd82a..354ec824d 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -31,6 +31,8 @@ alarm07 alarm07 bind01 bind01 bind02 bind02 bind03 bind03 +bind04 bind04 +bind05 bind05 bpf_map01 bpf_map01 bpf_prog01 bpf_prog01 diff --git a/testcases/kernel/syscalls/bind/.gitignore b/testcases/kernel/syscalls/bind/.gitignore index 4ebea9ee7..e18ceea56 100644 --- a/testcases/kernel/syscalls/bind/.gitignore +++ b/testcases/kernel/syscalls/bind/.gitignore @@ -1,3 +1,5 @@ /bind01 /bind02 /bind03 +/bind04 +/bind05 diff --git a/testcases/kernel/syscalls/bind/Makefile b/testcases/kernel/syscalls/bind/Makefile index 044619fb8..fffa146ad 100644 --- a/testcases/kernel/syscalls/bind/Makefile +++ b/testcases/kernel/syscalls/bind/Makefile @@ -5,4 +5,6 @@ top_srcdir ?= ../../../.. include $(top_srcdir)/include/mk/testcases.mk +bind04 bind05: CFLAGS += -pthread + include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/bind/bind04.c b/testcases/kernel/syscalls/bind/bind04.c new file mode 100644 index 000000000..51f19c6cd --- /dev/null +++ b/testcases/kernel/syscalls/bind/bind04.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019 Martin Doucha + */ + +/* + * Create and bind socket for various standard stream protocols. + * Then connect to it and send some test data. + */ + +#include +#include +#include +#include + +#include "tst_test.h" +#include "tst_net.h" +#include "tst_safe_pthread.h" +#include "libbind.h" + +static struct sockaddr_un unix_addr = { + .sun_family = AF_UNIX, + .sun_path = MAIN_SOCKET_FILE +}; +static struct sockaddr_un abstract_addr = { + .sun_family = AF_UNIX, + .sun_path = ABSTRACT_SOCKET_PATH +}; +static struct sockaddr_in ipv4_addr; +static struct sockaddr_in ipv4_any_addr; +static struct sockaddr_in6 ipv6_addr; +static struct sockaddr_in6 ipv6_any_addr; + +static struct test_case testcase_list[] = { + /* UNIX sockets */ + {SOCK_STREAM, 0, (struct sockaddr *)&unix_addr, sizeof(unix_addr), + "AF_UNIX pathname stream"}, + {SOCK_SEQPACKET, 0, (struct sockaddr *)&unix_addr, sizeof(unix_addr), + "AF_UNIX pathname seqpacket"}, + {SOCK_STREAM, 0, (struct sockaddr *)&abstract_addr, + sizeof(abstract_addr), "AF_UNIX abstract stream"}, + {SOCK_SEQPACKET, 0, (struct sockaddr *)&abstract_addr, + sizeof(abstract_addr), "AF_UNIX abstract seqpacket"}, + + /* IPv4 sockets */ + {SOCK_STREAM, 0, (struct sockaddr *)&ipv4_addr, sizeof(ipv4_addr), + "IPv4 loop TCP variant 1"}, + {SOCK_STREAM, IPPROTO_TCP, (struct sockaddr *)&ipv4_addr, + sizeof(ipv4_addr), "IPv4 loop TCP variant 2"}, + {SOCK_STREAM, IPPROTO_SCTP, (struct sockaddr *)&ipv4_addr, + sizeof(ipv4_addr), "IPv4 loop SCTP"}, + {SOCK_STREAM, 0, (struct sockaddr *)&ipv4_any_addr, + sizeof(ipv4_any_addr), "IPv4 any TCP variant 1"}, + {SOCK_STREAM, IPPROTO_TCP, (struct sockaddr *)&ipv4_any_addr, + sizeof(ipv4_any_addr), "IPv4 any TCP variant 2"}, + {SOCK_STREAM, IPPROTO_SCTP, (struct sockaddr *)&ipv4_any_addr, + sizeof(ipv4_any_addr), "IPv4 any SCTP"}, + + /* IPv6 sockets */ + {SOCK_STREAM, 0, (struct sockaddr *)&ipv6_addr, sizeof(ipv6_addr), + "IPv6 loop TCP variant 1"}, + {SOCK_STREAM, IPPROTO_TCP, (struct sockaddr *)&ipv6_addr, + sizeof(ipv6_addr), "IPv6 loop TCP variant 2"}, + {SOCK_STREAM, IPPROTO_SCTP, (struct sockaddr *)&ipv6_addr, + sizeof(ipv6_addr), "IPv6 loop SCTP"}, + {SOCK_STREAM, 0, (struct sockaddr *)&ipv6_any_addr, + sizeof(ipv6_any_addr), "IPv6 any TCP variant 1"}, + {SOCK_STREAM, IPPROTO_TCP, (struct sockaddr *)&ipv6_any_addr, + sizeof(ipv6_any_addr), "IPv6 any TCP variant 2"}, + {SOCK_STREAM, IPPROTO_SCTP, (struct sockaddr *)&ipv6_any_addr, + sizeof(ipv6_any_addr), "IPv6 any SCTP"} +}; + +static void setup(void) +{ + srand(time(0)); + + tst_init_sockaddr_inet(&ipv4_addr, IPV4_ADDRESS, 0); + tst_init_sockaddr_inet_bin(&ipv4_any_addr, INADDR_ANY, 0); + tst_init_sockaddr_inet6_bin(&ipv6_addr, &in6addr_loopback, 0); + tst_init_sockaddr_inet6_bin(&ipv6_any_addr, &in6addr_any, 0); +} + +static void *peer_thread(void *tc_ptr) +{ + const struct test_case *tc = tc_ptr; + int sock; + unsigned int request; + const char *response; + + sock = SAFE_SOCKET(tc->address->sa_family, tc->type, tc->protocol); + SAFE_CONNECT(sock, tc->address, tc->addrlen); + SAFE_READ(1, sock, &request, sizeof(request)); + + if (request < ARRAY_SIZE(testcase_list)) + response = testcase_list[request].description; + else + response = "Invalid request value"; + + SAFE_WRITE(1, sock, response, strlen(response) + 1); + SAFE_CLOSE(sock); + return NULL; +} + +static void test_bind(unsigned int n) +{ + struct test_case tc_copy, *tc = testcase_list + n; + struct sockaddr_storage listen_addr, remote_addr; + struct sockaddr_un *tmp_addr; + socklen_t remote_len = sizeof(struct sockaddr_storage); + int listen_sock, sock, size; + unsigned int rand_index; + pthread_t thread_id; + char buffer[BUFFER_SIZE]; + const char *exp_data; + + tst_res(TINFO, "Testing %s", tc->description); + listen_sock = SAFE_SOCKET(tc->address->sa_family, tc->type, + tc->protocol); + + TEST(bind(listen_sock, tc->address, tc->addrlen)); + + if (TST_RET) { + tst_res(TFAIL | TERRNO, "bind() failed"); + SAFE_CLOSE(listen_sock); + return; + } + + /* + * IPv4/IPv6 tests use wildcard addresses, resolve a valid connection + * address for peer thread + */ + memcpy(&tc_copy, tc, sizeof(struct test_case)); + tc_copy.addrlen = tst_get_connect_address(listen_sock, &listen_addr); + tc_copy.address = (struct sockaddr *)&listen_addr; + + SAFE_LISTEN(listen_sock, 1); + SAFE_PTHREAD_CREATE(&thread_id, NULL, peer_thread, &tc_copy); + sock = SAFE_ACCEPT(listen_sock, (struct sockaddr *)&remote_addr, + &remote_len); + + rand_index = rand() % ARRAY_SIZE(testcase_list); + SAFE_WRITE(1, sock, &rand_index, sizeof(rand_index)); + + size = SAFE_READ(0, sock, buffer, BUFFER_SIZE - 1); + buffer[size] = '\0'; + exp_data = testcase_list[rand_index].description; + + if (!strcmp(buffer, exp_data)) + tst_res(TPASS, "Communication successful"); + else + tst_res(TFAIL, "Received invalid data. Expected: \"%s\". " + "Received: \"%s\"", exp_data, buffer); + + SAFE_CLOSE(sock); + SAFE_CLOSE(listen_sock); + pthread_join(thread_id, NULL); + tmp_addr = (struct sockaddr_un *)tc->address; + + if (tc->address->sa_family == AF_UNIX && tmp_addr->sun_path[0]) + SAFE_UNLINK(tmp_addr->sun_path); +} + +static struct tst_test test = { + .test = test_bind, + .tcnt = ARRAY_SIZE(testcase_list), + .needs_tmpdir = 1, + .setup = setup, +}; diff --git a/testcases/kernel/syscalls/bind/bind05.c b/testcases/kernel/syscalls/bind/bind05.c new file mode 100644 index 000000000..16c9c711d --- /dev/null +++ b/testcases/kernel/syscalls/bind/bind05.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019 Martin Doucha + */ + +/* + * Create and bind socket for various standard datagram protocols. + * Then connect to it and send some test data. + */ + +#include +#include +#include +#include + +#include "tst_test.h" +#include "tst_net.h" +#include "tst_safe_pthread.h" +#include "libbind.h" + +static struct sockaddr_un unix_addr = { + .sun_family = AF_UNIX, + .sun_path = MAIN_SOCKET_FILE +}; +static struct sockaddr_un abstract_addr = { + .sun_family = AF_UNIX, + .sun_path = ABSTRACT_SOCKET_PATH +}; +static struct sockaddr_un peer_addr = { + .sun_family = AF_UNIX, + .sun_path = PEER_SOCKET_FILE +}; +static struct sockaddr_in ipv4_addr; +static struct sockaddr_in ipv4_any_addr; +static struct sockaddr_in6 ipv6_addr; +static struct sockaddr_in6 ipv6_any_addr; + +static struct test_case testcase_list[] = { + /* UNIX sockets */ + {SOCK_DGRAM, 0, (struct sockaddr *)&unix_addr, sizeof(unix_addr), + "AF_UNIX pathname datagram"}, + {SOCK_DGRAM, 0, (struct sockaddr *)&abstract_addr, + sizeof(abstract_addr), "AF_UNIX abstract datagram"}, + + /* IPv4 sockets */ + {SOCK_DGRAM, 0, (struct sockaddr *)&ipv4_addr, sizeof(ipv4_addr), + "IPv4 loop UDP variant 1"}, + {SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv4_addr, + sizeof(ipv4_addr), "IPv4 loop UDP variant 2"}, + {SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv4_addr, + sizeof(ipv4_addr), "IPv4 loop UDP-Lite"}, + {SOCK_DGRAM, 0, (struct sockaddr *)&ipv4_any_addr, + sizeof(ipv4_any_addr), "IPv4 any UDP variant 1"}, + {SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv4_any_addr, + sizeof(ipv4_any_addr), "IPv4 any UDP variant 2"}, + {SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv4_any_addr, + sizeof(ipv4_any_addr), "IPv4 any UDP-Lite"}, + + /* IPv6 sockets */ + {SOCK_DGRAM, 0, (struct sockaddr *)&ipv6_addr, sizeof(ipv6_addr), + "IPv6 loop UDP variant 1"}, + {SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv6_addr, + sizeof(ipv6_addr), "IPv6 loop UDP variant 2"}, + {SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv6_addr, + sizeof(ipv6_addr), "IPv6 loop UDP-Lite"}, + {SOCK_DGRAM, 0, (struct sockaddr *)&ipv6_any_addr, + sizeof(ipv6_any_addr), "IPv6 any UDP variant 1"}, + {SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv6_any_addr, + sizeof(ipv6_any_addr), "IPv6 any UDP variant 2"}, + {SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv6_any_addr, + sizeof(ipv6_any_addr), "IPv6 any UDP-Lite"} +}; + +static void setup(void) +{ + srand(time(0)); + + tst_init_sockaddr_inet(&ipv4_addr, IPV4_ADDRESS, 0); + tst_init_sockaddr_inet_bin(&ipv4_any_addr, INADDR_ANY, 0); + tst_init_sockaddr_inet6_bin(&ipv6_addr, &in6addr_loopback, 0); + tst_init_sockaddr_inet6_bin(&ipv6_any_addr, &in6addr_any, 0); +} + +static void *peer_thread(void *tc_ptr) +{ + const struct test_case *tc = tc_ptr; + int sock; + unsigned int request = 0; + const char *response; + + sock = SAFE_SOCKET(tc->address->sa_family, tc->type, tc->protocol); + + /* + * Both sides of AF_UNIX/SOCK_DGRAM socket must be bound for + * bidirectional communication + */ + if (tc->address->sa_family == AF_UNIX) + SAFE_BIND(sock, (struct sockaddr *)&peer_addr, + sizeof(struct sockaddr_un)); + + SAFE_CONNECT(sock, tc->address, tc->addrlen); + SAFE_WRITE(1, sock, &request, sizeof(request)); + SAFE_READ(1, sock, &request, sizeof(request)); + + if (request < ARRAY_SIZE(testcase_list)) + response = testcase_list[request].description; + else + response = "Invalid request value"; + + SAFE_WRITE(1, sock, response, strlen(response) + 1); + SAFE_CLOSE(sock); + + if (tc->address->sa_family == AF_UNIX) + SAFE_UNLINK(PEER_SOCKET_FILE); + + return NULL; +} + +static void test_bind(unsigned int n) +{ + struct test_case tc_copy, *tc = testcase_list + n; + struct sockaddr_storage listen_addr, remote_addr; + struct sockaddr_un *tmp_addr; + socklen_t remote_len = sizeof(struct sockaddr_storage); + int sock, size; + unsigned int rand_index; + pthread_t thread_id; + char buffer[BUFFER_SIZE]; + const char *exp_data; + + tst_res(TINFO, "Testing %s", tc->description); + sock = SAFE_SOCKET(tc->address->sa_family, tc->type, tc->protocol); + + TEST(bind(sock, tc->address, tc->addrlen)); + + if (TST_RET) { + tst_res(TFAIL | TERRNO, "bind() failed"); + SAFE_CLOSE(sock); + return; + } + + /* + * IPv4/IPv6 tests use wildcard addresses, resolve a valid connection + * address for peer thread + */ + memcpy(&tc_copy, tc, sizeof(struct test_case)); + tc_copy.addrlen = tst_get_connect_address(sock, &listen_addr); + tc_copy.address = (struct sockaddr *)&listen_addr; + + SAFE_PTHREAD_CREATE(&thread_id, NULL, peer_thread, &tc_copy); + size = recvfrom(sock, &rand_index, sizeof(rand_index), 0, + (struct sockaddr *)&remote_addr, &remote_len); + + if (size != sizeof(rand_index)) { + SAFE_CLOSE(sock); + tst_brk(TBROK | TERRNO, "Error while waiting for connection"); + } + + rand_index = rand() % ARRAY_SIZE(testcase_list); + SAFE_SENDTO(1, sock, &rand_index, sizeof(rand_index), 0, + (struct sockaddr *)&remote_addr, remote_len); + + size = SAFE_READ(0, sock, buffer, BUFFER_SIZE - 1); + buffer[size] = '\0'; + exp_data = testcase_list[rand_index].description; + + if (!strcmp(buffer, exp_data)) + tst_res(TPASS, "Communication successful"); + else + tst_res(TFAIL, "Received invalid data. Expected: \"%s\". " + "Received: \"%s\"", exp_data, buffer); + + SAFE_CLOSE(sock); + pthread_join(thread_id, NULL); + tmp_addr = (struct sockaddr_un *)tc->address; + + if (tc->address->sa_family == AF_UNIX && tmp_addr->sun_path[0]) + SAFE_UNLINK(tmp_addr->sun_path); +} + +static struct tst_test test = { + .test = test_bind, + .tcnt = ARRAY_SIZE(testcase_list), + .needs_tmpdir = 1, + .setup = setup, +}; diff --git a/testcases/kernel/syscalls/bind/libbind.h b/testcases/kernel/syscalls/bind/libbind.h new file mode 100644 index 000000000..e19758f1b --- /dev/null +++ b/testcases/kernel/syscalls/bind/libbind.h @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019 Martin Doucha + */ + +/* + * Common settings and data types for bind() connection tests + */ + +#include +#include +#include +#include +#include +#include + +#define MAIN_SOCKET_FILE "test.sock" +#define ABSTRACT_SOCKET_PATH "\0test.sock" +#define PEER_SOCKET_FILE "peer.sock" +#define IPV4_ADDRESS "127.0.0.1" +#define IPV6_ADDRESS "::1" +#define BUFFER_SIZE 128 + +struct test_case { + int type, protocol; + struct sockaddr *address; + socklen_t addrlen; + const char *description; +};