7 static const struct timeval default_timeout={.tv_sec=4, .tv_usec=0};
11 // ---------------------------------------------
12 struct ngadmin* ngadmin_init (const char *iface) {
17 // allocate main structure
18 nga=malloc(sizeof(struct ngadmin));
19 memset(nga, 0, sizeof(struct ngadmin));
21 strncpy(nga->iface, iface, IFNAMSIZ-1);
23 if ( startNetwork(nga)<0 ) {
28 nga->timeout=default_timeout;
29 if ( updateTimeout(nga)<0 ) {
41 // ------------------------------------
42 int ngadmin_close (struct ngadmin *nga) {
60 // ---------------------------------------------
61 int ngadmin_forceInterface (struct ngadmin *nga) {
69 if ( forceInterface(nga)!=0 ) {
79 // --------------------------------------------------------------
80 int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value) {
97 // -------------------------------------------------------------
98 int ngadmin_useGlobalBroadcast (struct ngadmin *nga, bool value) {
106 nga->globalbroad=value;
115 // ------------------------------------------------------------
116 int ngadmin_setPassword (struct ngadmin *nga, const char *pass) {
123 strncpy(nga->password, pass, PASSWORD_MAX);
132 // -------------------------------------------------------------------
133 int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv) {
138 if ( nga==NULL || tv==NULL ) {
144 if ( updateTimeout(nga)<0 ) {
155 // -----------------------------------
156 int ngadmin_scan (struct ngadmin *nga) {
159 List *attr, *swiList;
162 sent by official win client:
178 static const unsigned short hello[]={
202 // create attributes for an "hello" request
203 attr=createEmptyList();
205 pushBackList(attr, newEmptyAttr(hello[i]));
206 if ( hello[i]==ATTR_END ) break;
209 // send request to all potential switches
210 i=sendNgPacket(nga, CODE_READ_REQ, attr);
211 clearList(attr, (void(*)(void*))freeAttr);
217 // try to receive any packets until timeout
218 swiList=createEmptyList();
219 while ( recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr)>=0 ) {
220 sa=malloc(sizeof(struct swi_attr));
221 extractSwitchAttributes(sa, attr);
222 clearList(attr, (void(*)(void*))freeAttr);
223 pushBackList(swiList, sa);
226 nga->swi_count=swiList->count;
227 nga->swi_tab=convertToArray(swiList, sizeof(struct swi_attr));
236 // -----------------------------------------------------------------------
237 const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb) {
240 if ( nga==NULL || nb==NULL ) {
254 // ------------------------------------------------------------------
255 const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga) {
269 // --------------------------------------------
270 int ngadmin_login (struct ngadmin *nga, int id) {
279 } else if ( id<0 || id>=nga->swi_count ) {
284 sa=&nga->swi_tab[id];
287 attr=createEmptyList();
288 pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
289 if ( (ret=readRequest(nga, attr))==ERR_OK ) {
291 // TODO: if keep broadcasting is disabled, connect() the UDP socket so icmp errors messages (port unreachable, TTL exceeded in transit, ...) can be received
297 destroyList(attr, (void(*)(void*))freeAttr);
306 // --------------------------------------------------------------------
307 int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename) {
310 if ( nga==NULL || filename==NULL || *filename==0 ) {
312 } else if ( nga->current==NULL ) {
318 Firmware upgrade is not yet implemented.
319 This would require much more work and the use of a TFTP client.
320 Overall, it could be quite dangerous, as the switch may not check the binary
330 // -------------------------------------------------------------------
331 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
340 if ( nga==NULL || ports==NULL ) {
342 } else if ( nga->current==NULL ) {
347 attr=createEmptyList();
348 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
349 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
353 for (ln=attr->first; ln!=NULL; ln=ln->next) {
356 if ( at->attr==ATTR_PORT_STATUS && at->size>=2 && (i=p[0]-1)>=0 && i<nga->current->ports ) {
363 destroyList(attr, (void(*)(void*))freeAttr);
371 // --------------------------------------------------------
372 int ngadmin_setName (struct ngadmin *nga, const char *name) {
380 } else if ( nga->current==NULL ) {
385 attr=createEmptyList();
386 pushBackList(attr, name==NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
387 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
392 // successful, also update local name
394 nga->current->name[0]=0;
396 strncpy(nga->current->name, name, NAME_SIZE);
408 // ------------------------------------------------------------------------
409 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
418 if ( nga==NULL || ps==NULL ) {
420 } else if ( nga->current==NULL ) {
425 attr=createEmptyList();
426 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
427 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
432 for (ln=attr->first; ln!=NULL; ln=ln->next) {
434 if ( at->attr==ATTR_PORT_STATISTICS && at->size>=49 && (port=(int)(*(char*)at->data)-1)>=0 && port<nga->current->ports ) {
435 ps[port].recv=be64toh(*(unsigned long long*)(at->data+1+8*0));
436 ps[port].sent=be64toh(*(unsigned long long*)(at->data+1+8*1));
437 ps[port].crc=be64toh(*(unsigned long long*)(at->data+1+8*5));
438 // all offsets between 2 and 4 inclusive are unknown values
444 destroyList(attr, (void(*)(void*))freeAttr);
452 // ---------------------------------------------------
453 int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
458 attr=createEmptyList();
459 pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
462 return writeRequest(nga, attr);
468 // ---------------------------------------------------------------
469 int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
475 if ( nga==NULL || pass==NULL ) {
477 } else if ( nga->current==NULL ) {
482 attr=createEmptyList();
483 pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
484 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
489 // successful, also update local password
490 strncpy(nga->password, pass, PASSWORD_MAX);
501 // ----------------------------------------------------------
502 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
510 if ( nga==NULL || s==NULL ) {
512 } else if ( nga->current==NULL ) {
517 attr=createEmptyList();
518 pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
519 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
524 for (ln=attr->first; ln!=NULL; ln=ln->next) {
526 if ( at->attr==ATTR_STORM_ENABLE && at->size>=1 ) {
527 *s= *(char*)at->data!=0 ;
534 destroyList(attr, (void(*)(void*))freeAttr);
542 // ---------------------------------------------------------
543 int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
548 attr=createEmptyList();
549 pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
552 return writeRequest(nga, attr);
558 // ---------------------------------------------------------------
559 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
567 if ( nga==NULL || ports==NULL ) {
569 } else if ( nga->current==NULL ) {
574 attr=createEmptyList();
575 pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
576 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
581 for (ln=attr->first; ln!=NULL; ln=ln->next) {
583 if ( at->attr==ATTR_STORM_BITRATE && at->size>=5 && (i=(int)*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
584 ports[i]=ntohl(*(int*)(1+(char*)at->data));
590 destroyList(attr, (void(*)(void*))freeAttr);
598 // ---------------------------------------------------------------------
599 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
606 if ( nga==NULL || ports==NULL ) {
608 } else if ( nga->current==NULL ) {
613 attr=createEmptyList();
615 for (i=0; i<nga->current->ports; ++i) {
616 if ( ports[i]>=0 && ports[i]<=11 ) {
619 *(int*)(p+1)=htonl(ports[i]);
620 pushBackList(attr, newAttr(ATTR_STORM_BITRATE, 5, p));
625 return writeRequest(nga, attr);
631 // -----------------------------------------------------------
632 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
641 } __attribute__((packed)) *p;
644 if ( nga==NULL || ports==NULL ) {
646 } else if ( nga->current==NULL ) {
651 attr=createEmptyList();
652 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
653 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
654 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
659 for (ln=attr->first; ln!=NULL; ln=ln->next) {
662 if ( at->size<sizeof(*p) || p->port<1 || p->port>nga->current->ports ) continue;
663 if ( at->attr==ATTR_BITRATE_INPUT ) {
664 ports[(p->port-1)*2+0]=ntohl(p->bitrate);
665 } else if ( at->attr==ATTR_BITRATE_OUTPUT ) {
666 ports[(p->port-1)*2+1]=ntohl(p->bitrate);
672 destroyList(attr, (void(*)(void*))freeAttr);
680 // -----------------------------------------------------------------
681 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
688 if ( nga==NULL || ports==NULL ) {
690 } else if ( nga->current==NULL ) {
695 attr=createEmptyList();
697 for (i=0; i<nga->current->ports; ++i) {
698 if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
701 *(int*)(p+1)=htonl(ports[2*i+0]);
702 pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
704 if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
707 *(int*)(p+1)=htonl(ports[2*i+1]);
708 pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
713 return writeRequest(nga, attr);
719 // -------------------------------------------------
720 int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
728 if ( nga==NULL || s==NULL ) {
730 } else if ( nga->current==NULL ) {
735 attr=createEmptyList();
736 pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
737 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
742 for (ln=attr->first; ln!=NULL; ln=ln->next) {
744 if ( at->attr==ATTR_QOS_TYPE && at->size>=1 ) {
745 *s= *(char*)at->data ;
752 destroyList(attr, (void(*)(void*))freeAttr);
759 // ------------------------------------------------
760 int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
765 if ( s<QOS_PORT || s>QOS_DOT ) {
769 attr=createEmptyList();
770 pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
773 return writeRequest(nga, attr);
779 // -------------------------------------------------------
780 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
789 if ( nga==NULL || ports==NULL ) {
791 } else if ( nga->current==NULL ) {
796 attr=createEmptyList();
797 pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
798 if ( (ret=readRequest(nga, attr))<0 ) {
802 for (ln=attr->first; ln!=NULL; ln=ln->next) {
805 if ( at->attr==ATTR_QOS_CONFIG && at->size>=2 && --p[0]>=0 && p[0]<nga->current->ports ) {
806 ports[(int)p[0]]=p[1];
812 destroyList(attr, (void(*)(void*))freeAttr);
821 // --------------------------------------------------------------
822 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
829 if ( nga==NULL || ports==NULL ) {
831 } else if ( nga->current==NULL ) {
836 attr=createEmptyList();
838 for (i=0; i<nga->current->ports; ++i) {
839 if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
843 pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
848 return writeRequest(nga, attr);
854 // --------------------------------------
855 int ngadmin_restart (struct ngadmin *nga) {
860 attr=createEmptyList();
861 pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
864 return writeRequest(nga, attr);
870 // ---------------------------------------
871 int ngadmin_defaults (struct ngadmin *nga) {
877 attr=createEmptyList();
878 pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
879 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
884 // successful: delog and clean list
899 // -----------------------------------------------------
900 int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
910 if ( nga==NULL || ports==NULL ) {
912 } else if ( (sa=nga->current)==NULL ) {
917 attr=createEmptyList();
918 pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
919 if ( (ret=readRequest(nga, attr))<0 ) {
923 for (ln=attr->first; ln!=NULL; ln=ln->next) {
926 if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
928 for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
929 ports[i]=(p[2]>>(8-i))&1;
937 destroyList(attr, (void(*)(void*))freeAttr);
946 // -----------------------------------------------------------
947 int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
957 } else if ( (sa=nga->current)==NULL ) {
962 p=malloc(3); // FIXME: if ports>8
965 if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
967 for (i=1; i<=sa->ports; ++i) {
969 p[2]|=(ports[i]&1)<<(8-i);
974 attr=createEmptyList();
975 pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
978 return writeRequest(nga, attr);
984 // ----------------------------------------------------------------
985 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
996 if ( nga==NULL || ic==NULL ) {
998 } else if ( (sa=nga->current)==NULL ) {
1003 ATTR_IGMP_ENABLE_VLAN
1007 Apparently, read-querying these attributes at the same time causes the switch to reply garbage.
1008 Here we are forced to do like the official win app and send a separate request for each attribute.
1012 attr=createEmptyList();
1013 memset(ic, 0, sizeof(struct igmp_conf));
1016 pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
1017 if ( (ret=readRequest(nga, attr))<0 ) {
1021 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1024 if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
1025 ic->enable= ntohs(s[0])!=0 ;
1026 ic->vlan=htons(s[1]);
1031 clearList(attr, (void(*)(void*))freeAttr);
1034 pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
1035 if ( (ret=readRequest(nga, attr))<0 ) {
1039 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1042 if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
1043 ic->block= p[0]!=0 ;
1048 clearList(attr, (void(*)(void*))freeAttr);
1051 pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
1052 if ( (ret=readRequest(nga, attr))<0 ) {
1056 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1059 if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
1060 ic->validate= p[0]!=0 ;
1068 destroyList(attr, (void(*)(void*))freeAttr);
1077 // ----------------------------------------------------------------------
1078 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
1082 struct swi_attr *sa;
1085 if ( nga==NULL || ic==NULL ) {
1087 } else if ( (sa=nga->current)==NULL ) {
1092 s=malloc(2*sizeof(short));
1093 s[0]=htons(ic->enable!=false);
1094 s[1]=htons(ic->vlan&0x0FFF);
1096 attr=createEmptyList();
1097 pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, 2*sizeof(short), s));
1098 pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block!=false ));
1099 pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate!=false ));
1102 return writeRequest(nga, attr);
1108 // ----------------------------------------------------------------------
1109 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
1115 struct swi_attr *sa;
1119 if ( nga==NULL || ct==NULL ) {
1121 } else if ( (sa=nga->current)==NULL ) {
1126 attr=createEmptyList();
1128 for (i=0; i<nb; ++i) {
1129 if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
1134 pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
1136 ret=writeRequest(nga, attr);
1138 if ( ret<0 ) goto end;
1140 // the list is destroyed by writeRequest, so we need to recreate it
1141 attr=createEmptyList();
1142 pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
1144 if ( (ret=readRequest(nga, attr))<0 ) goto end;
1146 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1149 if ( at->attr==ATTR_CABLETEST_RESULT && at->size>=9 && p[0]==ct[i].port ) {
1150 ct[i].v1=ntohl(*(int*)&p[1]);
1151 ct[i].v2=ntohl(*(int*)&p[5]);
1156 // just empty the list, it will be used at next iteration
1157 clearList(attr, (void(*)(void*))freeAttr);
1164 destroyList(attr, (void(*)(void*))freeAttr);
1172 // --------------------------------------------------------------------
1173 int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) {
1176 struct swi_attr *sa;
1180 if ( nga==NULL || nc==NULL ) {
1182 } else if ( (sa=nga->current)==NULL ) {
1187 attr=createEmptyList();
1190 pushBackList(attr, newByteAttr(ATTR_DHCP, 1));
1192 pushBackList(attr, newByteAttr(ATTR_DHCP, 0));
1193 // only add non-null values
1194 if ( nc->ip.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
1195 if ( nc->netmask.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
1196 if ( nc->gw.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
1199 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
1204 // update local values
1205 sa->nc.dhcp=nc->dhcp;
1207 if ( nc->ip.s_addr!=0 ) sa->nc.ip=nc->ip;
1208 if ( nc->netmask.s_addr!=0 ) sa->nc.netmask=nc->netmask;
1209 if ( nc->gw.s_addr!=0 ) sa->nc.gw=nc->gw;
1221 // --------------------------------------------------
1222 int ngadmin_getVLANType (struct ngadmin *nga, int *t) {
1230 if ( nga==NULL || t==NULL ) {
1232 } else if ( nga->current==NULL ) {
1237 attr=createEmptyList();
1238 pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
1239 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1244 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1246 if ( at->attr==ATTR_VLAN_TYPE && at->size>=1 ) {
1247 *t= (int)*(char*)at->data ;
1254 destroyList(attr, (void(*)(void*))freeAttr);
1262 // -------------------------------------------------
1263 int ngadmin_setVLANType (struct ngadmin *nga, int t) {
1266 struct swi_attr *sa;
1269 if ( nga==NULL || t<1 || t>4 ) {
1271 } else if ( (sa=nga->current)==NULL ) {
1276 attr=createEmptyList();
1277 pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
1280 return writeRequest(nga, attr);
1286 // ------------------------------------------------------------------------------------------------------
1287 int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) {
1292 struct swi_attr *sa;
1293 int ret=ERR_OK, total, i;
1297 if ( nga==NULL || vlans==NULL || ports==NULL || nb==NULL || *nb<=0 ) {
1299 } else if ( (sa=nga->current)==NULL ) {
1307 attr=createEmptyList();
1308 pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
1309 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1314 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1317 if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1318 for (i=0; i<sa->ports; ++i) {
1319 if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
1320 else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
1321 else ports[i]=VLAN_NO;
1323 *vlans++=ntohs(*(unsigned short*)p);
1325 if ( ++*nb>total ) break; // no more room
1331 destroyList(attr, (void(*)(void*))freeAttr);
1339 // ----------------------------------------------------------------------------------------
1340 int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports) {
1345 struct swi_attr *sa;
1350 if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
1352 } else if ( (sa=nga->current)==NULL ) {
1357 attr=createEmptyList();
1358 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1359 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1364 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1367 if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1368 for (i=0; i<sa->ports; ++i) {
1369 if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
1370 else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
1371 else ports[i]=VLAN_NO;
1379 destroyList(attr, (void(*)(void*))freeAttr);
1387 // ----------------------------------------------------------------------------------------------
1388 int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) {
1393 struct swi_attr *sa;
1398 if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
1400 } else if ( (sa=nga->current)==NULL ) {
1405 // if nothing is to be changed, do nothing
1406 for (i=0; i<sa->ports && ports[i]==VLAN_UNSPEC; ++i);
1407 if ( i==sa->ports ) goto end;
1410 attr=createEmptyList();
1413 *(unsigned short*)p=htons(vlan);
1414 *(unsigned short*)&p[2]=0;
1416 // if all is to be changed, we do not need to read old config
1417 if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) {
1419 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1420 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1424 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1426 if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1427 *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2);
1432 clearList(attr, (void(*)(void*))freeAttr);
1438 for (i=0; i<sa->ports; ++i) {
1440 switch ( ports[i] ) {
1457 pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p));
1458 ret=writeRequest(nga, attr);
1463 destroyList(attr, (void(*)(void*))freeAttr);
1472 // ---------------------------------------------------------------
1473 int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan) {
1476 struct swi_attr *sa;
1479 if ( nga==NULL || vlan<1 || vlan>VLAN_MAX ) {
1481 } else if ( (sa=nga->current)==NULL ) {
1486 attr=createEmptyList();
1487 pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
1490 return writeRequest(nga, attr);
1496 // ----------------------------------------------------------------
1497 int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports) {
1502 struct swi_attr *sa;
1507 if ( nga==NULL || ports==NULL ) {
1509 } else if ( (sa=nga->current)==NULL ) {
1514 attr=createEmptyList();
1515 pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
1516 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1521 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1524 if ( at->attr==ATTR_VLAN_PVID && at->size>=3 && p[0]>=1 && p[0]<=sa->ports ) {
1525 ports[p[0]-1]=htons(*(unsigned short*)&p[1]);
1531 destroyList(attr, (void(*)(void*))freeAttr);
1539 // -------------------------------------------------------------------------------
1540 int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan) {
1543 struct swi_attr *sa;
1547 if ( nga==NULL || port<1 || vlan<1 || vlan>VLAN_MAX ) {
1549 } else if ( (sa=nga->current)==NULL ) {
1551 } else if ( port>sa->ports ) {
1556 attr=createEmptyList();
1559 *(unsigned short*)&p[1]=htons(vlan);
1561 pushBackList(attr, newAttr(ATTR_VLAN_PVID, 3, p));
1564 return writeRequest(nga, attr);