]> git.proxmox.com Git - ovs.git/blob - lib/cfg.c
Replace SHA-1 library with one that is clearly licensed.
[ovs.git] / lib / cfg.c
1 /* Copyright (c) 2008, 2009 Nicira Networks
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <config.h>
17 #include "cfg.h"
18 #include <arpa/inet.h>
19 #include <assert.h>
20 #include <dirent.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <fnmatch.h>
24 #include <inttypes.h>
25 #include <netinet/in.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include "coverage.h"
31 #include "dynamic-string.h"
32 #include "ofpbuf.h"
33 #include "packets.h"
34 #include "svec.h"
35 #include "timeval.h"
36 #include "util.h"
37
38 #define THIS_MODULE VLM_cfg
39 #include "vlog.h"
40
41 /* XXX This file really needs a unit test! For a while, cfg_get_string(0,
42 * "bridge.a.controller") would return the value of
43 * "bridge.a.controller.in-band", if it existed, and I'm really not certain
44 * that the fix didn't break other things. */
45
46 /* Configuration file name. */
47 static char *cfg_name;
48
49 /* Put the temporary file in the same directory as cfg_name, so that
50 * they are guaranteed to be in the same file system and therefore we can
51 * rename() tmp_name over cfg_name. */
52 static char *tmp_name;
53
54 /* Lock information. */
55 static char *lock_name;
56 static int lock_fd = -1;
57
58 /* Flag to indicate whether local modifications have been made. */
59 static bool dirty;
60
61 static uint8_t cfg_cookie[CFG_COOKIE_LEN];
62
63 /* Current configuration. Maintained in sorted order. */
64 static struct svec cfg = SVEC_EMPTY_INITIALIZER;
65
66 static bool has_double_dot(const char *key, size_t len);
67 static bool is_valid_key(const char *key, size_t len,
68 const char *file_name, int line_number,
69 const char *id);
70 static char *parse_section(const char *file_name, int line_number,
71 const char *);
72 static void parse_setting(const char *file_name, int line_number,
73 const char *section, const char *);
74 static int compare_key(const char *a, const char *b);
75 static char **find_key_le(const char *key);
76 static char **find_key_ge(const char *key);
77 static char *find_key(const char *);
78 static bool parse_mac(const char *, uint8_t mac[6]);
79 static bool parse_dpid(const char *, uint64_t *);
80 static bool is_key(const char *);
81 static bool is_int(const char *);
82 static bool is_bool(const char *);
83 static const char *extract_value(const char *key);
84 static const char *get_nth_value(int idx, const char *key);
85 static bool is_type(const char *s, enum cfg_flags);
86
87 #define CC_ALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
88 #define CC_DIGIT "0123456789"
89 #define CC_ALNUM CC_ALPHA CC_DIGIT
90 #define CC_SPACE " \t\r\n\v"
91
92 #define CC_FILE_NAME CC_ALNUM "._-"
93 #define CC_KEY CC_ALNUM "._-@$:+"
94
95 /* Sets 'file_name' as the configuration file read by cfg_read(). Returns 0 on
96 * success, otherwise a positive errno value if 'file_name' cannot be opened.
97 *
98 * This function does not actually read the named file or directory. Use
99 * cfg_read() to (re)read all the configuration files. */
100 int
101 cfg_set_file(const char *file_name)
102 {
103 const char *slash;
104 int fd;
105
106 if (cfg_name) {
107 assert(lock_fd < 0);
108 free(cfg_name);
109 free(lock_name);
110 free(tmp_name);
111 cfg_name = lock_name = tmp_name = NULL;
112 }
113
114 /* Make sure that we can open this file for reading. */
115 fd = open(file_name, O_RDONLY);
116 if (fd < 0) {
117 return errno;
118 }
119 close(fd);
120
121 cfg_name = xstrdup(file_name);
122
123 /* Put the temporary file in the same directory as cfg_name, so that they
124 * are guaranteed to be in the same file system, to guarantee that
125 * rename(tmp_name, cfg_name) will work. */
126 tmp_name = xasprintf("%s.~tmp~", file_name);
127
128 /* Put the lock file in the same directory as cfg_name, but prefixed by
129 * a dot so as not to garner administrator interest. */
130 slash = strrchr(file_name, '/');
131 if (slash) {
132 lock_name = xasprintf("%.*s/.%s.~lock~",
133 slash - file_name, file_name, slash + 1);
134 } else {
135 lock_name = xasprintf(".%s.~lock~", file_name);
136 }
137
138 VLOG_INFO("using \"%s\" as configuration file, \"%s\" as lock file",
139 file_name, lock_name);
140 return 0;
141 }
142
143 static int
144 update_cookie(void)
145 {
146 struct sha1_ctx context;
147 int i;
148
149 sha1_init(&context);
150 for (i = 0; i < cfg.n; i++) {
151 sha1_update(&context, cfg.names[i], strlen(cfg.names[i]));
152 sha1_update(&context, "\n", 1);
153 }
154 sha1_final(&context, cfg_cookie);
155
156 return 0;
157 }
158
159 /* Reads all of the configuration files or directories that have been added
160 * with cfg_add_file(), merges their content. Any previous configuration is
161 * replaced. Returns 0 if successful, otherwise a positive errno value. */
162 int
163 cfg_read(void)
164 {
165 struct svec old_cfg;
166 struct ds ds;
167 FILE *file;
168 char *section;
169 int line_number;
170
171
172 if (!cfg_name) {
173 return ENODEV;
174 }
175
176 /* Save old configuration data and clear the active configuration. */
177 svec_init(&old_cfg);
178 svec_swap(&old_cfg, &cfg);
179
180 /* Read new configuration. */
181 VLOG_DBG("reading configuration from %s", cfg_name);
182
183 file = fopen(cfg_name, "r");
184 if (!file) {
185 VLOG_ERR("failed to open \"%s\": %s", cfg_name, strerror(errno));
186 return errno;
187 }
188
189 ds_init(&ds);
190 section = NULL;
191 line_number = 0;
192 while (!ds_get_line(&ds, file)) {
193 const char *s = ds_cstr(&ds);
194 size_t indent = strspn(s, CC_SPACE);
195
196 line_number++;
197 s += indent;
198 if (*s == '#' || *s == '\0') {
199 /* Ignore comments and lines that contain only white space. */
200 } else if (*s == '[') {
201 if (!indent) {
202 free(section);
203 section = parse_section(cfg_name, line_number, s);
204 } else {
205 VLOG_ERR("%s:%d: ignoring indented section header",
206 cfg_name, line_number);
207 }
208 } else if (indent && !section) {
209 VLOG_ERR("%s:%d: ignoring indented line outside any section",
210 cfg_name, line_number);
211 } else {
212 if (!indent) {
213 free(section);
214 section = NULL;
215 }
216 parse_setting(cfg_name, line_number, section, s);
217 }
218 }
219 ds_destroy(&ds);
220 free(section);
221
222 svec_sort(&cfg);
223 svec_terminate(&cfg);
224 update_cookie();
225
226 fclose(file);
227
228 if (VLOG_IS_DBG_ENABLED()) {
229 struct svec removed, added;
230 size_t i;
231
232 svec_diff(&old_cfg, &cfg, &removed, NULL, &added);
233 if (removed.n || added.n) {
234 VLOG_DBG("configuration changes:");
235 for (i = 0; i < removed.n; i++) {
236 VLOG_DBG("-%s", removed.names[i]);
237 }
238 for (i = 0; i < added.n; i++) {
239 VLOG_DBG("+%s", added.names[i]);
240 }
241 } else {
242 VLOG_DBG("configuration unchanged");
243 }
244 svec_destroy(&added);
245 svec_destroy(&removed);
246 }
247 svec_destroy(&old_cfg);
248
249 dirty = false;
250
251 return 0;
252 }
253
254 /* Fills 'svec' with the entire configuration file. */
255 void
256 cfg_get_all(struct svec *svec)
257 {
258 svec_clear(svec);
259 svec_append(svec, &cfg);
260 }
261
262 int
263 cfg_get_cookie(uint8_t *cookie)
264 {
265 if (dirty) {
266 update_cookie();
267 }
268
269 memcpy(cookie, cfg_cookie, sizeof(cfg_cookie));
270 return 0;
271 }
272
273 void
274 cfg_unlock(void)
275 {
276 if (lock_fd != -1) {
277 COVERAGE_INC(cfg_unlock);
278 close(lock_fd);
279 lock_fd = -1;
280 }
281 }
282
283 static int
284 open_lockfile(const char *name)
285 {
286 for (;;) {
287 /* Try to open an existing lock file. */
288 int fd = open(name, O_RDWR);
289 if (fd >= 0) {
290 return fd;
291 } else if (errno != ENOENT) {
292 VLOG_WARN("%s: failed to open lock file: %s",
293 name, strerror(errno));
294 return -errno;
295 }
296
297 /* Try to create a new lock file. */
298 VLOG_INFO("%s: lock file does not exist, creating", name);
299 fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
300 if (fd >= 0) {
301 return fd;
302 } else if (errno != EEXIST) {
303 VLOG_WARN("%s: failed to create lock file: %s",
304 name, strerror(errno));
305 return -errno;
306 }
307
308 /* Someone else created the lock file. Try again. */
309 }
310 }
311
312 static int
313 try_lock(int fd, bool block)
314 {
315 struct flock l;
316 memset(&l, 0, sizeof l);
317 l.l_type = F_WRLCK;
318 l.l_whence = SEEK_SET;
319 l.l_start = 0;
320 l.l_len = 0;
321 return fcntl(fd, block ? F_SETLKW : F_SETLK, &l) == -1 ? errno : 0;
322 }
323
324 /* Locks the configuration file against modification by other processes and
325 * re-reads it from disk.
326 *
327 * The 'timeout' specifies the maximum number of milliseconds to wait for the
328 * config file to become free. Use 0 to avoid waiting or INT_MAX to wait
329 * forever.
330 *
331 * Returns 0 on success, otherwise a positive errno value. */
332 int
333 cfg_lock(uint8_t *cookie, int timeout)
334 {
335 long long int start = time_msec();
336 long long int elapsed = 0;
337 int fd;
338 uint8_t curr_cookie[CFG_COOKIE_LEN];
339
340 assert(lock_fd < 0);
341 COVERAGE_INC(cfg_lock);
342 for (;;) {
343 int error;
344
345 /* Open lock file. */
346 fd = open_lockfile(lock_name);
347 if (fd < 0) {
348 return -fd;
349 }
350
351 /* Try to lock it. This will block (if 'timeout' > 0). */
352 error = try_lock(fd, timeout > 0);
353 time_refresh();
354 elapsed = time_msec() - start;
355 if (!error) {
356 /* Success! */
357 break;
358 }
359
360 /* Lock failed. Close the lock file and reopen it on the next
361 * iteration, just in case someone deletes it underneath us (even
362 * though that should not happen). */
363 close(fd);
364 if (error != EINTR) {
365 /* Hard error, give up. */
366 COVERAGE_INC(cfg_lock_error);
367 VLOG_WARN("%s: failed to lock file "
368 "(after %lld ms, with %d-ms timeout): %s",
369 lock_name, elapsed, timeout, strerror(error));
370 return error;
371 }
372
373 /* Probably, the periodic timer set up by time_init() woke up us. Just
374 * check whether it's time to give up. */
375 if (timeout != INT_MAX && elapsed >= timeout) {
376 COVERAGE_INC(cfg_lock_timeout);
377 VLOG_WARN("%s: giving up on lock file after %lld ms",
378 lock_name, elapsed);
379 return ETIMEDOUT;
380 }
381 COVERAGE_INC(cfg_lock_retry);
382 }
383 if (elapsed) {
384 VLOG_WARN("%s: waited %lld ms for lock file", lock_name, elapsed);
385 }
386 lock_fd = fd;
387
388 cfg_read();
389
390 if (cookie) {
391 cfg_get_cookie(curr_cookie);
392
393 if (memcmp(curr_cookie, cookie, sizeof *curr_cookie)) {
394 /* Configuration has changed, so reject. */
395 cfg_unlock();
396 return EINVAL;
397 }
398 }
399
400 return 0;
401 }
402
403 static int
404 do_write_config(const void *data, size_t len)
405 {
406 FILE *file;
407 int error;
408
409 file = fopen(tmp_name, "w");
410 if (file == NULL) {
411 VLOG_WARN("could not open %s for writing: %s",
412 tmp_name, strerror(errno));
413 return errno;
414 }
415
416 fwrite(data, 1, len, file);
417
418 /* This is essentially equivalent to:
419 * error = ferror(file) || fflush(file) || fclose(file);
420 * but it doesn't short-circuit, so that it always closes 'file'. */
421 error = ferror(file);
422 error = fflush(file) || error;
423 error = fclose(file) || error;
424 if (error) {
425 VLOG_WARN("problem writing to %s: %s", tmp_name, strerror(errno));
426 return errno;
427 }
428
429 if (rename(tmp_name, cfg_name) < 0) {
430 VLOG_WARN("could not rename %s to %s: %s",
431 tmp_name, cfg_name, strerror(errno));
432 return errno;
433 }
434
435 dirty = false;
436
437 return 0;
438 }
439
440 /* Write the current configuration into the configuration file. Returns 0 if
441 * successful, otherwise a negative errno value. */
442 int
443 cfg_write(void)
444 {
445 char *content;
446 int retval;
447
448 svec_sort(&cfg);
449 content = (cfg.n
450 ? svec_join(&cfg, "\n", "\n")
451 : xstrdup("# This file intentionally left blank.\n"));
452 retval = do_write_config(content, strlen(content));
453 free(content);
454
455 return retval;
456 }
457
458 int
459 cfg_write_data(uint8_t *data, size_t len)
460 {
461 int retval = do_write_config(data, len);
462 if (!retval) {
463 cfg_read();
464 }
465 return retval;
466 }
467
468 /* Returns true if the configuration has changed since the last time it was
469 * read or written. */
470 bool
471 cfg_is_dirty(void)
472 {
473 return dirty;
474 }
475
476 void
477 cfg_buf_put(struct ofpbuf *buffer)
478 {
479 int i;
480
481 for (i = 0; i < cfg.n; i++) {
482 ofpbuf_put(buffer, cfg.names[i], strlen(cfg.names[i]));
483 ofpbuf_put(buffer, "\n", 1);
484 }
485 }
486
487 /* Formats the printf()-style format string in the parameter 'format', which
488 * must be the function's last parameter, into string variable 'dst'. The
489 * function is responsible for freeing 'dst'. */
490 #define FORMAT_KEY(FORMAT, DST) \
491 do { \
492 va_list args__; \
493 va_start(args__, FORMAT); \
494 (DST) = xvasprintf(FORMAT, args__); \
495 va_end(args__); \
496 } while (0)
497
498 /* Returns true if the configuration includes a key named 'key'. */
499 bool
500 cfg_has(const char *key_, ...)
501 {
502 char *key;
503 bool retval;
504
505 FORMAT_KEY(key_, key);
506 retval = find_key(key) != NULL;
507 free(key);
508 return retval;
509 }
510
511 bool
512 cfg_is_valid(enum cfg_flags flags, const char *key_, ...)
513 {
514 char *key, **first, **last, **p;
515 size_t n;
516 bool retval;
517
518 FORMAT_KEY(key_, key);
519 first = find_key_le(key);
520 last = find_key_ge(key);
521 n = last - first;
522 retval = ((!(flags & CFG_REQUIRED) || n)
523 && (!(flags & CFG_MULTIPLE) || n <= 1));
524 for (p = first; retval && p < last; p++) {
525 retval = is_type(strchr(*p, '=') + 1, flags);
526 }
527 free(key);
528 return retval;
529 }
530
531 /* Returns true if the configuration includes at least one key whose name
532 * begins with 'section' followed by a dot. */
533 bool
534 cfg_has_section(const char *section_, ...)
535 {
536 struct ds section;
537 bool retval = false;
538 va_list args;
539 char **p;
540
541 ds_init(&section);
542 va_start(args, section_);
543 ds_put_format_valist(&section, section_, args);
544 ds_put_char(&section, '.');
545 va_end(args);
546
547 for (p = cfg.names; *p; p++) { /* XXX this is inefficient */
548 if (!strncmp(section.string, *p, section.length)) {
549 retval = true;
550 break;
551 }
552 }
553
554 ds_destroy(&section);
555 return retval;
556 }
557
558 /* Returns the number of values for the given 'key'. The return value is 0 if
559 * no values exist for 'key'. */
560 int
561 cfg_count(const char *key_, ...)
562 {
563 char *key;
564 int retval;
565
566 FORMAT_KEY(key_, key);
567 retval = find_key_ge(key) - find_key_le(key);
568 free(key);
569 return retval;
570 }
571
572 /* Fills 'svec' with all of the immediate subsections of 'section'. For
573 * example, if 'section' is "bridge" and keys bridge.a, bridge.b, bridge.b.c,
574 * and bridge.c.x.y.z exist, then 'svec' would be initialized to a, b, and
575 * c. The caller must first initialize 'svec'. */
576 void
577 cfg_get_subsections(struct svec *svec, const char *section_, ...)
578 {
579 struct ds section;
580 va_list args;
581 char **p;
582
583 ds_init(&section);
584 va_start(args, section_);
585 ds_put_format_valist(&section, section_, args);
586 ds_put_char(&section, '.');
587 va_end(args);
588
589 svec_clear(svec);
590 for (p = cfg.names; *p; p++) { /* XXX this is inefficient */
591 if (!strncmp(section.string, *p, section.length)) {
592 const char *ss = *p + section.length;
593 size_t ss_len = strcspn(ss, ".=");
594 svec_add_nocopy(svec, xmemdup0(ss, ss_len));
595 }
596 }
597 svec_unique(svec);
598 ds_destroy(&section);
599 }
600
601 void
602 cfg_add_entry(const char *entry_, ...)
603 {
604 char *entry;
605
606 FORMAT_KEY(entry_, entry);
607 svec_add_nocopy(&cfg, entry);
608 svec_sort(&cfg);
609 svec_terminate(&cfg);
610 dirty = true;
611 }
612
613 void
614 cfg_del_entry(const char *entry_, ...)
615 {
616 char *entry;
617
618 FORMAT_KEY(entry_, entry);
619 svec_del(&cfg, entry);
620 svec_terminate(&cfg);
621 free(entry);
622 dirty = true;
623 }
624
625 void
626 cfg_del_section(const char *section_, ...)
627 {
628 struct ds section;
629 va_list args;
630 char **p;
631
632 ds_init(&section);
633 va_start(args, section_);
634 ds_put_format_valist(&section, section_, args);
635 ds_put_char(&section, '.');
636 va_end(args);
637
638 for (p = cfg.names; *p; p++) {
639 if (!strncmp(section.string, *p, section.length)) {
640 free(*p);
641 *p = NULL;
642 }
643 }
644 svec_compact(&cfg);
645 svec_terminate(&cfg);
646
647 ds_destroy(&section);
648 dirty = true;
649 }
650
651 void
652 cfg_del_match(const char *pattern_, ...)
653 {
654 bool matched = false;
655 char *pattern;
656 char **p;
657
658 FORMAT_KEY(pattern_, pattern);
659
660 for (p = cfg.names; *p; p++) {
661 if (!fnmatch(pattern, *p, 0)) {
662 free(*p);
663 *p = NULL;
664 matched = true;
665 }
666 }
667 if (matched) {
668 svec_compact(&cfg);
669 svec_terminate(&cfg);
670 dirty = true;
671 }
672
673 free(pattern);
674 }
675
676 /* Fills 'svec' with all of the key-value pairs that have sections that
677 * begin with 'section'. The caller must first initialize 'svec'. */
678 void
679 cfg_get_section(struct svec *svec, const char *section_, ...)
680 {
681 struct ds section;
682 va_list args;
683 char **p;
684
685 ds_init(&section);
686 va_start(args, section_);
687 ds_put_format_valist(&section, section_, args);
688 ds_put_char(&section, '.');
689 va_end(args);
690
691 for (p = cfg.names; *p; p++) { /* XXX this is inefficient */
692 if (!strncmp(section.string, *p, section.length)) {
693 svec_add(svec, *p);
694 }
695 }
696 ds_destroy(&section);
697 }
698
699 /* Returns the value numbered 'idx' of 'key'. Returns a null pointer if 'idx'
700 * is greater than or equal to cfg_count(key). The caller must not modify or
701 * free the returned string or retain its value beyond the next call to
702 * cfg_read(). */
703 const char *
704 cfg_get_string(int idx, const char *key_, ...)
705 {
706 const char *retval;
707 char *key;
708
709 FORMAT_KEY(key_, key);
710 retval = get_nth_value(idx, key);
711 free(key);
712 return retval;
713 }
714
715 /* Returns the value numbered 'idx' of 'key'. Returns a null pointer if 'idx'
716 * is greater than or equal to cfg_count(key) or if the value 'idx' of 'key' is
717 * not a valid key. The caller must not modify or free the returned string or
718 * retain its value beyond the next call to cfg_read(). */
719 const char *
720 cfg_get_key(int idx, const char *key_, ...)
721 {
722 const char *value, *retval;
723 char *key;
724
725 FORMAT_KEY(key_, key);
726 value = get_nth_value(idx, key);
727 retval = value && is_key(value) ? value : NULL;
728 free(key);
729 return retval;
730 }
731
732 /* Returns the value numbered 'idx' of 'key', converted to an integer. Returns
733 * 0 if 'idx' is greater than or equal to cfg_count(key) or if the value 'idx'
734 * of 'key' is not a valid integer. */
735 int
736 cfg_get_int(int idx, const char *key_, ...)
737 {
738 const char *value;
739 int retval;
740 char *key;
741
742 FORMAT_KEY(key_, key);
743 value = get_nth_value(idx, key);
744 retval = value && is_int(value) ? atoi(value) : 0;
745 free(key);
746 return retval;
747 }
748
749 /* Returns the value numbered 'idx' of 'key', converted to a boolean value.
750 * Returns false if 'idx' is greater than or equal to cfg_count(key) or if the
751 * value 'idx' of 'key' is not a valid boolean. */
752 bool
753 cfg_get_bool(int idx, const char *key_, ...)
754 {
755 const char *value;
756 bool retval;
757 char *key;
758
759 FORMAT_KEY(key_, key);
760 value = get_nth_value(idx, key);
761 retval = value && is_bool(value) ? !strcmp(value, "true") : false;
762 free(key);
763 return retval;
764 }
765
766 /* Returns the value numbered 'idx' of 'key', converted to an IP address in
767 * network byte order. Returns 0 if 'idx' is greater than or equal to
768 * cfg_count(key) or if the value 'idx' of 'key' is not a valid IP address (as
769 * determined by inet_aton()). */
770 uint32_t
771 cfg_get_ip(int idx, const char *key_, ...)
772 {
773 struct in_addr addr;
774 const char *value;
775 char *key;
776
777 FORMAT_KEY(key_, key);
778 value = get_nth_value(idx, key);
779 if (!value || !inet_aton(value, &addr)) {
780 addr.s_addr = htonl(0);
781 }
782 free(key);
783 return addr.s_addr;
784 }
785
786 /* Returns the value numbered 'idx' of 'key', converted to an MAC address in
787 * host byte order. Returns 0 if 'idx' is greater than or equal to
788 * cfg_count(key) or if the value 'idx' of 'key' is not a valid MAC address in
789 * the format "##:##:##:##:##:##". */
790 uint64_t
791 cfg_get_mac(int idx, const char *key_, ...)
792 {
793 uint8_t mac[ETH_ADDR_LEN];
794 const char *value;
795 char *key;
796
797 FORMAT_KEY(key_, key);
798 value = get_nth_value(idx, key);
799 if (!value || !parse_mac(value, mac)) {
800 memset(mac, 0, sizeof mac);
801 }
802 free(key);
803 return eth_addr_to_uint64(mac);
804 }
805
806 /* Returns the value numbered 'idx' of 'key', parsed as an datapath ID.
807 * Returns 0 if 'idx' is greater than or equal to cfg_count(key) or if the
808 * value 'idx' of 'key' is not a valid datapath ID consisting of exactly 12
809 * hexadecimal digits. */
810 uint64_t
811 cfg_get_dpid(int idx, const char *key_, ...)
812 {
813 uint64_t dpid;
814 const char *value;
815 char *key;
816
817 FORMAT_KEY(key_, key);
818 value = get_nth_value(idx, key);
819 if (!value || !parse_dpid(value, &dpid)) {
820 dpid = 0;
821 }
822 free(key);
823 return dpid;
824 }
825
826 /* Returns the value numbered 'idx' of 'key', converted to an integer. Returns
827 * -1 if 'idx' is greater than or equal to cfg_count(key) or if the value 'idx'
828 * of 'key' is not a valid integer between 0 and 4095. */
829 int
830 cfg_get_vlan(int idx, const char *key_, ...)
831 {
832 const char *value;
833 int retval;
834 char *key;
835
836 FORMAT_KEY(key_, key);
837 value = get_nth_value(idx, key);
838 if (value && is_int(value)) {
839 retval = atoi(value);
840 if (retval < 0 || retval > 4095) {
841 retval = -1;
842 }
843 } else {
844 retval = -1;
845 }
846 free(key);
847 return retval;
848 }
849
850 /* Fills 'svec' with all of the string values of 'key'. The caller must
851 * first initialize 'svec'. */
852 void
853 cfg_get_all_strings(struct svec *svec, const char *key_, ...)
854 {
855 char **p, **q;
856 char *key;
857
858 FORMAT_KEY(key_, key);
859 svec_clear(svec);
860 for (p = find_key_le(key), q = find_key_ge(key); p < q; p++) {
861 svec_add(svec, extract_value(*p));
862 }
863 free(key);
864 }
865
866 /* Fills 'svec' with all of the values of 'key' that are valid keys.
867 * Values of 'key' that are not valid keys are omitted. The caller
868 * must first initialize 'svec'. */
869 void
870 cfg_get_all_keys(struct svec *svec, const char *key_, ...)
871 {
872 char **p, **q;
873 char *key;
874
875 FORMAT_KEY(key_, key);
876 svec_clear(svec);
877 for (p = find_key_le(key), q = find_key_ge(key); p < q; p++) {
878 const char *value = extract_value(*p);
879 if (is_key(value)) {
880 svec_add(svec, value);
881 }
882 }
883 free(key);
884 }
885 \f
886 static bool
887 has_double_dot(const char *key, size_t len)
888 {
889 if (len >= 2) {
890 size_t i;
891
892 for (i = 0; i < len - 1; i++) {
893 if (key[i] == '.' && key[i + 1] == '.') {
894 return true;
895 }
896 }
897 }
898 return false;
899 }
900
901 static bool
902 is_valid_key(const char *key, size_t len,
903 const char *file_name, int line_number, const char *id)
904 {
905 if (!len) {
906 VLOG_ERR("%s:%d: missing %s name", file_name, line_number, id);
907 return false;
908 } else if (key[0] == '.') {
909 VLOG_ERR("%s:%d: %s name \"%.*s\" begins with invalid character '.'",
910 file_name, line_number, id, (int) len, key);
911 return false;
912 } else if (key[len - 1] == '.') {
913 VLOG_ERR("%s:%d: %s name \"%.*s\" ends with invalid character '.'",
914 file_name, line_number, id, (int) len, key);
915 return false;
916 } else if (has_double_dot(key, len)) {
917 VLOG_ERR("%s:%d: %s name \"%.*s\" contains '..', which is not allowed",
918 file_name, line_number, id, (int) len, key);
919 return false;
920 } else {
921 return true;
922 }
923 }
924
925 static char *
926 parse_section(const char *file_name, int line_number, const char *s)
927 {
928 struct ds section;
929 size_t len;
930
931 ds_init(&section);
932
933 /* Skip [ and any white space. */
934 s++;
935 s += strspn(s, CC_SPACE);
936
937 /* Obtain the section name. */
938 len = strspn(s, CC_KEY);
939 if (!is_valid_key(s, len, file_name, line_number, "section")) {
940 goto error;
941 }
942 ds_put_buffer(&section, s, len);
943 s += len;
944
945 /* Obtain the subsection name, if any. */
946 s += strspn(s, CC_SPACE);
947 if (*s == '"') {
948 s++;
949 len = strspn(s, CC_KEY);
950 if (!is_valid_key(s, len, file_name, line_number, "subsection")) {
951 goto error;
952 }
953 ds_put_char(&section, '.');
954 ds_put_buffer(&section, s, len);
955 s += len;
956 if (*s != '"') {
957 VLOG_ERR("%s:%d: missing '\"' following subsection name",
958 file_name, line_number);
959 goto error;
960 }
961 s++;
962 s += strspn(s, CC_SPACE);
963 }
964
965 /* Check for ]. */
966 if (*s != ']') {
967 VLOG_ERR("%s:%d: missing ']' following section name",
968 file_name, line_number);
969 goto error;
970 }
971 s++;
972 s += strspn(s, CC_SPACE);
973 if (*s != '\0') {
974 VLOG_ERR("%s:%d: trailing garbage following ']'",
975 file_name, line_number);
976 goto error;
977 }
978
979 return ds_cstr(&section);
980
981 error:
982 ds_destroy(&section);
983 return NULL;
984 }
985
986 static void
987 parse_setting(const char *file_name, int line_number, const char *section,
988 const char *s)
989 {
990 struct ds key = DS_EMPTY_INITIALIZER;
991 struct ds value = DS_EMPTY_INITIALIZER;
992 size_t len;
993
994 if (section) {
995 ds_put_format(&key, "%s.", section);
996 }
997
998 /* Obtain the key. */
999 len = strspn(s, CC_KEY);
1000 if (!len) {
1001 VLOG_ERR("%s:%d: missing key name", file_name, line_number);
1002 goto done;
1003 }
1004 if (!is_valid_key(s, len, file_name, line_number, "key")) {
1005 goto done;
1006 }
1007 ds_put_buffer(&key, s, len);
1008 s += len;
1009
1010 /* Skip the '='. */
1011 s += strspn(s, CC_SPACE);
1012 if (*s != '=') {
1013 VLOG_ERR("%s:%d: missing '=' following key", file_name, line_number);
1014 goto done;
1015 }
1016 s++;
1017 s += strspn(s, CC_SPACE);
1018
1019 /* Obtain the value. */
1020 ds_put_cstr(&value, s);
1021 while (value.length > 0 && strchr(CC_SPACE, ds_last(&value))) {
1022 value.length--;
1023 }
1024
1025 /* Add the setting. */
1026 svec_add_nocopy(&cfg, xasprintf("%s=%s", ds_cstr(&key), ds_cstr(&value)));
1027
1028 done:
1029 ds_destroy(&key);
1030 ds_destroy(&value);
1031 }
1032
1033 static int
1034 compare_key(const char *a, const char *b)
1035 {
1036 for (;;) {
1037 int ac = *a == '\0' || *a == '=' ? INT_MAX : *a;
1038 int bc = *b == '\0' || *b == '=' ? INT_MAX : *b;
1039 if (ac != bc) {
1040 return ac < bc ? -1 : 1;
1041 } else if (ac == INT_MAX) {
1042 return 0;
1043 }
1044 a++;
1045 b++;
1046 }
1047 }
1048
1049 /* Returns the address of the greatest configuration string with a key less
1050 * than or equal to 'key'. Returns the address of the null terminator if all
1051 * configuration strings are greater than 'key'. */
1052 static char **
1053 find_key_le(const char *key)
1054 {
1055 int low = 0;
1056 int len = cfg.n;
1057 while (len > 0) {
1058 int half = len >> 1;
1059 int middle = low + half;
1060 if (compare_key(cfg.names[middle], key) < 0) {
1061 low = middle + 1;
1062 len -= half + 1;
1063 } else {
1064 len = half;
1065 }
1066 }
1067 return &cfg.names[low];
1068 }
1069
1070 /* Returns the address of the least configuration string with a key greater
1071 * than or equal to 'key'. Returns the address of the null terminator if all
1072 * configuration strings are less than 'key'. */
1073 static char **
1074 find_key_ge(const char *key)
1075 {
1076 int low = 0;
1077 int len = cfg.n;
1078 while (len > 0) {
1079 int half = len >> 1;
1080 int middle = low + half;
1081 if (compare_key(cfg.names[middle], key) > 0) {
1082 len = half;
1083 } else {
1084 low = middle + 1;
1085 len -= half + 1;
1086 }
1087 }
1088 return &cfg.names[low];
1089 }
1090
1091 static char *
1092 find_key(const char *key)
1093 {
1094 char **p = find_key_le(key);
1095 return p < &cfg.names[cfg.n] && !compare_key(*p, key) ? *p : NULL;
1096 }
1097
1098 static bool
1099 parse_mac(const char *s, uint8_t mac[6])
1100 {
1101 return sscanf(s, "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8,
1102 &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6;
1103 }
1104
1105 static bool
1106 parse_dpid(const char *s, uint64_t *dpid)
1107 {
1108 if (strlen(s) == 12 && strspn(s, "0123456789abcdefABCDEF") == 12) {
1109 *dpid = strtoll(s, NULL, 16);
1110 return true;
1111 } else {
1112 return false;
1113 }
1114 }
1115
1116 static bool
1117 is_key(const char *s)
1118 {
1119 /* XXX needs to check the same things as is_valid_key() too. */
1120 return *s && s[strspn(s, CC_KEY)] == '\0';
1121 }
1122
1123 static bool
1124 is_int(const char *s)
1125 {
1126 return *s && s[strspn(s, CC_DIGIT)] == '\0';
1127 }
1128
1129 static bool
1130 is_bool(const char *s)
1131 {
1132 return !strcmp(s, "true") || !strcmp(s, "false");
1133 }
1134
1135 static const char *
1136 extract_value(const char *key)
1137 {
1138 const char *p = strchr(key, '=');
1139 return p ? p + 1 : NULL;
1140 }
1141
1142 static const char *
1143 get_nth_value(int idx, const char *key)
1144 {
1145 char **p = find_key_le(key);
1146 char **q = find_key_ge(key);
1147 return idx < q - p ? extract_value(p[idx]) : NULL;
1148 }
1149
1150 static bool
1151 is_type(const char *s, enum cfg_flags flags)
1152 {
1153 uint8_t mac[ETH_ADDR_LEN];
1154 struct in_addr addr;
1155 uint64_t dpid;
1156
1157 return (flags & CFG_STRING
1158 || (flags & CFG_KEY && is_key(s))
1159 || (flags & CFG_INT && is_int(s))
1160 || (flags & CFG_BOOL && is_bool(s))
1161 || (flags & CFG_IP && inet_aton(s, &addr))
1162 || (flags & CFG_MAC && parse_mac(s, mac))
1163 || (flags & CFG_DPID && parse_dpid(s, &dpid)));
1164 }