*.o
*~
*.so
+*.a
admin
admind
lib/doc/
+raw/doc/
brouillon
-all: lib libdoc cli
+all: raw lib libdoc cli
-lib: force
+raw: force
+ @+$(MAKE) -C raw lib
+
+
+lib: raw force
@+$(MAKE) -C lib lib
@+$(MAKE) -C lib libdoc
-cli: force
+cli: lib force
@+$(MAKE) -C cli
clean:
+ @+$(MAKE) -C raw clean
@+$(MAKE) -C lib clean
@+$(MAKE) -C cli clean
mrproper: clean
+ @+$(MAKE) -C raw mrproper
@+$(MAKE) -C lib mrproper
@+$(MAKE) -C cli mrproper
CC=gcc
-CFLAGS=-DBUILD_LIB -I../include/ -W -Wall -Wextra -Os -fno-strict-aliasing -fvisibility=hidden -fPIC
-LDFLAGS=
+CFLAGS=-DBUILD_LIB -I../../raw/include/ -I../include/ -W -Wall -Wextra -Os -fno-strict-aliasing -fvisibility=hidden -fPIC
+LDFLAGS=-L../../raw/ -lrawnsdp
EXEC=../libngadmin.so
SRC=$(wildcard *.c)
+++ /dev/null
-
-#include <ngadmin.h>
-
-#include "lib.h"
-#include "attr.h"
-#include "protocol.h"
-
-
-#define ATTR_HANDLER_ENTRY(at, sz, enc, dec) {.attr = at, .size = sz, .encode = enc, .decode = dec}
-
-
-
-static bool bool_endecode (struct attr *at, unsigned char ports UNUSED)
-{
- *(char*)at->data = (*(char*)at->data != 0);
-
- return true;
-}
-
-
-static bool ports_status_decode (struct attr *at, unsigned char ports)
-{
- struct attr_port_status *ps = at->data;
-
- if (ps->port < 1 || ps->port > ports)
- return false;
-
- switch (ps->status) {
- case SPEED_DOWN:
- case SPEED_10:
- case SPEED_100:
- case SPEED_1000:
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-
-static bool port_stat_decode (struct attr *at, unsigned char ports)
-{
- struct attr_port_stat *ps = at->data;
- unsigned long long *v;
-
- if (ps->port < 1 || ps->port > ports)
- return false;
-
- for (v = &ps->recv; ((char*)v) - ((char*)ps) < (int)sizeof(struct attr_port_stat); v++)
- *v = be64toh(*v);
-
-
- return true;
-}
-
-
-static bool bitrate_decode (struct attr *at, unsigned char ports)
-{
- struct attr_bitrate *sb = at->data;
-
- if (sb->port < 1 || sb->port > ports)
- return false;
-
- sb->bitrate = ntohl(sb->bitrate);
- if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
- return false;
-
- return true;
-}
-
-
-static bool bitrate_encode (struct attr *at, unsigned char ports)
-{
- struct attr_bitrate *sb = at->data;
-
- if (sb->port < 1 || sb->port > ports)
- return false;
-
- if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
- return false;
- sb->bitrate = htonl(sb->bitrate);
-
- return true;
-}
-
-
-static bool qos_mode_endecode (struct attr *at, unsigned char ports UNUSED)
-{
- unsigned char v = *(char*)at->data;
-
- return (v == QOS_PORT || v == QOS_DOT);
-}
-
-
-static bool qos_endecode (struct attr *at, unsigned char ports)
-{
- struct attr_qos *aq = at->data;
-
- if (aq->port < 1 || aq->port > ports)
- return false;
-
- return (aq->prio >= PRIO_HIGH && aq->prio <= PRIO_LOW);
-}
-
-
-static bool pvid_decode (struct attr *at, unsigned char ports)
-{
- struct attr_pvid *ap= at->data;
-
- if (ap->port < 1 || ap->port > ports)
- return false;
-
- ap->vlan = ntohs(ap->vlan);
-
- return (ap->vlan >= VLAN_MIN && ap->vlan <= VLAN_MAX);
-}
-
-
-static bool pvid_encode (struct attr *at, unsigned char ports)
-{
- struct attr_pvid *ap= at->data;
-
- if (ap->port < 1 || ap->port > ports)
- return false;
-
- if (ap->vlan < VLAN_MIN || ap->vlan > VLAN_MAX)
- return false;
-
- ap->vlan = htons(ap->vlan);
-
- return true;
-}
-
-
-static bool vlan_destroy_encode (struct attr *at, unsigned char ports UNUSED)
-{
- unsigned short v = *(unsigned short*)at->data;
-
- if (v < VLAN_MIN || v > VLAN_MAX)
- return false;
-
- *(unsigned short*)at->data = htons(v);
-
- return true;
-}
-
-
-static bool mirror_decode (struct attr *at, unsigned char ports)
-{
- unsigned char *r = at->data, *p;
- int port;
-
-
- if (at->size != 3 + ((ports - 1) >> 3))
- return false;
-
- /* r[0] == 0 is allowed and means mirroring is disabled */
- if (r[0] > ports)
- return false;
-
- p = malloc(1 + ports);
- if (p == NULL)
- return false;
-
- memset(p, 0, 1 + ports);
-
- if (r[0] == 0)
- goto end;
-
- p[0] = r[0];
-
- for (port = 1; port <= ports; port++)
- p[port] = (r[2] >> (8 - port)) & 1; /* FIXME: if ports > 8 */
-
-end:
- free(at->data);
- at->data = p;
- at->size = 1 + ports;
-
-
- return true;
-}
-
-
-static bool mirror_encode (struct attr *at, unsigned char ports)
-{
- unsigned char *p = at->data, *r;
- int port;
-
-
- if (at->size != 1 + ports)
- return false;
-
- /* p[0] == 0 is allowed and means mirroring is disabled */
- if (p[0] > ports)
- return false;
-
- r = malloc(3 + ((ports - 1) >> 3));
- if (r == NULL)
- return false;
-
- memset(r, 0, 3 + ((ports - 1) >> 3));
-
- if (p[0] == 0)
- goto end;
-
- r[0] = p[0];
-
- for (port = 1; port <= ports; port++) {
- if (p[0] != port)
- r[2] |= (p[port] & 1) << (8 - port); /* FIXME: if ports > 8 */
- }
-
-end:
- free(at->data);
- at->data = r;
- at->size = 3 + ((ports - 1) >> 3);
-
-
- return true;
-}
-
-
-static bool igmp_vlan_decode (struct attr *at, unsigned char ports UNUSED)
-{
- struct attr_igmp_vlan *aiv = at->data;
-
- aiv->enable = ntohs(aiv->enable);
- if (aiv->enable != 0 && aiv->enable != 1)
- return false;
-
- aiv->vlan = ntohs(aiv->vlan);
- if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_MAX)
- return false;
-
- return true;
-}
-
-
-static bool igmp_vlan_encode (struct attr *at, unsigned char ports UNUSED)
-{
- struct attr_igmp_vlan *aiv = at->data;
-
- if (aiv->enable != 0 && aiv->enable != 1)
- return false;
- aiv->enable = htons(aiv->enable);
-
- if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_MAX)
- return false;
- aiv->vlan = htons(aiv->vlan);
-
- return true;
-}
-
-
-static bool cabletest_do_encode (struct attr *at, unsigned char ports)
-{
- struct attr_cabletest_do *acd = at->data;
-
- if (acd->port < 1 || acd->port > ports)
- return false;
-
- return (acd->action == 1);
-}
-
-
-static bool cabletest_result_encode (struct attr *at, unsigned char ports)
-{
- unsigned char v = *(unsigned char*)at->data;
-
- return (v >= 1 && v <= ports);
-}
-
-
-static bool cabletest_result_decode (struct attr *at, unsigned char ports)
-{
- struct attr_cabletest_result *acr = at->data;
-
- if (acr->port < 1 || acr->port > ports)
- return false;
-
- acr->v1 = ntohl(acr->v1);
- acr->v2 = ntohl(acr->v2);
-
- return true;
-}
-
-
-static bool cabletest_result_endecode (struct attr *at, unsigned char ports)
-{
- switch (at->size) {
-
- case 1:
- return cabletest_result_encode(at, ports);
-
- case sizeof(struct attr_cabletest_result):
- return cabletest_result_decode(at, ports);
-
- default:
- return false;
- }
-}
-
-
-static bool vlan_type_endecode (struct attr *at, unsigned char ports UNUSED)
-{
- char v = *(char*)at->data;
-
- return (v >= VLAN_DISABLED && v <= VLAN_DOT_ADV);
-}
-
-
-static bool vlan_dot_decode (struct attr *at, unsigned char ports)
-{
- char *r = at->data;
- struct attr_vlan_dot *avd;
- int port;
-
-
- if (at->size != (2 + 2 * (1 + ((ports - 1) >> 3))))
- return false;
-
- avd = malloc(sizeof(struct attr_vlan_dot) + ports);
- if (avd == NULL)
- return false;
-
- avd->vlan = ntohs(*(unsigned short*)r);
- r += 2;
-
- for (port = 0; port < ports; port++) {
- /* FIXME: if ports > 8 */
- if ((r[1] >> (7 - port)) & 1)
- avd->ports[port] = VLAN_TAGGED;
- else if ((r[0] >> (7 - port)) & 1)
- avd->ports[port] = VLAN_UNTAGGED;
- else
- avd->ports[port] = VLAN_NO;
- }
-
- free(at->data);
- at->data = avd;
- at->size = sizeof(struct attr_vlan_dot) + ports;
-
-
- return true;
-}
-
-
-static bool vlan_dot_encode (struct attr *at, unsigned char ports)
-{
- struct attr_vlan_dot *avd = at->data;
- char *r, fl;
- unsigned int size, port;
-
-
- if (avd->vlan < VLAN_MIN || avd->vlan > VLAN_MAX)
- return false;
-
- /* just a header is valid */
- if (at->size == sizeof(struct attr_vlan_dot))
- size = 2;
- else if (at->size == sizeof(struct attr_vlan_dot) + ports)
- size = (2 + 2 * (1 + ((ports - 1) >> 3)));
- else
- return false;
-
- r = malloc(size);
- if (r == NULL)
- return false;
-
- memset(r, 0, size);
- *(unsigned short*)r = htons(avd->vlan);
-
- if (size == 2)
- goto end;
-
- r += 2;
-
- for (port = 0; port < ports; port++) {
- /* FIXME: if ports > 8 */
- fl = (1 << (7 - port));
- switch (avd->ports[port]) {
- case VLAN_TAGGED:
- r[1] |= fl;
- case VLAN_UNTAGGED:
- r[0] |= fl;
- }
- }
-
- r -= 2;
-
-end:
- free(at->data);
- at->data = r;
- at->size = size;
-
-
- return true;
-}
-
-
-
-/* WARNING: attributes codes MUST be in ascending order */
-static const struct attr_handler attrtab[] = {
- ATTR_HANDLER_ENTRY(ATTR_MAC, 6, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_IP, 4, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_NETMASK, 4, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_GATEWAY, 4, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_DHCP, 2, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_RESTART, 1, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_DEFAULTS, 1, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_PORT_STATUS, sizeof(struct attr_port_status), NULL, ports_status_decode),
- ATTR_HANDLER_ENTRY(ATTR_PORT_STATISTICS, sizeof(struct attr_port_stat), NULL, port_stat_decode),
- ATTR_HANDLER_ENTRY(ATTR_STATS_RESET, 1, bool_endecode, bool_endecode),
- ATTR_HANDLER_ENTRY(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), cabletest_do_encode, NULL),
- ATTR_HANDLER_ENTRY(ATTR_CABLETEST_RESULT, 0, cabletest_result_endecode, cabletest_result_endecode),
- ATTR_HANDLER_ENTRY(ATTR_VLAN_TYPE, 1, vlan_type_endecode, vlan_type_endecode),
- ATTR_HANDLER_ENTRY(ATTR_VLAN_DOT_CONF, 0, vlan_dot_encode, vlan_dot_decode),
- ATTR_HANDLER_ENTRY(ATTR_VLAN_DESTROY, 2, vlan_destroy_encode, NULL),
- ATTR_HANDLER_ENTRY(ATTR_VLAN_PVID, sizeof(struct attr_pvid), pvid_encode, pvid_decode),
- ATTR_HANDLER_ENTRY(ATTR_QOS_TYPE, 1, qos_mode_endecode, qos_mode_endecode),
- ATTR_HANDLER_ENTRY(ATTR_QOS_CONFIG, sizeof(struct attr_qos), qos_endecode, qos_endecode),
- ATTR_HANDLER_ENTRY(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
- ATTR_HANDLER_ENTRY(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
- ATTR_HANDLER_ENTRY(ATTR_STORM_ENABLE, 1, bool_endecode, bool_endecode),
- ATTR_HANDLER_ENTRY(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
- ATTR_HANDLER_ENTRY(ATTR_MIRROR, 0, mirror_encode, mirror_decode),
- ATTR_HANDLER_ENTRY(ATTR_PORTS_COUNT, 1, NULL, NULL),
- ATTR_HANDLER_ENTRY(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), igmp_vlan_encode, igmp_vlan_decode),
- ATTR_HANDLER_ENTRY(ATTR_IGMP_BLOCK_UNK, 1, bool_endecode, bool_endecode),
- ATTR_HANDLER_ENTRY(ATTR_IGMP_VALID_V3, 1, bool_endecode, bool_endecode)
-};
-
-
-
-const struct attr_handler* getAttrHandler (unsigned short attrcode)
-{
- const struct attr_handler *ah;
- const unsigned int tab_size = sizeof(attrtab) / sizeof(struct attr_handler);
- unsigned int inf, sup, index;
-
-
- inf = 0;
- sup = tab_size;
- index = tab_size >> 1;
- while (index < sup) {
- ah = &attrtab[index];
-
- if (ah->attr > attrcode) {
- sup = index;
- index -= ((index - inf) >> 1) + ((index - inf) & 1);
- } else if (ah->attr < attrcode) {
- inf = index;
- index += ((sup - index) >> 1) + ((sup - index) & 1);
- } else {
- return ah;
- }
- }
-
-
- return NULL;
-}
-
-
+++ /dev/null
-
-#ifndef DEF_ATTR
-#define DEF_ATTR
-
-
-#include <stdbool.h>
-
-#include "protocol.h"
-
-
-#define ATTR_PRODUCT 0x0001
-#define ATTR_UNK_0002 0x0002
-#define ATTR_NAME 0x0003
-#define ATTR_MAC 0x0004
-#define ATTR_UNK_0005 0x0005
-#define ATTR_IP 0x0006
-#define ATTR_NETMASK 0x0007
-#define ATTR_GATEWAY 0x0008
-#define ATTR_NEW_PASSWORD 0x0009
-#define ATTR_PASSWORD 0x000A
-#define ATTR_DHCP 0x000B
-#define ATTR_UNK_000C 0x000C
-#define ATTR_FIRM_VER 0x000D
-#define ATTR_UNK_000E 0x000E
-#define ATTR_UNK_000F 0x000F
-#define ATTR_FIRM_UPGRADE 0x0010
-#define ATTR_RESTART 0x0013
-#define ATTR_DEFAULTS 0x0400
-#define ATTR_PORT_STATUS 0x0C00
-#define ATTR_PORT_STATISTICS 0x1000
-#define ATTR_STATS_RESET 0x1400
-#define ATTR_CABLETEST_DO 0x1800
-#define ATTR_CABLETEST_RESULT 0x1C00
-#define ATTR_VLAN_TYPE 0x2000
-#define ATTR_VLAN_PORT_CONF 0x2400
-#define ATTR_VLAN_DOT_CONF 0x2800
-#define ATTR_VLAN_DESTROY 0x2C00
-#define ATTR_VLAN_PVID 0x3000
-#define ATTR_QOS_TYPE 0x3400
-#define ATTR_QOS_CONFIG 0x3800
-#define ATTR_BITRATE_INPUT 0x4C00
-#define ATTR_BITRATE_OUTPUT 0x5000
-#define ATTR_STORM_ENABLE 0x5400
-#define ATTR_STORM_BITRATE 0x5800
-#define ATTR_MIRROR 0x5C00
-#define ATTR_PORTS_COUNT 0x6000
-#define ATTR_MAX_VLAN 0x6400
-#define ATTR_IGMP_ENABLE_VLAN 0x6800
-#define ATTR_IGMP_BLOCK_UNK 0x6C00
-#define ATTR_IGMP_VALID_V3 0x7000
-#define ATTR_TLV_BITMAP 0x7400
-#define ATTR_END 0xFFFF
-
-#define UNUSED __attribute__((unused))
-
-
-struct attr_handler {
- unsigned short attr; /* attribute code */
- unsigned int size; /* expected data size */
- bool (*encode)(struct attr *at, unsigned char ports); /* encode function */
- bool (*decode)(struct attr *at, unsigned char ports); /* decode function */
-};
-
-
-const struct attr_handler* getAttrHandler (unsigned short attrcode);
-
-
-
-
-struct attr_port_status {
- unsigned char port;
- unsigned char status;
- unsigned char unk;
-} __attribute__((packed));
-
-
-struct attr_port_stat {
- unsigned char port;
- unsigned long long recv;
- unsigned long long sent;
- unsigned long long unk1;
- unsigned long long unk2;
- unsigned long long unk3;
- unsigned long long crc;
-} __attribute__((packed));
-
-
-struct attr_bitrate {
- unsigned char port;
- int bitrate;
-} __attribute__((packed));
-
-
-struct attr_qos {
- unsigned char port;
- unsigned char prio;
-} __attribute__((packed));
-
-
-struct attr_pvid {
- unsigned char port;
- unsigned short vlan;
-} __attribute__((packed));
-
-
-struct attr_igmp_vlan {
- unsigned short enable;
- unsigned short vlan;
-} __attribute__((packed));
-
-
-struct attr_cabletest_do {
- unsigned char port;
- unsigned char action;
-} __attribute__((packed));
-
-
-struct attr_cabletest_result {
- unsigned char port;
- unsigned int v1;
- unsigned int v2;
-} __attribute__((packed));
-
-
-struct attr_vlan_dot {
- unsigned short vlan;
- unsigned char ports[0];
-};
-
-
-#endif
-
+++ /dev/null
-
-#include "list.h"
-
-
-
-
-// -------------------------
-List* createEmptyList (void) {
-
- List *l;
-
-
- l=malloc(sizeof(List));
- l->first=NULL;
- l->last=NULL;
- l->count=0;
-
- #ifdef MT_SAFE_LIST
- pthread_cond_init(&l->cond, NULL);
- pthread_mutex_init(&l->mutex, NULL);
- #endif
-
-
- return l;
-
-}
-
-
-
-// ------------------------------------------------
-void destroyList (List *l, void (*freefunc)(void*)) {
-
- ListNode *pr, *ln;
-
-
-
- if ( l==NULL ) {
- return;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_destroy(&l->mutex);
- pthread_cond_destroy(&l->cond);
- #endif
-
- for (ln=l->first; ln!=NULL; ) {
-
- pr=ln;
-
- if ( freefunc!=NULL ) {
- freefunc(pr->data);
- }
-
- ln=pr->next;
- free(pr);
-
- }
-
-
- free(l);
-
-}
-
-
-
-// -------------------------------------
-void pushFrontList (List *l, void* data) {
-
- ListNode *ln;
-
-
- if ( l==NULL ) {
- return;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- ln=malloc(sizeof(ListNode));
- ln->data=data;
- ln->prev=NULL;
- ln->next=l->first;
-
- if ( l->first==NULL ) {
- l->last=ln;
- } else {
- l->first->prev=ln;
- }
-
- l->first=ln;
- l->count++;
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- #endif
-
-}
-
-
-
-// ------------------------------------
-void pushBackList (List *l, void* data) {
-
- ListNode *ln;
-
-
- if ( l==NULL ) {
- return;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- ln=malloc(sizeof(ListNode));
- ln->data=data;
- ln->prev=l->last;
- ln->next=NULL;
-
- if ( l->last==NULL ) {
- l->first=ln;
- } else {
- l->last->next=ln;
- }
-
- l->last=ln;
- l->count++;
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- #endif
-
-}
-
-
-
-// -------------------------
-void* popFrontList (List *l) {
-
- ListNode *ln;
- void* data;
-
-
- if ( l==NULL ) {
- return NULL;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- if ( (ln=l->first)==NULL ) {
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- #endif
- return NULL;
- }
-
- data=ln->data;
- l->first=ln->next;
-
- if ( ln->next==NULL ) {
- l->last=NULL;
- } else {
- ln->next->prev=NULL;
- }
-
- l->count--;
- free(ln);
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- #endif
-
-
- return data;
-
-}
-
-
-
-// ------------------------
-void* popBackList (List *l) {
-
- ListNode *ln;
- void* data;
-
-
-
- if ( l==NULL ) {
- return NULL;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- if ( (ln=l->last)==NULL ) {
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- #endif
- return NULL;
- }
-
- data=ln->data;
- l->last=ln->prev;
-
- if ( ln->prev==NULL ) {
- l->first=NULL;
- } else {
- ln->prev->next=NULL;
- }
-
- l->count--;
- free(ln);
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- #endif
-
-
- return data;
-
-}
-
-
-
-// ----------------------------------------------
-void clearList (List *l, void (*freefunc)(void*)) {
-
- ListNode *ln, *pr;
-
-
- if ( l==NULL ) {
- return;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- for (ln=l->first; ln!=NULL; ) {
-
- pr=ln;
-
- if ( freefunc!=NULL ) {
- freefunc(pr->data);
- }
-
- ln=pr->next;
- free(pr);
-
- }
-
- l->first=NULL;
- l->last=NULL;
- l->count=0;
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- #endif
-
-}
-
-
-
-// ---------------------------------------------------------------
-bool findAndDestroy (List *l, void* data, void (*freefunc)(void*)) {
-
- ListNode *ln;
-
-
-
- if ( l==NULL ) {
- return false;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- for (ln=l->first; ln!=NULL && ln->data!=data; ln=ln->next);
-
- if ( ln==NULL ) {
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- #endif
-
- } else {
-
- if ( ln->prev==NULL ) {
- l->first=ln->next;
- } else {
- ln->prev->next=ln->next;
- }
-
- if ( ln->next==NULL ) {
- l->last=ln->prev;
- } else {
- ln->next->prev=ln->prev;
- }
-
-
- if ( freefunc!=NULL ) {
- freefunc(data);
- }
-
- l->count--;
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- #endif
-
- }
-
-
-
- return true;
-
-}
-
-
-
-// -------------------------------------------------
-void browseList (List *l, void (*browsefunc)(void*)) {
-
- ListNode *ln;
-
-
-
- if ( l==NULL || browsefunc==NULL ) {
- return;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- for (ln=l->first; ln!=NULL; ln=ln->next) {
- browsefunc(ln->data);
- }
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- #endif
-
-}
-
-
-// --------------------------------------
-void* convertToArray (List *l, size_t sz) {
-
- ListNode *ln;
- void *tab=NULL, *p;
-
-
-
- if ( l==NULL || sz==0 ) {
- return NULL;
- }
-
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_lock(&l->mutex);
- #endif
-
- if ( l->count>0 ) {
-
- tab=malloc(l->count*sz);
- p=tab;
-
- for (ln=l->first; ln!=NULL; ln=ln->next) {
- memcpy(p, ln->data, sz);
- p+=sz;
- }
-
- }
-
- #ifdef MT_SAFE_LIST
- pthread_mutex_unlock(&l->mutex);
- #endif
-
-
- return tab;
-
-}
-
-
-
-
+++ /dev/null
-
-#ifndef DEF_LIST
-#define DEF_LIST
-
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-
-#ifdef MT_SAFE_LIST
-#include <pthread.h>
-#endif
-
-
-
-typedef struct ListNode ListNode;
-
-struct ListNode {
- void* data;
- ListNode *prev, *next;
-};
-
-
-typedef struct {
- ListNode *first, *last;
- unsigned int count;
- #ifdef MT_SAFE_LIST
- pthread_cond_t cond;
- pthread_mutex_t mutex;
- #endif
-} List;
-
-
-
-
-// Creates an empty list
-List* createEmptyList (void);
-
-// Destroys a list, and eventually frees the elements
-// NOT MT SAFE
-void destroyList (List *l, void (*freefunc)(void*));
-
-// Adds an element at front of the list
-void pushFrontList (List *l, void* data);
-
-// Adds an element at back of the list
-void pushBackList (List *l, void* data);
-
-// Pops an element from the front of the list and returns its value
-void* popFrontList (List *l);
-
-// Pops an element from the back of the list and returns its value
-void* popBackList (List *l);
-
-// Clears all the items of the list, and eventually frees them
-void clearList (List *l, void (*freefunc)(void*));
-
-// Find and destroy a particular element of the list, and eventually frees it
-bool findAndDestroy (List *l, void* data, void (*freefunc)(void*));
-
-// Browse all the items of the list through the callback function
-void browseList (List *l, void (*browsefunc)(void*));
-
-//
-void* convertToArray (List *l, size_t sz);
-
-
-
-
-#endif
-
+++ /dev/null
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <errno.h>
-
-#include "attr.h"
-#include "protocol.h"
-
-
-
-int trim (char *txt, int start)
-{
- char *p;
-
- if (txt == NULL)
- return 0;
-
- p = txt + start;
- while (p >= txt && (*p == ' ' || *p == '\n')) {
- *p = '\0';
- p--;
- }
-
- return p - txt + 1;
-}
-
-
-void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum)
-{
- memset(nh, 0, sizeof(struct ng_header));
- nh->version = 1;
- nh->code = code;
-
- memcpy(nh->client_mac, client_mac, ETH_ALEN);
-
- if (switch_mac != NULL)
- memcpy(nh->switch_mac, switch_mac, ETH_ALEN);
-
- nh->seqnum = htonl(seqnum);
- memcpy(nh->proto_id, "NSDP", 4);
-}
-
-
-bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum)
-{
- if (nh->version != 1)
- return false;
-
- if (code > 0 && nh->code != code)
- return false;
-
- if (nh->unk1 != 0)
- return false;
-
- if (*(unsigned short*)nh->unk2 != 0)
- return false;
-
- if (client_mac != NULL && memcmp(nh->client_mac, client_mac, ETH_ALEN) != 0)
- return false;
-
- if (switch_mac != NULL && memcmp(nh->switch_mac, switch_mac, ETH_ALEN) != 0)
- return false;
-
- if (seqnum > 0 && ntohl(nh->seqnum) != seqnum)
- return false;
-
- if (memcmp(nh->proto_id, "NSDP", 4) != 0)
- return false;
-
- if (*(unsigned int*)nh->unk3 != 0)
- return false;
-
- return true;
-}
-
-
-void addPacketAttr (struct ng_packet *np, struct attr *at)
-{
- struct attr_header *ah = np->ah;
-
-
- if ((int)(getPacketTotalSize(np) + sizeof(struct attr_header) + at->size) > np->maxlen)
- return;
-
- ah->attr = htons(at->attr);
- ah->size = htons(at->size);
-
- if (at->size > 0 && at->data != NULL)
- memcpy(ah->data, at->data, at->size);
-
- np->ah = (struct attr_header*)(ah->data + at->size);
-}
-
-
-struct attr* newAttr (unsigned short attr, unsigned short size, void *data)
-{
- struct attr *at;
-
-
- at = malloc(sizeof(struct attr));
- if (at == NULL)
- return NULL;
-
- at->attr = attr;
- at->size = size;
- at->data = data;
-
-
- return at;
-}
-
-
-void freeAttr (struct attr *at)
-{
- if (at != NULL) {
- free(at->data);
- free(at);
- }
-}
-
-
-int addPacketAttributes (struct ng_packet *np, const List* attr, unsigned char ports)
-{
- ListNode *ln;
- struct attr *at;
- const struct attr_handler *ah;
-
-
- if (attr == NULL)
- return 0;
-
- for (ln = attr->first; ln != NULL; ln = ln->next) {
- at = ln->data;
- ah = getAttrHandler(at->attr);
- if (ah != NULL) {
- if (ah->size > 0 && at->size > 0 && at->size != ah->size)
- return -EINVAL;
- if (at->size > 0 && ah->encode != NULL && !ah->encode(at, ports))
- return -EINVAL;
- }
-
- addPacketAttr(np, at);
- }
-
-
- return 0;
-}
-
-
-int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr, unsigned short filter_attr, unsigned char ports)
-{
- struct attr *at;
- const struct attr_handler *ah;
- int ret = 0;
- unsigned short size;
- bool valid;
-
-
- if (error != NULL)
- *error = np->nh->error;
- if (attr_error != NULL)
- *attr_error = ntohs(np->nh->attr);
-
- while (getPacketTotalSize(np) < np->maxlen) {
-
- /* no room for an attribute header: error */
- if (getPacketTotalSize(np) + (int)sizeof(struct attr_header) > np->maxlen) {
- ret = -1;
- break;
- }
-
- /* create new attribute */
- size = ntohs(np->ah->size);
- at = newAttr(ntohs(np->ah->attr), size, NULL);
- if (at == NULL) {
- ret = -1;
- break;
- }
-
- /* attribute data bigger than the remaining size: error */
- if (getPacketTotalSize(np) + (int)sizeof(struct attr_header) + size > np->maxlen) {
- free(at);
- ret = -1;
- break;
- }
-
- /* copy attribute raw data */
- if (size == 0) {
- at->data = NULL;
- } else {
- at->data = malloc(size * sizeof(char));
- memcpy(at->data, np->ah->data, size);
- }
-
- /* decode attribute data */
- valid = true;
-
- if (filter_attr != ATTR_END && at->attr != filter_attr) {
- valid = false;
- goto next;
- }
-
- ah = getAttrHandler(at->attr);
- if (at->data == NULL || ah == NULL)
- goto next;
-
- if (ah->size > 0 && size != ah->size) {
- valid = false;
- goto next;
- }
-
- if (ah->decode != NULL)
- valid = ah->decode(at, ports);
-
-next:
- /* stop on an END attribute */
- if (at->attr == ATTR_END) {
- free(at);
- break;
- }
-
- /* move to next attribute */
- np->ah = (struct attr_header*)(np->ah->data + size);
-
- if (valid)
- pushBackList(attr, at);
- else
- free(at);
- }
-
-
- return ret;
-}
-
-
+++ /dev/null
-
-#ifndef DEF_PROTOCOL
-#define DEF_PROTOCOL
-
-
-#include <stdlib.h>
-#include <arpa/inet.h>
-
-#include <netinet/ether.h>
-
-#include "list.h"
-
-
-#define CLIENT_PORT 63321
-#define SWITCH_PORT 63322
-
-#define CODE_READ_REQ 1
-#define CODE_READ_REP 2
-#define CODE_WRITE_REQ 3
-#define CODE_WRITE_REP 4
-
-#define ERROR_READONLY 3
-#define ERROR_INVALID_VALUE 5
-#define ERROR_DENIED 7
-
-
-struct ng_header {
- char version; /* always 1, maybe version */
- char code; /* request code: read request, read reply, write request, write reply */
- unsigned char error; /* error code, 0 when no error */
- unsigned char unk1; /* always 0, unknown */
- unsigned short attr; /* attribute code which caused error, 0 when no error */
- char unk2[2]; /* always 0, unknown */
- char client_mac[ETH_ALEN]; /* client MAC address */
- char switch_mac[ETH_ALEN]; /* switch MAC address */
- unsigned int seqnum; /* sequence number */
- char proto_id[4]; /* always "NSDP", maybe short for "Netgear Switch Description Protocol" */
- char unk3[4]; /* always 0, unknown */
- char data[0];
-} __attribute__((packed));
-
-
-struct attr_header {
- unsigned short attr;
- unsigned short size;
- char data[0];
-} __attribute__((packed));
-
-
-struct ng_packet {
- union {
- char *buffer;
- struct ng_header *nh;
- };
- int maxlen;
- struct attr_header *ah;
-};
-
-
-struct attr {
- unsigned short attr;
- unsigned short size;
- void *data;
-};
-
-
-
-int trim (char *txt, int start);
-
-
-static inline int min (int a, int b)
-{
- return a < b ? a : b;
-}
-
-
-void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
-
-
-bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
-
-
-static inline void initNgPacket (struct ng_packet *np)
-{
- np->ah = (struct attr_header*)np->nh->data;
-}
-
-
-void addPacketAttr (struct ng_packet *np, struct attr *at);
-
-
-static inline int getPacketTotalSize (const struct ng_packet *np)
-{
- return ((char*)np->ah) - np->buffer;
-}
-
-
-struct attr* newAttr (unsigned short attr, unsigned short size, void *data);
-
-
-static inline struct attr* newEmptyAttr (unsigned short attr)
-{
- return newAttr(attr, 0, NULL);
-}
-
-
-static inline struct attr* newByteAttr (unsigned short attr, unsigned char value)
-{
- char *v = malloc(sizeof(char));
-
- *v = value;
-
- return newAttr(attr, sizeof(char), v);
-}
-
-
-static inline struct attr* newShortAttr (unsigned short attr, short value)
-{
- short *v = malloc(sizeof(short));
-
- *v = value;
-
- return newAttr(attr, sizeof(short), v);
-}
-
-
-static inline struct attr* newIntAttr (unsigned short attr, int value)
-{
- int *v = malloc(sizeof(int));
-
- *v = value;
-
- return newAttr(attr, sizeof(int), v);
-}
-
-
-static inline struct attr* newAddrAttr (unsigned short attr, struct in_addr value)
-{
- struct in_addr *v = malloc(sizeof(struct in_addr));
-
- *v = value;
-
- return newAttr(attr, sizeof(struct in_addr), v);
-}
-
-
-void freeAttr (struct attr *at);
-
-
-int addPacketAttributes (struct ng_packet *np, const List* attr, unsigned char ports);
-
-
-int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr, unsigned short filter_attr, unsigned char ports);
-
-
-#endif
-
--- /dev/null
+
+
+
+all: lib libdoc
+
+
+
+lib:
+ @+$(MAKE) -C src
+
+libdoc:
+ doxygen rawnsdp
+
+
+clean:
+ @rm -rf doc
+ @+$(MAKE) -C src clean
+
+mrproper: clean
+ @+$(MAKE) -C src mrproper
+
--- /dev/null
+
+#ifndef DEF_ATTR
+#define DEF_ATTR
+
+
+#include <stdbool.h>
+
+#include "protocol.h"
+
+
+#define ATTR_PRODUCT 0x0001
+#define ATTR_UNK_0002 0x0002
+#define ATTR_NAME 0x0003
+#define ATTR_MAC 0x0004
+#define ATTR_UNK_0005 0x0005
+#define ATTR_IP 0x0006
+#define ATTR_NETMASK 0x0007
+#define ATTR_GATEWAY 0x0008
+#define ATTR_NEW_PASSWORD 0x0009
+#define ATTR_PASSWORD 0x000A
+#define ATTR_DHCP 0x000B
+#define ATTR_UNK_000C 0x000C
+#define ATTR_FIRM_VER 0x000D
+#define ATTR_UNK_000E 0x000E
+#define ATTR_UNK_000F 0x000F
+#define ATTR_FIRM_UPGRADE 0x0010
+#define ATTR_RESTART 0x0013
+#define ATTR_DEFAULTS 0x0400
+#define ATTR_PORT_STATUS 0x0C00
+#define ATTR_PORT_STATISTICS 0x1000
+#define ATTR_STATS_RESET 0x1400
+#define ATTR_CABLETEST_DO 0x1800
+#define ATTR_CABLETEST_RESULT 0x1C00
+#define ATTR_VLAN_TYPE 0x2000
+#define ATTR_VLAN_PORT_CONF 0x2400
+#define ATTR_VLAN_DOT_CONF 0x2800
+#define ATTR_VLAN_DESTROY 0x2C00
+#define ATTR_VLAN_PVID 0x3000
+#define ATTR_QOS_TYPE 0x3400
+#define ATTR_QOS_CONFIG 0x3800
+#define ATTR_BITRATE_INPUT 0x4C00
+#define ATTR_BITRATE_OUTPUT 0x5000
+#define ATTR_STORM_ENABLE 0x5400
+#define ATTR_STORM_BITRATE 0x5800
+#define ATTR_MIRROR 0x5C00
+#define ATTR_PORTS_COUNT 0x6000
+#define ATTR_MAX_VLAN 0x6400
+#define ATTR_IGMP_ENABLE_VLAN 0x6800
+#define ATTR_IGMP_BLOCK_UNK 0x6C00
+#define ATTR_IGMP_VALID_V3 0x7000
+#define ATTR_TLV_BITMAP 0x7400
+#define ATTR_END 0xFFFF
+
+#define UNUSED __attribute__((unused))
+
+
+struct attr_handler {
+ unsigned short attr; /* attribute code */
+ unsigned int size; /* expected data size */
+ bool (*encode)(struct attr *at, unsigned char ports); /* encode function */
+ bool (*decode)(struct attr *at, unsigned char ports); /* decode function */
+};
+
+
+const struct attr_handler* getAttrHandler (unsigned short attrcode);
+
+
+
+
+struct attr_port_status {
+ unsigned char port;
+ unsigned char status;
+ unsigned char unk;
+} __attribute__((packed));
+
+
+struct attr_port_stat {
+ unsigned char port;
+ unsigned long long recv;
+ unsigned long long sent;
+ unsigned long long unk1;
+ unsigned long long unk2;
+ unsigned long long unk3;
+ unsigned long long crc;
+} __attribute__((packed));
+
+
+struct attr_bitrate {
+ unsigned char port;
+ int bitrate;
+} __attribute__((packed));
+
+
+struct attr_qos {
+ unsigned char port;
+ unsigned char prio;
+} __attribute__((packed));
+
+
+struct attr_pvid {
+ unsigned char port;
+ unsigned short vlan;
+} __attribute__((packed));
+
+
+struct attr_igmp_vlan {
+ unsigned short enable;
+ unsigned short vlan;
+} __attribute__((packed));
+
+
+struct attr_cabletest_do {
+ unsigned char port;
+ unsigned char action;
+} __attribute__((packed));
+
+
+struct attr_cabletest_result {
+ unsigned char port;
+ unsigned int v1;
+ unsigned int v2;
+} __attribute__((packed));
+
+
+struct attr_vlan_dot {
+ unsigned short vlan;
+ unsigned char ports[0];
+};
+
+
+#endif
+
--- /dev/null
+
+#ifndef DEF_LIST
+#define DEF_LIST
+
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#ifdef MT_SAFE_LIST
+#include <pthread.h>
+#endif
+
+
+
+typedef struct ListNode ListNode;
+
+struct ListNode {
+ void* data;
+ ListNode *prev, *next;
+};
+
+
+typedef struct {
+ ListNode *first, *last;
+ unsigned int count;
+ #ifdef MT_SAFE_LIST
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+ #endif
+} List;
+
+
+
+
+// Creates an empty list
+List* createEmptyList (void);
+
+// Destroys a list, and eventually frees the elements
+// NOT MT SAFE
+void destroyList (List *l, void (*freefunc)(void*));
+
+// Adds an element at front of the list
+void pushFrontList (List *l, void* data);
+
+// Adds an element at back of the list
+void pushBackList (List *l, void* data);
+
+// Pops an element from the front of the list and returns its value
+void* popFrontList (List *l);
+
+// Pops an element from the back of the list and returns its value
+void* popBackList (List *l);
+
+// Clears all the items of the list, and eventually frees them
+void clearList (List *l, void (*freefunc)(void*));
+
+// Find and destroy a particular element of the list, and eventually frees it
+bool findAndDestroy (List *l, void* data, void (*freefunc)(void*));
+
+// Browse all the items of the list through the callback function
+void browseList (List *l, void (*browsefunc)(void*));
+
+//
+void* convertToArray (List *l, size_t sz);
+
+
+
+
+#endif
+
--- /dev/null
+
+#ifndef DEF_PROTOCOL
+#define DEF_PROTOCOL
+
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include <netinet/ether.h>
+
+#include "list.h"
+
+
+#define CLIENT_PORT 63321
+#define SWITCH_PORT 63322
+
+#define CODE_READ_REQ 1
+#define CODE_READ_REP 2
+#define CODE_WRITE_REQ 3
+#define CODE_WRITE_REP 4
+
+#define ERROR_READONLY 3
+#define ERROR_INVALID_VALUE 5
+#define ERROR_DENIED 7
+
+
+struct ng_header {
+ char version; /* always 1, maybe version */
+ char code; /* request code: read request, read reply, write request, write reply */
+ unsigned char error; /* error code, 0 when no error */
+ unsigned char unk1; /* always 0, unknown */
+ unsigned short attr; /* attribute code which caused error, 0 when no error */
+ char unk2[2]; /* always 0, unknown */
+ char client_mac[ETH_ALEN]; /* client MAC address */
+ char switch_mac[ETH_ALEN]; /* switch MAC address */
+ unsigned int seqnum; /* sequence number */
+ char proto_id[4]; /* always "NSDP", maybe short for "Netgear Switch Description Protocol" */
+ char unk3[4]; /* always 0, unknown */
+ char data[0];
+} __attribute__((packed));
+
+
+struct attr_header {
+ unsigned short attr;
+ unsigned short size;
+ char data[0];
+} __attribute__((packed));
+
+
+struct ng_packet {
+ union {
+ char *buffer;
+ struct ng_header *nh;
+ };
+ int maxlen;
+ struct attr_header *ah;
+};
+
+
+struct attr {
+ unsigned short attr;
+ unsigned short size;
+ void *data;
+};
+
+
+
+int trim (char *txt, int start);
+
+
+static inline int min (int a, int b)
+{
+ return a < b ? a : b;
+}
+
+
+void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
+
+
+bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
+
+
+static inline void initNgPacket (struct ng_packet *np)
+{
+ np->ah = (struct attr_header*)np->nh->data;
+}
+
+
+void addPacketAttr (struct ng_packet *np, struct attr *at);
+
+
+static inline int getPacketTotalSize (const struct ng_packet *np)
+{
+ return ((char*)np->ah) - np->buffer;
+}
+
+
+struct attr* newAttr (unsigned short attr, unsigned short size, void *data);
+
+
+static inline struct attr* newEmptyAttr (unsigned short attr)
+{
+ return newAttr(attr, 0, NULL);
+}
+
+
+static inline struct attr* newByteAttr (unsigned short attr, unsigned char value)
+{
+ char *v = malloc(sizeof(char));
+
+ *v = value;
+
+ return newAttr(attr, sizeof(char), v);
+}
+
+
+static inline struct attr* newShortAttr (unsigned short attr, short value)
+{
+ short *v = malloc(sizeof(short));
+
+ *v = value;
+
+ return newAttr(attr, sizeof(short), v);
+}
+
+
+static inline struct attr* newIntAttr (unsigned short attr, int value)
+{
+ int *v = malloc(sizeof(int));
+
+ *v = value;
+
+ return newAttr(attr, sizeof(int), v);
+}
+
+
+static inline struct attr* newAddrAttr (unsigned short attr, struct in_addr value)
+{
+ struct in_addr *v = malloc(sizeof(struct in_addr));
+
+ *v = value;
+
+ return newAttr(attr, sizeof(struct in_addr), v);
+}
+
+
+void freeAttr (struct attr *at);
+
+
+int addPacketAttributes (struct ng_packet *np, const List* attr, unsigned char ports);
+
+
+int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr, unsigned short filter_attr, unsigned char ports);
+
+
+#endif
+
--- /dev/null
+
+CC=gcc
+AR=ar
+CFLAGS=-I../include/ -I../../lib/include/ -W -Wall -Wextra -Os -fno-strict-aliasing -fvisibility=hidden -fPIC
+EXEC=../librawnsdp.a
+
+SRC=$(wildcard *.c)
+OBJ=$(SRC:.c=.o)
+
+
+ifeq ($(DEBUG), yes)
+CFLAGS+=-g
+else
+CFLAGS+=-fomit-frame-pointer
+endif
+
+
+$(EXEC): $(OBJ)
+ $(AR) rcs $@ $^
+
+%.o: %.c
+ $(CC) -c $^ -o $@ $(CFLAGS)
+
+
+clean:
+ @rm -f *.o
+
+mrproper: clean
+ @rm -f $(EXEC)
+
+
--- /dev/null
+
+#include <ngadmin.h>
+
+#include "attr.h"
+#include "protocol.h"
+
+
+#define ATTR_HANDLER_ENTRY(at, sz, enc, dec) {.attr = at, .size = sz, .encode = enc, .decode = dec}
+
+
+
+static bool bool_endecode (struct attr *at, unsigned char ports UNUSED)
+{
+ *(char*)at->data = (*(char*)at->data != 0);
+
+ return true;
+}
+
+
+static bool ports_status_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_port_status *ps = at->data;
+
+ if (ps->port < 1 || ps->port > ports)
+ return false;
+
+ switch (ps->status) {
+ case SPEED_DOWN:
+ case SPEED_10:
+ case SPEED_100:
+ case SPEED_1000:
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool port_stat_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_port_stat *ps = at->data;
+ unsigned long long *v;
+
+ if (ps->port < 1 || ps->port > ports)
+ return false;
+
+ for (v = &ps->recv; ((char*)v) - ((char*)ps) < (int)sizeof(struct attr_port_stat); v++)
+ *v = be64toh(*v);
+
+
+ return true;
+}
+
+
+static bool bitrate_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_bitrate *sb = at->data;
+
+ if (sb->port < 1 || sb->port > ports)
+ return false;
+
+ sb->bitrate = ntohl(sb->bitrate);
+ if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
+ return false;
+
+ return true;
+}
+
+
+static bool bitrate_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_bitrate *sb = at->data;
+
+ if (sb->port < 1 || sb->port > ports)
+ return false;
+
+ if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
+ return false;
+ sb->bitrate = htonl(sb->bitrate);
+
+ return true;
+}
+
+
+static bool qos_mode_endecode (struct attr *at, unsigned char ports UNUSED)
+{
+ unsigned char v = *(char*)at->data;
+
+ return (v == QOS_PORT || v == QOS_DOT);
+}
+
+
+static bool qos_endecode (struct attr *at, unsigned char ports)
+{
+ struct attr_qos *aq = at->data;
+
+ if (aq->port < 1 || aq->port > ports)
+ return false;
+
+ return (aq->prio >= PRIO_HIGH && aq->prio <= PRIO_LOW);
+}
+
+
+static bool pvid_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_pvid *ap= at->data;
+
+ if (ap->port < 1 || ap->port > ports)
+ return false;
+
+ ap->vlan = ntohs(ap->vlan);
+
+ return (ap->vlan >= VLAN_MIN && ap->vlan <= VLAN_MAX);
+}
+
+
+static bool pvid_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_pvid *ap= at->data;
+
+ if (ap->port < 1 || ap->port > ports)
+ return false;
+
+ if (ap->vlan < VLAN_MIN || ap->vlan > VLAN_MAX)
+ return false;
+
+ ap->vlan = htons(ap->vlan);
+
+ return true;
+}
+
+
+static bool vlan_destroy_encode (struct attr *at, unsigned char ports UNUSED)
+{
+ unsigned short v = *(unsigned short*)at->data;
+
+ if (v < VLAN_MIN || v > VLAN_MAX)
+ return false;
+
+ *(unsigned short*)at->data = htons(v);
+
+ return true;
+}
+
+
+static bool mirror_decode (struct attr *at, unsigned char ports)
+{
+ unsigned char *r = at->data, *p;
+ int port;
+
+
+ if (at->size != 3 + ((ports - 1) >> 3))
+ return false;
+
+ /* r[0] == 0 is allowed and means mirroring is disabled */
+ if (r[0] > ports)
+ return false;
+
+ p = malloc(1 + ports);
+ if (p == NULL)
+ return false;
+
+ memset(p, 0, 1 + ports);
+
+ if (r[0] == 0)
+ goto end;
+
+ p[0] = r[0];
+
+ for (port = 1; port <= ports; port++)
+ p[port] = (r[2] >> (8 - port)) & 1; /* FIXME: if ports > 8 */
+
+end:
+ free(at->data);
+ at->data = p;
+ at->size = 1 + ports;
+
+
+ return true;
+}
+
+
+static bool mirror_encode (struct attr *at, unsigned char ports)
+{
+ unsigned char *p = at->data, *r;
+ int port;
+
+
+ if (at->size != 1 + ports)
+ return false;
+
+ /* p[0] == 0 is allowed and means mirroring is disabled */
+ if (p[0] > ports)
+ return false;
+
+ r = malloc(3 + ((ports - 1) >> 3));
+ if (r == NULL)
+ return false;
+
+ memset(r, 0, 3 + ((ports - 1) >> 3));
+
+ if (p[0] == 0)
+ goto end;
+
+ r[0] = p[0];
+
+ for (port = 1; port <= ports; port++) {
+ if (p[0] != port)
+ r[2] |= (p[port] & 1) << (8 - port); /* FIXME: if ports > 8 */
+ }
+
+end:
+ free(at->data);
+ at->data = r;
+ at->size = 3 + ((ports - 1) >> 3);
+
+
+ return true;
+}
+
+
+static bool igmp_vlan_decode (struct attr *at, unsigned char ports UNUSED)
+{
+ struct attr_igmp_vlan *aiv = at->data;
+
+ aiv->enable = ntohs(aiv->enable);
+ if (aiv->enable != 0 && aiv->enable != 1)
+ return false;
+
+ aiv->vlan = ntohs(aiv->vlan);
+ if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_MAX)
+ return false;
+
+ return true;
+}
+
+
+static bool igmp_vlan_encode (struct attr *at, unsigned char ports UNUSED)
+{
+ struct attr_igmp_vlan *aiv = at->data;
+
+ if (aiv->enable != 0 && aiv->enable != 1)
+ return false;
+ aiv->enable = htons(aiv->enable);
+
+ if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_MAX)
+ return false;
+ aiv->vlan = htons(aiv->vlan);
+
+ return true;
+}
+
+
+static bool cabletest_do_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_cabletest_do *acd = at->data;
+
+ if (acd->port < 1 || acd->port > ports)
+ return false;
+
+ return (acd->action == 1);
+}
+
+
+static bool cabletest_result_encode (struct attr *at, unsigned char ports)
+{
+ unsigned char v = *(unsigned char*)at->data;
+
+ return (v >= 1 && v <= ports);
+}
+
+
+static bool cabletest_result_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_cabletest_result *acr = at->data;
+
+ if (acr->port < 1 || acr->port > ports)
+ return false;
+
+ acr->v1 = ntohl(acr->v1);
+ acr->v2 = ntohl(acr->v2);
+
+ return true;
+}
+
+
+static bool cabletest_result_endecode (struct attr *at, unsigned char ports)
+{
+ switch (at->size) {
+
+ case 1:
+ return cabletest_result_encode(at, ports);
+
+ case sizeof(struct attr_cabletest_result):
+ return cabletest_result_decode(at, ports);
+
+ default:
+ return false;
+ }
+}
+
+
+static bool vlan_type_endecode (struct attr *at, unsigned char ports UNUSED)
+{
+ char v = *(char*)at->data;
+
+ return (v >= VLAN_DISABLED && v <= VLAN_DOT_ADV);
+}
+
+
+static bool vlan_dot_decode (struct attr *at, unsigned char ports)
+{
+ char *r = at->data;
+ struct attr_vlan_dot *avd;
+ int port;
+
+
+ if (at->size != (2 + 2 * (1 + ((ports - 1) >> 3))))
+ return false;
+
+ avd = malloc(sizeof(struct attr_vlan_dot) + ports);
+ if (avd == NULL)
+ return false;
+
+ avd->vlan = ntohs(*(unsigned short*)r);
+ r += 2;
+
+ for (port = 0; port < ports; port++) {
+ /* FIXME: if ports > 8 */
+ if ((r[1] >> (7 - port)) & 1)
+ avd->ports[port] = VLAN_TAGGED;
+ else if ((r[0] >> (7 - port)) & 1)
+ avd->ports[port] = VLAN_UNTAGGED;
+ else
+ avd->ports[port] = VLAN_NO;
+ }
+
+ free(at->data);
+ at->data = avd;
+ at->size = sizeof(struct attr_vlan_dot) + ports;
+
+
+ return true;
+}
+
+
+static bool vlan_dot_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_vlan_dot *avd = at->data;
+ char *r, fl;
+ unsigned int size, port;
+
+
+ if (avd->vlan < VLAN_MIN || avd->vlan > VLAN_MAX)
+ return false;
+
+ /* just a header is valid */
+ if (at->size == sizeof(struct attr_vlan_dot))
+ size = 2;
+ else if (at->size == sizeof(struct attr_vlan_dot) + ports)
+ size = (2 + 2 * (1 + ((ports - 1) >> 3)));
+ else
+ return false;
+
+ r = malloc(size);
+ if (r == NULL)
+ return false;
+
+ memset(r, 0, size);
+ *(unsigned short*)r = htons(avd->vlan);
+
+ if (size == 2)
+ goto end;
+
+ r += 2;
+
+ for (port = 0; port < ports; port++) {
+ /* FIXME: if ports > 8 */
+ fl = (1 << (7 - port));
+ switch (avd->ports[port]) {
+ case VLAN_TAGGED:
+ r[1] |= fl;
+ case VLAN_UNTAGGED:
+ r[0] |= fl;
+ }
+ }
+
+ r -= 2;
+
+end:
+ free(at->data);
+ at->data = r;
+ at->size = size;
+
+
+ return true;
+}
+
+
+
+/* WARNING: attributes codes MUST be in ascending order */
+static const struct attr_handler attrtab[] = {
+ ATTR_HANDLER_ENTRY(ATTR_MAC, 6, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_IP, 4, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_NETMASK, 4, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_GATEWAY, 4, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_DHCP, 2, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_RESTART, 1, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_DEFAULTS, 1, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_PORT_STATUS, sizeof(struct attr_port_status), NULL, ports_status_decode),
+ ATTR_HANDLER_ENTRY(ATTR_PORT_STATISTICS, sizeof(struct attr_port_stat), NULL, port_stat_decode),
+ ATTR_HANDLER_ENTRY(ATTR_STATS_RESET, 1, bool_endecode, bool_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), cabletest_do_encode, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_CABLETEST_RESULT, 0, cabletest_result_endecode, cabletest_result_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_TYPE, 1, vlan_type_endecode, vlan_type_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_DOT_CONF, 0, vlan_dot_encode, vlan_dot_decode),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_DESTROY, 2, vlan_destroy_encode, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_PVID, sizeof(struct attr_pvid), pvid_encode, pvid_decode),
+ ATTR_HANDLER_ENTRY(ATTR_QOS_TYPE, 1, qos_mode_endecode, qos_mode_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_QOS_CONFIG, sizeof(struct attr_qos), qos_endecode, qos_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
+ ATTR_HANDLER_ENTRY(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
+ ATTR_HANDLER_ENTRY(ATTR_STORM_ENABLE, 1, bool_endecode, bool_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
+ ATTR_HANDLER_ENTRY(ATTR_MIRROR, 0, mirror_encode, mirror_decode),
+ ATTR_HANDLER_ENTRY(ATTR_PORTS_COUNT, 1, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), igmp_vlan_encode, igmp_vlan_decode),
+ ATTR_HANDLER_ENTRY(ATTR_IGMP_BLOCK_UNK, 1, bool_endecode, bool_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_IGMP_VALID_V3, 1, bool_endecode, bool_endecode)
+};
+
+
+
+const struct attr_handler* getAttrHandler (unsigned short attrcode)
+{
+ const struct attr_handler *ah;
+ const unsigned int tab_size = sizeof(attrtab) / sizeof(struct attr_handler);
+ unsigned int inf, sup, index;
+
+
+ inf = 0;
+ sup = tab_size;
+ index = tab_size >> 1;
+ while (index < sup) {
+ ah = &attrtab[index];
+
+ if (ah->attr > attrcode) {
+ sup = index;
+ index -= ((index - inf) >> 1) + ((index - inf) & 1);
+ } else if (ah->attr < attrcode) {
+ inf = index;
+ index += ((sup - index) >> 1) + ((sup - index) & 1);
+ } else {
+ return ah;
+ }
+ }
+
+
+ return NULL;
+}
+
+
--- /dev/null
+
+#include "list.h"
+
+
+
+
+// -------------------------
+List* createEmptyList (void) {
+
+ List *l;
+
+
+ l=malloc(sizeof(List));
+ l->first=NULL;
+ l->last=NULL;
+ l->count=0;
+
+ #ifdef MT_SAFE_LIST
+ pthread_cond_init(&l->cond, NULL);
+ pthread_mutex_init(&l->mutex, NULL);
+ #endif
+
+
+ return l;
+
+}
+
+
+
+// ------------------------------------------------
+void destroyList (List *l, void (*freefunc)(void*)) {
+
+ ListNode *pr, *ln;
+
+
+
+ if ( l==NULL ) {
+ return;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_destroy(&l->mutex);
+ pthread_cond_destroy(&l->cond);
+ #endif
+
+ for (ln=l->first; ln!=NULL; ) {
+
+ pr=ln;
+
+ if ( freefunc!=NULL ) {
+ freefunc(pr->data);
+ }
+
+ ln=pr->next;
+ free(pr);
+
+ }
+
+
+ free(l);
+
+}
+
+
+
+// -------------------------------------
+void pushFrontList (List *l, void* data) {
+
+ ListNode *ln;
+
+
+ if ( l==NULL ) {
+ return;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ ln=malloc(sizeof(ListNode));
+ ln->data=data;
+ ln->prev=NULL;
+ ln->next=l->first;
+
+ if ( l->first==NULL ) {
+ l->last=ln;
+ } else {
+ l->first->prev=ln;
+ }
+
+ l->first=ln;
+ l->count++;
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ #endif
+
+}
+
+
+
+// ------------------------------------
+void pushBackList (List *l, void* data) {
+
+ ListNode *ln;
+
+
+ if ( l==NULL ) {
+ return;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ ln=malloc(sizeof(ListNode));
+ ln->data=data;
+ ln->prev=l->last;
+ ln->next=NULL;
+
+ if ( l->last==NULL ) {
+ l->first=ln;
+ } else {
+ l->last->next=ln;
+ }
+
+ l->last=ln;
+ l->count++;
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ #endif
+
+}
+
+
+
+// -------------------------
+void* popFrontList (List *l) {
+
+ ListNode *ln;
+ void* data;
+
+
+ if ( l==NULL ) {
+ return NULL;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ if ( (ln=l->first)==NULL ) {
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ #endif
+ return NULL;
+ }
+
+ data=ln->data;
+ l->first=ln->next;
+
+ if ( ln->next==NULL ) {
+ l->last=NULL;
+ } else {
+ ln->next->prev=NULL;
+ }
+
+ l->count--;
+ free(ln);
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ #endif
+
+
+ return data;
+
+}
+
+
+
+// ------------------------
+void* popBackList (List *l) {
+
+ ListNode *ln;
+ void* data;
+
+
+
+ if ( l==NULL ) {
+ return NULL;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ if ( (ln=l->last)==NULL ) {
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ #endif
+ return NULL;
+ }
+
+ data=ln->data;
+ l->last=ln->prev;
+
+ if ( ln->prev==NULL ) {
+ l->first=NULL;
+ } else {
+ ln->prev->next=NULL;
+ }
+
+ l->count--;
+ free(ln);
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ #endif
+
+
+ return data;
+
+}
+
+
+
+// ----------------------------------------------
+void clearList (List *l, void (*freefunc)(void*)) {
+
+ ListNode *ln, *pr;
+
+
+ if ( l==NULL ) {
+ return;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ for (ln=l->first; ln!=NULL; ) {
+
+ pr=ln;
+
+ if ( freefunc!=NULL ) {
+ freefunc(pr->data);
+ }
+
+ ln=pr->next;
+ free(pr);
+
+ }
+
+ l->first=NULL;
+ l->last=NULL;
+ l->count=0;
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ #endif
+
+}
+
+
+
+// ---------------------------------------------------------------
+bool findAndDestroy (List *l, void* data, void (*freefunc)(void*)) {
+
+ ListNode *ln;
+
+
+
+ if ( l==NULL ) {
+ return false;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ for (ln=l->first; ln!=NULL && ln->data!=data; ln=ln->next);
+
+ if ( ln==NULL ) {
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ #endif
+
+ } else {
+
+ if ( ln->prev==NULL ) {
+ l->first=ln->next;
+ } else {
+ ln->prev->next=ln->next;
+ }
+
+ if ( ln->next==NULL ) {
+ l->last=ln->prev;
+ } else {
+ ln->next->prev=ln->prev;
+ }
+
+
+ if ( freefunc!=NULL ) {
+ freefunc(data);
+ }
+
+ l->count--;
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ #endif
+
+ }
+
+
+
+ return true;
+
+}
+
+
+
+// -------------------------------------------------
+void browseList (List *l, void (*browsefunc)(void*)) {
+
+ ListNode *ln;
+
+
+
+ if ( l==NULL || browsefunc==NULL ) {
+ return;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ for (ln=l->first; ln!=NULL; ln=ln->next) {
+ browsefunc(ln->data);
+ }
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ #endif
+
+}
+
+
+// --------------------------------------
+void* convertToArray (List *l, size_t sz) {
+
+ ListNode *ln;
+ void *tab=NULL, *p;
+
+
+
+ if ( l==NULL || sz==0 ) {
+ return NULL;
+ }
+
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_lock(&l->mutex);
+ #endif
+
+ if ( l->count>0 ) {
+
+ tab=malloc(l->count*sz);
+ p=tab;
+
+ for (ln=l->first; ln!=NULL; ln=ln->next) {
+ memcpy(p, ln->data, sz);
+ p+=sz;
+ }
+
+ }
+
+ #ifdef MT_SAFE_LIST
+ pthread_mutex_unlock(&l->mutex);
+ #endif
+
+
+ return tab;
+
+}
+
+
+
+
--- /dev/null
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+
+#include "attr.h"
+#include "protocol.h"
+
+
+
+int trim (char *txt, int start)
+{
+ char *p;
+
+ if (txt == NULL)
+ return 0;
+
+ p = txt + start;
+ while (p >= txt && (*p == ' ' || *p == '\n')) {
+ *p = '\0';
+ p--;
+ }
+
+ return p - txt + 1;
+}
+
+
+void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum)
+{
+ memset(nh, 0, sizeof(struct ng_header));
+ nh->version = 1;
+ nh->code = code;
+
+ memcpy(nh->client_mac, client_mac, ETH_ALEN);
+
+ if (switch_mac != NULL)
+ memcpy(nh->switch_mac, switch_mac, ETH_ALEN);
+
+ nh->seqnum = htonl(seqnum);
+ memcpy(nh->proto_id, "NSDP", 4);
+}
+
+
+bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum)
+{
+ if (nh->version != 1)
+ return false;
+
+ if (code > 0 && nh->code != code)
+ return false;
+
+ if (nh->unk1 != 0)
+ return false;
+
+ if (*(unsigned short*)nh->unk2 != 0)
+ return false;
+
+ if (client_mac != NULL && memcmp(nh->client_mac, client_mac, ETH_ALEN) != 0)
+ return false;
+
+ if (switch_mac != NULL && memcmp(nh->switch_mac, switch_mac, ETH_ALEN) != 0)
+ return false;
+
+ if (seqnum > 0 && ntohl(nh->seqnum) != seqnum)
+ return false;
+
+ if (memcmp(nh->proto_id, "NSDP", 4) != 0)
+ return false;
+
+ if (*(unsigned int*)nh->unk3 != 0)
+ return false;
+
+ return true;
+}
+
+
+void addPacketAttr (struct ng_packet *np, struct attr *at)
+{
+ struct attr_header *ah = np->ah;
+
+
+ if ((int)(getPacketTotalSize(np) + sizeof(struct attr_header) + at->size) > np->maxlen)
+ return;
+
+ ah->attr = htons(at->attr);
+ ah->size = htons(at->size);
+
+ if (at->size > 0 && at->data != NULL)
+ memcpy(ah->data, at->data, at->size);
+
+ np->ah = (struct attr_header*)(ah->data + at->size);
+}
+
+
+struct attr* newAttr (unsigned short attr, unsigned short size, void *data)
+{
+ struct attr *at;
+
+
+ at = malloc(sizeof(struct attr));
+ if (at == NULL)
+ return NULL;
+
+ at->attr = attr;
+ at->size = size;
+ at->data = data;
+
+
+ return at;
+}
+
+
+void freeAttr (struct attr *at)
+{
+ if (at != NULL) {
+ free(at->data);
+ free(at);
+ }
+}
+
+
+int addPacketAttributes (struct ng_packet *np, const List* attr, unsigned char ports)
+{
+ ListNode *ln;
+ struct attr *at;
+ const struct attr_handler *ah;
+
+
+ if (attr == NULL)
+ return 0;
+
+ for (ln = attr->first; ln != NULL; ln = ln->next) {
+ at = ln->data;
+ ah = getAttrHandler(at->attr);
+ if (ah != NULL) {
+ if (ah->size > 0 && at->size > 0 && at->size != ah->size)
+ return -EINVAL;
+ if (at->size > 0 && ah->encode != NULL && !ah->encode(at, ports))
+ return -EINVAL;
+ }
+
+ addPacketAttr(np, at);
+ }
+
+
+ return 0;
+}
+
+
+int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr, unsigned short filter_attr, unsigned char ports)
+{
+ struct attr *at;
+ const struct attr_handler *ah;
+ int ret = 0;
+ unsigned short size;
+ bool valid;
+
+
+ if (error != NULL)
+ *error = np->nh->error;
+ if (attr_error != NULL)
+ *attr_error = ntohs(np->nh->attr);
+
+ while (getPacketTotalSize(np) < np->maxlen) {
+
+ /* no room for an attribute header: error */
+ if (getPacketTotalSize(np) + (int)sizeof(struct attr_header) > np->maxlen) {
+ ret = -1;
+ break;
+ }
+
+ /* create new attribute */
+ size = ntohs(np->ah->size);
+ at = newAttr(ntohs(np->ah->attr), size, NULL);
+ if (at == NULL) {
+ ret = -1;
+ break;
+ }
+
+ /* attribute data bigger than the remaining size: error */
+ if (getPacketTotalSize(np) + (int)sizeof(struct attr_header) + size > np->maxlen) {
+ free(at);
+ ret = -1;
+ break;
+ }
+
+ /* copy attribute raw data */
+ if (size == 0) {
+ at->data = NULL;
+ } else {
+ at->data = malloc(size * sizeof(char));
+ memcpy(at->data, np->ah->data, size);
+ }
+
+ /* decode attribute data */
+ valid = true;
+
+ if (filter_attr != ATTR_END && at->attr != filter_attr) {
+ valid = false;
+ goto next;
+ }
+
+ ah = getAttrHandler(at->attr);
+ if (at->data == NULL || ah == NULL)
+ goto next;
+
+ if (ah->size > 0 && size != ah->size) {
+ valid = false;
+ goto next;
+ }
+
+ if (ah->decode != NULL)
+ valid = ah->decode(at, ports);
+
+next:
+ /* stop on an END attribute */
+ if (at->attr == ATTR_END) {
+ free(at);
+ break;
+ }
+
+ /* move to next attribute */
+ np->ah = (struct attr_header*)(np->ah->data + size);
+
+ if (valid)
+ pushBackList(attr, at);
+ else
+ free(at);
+ }
+
+
+ return ret;
+}
+
+