connection_exit.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "or.h"
  5. int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) {
  6. connection_t *n_stream;
  7. char *colon;
  8. if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0,cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) {
  9. log_fn(LOG_WARNING,"relay begin cell has no \\0. Dropping.");
  10. return 0;
  11. }
  12. colon = strchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE, ':');
  13. if(!colon) {
  14. log_fn(LOG_WARNING,"relay begin cell has no colon. Dropping.");
  15. return 0;
  16. }
  17. *colon = 0;
  18. if(!atoi(colon+1)) { /* bad port */
  19. log_fn(LOG_DEBUG,"relay begin cell has invalid port. Dropping.");
  20. return 0;
  21. }
  22. log_fn(LOG_DEBUG,"Creating new exit connection.");
  23. n_stream = connection_new(CONN_TYPE_EXIT);
  24. if(!n_stream) {
  25. log_fn(LOG_DEBUG,"connection_new failed. Dropping.");
  26. return 0;
  27. }
  28. memcpy(n_stream->stream_id, cell->payload + RELAY_HEADER_SIZE, STREAM_ID_SIZE);
  29. n_stream->address = strdup(cell->payload + RELAY_HEADER_SIZE + STREAM_ID_SIZE);
  30. n_stream->port = atoi(colon+1);
  31. n_stream->state = EXIT_CONN_STATE_RESOLVING;
  32. n_stream->receiver_bucket = -1; /* edge connections don't do receiver buckets */
  33. n_stream->bandwidth = -1;
  34. n_stream->s = -1; /* not yet valid */
  35. n_stream->package_window = STREAMWINDOW_START;
  36. n_stream->deliver_window = STREAMWINDOW_START;
  37. if(connection_add(n_stream) < 0) { /* no space, forget it */
  38. log_fn(LOG_DEBUG,"connection_add failed. Dropping.");
  39. connection_free(n_stream);
  40. return 0;
  41. }
  42. /* add it into the linked list of streams on this circuit */
  43. n_stream->next_stream = circ->n_streams;
  44. circ->n_streams = n_stream;
  45. /* send it off to the gethostbyname farm */
  46. switch(dns_resolve(n_stream)) {
  47. case 1: /* resolve worked */
  48. if(connection_exit_connect(n_stream) >= 0)
  49. return 0;
  50. /* else fall through */
  51. case -1: /* resolve failed */
  52. log_fn(LOG_DEBUG,"Couldn't queue resolve request.");
  53. connection_remove(n_stream);
  54. connection_free(n_stream);
  55. case 0: /* resolve added to pending list */
  56. ;
  57. }
  58. return 0;
  59. }
  60. int connection_exit_connect(connection_t *conn) {
  61. int s; /* for the new socket */
  62. struct sockaddr_in dest_addr;
  63. if(router_compare_to_exit_policy(conn) < 0) {
  64. log_fn(LOG_INFO,"%s:%d failed exit policy. Closing.", conn->address, conn->port);
  65. return -1;
  66. }
  67. /* all the necessary info is here. Start the connect() */
  68. s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  69. if (s < 0) {
  70. log_fn(LOG_ERR,"Error creating network socket.");
  71. return -1;
  72. }
  73. set_socket_nonblocking(s);
  74. memset((void *)&dest_addr,0,sizeof(dest_addr));
  75. dest_addr.sin_family = AF_INET;
  76. dest_addr.sin_port = htons(conn->port);
  77. dest_addr.sin_addr.s_addr = htonl(conn->addr);
  78. log_fn(LOG_DEBUG,"Connecting to %s:%u.",conn->address,conn->port);
  79. if(connect(s,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0) {
  80. if(!ERRNO_CONN_EINPROGRESS(errno)) {
  81. /* yuck. kill it. */
  82. perror("connect");
  83. log_fn(LOG_DEBUG,"Connect failed.");
  84. return -1;
  85. } else {
  86. /* it's in progress. set state appropriately and return. */
  87. conn->s = s;
  88. connection_set_poll_socket(conn);
  89. conn->state = EXIT_CONN_STATE_CONNECTING;
  90. log_fn(LOG_DEBUG,"connect in progress, socket %d.",s);
  91. connection_watch_events(conn, POLLOUT | POLLIN | POLLERR);
  92. /* writable indicates finish, readable indicates broken link,
  93. error indicates broken link in windowsland. */
  94. return 0;
  95. }
  96. }
  97. /* it succeeded. we're connected. */
  98. log_fn(LOG_DEBUG,"Connection to %s:%u established.",conn->address,conn->port);
  99. conn->s = s;
  100. connection_set_poll_socket(conn);
  101. conn->state = EXIT_CONN_STATE_OPEN;
  102. if(connection_wants_to_flush(conn)) { /* in case there are any queued data cells */
  103. log_fn(LOG_ERR,"tell roger: newly connected conn had data waiting!");
  104. // connection_start_writing(conn);
  105. }
  106. // connection_process_inbuf(conn);
  107. connection_watch_events(conn, POLLIN);
  108. /* also, deliver a 'connected' cell back through the circuit. */
  109. return connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED);
  110. }
  111. /*
  112. Local Variables:
  113. mode:c
  114. indent-tabs-mode:nil
  115. c-basic-offset:2
  116. End:
  117. */