1 /* See the DRL-LICENSE file for this file's software license. */
6 #include <libxml/xmlmemory.h>
7 #include <libxml/parser.h>
8 #include <netinet/in.h>
12 #include <sys/socket.h>
14 #include "raterouter.h"
15 #include "ratetypes.h"
20 void free_ident(ident_config *ident) {
22 while (ident->peers) {
23 ident_peer *tofree = ident->peers;
24 ident->peers = ident->peers->next;
29 while (ident->members) {
30 ident_member *tofree = ident->members;
31 ident->members = ident->members->next;
39 void free_ident_list(ident_config *list) {
49 static int xid_filter(const struct dirent *d) {
50 if (atoi(d->d_name) > 0)
56 int get_eligible_leaves(drl_instance_t *instance) {
57 struct dirent **names;
59 leaf_t *leaves = NULL;
60 map_handle leaf_map = allocate_map();
62 if (leaf_map == NULL) {
66 count = scandir("/proc/virtual", &names, xid_filter, alphasort);
72 leaves = malloc(count * sizeof(leaf_t));
74 /* Couldn't allocate leaves array. Need to free names memory. */
83 for (i = 0; i < count; ++i) {
84 leaves[i].xid = atoi(names[i]->d_name);
85 leaves[i].parent = NULL;
89 map_insert(leaf_map, &leaves[i].xid, sizeof(leaves[i].xid), &leaves[i]);
94 instance->leaf_map = leaf_map;
95 instance->leaves = leaves;
96 instance->leaf_count = count;
101 static int parse_common(xmlDocPtr doc, xmlNodePtr ident, ident_config *common) {
108 xmlChar *mainloop_intervals;
109 xmlChar *communication_intervals;
110 xmlChar *independent;
111 xmlNodePtr fields = ident->children;
112 ident_peer *current = NULL;
114 /* Make sure no required fields are missing. */
115 id = xmlGetProp(ident, (const xmlChar *) "id");
117 printlog(LOG_CRITICAL, "Ident missing globally unique identifier.\n");
120 common->id = atoi((const char *) id);
124 limit = xmlGetProp(ident, (const xmlChar *) "limit");
126 printlog(LOG_CRITICAL, "Ident missing global rate limit.\n");
129 common->limit = atoi((const char *) limit);
133 commfabric = xmlGetProp(ident, (const xmlChar *) "commfabric");
134 if (commfabric == NULL) {
135 printlog(LOG_CRITICAL, "Ident missing comm fabric specifier.\n");
138 if (!xmlStrcmp(commfabric, (const xmlChar *) "MESH")) {
139 common->commfabric = COMM_MESH;
140 } else if (!xmlStrcmp(commfabric, (const xmlChar *) "GOSSIP")) {
141 common->commfabric = COMM_GOSSIP;
143 printlog(LOG_CRITICAL, "Unknown/invalid comm fabric.\n");
150 /* Only care about branching factor if we're using gossip. */
151 if (common->commfabric == COMM_GOSSIP) {
152 branch = xmlGetProp(ident, (const xmlChar *) "branch");
153 if (branch == NULL) {
154 printlog(LOG_CRITICAL, "Ident missing gossip branch.\n");
157 common->branch = atoi((const char *) branch);
162 accounting = xmlGetProp(ident, (const xmlChar *) "accounting");
163 if (accounting == NULL) {
164 printlog(LOG_CRITICAL, "Ident missing accounting.\n");
167 if (!xmlStrcmp(accounting, (const xmlChar *) "STANDARD")) {
168 common->accounting = ACT_STANDARD;
169 } else if (!xmlStrcmp(accounting, (const xmlChar *) "SAMPLEHOLD")) {
170 common->accounting = ACT_SAMPLEHOLD;
171 } else if (!xmlStrcmp(accounting, (const xmlChar *) "SIMPLE")) {
172 common->accounting = ACT_SIMPLE;
173 } else if (!xmlStrcmp(accounting, (const xmlChar *) "MULTIPLEINTERVAL")) {
174 common->accounting = ACT_MULTIPLE;
176 printlog(LOG_CRITICAL, "Unknown/invalid accounting table.\n");
183 ewma = xmlGetProp(ident, (const xmlChar *) "ewma");
185 printlog(LOG_CRITICAL, "Ident missing ewma weight.\n");
188 common->fixed_ewma_weight = atof((const char *) ewma);
192 mainloop_intervals = xmlGetProp(ident, (const xmlChar *) "loop_intervals");
193 if (mainloop_intervals == NULL) {
194 printlog(LOG_WARN, "Ident id: %d missing loop_intervals, assuming 1.\n", common->id);
195 common->mainloop_intervals = 1;
197 common->mainloop_intervals = atoi((const char *) mainloop_intervals);
198 xmlFree(mainloop_intervals);
201 communication_intervals = xmlGetProp(ident, (const xmlChar *) "comm_intervals");
202 if (communication_intervals == NULL) {
203 printlog(LOG_WARN, "Ident id: %d missing comm_intervals, assuming 1.\n", common->id);
204 common->communication_intervals = 1;
206 common->communication_intervals = atoi((const char *) communication_intervals);
207 xmlFree(communication_intervals);
210 independent = xmlGetProp(ident, (const xmlChar *) "independent");
211 if (independent == NULL) {
212 common->independent = 0;
214 common->independent = atoi((const char *) independent);
215 xmlFree(independent);
218 while (fields != NULL) {
219 if((!xmlStrcmp(fields->name, (const xmlChar *) "peer"))) {
220 xmlChar *ip = xmlNodeListGetString(doc, fields->children, 1);
221 if (current == NULL) {
223 common->peers = malloc(sizeof(ident_peer));
224 if (common->peers == NULL) {
227 common->peers->ip = inet_addr((const char *) ip);
228 common->peers->next = NULL;
229 common->peer_count += 1;
230 current = common->peers;
232 /* Add it to the list. */
233 current->next = malloc(sizeof(ident_peer));
234 if (current->next == NULL) {
237 current = current->next;
238 current->ip = inet_addr((const char *) ip);
239 common->peer_count += 1;
240 current->next = NULL;
244 fields = fields->next;
247 if (common->peers == NULL) {
248 printlog(LOG_CRITICAL, "Must have at least one peer.\n");
256 static ident_config *parse_machine(xmlDocPtr doc, xmlNodePtr ident, parsed_configs *configs) {
257 ident_config *common = malloc(sizeof(ident_config));
259 if (common == NULL) {
263 memset(common, 0, sizeof(ident_config));
264 if (parse_common(doc, ident, common)) {
269 /* No further information needed for machine-level identities. */
270 common->type = IDENT_MACHINE;
271 common->members = NULL;
274 if (configs->last_machine == NULL) {
275 configs->machines = common;
276 configs->last_machine = common;
278 configs->last_machine->next = common;
279 configs->last_machine = common;
282 configs->machine_count += 1;
287 static ident_config *parse_set(xmlDocPtr doc, xmlNodePtr ident, parsed_configs *configs) {
288 xmlNodePtr fields = ident->children;
289 ident_config *common = malloc(sizeof(ident_config));
290 ident_member *current = NULL;
292 if (common == NULL) {
296 memset(common, 0, sizeof(ident_config));
297 if (parse_common(doc, ident, common)) {
302 while (fields != NULL) {
303 ident_member *member = NULL;
305 if (!xmlStrcmp(fields->name, (const xmlChar *) "xid")) {
306 xmlChar *xid = xmlNodeListGetString(doc, fields->children, 1);
308 if (atoi((const char *) xid) >= 0) {
309 member = malloc(sizeof(ident_member));
310 if (member == NULL) {
315 member->type = MEMBER_XID;
316 sscanf((const char *) xid, "%x", &member->value);
325 } else if (!xmlStrcmp(fields->name, (const xmlChar *) "guid")) {
326 xmlChar *guid = xmlNodeListGetString(doc, fields->children, 1);
328 if (atoi((const char *) guid) >= 0) {
329 member = malloc(sizeof(ident_member));
330 if (member == NULL) {
335 member->type = MEMBER_GUID;
336 member->value = atoi((const char *) guid);
348 if (common->members == NULL) {
349 common->members = member;
352 current->next = member;
357 fields = fields->next;
360 /* A sliver set must have at least one member (xid or guid) or else it is
362 if (common->members == NULL) {
367 common->type = IDENT_SET;
370 if (configs->last_set == NULL) {
371 configs->sets = common;
372 configs->last_set = common;
374 configs->last_set->next = common;
375 configs->last_set = common;
378 configs->set_count += 1;
383 int parse_drl_config(const char *configfile, parsed_configs *configs) {
385 xmlNodePtr drl, ident;
387 configs->machines = NULL;
388 configs->sets = NULL;
389 configs->last_machine = NULL;
390 configs->last_set = NULL;
391 configs->machine_count = 0;
392 configs->set_count = 0;
394 if(!(doc = xmlParseFile(configfile))){
395 printlog(LOG_CRITICAL, "Config file (%s) not parsed successfully.\n", configfile);
400 if(!(drl = xmlDocGetRootElement(doc))){
401 printlog(LOG_CRITICAL, "Config file (%s) has no root element.\n", configfile);
405 if(xmlStrcmp(drl->name, (const xmlChar *) "drl")){
406 printlog(LOG_CRITICAL, "Config file (%s) of the wrong type, root node != drl\n", configfile);
411 ident = drl->children;
412 while(ident != NULL) {
413 ident_config *new = NULL;
415 if((!xmlStrcmp(ident->name, (const xmlChar *) "machine"))) {
416 new = parse_machine(doc, ident, configs);
417 } else if ((!xmlStrcmp(ident->name, (const xmlChar *) "set"))) {
418 new = parse_set(doc, ident, configs);
419 } else if ((!xmlStrcmp(ident->name, (const xmlChar *) "text"))) {
420 /* libxml seems to wrap everything inside two 'text's. */
426 /* FIXME: Make this more descriptive. :) */
427 printlog(LOG_CRITICAL, "Error occurred while parsing...\n");
429 free_ident_list(configs->machines);
430 free_ident_list(configs->sets);
432 configs->machines = NULL;
433 configs->sets = NULL;
434 configs->last_machine = NULL;
435 configs->last_set = NULL;
446 /* Return the list of parsed identities. */