]> git.saurik.com Git - apple/mdnsresponder.git/blob - ServiceRegistration/srp-simple.c
mDNSResponder-1096.0.2.tar.gz
[apple/mdnsresponder.git] / ServiceRegistration / srp-simple.c
1 /* srp-simple.c
2 *
3 * Copyright (c) 2018 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Simple Service Registration Protocol Client
18 *
19 * This is intended for the constrained node solution for SRP. It's intended to be flexible and
20 * understandable while linking in the minimum possible support code to reduce code size. It does
21 * no mallocs, does not put anything big on the stack, and doesn't require an event loop.
22 */
23
24 #include <stdio.h>
25 #include <arpa/inet.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include "srp.h"
30 #include "dns-msg.h"
31 #include "srp-crypto.h"
32
33 static void
34 dns_response_callback(dns_transaction_t *txn)
35 {
36 }
37
38 int
39 main(int argc, char **argv)
40 {
41 const char *host_name = "thread-demo";
42 const char *zone_name = "default.service.arpa";
43 const char *host_fqdn = "thread-demo.default.service.arpa";
44 const char *service_type = "_ipps._tcp";
45 const char *a_record = "127.0.0.1";
46 const char *aaaa_record = "::1";
47 const char *txt_record = "0";
48 const char *anycast_address = "127.0.0.1";
49 // const char *anycast_address = "73.186.137.119"; // cer.fugue.com
50 const char *keyfile_name = "srp-simple.key";
51 int port = 9992;
52 srp_key_t *key;
53 dns_wire_t message, response;
54 uint16_t key_tag;
55 static dns_transaction_t txn;
56 dns_towire_state_t *towire = &txn.towire;
57 dns_name_pointer_t p_host_name;
58 dns_name_pointer_t p_zone_name;
59 dns_name_pointer_t p_service_name;
60 dns_name_pointer_t p_service_instance_name;
61 int line;
62
63 key = srp_load_keypair(keyfile_name);
64 if (key == NULL) {
65 key = srp_generate_key();
66 if (key == NULL) {
67 printf("Unable to load or generate a key.");
68 exit(1);
69 }
70 if (!srp_write_key_to_file(keyfile_name, key)) {
71 printf("Unable to safe generated key.");
72 exit(1);
73 }
74 }
75
76 #define CH if (towire->error) { line = __LINE__; goto fail; }
77
78 // Generate a random UUID.
79 #ifdef NOTYET
80 message.id = srp_random16();
81 #else
82 srandomdev();
83 message.id = (uint32_t)(random()) & 65535;
84 #endif
85 message.bitfield = 0;
86 dns_qr_set(&message, dns_qr_query);
87 dns_opcode_set(&message, dns_opcode_update);
88
89 // Message data...
90 memset(&txn, 0, sizeof txn);
91 towire->p = &message.data[0]; // We start storing RR data here.
92 towire->lim = &message.data[DNS_DATA_SIZE]; // This is the limit to how much we can store.
93 towire->message = &message;
94 txn.response = &response;
95 txn.response_length = (int)(sizeof response);
96
97 message.qdcount = htons(1); // ZOCOUNT = 1
98 // Copy in Zone name (and save pointer)
99 // ZTYPE = SOA
100 // ZCLASS = IN
101 dns_full_name_to_wire(&p_zone_name, towire, zone_name); CH;
102 dns_u16_to_wire(towire, dns_rrtype_soa); CH;
103 dns_u16_to_wire(towire, dns_qclass_in); CH;
104
105 message.ancount = 0;
106 // PRCOUNT = 0
107
108 message.nscount = 0;
109 // UPCOUNT = ...
110
111 // Host Description:
112 // * Delete all RRsets from <hostname>; remember the pointer to hostname
113 // NAME = hostname label followed by pointer to SOA name.
114 // TYPE = ANY
115 // CLASS = ANY
116 // TTL = 0
117 // RDLENGTH = 0
118 dns_name_to_wire(&p_host_name, towire, host_name); CH;
119 dns_pointer_to_wire(&p_host_name, towire, &p_zone_name); CH;
120 dns_u16_to_wire(towire, dns_rrtype_any); CH;
121 dns_u16_to_wire(towire, dns_qclass_any); CH;
122 dns_ttl_to_wire(towire, 0); CH;
123 dns_u16_to_wire(towire, 0); CH;
124 message.nscount++;
125 // * Add either or both of an A or AAAA RRset, each of which contains one
126 // or more A or AAAA RRs.
127 // NAME = pointer to hostname from Delete (above)
128 // TYPE = A or AAAA
129 // CLASS = IN
130 // TTL = 3600 ?
131 // RDLENGTH = number of RRs * RR length (4 or 16)
132 // RDATA = <the data>
133 dns_pointer_to_wire(NULL, towire, &p_host_name); CH;
134 dns_u16_to_wire(towire, dns_rrtype_a); CH;
135 dns_u16_to_wire(towire, dns_qclass_in); CH;
136 dns_ttl_to_wire(towire, 3600); CH;
137 dns_rdlength_begin(towire); CH;
138 dns_rdata_a_to_wire(towire, a_record); CH;
139 dns_rdlength_end(towire); CH;
140 message.nscount++;
141
142 dns_pointer_to_wire(NULL, towire, &p_host_name); CH;
143 dns_u16_to_wire(towire, dns_rrtype_aaaa); CH;
144 dns_u16_to_wire(towire, dns_qclass_in); CH;
145 dns_ttl_to_wire(towire, 3600); CH;
146 dns_rdlength_begin(towire); CH;
147 dns_rdata_aaaa_to_wire(towire, aaaa_record); CH;
148 dns_rdlength_end(towire); CH;
149 message.nscount++;
150
151 // * Exactly one KEY RR:
152 // NAME = pointer to hostname from Delete (above)
153 // TYPE = KEY
154 // CLASS = IN
155 // TTL = 3600
156 // RDLENGTH = length of key + 4 (32 bits)
157 // RDATA = <flags(16) = 0000 0010 0000 0001, protocol(8) = 3, algorithm(8) = 8?, public key(variable)>
158 dns_pointer_to_wire(NULL, towire, &p_host_name); CH;
159 dns_u16_to_wire(towire, dns_rrtype_key); CH;
160 dns_u16_to_wire(towire, dns_qclass_in); CH;
161 dns_ttl_to_wire(towire, 3600); CH;
162 dns_rdlength_begin(towire); CH;
163 key_tag = dns_rdata_key_to_wire(towire, 0, 2, 1, key); CH;
164 dns_rdlength_end(towire); CH;
165 message.nscount++;
166
167 // Service Discovery:
168 // * Update PTR RR
169 // NAME = service name (_a._b.service.arpa)
170 // TYPE = PTR
171 // CLASS = IN
172 // TTL = 3600
173 // RDLENGTH = 2
174 // RDATA = service instance name
175 dns_name_to_wire(&p_service_name, towire, service_type); CH;
176 dns_pointer_to_wire(&p_service_name, towire, &p_zone_name); CH;
177 dns_u16_to_wire(towire, dns_rrtype_ptr); CH;
178 dns_u16_to_wire(towire, dns_qclass_in); CH;
179 dns_ttl_to_wire(towire, 3600); CH;
180 dns_rdlength_begin(towire); CH;
181 dns_name_to_wire(&p_service_instance_name, towire, host_name); CH;
182 dns_pointer_to_wire(&p_service_instance_name, towire, &p_service_name); CH;
183 dns_rdlength_end(towire); CH;
184 message.nscount++;
185
186 // Service Description:
187 // * Delete all RRsets from service instance name
188 // NAME = service instance name (save pointer to service name, which is the second label)
189 // TYPE = ANY
190 // CLASS = ANY
191 // TTL = 0
192 // RDLENGTH = 0
193 dns_pointer_to_wire(NULL, towire, &p_service_instance_name); CH;
194 dns_u16_to_wire(towire, dns_rrtype_any); CH;
195 dns_u16_to_wire(towire, dns_qclass_any); CH;
196 dns_ttl_to_wire(towire, 0); CH;
197 dns_u16_to_wire(towire, 0); CH;
198 message.nscount++;
199
200 // * Add one SRV RRset pointing to Host Description
201 // NAME = pointer to service instance name from above
202 // TYPE = SRV
203 // CLASS = IN
204 // TTL = 3600
205 // RDLENGTH = 8
206 // RDATA = <priority(16) = 0, weight(16) = 0, port(16) = service port, target = pointer to hostname>
207 dns_pointer_to_wire(NULL, towire, &p_service_instance_name); CH;
208 dns_u16_to_wire(towire, dns_rrtype_srv); CH;
209 dns_u16_to_wire(towire, dns_qclass_in); CH;
210 dns_ttl_to_wire(towire, 3600); CH;
211 dns_rdlength_begin(towire); CH;
212 dns_u16_to_wire(towire, 0); // priority CH;
213 dns_u16_to_wire(towire, 0); // weight CH;
214 dns_u16_to_wire(towire, port); // port CH;
215 dns_pointer_to_wire(NULL, towire, &p_host_name); CH;
216 dns_rdlength_end(towire); CH;
217 message.nscount++;
218
219 // * Add one or more TXT records
220 // NAME = pointer to service instance name from above
221 // TYPE = TXT
222 // CLASS = IN
223 // TTL = 3600
224 // RDLENGTH = <length of text>
225 // RDATA = <text>
226 dns_pointer_to_wire(NULL, towire, &p_service_instance_name); CH;
227 dns_u16_to_wire(towire, dns_rrtype_txt); CH;
228 dns_u16_to_wire(towire, dns_qclass_in); CH;
229 dns_ttl_to_wire(towire, 3600); CH;
230 dns_rdlength_begin(towire); CH;
231 dns_rdata_txt_to_wire(towire, txt_record); CH;
232 dns_rdlength_end(towire); CH;
233 message.nscount++;
234 message.nscount = htons(message.nscount);
235
236 // What about services with more than one name? Are these multiple service descriptions?
237
238 // ARCOUNT = 2
239 // EDNS(0) options
240 // ...
241 // SIG(0)
242
243 message.arcount = htons(1);
244 dns_edns0_header_to_wire(towire, DNS_MAX_UDP_PAYLOAD, 0, 0, 1); CH; // XRCODE = 0; VERSION = 0; DO=1
245 dns_rdlength_begin(towire); CH;
246 dns_u16_to_wire(towire, dns_opt_update_lease); CH; // OPTION-CODE
247 dns_edns0_option_begin(towire); CH; // OPTION-LENGTH
248 dns_u32_to_wire(towire, 3600); CH; // LEASE (1 hour)
249 dns_u32_to_wire(towire, 604800); CH; // KEY-LEASE (7 days)
250 dns_edns0_option_end(towire); CH; // Now we know OPTION-LENGTH
251 dns_rdlength_end(towire); CH;
252
253 dns_sig0_signature_to_wire(towire, key, key_tag, &p_host_name, host_fqdn); CH;
254 // The signature is computed before counting the signature RR in the header counts.
255 message.arcount = htons(ntohs(message.arcount) + 1);
256
257 // Send the update
258 if (dns_send_to_server(&txn, anycast_address, 53, dns_response_callback) < 0) {
259 line = __LINE__;
260 fail:
261 printf("dns_send_to_server failed: %s at line %d\n", strerror(towire->error), line);
262 }
263 }
264
265 // Local Variables:
266 // mode: C
267 // tab-width: 4
268 // c-file-style: "bsd"
269 // c-basic-offset: 4
270 // fill-column: 108
271 // indent-tabs-mode: nil
272 // End: