• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
21 #include "safe_net_fn.h"
22 
tst_sock_addr(const struct sockaddr * sa,socklen_t salen,char * res,size_t len)23 char *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 
tst_getsockport(const char * file,const int lineno,int sockfd)84 int tst_getsockport(const char *file, const int lineno, int sockfd)
85 {
86 	struct sockaddr_storage ss;
87 	socklen_t addrlen = sizeof(ss);
88 	struct sockaddr *sa = (struct sockaddr *)&ss;
89 
90 	safe_getsockname(file, lineno, NULL, sockfd, sa, &addrlen);
91 
92 	switch (sa->sa_family) {
93 	case AF_INET: {
94 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
95 
96 		return ntohs(sin->sin_port);
97 	}
98 	case AF_INET6: {
99 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
100 
101 		return ntohs(sin6->sin6_port);
102 	} }
103 
104 	return -1;
105 }
106 
safe_socket(const char * file,const int lineno,void (cleanup_fn)(void),int domain,int type,int protocol)107 int safe_socket(const char *file, const int lineno, void (cleanup_fn)(void),
108 		int domain, int type, int protocol)
109 {
110 	int rval, ttype;
111 
112 	rval = socket(domain, type, protocol);
113 
114 	if (rval < 0) {
115 		switch (errno) {
116 		case EPROTONOSUPPORT:
117 		case ESOCKTNOSUPPORT:
118 		case EOPNOTSUPP:
119 		case EPFNOSUPPORT:
120 		case EAFNOSUPPORT:
121 			ttype = TCONF;
122 			break;
123 		default:
124 			ttype = TBROK;
125 		}
126 
127 		tst_brkm(ttype | TERRNO, cleanup_fn,
128 			 "%s:%d: socket(%d, %d, %d) failed", file, lineno,
129 			 domain, type, protocol);
130 	}
131 
132 	return rval;
133 }
134 
safe_getsockopt(const char * file,const int lineno,int sockfd,int level,int optname,void * optval,socklen_t * optlen)135 int safe_getsockopt(const char *file, const int lineno, int sockfd, int level,
136 		    int optname, void *optval, socklen_t *optlen)
137 {
138 	int rval = getsockopt(sockfd, level, optname, optval, optlen);
139 
140 	if (!rval)
141 		return 0;
142 
143 	tst_brkm(TBROK | TERRNO, NULL,
144 		 "%s:%d: getsockopt(%d, %d, %d, %p, %p) failed",
145 		 file, lineno, sockfd, level, optname, optval, optlen);
146 
147 	return rval;
148 }
149 
safe_setsockopt(const char * file,const int lineno,int sockfd,int level,int optname,const void * optval,socklen_t optlen)150 int safe_setsockopt(const char *file, const int lineno, int sockfd, int level,
151 		    int optname, const void *optval, socklen_t optlen)
152 {
153 	int rval;
154 
155 	rval = setsockopt(sockfd, level, optname, optval, optlen);
156 
157 	if (rval) {
158 		tst_brkm(TBROK | TERRNO, NULL,
159 			 "%s:%d: setsockopt(%d, %d, %d, %p, %d) failed",
160 			 file, lineno, sockfd, level, optname, optval, optlen);
161 	}
162 
163 	return rval;
164 }
165 
safe_send(const char * file,const int lineno,char len_strict,int sockfd,const void * buf,size_t len,int flags)166 ssize_t safe_send(const char *file, const int lineno, char len_strict,
167 		  int sockfd, const void *buf, size_t len, int flags)
168 {
169 	ssize_t rval;
170 
171 	rval = send(sockfd, buf, len, flags);
172 
173 	if (rval == -1 || (len_strict && (size_t)rval != len)) {
174 		tst_brkm(TBROK | TERRNO, NULL,
175 			 "%s:%d: send(%d, %p, %zu, %d) failed",
176 			 file, lineno, sockfd, buf, len, flags);
177 	}
178 
179 	return rval;
180 }
181 
safe_sendto(const char * file,const int lineno,char len_strict,int sockfd,const void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)182 ssize_t safe_sendto(const char *file, const int lineno, char len_strict,
183 		    int sockfd, const void *buf, size_t len, int flags,
184 		    const struct sockaddr *dest_addr, socklen_t addrlen)
185 {
186 	ssize_t rval;
187 	char res[128];
188 
189 	rval = sendto(sockfd, buf, len, flags, dest_addr, addrlen);
190 
191 	if (rval == -1 || (len_strict && (size_t)rval != len)) {
192 		tst_brkm(TBROK | TERRNO, NULL,
193 			 "%s:%d: sendto(%d, %p, %zu, %d, %s, %d) failed",
194 			 file, lineno, sockfd, buf, len, flags,
195 			 tst_sock_addr(dest_addr, addrlen, res, sizeof(res)),
196 			 addrlen);
197 	}
198 
199 	return rval;
200 }
201 
safe_sendmsg(const char * file,const int lineno,size_t len,int sockfd,const struct msghdr * msg,int flags)202 ssize_t safe_sendmsg(const char *file, const int lineno, size_t len,
203 		     int sockfd, const struct msghdr *msg, int flags)
204 {
205 	ssize_t rval;
206 
207 	rval = sendmsg(sockfd, msg, flags);
208 
209 	if (rval == -1) {
210 		tst_brkm(TBROK | TERRNO, NULL,
211 			 "%s:%d: sendmsg(%d, %p, %d) failed",
212 			 file, lineno, sockfd, msg, flags);
213 	}
214 
215 	if (len && (size_t)rval != len) {
216 		tst_brkm(TBROK, NULL,
217 			 "%s:%d: sendmsg(%d, %p, %d) ret(%zd) != len(%zu)",
218 			 file, lineno, sockfd, msg, flags, rval, len);
219 	}
220 
221 	return rval;
222 }
223 
safe_recvmsg(const char * file,const int lineno,size_t len,int sockfd,struct msghdr * msg,int flags)224 ssize_t safe_recvmsg(const char *file, const int lineno, size_t len,
225 		     int sockfd, struct msghdr *msg, int flags)
226 {
227 	ssize_t rval;
228 
229 	rval = recvmsg(sockfd, msg, flags);
230 
231 	if (rval == -1) {
232 		tst_brkm(TBROK | TERRNO, NULL,
233 			 "%s:%d: recvmsg(%d, %p, %d) failed",
234 			 file, lineno, sockfd, msg, flags);
235 	}
236 
237 	if (len && (size_t)rval != len) {
238 		tst_brkm(TBROK, NULL,
239 			 "%s:%d: recvmsg(%d, %p, %d) ret(%zd) != len(%zu)",
240 			 file, lineno, sockfd, msg, flags, rval, len);
241 	}
242 
243 	return rval;
244 
245 }
246 
safe_bind(const char * file,const int lineno,void (cleanup_fn)(void),int socket,const struct sockaddr * address,socklen_t address_len)247 int safe_bind(const char *file, const int lineno, void (cleanup_fn)(void),
248 	      int socket, const struct sockaddr *address,
249 	      socklen_t address_len)
250 {
251 	int i;
252 	char buf[128];
253 
254 	for (i = 0; i < 120; i++) {
255 		if (!bind(socket, address, address_len))
256 			return 0;
257 
258 		if (errno != EADDRINUSE) {
259 			tst_brkm(TBROK | TERRNO, cleanup_fn,
260 				 "%s:%d: bind(%d, %s, %d) failed", file, lineno,
261 				 socket, tst_sock_addr(address, address_len,
262 						       buf, sizeof(buf)),
263 				 address_len);
264 			return -1;
265 		}
266 
267 		if ((i + 1) % 10 == 0) {
268 			tst_resm(TINFO, "address is in use, waited %3i sec",
269 				 i + 1);
270 		}
271 
272 		sleep(1);
273 	}
274 
275 	tst_brkm(TBROK | TERRNO, cleanup_fn,
276 		 "%s:%d: Failed to bind(%d, %s, %d) after 120 retries", file,
277 		 lineno, socket,
278 		 tst_sock_addr(address, address_len, buf, sizeof(buf)),
279 		 address_len);
280 	return -1;
281 }
282 
safe_listen(const char * file,const int lineno,void (cleanup_fn)(void),int socket,int backlog)283 int safe_listen(const char *file, const int lineno, void (cleanup_fn)(void),
284 		int socket, int backlog)
285 {
286 	int rval;
287 
288 	rval = listen(socket, backlog);
289 
290 	if (rval < 0) {
291 		tst_brkm(TBROK | TERRNO, cleanup_fn,
292 			 "%s:%d: listen(%d, %d) failed", file, lineno, socket,
293 			 backlog);
294 	}
295 
296 	return rval;
297 }
298 
safe_connect(const char * file,const int lineno,void (cleanup_fn)(void),int sockfd,const struct sockaddr * addr,socklen_t addrlen)299 int safe_connect(const char *file, const int lineno, void (cleanup_fn)(void),
300 		 int sockfd, const struct sockaddr *addr, socklen_t addrlen)
301 {
302 	int rval;
303 	char buf[128];
304 
305 	rval = connect(sockfd, addr, addrlen);
306 
307 	if (rval < 0) {
308 		tst_brkm(TBROK | TERRNO, cleanup_fn,
309 			 "%s:%d: connect(%d, %s, %d) failed", file, lineno,
310 			 sockfd, tst_sock_addr(addr, addrlen, buf,
311 					       sizeof(buf)), addrlen);
312 	}
313 
314 	return rval;
315 }
316 
safe_getsockname(const char * file,const int lineno,void (cleanup_fn)(void),int sockfd,struct sockaddr * addr,socklen_t * addrlen)317 int safe_getsockname(const char *file, const int lineno,
318 		     void (cleanup_fn)(void), int sockfd, struct sockaddr *addr,
319 		     socklen_t *addrlen)
320 {
321 	int rval;
322 	char buf[128];
323 
324 	rval = getsockname(sockfd, addr, addrlen);
325 
326 	if (rval < 0) {
327 		tst_brkm(TBROK | TERRNO, cleanup_fn,
328 			 "%s:%d: getsockname(%d, %s, %d) failed", file, lineno,
329 			 sockfd, tst_sock_addr(addr, *addrlen, buf,
330 					       sizeof(buf)), *addrlen);
331 	}
332 
333 	return rval;
334 }
335 
safe_gethostname(const char * file,const int lineno,char * name,size_t size)336 int safe_gethostname(const char *file, const int lineno,
337 		     char *name, size_t size)
338 {
339 	int rval = gethostname(name, size);
340 
341 	if (rval < 0) {
342 		tst_brkm(TBROK | TERRNO, NULL,
343 			 "%s:%d: gethostname(%p, %zu) failed",
344 			 file, lineno, name, size);
345 	}
346 
347 	return rval;
348 }
349