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;