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