forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconnectd.c
1718 lines (1506 loc) · 55.6 KB
/
connectd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
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
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*~ Welcome to the connect daemon: maintainer of connectivity!
*
* This is another separate daemon which is responsible for reaching out to
* other peers, and also accepting their incoming connections. It talks to
* them for just long enough to validate their identity using a cryptographic
* handshake, then receive and send supported feature sets; then it hands them
* up to lightningd which will fire up a specific per-peer daemon to talk to
* it.
*/
#include <ccan/array_size/array_size.h>
#include <ccan/asort/asort.h>
#include <ccan/build_assert/build_assert.h>
#include <ccan/cast/cast.h>
#include <ccan/container_of/container_of.h>
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
#include <ccan/crypto/siphash24/siphash24.h>
#include <ccan/endian/endian.h>
#include <ccan/fdpass/fdpass.h>
#include <ccan/io/fdpass/fdpass.h>
#include <ccan/io/io.h>
#include <ccan/list/list.h>
#include <ccan/mem/mem.h>
#include <ccan/noerr/noerr.h>
#include <ccan/str/str.h>
#include <ccan/take/take.h>
#include <ccan/tal/str/str.h>
#include <ccan/timer/timer.h>
#include <common/bech32.h>
#include <common/bech32_util.h>
#include <common/cryptomsg.h>
#include <common/daemon_conn.h>
#include <common/decode_array.h>
#include <common/ecdh_hsmd.h>
#include <common/errcode.h>
#include <common/features.h>
#include <common/jsonrpc_errors.h>
#include <common/memleak.h>
#include <common/ping.h>
#include <common/pseudorand.h>
#include <common/status.h>
#include <common/subdaemon.h>
#include <common/timeout.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <common/version.h>
#include <common/wire_error.h>
#include <common/wireaddr.h>
#include <connectd/connectd.h>
#include <connectd/connectd_gossipd_wiregen.h>
#include <connectd/connectd_wiregen.h>
#include <connectd/handshake.h>
#include <connectd/netaddress.h>
#include <connectd/peer_exchange_initmsg.h>
#include <connectd/tor.h>
#include <connectd/tor_autoservice.h>
#include <errno.h>
#include <gossipd/gossipd_wiregen.h>
#include <hsmd/hsmd_wiregen.h>
#include <inttypes.h>
#include <lightningd/gossip_msg.h>
#include <netdb.h>
#include <netinet/in.h>
#include <secp256k1_ecdh.h>
#include <sodium.h>
#include <sodium/randombytes.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <wire/peer_wire.h>
#include <wire/wire_io.h>
#include <wire/wire_sync.h>
#include <zlib.h>
/*~ We are passed two file descriptors when exec'ed from `lightningd`: the
* first is a connection to `hsmd`, which we need for the cryptographic
* handshake, and the second is to `gossipd`: it gathers network gossip and
* thus may know how to reach certain peers. */
#define HSM_FD 3
#define GOSSIPCTL_FD 4
/*~ In C convention, constants are UPPERCASE macros. Not everything needs to
* be a constant, but it soothes the programmer's conscience to encapsulate
* arbitrary decisions like these in one place. */
#define MAX_CONNECT_ATTEMPTS 10
#define INITIAL_WAIT_SECONDS 1
#define MAX_WAIT_SECONDS 300
/*~ We keep a hash table (ccan/htable) of public keys, which tells us what
* peers are already connected. The HTABLE_DEFINE_TYPE() macro needs a
* keyof() function to extract the key. For this simple use case, that's the
* identity function: */
static const struct node_id *node_id_keyof(const struct node_id *pc)
{
return pc;
}
/*~ We also need to define a hashing function. siphash24 is a fast yet
* cryptographic hash in ccan/crypto/siphash24; we might be able to get away
* with a slightly faster hash with fewer guarantees, but it's good hygiene to
* use this unless it's a proven bottleneck. siphash_seed() is a function in
* common/pseudorand which sets up a seed for our hashing; it's different
* every time the program is run. */
static size_t node_id_hash(const struct node_id *id)
{
return siphash24(siphash_seed(), id->k, sizeof(id->k));
}
/*~ This defines 'struct node_set' which contains 'struct node_id' pointers. */
HTABLE_DEFINE_TYPE(struct node_id,
node_id_keyof,
node_id_hash,
node_id_eq,
node_set);
/*~ This is the global state, like `struct lightningd *ld` in lightningd. */
struct daemon {
/* Who am I? */
struct node_id id;
/* pubkey equivalent. */
struct pubkey mykey;
/* Base for timeout timers, and how long to wait for init msg */
struct timers timers;
u32 timeout_secs;
/* Peers that we've handed to `lightningd`, which it hasn't told us
* have disconnected. */
struct node_set peers;
/* Peers we are trying to reach */
struct list_head connecting;
/* Connection to main daemon. */
struct daemon_conn *master;
/* Allow localhost to be considered "public": DEVELOPER-only option,
* but for simplicity we don't #if DEVELOPER-wrap it here. */
bool dev_allow_localhost;
/* We support use of a SOCKS5 proxy (e.g. Tor) */
struct addrinfo *proxyaddr;
/* They can tell us we must use proxy even for non-Tor addresses. */
bool use_proxy_always;
/* There are DNS seeds we can use to look up node addresses as a last
* resort, but doing so leaks our address so can be disabled. */
bool use_dns;
/* The address that the broken response returns instead of
* NXDOMAIN. NULL if we have not detected a broken resolver. */
struct sockaddr *broken_resolver_response;
/* File descriptors to listen on once we're activated. */
struct listen_fd *listen_fds;
/* Allow to define the default behavior of tor services calls*/
bool use_v3_autotor;
/* Our features, as lightningd told us */
struct feature_set *our_features;
};
/* Peers we're trying to reach: we iterate through addrs until we succeed
* or fail. */
struct connecting {
/* daemon->connecting */
struct list_node list;
struct daemon *daemon;
struct io_conn *conn;
/* The ID of the peer (not necessarily unique, in transit!) */
struct node_id id;
/* We iterate through the tal_count(addrs) */
size_t addrnum;
struct wireaddr_internal *addrs;
/* NULL if there wasn't a hint. */
struct wireaddr_internal *addrhint;
/* How far did we get? */
const char *connstate;
/* Accumulated errors */
char *errors;
/* How many seconds did we wait this time? */
u32 seconds_waited;
};
/*~ C programs should generally be written bottom-to-top, with the root
* function at the bottom, and functions it calls above it. That avoids
* us having to pre-declare functions; but in the case of mutual recursion
* pre-declarations are necessary (also, sometimes we do it to avoid making
* a patch hard to review with gratuitous reorganizations). */
static void try_connect_one_addr(struct connecting *connect);
/*~ Some ISP resolvers will reply with a dummy IP to queries that would otherwise
* result in an NXDOMAIN reply. This just checks whether we have one such
* resolver upstream and remembers its reply so we can try to filter future
* dummies out.
*/
static bool broken_resolver(struct daemon *daemon)
{
struct addrinfo *addrinfo;
struct addrinfo hints;
const char *hostname = "nxdomain-test.doesntexist";
int err;
/* If they told us to never do DNS queries, don't even do this one and also not if we just say that we don't */
if (!daemon->use_dns || daemon->use_proxy_always) {
daemon->broken_resolver_response = NULL;
return false;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG;
err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", 42),
&hints, &addrinfo);
/*~ Note the use of tal_dup here: it is a memdup for tal, but it's
* type-aware so it's less error-prone. */
if (err == 0) {
daemon->broken_resolver_response
= tal_dup(daemon, struct sockaddr, addrinfo->ai_addr);
freeaddrinfo(addrinfo);
} else
daemon->broken_resolver_response = NULL;
return daemon->broken_resolver_response != NULL;
}
/*~ Here we see our first tal destructor: in this case the 'struct connect'
* simply removes itself from the list of all 'connect' structs. */
static void destroy_connecting(struct connecting *connect)
{
/*~ We don't *need* the list_head here; `list_del(&connect->list)`
* would work. But we have access to it, and `list_del_from()` is
* clearer for readers, and also does a very brief sanity check that
* the list isn't already empty which catches a surprising number of
* bugs! (If CCAN_LIST_DEBUG were defined, it would perform a
* complete list traverse to check it was in the list before
* deletion). */
list_del_from(&connect->daemon->connecting, &connect->list);
}
/*~ Most simple search functions start with find_; in this case, search
* for an existing attempt to connect the given peer id. */
static struct connecting *find_connecting(struct daemon *daemon,
const struct node_id *id)
{
struct connecting *i;
/*~ Note the node_id_eq function: this is generally preferred over
* doing a memcmp() manually, as it is both typesafe and can handle
* any padding which the C compiler is allowed to insert between
* members (unnecessary here, as there's no padding in a `struct
* node_id`). */
list_for_each(&daemon->connecting, i, list)
if (node_id_eq(id, &i->id))
return i;
return NULL;
}
/*~ Once we've connected, we disable the callback which would cause us to
* to try the next address. */
static void connected_to_peer(struct daemon *daemon,
struct io_conn *conn,
const struct node_id *id)
{
struct connecting *outgoing;
/* We allocate 'conn' as a child of 'connect': we don't want to free
* it just yet though. tal_steal() it onto the permanent 'daemon'
* struct. */
tal_steal(daemon, conn);
/* This is either us (if conn is an outgoing connection), or
* NULL or a separate attempt (if we're an incoming): in
* that case, kill the outgoing in favor of our successful
* incoming connection. */
outgoing = find_connecting(daemon, id);
if (outgoing) {
/* Don't call destroy_io_conn, since we're done. */
if (outgoing->conn)
io_set_finish(outgoing->conn, NULL, NULL);
/* Now free the 'connecting' struct. */
tal_free(outgoing);
}
}
/*~ Every per-peer daemon needs a connection to the gossip daemon; this allows
* it to forward gossip to/from the peer. The gossip daemon needs to know a
* few of the features of the peer and its id (for reporting).
*
* Every peer also has read-only access to the gossip_store, which is handed
* out by gossipd too, and also a "gossip_state" indicating where we're up to.
*
* 'features' is a field in the `init` message, indicating properties of the
* node.
*/
static bool get_gossipfds(struct daemon *daemon,
const struct node_id *id,
const u8 *their_features,
struct per_peer_state *pps)
{
bool gossip_queries_feature, initial_routing_sync, success;
u8 *msg;
/*~ The way features generally work is that both sides need to offer it;
* we always offer `gossip_queries`, but this check is explicit. */
gossip_queries_feature
= feature_negotiated(daemon->our_features, their_features,
OPT_GOSSIP_QUERIES);
/*~ `initial_routing_sync` is supported by every node, since it was in
* the initial lightning specification: it means the peer wants the
* backlog of existing gossip. */
initial_routing_sync
= feature_offered(their_features, OPT_INITIAL_ROUTING_SYNC);
/*~ We do this communication sync, since gossipd is our friend and
* it's easier. If gossipd fails, we fail. */
msg = towire_gossipd_new_peer(NULL, id, gossip_queries_feature,
initial_routing_sync);
if (!wire_sync_write(GOSSIPCTL_FD, take(msg)))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed writing to gossipctl: %s",
strerror(errno));
msg = wire_sync_read(tmpctx, GOSSIPCTL_FD);
if (!fromwire_gossipd_new_peer_reply(pps, msg, &success, &pps->gs))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed parsing msg gossipctl: %s",
tal_hex(tmpctx, msg));
/* Gossipd might run out of file descriptors, so it tells us, and we
* give up on connecting this peer. */
if (!success) {
status_broken("Gossipd did not give us an fd: losing peer %s",
type_to_string(tmpctx, struct node_id, id));
return false;
}
/* Otherwise, the next thing in the socket will be the file descriptors
* for the per-peer daemon. */
pps->gossip_fd = fdpass_recv(GOSSIPCTL_FD);
pps->gossip_store_fd = fdpass_recv(GOSSIPCTL_FD);
return true;
}
/*~ This is an ad-hoc marshalling structure where we store arguments so we
* can call peer_connected again. */
struct peer_reconnected {
struct daemon *daemon;
struct node_id id;
struct wireaddr_internal addr;
struct crypto_state cs;
const u8 *their_features;
};
/*~ For simplicity, lightningd only ever deals with a single connection per
* peer. So if we already know about a peer, we tell lightning to disconnect
* the old one and retry once it does. */
static struct io_plan *retry_peer_connected(struct io_conn *conn,
struct peer_reconnected *pr)
{
struct io_plan *plan;
/*~ As you can see, we've had issues with this code before :( */
status_peer_debug(&pr->id, "processing now old peer gone");
/*~ Usually the pattern is to return this directly, but we have to free
* our temporary structure. */
plan = peer_connected(conn, pr->daemon, &pr->id, &pr->addr, &pr->cs,
take(pr->their_features));
tal_free(pr);
return plan;
}
/*~ If we already know about this peer, we tell lightningd and it disconnects
* the old one. We wait until it tells us that's happened. */
static struct io_plan *peer_reconnected(struct io_conn *conn,
struct daemon *daemon,
const struct node_id *id,
const struct wireaddr_internal *addr,
const struct crypto_state *cs,
const u8 *their_features TAKES)
{
u8 *msg;
struct peer_reconnected *pr;
status_peer_debug(id, "reconnect");
/* Tell master to kill it: will send peer_disconnect */
msg = towire_connectd_reconnected(NULL, id);
daemon_conn_send(daemon->master, take(msg));
/* Save arguments for next time. */
pr = tal(daemon, struct peer_reconnected);
pr->daemon = daemon;
pr->id = *id;
pr->cs = *cs;
pr->addr = *addr;
/*~ Note that tal_dup_talarr() will do handle the take() of features
* (turning it into a simply tal_steal() in those cases). */
pr->their_features = tal_dup_talarr(pr, u8, their_features);
/*~ ccan/io supports waiting on an address: in this case, the key in
* the peer set. When someone calls `io_wake()` on that address, it
* will call retry_peer_connected above. */
return io_wait(conn, node_set_get(&daemon->peers, id),
/*~ The notleak() wrapper is a DEVELOPER-mode hack so
* that our memory leak detection doesn't consider 'pr'
* (which is not referenced from our code) to be a
* memory leak. */
retry_peer_connected, notleak(pr));
}
/*~ Note the lack of static: this is called by peer_exchange_initmsg.c once the
* INIT messages are exchanged, and also by the retry code above. */
struct io_plan *peer_connected(struct io_conn *conn,
struct daemon *daemon,
const struct node_id *id,
const struct wireaddr_internal *addr,
struct crypto_state *cs,
const u8 *their_features TAKES)
{
u8 *msg;
struct per_peer_state *pps;
int unsup;
size_t depender, missing;
if (node_set_get(&daemon->peers, id))
return peer_reconnected(conn, daemon, id, addr, cs,
their_features);
/* We promised we'd take it by marking it TAKEN above; prepare to free it. */
if (taken(their_features))
tal_steal(tmpctx, their_features);
/* BOLT #1:
*
* The receiving node:
* ...
* - upon receiving unknown _odd_ feature bits that are non-zero:
* - MUST ignore the bit.
* - upon receiving unknown _even_ feature bits that are non-zero:
* - MUST fail the connection.
*/
unsup = features_unsupported(daemon->our_features, their_features,
INIT_FEATURE);
if (unsup != -1) {
msg = towire_warningfmt(NULL, NULL, "Unsupported feature %u",
unsup);
msg = cryptomsg_encrypt_msg(tmpctx, cs, take(msg));
return io_write(conn, msg, tal_count(msg), io_close_cb, NULL);
}
if (!feature_check_depends(their_features, &depender, &missing)) {
msg = towire_warningfmt(NULL, NULL,
"Feature %zu requires feature %zu",
depender, missing);
msg = cryptomsg_encrypt_msg(tmpctx, cs, take(msg));
return io_write(conn, msg, tal_count(msg), io_close_cb, NULL);
}
/* We've successfully connected. */
connected_to_peer(daemon, conn, id);
/* This contains the per-peer state info; gossipd fills in pps->gs */
pps = new_per_peer_state(tmpctx, cs);
/* If gossipd can't give us a file descriptor, we give up connecting. */
if (!get_gossipfds(daemon, id, their_features, pps))
return io_close(conn);
/* Create message to tell master peer has connected. */
msg = towire_connectd_peer_connected(NULL, id, addr, pps, their_features);
/*~ daemon_conn is a message queue for inter-daemon communication: we
* queue up the `connect_peer_connected` message to tell lightningd
* we have connected, and give the peer and gossip fds. */
daemon_conn_send(daemon->master, take(msg));
/* io_conn_fd() extracts the fd from ccan/io's io_conn */
daemon_conn_send_fd(daemon->master, io_conn_fd(conn));
daemon_conn_send_fd(daemon->master, pps->gossip_fd);
daemon_conn_send_fd(daemon->master, pps->gossip_store_fd);
/* Don't try to close these on freeing. */
pps->gossip_store_fd = pps->gossip_fd = -1;
/*~ Finally, we add it to the set of pubkeys: tal_dup will handle
* take() args for us, by simply tal_steal()ing it. */
node_set_add(&daemon->peers, tal_dup(daemon, struct node_id, id));
/*~ We want to free the connection, but not close the fd (which is
* queued to go to lightningd), so use this variation on io_close: */
return io_close_taken_fd(conn);
}
/*~ handshake.c's handles setting up the crypto state once we get a connection
* in; we hand it straight to peer_exchange_initmsg() to send and receive INIT
* and call peer_connected(). */
static struct io_plan *handshake_in_success(struct io_conn *conn,
const struct pubkey *id_key,
const struct wireaddr_internal *addr,
struct crypto_state *cs,
struct daemon *daemon)
{
struct node_id id;
node_id_from_pubkey(&id, id_key);
status_peer_debug(&id, "Connect IN");
return peer_exchange_initmsg(conn, daemon, daemon->our_features,
cs, &id, addr);
}
/*~ If the timer goes off, we simply free everything, which hangs up. */
static void conn_timeout(struct io_conn *conn)
{
status_debug("conn timed out");
errno = ETIMEDOUT;
io_close(conn);
}
/*~ When we get a connection in we set up its network address then call
* handshake.c to set up the crypto state. */
static struct io_plan *connection_in(struct io_conn *conn, struct daemon *daemon)
{
struct wireaddr_internal addr;
struct sockaddr_storage s = {};
socklen_t len = sizeof(s);
/* The cast here is a weird Berkeley sockets API feature... */
if (getpeername(io_conn_fd(conn), (struct sockaddr *)&s, &len) != 0) {
status_debug("Failed to get peername for incoming conn: %s",
strerror(errno));
return io_close(conn);
}
if (s.ss_family == AF_INET6) {
struct sockaddr_in6 *s6 = (void *)&s;
addr.itype = ADDR_INTERNAL_WIREADDR;
wireaddr_from_ipv6(&addr.u.wireaddr,
&s6->sin6_addr, ntohs(s6->sin6_port));
} else if (s.ss_family == AF_INET) {
struct sockaddr_in *s4 = (void *)&s;
addr.itype = ADDR_INTERNAL_WIREADDR;
wireaddr_from_ipv4(&addr.u.wireaddr,
&s4->sin_addr, ntohs(s4->sin_port));
} else if (s.ss_family == AF_UNIX) {
struct sockaddr_un *sun = (void *)&s;
addr.itype = ADDR_INTERNAL_SOCKNAME;
memcpy(addr.u.sockname, sun->sun_path, sizeof(sun->sun_path));
} else {
status_broken("Unknown socket type %i for incoming conn",
s.ss_family);
return io_close(conn);
}
/* If they don't complete handshake in reasonable time, hang up */
notleak(new_reltimer(&daemon->timers, conn,
time_from_sec(daemon->timeout_secs),
conn_timeout, conn));
/*~ The crypto handshake differs depending on whether you received or
* initiated the socket connection, so there are two entry points.
* Note, again, the notleak() to avoid our simplistic leak detection
* code from thinking `conn` (which we don't keep a pointer to) is
* leaked */
return responder_handshake(notleak(conn), &daemon->mykey, &addr,
handshake_in_success, daemon);
}
/*~ These are the mirror functions for the connecting-out case. */
static struct io_plan *handshake_out_success(struct io_conn *conn,
const struct pubkey *key,
const struct wireaddr_internal *addr,
struct crypto_state *cs,
struct connecting *connect)
{
struct node_id id;
node_id_from_pubkey(&id, key);
connect->connstate = "Exchanging init messages";
status_peer_debug(&id, "Connect OUT");
return peer_exchange_initmsg(conn, connect->daemon,
connect->daemon->our_features,
cs, &id, addr);
}
struct io_plan *connection_out(struct io_conn *conn, struct connecting *connect)
{
struct pubkey outkey;
/* This shouldn't happen: lightningd should not give invalid ids! */
if (!pubkey_from_node_id(&outkey, &connect->id)) {
status_broken("Connection out to invalid id %s",
type_to_string(tmpctx, struct node_id,
&connect->id));
return io_close(conn);
}
/* If they don't complete handshake in reasonable time, hang up */
notleak(new_reltimer(&connect->daemon->timers, conn,
time_from_sec(connect->daemon->timeout_secs),
conn_timeout, conn));
status_peer_debug(&connect->id, "Connected out, starting crypto");
connect->connstate = "Cryptographic handshake";
return initiator_handshake(conn, &connect->daemon->mykey, &outkey,
&connect->addrs[connect->addrnum],
handshake_out_success, connect);
}
/*~ When we've exhausted all addresses without success, we come here.
*
* Note that gcc gets upset if we put the PRINTF_FMT at the end like this if
* it's an actual function definition, but etags gets confused and ignores the
* rest of the file if we put PRINTF_FMT at the front. So we put it at the
* end, in a gratuitous declaration.
*/
static void connect_failed(struct daemon *daemon,
const struct node_id *id,
u32 seconds_waited,
const struct wireaddr_internal *addrhint,
errcode_t errcode,
const char *errfmt, ...)
PRINTF_FMT(6,7);
static void connect_failed(struct daemon *daemon,
const struct node_id *id,
u32 seconds_waited,
const struct wireaddr_internal *addrhint,
errcode_t errcode,
const char *errfmt, ...)
{
u8 *msg;
va_list ap;
char *errmsg;
u32 wait_seconds;
va_start(ap, errfmt);
errmsg = tal_vfmt(tmpctx, errfmt, ap);
va_end(ap);
/* Wait twice as long to reconnect, between min and max. */
wait_seconds = seconds_waited * 2;
if (wait_seconds > MAX_WAIT_SECONDS)
wait_seconds = MAX_WAIT_SECONDS;
if (wait_seconds < INITIAL_WAIT_SECONDS)
wait_seconds = INITIAL_WAIT_SECONDS;
/* lightningd may have a connect command waiting to know what
* happened. We leave it to lightningd to decide if it wants to try
* again, with the wait_seconds as a hint of how long before
* asking. */
msg = towire_connectd_connect_failed(NULL, id, errcode, errmsg,
wait_seconds, addrhint);
daemon_conn_send(daemon->master, take(msg));
status_peer_debug(id, "Failed connected out: %s", errmsg);
}
/* add errors to error list */
void add_errors_to_error_list(struct connecting *connect, const char *error)
{
tal_append_fmt(&connect->errors,
"%s. ", error);
}
/*~ This is the destructor for the (unsuccessful) outgoing connection. We accumulate
* the errors which occurred, so we can report to lightningd properly in case
* they all fail, and try the next address.
*
* This is a specialized form of destructor which takes an extra argument;
* it set up by either the creatively-named tal_add_destructor2(), or by
* the ccan/io's io_set_finish() on a connection. */
static void destroy_io_conn(struct io_conn *conn, struct connecting *connect)
{
/*~ tal_append_fmt appends to a tal string. It's terribly convenient */
const char *errstr = strerror(errno);
/* errno 0 means they hung up on us. */
if (errno == 0) {
errstr = "peer closed connection";
if (streq(connect->connstate, "Cryptographic handshake"))
errstr = "peer closed connection (wrong key?)";
}
add_errors_to_error_list(connect,
tal_fmt(tmpctx, "%s: %s: %s",
type_to_string(tmpctx, struct wireaddr_internal,
&connect->addrs[connect->addrnum]),
connect->connstate, errstr));
connect->addrnum++;
try_connect_one_addr(connect);
}
/* This initializes a fresh io_conn by setting it to io_connect to the
* destination */
static struct io_plan *conn_init(struct io_conn *conn,
struct connecting *connect)
{
/*~ I generally dislike the pattern of "set to NULL, assert if NULL at
* bottom". On -O2 and above the compiler will warn you at compile time
* if a there is a path by which the variable is not set, which is always
* preferable to a runtime assertion. In this case, it's the best way
* to use the "enum in a switch" trick to make sure we handle all enum
* cases, so I use it. */
struct addrinfo *ai = NULL;
const struct wireaddr_internal *addr = &connect->addrs[connect->addrnum];
switch (addr->itype) {
case ADDR_INTERNAL_SOCKNAME:
ai = wireaddr_internal_to_addrinfo(tmpctx, addr);
break;
case ADDR_INTERNAL_ALLPROTO:
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect to all protocols");
break;
case ADDR_INTERNAL_AUTOTOR:
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect to autotor address");
break;
case ADDR_INTERNAL_STATICTOR:
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect to statictor address");
break;
case ADDR_INTERNAL_FORPROXY:
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect to forproxy address");
break;
case ADDR_INTERNAL_WIREADDR:
/* If it was a Tor address, we wouldn't be here. */
ai = wireaddr_to_addrinfo(tmpctx, &addr->u.wireaddr);
break;
}
assert(ai);
io_set_finish(conn, destroy_io_conn, connect);
return io_connect(conn, ai, connection_out, connect);
}
/* This initializes a fresh io_conn by setting it to io_connect to the
* SOCKS proxy, as handled in tor.c. */
static struct io_plan *conn_proxy_init(struct io_conn *conn,
struct connecting *connect)
{
const char *host = NULL;
u16 port;
const struct wireaddr_internal *addr = &connect->addrs[connect->addrnum];
switch (addr->itype) {
case ADDR_INTERNAL_FORPROXY:
host = addr->u.unresolved.name;
port = addr->u.unresolved.port;
break;
case ADDR_INTERNAL_WIREADDR:
host = fmt_wireaddr_without_port(tmpctx, &addr->u.wireaddr);
port = addr->u.wireaddr.port;
break;
case ADDR_INTERNAL_SOCKNAME:
case ADDR_INTERNAL_ALLPROTO:
case ADDR_INTERNAL_AUTOTOR:
case ADDR_INTERNAL_STATICTOR:
break;
}
if (!host)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect to %u address", addr->itype);
io_set_finish(conn, destroy_io_conn, connect);
return io_tor_connect(conn, connect->daemon->proxyaddr, host, port,
connect);
}
/*~ This is the routine which tries to connect. */
static void try_connect_one_addr(struct connecting *connect)
{
int fd, af;
bool use_proxy = connect->daemon->use_proxy_always;
const struct wireaddr_internal *addr = &connect->addrs[connect->addrnum];
struct io_conn *conn;
/* In case we fail without a connection, make destroy_io_conn happy */
connect->conn = NULL;
/* Out of addresses? */
if (connect->addrnum == tal_count(connect->addrs)) {
connect_failed(connect->daemon, &connect->id,
connect->seconds_waited,
connect->addrhint, CONNECT_ALL_ADDRESSES_FAILED,
"%s", connect->errors);
tal_free(connect);
return;
}
/* Might not even be able to create eg. IPv6 sockets */
af = -1;
switch (addr->itype) {
case ADDR_INTERNAL_SOCKNAME:
af = AF_LOCAL;
/* Local sockets don't use tor proxy */
use_proxy = false;
break;
case ADDR_INTERNAL_ALLPROTO:
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect ALLPROTO");
case ADDR_INTERNAL_AUTOTOR:
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect AUTOTOR");
case ADDR_INTERNAL_STATICTOR:
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't connect STATICTOR");
case ADDR_INTERNAL_FORPROXY:
use_proxy = true;
break;
case ADDR_INTERNAL_WIREADDR:
switch (addr->u.wireaddr.type) {
case ADDR_TYPE_TOR_V2:
case ADDR_TYPE_TOR_V3:
use_proxy = true;
break;
case ADDR_TYPE_IPV4:
af = AF_INET;
break;
case ADDR_TYPE_IPV6:
af = AF_INET6;
break;
}
}
/* If we have to use proxy but we don't have one, we fail. */
if (use_proxy) {
if (!connect->daemon->proxyaddr) {
status_debug("Need proxy");
af = -1;
} else
af = connect->daemon->proxyaddr->ai_family;
}
if (af == -1) {
fd = -1;
errno = EPROTONOSUPPORT;
} else
fd = socket(af, SOCK_STREAM, 0);
/* We might not have eg. IPv6 support, or it might be an onion addr
* and we have no proxy. */
if (fd < 0) {
tal_append_fmt(&connect->errors,
"%s: opening %i socket gave %s. ",
type_to_string(tmpctx, struct wireaddr_internal,
addr),
af, strerror(errno));
/* This causes very limited recursion. */
connect->addrnum++;
try_connect_one_addr(connect);
return;
}
/* This creates the new connection using our fd, with the initialization
* function one of the above. */
if (use_proxy)
conn = io_new_conn(connect, fd, conn_proxy_init, connect);
else
conn = io_new_conn(connect, fd, conn_init, connect);
/* Careful! io_new_conn can fail (immediate connect() failure), and
* that frees connect. */
if (conn)
connect->conn = conn;
}
/*~ connectd is responsible for incoming connections, but it's the process of
* setting up the listening ports which gives us information we need for startup
* (such as our own address). So we perform setup in two phases: first we bind
* the sockets according to the command line arguments (if any), then we start
* listening for connections to them once lightningd is ready.
*
* This stores the fds we're going to listen on: */
struct listen_fd {
int fd;
/* If we bind() IPv6 then IPv4 to same port, we *may* fail to listen()
* on the IPv4 socket: under Linux, by default, the IPv6 listen()
* covers IPv4 too. Normally we'd consider failing to listen on a
* port to be fatal, so we note this when setting up addresses. */
bool mayfail;
};
static void add_listen_fd(struct daemon *daemon, int fd, bool mayfail)
{
/*~ utils.h contains a convenience macro tal_arr_expand which
* reallocates a tal_arr to make it one longer, then returns a pointer
* to the (new) last element. */
struct listen_fd l;
l.fd = fd;
l.mayfail = mayfail;
tal_arr_expand(&daemon->listen_fds, l);
}
/*~ Helper routine to create and bind a socket of a given type; like many
* daemons we set it SO_REUSEADDR so we won't have to wait 2 minutes to reuse
* it on restart.
*
* I generally avoid "return -1 on error", but for file-descriptors it's the
* UNIX standard, so it's not as offensive here as it would be in other
* contexts.
*/
static int make_listen_fd(int domain, void *addr, socklen_t len, bool mayfail)
{
int fd = socket(domain, SOCK_STREAM, 0);
int on = 1;
if (fd < 0) {
if (!mayfail)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed to create %u socket: %s",
domain, strerror(errno));
status_debug("Failed to create %u socket: %s",
domain, strerror(errno));
return -1;
}
/* Re-use, please.. */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
status_unusual("Failed setting socket reuse: %s",
strerror(errno));
if (bind(fd, addr, len) != 0) {
if (!mayfail)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed to bind on %u socket: %s",
domain, strerror(errno));
status_debug("Failed to create %u socket: %s",
domain, strerror(errno));
goto fail;
}
return fd;
fail:
/*~ ccan/noerr contains convenient routines which don't clobber the
* errno global; in this case, the caller can report errno. */
close_noerr(fd);
return -1;
}
/* Return true if it created socket successfully. */
static bool handle_wireaddr_listen(struct daemon *daemon,
const struct wireaddr *wireaddr,
bool mayfail)
{
int fd;
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
/* Note the use of a switch() over enum here, even though it must be
* IPv4 or IPv6 here; that will catch future changes. */
switch (wireaddr->type) {
case ADDR_TYPE_IPV4:
wireaddr_to_ipv4(wireaddr, &addr);
/* We might fail if IPv6 bound to port first */
fd = make_listen_fd(AF_INET, &addr, sizeof(addr), mayfail);
if (fd >= 0) {
status_debug("Created IPv4 listener on port %u",
wireaddr->port);
add_listen_fd(daemon, fd, mayfail);
return true;
}
return false;
case ADDR_TYPE_IPV6:
wireaddr_to_ipv6(wireaddr, &addr6);
fd = make_listen_fd(AF_INET6, &addr6, sizeof(addr6), mayfail);
if (fd >= 0) {
status_debug("Created IPv6 listener on port %u",
wireaddr->port);
add_listen_fd(daemon, fd, mayfail);
return true;
}
return false;
case ADDR_TYPE_TOR_V2:
case ADDR_TYPE_TOR_V3:
break;
}