comparison netio.c @ 1478:3a933956437e coverity

update coverity
author Matt Johnston <matt@ucc.asn.au>
date Fri, 09 Feb 2018 23:49:22 +0800
parents f787f60f8e45
children 2d450c1056e3
comparison
equal deleted inserted replaced
1439:8d24733026c5 1478:3a933956437e
17 or NULL. */ 17 or NULL. */
18 18
19 int sock; 19 int sock;
20 20
21 char* errstring; 21 char* errstring;
22 char *bind_address, *bind_port;
22 }; 23 };
23 24
24 /* Deallocate a progress connection. Removes from the pending list if iter!=NULL. 25 /* Deallocate a progress connection. Removes from the pending list if iter!=NULL.
25 Does not close sockets */ 26 Does not close sockets */
26 static void remove_connect(struct dropbear_progress_connection *c, m_list_elem *iter) { 27 static void remove_connect(struct dropbear_progress_connection *c, m_list_elem *iter) {
28 freeaddrinfo(c->res); 29 freeaddrinfo(c->res);
29 } 30 }
30 m_free(c->remotehost); 31 m_free(c->remotehost);
31 m_free(c->remoteport); 32 m_free(c->remoteport);
32 m_free(c->errstring); 33 m_free(c->errstring);
34 m_free(c->bind_address);
35 m_free(c->bind_port);
33 m_free(c); 36 m_free(c);
34 37
35 if (iter) { 38 if (iter) {
36 list_remove(iter); 39 list_remove(iter);
37 } 40 }
49 c->cb_data = NULL; 52 c->cb_data = NULL;
50 } 53 }
51 54
52 static void connect_try_next(struct dropbear_progress_connection *c) { 55 static void connect_try_next(struct dropbear_progress_connection *c) {
53 struct addrinfo *r; 56 struct addrinfo *r;
57 int err;
54 int res = 0; 58 int res = 0;
55 int fastopen = 0; 59 int fastopen = 0;
56 #if DROPBEAR_CLIENT_TCP_FAST_OPEN 60 #if DROPBEAR_CLIENT_TCP_FAST_OPEN
57 struct msghdr message; 61 struct msghdr message;
58 #endif 62 #endif
62 dropbear_assert(c->sock == -1); 66 dropbear_assert(c->sock == -1);
63 67
64 c->sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 68 c->sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
65 if (c->sock < 0) { 69 if (c->sock < 0) {
66 continue; 70 continue;
71 }
72
73 if (c->bind_address || c->bind_port) {
74 /* bind to a source port/address */
75 struct addrinfo hints;
76 struct addrinfo *bindaddr = NULL;
77 memset(&hints, 0, sizeof(hints));
78 hints.ai_socktype = SOCK_STREAM;
79 hints.ai_family = r->ai_family;
80 hints.ai_flags = AI_PASSIVE;
81
82 err = getaddrinfo(c->bind_address, c->bind_port, &hints, &bindaddr);
83 if (err) {
84 int len = 100 + strlen(gai_strerror(err));
85 m_free(c->errstring);
86 c->errstring = (char*)m_malloc(len);
87 snprintf(c->errstring, len, "Error resolving bind address '%s' (port %s). %s",
88 c->bind_address, c->bind_port, gai_strerror(err));
89 TRACE(("Error resolving bind: %s", gai_strerror(err)))
90 close(c->sock);
91 c->sock = -1;
92 continue;
93 }
94 res = bind(c->sock, bindaddr->ai_addr, bindaddr->ai_addrlen);
95 freeaddrinfo(bindaddr);
96 bindaddr = NULL;
97 if (res < 0) {
98 /* failure */
99 int keep_errno = errno;
100 int len = 300;
101 m_free(c->errstring);
102 c->errstring = m_malloc(len);
103 snprintf(c->errstring, len, "Error binding local address '%s' (port %s). %s",
104 c->bind_address, c->bind_port, strerror(keep_errno));
105 close(c->sock);
106 c->sock = -1;
107 continue;
108 }
67 } 109 }
68 110
69 ses.maxfd = MAX(ses.maxfd, c->sock); 111 ses.maxfd = MAX(ses.maxfd, c->sock);
70 set_sock_nodelay(c->sock); 112 set_sock_nodelay(c->sock);
71 setnonblocking(c->sock); 113 setnonblocking(c->sock);
128 } 170 }
129 } 171 }
130 172
131 /* Connect via TCP to a host. */ 173 /* Connect via TCP to a host. */
132 struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport, 174 struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport,
133 connect_callback cb, void* cb_data) 175 connect_callback cb, void* cb_data,
176 const char* bind_address, const char* bind_port)
134 { 177 {
135 struct dropbear_progress_connection *c = NULL; 178 struct dropbear_progress_connection *c = NULL;
136 int err; 179 int err;
137 struct addrinfo hints; 180 struct addrinfo hints;
138 181
158 remotehost, remoteport, gai_strerror(err)); 201 remotehost, remoteport, gai_strerror(err));
159 TRACE(("Error resolving: %s", gai_strerror(err))) 202 TRACE(("Error resolving: %s", gai_strerror(err)))
160 } else { 203 } else {
161 c->res_iter = c->res; 204 c->res_iter = c->res;
162 } 205 }
206
207 if (bind_address) {
208 c->bind_address = m_strdup(bind_address);
209 }
210 if (bind_port) {
211 c->bind_port = m_strdup(bind_port);
212 }
163 213
164 return c; 214 return c;
165 } 215 }
166 216
167 void remove_connect_pending() { 217 void remove_connect_pending() {
195 } 245 }
196 iter = next_iter; 246 iter = next_iter;
197 } 247 }
198 } 248 }
199 249
200 void handle_connect_fds(fd_set *writefd) { 250 void handle_connect_fds(const fd_set *writefd) {
201 m_list_elem *iter; 251 m_list_elem *iter;
202 TRACE(("enter handle_connect_fds")) 252 TRACE(("enter handle_connect_fds"))
203 for (iter = ses.conn_pending.first; iter; iter = iter->next) { 253 for (iter = ses.conn_pending.first; iter; iter = iter->next) {
204 int val; 254 int val;
205 socklen_t vallen = sizeof(val); 255 socklen_t vallen = sizeof(val);
238 288
239 void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue) { 289 void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue) {
240 c->writequeue = writequeue; 290 c->writequeue = writequeue;
241 } 291 }
242 292
243 void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count) { 293 void packet_queue_to_iovec(const struct Queue *queue, struct iovec *iov, unsigned int *iov_count) {
244 struct Link *l; 294 struct Link *l;
245 unsigned int i; 295 unsigned int i;
246 int len; 296 int len;
247 buffer *writebuf; 297 buffer *writebuf;
248 298
346 strerror(errno)); 396 strerror(errno));
347 #endif 397 #endif
348 398
349 } 399 }
350 400
401 /* from openssh/canohost.c avoid premature-optimization */
402 int get_sock_port(int sock) {
403 struct sockaddr_storage from;
404 socklen_t fromlen;
405 char strport[NI_MAXSERV];
406 int r;
407
408 /* Get IP address of client. */
409 fromlen = sizeof(from);
410 memset(&from, 0, sizeof(from));
411 if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
412 TRACE(("getsockname failed: %d", errno))
413 return 0;
414 }
415
416 /* Work around Linux IPv6 weirdness */
417 if (from.ss_family == AF_INET6)
418 fromlen = sizeof(struct sockaddr_in6);
419
420 /* Non-inet sockets don't have a port number. */
421 if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
422 return 0;
423
424 /* Return port number. */
425 if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
426 strport, sizeof(strport), NI_NUMERICSERV)) != 0) {
427 TRACE(("netio.c/get_sock_port/getnameinfo NI_NUMERICSERV failed: %d", r))
428 }
429 return atoi(strport);
430 }
431
351 /* Listen on address:port. 432 /* Listen on address:port.
352 * Special cases are address of "" listening on everything, 433 * Special cases are address of "" listening on everything,
353 * and address of NULL listening on localhost only. 434 * and address of NULL listening on localhost only.
354 * Returns the number of sockets bound on success, or -1 on failure. On 435 * Returns the number of sockets bound on success, or -1 on failure. On
355 * failure, if errstring wasn't NULL, it'll be a newly malloced error 436 * failure, if errstring wasn't NULL, it'll be a newly malloced error
398 } 479 }
399 TRACE(("leave dropbear_listen: failed resolving")) 480 TRACE(("leave dropbear_listen: failed resolving"))
400 return -1; 481 return -1;
401 } 482 }
402 483
484 /*
485 * when listening on server-assigned-port 0
486 * the assigned ports may differ for address families (v4/v6)
487 * causing problems for tcpip-forward
488 * caller can do a get_socket_address to discover assigned-port
489 * hence, use same port for all address families
490 */
491 u_int16_t *allocated_lport_p = 0;
492 int allocated_lport = 0;
403 493
404 nsock = 0; 494 nsock = 0;
405 for (res = res0; res != NULL && nsock < sockcount; 495 for (res = res0; res != NULL && nsock < sockcount;
406 res = res->ai_next) { 496 res = res->ai_next) {
497
498 if (allocated_lport > 0) {
499 if (AF_INET == res->ai_family) {
500 allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
501 } else if (AF_INET6 == res->ai_family) {
502 allocated_lport_p = &((struct sockaddr_in6 *)res->ai_addr)->sin6_port;
503 }
504 *allocated_lport_p = htons(allocated_lport);
505 }
407 506
408 /* Get a socket */ 507 /* Get a socket */
409 socks[nsock] = socket(res->ai_family, res->ai_socktype, 508 socks[nsock] = socket(res->ai_family, res->ai_socktype,
410 res->ai_protocol); 509 res->ai_protocol);
411 510
447 if (listen(sock, DROPBEAR_LISTEN_BACKLOG) < 0) { 546 if (listen(sock, DROPBEAR_LISTEN_BACKLOG) < 0) {
448 err = errno; 547 err = errno;
449 close(sock); 548 close(sock);
450 TRACE(("listen() failed")) 549 TRACE(("listen() failed"))
451 continue; 550 continue;
551 }
552
553 if (0 == allocated_lport) {
554 allocated_lport = get_sock_port(sock);
452 } 555 }
453 556
454 *maxfd = MAX(*maxfd, sock); 557 *maxfd = MAX(*maxfd, sock);
455 558
456 nsock++; 559 nsock++;