blob: 708fab7f2c01c209d9a31eba3e3ae98741f03e23 [file] [log] [blame]
akmhoque5b39a432013-02-11 09:49:06 -06001#include <stdio.h>
2#include <stdlib.h>
3#include <netinet/in.h>
4#include <netdb.h>
5#include <sys/time.h>
6#include <sys/types.h>
7#include <unistd.h>
8#include <stdarg.h>
9#include <string.h>
10
11#include <ccn/ccn.h>
12#include <ccn/uri.h>
13#include <ccn/face_mgmt.h>
14#include <ccn/reg_mgmt.h>
15#include <ccn/charbuf.h>
16
17
18
19#include "nlsr_face.h"
20
21static void
22ccn_fib_warn(int lineno, const char *format, ...)
23{
24 struct timeval t;
25 va_list ap;
26 va_start(ap, format);
27 gettimeofday(&t, NULL);
28 fprintf(stderr, "%d.%06d ccn_fib[%d]:%d: ", (int)t.tv_sec, (unsigned)t.tv_usec, (int)getpid(), lineno);
29 vfprintf(stderr, format, ap);
30 va_end(ap);
31}
32
33static void
34ccn_fib_fatal(int lineno, const char *format, ...)
35{
36 struct timeval t;
37 va_list ap;
38 va_start(ap, format);
39 gettimeofday(&t, NULL);
40 fprintf(stderr, "%d.%06d ccn_fib[%d]:%d: ", (int)t.tv_sec, (unsigned)t.tv_usec, (int)getpid(), lineno);
41 vfprintf(stderr, format, ap);
42 va_end(ap);
43 exit(1);
44}
45
46#define ON_ERROR_EXIT(resval, msg) on_error_exit((resval), __LINE__, msg)
47
48static void
49on_error_exit(int res, int lineno, const char *msg)
50{
51 if (res >= 0)
52 return;
53 ccn_fib_fatal(lineno, "fatal error, res = %d, %s\n", res, msg);
54}
55
56#define ON_ERROR_CLEANUP(resval) \
57{ \
58 if ((resval) < 0) { \
59 ccn_fib_warn (__LINE__, "OnError cleanup\n"); \
60 goto cleanup; \
61 } \
62}
63
64#define ON_NULL_CLEANUP(resval) \
65{ \
66 if ((resval) == NULL) { \
67 ccn_fib_warn(__LINE__, "OnNull cleanup\n"); \
68 goto cleanup; \
69 } \
70}
71
72
73/**
74 *
75 * Bind a prefix to a face
76 *
77 */
78static int
79register_unregister_prefix(struct ccn *h, struct ccn_charbuf *local_scope_template,
80 struct ccn_charbuf *no_name, struct ccn_charbuf *name_prefix,
81 struct ccn_face_instance *face_instance, int operation)
82{
83 struct ccn_charbuf *temp = NULL;
84 struct ccn_charbuf *resultbuf = NULL;
85 struct ccn_charbuf *signed_info = NULL;
86 struct ccn_charbuf *name = NULL;
87 struct ccn_charbuf *prefixreg = NULL;
88 struct ccn_parsed_ContentObject pcobuf = {0};
89 struct ccn_forwarding_entry forwarding_entry_storage = {0};
90 struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage;
91 struct ccn_forwarding_entry *new_forwarding_entry;
92 const unsigned char *ptr = NULL;
93 size_t length = 0;
94 int res;
95
96 /* Register or unregister the prefix */
97 forwarding_entry->action = (operation == OP_REG) ? "prefixreg" : "unreg";
98 forwarding_entry->name_prefix = name_prefix;
99 forwarding_entry->ccnd_id = face_instance->ccnd_id;
100 forwarding_entry->ccnd_id_size = face_instance->ccnd_id_size;
101 forwarding_entry->faceid = face_instance->faceid;
102 forwarding_entry->flags = -1;
103 forwarding_entry->lifetime = 2100;
104
105 prefixreg = ccn_charbuf_create();
106 ccnb_append_forwarding_entry(prefixreg, forwarding_entry);
107 temp = ccn_charbuf_create();
108 res = ccn_sign_content(h, temp, no_name, NULL, prefixreg->buf, prefixreg->length);
109 resultbuf = ccn_charbuf_create();
110
111 /* construct Interest containing prefixreg request */
112 name = ccn_charbuf_create();
113 ccn_name_init(name);
114 ccn_name_append_str(name, "ccnx");
115 ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size);
116 ccn_name_append_str(name, (operation == OP_REG) ? "prefixreg" : "unreg");
117 ccn_name_append(name, temp->buf, temp->length);
118
119 /* send Interest, get Data */
120 res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
121 ON_ERROR_CLEANUP(res);
122
123 res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length);
124 ON_ERROR_CLEANUP(res);
125
126 /* extract new forwarding entry from Data */
127 new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length);
128 ON_NULL_CLEANUP(new_forwarding_entry);
129
130 res = new_forwarding_entry->faceid;
131
132 ccn_forwarding_entry_destroy(&new_forwarding_entry);
133 ccn_charbuf_destroy(&signed_info);
134 ccn_charbuf_destroy(&temp);
135 ccn_charbuf_destroy(&resultbuf);
136 ccn_charbuf_destroy(&name);
137 ccn_charbuf_destroy(&prefixreg);
138
139 return res;
140
141 cleanup:
142 ccn_forwarding_entry_destroy(&new_forwarding_entry);
143 ccn_charbuf_destroy(&signed_info);
144 ccn_charbuf_destroy(&temp);
145 ccn_charbuf_destroy(&resultbuf);
146 ccn_charbuf_destroy(&name);
147 ccn_charbuf_destroy(&prefixreg);
148
149 return -1;
150}
151
152/**
153 *
154 * Create new face by sending out a request Interest
155 * The actual new face instance is returned
156 *
157 */
158static
159struct ccn_face_instance *create_face(struct ccn *h, struct ccn_charbuf *local_scope_template,
160 struct ccn_charbuf *no_name, struct ccn_face_instance *face_instance)
161{
162 struct ccn_charbuf *newface = NULL;
163 struct ccn_charbuf *signed_info = NULL;
164 struct ccn_charbuf *temp = NULL;
165 struct ccn_charbuf *name = NULL;
166 struct ccn_charbuf *resultbuf = NULL;
167 struct ccn_parsed_ContentObject pcobuf = {0};
168 struct ccn_face_instance *new_face_instance = NULL;
169 const unsigned char *ptr = NULL;
170 size_t length = 0;
171 int res = 0;
172
173 /* Encode the given face instance */
174 newface = ccn_charbuf_create();
175 ccnb_append_face_instance(newface, face_instance);
176
177 temp = ccn_charbuf_create();
178 res = ccn_sign_content(h, temp, no_name, NULL, newface->buf, newface->length);
179 resultbuf = ccn_charbuf_create();
180
181 /* Construct the Interest name that will create the face */
182 name = ccn_charbuf_create();
183 ccn_name_init(name);
184 ccn_name_append_str(name, "ccnx");
185 ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size);
186 ccn_name_append_str(name, face_instance->action);
187 ccn_name_append(name, temp->buf, temp->length);
188
189 /* send Interest to retrieve Data that contains the newly created face */
190 res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
191 ON_ERROR_CLEANUP(res);
192
193 /* decode Data to get the actual face instance */
194 res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length);
195 ON_ERROR_CLEANUP(res);
196
197 new_face_instance = ccn_face_instance_parse(ptr, length);
198
199 ccn_charbuf_destroy(&newface);
200 ccn_charbuf_destroy(&signed_info);
201 ccn_charbuf_destroy(&temp);
202 ccn_charbuf_destroy(&resultbuf);
203 ccn_charbuf_destroy(&name);
204
205 return new_face_instance;
206
207 cleanup:
208 ccn_charbuf_destroy(&newface);
209 ccn_charbuf_destroy(&signed_info);
210 ccn_charbuf_destroy(&temp);
211 ccn_charbuf_destroy(&resultbuf);
212 ccn_charbuf_destroy(&name);
213
214 return NULL;
215}
216
217/**
218 *
219 * Get ccnd id
220 *
221 */
222static int
223get_ccndid(struct ccn *h, struct ccn_charbuf *local_scope_template,
224 unsigned char *ccndid)
225{
226 struct ccn_charbuf *name = NULL;
227 struct ccn_charbuf *resultbuf = NULL;
228 struct ccn_parsed_ContentObject pcobuf = {0};
229 char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY";
230 const unsigned char *ccndid_result;
231 static size_t ccndid_result_size;
232 int res;
233
234 name = ccn_charbuf_create();
235 resultbuf = ccn_charbuf_create();
236
237 res = ccn_name_from_uri(name, ccndid_uri);
238 ON_ERROR_EXIT(res, "Unable to parse service locator URI for ccnd key\n");
239
240 /* get Data */
241 res = ccn_get(h, name, local_scope_template, 4500, resultbuf, &pcobuf, NULL, 0);
242 ON_ERROR_EXIT(res, "Unable to get key from ccnd\n");
243
244 /* extract from Data */
245 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
246 resultbuf->buf,
247 pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest],
248 pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest],
249 &ccndid_result, &ccndid_result_size);
250 ON_ERROR_EXIT(res, "Unable to parse ccnd response for ccnd id\n");
251
252 memcpy((void *)ccndid, ccndid_result, ccndid_result_size);
253
254 ccn_charbuf_destroy(&name);
255 ccn_charbuf_destroy(&resultbuf);
256
257 return (ccndid_result_size);
258}
259
260/**
261 * Construct a new face instance based on the given address and port
262 * This face instance is only used to send new face request
263 */
264static struct
265ccn_face_instance *construct_face(const unsigned char *ccndid, size_t ccndid_size,
266 const char *address, const char *port, unsigned int tunnel_proto)
267{
268 struct ccn_face_instance *fi = calloc(1, sizeof(*fi));
269 char rhostnamebuf[NI_MAXHOST];
270 char rhostportbuf[NI_MAXSERV];
271 struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG),
272 .ai_socktype = SOCK_DGRAM};
273 struct addrinfo *raddrinfo = NULL;
274 struct ccn_charbuf *store = ccn_charbuf_create();
275 int host_off = -1;
276 int port_off = -1;
277 int res;
278
279 res = getaddrinfo(address, port, &hints, &raddrinfo);
280 if (res != 0 || raddrinfo == NULL)
281 {
282 fprintf(stderr, "Error: getaddrinfo\n");
283 return NULL;
284 }
285
286 res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen,
287 rhostnamebuf, sizeof(rhostnamebuf),
288 rhostportbuf, sizeof(rhostportbuf),
289 NI_NUMERICHOST | NI_NUMERICSERV);
290 freeaddrinfo(raddrinfo);
291 if (res != 0)
292 {
293 fprintf(stderr, "Error: getnameinfo\n");
294 return NULL;
295 }
296
297 fi->store = store;
298 fi->descr.ipproto = tunnel_proto;
299 fi->descr.mcast_ttl = CCN_FIB_MCASTTTL;
300 fi->lifetime = CCN_FIB_LIFETIME;
301
302 ccn_charbuf_append(store, "newface", strlen("newface") + 1);
303 host_off = store->length;
304 ccn_charbuf_append(store, rhostnamebuf, strlen(rhostnamebuf) + 1);
305 port_off = store->length;
306 ccn_charbuf_append(store, rhostportbuf, strlen(rhostportbuf) + 1);
307
308 char *b = (char *)store->buf;
309 fi->action = b;
310 fi->descr.address = b + host_off;
311 fi->descr.port = b + port_off;
312 fi->descr.source_address = NULL;
313 fi->ccnd_id = ccndid;
314 fi->ccnd_id_size = ccndid_size;
315
316 return fi;
317}
318
319/**
320 * initialize local data
321 */
322static void
323init_data(struct ccn_charbuf *local_scope_template,
324 struct ccn_charbuf *no_name)
325{
326 ccn_charbuf_append_tt(local_scope_template, CCN_DTAG_Interest, CCN_DTAG);
327 ccn_charbuf_append_tt(local_scope_template, CCN_DTAG_Name, CCN_DTAG);
328 ccn_charbuf_append_closer(local_scope_template); /* </Name> */
329 ccnb_tagged_putf(local_scope_template, CCN_DTAG_Scope, "1");
330 ccn_charbuf_append_closer(local_scope_template); /* </Interest> */
331
332 ccn_name_init(no_name);
333}
334
335static int
336add_delete_ccn_face(struct ccn *h, const char *uri, const char *address, const unsigned int p, int operation,unsigned int tunnel_proto)
337{
338 struct ccn_charbuf *prefix;
339 char port[6];
340 struct ccn_charbuf *local_scope_template = ccn_charbuf_create();
341 struct ccn_charbuf *no_name = ccn_charbuf_create();
342 unsigned char ccndid_storage[32] = {0};
343 unsigned char *ccndid = ccndid_storage;
344 size_t ccndid_size = 0;
345 struct ccn_face_instance *fi;
346 struct ccn_face_instance *nfi;
347 int res;
348
349 prefix = ccn_charbuf_create();
350 res = ccn_name_from_uri(prefix, uri);
351 ON_ERROR_CLEANUP(res);
352 memset(port, 0, 6);
353 sprintf(port, "%d", p);
354
355 init_data(local_scope_template, no_name);
356
357 ccndid_size = get_ccndid(h, local_scope_template, ccndid);
358 if (ccndid_size != sizeof(ccndid_storage))
359 {
360 fprintf(stderr, "Incorrect size for ccnd id in response\n");
361 ON_ERROR_CLEANUP(-1);
362 }
363
364 /* construct a face instance for new face request */
365 fi = construct_face(ccndid, ccndid_size, address, port,tunnel_proto);
366 ON_NULL_CLEANUP(fi);
367
368 /* send new face request to actually create a new face */
369 nfi = create_face(h, local_scope_template, no_name, fi);
370 ON_NULL_CLEANUP(nfi);
371
372
373 res = register_unregister_prefix(h, local_scope_template, no_name, prefix, nfi, operation);
374 ON_ERROR_CLEANUP(res);
375
376 int faceid=nfi->faceid;
377
378 ccn_charbuf_destroy(&local_scope_template);
379 ccn_charbuf_destroy(&no_name);
380 ccn_face_instance_destroy(&fi);
381 ccn_face_instance_destroy(&nfi);
382 ccn_charbuf_destroy(&prefix);
383
384
385 return faceid;
386
387 cleanup:
388 ccn_charbuf_destroy(&prefix);
389 ccn_charbuf_destroy(&local_scope_template);
390 ccn_charbuf_destroy(&no_name);
391 ccn_face_instance_destroy(&fi);
392 ccn_face_instance_destroy(&nfi);
393
394 return -1;
395}
396
397
398int
399add_ccn_face(struct ccn *h, const char *uri, const char *address, const unsigned int port, unsigned int tunnel_proto)
400{
401 return add_delete_ccn_face(h, uri, address, port, OP_REG,tunnel_proto);
402}
403
404
405int
406delete_ccn_face(struct ccn *h, const char *uri, const char *address, const unsigned int port,unsigned int tunnel_proto)
407{
408 return add_delete_ccn_face(h, uri, address, port, OP_UNREG,tunnel_proto);
409}
410