5 #include <ngadmin.h> /* FIXME */
7 #include <nsdp/protocol.h>
10 struct attr* newAttr (unsigned short attr, unsigned short size, void *data)
14 at = malloc(sizeof(struct attr));
26 void freeAttr (struct attr *at)
35 void filterAttributes (List *attr, ...)
40 unsigned short attrcode;
44 for (ln = attr->first; ln != NULL; ) {
50 while (!keep && attrcode != ATTR_END) {
51 attrcode = (unsigned short)va_arg(ap, unsigned int);
52 keep = keep || (at->attr == attrcode);
61 destroyElement(attr, pr, (void(*)(void*))freeAttr);
67 static int ports_status_endecode (struct attr *at)
69 struct attr_port_status *ps = at->data;
71 if (at->size != sizeof(struct attr_port_status))
93 static int port_stat_endecode (struct attr *at, bool encode)
95 struct attr_port_stat *ps = at->data;
96 unsigned long long *v;
98 if (at->size != sizeof(struct attr_port_stat))
104 for (v = &ps->recv; ((void*)v) - ((void*)ps) < (int)sizeof(struct attr_port_stat); v++)
105 *v = encode ? htobe64(*v) : be64toh(*v);
111 static int qos_endecode (struct attr *at)
113 struct attr_qos *aq = at->data;
115 if (at->size != sizeof(struct attr_qos))
121 if (aq->prio < PRIO_HIGH || aq->prio > PRIO_LOW)
128 static int bitrate_endecode (struct attr *at, bool encode)
130 struct attr_bitrate *sb = at->data;
132 if (at->size != sizeof(struct attr_bitrate))
139 sb->bitrate = ntohl(sb->bitrate);
141 if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
145 sb->bitrate = htonl(sb->bitrate);
151 static int pvid_endecode (struct attr *at, bool encode)
153 struct attr_pvid *ap = at->data;
155 if (at->size != sizeof(struct attr_pvid))
162 ap->vlan = ntohs(ap->vlan);
164 if (ap->vlan < VLAN_MIN || ap->vlan > VLAN_DOT_MAX)
168 ap->vlan = htons(ap->vlan);
174 static int cabletest_do_endecode (struct attr *at)
176 struct attr_cabletest_do *acd = at->data;
178 if (at->size != sizeof(struct attr_cabletest_do))
181 if (acd->port < 1 || acd->action != 1)
188 static int cabletest_result_endecode (struct attr *at, bool encode)
190 struct attr_cabletest_result *acr = at->data;
192 /* Note: this attribute is special
193 * - when sent by the client, it contains the port number whe want to
194 * get cabletest results from
195 * - when the switch replies, it contains the actual test results data
198 /* no need to check the size, the only possible value under 1
199 * is 0 and in that case the decoder is not called
207 if (at->size != sizeof(struct attr_cabletest_result))
211 acr->v1 = htonl(acr->v1);
212 acr->v2 = htonl(acr->v2);
214 acr->v1 = ntohl(acr->v1);
215 acr->v2 = ntohl(acr->v2);
222 static int igmp_vlan_endecode (struct attr *at, bool encode)
224 struct attr_igmp_vlan *aiv = at->data;
226 if (at->size != sizeof(struct attr_igmp_vlan))
230 aiv->enable = ntohs(aiv->enable);
231 aiv->vlan = ntohs(aiv->vlan);
234 aiv->enable = (aiv->enable != 0);
235 if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_DOT_MAX)
239 aiv->enable = htons(aiv->enable);
240 aiv->vlan = htons(aiv->vlan);
247 static int mirror_encode (struct attr *at)
249 struct attr_mirror *am = at->data;
250 unsigned char p, ports, *r;
254 /* no need to check attribute size, since
255 * sizeof(struct attr_mirror) == 1 and encoder is not
256 * called when attribute size is zero (ie empty attribute)
258 * am->outport encodes the outgoing mirror port and the array
259 * the ports from which the data is copied, it must not be empty
261 * am->outport == 0 is allowed and means mirroring is disabled
263 ports = at->size - sizeof(struct attr_mirror);
264 if (am->outport > 0 && ports == 0)
267 sz = 3 + ((ports - 1) >> 3);
275 /* FIXME: if ports > 8 */
276 for (p = 1; p <= ports; p++) {
277 if (am->outport != p)
278 r[2] |= (am->ports[p - 1] & 1) << (8 - p);
290 static int mirror_decode (struct attr *at)
292 struct attr_mirror *am;
293 unsigned char p, ports, *r = at->data;
300 /* note: we cannot compute the exact amount of ports from here,
301 * instead we have the immediate superior multiple of 8
302 * it will be the user's job to ignore extra entries
304 ports = ((at->size - 2) << 3);
306 /* r[0] == 0 is allowed and means mirroring is disabled */
309 sz = sizeof(struct attr_mirror) + ports;
318 /* FIXME: if ports > 8 */
319 for (p = 1; p <= ports; p++)
320 am->ports[p - 1] = (r[2] >> (8 - p)) & 1;
331 static int vlan_port_encode (struct attr *at)
333 struct attr_vlan_conf *avc = at->data;
334 unsigned char p, ports, *r;
338 /* just a header is valid */
339 if (at->size < sizeof(struct attr_vlan_conf))
341 ports = at->size - sizeof(struct attr_vlan_conf);
343 if (avc->vlan < VLAN_MIN || avc->vlan > VLAN_PORT_MAX)
349 sz = (2 + 1 + ((ports - 1) >> 3));
356 *(unsigned short*)r = htons(avc->vlan);
358 /* FIXME: if ports > 8 */
359 for (p = 0; p < ports; p++) {
360 if (avc->ports[p] == VLAN_UNTAGGED)
361 r[2] |= (1 << (7 - p));
373 static int vlan_port_decode (struct attr *at)
375 unsigned char p, ports, *r = at->data;
376 struct attr_vlan_conf *avc;
383 /* note: we cannot compute the exact amount of ports from here,
384 * instead we have the immediate superior multiple of 8
385 * it will be the user's job to ignore extra entries
387 ports = ((at->size - 2) << 3);
389 sz = sizeof(struct attr_vlan_conf) + ports;
394 avc->vlan = ntohs(*(unsigned short*)r);
396 /* FIXME: if ports > 8 */
397 for (p = 0; p < ports; p++) {
398 if ((r[2] >> (7 - p)) & 1)
399 avc->ports[p] = VLAN_UNTAGGED;
401 avc->ports[p] = VLAN_NO;
413 static int vlan_dot_encode (struct attr *at)
415 struct attr_vlan_conf *avc = at->data;
416 unsigned char p, ports, *r, fl;
420 /* just a header is valid */
421 if (at->size < sizeof(struct attr_vlan_conf))
423 ports = at->size - sizeof(struct attr_vlan_conf);
425 if (avc->vlan < VLAN_MIN || avc->vlan > VLAN_DOT_MAX)
431 sz = 2 + 2 * (1 + ((ports - 1) >> 3));
438 *(unsigned short*)r = htons(avc->vlan);
440 /* FIXME: if ports > 8 */
441 for (p = 0; p < ports; p++) {
443 switch (avc->ports[p]) {
446 /* a tagged VLAN is also marked as untagged
447 * so do not put a "break" here
464 static int vlan_dot_decode (struct attr *at)
466 unsigned char p, ports, *r = at->data;
467 struct attr_vlan_conf *avc;
471 /* attribute size must be a multiple of 2 because there are
472 * 2 bytes (1 for tagged and 1 for untagged) per block of
473 * 8 ports, plus the 2 first bytes for the VLAN id
475 if (at->size < 2 || (at->size & 1) != 0)
478 /* note: we cannot compute the exact amount of ports from here,
479 * instead we have the immediate superior multiple of 8
480 * it will be the user's job to ignore extra entries
482 ports = ((at->size - 2) / 2) << 3;
484 sz = sizeof(struct attr_vlan_conf) + ports;
489 avc->vlan = ntohs(*(unsigned short*)r);
491 /* FIXME: if ports > 8 */
492 for (p = 0; p < ports; p++) {
493 if ((r[3] >> (7 - p)) & 1)
494 avc->ports[p] = VLAN_TAGGED;
495 else if ((r[2] >> (7 - p)) & 1)
496 avc->ports[p] = VLAN_UNTAGGED;
498 avc->ports[p] = VLAN_NO;
510 static int processAttr (struct attr *at, bool encode)
512 unsigned char *byte = at->data;
513 unsigned short *word = at->data;
514 unsigned int *dword = at->data;
517 /* empty attributes are not processed */
521 if (at->data == NULL)
527 if (at->size != ETH_ALEN)
534 /* IP addresses are kept in network byte order even on the host */
535 if (at->size != sizeof(struct in_addr))
540 case ATTR_PORTS_COUNT:
548 case ATTR_STATS_RESET:
549 case ATTR_STORM_ENABLE:
550 case ATTR_IGMP_BLOCK_UNK:
551 case ATTR_IGMP_VALID_V3:
552 case ATTR_LOOP_DETECT:
556 *byte = (*byte != 0);
561 /* Note: DHCP attribute is special, it is 2 two bytes long
562 * when sent by the switch but only 1 byte long when sent
566 *byte = (*byte != 0);
568 } else if (at->size > 2) {
573 *word = ntohs(*word);
575 *word = (*word != 0);
578 *word = htons(*word);
587 *dword = ntohl(*dword);
589 *dword = (*dword != 0);
592 *dword = htonl(*dword);
600 /* no need to check if *byte < VLAN_DISABLED because
601 * byte is unsigned and VLAN_DISABLED is 0 */
602 if (*byte > VLAN_DOT_ADV)
611 if (*byte < QOS_PORT || *byte > QOS_DOT)
616 case ATTR_QOS_CONFIG:
617 return qos_endecode(at);
619 case ATTR_VLAN_DESTROY:
624 *word = ntohs(*word);
626 if (*word < VLAN_MIN || *word > VLAN_DOT_MAX)
630 *word = htons(*word);
634 case ATTR_PORT_STATUS:
635 return ports_status_endecode(at);
637 case ATTR_PORT_STATISTICS:
638 return port_stat_endecode(at, encode);
640 case ATTR_BITRATE_INPUT:
641 case ATTR_BITRATE_OUTPUT:
642 case ATTR_STORM_BITRATE:
643 return bitrate_endecode(at, encode);
646 return pvid_endecode(at, encode);
648 case ATTR_CABLETEST_DO:
649 return cabletest_do_endecode(at);
651 case ATTR_CABLETEST_RESULT:
652 return cabletest_result_endecode(at, encode);
654 case ATTR_IGMP_ENABLE_VLAN:
655 return igmp_vlan_endecode(at, encode);
659 return mirror_encode(at);
661 return mirror_decode(at);
663 case ATTR_VLAN_PORT_CONF:
665 return vlan_port_encode(at);
667 return vlan_port_decode(at);
669 case ATTR_VLAN_DOT_CONF:
671 return vlan_dot_encode(at);
673 return vlan_dot_decode(at);
675 /* undefined attributes are not modified */
682 int encodeAttr (struct attr *at)
684 return processAttr(at, true);
688 int decodeAttr (struct attr *at)
690 return processAttr(at, false);