swconfig: show tagged port flag
[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 }