1let
2 carolKey = "2d2a338b46f8e4a8c462f0c385b481292a05f678e19a2b82755258cf0f0af7e2";
3 carolPubKey = "n932l3pjvmhtxxcdrqq2qpw5zc58f01vvjx01h4dtd1bb0nnu2h0.k";
4 carolPassword = "678287829ce4c67bc8b227e56d94422ee1b85fa11618157b2f591de6c6322b52";
5
6 basicConfig =
7 { ... }:
8 { services.cjdns.enable = true;
9
10 # Turning off DHCP isn't very realistic but makes
11 # the sequence of address assignment less stochastic.
12 networking.useDHCP = false;
13
14 # CJDNS output is incompatible with the XML log.
15 systemd.services.cjdns.serviceConfig.StandardOutput = "null";
16 #networking.firewall.enable = true;
17 networking.firewall.allowPing = true;
18 #networking.firewall.rejectPackets = true;
19 };
20
21in
22
23import ./make-test.nix ({ pkgs, ...} : {
24 name = "cjdns";
25 meta = with pkgs.stdenv.lib.maintainers; {
26 maintainers = [ ehmry ];
27 };
28
29 nodes = rec
30 { # Alice finds peers over over ETHInterface.
31 alice =
32 { ... }:
33 { imports = [ basicConfig ];
34
35 services.cjdns.ETHInterface.bind = "eth1";
36
37 services.httpd.enable = true;
38 services.httpd.adminAddr = "foo@example.org";
39 networking.firewall.allowedTCPPorts = [ 80 ];
40 };
41
42 # Bob explicitly connects to Carol over UDPInterface.
43 bob =
44 { ... }:
45
46 { imports = [ basicConfig ];
47
48 networking.interfaces.eth1.ipv4.addresses = [
49 { address = "192.168.0.2"; prefixLength = 24; }
50 ];
51
52 services.cjdns =
53 { UDPInterface =
54 { bind = "0.0.0.0:1024";
55 connectTo."192.168.0.1:1024" =
56 { password = carolPassword;
57 publicKey = carolPubKey;
58 };
59 };
60 };
61 };
62
63 # Carol listens on ETHInterface and UDPInterface,
64 # but knows neither Alice or Bob.
65 carol =
66 { ... }:
67 { imports = [ basicConfig ];
68
69 environment.etc."cjdns.keys".text = ''
70 CJDNS_PRIVATE_KEY=${carolKey}
71 CJDNS_ADMIN_PASSWORD=FOOBAR
72 '';
73
74 networking.interfaces.eth1.ipv4.addresses = [
75 { address = "192.168.0.1"; prefixLength = 24; }
76 ];
77
78 services.cjdns =
79 { authorizedPasswords = [ carolPassword ];
80 ETHInterface.bind = "eth1";
81 UDPInterface.bind = "192.168.0.1:1024";
82 };
83 networking.firewall.allowedUDPPorts = [ 1024 ];
84 };
85
86 };
87
88 testScript =
89 ''
90 startAll;
91
92 $alice->waitForUnit("cjdns.service");
93 $bob->waitForUnit("cjdns.service");
94 $carol->waitForUnit("cjdns.service");
95
96 sub cjdnsIp {
97 my ($machine) = @_;
98 my $ip = (split /[ \/]+/, $machine->succeed("ip -o -6 addr show dev tun0"))[3];
99 $machine->log("has ip $ip");
100 return $ip;
101 }
102
103 my $aliceIp6 = cjdnsIp $alice;
104 my $bobIp6 = cjdnsIp $bob;
105 my $carolIp6 = cjdnsIp $carol;
106
107 # ping a few times each to let the routing table establish itself
108
109 $alice->succeed("ping -c 4 $carolIp6");
110 $bob->succeed("ping -c 4 $carolIp6");
111
112 $carol->succeed("ping -c 4 $aliceIp6");
113 $carol->succeed("ping -c 4 $bobIp6");
114
115 $alice->succeed("ping -c 4 $bobIp6");
116 $bob->succeed("ping -c 4 $aliceIp6");
117
118 $alice->waitForUnit("httpd.service");
119
120 $bob->succeed("curl --fail -g http://[$aliceIp6]");
121 '';
122})