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