1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2017-2019 Petr Vorel <pvorel@suse.cz>
4 */
5
6 #include <arpa/inet.h>
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #define MAX_IPV4_PREFIX 32
13 #define MAX_IPV6_PREFIX 128
14
15 #define tst_res_comment(...) { \
16 fprintf(stderr, "# "); \
17 tst_res(__VA_ARGS__); } \
18
19
20 #define tst_brk_comment(...) { \
21 fprintf(stderr, "# "); \
22 tst_brk(TCONF, __VA_ARGS__); } \
23
print_svar(const char * name,const char * val)24 static inline void print_svar(const char *name, const char *val)
25 {
26 if (name && val)
27 printf("export %s=\"%s\"\n", name, val);
28 }
29
print_svar_change(const char * name,const char * val)30 static inline void print_svar_change(const char *name, const char *val)
31 {
32 if (name && val)
33 printf("export %s=\"${%s:-%s}\"\n", name, name, val);
34 }
35
36 /*
37 * Function bit_count is from ipcalc project, ipcalc.c.
38 */
bit_count(uint32_t i)39 static inline int bit_count(uint32_t i)
40 {
41 int c = 0;
42 unsigned int seen_one = 0;
43
44 while (i > 0) {
45 if (i & 1) {
46 seen_one = 1;
47 c++;
48 } else {
49 if (seen_one)
50 return -1;
51 }
52 i >>= 1;
53 }
54
55 return c;
56 }
57
58 /*
59 * Function mask2prefix is from ipcalc project, ipcalc.c.
60 */
mask2prefix(struct in_addr mask)61 static inline int mask2prefix(struct in_addr mask)
62 {
63 return bit_count(ntohl(mask.s_addr));
64 }
65
66 /*
67 * Function ipv4_mask_to_int is from ipcalc project, ipcalc.c.
68 */
ipv4_mask_to_int(const char * prefix)69 static inline int ipv4_mask_to_int(const char *prefix)
70 {
71 int ret;
72 struct in_addr in;
73
74 ret = inet_pton(AF_INET, prefix, &in);
75 if (ret == 0)
76 return -1;
77
78 return mask2prefix(in);
79 }
80
81 /*
82 * Function safe_atoi is from ipcalc project, ipcalc.c.
83 */
safe_atoi(const char * s,int * ret_i)84 static inline int safe_atoi(const char *s, int *ret_i)
85 {
86 char *x = NULL;
87 long l;
88
89 errno = 0;
90 l = strtol(s, &x, 0);
91
92 if (!x || x == s || *x || errno)
93 return errno > 0 ? -errno : -EINVAL;
94
95 if ((long)(int)l != l)
96 return -ERANGE;
97
98 *ret_i = (int)l;
99
100 return 0;
101 }
102
103 /*
104 * Function get_prefix use code from ipcalc project, str_to_prefix/ipcalc.c.
105 */
get_prefix(const char * ip_str,int is_ipv6)106 static inline int get_prefix(const char *ip_str, int is_ipv6)
107 {
108 char *prefix_str = NULL;
109 int prefix = -1, r;
110
111 prefix_str = strchr(ip_str, '/');
112 if (!prefix_str)
113 return -1;
114
115 *(prefix_str++) = '\0';
116
117 if (!is_ipv6 && strchr(prefix_str, '.'))
118 prefix = ipv4_mask_to_int(prefix_str);
119 else {
120 r = safe_atoi(prefix_str, &prefix);
121 if (r != 0)
122 tst_brk_comment("conversion error: '%s' is not integer",
123 prefix_str);
124 }
125
126 if (prefix < 0 || ((is_ipv6 && prefix > MAX_IPV6_PREFIX) ||
127 (!is_ipv6 && prefix > MAX_IPV4_PREFIX)))
128 tst_brk_comment("bad %s prefix: %s", is_ipv6 ? "IPv6" : "IPv4",
129 prefix_str);
130
131 return prefix;
132 }
133
get_in_addr(const char * ip_str,struct in_addr * ip)134 static inline void get_in_addr(const char *ip_str, struct in_addr *ip)
135 {
136 if (inet_pton(AF_INET, ip_str, ip) <= 0)
137 tst_brk_comment("bad IPv4 address: '%s'", ip_str);
138 }
139
get_in6_addr(const char * ip_str,struct in6_addr * ip6)140 static inline void get_in6_addr(const char *ip_str, struct in6_addr *ip6)
141 {
142 if (inet_pton(AF_INET6, ip_str, ip6) <= 0)
143 tst_brk_comment("bad IPv6 address: '%s'", ip_str);
144 }
145