comparison netio.c @ 1467:7279a633cc50

Merge branch 'houseofkodai-cli_bind_address_connect'
author Matt Johnston <matt@ucc.asn.au>
date Fri, 26 Jan 2018 00:32:39 +0800
parents f787f60f8e45
children 2d450c1056e3
comparison
equal deleted inserted replaced
1464:ad637c9e0f6f 1467:7279a633cc50
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
157 snprintf(c->errstring, len, "Error resolving '%s' port '%s'. %s", 200 snprintf(c->errstring, len, "Error resolving '%s' port '%s'. %s",
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;
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);
162 } 212 }
163 213
164 return c; 214 return c;
165 } 215 }
166 216