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_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 116 ssize_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 132 ssize_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 152 int 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); 169 return -1; 170 } 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); 185 return -1; 186 } 187 188 int 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 204 int 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 222 int 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 } 240 241 int 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 } 254