create a socket */
| 160 | |
| 161 | /* create a socket */ |
| 162 | int |
| 163 | create_socket(int domain, int type, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, struct addrinfo **server_res_out) |
| 164 | { |
| 165 | struct addrinfo hints, *local_res = NULL, *server_res = NULL; |
| 166 | int s, saved_errno; |
| 167 | char portstr[6]; |
| 168 | |
| 169 | if (local) { |
| 170 | memset(&hints, 0, sizeof(hints)); |
| 171 | hints.ai_family = domain; |
| 172 | hints.ai_socktype = type; |
| 173 | if ((gerror = getaddrinfo(local, NULL, &hints, &local_res)) != 0) |
| 174 | return -1; |
| 175 | } |
| 176 | |
| 177 | memset(&hints, 0, sizeof(hints)); |
| 178 | hints.ai_family = domain; |
| 179 | hints.ai_socktype = type; |
| 180 | snprintf(portstr, sizeof(portstr), "%d", port); |
| 181 | if ((gerror = getaddrinfo(server, portstr, &hints, &server_res)) != 0) { |
| 182 | if (local) |
| 183 | freeaddrinfo(local_res); |
| 184 | return -1; |
| 185 | } |
| 186 | |
| 187 | s = socket(server_res->ai_family, type, proto); |
| 188 | if (s < 0) { |
| 189 | if (local) |
| 190 | freeaddrinfo(local_res); |
| 191 | freeaddrinfo(server_res); |
| 192 | return -1; |
| 193 | } |
| 194 | |
| 195 | if (bind_dev) { |
| 196 | if (bind_to_device(s, domain, bind_dev) < 0) { |
| 197 | saved_errno = errno; |
| 198 | close(s); |
| 199 | freeaddrinfo(local_res); |
| 200 | freeaddrinfo(server_res); |
| 201 | errno = saved_errno; |
| 202 | return -1; |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | /* Bind the local address if given a name (with or without --cport) */ |
| 207 | if (local) { |
| 208 | if (local_port) { |
| 209 | struct sockaddr_in *lcladdr; |
| 210 | lcladdr = (struct sockaddr_in *)local_res->ai_addr; |
| 211 | lcladdr->sin_port = htons(local_port); |
| 212 | } |
| 213 | |
| 214 | if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) { |
| 215 | saved_errno = errno; |
| 216 | close(s); |
| 217 | freeaddrinfo(local_res); |
| 218 | freeaddrinfo(server_res); |
| 219 | errno = saved_errno; |
no test coverage detected
searching dependent graphs…