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 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 84 int 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 100 int safe_bind(const char *file, const int lineno, void (cleanup_fn)(void), 101 int socket, const struct sockaddr *address, 102 socklen_t address_len) 103 { 104 int i; 105 char buf[128]; 106 107 for (i = 0; i < 120; i++) { 108 if (!bind(socket, address, address_len)) 109 return 0; 110 111 if (errno != EADDRINUSE) { 112 tst_brkm(TBROK | TERRNO, cleanup_fn, 113 "%s:%d: bind(%d, %s, %d) failed", file, lineno, 114 socket, tst_sock_addr(address, address_len, 115 buf, sizeof(buf)), 116 address_len); 117 } 118 119 if ((i + 1) % 10 == 0) { 120 tst_resm(TINFO, "address is in use, waited %3i sec", 121 i + 1); 122 } 123 124 sleep(1); 125 } 126 127 tst_brkm(TBROK | TERRNO, cleanup_fn, 128 "%s:%d: Failed to bind(%d, %s, %d) after 120 retries", file, 129 lineno, socket, 130 tst_sock_addr(address, address_len, buf, sizeof(buf)), 131 address_len); 132 } 133 134 int safe_listen(const char *file, const int lineno, void (cleanup_fn)(void), 135 int socket, int backlog) 136 { 137 int rval; 138 139 rval = listen(socket, backlog); 140 141 if (rval < 0) { 142 tst_brkm(TBROK | TERRNO, cleanup_fn, 143 "%s:%d: listen(%d, %d) failed", file, lineno, socket, 144 backlog); 145 } 146 147 return rval; 148 } 149 150 int safe_connect(const char *file, const int lineno, void (cleanup_fn)(void), 151 int sockfd, const struct sockaddr *addr, socklen_t addrlen) 152 { 153 int rval; 154 char buf[128]; 155 156 rval = connect(sockfd, addr, addrlen); 157 158 if (rval < 0) { 159 tst_brkm(TBROK | TERRNO, cleanup_fn, 160 "%s:%d: connect(%d, %s, %d) failed", file, lineno, 161 sockfd, tst_sock_addr(addr, addrlen, buf, 162 sizeof(buf)), addrlen); 163 } 164 165 return rval; 166 } 167 168 int safe_getsockname(const char *file, const int lineno, 169 void (cleanup_fn)(void), int sockfd, struct sockaddr *addr, 170 socklen_t *addrlen) 171 { 172 int rval; 173 char buf[128]; 174 175 rval = getsockname(sockfd, addr, addrlen); 176 177 if (rval < 0) { 178 tst_brkm(TBROK | TERRNO, cleanup_fn, 179 "%s:%d: getsockname(%d, %s, %d) failed", file, lineno, 180 sockfd, tst_sock_addr(addr, *addrlen, buf, 181 sizeof(buf)), *addrlen); 182 } 183 184 return rval; 185 } 186