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