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