circuit.c 43.2 KB
Newer Older
1
/* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
2
3
/* See LICENSE for licensing information */
/* $Id$ */
Roger Dingledine's avatar
Roger Dingledine committed
4
5
6

#include "or.h"

7
8
extern or_options_t options; /* command-line and config-file options */

9
static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
10
11
                crypt_path_t **layer_hint, char *recognized);
static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction);
Roger Dingledine's avatar
Roger Dingledine committed
12
static void circuit_free_cpath_node(crypt_path_t *victim);
13
static uint16_t get_unique_circ_id_by_conn(connection_t *conn, int circ_id_type);
14
static void circuit_rep_hist_note_result(circuit_t *circ);
Roger Dingledine's avatar
Roger Dingledine committed
15

16
17
18
unsigned long stats_n_relay_cells_relayed = 0;
unsigned long stats_n_relay_cells_delivered = 0;

Roger Dingledine's avatar
Roger Dingledine committed
19
20
/********* START VARIABLES **********/

21
static int circuitlist_len=0;
Roger Dingledine's avatar
Roger Dingledine committed
22
static circuit_t *global_circuitlist=NULL;
23
char *circuit_state_to_string[] = {
Roger Dingledine's avatar
Roger Dingledine committed
24
25
26
27
  "doing handshakes",        /* 0 */
  "processing the onion",    /* 1 */
  "connecting to firsthop",  /* 2 */
  "open"                     /* 3 */
28
29
};

Roger Dingledine's avatar
Roger Dingledine committed
30
31
32
33
34
35
36
37
38
39
/********* END VARIABLES ************/

void circuit_add(circuit_t *circ) {
  if(!global_circuitlist) { /* first one */
    global_circuitlist = circ;
    circ->next = NULL;
  } else {
    circ->next = global_circuitlist;
    global_circuitlist = circ;
  }
40
  ++circuitlist_len;
Roger Dingledine's avatar
Roger Dingledine committed
41
42
43
44
45
}

void circuit_remove(circuit_t *circ) {
  circuit_t *tmpcirc;

Roger Dingledine's avatar
Roger Dingledine committed
46
  assert(circ && global_circuitlist);
Roger Dingledine's avatar
Roger Dingledine committed
47
48
49

  if(global_circuitlist == circ) {
    global_circuitlist = global_circuitlist->next;
50
    --circuitlist_len;
Roger Dingledine's avatar
Roger Dingledine committed
51
52
53
54
55
56
    return;
  }

  for(tmpcirc = global_circuitlist;tmpcirc->next;tmpcirc = tmpcirc->next) {
    if(tmpcirc->next == circ) {
      tmpcirc->next = circ->next;
57
      --circuitlist_len;
Roger Dingledine's avatar
Roger Dingledine committed
58
59
60
61
62
      return;
    }
  }
}

63
64
65
void circuit_close_all_marked()
{
  circuit_t *tmp,*m;
66

67
68
69
70
71
72
  while (global_circuitlist && global_circuitlist->marked_for_close) {
    tmp = global_circuitlist->next;
    circuit_free(global_circuitlist);
    global_circuitlist = tmp;
  }

73
74
75
  tmp = global_circuitlist;
  while (tmp && tmp->next) {
    if (tmp->next->marked_for_close) {
76
77
78
      m = tmp->next->next;
      circuit_free(tmp->next);
      tmp->next = m;
79
80
81
82
      /* Need to check new tmp->next; don't advance tmp. */
    } else {
      /* Advance tmp. */
      tmp = tmp->next;
83
84
85
86
87
    }
  }
}


88
circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn) {
Roger Dingledine's avatar
Roger Dingledine committed
89
  circuit_t *circ;
Roger Dingledine's avatar
Roger Dingledine committed
90

91
  circ = tor_malloc_zero(sizeof(circuit_t));
92
  circ->magic = CIRCUIT_MAGIC;
Roger Dingledine's avatar
Roger Dingledine committed
93

94
  circ->timestamp_created = time(NULL);
95

96
  circ->p_circ_id = p_circ_id;
Roger Dingledine's avatar
Roger Dingledine committed
97
98
  circ->p_conn = p_conn;

99
  circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
Roger Dingledine's avatar
Roger Dingledine committed
100

101
102
103
  /* CircIDs */
  circ->p_circ_id = p_circ_id;
  /* circ->n_circ_id remains 0 because we haven't identified the next hop yet */
Roger Dingledine's avatar
Roger Dingledine committed
104

105
106
  circ->package_window = CIRCWINDOW_START;
  circ->deliver_window = CIRCWINDOW_START;
107

108
109
  circ->next_stream_id = crypto_pseudo_rand_int(1<<16);

Roger Dingledine's avatar
Roger Dingledine committed
110
111
112
113
114
115
  circuit_add(circ);

  return circ;
}

