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_macros_fn.h" 22#include "safe_net_fn.h" 23 24char *tst_sock_addr(const struct sockaddr *sa, socklen_t salen, char *res, 25 size_t len) 26{ 27 char portstr[8]; 28 29 switch (sa->sa_family) { 30 31 case AF_INET: { 32 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 33 34 if (!inet_ntop(AF_INET, &sin->sin_addr, res, len)) 35 return NULL; 36 37 if (ntohs(sin->sin_port) != 0) { 38 snprintf(portstr, sizeof(portstr), ":%d", 39 ntohs(sin->sin_port)); 40 strcat(res, portstr); 41 } 42 43 return res; 44 } 45 46 case AF_INET6: { 47 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 48 49 res[0] = '['; 50 if (!inet_ntop(AF_INET6, &sin6->sin6_addr, res + 1, len - 1)) 51 return NULL; 52 53 if (ntohs(sin6->sin6_port) != 0) { 54 snprintf(portstr, sizeof(portstr), "]:%d", 55 ntohs(sin6->sin6_port)); 56 strcat(res, portstr); 57 return res; 58 } 59 60 return res + 1; 61 } 62 63 case AF_UNIX: { 64 struct sockaddr_un *unp = (struct sockaddr_un *)sa; 65 66 if (unp->sun_path[0] == '\0') 67 strcpy(res, "(no pathname bound)"); 68 else 69 snprintf(res, len, "%s", unp->sun_path); 70 71 return res; 72 } 73 74 default: { 75 snprintf(res, len, 76 "sock_ntop: unknown AF_xxx: %d, len: %d", 77 sa->sa_family, salen); 78 79 return res; 80 } 81 82 } 83} 84 85int tst_getsockport(const char *file, const int lineno, int sockfd) 86{ 87 struct sockaddr_storage ss; 88 socklen_t addrlen = sizeof(ss); 89 struct sockaddr *sa = (struct sockaddr *)&ss; 90 91 safe_getsockname(file, lineno, NULL, sockfd, sa, &addrlen); 92 93 switch (sa->sa_family) { 94 case AF_INET: { 95 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 96 97 return ntohs(sin->sin_port); 98 } 99 case AF_INET6: { 100 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 101 102 return ntohs(sin6->sin6_port); 103 } } 104 105 return -1; 106} 107 108int safe_socket(const char *file, const int lineno, void (cleanup_fn)(void), 109 int domain, int type, int protocol) 110{ 111 int rval, ttype; 112 113 rval = socket(domain, type, protocol); 114 115 if (rval == -1) { 116 switch (errno) { 117 case EPROTONOSUPPORT: 118 case ESOCKTNOSUPPORT: 119 case EOPNOTSUPP: 120 case EPFNOSUPPORT: 121 case EAFNOSUPPORT: 122 ttype = TCONF; 123 break; 124 default: 125 ttype = TBROK; 126 } 127 128 tst_brkm_(file, lineno, ttype | TERRNO, cleanup_fn, 129 "socket(%d, %d, %d) failed", domain, type, protocol); 130 } else if (rval < 0) { 131 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 132 "Invalid socket(%d, %d, %d) return value %d", domain, 133 type, protocol, rval); 134 } 135 136 return rval; 137} 138 139int safe_socketpair(const char *file, const int lineno, int domain, int type, 140 int protocol, int sv[]) 141{ 142 int rval, ttype; 143 144 rval = socketpair(domain, type, protocol, sv); 145 146 if (rval == -1) { 147 switch (errno) { 148 case EPROTONOSUPPORT: 149 case EOPNOTSUPP: 150 case EAFNOSUPPORT: 151 ttype = TCONF; 152 break; 153 default: 154 ttype = TBROK; 155 } 156 157 tst_brkm_(file, lineno, ttype | TERRNO, NULL, 158 "socketpair(%d, %d, %d, %p) failed", domain, type, 159 protocol, sv); 160 } else if (rval) { 161 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 162 "Invalid socketpair(%d, %d, %d, %p) return value %d", 163 domain, type, protocol, sv, rval); 164 } 165 166 return rval; 167} 168 169int safe_getsockopt(const char *file, const int lineno, int sockfd, int level, 170 int optname, void *optval, socklen_t *optlen) 171{ 172 int rval = getsockopt(sockfd, level, optname, optval, optlen); 173 174 if (rval == -1) { 175 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 176 "getsockopt(%d, %d, %d, %p, %p) failed", 177 sockfd, level, optname, optval, optlen); 178 } else if (rval) { 179 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 180 "Invalid getsockopt(%d, %d, %d, %p, %p) return value %d", 181 sockfd, level, optname, optval, optlen, rval); 182 } 183 184 return rval; 185} 186 187int safe_setsockopt(const char *file, const int lineno, int sockfd, int level, 188 int optname, const void *optval, socklen_t optlen) 189{ 190 int rval; 191 192 rval = setsockopt(sockfd, level, optname, optval, optlen); 193 194 if (rval == -1) { 195 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 196 "setsockopt(%d, %d, %d, %p, %d) failed", 197 sockfd, level, optname, optval, optlen); 198 } else if (rval) { 199 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 200 "Invalid setsockopt(%d, %d, %d, %p, %d) return value %d", 201 sockfd, level, optname, optval, optlen, rval); 202 } 203 204 return rval; 205} 206 207ssize_t safe_send(const char *file, const int lineno, char len_strict, 208 int sockfd, const void *buf, size_t len, int flags) 209{ 210 ssize_t rval; 211 212 rval = send(sockfd, buf, len, flags); 213 214 if (rval == -1 || (len_strict && (size_t)rval != len)) { 215 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 216 "send(%d, %p, %zu, %d) failed", sockfd, buf, len, 217 flags); 218 } else if (rval < 0) { 219 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 220 "Invalid send(%d, %p, %zu, %d) return value %zd", 221 sockfd, buf, len, flags, rval); 222 } 223 224 return rval; 225} 226 227ssize_t safe_sendto(const char *file, const int lineno, char len_strict, 228 int sockfd, const void *buf, size_t len, int flags, 229 const struct sockaddr *dest_addr, socklen_t addrlen) 230{ 231 ssize_t rval; 232 char res[128]; 233 234 rval = sendto(sockfd, buf, len, flags, dest_addr, addrlen); 235 236 if (rval == -1 || (len_strict && (size_t)rval != len)) { 237 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 238 "sendto(%d, %p, %zu, %d, %s, %d) failed", 239 sockfd, buf, len, flags, 240 tst_sock_addr(dest_addr, addrlen, res, sizeof(res)), 241 addrlen); 242 } else if (rval < 0) { 243 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 244 "Invalid sendto(%d, %p, %zu, %d, %s, %d) return value %zd", 245 sockfd, buf, len, flags, 246 tst_sock_addr(dest_addr, addrlen, res, sizeof(res)), 247 addrlen, rval); 248 } 249 250 return rval; 251} 252 253ssize_t safe_sendmsg(const char *file, const int lineno, size_t len, 254 int sockfd, const struct msghdr *msg, int flags) 255{ 256 ssize_t rval; 257 258 rval = sendmsg(sockfd, msg, flags); 259 260 if (rval == -1) { 261 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 262 "sendmsg(%d, %p, %d) failed", sockfd, msg, flags); 263 } else if (rval < 0) { 264 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 265 "Invalid sendmsg(%d, %p, %d) return value %zd", 266 sockfd, msg, flags, rval); 267 } else if (len && (size_t)rval != len) { 268 tst_brkm_(file, lineno, TBROK, NULL, 269 "sendmsg(%d, %p, %d) ret(%zd) != len(%zu)", 270 sockfd, msg, flags, rval, len); 271 } 272 273 return rval; 274} 275 276ssize_t safe_recv(const char *file, const int lineno, size_t len, 277 int sockfd, void *buf, size_t size, int flags) 278{ 279 ssize_t rval; 280 281 rval = recv(sockfd, buf, size, flags); 282 283 if (rval == -1) { 284 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 285 "recv(%d, %p, %zu, %d) failed", sockfd, buf, size, 286 flags); 287 } else if (rval < 0) { 288 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 289 "Invalid recv(%d, %p, %zu, %d) return value %zd", 290 sockfd, buf, size, flags, rval); 291 } else if (len && (size_t)rval != len) { 292 tst_brkm_(file, lineno, TBROK, NULL, 293 "recv(%d, %p, %zu, %d) ret(%zd) != len(%zu)", 294 sockfd, buf, size, flags, rval, len); 295 } 296 297 return rval; 298 299} 300 301ssize_t safe_recvmsg(const char *file, const int lineno, size_t len, 302 int sockfd, struct msghdr *msg, int flags) 303{ 304 ssize_t rval; 305 306 rval = recvmsg(sockfd, msg, flags); 307 308 if (rval == -1) { 309 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 310 "recvmsg(%d, %p, %d) failed", sockfd, msg, flags); 311 } else if (rval < 0) { 312 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 313 "Invalid recvmsg(%d, %p, %d) return value %zd", 314 sockfd, msg, flags, rval); 315 } else if (len && (size_t)rval != len) { 316 tst_brkm_(file, lineno, TBROK, NULL, 317 "recvmsg(%d, %p, %d) ret(%zd) != len(%zu)", 318 sockfd, msg, flags, rval, len); 319 } 320 321 return rval; 322 323} 324 325int safe_bind(const char *file, const int lineno, void (cleanup_fn)(void), 326 int socket, const struct sockaddr *address, 327 socklen_t address_len) 328{ 329 int i, ret; 330 char buf[128]; 331 332 for (i = 0; i < 120; i++) { 333 ret = bind(socket, address, address_len); 334 335 if (!ret) 336 return 0; 337 338 if (ret != -1) { 339 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 340 "Invalid bind(%d, %s, %d) return value %d", 341 socket, tst_sock_addr(address, address_len, 342 buf, sizeof(buf)), address_len, ret); 343 return ret; 344 } else if (errno != EADDRINUSE) { 345 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 346 "bind(%d, %s, %d) failed", socket, 347 tst_sock_addr(address, address_len, buf, 348 sizeof(buf)), address_len); 349 return ret; 350 } 351 352 if ((i + 1) % 10 == 0) { 353 tst_resm_(file, lineno, TINFO, 354 "address is in use, waited %3i sec", i + 1); 355 } 356 357 sleep(1); 358 } 359 360 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 361 "Failed to bind(%d, %s, %d) after 120 retries", socket, 362 tst_sock_addr(address, address_len, buf, sizeof(buf)), 363 address_len); 364 return -1; 365} 366 367int safe_listen(const char *file, const int lineno, void (cleanup_fn)(void), 368 int socket, int backlog) 369{ 370 int rval; 371 int res = TBROK; 372 373 rval = listen(socket, backlog); 374 375 if (rval == -1) { 376 if (errno == ENOSYS) 377 res = TCONF; 378 tst_brkm_(file, lineno, res | TERRNO, cleanup_fn, 379 "listen(%d, %d) failed", socket, backlog); 380 } else if (rval) { 381 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 382 "Invalid listen(%d, %d) return value %d", socket, 383 backlog, rval); 384 } 385 386 return rval; 387} 388 389int safe_accept(const char *file, const int lineno, void (cleanup_fn)(void), 390 int sockfd, struct sockaddr *addr, socklen_t *addrlen) 391{ 392 int rval; 393 394 rval = accept(sockfd, addr, addrlen); 395 396 if (rval == -1) { 397 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 398 "accept(%d, %p, %d) failed", sockfd, addr, *addrlen); 399 } else if (rval < 0) { 400 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 401 "Invalid accept(%d, %p, %d) return value %d", sockfd, 402 addr, *addrlen, rval); 403 } 404 405 return rval; 406} 407 408int safe_connect(const char *file, const int lineno, void (cleanup_fn)(void), 409 int sockfd, const struct sockaddr *addr, socklen_t addrlen) 410{ 411 int rval; 412 char buf[128]; 413 414 rval = connect(sockfd, addr, addrlen); 415 416 if (rval == -1) { 417 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 418 "connect(%d, %s, %d) failed", sockfd, 419 tst_sock_addr(addr, addrlen, buf, sizeof(buf)), 420 addrlen); 421 } else if (rval) { 422 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 423 "Invalid connect(%d, %s, %d) return value %d", sockfd, 424 tst_sock_addr(addr, addrlen, buf, sizeof(buf)), 425 addrlen, rval); 426 } 427 428 return rval; 429} 430 431int safe_getsockname(const char *file, const int lineno, 432 void (cleanup_fn)(void), int sockfd, struct sockaddr *addr, 433 socklen_t *addrlen) 434{ 435 int rval; 436 char buf[128]; 437 438 rval = getsockname(sockfd, addr, addrlen); 439 440 if (rval == -1) { 441 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 442 "getsockname(%d, %s, %d) failed", sockfd, 443 tst_sock_addr(addr, *addrlen, buf, sizeof(buf)), 444 *addrlen); 445 } else if (rval) { 446 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn, 447 "Invalid getsockname(%d, %s, %d) return value %d", 448 sockfd, tst_sock_addr(addr, *addrlen, buf, 449 sizeof(buf)), *addrlen, rval); 450 } 451 452 return rval; 453} 454 455int safe_gethostname(const char *file, const int lineno, 456 char *name, size_t size) 457{ 458 int rval = gethostname(name, size); 459 460 if (rval == -1) { 461 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 462 "gethostname(%p, %zu) failed", name, size); 463 } else if (rval) { 464 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 465 "Invalid gethostname(%p, %zu) return value %d", name, 466 size, rval); 467 } 468 469 return rval; 470} 471 472int safe_sethostname(const char *file, const int lineno, 473 const char *name, size_t size) 474{ 475 int rval = sethostname(name, size); 476 477 if (rval == -1) { 478 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 479 "sethostname(%p, %zu) failed", name, size); 480 } else if (rval) { 481 tst_brkm_(file, lineno, TBROK | TERRNO, NULL, 482 "Invalid sethostname(%p, %zu) return value %d", name, 483 size, rval); 484 } 485 486 return rval; 487} 488 489/* 490 * @return port in network byte order. 491 */ 492unsigned short tst_get_unused_port(const char *file, const int lineno, 493 void (cleanup_fn)(void), unsigned short family, int type) 494{ 495 int sock, ret; 496 socklen_t slen; 497 struct sockaddr_storage _addr; 498 struct sockaddr *addr = (struct sockaddr *)&_addr; 499 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; 500 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; 501 502 switch (family) { 503 case AF_INET: 504 addr4->sin_family = AF_INET; 505 addr4->sin_port = 0; 506 addr4->sin_addr.s_addr = INADDR_ANY; 507 slen = sizeof(*addr4); 508 break; 509 510 case AF_INET6: 511 addr6->sin6_family = AF_INET6; 512 addr6->sin6_port = 0; 513 addr6->sin6_addr = in6addr_any; 514 slen = sizeof(*addr6); 515 break; 516 517 default: 518 tst_brkm_(file, lineno, TBROK, cleanup_fn, 519 "%s(): Unsupported socket family %d", __func__, 520 family); 521 return -1; 522 } 523 524 sock = safe_socket(file, lineno, cleanup_fn, addr->sa_family, type, 0); 525 526 if (sock < 0) 527 return sock; 528 529 ret = safe_bind(file, lineno, cleanup_fn, sock, addr, slen); 530 531 if (ret) 532 return ret; 533 534 ret = safe_getsockname(file, lineno, cleanup_fn, sock, addr, &slen); 535 536 if (ret) 537 return ret; 538 539 ret = safe_close(file, lineno, cleanup_fn, sock); 540 541 if (ret) 542 return ret; 543 544 switch (family) { 545 case AF_INET: 546 return addr4->sin_port; 547 case AF_INET6: 548 return addr6->sin6_port; 549 default: 550 return -1; 551 } 552} 553