comparison netio.c @ 1465:f7a53832501d

cli_bind_address_connect * replaces -b dummy option in dbclient to be similar with openssh -b option * useful in multi-wan connections
author houseofkodai <karthik@houseofkodai.in>
date Mon, 01 May 2017 08:26:15 +0530
parents ad637c9e0f6f
children f787f60f8e45
comparison
equal deleted inserted replaced
1464:ad637c9e0f6f 1465:f7a53832501d
17 or NULL. */ 17 or NULL. */
18 18
19 int sock; 19 int sock;
20 20
21 char* errstring; 21 char* errstring;
22 struct addrinfo *bind_addrinfo;
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 if (c->bind_addrinfo) freeaddrinfo(c->bind_addrinfo);
33 m_free(c); 35 m_free(c);
34 36
35 if (iter) { 37 if (iter) {
36 list_remove(iter); 38 list_remove(iter);
37 } 39 }
62 dropbear_assert(c->sock == -1); 64 dropbear_assert(c->sock == -1);
63 65
64 c->sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 66 c->sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
65 if (c->sock < 0) { 67 if (c->sock < 0) {
66 continue; 68 continue;
69 }
70
71 if (c->bind_addrinfo) {
72 if (bind(c->sock, c->bind_addrinfo->ai_addr, c->bind_addrinfo->ai_addrlen) < 0) {
73 /* failure */
74 m_free(c->errstring);
75 c->errstring = m_strdup(strerror(errno));
76 close(c->sock);
77 c->sock = -1;
78 continue;
79 }
67 } 80 }
68 81
69 ses.maxfd = MAX(ses.maxfd, c->sock); 82 ses.maxfd = MAX(ses.maxfd, c->sock);
70 set_sock_nodelay(c->sock); 83 set_sock_nodelay(c->sock);
71 setnonblocking(c->sock); 84 setnonblocking(c->sock);
128 } 141 }
129 } 142 }
130 143
131 /* Connect via TCP to a host. */ 144 /* Connect via TCP to a host. */
132 struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport, 145 struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport,
133 connect_callback cb, void* cb_data) 146 connect_callback cb, void* cb_data, char* bind_address)
134 { 147 {
135 struct dropbear_progress_connection *c = NULL; 148 struct dropbear_progress_connection *c = NULL;
136 int err; 149 int err;
137 struct addrinfo hints; 150 struct addrinfo hints;
138 151
140 c->remotehost = m_strdup(remotehost); 153 c->remotehost = m_strdup(remotehost);
141 c->remoteport = m_strdup(remoteport); 154 c->remoteport = m_strdup(remoteport);
142 c->sock = -1; 155 c->sock = -1;
143 c->cb = cb; 156 c->cb = cb;
144 c->cb_data = cb_data; 157 c->cb_data = cb_data;
158 c->bind_addrinfo = NULL;
145 159
146 list_append(&ses.conn_pending, c); 160 list_append(&ses.conn_pending, c);
147 161
148 memset(&hints, 0, sizeof(hints)); 162 memset(&hints, 0, sizeof(hints));
149 hints.ai_socktype = SOCK_STREAM; 163 hints.ai_socktype = SOCK_STREAM;
157 snprintf(c->errstring, len, "Error resolving '%s' port '%s'. %s", 171 snprintf(c->errstring, len, "Error resolving '%s' port '%s'. %s",
158 remotehost, remoteport, gai_strerror(err)); 172 remotehost, remoteport, gai_strerror(err));
159 TRACE(("Error resolving: %s", gai_strerror(err))) 173 TRACE(("Error resolving: %s", gai_strerror(err)))
160 } else { 174 } else {
161 c->res_iter = c->res; 175 c->res_iter = c->res;
176 }
177
178 if (NULL != bind_address) {
179 memset(&hints, 0, sizeof(hints));
180 hints.ai_socktype = SOCK_STREAM;
181 hints.ai_family = AF_UNSPEC;
182 err = getaddrinfo(bind_address, NULL, &hints, &c->bind_addrinfo);
183 if (err) {
184 int len;
185 len = 100 + strlen(gai_strerror(err));
186 c->errstring = (char*)m_malloc(len);
187 snprintf(c->errstring, len, "Error resolving '%s'. %s",
188 bind_address, gai_strerror(err));
189 TRACE(("Error resolving: %s", gai_strerror(err)))
190 c->res_iter = NULL;
191 }
162 } 192 }
163 193
164 return c; 194 return c;
165 } 195 }
166 196