void circuit_free(circuit_t *circ) {
116
  assert(circ);
117
  assert(circ->magic == CIRCUIT_MAGIC);
118
119
120
121
  if (circ->n_crypto)
    crypto_free_cipher_env(circ->n_crypto);
  if (circ->p_crypto)
    crypto_free_cipher_env(circ->p_crypto);
122
123
124
125
  if (circ->n_digest)
    crypto_free_digest_env(circ->n_digest);
  if (circ->p_digest)
    crypto_free_digest_env(circ->p_digest);
Roger Dingledine's avatar
Roger Dingledine committed
126
127
  if(circ->build_state)
    tor_free(circ->build_state->chosen_exit);
128
  tor_free(circ->build_state);
129
  circuit_free_cpath(circ->cpath);
130
  memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
Roger Dingledine's avatar
Roger Dingledine committed
131
  free(circ);
132
133
}

134
void circuit_free_cpath(crypt_path_t *cpath) {
135
  crypt_path_t *victim, *head=cpath;
136

137
138
139
140
141
142
143
144
145
146
147
148
149
  if(!cpath)
    return;

  /* it's a doubly linked list, so we have to notice when we've
   * gone through it once. */
  while(cpath->next && cpath->next != head) {
    victim = cpath;
    cpath = victim->next;
    circuit_free_cpath_node(victim);
  }

  circuit_free_cpath_node(cpath);
}
Roger Dingledine's avatar
Roger Dingledine committed
150

Roger Dingledine's avatar
Roger Dingledine committed
151
static void circuit_free_cpath_node(crypt_path_t *victim) {
152
153
154
155
  if(victim->f_crypto)
    crypto_free_cipher_env(victim->f_crypto);
  if(victim->b_crypto)
    crypto_free_cipher_env(victim->b_crypto);
156
157
158
159
  if(victim->f_digest)
    crypto_free_digest_env(victim->f_digest);
  if(victim->b_digest)
    crypto_free_digest_env(victim->b_digest);
160
161
  if(victim->handshake_state)
    crypto_dh_free(victim->handshake_state);
162
  free(victim);
Roger Dingledine's avatar
Roger Dingledine committed
163
164
}

165
/* return 0 if can't get a unique circ_id. */
166
167
static uint16_t get_unique_circ_id_by_conn(connection_t *conn, int circ_id_type) {
  uint16_t test_circ_id;
168
  int attempts=0;
169
  uint16_t high_bit;
170

171
  assert(conn && conn->type == CONN_TYPE_OR);
172
  high_bit = (circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
173
  do {
174
    /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
175
176
177
178
179
     * circID such that (high_bit|test_circ_id) is not already used. */
    test_circ_id = conn->next_circ_id++;
    if (test_circ_id == 0 || test_circ_id >= 1<<15) {
      test_circ_id = 1;
      conn->next_circ_id = 2;
180
    }
181
182
183
184
185
186
187
    if(++attempts > 1<<15) {
      /* Make sure we don't loop forever if all circ_id's are used. This
       * matters because it's an external DoS vulnerability.
       */
      log_fn(LOG_WARN,"No unused circ IDs. Failing.");
      return 0;
    }
188
189
190
    test_circ_id |= high_bit;
  } while(circuit_get_by_circ_id_conn(test_circ_id, conn));
  return test_circ_id;
Roger Dingledine's avatar
Roger Dingledine committed
191
192
}

193
circuit_t *circuit_get_by_circ_id_conn(uint16_t circ_id, connection_t *conn) {
Roger Dingledine's avatar
Roger Dingledine committed
194
  circuit_t *circ;
195
  connection_t *tmpconn;
Roger Dingledine's avatar
Roger Dingledine committed
196
197

  for(circ=global_circuitlist;circ;circ = circ->next) {
198
199
200
    if (circ->marked_for_close)
      continue;

201
    if(circ->p_circ_id == circ_id) {
202
203
204
      if(circ->p_conn == conn)
        return circ;
      for(tmpconn = circ->p_streams; tmpconn; tmpconn = tmpconn->next_stream) {
205
206
207
208
        if(tmpconn == conn)
          return circ;
      }
    }
209
    if(circ->n_circ_id == circ_id) {
210
211
212
      if(circ->n_conn == conn)
        return circ;
      for(tmpconn = circ->n_streams; tmpconn; tmpconn = tmpconn->next_stream) {
213
214
215
216
        if(tmpconn == conn)
          return circ;
      }
    }
Roger Dingledine's avatar
Roger Dingledine committed
217
218
219
220
221
222
  }
  return NULL;
}

circuit_t *circuit_get_by_conn(connection_t *conn) {
  circuit_t *circ;
223
  connection_t *tmpconn;
Roger Dingledine's avatar
Roger Dingledine committed
224
225

  for(circ=global_circuitlist;circ;circ = circ->next) {
226
227
228
    if (circ->marked_for_close)
      continue;

229
230
231
232
233
    if(circ->p_conn == conn)
      return circ;
    if(circ->n_conn == conn)
      return circ;
    for(tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream)
234
235
      if(tmpconn == conn)
        return circ;
236
    for(tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream)
237
238
      if(tmpconn == conn)
        return circ;
Roger Dingledine's avatar
Roger Dingledine committed
239
240
241
242
  }
  return NULL;
}

243
/* Find the newest circ that conn can use, preferably one which is
244
 * dirty. Circ must not be too old.
245
246
247
 * If !conn, return newest.
 *
 * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN.
248
 */
249
circuit_t *circuit_get_newest(connection_t *conn, int must_be_open) {
250
  circuit_t *circ, *newest=NULL, *leastdirty=NULL;
251
  routerinfo_t *exitrouter;
252
253

  for(circ=global_circuitlist;circ;circ = circ->next) {
254
255
256
257
    if(!circ->cpath)
      continue; /* this circ doesn't start at us */
    if(must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn))
      continue; /* ignore non-open circs */
258
259
    if (circ->marked_for_close)
      continue;
260
261
262
263
264
    if(conn) {
      if(circ->state == CIRCUIT_STATE_OPEN && circ->n_conn) /* open */
        exitrouter = router_get_by_addr_port(circ->cpath->prev->addr, circ->cpath->prev->port);
      else /* not open */
        exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
265
      if(!exitrouter || connection_ap_can_use_exit(conn, exitrouter) == ADDR_POLICY_REJECTED) {
266
267
        /* can't exit from this router */
        continue;
268
269
      }
    }
270
271
272
273
274
275
276
    if(!newest || newest->timestamp_created < circ->timestamp_created) {
      newest = circ;
    }
    if(conn && circ->timestamp_dirty &&
       (!leastdirty || leastdirty->timestamp_dirty < circ->timestamp_dirty)) {
      leastdirty = circ;
    }
277
278
279
280
  }

  if(leastdirty &&
     leastdirty->timestamp_dirty+options.NewCircuitPeriod > time(NULL)) {
Roger Dingledine's avatar
Roger Dingledine committed
281
282
/*    log_fn(LOG_DEBUG,"Choosing in-use circuit %s:%d:%d.",
           leastdirty->n_conn->address, leastdirty->n_port, leastdirty->n_circ_id); */
283
284
285
    return leastdirty;
  }
  if(newest) {
Roger Dingledine's avatar
Roger Dingledine committed
286
287
/*    log_fn(LOG_DEBUG,"Choosing circuit %s:%d:%d.",
           newest->n_conn->address, newest->n_port, newest->n_circ_id); */
288
    return newest;
289
  }
290
  return NULL;
291
292
}

