]> git.sur5r.net Git - ngadmin/blob - lib/src/ngadmin.c
4ab33060d1f95f5c02620681d53d69b90cccc88f
[ngadmin] / lib / src / ngadmin.c
1
2 #include <errno.h>
3
4 #include <ngadmin.h>
5
6 #include "lib.h"
7 #include "network.h"
8 #include "attr.h"
9 #include "protocol.h"
10
11
12
13 static const struct timeval default_timeout = {.tv_sec = 4, .tv_usec = 0};
14
15
16
17 struct ngadmin* ngadmin_init (const char *iface)
18 {
19         struct ngadmin *nga;
20         
21         
22         /* allocate main structure */
23         nga = malloc(sizeof(struct ngadmin));
24         memset(nga, 0, sizeof(struct ngadmin));
25         
26         strncpy(nga->iface, iface, IFNAMSIZ - 1);
27         
28         if (startNetwork(nga) < 0) {
29                 free(nga);
30                 return NULL;
31         }
32         
33         nga->timeout = default_timeout;
34         if (updateTimeout(nga) < 0) {
35                 free(nga);
36                 return NULL;
37         }
38         
39         
40         return nga;
41 }
42
43
44 int ngadmin_close (struct ngadmin *nga)
45 {
46         if (nga == NULL)
47                 return ERR_INVARG;
48                 
49         stopNetwork(nga);
50         free(nga->swi_tab);
51         free(nga);
52         
53         return ERR_OK;
54 }
55
56
57 int ngadmin_forceInterface (struct ngadmin *nga)
58 {
59         if (nga == NULL)
60                 return ERR_INVARG;
61         
62         return forceInterface(nga) == 0 ? ERR_OK : ERR_NET;
63 }
64
65
66 int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value)
67 {
68         if (nga == NULL)
69                 return ERR_INVARG;
70         
71         nga->keepbroad = value;
72         
73         return ERR_OK;
74 }
75
76
77 int ngadmin_useGlobalBroadcast (struct ngadmin *nga, bool value)
78 {
79         if (nga == NULL)
80                 return ERR_INVARG;
81         
82         nga->globalbroad = value;
83         
84         return ERR_OK;
85 }
86
87
88 int ngadmin_setPassword (struct ngadmin *nga, const char *pass)
89 {
90         if (nga == NULL)
91                 return ERR_INVARG;
92         
93         strncpy(nga->password, pass, PASSWORD_MAX);
94         
95         return ERR_OK;
96 }
97
98
99 int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv)
100 {
101         int ret = ERR_OK;
102         
103         
104         if (nga == NULL || tv == NULL)
105                 return ERR_INVARG;
106         
107         nga->timeout = *tv;
108         if (updateTimeout(nga) < 0)
109                 ret = ERR_NET;
110         
111         
112         return ret;
113 }
114
115
116 int ngadmin_scan (struct ngadmin *nga)
117 {
118         int i;
119         List *attr, *swiList;
120         struct swi_attr *sa;
121         /*
122         sent by official win client:
123         ATTR_PRODUCT,
124         ATTR_UNK2,
125         ATTR_NAME,
126         ATTR_MAC,
127         ATTR_UNK5,
128         ATTR_IP,
129         ATTR_NETMASK,
130         ATTR_GATEWAY,
131         ATTR_DHCP,
132         ATTR_UNK12,
133         ATTR_FIRM_VER,
134         ATTR_UNK14,
135         ATTR_UNK15,
136         ATTR_END
137         */
138         static const unsigned short hello[] = {
139                 ATTR_PRODUCT,
140                 ATTR_NAME,
141                 ATTR_MAC,
142                 ATTR_IP,
143                 ATTR_NETMASK,
144                 ATTR_GATEWAY,
145                 ATTR_DHCP,
146                 ATTR_FIRM_VER,
147                 ATTR_PORTS_COUNT,
148                 ATTR_END
149         };
150         
151         
152         if (nga == NULL)
153                 return ERR_INVARG;
154         
155         free(nga->swi_tab);
156         nga->swi_tab = NULL;
157         nga->swi_count = 0;
158         nga->current = NULL;
159         
160         
161         /* create attributes for an "hello" request */
162         attr = createEmptyList();
163         for (i = 0; ; i++) {
164                 pushBackList(attr, newEmptyAttr(hello[i]));
165                 if (hello[i] == ATTR_END)
166                         break;
167         }
168         
169         /* send request to all potential switches */
170         i = sendNgPacket(nga, CODE_READ_REQ, attr);
171         clearList(attr, (void(*)(void*))freeAttr);
172         if (i == -EINVAL)
173                 return ERR_INVARG;
174         else if (i < 0)
175                 return ERR_NET;
176         
177         /* try to receive any packets until timeout */
178         swiList = createEmptyList();
179         /* FIXME: end after timeout whatever received packet is good or not */
180         while (recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr, ATTR_END) >= 0) {
181                 sa = malloc(sizeof(struct swi_attr));
182                 if (sa == NULL)
183                         return ERR_MEM;
184                 extractSwitchAttributes(sa, attr);
185                 clearList(attr, (void(*)(void*))freeAttr);
186                 pushBackList(swiList, sa);
187         }
188         
189         nga->swi_count = swiList->count;
190         nga->swi_tab = convertToArray(swiList, sizeof(struct swi_attr));
191         destroyList(swiList, free);
192         destroyList(attr, (void(*)(void*))freeAttr);
193         
194         
195         return ERR_OK;
196 }
197
198
199 const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb)
200 {
201         if (nga == NULL || nb == NULL)
202                 return NULL;
203         
204         *nb = nga->swi_count;
205         
206         return nga->swi_tab;
207 }
208
209
210 const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga)
211 {
212         if (nga == NULL)
213                 return NULL;
214         
215         return nga->current;
216 }
217
218
219 int ngadmin_login (struct ngadmin *nga, int id)
220 {
221         List *attr;
222         int ret = ERR_OK;
223         struct swi_attr *sa;
224         
225         
226         if (nga == NULL)
227                 return ERR_INVARG;
228         else if (id < 0 || id >= nga->swi_count)
229                 return ERR_BADID;
230         
231         sa = &nga->swi_tab[id];
232         nga->current = sa;
233         
234         attr = createEmptyList();
235         pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
236         ret = readRequest(nga, attr, ATTR_END);
237         if (ret == ERR_OK ) {
238                 /* login succeeded */
239                 /* TODO: if keep broadcasting is disabled, connect() the UDP 
240                 socket so icmp errors messages (port unreachable, TTL exceeded 
241                 in transit, ...) can be received */
242         } else {
243                 /* login failed */
244                 nga->current = NULL;
245         }
246         
247         destroyList(attr, (void(*)(void*))freeAttr);
248         
249         
250         return ret;
251 }
252
253
254 int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename)
255 {
256         if (nga == NULL || filename == NULL || *filename == 0)
257                 return ERR_INVARG;
258         else if (nga->current == NULL)
259                 return ERR_NOTLOG;
260         
261         /*
262         Firmware upgrade is not yet implemented. 
263         This would require much more work and the use of a TFTP client. 
264         Overall, it could be quite dangerous, as the switch may not check the binary 
265         content sent to it. 
266         */
267         
268         return ERR_NOTIMPL;
269 }
270
271
272 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
273 {
274         List *attr;
275         ListNode *ln;
276         struct attr *at;
277         int ret = ERR_OK;
278         struct attr_port_status *ps;
279         
280         
281         if (nga == NULL || ports == NULL)
282                 return ERR_INVARG;
283         else if (nga->current == NULL)
284                 return ERR_NOTLOG;
285         
286         
287         attr = createEmptyList();
288         pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
289         ret = readRequest(nga, attr, ATTR_PORT_STATUS);
290         if (ret != ERR_OK)
291                 goto end;
292         
293         memset(ports, SPEED_UNK, nga->current->ports);
294         
295         for (ln = attr->first; ln != NULL; ln = ln->next) {
296                 at = ln->data;
297                 ps = at->data;
298                 ports[ps->port - 1] = ps->status;
299         }
300         
301 end:
302         destroyList(attr, (void(*)(void*))freeAttr);
303         
304         
305         return ret;
306 }
307
308
309 int ngadmin_setName (struct ngadmin *nga, const char *name)
310 {
311         List *attr;
312         int ret = ERR_OK;
313         
314         
315         if (nga == NULL)
316                 return ERR_INVARG;
317         else if (nga->current == NULL)
318                 return ERR_NOTLOG;
319         
320         
321         attr = createEmptyList();
322         pushBackList(attr, name == NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
323         ret = writeRequest(nga, attr);
324         if (ret != ERR_OK)
325                 goto end;
326          
327         /* successful, also update local name */
328         if (name == NULL)
329                 memset(nga->current->name, '\0', NAME_SIZE);
330         else
331                 strncpy(nga->current->name, name, NAME_SIZE);
332         
333 end:
334         return ret;
335 }
336
337
338 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
339 {
340         List *attr;
341         ListNode *ln;
342         struct attr *at;
343         int ret = ERR_OK;
344         struct attr_port_stat *aps;
345         
346         
347         if (nga == NULL || ps == NULL)
348                 return ERR_INVARG;
349         else if (nga->current == NULL)
350                 return ERR_NOTLOG;
351         
352         attr = createEmptyList();
353         pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
354         ret = readRequest(nga, attr, ATTR_PORT_STATISTICS);
355         if (ret != ERR_OK)
356                 goto end;
357         
358         memset(ps, 0, nga->current->ports * sizeof(struct port_stats));
359         
360         for (ln = attr->first; ln != NULL; ln = ln->next) {
361                 at = ln->data;
362                 aps = at->data;
363                 ps[aps->port -1].recv = aps->recv;
364                 ps[aps->port -1].sent = aps->sent;
365                 ps[aps->port -1].crc = aps->crc;
366         }
367         
368 end:
369         destroyList(attr, (void(*)(void*))freeAttr);
370         
371         
372         return ret;
373 }
374
375
376 int ngadmin_resetPortsStatistics (struct ngadmin *nga)
377 {
378         List *attr;
379         
380         
381         attr = createEmptyList();
382         pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
383         
384         
385         return writeRequest(nga, attr);
386 }
387
388
389 int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
390 {
391         List *attr;
392         int ret = ERR_OK;
393         
394         
395         if (nga == NULL || pass == NULL)
396                 return ERR_INVARG;
397         else if (nga->current == NULL)
398                 return ERR_NOTLOG;
399         
400         
401         attr = createEmptyList();
402         pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
403         ret = writeRequest(nga, attr);
404         if (ret != ERR_OK)
405                 goto end;
406         
407         
408         /* successful, also update local password */
409         strncpy(nga->password, pass, PASSWORD_MAX);
410         
411 end:
412         
413         return ret;
414 }
415
416
417 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s)
418 {
419         List *attr;
420         struct attr *at;
421         int ret = ERR_OK;
422         
423         
424         if (nga == NULL || s == NULL)
425                 return ERR_INVARG;
426         else if (nga->current == NULL)
427                 return ERR_NOTLOG;
428         
429         
430         attr = createEmptyList();
431         pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
432         ret = readRequest(nga, attr, ATTR_STORM_ENABLE);
433         if (ret != ERR_OK)
434                 goto end;
435         
436         *s = 0;
437         
438         if (attr->first != NULL) {
439                 at = attr->first->data;
440                 *s = *(char*)at->data;
441         }
442         
443         
444 end:
445         destroyList(attr, (void(*)(void*))freeAttr);
446         
447         
448         return ret;
449 }
450
451
452 int ngadmin_setStormFilterState (struct ngadmin *nga, int s)
453 {
454         List *attr;
455         
456         
457         attr = createEmptyList();
458         pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s != 0));
459         
460         
461         return writeRequest(nga, attr);
462 }
463
464
465 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
466 {
467         List *attr;
468         ListNode *ln;
469         struct attr *at;
470         int ret = ERR_OK, port;
471         struct attr_bitrate *sb;
472         
473         
474         if (nga == NULL || ports == NULL)
475                 return ERR_INVARG;
476         else if (nga->current == NULL)
477                 return ERR_NOTLOG;
478         
479         
480         attr = createEmptyList();
481         pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
482         ret = readRequest(nga, attr, ATTR_STORM_BITRATE);
483         if (ret != ERR_OK)
484                 goto end;
485         
486         for (port = 0; port < nga->current->ports; port++)
487                 ports[port] = BITRATE_UNSPEC;
488         
489         for (ln = attr->first; ln != NULL; ln = ln->next) {
490                 at = ln->data;
491                 sb = at->data;
492                 ports[sb->port - 1] = sb->bitrate;
493         }
494         
495         
496 end:
497         destroyList(attr, (void(*)(void*))freeAttr);
498         
499         
500         return ret;
501 }
502
503
504 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports)
505 {
506         List *attr;
507         int port;
508         struct attr_bitrate *sb;
509         
510         
511         if (nga == NULL || ports == NULL)
512                 return ERR_INVARG;
513         else if (nga->current == NULL)
514                 return ERR_NOTLOG;
515         
516         
517         attr = createEmptyList();
518         
519         for (port = 0; port < nga->current->ports; port++) {
520                 if (ports[port] != BITRATE_UNSPEC) {
521                         sb = malloc(sizeof(struct attr_bitrate));
522                         if (sb == NULL)
523                                 return ERR_MEM;
524                         sb->port = port + 1;
525                         sb->bitrate = ports[port];
526                         pushBackList(attr, newAttr(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), sb));
527                 }
528         }
529         
530         return writeRequest(nga, attr);
531 }
532
533
534 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
535 {
536         List *attr;
537         ListNode *ln;
538         struct attr *at;
539         int ret = ERR_OK, port;
540         struct attr_bitrate *pb;
541         
542         
543         if (nga == NULL || ports == NULL)
544                 return ERR_INVARG;
545         else if (nga->current == NULL)
546                 return ERR_NOTLOG;
547         
548         
549         attr = createEmptyList();
550         pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
551         pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
552         ret = readRequest(nga, attr, ATTR_END);
553         if (ret != ERR_OK)
554                 goto end;
555         
556         
557         for (port = 0; port < nga->current->ports; port++) {
558                 ports[2 * port + 0] = BITRATE_UNSPEC;
559                 ports[2 * port + 1] = BITRATE_UNSPEC;
560         }
561         
562         for (ln = attr->first; ln != NULL; ln = ln->next) {
563                 at = ln->data;
564                 pb = at->data;
565                 if (at->attr == ATTR_BITRATE_INPUT)
566                         ports[(pb->port - 1) * 2 + 0] = pb->bitrate;
567                 else if (at->attr == ATTR_BITRATE_OUTPUT)
568                         ports[(pb->port - 1) * 2 + 1] = pb->bitrate;
569         }
570         
571         
572 end:
573         destroyList(attr, (void(*)(void*))freeAttr);
574         
575         return ret;
576 }
577
578
579 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports)
580 {
581         List *attr;
582         int port;
583         struct attr_bitrate *pb;
584         
585         
586         if (nga == NULL || ports == NULL)
587                 return ERR_INVARG;
588         else if (nga->current == NULL)
589                 return ERR_NOTLOG;
590         
591         
592         attr = createEmptyList();
593         
594         for (port = 0; port < nga->current->ports; port++) {
595                 if (ports[2 * port + 0] >= BITRATE_NOLIMIT && ports[2 * port + 0] <= BITRATE_512M) {
596                         pb = malloc(sizeof(struct attr_bitrate));
597                         if (pb == NULL)
598                                 return ERR_MEM;
599                         pb->port = port + 1;
600                         pb->bitrate = ports[2 * port + 0];
601                         pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), pb));
602                 }
603                 if (ports[2 * port + 1] >= BITRATE_NOLIMIT && ports[2 * port + 1] <= BITRATE_512M) {
604                         pb = malloc(sizeof(struct attr_bitrate));
605                         if (pb == NULL)
606                                 return ERR_MEM;
607                         pb->port = port + 1;
608                         pb->bitrate = ports[2 * port + 1];
609                         pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), pb));
610                 }
611         }
612         
613         
614         return writeRequest(nga, attr);
615 }
616
617
618 int ngadmin_getQOSMode (struct ngadmin *nga, int *s)
619 {
620         List *attr;
621         struct attr *at;
622         int ret = ERR_OK;
623         
624         
625         if (nga == NULL || s == NULL)
626                 return ERR_INVARG;
627         else if (nga->current == NULL)
628                 return ERR_NOTLOG;
629         
630         
631         attr = createEmptyList();
632         pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
633         ret = readRequest(nga, attr, ATTR_QOS_TYPE);
634         if (ret != ERR_OK)
635                 goto end;
636         
637         *s = 0;
638         
639         if (attr->first != NULL) {
640                 at = attr->first->data;
641                 *s = *(char*)at->data;
642         }
643         
644         
645 end:
646         destroyList(attr, (void(*)(void*))freeAttr);
647         
648         
649         return ret;
650 }
651
652
653 int ngadmin_setQOSMode (struct ngadmin *nga, int s)
654 {
655         List *attr;
656         
657         
658         attr = createEmptyList();
659         pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
660         
661         
662         return writeRequest(nga, attr);
663 }
664
665
666 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
667 {
668         List *attr;
669         ListNode *ln;
670         struct attr *at;
671         int ret = ERR_OK, port;
672         struct attr_qos *aq;
673         
674         
675         if (nga == NULL || ports == NULL)
676                 return ERR_INVARG;
677         else if (nga->current == NULL)
678                 return ERR_NOTLOG;
679         
680         
681         attr = createEmptyList();
682         pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
683         ret = readRequest(nga, attr, ATTR_QOS_CONFIG);
684         if (ret < 0)
685                 goto end;
686         
687         for (port = 0; port < nga->current->ports; port++)
688                 ports[port] = PRIO_UNSPEC;
689         
690         for (ln = attr->first; ln != NULL; ln = ln->next) {
691                 at = ln->data;
692                 aq = at->data;
693                 ports[aq->port - 1] = aq->prio;
694         }
695         
696         
697 end:
698         destroyList(attr, (void(*)(void*))freeAttr);
699         
700         
701         return ret;
702 }
703
704
705 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports)
706 {
707         List *attr;
708         int port;
709         struct attr_qos *aq;
710         
711         
712         if (nga == NULL || ports == NULL)
713                 return ERR_INVARG;
714         else if (nga->current == NULL)
715                 return ERR_NOTLOG;
716         
717         
718         attr = createEmptyList();
719         
720         for (port = 0; port < nga->current->ports; port++) {
721                 if (ports[port] >= PRIO_HIGH && ports[port] <= PRIO_LOW) {
722                         aq = malloc(sizeof(struct attr_qos));
723                         if (aq == NULL)
724                                 return ERR_MEM;
725                         aq->port = port + 1;
726                         aq->prio = ports[port];
727                         pushBackList(attr, newAttr(ATTR_QOS_CONFIG, sizeof(struct attr_qos), aq));
728                 }
729         }
730         
731         
732         return writeRequest(nga, attr);
733 }
734
735
736 int ngadmin_restart (struct ngadmin *nga)
737 {
738         List *attr;
739         
740         
741         attr = createEmptyList();
742         pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
743         
744         
745         return writeRequest(nga, attr);
746 }
747
748
749 int ngadmin_defaults (struct ngadmin *nga)
750 {
751         List *attr;
752         int ret = ERR_OK;
753         
754         
755         attr = createEmptyList();
756         pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
757         ret = writeRequest(nga, attr);
758         if (ret != ERR_OK)
759                 goto end;
760         
761         
762         /* successful: delog and clean list */
763         free(nga->swi_tab);
764         nga->swi_tab = NULL;
765         nga->swi_count = 0;
766         nga->current = NULL;
767         
768 end:
769         return ret;
770 }
771
772
773 int ngadmin_getMirror (struct ngadmin *nga, char *ports)
774 {
775         List *attr;
776         struct attr *at;
777         int ret = ERR_OK;
778         
779         
780         if (nga == NULL || ports == NULL)
781                 return ERR_INVARG;
782         else if (nga->current == NULL)
783                 return ERR_NOTLOG;
784         
785         
786         attr = createEmptyList();
787         pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
788         ret = readRequest(nga, attr, ATTR_MIRROR);
789         if (ret < 0)
790                 goto end;
791         
792         memset(ports, 0, 1 + nga->current->ports);
793         
794         if (attr->first != NULL) {
795                 at = attr->first->data;
796                 memcpy(ports, at->data, 1 + nga->current->ports);
797         }
798         
799         
800 end:
801         destroyList(attr, (void(*)(void*))freeAttr);
802         
803         
804         return ret;
805 }
806
807
808 int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
809 {
810         List *attr;
811         char *p;
812         
813         
814         if (nga == NULL)
815                 return ERR_INVARG;
816         else if (nga->current == NULL)
817                 return ERR_NOTLOG;
818         
819         
820         p = malloc(1 + nga->current->ports);
821         if (p == NULL)
822                 return ERR_MEM;
823         
824         if (ports == NULL)
825                 memset(p, 0, 1 + nga->current->ports);
826         else
827                 memcpy(p, ports, 1 + nga->current->ports);
828         
829         attr = createEmptyList();
830         pushBackList(attr, newAttr(ATTR_MIRROR, 1 + nga->current->ports, p));
831         
832         
833         return writeRequest(nga, attr);
834 }
835
836
837 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic)
838 {
839         List *attr;
840         struct attr *at;
841         int ret = ERR_OK;
842         struct attr_igmp_vlan *aiv;
843         
844         
845         if (nga == NULL || ic == NULL)
846                 return ERR_INVARG;
847         else if (nga->current == NULL)
848                 return ERR_NOTLOG;
849         
850         /*
851         ATTR_IGMP_ENABLE_VLAN
852         ATTR_IGMP_BLOCK_UNK
853         ATTR_IGMP_VALID_V3
854         
855         Apparently, read-querying these attributes at the same time causes the switch to reply garbage. 
856         Here we are forced to do like the official win app and send a separate request for each attribute. 
857         */
858         
859         
860         attr = createEmptyList();
861         memset(ic, 0, sizeof(struct igmp_conf));
862         
863         
864         pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
865         ret = readRequest(nga, attr, ATTR_IGMP_ENABLE_VLAN);
866         if (ret < 0)
867                 goto end;
868         
869         if (attr->first != NULL) {
870                 at = attr->first->data;
871                 aiv = at->data;
872                 ic->enable = aiv->enable;
873                 ic->vlan = aiv->vlan;
874         }
875         
876         clearList(attr, (void(*)(void*))freeAttr);
877         
878         
879         pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
880         ret = readRequest(nga, attr, ATTR_IGMP_BLOCK_UNK);
881         if (ret < 0)
882                 goto end;
883         
884         if (attr->first != NULL) {
885                 at = attr->first->data;
886                 ic->block = *(char*)at->data;
887         }
888         
889         clearList(attr, (void(*)(void*))freeAttr);
890         
891         
892         pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
893         ret = readRequest(nga, attr, ATTR_IGMP_VALID_V3);
894         if (ret < 0)
895                 goto end;
896         
897         if (attr->first != NULL) {
898                 at = attr->first->data;
899                 ic->validate = *(char*)at->data;
900         }
901         
902         
903 end:
904         destroyList(attr, (void(*)(void*))freeAttr);
905         
906         
907         return ret;
908 }
909
910
911 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic)
912 {
913         List *attr;
914         struct attr_igmp_vlan *aiv;
915         
916         
917         if (nga == NULL || ic == NULL)
918                 return ERR_INVARG;
919         else if (nga->current == NULL)
920                 return ERR_NOTLOG;
921         
922         
923         aiv = malloc(sizeof(struct attr_igmp_vlan));
924         if (aiv == NULL)
925                 return ERR_MEM;
926         aiv->enable = ic->enable;
927         aiv->vlan = ic->vlan;
928         
929         
930         attr = createEmptyList();
931         pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), aiv));
932         pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block != false));
933         pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate != false));
934         
935         
936         return writeRequest(nga, attr);
937 }
938
939
940 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb)
941 {
942         List *attr;
943         ListNode *ln;
944         struct attr *at;
945         int ret = ERR_OK, i;
946         struct attr_cabletest_do *acd;
947         struct attr_cabletest_result *acr;
948         
949         
950         if (nga == NULL || ct == NULL)
951                 return ERR_INVARG;
952         else if (nga->current == NULL)
953                 return ERR_NOTLOG;
954         
955         
956         attr = createEmptyList();
957         
958         for (i = 0; i < nb; i++) {
959                 
960                 acd = malloc(sizeof(struct attr_cabletest_do));
961                 if (acd == NULL)
962                         return ERR_MEM;
963                 acd->port = ct[i].port;
964                 acd->action = 1;
965                 pushBackList(attr, newAttr(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), acd));
966                 
967                 ret = writeRequest(nga, attr);
968                 attr = NULL;
969                 if (ret < 0)
970                         goto end;
971                 
972                 /* the list is destroyed by writeRequest, so we need to recreate it */
973                 attr = createEmptyList();
974                 pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
975                 ret = readRequest(nga, attr, ATTR_CABLETEST_RESULT);
976                 if (ret < 0)
977                         goto end;
978                 
979                 for (ln = attr->first; ln != NULL; ln = ln->next) {
980                         at = ln->data;
981                         acr = at->data;
982                         if (at->size == sizeof(struct attr_cabletest_result) && acr->port == ct[i].port) {
983                                 ct[i].v1 = acr->v1;
984                                 ct[i].v2 = acr->v2;
985                                 break;
986                         }
987                 }
988                 
989                 /* just empty the list, it will be used at next iteration */
990                 clearList(attr, (void(*)(void*))freeAttr);
991         }
992         
993         
994 end:
995         destroyList(attr, (void(*)(void*))freeAttr);
996         
997         
998         return ret;
999 }
1000
1001
1002 int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc)
1003 {
1004         List *attr;
1005         int ret = ERR_OK;
1006         struct swi_attr *sa;
1007         
1008         
1009         if (nga == NULL || nc == NULL)
1010                 return ERR_INVARG;
1011         
1012         sa = nga->current;
1013         if (sa == NULL)
1014                 return ERR_NOTLOG;
1015         
1016         
1017         attr = createEmptyList();
1018         
1019         if (nc->dhcp) {
1020                 pushBackList(attr, newShortAttr(ATTR_DHCP, 1));
1021         } else {
1022                 pushBackList(attr, newShortAttr(ATTR_DHCP, 0));
1023                 /* only add non-null values */
1024                 if (nc->ip.s_addr != 0)
1025                         pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
1026                 if (nc->netmask.s_addr != 0)
1027                         pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
1028                 if (nc->gw.s_addr != 0)
1029                         pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
1030         }
1031         
1032         ret = writeRequest(nga, attr);
1033         if (ret != ERR_OK)
1034                 goto end;
1035         
1036         
1037         /* update local values */
1038         sa->nc.dhcp = nc->dhcp;
1039         if (!nc->dhcp) {
1040                 if (nc->ip.s_addr !=0)
1041                         sa->nc.ip = nc->ip;
1042                 if (nc->netmask.s_addr != 0)
1043                         sa->nc.netmask = nc->netmask;
1044                 if (nc->gw.s_addr != 0)
1045                         sa->nc.gw = nc->gw;
1046         }
1047         
1048         
1049 end:
1050         
1051         return ret;
1052 }
1053
1054
1055 int ngadmin_getVLANType (struct ngadmin *nga, int *t)
1056 {
1057         List *attr;
1058         struct attr *at;
1059         int ret = ERR_OK;
1060         
1061         
1062         if (nga == NULL || t == NULL)
1063                 return ERR_INVARG;
1064         else if (nga->current == NULL)
1065                 return ERR_NOTLOG;
1066         
1067         
1068         attr = createEmptyList();
1069         pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
1070         ret=readRequest(nga, attr, ATTR_VLAN_TYPE);
1071         if (ret != ERR_OK)
1072                 goto end;
1073         
1074         *t = VLAN_DISABLED;
1075         
1076         if (attr->first != NULL) {
1077                 at = attr->first->data;
1078                 *t =(int)*(char*)at->data;
1079         }
1080         
1081         
1082 end:
1083         destroyList(attr, (void(*)(void*))freeAttr);
1084         
1085         
1086         return ret;
1087 }
1088
1089
1090 int ngadmin_setVLANType (struct ngadmin *nga, int t)
1091 {
1092         List *attr;
1093         
1094         
1095         if (nga == NULL || t < 1 || t > 4)
1096                 return ERR_INVARG;
1097         else if (nga->current == NULL)
1098                 return ERR_NOTLOG;
1099         
1100         
1101         attr = createEmptyList();
1102         pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
1103         
1104         
1105         return writeRequest(nga, attr);
1106 }
1107
1108
1109 int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb)
1110 {
1111         List *attr;
1112         ListNode *ln;
1113         struct attr *at;
1114         int ret = ERR_OK, total;
1115         struct attr_vlan_dot *avd;
1116         
1117         
1118         if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
1119                 return ERR_INVARG;
1120         else if (nga->current == NULL)
1121                 return ERR_NOTLOG;
1122         
1123         
1124         total = *nb;
1125         *nb = 0;
1126         
1127         attr = createEmptyList();
1128         pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
1129         ret = readRequest(nga, attr, ATTR_VLAN_DOT_CONF);
1130         if (ret != ERR_OK)
1131                 goto end;
1132         
1133         memset(vlans, 0, total * sizeof(unsigned short));
1134         memset(ports, 0, total * nga->current->ports);
1135         
1136         for (ln = attr->first; ln != NULL; ln = ln->next) {
1137                 at = ln->data;
1138                 avd = at->data;
1139                 
1140                 *vlans = avd->vlan;
1141                 memcpy(ports, avd->ports, nga->current->ports);
1142                 
1143                 vlans++;
1144                 ports += nga->current->ports;
1145                 (*nb)++;
1146                 
1147                 if (*nb > total)
1148                         break; /* no more room */
1149         }
1150         
1151         
1152 end:
1153         destroyList(attr, (void(*)(void*))freeAttr);
1154         
1155         
1156         return ret;
1157 }
1158
1159
1160 int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports)
1161 {
1162         List *attr;
1163         ListNode *ln;
1164         struct attr *at;
1165         int ret = ERR_OK;
1166         struct attr_vlan_dot *avd;
1167         
1168         
1169         if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
1170                 return ERR_INVARG;
1171         else if (nga->current == NULL)
1172                 return ERR_NOTLOG;
1173         
1174         
1175         attr = createEmptyList();
1176         pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1177         ret = readRequest(nga, attr, ATTR_END);
1178         if (ret != ERR_OK)
1179                 goto end;
1180         
1181         memset(ports, 0, nga->current->ports);
1182         
1183         for (ln = attr->first; ln != NULL; ln = ln->next) {
1184                 at = ln->data;
1185                 avd = at->data;
1186                 if (avd->vlan == vlan) {
1187                         memcpy(ports, avd->ports, nga->current->ports);
1188                         break;
1189                 }
1190         }
1191         
1192         
1193 end:
1194         destroyList(attr, (void(*)(void*))freeAttr);
1195         
1196         
1197         return ret;
1198 }
1199
1200
1201 int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports)
1202 {
1203         List *attr = NULL;
1204         struct attr *at;
1205         struct swi_attr *sa;
1206         struct attr_vlan_dot *avd;
1207         int ret = ERR_OK, port;
1208         
1209         
1210         if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
1211                 return ERR_INVARG;
1212         
1213         sa = nga->current;
1214         if (sa == NULL)
1215                 return ERR_NOTLOG;
1216         
1217         
1218         /* if nothing is to be changed, do nothing */
1219         for (port = 0; port < sa->ports && ports[port] == VLAN_UNSPEC; port++);
1220         if (port == sa->ports )
1221                 goto end;
1222         
1223         
1224         attr = createEmptyList();
1225         avd = malloc(sizeof(struct attr_vlan_dot) + sa->ports);
1226         if (avd == NULL)
1227                 return ERR_MEM;
1228         
1229         avd->vlan = vlan;
1230         
1231         /* if all is to be changed, we do not need to read old config */
1232         if (memchr(ports, VLAN_UNSPEC, sa->ports) != NULL) {
1233                 
1234                 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1235                 ret = readRequest(nga, attr, ATTR_VLAN_DOT_CONF);
1236                 if (ret != ERR_OK)
1237                         goto end;
1238                 
1239                 if (attr->first != NULL) {
1240                         at = attr->first->data;
1241                         memcpy(avd, at->data, sizeof(struct attr_vlan_dot) + sa->ports);
1242                 }
1243                 
1244                 clearList(attr, (void(*)(void*))freeAttr);
1245         }
1246         
1247         
1248         /* apply changes */
1249         for (port = 0; port < sa->ports; port++) {
1250                 if (ports[port] != VLAN_UNSPEC)
1251                         avd->ports[port] = ports[port];
1252         }
1253         
1254         
1255         pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_dot) + sa->ports, avd));
1256         ret = writeRequest(nga, attr);
1257         attr = NULL;
1258         
1259         
1260 end:
1261         destroyList(attr, (void(*)(void*))freeAttr);
1262         
1263         
1264         return ret;
1265 }
1266
1267
1268 int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan)
1269 {
1270         List *attr;
1271         
1272         
1273         if (nga == NULL || vlan < 1 || vlan > VLAN_MAX)
1274                 return ERR_INVARG;
1275         else if (nga->current == NULL)
1276                 return ERR_NOTLOG;
1277         
1278         
1279         attr = createEmptyList();
1280         pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
1281         
1282         
1283         return writeRequest(nga, attr);
1284 }
1285
1286
1287 int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
1288 {
1289         List *attr;
1290         ListNode *ln;
1291         struct attr *at;
1292         int ret = ERR_OK;
1293         struct attr_pvid *ap;
1294         
1295         
1296         if (nga == NULL || ports == NULL)
1297                 return ERR_INVARG;
1298         else if (nga->current == NULL)
1299                 return ERR_NOTLOG;
1300         
1301         
1302         attr = createEmptyList();
1303         pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
1304         ret = readRequest(nga, attr, ATTR_VLAN_PVID);
1305         if (ret != ERR_OK)
1306                 goto end;
1307         
1308         memset(ports, 0, nga->current->ports * sizeof(unsigned short));
1309         
1310         for (ln = attr->first; ln != NULL; ln = ln->next) {
1311                 at = ln->data;
1312                 ap = at->data;
1313                 ports[ap->port - 1] = ap->vlan;
1314         }
1315         
1316         
1317 end:
1318         destroyList(attr, (void(*)(void*))freeAttr);
1319         
1320         
1321         return ret;
1322 }
1323
1324
1325 int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan)
1326 {
1327         List *attr;
1328         struct attr_pvid *ap;
1329         
1330         
1331         if (nga == NULL || port < 1 || vlan < 1 || vlan > VLAN_MAX)
1332                 return ERR_INVARG;
1333         else if (nga->current == NULL)
1334                 return ERR_NOTLOG;
1335         else if (port > nga->current->ports)
1336                 return ERR_INVARG;
1337         
1338         
1339         attr = createEmptyList();
1340         ap = malloc(sizeof(struct attr_pvid));
1341         if (ap == NULL)
1342                 return ERR_MEM;
1343         ap->port = port;
1344         ap->vlan = vlan;
1345         
1346         pushBackList(attr, newAttr(ATTR_VLAN_PVID, sizeof(struct attr_pvid), ap));
1347         
1348         
1349         return writeRequest(nga, attr);
1350 }
1351
1352
1353