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)
228 else if (id < 0 || id >= nga->swi_count)
231 sa = &nga->swi_tab[id];
234 attr = createEmptyList();
235 pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
236 ret = readRequest(nga, attr);
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 */
247 destroyList(attr, (void(*)(void*))freeAttr);
254 int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename)
256 if (nga == NULL || filename == NULL || *filename == 0)
258 else if (nga->current == NULL)
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
272 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
278 struct attr_port_status *ps;
281 if (nga == NULL || ports == NULL)
283 else if (nga->current == NULL)
287 attr = createEmptyList();
288 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
289 ret = readRequest(nga, attr);
293 filterAttributes(attr, ATTR_PORT_STATUS, ATTR_END);
295 memset(ports, SPEED_UNK, nga->current->ports);
297 for (ln = attr->first; ln != NULL; ln = ln->next) {
300 ports[ps->port - 1] = ps->status;
304 destroyList(attr, (void(*)(void*))freeAttr);
311 int ngadmin_setName (struct ngadmin *nga, const char *name)
319 else if (nga->current == NULL)
323 attr = createEmptyList();
324 pushBackList(attr, name == NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
325 ret = writeRequest(nga, attr);
329 /* successful, also update local name */
331 memset(nga->current->name, '\0', NAME_SIZE);
333 strncpy(nga->current->name, name, NAME_SIZE);
340 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
346 struct attr_port_stat *aps;
349 if (nga == NULL || ps == NULL)
351 else if (nga->current == NULL)
354 attr = createEmptyList();
355 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
356 ret = readRequest(nga, attr);
360 filterAttributes(attr, ATTR_PORT_STATISTICS, ATTR_END);
362 memset(ps, 0, nga->current->ports * sizeof(struct port_stats));
364 for (ln = attr->first; ln != NULL; ln = ln->next) {
367 ps[aps->port -1].recv = aps->recv;
368 ps[aps->port -1].sent = aps->sent;
369 ps[aps->port -1].crc = aps->crc;
373 destroyList(attr, (void(*)(void*))freeAttr);
380 int ngadmin_resetPortsStatistics (struct ngadmin *nga)
385 attr = createEmptyList();
386 pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
389 return writeRequest(nga, attr);
393 int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
399 if (nga == NULL || pass == NULL)
401 else if (nga->current == NULL)
405 attr = createEmptyList();
406 pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
407 ret = writeRequest(nga, attr);
412 /* successful, also update local password */
413 strncpy(nga->password, pass, PASSWORD_MAX);
421 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s)
428 if (nga == NULL || s == NULL)
430 else if (nga->current == NULL)
434 attr = createEmptyList();
435 pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
436 ret = readRequest(nga, attr);
440 filterAttributes(attr, ATTR_STORM_ENABLE, ATTR_END);
444 if (attr->first != NULL) {
445 at = attr->first->data;
446 *s = *(char*)at->data;
451 destroyList(attr, (void(*)(void*))freeAttr);
458 int ngadmin_setStormFilterState (struct ngadmin *nga, int s)
463 attr = createEmptyList();
464 pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s != 0));
467 return writeRequest(nga, attr);
471 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
476 int ret = ERR_OK, port;
477 struct attr_bitrate *sb;
480 if (nga == NULL || ports == NULL)
482 else if (nga->current == NULL)
486 attr = createEmptyList();
487 pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
488 ret = readRequest(nga, attr);
492 filterAttributes(attr, ATTR_STORM_BITRATE, ATTR_END);
494 for (port = 0; port < nga->current->ports; port++)
495 ports[port] = BITRATE_UNSPEC;
497 for (ln = attr->first; ln != NULL; ln = ln->next) {
500 ports[sb->port - 1] = sb->bitrate;
505 destroyList(attr, (void(*)(void*))freeAttr);
512 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports)
516 struct attr_bitrate *sb;
519 if (nga == NULL || ports == NULL)
521 else if (nga->current == NULL)
525 attr = createEmptyList();
527 for (port = 0; port < nga->current->ports; port++) {
528 if (ports[port] != BITRATE_UNSPEC) {
529 sb = malloc(sizeof(struct attr_bitrate));
533 sb->bitrate = ports[port];
534 pushBackList(attr, newAttr(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), sb));
538 return writeRequest(nga, attr);
542 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
547 int ret = ERR_OK, port;
548 struct attr_bitrate *pb;
551 if (nga == NULL || ports == NULL)
553 else if (nga->current == NULL)
557 attr = createEmptyList();
558 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
559 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
560 ret = readRequest(nga, attr);
565 for (port = 0; port < nga->current->ports; port++) {
566 ports[2 * port + 0] = BITRATE_UNSPEC;
567 ports[2 * port + 1] = BITRATE_UNSPEC;
570 for (ln = attr->first; ln != NULL; ln = ln->next) {
573 if (at->attr == ATTR_BITRATE_INPUT)
574 ports[(pb->port - 1) * 2 + 0] = pb->bitrate;
575 else if (at->attr == ATTR_BITRATE_OUTPUT)
576 ports[(pb->port - 1) * 2 + 1] = pb->bitrate;
581 destroyList(attr, (void(*)(void*))freeAttr);
587 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports)
591 struct attr_bitrate *pb;
594 if (nga == NULL || ports == NULL)
596 else if (nga->current == NULL)
600 attr = createEmptyList();
602 for (port = 0; port < nga->current->ports; port++) {
603 if (ports[2 * port + 0] >= BITRATE_NOLIMIT && ports[2 * port + 0] <= BITRATE_512M) {
604 pb = malloc(sizeof(struct attr_bitrate));
608 pb->bitrate = ports[2 * port + 0];
609 pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), pb));
611 if (ports[2 * port + 1] >= BITRATE_NOLIMIT && ports[2 * port + 1] <= BITRATE_512M) {
612 pb = malloc(sizeof(struct attr_bitrate));
616 pb->bitrate = ports[2 * port + 1];
617 pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), pb));
622 return writeRequest(nga, attr);
626 int ngadmin_getQOSMode (struct ngadmin *nga, int *s)
633 if (nga == NULL || s == NULL)
635 else if (nga->current == NULL)
639 attr = createEmptyList();
640 pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
641 ret = readRequest(nga, attr);
645 filterAttributes(attr, ATTR_QOS_TYPE, ATTR_END);
649 if (attr->first != NULL) {
650 at = attr->first->data;
651 *s = *(char*)at->data;
656 destroyList(attr, (void(*)(void*))freeAttr);
663 int ngadmin_setQOSMode (struct ngadmin *nga, int s)
668 attr = createEmptyList();
669 pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
672 return writeRequest(nga, attr);
676 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
681 int ret = ERR_OK, port;
685 if (nga == NULL || ports == NULL)
687 else if (nga->current == NULL)
691 attr = createEmptyList();
692 pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
693 ret = readRequest(nga, attr);
697 filterAttributes(attr, ATTR_QOS_CONFIG, ATTR_END);
699 for (port = 0; port < nga->current->ports; port++)
700 ports[port] = PRIO_UNSPEC;
702 for (ln = attr->first; ln != NULL; ln = ln->next) {
705 ports[aq->port - 1] = aq->prio;
710 destroyList(attr, (void(*)(void*))freeAttr);
717 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports)
724 if (nga == NULL || ports == NULL)
726 else if (nga->current == NULL)
730 attr = createEmptyList();
732 for (port = 0; port < nga->current->ports; port++) {
733 if (ports[port] >= PRIO_HIGH && ports[port] <= PRIO_LOW) {
734 aq = malloc(sizeof(struct attr_qos));
738 aq->prio = ports[port];
739 pushBackList(attr, newAttr(ATTR_QOS_CONFIG, sizeof(struct attr_qos), aq));
744 return writeRequest(nga, attr);
748 int ngadmin_restart (struct ngadmin *nga)
753 attr = createEmptyList();
754 pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
757 return writeRequest(nga, attr);
761 int ngadmin_defaults (struct ngadmin *nga)
767 attr = createEmptyList();
768 pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
769 ret = writeRequest(nga, attr);
774 /* successful: delog and clean list */
785 int ngadmin_getMirror (struct ngadmin *nga, char *ports)
792 if (nga == NULL || ports == NULL)
794 else if (nga->current == NULL)
798 attr = createEmptyList();
799 pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
800 ret = readRequest(nga, attr);
804 filterAttributes(attr, ATTR_MIRROR, ATTR_END);
806 memset(ports, 0, 1 + nga->current->ports);
808 if (attr->first != NULL) {
809 at = attr->first->data;
810 memcpy(ports, at->data, 1 + nga->current->ports);
815 destroyList(attr, (void(*)(void*))freeAttr);
822 int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
830 else if (nga->current == NULL)
834 p = malloc(1 + nga->current->ports);
839 memset(p, 0, 1 + nga->current->ports);
841 memcpy(p, ports, 1 + nga->current->ports);
843 attr = createEmptyList();
844 pushBackList(attr, newAttr(ATTR_MIRROR, 1 + nga->current->ports, p));
847 return writeRequest(nga, attr);
851 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic)
856 struct attr_igmp_vlan *aiv;
859 if (nga == NULL || ic == NULL)
861 else if (nga->current == NULL)
865 ATTR_IGMP_ENABLE_VLAN
869 Apparently, read-querying these attributes at the same time causes the switch to reply garbage.
870 Here we are forced to do like the official win app and send a separate request for each attribute.
874 attr = createEmptyList();
875 memset(ic, 0, sizeof(struct igmp_conf));
878 pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
879 ret = readRequest(nga, attr);
883 filterAttributes(attr, ATTR_IGMP_ENABLE_VLAN, ATTR_END);
885 if (attr->first != NULL) {
886 at = attr->first->data;
888 ic->enable = aiv->enable;
889 ic->vlan = aiv->vlan;
892 clearList(attr, (void(*)(void*))freeAttr);
895 pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
896 ret = readRequest(nga, attr);
900 filterAttributes(attr, ATTR_IGMP_BLOCK_UNK, ATTR_END);
902 if (attr->first != NULL) {
903 at = attr->first->data;
904 ic->block = *(char*)at->data;
907 clearList(attr, (void(*)(void*))freeAttr);
910 pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
911 ret = readRequest(nga, attr);
915 filterAttributes(attr, ATTR_IGMP_VALID_V3, ATTR_END);
917 if (attr->first != NULL) {
918 at = attr->first->data;
919 ic->validate = *(char*)at->data;
924 destroyList(attr, (void(*)(void*))freeAttr);
931 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic)
934 struct attr_igmp_vlan *aiv;
937 if (nga == NULL || ic == NULL)
939 else if (nga->current == NULL)
943 aiv = malloc(sizeof(struct attr_igmp_vlan));
946 aiv->enable = ic->enable;
947 aiv->vlan = ic->vlan;
950 attr = createEmptyList();
951 pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), aiv));
952 pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block != false));
953 pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate != false));
956 return writeRequest(nga, attr);
960 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb)
966 struct attr_cabletest_do *acd;
967 struct attr_cabletest_result *acr;
970 if (nga == NULL || ct == NULL)
972 else if (nga->current == NULL)
976 attr = createEmptyList();
978 for (i = 0; i < nb; i++) {
980 acd = malloc(sizeof(struct attr_cabletest_do));
983 acd->port = ct[i].port;
985 pushBackList(attr, newAttr(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), acd));
987 ret = writeRequest(nga, attr);
992 /* the list is destroyed by writeRequest, so we need to recreate it */
993 attr = createEmptyList();
994 pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
995 ret = readRequest(nga, attr);
999 filterAttributes(attr, ATTR_CABLETEST_RESULT, ATTR_END);
1001 for (ln = attr->first; ln != NULL; ln = ln->next) {
1004 if (at->size == sizeof(struct attr_cabletest_result) && acr->port == ct[i].port) {
1011 /* just empty the list, it will be used at next iteration */
1012 clearList(attr, (void(*)(void*))freeAttr);
1017 destroyList(attr, (void(*)(void*))freeAttr);
1024 int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc)
1028 struct swi_attr *sa;
1031 if (nga == NULL || nc == NULL)
1039 attr = createEmptyList();
1042 pushBackList(attr, newShortAttr(ATTR_DHCP, 1));
1044 pushBackList(attr, newShortAttr(ATTR_DHCP, 0));
1045 /* only add non-null values */
1046 if (nc->ip.s_addr != 0)
1047 pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
1048 if (nc->netmask.s_addr != 0)
1049 pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
1050 if (nc->gw.s_addr != 0)
1051 pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
1054 ret = writeRequest(nga, attr);
1059 /* update local values */
1060 sa->nc.dhcp = nc->dhcp;
1062 if (nc->ip.s_addr !=0)
1064 if (nc->netmask.s_addr != 0)
1065 sa->nc.netmask = nc->netmask;
1066 if (nc->gw.s_addr != 0)
1077 int ngadmin_getVLANType (struct ngadmin *nga, int *t)
1084 if (nga == NULL || t == NULL)
1086 else if (nga->current == NULL)
1090 attr = createEmptyList();
1091 pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
1092 ret=readRequest(nga, attr);
1096 filterAttributes(attr, ATTR_VLAN_TYPE, ATTR_END);
1100 if (attr->first != NULL) {
1101 at = attr->first->data;
1102 *t =(int)*(char*)at->data;
1107 destroyList(attr, (void(*)(void*))freeAttr);
1114 int ngadmin_setVLANType (struct ngadmin *nga, int t)
1119 if (nga == NULL || t < 1 || t > 4)
1121 else if (nga->current == NULL)
1125 attr = createEmptyList();
1126 pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
1129 return writeRequest(nga, attr);
1133 int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb)
1138 int ret = ERR_OK, total;
1139 struct attr_vlan_dot *avd;
1142 if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
1144 else if (nga->current == NULL)
1151 attr = createEmptyList();
1152 pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
1153 ret = readRequest(nga, attr);
1157 filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
1159 memset(vlans, 0, total * sizeof(unsigned short));
1160 memset(ports, 0, total * nga->current->ports);
1162 for (ln = attr->first; ln != NULL; ln = ln->next) {
1167 memcpy(ports, avd->ports, nga->current->ports);
1170 ports += nga->current->ports;
1174 break; /* no more room */
1179 destroyList(attr, (void(*)(void*))freeAttr);
1186 int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports)
1192 struct attr_vlan_dot *avd;
1195 if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
1197 else if (nga->current == NULL)
1201 attr = createEmptyList();
1202 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1203 ret = readRequest(nga, attr);
1207 filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
1209 memset(ports, 0, nga->current->ports);
1211 for (ln = attr->first; ln != NULL; ln = ln->next) {
1214 if (avd->vlan == vlan) {
1215 memcpy(ports, avd->ports, nga->current->ports);
1222 destroyList(attr, (void(*)(void*))freeAttr);
1229 int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports)
1233 struct swi_attr *sa;
1234 struct attr_vlan_dot *avd;
1235 int ret = ERR_OK, port;
1238 if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
1246 /* if nothing is to be changed, do nothing */
1247 for (port = 0; port < sa->ports && ports[port] == VLAN_UNSPEC; port++);
1248 if (port == sa->ports )
1252 attr = createEmptyList();
1253 avd = malloc(sizeof(struct attr_vlan_dot) + sa->ports);
1259 /* if all is to be changed, we do not need to read old config */
1260 if (memchr(ports, VLAN_UNSPEC, sa->ports) != NULL) {
1262 pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1263 ret = readRequest(nga, attr);
1267 filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
1269 if (attr->first != NULL) {
1270 at = attr->first->data;
1271 memcpy(avd, at->data, sizeof(struct attr_vlan_dot) + sa->ports);
1274 clearList(attr, (void(*)(void*))freeAttr);
1279 for (port = 0; port < sa->ports; port++) {
1280 if (ports[port] != VLAN_UNSPEC)
1281 avd->ports[port] = ports[port];
1285 pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_dot) + sa->ports, avd));
1286 ret = writeRequest(nga, attr);
1291 destroyList(attr, (void(*)(void*))freeAttr);
1298 int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan)
1303 if (nga == NULL || vlan < 1 || vlan > VLAN_MAX)
1305 else if (nga->current == NULL)
1309 attr = createEmptyList();
1310 pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
1313 return writeRequest(nga, attr);
1317 int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
1323 struct attr_pvid *ap;
1326 if (nga == NULL || ports == NULL)
1328 else if (nga->current == NULL)
1332 attr = createEmptyList();
1333 pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
1334 ret = readRequest(nga, attr);
1338 filterAttributes(attr, ATTR_VLAN_PVID, ATTR_END);
1340 memset(ports, 0, nga->current->ports * sizeof(unsigned short));
1342 for (ln = attr->first; ln != NULL; ln = ln->next) {
1345 ports[ap->port - 1] = ap->vlan;
1350 destroyList(attr, (void(*)(void*))freeAttr);
1357 int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan)
1360 struct attr_pvid *ap;
1363 if (nga == NULL || port < 1 || vlan < 1 || vlan > VLAN_MAX)
1365 else if (nga->current == NULL)
1367 else if (port > nga->current->ports)
1371 attr = createEmptyList();
1372 ap = malloc(sizeof(struct attr_pvid));
1378 pushBackList(attr, newAttr(ATTR_VLAN_PVID, sizeof(struct attr_pvid), ap));
1381 return writeRequest(nga, attr);