293
#define MIN_SECONDS_BEFORE_EXPIRING_CIRC 10
294
/* circuits that were born at the end of their second might be expired
295
296
 * after 10.1 seconds; circuits born at the beginning might be expired
 * after closer to 11 seconds.
297
298
299
300
301
302
 */

/* close all circuits that start at us, aren't open, and were born
 * at least MIN_SECONDS_BEFORE_EXPIRING_CIRC seconds ago */
void circuit_expire_building(void) {
  int now = time(NULL);
303
  circuit_t *victim, *circ = global_circuitlist;
304

305
306
307
308
309
  while(circ) {
    victim = circ;
    circ = circ->next;
    if(victim->cpath &&
       victim->state != CIRCUIT_STATE_OPEN &&
310
311
       victim->timestamp_created + MIN_SECONDS_BEFORE_EXPIRING_CIRC+1 < now &&
       !victim->marked_for_close) {
312
      if(victim->n_conn)
313
        log_fn(LOG_INFO,"Abandoning circ %s:%d:%d (state %d:%s)",
314
315
               victim->n_conn->address, victim->n_port, victim->n_circ_id,
               victim->state, circuit_state_to_string[victim->state]);
316
      else
317
318
        log_fn(LOG_INFO,"Abandoning circ %d (state %d:%s)", victim->n_circ_id,
               victim->state, circuit_state_to_string[victim->state]);
319
      circuit_log_path(LOG_INFO,victim);
320
      circuit_mark_for_close(victim);
321
322
323
324
325
326
327
328
329
330
    }
  }
}

/* count the number of circs starting at us that aren't open */
int circuit_count_building(void) {
  circuit_t *circ;
  int num=0;

  for(circ=global_circuitlist;circ;circ = circ->next) {
331
332
    if(circ->cpath
       && circ->state != CIRCUIT_STATE_OPEN
333
       && !circ->marked_for_close)
334
335
336
337
338
      num++;
  }
  return num;
}

339
340
341
342
343
344
345
346
347
348
#define MIN_CIRCUITS_HANDLING_STREAM 2
/* return 1 if at least MIN_CIRCUITS_HANDLING_STREAM non-open circuits
 * will have an acceptable exit node for conn. Else return 0.
 */
int circuit_stream_is_being_handled(connection_t *conn) {
  circuit_t *circ;
  routerinfo_t *exitrouter;
  int num=0;

  for(circ=global_circuitlist;circ;circ = circ->next) {
349
    if(circ->cpath && circ->state != CIRCUIT_STATE_OPEN &&
350
       !circ->marked_for_close) {
351
      exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
352
      if(exitrouter && connection_ap_can_use_exit(conn, exitrouter) != ADDR_POLICY_REJECTED)
353
354
355
356
357
358
359
        if(++num >= MIN_CIRCUITS_HANDLING_STREAM)
          return 1;
    }
  }
  return 0;
}

