aboutsummaryrefslogtreecommitdiffstats
path: root/.gitignore
Commit message (Expand)AuthorAgeFilesLines
* add git-src to .gitignoreJohn Crispin2014-01-121-1/+2
* .gitignore: Ignore Emacs editor generated filesVasilis Tsiligiannis2011-10-311-0/+4
* [buildroot] add vim temp files (*~) to .gitignoreJo-Philipp Wich2011-04-291-0/+1
* gitignore: add *.rej and *.orig to .gitignoreFlorian Fainelli2011-04-031-0/+2
* .gitignore: add *.o and .DS_Store by default - apparently some git versions d...Felix Fietkau2010-12-041-0/+2
* .gitignore: Undo accidental commit.Daniel Dickinson2010-05-101-0/+3
* brcm-2.4: Fixed preinit and failsafe switch configurationDaniel Dickinson2010-05-101-3/+0
* .gitignore: ignore vim swap filesFelix Fietkau2009-12-161-0/+1
* add logs/ to .gitignoreFelix Fietkau2009-04-241-0/+1
* add feeds.conf to .gitignoreFelix Fietkau2008-09-231-0/+1
* add missing gitignore change for build environmentsFelix Fietkau2008-08-061-0/+1
* update svn:ignore and .gitignoreFelix Fietkau2008-06-061-6/+6
* add package/openwrt-packages to .gitignoreFelix Fietkau2008-02-091-0/+1
* add package/feeds to .gitignoreFelix Fietkau2007-10-131-0/+1
* add feeds to .gitignoreFelix Fietkau2007-10-091-0/+1
* update svn and git ignore settingsFelix Fietkau2007-08-071-1/+1
* make top-level .gitignore only apply to top-level files/directories (#1960)Felix Fietkau2007-06-251-8/+8
* Add gitignore filesFelix Fietkau2007-05-291-0/+8
/a> 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
/*
 * uci.c: UCI binding for the switch configuration utility
 *
 * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundatio.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <stdint.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <uci.h>

#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/genetlink.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/switch.h>
#include "swlib.h"

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif

struct swlib_setting {
	struct switch_attr *attr;
	const char *name;
	int port_vlan;
	const char *val;
	struct swlib_setting *next;
};

struct swlib_setting early_settings[] = {
	{ .name = "reset" },
	{ .name = "enable_vlan" },
};

static struct swlib_setting *settings;
static struct swlib_setting **head;

static int
swlib_map_settings(struct switch_dev *dev, int type, int port_vlan, struct uci_section *s)
{
	struct swlib_setting *setting;
	struct switch_attr *attr;
	struct uci_element *e;
	struct uci_option *o;
	int i;

	uci_foreach_element(&s->options, e) {
		o = uci_to_option(e);

		if (o->type != UCI_TYPE_STRING)
			continue;

		if (!strcmp(e->name, "device"))
			continue;

		/* map early settings */
		if (type == SWLIB_ATTR_GROUP_GLOBAL) {
			int i;

			for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
				if (strcmp(e->name, early_settings[i].name) != 0)
					continue;

				early_settings[i].val = o->v.string;
				goto skip;
			}
		}

		attr = swlib_lookup_attr(dev, type, e->name);
		if (!attr)
			continue;

		setting = malloc(sizeof(struct swlib_setting));
		memset(setting, 0, sizeof(struct swlib_setting));
		setting->attr = attr;
		setting->port_vlan = port_vlan;
		setting->val = o->v.string;
		*head = setting;
		head = &setting->next;
skip:
		continue;
	}
}

int swlib_apply_from_uci(struct switch_dev *dev, struct uci_package *p)
{
	struct switch_attr *attr;
	struct uci_context *ctx = p->ctx;
	struct uci_element *e;
	struct uci_section *s;
	struct uci_option *o;
	struct uci_ptr ptr;
	struct switch_val val;
	int i;

	settings = NULL;
	head = &settings;

	uci_foreach_element(&p->sections, e) {
		struct uci_element *n;

		s = uci_to_section(e);

		if (strcmp(s->type, "switch") != 0)
			continue;

		uci_foreach_element(&s->options, n) {
			struct uci_option *o = uci_to_option(n);

			if (strcmp(n->name, "name") != 0)
				continue;

			if (o->type != UCI_TYPE_STRING)
				continue;

			if (!strcmp(o->v.string, dev->dev_name))
				goto found;

			break;
		}

		if (strcmp(e->name, dev->dev_name) != 0)
			continue;

		goto found;
	}

	/* not found */
	return -1;

found:
	/* look up available early options, which need to be taken care
	 * of in the correct order */
	for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
		early_settings[i].attr = swlib_lookup_attr(dev,
			SWLIB_ATTR_GROUP_GLOBAL, early_settings[i].name);
	}
	swlib_map_settings(dev, SWLIB_ATTR_GROUP_GLOBAL, 0, s);

	/* look for port or vlan sections */
	uci_foreach_element(&p->sections, e) {
		struct uci_element *os;
		s = uci_to_section(e);

		if (!strcmp(s->type, "switch_port")) {
			char *devn, *port, *port_err = NULL;
			int port_n;

			uci_foreach_element(&s->options, os) {
				o = uci_to_option(os);
				if (o->type != UCI_TYPE_STRING)
					continue;

				if (!strcmp(os->name, "device")) {
					devn = o->v.string;
					if (strcmp(devn, dev->dev_name) != 0)
						devn = NULL;
				} else if (!strcmp(os->name, "port")) {
					port = o->v.string;
				}
			}
			if (!dev || !port || !port[0])
				continue;

			port_n = strtoul(port, &port_err, 0);
			if (port_err && port_err[0])
				continue;

			swlib_map_settings(dev, SWLIB_ATTR_GROUP_PORT, port_n, s);
		} else if (!strcmp(s->type, "switch_vlan")) {
			char *devn, *vlan, *vlan_err = NULL;
			int vlan_n;

			uci_foreach_element(&s->options, os) {
				o = uci_to_option(os);
				if (o->type != UCI_TYPE_STRING)
					continue;

				if (!strcmp(os->name, "device")) {
					devn = o->v.string;
					if (strcmp(devn, dev->dev_name) != 0)
						devn = NULL;
				} else if (!strcmp(os->name, "vlan")) {
					vlan = o->v.string;
				}
			}
			if (!dev || !vlan || !vlan[0])
				continue;

			vlan_n = strtoul(vlan, &vlan_err, 0);
			if (vlan_err && vlan_err[0])
				continue;

			swlib_map_settings(dev, SWLIB_ATTR_GROUP_VLAN, vlan_n, s);
		}
	}

	for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
		struct swlib_setting *st = &early_settings[i];
		if (!st->attr || !st->val)
			continue;
		swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);

	}

	while (settings) {
		struct swlib_setting *st = settings;

		swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);
		st = st->next;
		free(settings);
		settings = st;
	}

	/* Apply the config */
	attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, "apply");
	if (!attr)
		return 0;

	memset(&val, 0, sizeof(val));
	swlib_set_attr(dev, attr, &val);

	return 0;
}