13 static const struct timeval default_timeout = {.tv_sec = 4, .tv_usec = 0};
17 struct ngadmin* ngadmin_init (const char *iface)
22 /* allocate main structure */
23 nga = malloc(sizeof(struct ngadmin));
24 memset(nga, 0, sizeof(struct ngadmin));
26 strncpy(nga->iface, iface, IFNAMSIZ - 1);
28 if (startNetwork(nga) < 0) {
33 nga->timeout = default_timeout;
34 if (updateTimeout(nga) < 0) {
44 int ngadmin_close (struct ngadmin *nga)
57 int ngadmin_forceInterface (struct ngadmin *nga)
62 return forceInterface(nga) == 0 ? ERR_OK : ERR_NET;
66 int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value)
71 nga->keepbroad = value;
77 int ngadmin_useGlobalBroadcast (struct ngadmin *nga, bool value)
82 nga->globalbroad = value;
88 int ngadmin_setPassword (struct ngadmin *nga, const char *pass)
93 strncpy(nga->password, pass, PASSWORD_MAX);
99 int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv)
104 if (nga == NULL || tv == NULL)
108 if (updateTimeout(nga) < 0)
116 int ngadmin_scan (struct ngadmin *nga)
119 List *attr, *swiList;
122 sent by official win client:
138 static const unsigned short hello[] = {
161 /* create attributes for an "hello" request */
162 attr = createEmptyList();
164 pushBackList(attr, newEmptyAttr(hello[i]));
165 if (hello[i] == ATTR_END)
169 /* send request to all potential switches */
170 i = sendNgPacket(nga, CODE_READ_REQ, attr);
171 clearList(attr, (void(*)(void*))freeAttr);
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) >= 0) {
181 sa = malloc(sizeof(struct swi_attr));
184 extractSwitchAttributes(sa, attr);
185 clearList(attr, (void(*)(void*))freeAttr);
186 pushBackList(swiList, sa);
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);
199 const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb)
201 if (nga == NULL || nb == NULL)
204 *nb = nga->swi_count;
210 const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga)
219 int ngadmin_login (struct ngadmin *nga, int id)
229 else if (id < 0 || id >= nga->swi_count)
232 sa = &nga->swi_tab[id];
234 nga->encrypt_pass = false;
236 attr = createEmptyList();
237 pushBackList(attr, newEmptyAttr(ATTR_ENCPASS));
238 ret = readRequest(nga, attr);
242 filterAttributes(attr, ATTR_ENCPASS, ATTR_END);
243 if (attr->first != NULL) {
244 at = attr->first->data;
245 nga->encrypt_pass = (at->size == 4 && ntohl(*(unsigned int*)at->data) == 1);
247 clearList(attr, (void(*)(void*))freeAttr);
249 /* Strangely, passwords must never be encrypted inside a read request,
250 * or it will be rejected. Seems more to be a firmware bug. */
251 pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
252 ret = readRequest(nga, attr);
253 if (ret == ERR_OK ) {
254 /* login succeeded */
255 /* TODO: if keep broadcasting is disabled, connect() the UDP
256 socket so icmp errors messages (port unreachable, TTL exceeded
257 in transit, ...) can be received */
264 destroyList(attr, (void(*)(void*))freeAttr);
271 int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename)
273 if (nga == NULL || filename == NULL || *filename == 0)
275 else if (nga->current == NULL)
279 Firmware upgrade is not yet implemented.
280 This would require much more work and the use of a TFTP client.
281 Overall, it could be quite dangerous, as the switch may not check the binary
289 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
295 struct attr_port_status *ps;
298 if (nga == NULL || ports == NULL)
300 else if (nga->current == NULL)
304 attr = createEmptyList();
305 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
306 ret = readRequest(nga, attr);
310 filterAttributes(attr, ATTR_PORT_STATUS, ATTR_END);
312 memset(ports, SPEED_UNK, nga->current->ports);
314 for (ln = attr->first; ln != NULL; ln = ln->next) {
317 ports[ps->port - 1] = ps->status;
321 destroyList(attr, (void(*)(void*))freeAttr);
328 int ngadmin_setName (struct ngadmin *nga, const char *name)
336 else if (nga->current == NULL)
340 attr = createEmptyList();
341 pushBackList(attr, name == NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
342 ret = writeRequest(nga, attr);
346 /* successful, also update local name */
348 memset(nga->current->name, '\0', NAME_SIZE);
350 strncpy(nga->current->name, name, NAME_SIZE);
357 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
363 struct attr_port_stat *aps;
366 if (nga == NULL || ps == NULL)
368 else if (nga->current == NULL)
371 attr = createEmptyList();
372 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
373 ret = readRequest(nga, attr);
377 filterAttributes(attr, ATTR_PORT_STATISTICS, ATTR_END);
379 memset(ps, 0, nga->current->ports * sizeof(struct port_stats));
381 for (ln = attr->first; ln != NULL; ln = ln->next) {
384 ps[aps->port -1].recv = aps->recv;
385 ps[aps->port -1].sent = aps->sent;
386 ps[aps->port -1].crc = aps->crc;
390 destroyList(attr, (void(*)(void*))freeAttr);
397 int ngadmin_resetPortsStatistics (struct ngadmin *nga)
402 attr = createEmptyList();
403 pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
406 return writeRequest(nga, attr);
410 int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
417 if (nga == NULL || pass == NULL)
419 else if (nga->current == NULL)
423 attr = createEmptyList();
424 at = newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass));
425 if (nga->encrypt_pass)
426 passwordEndecode(at->data, at->size);
427 pushBackList(attr, at);
428 ret = writeRequest(nga, attr);
433 /* successful, also update local password */
434 strncpy(nga->password, pass, PASSWORD_MAX);
442 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s)
449 if (nga == NULL || s == NULL)
451 else if (nga->current == NULL)
455 attr = createEmptyList();
456 pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
457 ret = readRequest(nga, attr);
461 filterAttributes(attr, ATTR_STORM_ENABLE, ATTR_END);
465 if (attr->first != NULL) {
466 at = attr->first->data;
467 *s = *(char*)at->data;
472 destroyList(attr, (void(*)(void*))freeAttr);
479 int ngadmin_setStormFilterState (struct ngadmin *nga, int s)
484 attr = createEmptyList();
485 pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s != 0));
488 return writeRequest(nga, attr);
492 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
497 int ret = ERR_OK, port;
498 struct attr_bitrate *sb;
501 if (nga == NULL || ports == NULL)
503 else if (nga->current == NULL)
507 attr = createEmptyList();
508 pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
509 ret = readRequest(nga, attr);
513 filterAttributes(attr, ATTR_STORM_BITRATE, ATTR_END);
515 for (port = 0; port < nga->current->ports; port++)
516 ports[port] = BITRATE_UNSPEC;
518 for (ln = attr->first; ln != NULL; ln = ln->next) {
521 ports[sb->port - 1] = sb->bitrate;
526 destroyList(attr, (void(*)(void*))freeAttr);
533 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports)
537 struct attr_bitrate *sb;
540 if (nga == NULL || ports == NULL)
542 else if (nga->current == NULL)
546 attr = createEmptyList();
548 for (port = 0; port < nga->current->ports; port++) {
549 if (ports[port] != BITRATE_UNSPEC) {
550 sb = malloc(sizeof(struct attr_bitrate));
554 sb->bitrate = ports[port];
555 pushBackList(attr, newAttr(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), sb));
559 return writeRequest(nga, attr);
563 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
568 int ret = ERR_OK, port;
569 struct attr_bitrate *pb;
572 if (nga == NULL || ports == NULL)
574 else if (nga->current == NULL)
578 attr = createEmptyList();
579 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
580 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
581 ret = readRequest(nga, attr);
586 for (port = 0; port < nga->current->ports; port++) {
587 ports[2 * port + 0] = BITRATE_UNSPEC;
588 ports[2 * port + 1] = BITRATE_UNSPEC;
591 for (ln = attr->first; ln != NULL; ln = ln->next) {
594 if (at->attr == ATTR_BITRATE_INPUT)
595 ports[(pb->port - 1) * 2 + 0] = pb->bitrate;
596 else if (at->attr == ATTR_BITRATE_OUTPUT)
597 ports[(pb->port - 1) * 2 + 1] = pb->bitrate;
602 destroyList(attr, (void(*)(void*))freeAttr);
608 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports)
612 struct attr_bitrate *pb;
615 if (nga == NULL || ports == NULL)
617 else if (nga->current == NULL)
621 attr = createEmptyList();
623 for (port = 0; port < nga->current->ports; port++) {
624 if (ports[2 * port + 0] >= BITRATE_NOLIMIT && ports[2 * port + 0] <= BITRATE_512M) {
625 pb = malloc(sizeof(struct attr_bitrate));
629 pb->bitrate = ports[2 * port + 0];
630 pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), pb));
632 if (ports[2 * port + 1] >= BITRATE_NOLIMIT && ports[2 * port + 1] <= BITRATE_512M) {
633 pb = malloc(sizeof(struct attr_bitrate));
637 pb->bitrate = ports[2 * port + 1];
638 pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), pb));
643 return writeRequest(nga, attr);
647 int ngadmin_getQOSMode (struct ngadmin *nga, int *s)
654 if (nga == NULL || s == NULL)
656 else if (nga->current == NULL)
660 attr = createEmptyList();
661 pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
662 ret = readRequest(nga, attr);
666 filterAttributes(attr, ATTR_QOS_TYPE, ATTR_END);
670 if (attr->first != NULL) {
671 at = attr->first->data;
672 *s = *(char*)at->data;
677 destroyList(attr, (void(*)(void*))freeAttr);
684 int ngadmin_setQOSMode (struct ngadmin *nga, int s)
689 attr = createEmptyList();
690 pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
693 return writeRequest(nga, attr);
697 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
702 int ret = ERR_OK, port;
706 if (nga == NULL || ports == NULL)
708 else if (nga->current == NULL)
712 attr = createEmptyList();
713 pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
714 ret = readRequest(nga, attr);
718 filterAttributes(attr, ATTR_QOS_CONFIG, ATTR_END);
720 for (port = 0; port < nga->current->ports; port++)
721 ports[port] = PRIO_UNSPEC;
723 for (ln = attr->first; ln != NULL; ln = ln->next) {
726 ports[aq->port - 1] = aq->prio;
731 destroyList(attr, (void(*)(void*))freeAttr);
738 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports)
745 if (nga == NULL || ports == NULL)
747 else if (nga->current == NULL)
751 attr = createEmptyList();
753 for (port = 0; port < nga->current->ports; port++) {
754 if (ports[port] >= PRIO_HIGH && ports[port] <= PRIO_LOW) {
755 aq = malloc(sizeof(struct attr_qos));
759 aq->prio = ports[port];
760 pushBackList(attr, newAttr(ATTR_QOS_CONFIG, sizeof(struct attr_qos), aq));
765 return writeRequest(nga, attr);
769 int ngadmin_restart (struct ngadmin *nga)
774 attr = createEmptyList();
775 pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
778 return writeRequest(nga, attr);
782 int ngadmin_defaults (struct ngadmin *nga)
788 attr = createEmptyList();
789 pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
790 ret = writeRequest(nga, attr);
795 /* successful: delog and clean list */
806 int ngadmin_getMirror (struct ngadmin *nga, char *ports)
813 if (nga == NULL || ports == NULL)
815 else if (nga->current == NULL)
819 attr = createEmptyList();
820 pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
821 ret = readRequest(nga, attr);
825 filterAttributes(attr, ATTR_MIRROR, ATTR_END);
827 memset(ports, 0, 1 + nga->current->ports);
829 if (attr->first != NULL) {
830 at = attr->first->data;
831 memcpy(ports, at->data, 1 + nga->current->ports);
836 destroyList(attr, (void(*)(void*))freeAttr);
843 int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
851 else if (nga->current == NULL)
855 p = malloc(1 + nga->current->ports);
860 memset(p, 0, 1 + nga->current->ports);
862 memcpy(p, ports, 1 + nga->current->ports);
864 attr = createEmptyList();
865 pushBackList(attr, newAttr(ATTR_MIRROR, 1 + nga->current->ports, p));
868 return writeRequest(nga, attr);
872 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic)
877 struct attr_igmp_vlan *aiv;
880 if (nga == NULL || ic == NULL)
882 else if (nga->current == NULL)
886 ATTR_IGMP_ENABLE_VLAN
890 Apparently, read-querying these attributes at the same time causes the switch to reply garbage.
891 Here we are forced to do like the official win app and send a separate request for each attribute.
895 attr = createEmptyList();
896 memset(ic, 0, sizeof(struct igmp_conf));
899 pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
900 ret = readRequest(nga, attr);
904 filterAttributes(attr, ATTR_IGMP_ENABLE_VLAN, ATTR_END);
906 if (attr->first != NULL) {
907 at = attr->first->data;
909 ic->enable = aiv->enable;
910 ic->vlan = aiv->vlan;
913 clearList(attr, (void(*)(void*))freeAttr);
916 pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
917 ret = readRequest(nga, attr);
921 filterAttributes(attr, ATTR_IGMP_BLOCK_UNK, ATTR_END);
923 if (attr->first != NULL) {
924 at = attr->first->data;
925 ic->block = *(char*)at->data;
928 clearList(attr, (void(*)(void*))freeAttr);
931 pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
932 ret = readRequest(nga, attr);
936 filterAttributes(attr, ATTR_IGMP_VALID_V3, ATTR_END);
938 if (attr->first != NULL) {
939 at = attr->first->data;
940 ic->validate = *(char*)at->data;
945 destroyList(attr, (void(*)(void*))freeAttr);
952 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic)
955 struct attr_igmp_vlan *aiv;
958 if (nga == NULL || ic == NULL)
960 else if (nga->current == NULL)
964 aiv = malloc(sizeof(struct attr_igmp_vlan));
967 aiv->enable = ic->enable;
968 aiv->vlan = ic->vlan;
971 attr = createEmptyList();
972 pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), aiv));
973 pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block != false));
974 pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate != false));
977 return writeRequest(nga, attr);
981 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb)
987 struct attr_cabletest_do *acd;
988 struct attr_cabletest_result *acr;
991 if (nga == NULL || ct == NULL)
993 else if (nga->current == NULL)
997 attr = createEmptyList();
999 for (i = 0; i < nb; i++) {
1001 acd = malloc(sizeof(struct attr_cabletest_do));
1004 acd->port = ct[i].port;
1006 pushBackList(attr, newAttr(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), acd));
1008 ret = writeRequest(nga, attr);
1013 /* the list is destroyed by writeRequest, so we need to recreate it */
1014 attr = createEmptyList();
1015 pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
1016 ret = readRequest(nga, attr);
1020 filterAttributes(attr, ATTR_CABLETEST_RESULT, ATTR_END);
1022 for (ln = attr->first; ln != NULL; ln = ln->next) {
1025 if (at->size == sizeof(struct attr_cabletest_result) && acr->port == ct[i].port) {
1032 /* just empty the list, it will be used at next iteration */
1033 clearList(attr, (void(*)(void*))freeAttr);
1038 destroyList(attr, (void(*)(void*))freeAttr);
1045 int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc)
1049 struct swi_attr *sa;
1052 if (nga == NULL || nc == NULL)
1060 attr = createEmptyList();
1063 pushBackList(attr, newShortAttr(ATTR_DHCP, 1));
1065 pushBackList(attr, newShortAttr(ATTR_DHCP, 0));
1066 /* only add non-null values */
1067 if (nc->ip.s_addr != 0)
1068 pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
1069 if (nc->netmask.s_addr != 0)
1070 pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
1071 if (nc->gw.s_addr != 0)
1072 pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
1075 ret = writeRequest(nga, attr);
1080 /* update local values */
1081 sa->nc.dhcp = nc->dhcp;
1083 if (nc->ip.s_addr !=0)
1085 if (nc->netmask.s_addr != 0)
1086 sa->nc.netmask = nc->netmask;
1087 if (nc->gw.s_addr != 0)
1098 int ngadmin_getVLANType (struct ngadmin *nga, int *t)
1105 if (nga == NULL || t == NULL)
1107 else if (nga->current == NULL)
1111 attr = createEmptyList();
1112 pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
1113 ret=readRequest(nga, attr);
1117 filterAttributes(attr, ATTR_VLAN_TYPE, ATTR_END);
1121 if (attr->first != NULL) {
1122 at = attr->first->data;
1123 *t =(int)*(char*)at->data;
1128 destroyList(attr, (void(*)(void*))freeAttr);
1135 int ngadmin_setVLANType (struct ngadmin *nga, int t)
1140 if (nga == NULL || t < 1 || t > 4)
1142 else if (nga->current == NULL)
1146 attr = createEmptyList();
1147 pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
1150 return writeRequest(nga, attr);
1154 int ngadmin_getVLANPortConf (struct ngadmin *nga, unsigned char *ports)
1160 struct attr_vlan_conf *avc;
1161 struct swi_attr *sa;
1165 if (nga == NULL || ports== NULL)
1173 attr = createEmptyList();
1174 pushBackList(attr, newEmptyAttr(ATTR_VLAN_PORT_CONF));
1175 ret = readRequest(nga, attr);
1179 filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
1181 memset(ports, 0, sa->ports);
1183 for (ln = attr->first; ln != NULL; ln = ln->next) {
1187 if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
1190 for (port = 0; port < sa->ports; port++) {
1191 if (avc->ports[port] == VLAN_UNTAGGED)
1192 ports[port] = avc->vlan;
1198 destroyList(attr, (void(*)(void*))freeAttr);
1205 int ngadmin_setVLANPortConf (struct ngadmin *nga, const unsigned char *ports)
1210 struct swi_attr *sa;
1211 struct attr_vlan_conf *avc;
1212 int ret = ERR_OK, port;
1216 if (nga == NULL || ports == NULL)
1223 /* if nothing is to be changed, do nothing */
1224 for (port = 0; port < sa->ports && ports[port] == 0; port++);
1225 if (port == sa->ports )
1228 attr = createEmptyList();
1230 if (memchr(ports, 0, sa->ports) != NULL) {
1231 /* if at least one port is unchanged, we need to read old config */
1232 pushBackList(attr, newEmptyAttr(ATTR_VLAN_PORT_CONF));
1233 ret = readRequest(nga, attr);
1237 filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
1238 /* FIXME: check if the returned array effectively contains correct data */
1240 /* create an empty VLAN config */
1241 for (vlan = VLAN_MIN; vlan <= VLAN_PORT_MAX; vlan++) {
1242 avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
1244 memset(avc->ports, 0, sa->ports);
1245 pushBackList(attr, newAttr(ATTR_VLAN_PORT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
1249 for (ln = attr->first; ln != NULL; ln = ln->next) {
1252 for (port = 0; port < sa->ports; port++) {
1253 if (ports[port] == avc->vlan)
1254 avc->ports[port] = VLAN_UNTAGGED;
1256 avc->ports[port] = VLAN_NO;
1260 ret = writeRequest(nga, attr);
1265 destroyList(attr, (void(*)(void*))freeAttr);
1272 int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb)
1277 int ret = ERR_OK, total;
1278 struct attr_vlan_conf *avc;
1279 struct swi_attr *sa;
1282 if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
1293 attr = createEmptyList();
1294 pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
1295 ret = readRequest(nga, attr);
1299 filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
1301 memset(vlans, 0, total * sizeof(unsigned short));
1302 memset(ports, 0, total * sa->ports);
1304 for (ln = attr->first; ln != NULL; ln = ln->next) {
1308 if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
1312 memcpy(ports, avc->ports, sa->ports);
1319 break; /* no more room */
1324 destroyList(attr, (void(*)(void*))freeAttr);
1331 int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports)
1337 struct attr_vlan_conf *avc;
1340 if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
1342 else if (nga->current == NULL)
1346 attr = createEmptyList();
1347 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1348 ret = readRequest(nga, attr);
1352 filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
1354 memset(ports, 0, nga->current->ports);
1356 for (ln = attr->first; ln != NULL; ln = ln->next) {
1359 if (avc->vlan == vlan) {
1360 memcpy(ports, avc->ports, nga->current->ports);
1367 destroyList(attr, (void(*)(void*))freeAttr);
1374 int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports)
1378 struct swi_attr *sa;
1379 struct attr_vlan_conf *avc;
1380 int ret = ERR_OK, port;
1383 if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
1391 /* if nothing is to be changed, do nothing */
1392 for (port = 0; port < sa->ports && ports[port] == VLAN_UNSPEC; port++);
1393 if (port == sa->ports )
1397 attr = createEmptyList();
1398 avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
1404 /* if all is to be changed, we do not need to read old config */
1405 if (memchr(ports, VLAN_UNSPEC, sa->ports) != NULL) {
1407 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1408 ret = readRequest(nga, attr);
1412 filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
1414 if (attr->first != NULL) {
1415 at = attr->first->data;
1416 memcpy(avc, at->data, sizeof(struct attr_vlan_conf) + sa->ports);
1419 clearList(attr, (void(*)(void*))freeAttr);
1424 for (port = 0; port < sa->ports; port++) {
1425 if (ports[port] != VLAN_UNSPEC)
1426 avc->ports[port] = ports[port];
1430 pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
1431 ret = writeRequest(nga, attr);
1436 destroyList(attr, (void(*)(void*))freeAttr);
1443 int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan)
1448 if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
1450 else if (nga->current == NULL)
1454 attr = createEmptyList();
1455 pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
1458 return writeRequest(nga, attr);
1462 int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
1468 struct attr_pvid *ap;
1471 if (nga == NULL || ports == NULL)
1473 else if (nga->current == NULL)
1477 attr = createEmptyList();
1478 pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
1479 ret = readRequest(nga, attr);
1483 filterAttributes(attr, ATTR_VLAN_PVID, ATTR_END);
1485 memset(ports, 0, nga->current->ports * sizeof(unsigned short));
1487 for (ln = attr->first; ln != NULL; ln = ln->next) {
1490 ports[ap->port - 1] = ap->vlan;
1495 destroyList(attr, (void(*)(void*))freeAttr);
1502 int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan)
1505 struct attr_pvid *ap;
1508 if (nga == NULL || port < 1 || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
1510 else if (nga->current == NULL)
1512 else if (port > nga->current->ports)
1516 attr = createEmptyList();
1517 ap = malloc(sizeof(struct attr_pvid));
1523 pushBackList(attr, newAttr(ATTR_VLAN_PVID, sizeof(struct attr_pvid), ap));
1526 return writeRequest(nga, attr);