360
/* update digest from the payload of cell. assign integrity part to cell. */
361
static void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) {
362
  char integrity[4];
363
  relay_header_t rh;
364
365

  crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
366
  crypto_digest_get_digest(digest, integrity, 4);
367
368
//  log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.",
//    integrity[0], integrity[1], integrity[2], integrity[3]);
369
  relay_header_unpack(&rh, cell->payload);
370
  memcpy(rh.integrity, integrity, 4);
371
  relay_header_pack(cell->payload, &rh);
372
373
374
}

/* update digest from the payload of cell (with the integrity part set
375
376
 * to 0). If the integrity part is valid return 1, else restore digest
 * and cell to their original state and return 0.
377
 */
378
static int relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) {
379
  char received_integrity[4], calculated_integrity[4];
380
  relay_header_t rh;
381
382
383
  crypto_digest_env_t *backup_digest=NULL;

  backup_digest = crypto_digest_dup(digest);
384
385

  relay_header_unpack(&rh, cell->payload);
386
387
  memcpy(received_integrity, rh.integrity, 4);
  memset(rh.integrity, 0, 4);
388
  relay_header_pack(cell->payload, &rh);
389

390
391
392
//  log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.",
//    received_integrity[0], received_integrity[1],
//    received_integrity[2], received_integrity[3]);
393
394

  crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
395
  crypto_digest_get_digest(digest, calculated_integrity, 4);
396

397
  if(memcmp(received_integrity, calculated_integrity, 4)) {
398
//    log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing.");
399
// (%d vs %d).", received_integrity, calculated_integrity);
400
401
402
    /* restore digest to its old form */
    crypto_digest_assign(digest, backup_digest);
    /* restore the relay header */
403
    memcpy(rh.integrity, received_integrity, 4);
404
405
406
    relay_header_pack(cell->payload, &rh);
    crypto_free_digest_env(backup_digest);
    return 0;
407
  }
408
409
  crypto_free_digest_env(backup_digest);
  return 1;
410
411
}

412
413
414
415
416
417
static int relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
                                   int encrypt_mode) {
  char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */
  relay_header_t rh;

  relay_header_unpack(&rh, in);
418
//  log_fn(LOG_DEBUG,"before crypt: %d",rh.recognized);
419
420
421
422
423
424
425
  if(( encrypt_mode && crypto_cipher_encrypt(cipher, in, CELL_PAYLOAD_SIZE, out)) ||
     (!encrypt_mode && crypto_cipher_decrypt(cipher, in, CELL_PAYLOAD_SIZE, out))) {
    log_fn(LOG_WARN,"Error during crypt: %s", crypto_perror());
    return -1;
  }
  memcpy(in,out,CELL_PAYLOAD_SIZE);
  relay_header_unpack(&rh, in);
426
//  log_fn(LOG_DEBUG,"after crypt: %d",rh.recognized);
427
428
429
430
431
432
433
434
435
436
437
438
  return 0;
}

/*
receive a relay cell:
  - crypt it (encrypt APward, decrypt at AP, decrypt exitward)
  - check if recognized (if exitward)
  - if recognized, check digest, find right conn, deliver to edge.
  - else connection_or_write_cell_to_buf to the right conn
*/
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
                               int cell_direction) {
439
  connection_t *conn=NULL;
440
  crypt_path_t *layer_hint=NULL;
441
  char recognized=0;
442
443

  assert(cell && circ);
Roger Dingledine's avatar
Roger Dingledine committed
444
  assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN);
445
446
  if (circ->marked_for_close)
    return 0;
447

448
  if(relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) {
Roger Dingledine's avatar
Roger Dingledine committed
449
    log_fn(LOG_WARN,"relay crypt failed. Dropping connection.");
Roger Dingledine's avatar
Roger Dingledine committed
450
451
452
    return -1;
  }

453
  if(recognized) {
454
    conn = relay_lookup_conn(circ, cell, cell_direction);
455
    if(cell_direction == CELL_DIRECTION_OUT) {
456
      ++stats_n_relay_cells_delivered;
457
      log_fn(LOG_DEBUG,"Sending to exit.");
Roger Dingledine's avatar
Roger Dingledine committed
458
459
460
461
      if (connection_edge_process_relay_cell(cell, circ, conn, EDGE_EXIT, NULL) < 0) {
        log_fn(LOG_WARN,"connection_edge_process_relay_cell (at exit) failed.");
        return -1;
      }
462
463
    }
    if(cell_direction == CELL_DIRECTION_IN) {
464
      ++stats_n_relay_cells_delivered;
465
      log_fn(LOG_DEBUG,"Sending to AP.");
Roger Dingledine's avatar
Roger Dingledine committed
466
467
468
469
      if (connection_edge_process_relay_cell(cell, circ, conn, EDGE_AP, layer_hint) < 0) {
        log_fn(LOG_WARN,"connection_edge_process_relay_cell (at AP) failed.");
        return -1;
      }
470
    }
471
    return 0;
Roger Dingledine's avatar
Roger Dingledine committed
472
  }
