]> git.sur5r.net Git - ngadmin/blob - lib/src/vlan.c
12e99c77828b921c2dfe1d0f417956b4b97c11f7
[ngadmin] / lib / src / vlan.c
1
2 #include <ngadmin.h>
3
4 #include <attr.h>
5 #include <protocol.h>
6
7 #include "lib.h"
8 #include "network.h"
9
10
11 int ngadmin_getVLANType (struct ngadmin *nga, int *t)
12 {
13         List *attr;
14         struct attr *at;
15         int ret = ERR_OK;
16         
17         
18         if (nga == NULL || t == NULL)
19                 return ERR_INVARG;
20         else if (nga->current == NULL)
21                 return ERR_NOTLOG;
22         
23         
24         attr = createEmptyList();
25         pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
26         ret=readRequest(nga, attr);
27         if (ret != ERR_OK)
28                 goto end;
29         
30         filterAttributes(attr, ATTR_VLAN_TYPE, ATTR_END);
31         
32         *t = VLAN_DISABLED;
33         
34         if (attr->first != NULL) {
35                 at = attr->first->data;
36                 *t =(int)*(char*)at->data;
37         }
38         
39         
40 end:
41         destroyList(attr, (void(*)(void*))freeAttr);
42         
43         
44         return ret;
45 }
46
47
48 int ngadmin_setVLANType (struct ngadmin *nga, int t)
49 {
50         List *attr;
51         
52         
53         if (nga == NULL || t < 1 || t > 4)
54                 return ERR_INVARG;
55         else if (nga->current == NULL)
56                 return ERR_NOTLOG;
57         
58         
59         attr = createEmptyList();
60         pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
61         
62         
63         return writeRequest(nga, attr);
64 }
65
66
67 int ngadmin_getVLANPortConf (struct ngadmin *nga, unsigned char *ports)
68 {
69         List *attr;
70         ListNode *ln;
71         struct attr *at;
72         int ret = ERR_OK;
73         struct attr_vlan_conf *avc;
74         struct swi_attr *sa;
75         int port;
76         
77         
78         if (nga == NULL || ports== NULL)
79                 return ERR_INVARG;
80         
81         sa = nga->current;
82         if (sa == NULL)
83                 return ERR_NOTLOG;
84         
85         
86         attr = createEmptyList();
87         pushBackList(attr, newEmptyAttr(ATTR_VLAN_PORT_CONF));
88         ret = readRequest(nga, attr);
89         if (ret != ERR_OK)
90                 goto end;
91         
92         filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
93         
94         memset(ports, 0, sa->ports);
95         
96         for (ln = attr->first; ln != NULL; ln = ln->next) {
97                 at = ln->data;
98                 avc = at->data;
99
100                 if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
101                         return ERR_INVARG;
102                 
103                 for (port = 0; port < sa->ports; port++) {
104                         if (avc->ports[port] == VLAN_UNTAGGED)
105                                 ports[port] = avc->vlan;
106                 }
107         }
108         
109         
110 end:
111         destroyList(attr, (void(*)(void*))freeAttr);
112         
113         
114         return ret;
115 }
116
117
118 int ngadmin_setVLANPortConf (struct ngadmin *nga, const unsigned char *ports)
119 {
120         List *conf_old = NULL, *conf_new = NULL;
121         ListNode *ln;
122         struct attr *at;
123         struct swi_attr *sa;
124         struct attr_vlan_conf *avc_old, *avc_new;
125         int ret = ERR_OK, port;
126         
127         
128         if (nga == NULL || ports == NULL)
129                 return ERR_INVARG;
130         
131         sa = nga->current;
132         if (sa == NULL)
133                 return ERR_NOTLOG;
134         
135         /* if nothing is to be changed, do nothing */
136         for (port = 0; port < sa->ports && ports[port] == 0; port++);
137         if (port == sa->ports)
138                 goto end;
139         
140         /* read old config */
141         conf_old = createEmptyList();
142         pushBackList(conf_old, newEmptyAttr(ATTR_VLAN_PORT_CONF));
143         ret = readRequest(nga, conf_old);
144         if (ret != ERR_OK)
145                 goto end;
146         
147         filterAttributes(conf_old, ATTR_VLAN_PORT_CONF, ATTR_END);
148         
149         if (conf_old->first == NULL) {
150                 ret = ERR_INVARG;
151                 goto end;
152         }
153         
154         /* merge old config with requested config */
155         conf_new = createEmptyList();
156         avc_new = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
157         
158         for (ln = conf_old->first; ln != NULL; ln = ln->next) {
159                 at = ln->data;
160                 avc_old = at->data;
161                 
162                 if (at->size != sizeof(struct attr_vlan_conf) + sa->ports) {
163                         ret = ERR_INVARG;
164                         free(avc_new);
165                         goto end;
166                 }
167                 
168                 /* compute new VLAN configuration */
169                 avc_new->vlan = avc_old->vlan;
170                 
171                 for (port = 0; port < sa->ports; port++) {
172                         if (ports[port] == 0)
173                                 avc_new->ports[port] = avc_old->ports[port];
174                         else if (ports[port] == avc_new->vlan)
175                                 avc_new->ports[port] = VLAN_UNTAGGED;
176                         else
177                                 avc_new->ports[port] = VLAN_NO;
178                 }
179                 
180                 /* only add it if it is different from old config */
181                 if (memcmp(avc_old->ports, avc_new->ports, sa->ports) != 0) {
182                         pushBackList(conf_new, newAttr(ATTR_VLAN_PORT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc_new));
183                         avc_new = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
184                 }
185         }
186         
187         free(avc_new);
188         
189         /* if no VLAN is changed, no need to send anything to the switch */
190         if (conf_new->first == NULL)
191                 goto end;
192         
193         /* send new configuration to the switch */
194         ret = writeRequest(nga, conf_new);
195         conf_new = NULL;
196         
197 end:
198         destroyList(conf_old, (void(*)(void*))freeAttr);
199         destroyList(conf_new, (void(*)(void*))freeAttr);
200         
201         
202         return ret;
203 }
204
205
206 int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb)
207 {
208         List *attr;
209         ListNode *ln;
210         struct attr *at;
211         int ret = ERR_OK, total;
212         struct attr_vlan_conf *avc;
213         struct swi_attr *sa;
214         
215         
216         if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
217                 return ERR_INVARG;
218         
219         sa = nga->current;
220         if (sa == NULL)
221                 return ERR_NOTLOG;
222         
223         
224         total = *nb;
225         *nb = 0;
226         
227         attr = createEmptyList();
228         pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
229         ret = readRequest(nga, attr);
230         if (ret != ERR_OK)
231                 goto end;
232         
233         filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
234         
235         memset(vlans, 0, total * sizeof(unsigned short));
236         memset(ports, 0, total * sa->ports);
237         
238         for (ln = attr->first; ln != NULL; ln = ln->next) {
239                 at = ln->data;
240                 avc = at->data;
241                 
242                 if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
243                         return ERR_INVARG;
244                 
245                 *vlans = avc->vlan;
246                 memcpy(ports, avc->ports, sa->ports);
247                 
248                 vlans++;
249                 ports += sa->ports;
250                 (*nb)++;
251                 
252                 if (*nb > total)
253                         break; /* no more room */
254         }
255         
256         
257 end:
258         destroyList(attr, (void(*)(void*))freeAttr);
259         
260         
261         return ret;
262 }
263
264
265 int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports)
266 {
267         List *attr;
268         ListNode *ln;
269         struct attr *at;
270         int ret = ERR_OK;
271         struct attr_vlan_conf *avc;
272         
273         
274         if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
275                 return ERR_INVARG;
276         else if (nga->current == NULL)
277                 return ERR_NOTLOG;
278         
279         
280         attr = createEmptyList();
281         pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
282         ret = readRequest(nga, attr);
283         if (ret != ERR_OK)
284                 goto end;
285         
286         filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
287         
288         memset(ports, 0, nga->current->ports);
289         
290         for (ln = attr->first; ln != NULL; ln = ln->next) {
291                 at = ln->data;
292                 avc = at->data;
293                 if (avc->vlan == vlan) {
294                         memcpy(ports, avc->ports, nga->current->ports);
295                         break;
296                 }
297         }
298         
299         
300 end:
301         destroyList(attr, (void(*)(void*))freeAttr);
302         
303         
304         return ret;
305 }
306
307
308 int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports)
309 {
310         List *attr = NULL;
311         struct attr *at;
312         struct swi_attr *sa;
313         struct attr_vlan_conf *avc;
314         int ret = ERR_OK, port;
315         
316         
317         if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
318                 return ERR_INVARG;
319         
320         sa = nga->current;
321         if (sa == NULL)
322                 return ERR_NOTLOG;
323         
324         
325         /* if nothing is to be changed, do nothing */
326         for (port = 0; port < sa->ports && ports[port] == VLAN_UNSPEC; port++);
327         if (port == sa->ports )
328                 goto end;
329         
330         
331         attr = createEmptyList();
332         avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
333         if (avc == NULL)
334                 return ERR_MEM;
335         
336         avc->vlan = vlan;
337         
338         /* if all is to be changed, we do not need to read old config */
339         if (memchr(ports, VLAN_UNSPEC, sa->ports) != NULL) {
340                 
341                 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
342                 ret = readRequest(nga, attr);
343                 if (ret != ERR_OK)
344                         goto end;
345                 
346                 filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
347                 
348                 /* check if the switch is in 802.1Q mode */
349                 if (attr->first == NULL) {
350                         ret = ERR_INVARG;
351                         goto end;
352                 } else {
353                         at = attr->first->data;
354                         if (at->size != sizeof(struct attr_vlan_conf) + sa->ports) {
355                                 ret = ERR_INVARG;
356                                 goto end;
357                         }
358                 }
359                 
360                 memcpy(avc, at->data, sizeof(struct attr_vlan_conf) + sa->ports);
361                 clearList(attr, (void(*)(void*))freeAttr);
362         }
363         
364         
365         /* apply changes */
366         for (port = 0; port < sa->ports; port++) {
367                 if (ports[port] != VLAN_UNSPEC)
368                         avc->ports[port] = ports[port];
369         }
370         
371         
372         pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
373         ret = writeRequest(nga, attr);
374         attr = NULL;
375         
376         
377 end:
378         destroyList(attr, (void(*)(void*))freeAttr);
379         
380         
381         return ret;
382 }
383
384
385 int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan)
386 {
387         List *attr;
388         
389         
390         if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
391                 return ERR_INVARG;
392         else if (nga->current == NULL)
393                 return ERR_NOTLOG;
394         
395         
396         attr = createEmptyList();
397         pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
398         
399         
400         return writeRequest(nga, attr);
401 }
402
403
404 int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
405 {
406         List *attr;
407         ListNode *ln;
408         struct attr *at;
409         int ret = ERR_OK;
410         struct attr_pvid *ap;
411         
412         
413         if (nga == NULL || ports == NULL)
414                 return ERR_INVARG;
415         else if (nga->current == NULL)
416                 return ERR_NOTLOG;
417         
418         
419         attr = createEmptyList();
420         pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
421         ret = readRequest(nga, attr);
422         if (ret != ERR_OK)
423                 goto end;
424         
425         filterAttributes(attr, ATTR_VLAN_PVID, ATTR_END);
426         
427         memset(ports, 0, nga->current->ports * sizeof(unsigned short));
428         
429         for (ln = attr->first; ln != NULL; ln = ln->next) {
430                 at = ln->data;
431                 ap = at->data;
432                 ports[ap->port - 1] = ap->vlan;
433         }
434         
435         
436 end:
437         destroyList(attr, (void(*)(void*))freeAttr);
438         
439         
440         return ret;
441 }
442
443
444 int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan)
445 {
446         List *attr;
447         struct attr_pvid *ap;
448         
449         
450         if (nga == NULL || port < 1 || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
451                 return ERR_INVARG;
452         else if (nga->current == NULL)
453                 return ERR_NOTLOG;
454         else if (port > nga->current->ports)
455                 return ERR_INVARG;
456         
457         
458         attr = createEmptyList();
459         ap = malloc(sizeof(struct attr_pvid));
460         if (ap == NULL)
461                 return ERR_MEM;
462         ap->port = port;
463         ap->vlan = vlan;
464         
465         pushBackList(attr, newAttr(ATTR_VLAN_PVID, sizeof(struct attr_pvid), ap));
466         
467         
468         return writeRequest(nga, attr);
469 }
470
471