433d7a0fac56ba6cb47e402fe573ed909941e8ed
[sliver-openvswitch.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;
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
343     time_refresh();
344     start = time_msec();
345     for (;;) {
346         int error;
347
348         /* Open lock file. */
349         fd = open_lockfile(lock_name);
350         if (fd < 0) {
351             return -fd;
352         }
353
354         /* Try to lock it.  This will block (if 'timeout' > 0). */
355         error = try_lock(fd, timeout > 0);
356         time_refresh();
357         elapsed = time_msec() - start;
358         if (!error) {
359             /* Success! */
360             break;
361         }
362
363         /* Lock failed.  Close the lock file and reopen it on the next
364          * iteration, just in case someone deletes it underneath us (even
365          * though that should not happen). */
366         close(fd);
367         if (error != EINTR) {
368             /* Hard error, give up. */
369             COVERAGE_INC(cfg_lock_error);
370             VLOG_WARN("%s: failed to lock file "
371                       "(after %lld ms, with %d-ms timeout): %s",
372                       lock_name, elapsed, timeout, strerror(error));
373             return error;
374         }
375
376         /* Probably, the periodic timer set up by time_init() woke up us.  Just
377          * check whether it's time to give up. */
378         if (timeout != INT_MAX && elapsed >= timeout) {
379             COVERAGE_INC(cfg_lock_timeout);
380             VLOG_WARN("%s: giving up on lock file after %lld ms",
381                       lock_name, elapsed);
382             return ETIMEDOUT;
383         }
384         COVERAGE_INC(cfg_lock_retry);
385     }
386     if (elapsed) {
387         VLOG_WARN("%s: waited %lld ms for lock file", lock_name, elapsed);
388     }
389     lock_fd = fd;
390
391     cfg_read();
392
393     if (cookie) {
394         cfg_get_cookie(curr_cookie);
395
396         if (memcmp(curr_cookie, cookie, sizeof *curr_cookie)) {
397             /* Configuration has changed, so reject. */
398             cfg_unlock();
399             return EINVAL;
400         }
401     }
402
403     return 0;
404 }
405
406 static int
407 do_write_config(const void *data, size_t len)
408 {
409     FILE *file;
410     int error;
411
412     file = fopen(tmp_name, "w");
413     if (file == NULL) {
414         VLOG_WARN("could not open %s for writing: %s",
415                   tmp_name, strerror(errno));
416         return errno;
417     }
418
419     fwrite(data, 1, len, file);
420
421     /* This is essentially equivalent to:
422      *       error = ferror(file) || fflush(file) || fclose(file);
423      * but it doesn't short-circuit, so that it always closes 'file'. */
424     error = ferror(file);
425     error = fflush(file) || error;
426     error = fclose(file) || error;
427     if (error) {
428         VLOG_WARN("problem writing to %s: %s", tmp_name, strerror(errno));
429         return errno;
430     }
431
432     if (rename(tmp_name, cfg_name) < 0) {
433         VLOG_WARN("could not rename %s to %s: %s",
434                   tmp_name, cfg_name, strerror(errno));
435         return errno;
436     }
437
438     dirty = false;
439
440     return 0;
441 }
442
443 /* Write the current configuration into the configuration file.  Returns 0 if
444  * successful, otherwise a negative errno value. */
445 int
446 cfg_write(void)
447 {
448     char *content;
449     int retval;
450
451     svec_sort(&cfg);
452     content = (cfg.n
453                ? svec_join(&cfg, "\n", "\n")
454                : xstrdup("# This file intentionally left blank.\n"));
455     retval = do_write_config(content, strlen(content));
456     free(content);
457
458     return retval;
459 }
460
461 int
462 cfg_write_data(uint8_t *data, size_t len)
463 {
464     int retval = do_write_config(data, len);
465     if (!retval) {
466         cfg_read();
467     }
468     return retval;
469 }
470
471 /* Returns true if the configuration has changed since the last time it was
472  * read or written. */
473 bool
474 cfg_is_dirty(void)
475 {
476     return dirty;
477 }
478
479 void
480 cfg_buf_put(struct ofpbuf *buffer)
481 {
482     int i;
483
484     for (i = 0; i < cfg.n; i++) {
485         ofpbuf_put(buffer, cfg.names[i], strlen(cfg.names[i]));
486         ofpbuf_put(buffer, "\n", 1);
487     }
488 }
489
490 /* Formats the printf()-style format string in the parameter 'format', which
491  * must be the function's last parameter, into string variable 'dst'.  The
492  * function is responsible for freeing 'dst'. */
493 #define FORMAT_KEY(FORMAT, DST)                 \
494     do {                                        \
495       va_list args__;                           \
496       va_start(args__, FORMAT);                 \
497       (DST) = xvasprintf(FORMAT, args__);       \
498       va_end(args__);                           \
499     } while (0)
500
501 /* Returns true if the configuration includes a key named 'key'. */
502 bool
503 cfg_has(const char *key_, ...)
504 {
505     char *key;
506     bool retval;
507
508     FORMAT_KEY(key_, key);
509     retval = find_key(key) != NULL;
510     free(key);
511     return retval;
512 }
513
514 bool
515 cfg_is_valid(enum cfg_flags flags, const char *key_, ...)
516 {
517     char *key, **first, **last, **p;
518     size_t n;
519     bool retval;
520
521     FORMAT_KEY(key_, key);
522     first = find_key_le(key);
523     last = find_key_ge(key);
524     n = last - first;
525     retval = ((!(flags & CFG_REQUIRED) || n)
526               && (!(flags & CFG_MULTIPLE) || n <= 1));
527     for (p = first; retval && p < last; p++) {
528         retval = is_type(strchr(*p, '=') + 1, flags);
529     }
530     free(key);
531     return retval;
532 }
533
534 /* Returns true if the configuration includes at least one key whose name
535  * begins with 'section' followed by a dot. */
536 bool
537 cfg_has_section(const char *section_, ...)
538 {
539     struct ds section;
540     bool retval = false;
541     va_list args;
542     char **p;
543
544     ds_init(&section);
545     va_start(args, section_);
546     ds_put_format_valist(&section, section_, args);
547     ds_put_char(&section, '.');
548     va_end(args);
549
550     for (p = cfg.names; *p; p++) { /* XXX this is inefficient */
551         if (!strncmp(section.string, *p, section.length)) {
552             retval = true;
553             break;
554         }
555     }
556
557     ds_destroy(&section);
558     return retval;
559 }
560
561 /* Returns the number of values for the given 'key'.  The return value is 0 if
562  * no values exist for 'key'. */
563 int
564 cfg_count(const char *key_, ...)
565 {
566     char *key;
567     int retval;
568
569     FORMAT_KEY(key_, key);
570     retval = find_key_ge(key) - find_key_le(key);
571     free(key);
572     return retval;
573 }
574
575 /* Fills 'svec' with all of the immediate subsections of 'section'.  For
576  * example, if 'section' is "bridge" and keys bridge.a, bridge.b, bridge.b.c,
577  * and bridge.c.x.y.z exist, then 'svec' would be initialized to a, b, and
578  * c.  The caller must first initialize 'svec'. */
579 void
580 cfg_get_subsections(struct svec *svec, const char *section_, ...)
581 {
582     struct ds section;
583     va_list args;
584     char **p;
585
586     ds_init(&section);
587     va_start(args, section_);
588     ds_put_format_valist(&section, section_, args);
589     ds_put_char(&section, '.');
590     va_end(args);
591
592     svec_clear(svec);
593     for (p = cfg.names; *p; p++) { /* XXX this is inefficient */
594         if (!strncmp(section.string, *p, section.length)) {
595             const char *ss = *p + section.length;
596             size_t ss_len = strcspn(ss, ".=");
597             svec_add_nocopy(svec, xmemdup0(ss, ss_len));
598         }
599     }
600     svec_unique(svec);
601     ds_destroy(&section);
602 }
603
604 void
605 cfg_add_entry(const char *entry_, ...)
606 {
607     char *entry;
608
609     FORMAT_KEY(entry_, entry);
610     svec_add_nocopy(&cfg, entry);
611     svec_sort(&cfg);
612     svec_terminate(&cfg);
613     dirty = true;
614 }
615
616 void
617 cfg_del_entry(const char *entry_, ...)
618 {
619     char *entry;
620
621     FORMAT_KEY(entry_, entry);
622     svec_del(&cfg, entry);
623     svec_terminate(&cfg);
624     free(entry);
625     dirty = true;
626 }
627
628 void
629 cfg_del_section(const char *section_, ...)
630 {
631     struct ds section;
632     va_list args;
633     char **p;
634
635     ds_init(&section);
636     va_start(args, section_);
637     ds_put_format_valist(&section, section_, args);
638     ds_put_char(&section, '.');
639     va_end(args);
640
641     for (p = cfg.names; *p; p++) {
642         if (!strncmp(section.string, *p, section.length)) {
643             free(*p);
644             *p = NULL;
645         }
646     }
647     svec_compact(&cfg);
648     svec_terminate(&cfg);
649
650     ds_destroy(&section);
651     dirty = true;
652 }
653
654 void
655 cfg_del_match(const char *pattern_, ...)
656 {
657     bool matched = false;
658     char *pattern;
659     char **p;
660
661     FORMAT_KEY(pattern_, pattern);
662
663     for (p = cfg.names; *p; p++) {
664         if (!fnmatch(pattern, *p, 0)) {
665             free(*p);
666             *p = NULL;
667             matched = true;
668         }
669     }
670     if (matched) {
671         svec_compact(&cfg);
672         svec_terminate(&cfg);
673         dirty = true;
674     }
675
676     free(pattern);
677 }
678
679 /* Fills 'svec' with all of the key-value pairs that match shell glob pattern
680  * 'pattern'.  The caller must first initialize 'svec'. */
681 void
682 cfg_get_matches(struct svec *svec, const char *pattern_, ...)
683 {
684     char *pattern;
685     char **p;
686
687     FORMAT_KEY(pattern_, pattern);
688
689     for (p = cfg.names; *p; p++) {
690         if (!fnmatch(pattern, *p, 0)) {
691             svec_add(svec, *p);
692         }
693     }
694
695     free(pattern);
696 }
697
698 /* Fills 'svec' with all of the key-value pairs that have sections that
699  * begin with 'section'.  The caller must first initialize 'svec'. */
700 void
701 cfg_get_section(struct svec *svec, const char *section_, ...)
702 {
703     struct ds section;
704     va_list args;
705     char **p;
706
707     ds_init(&section);
708     va_start(args, section_);
709     ds_put_format_valist(&section, section_, args);
710     ds_put_char(&section, '.');
711     va_end(args);
712
713     for (p = cfg.names; *p; p++) { /* XXX this is inefficient */
714         if (!strncmp(section.string, *p, section.length)) {
715             svec_add(svec, *p);
716         }
717     }
718     ds_destroy(&section);
719 }
720
721 /* Returns the value numbered 'idx' of 'key'.  Returns a null pointer if 'idx'
722  * is greater than or equal to cfg_count(key).  The caller must not modify or
723  * free the returned string or retain its value beyond the next call to
724  * cfg_read(). */
725 const char *
726 cfg_get_string(int idx, const char *key_, ...)
727 {
728     const char *retval;
729     char *key;
730
731     FORMAT_KEY(key_, key);
732     retval = get_nth_value(idx, key);
733     free(key);
734     return retval;
735 }
736
737 /* Returns the value numbered 'idx' of 'key'.  Returns a null pointer if 'idx'
738  * is greater than or equal to cfg_count(key) or if the value 'idx' of 'key' is
739  * not a valid key.  The caller must not modify or free the returned string or
740  * retain its value beyond the next call to cfg_read(). */
741 const char *
742 cfg_get_key(int idx, const char *key_, ...)
743 {
744     const char *value, *retval;
745     char *key;
746
747     FORMAT_KEY(key_, key);
748     value = get_nth_value(idx, key);
749     retval = value && is_key(value) ? value : NULL;
750     free(key);
751     return retval;
752 }
753
754 /* Returns the value numbered 'idx' of 'key', converted to an integer.  Returns
755  * 0 if 'idx' is greater than or equal to cfg_count(key) or if the value 'idx'
756  * of 'key' is not a valid integer.  */
757 int
758 cfg_get_int(int idx, const char *key_, ...)
759 {
760     const char *value;
761     int retval;
762     char *key;
763
764     FORMAT_KEY(key_, key);
765     value = get_nth_value(idx, key);
766     retval = value && is_int(value) ? atoi(value) : 0;
767     free(key);
768     return retval;
769 }
770
771 /* Returns the value numbered 'idx' of 'key', converted to a boolean value.
772  * Returns false if 'idx' is greater than or equal to cfg_count(key) or if the
773  * value 'idx' of 'key' is not a valid boolean.  */
774 bool
775 cfg_get_bool(int idx, const char *key_, ...)
776 {
777     const char *value;
778     bool retval;
779     char *key;
780
781     FORMAT_KEY(key_, key);
782     value = get_nth_value(idx, key);
783     retval = value && is_bool(value) ? !strcmp(value, "true") : false;
784     free(key);
785     return retval;
786 }
787
788 /* Returns the value numbered 'idx' of 'key', converted to an IP address in
789  * network byte order.  Returns 0 if 'idx' is greater than or equal to
790  * cfg_count(key) or if the value 'idx' of 'key' is not a valid IP address (as
791  * determined by inet_aton()).  */
792 uint32_t
793 cfg_get_ip(int idx, const char *key_, ...)
794 {
795     struct in_addr addr;
796     const char *value;
797     char *key;
798
799     FORMAT_KEY(key_, key);
800     value = get_nth_value(idx, key);
801     if (!value || !inet_aton(value, &addr)) {
802         addr.s_addr = htonl(0);
803     }
804     free(key);
805     return addr.s_addr;
806 }
807
808 /* Returns the value numbered 'idx' of 'key', converted to an MAC address in
809  * host byte order.  Returns 0 if 'idx' is greater than or equal to
810  * cfg_count(key) or if the value 'idx' of 'key' is not a valid MAC address in
811  * the format "##:##:##:##:##:##".  */
812 uint64_t
813 cfg_get_mac(int idx, const char *key_, ...)
814 {
815     uint8_t mac[ETH_ADDR_LEN];
816     const char *value;
817     char *key;
818
819     FORMAT_KEY(key_, key);
820     value = get_nth_value(idx, key);
821     if (!value || !parse_mac(value, mac)) {
822         memset(mac, 0, sizeof mac);
823     }
824     free(key);
825     return eth_addr_to_uint64(mac);
826 }
827
828 /* Returns the value numbered 'idx' of 'key', parsed as an datapath ID.
829  * Returns 0 if 'idx' is greater than or equal to cfg_count(key) or if the
830  * value 'idx' of 'key' is not a valid datapath ID consisting of exactly 12
831  * hexadecimal digits.  */
832 uint64_t
833 cfg_get_dpid(int idx, const char *key_, ...)
834 {
835     uint64_t dpid;
836     const char *value;
837     char *key;
838
839     FORMAT_KEY(key_, key);
840     value = get_nth_value(idx, key);
841     if (!value || !parse_dpid(value, &dpid)) {
842         dpid = 0;
843     }
844     free(key);
845     return dpid;
846 }
847
848 /* Returns the value numbered 'idx' of 'key', converted to an integer.  Returns
849  * -1 if 'idx' is greater than or equal to cfg_count(key) or if the value 'idx'
850  * of 'key' is not a valid integer between 0 and 4095.  */
851 int
852 cfg_get_vlan(int idx, const char *key_, ...)
853 {
854     const char *value;
855     int retval;
856     char *key;
857
858     FORMAT_KEY(key_, key);
859     value = get_nth_value(idx, key);
860     if (value && is_int(value)) {
861         retval = atoi(value);
862         if (retval < 0 || retval > 4095) {
863             retval = -1;
864         }
865     } else {
866         retval = -1;
867     }
868     free(key);
869     return retval;
870 }
871
872 /* Fills 'svec' with all of the string values of 'key'.  The caller must
873  * first initialize 'svec'. */
874 void
875 cfg_get_all_strings(struct svec *svec, const char *key_, ...)
876 {
877     char **p, **q;
878     char *key;
879
880     FORMAT_KEY(key_, key);
881     svec_clear(svec);
882     for (p = find_key_le(key), q = find_key_ge(key); p < q; p++) {
883         svec_add(svec, extract_value(*p));
884     }
885     free(key);
886 }
887
888 /* Fills 'svec' with all of the values of 'key' that are valid keys.
889  * Values of 'key' that are not valid keys are omitted.   The caller 
890  * must first initialize 'svec'. */
891 void
892 cfg_get_all_keys(struct svec *svec, const char *key_, ...)
893 {
894     char **p, **q;
895     char *key;
896
897     FORMAT_KEY(key_, key);
898     svec_clear(svec);
899     for (p = find_key_le(key), q = find_key_ge(key); p < q; p++) {
900         const char *value = extract_value(*p);
901         if (is_key(value)) {
902             svec_add(svec, value);
903         }
904     }
905     free(key);
906 }
907 \f
908 static bool
909 has_double_dot(const char *key, size_t len)
910 {
911     if (len >= 2) {
912         size_t i;
913
914         for (i = 0; i < len - 1; i++) {
915             if (key[i] == '.' && key[i + 1] == '.') {
916                 return true;
917             }
918         }
919     }
920     return false;
921 }
922
923 static bool
924 is_valid_key(const char *key, size_t len,
925                  const char *file_name, int line_number, const char *id)
926 {
927     if (!len) {
928         VLOG_ERR("%s:%d: missing %s name", file_name, line_number, id);
929         return false;
930     } else if (key[0] == '.') {
931         VLOG_ERR("%s:%d: %s name \"%.*s\" begins with invalid character '.'",
932                  file_name, line_number, id, (int) len, key);
933         return false;
934     } else if (key[len - 1] == '.') {
935         VLOG_ERR("%s:%d: %s name \"%.*s\" ends with invalid character '.'",
936                  file_name, line_number, id, (int) len, key);
937         return false;
938     } else if (has_double_dot(key, len)) {
939         VLOG_ERR("%s:%d: %s name \"%.*s\" contains '..', which is not allowed",
940                  file_name, line_number, id, (int) len, key);
941         return false;
942     } else {
943         return true;
944     }
945 }
946
947 static char *
948 parse_section(const char *file_name, int line_number, const char *s)
949 {
950     struct ds section;
951     size_t len;
952
953     ds_init(&section);
954
955     /* Skip [ and any white space. */
956     s++;
957     s += strspn(s, CC_SPACE);
958
959     /* Obtain the section name. */
960     len = strspn(s, CC_KEY);
961     if (!is_valid_key(s, len, file_name, line_number, "section")) {
962         goto error;
963     }
964     ds_put_buffer(&section, s, len);
965     s += len;
966
967     /* Obtain the subsection name, if any. */
968     s += strspn(s, CC_SPACE);
969     if (*s == '"') {
970         s++;
971         len = strspn(s, CC_KEY);
972         if (!is_valid_key(s, len, file_name, line_number, "subsection")) {
973             goto error;
974         }
975         ds_put_char(&section, '.');
976         ds_put_buffer(&section, s, len);
977         s += len;
978         if (*s != '"') {
979             VLOG_ERR("%s:%d: missing '\"' following subsection name",
980                      file_name, line_number);
981             goto error;
982         }
983         s++;
984         s += strspn(s, CC_SPACE);
985     }
986
987     /* Check for ]. */
988     if (*s != ']') {
989         VLOG_ERR("%s:%d: missing ']' following section name",
990                  file_name, line_number);
991         goto error;
992     }
993     s++;
994     s += strspn(s, CC_SPACE);
995     if (*s != '\0') {
996         VLOG_ERR("%s:%d: trailing garbage following ']'",
997                  file_name, line_number);
998         goto error;
999     }
1000
1001     return ds_cstr(&section);
1002
1003 error:
1004     ds_destroy(&section);
1005     return NULL;
1006 }
1007
1008 static void
1009 parse_setting(const char *file_name, int line_number, const char *section,
1010               const char *s)
1011 {
1012     struct ds key = DS_EMPTY_INITIALIZER;
1013     struct ds value = DS_EMPTY_INITIALIZER;
1014     size_t len;
1015
1016     if (section) {
1017         ds_put_format(&key, "%s.", section);
1018     }
1019
1020     /* Obtain the key. */
1021     len = strspn(s, CC_KEY);
1022     if (!len) {
1023         VLOG_ERR("%s:%d: missing key name", file_name, line_number);
1024         goto done;
1025     }
1026     if (!is_valid_key(s, len, file_name, line_number, "key")) {
1027         goto done;
1028     }
1029     ds_put_buffer(&key, s, len);
1030     s += len;
1031
1032     /* Skip the '='. */
1033     s += strspn(s, CC_SPACE);
1034     if (*s != '=') {
1035         VLOG_ERR("%s:%d: missing '=' following key", file_name, line_number);
1036         goto done;
1037     }
1038     s++;
1039     s += strspn(s, CC_SPACE);
1040
1041     /* Obtain the value. */
1042     ds_put_cstr(&value, s);
1043     while (value.length > 0 && strchr(CC_SPACE, ds_last(&value))) {
1044         value.length--;
1045     }
1046
1047     /* Add the setting. */
1048     svec_add_nocopy(&cfg, xasprintf("%s=%s", ds_cstr(&key), ds_cstr(&value)));
1049
1050 done:
1051     ds_destroy(&key);
1052     ds_destroy(&value);
1053 }
1054
1055 static int
1056 compare_key(const char *a, const char *b)
1057 {
1058     for (;;) {
1059         int ac = *a == '\0' || *a == '=' ? INT_MAX : *a;
1060         int bc = *b == '\0' || *b == '=' ? INT_MAX : *b;
1061         if (ac != bc) {
1062             return ac < bc ? -1 : 1;
1063         } else if (ac == INT_MAX) {
1064             return 0;
1065         }
1066         a++;
1067         b++;
1068     }
1069 }
1070
1071 /* Returns the address of the greatest configuration string with a key less
1072  * than or equal to 'key'.  Returns the address of the null terminator if all
1073  * configuration strings are greater than 'key'. */
1074 static char **
1075 find_key_le(const char *key)
1076 {
1077     int low = 0;
1078     int len = cfg.n;
1079     while (len > 0) {
1080         int half = len >> 1;
1081         int middle = low + half;
1082         if (compare_key(cfg.names[middle], key) < 0) {
1083             low = middle + 1;
1084             len -= half + 1;
1085         } else {
1086             len = half;
1087         }
1088     }
1089     return &cfg.names[low];
1090 }
1091
1092 /* Returns the address of the least configuration string with a key greater
1093  * than or equal to 'key'.  Returns the address of the null terminator if all
1094  * configuration strings are less than 'key'. */
1095 static char **
1096 find_key_ge(const char *key)
1097 {
1098     int low = 0;
1099     int len = cfg.n;
1100     while (len > 0) {
1101         int half = len >> 1;
1102         int middle = low + half;
1103         if (compare_key(cfg.names[middle], key) > 0) {
1104             len = half;
1105         } else {
1106             low = middle + 1;
1107             len -= half + 1;
1108         }
1109     }
1110     return &cfg.names[low];
1111 }
1112
1113 static char *
1114 find_key(const char *key)
1115 {
1116     char **p = find_key_le(key);
1117     return p < &cfg.names[cfg.n] && !compare_key(*p, key) ? *p : NULL;
1118 }
1119
1120 static bool
1121 parse_mac(const char *s, uint8_t mac[6])
1122 {
1123     return (sscanf(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
1124             == ETH_ADDR_SCAN_COUNT);
1125 }
1126
1127 static bool
1128 parse_dpid(const char *s, uint64_t *dpid)
1129 {
1130     if (strlen(s) == 12 && strspn(s, "0123456789abcdefABCDEF") == 12) {
1131         *dpid = strtoll(s, NULL, 16);
1132         return true;
1133     } else {
1134         return false;
1135     }
1136 }
1137
1138 static bool
1139 is_key(const char *s)
1140 {
1141     /* XXX needs to check the same things as is_valid_key() too. */
1142     return *s && s[strspn(s, CC_KEY)] == '\0';
1143 }
1144
1145 static bool
1146 is_int(const char *s)
1147 {
1148     return *s && s[strspn(s, CC_DIGIT)] == '\0';
1149 }
1150
1151 static bool
1152 is_bool(const char *s)
1153 {
1154     return !strcmp(s, "true") || !strcmp(s, "false");
1155 }
1156
1157 static const char *
1158 extract_value(const char *key)
1159 {
1160     const char *p = strchr(key, '=');
1161     return p ? p + 1 : NULL;
1162 }
1163
1164 static const char *
1165 get_nth_value(int idx, const char *key)
1166 {
1167     char **p = find_key_le(key);
1168     char **q = find_key_ge(key);
1169     return idx < q - p ? extract_value(p[idx]) : NULL;
1170 }
1171
1172 static bool
1173 is_type(const char *s, enum cfg_flags flags)
1174 {
1175     uint8_t mac[ETH_ADDR_LEN];
1176     struct in_addr addr;
1177     uint64_t dpid;
1178
1179     return (flags & CFG_STRING
1180             || (flags & CFG_KEY && is_key(s))
1181             || (flags & CFG_INT && is_int(s))
1182             || (flags & CFG_BOOL && is_bool(s))
1183             || (flags & CFG_IP && inet_aton(s, &addr))
1184             || (flags & CFG_MAC && parse_mac(s, mac))
1185             || (flags & CFG_DPID && parse_dpid(s, &dpid)));
1186 }