473
474

  /* not recognized. pass it on. */
475
476
  if(cell_direction == CELL_DIRECTION_OUT) {
    cell->circ_id = circ->n_circ_id; /* switch it */
477
    conn = circ->n_conn;
478
479
  } else {
    cell->circ_id = circ->p_circ_id; /* switch it */
480
    conn = circ->p_conn;
481
  }
482

Roger Dingledine's avatar
Roger Dingledine committed
483
  if(!conn) {
484
    log_fn(LOG_WARN,"Didn't recognize cell, but circ stops here! Closing circ.");
485
    return -1;
486
  }
487

488
  log_fn(LOG_DEBUG,"Passing on unrecognized cell.");
Roger Dingledine's avatar
Roger Dingledine committed
489
  ++stats_n_relay_cells_relayed;
Nick Mathewson's avatar
Nick Mathewson committed
490
  connection_or_write_cell_to_buf(cell, conn);
491
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
492
493
}

494
/* wrap this into receive_relay_cell one day */
495
static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
496
                       crypt_path_t **layer_hint, char *recognized) {
497
  crypt_path_t *thishop;
498
  relay_header_t rh;
Roger Dingledine's avatar
Roger Dingledine committed
499

500
  assert(circ && cell && recognized);
501
  assert(cell_direction == CELL_DIRECTION_IN || cell_direction == CELL_DIRECTION_OUT);
Roger Dingledine's avatar
Roger Dingledine committed
502

Roger Dingledine's avatar
Roger Dingledine committed
503
  if(cell_direction == CELL_DIRECTION_IN) {
504
505
    if(circ->cpath) { /* we're at the beginning of the circuit.
                         We'll want to do layered crypts. */
506
      thishop = circ->cpath;
507
      if(thishop->state != CPATH_STATE_OPEN) {
508
        log_fn(LOG_WARN,"Relay cell before first created cell? Closing.");
509
510
        return -1;
      }
511
      do { /* Remember: cpath is in forward order, that is, first hop first. */
512
        assert(thishop);
513

514
        if(relay_crypt_one_payload(thishop->b_crypto, cell->payload, 0) < 0)
515
          return -1;
516

517
        relay_header_unpack(&rh, cell->payload);
518
        if(rh.recognized == 0) {
519
520
521
522
523
524
          /* it's possibly recognized. have to check digest to be sure. */
          if(relay_digest_matches(thishop->b_digest, cell)) {
            *recognized = 1;
            *layer_hint = thishop;
            return 0;
          }
525
        }
526

527
        thishop = thishop->next;
528
      } while(thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
529
530
      log_fn(LOG_WARN,"in-cell at OP not recognized. Closing.");
      return -1;
531
    } else { /* we're in the middle. Just one crypt. */
532
      if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
533
        return -1;
534
//      log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP.");
Roger Dingledine's avatar
Roger Dingledine committed
535
    }
536
  } else /* cell_direction == CELL_DIRECTION_OUT */ {
537
    /* we're in the middle. Just one crypt. */
538

539
    if(relay_crypt_one_payload(circ->n_crypto, cell->payload, 0) < 0)
540
541
      return -1;

542
543
544
545
546
547
    relay_header_unpack(&rh, cell->payload);
    if (rh.recognized == 0) {
      /* it's possibly recognized. have to check digest to be sure. */
      if(relay_digest_matches(circ->n_digest, cell)) {
        *recognized = 1;
        return 0;
548
549
550
551
552
553
554
555
      }
    }
  }
  return 0;
}

/*
package a relay cell:
556
557
 1) encrypt it to the right conn
 2) connection_or_write_cell_to_buf to the right conn
558
559
560
561
562
563
564
*/
int
circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
                           int cell_direction,
                           crypt_path_t *layer_hint)
{
  connection_t *conn; /* where to send the cell */
565
  crypt_path_t *thishop; /* counter for repeated crypts */
566
567
568
569

  if(cell_direction == CELL_DIRECTION_OUT) {
    conn = circ->n_conn;
    if(!conn) {
570
      log_fn(LOG_WARN,"outgoing relay cell has n_conn==NULL. Dropping.");
571
572
      return 0; /* just drop it */
    }
573
    relay_set_digest(layer_hint->f_digest, cell);
574

575
576
577
578
    thishop = layer_hint;
    /* moving from farthest to nearest hop */
    do {
      assert(thishop);
579

580
      log_fn(LOG_DEBUG,"crypting a layer of the relay cell.");
581
      if(relay_crypt_one_payload(thishop->f_crypto, cell->payload, 1) < 0) {
582
583
        return -1;
      }
584

585
586
      thishop = thishop->prev;
    } while (thishop != circ->cpath->prev);
587
588
589
590

  } else { /* incoming cell */
    conn = circ->p_conn;
    if(!conn) {
591
      log_fn(LOG_WARN,"incoming relay cell has p_conn==NULL. Dropping.");
592
      return 0; /* just drop it */
Roger Dingledine's avatar
Roger Dingledine committed
593
    }
594
595
596
    relay_set_digest(circ->p_digest, cell);
    if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
      return -1;
Roger Dingledine's avatar
Roger Dingledine committed
597
  }
598
599
  ++stats_n_relay_cells_relayed;
  connection_or_write_cell_to_buf(cell, conn);
600
601
602
  return 0;
}

