command.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include "or.h"
  2. void command_process_cell(cell_t *cell, connection_t *conn) {
  3. if(check_sane_cell(cell) < 0)
  4. return;
  5. switch(cell->command) {
  6. case CELL_PADDING:
  7. /* do nothing */
  8. break;
  9. case CELL_CREATE:
  10. command_process_create_cell(cell, conn);
  11. break;
  12. case CELL_DATA:
  13. command_process_data_cell(cell, conn);
  14. break;
  15. case CELL_DESTROY:
  16. command_process_destroy_cell(cell, conn);
  17. break;
  18. }
  19. }
  20. void command_process_create_cell(cell_t *cell, connection_t *conn) {
  21. circuit_t *circ;
  22. connection_t *n_conn;
  23. unsigned char *cellbuf; /* array of cells */
  24. int cellbuflen; /* size of cellbuf in bytes */
  25. cell_t *tmpcell; /* pointer to an arbitrary cell */
  26. int retval, i;
  27. circ = circuit_get_by_aci_conn(cell->aci, conn);
  28. if(circ && circ->state != CIRCUIT_STATE_OPEN_WAIT) {
  29. log(LOG_DEBUG,"command_process_create_cell(): received CREATE cell, not in open_wait. Dropping.");
  30. return;
  31. }
  32. if(!circ) { /* if it's not there, create it */
  33. circ = circuit_new(cell->aci, conn);
  34. circ->state = CIRCUIT_STATE_OPEN_WAIT;
  35. memcpy((void *)&circ->onionlen,(void *)cell->payload, 4);
  36. circ->onionlen = ntohl(circ->onionlen);
  37. log(LOG_DEBUG,"command_process_create_cell(): Onion length is %u.",circ->onionlen);
  38. if(circ->onionlen > 50000) { /* too big */
  39. log(LOG_DEBUG,"That's ludicrous. Closing.");
  40. circuit_close(circ);
  41. return;
  42. }
  43. circ->onion = (unsigned char *)malloc(circ->onionlen);
  44. if(!circ->onion) {
  45. log(LOG_DEBUG,"command_process_create_cell(): Out of memory. Closing.");
  46. circuit_close(circ);
  47. return;
  48. }
  49. if(circ->onionlen < cell->length-4) { /* protect from buffer overflow */
  50. log(LOG_DEBUG,"command_process_create_cell(): Onion too small. Closing.");
  51. circuit_close(circ);
  52. return;
  53. }
  54. memcpy((void *)circ->onion,(void *)(cell->payload+4),cell->length-4);
  55. circ->recvlen = cell->length-4;
  56. log(LOG_DEBUG,"command_process_create_cell(): Primary create cell handled, have received %d of %d onion bytes.",
  57. circ->recvlen,circ->onionlen);
  58. } else { /* pull over as much of the onion as we can */
  59. if(cell->length + circ->recvlen > circ->onionlen) { /* protect from buffer overflow */
  60. log(LOG_DEBUG,"command_process_create_cell(): payload too big for onion. Closing.");
  61. circuit_close(circ);
  62. return;
  63. }
  64. memcpy((void *)(circ->onion+circ->recvlen),(void *)cell->payload,cell->length);
  65. circ->recvlen += cell->length;
  66. log(LOG_DEBUG,"command_process_create_cell(): Secondary create cell handled, have received %d of %d onion bytes.",
  67. circ->recvlen,circ->onionlen);
  68. }
  69. if(circ->recvlen != circ->onionlen) {
  70. log(LOG_DEBUG,"command_process_create_cell(): Onion not all here yet. Ok.");
  71. return;
  72. }
  73. /* we're all ready to go now. */
  74. circ->state = CIRCUIT_STATE_OPEN;
  75. if(process_onion(circ, conn) < 0) {
  76. log(LOG_DEBUG,"command_process_create_cell(): Onion processing failed. Closing.");
  77. circuit_close(circ);
  78. return;
  79. }
  80. if(circ->n_addr && circ->n_port) { /* must send create cells to the next router */
  81. n_conn = connection_get_by_addr_port(circ->n_addr,circ->n_port);
  82. if(!n_conn || n_conn->type != CONN_TYPE_OR) {
  83. /* i've disabled making connections through OPs, but it's definitely
  84. * possible here. I'm not sure if it would be a bug or a feature. -RD
  85. */
  86. log(LOG_DEBUG,"command_process_create_cell(): Next router not connected. Closing.");
  87. circuit_close(circ);
  88. }
  89. circ->n_conn = n_conn;
  90. log(LOG_DEBUG,"command_process_create_cell(): n_conn is %s:%u",n_conn->address,ntohs(n_conn->port));
  91. /* send the CREATE cells on to the next hop */
  92. pad_onion(circ->onion,circ->onionlen, sizeof(onion_layer_t));
  93. log(LOG_DEBUG,"command_process_create_cell(): Padded the onion with random data.");
  94. retval = pack_create(circ->n_aci, circ->onion, circ->onionlen, &cellbuf, &cellbuflen);
  95. free((void *)circ->onion);
  96. circ->onion = NULL;
  97. if (retval == -1) /* pack_create() error */
  98. {
  99. log(LOG_DEBUG,"command_process_create_cell(): Could not pack the onion into CREATE cells. Closing the connection.");
  100. circuit_close(circ);
  101. return;
  102. }
  103. log(LOG_DEBUG,"command_process_create_cell(): Onion packed into CREATE cells. Buffering the cells.");
  104. /* queue the create cells for transmission to the next hop */
  105. tmpcell = (cell_t *)cellbuf;
  106. for (i=0;i<cellbuflen/sizeof(cell_t);i++)
  107. {
  108. retval = connection_write_cell_to_buf(tmpcell, n_conn);
  109. if (retval == -1) /* buffering failed, drop the connection */
  110. {
  111. log(LOG_DEBUG,"command_process_create_cell(): Could not buffer new create cells. Closing.");
  112. circuit_close(circ);
  113. return;
  114. }
  115. tmpcell++;
  116. }
  117. free((void *)cellbuf);
  118. return;
  119. } else { /* this is destined for an app */
  120. log(LOG_DEBUG,"command_process_create_cell(): Creating new application connection.");
  121. n_conn = connection_new(CONN_TYPE_APP);
  122. if(!n_conn) {
  123. log(LOG_DEBUG,"command_process_create_cell(): connection_new failed. Closing.");
  124. circuit_close(circ);
  125. return;
  126. }
  127. n_conn->state = APP_CONN_STATE_CONNECTING_WAIT;
  128. n_conn->s = -1; /* not yet valid */
  129. if(connection_add(n_conn) < 0) { /* no space, forget it */
  130. log(LOG_DEBUG,"command_process_create_cell(): connection_add failed. Closing.");
  131. connection_free(n_conn);
  132. circuit_close(circ);
  133. return;
  134. }
  135. circ->n_conn = n_conn;
  136. return;
  137. }
  138. }
  139. void command_process_data_cell(cell_t *cell, connection_t *conn) {
  140. circuit_t *circ;
  141. /* FIXME do something with 'close' state, here */
  142. circ = circuit_get_by_aci_conn(cell->aci, conn);
  143. if(!circ) {
  144. log(LOG_DEBUG,"command_process_data_cell(): received DATA cell for unknown circuit. Dropping.");
  145. return;
  146. }
  147. if(circ->state == CIRCUIT_STATE_OPEN_WAIT) {
  148. log(LOG_DEBUG,"command_process_data_cell(): circuit in open_wait. Dropping data cell.");
  149. return;
  150. }
  151. /* at this point both circ->n_conn and circ->p_conn are guaranteed to be set */
  152. if(cell->aci == circ->p_aci) { /* it's an outgoing cell */
  153. cell->aci = circ->n_aci; /* switch it */
  154. if(circuit_deliver_data_cell(cell, circ, circ->n_conn, 'd') < 0) {
  155. log(LOG_DEBUG,"command_process_data_cell(): circuit_deliver_data_cell (forward) failed. Closing.");
  156. circuit_close(circ);
  157. return;
  158. }
  159. } else { /* it's an ingoing cell */
  160. cell->aci = circ->p_aci; /* switch it */
  161. if(circuit_deliver_data_cell(cell, circ, circ->p_conn, 'e') < 0) {
  162. log(LOG_DEBUG,"command_process_data_cell(): circuit_deliver_data_cell (backward) failed. Closing.");
  163. circuit_close(circ);
  164. return;
  165. }
  166. }
  167. }
  168. void command_process_destroy_cell(cell_t *cell, connection_t *conn) {
  169. circuit_t *circ;
  170. circ = circuit_get_by_aci_conn(cell->aci, conn);
  171. if(!circ) {
  172. log(LOG_DEBUG,"command_process_destroy_cell(): received DESTROY cell for unknown circuit. Dropping.");
  173. return;
  174. }
  175. log(LOG_DEBUG,"command_process_destroy_cell(): Received for aci %d.",cell->aci);
  176. circuit_remove(circ);
  177. if(cell->aci == circ->p_aci) /* the destroy came from behind */
  178. connection_send_destroy(circ->n_aci, circ->n_conn);
  179. if(cell->aci == circ->n_aci) /* the destroy came from ahead */
  180. connection_send_destroy(circ->p_aci, circ->p_conn);
  181. circuit_free(circ);
  182. }