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