603
604
605
static connection_t *
relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
{
606
  connection_t *tmpconn;
607
  relay_header_t rh;
608

609
610
611
612
  relay_header_unpack(&rh, cell->payload);

  if(!rh.stream_id)
    return NULL;
613
614

  if(cell_direction == CELL_DIRECTION_OUT)
615
    tmpconn = circ->n_streams;
616
  else
617
    tmpconn = circ->p_streams;
618
619

  for( ; tmpconn; tmpconn=tmpconn->next_stream) {
620
621
622
    if(rh.stream_id == tmpconn->stream_id) {
      log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id);
      return tmpconn;
623
    }
624
//    log_fn(LOG_DEBUG,"considered stream %d, not it.",tmpconn->stream_id);
625
  }
626
  return NULL; /* probably a begin relay cell */
627
628
}

629
void circuit_resume_edge_reading(circuit_t *circ, int edge_type, crypt_path_t *layer_hint) {
630
631
632
633
  connection_t *conn;

  assert(edge_type == EDGE_EXIT || edge_type == EDGE_AP);

634
  log_fn(LOG_DEBUG,"resuming");
635

Roger Dingledine's avatar
   
Roger Dingledine committed
636
  if(edge_type == EDGE_EXIT)
637
    conn = circ->n_streams;
Roger Dingledine's avatar
   
Roger Dingledine committed
638
  else
639
    conn = circ->p_streams;
Roger Dingledine's avatar
   
Roger Dingledine committed
640

641
  for( ; conn; conn=conn->next_stream) {
642
643
    if((edge_type == EDGE_EXIT && conn->package_window > 0) ||
       (edge_type == EDGE_AP   && conn->package_window > 0 && conn->cpath_layer == layer_hint)) {
644
      connection_start_reading(conn);
Nick Mathewson's avatar
Nick Mathewson committed
645
      connection_edge_package_raw_inbuf(conn); /* handle whatever might still be on the inbuf */
646
647
648

      /* If the circuit won't accept any more data, return without looking
       * at any more of the streams. Any connections that should be stopped
Nick Mathewson's avatar
Nick Mathewson committed
649
       * have already been stopped by connection_edge_package_raw_inbuf. */
650
651
      if(circuit_consider_stop_edge_reading(circ, edge_type, layer_hint))
        return;
652
653
654
655
656
    }
  }
}

/* returns 1 if the window is empty, else 0. If it's empty, tell edge conns to stop reading. */
657
int circuit_consider_stop_edge_reading(circuit_t *circ, int edge_type, crypt_path_t *layer_hint) {
658
659
660
  connection_t *conn = NULL;

  assert(edge_type == EDGE_EXIT || edge_type == EDGE_AP);
661
  assert(edge_type == EDGE_EXIT || layer_hint);
662

663
  log_fn(LOG_DEBUG,"considering");
664
  if(edge_type == EDGE_EXIT && circ->package_window <= 0)
665
    conn = circ->n_streams;
666
  else if(edge_type == EDGE_AP && layer_hint->package_window <= 0)
667
    conn = circ->p_streams;
668
669
670
  else
    return 0;

671
  for( ; conn; conn=conn->next_stream)
672
673
    if(!layer_hint || conn->cpath_layer == layer_hint)
      connection_stop_reading(conn);
674

675
  log_fn(LOG_DEBUG,"yes. stopped.");
676
677
678
  return 1;
}

679
680
681
682
683
void circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t *layer_hint) {
  while((edge_type == EDGE_AP ? layer_hint->deliver_window : circ->deliver_window) <
         CIRCWINDOW_START - CIRCWINDOW_INCREMENT) {
    log_fn(LOG_DEBUG,"Queueing circuit sendme.");
    if(edge_type == EDGE_AP)
684
      layer_hint->deliver_window += CIRCWINDOW_INCREMENT;
685
    else
686
      circ->deliver_window += CIRCWINDOW_INCREMENT;
687
688
    if(connection_edge_send_command(NULL, circ, RELAY_COMMAND_SENDME,
                                    NULL, 0, layer_hint) < 0) {
689
      log_fn(LOG_WARN,"connection_edge_send_command failed. Circuit's closed.");
690
      return; /* the circuit's closed, don't continue */
691
692
    }
  }
Roger Dingledine's avatar
Roger Dingledine committed
693
694
}

