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 // FIXME: end after timeout whatever received packet is good or not
220 while ( recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr)>=0 ) {
221 sa=malloc(sizeof(struct swi_attr));
222 extractSwitchAttributes(sa, attr);
223 clearList(attr, (void(*)(void*))freeAttr);
224 pushBackList(swiList, sa);
227 nga->swi_count=swiList->count;
228 nga->swi_tab=convertToArray(swiList, sizeof(struct swi_attr));
229 destroyList(swiList, free);
230 destroyList(attr, (void(*)(void*))freeAttr);
239 // -----------------------------------------------------------------------
240 const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb) {
243 if ( nga==NULL || nb==NULL ) {
257 // ------------------------------------------------------------------
258 const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga) {
272 // --------------------------------------------
273 int ngadmin_login (struct ngadmin *nga, int id) {
282 } else if ( id<0 || id>=nga->swi_count ) {
287 sa=&nga->swi_tab[id];
290 attr=createEmptyList();
291 pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
292 if ( (ret=readRequest(nga, attr))==ERR_OK ) {
294 // TODO: if keep broadcasting is disabled, connect() the UDP socket so icmp errors messages (port unreachable, TTL exceeded in transit, ...) can be received
300 destroyList(attr, (void(*)(void*))freeAttr);
309 // --------------------------------------------------------------------
310 int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename) {
313 if ( nga==NULL || filename==NULL || *filename==0 ) {
315 } else if ( nga->current==NULL ) {
321 Firmware upgrade is not yet implemented.
322 This would require much more work and the use of a TFTP client.
323 Overall, it could be quite dangerous, as the switch may not check the binary
333 // -------------------------------------------------------------------
334 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
343 if ( nga==NULL || ports==NULL ) {
345 } else if ( nga->current==NULL ) {
350 attr=createEmptyList();
351 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
352 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
356 for (ln=attr->first; ln!=NULL; ln=ln->next) {
359 if ( at->attr==ATTR_PORT_STATUS && at->size>=2 && (i=p[0]-1)>=0 && i<nga->current->ports ) {
366 destroyList(attr, (void(*)(void*))freeAttr);
375 // --------------------------------------------------------
376 int ngadmin_setName (struct ngadmin *nga, const char *name) {
384 } else if ( nga->current==NULL ) {
389 attr=createEmptyList();
390 pushBackList(attr, name==NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
391 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
396 // successful, also update local name
398 nga->current->name[0]=0;
400 strncpy(nga->current->name, name, NAME_SIZE);
412 // ------------------------------------------------------------------------
413 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
422 if ( nga==NULL || ps==NULL ) {
424 } else if ( nga->current==NULL ) {
429 attr=createEmptyList();
430 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
431 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
436 for (ln=attr->first; ln!=NULL; ln=ln->next) {
438 if ( at->attr==ATTR_PORT_STATISTICS && at->size>=49 && (port=(int)(*(char*)at->data)-1)>=0 && port<nga->current->ports ) {
439 ps[port].recv=be64toh(*(unsigned long long*)(at->data+1+8*0));
440 ps[port].sent=be64toh(*(unsigned long long*)(at->data+1+8*1));
441 ps[port].crc=be64toh(*(unsigned long long*)(at->data+1+8*5));
442 // all offsets between 2 and 4 inclusive are unknown values
448 destroyList(attr, (void(*)(void*))freeAttr);
457 // ---------------------------------------------------
458 int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
463 attr=createEmptyList();
464 pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
467 return writeRequest(nga, attr);
473 // ---------------------------------------------------------------
474 int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
480 if ( nga==NULL || pass==NULL ) {
482 } else if ( nga->current==NULL ) {
487 attr=createEmptyList();
488 pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
489 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
494 // successful, also update local password
495 strncpy(nga->password, pass, PASSWORD_MAX);
506 // ----------------------------------------------------------
507 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
515 if ( nga==NULL || s==NULL ) {
517 } else if ( nga->current==NULL ) {
522 attr=createEmptyList();
523 pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
524 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
529 for (ln=attr->first; ln!=NULL; ln=ln->next) {
531 if ( at->attr==ATTR_STORM_ENABLE && at->size>=1 ) {
532 *s= *(char*)at->data!=0 ;
539 destroyList(attr, (void(*)(void*))freeAttr);
548 // ---------------------------------------------------------
549 int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
554 attr=createEmptyList();
555 pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
558 return writeRequest(nga, attr);
564 // ---------------------------------------------------------------
565 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
573 if ( nga==NULL || ports==NULL ) {
575 } else if ( nga->current==NULL ) {
580 attr=createEmptyList();
581 pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
582 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
587 for (ln=attr->first; ln!=NULL; ln=ln->next) {
589 if ( at->attr==ATTR_STORM_BITRATE && at->size>=5 && (i=(int)*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
590 ports[i]=ntohl(*(int*)(1+(char*)at->data));
596 destroyList(attr, (void(*)(void*))freeAttr);
605 // ---------------------------------------------------------------------
606 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
613 if ( nga==NULL || ports==NULL ) {
615 } else if ( nga->current==NULL ) {
620 attr=createEmptyList();
622 for (i=0; i<nga->current->ports; ++i) {
623 if ( ports[i]>=0 && ports[i]<=11 ) {
626 *(int*)(p+1)=htonl(ports[i]);
627 pushBackList(attr, newAttr(ATTR_STORM_BITRATE, 5, p));
632 return writeRequest(nga, attr);
638 // -----------------------------------------------------------
639 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
648 } __attribute__((packed)) *p;
651 if ( nga==NULL || ports==NULL ) {
653 } else if ( nga->current==NULL ) {
658 attr=createEmptyList();
659 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
660 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
661 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
666 for (ln=attr->first; ln!=NULL; ln=ln->next) {
669 if ( at->size<sizeof(*p) || p->port<1 || p->port>nga->current->ports ) continue;
670 if ( at->attr==ATTR_BITRATE_INPUT ) {
671 ports[(p->port-1)*2+0]=ntohl(p->bitrate);
672 } else if ( at->attr==ATTR_BITRATE_OUTPUT ) {
673 ports[(p->port-1)*2+1]=ntohl(p->bitrate);
679 destroyList(attr, (void(*)(void*))freeAttr);
688 // -----------------------------------------------------------------
689 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
696 if ( nga==NULL || ports==NULL ) {
698 } else if ( nga->current==NULL ) {
703 attr=createEmptyList();
705 for (i=0; i<nga->current->ports; ++i) {
706 if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
709 *(int*)(p+1)=htonl(ports[2*i+0]);
710 pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
712 if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
715 *(int*)(p+1)=htonl(ports[2*i+1]);
716 pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
721 return writeRequest(nga, attr);
727 // -------------------------------------------------
728 int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
736 if ( nga==NULL || s==NULL ) {
738 } else if ( nga->current==NULL ) {
743 attr=createEmptyList();
744 pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
745 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
750 for (ln=attr->first; ln!=NULL; ln=ln->next) {
752 if ( at->attr==ATTR_QOS_TYPE && at->size>=1 ) {
753 *s= *(char*)at->data ;
760 destroyList(attr, (void(*)(void*))freeAttr);
768 // ------------------------------------------------
769 int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
774 if ( s<QOS_PORT || s>QOS_DOT ) {
778 attr=createEmptyList();
779 pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
782 return writeRequest(nga, attr);
788 // -------------------------------------------------------
789 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
798 if ( nga==NULL || ports==NULL ) {
800 } else if ( nga->current==NULL ) {
805 attr=createEmptyList();
806 pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
807 if ( (ret=readRequest(nga, attr))<0 ) {
811 for (ln=attr->first; ln!=NULL; ln=ln->next) {
814 if ( at->attr==ATTR_QOS_CONFIG && at->size>=2 && --p[0]>=0 && p[0]<nga->current->ports ) {
815 ports[(int)p[0]]=p[1];
821 destroyList(attr, (void(*)(void*))freeAttr);
830 // --------------------------------------------------------------
831 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
838 if ( nga==NULL || ports==NULL ) {
840 } else if ( nga->current==NULL ) {
845 attr=createEmptyList();
847 for (i=0; i<nga->current->ports; ++i) {
848 if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
852 pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
857 return writeRequest(nga, attr);
863 // --------------------------------------
864 int ngadmin_restart (struct ngadmin *nga) {
869 attr=createEmptyList();
870 pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
873 return writeRequest(nga, attr);
879 // ---------------------------------------
880 int ngadmin_defaults (struct ngadmin *nga) {
886 attr=createEmptyList();
887 pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
888 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
893 // successful: delog and clean list
908 // -----------------------------------------------------
909 int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
919 if ( nga==NULL || ports==NULL ) {
921 } else if ( (sa=nga->current)==NULL ) {
926 attr=createEmptyList();
927 pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
928 if ( (ret=readRequest(nga, attr))<0 ) {
932 for (ln=attr->first; ln!=NULL; ln=ln->next) {
935 if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
937 for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
938 ports[i]=(p[2]>>(8-i))&1;
946 destroyList(attr, (void(*)(void*))freeAttr);
955 // -----------------------------------------------------------
956 int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
966 } else if ( (sa=nga->current)==NULL ) {
971 p=malloc(3); // FIXME: if ports>8
974 if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
976 for (i=1; i<=sa->ports; ++i) {
978 p[2]|=(ports[i]&1)<<(8-i);
983 attr=createEmptyList();
984 pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
987 return writeRequest(nga, attr);
993 // ----------------------------------------------------------------
994 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
1005 if ( nga==NULL || ic==NULL ) {
1007 } else if ( (sa=nga->current)==NULL ) {
1012 ATTR_IGMP_ENABLE_VLAN
1016 Apparently, read-querying these attributes at the same time causes the switch to reply garbage.
1017 Here we are forced to do like the official win app and send a separate request for each attribute.
1021 attr=createEmptyList();
1022 memset(ic, 0, sizeof(struct igmp_conf));
1025 pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
1026 if ( (ret=readRequest(nga, attr))<0 ) {
1030 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1033 if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
1034 ic->enable= ntohs(s[0])!=0 ;
1035 ic->vlan=htons(s[1]);
1040 clearList(attr, (void(*)(void*))freeAttr);
1043 pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
1044 if ( (ret=readRequest(nga, attr))<0 ) {
1048 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1051 if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
1052 ic->block= p[0]!=0 ;
1057 clearList(attr, (void(*)(void*))freeAttr);
1060 pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
1061 if ( (ret=readRequest(nga, attr))<0 ) {
1065 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1068 if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
1069 ic->validate= p[0]!=0 ;
1077 destroyList(attr, (void(*)(void*))freeAttr);
1086 // ----------------------------------------------------------------------
1087 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
1091 struct swi_attr *sa;
1094 if ( nga==NULL || ic==NULL ) {
1096 } else if ( (sa=nga->current)==NULL ) {
1101 s=malloc(2*sizeof(short));
1102 s[0]=htons(ic->enable!=false);
1103 s[1]=htons(ic->vlan&0x0FFF);
1105 attr=createEmptyList();
1106 pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, 2*sizeof(short), s));
1107 pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block!=false ));
1108 pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate!=false ));
1111 return writeRequest(nga, attr);
1117 // ----------------------------------------------------------------------
1118 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
1124 struct swi_attr *sa;
1128 if ( nga==NULL || ct==NULL ) {
1130 } else if ( (sa=nga->current)==NULL ) {
1135 attr=createEmptyList();
1137 for (i=0; i<nb; ++i) {
1138 if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
1143 pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
1145 ret=writeRequest(nga, attr);
1147 if ( ret<0 ) goto end;
1149 // the list is destroyed by writeRequest, so we need to recreate it
1150 attr=createEmptyList();
1151 pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
1153 if ( (ret=readRequest(nga, attr))<0 ) goto end;
1155 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1158 if ( at->attr==ATTR_CABLETEST_RESULT && at->size>=9 && p[0]==ct[i].port ) {
1159 ct[i].v1=ntohl(*(int*)&p[1]);
1160 ct[i].v2=ntohl(*(int*)&p[5]);
1165 // just empty the list, it will be used at next iteration
1166 clearList(attr, (void(*)(void*))freeAttr);
1173 destroyList(attr, (void(*)(void*))freeAttr);
1182 // --------------------------------------------------------------------
1183 int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) {
1186 struct swi_attr *sa;
1190 if ( nga==NULL || nc==NULL ) {
1192 } else if ( (sa=nga->current)==NULL ) {
1197 attr=createEmptyList();
1200 pushBackList(attr, newByteAttr(ATTR_DHCP, 1));
1202 pushBackList(attr, newByteAttr(ATTR_DHCP, 0));
1203 // only add non-null values
1204 if ( nc->ip.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
1205 if ( nc->netmask.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
1206 if ( nc->gw.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
1209 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
1214 // update local values
1215 sa->nc.dhcp=nc->dhcp;
1217 if ( nc->ip.s_addr!=0 ) sa->nc.ip=nc->ip;
1218 if ( nc->netmask.s_addr!=0 ) sa->nc.netmask=nc->netmask;
1219 if ( nc->gw.s_addr!=0 ) sa->nc.gw=nc->gw;
1231 // --------------------------------------------------
1232 int ngadmin_getVLANType (struct ngadmin *nga, int *t) {
1240 if ( nga==NULL || t==NULL ) {
1242 } else if ( nga->current==NULL ) {
1247 attr=createEmptyList();
1248 pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
1249 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1254 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1256 if ( at->attr==ATTR_VLAN_TYPE && at->size>=1 ) {
1257 *t= (int)*(char*)at->data ;
1264 destroyList(attr, (void(*)(void*))freeAttr);
1273 // -------------------------------------------------
1274 int ngadmin_setVLANType (struct ngadmin *nga, int t) {
1277 struct swi_attr *sa;
1280 if ( nga==NULL || t<1 || t>4 ) {
1282 } else if ( (sa=nga->current)==NULL ) {
1287 attr=createEmptyList();
1288 pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
1291 return writeRequest(nga, attr);
1297 // ------------------------------------------------------------------------------------------------------
1298 int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) {
1303 struct swi_attr *sa;
1304 int ret=ERR_OK, total, i;
1308 if ( nga==NULL || vlans==NULL || ports==NULL || nb==NULL || *nb<=0 ) {
1310 } else if ( (sa=nga->current)==NULL ) {
1318 attr=createEmptyList();
1319 pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
1320 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1325 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1328 if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1329 for (i=0; i<sa->ports; ++i) {
1330 if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
1331 else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
1332 else ports[i]=VLAN_NO;
1334 *vlans++=ntohs(*(unsigned short*)p);
1336 if ( ++*nb>total ) break; // no more room
1342 destroyList(attr, (void(*)(void*))freeAttr);
1351 // ----------------------------------------------------------------------------------------
1352 int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports) {
1357 struct swi_attr *sa;
1362 if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
1364 } else if ( (sa=nga->current)==NULL ) {
1369 attr=createEmptyList();
1370 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1371 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1376 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1379 if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1380 for (i=0; i<sa->ports; ++i) {
1381 if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
1382 else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
1383 else ports[i]=VLAN_NO;
1391 destroyList(attr, (void(*)(void*))freeAttr);
1400 // ----------------------------------------------------------------------------------------------
1401 int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) {
1406 struct swi_attr *sa;
1411 if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
1413 } else if ( (sa=nga->current)==NULL ) {
1418 // if nothing is to be changed, do nothing
1419 for (i=0; i<sa->ports && ports[i]==VLAN_UNSPEC; ++i);
1420 if ( i==sa->ports ) goto end;
1423 attr=createEmptyList();
1426 *(unsigned short*)p=htons(vlan);
1427 *(unsigned short*)&p[2]=0;
1429 // if all is to be changed, we do not need to read old config
1430 if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) {
1432 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1433 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1437 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1439 if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1440 *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2);
1445 clearList(attr, (void(*)(void*))freeAttr);
1451 for (i=0; i<sa->ports; ++i) {
1453 switch ( ports[i] ) {
1469 pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p));
1470 ret=writeRequest(nga, attr);
1475 destroyList(attr, (void(*)(void*))freeAttr);
1485 // ---------------------------------------------------------------
1486 int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan) {
1489 struct swi_attr *sa;
1492 if ( nga==NULL || vlan<1 || vlan>VLAN_MAX ) {
1494 } else if ( (sa=nga->current)==NULL ) {
1499 attr=createEmptyList();
1500 pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
1503 return writeRequest(nga, attr);
1509 // ----------------------------------------------------------------
1510 int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports) {
1515 struct swi_attr *sa;
1520 if ( nga==NULL || ports==NULL ) {
1522 } else if ( (sa=nga->current)==NULL ) {
1527 attr=createEmptyList();
1528 pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
1529 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1534 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1537 if ( at->attr==ATTR_VLAN_PVID && at->size>=3 && p[0]>=1 && p[0]<=sa->ports ) {
1538 ports[p[0]-1]=htons(*(unsigned short*)&p[1]);
1544 destroyList(attr, (void(*)(void*))freeAttr);
1553 // -------------------------------------------------------------------------------
1554 int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan) {
1557 struct swi_attr *sa;
1561 if ( nga==NULL || port<1 || vlan<1 || vlan>VLAN_MAX ) {
1563 } else if ( (sa=nga->current)==NULL ) {
1565 } else if ( port>sa->ports ) {
1570 attr=createEmptyList();
1573 *(unsigned short*)&p[1]=htons(vlan);
1575 pushBackList(attr, newAttr(ATTR_VLAN_PVID, 3, p));
1578 return writeRequest(nga, attr);