Mercurial > hg > nnchat
comparison network.c @ 615:399ce077b2a0
Factorize more proxy initialization stuff into separate functions.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 20 May 2014 07:15:48 +0300 |
parents | 1fc22e8efd26 |
children |
comparison
equal
deleted
inserted
replaced
614:1fc22e8efd26 | 615:399ce077b2a0 |
---|---|
238 th_free(buf); | 238 th_free(buf); |
239 return ret; | 239 return ret; |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 static int nn_conn_socks4_negotiate(nn_conn_t *conn, const int port, const char *host) | |
244 { | |
245 struct nn_socks4_res_t *sockres; | |
246 struct nn_socks4_t *socksh; | |
247 size_t bufsiz; | |
248 uint8_t *ptr, *buf; | |
249 | |
250 (void) host; | |
251 | |
252 nn_conn_msg(conn, "Initializing SOCKS 4/a proxy negotiation.\n"); | |
253 | |
254 bufsiz = sizeof(struct nn_socks4_t) + strlen(conn->proxy.userid) + 1; | |
255 if (conn->proxy.type == NN_PROXY_SOCKS4A) | |
256 bufsiz += strlen(conn->host) + 1; | |
257 | |
258 if ((ptr = buf = th_malloc(bufsiz)) == NULL) | |
259 { | |
260 nn_conn_err(conn, "Could not allocate memory for SOCKS negotiation buffer, %d bytes.\n", bufsiz); | |
261 return FALSE; | |
262 } | |
263 | |
264 // Create SOCKS 4 handshake | |
265 socksh = (struct nn_socks4_t *) buf; | |
266 socksh->version = 4; | |
267 socksh->command = NN_PROXY_CMD_CONNECT; | |
268 socksh->port = htons(port); | |
269 socksh->addr = (conn->proxy.type == NN_PROXY_SOCKS4A) ? htonl(0x00000032) : conn->addr.s_addr; | |
270 ptr += sizeof(struct nn_socks4_t); | |
271 | |
272 strcpy((char *) ptr, conn->proxy.userid); | |
273 | |
274 if (conn->proxy.type == NN_PROXY_SOCKS4A) | |
275 { | |
276 ptr += strlen(conn->proxy.userid) + 1; | |
277 strcpy((char *)ptr, conn->host); | |
278 } | |
279 | |
280 // Send request | |
281 if (!nn_conn_proxy_send(conn, buf, bufsiz)) | |
282 return FALSE; | |
283 | |
284 // Wait for SOCKS server to reply | |
285 if (nn_conn_proxy_wait(conn) != 0) | |
286 return FALSE; | |
287 | |
288 sockres = (struct nn_socks4_res_t *) &(conn->buf); | |
289 if (sockres->nb != 0) | |
290 { | |
291 nn_conn_err(conn, "Invalid SOCKS 4 server reply, does not begin with NUL byte (%d).\n", sockres->nb); | |
292 return FALSE; | |
293 } | |
294 if (sockres->result != 0x5a) | |
295 { | |
296 char *s = NULL; | |
297 switch (sockres->result) | |
298 { | |
299 case 0x5b: s = "Request rejected or failed"; break; | |
300 case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break; | |
301 case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break; | |
302 default: s = "Unknown SOCKS 4 error response"; break; | |
303 } | |
304 nn_conn_err(conn, "SOCKS 4 setup failed, 0x%02x: %s.\n", sockres->result, s); | |
305 return FALSE; | |
306 } | |
307 | |
308 return TRUE; | |
309 } | |
310 | |
311 | |
243 int nn_conn_open(nn_conn_t *conn, const int port, const char *host) | 312 int nn_conn_open(nn_conn_t *conn, const int port, const char *host) |
244 { | 313 { |
245 struct sockaddr_in dest; | 314 struct sockaddr_in dest; |
246 | 315 |
247 if (conn == NULL) | 316 if (conn == NULL) |
259 // Prepare for connection | 328 // Prepare for connection |
260 dest.sin_family = AF_INET; | 329 dest.sin_family = AF_INET; |
261 | 330 |
262 if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) | 331 if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) |
263 { | 332 { |
333 // If using a proxy, we connect to the proxy server | |
264 dest.sin_port = htons(conn->proxy.port); | 334 dest.sin_port = htons(conn->proxy.port); |
265 dest.sin_addr = conn->proxy.addr; | 335 dest.sin_addr = conn->proxy.addr; |
266 | 336 |
267 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n", | 337 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n", |
268 nn_proxy_types[conn->proxy.type], | 338 nn_proxy_types[conn->proxy.type], |
293 | 363 |
294 FD_ZERO(&(conn->sockfds)); | 364 FD_ZERO(&(conn->sockfds)); |
295 FD_SET(conn->socket, &(conn->sockfds)); | 365 FD_SET(conn->socket, &(conn->sockfds)); |
296 | 366 |
297 // Proxy-specific setup | 367 // Proxy-specific setup |
298 if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) | 368 switch (conn->proxy.type) |
299 { | 369 { |
300 struct nn_socks4_res_t *sockres; | 370 case NN_PROXY_SOCKS4: |
301 struct nn_socks4_t *socksh; | 371 case NN_PROXY_SOCKS4A: |
302 size_t bufsiz; | 372 if (!nn_conn_socks4_negotiate(conn, port, host)) |
303 uint8_t *ptr, *buf; | 373 goto error; |
304 | 374 nn_conn_msg(conn, "SOCKS 4 connection established!\n"); |
305 nn_conn_msg(conn, "Initializing SOCKS 4/a proxy negotiation.\n"); | 375 break; |
306 | |
307 bufsiz = sizeof(struct nn_socks4_t) + strlen(conn->proxy.userid) + 1; | |
308 if (conn->proxy.type == NN_PROXY_SOCKS4A) | |
309 bufsiz += strlen(conn->host) + 1; | |
310 | |
311 if ((ptr = buf = th_malloc(bufsiz)) == NULL) | |
312 { | |
313 conn->err = -1; | |
314 nn_conn_err(conn, "Could not allocate memory for SOCKS negotiation buffer, %d bytes.\n", bufsiz); | |
315 goto error; | |
316 } | |
317 | |
318 // Create SOCKS 5 handshake | |
319 socksh = (struct nn_socks4_t *) buf; | |
320 socksh->version = 4; | |
321 socksh->command = NN_PROXY_CMD_CONNECT; | |
322 socksh->port = htons(port); | |
323 socksh->addr = (conn->proxy.type == NN_PROXY_SOCKS4A) ? htonl(0x00000032) : conn->addr.s_addr; | |
324 ptr += sizeof(struct nn_socks4_t); | |
325 | |
326 strcpy((char *) ptr, conn->proxy.userid); | |
327 | |
328 if (conn->proxy.type == NN_PROXY_SOCKS4A) | |
329 { | |
330 ptr += strlen(conn->proxy.userid) + 1; | |
331 strcpy((char *)ptr, conn->host); | |
332 } | |
333 | |
334 // Send request | |
335 if (!nn_conn_proxy_send(conn, buf, bufsiz)) | |
336 goto error; | |
337 | |
338 // Wait for SOCKS server to reply | |
339 if (nn_conn_proxy_wait(conn) != 0) | |
340 goto error; | |
341 | |
342 sockres = (struct nn_socks4_res_t *) &(conn->buf); | |
343 if (sockres->nb != 0) | |
344 { | |
345 nn_conn_err(conn, "Invalid SOCKS 4 server reply, does not begin with NUL byte (%d).\n", sockres->nb); | |
346 goto error; | |
347 } | |
348 if (sockres->result != 0x5a) | |
349 { | |
350 char *s = NULL; | |
351 switch (sockres->result) | |
352 { | |
353 case 0x5b: s = "Request rejected or failed"; break; | |
354 case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break; | |
355 case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break; | |
356 default: s = "Unknown SOCKS 4 error response"; break; | |
357 } | |
358 nn_conn_err(conn, "SOCKS 4 setup failed, 0x%02x: %s.\n", sockres->result, s); | |
359 goto error; | |
360 } | |
361 | |
362 nn_conn_msg(conn, "SOCKS 4 connection established!\n"); | |
363 } | 376 } |
364 | 377 |
365 nn_conn_reset(conn); | 378 nn_conn_reset(conn); |
366 conn->status = NN_CONN_OPEN; | 379 conn->status = NN_CONN_OPEN; |
367 return 0; | 380 return 0; |