695
int _circuit_mark_for_close(circuit_t *circ) {
696
697
  connection_t *conn;

698
699
700
701
  assert_circuit_ok(circ);
  if (circ->marked_for_close < 0)
    return -1;

702
703
704
  if(circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
    onion_pending_remove(circ);
  }
705
706
707
708
709
710
  /* If the circuit ever became OPEN, we sent it to the reputation history
   * module then.  If it isn't OPEN, we send it there now to remember which
   * links worked and which didn't.
   */
  if (circ->state != CIRCUIT_STATE_OPEN)
    circuit_rep_hist_note_result(circ);
711

712
  if(circ->n_conn)
713
    connection_send_destroy(circ->n_circ_id, circ->n_conn);
714
  for(conn=circ->n_streams; conn; conn=conn->next_stream) {
715
    connection_edge_destroy(circ->n_circ_id, conn);
716
  }
717
  if(circ->p_conn)
718
    connection_send_destroy(circ->n_circ_id, circ->p_conn);
719
  for(conn=circ->p_streams; conn; conn=conn->next_stream) {
720
    connection_edge_destroy(circ->p_circ_id, conn);
721
  }
722
723
  if (circ->state == CIRCUIT_STATE_BUILDING ||
      circ->state == CIRCUIT_STATE_OR_WAIT) {
724
    /* If we never built the circuit, note it as a failure. */
725
726
    /* Note that we can't just check circ->cpath here, because if
     * circuit-building failed immediately, it won't be set yet. */
727
728
    circuit_increment_failure_count();
  }
729
730
731

  circ->marked_for_close = 1;
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
732
733
}

734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
void circuit_detach_stream(circuit_t *circ, connection_t *conn) {
  connection_t *prevconn;

  assert(circ);
  assert(conn);

  if(conn == circ->p_streams) {
    circ->p_streams = conn->next_stream;
    return;
  }
  if(conn == circ->n_streams) {
    circ->n_streams = conn->next_stream;
    return;
  }
  for(prevconn = circ->p_streams; prevconn && prevconn->next_stream && prevconn->next_stream != conn; prevconn = prevconn->next_stream) ;
  if(prevconn && prevconn->next_stream) {
    prevconn->next_stream = conn->next_stream;
    return;
  }
  for(prevconn = circ->n_streams; prevconn && prevconn->next_stream && prevconn->next_stream != conn; prevconn = prevconn->next_stream) ;
  if(prevconn && prevconn->next_stream) {
    prevconn->next_stream = conn->next_stream;
    return;
  }
  log_fn(LOG_ERR,"edge conn not in circuit's list?");
  assert(0); /* should never get here */
}

Roger Dingledine's avatar
Roger Dingledine committed
762
763
764
765
766
767
void circuit_about_to_close_connection(connection_t *conn) {
  /* send destroys for all circuits using conn */
  /* currently, we assume it's too late to flush conn's buf here.
   * down the road, maybe we'll consider that eof doesn't mean can't-write
   */
  circuit_t *circ;
768

769
770
771
772
773
774
775
776
  switch(conn->type) {
    case CONN_TYPE_OR:
      /* We must close all the circuits on it. */
      while((circ = circuit_get_by_conn(conn))) {
        if(circ->n_conn == conn) /* it's closing in front of us */
          circ->n_conn = NULL;
        if(circ->p_conn == conn) /* it's closing behind us */
          circ->p_conn = NULL;
777
        circuit_mark_for_close(circ);
Roger Dingledine's avatar
Roger Dingledine committed
778
      }
779
      return;
780
781
    case CONN_TYPE_AP:
    case CONN_TYPE_EXIT:
782

783
784
785
786
      /* It's an edge conn. Need to remove it from the linked list of
       * conn's for this circuit. Confirm that 'end' relay command has
       * been sent. But don't kill the circuit.
       */
Roger Dingledine's avatar
Roger Dingledine committed
787

788
789
790
791
792
      circ = circuit_get_by_conn(conn);
      if(!circ)
        return;

      if(!conn->has_sent_end) {
793
794
        log_fn(LOG_WARN,"Edge connection hasn't sent end yet? Bug.");
        connection_mark_for_close(conn, END_STREAM_REASON_MISC);
795
796
      }

797
798
      circuit_detach_stream(circ, conn);

799
  } /* end switch */
Roger Dingledine's avatar
Roger Dingledine committed
800
801
}

802
void circuit_log_path(int severity, circuit_t *circ) {
803
804
  char buf[1024];
  char *s = buf;
805
  struct crypt_path_t *hop;
806
  char *states[] = {"closed", "waiting for keys", "open"};
807
808
  routerinfo_t *router;
  assert(circ->cpath);
809

810
  snprintf(s, sizeof(buf)-1, "circ (length %d, exit %s): ",
811
812
813
          circ->build_state->desired_path_len, circ->build_state->chosen_exit);
  hop=circ->cpath;
  do {
814
    s = buf + strlen(buf);
815
816
    router = router_get_by_addr_port(hop->addr,hop->port);
    if(router) {
817
818
      snprintf(s, sizeof(buf) - (s - buf), "%s(%s) ",
               router->nickname, states[hop->state]);
819
    } else {
820
      snprintf(s, sizeof(buf) - (s - buf), "UNKNOWN ");
821
    }
822
823
    hop=hop->next;
  } while(hop!=circ->cpath);
824
  log_fn(severity,"%s",buf);
825
826
}

