swconfig: show tagged port flag
[openwrt/openwrt.git] / package / swconfig / src / cli.c
1 /*
2 * swconfig.c: Switch configuration utility
3 *
4 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundatio.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <inttypes.h>
20 #include <errno.h>
21 #include <stdint.h>
22 #include <getopt.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <uci.h>
26
27 #include <linux/types.h>
28 #include <linux/netlink.h>
29 #include <linux/genetlink.h>
30 #include <netlink/netlink.h>
31 #include <netlink/genl/genl.h>
32 #include <netlink/genl/ctrl.h>
33 #include <linux/switch.h>
34 #include "swlib.h"
35
36 enum {
37 GET,
38 SET,
39 LOAD
40 };
41
42 static void
43 print_attrs(const struct switch_attr *attr)
44 {
45 int i = 0;
46 while (attr) {
47 const char *type;
48 switch(attr->type) {
49 case SWITCH_TYPE_INT:
50 type = "int";
51 break;
52 case SWITCH_TYPE_STRING:
53 type = "string";
54 break;
55 case SWITCH_TYPE_PORTS:
56 type = "ports";
57 break;
58 case SWITCH_TYPE_NOVAL:
59 type = "none";
60 break;
61 default:
62 type = "unknown";
63 break;
64 }
65 printf("\tAttribute %d (%s): %s (%s)\n", ++i, type, attr->name, attr->description);
66 attr = attr->next;
67 }
68 }
69
70 static void
71 list_attributes(struct switch_dev *dev)
72 {
73 printf("Switch %d: %s(%s), ports: %d, vlans: %d\n", dev->id, dev->dev_name, dev->name, dev->ports, dev->vlans);
74 printf(" --switch\n");
75 print_attrs(dev->ops);
76 printf(" --vlan\n");
77 print_attrs(dev->vlan_ops);
78 printf(" --port\n");
79 print_attrs(dev->port_ops);
80 }
81
82 static void
83 print_usage(void)
84 {
85 printf("swconfig dev <dev> [port <port>|vlan <vlan>] (help|set <key> <value>|get <key>|load <config>)\n");
86 exit(1);
87 }
88
89 static void
90 swconfig_load_uci(struct switch_dev *dev, const char *name)
91 {
92 struct uci_context *ctx;
93 struct uci_package *p = NULL;
94 struct uci_element *e;
95 int ret = -1;
96
97 ctx = uci_alloc_context();
98 if (!ctx)
99 return;
100
101 uci_load(ctx, name, &p);
102 if (!p) {
103 uci_perror(ctx, "Failed to load config file: ");
104 goto out;
105 }
106
107 ret = swlib_apply_from_uci(dev, p);
108 if (ret < 0)
109 fprintf(stderr, "Failed to apply configuration for switch '%s'\n", dev->dev_name);
110
111 out:
112 uci_free_context(ctx);
113 exit(ret);
114 }
115
116 int main(int argc, char **argv)
117 {
118 int retval = 0;
119 struct switch_dev *dev;
120 struct switch_attr *a;
121 struct switch_val val;
122 int err;
123 int i;
124
125 struct switch_port *ports;
126
127 int cmd = 0;
128 char *cdev = NULL;
129 int cport = -1;
130 int cvlan = -1;
131 char *ckey = NULL;
132 char *cvalue = NULL;
133 int chelp = 0;
134
135 if(argc < 4)
136 print_usage();
137
138 if(strcmp(argv[1], "dev"))
139 print_usage();
140
141 cdev = argv[2];
142
143 for(i = 3; i < argc; i++)
144 {
145 int p;
146 if (!strcmp(argv[i], "help")) {
147 chelp = 1;
148 continue;
149 }
150 if( i + 1 >= argc)
151 print_usage();
152 p = atoi(argv[i + 1]);
153 if (!strcmp(argv[i], "port")) {
154 cport = p;
155 } else if (!strcmp(argv[i], "vlan")) {
156 cvlan = p;
157 } else if (!strcmp(argv[i], "set")) {
158 if(argc <= i + 1)
159 print_usage();
160 cmd = SET;
161 ckey = argv[i + 1];
162 if (argc > i + 2)
163 cvalue = argv[i + 2];
164 else
165 cvalue = NULL;
166 i++;
167 } else if (!strcmp(argv[i], "get")) {
168 cmd = GET;
169 ckey = argv[i + 1];
170 } else if (!strcmp(argv[i], "load")) {
171 if ((cport >= 0) || (cvlan >= 0))
172 print_usage();
173
174 ckey = argv[i + 1];
175 cmd = LOAD;
176 } else {
177 print_usage();
178 }
179 i++;
180 }
181
182 if(cport > -1 && cvlan > -1)
183 print_usage();
184
185 dev = swlib_connect(cdev);
186 if (!dev) {
187 fprintf(stderr, "Failed to connect to the switch\n");
188 return 1;
189 }
190
191 ports = malloc(sizeof(struct switch_port) * dev->ports);
192 memset(ports, 0, sizeof(struct switch_port) * dev->ports);
193 swlib_scan(dev);
194
195 if(chelp)
196 {
197 list_attributes(dev);
198 goto out;
199 }
200
201 if (cmd != LOAD) {
202 if(cport > -1)
203 a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_PORT, ckey);
204 else if(cvlan > -1)
205 a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, ckey);
206 else
207 a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, ckey);
208
209 if(!a)
210 {
211 fprintf(stderr, "Unknown attribute \"%s\"\n", ckey);
212 goto out;
213 }
214 }
215
216 switch(cmd)
217 {
218 case SET:
219 if ((a->type != SWITCH_TYPE_NOVAL) &&
220 (cvalue == NULL))
221 print_usage();
222
223 if(cvlan > -1)
224 cport = cvlan;
225
226 if(swlib_set_attr_string(dev, a, cport, cvalue) < 0)
227 {
228 fprintf(stderr, "failed\n");
229 retval = -1;
230 goto out;
231 }
232 break;
233 case GET:
234 if(cvlan > -1)
235 val.port_vlan = cvlan;
236 if(cport > -1)
237 val.port_vlan = cport;
238 if(swlib_get_attr(dev, a, &val) < 0)
239 {
240 fprintf(stderr, "failed\n");
241 retval = -1;
242 goto out;
243 }
244 switch(a->type) {
245 case SWITCH_TYPE_INT:
246 printf("%d\n", val.value.i);
247 break;
248 case SWITCH_TYPE_STRING:
249 printf("%s\n", val.value.s);
250 break;
251 case SWITCH_TYPE_PORTS:
252 for(i = 0; i < val.len; i++) {
253 printf("%d%s ",
254 val.value.ports[i].id,
255 (val.value.ports[i].flags &
256 SWLIB_PORT_FLAG_TAGGED) ? "t" : "");
257 }
258 printf("\n");
259 break;
260 }
261 break;
262 case LOAD:
263 swconfig_load_uci(dev, ckey);
264 break;
265 }
266
267 out:
268 swlib_free_all(dev);
269 free(ports);
270
271 return 0;
272 }