blob: e48b06d4e3b8565053a2177679b4816942367dfc [file] [log] [blame]
Zeng Linggang370a3a42015-10-21 11:15:23 +08001/*
2 * Copyright (c) 2015 Fujitsu Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19#include <errno.h>
20#include "test.h"
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010021#include "safe_net_fn.h"
Zeng Linggang370a3a42015-10-21 11:15:23 +080022
23char *tst_sock_addr(const struct sockaddr *sa, socklen_t salen, char *res,
24 size_t len)
25{
26 char portstr[8];
27
28 switch (sa->sa_family) {
29
30 case AF_INET: {
31 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
32
33 if (!inet_ntop(AF_INET, &sin->sin_addr, res, len))
34 return NULL;
35
36 if (ntohs(sin->sin_port) != 0) {
37 snprintf(portstr, sizeof(portstr), ":%d",
38 ntohs(sin->sin_port));
39 strcat(res, portstr);
40 }
41
42 return res;
43 }
44
45 case AF_INET6: {
46 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
47
48 res[0] = '[';
49 if (!inet_ntop(AF_INET6, &sin6->sin6_addr, res + 1, len - 1))
50 return NULL;
51
52 if (ntohs(sin6->sin6_port) != 0) {
53 snprintf(portstr, sizeof(portstr), "]:%d",
54 ntohs(sin6->sin6_port));
55 strcat(res, portstr);
56 return res;
57 }
58
59 return res + 1;
60 }
61
62 case AF_UNIX: {
63 struct sockaddr_un *unp = (struct sockaddr_un *)sa;
64
65 if (unp->sun_path[0] == '\0')
66 strcpy(res, "(no pathname bound)");
67 else
68 snprintf(res, len, "%s", unp->sun_path);
69
70 return res;
71 }
72
73 default: {
74 snprintf(res, len,
75 "sock_ntop: unknown AF_xxx: %d, len: %d",
76 sa->sa_family, salen);
77
78 return res;
79 }
80
81 }
82}
83
84int safe_socket(const char *file, const int lineno, void (cleanup_fn)(void),
85 int domain, int type, int protocol)
86{
87 int rval;
88
89 rval = socket(domain, type, protocol);
90
91 if (rval < 0) {
92 tst_brkm(TBROK | TERRNO, cleanup_fn,
93 "%s:%d: socket(%d, %d, %d) failed", file, lineno,
94 domain, type, protocol);
95 }
96
97 return rval;
98}
99
Alexey Kodanev5c189fc2017-02-27 13:53:34 +0300100int safe_setsockopt(const char *file, const int lineno, int sockfd, int level,
101 int optname, const void *optval, socklen_t optlen)
102{
103 int rval;
104
105 rval = setsockopt(sockfd, level, optname, optval, optlen);
106
107 if (rval) {
108 tst_brkm(TBROK | TERRNO, NULL,
109 "%s:%d: setsockopt(%d, %d, %d, %p, %d) failed",
110 file, lineno, sockfd, level, optname, optval, optlen);
111 }
112
113 return rval;
114}
115
116ssize_t safe_send(const char *file, const int lineno, char len_strict,
117 int sockfd, const void *buf, size_t len, int flags)
118{
119 ssize_t rval;
120
121 rval = send(sockfd, buf, len, flags);
122
123 if (rval == -1 || (len_strict && (size_t)rval != len)) {
124 tst_brkm(TBROK | TERRNO, NULL,
125 "%s:%d: send(%d, %p, %zu, %d) failed",
126 file, lineno, sockfd, buf, len, flags);
127 }
128
129 return rval;
130}
131
132ssize_t safe_sendto(const char *file, const int lineno, char len_strict,
133 int sockfd, const void *buf, size_t len, int flags,
134 const struct sockaddr *dest_addr, socklen_t addrlen)
135{
136 ssize_t rval;
137 char res[128];
138
139 rval = sendto(sockfd, buf, len, flags, dest_addr, addrlen);
140
141 if (rval == -1 || (len_strict && (size_t)rval != len)) {
142 tst_brkm(TBROK | TERRNO, NULL,
143 "%s:%d: sendto(%d, %p, %zu, %d, %s, %d) failed",
144 file, lineno, sockfd, buf, len, flags,
145 tst_sock_addr(dest_addr, addrlen, res, sizeof(res)),
146 addrlen);
147 }
148
149 return rval;
150}
151
Zeng Linggang370a3a42015-10-21 11:15:23 +0800152int safe_bind(const char *file, const int lineno, void (cleanup_fn)(void),
153 int socket, const struct sockaddr *address,
154 socklen_t address_len)
155{
156 int i;
157 char buf[128];
158
159 for (i = 0; i < 120; i++) {
160 if (!bind(socket, address, address_len))
161 return 0;
162
163 if (errno != EADDRINUSE) {
164 tst_brkm(TBROK | TERRNO, cleanup_fn,
165 "%s:%d: bind(%d, %s, %d) failed", file, lineno,
166 socket, tst_sock_addr(address, address_len,
167 buf, sizeof(buf)),
168 address_len);
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100169 return -1;
Zeng Linggang370a3a42015-10-21 11:15:23 +0800170 }
171
172 if ((i + 1) % 10 == 0) {
173 tst_resm(TINFO, "address is in use, waited %3i sec",
174 i + 1);
175 }
176
177 sleep(1);
178 }
179
180 tst_brkm(TBROK | TERRNO, cleanup_fn,
181 "%s:%d: Failed to bind(%d, %s, %d) after 120 retries", file,
182 lineno, socket,
183 tst_sock_addr(address, address_len, buf, sizeof(buf)),
184 address_len);
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100185 return -1;
Zeng Linggang370a3a42015-10-21 11:15:23 +0800186}
187
188int safe_listen(const char *file, const int lineno, void (cleanup_fn)(void),
189 int socket, int backlog)
190{
191 int rval;
192
193 rval = listen(socket, backlog);
194
195 if (rval < 0) {
196 tst_brkm(TBROK | TERRNO, cleanup_fn,
197 "%s:%d: listen(%d, %d) failed", file, lineno, socket,
198 backlog);
199 }
200
201 return rval;
202}
203
204int safe_connect(const char *file, const int lineno, void (cleanup_fn)(void),
205 int sockfd, const struct sockaddr *addr, socklen_t addrlen)
206{
207 int rval;
208 char buf[128];
209
210 rval = connect(sockfd, addr, addrlen);
211
212 if (rval < 0) {
213 tst_brkm(TBROK | TERRNO, cleanup_fn,
214 "%s:%d: connect(%d, %s, %d) failed", file, lineno,
215 sockfd, tst_sock_addr(addr, addrlen, buf,
216 sizeof(buf)), addrlen);
217 }
218
219 return rval;
220}
221
222int safe_getsockname(const char *file, const int lineno,
223 void (cleanup_fn)(void), int sockfd, struct sockaddr *addr,
224 socklen_t *addrlen)
225{
226 int rval;
227 char buf[128];
228
229 rval = getsockname(sockfd, addr, addrlen);
230
231 if (rval < 0) {
232 tst_brkm(TBROK | TERRNO, cleanup_fn,
233 "%s:%d: getsockname(%d, %s, %d) failed", file, lineno,
234 sockfd, tst_sock_addr(addr, *addrlen, buf,
235 sizeof(buf)), *addrlen);
236 }
237
238 return rval;
239}
Alexey Kodanev5065a9e2016-06-16 13:14:52 +0300240
241int safe_gethostname(const char *file, const int lineno,
242 char *name, size_t size)
243{
244 int rval = gethostname(name, size);
245
246 if (rval < 0) {
247 tst_brkm(TBROK | TERRNO, NULL,
248 "%s:%d: gethostname(%p, %zu) failed",
249 file, lineno, name, size);
250 }
251
252 return rval;
253}