827
828
829
830
831
832
833
834
835
836
837
838
/* Tell the rep(utation)hist(ory) module about the status of the links
 * in circ.  Hops that have become OPEN are marked as successfully
 * extended; the _first_ hop that isn't open (if any) is marked as
 * unable to extend.
 */
static void
circuit_rep_hist_note_result(circuit_t *circ)
{
  struct crypt_path_t *hop;
  char *prev_nickname = NULL;
  routerinfo_t *router;
  hop = circ->cpath;
839
840
841
842
843
844
845
846
  if(!hop) {
    /* XXX
     * if !hop, then we're not the beginning of this circuit.
     * for now, just forget about it. later, we should remember when
     * extends-through-us failed, too.
     */
    return;
  }
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  if (options.ORPort) {
    prev_nickname = options.Nickname;
  }
  do {
    router = router_get_by_addr_port(hop->addr,hop->port);
    if (router) {
      if (prev_nickname) {
        if (hop->state == CPATH_STATE_OPEN)
          rep_hist_note_extend_succeeded(prev_nickname, router->nickname);
        else {
          rep_hist_note_extend_failed(prev_nickname, router->nickname);
          break;
        }
      }
      prev_nickname = router->nickname;
    } else {
      prev_nickname = NULL;
    }
    hop=hop->next;
  } while (hop!=circ->cpath);
}

869
870
871
static void
circuit_dump_details(int severity, circuit_t *circ, int poll_index,
                     char *type, int this_circid, int other_circid) {
872
873
874
875
876
877
878
879
880
  struct crypt_path_t *hop;
  log(severity,"Conn %d has %s circuit: circID %d (other side %d), state %d (%s), born %d",
      poll_index, type, this_circid, other_circid, circ->state,
      circuit_state_to_string[circ->state], (int)circ->timestamp_created);
  if(circ->cpath) { /* circ starts at this node */
    if(circ->state == CIRCUIT_STATE_BUILDING)
      log(severity,"Building: desired len %d, planned exit node %s.",
          circ->build_state->desired_path_len, circ->build_state->chosen_exit);
    for(hop=circ->cpath;hop->next != circ->cpath; hop=hop->next)
881
      log(severity,"hop: state %d, addr 0x%.8x, port %d", hop->state,
Roger Dingledine's avatar
Roger Dingledine committed
882
          (unsigned int)hop->addr,
883
          (int)hop->port);
884
885
886
  }
}

887
void circuit_dump_by_conn(connection_t *conn, int severity) {
888
  circuit_t *circ;
889
  connection_t *tmpconn;
890
891

  for(circ=global_circuitlist;circ;circ = circ->next) {
892
    if(circ->p_conn == conn)
893
894
      circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
                           circ->p_circ_id, circ->n_circ_id);
895
    for(tmpconn=circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
896
      if(tmpconn == conn) {
897
898
        circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
                             circ->p_circ_id, circ->n_circ_id);
899
      }
900
    }
901
    if(circ->n_conn == conn)
902
903
      circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
                           circ->n_circ_id, circ->p_circ_id);
904
    for(tmpconn=circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
905
      if(tmpconn == conn) {
906
907
        circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
                             circ->n_circ_id, circ->p_circ_id);
908
      }
909
910
911
912
    }
  }
}

913
914
/* Don't keep more than 10 unused open circuits around. */
#define MAX_UNUSED_OPEN_CIRCUITS 10
915

916
void circuit_expire_unused_circuits(void) {
917
  circuit_t *circ;
918
  time_t now = time(NULL);
919
920
  smartlist_t *unused_open_circs;
  int i;
921

922
923
924
925
926
  unused_open_circs = smartlist_create(circuitlist_len);

  for (circ = global_circuitlist; circ; circ = circ->next) {
    if (circ->marked_for_close)
      continue;
927
928
929
    /* If the circuit has been dirty for too long, and there are no streams
     * on it, mark it for close.
     */
930
931
932
933
934
935
936
937
938
939
940
941
942
943
    if (circ->timestamp_dirty &&
        circ->timestamp_dirty + options.NewCircuitPeriod < now &&
        !circ->p_conn &&
        !circ->p_streams) {
      log_fn(LOG_DEBUG,"Closing n_circ_id %d",circ->n_circ_id);
      circuit_mark_for_close(circ);
    } else if (!circ->timestamp_dirty && circ->cpath &&
               circ->state == CIRCUIT_STATE_OPEN) {
      /* Also, gather a list of open unused circuits that we created.
       * Because we add elements to the front of global_circuitlist,
       * the last elements of unused_open_circs will be the oldest
       * ones.
       */
      smartlist_add(unused_open_circs, circ);
944
945
    }
  }
946
947
948
949
950
  for (i = MAX_UNUSED_OPEN_CIRCUITS; i < unused_open_circs->num_used; ++i) {
    circuit_t *circ=(circuit_t*)(unused_open_circs->list[i]);
    circuit_mark_for_close(circ);
  }
  smartlist_free(unused_open_circs);
951
952
}

Roger Dingledine's avatar
Roger Dingledine committed
953
/* Number of consecutive failures so far; should only be touched by