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 */
10 static int connection_ap_handshake_process_socks(connection_t
*conn
);
11 static int connection_ap_handshake_attach_circuit(connection_t
*conn
);
12 static void connection_ap_handshake_send_begin(connection_t
*ap_conn
, circuit_t
*circ
);
13 static int connection_ap_handshake_socks_reply(connection_t
*conn
, char *reply
,
14 int replylen
, char success
);
16 static int connection_exit_begin_conn(cell_t
*cell
, circuit_t
*circ
);
17 static void connection_edge_consider_sending_sendme(connection_t
*conn
);
19 static uint32_t client_dns_lookup_entry(const char *address
);
20 static void client_dns_set_entry(const char *address
, uint32_t val
);
22 int connection_edge_process_inbuf(connection_t
*conn
) {
25 assert(conn
->type
== CONN_TYPE_AP
|| conn
->type
== CONN_TYPE_EXIT
);
27 if(conn
->inbuf_reached_eof
) {
29 /* eof reached; we're done reading, but we might want to write more. */
30 conn
->done_receiving
= 1;
31 shutdown(conn
->s
, 0); /* XXX check return, refactor NM */
32 if (conn
->done_sending
) {
33 connection_edge_end(conn
, END_STREAM_REASON_DONE
, conn
->cpath_layer
);
35 connection_edge_send_command(conn
, circuit_get_by_conn(conn
), RELAY_COMMAND_END
,
36 NULL
, 0, conn
->cpath_layer
);
40 /* eof reached, kill it. */
41 log_fn(LOG_INFO
,"conn (fd %d) reached eof. Closing.", conn
->s
);
42 connection_edge_end(conn
, END_STREAM_REASON_DONE
, conn
->cpath_layer
);
48 case AP_CONN_STATE_SOCKS_WAIT
:
49 if(connection_ap_handshake_process_socks(conn
) < 0) {
50 connection_edge_end(conn
, END_STREAM_REASON_MISC
, conn
->cpath_layer
);
54 case AP_CONN_STATE_OPEN
:
55 case EXIT_CONN_STATE_OPEN
:
56 if(connection_edge_package_raw_inbuf(conn
) < 0) {
57 connection_edge_end(conn
, END_STREAM_REASON_MISC
, conn
->cpath_layer
);
61 case EXIT_CONN_STATE_CONNECTING
:
62 log_fn(LOG_INFO
,"text from server while in 'connecting' state at exit. Leaving it on buffer.");
69 char *connection_edge_end_reason(char *payload
, unsigned char length
) {
71 log_fn(LOG_WARN
,"End cell arrived with length 0. Should be at least 1.");
74 if(*payload
< END_STREAM_REASON_MISC
|| *payload
> END_STREAM_REASON_DONE
) {
75 log_fn(LOG_WARN
,"Reason for ending (%d) not recognized.",*payload
);
79 case END_STREAM_REASON_MISC
: return "misc error";
80 case END_STREAM_REASON_RESOLVEFAILED
: return "resolve failed";
81 case END_STREAM_REASON_CONNECTFAILED
: return "connect failed";
82 case END_STREAM_REASON_EXITPOLICY
: return "exit policy failed";
83 case END_STREAM_REASON_DESTROY
: return "destroyed";
84 case END_STREAM_REASON_DONE
: return "closed normally";
90 void connection_edge_end(connection_t
*conn
, char reason
, crypt_path_t
*cpath_layer
) {
95 if(conn
->has_sent_end
) {
96 log_fn(LOG_WARN
,"It appears I've already sent the end. Are you calling me twice?");
101 if(reason
== END_STREAM_REASON_EXITPOLICY
) {
102 *(uint32_t *)(payload
+1) = htonl(conn
->addr
);
106 circ
= circuit_get_by_conn(conn
);
108 log_fn(LOG_DEBUG
,"Marking conn (fd %d) and sending end.",conn
->s
);
109 connection_edge_send_command(conn
, circ
, RELAY_COMMAND_END
,
110 payload
, payload_len
, cpath_layer
);
113 conn
->marked_for_close
= 1;
114 conn
->has_sent_end
= 1;
117 int connection_edge_send_command(connection_t
*fromconn
, circuit_t
*circ
, int relay_command
,
118 void *payload
, int payload_len
, crypt_path_t
*cpath_layer
) {
121 int is_control_cell
=0;
124 log_fn(LOG_WARN
,"no circ. Closing.");
128 if(!fromconn
|| relay_command
== RELAY_COMMAND_BEGIN
) /* XXX more */
131 memset(&cell
, 0, sizeof(cell_t
));
132 if(fromconn
&& fromconn
->type
== CONN_TYPE_AP
) {
133 cell
.circ_id
= circ
->n_circ_id
;
134 cell_direction
= CELL_DIRECTION_OUT
;
136 /* NOTE: if !fromconn, we assume that it's heading towards the OP */
137 cell
.circ_id
= circ
->p_circ_id
;
138 cell_direction
= CELL_DIRECTION_IN
;
141 cell
.command
= CELL_RELAY
;
142 SET_CELL_RELAY_COMMAND(cell
, relay_command
);
144 SET_CELL_STREAM_ID(cell
, ZERO_STREAM
);
146 SET_CELL_STREAM_ID(cell
, fromconn
->stream_id
);
148 cell
.length
= RELAY_HEADER_SIZE
+ payload_len
;
150 memcpy(cell
.payload
+RELAY_HEADER_SIZE
,payload
,payload_len
);
152 log_fn(LOG_DEBUG
,"delivering %d cell %s.", relay_command
,
153 cell_direction
== CELL_DIRECTION_OUT
? "forward" : "backward");
155 if(circuit_deliver_relay_cell(&cell
, circ
, cell_direction
, cpath_layer
) < 0) {
156 log_fn(LOG_WARN
,"circuit_deliver_relay_cell failed. Closing.");
163 /* an incoming relay cell has arrived. return -1 if you want to tear down the
164 * circuit, else 0. */
165 int connection_edge_process_relay_cell(cell_t
*cell
, circuit_t
*circ
, connection_t
*conn
,
166 int edge_type
, crypt_path_t
*layer_hint
) {
168 static int num_seen
=0;
171 assert(cell
&& circ
);
173 relay_command
= CELL_RELAY_COMMAND(*cell
);
174 // log_fn(LOG_DEBUG,"command %d stream %d", relay_command, stream_id);
176 log_fn(LOG_DEBUG
,"Now seen %d relay cells here.", num_seen
);
178 /* either conn is NULL, in which case we've got a control cell, or else
179 * conn points to the recognized stream. */
181 if(conn
&& conn
->state
!= AP_CONN_STATE_OPEN
&& conn
->state
!= EXIT_CONN_STATE_OPEN
) {
182 if(conn
->type
== CONN_TYPE_EXIT
&& relay_command
== RELAY_COMMAND_END
) {
183 log_fn(LOG_INFO
,"Exit got end (%s) before we're connected. Marking for close.",
184 connection_edge_end_reason(cell
->payload
+RELAY_HEADER_SIZE
, cell
->length
));
185 if(conn
->state
== EXIT_CONN_STATE_RESOLVING
) {
186 log_fn(LOG_INFO
,"...and informing resolver we don't want the answer anymore.");
187 dns_cancel_pending_resolve(conn
->address
, conn
);
189 conn
->marked_for_close
= 1;
190 conn
->has_sent_end
= 1;
193 log_fn(LOG_WARN
,"Got an unexpected relay cell, not in 'open' state. Closing.");
194 connection_edge_end(conn
, END_STREAM_REASON_MISC
, conn
->cpath_layer
);
199 switch(relay_command
) {
200 case RELAY_COMMAND_BEGIN
:
201 if(edge_type
== EDGE_AP
) {
202 log_fn(LOG_WARN
,"relay begin request unsupported at AP. Dropping.");
206 log_fn(LOG_WARN
,"begin cell for known stream. Dropping.");
209 connection_exit_begin_conn(cell
, circ
);
211 case RELAY_COMMAND_DATA
:
212 ++stats_n_data_cells_received
;
213 if((edge_type
== EDGE_AP
&& --layer_hint
->deliver_window
< 0) ||
214 (edge_type
== EDGE_EXIT
&& --circ
->deliver_window
< 0)) {
215 log_fn(LOG_WARN
,"(relay data) circ deliver_window below 0. Killing.");
216 connection_edge_end(conn
, END_STREAM_REASON_MISC
, conn
->cpath_layer
);
219 log_fn(LOG_DEBUG
,"circ deliver_window now %d.", edge_type
== EDGE_AP
? layer_hint
->deliver_window
: circ
->deliver_window
);
221 if(circuit_consider_sending_sendme(circ
, edge_type
, layer_hint
) < 0) {
222 log_fn(LOG_WARN
,"circuit_consider_sending_sendme() failed.");
223 conn
->has_sent_end
= 1; /* we failed because conn is broken. can't send end. */
228 log_fn(LOG_INFO
,"relay cell dropped, unknown stream %d.",*(int*)conn
->stream_id
);
232 if(--conn
->deliver_window
< 0) { /* is it below 0 after decrement? */
233 log_fn(LOG_WARN
,"(relay data) conn deliver_window below 0. Killing.");
234 return -1; /* somebody's breaking protocol. kill the whole circuit. */
237 // printf("New text for buf (%d bytes): '%s'", cell->length - RELAY_HEADER_SIZE, cell->payload + RELAY_HEADER_SIZE);
238 stats_n_data_bytes_received
+= (cell
->length
- RELAY_HEADER_SIZE
);
239 connection_write_to_buf(cell
->payload
+ RELAY_HEADER_SIZE
,
240 cell
->length
- RELAY_HEADER_SIZE
, conn
);
241 connection_edge_consider_sending_sendme(conn
);
243 case RELAY_COMMAND_END
:
245 log_fn(LOG_INFO
,"end cell (%s) dropped, unknown stream %d.",
246 connection_edge_end_reason(cell
->payload
+RELAY_HEADER_SIZE
, cell
->length
),
247 *(int*)conn
->stream_id
);
250 if(cell
->length
-RELAY_HEADER_SIZE
>= 5 &&
251 *(cell
->payload
+RELAY_HEADER_SIZE
) == END_STREAM_REASON_EXITPOLICY
) {
252 /* No need to close the connection. We'll hold it open while
253 * we try a new exit node.
254 * cell->payload+RELAY_HEADER_SIZE+1 holds the destination addr.
256 addr
= ntohl(*(uint32_t*)(cell
->payload
+RELAY_HEADER_SIZE
+1));
257 client_dns_set_entry(conn
->socks_request
->address
, addr
);
258 conn
->state
= AP_CONN_STATE_CIRCUIT_WAIT
;
259 if(connection_ap_handshake_attach_circuit(conn
) < 0)
260 circuit_launch_new(); /* Build another circuit to handle this stream */
263 log_fn(LOG_INFO
,"end cell (%s) for stream %d. Removing stream.",
264 connection_edge_end_reason(cell
->payload
+RELAY_HEADER_SIZE
, cell
->length
),
265 *(int*)conn
->stream_id
);
268 conn
->done_sending
= 1;
269 shutdown(conn
->s
, 1); /* XXX check return; refactor NM */
270 if (conn
->done_receiving
) {
271 conn
->marked_for_close
= 1;
272 conn
->has_sent_end
= 1; /* no need to send end, we just got one! */
275 conn
->marked_for_close
= 1;
276 conn
->has_sent_end
= 1; /* no need to send end, we just got one! */
279 case RELAY_COMMAND_EXTEND
:
281 log_fn(LOG_WARN
,"'extend' for non-zero stream. Dropping.");
284 return circuit_extend(cell
, circ
);
285 case RELAY_COMMAND_EXTENDED
:
286 if(edge_type
== EDGE_EXIT
) {
287 log_fn(LOG_WARN
,"'extended' unsupported at exit. Dropping.");
290 log_fn(LOG_DEBUG
,"Got an extended cell! Yay.");
291 if(circuit_finish_handshake(circ
, cell
->payload
+RELAY_HEADER_SIZE
) < 0) {
292 log_fn(LOG_WARN
,"circuit_finish_handshake failed.");
295 if (circuit_send_next_onion_skin(circ
)<0) {
296 log_fn(LOG_WARN
,"circuit_send_next_onion_skin() failed.");
300 case RELAY_COMMAND_TRUNCATE
:
301 if(edge_type
== EDGE_AP
) {
302 log_fn(LOG_WARN
,"'truncate' unsupported at AP. Dropping.");
306 connection_send_destroy(circ
->n_circ_id
, circ
->n_conn
);
309 log_fn(LOG_DEBUG
, "Processed 'truncate', replying.");
310 connection_edge_send_command(NULL
, circ
, RELAY_COMMAND_TRUNCATED
,
313 case RELAY_COMMAND_TRUNCATED
:
314 if(edge_type
== EDGE_EXIT
) {
315 log_fn(LOG_WARN
,"'truncated' unsupported at exit. Dropping.");
318 circuit_truncated(circ
, layer_hint
);
320 case RELAY_COMMAND_CONNECTED
:
321 if(edge_type
== EDGE_EXIT
) {
322 log_fn(LOG_WARN
,"'connected' unsupported at exit. Dropping.");
326 log_fn(LOG_INFO
,"connected cell dropped, unknown stream %d.",*(int*)conn
->stream_id
);
329 log_fn(LOG_INFO
,"Connected! Notifying application.");
330 if (cell
->length
-RELAY_HEADER_SIZE
== 4) {
331 addr
= ntohl(*(uint32_t*)(cell
->payload
+ RELAY_HEADER_SIZE
));
332 client_dns_set_entry(conn
->socks_request
->address
, addr
);
334 if(connection_ap_handshake_socks_reply(conn
, NULL
, 0, 1) < 0) {
335 log_fn(LOG_INFO
,"Writing to socks-speaking application failed. Closing.");
336 connection_edge_end(conn
, END_STREAM_REASON_MISC
, conn
->cpath_layer
);
339 case RELAY_COMMAND_SENDME
:
341 if(edge_type
== EDGE_AP
) {
343 layer_hint
->package_window
+= CIRCWINDOW_INCREMENT
;
344 log_fn(LOG_DEBUG
,"circ-level sendme at AP, packagewindow %d.", layer_hint
->package_window
);
345 circuit_resume_edge_reading(circ
, EDGE_AP
, layer_hint
);
348 circ
->package_window
+= CIRCWINDOW_INCREMENT
;
349 log_fn(LOG_DEBUG
,"circ-level sendme at exit, packagewindow %d.", circ
->package_window
);
350 circuit_resume_edge_reading(circ
, EDGE_EXIT
, layer_hint
);
354 conn
->package_window
+= STREAMWINDOW_INCREMENT
;
355 log_fn(LOG_DEBUG
,"stream-level sendme, packagewindow now %d.", conn
->package_window
);
356 connection_start_reading(conn
);
357 connection_edge_package_raw_inbuf(conn
); /* handle whatever might still be on the inbuf */
360 log_fn(LOG_WARN
,"unknown relay command %d.",relay_command
);
367 int connection_edge_finished_flushing(connection_t
*conn
) {
368 unsigned char connected_payload
[4];
369 int e
, len
=sizeof(e
);
372 assert(conn
->type
== CONN_TYPE_AP
|| conn
->type
== CONN_TYPE_EXIT
);
374 switch(conn
->state
) {
375 case EXIT_CONN_STATE_CONNECTING
:
376 if (getsockopt(conn
->s
, SOL_SOCKET
, SO_ERROR
, (void*)&e
, &len
) < 0) { /* not yet */
377 if(!ERRNO_CONN_EINPROGRESS(errno
)) {
379 log_fn(LOG_DEBUG
,"in-progress exit connect failed. Removing.");
382 log_fn(LOG_DEBUG
,"in-progress exit connect still waiting.");
383 return 0; /* no change, see if next time is better */
386 /* the connect has finished. */
388 log_fn(LOG_INFO
,"Exit connection to %s:%u established.",
389 conn
->address
,conn
->port
);
391 conn
->state
= EXIT_CONN_STATE_OPEN
;
392 connection_watch_events(conn
, POLLIN
); /* stop writing, continue reading */
393 if(connection_wants_to_flush(conn
)) /* in case there are any queued relay cells */
394 connection_start_writing(conn
);
395 /* deliver a 'connected' relay cell back through the circuit. */
396 *(uint32_t*)connected_payload
= htonl(conn
->addr
);
397 if(connection_edge_send_command(conn
, circuit_get_by_conn(conn
),
398 RELAY_COMMAND_CONNECTED
, NULL
, 0, conn
->cpath_layer
) < 0)
399 return 0; /* circuit is closed, don't continue */
400 return connection_process_inbuf(conn
); /* in case the server has written anything */
401 case AP_CONN_STATE_OPEN
:
402 case EXIT_CONN_STATE_OPEN
:
403 connection_stop_writing(conn
);
404 connection_edge_consider_sending_sendme(conn
);
406 case AP_CONN_STATE_SOCKS_WAIT
:
407 connection_stop_writing(conn
);
410 log_fn(LOG_WARN
,"BUG: called in unexpected state: %d", conn
->state
);
416 uint64_t stats_n_data_cells_packaged
= 0;
417 uint64_t stats_n_data_bytes_packaged
= 0;
418 uint64_t stats_n_data_cells_received
= 0;
419 uint64_t stats_n_data_bytes_received
= 0;
421 int connection_edge_package_raw_inbuf(connection_t
*conn
) {
422 int amount_to_process
, length
;
423 char payload
[CELL_PAYLOAD_SIZE
];
427 assert(!connection_speaks_cells(conn
));
429 repeat_connection_edge_package_raw_inbuf
:
431 circ
= circuit_get_by_conn(conn
);
433 log_fn(LOG_INFO
,"conn has no circuits! Closing.");
437 if(circuit_consider_stop_edge_reading(circ
, conn
->type
, conn
->cpath_layer
))
440 if(conn
->package_window
<= 0) {
441 log_fn(LOG_WARN
,"called with package_window %d. Tell Roger.", conn
->package_window
);
442 connection_stop_reading(conn
);
446 amount_to_process
= buf_datalen(conn
->inbuf
);
448 if(!amount_to_process
)
451 if(amount_to_process
> CELL_PAYLOAD_SIZE
- RELAY_HEADER_SIZE
) {
452 length
= CELL_PAYLOAD_SIZE
- RELAY_HEADER_SIZE
;
454 length
= amount_to_process
;
456 stats_n_data_bytes_packaged
+= length
;
457 stats_n_data_cells_packaged
+= 1;
459 connection_fetch_from_buf(payload
, length
, conn
);
461 log_fn(LOG_DEBUG
,"(%d) Packaging %d bytes (%d waiting).",conn
->s
,length
,
462 (int)buf_datalen(conn
->inbuf
));
464 if(connection_edge_send_command(conn
, circ
, RELAY_COMMAND_DATA
,
465 payload
, length
, conn
->cpath_layer
) < 0)
466 return 0; /* circuit is closed, don't continue */
468 if(conn
->type
== CONN_TYPE_EXIT
) {
469 assert(circ
->package_window
> 0);
470 circ
->package_window
--;
471 } else { /* we're an AP */
472 assert(conn
->type
== CONN_TYPE_AP
);
473 assert(conn
->cpath_layer
->package_window
> 0);
474 conn
->cpath_layer
->package_window
--;
477 if(--conn
->package_window
<= 0) { /* is it 0 after decrement? */
478 connection_stop_reading(conn
);
479 log_fn(LOG_DEBUG
,"conn->package_window reached 0.");
480 circuit_consider_stop_edge_reading(circ
, conn
->type
, conn
->cpath_layer
);
481 return 0; /* don't process the inbuf any more */
483 log_fn(LOG_DEBUG
,"conn->package_window is now %d",conn
->package_window
);
485 /* handle more if there's more, or return 0 if there isn't */
486 goto repeat_connection_edge_package_raw_inbuf
;
489 /* Tell any APs that are waiting for a new circuit that one is available */
490 void connection_ap_attach_pending(void)
492 connection_t
**carray
;
495 get_connection_array(&carray
, &n
);
497 for (i
= 0; i
< n
; ++i
) {
498 if (carray
[i
]->type
!= CONN_TYPE_AP
||
499 carray
[i
]->type
!= AP_CONN_STATE_CIRCUIT_WAIT
)
501 if (connection_ap_handshake_attach_circuit(carray
[i
])<0) {
502 if(!circuit_get_newest(carray
[i
], 0)) {
503 /* if there are no acceptable clean or not-very-dirty circs on the way */
504 circuit_launch_new();
510 static void connection_edge_consider_sending_sendme(connection_t
*conn
) {
513 if(connection_outbuf_too_full(conn
))
516 circ
= circuit_get_by_conn(conn
);
518 /* this can legitimately happen if the destroy has already
519 * arrived and torn down the circuit */
520 log_fn(LOG_INFO
,"No circuit associated with conn. Skipping.");
524 while(conn
->deliver_window
< STREAMWINDOW_START
- STREAMWINDOW_INCREMENT
) {
525 log_fn(LOG_DEBUG
,"Outbuf %d, Queueing stream sendme.", conn
->outbuf_flushlen
);
526 conn
->deliver_window
+= STREAMWINDOW_INCREMENT
;
527 if(connection_edge_send_command(conn
, circ
, RELAY_COMMAND_SENDME
,
528 NULL
, 0, conn
->cpath_layer
) < 0) {
529 log_fn(LOG_WARN
,"connection_edge_send_command failed. Returning.");
530 return; /* the circuit's closed, don't continue */
535 static int connection_ap_handshake_process_socks(connection_t
*conn
) {
536 socks_request_t
*socks
;
540 assert(conn
->type
== CONN_TYPE_AP
);
541 assert(conn
->state
== AP_CONN_STATE_SOCKS_WAIT
);
542 assert(conn
->socks_request
);
543 socks
= conn
->socks_request
;
545 log_fn(LOG_DEBUG
,"entered.");
547 sockshere
= fetch_from_buf_socks(conn
->inbuf
, socks
);
548 if(sockshere
== -1 || sockshere
== 0) {
549 if(socks
->replylen
) { /* we should send reply back */
550 log_fn(LOG_DEBUG
,"reply is already set for us. Using it.");
551 connection_ap_handshake_socks_reply(conn
, socks
->reply
, socks
->replylen
, 0);
552 } else if(sockshere
== -1) { /* send normal reject */
553 log_fn(LOG_WARN
,"Fetching socks handshake failed. Closing.");
554 connection_ap_handshake_socks_reply(conn
, NULL
, 0, 0);
556 log_fn(LOG_DEBUG
,"socks handshake not all here yet.");
559 } /* else socks handshake is done, continue processing */
561 conn
->state
= AP_CONN_STATE_CIRCUIT_WAIT
;
562 if(connection_ap_handshake_attach_circuit(conn
) < 0)
563 circuit_launch_new(); /* Build another circuit to handle this stream */
567 /* Try to find a live circuit. If we don't find one, tell 'conn' to
568 * stop reading and return 0. Otherwise, associate the CONN_TYPE_AP
569 * connection 'conn' with a safe live circuit, start sending a
570 * BEGIN cell down the circuit, and return 1.
572 static int connection_ap_handshake_attach_circuit(connection_t
*conn
) {
576 assert(conn
->type
== CONN_TYPE_AP
);
577 assert(conn
->state
== AP_CONN_STATE_CIRCUIT_WAIT
);
578 assert(conn
->socks_request
);
580 /* find the circuit that we should use, if there is one. */
581 circ
= circuit_get_newest(conn
, 1);
584 log_fn(LOG_INFO
,"No safe circuit ready for edge connection; delaying.");
585 connection_stop_reading(conn
); /* don't read until the connected cell arrives */
589 connection_start_reading(conn
);
591 if(!circ
->timestamp_dirty
)
592 circ
->timestamp_dirty
= time(NULL
);
594 /* add it into the linked list of streams on this circuit */
595 log_fn(LOG_DEBUG
,"attaching new conn to circ. n_circ_id %d.", circ
->n_circ_id
);
596 conn
->next_stream
= circ
->p_streams
;
597 /* assert_connection_ok(conn, time(NULL)); */
598 circ
->p_streams
= conn
;
600 assert(circ
->cpath
&& circ
->cpath
->prev
);
601 assert(circ
->cpath
->prev
->state
== CPATH_STATE_OPEN
);
602 conn
->cpath_layer
= circ
->cpath
->prev
;
604 connection_ap_handshake_send_begin(conn
, circ
);
609 /* deliver the destaddr:destport in a relay cell */
610 static void connection_ap_handshake_send_begin(connection_t
*ap_conn
, circuit_t
*circ
)
612 char payload
[CELL_PAYLOAD_SIZE
];
615 const char *string_addr
;
617 assert(ap_conn
->type
== CONN_TYPE_AP
);
618 assert(ap_conn
->state
== AP_CONN_STATE_CIRCUIT_WAIT
);
619 assert(ap_conn
->socks_request
);
621 crypto_pseudo_rand(STREAM_ID_SIZE
, ap_conn
->stream_id
);
622 /* FIXME check for collisions */
624 in
.s_addr
= htonl(client_dns_lookup_entry(ap_conn
->socks_request
->address
));
625 string_addr
= in
.s_addr
? inet_ntoa(in
) : NULL
;
627 memcpy(payload
, ap_conn
->stream_id
, STREAM_ID_SIZE
);
628 payload_len
= STREAM_ID_SIZE
+ 1 +
629 snprintf(payload
+STREAM_ID_SIZE
,CELL_PAYLOAD_SIZE
-RELAY_HEADER_SIZE
-STREAM_ID_SIZE
,
631 string_addr
? string_addr
: ap_conn
->socks_request
->address
,
632 ap_conn
->socks_request
->port
);
634 log_fn(LOG_DEBUG
,"Sending relay cell to begin stream %d.",*(int *)ap_conn
->stream_id
);
636 if(connection_edge_send_command(ap_conn
, circ
, RELAY_COMMAND_BEGIN
,
637 payload
, payload_len
, ap_conn
->cpath_layer
) < 0)
638 return; /* circuit is closed, don't continue */
640 ap_conn
->package_window
= STREAMWINDOW_START
;
641 ap_conn
->deliver_window
= STREAMWINDOW_START
;
642 ap_conn
->state
= AP_CONN_STATE_OPEN
;
643 /* XXX Right now, we rely on the socks client not to send us any data
644 * XXX until we've sent back a socks reply. (If it does, we could wind
645 * XXX up packaging that data and sending it to the exit, then later having
646 * XXX the exit refuse us.)
647 * XXX Perhaps we should grow an AP_CONN_STATE_CONNECTING state.
649 log_fn(LOG_INFO
,"Address/port sent, ap socket %d, n_circ_id %d",ap_conn
->s
,circ
->n_circ_id
);
653 static int connection_ap_handshake_socks_reply(connection_t
*conn
, char *reply
,
654 int replylen
, char success
) {
657 if(replylen
) { /* we already have a reply in mind */
658 connection_write_to_buf(reply
, replylen
, conn
);
659 return flush_buf(conn
->s
, conn
->outbuf
, &conn
->outbuf_flushlen
); /* try to flush it */
661 assert(conn
->socks_request
);
662 if(conn
->socks_request
->socks_version
== 4) {
663 memset(buf
,0,SOCKS4_NETWORK_LEN
);
664 #define SOCKS4_GRANTED 90
665 #define SOCKS4_REJECT 91
666 buf
[1] = (success
? SOCKS4_GRANTED
: SOCKS4_REJECT
);
667 /* leave version, destport, destip zero */
668 connection_write_to_buf(buf
, SOCKS4_NETWORK_LEN
, conn
);
669 return flush_buf(conn
->s
, conn
->outbuf
, &conn
->outbuf_flushlen
); /* try to flush it */
671 if(conn
->socks_request
->socks_version
== 5) {
672 buf
[0] = 5; /* version 5 */
673 #define SOCKS5_SUCCESS 0
674 #define SOCKS5_GENERIC_ERROR 1
675 buf
[1] = success
? SOCKS5_SUCCESS
: SOCKS5_GENERIC_ERROR
;
677 buf
[3] = 1; /* ipv4 addr */
678 memset(buf
+4,0,6); /* Set external addr/port to 0.
679 The spec doesn't seem to say what to do here. -RD */
680 connection_write_to_buf(buf
,10,conn
);
681 return flush_buf(conn
->s
, conn
->outbuf
, &conn
->outbuf_flushlen
); /* try to flush it */
683 return 0; /* if socks_version isn't 4 or 5, don't send anything */
686 static int connection_exit_begin_conn(cell_t
*cell
, circuit_t
*circ
) {
687 connection_t
*n_stream
;
690 /* XXX currently we don't send an end cell back if we drop the
691 * begin because it's malformed.
694 if(!memchr(cell
->payload
+RELAY_HEADER_SIZE
+STREAM_ID_SIZE
,0,
695 cell
->length
-RELAY_HEADER_SIZE
-STREAM_ID_SIZE
)) {
696 log_fn(LOG_WARN
,"relay begin cell has no \\0. Dropping.");
699 colon
= strchr(cell
->payload
+RELAY_HEADER_SIZE
+STREAM_ID_SIZE
, ':');
701 log_fn(LOG_WARN
,"relay begin cell has no colon. Dropping.");
706 if(!atoi(colon
+1)) { /* bad port */
707 log_fn(LOG_WARN
,"relay begin cell has invalid port. Dropping.");
711 log_fn(LOG_DEBUG
,"Creating new exit connection.");
712 n_stream
= connection_new(CONN_TYPE_EXIT
);
714 memcpy(n_stream
->stream_id
, cell
->payload
+ RELAY_HEADER_SIZE
, STREAM_ID_SIZE
);
715 n_stream
->address
= tor_strdup(cell
->payload
+ RELAY_HEADER_SIZE
+ STREAM_ID_SIZE
);
716 n_stream
->port
= atoi(colon
+1);
717 n_stream
->state
= EXIT_CONN_STATE_RESOLVING
;
718 /* leave n_stream->s at -1, because it's not yet valid */
719 n_stream
->package_window
= STREAMWINDOW_START
;
720 n_stream
->deliver_window
= STREAMWINDOW_START
;
721 if(connection_add(n_stream
) < 0) { /* no space, forget it */
722 log_fn(LOG_WARN
,"connection_add failed. Dropping.");
723 connection_free(n_stream
);
727 /* add it into the linked list of streams on this circuit */
728 n_stream
->next_stream
= circ
->n_streams
;
729 circ
->n_streams
= n_stream
;
731 /* send it off to the gethostbyname farm */
732 switch(dns_resolve(n_stream
)) {
733 case 1: /* resolve worked */
734 connection_exit_connect(n_stream
);
736 case -1: /* resolve failed */
737 log_fn(LOG_INFO
,"Resolve failed (%s).", n_stream
->address
);
738 connection_edge_end(n_stream
, END_STREAM_REASON_RESOLVEFAILED
, NULL
);
739 /* case 0, resolve added to pending list */
744 void connection_exit_connect(connection_t
*conn
) {
745 unsigned char connected_payload
[4];
747 if(router_compare_to_exit_policy(conn
) < 0) {
748 log_fn(LOG_INFO
,"%s:%d failed exit policy. Closing.", conn
->address
, conn
->port
);
749 connection_edge_end(conn
, END_STREAM_REASON_EXITPOLICY
, NULL
);
753 switch(connection_connect(conn
, conn
->address
, conn
->addr
, conn
->port
)) {
755 connection_edge_end(conn
, END_STREAM_REASON_CONNECTFAILED
, NULL
);
758 connection_set_poll_socket(conn
);
759 conn
->state
= EXIT_CONN_STATE_CONNECTING
;
761 connection_watch_events(conn
, POLLOUT
| POLLIN
| POLLERR
);
762 /* writable indicates finish, readable indicates broken link,
763 error indicates broken link in windowsland. */
765 /* case 1: fall through */
768 connection_set_poll_socket(conn
);
769 conn
->state
= EXIT_CONN_STATE_OPEN
;
770 if(connection_wants_to_flush(conn
)) { /* in case there are any queued data cells */
771 log_fn(LOG_WARN
,"tell roger: newly connected conn had data waiting!");
772 // connection_start_writing(conn);
774 // connection_process_inbuf(conn);
775 connection_watch_events(conn
, POLLIN
);
777 /* also, deliver a 'connected' cell back through the circuit. */
778 *((uint32_t*) connected_payload
) = htonl(conn
->addr
);
779 connection_edge_send_command(conn
, circuit_get_by_conn(conn
), RELAY_COMMAND_CONNECTED
,
780 connected_payload
, 4, conn
->cpath_layer
);
783 int connection_ap_can_use_exit(connection_t
*conn
, routerinfo_t
*exit
)
788 assert(conn
->type
== CONN_TYPE_AP
);
789 assert(conn
->socks_request
);
791 addr
= client_dns_lookup_entry(conn
->socks_request
->address
);
792 return router_supports_exit_address(addr
, conn
->port
, exit
);
795 /* ***** Client DNS code ***** */
796 #define MAX_DNS_ENTRY_AGE 30*60
798 /* XXX Perhaps this should get merged with the dns.c code somehow. */
799 struct client_dns_entry
{
800 SPLAY_ENTRY(client_dns_entry
) node
;
805 static int client_dns_size
= 0;
806 static SPLAY_HEAD(client_dns_tree
, client_dns_entry
) client_dns_root
;
808 static int compare_client_dns_entries(struct client_dns_entry
*a
,
809 struct client_dns_entry
*b
)
811 return strcasecmp(a
->address
, b
->address
);
814 static void client_dns_entry_free(struct client_dns_entry
*ent
)
816 tor_free(ent
->address
);
820 SPLAY_PROTOTYPE(client_dns_tree
, client_dns_entry
, node
, compare_client_dns_entries
);
821 SPLAY_GENERATE(client_dns_tree
, client_dns_entry
, node
, compare_client_dns_entries
);
823 void client_dns_init(void) {
824 SPLAY_INIT(&client_dns_root
);
828 static uint32_t client_dns_lookup_entry(const char *address
)
830 struct client_dns_entry
*ent
;
831 struct client_dns_entry search
;
837 if (inet_aton(address
, &in
)) {
838 log_fn(LOG_DEBUG
, "Using static address %s (%08X)", address
,
840 return ntohl(in
.s_addr
);
842 search
.address
= (char*)address
;
843 ent
= SPLAY_FIND(client_dns_tree
, &client_dns_root
, &search
);
845 log_fn(LOG_DEBUG
, "No entry found for address %s", address
);
849 if (ent
->expires
< now
) {
850 log_fn(LOG_DEBUG
, "Expired entry found for address %s", address
);
851 SPLAY_REMOVE(client_dns_tree
, &client_dns_root
, ent
);
852 client_dns_entry_free(ent
);
856 in
.s_addr
= htonl(ent
->addr
);
857 log_fn(LOG_DEBUG
, "Found cached entry for address %s: %s", address
,
862 static void client_dns_set_entry(const char *address
, uint32_t val
)
864 struct client_dns_entry
*ent
;
865 struct client_dns_entry search
;
872 if (inet_aton(address
, &in
)) {
873 if (ntohl(in
.s_addr
) == val
)
875 in
.s_addr
= htonl(val
);
877 "Trying to store incompatible cached value %s for static address %s",
878 inet_ntoa(in
), address
);
881 search
.address
= (char*) address
;
883 ent
= SPLAY_FIND(client_dns_tree
, &client_dns_root
, &search
);
885 in
.s_addr
= htonl(val
);
886 log_fn(LOG_DEBUG
, "Updating entry for address %s: %s", address
,
889 ent
->expires
= now
+MAX_DNS_ENTRY_AGE
;
891 in
.s_addr
= htonl(val
);
892 log_fn(LOG_DEBUG
, "Caching result for address %s: %s", address
,
894 ent
= tor_malloc(sizeof(struct client_dns_entry
));
895 ent
->address
= tor_strdup(address
);
897 ent
->expires
= now
+MAX_DNS_ENTRY_AGE
;
898 SPLAY_INSERT(client_dns_tree
, &client_dns_root
, ent
);
903 void client_dns_clean(void)
905 struct client_dns_entry
**expired_entries
;
906 int n_expired_entries
= 0;
907 struct client_dns_entry
*ent
;
913 expired_entries
= tor_malloc(client_dns_size
*
914 sizeof(struct client_dns_entry
*));
917 SPLAY_FOREACH(ent
, client_dns_tree
, &client_dns_root
) {
918 if (ent
->expires
< now
) {
919 expired_entries
[n_expired_entries
++] = ent
;
922 for (i
= 0; i
< n_expired_entries
; ++i
) {
923 SPLAY_REMOVE(client_dns_tree
, &client_dns_root
, expired_entries
[i
]);
924 client_dns_entry_free(expired_entries
[i
]);
926 tor_free(expired_entries
);