1 /* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
2 /* See LICENSE for licensing information */
8 extern or_options_t options
; /* command-line and config-file options */
9 extern char *conn_state_to_string
[][_CONN_TYPE_MAX
+1];
11 static int connection_ap_handshake_process_socks(connection_t
*conn
);
12 static int connection_ap_handshake_attach_circuit(connection_t
*conn
);
13 static int connection_ap_handshake_attach_circuit_helper(connection_t
*conn
);
14 static void connection_ap_handshake_send_begin(connection_t
*ap_conn
, circuit_t
*circ
);
15 static int connection_ap_handshake_socks_reply(connection_t
*conn
, char *reply
,
16 int replylen
, char success
);
18 static int connection_exit_begin_conn(cell_t
*cell
, circuit_t
*circ
);
19 static void connection_edge_consider_sending_sendme(connection_t
*conn
);
21 static uint32_t client_dns_lookup_entry(const char *address
);
22 static void client_dns_set_entry(const char *address
, uint32_t val
);
24 void relay_header_pack(char *dest
, const relay_header_t
*src
) {
25 *(uint8_t*)(dest
) = src
->command
;
26 *(uint16_t*)(dest
+1) = htons(src
->recognized
);
27 *(uint16_t*)(dest
+3) = htons(src
->stream_id
);
28 memcpy(dest
+5, src
->integrity
, 4);
29 *(uint16_t*)(dest
+9) = htons(src
->length
);
32 void relay_header_unpack(relay_header_t
*dest
, const char *src
) {
33 dest
->command
= *(uint8_t*)(src
);
34 dest
->recognized
= ntohs(*(uint16_t*)(src
+1));
35 dest
->stream_id
= ntohs(*(uint16_t*)(src
+3));
36 memcpy(dest
->integrity
, src
+5, 4);
37 dest
->length
= ntohs(*(uint16_t*)(src
+9));
40 int connection_edge_process_inbuf(connection_t
*conn
) {
43 assert(conn
->type
== CONN_TYPE_AP
|| conn
->type
== CONN_TYPE_EXIT
);
45 if(conn
->inbuf_reached_eof
) {
47 /* eof reached; we're done reading, but we might want to write more. */
48 conn
->done_receiving
= 1;
49 shutdown(conn
->s
, 0); /* XXX check return, refactor NM */
50 if (conn
->done_sending
) {
51 connection_mark_for_close(conn
, END_STREAM_REASON_DONE
);
53 connection_edge_send_command(conn
, circuit_get_by_conn(conn
), RELAY_COMMAND_END
,
54 NULL
, 0, conn
->cpath_layer
);
58 /* eof reached, kill it. */
59 log_fn(LOG_INFO
,"conn (fd %d) reached eof. Closing.", conn
->s
);
60 connection_mark_for_close(conn
, END_STREAM_REASON_DONE
);
66 case AP_CONN_STATE_SOCKS_WAIT
:
67 if(connection_ap_handshake_process_socks(conn
) < 0) {
68 connection_mark_for_close(conn
, END_STREAM_REASON_MISC
);
72 case AP_CONN_STATE_OPEN
:
73 case EXIT_CONN_STATE_OPEN
:
74 if(conn
->package_window
<= 0) {
75 log_fn(LOG_WARN
,"called with package_window %d. Tell Roger.", conn
->package_window
);
78 if(connection_edge_package_raw_inbuf(conn
) < 0) {
79 connection_mark_for_close(conn
, END_STREAM_REASON_MISC
);
83 case EXIT_CONN_STATE_CONNECTING
:
84 log_fn(LOG_INFO
,"text from server while in 'connecting' state at exit. Leaving it on buffer.");
87 log_fn(LOG_WARN
,"Got unexpected state %d. Closing.",conn
->state
);
91 static char *connection_edge_end_reason(char *payload
, uint16_t length
) {
93 log_fn(LOG_WARN
,"End cell arrived with length 0. Should be at least 1.");
96 if(*payload
< END_STREAM_REASON_MISC
|| *payload
> END_STREAM_REASON_DONE
) {
97 log_fn(LOG_WARN
,"Reason for ending (%d) not recognized.",*payload
);
101 case END_STREAM_REASON_MISC
: return "misc error";
102 case END_STREAM_REASON_RESOLVEFAILED
: return "resolve failed";
103 case END_STREAM_REASON_CONNECTFAILED
: return "connect failed";
104 case END_STREAM_REASON_EXITPOLICY
: return "exit policy failed";
105 case END_STREAM_REASON_DESTROY
: return "destroyed";
106 case END_STREAM_REASON_DONE
: return "closed normally";
112 int connection_edge_end(connection_t
*conn
, char reason
, crypt_path_t
*cpath_layer
) {
117 if(conn
->has_sent_end
) {
118 log_fn(LOG_WARN
,"It appears I've already sent the end. Are you calling me twice?");
123 if(reason
== END_STREAM_REASON_EXITPOLICY
) {
124 *(uint32_t *)(payload
+1) = htonl(conn
->addr
);
128 circ
= circuit_get_by_conn(conn
);
129 if(circ
&& !circ
->marked_for_close
) {
130 log_fn(LOG_DEBUG
,"Marking conn (fd %d) and sending end.",conn
->s
);
131 connection_edge_send_command(conn
, circ
, RELAY_COMMAND_END
,
132 payload
, payload_len
, cpath_layer
);
134 log_fn(LOG_DEBUG
,"Marking conn (fd %d); no circ to send end.",conn
->s
);
137 conn
->has_sent_end
= 1;
141 int connection_edge_send_command(connection_t
*fromconn
, circuit_t
*circ
, int relay_command
,
142 void *payload
, int payload_len
, crypt_path_t
*cpath_layer
) {
148 log_fn(LOG_WARN
,"no circ. Closing.");
150 connection_mark_for_close(fromconn
,0);
154 memset(&cell
, 0, sizeof(cell_t
));
155 cell
.command
= CELL_RELAY
;
156 // if(fromconn && fromconn->type == CONN_TYPE_AP) {
158 cell
.circ_id
= circ
->n_circ_id
;
159 cell_direction
= CELL_DIRECTION_OUT
;
161 cell
.circ_id
= circ
->p_circ_id
;
162 cell_direction
= CELL_DIRECTION_IN
;
165 memset(&rh
, 0, sizeof(rh
));
166 rh
.command
= relay_command
;
168 rh
.stream_id
= fromconn
->stream_id
; /* else it's 0 */
169 rh
.length
= payload_len
;
170 relay_header_pack(cell
.payload
, &rh
);
172 memcpy(cell
.payload
+RELAY_HEADER_SIZE
, payload
, payload_len
);
174 log_fn(LOG_DEBUG
,"delivering %d cell %s.", relay_command
,
175 cell_direction
== CELL_DIRECTION_OUT
? "forward" : "backward");
177 if(circuit_package_relay_cell(&cell
, circ
, cell_direction
, cpath_layer
) < 0) {
178 log_fn(LOG_WARN
,"circuit_package_relay_cell failed. Closing.");
185 /* an incoming relay cell has arrived. return -1 if you want to tear down the
186 * circuit, else 0. */
187 int connection_edge_process_relay_cell(cell_t
*cell
, circuit_t
*circ
, connection_t
*conn
,
188 int edge_type
, crypt_path_t
*layer_hint
) {
189 static int num_seen
=0;
193 assert(cell
&& circ
);
195 relay_header_unpack(&rh
, cell
->payload
);
196 // log_fn(LOG_DEBUG,"command %d stream %d", rh.command, rh.stream_id);
198 log_fn(LOG_DEBUG
,"Now seen %d relay cells here.", num_seen
);
200 /* either conn is NULL, in which case we've got a control cell, or else
201 * conn points to the recognized stream. */
203 if(conn
&& conn
->state
!= AP_CONN_STATE_OPEN
&& conn
->state
!= EXIT_CONN_STATE_OPEN
) {
204 if(rh
.command
== RELAY_COMMAND_END
) {
205 log_fn(LOG_INFO
,"Exit got end (%s) before we're connected. Marking for close.",
206 connection_edge_end_reason(cell
->payload
+RELAY_HEADER_SIZE
, rh
.length
));
207 conn
->has_sent_end
= 1; /* So we don't send an end cell. */
208 connection_mark_for_close(conn
, 0);
211 if(conn
->type
== CONN_TYPE_AP
&& rh
.command
== RELAY_COMMAND_CONNECTED
) {
212 if(conn
->state
!= AP_CONN_STATE_CONNECTING
) {
213 log_fn(LOG_WARN
,"Got 'connected' while not in state connecting. Dropping.");
216 log_fn(LOG_INFO
,"Connected! Notifying application.");
217 conn
->state
= AP_CONN_STATE_OPEN
;
218 if (rh
.length
>= 4) {
219 addr
= ntohl(*(uint32_t*)(cell
->payload
+ RELAY_HEADER_SIZE
));
220 client_dns_set_entry(conn
->socks_request
->address
, addr
);
222 log_fn(LOG_WARN
,"'connected' received after %d seconds.",
223 (int)(time(NULL
) - conn
->timestamp_lastread
));
224 circuit_log_path(LOG_WARN
,circ
);
225 if(connection_ap_handshake_socks_reply(conn
, NULL
, 0, 1) < 0) {
226 log_fn(LOG_INFO
,"Writing to socks-speaking application failed. Closing.");
227 connection_mark_for_close(conn
, END_STREAM_REASON_MISC
);
231 log_fn(LOG_WARN
,"Got an unexpected relay command %d, in state %d (%s). Closing.",
232 rh
.command
, conn
->state
, conn_state_to_string
[conn
->type
][conn
->state
]);
233 connection_mark_for_close(conn
, END_STREAM_REASON_MISC
);
239 case RELAY_COMMAND_DROP
:
240 log_fn(LOG_INFO
,"Got a relay-level padding cell. Dropping.");
242 case RELAY_COMMAND_BEGIN
:
243 if(edge_type
== EDGE_AP
) {
244 log_fn(LOG_WARN
,"relay begin request unsupported at AP. Dropping.");
248 log_fn(LOG_WARN
,"begin cell for known stream. Dropping.");
251 connection_exit_begin_conn(cell
, circ
);
253 case RELAY_COMMAND_DATA
:
254 ++stats_n_data_cells_received
;
255 if((edge_type
== EDGE_AP
&& --layer_hint
->deliver_window
< 0) ||
256 (edge_type
== EDGE_EXIT
&& --circ
->deliver_window
< 0)) {
257 log_fn(LOG_WARN
,"(relay data) circ deliver_window below 0. Killing.");
258 connection_mark_for_close(conn
, END_STREAM_REASON_MISC
);
261 log_fn(LOG_DEBUG
,"circ deliver_window now %d.", edge_type
== EDGE_AP
?
262 layer_hint
->deliver_window
: circ
->deliver_window
);
264 circuit_consider_sending_sendme(circ
, edge_type
, layer_hint
);
267 log_fn(LOG_INFO
,"data cell dropped, unknown stream.");
271 if(--conn
->deliver_window
< 0) { /* is it below 0 after decrement? */
272 log_fn(LOG_WARN
,"(relay data) conn deliver_window below 0. Killing.");
273 return -1; /* somebody's breaking protocol. kill the whole circuit. */
276 stats_n_data_bytes_received
+= rh
.length
;
277 connection_write_to_buf(cell
->payload
+ RELAY_HEADER_SIZE
,
279 connection_edge_consider_sending_sendme(conn
);
281 case RELAY_COMMAND_END
:
283 log_fn(LOG_INFO
,"end cell (%s) dropped, unknown stream.",
284 connection_edge_end_reason(cell
->payload
+RELAY_HEADER_SIZE
, rh
.length
));
288 *(cell
->payload
+RELAY_HEADER_SIZE
) == END_STREAM_REASON_EXITPOLICY
) {
289 /* No need to close the connection. We'll hold it open while
290 * we try a new exit node.
291 * cell->payload+RELAY_HEADER_SIZE+1 holds the destination addr.
293 addr
= ntohl(*(uint32_t*)(cell
->payload
+RELAY_HEADER_SIZE
+1));
294 client_dns_set_entry(conn
->socks_request
->address
, addr
);
295 conn
->state
= AP_CONN_STATE_CIRCUIT_WAIT
;
296 if(connection_ap_handshake_attach_circuit(conn
) >= 0)
298 /* else, conn will get closed below */
300 /* XXX add to this log_fn the exit node's nickname? */
301 log_fn(LOG_INFO
,"end cell (%s) for stream %d. Removing stream.",
302 connection_edge_end_reason(cell
->payload
+RELAY_HEADER_SIZE
, rh
.length
),
306 conn
->done_sending
= 1;
307 shutdown(conn
->s
, 1); /* XXX check return; refactor NM */
308 if (conn
->done_receiving
) {
309 conn
->has_sent_end
= 1; /* no need to send end, we just got one! */
310 connection_mark_for_close(conn
, END_STREAM_REASON_DONE
);
313 conn
->has_sent_end
= 1; /* no need to send end, we just got one! */
314 connection_mark_for_close(conn
, 0);
317 case RELAY_COMMAND_EXTEND
:
319 log_fn(LOG_WARN
,"'extend' for non-zero stream. Dropping.");
322 return circuit_extend(cell
, circ
);
323 case RELAY_COMMAND_EXTENDED
:
324 if(edge_type
== EDGE_EXIT
) {
325 log_fn(LOG_WARN
,"'extended' unsupported at exit. Dropping.");
328 log_fn(LOG_DEBUG
,"Got an extended cell! Yay.");
329 if(circuit_finish_handshake(circ
, cell
->payload
+RELAY_HEADER_SIZE
) < 0) {
330 log_fn(LOG_WARN
,"circuit_finish_handshake failed.");
333 if (circuit_send_next_onion_skin(circ
)<0) {
334 log_fn(LOG_INFO
,"circuit_send_next_onion_skin() failed.");
338 case RELAY_COMMAND_TRUNCATE
:
339 if(edge_type
== EDGE_AP
) {
340 log_fn(LOG_WARN
,"'truncate' unsupported at AP. Dropping.");
344 connection_send_destroy(circ
->n_circ_id
, circ
->n_conn
);
347 log_fn(LOG_DEBUG
, "Processed 'truncate', replying.");
348 connection_edge_send_command(NULL
, circ
, RELAY_COMMAND_TRUNCATED
,
351 case RELAY_COMMAND_TRUNCATED
:
352 if(edge_type
== EDGE_EXIT
) {
353 log_fn(LOG_WARN
,"'truncated' unsupported at exit. Dropping.");
356 circuit_truncated(circ
, layer_hint
);
358 case RELAY_COMMAND_CONNECTED
:
359 log_fn(LOG_WARN
,"'connected' unsupported while open. Closing.");
361 case RELAY_COMMAND_SENDME
:
363 if(edge_type
== EDGE_AP
) {
365 layer_hint
->package_window
+= CIRCWINDOW_INCREMENT
;
366 log_fn(LOG_DEBUG
,"circ-level sendme at AP, packagewindow %d.",
367 layer_hint
->package_window
);
368 circuit_resume_edge_reading(circ
, EDGE_AP
, layer_hint
);
371 circ
->package_window
+= CIRCWINDOW_INCREMENT
;
372 log_fn(LOG_DEBUG
,"circ-level sendme at exit, packagewindow %d.",
373 circ
->package_window
);
374 circuit_resume_edge_reading(circ
, EDGE_EXIT
, layer_hint
);
378 conn
->package_window
+= STREAMWINDOW_INCREMENT
;
379 log_fn(LOG_DEBUG
,"stream-level sendme, packagewindow now %d.", conn
->package_window
);
380 connection_start_reading(conn
);
381 connection_edge_package_raw_inbuf(conn
); /* handle whatever might still be on the inbuf */
384 log_fn(LOG_WARN
,"unknown relay command %d.",rh
.command
);
388 int connection_edge_finished_flushing(connection_t
*conn
) {
389 unsigned char connected_payload
[4];
390 int e
, len
=sizeof(e
);
393 assert(conn
->type
== CONN_TYPE_AP
|| conn
->type
== CONN_TYPE_EXIT
);
395 switch(conn
->state
) {
396 case EXIT_CONN_STATE_CONNECTING
:
397 if (getsockopt(conn
->s
, SOL_SOCKET
, SO_ERROR
, (void*)&e
, &len
) < 0) { /* not yet */
398 if(!ERRNO_CONN_EINPROGRESS(errno
)) {
400 log_fn(LOG_DEBUG
,"in-progress exit connect failed. Removing.");
403 log_fn(LOG_DEBUG
,"in-progress exit connect still waiting.");
404 return 0; /* no change, see if next time is better */
407 /* the connect has finished. */
409 log_fn(LOG_INFO
,"Exit connection to %s:%u established.",
410 conn
->address
,conn
->port
);
412 conn
->state
= EXIT_CONN_STATE_OPEN
;
413 connection_watch_events(conn
, POLLIN
); /* stop writing, continue reading */
414 if(connection_wants_to_flush(conn
)) /* in case there are any queued relay cells */
415 connection_start_writing(conn
);
416 /* deliver a 'connected' relay cell back through the circuit. */
417 *(uint32_t*)connected_payload
= htonl(conn
->addr
);
418 if(connection_edge_send_command(conn
, circuit_get_by_conn(conn
),
419 RELAY_COMMAND_CONNECTED
, connected_payload
, 4, NULL
) < 0)
420 return 0; /* circuit is closed, don't continue */
421 assert(conn
->package_window
> 0);
422 return connection_edge_process_inbuf(conn
); /* in case the server has written anything */
423 case AP_CONN_STATE_OPEN
:
424 case EXIT_CONN_STATE_OPEN
:
425 connection_stop_writing(conn
);
426 connection_edge_consider_sending_sendme(conn
);
428 case AP_CONN_STATE_SOCKS_WAIT
:
429 case AP_CONN_STATE_CIRCUIT_WAIT
:
430 connection_stop_writing(conn
);
433 log_fn(LOG_WARN
,"BUG: called in unexpected state: %d", conn
->state
);
439 uint64_t stats_n_data_cells_packaged
= 0;
440 uint64_t stats_n_data_bytes_packaged
= 0;
441 uint64_t stats_n_data_cells_received
= 0;
442 uint64_t stats_n_data_bytes_received
= 0;
444 int connection_edge_package_raw_inbuf(connection_t
*conn
) {
445 int amount_to_process
, length
;
446 char payload
[CELL_PAYLOAD_SIZE
];
450 assert(!connection_speaks_cells(conn
));
452 repeat_connection_edge_package_raw_inbuf
:
454 circ
= circuit_get_by_conn(conn
);
456 log_fn(LOG_INFO
,"conn has no circuits! Closing.");
460 if(circuit_consider_stop_edge_reading(circ
, conn
->type
, conn
->cpath_layer
))
463 if(conn
->package_window
<= 0) {
464 log_fn(LOG_WARN
,"called with package_window %d. Tell Roger.", conn
->package_window
);
465 connection_stop_reading(conn
);
469 amount_to_process
= buf_datalen(conn
->inbuf
);
471 if(!amount_to_process
)
474 if(amount_to_process
> RELAY_PAYLOAD_SIZE
) {
475 length
= RELAY_PAYLOAD_SIZE
;
477 length
= amount_to_process
;
479 stats_n_data_bytes_packaged
+= length
;
480 stats_n_data_cells_packaged
+= 1;
482 connection_fetch_from_buf(payload
, length
, conn
);
484 log_fn(LOG_DEBUG
,"(%d) Packaging %d bytes (%d waiting).", conn
->s
, length
,
485 (int)buf_datalen(conn
->inbuf
));
487 if(connection_edge_send_command(conn
, circ
, RELAY_COMMAND_DATA
,
488 payload
, length
, conn
->cpath_layer
) < 0)
489 return 0; /* circuit is closed, don't continue */
491 if(conn
->type
== CONN_TYPE_EXIT
) {
492 assert(circ
->package_window
> 0);
493 circ
->package_window
--;
494 } else { /* we're an AP */
495 assert(conn
->type
== CONN_TYPE_AP
);
496 assert(conn
->cpath_layer
->package_window
> 0);
497 conn
->cpath_layer
->package_window
--;
500 if(--conn
->package_window
<= 0) { /* is it 0 after decrement? */
501 connection_stop_reading(conn
);
502 log_fn(LOG_DEBUG
,"conn->package_window reached 0.");
503 circuit_consider_stop_edge_reading(circ
, conn
->type
, conn
->cpath_layer
);
504 return 0; /* don't process the inbuf any more */
506 log_fn(LOG_DEBUG
,"conn->package_window is now %d",conn
->package_window
);
508 /* handle more if there's more, or return 0 if there isn't */
509 goto repeat_connection_edge_package_raw_inbuf
;
512 void connection_ap_expire_beginning(void) {
513 connection_t
**carray
;
516 time_t now
= time(NULL
);
518 get_connection_array(&carray
, &n
);
520 for (i
= 0; i
< n
; ++i
) {
522 if (conn
->type
!= CONN_TYPE_AP
||
523 conn
->state
!= AP_CONN_STATE_CONNECTING
)
525 if (now
- conn
->timestamp_lastread
>= 15) {
526 log_fn(LOG_WARN
,"Stream is %d seconds late. Retrying.",
527 (int)(now
- conn
->timestamp_lastread
));
528 /* move it back into 'pending' state. It's possible it will
529 * reattach to this same circuit, but that's good enough for now.
531 conn
->state
= AP_CONN_STATE_CIRCUIT_WAIT
;
532 circuit_detach_stream(circuit_get_by_conn(conn
), conn
);
533 /* give it another 15 seconds to try */
534 conn
->timestamp_lastread
+= 15;
535 if(connection_ap_handshake_attach_circuit(conn
)<0) {
536 /* it will never work */
537 conn
->has_sent_end
= 1; /* Don't need to send end -- why? */
538 /* XXX you're right, there's a bug. we should send an end cell
539 * above, right before circuit_detach_stream. But if attach_circuit()
540 * fails, then in fact we should mark without sending an end, because
541 * we're not connected to anything. -RD */
542 connection_mark_for_close(conn
, 0);
548 /* Tell any APs that are waiting for a new circuit that one is available */
549 void connection_ap_attach_pending(void)
551 connection_t
**carray
;
555 get_connection_array(&carray
, &n
);
557 for (i
= 0; i
< n
; ++i
) {
559 if (conn
->type
!= CONN_TYPE_AP
||
560 conn
->state
!= AP_CONN_STATE_CIRCUIT_WAIT
)
562 if(connection_ap_handshake_attach_circuit(conn
) < 0) {
563 /* it will never work */
564 conn
->has_sent_end
= 1; /* because there is no 'other end' of the stream */
565 /* (XXX maybe has_sent_end should be called no_need_to_send_end or something) */
566 connection_mark_for_close(conn
,0);
571 static void connection_edge_consider_sending_sendme(connection_t
*conn
) {
574 if(connection_outbuf_too_full(conn
))
577 circ
= circuit_get_by_conn(conn
);
579 /* this can legitimately happen if the destroy has already
580 * arrived and torn down the circuit */
581 log_fn(LOG_INFO
,"No circuit associated with conn. Skipping.");
585 while(conn
->deliver_window
< STREAMWINDOW_START
- STREAMWINDOW_INCREMENT
) {
586 log_fn(LOG_DEBUG
,"Outbuf %d, Queueing stream sendme.", conn
->outbuf_flushlen
);
587 conn
->deliver_window
+= STREAMWINDOW_INCREMENT
;
588 if(connection_edge_send_command(conn
, circ
, RELAY_COMMAND_SENDME
,
589 NULL
, 0, conn
->cpath_layer
) < 0) {
590 log_fn(LOG_WARN
,"connection_edge_send_command failed. Returning.");
591 return; /* the circuit's closed, don't continue */
596 static int connection_ap_handshake_process_socks(connection_t
*conn
) {
597 socks_request_t
*socks
;
601 assert(conn
->type
== CONN_TYPE_AP
);
602 assert(conn
->state
== AP_CONN_STATE_SOCKS_WAIT
);
603 assert(conn
->socks_request
);
604 socks
= conn
->socks_request
;
606 log_fn(LOG_DEBUG
,"entered.");
608 sockshere
= fetch_from_buf_socks(conn
->inbuf
, socks
);
609 if(sockshere
== -1 || sockshere
== 0) {
610 if(socks
->replylen
) { /* we should send reply back */
611 log_fn(LOG_DEBUG
,"reply is already set for us. Using it.");
612 connection_ap_handshake_socks_reply(conn
, socks
->reply
, socks
->replylen
, 0);
613 } else if(sockshere
== -1) { /* send normal reject */
614 log_fn(LOG_WARN
,"Fetching socks handshake failed. Closing.");
615 connection_ap_handshake_socks_reply(conn
, NULL
, 0, 0);
617 log_fn(LOG_DEBUG
,"socks handshake not all here yet.");
620 } /* else socks handshake is done, continue processing */
622 conn
->state
= AP_CONN_STATE_CIRCUIT_WAIT
;
623 return connection_ap_handshake_attach_circuit(conn
);
626 static int connection_ap_handshake_attach_circuit(connection_t
*conn
) {
627 /* try attaching. launch new circuit if needed.
628 * return -1 if conn needs to die, else 0. */
629 switch(connection_ap_handshake_attach_circuit_helper(conn
)) {
630 case -1: /* it will never work */
632 case 0: /* no useful circuits available */
633 if(!circuit_get_newest(conn
, 0)) /* is one already on the way? */
634 circuit_launch_new();
636 default: /* case 1, it succeeded, great */
641 /* Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
642 * we don't find one: if conn cannot be handled by any known nodes,
643 * warn and return -1; else tell conn to stop reading and return 0.
644 * Otherwise, associate conn with a safe live circuit, start
645 * sending a BEGIN cell down the circuit, and return 1.
647 static int connection_ap_handshake_attach_circuit_helper(connection_t
*conn
) {
652 assert(conn
->type
== CONN_TYPE_AP
);
653 assert(conn
->state
== AP_CONN_STATE_CIRCUIT_WAIT
);
654 assert(conn
->socks_request
);
656 /* find the circuit that we should use, if there is one. */
657 circ
= circuit_get_newest(conn
, 1);
660 log_fn(LOG_INFO
,"No safe circuit ready for edge connection; delaying.");
661 addr
= client_dns_lookup_entry(conn
->socks_request
->address
);
662 if(router_exit_policy_all_routers_reject(addr
, conn
->socks_request
->port
)) {
663 log_fn(LOG_WARN
,"No node exists that will handle exit to %s:%d. Rejecting.",
664 conn
->socks_request
->address
, conn
->socks_request
->port
);
667 connection_stop_reading(conn
); /* don't read until the connected cell arrives */
671 connection_start_reading(conn
);
673 /* here, print the circ's path. so people can figure out which circs are sucking. */
674 circuit_log_path(LOG_WARN
,circ
);
676 if(!circ
->timestamp_dirty
)
677 circ
->timestamp_dirty
= time(NULL
);
679 /* add it into the linked list of streams on this circuit */
680 log_fn(LOG_DEBUG
,"attaching new conn to circ. n_circ_id %d.", circ
->n_circ_id
);
681 conn
->next_stream
= circ
->p_streams
;
682 /* assert_connection_ok(conn, time(NULL)); */
683 circ
->p_streams
= conn
;
685 assert(circ
->cpath
&& circ
->cpath
->prev
);
686 assert(circ
->cpath
->prev
->state
== CPATH_STATE_OPEN
);
687 conn
->cpath_layer
= circ
->cpath
->prev
;
689 connection_ap_handshake_send_begin(conn
, circ
);
694 /* Iterate over the two bytes of stream_id until we get one that is not
695 * already in use. Return 0 if can't get a unique stream_id.
697 static uint16_t get_unique_stream_id_by_circ(circuit_t
*circ
) {
698 connection_t
*tmpconn
;
699 uint16_t test_stream_id
;
703 test_stream_id
= circ
->next_stream_id
++;
704 if(++attempts
> 1<<16) {
705 /* Make sure we don't loop forever if all stream_id's are used. */
706 log_fn(LOG_WARN
,"No unused stream IDs. Failing.");
709 if (test_stream_id
== 0)
711 for(tmpconn
= circ
->p_streams
; tmpconn
; tmpconn
=tmpconn
->next_stream
)
712 if(tmpconn
->stream_id
== test_stream_id
)
714 return test_stream_id
;
717 /* deliver the destaddr:destport in a relay cell */
718 static void connection_ap_handshake_send_begin(connection_t
*ap_conn
, circuit_t
*circ
)
720 char payload
[CELL_PAYLOAD_SIZE
];
723 const char *string_addr
;
725 assert(ap_conn
->type
== CONN_TYPE_AP
);
726 assert(ap_conn
->state
== AP_CONN_STATE_CIRCUIT_WAIT
);
727 assert(ap_conn
->socks_request
);
729 ap_conn
->stream_id
= get_unique_stream_id_by_circ(circ
);
730 if (ap_conn
->stream_id
==0) {
731 ap_conn
->has_sent_end
= 1; /* there is no 'other side' yet */
732 connection_mark_for_close(ap_conn
, 0);
736 in
.s_addr
= htonl(client_dns_lookup_entry(ap_conn
->socks_request
->address
));
737 string_addr
= in
.s_addr
? inet_ntoa(in
) : NULL
;
739 snprintf(payload
,RELAY_PAYLOAD_SIZE
,
741 string_addr
? string_addr
: ap_conn
->socks_request
->address
,
742 ap_conn
->socks_request
->port
);
743 payload_len
= strlen(payload
)+1;
745 log_fn(LOG_DEBUG
,"Sending relay cell to begin stream %d.",ap_conn
->stream_id
);
747 if(connection_edge_send_command(ap_conn
, circ
, RELAY_COMMAND_BEGIN
,
748 payload
, payload_len
, ap_conn
->cpath_layer
) < 0)
749 return; /* circuit is closed, don't continue */
751 ap_conn
->package_window
= STREAMWINDOW_START
;
752 ap_conn
->deliver_window
= STREAMWINDOW_START
;
753 ap_conn
->state
= AP_CONN_STATE_CONNECTING
;
754 /* XXX Right now, we rely on the socks client not to send us any data
755 * XXX until we've sent back a socks reply. (If it does, we could wind
756 * XXX up packaging that data and sending it to the exit, then later having
757 * XXX the exit refuse us.)
759 log_fn(LOG_INFO
,"Address/port sent, ap socket %d, n_circ_id %d",ap_conn
->s
,circ
->n_circ_id
);
763 static int connection_ap_handshake_socks_reply(connection_t
*conn
, char *reply
,
764 int replylen
, char success
) {
767 if(replylen
) { /* we already have a reply in mind */
768 connection_write_to_buf(reply
, replylen
, conn
);
769 return flush_buf(conn
->s
, conn
->outbuf
, &conn
->outbuf_flushlen
); /* try to flush it */
771 assert(conn
->socks_request
);
772 if(conn
->socks_request
->socks_version
== 4) {
773 memset(buf
,0,SOCKS4_NETWORK_LEN
);
774 #define SOCKS4_GRANTED 90
775 #define SOCKS4_REJECT 91
776 buf
[1] = (success
? SOCKS4_GRANTED
: SOCKS4_REJECT
);
777 /* leave version, destport, destip zero */
778 connection_write_to_buf(buf
, SOCKS4_NETWORK_LEN
, conn
);
779 return flush_buf(conn
->s
, conn
->outbuf
, &conn
->outbuf_flushlen
); /* try to flush it */
781 if(conn
->socks_request
->socks_version
== 5) {
782 buf
[0] = 5; /* version 5 */
783 #define SOCKS5_SUCCESS 0
784 #define SOCKS5_GENERIC_ERROR 1
785 buf
[1] = success
? SOCKS5_SUCCESS
: SOCKS5_GENERIC_ERROR
;
787 buf
[3] = 1; /* ipv4 addr */
788 memset(buf
+4,0,6); /* Set external addr/port to 0.
789 The spec doesn't seem to say what to do here. -RD */
790 connection_write_to_buf(buf
,10,conn
);
791 return flush_buf(conn
->s
, conn
->outbuf
, &conn
->outbuf_flushlen
); /* try to flush it */
793 return 0; /* if socks_version isn't 4 or 5, don't send anything */
796 static int connection_exit_begin_conn(cell_t
*cell
, circuit_t
*circ
) {
797 connection_t
*n_stream
;
801 relay_header_unpack(&rh
, cell
->payload
);
803 /* XXX currently we don't send an end cell back if we drop the
804 * begin because it's malformed.
807 if(!memchr(cell
->payload
+RELAY_HEADER_SIZE
, 0, rh
.length
)) {
808 log_fn(LOG_WARN
,"relay begin cell has no \\0. Dropping.");
811 colon
= strchr(cell
->payload
+RELAY_HEADER_SIZE
, ':');
813 log_fn(LOG_WARN
,"relay begin cell has no colon. Dropping.");
818 if(!atoi(colon
+1)) { /* bad port */
819 log_fn(LOG_WARN
,"relay begin cell has invalid port. Dropping.");
823 log_fn(LOG_DEBUG
,"Creating new exit connection.");
824 n_stream
= connection_new(CONN_TYPE_EXIT
);
826 n_stream
->stream_id
= rh
.stream_id
;
827 n_stream
->address
= tor_strdup(cell
->payload
+ RELAY_HEADER_SIZE
);
828 n_stream
->port
= atoi(colon
+1);
829 n_stream
->state
= EXIT_CONN_STATE_RESOLVING
;
830 /* leave n_stream->s at -1, because it's not yet valid */
831 n_stream
->package_window
= STREAMWINDOW_START
;
832 n_stream
->deliver_window
= STREAMWINDOW_START
;
833 if(connection_add(n_stream
) < 0) { /* no space, forget it */
834 log_fn(LOG_WARN
,"connection_add failed. Dropping.");
835 connection_free(n_stream
);
839 /* add it into the linked list of streams on this circuit */
840 n_stream
->next_stream
= circ
->n_streams
;
841 circ
->n_streams
= n_stream
;
843 /* send it off to the gethostbyname farm */
844 switch(dns_resolve(n_stream
)) {
845 case 1: /* resolve worked */
846 connection_exit_connect(n_stream
);
848 case -1: /* resolve failed */
849 log_fn(LOG_INFO
,"Resolve failed (%s).", n_stream
->address
);
850 connection_mark_for_close(n_stream
, END_STREAM_REASON_RESOLVEFAILED
);
851 /* case 0, resolve added to pending list */
856 void connection_exit_connect(connection_t
*conn
) {
857 unsigned char connected_payload
[4];
859 if(router_compare_to_my_exit_policy(conn
) == ADDR_POLICY_REJECTED
) {
860 log_fn(LOG_INFO
,"%s:%d failed exit policy. Closing.", conn
->address
, conn
->port
);
861 connection_mark_for_close(conn
, END_STREAM_REASON_EXITPOLICY
);
865 switch(connection_connect(conn
, conn
->address
, conn
->addr
, conn
->port
)) {
867 connection_mark_for_close(conn
, END_STREAM_REASON_CONNECTFAILED
);
870 connection_set_poll_socket(conn
);
871 conn
->state
= EXIT_CONN_STATE_CONNECTING
;
873 connection_watch_events(conn
, POLLOUT
| POLLIN
| POLLERR
);
874 /* writable indicates finish, readable indicates broken link,
875 error indicates broken link in windowsland. */
877 /* case 1: fall through */
880 connection_set_poll_socket(conn
);
881 conn
->state
= EXIT_CONN_STATE_OPEN
;
882 if(connection_wants_to_flush(conn
)) { /* in case there are any queued data cells */
883 log_fn(LOG_WARN
,"tell roger: newly connected conn had data waiting!");
884 // connection_start_writing(conn);
886 // connection_process_inbuf(conn);
887 connection_watch_events(conn
, POLLIN
);
889 /* also, deliver a 'connected' cell back through the circuit. */
890 *((uint32_t*) connected_payload
) = htonl(conn
->addr
);
891 connection_edge_send_command(conn
, circuit_get_by_conn(conn
), RELAY_COMMAND_CONNECTED
,
892 connected_payload
, 4, NULL
);
895 int connection_ap_can_use_exit(connection_t
*conn
, routerinfo_t
*exit
)
900 assert(conn
->type
== CONN_TYPE_AP
);
901 assert(conn
->socks_request
);
903 log_fn(LOG_DEBUG
,"considering nickname %s, for address %s / port %d:",
904 exit
->nickname
, conn
->socks_request
->address
,
905 conn
->socks_request
->port
);
906 addr
= client_dns_lookup_entry(conn
->socks_request
->address
);
907 return router_compare_addr_to_exit_policy(addr
,
908 conn
->socks_request
->port
, exit
->exit_policy
);
911 /* ***** Client DNS code ***** */
913 /* XXX Perhaps this should get merged with the dns.c code somehow. */
914 /* XXX But we can't just merge them, because then nodes that act as
915 * both OR and OP could be attacked: people could rig the dns cache
916 * by answering funny things to stream begin requests, and later
917 * other clients would reuse those funny addr's. Hm.
919 struct client_dns_entry
{
920 SPLAY_ENTRY(client_dns_entry
) node
;
925 static int client_dns_size
= 0;
926 static SPLAY_HEAD(client_dns_tree
, client_dns_entry
) client_dns_root
;
928 static int compare_client_dns_entries(struct client_dns_entry
*a
,
929 struct client_dns_entry
*b
)
931 return strcasecmp(a
->address
, b
->address
);
934 static void client_dns_entry_free(struct client_dns_entry
*ent
)
936 tor_free(ent
->address
);
940 SPLAY_PROTOTYPE(client_dns_tree
, client_dns_entry
, node
, compare_client_dns_entries
);
941 SPLAY_GENERATE(client_dns_tree
, client_dns_entry
, node
, compare_client_dns_entries
);
943 void client_dns_init(void) {
944 SPLAY_INIT(&client_dns_root
);
948 static uint32_t client_dns_lookup_entry(const char *address
)
950 struct client_dns_entry
*ent
;
951 struct client_dns_entry search
;
957 if (inet_aton(address
, &in
)) {
958 log_fn(LOG_DEBUG
, "Using static address %s (%08lX)", address
,
959 (unsigned long)ntohl(in
.s_addr
));
960 return ntohl(in
.s_addr
);
962 search
.address
= (char*)address
;
963 ent
= SPLAY_FIND(client_dns_tree
, &client_dns_root
, &search
);
965 log_fn(LOG_DEBUG
, "No entry found for address %s", address
);
969 if (ent
->expires
< now
) {
970 log_fn(LOG_DEBUG
, "Expired entry found for address %s", address
);
971 SPLAY_REMOVE(client_dns_tree
, &client_dns_root
, ent
);
972 client_dns_entry_free(ent
);
976 in
.s_addr
= htonl(ent
->addr
);
977 log_fn(LOG_DEBUG
, "Found cached entry for address %s: %s", address
,
982 static void client_dns_set_entry(const char *address
, uint32_t val
)
984 struct client_dns_entry
*ent
;
985 struct client_dns_entry search
;
992 if (inet_aton(address
, &in
))
994 search
.address
= (char*) address
;
996 ent
= SPLAY_FIND(client_dns_tree
, &client_dns_root
, &search
);
998 in
.s_addr
= htonl(val
);
999 log_fn(LOG_DEBUG
, "Updating entry for address %s: %s", address
,
1002 ent
->expires
= now
+MAX_DNS_ENTRY_AGE
;
1004 in
.s_addr
= htonl(val
);
1005 log_fn(LOG_DEBUG
, "Caching result for address %s: %s", address
,
1007 ent
= tor_malloc(sizeof(struct client_dns_entry
));
1008 ent
->address
= tor_strdup(address
);
1010 ent
->expires
= now
+MAX_DNS_ENTRY_AGE
;
1011 SPLAY_INSERT(client_dns_tree
, &client_dns_root
, ent
);
1016 void client_dns_clean(void)
1018 struct client_dns_entry
**expired_entries
;
1019 int n_expired_entries
= 0;
1020 struct client_dns_entry
*ent
;
1024 if(!client_dns_size
)
1026 expired_entries
= tor_malloc(client_dns_size
*
1027 sizeof(struct client_dns_entry
*));
1030 SPLAY_FOREACH(ent
, client_dns_tree
, &client_dns_root
) {
1031 if (ent
->expires
< now
) {
1032 expired_entries
[n_expired_entries
++] = ent
;
1035 for (i
= 0; i
< n_expired_entries
; ++i
) {
1036 SPLAY_REMOVE(client_dns_tree
, &client_dns_root
, expired_entries
[i
]);
1037 client_dns_entry_free(expired_entries
[i
]);
1039 tor_free(expired_entries
);
1045 indent-tabs-mode:nil