X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=ucimap-example.c;h=18c3c1f05397bcb5137530226f817fbe373e1af9;hp=4309a76d7680503af92a76f3184eed975eb305b5;hb=ec8cbbbe0f20e67cbd3bd471b9ac55ceacaef7b8;hpb=d788264ddc370ffb5f9fe1f451ac6845da0dfda0 diff --git a/ucimap-example.c b/ucimap-example.c index 4309a76..18c3c1f 100644 --- a/ucimap-example.c +++ b/ucimap-example.c @@ -1,6 +1,6 @@ /* * ucimap-example - sample code for the ucimap library - * Copyright (C) 2008 Felix Fietkau + * Copyright (C) 2008-2009 Felix Fietkau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -16,59 +16,219 @@ #include #include #include +#include "list.h" + +struct list_head ifs; struct uci_network { + struct ucimap_section_data map; struct list_head list; + struct list_head alias; const char *name; const char *proto; const char *ifname; - const char *ipaddr; + unsigned char *ipaddr; int test; bool enabled; + struct ucimap_list *aliases; +}; + +struct uci_alias { + struct ucimap_section_data map; + struct list_head list; + + const char *name; + struct uci_network *interface; }; static int -network_init_section(struct uci_map *map, void *section, struct uci_section *s) +network_parse_ip(void *section, struct uci_optmap *om, union ucimap_data *data, const char *str) +{ + unsigned char *target; + int tmp[4]; + int i; + + if (sscanf(str, "%d.%d.%d.%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]) != 4) + return -1; + + target = malloc(4); + if (!target) + return -1; + + data->ptr = target; + for (i = 0; i < 4; i++) + target[i] = (char) tmp[i]; + + return 0; +} + +static int +network_format_ip(void *section, struct uci_optmap *om, union ucimap_data *data, char **str) +{ + static char buf[16]; + unsigned char *ip = (unsigned char *) data->ptr; + + if (ip) { + sprintf(buf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + *str = buf; + } else { + *str = NULL; + } + + return 0; +} + +static void +network_free_ip(void *section, struct uci_optmap *om, void *ptr) +{ + free(ptr); +} + +static int +network_init_interface(struct uci_map *map, void *section, struct uci_section *s) { struct uci_network *net = section; INIT_LIST_HEAD(&net->list); + INIT_LIST_HEAD(&net->alias); net->name = s->e.name; net->test = -1; return 0; } static int -network_add_section(struct uci_map *map, void *section) +network_init_alias(struct uci_map *map, void *section, struct uci_section *s) +{ + struct uci_alias *alias = section; + + INIT_LIST_HEAD(&alias->list); + alias->name = s->e.name; + return 0; +} + +static int +network_add_interface(struct uci_map *map, void *section) { struct uci_network *net = section; - struct uci_network **nptr = map->priv; - *nptr = net; + list_add_tail(&net->list, &ifs); + return 0; } -struct uci_optmap network_smap_options[] = { - OPTMAP_OPTION(UCIMAP_STRING, struct uci_network, proto, .data.s.maxlen = 32), - OPTMAP_OPTION(UCIMAP_STRING, struct uci_network, ifname), - OPTMAP_OPTION(UCIMAP_STRING, struct uci_network, ipaddr), - OPTMAP_OPTION(UCIMAP_BOOL, struct uci_network, enabled), - OPTMAP_OPTION(UCIMAP_INT, struct uci_network, test), +static int +network_add_alias(struct uci_map *map, void *section) +{ + struct uci_alias *a = section; + + if (a->interface) + list_add_tail(&a->list, &a->interface->alias); + + return 0; +} + +static struct ucimap_section_data * +network_allocate(struct uci_map *map, struct uci_sectionmap *sm, struct uci_section *s) +{ + struct uci_network *p = malloc(sizeof(struct uci_network)); + if (!p) + return NULL; + memset(p, 0, sizeof(struct uci_network)); + return &p->map; +} + +struct my_optmap { + struct uci_optmap map; + int test; +}; + +static struct uci_sectionmap network_interface; +static struct uci_sectionmap network_alias; + +static struct my_optmap network_interface_options[] = { + { + .map = { + UCIMAP_OPTION(struct uci_network, proto), + .type = UCIMAP_STRING, + .name = "proto", + .data.s.maxlen = 32, + } + }, + { + .map = { + UCIMAP_OPTION(struct uci_network, ifname), + .type = UCIMAP_STRING, + .name = "ifname" + } + }, + { + .map = { + UCIMAP_OPTION(struct uci_network, ipaddr), + .type = UCIMAP_CUSTOM, + .name = "ipaddr", + .parse = network_parse_ip, + .format = network_format_ip, + .free = network_free_ip, + } + }, + { + .map = { + UCIMAP_OPTION(struct uci_network, enabled), + .type = UCIMAP_BOOL, + .name = "enabled", + } + }, + { + .map = { + UCIMAP_OPTION(struct uci_network, test), + .type = UCIMAP_INT, + .name = "test" + } + }, + { + .map = { + UCIMAP_OPTION(struct uci_network, aliases), + .type = UCIMAP_LIST | UCIMAP_SECTION | UCIMAP_LIST_AUTO, + .data.sm = &network_alias + } + } +}; + +static struct uci_sectionmap network_interface = { + UCIMAP_SECTION(struct uci_network, map), + .type = "interface", + .alloc = network_allocate, + .init = network_init_interface, + .add = network_add_interface, + .options = &network_interface_options[0].map, + .n_options = ARRAY_SIZE(network_interface_options), + .options_size = sizeof(struct my_optmap) }; -struct uci_sectmap network_smap[] = { +static struct uci_optmap network_alias_options[] = { { - .type = "interface", - .options = network_smap_options, - .alloc_len = sizeof(struct uci_network), - .init_section = network_init_section, - .add_section = network_add_section, - .n_options = ARRAY_SIZE(network_smap_options), + UCIMAP_OPTION(struct uci_alias, interface), + .type = UCIMAP_SECTION, + .data.sm = &network_interface } }; -struct uci_map network_map = { +static struct uci_sectionmap network_alias = { + UCIMAP_SECTION(struct uci_alias, map), + .type = "alias", + .options = network_alias_options, + .init = network_init_alias, + .add = network_add_alias, + .n_options = ARRAY_SIZE(network_alias_options), +}; + +static struct uci_sectionmap *network_smap[] = { + &network_interface, + &network_alias, +}; + +static struct uci_map network_map = { .sections = network_smap, .n_sections = ARRAY_SIZE(network_smap), }; @@ -78,38 +238,83 @@ int main(int argc, char **argv) { struct uci_context *ctx; struct uci_package *pkg; - struct uci_network *net = NULL; + struct list_head *p; + struct uci_network *net; + struct uci_alias *alias; + bool set = false; + int i; + INIT_LIST_HEAD(&ifs); ctx = uci_alloc_context(); + if (!ctx) + return -1; ucimap_init(&network_map); + if ((argc >= 2) && !strcmp(argv[1], "-s")) { + uci_set_savedir(ctx, "./test/save"); + set = true; + } + + uci_set_confdir(ctx, "./test/config"); uci_load(ctx, "network", &pkg); - network_map.priv = &net; ucimap_parse(&network_map, pkg); - if (!net) - goto done; + list_for_each(p, &ifs) { + const unsigned char *ipaddr; + int n_aliases = 0; + + net = list_entry(p, struct uci_network, list); + ipaddr = net->ipaddr; + if (!ipaddr) + ipaddr = (const unsigned char *) "\x00\x00\x00\x00"; - printf("New network section '%s'\n" + printf("New network section '%s'\n" " type: %s\n" " ifname: %s\n" - " ipaddr: %s\n" + " ipaddr: %d.%d.%d.%d\n" " test: %d\n" " enabled: %s\n", net->name, net->proto, net->ifname, - net->ipaddr, + ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3], net->test, (net->enabled ? "on" : "off")); - net->ipaddr = "2.3.4.5"; - ucimap_set_changed(net, &net->ipaddr); - ucimap_store_section(&network_map, pkg, net); - uci_save(ctx, pkg); + if (net->aliases->n_items > 0) { + printf("Configured aliases:"); + for (i = 0; i < net->aliases->n_items; i++) { + alias = net->aliases->item[i].ptr; + printf(" %s", alias->name); + } + printf("\n"); + } + list_for_each_entry(alias, &net->alias, list) { + n_aliases++; + for (i = 0; i < net->aliases->n_items; i++) { + if (alias == net->aliases->item[i].ptr) + goto next_alias; + } + printf("New alias: %s\n", alias->name); +next_alias: + continue; + } + if (set && !strcmp(net->name, "lan")) { + ucimap_free_item(&net->map, &net->ipaddr); + ucimap_set_changed(&net->map, &net->ipaddr); + ucimap_resize_list(&net->map, &net->aliases, n_aliases); + net->aliases->n_items = 0; + list_for_each_entry(alias, &net->alias, list) { + net->aliases->item[net->aliases->n_items++].ptr = alias; + } + ucimap_set_changed(&net->map, &net->aliases); + ucimap_store_section(&network_map, pkg, &net->map); + uci_save(ctx, pkg); + } + } + -done: ucimap_cleanup(&network_map); uci_free_context(ctx);