Mercurial > dropbear
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 |